text:
/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/targeting/test/testattrtank.H $                       */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2013,2017                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#ifndef TESTATTRTANK_H
#define TESTATTRTANK_H

/**
 *  @file testattrtank.H
 *
 *  @brief Test case for AttributeTank
*/

#include <cxxtest/TestSuite.H>

#include <targeting/common/attributeTank.H>
#include <targeting/attrPlatOverride.H>
#include <pnor/pnorif.H>
#include <kernel/bltohbdatamgr.H>

using namespace TARGETING;

class AttrTankTest: public CxxTest::TestSuite
{
public:

    //**************************************************************************
    // tankTest1. Test AttributeTank functions with empty tank
    //**************************************************************************
    void tankTest1(void)
    {
        do
        {
            // Create a local AttributeTank
            AttributeTank l_tank;

            // Check that tank is empty
            if (l_tank.attributesExist())
            {
                TS_FAIL("tankTest1: Error. AttributeTank is not empty (1)");
                break;
            }

            if (l_tank.attributeExists(5))
            {
                TS_FAIL("tankTest1: Error. AttributeTank is not empty (2)");
                break;
            }

            // Clear all attributes from empty tank
            l_tank.clearAllAttributes();

            // Clear a non-const attribute from empty tank
            l_tank.clearNonConstAttribute(ATTR_SCRATCH_UINT64_1,
                                          TYPE_SYS,
                                          AttributeTank::ATTR_POS_NA,
                                          AttributeTank::ATTR_UNIT_POS_NA,
                                          AttributeTank::ATTR_NODE_NA);

            // Try to get an attribute from empty tank
            uint64_t l_val = 0;
            if (l_tank.getAttribute(ATTR_SCRATCH_UINT64_1,
                                    TYPE_SYS,
                                    AttributeTank::ATTR_POS_NA,
                                    AttributeTank::ATTR_UNIT_POS_NA,
                                    AttributeTank::ATTR_NODE_NA,
                                    &l_val))
            {
                TS_FAIL("tankTest1: Error. Got attr from empty tank (3)");
                break;
            }

            // Try to serialize all attributes from empty tank
            std::vector<AttributeTank::AttributeSerializedChunk> l_attributes;
            l_tank.serializeAttributes(AttributeTank::ALLOC_TYPE_MALLOC,
                                       4096, l_attributes);

            if (l_attributes.size())
            {
                TS_FAIL("tankTest1: Error. Got attrs from empty tank (4)");
                break;
            }

        } while (0);

        TS_TRACE("tankTest1 complete" );
    }

    //**************************************************************************
    // tankTest2. Test AttributeTank functions with single attribute in tank
    //**************************************************************************
    void test2(void)
    {
        do
        {
            // Create a local AttributeTank
            AttributeTank l_tank;

            // Add ATTR_SCRATCH_UINT64_1 to the tank
            uint64_t l_val = 4;
            l_tank.setAttribute(ATTR_SCRATCH_UINT64_1,
                                TYPE_SYS,
                                AttributeTank::ATTR_POS_NA,
                                AttributeTank::ATTR_UNIT_POS_NA,
                                AttributeTank::ATTR_NODE_NA,
                                0, sizeof(l_val), &l_val);

            // Check that attributes exist in the tank
            if (!l_tank.attributesExist())
            {
                TS_FAIL("tankTest2: Error. AttributeTank is empty (1)");
                break;
            }

            if (!l_tank.attributeExists(ATTR_SCRATCH_UINT64_1))
            {
                TS_FAIL("tankTest2: Error. Attribute not in tank (2)");
                break;
            }

            if (l_tank.attributeExists(1))
            {
                TS_FAIL("tankTest2: Error. Wrong attribute in tank (3)");
                break;
            }

            // Try to get the wrong attribute from the tank (wrong att ID)
            l_val = 0;
            if (l_tank.getAttribute(ATTR_SCRATCH_UINT64_2,
                                    TYPE_SYS,
                                    AttributeTank::ATTR_POS_NA,
                                    AttributeTank::ATTR_UNIT_POS_NA,
                                    AttributeTank::ATTR_NODE_NA,
                                    &l_val))
            {
                TS_FAIL("tankTest2: Error. Got wrong attr from tank (4)");
                break;
            }

            // Try to get the wrong attribute from the tank (wrong target type)
            l_val = 0;
            if (l_tank.getAttribute(ATTR_SCRATCH_UINT64_1,
                                    TYPE_PROC,
                                    AttributeTank::ATTR_POS_NA,
                                    AttributeTank::ATTR_UNIT_POS_NA,
                                    AttributeTank::ATTR_NODE_NA,
                                    &l_val))
            {
                TS_FAIL("tankTest2: Error. Got wrong attr from tank (5)");
                break;
            }

            // Get the attribute from the tank
            l_val = 0;
            if (!(l_tank.getAttribute(ATTR_SCRATCH_UINT64_1,
                                      TYPE_SYS,
                                      AttributeTank::ATTR_POS_NA,
                                      AttributeTank::ATTR_UNIT_POS_NA,
                                      AttributeTank::ATTR_NODE_NA,
                                      &l_val)))
            {
                TS_FAIL("tankTest2: Error. Did not get attr from tank (6)");
                break;
            }

            if (l_val != 4)
            {
                TS_FAIL("tankTest2: Error. Got bad value (0x%llx) from tank (7)",
                        l_val);
                break;
            }

            // Get the attribute from the tank using a real position
            // This should succeed because attribute in tank matches all positions
            l_val = 0;
            if (!(l_tank.getAttribute(ATTR_SCRATCH_UINT64_1,
                                      TYPE_SYS,
                                      1,
                                      AttributeTank::ATTR_UNIT_POS_NA,
                                      AttributeTank::ATTR_NODE_NA,
                                      &l_val)))
            {
                TS_FAIL("tankTest2: Error. Did not get attr from tank (8)");
                break;
            }

            if (l_val != 4)
            {
                TS_FAIL("tankTest2: Error. Got bad value (0x%llx) from tank (9)",
                        l_val);
                break;
            }

            // Get the attribute from the tank using a real unit-position
            // This should succeed because attribute in tank matches all unit
            // positions
            l_val = 0;
            if (!(l_tank.getAttribute(ATTR_SCRATCH_UINT64_1,
                                      TYPE_SYS,
                                      AttributeTank::ATTR_POS_NA,
                                      2,
                                      AttributeTank::ATTR_NODE_NA,
                                      &l_val)))
            {
                TS_FAIL("tankTest2: Error. Did not get attr from tank (10)");
                break;
            }

            if (l_val != 4)
            {
                TS_FAIL("tankTest2: Error. Got bad value (0x%llx) from tank (11)",
                        l_val);
                break;
            }

            // Get the attribute from the tank using a real node-number
            // This should succeed because attribute in tank matches all node
            // numbers
            l_val = 0;
            if (!(l_tank.getAttribute(ATTR_SCRATCH_UINT64_1,
                                      TYPE_SYS,
                                      AttributeTank::ATTR_POS_NA,
                                      AttributeTank::ATTR_UNIT_POS_NA,
                                      1,
                                      &l_val)))
            {
                TS_FAIL("tankTest2: Error. Did not get attr from tank (12)");
                break;
            }

            if (l_val != 4)
            {
                TS_FAIL("tankTest2: Error. Got bad value (0x%llx) from tank (13)",
                        l_val);
                break;
            }

            // Serialize all attributes from the tank
            std::vector<AttributeTank::AttributeSerializedChunk> l_attributes;
            l_tank.serializeAttributes(AttributeTank::ALLOC_TYPE_NEW,
                                       4096, l_attributes);

            if (l_attributes.size() != 1)
            {
                TS_FAIL("tankTest2: Error. Got wrong number of chunks (%d) from tank (14)",
                        l_attributes.size());
                break;
            }

            if (l_attributes[0].iv_size !=
                (sizeof(AttributeTank::AttributeHeader) + sizeof(l_val)))
            {
                TS_FAIL("tankTest2: Error. Got wrong size (%d) of attrs from tank (15)",
                        l_attributes[0].iv_size);
                break;
            }

            uint64_t * l_pVal = reinterpret_cast<uint64_t *>
                (l_attributes[0].iv_pAttributes +
                 sizeof(AttributeTank::AttributeHeader));

            if (*l_pVal != 4)
            {
                TS_FAIL("tankTest2: Error. Got bad value (0x%016llx) from tank (16)",
                        *l_pVal);
                break;
            }

            // Clear the tank and check it was cleared
            l_tank.clearAllAttributes();

            l_val = 0;
            if (l_tank.getAttribute(ATTR_SCRATCH_UINT64_1,
                                    TYPE_SYS,
                                    AttributeTank::ATTR_POS_NA,
                                    AttributeTank::ATTR_UNIT_POS_NA,
                                    AttributeTank::ATTR_NODE_NA,
                                    &l_val))
            {
                TS_FAIL("tankTest2: Error. Got value from empty tank (17)");
                break;
            }

            // Deserialize the attribute back into the tank
            l_tank.deserializeAttributes(l_attributes[0]);

            // Check the attribute made it back into the tank
            l_val = 0;
            if (!(l_tank.getAttribute(ATTR_SCRATCH_UINT64_1,
                                      TYPE_SYS,
                                      AttributeTank::ATTR_POS_NA,
                                      AttributeTank::ATTR_UNIT_POS_NA,
                                      AttributeTank::ATTR_NODE_NA,
                                      &l_val)))
            {
                TS_FAIL("tankTest2: Error. Did not get attr from tank (18)");
                break;
            }

            if (l_val != 4)
            {
                TS_FAIL("tankTest2: Error. Got bad value (0x%llx) from tank (19)",
                        l_val);
                break;
            }

            // Free the memory in the attribute chunk
            delete [] l_attributes[0].iv_pAttributes;
            l_attributes[0].iv_pAttributes = NULL;

        } while (0);

        TS_TRACE("tankTest2 complete" );
    }

    //**************************************************************************
    // tankTest3. Test AttributeTank functions with multiple attributes in tank
    //**************************************************************************
    void test3(void)
    {
        do
        {
            // Create a local AttributeTank
            AttributeTank l_tank;

            // Add ATTR_SCRATCH_UINT64_1 as a proc chip attribute to the tank
            uint64_t l_val = 4;
            l_tank.setAttribute(ATTR_SCRATCH_UINT64_1,
                                TYPE_PROC,
                                1,
                                AttributeTank::ATTR_UNIT_POS_NA,
                                AttributeTank::ATTR_NODE_NA,
                                0, sizeof(l_val), &l_val);

            // Add ATTR_SCRATCH_UINT32_1 as an MBA attribute to the tank
            uint32_t l_val2 = 5;
            l_tank.setAttribute(ATTR_SCRATCH_UINT32_1,
                                TYPE_MBA,
                                1,
                                2,
                                3,
                                0, sizeof(l_val2), &l_val2);

            // Get the first attribute from the tank
            l_val = 0;
            if (!(l_tank.getAttribute(ATTR_SCRATCH_UINT64_1,
                                      TYPE_PROC,
                                      1,
                                      AttributeTank::ATTR_UNIT_POS_NA,
                                      AttributeTank::ATTR_NODE_NA,
                                      &l_val)))
            {
                TS_FAIL("tankTest3: Error. Did not get attr from tank (1)");
                break;
            }

            if (l_val != 4)
            {
                TS_FAIL("tankTest3: Error. Got bad value (0x%016llx) from tank (2)",
                        l_val);
                break;
            }

            // Try to get the first attribute from the tank with the wrong pos
            l_val = 0;
            if (l_tank.getAttribute(ATTR_SCRATCH_UINT64_1,
                                    TYPE_PROC,
                                    2,
                                    AttributeTank::ATTR_UNIT_POS_NA,
                                    AttributeTank::ATTR_NODE_NA,
                                    &l_val))
            {
                TS_FAIL("tankTest3: Error. Got wrong attr from tank (3)");
                break;
            }

            // Get the second attribute from the tank
            l_val2 = 0;
            if (!(l_tank.getAttribute(ATTR_SCRATCH_UINT32_1,
                                      TYPE_MBA,
                                      1,
                                      2,
                                      3,
                                      &l_val2)))
            {
                TS_FAIL("tankTest3: Error. Did not get attr from tank (4)");
                break;
            }

            if (l_val2 != 5)
            {
                TS_FAIL("tankTest3: Error. Got bad value (0x%llx) from tank (5)",
                        l_val);
                break;
            }

            // Try to get the second attribute from the tank with the wrong
            // unit position
            l_val2 = 0;
            if (l_tank.getAttribute(ATTR_SCRATCH_UINT32_1,
                                    TYPE_MBA,
                                    1,
                                    3,
                                    3,
                                    &l_val2))
            {
                TS_FAIL("tankTest3: Error. Got wrong attr from tank (6)");
                break;
            }

            // Try to get the second attribute from the tank with the wrong
            // node number
            l_val2 = 0;
            if (l_tank.getAttribute(ATTR_SCRATCH_UINT32_1,
                                    TYPE_MBA,
                                    1,
                                    2,
                                    4,
                                    &l_val2))
            {
                TS_FAIL("tankTest3: Error. Got wrong attr from tank (7)");
                break;
            }

            // Serialize all attributes from the tank into a single chunk
            std::vector<AttributeTank::AttributeSerializedChunk> l_attributes;
            l_tank.serializeAttributes(AttributeTank::ALLOC_TYPE_MALLOC,
                                       4096, l_attributes);

            if (l_attributes.size() != 1)
            {
                TS_FAIL("tankTest3: Error. Got wrong number of chunks (%d) from tank (8)",
                        l_attributes.size());
                break;
            }

            if (l_attributes[0].iv_size !=
                (sizeof(AttributeTank::AttributeHeader) + sizeof(l_val) +
                 sizeof(AttributeTank::AttributeHeader) + sizeof(l_val2)) )
            {
                TS_FAIL("tankTest3: Error. Got wrong size (%d) of attrs from tank (9)",
                        l_attributes[0].iv_size);
                break;
            }

            uint64_t * l_pVal = reinterpret_cast<uint64_t *>
                (l_attributes[0].iv_pAttributes +
                 sizeof(AttributeTank::AttributeHeader));

            if (*l_pVal != 4)
            {
                TS_FAIL("tankTest3: Error. Got bad value (0x%016llx) from tank (10)",
                        *l_pVal);
                break;
            }

            uint32_t * l_pVal2 = reinterpret_cast<uint32_t *>
                (l_attributes[0].iv_pAttributes +
                 sizeof(AttributeTank::AttributeHeader) +
                 sizeof(l_val) + sizeof(AttributeTank::AttributeHeader));

            if (*l_pVal2 != 5)
            {
                TS_FAIL("tankTest3: Error. Got bad value (0x%08x) from tank (11)",
                        *l_pVal2);
                break;
            }

            // Clear the tank
            l_tank.clearAllAttributes();

            // Deserialize the attribute back into the tank
            l_tank.deserializeAttributes(l_attributes[0]);

            // Check the first attribute made it back into the tank
            l_val = 0;
            if (!(l_tank.getAttribute(ATTR_SCRATCH_UINT64_1,
                                      TYPE_PROC,
                                      1,
                                      AttributeTank::ATTR_UNIT_POS_NA,
                                      AttributeTank::ATTR_NODE_NA,
                                      &l_val)))
            {
                TS_FAIL("tankTest3: Error. Did not get attr from tank (12)");
                break;
            }

            if (l_val != 4)
            {
                TS_FAIL("tankTest3: Error. Got bad value (0x%016llx) from tank (13)",
                        l_val);
                break;
            }

            // Check the second attribute made it back into the tank
            l_val2 = 0;
            if (!(l_tank.getAttribute(ATTR_SCRATCH_UINT32_1,
                                      TYPE_MBA,
                                      1,
                                      2,
                                      3,
                                      &l_val2)))
            {
                TS_FAIL("tankTest3: Error. Did not get attr from tank (14)");
                break;
            }

            if (l_val2 != 5)
            {
                TS_FAIL("tankTest3: Error. Got bad value (0x%llx) from tank (15)",
                        l_val);
                break;
            }

            // Free the memory in the attribute chunk
            free (l_attributes[0].iv_pAttributes);
            l_attributes[0].iv_pAttributes = NULL;
            l_attributes.clear();

            // Serialize all attributes from the tank into a two chunks
            // Use a chunk size small enough to only fit a single attribute
            l_tank.serializeAttributes(AttributeTank::ALLOC_TYPE_MALLOC,
                sizeof(AttributeTank::AttributeHeader) + sizeof(l_val) + 8,
                l_attributes);

            if (l_attributes.size() != 2)
            {
                TS_FAIL("tankTest3: Error. Got wrong number of chunks (%d) from tank (16)",
                        l_attributes.size());
                break;
            }

            if (l_attributes[0].iv_size !=
                (sizeof(AttributeTank::AttributeHeader) + sizeof(l_val)))
            {
                TS_FAIL("tankTest3: Error. Got wrong size (%d) of attrs from tank (17)",
                        l_attributes[0].iv_size);
                break;
            }

            l_pVal = reinterpret_cast<uint64_t *>
                (l_attributes[0].iv_pAttributes +
                 sizeof(AttributeTank::AttributeHeader));

            if (*l_pVal != 4)
            {
                TS_FAIL("tankTest3: Error. Got bad value (0x%016llx) from tank (18)",
                        *l_pVal);
                break;
            }

            if (l_attributes[1].iv_size !=
                (sizeof(AttributeTank::AttributeHeader) + sizeof(l_val2)))
            {
                TS_FAIL("tankTest3: Error. Got wrong size (%d) of attrs from tank (19)",
                        l_attributes[1].iv_size);
                break;
            }

            l_pVal2 = reinterpret_cast<uint32_t *>
                (l_attributes[1].iv_pAttributes +
                 sizeof(AttributeTank::AttributeHeader));

            if (*l_pVal2 != 5)
            {
                TS_FAIL("tankTest3: Error. Got bad value (0x%016llx) from tank (20)",
                        *l_pVal);
                break;
            }

            // Clear the tank
            l_tank.clearAllAttributes();

            // Deserialize the attributes back into the tank
            l_tank.deserializeAttributes(l_attributes[0]);
            l_tank.deserializeAttributes(l_attributes[1]);

            // Check the first attribute made it back into the tank
            l_val = 0;
            if (!(l_tank.getAttribute(ATTR_SCRATCH_UINT64_1,
                                      TYPE_PROC,
                                      1,
                                      AttributeTank::ATTR_UNIT_POS_NA,
                                      AttributeTank::ATTR_NODE_NA,
                                      &l_val)))
            {
                TS_FAIL("tankTest3: Error. Did not get attr from tank (21)");
                break;
            }

            if (l_val != 4)
            {
                TS_FAIL("tankTest3: Error. Got bad value (0x%016llx) from tank (22)",
                        l_val);
                break;
            }

            // Check the second attribute made it back into the tank
            l_val2 = 0;
            if (!(l_tank.getAttribute(ATTR_SCRATCH_UINT32_1,
                                      TYPE_MBA,
                                      1,
                                      2,
                                      3,
                                      &l_val2)))
            {
                TS_FAIL("tankTest3: Error. Did not get attr from tank (23)");
                break;
            }

            if (l_val2 != 5)
            {
                TS_FAIL("tankTest3: Error. Got bad value (0x%llx) from tank (24)",
                        l_val);
                break;
            }

            // Free the memory in the attribute chunks
            free (l_attributes[0].iv_pAttributes);
            l_attributes[0].iv_pAttributes = NULL;
            free (l_attributes[1].iv_pAttributes);
            l_attributes[1].iv_pAttributes = NULL;

        } while (0);

        TS_TRACE("tankTest3 complete" );
    }

    //**************************************************************************
    // tankTest4. Test AttributeTank functions with a constant attribute
    //**************************************************************************
    void test4(void)
    {
        do
        {
            // Create a local AttributeTank (this is not the singleton)
            AttributeTank l_tank;

            // Set const attribute
            uint8_t l_val = 4;
            l_tank.setAttribute(ATTR_SCRATCH_UINT8_1,
                                TYPE_SYS,
                                AttributeTank::ATTR_POS_NA,
                                AttributeTank::ATTR_UNIT_POS_NA,
                                AttributeTank::ATTR_NODE_NA,
                                AttributeTank::ATTR_FLAG_CONST,
                                sizeof(l_val), &l_val);

            // Try to clear the attribute, it should not be cleared
            l_tank.clearNonConstAttribute(ATTR_SCRATCH_UINT8_1,
                                          TYPE_SYS,
                                          AttributeTank::ATTR_POS_NA,
                                          AttributeTank::ATTR_UNIT_POS_NA,
                                          AttributeTank::ATTR_NODE_NA);

            // Check that tank is not-empty
            if (!l_tank.attributesExist())
            {
                TS_FAIL("tankTest4: Error. AttributeTank is empty (1)");
                break;
            }

            // Clear all attribute
            l_tank.clearAllAttributes();

            // Check that tank is empty
            if (l_tank.attributesExist())
            {
                TS_FAIL("tankTest4: Error. AttributeTank is not empty (2)");
                break;
            }

        } while (0);

        TS_TRACE("tankTest4 complete" );
    }

    //**************************************************************************
    // tankTest5. Test adding the same attribute twice to a tank
    //**************************************************************************
    void test5(void)
    {
        do
        {
            // Create a local AttributeTank (this is not the singleton)
            AttributeTank l_tank;

            // Add ATTR_SCRATCH_UINT64_1 to the tank twice (the second one
            // should replace the first
            uint64_t l_val = 4;
            l_tank.setAttribute(ATTR_SCRATCH_UINT64_1,
                                TYPE_SYS,
                                AttributeTank::ATTR_POS_NA,
                                AttributeTank::ATTR_UNIT_POS_NA,
                                1,
                                0, sizeof(l_val), &l_val);

            l_val = 5;
            l_tank.setAttribute(ATTR_SCRATCH_UINT64_1,
                                TYPE_SYS,
                                AttributeTank::ATTR_POS_NA,
                                AttributeTank::ATTR_UNIT_POS_NA,
                                1,
                                0, sizeof(l_val), &l_val);

            // Get the attribute from the tank
            l_val = 0;
            if (!(l_tank.getAttribute(ATTR_SCRATCH_UINT64_1,
                                      TYPE_SYS,
                                      AttributeTank::ATTR_POS_NA,
                                      AttributeTank::ATTR_UNIT_POS_NA,
                                      1,
                                      &l_val)))
            {
                TS_FAIL("tankTest5: Error. Did not get attr from tank (1)");
                break;
            }

            if (l_val != 5)
            {
                TS_FAIL("tankTest5: Error. Got bad value (0x%llx) from tank (2)",
                        l_val);
                break;
            }

            // Serialize all attributes from the tank
            std::vector<AttributeTank::AttributeSerializedChunk> l_attributes;
            l_tank.serializeAttributes(AttributeTank::ALLOC_TYPE_NEW,
                                       4096, l_attributes);

            if (l_attributes.size() != 1)
            {
                TS_FAIL("tankTest5: Error. Got wrong number of chunks (%d) from tank (3)",
                        l_attributes.size());
                break;
            }

            if (l_attributes[0].iv_size !=
                (sizeof(AttributeTank::AttributeHeader) + sizeof(l_val)))
            {
                TS_FAIL("tankTest5: Error. Got wrong size (%d) of attrs from tank (4)",
                        l_attributes[0].iv_size);
                break;
            }

            uint64_t * l_pVal = reinterpret_cast<uint64_t *>
                (l_attributes[0].iv_pAttributes +
                 sizeof(AttributeTank::AttributeHeader));

            if (*l_pVal != 5)
            {
                TS_FAIL("tankTest5: Error. Got bad value (0x%016llx) from tank (5)",
                        *l_pVal);
                break;
            }
            delete [] l_attributes[0].iv_pAttributes;
            l_attributes[0].iv_pAttributes = NULL;

        } while (0);

        TS_TRACE("tankTest5 complete" );
    }

    //**************************************************************************
    // tankTest6. Test AttributeTank clearAllAttributes with node filter
    //**************************************************************************
    void test6(void)
    {
        do
        {
            // Create a local AttributeTank
            AttributeTank l_tank;

            // Add an attribute for NODE_NA to the tank
            uint64_t l_val = 4;
            l_tank.setAttribute(ATTR_SCRATCH_UINT64_1,
                                TYPE_PROC,
                                1,
                                AttributeTank::ATTR_UNIT_POS_NA,
                                AttributeTank::ATTR_NODE_NA,
                                0, sizeof(l_val), &l_val);

            // Add an attribute for node 3 to the tank
            uint32_t l_val2 = 5;
            l_tank.setAttribute(ATTR_SCRATCH_UINT32_1,
                                TYPE_MBA,
                                1,
                                2,
                                3,
                                0, sizeof(l_val2), &l_val2);

            // Clear NOT_ALL_NODES attributes
            l_tank.clearAllAttributes(AttributeTank::NODE_FILTER_NOT_ALL_NODES);

            // Get the NODE_NA attribute from the tank
            l_val = 0;
            if (!(l_tank.getAttribute(ATTR_SCRATCH_UINT64_1,
                                      TYPE_PROC,
                                      1,
                                      AttributeTank::ATTR_UNIT_POS_NA,
                                      AttributeTank::ATTR_NODE_NA,
                                      &l_val)))
            {
                TS_FAIL("tankTest6: Error. Did not get attr from tank (1)");
                break;
            }

            if (l_val != 4)
            {
                TS_FAIL("tankTest6: Error. Got bad value (0x%llx) from tank (2)",
                        l_val);
                break;
            }

            // Try to get the node 3 attribute from the tank (should be cleared)
            l_val2 = 0;
            if (l_tank.getAttribute(ATTR_SCRATCH_UINT32_1,
                                    TYPE_MBA,
                                    1,
                                    2,
                                    3,
                                    &l_val2))
            {
                TS_FAIL("tankTest6: Error. Got cleared attr from tank (3)");
                break;
            }

            // Add the node 3 attribute back to the tank
            l_val2 = 5;
            l_tank.setAttribute(ATTR_SCRATCH_UINT32_1,
                                TYPE_MBA,
                                1,
                                2,
                                3,
                                0, sizeof(l_val2), &l_val2);

            // Clear SPECIFIC_NODE_AND_ALL attributes for node 6
            l_tank.clearAllAttributes(
                AttributeTank::NODE_FILTER_SPECIFIC_NODE_AND_ALL, 6);

            // Try to get the NODE_NA attribute from the tank (should be
            // cleared)
            l_val = 0;
            if (l_tank.getAttribute(ATTR_SCRATCH_UINT64_1,
                                    TYPE_PROC,
                                    1,
                                    AttributeTank::ATTR_UNIT_POS_NA,
                                    AttributeTank::ATTR_NODE_NA,
                                    &l_val))
            {
                TS_FAIL("tankTest6: Error. Got cleared attr from tank (4)");
                break;
            }

            // Get the node 3 attribute from the tank
            l_val2 = 0;
            if (!(l_tank.getAttribute(ATTR_SCRATCH_UINT32_1,
                                      TYPE_MBA,
                                      1,
                                      2,
                                      3,
                                      &l_val2)))
            {
                TS_FAIL("tankTest6: Error. Did not get attr from tank (5)");
                break;
            }

            if (l_val2 != 5)
            {
                TS_FAIL("tankTest6: Error. Got bad value (0x%llx) from tank (6)",
                        l_val2);
                break;
            }

            // Add the NODE_NA attribute back to the tank
            l_val = 4;
            l_tank.setAttribute(ATTR_SCRATCH_UINT64_1,
                                TYPE_PROC,
                                1,
                                AttributeTank::ATTR_UNIT_POS_NA,
                                AttributeTank::ATTR_NODE_NA,
                                0, sizeof(l_val), &l_val);

            // Clear SPECIFIC_NODE_AND_ALL attributes for node 3
            l_tank.clearAllAttributes(
                AttributeTank::NODE_FILTER_SPECIFIC_NODE_AND_ALL, 3);

            // Try to get the NODE_NA attribute from the tank (should be
            // cleared)
            l_val = 0;
            if (l_tank.getAttribute(ATTR_SCRATCH_UINT64_1,
                                    TYPE_PROC,
                                    1,
                                    AttributeTank::ATTR_UNIT_POS_NA,
                                    AttributeTank::ATTR_NODE_NA,
                                    &l_val))
            {
                TS_FAIL("tankTest6: Error. Got cleared attr from tank (7)");
                break;
            }

            // Try to get the node 3 attribute from the tank (should be cleared)
            l_val2 = 0;
            if (l_tank.getAttribute(ATTR_SCRATCH_UINT32_1,
                                    TYPE_MBA,
                                    1,
                                    2,
                                    3,
                                    &l_val2))
            {
                TS_FAIL("tankTest6: Error. Got cleared attr from tank (8)");
                break;
            }

            // Add the NODE_NA attribute back to the tank
            l_val = 4;
            l_tank.setAttribute(ATTR_SCRATCH_UINT64_1,
                                TYPE_PROC,
                                1,
                                AttributeTank::ATTR_UNIT_POS_NA,
                                AttributeTank::ATTR_NODE_NA,
                                0, sizeof(l_val), &l_val);

            // Add the node 3 attribute back to the tank
            l_val2 = 5;
            l_tank.setAttribute(ATTR_SCRATCH_UINT32_1,
                                TYPE_MBA,
                                1,
                                2,
                                3,
                                0, sizeof(l_val2), &l_val2);

            // Clear SPECIFIC_NODE attributes for node 6
            l_tank.clearAllAttributes(
                AttributeTank::NODE_FILTER_SPECIFIC_NODE, 6);

            // Get the NODE_NA attribute from the tank
            l_val = 0;
            if (!(l_tank.getAttribute(ATTR_SCRATCH_UINT64_1,
                                      TYPE_PROC,
                                      1,
                                      AttributeTank::ATTR_UNIT_POS_NA,
                                      AttributeTank::ATTR_NODE_NA,
                                      &l_val)))
            {
                TS_FAIL("tankTest6: Error. Did not get attr from tank (9)");
                break;
            }

            if (l_val != 4)
            {
                TS_FAIL("tankTest6: Error. Got bad value (0x%llx) from tank (10)",
                        l_val);
                break;
            }

            // Get the node 3 attribute from the tank
            l_val2 = 0;
            if (!(l_tank.getAttribute(ATTR_SCRATCH_UINT32_1,
                                      TYPE_MBA,
                                      1,
                                      2,
                                      3,
                                      &l_val2)))
            {
                TS_FAIL("tankTest6: Error. Did not get attr from tank (11)");
                break;
            }

            if (l_val2 != 5)
            {
                TS_FAIL("tankTest6: Error. Got bad value (0x%llx) from tank (12)",
                        l_val2);
                break;
            }

            // Clear SPECIFIC_NODE attributes for node 3
            l_tank.clearAllAttributes(
                AttributeTank::NODE_FILTER_SPECIFIC_NODE, 3);

            // Get the NODE_NA attribute from the tank
            l_val = 0;
            if (!(l_tank.getAttribute(ATTR_SCRATCH_UINT64_1,
                                      TYPE_PROC,
                                      1,
                                      AttributeTank::ATTR_UNIT_POS_NA,
                                      AttributeTank::ATTR_NODE_NA,
                                      &l_val)))
            {
                TS_FAIL("tankTest6: Error. Did not get attr from tank (13)");
                break;
            }

            if (l_val != 4)
            {
                TS_FAIL("tankTest6: Error. Got bad value (0x%llx) from tank (14)",
                        l_val);
                break;
            }

            // Try to get the node 3 attribute from the tank (should be cleared)
            l_val2 = 0;
            if (l_tank.getAttribute(ATTR_SCRATCH_UINT32_1,
                                    TYPE_MBA,
                                    1,
                                    2,
                                    3,
                                    &l_val2))
            {
                TS_FAIL("tankTest6: Error. Got cleared attr from tank (15)");
                break;
            }

        } while (0);

        TS_TRACE("tankTest6 complete" );
    }

    //**************************************************************************
    // tankTest7. Test AttributeTank clearNonConstAttribute
    //**************************************************************************
    void test7(void)
    {
        do
        {
            // Create a local AttributeTank
            AttributeTank l_tank;

            // Add a const attribute for node 3 to the tank
            uint32_t l_val2 = 5;
            l_tank.setAttribute(ATTR_SCRATCH_UINT32_1,
                                TYPE_MBA,
                                1,
                                2,
                                3,
                                AttributeTank::ATTR_FLAG_CONST,
                                sizeof(l_val2), &l_val2);

            // Try to clear the attribute, it should not be cleared
            l_tank.clearNonConstAttribute(ATTR_SCRATCH_UINT32_1,
                                          TYPE_MBA,
                                          1,
                                          2,
                                          3);

            // Get the node 3 attribute from the tank
            l_val2 = 0;
            if (!(l_tank.getAttribute(ATTR_SCRATCH_UINT32_1,
                                      TYPE_MBA,
                                      1,
                                      2,
                                      3,
                                      &l_val2)))
            {
                TS_FAIL("tankTest7: Error. Did not get attr from tank (1)");
                break;
            }

            if (l_val2 != 5)
            {
                TS_FAIL("tankTest7: Error. Got bad value (0x%llx) from tank (2)",
                        l_val2);
                break;
            }

            // Clear all attributes from the tank
            l_tank.clearAllAttributes();

            // Add a non-const attribute for node 3 to the tank
            l_val2 = 5;
            l_tank.setAttribute(ATTR_SCRATCH_UINT32_1,
                                TYPE_MBA,
                                1,
                                2,
                                3,
                                0,
                                sizeof(l_val2), &l_val2);

            // Try to clear the attribute with node 1, it should not be cleared
            l_tank.clearNonConstAttribute(ATTR_SCRATCH_UINT32_1,
                                          TYPE_MBA,
                                          1,
                                          2,
                                          1);

            // Get the node 3 attribute from the tank
            l_val2 = 0;
            if (!(l_tank.getAttribute(ATTR_SCRATCH_UINT32_1,
                                      TYPE_MBA,
                                      1,
                                      2,
                                      3,
                                      &l_val2)))
            {
                TS_FAIL("tankTest7: Error. Did not get attr from tank (3)");
                break;
            }

            if (l_val2 != 5)
            {
                TS_FAIL("tankTest7: Error. Got bad value (0x%llx) from tank (4)",
                        l_val2);
                break;
            }

            // Clear the attribute
            l_tank.clearNonConstAttribute(ATTR_SCRATCH_UINT32_1,
                                          TYPE_MBA,
                                          1,
                                          2,
                                          3);

            // Try to get the node 3 attribute from the tank (should be cleared)
            l_val2 = 0;
            if (l_tank.getAttribute(ATTR_SCRATCH_UINT32_1,
                                    TYPE_MBA,
                                    1,
                                    2,
                                    3,
                                    &l_val2))
            {
                TS_FAIL("tankTest7: Error. Got cleared attr from tank (5)");
                break;
            }

        } while (0);

        TS_TRACE("tankTest7 complete" );
    }

    /**
     * @brief Test BMC Attr Override function
     *        Set attributes into 3 different tanks. Then place overrides in
     *        both correct/incorrect simulated pnor sections. Finally call
     *        getAttrOverrides to deserialize each sections data and verify
     *        that it did not apply incorrect overrides and applied correct ones
     *
     */
    void testBMCAttrOverride(void)
    {
        errlHndl_t l_errhdl = NULL;
        const uint64_t l_chunkSize = 4096;

        // Simulate Pnor ATTR_TMP and ATTR_PERM sections in memory
        PNOR::SectionInfo_t l_attrTmpSec;
        l_attrTmpSec.id = PNOR::ATTR_TMP;
        l_attrTmpSec.name = "Test Attr Tmp";
        l_attrTmpSec.vaddr = reinterpret_cast<uint64_t>(malloc(3*l_chunkSize));

        PNOR::SectionInfo_t l_attrPermSec;
        l_attrPermSec.id = PNOR::ATTR_PERM;
        l_attrPermSec.name = "Test Attr Perm";
        l_attrPermSec.vaddr = reinterpret_cast<uint64_t>(malloc(3*l_chunkSize));

        // This test needs Attribute Overrides to work, so save global variable
        // before setting it to 'true' for the duration of this test
        bool save_allowAttrOverrides = g_BlToHbDataManager.iv_data.allowAttrOverrides;
        g_BlToHbDataManager.iv_data.allowAttrOverrides = true;
        TS_TRACE("testBMCAttrOverride: saved Allow Attr Override (%d) and set to true", save_allowAttrOverrides);

        do
        {
            // Create local AttributeTanks
            AttributeTank l_FapiTank;
            AttributeTank l_TargetTank;
            AttributeTank l_PermTank;

            // Create local array of those tanks
            AttributeTank* l_tanks[AttributeTank::TANK_LAYER_LAST];

            // Create Attr Overrides
            // Add ATTR_SCRATCH_UINT64_1 to the Fapi tank
            uint64_t l_val = 4;
            l_FapiTank.setAttribute(ATTR_SCRATCH_UINT64_1,
                                    TYPE_PROC,
                                    AttributeTank::ATTR_POS_NA,
                                    AttributeTank::ATTR_UNIT_POS_NA,
                                    AttributeTank::ATTR_NODE_NA,
                                    0, sizeof(l_val), &l_val);

            // Add ATTR_SCRATCH_UINT64_1 to the Target tank
            l_TargetTank.setAttribute(ATTR_SCRATCH_UINT64_1,
                                      TYPE_PROC,
                                      1,
                                      AttributeTank::ATTR_UNIT_POS_NA,
                                      AttributeTank::ATTR_NODE_NA,
                                      0, sizeof(l_val), &l_val);
            // Add ATTR_SCRATCH_UINT64_1 to the Perm tank
            l_PermTank.setAttribute(ATTR_SCRATCH_UINT64_1,
                                    TYPE_PROC,
                                    1,
                                    AttributeTank::ATTR_UNIT_POS_NA,
                                    AttributeTank::ATTR_NODE_NA,
                                    0, sizeof(l_val), &l_val);

            ////////////////////////////////////////////////////////////////////
            // Fill in simulated pnor sections
            // Add a fapi, targ, and perm overrides to both sections to test
            // catching incorrect ones and applying the correct ones

            uint32_t l_permIndex = 0;
            uint32_t l_tmpIndex = 0;
            AttrOverrideSection * l_pAttrOverSec = NULL;
            AttributeTank::AttributeSerializedChunk l_chunk;

            // Fapi - Serialize all attributes from each tank
            AttributeTank::AttributeSerializedChunks_t l_attributes;
            l_FapiTank.serializeAttributes(AttributeTank::ALLOC_TYPE_NEW,
                    l_chunkSize, l_attributes);

            // Copy Fapi Overrides to test tmp and perm sections
            for (AttributeTank::AttributeSerializedChunks_t::iterator
                    chunkIter = l_attributes.begin();
                    chunkIter != l_attributes.end();
                    ++chunkIter)
            {
                l_chunk = *chunkIter;

                // handle tmp section
                l_pAttrOverSec = reinterpret_cast<AttrOverrideSection *>
                                        (l_attrTmpSec.vaddr + l_tmpIndex);
                l_pAttrOverSec->iv_layer = AttributeTank::TANK_LAYER_FAPI;
                l_pAttrOverSec->iv_size = l_chunk.iv_size;
                memcpy(&l_pAttrOverSec->iv_chunk, l_chunk.iv_pAttributes,
                        l_chunk.iv_size);
                l_tmpIndex += sizeof(AttrOverrideSection)+
                                        l_pAttrOverSec->iv_size;

                // handle perm section
                l_pAttrOverSec = reinterpret_cast<AttrOverrideSection *>
                                        (l_attrPermSec.vaddr + l_permIndex);
                l_pAttrOverSec->iv_layer = AttributeTank::TANK_LAYER_FAPI;
                l_pAttrOverSec->iv_size = l_chunk.iv_size;
                memcpy(&l_pAttrOverSec->iv_chunk, l_chunk.iv_pAttributes,
                        l_chunk.iv_size);
                l_permIndex += sizeof(AttrOverrideSection)+
                                        l_pAttrOverSec->iv_size;
            }

            // Targeting - Serialize all attributes from tank
            l_attributes.clear();
            l_TargetTank.serializeAttributes(AttributeTank::ALLOC_TYPE_NEW,
                    l_chunkSize, l_attributes);

            // Copy Target Override chunk to test tmp and perm sections
            for (AttributeTank::AttributeSerializedChunks_t::iterator
                    chunkIter = l_attributes.begin();
                    chunkIter != l_attributes.end();
                    ++chunkIter)
            {
                l_chunk = *chunkIter;

                // handle tmp section
                l_pAttrOverSec = reinterpret_cast<AttrOverrideSection *>
                                        (l_attrTmpSec.vaddr + l_tmpIndex);
                l_pAttrOverSec->iv_layer = AttributeTank::TANK_LAYER_TARG;
                l_pAttrOverSec->iv_size = l_chunk.iv_size;
                memcpy(&l_pAttrOverSec->iv_chunk, l_chunk.iv_pAttributes,
                        l_chunk.iv_size);
                l_tmpIndex += sizeof(AttrOverrideSection)+
                                        l_pAttrOverSec->iv_size;

                // handle perm section
                l_pAttrOverSec = reinterpret_cast<AttrOverrideSection *>
                                        (l_attrPermSec.vaddr + l_permIndex);
                l_pAttrOverSec->iv_layer = AttributeTank::TANK_LAYER_TARG;
                l_pAttrOverSec->iv_size = l_chunk.iv_size;
                memcpy(&l_pAttrOverSec->iv_chunk, l_chunk.iv_pAttributes,
                        l_chunk.iv_size);
                l_permIndex += sizeof(AttrOverrideSection)+
                                        l_pAttrOverSec->iv_size;
            }

            // Permanent - Serialize all attributes from tank
            l_attributes.clear();
            l_PermTank.serializeAttributes(AttributeTank::ALLOC_TYPE_NEW,
                    l_chunkSize, l_attributes);

            // Copy Perm Override chunk to test tmp and perm sections
            for (AttributeTank::AttributeSerializedChunks_t::iterator
                    chunkIter = l_attributes.begin();
                    chunkIter != l_attributes.end();
                    ++chunkIter)
            {
                l_chunk = *chunkIter;

                // handle tmp section
                l_pAttrOverSec = reinterpret_cast<AttrOverrideSection *>
                                        (l_attrTmpSec.vaddr + l_tmpIndex);
                l_pAttrOverSec->iv_layer = AttributeTank::TANK_LAYER_PERM;
                l_pAttrOverSec->iv_size = l_chunk.iv_size;
                memcpy(&l_pAttrOverSec->iv_chunk, l_chunk.iv_pAttributes,
                        l_chunk.iv_size);
                l_tmpIndex += sizeof(AttrOverrideSection)+
                                        l_pAttrOverSec->iv_size;

                // handle perm section
                l_pAttrOverSec = reinterpret_cast<AttrOverrideSection *>
                                        (l_attrPermSec.vaddr + l_permIndex);
                l_pAttrOverSec->iv_layer = AttributeTank::TANK_LAYER_PERM;
                l_pAttrOverSec->iv_size = l_chunk.iv_size;
                memcpy(&l_pAttrOverSec->iv_chunk, l_chunk.iv_pAttributes,
                        l_chunk.iv_size);
                l_permIndex += sizeof(AttrOverrideSection)+
                                        l_pAttrOverSec->iv_size;
            }

            // Add termination section

            // handle tmp section
            l_pAttrOverSec = reinterpret_cast<AttrOverrideSection *>
                                    (l_attrTmpSec.vaddr + l_tmpIndex);
            l_pAttrOverSec->iv_layer = AttributeTank::TANK_LAYER_TERM;
            l_pAttrOverSec->iv_size = 0;
            l_tmpIndex += sizeof(AttrOverrideSection);

            // handle perm section
            l_pAttrOverSec = reinterpret_cast<AttrOverrideSection *>
                                    (l_attrPermSec.vaddr + l_permIndex);
            l_pAttrOverSec->iv_layer = AttributeTank::TANK_LAYER_TERM;
            l_pAttrOverSec->iv_size = 0;
            l_permIndex += sizeof(AttrOverrideSection);

            // Update final size of created section
            l_attrTmpSec.size = l_tmpIndex;
            l_attrPermSec.size = l_permIndex;

            ////////////////////////////////////////////////////////////////////
            // Test simulated pnor sections attr overrides

            // Test Attr Tmp - should only include Fapi and Targ overrides
            l_FapiTank.clearAllAttributes();
            l_TargetTank.clearAllAttributes();
            l_PermTank.clearAllAttributes();

            l_tanks[AttributeTank::TANK_LAYER_FAPI-1] = &l_FapiTank;
            l_tanks[AttributeTank::TANK_LAYER_TARG-1] = &l_TargetTank;
            l_tanks[AttributeTank::TANK_LAYER_PERM-1] = &l_PermTank;

            // Call function that actually reads in attribute overrides
            l_errhdl = getAttrOverrides(l_attrTmpSec, l_tanks);

            if (l_errhdl)
            {
                errlCommit(l_errhdl, TARG_COMP_ID);
                TS_FAIL("testattrtank::testBMCAttrOverride getAttrOverrides() failed");
                break;
            }

            ////////////////////////////////////////////////////////////////////
            // Check the first attribute made it back into the Fapi tank
            l_val = 0;
            if (!(l_FapiTank.getAttribute(ATTR_SCRATCH_UINT64_1,
                                          TYPE_PROC,
                                          AttributeTank::ATTR_POS_NA,
                                          AttributeTank::ATTR_UNIT_POS_NA,
                                          AttributeTank::ATTR_NODE_NA,
                                          &l_val)))
            {
                TS_FAIL("testattrtank::testBMCAttrOverride: Error. Did not get attr from Fapi Tank");
                break;
            }
            if (l_val != 4)
            {
                TS_FAIL("testattrtank::testBMCAttrOverride: Error. Got bad value (0x%X) from Fapi Tank",
                        l_val);
                break;
            }

            // Check the first attribute made it back into the Target tank
            l_val = 0;
            if (!(l_TargetTank.getAttribute(ATTR_SCRATCH_UINT64_1,
                                            TYPE_PROC,
                                            1,
                                            AttributeTank::ATTR_UNIT_POS_NA,
                                            AttributeTank::ATTR_NODE_NA,
                                            &l_val)))
            {
                TS_FAIL("testattrtank::testBMCAttrOverride: Error. Did not get attr from Target Tank");
                break;
            }
            if (l_val != 4)
            {
                TS_FAIL("testattrtank::testBMCAttrOverride: Error. Got bad value (0x%X) from Target Tank",
                        l_val);
                break;
            }

            // Check to make sure no Permanent overrides were applied
            if (l_PermTank.size() > 0)
            {
                TS_FAIL("testattrtank::testBMCAttrOverride: Error. A permanent override was found and applied in the PNOR::TMP section");
                break;
            }

            // Test Attr Perm - should only include Perm overrides
            l_tanks[AttributeTank::TANK_LAYER_FAPI-1]->clearAllAttributes();
            l_tanks[AttributeTank::TANK_LAYER_TARG-1]->clearAllAttributes();
            l_tanks[AttributeTank::TANK_LAYER_PERM-1]->clearAllAttributes();

            // Call function that actually reads in attribute overrides
            l_errhdl = getAttrOverrides(l_attrPermSec, l_tanks);

            // Check the first attribute made it back into the Perm tank
            l_val = 0;
            if (!(l_PermTank.getAttribute(ATTR_SCRATCH_UINT64_1,
                                          TYPE_PROC,
                                          1,
                                          AttributeTank::ATTR_UNIT_POS_NA,
                                          AttributeTank::ATTR_NODE_NA,
                                          &l_val)))
            {
                TS_FAIL("testattrtank::testBMCAttrOverride: Error. Did not get attr from Perm Tank");
                break;
            }
            if (l_val != 4)
            {
                TS_FAIL("testattrtank::testBMCAttrOverride: Error. Got bad value (0x%X) from Perm Tank",
                        l_val);
                break;
            }
            // Check to make sure no Fapi overrides were applied
            if (l_FapiTank.size() > 0)
            {
                TS_FAIL("testattrtank::testBMCAttrOverride: Error. A fapi override was found and applied in the PNOR::PERM section");
                break;
            }
            // Check to make sure no Targ overrides were applied
            if (l_TargetTank.size() > 0)
            {
                TS_FAIL("testattrtank::testBMCAttrOverride: Error. A targ override was found and applied in the PNOR::PERM section");
                break;
            }

        } while(0);

        // Restore Allow Attr Override Setting
        g_BlToHbDataManager.iv_data.allowAttrOverrides = save_allowAttrOverrides;
        TS_TRACE("testBMCAttrOverride: restored Allow Attr Override (%d)", save_allowAttrOverrides);

        // Free memory
        free (reinterpret_cast<char *>(l_attrTmpSec.vaddr));
        free (reinterpret_cast<char *>(l_attrPermSec.vaddr));
    }

    /**
     * @brief Test to check if the const array tankLayerToPnor is sorted
     *        which also indicates in enum order
     */
    void testTankLayerToPnorSorted(void)
    {
        for (size_t i = 0; i < (AttributeTank::TANK_LAYER_LAST - 1); ++i)
        {
            if (tankLayerToPnor[i].first > tankLayerToPnor[i+1].first)
            {
                TS_FAIL("testattrtank::testTankLayerToPnorSorted: attrPlatOverride.H tankLayerToPnor[] is not sorted");
            }
        }
    }
};

#endif


Lease Terms: 12 months. Short term leases available on all one bedroom units.3 Month lease & 6 Month LeasesSecurity Deposit: 1 Month rent Or $500 if qualified. Pet Policy: 2 pets maximum with a $30/month pet fee, $250 Non-refundable pet deposit per pet. Dogs: breed restrictions apply.
1-3bd, 1-2ba • 1,356 sq. ft.


Learning to hit the golf ball requires integrating the senses and movement to make enough power from the swing action to obtain your ball to target. A golfer must coordinate all the muscles used in the movement like a unit and generate enough speed and power through this process to obtain the desired result. To learn and practice the swing movement is usually to modify this method through time until muscle movements are smooth and automatic as well as the result accurate.
1. Don't Talk Bad About People — One major lesson while attending college is usually to try and talk good about your peers or don't say anything at all. For some people this really is hard and not impossible. If you talk well about people or give non-conclusive answers about your classmates or roommates then you certainly will be more liked as well as your time attending school will go much more smoothly. If you say negative reasons for your classmates and roommates then individuals will eventually shun you together with start saying bad reasons for you and your college experience could be quickly ruined. This isn't secondary school, you are designed to start acting like an adult so start being mature.
Another fun and interesting event to host would be marathons. In here, you can decide to have walk-a-thons or bike-a-thons. Like the latter, this will likely allow you to gather an enormous crowd that may more than likely be made up of proud parents. Choose a good venue in which you will have enough space for your event. If your school features a soccer field which is large enough for this, you can try to make use of that. Like the latter, additionally you have to set up an admission or registration fee just for this. Print numbers which will be placed on the shirts of your respective participants so that they get the feel that these are really doing a marathon. This will get students and parents really excited. You can try picking a prize for the winner. On the other hand, you'll be able to also try doing things differently by telling your students to inquire about pledges using their parents per lap that they can be able to finish. For example, if someone of your students grows to finish one lap, their parents will donate $5. Be sure to provide refreshments for the students because they will certainly be tired as soon as the marathon is over.
The training uses on-page exhibition and allow the entire group of students get the job done first hand on actual customers. This is done to provide them courage on themselves to perform the job well. The teachers are all professionals and also have rendered hundreds of hours with this sort of work so studying under them is basically great. Each teacher is licensed to train and licensed by the California education Department and that means you are sure you're managing the pros.


text:
Q: C++ templates declaration is not visible I have following code:
#include <cstddef>
#include <cstdint>

using ReadIteratorType = Buffer::iterator;
using WriteIteratorType = Buffer::iterator;

template <typename TReadIterator, typename TWriteIterator>
class FieldBase
{
public:
    using ReadIterator = TReadIterator;
    using WriteIterator = TWriteIterator;

    virtual void read(ReadIterator& readIterator, std::size_t& len) = 0;
    virtual void write(WriteIterator& writeIterator, std::size_t& len) = 0;
};

template <typename TValue>
class Field : public FieldBase<ReadIteratorType, WriteIteratorType>
{
public:
    using ValueType = TValue;

    virtual const ValueType& getValue() const { return m_value; };
    virtual void setValue(const ValueType& value) { m_value = value;}
    constexpr std::size_t length() { return sizeof(TValue); }

protected:
    ValueType m_value {};
};

template <typename T>
class IntField : public Field<T>
{
public:

    void read(ReadIterator& readIterator, std::size_t& len) override
    {

    }

    void write(WriteIterator& writeIterator, std::size_t& len) override
    {

    }
};

Whenever I try to compile this particular code I have t

error: 'ReadIterator' has not been declared
       void read(ReadIterator& readIterator, std::size_t& len) override
error: 'WriteIterator' has not been declared
       void write(WriteIterator& writeIterator, std::size_t& len) override

But if I change definition IntField class to class IntField : public Field or whatever that has certain type it compiles properly. Why the IntField can't be template in current context?

A: This is a well-known problem. Compiler doesn't know that ReadIterator needs to come from the templated base class, as it tries to resolve the name during first step of template instantiation. You might find more information on the 2-phase name lookup here: http://blog.llvm.org/2009/12/dreaded-two-phase-name-lookup.html
You need to be verbose here:
void read(typename Field<T>::ReadIterator& readIterator, std::size_t& len) override

Or, to save some typing:
using base_t = Field<T>;
void read(typename base_t::ReadIterator& readIterator, std::size_t& len) override

On a side note, your code doesn't make a huge lot of sense to me. I would expect your IntField to not be a template:
class IntField : public Field<int>
// ...

redpajama_set_name: RedPajamaStackExchange


"Practice what you preach� ultimately got me into this mess. I kept telling my children and my students that if you are not happy, make a change and change is a scary place!! So here I am, making a change and starting from scratch; leaving a well paying, coveted teaching position to follow my bliss and face my fears.
Chasing Euphoria, is the blog journal of my journey into the gorgeous, terrifying unknown. Going from a full-time salary to a line of credit paycheck, I am chasing my dream, writing a book and living my theory that if we lead our lives with our inner passions, the rest (and the money) will follow. Ultimately, Chasing Euphoria is the result and beauty of my second disaster.
I am currently working on my first book, The Beauty of Disaster, a self-help motivational memoir and guide to offer people a positive perspective on the disasters we face in life.
Inspired by the flood I experienced in Minden, Ontario in the spring of 2013, I take you through my personal experiences, introduce you to my perfect bully as I realize the pitfalls of compassion, the freedom of pain, and accept and release my inner dandelion in my blog Chasing Euphoria.
I question the intellectual focus of education. I offer insight into our childhood bully and I give practical tools to make change. My goal is to empower compassionate people, our greatest commodity, and reduce the power of the intellectual bully.
ready for sale by the spring of 2014.
My dear precious friend, I am Euphoric about reading the 1st two entries. Absolutely from the heart - love Melody Beattie! And you even more! Keep being brave vulnerable and strong!!
I just read your first entry. Amazing. Inspiring, truthful and expressive. I loved it. I've been journaling more lately as well. Reading one of your entries will become part of that process!
I love it. I feel like we are talking to each other face to face. You are opening my mind. I can hardly wait to read more.
Dear Sweet Pea is an advice column for people of all ages looking for a fresh perspective on a problem in order to move beyond the problem with love and learning. I have often found that a simple shift in perspective was all I needed to help navigate the rapids of life. It is a long-term goal and dream of mine to start such an advice column.
My push into article writing began with the Minden flood. A series of 4 articles was accepted by The Minden Times. Sadly, due to employment circumstances, I made the difficult choice to publish only the first and last articles. Gratefully, I enjoyed article writing so much that I want to write more. Check out the list of topics and titles (Services – "Workshops, Seminars and Presentations�) for potential articles I can write for your paper, magazine or newsletter.
Thank you for sending the articles-just have read the first one, and I look forward to reading the rest. You are bringing something good to the world. Â The experience of reading the article I found gentle and so that helped me read in a reflective way. Bravo!
As I sit in my parents home and my mother's beautiful art studio I reflect on the happenings in Minden and all that has happened to me, to my neighbours, to my community, and all of the conversations that I have had involving and revolving around the flood waters that surround my home and my community.
Like so many others, on Sunday I evacuated out of my home on Invergordon Avenue, and like so many others have watched the river waters rise and fall and rise again around my home, my neighbourhood, and my community. Like so many others I count my blessings that my situation is not as bad as the people down the road from me who have been under water since Friday, and I experience a sense of guilt and gratitude every day when I paddle along my road to my home to discover that my basement is still dry and my sump pump is keeping my house safe. I wish I could say the same for my wonderful neighbours with whom I am sharing this pivotal and life changing experience.
It is precisely that life changing experience that I will write about in this and subsequent pieces. As things seem to work in my mind, odd thoughts appear out of nowhere, and this morning, after shedding tears listening to the woman on the radio talk of the stress the evacuees must be feeling because their home and place of refuge is under water, the song from my childhood church days sang, "Peace is Flowing Like a River, Flowing out of you and me, Flowing out into the desert, Setting all the captives free.� Using those four lines I will write four pieces about this experience.
All of us are wondering why. All of us are wondering how. All of us are wondering what next. All of us are wondering who is responsible. And all of us have been given an opportunity to find great strength and change in this difficult and challenging situation. In a conversation with my neighbours we discussed lightly and heatedly our frustrations, our speculations, our concerns, and our wonders; all of which left us spinning in a place of unknown waters. Within that conversation came the questions: what are we going to do? How can we make change? And I have decided that as writer, it is here that I will start the process.
I see this tragedy as a means of creating great change and that Minden has the opportunity to lead the way to new and better things because we are great and caring people. That said, we also have to honour the fact that we are hurting. Floods pull things up and flush them away. The longer this flood lasts, more pain will surface and more help will be needed, especially for the victims of the flood, to help flush this pain away. We are all experiencing the pulling of things and frustrations and resentments that are ages old and deep into the recesses of our minds that we have buried.
I myself am experiencing that very thing on many levels: you "suck it up,� count your blessings, keep feelings and emotions in check, and get on with it because you have responsibilities. You just have to put it out of your head and be strong. Well I am strong, but I cannot put it out of my head and the speed with which this experience dropped me into a depressive state caught me off guard. It was difficult to admit that I needed help. It was very difficult to cry publicly and lose emotional control. It was extremely difficult to admit that I couldn't continue at work; that I had to get a doctor's note and admit that I was depressed. And I am fortunate enough to have a job where I can get the time off and that mental health services are available to me. I am fortunate to have parents living in the area with a place for my children and I to stay. I am fortunate that my basement is holding steady despite the fact that the only way to access it is to canoe along Invergordon. For me to admit that I need time off work, that I need mental health assistance, that I am not strong enough to cope with this alone are just a few of the many fearful areas that those of us directly impacted by this flood have to face.
In all of this so many different levels of our societal structures and beliefs will come into question: How do we deal with feelings that the powers that be "withhold information� – that politicians and leaders cannot tell it to us straight for fear of litigation? How do we cope with the frustration that the information received is so ambiguous and "cover-your-backside like� that no one really knows anything? That there is so much bureaucratic red tape that nothing will get done in an expedient manner? That our town councilors, even though they want to show compassion and offer true financial assistance can't, because the paperwork process is a flood unto itself? And our children? How can we help them through the stress they are experiencing and give them the tools to find their own peace as the very place they call home is surrounded by water?
As we move through this it is my dream that true compassionate leadership will emerge. That people who have the power to change financial compensation, like government and insurance companies will make it happen and cut the red tape that has us tied in knots. Sadly, I do not hang my hopes of change there.
Instead I hope that as a community we find acceptance, set aside blame, make change, find learning and peace. We are all good people; good people who are living in a world of fear. Together we will help each other, support each other and ourselves through this extremely difficult experience. Together we will find beautiful opportunities that this experience will bring, including embracing the tears, angers and frustrations. It is time for all of those emotions that are surfacing as a symptom of this flood, all of the things, if we are to be brutally honest, that have bothered us for years, to surface, to be expressed, and to be washed away as the waters recede so that we can replace our inner homes with a foundation and structure that is more to our joy versus our prison.
Some of us will have to go further than others. Some of us will have to lead the way. All of us will have to find what we want to change and change it. We can make the world watch and we can be the model that leads the way. Let us do so with compassion. Let us show the world how we wash away our pain and rebuild with love and community versus anger and resentment so that we can return to our peace which flows like a river.


text:
The Great Gorge of the Ruth Glacier
Download Original Article
An overview of Alaska's legendary alpine valley
Author: Joseph Puryear
Set in the heart of the central Alaska Range, the Great Gorge of the Ruth Glacier is a massive geographic rift that has shaped a climbing area like no other. More than 20 peaks border the sides of the north-south-trending valley, with walls up to 5,000 feet rising directly off the smooth and gentle glacier that lines the floor. Although not often compared to Yosemite, up north this is the Valley, Alaska-style. With easy approaches and huge walls just a short distance from a fly-in base camp, the Ruth Gorge may be North America's ultimate alpine climbing destination. However, climbers won't always find endless splitters, perfect granite, plastic ice, and ideal weather. Instead, they will find some of the most intimidating mountains in the world. Written into the history of these walls are stories of struggle, survival, and death, but also of triumph, camaraderie, and, above all, respect for an immensity found in few places in the world.
The Ruth Glacier, nearly 35 miles long, feeds off the slopes of Denali and Mt. Silverthrone. Numerous forks of the glacier merge into the huge icefield known as the Don Sheldon Amphitheater (a.k.a. Ruth Amphitheater). This vast snow arena encompasses some 25 square miles. Then, with nowhere else to go, the great mass of ice is pushed down a mile-wide constriction rimmed by walls up to 5,000 feet high. With so much ice being squeezed through such a narrow slot, it's no wonder that the glacier has been measured to be more than 3,800 feet deep and moving at a rate of over three feet per day. Without the ice, this canyon would have a sheer 8,700-foot rise to the top of Mt. Dickey.
The western side of the Gorge holds most of the great stalwarts—huge granite monoliths rising abruptly out of the glacier. Any one of these peaks would be a major destination. The east side, although generally less impressive, still holds several 2,000- to 3,000-foot walls. One of these is perhaps the area's most remarkable peak: the complex façade of the Moose's Tooth. This, along with several other "Tooth" peaks, creates a seemingly impenetrable alpine bastion that oversees the entire Ruth Glacier.
In the minds of most climbers, the Gorge historically has had two strikes against it that have kept it from becoming popular. The legendary Alaskan weather has been responsible for numerous epics and has left many climbers empty-handed. However, although major storms do occur often, the snow tends to quickly slough off the steep routes, and the rock dries rapidly after even torrential rainstorms. The area also has gotten a bad rap over the years for poor and occasionally treacherous rock. This is definitely true for much of the Gorge, and climbers looking to do first ascents should be ready to attack the infamous "Cracker Jack" granite that can literally require one to chop steps. Also, atop many of the western-side peaks is a layer of black schist that has been likened to ascending stacked china dishes. That said, there are long stretches of exceptional and highly textured granite on several formations, including the south face of Bradley, the Eye Tooth, the Stump, and Hut Tower, to name a few.
The first humans to venture into the Ruth Gorge were the infamous Frederick Cook and a guide in 1906. Cook claimed to make the first ascent of Denali via this approach, but this was soon discredited as a hoax. They succeeded only in climbing 5,350-foot "Fake Peak," a small bump on a side glacier. Cook named the Ruth after his stepdaughter, Ruth Hunt.
In 1910 Belmore Browne and Hershel Parker wandered up the gorge on a quest to debunk Cook's claim. Naming peaks as they went, they weren't overly creative, designating some with individuals' names like Johnson, Wake, and Dickey. They named the most fantastic peak they saw Mt. Hubbard after the president of the Perry Arctic Club. This name fortunately was changed to the Moose's Tooth, a translation of the indigenous Athabascan name. With names like the Gargoyle, Werewolf Tower, and the Bear Tooth, the rest of the peaks on the eastern side also fared much better.
A group of four from Oregon's Mazamas was first to surmount a peak in the gorge with their climb of Mt. Barrill by its northwest slopes in 1910. Bradford Washburn surveyed much of the area in 1955 and climbed Mt. Dickey by its western slope. It was Washburn who perhaps first realized the extensive potential of the area. In his 1956 article in this journal, he wrote, "It would be hard to find a spot more easy of access where glorious glacier walks, easy lower climbs, and magnificent major ascents can all be accomplished out of the same air-supplied base camp, set amid North America's finest scenery and hardly a day's travel from New York!"
The first technical climb in the gorge was on the Moose's Tooth in 1964, when its long west ridge was climbed by a German party. Defining the bold style that came to dominate climbing in the Ruth Gorge, they ascended the entire spine of the Moose's Tooth in a single push from a camp low on the route.
In the mid-1970s the first big-wall routes started going up. The southeast face of Mt. Dickey (climbed in 1974 by David Roberts, Galen Rowell, and Ed Ward) was the first of seven major ascents on this monolith's 5,000-foot south and east walls. Although fixed lines were employed on the lower 900 feet, this groundbreaking big-wall ascent set the standard for committing routes. The same year, in similar style, Gary Bocarde, Michael Clark, Charles Porter, and John Svenson climbed the sheer southwest face of the Moose's Tooth—the second route to be climbed on this multifaceted mountain. On their "Moose Antler" ascent, the climbers carried an actual moose antler that proved easier to haul than the bags. Bocarde was a big mover in the early stages of climbing in the Gorge, accomplishing the first ascents of many of the peaks on its west side.
After a lull in the early 1980s, the Ruth Gorge saw a climbing boom when Austrian Andi Orgler came onto the scene. During the late 1980s and early 1990s, Orgler and a few key partners were responsible for a surge in new-route activity, including major ascents on Mt. Bradley, Mt. Dickey, Mt. Barrill, the Eye Tooth, and several of the smaller east-side peaks. On his first trip to the Gorge in 1987, Orgler, along with Sepp Jöchler, raced up the nearly 5,000-foot east buttress of Bradley in a mere 14 hours. In 1988 he and Tommi Bonapace completed the 51- pitch Wine Bottle Route on Dickey. This was one of the finest alpine-style ascents accomplished in Alaska, climbed at a high technical standard without drilling a single hole. Orgler and partners went on to climb a huge route on the south face of Bradley—The Pearl—which, in addition to other Ruth Gorge achievements, gained them world recognition with the Piolet d'Or award in 1995.
The past decade has seen its share of equally impressive ascents. Hard, technical, early- season mixed climbs have been the biggest focus. The Elevator Shaft on Mt. Johnson was an extraordinary achievement on a dangerous ice climb that saw no fewer than four attempts and some major epics before it was finally climbed by Doug Chabot and Jack Tackle in 1995. The Gift (That Keeps on Giving) on Bradley (climbed in 1998 by Jonny Blitz, Steve House, and Mark Twight) was a bold and cold undertaking that brought mixed climbing in the Gorge to a new level. In 2002 Sean Easton and Ueli Steck undertook an audacious early-season climb with their ascent of Blood From the Stone on Mt. Dickey. Linking incipient ice ribbons, they pieced together a line directly up the mountain's massive east wall—a line that doesn't often form and had never seen a prior attempt.
There is still some great new-route potential for climbers up to the task. The 2005 season can attest to that, as major first ascents were accomplished on Mt. Bradley, the Moose's Tooth, and Mt. Grosvenor. One of the Alaska Range's last great problems is located on the east buttress of Mt. Johnson, which has thwarted attempts for over 20 years by some of the world's finest alpinists, including Yvon Chouinard, Mugs Stump, and a noteworthy attempt by Renny Jackson and Doug Chabot, who climbed 38 pitches to a prominent tower on the ridge. After difficult free and aid climbing low on the route, the duo was horrified up higher when entire pitches required steps to be chopped with ice tools in 5.10 gravel. With many more appalling pitches ahead, they decided retreat was in order. Other major unsolved problems include the north face of Mt. Church—a 4,000-foot straight-shot ice and mixed route directly up the center of the face—and the direct north face of Johnson.
Climbing in the Ruth Gorge is best done from March through July. Although there are rumors of dry rock and late-season ice in the fall, the first winter storms have perplexed more than a few parties. Early season is best for technical ice and mixed routes, as they generally fall out of shape by mid-May. The best rock climbing season starts in June and tends to get better as more snow melts off the cliffs. Easier snow climbs can be done throughout the season, although crevasse and icefall difficulties can make late-season ascents interesting. The low elevation (between 4,500 and 10,300 feet) precludes much need for acclimatization.
A fly-in approach is necessary from the town of Talkeetna. Most parties start from the Mountain House airstrip above the Don Sheldon Amphitheater. For climbing the south-face routes on the Moose's Tooth, the Root Canal airstrip can be used. Landing in the Ruth Gorge itself can sometimes be preferable, although it is often necessary for climbers to haul their gear back up to the Mountain House for pickup. The Ruth Gorge is located within Denali National Park. Climbers are required to pay a small entrance fee and are encouraged to register with the ranger station in Talkeetna. Check the NPS website (www.nps.gov/dena/home/mountaineering/ index.htm) for more details.
Although it is home to many of the most difficult routes in North America, the Ruth Gorge also hosts a variety of novice and intermediate routes that climbers have enjoyed for years. Nearly 80 routes have been opened, but the route lines shown in the photos in this article reveal as much of what hasn't been climbed as what has been.
For nearly a century, Ruth Gorge climbers have shown exceptional respect for the great forces of the natural environment and for a spirit and history that has helped define the essence of alpinism. While the entire sweeping, 500-mile arc of the Alaska Range is an alpine mecca, the Ruth Gorge and its solid core of outstanding alpine achievements have created a valley of legends.
A Note About the Author:
Joseph Puryear has been climbing and suffering in the Alaska Range for more than a decade. He is the author of the new book Alaska Climbing, a comprehensive guide to 30 of the best routes in the central Alaska Range; visit Puryear's website, www.cascadeimages.com, or www.supertopo.com for more information. (Several Ruth Gorge routes can be found in this book.) When not enjoying their small cabin in Talkeetna, Joe and his wife, Michelle, make their home in Leavenworth, Washington.
Quebrada Rurec: Pietrorrrago: Vaffanculo!; Itsoc Huanca, Libertad es Partecipacion
Pariakaka, Peru 6 Mil
Gyajikang, Second Ascent and First Complete Ascent of West Ridge
Kyzyl Asker, Southeast Face Attempt
Cayesh, Slo-Am Route

redpajama_set_name: RedPajamaCommonCrawl


text:
Have a look at this animation to understand what Piql is.
Greats news from a great partner! Piql announces Norwegian Technology that secures 500 years access to digital data.
OSLO, Norway, September 18, 2014 /PRNewswire/ —
Malicious hacking, bit rot and data corruption; the challenges are immense when it comes to securing digital data. Then how can long-term access to our digital heritage be assured? Norwegian company Piql has found the answer by reinventing the use of a well-known storage medium.
There is a worldwide concern about the lack of technologies truly suited for long-term preservation of digital data. Magnetic storage medium are short-lived and best used for back-ups, whilst security and privacy issues make the Cloud unsuitable for the purpose. 5%[1] of the world's digital data requires secure, long-term preservation.
(Logo: http://photos.prnewswire.com/prnh/20140917/706227-a )
(Photo: http://photos.prnewswire.com/prnh/20140917/706227-b )
With a €20 million research project, supported by the EU and the Norwegian government[2], Piql has developed a unique solution for migration-free digital preservation. The technology lifts photosensitive film into the digital era.
"Our goal has been to keep valuable digital data securely preserved and accessible for 500 years. Ensuring that the data cannot be modified or deleted is imperative in this context." comments Rune Bjerkestrand, Managing Director of Piql AS. A true preservation solution must also secure future access independent of availability to specific technologies or vendors.
Photosensitive film has been used as a preservation medium for decades, by archives (microfilm) and by the large film studios in e.g. Hollywood. However the usage has been limited to preservation of analogue images. Piql's technology enables preservation of digital data on high-resolution film. The data is written on a preservation medium with proven long-term qualities, stored offline in physical form. Yet the data is fully searchable as in other digital storage technologies. Instructions on how to retrieve the data in the future is written in readable text on the film.
Piql supplements technologies used for short-lived information and back-ups, and is offered to data owners through an international network of service providers.
Piql AS provides solutions within digital preservation, and has converted photosensitive film into a digital storage medium. Piql is also behind Cinevator, the world's leading digital film printer. The company was started in 2002 and is based in Drammen, Norway


From our HEAVENLY HELVETICA COLLECTION.
IN HIM. In Christ alone my hope is found. A modest print with some typographic pink play!
You can choose to have this with the key tagline "in Christ alone my hope is found" - see this option in our drop down list.
Only available as a large poster print (50 x 70cm) print is printed on 275gsm white satin paper stock.