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 TEST_F(PrivateHeaderTest, SizeTest)
27 {
28     EXPECT_EQ(PrivateHeader::flattenedSize(), 48);
29 }
30 
31 TEST_F(PrivateHeaderTest, UnflattenFlattenTest)
32 {
33     auto data = pelDataFactory(TestPELType::privateHeaderSection);
34 
35     Stream stream(data);
36     PrivateHeader ph(stream);
37     EXPECT_EQ(ph.valid(), true);
38 
39     EXPECT_EQ(ph.header().id, 0x5048);
40     EXPECT_EQ(ph.header().size, PrivateHeader::flattenedSize());
41     EXPECT_EQ(ph.header().version, 0x01);
42     EXPECT_EQ(ph.header().subType, 0x02);
43     EXPECT_EQ(ph.header().componentID, 0x0304);
44 
45     auto ct = ph.createTimestamp();
46     EXPECT_EQ(ct.yearMSB, 0x20);
47     EXPECT_EQ(ct.yearLSB, 0x30);
48     EXPECT_EQ(ct.month, 0x05);
49     EXPECT_EQ(ct.day, 0x09);
50     EXPECT_EQ(ct.hour, 0x11);
51     EXPECT_EQ(ct.minutes, 0x1E);
52     EXPECT_EQ(ct.seconds, 0x01);
53     EXPECT_EQ(ct.hundredths, 0x63);
54 
55     auto mt = ph.commitTimestamp();
56     EXPECT_EQ(mt.yearMSB, 0x20);
57     EXPECT_EQ(mt.yearLSB, 0x31);
58     EXPECT_EQ(mt.month, 0x06);
59     EXPECT_EQ(mt.day, 0x0F);
60     EXPECT_EQ(mt.hour, 0x09);
61     EXPECT_EQ(mt.minutes, 0x22);
62     EXPECT_EQ(mt.seconds, 0x3A);
63     EXPECT_EQ(mt.hundredths, 0x00);
64 
65     EXPECT_EQ(ph.creatorID(), 0x4F);
66     EXPECT_EQ(ph.logType(), 0x00);
67     EXPECT_EQ(ph.sectionCount(), 0x02);
68     EXPECT_EQ(ph.obmcLogID(), 0x90919293);
69 
70     char expected[] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x00};
71     EXPECT_TRUE(memcmp(ph.creatorVersion().version, expected, 8) == 0);
72 
73     EXPECT_EQ(ph.plid(), 0x50515253);
74     EXPECT_EQ(ph.id(), 0x80818283);
75 
76     // Now flatten into a vector and check that this vector
77     // matches the original one.
78     std::vector<uint8_t> newData;
79     Stream newStream(newData);
80 
81     ph.flatten(newStream);
82     EXPECT_EQ(data, newData);
83 
84     // Change a field, then flatten and unflatten again
85     ph.setID(0x55);
86 
87     newStream.offset(0);
88     newData.clear();
89     ph.flatten(newStream);
90     EXPECT_NE(data, newData);
91 
92     newStream.offset(0);
93     PrivateHeader newPH(newStream);
94 
95     EXPECT_TRUE(newPH.valid());
96     EXPECT_EQ(newPH.id(), 0x55);
97 }
98 
99 TEST_F(PrivateHeaderTest, ShortDataTest)
100 {
101     auto data = pelDataFactory(TestPELType::privateHeaderSection);
102     data.resize(PrivateHeader::flattenedSize() - 1);
103     Stream stream(data);
104 
105     PrivateHeader ph(stream);
106 
107     EXPECT_EQ(ph.valid(), false);
108 }
109 
110 TEST_F(PrivateHeaderTest, CorruptDataTest1)
111 {
112     auto data = pelDataFactory(TestPELType::privateHeaderSection);
113     Stream stream(data);
114 
115     data.at(0) = 0; // corrupt the section ID
116 
117     PrivateHeader ph(stream);
118 
119     EXPECT_EQ(ph.valid(), false);
120 }
121 
122 TEST_F(PrivateHeaderTest, CorruptDataTest2)
123 {
124     auto data = pelDataFactory(TestPELType::privateHeaderSection);
125     Stream stream(data);
126 
127     data.at(4) = 0x22; // corrupt the version
128 
129     PrivateHeader ph(stream);
130 
131     EXPECT_EQ(ph.valid(), false);
132 }
133 
134 TEST_F(PrivateHeaderTest, CorruptDataTest3)
135 {
136     auto data = pelDataFactory(TestPELType::privateHeaderSection);
137     Stream stream(data);
138 
139     data.at(27) = 1; // corrupt the section count
140 
141     PrivateHeader ph(stream);
142 
143     EXPECT_EQ(ph.valid(), false);
144 }
145 
146 // Construct a PrivateHeader from scratch
147 TEST_F(PrivateHeaderTest, ConstructionTest)
148 {
149     tm time_tm;
150     time_tm.tm_year = 125;
151     time_tm.tm_mon = 11;
152     time_tm.tm_mday = 31;
153     time_tm.tm_hour = 15;
154     time_tm.tm_min = 23;
155     time_tm.tm_sec = 42;
156     time_tm.tm_isdst = 0;
157 
158     // Convert the above time into a uint64_t in ms since the epoch time
159     auto timepoint = std::chrono::system_clock::from_time_t(mktime(&time_tm));
160     auto timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(
161                          timepoint.time_since_epoch())
162                          .count();
163 
164     PrivateHeader ph(0x3300, 42, timestamp);
165 
166     EXPECT_TRUE(ph.valid());
167     EXPECT_EQ(ph.header().id, 0x5048);
168     EXPECT_EQ(ph.header().size, PrivateHeader::flattenedSize());
169     EXPECT_EQ(ph.header().version, 0x01);
170     EXPECT_EQ(ph.header().subType, 0x00);
171     EXPECT_EQ(ph.header().componentID, 0x3300);
172 
173     auto& ct = ph.createTimestamp();
174     EXPECT_EQ(ct.yearMSB, 0x20);
175     EXPECT_EQ(ct.yearLSB, 0x25);
176     EXPECT_EQ(ct.month, 0x12);
177     EXPECT_EQ(ct.day, 0x31);
178     EXPECT_EQ(ct.hour, 0x15);
179     EXPECT_EQ(ct.minutes, 0x23);
180     EXPECT_EQ(ct.seconds, 0x42);
181     EXPECT_EQ(ct.hundredths, 0x00);
182 
183     EXPECT_EQ(ph.creatorID(), 'O');
184     EXPECT_EQ(ph.logType(), 0x00);
185     EXPECT_EQ(ph.sectionCount(), 0x01);
186     EXPECT_EQ(ph.obmcLogID(), 42);
187 
188     char expected[] = {0, 0, 0, 0, 0, 0, 0, 0};
189     EXPECT_TRUE(memcmp(ph.creatorVersion().version, expected, 8) == 0);
190 
191     EXPECT_EQ(ph.id(), 0x50000001);
192     EXPECT_EQ(ph.id(), ph.plid());
193 }
194