summaryrefslogtreecommitdiffstats
path: root/src/usr/pnor/test/ecctest.H
blob: ddcf3c987b74c19ab371e9023b14db77b862d12b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/pnor/test/ecctest.H $                                 */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 2013,2014              */
/*                                                                        */
/* 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                                                     */
#include <cxxtest/TestSuite.H>
#include <pnor/ecc.H>
#include <stdlib.h>
#include <string.h>

// Forward declarations, see ecc.C
namespace PNOR
{
    namespace ECC
    {
        uint8_t generateECC(uint64_t i_data);
        uint8_t verifyECC(uint64_t i_data, uint8_t i_ecc);
        uint8_t correctECC(uint64_t& io_data, uint8_t& io_ecc);
    }
}

class ECCTest : public CxxTest::TestSuite
{
    public:

        void testConsistency()
        {
            uint64_t data = 0x8d8aeff460bd2fc8; // <-- random data.
            uint8_t ecc = PNOR::ECC::generateECC(data);

            uint8_t result = PNOR::ECC::verifyECC(data, ecc);
            if (PNOR::ECC::GD != result)
            {
                TS_FAIL("ECCTest::testConsistency: Inconsistent results: "
                        "0x%16x 0x%2x: %d",
                        data, ecc, result);
            }
        }

        void testCorrection()
        {
            uint64_t data = 0x8d8aeff460bd2fc8; // <-- random data.
            uint8_t ecc = PNOR::ECC::generateECC(data);

            for (int i = 0; i < 64; i++)
            {
                uint64_t bad_data = data ^ (1ul << (63 - i));
                uint8_t result = PNOR::ECC::verifyECC(bad_data, ecc);

                if (i != result)
                {
                    TS_FAIL("ECCTest::testCorrection: Incorrect correct data: "
                            "0x%16x 0x%2x: %d %d",
                            data, ecc, i, result);
                }
            }

            for (int i = 0; i < 8; i++)
            {
                uint8_t bad_ecc = ecc ^ (1 << i);
                uint8_t result = PNOR::ECC::verifyECC(data, bad_ecc);

                if (i != (result - PNOR::ECC::E7))
                {
                    TS_FAIL("ECCTest::testCorrection: Incorrect correct ecc: "
                            "0x%16x 0x%2x: %d %d",
                            data, ecc, i, result);
                }
            }
        }

        void testUncorrectable()
        {
            uint64_t data = 0x8d8aeff460bd2fc8; // <-- random data.
            uint8_t ecc = PNOR::ECC::generateECC(data);

            for (int i = 0; i < 64; i++)
            {
                for (int j = 0; j < 64; j++)
                {
                    if (i == j)
                    {
                        continue;
                    }

                    uint64_t bad_data = data ^ (1ul << i) ^ (1ul << j);
                    uint8_t result = PNOR::ECC::verifyECC(bad_data, ecc);

                    if (PNOR::ECC::UE != result)
                    {
                        TS_FAIL("ECCTest::testUncorrectable: Non-UE: "
                                "0x%16x 0x%2x : %d %d",
                                data, ecc, i, j);
                    }
                }
            }
        }

        void testInject()
        {
            uint64_t data = 0x8d8aeff460bd2fc8; // <-- random data.
            size_t s = sizeof(data);

            // Allocate buffers.
            uint8_t* in_data = new uint8_t[s];
            memcpy(in_data, &data, s);
            uint8_t* out_data = new uint8_t[(s * 9) / 8];

            // Inject ECC.
            PNOR::ECC::injectECC(in_data, s, out_data);

            // Clear source.
            memset(in_data, '\0', s);

            // Remove ECC.
            PNOR::ECC::removeECC(out_data, in_data, s);

            // Ensure data matches.
            if (0 != memcmp(in_data, &data, s))
            {
                TS_FAIL("ECCTest::testInject: Data mismatch: %16x %16x\n",
                        data, *reinterpret_cast<uint64_t*>(in_data));
            }

            delete[] in_data;
            delete[] out_data;
        }
};
OpenPOWER on IntegriCloud