1 /**
2  * Copyright © 2019 IBM Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include "extensions/openpower-pels/private_header.hpp"
17 #include "pel_utils.hpp"
18 
19 #include <gtest/gtest.h>
20 
21 using namespace openpower::pels;
22 
23 class PrivateHeaderTest : public CleanLogID
24 {
25 };
26 
27 TEST_F(PrivateHeaderTest, SizeTest)
28 {
29     EXPECT_EQ(PrivateHeader::flattenedSize(), 48);
30 }
31 
32 TEST_F(PrivateHeaderTest, UnflattenFlattenTest)
33 {
34     auto data = pelDataFactory(TestPELType::privateHeaderSection);
35 
36     Stream stream(data);
37     PrivateHeader ph(stream);
38     EXPECT_EQ(ph.valid(), true);
39 
40     EXPECT_EQ(ph.header().id, 0x5048);
41     EXPECT_EQ(ph.header().size, PrivateHeader::flattenedSize());
42     EXPECT_EQ(ph.header().version, 0x01);
43     EXPECT_EQ(ph.header().subType, 0x02);
44     EXPECT_EQ(ph.header().componentID, 0x0304);
45 
46     auto ct = ph.createTimestamp();
47     EXPECT_EQ(ct.yearMSB, 0x20);
48     EXPECT_EQ(ct.yearLSB, 0x30);
49     EXPECT_EQ(ct.month, 0x05);
50     EXPECT_EQ(ct.day, 0x09);
51     EXPECT_EQ(ct.hour, 0x11);
52     EXPECT_EQ(ct.minutes, 0x1E);
53     EXPECT_EQ(ct.seconds, 0x01);
54     EXPECT_EQ(ct.hundredths, 0x63);
55 
56     auto mt = ph.commitTimestamp();
57     EXPECT_EQ(mt.yearMSB, 0x20);
58     EXPECT_EQ(mt.yearLSB, 0x31);
59     EXPECT_EQ(mt.month, 0x06);
60     EXPECT_EQ(mt.day, 0x0F);
61     EXPECT_EQ(mt.hour, 0x09);
62     EXPECT_EQ(mt.minutes, 0x22);
63     EXPECT_EQ(mt.seconds, 0x3A);
64     EXPECT_EQ(mt.hundredths, 0x00);
65 
66     EXPECT_EQ(ph.creatorID(), 0x4F);
67     EXPECT_EQ(ph.logType(), 0x00);
68     EXPECT_EQ(ph.sectionCount(), 0x02);
69     EXPECT_EQ(ph.obmcLogID(), 0x90919293);
70 
71     char expected[] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x00};
72     EXPECT_TRUE(memcmp(ph.creatorVersion().version, expected, 8) == 0);
73 
74     EXPECT_EQ(ph.plid(), 0x50515253);
75     EXPECT_EQ(ph.id(), 0x80818283);
76 
77     // Now flatten into a vector and check that this vector
78     // matches the original one.
79     std::vector<uint8_t> newData;
80     Stream newStream(newData);
81 
82     ph.flatten(newStream);
83     EXPECT_EQ(data, newData);
84 
85     // Change a field, then flatten and unflatten again
86     ph.setID(0x55);
87 
88     newStream.offset(0);
89     newData.clear();
90     ph.flatten(newStream);
91     EXPECT_NE(data, newData);
92 
93     newStream.offset(0);
94     PrivateHeader newPH(newStream);
95 
96     EXPECT_TRUE(newPH.valid());
97     EXPECT_EQ(newPH.id(), 0x55);
98 }
99 
100 TEST_F(PrivateHeaderTest, ShortDataTest)
101 {
102     auto data = pelDataFactory(TestPELType::privateHeaderSection);
103     data.resize(PrivateHeader::flattenedSize() - 1);
104     Stream stream(data);
105 
106     PrivateHeader ph(stream);
107 
108     EXPECT_EQ(ph.valid(), false);
109 }
110 
111 TEST_F(PrivateHeaderTest, CorruptDataTest1)
112 {
113     auto data = pelDataFactory(TestPELType::privateHeaderSection);
114     Stream stream(data);
115 
116     data.at(0) = 0; // corrupt the section ID
117 
118     PrivateHeader ph(stream);
119 
120     EXPECT_EQ(ph.valid(), false);
121 }
122 
123 TEST_F(PrivateHeaderTest, CorruptDataTest2)
124 {
125     auto data = pelDataFactory(TestPELType::privateHeaderSection);
126     Stream stream(data);
127 
128     data.at(4) = 0x22; // corrupt the version
129 
130     PrivateHeader ph(stream);
131 
132     EXPECT_EQ(ph.valid(), false);
133 }
134 
135 TEST_F(PrivateHeaderTest, CorruptDataTest3)
136 {
137     auto data = pelDataFactory(TestPELType::privateHeaderSection);
138     Stream stream(data);
139 
140     data.at(27) = 1; // corrupt the section count
141 
142     PrivateHeader ph(stream);
143 
144     EXPECT_EQ(ph.valid(), false);
145 }
146 
147 // Construct a PrivateHeader from scratch
148 TEST_F(PrivateHeaderTest, ConstructionTest)
149 {
150     tm time_tm;
151     time_tm.tm_year = 125;
152     time_tm.tm_mon = 11;
153     time_tm.tm_mday = 31;
154     time_tm.tm_hour = 15;
155     time_tm.tm_min = 23;
156     time_tm.tm_sec = 42;
157     time_tm.tm_isdst = 0;
158 
159     // Convert the above time into a uint64_t in ms since the epoch time
160     auto timepoint = std::chrono::system_clock::from_time_t(mktime(&time_tm));
161     auto timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(
162                          timepoint.time_since_epoch())
163                          .count();
164 
165     PrivateHeader ph(0x3300, 42, timestamp);
166 
167     EXPECT_TRUE(ph.valid());
168     EXPECT_EQ(ph.header().id, 0x5048);
169     EXPECT_EQ(ph.header().size, PrivateHeader::flattenedSize());
170     EXPECT_EQ(ph.header().version, 0x01);
171     EXPECT_EQ(ph.header().subType, 0x00);
172     EXPECT_EQ(ph.header().componentID, 0x3300);
173 
174     auto& ct = ph.createTimestamp();
175     EXPECT_EQ(ct.yearMSB, 0x20);
176     EXPECT_EQ(ct.yearLSB, 0x25);
177     EXPECT_EQ(ct.month, 0x12);
178     EXPECT_EQ(ct.day, 0x31);
179     EXPECT_EQ(ct.hour, 0x15);
180     EXPECT_EQ(ct.minutes, 0x23);
181     EXPECT_EQ(ct.seconds, 0x42);
182     EXPECT_EQ(ct.hundredths, 0x00);
183 
184     EXPECT_EQ(ph.creatorID(), 'O');
185     EXPECT_EQ(ph.logType(), 0x00);
186     EXPECT_EQ(ph.sectionCount(), 0x01);
187     EXPECT_EQ(ph.obmcLogID(), 42);
188 
189     char expected[] = {0, 0, 0, 0, 0, 0, 0, 0};
190     EXPECT_TRUE(memcmp(ph.creatorVersion().version, expected, 8) == 0);
191 
192     EXPECT_EQ(ph.id(), 0x50000001);
193     EXPECT_EQ(ph.id(), ph.plid());
194 }
195