utils_unittest.cc revision 5fe0c4ede81b82ae3425ddbbb698eceef14cbc78
1//
2// Copyright (C) 2012 The Android Open Source Project
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
17#include "update_engine/common/utils.h"
18
19#include <errno.h>
20#include <stdint.h>
21#include <sys/stat.h>
22#include <sys/types.h>
23
24#include <map>
25#include <string>
26#include <vector>
27
28#include <base/files/file_path.h>
29#include <base/files/file_util.h>
30#include <base/files/scoped_temp_dir.h>
31#include <base/strings/string_util.h>
32#include <base/strings/stringprintf.h>
33#include <brillo/message_loops/fake_message_loop.h>
34#include <brillo/message_loops/message_loop_utils.h>
35#include <gtest/gtest.h>
36
37#include "update_engine/common/test_utils.h"
38
39using brillo::FakeMessageLoop;
40using std::map;
41using std::string;
42using std::vector;
43
44namespace chromeos_update_engine {
45
46class UtilsTest : public ::testing::Test { };
47
48TEST(UtilsTest, CanParseECVersion) {
49  // Should be able to parse and valid key value line.
50  EXPECT_EQ("12345", utils::ParseECVersion("fw_version=12345"));
51  EXPECT_EQ("123456", utils::ParseECVersion(
52      "b=1231a fw_version=123456 a=fasd2"));
53  EXPECT_EQ("12345", utils::ParseECVersion("fw_version=12345"));
54  EXPECT_EQ("00VFA616", utils::ParseECVersion(
55      "vendor=\"sam\" fw_version=\"00VFA616\""));
56
57  // For invalid entries, should return the empty string.
58  EXPECT_EQ("", utils::ParseECVersion("b=1231a fw_version a=fasd2"));
59}
60
61TEST(UtilsTest, ReadFileFailure) {
62  brillo::Blob empty;
63  EXPECT_FALSE(utils::ReadFile("/this/doesn't/exist", &empty));
64}
65
66TEST(UtilsTest, ReadFileChunk) {
67  base::FilePath file;
68  EXPECT_TRUE(base::CreateTemporaryFile(&file));
69  ScopedPathUnlinker unlinker(file.value());
70  brillo::Blob data;
71  const size_t kSize = 1024 * 1024;
72  for (size_t i = 0; i < kSize; i++) {
73    data.push_back(i % 255);
74  }
75  EXPECT_TRUE(utils::WriteFile(file.value().c_str(), data.data(), data.size()));
76  brillo::Blob in_data;
77  EXPECT_TRUE(utils::ReadFileChunk(file.value().c_str(), kSize, 10, &in_data));
78  EXPECT_TRUE(in_data.empty());
79  EXPECT_TRUE(utils::ReadFileChunk(file.value().c_str(), 0, -1, &in_data));
80  EXPECT_TRUE(data == in_data);
81  in_data.clear();
82  EXPECT_TRUE(utils::ReadFileChunk(file.value().c_str(), 10, 20, &in_data));
83  EXPECT_TRUE(brillo::Blob(data.begin() + 10, data.begin() + 10 + 20) ==
84              in_data);
85}
86
87TEST(UtilsTest, ErrnoNumberAsStringTest) {
88  EXPECT_EQ("No such file or directory", utils::ErrnoNumberAsString(ENOENT));
89}
90
91TEST(UtilsTest, IsSymlinkTest) {
92  string temp_dir;
93  EXPECT_TRUE(utils::MakeTempDirectory("symlink-test.XXXXXX", &temp_dir));
94  string temp_file = temp_dir + "/temp-file";
95  EXPECT_TRUE(utils::WriteFile(temp_file.c_str(), "", 0));
96  string temp_symlink = temp_dir + "/temp-symlink";
97  EXPECT_EQ(0, symlink(temp_file.c_str(), temp_symlink.c_str()));
98  EXPECT_FALSE(utils::IsSymlink(temp_dir.c_str()));
99  EXPECT_FALSE(utils::IsSymlink(temp_file.c_str()));
100  EXPECT_TRUE(utils::IsSymlink(temp_symlink.c_str()));
101  EXPECT_FALSE(utils::IsSymlink("/non/existent/path"));
102  EXPECT_TRUE(base::DeleteFile(base::FilePath(temp_dir), true));
103}
104
105TEST(UtilsTest, SplitPartitionNameTest) {
106  string disk;
107  int part_num;
108
109  EXPECT_TRUE(utils::SplitPartitionName("/dev/sda3", &disk, &part_num));
110  EXPECT_EQ("/dev/sda", disk);
111  EXPECT_EQ(3, part_num);
112
113  EXPECT_TRUE(utils::SplitPartitionName("/dev/sdp1234", &disk, &part_num));
114  EXPECT_EQ("/dev/sdp", disk);
115  EXPECT_EQ(1234, part_num);
116
117  EXPECT_TRUE(utils::SplitPartitionName("/dev/mmcblk0p3", &disk, &part_num));
118  EXPECT_EQ("/dev/mmcblk0", disk);
119  EXPECT_EQ(3, part_num);
120
121  EXPECT_TRUE(utils::SplitPartitionName("/dev/ubiblock3_2", &disk, &part_num));
122  EXPECT_EQ("/dev/ubiblock", disk);
123  EXPECT_EQ(3, part_num);
124
125  EXPECT_TRUE(utils::SplitPartitionName("/dev/loop10", &disk, &part_num));
126  EXPECT_EQ("/dev/loop", disk);
127  EXPECT_EQ(10, part_num);
128
129  EXPECT_TRUE(utils::SplitPartitionName("/dev/loop28p11", &disk, &part_num));
130  EXPECT_EQ("/dev/loop28", disk);
131  EXPECT_EQ(11, part_num);
132
133  EXPECT_TRUE(utils::SplitPartitionName("/dev/loop10_0", &disk, &part_num));
134  EXPECT_EQ("/dev/loop", disk);
135  EXPECT_EQ(10, part_num);
136
137  EXPECT_TRUE(utils::SplitPartitionName("/dev/loop28p11_0", &disk, &part_num));
138  EXPECT_EQ("/dev/loop28", disk);
139  EXPECT_EQ(11, part_num);
140
141  EXPECT_FALSE(utils::SplitPartitionName("/dev/mmcblk0p", &disk, &part_num));
142  EXPECT_FALSE(utils::SplitPartitionName("/dev/sda", &disk, &part_num));
143  EXPECT_FALSE(utils::SplitPartitionName("/dev/foo/bar", &disk, &part_num));
144  EXPECT_FALSE(utils::SplitPartitionName("/", &disk, &part_num));
145  EXPECT_FALSE(utils::SplitPartitionName("", &disk, &part_num));
146}
147
148TEST(UtilsTest, MakePartitionNameTest) {
149  EXPECT_EQ("/dev/sda4", utils::MakePartitionName("/dev/sda", 4));
150  EXPECT_EQ("/dev/sda123", utils::MakePartitionName("/dev/sda", 123));
151  EXPECT_EQ("/dev/mmcblk2", utils::MakePartitionName("/dev/mmcblk", 2));
152  EXPECT_EQ("/dev/mmcblk0p2", utils::MakePartitionName("/dev/mmcblk0", 2));
153  EXPECT_EQ("/dev/loop8", utils::MakePartitionName("/dev/loop", 8));
154  EXPECT_EQ("/dev/loop12p2", utils::MakePartitionName("/dev/loop12", 2));
155  EXPECT_EQ("/dev/ubi5_0", utils::MakePartitionName("/dev/ubiblock", 5));
156  EXPECT_EQ("/dev/mtd4", utils::MakePartitionName("/dev/ubiblock", 4));
157  EXPECT_EQ("/dev/ubi3_0", utils::MakePartitionName("/dev/ubiblock", 3));
158  EXPECT_EQ("/dev/mtd2", utils::MakePartitionName("/dev/ubiblock", 2));
159  EXPECT_EQ("/dev/ubi1_0", utils::MakePartitionName("/dev/ubiblock", 1));
160}
161
162TEST(UtilsTest, MakePartitionNameForMountTest) {
163  EXPECT_EQ("/dev/sda4", utils::MakePartitionNameForMount("/dev/sda4"));
164  EXPECT_EQ("/dev/sda123", utils::MakePartitionNameForMount("/dev/sda123"));
165  EXPECT_EQ("/dev/mmcblk2", utils::MakePartitionNameForMount("/dev/mmcblk2"));
166  EXPECT_EQ("/dev/mmcblk0p2",
167            utils::MakePartitionNameForMount("/dev/mmcblk0p2"));
168  EXPECT_EQ("/dev/loop0", utils::MakePartitionNameForMount("/dev/loop0"));
169  EXPECT_EQ("/dev/loop8", utils::MakePartitionNameForMount("/dev/loop8"));
170  EXPECT_EQ("/dev/loop12p2",
171            utils::MakePartitionNameForMount("/dev/loop12p2"));
172  EXPECT_EQ("/dev/ubiblock5_0",
173            utils::MakePartitionNameForMount("/dev/ubiblock5_0"));
174  EXPECT_EQ("/dev/mtd4",
175            utils::MakePartitionNameForMount("/dev/ubi4_0"));
176  EXPECT_EQ("/dev/ubiblock3_0",
177            utils::MakePartitionNameForMount("/dev/ubiblock3"));
178  EXPECT_EQ("/dev/mtd2", utils::MakePartitionNameForMount("/dev/ubi2"));
179  EXPECT_EQ("/dev/ubi1_0",
180            utils::MakePartitionNameForMount("/dev/ubiblock1"));
181}
182
183TEST(UtilsTest, FuzzIntTest) {
184  static const uint32_t kRanges[] = { 0, 1, 2, 20 };
185  for (uint32_t range : kRanges) {
186    const int kValue = 50;
187    for (int tries = 0; tries < 100; ++tries) {
188      uint32_t value = utils::FuzzInt(kValue, range);
189      EXPECT_GE(value, kValue - range / 2);
190      EXPECT_LE(value, kValue + range - range / 2);
191    }
192  }
193}
194
195TEST(UtilsTest, RunAsRootGetFilesystemSizeTest) {
196  string img;
197  EXPECT_TRUE(utils::MakeTempFile("img.XXXXXX", &img, nullptr));
198  ScopedPathUnlinker img_unlinker(img);
199  test_utils::CreateExtImageAtPath(img, nullptr);
200  // Extend the "partition" holding the file system from 10MiB to 20MiB.
201  EXPECT_EQ(0, test_utils::System(base::StringPrintf(
202      "dd if=/dev/zero of=%s seek=20971519 bs=1 count=1 status=none",
203      img.c_str())));
204  EXPECT_EQ(20 * 1024 * 1024, utils::FileSize(img));
205  int block_count = 0;
206  int block_size = 0;
207  EXPECT_TRUE(utils::GetFilesystemSize(img, &block_count, &block_size));
208  EXPECT_EQ(4096, block_size);
209  EXPECT_EQ(10 * 1024 * 1024 / 4096, block_count);
210}
211
212// Squashfs example filesystem, generated with:
213//   echo hola>hola
214//   mksquashfs hola hola.sqfs -noappend -nopad
215//   hexdump hola.sqfs -e '16/1 "%02x, " "\n"'
216const uint8_t kSquashfsFile[] = {
217  0x68, 0x73, 0x71, 0x73, 0x02, 0x00, 0x00, 0x00,  // magic, inodes
218  0x3e, 0x49, 0x61, 0x54, 0x00, 0x00, 0x02, 0x00,
219  0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x11, 0x00,
220  0xc0, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00,  // flags, noids, major, minor
221  0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // root_inode
222  0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // bytes_used
223  0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
224  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
225  0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
226  0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
227  0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
228  0xd5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
229  0x68, 0x6f, 0x6c, 0x61, 0x0a, 0x2c, 0x00, 0x78,
230  0xda, 0x63, 0x62, 0x58, 0xc2, 0xc8, 0xc0, 0xc0,
231  0xc8, 0xd0, 0x6b, 0x91, 0x18, 0x02, 0x64, 0xa0,
232  0x00, 0x56, 0x06, 0x90, 0xcc, 0x7f, 0xb0, 0xbc,
233  0x9d, 0x67, 0x62, 0x08, 0x13, 0x54, 0x1c, 0x44,
234  0x4b, 0x03, 0x31, 0x33, 0x10, 0x03, 0x00, 0xb5,
235  0x87, 0x04, 0x89, 0x16, 0x00, 0x78, 0xda, 0x63,
236  0x60, 0x80, 0x00, 0x46, 0x28, 0xcd, 0xc4, 0xc0,
237  0xcc, 0x90, 0x91, 0x9f, 0x93, 0x08, 0x00, 0x04,
238  0x70, 0x01, 0xab, 0x10, 0x80, 0x60, 0x00, 0x00,
239  0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
240  0x01, 0x00, 0x00, 0x00, 0x00, 0xab, 0x00, 0x00,
241  0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x78,
242  0xda, 0x63, 0x60, 0x80, 0x00, 0x05, 0x28, 0x0d,
243  0x00, 0x01, 0x10, 0x00, 0x21, 0xc5, 0x00, 0x00,
244  0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0x99,
245  0xcd, 0x02, 0x00, 0x88, 0x13, 0x00, 0x00, 0xdd,
246  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
247};
248
249TEST(UtilsTest, GetSquashfs4Size) {
250  uint8_t buffer[sizeof(kSquashfsFile)];
251  memcpy(buffer, kSquashfsFile, sizeof(kSquashfsFile));
252
253  int block_count = -1;
254  int block_size = -1;
255  // Not enough bytes passed.
256  EXPECT_FALSE(utils::GetSquashfs4Size(buffer, 10, nullptr, nullptr));
257
258  // The whole file system is passed, which is enough for parsing.
259  EXPECT_TRUE(utils::GetSquashfs4Size(buffer, sizeof(kSquashfsFile),
260                                      &block_count, &block_size));
261  EXPECT_EQ(4096, block_size);
262  EXPECT_EQ(1, block_count);
263
264  // Modify the major version to 5.
265  uint16_t* s_major = reinterpret_cast<uint16_t*>(buffer + 0x1c);
266  *s_major = 5;
267  EXPECT_FALSE(utils::GetSquashfs4Size(buffer, 10, nullptr, nullptr));
268  memcpy(buffer, kSquashfsFile, sizeof(kSquashfsFile));
269
270  // Modify the bytes_used to have 6 blocks.
271  int64_t* bytes_used = reinterpret_cast<int64_t*>(buffer + 0x28);
272  *bytes_used = 4096 * 5 + 1;  // 6 "blocks".
273  EXPECT_TRUE(utils::GetSquashfs4Size(buffer, sizeof(kSquashfsFile),
274                                      &block_count, &block_size));
275  EXPECT_EQ(4096, block_size);
276  EXPECT_EQ(6, block_count);
277}
278
279namespace {
280void GetFileFormatTester(const string& expected,
281                         const vector<uint8_t>& contents) {
282  test_utils::ScopedTempFile file;
283  ASSERT_TRUE(utils::WriteFile(file.GetPath().c_str(),
284                               reinterpret_cast<const char*>(contents.data()),
285                               contents.size()));
286  EXPECT_EQ(expected, utils::GetFileFormat(file.GetPath()));
287}
288}  // namespace
289
290TEST(UtilsTest, GetFileFormatTest) {
291  EXPECT_EQ("File not found.", utils::GetFileFormat("/path/to/nowhere"));
292  GetFileFormatTester("data", vector<uint8_t>{1, 2, 3, 4, 5, 6, 7, 8});
293  GetFileFormatTester("ELF", vector<uint8_t>{0x7f, 0x45, 0x4c, 0x46});
294
295  // Real tests from cros_installer on different boards.
296  // ELF 32-bit LSB executable, Intel 80386
297  GetFileFormatTester(
298      "ELF 32-bit little-endian x86",
299      vector<uint8_t>{0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00,
300                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
301                      0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00,
302                      0x90, 0x83, 0x04, 0x08, 0x34, 0x00, 0x00, 0x00});
303
304  // ELF 32-bit LSB executable, MIPS
305  GetFileFormatTester(
306      "ELF 32-bit little-endian mips",
307      vector<uint8_t>{0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00,
308                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
309                      0x03, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00,
310                      0xc0, 0x12, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00});
311
312  // ELF 32-bit LSB executable, ARM
313  GetFileFormatTester(
314      "ELF 32-bit little-endian arm",
315      vector<uint8_t>{0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00,
316                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
317                      0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00,
318                      0x85, 0x8b, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00});
319
320  // ELF 64-bit LSB executable, x86-64
321  GetFileFormatTester(
322      "ELF 64-bit little-endian x86-64",
323      vector<uint8_t>{0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00,
324                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
325                      0x02, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00,
326                      0xb0, 0x04, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00});
327}
328
329TEST(UtilsTest, ScheduleCrashReporterUploadTest) {
330  // Not much to test. At least this tests for memory leaks, crashes,
331  // log errors.
332  FakeMessageLoop loop(nullptr);
333  loop.SetAsCurrent();
334  utils::ScheduleCrashReporterUpload();
335  // Test that we scheduled one callback from the crash reporter.
336  EXPECT_EQ(1, brillo::MessageLoopRunMaxIterations(&loop, 100));
337  EXPECT_FALSE(loop.PendingTasks());
338}
339
340TEST(UtilsTest, FormatTimeDeltaTest) {
341  // utils::FormatTimeDelta() is not locale-aware (it's only used for logging
342  // which is not localized) so we only need to test the C locale
343  EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromMilliseconds(100)),
344            "0.1s");
345  EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(0)),
346            "0s");
347  EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(1)),
348            "1s");
349  EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(59)),
350            "59s");
351  EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(60)),
352            "1m0s");
353  EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(61)),
354            "1m1s");
355  EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(90)),
356            "1m30s");
357  EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(1205)),
358            "20m5s");
359  EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(3600)),
360            "1h0m0s");
361  EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(3601)),
362            "1h0m1s");
363  EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(3661)),
364            "1h1m1s");
365  EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(7261)),
366            "2h1m1s");
367  EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(86400)),
368            "1d0h0m0s");
369  EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(86401)),
370            "1d0h0m1s");
371  EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(200000)),
372            "2d7h33m20s");
373  EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(200000) +
374                                   base::TimeDelta::FromMilliseconds(1)),
375            "2d7h33m20.001s");
376  EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(-1)),
377            "-1s");
378}
379
380TEST(UtilsTest, TimeFromStructTimespecTest) {
381  struct timespec ts;
382
383  // Unix epoch (Thursday 00:00:00 UTC on Jan 1, 1970)
384  ts = (struct timespec) {.tv_sec = 0, .tv_nsec = 0};
385  EXPECT_EQ(base::Time::UnixEpoch(), utils::TimeFromStructTimespec(&ts));
386
387  // 42 ms after the Unix billennium (Sunday 01:46:40 UTC on September 9, 2001)
388  ts = (struct timespec) {.tv_sec = 1000 * 1000 * 1000,
389                          .tv_nsec = 42 * 1000 * 1000};
390  base::Time::Exploded exploded = (base::Time::Exploded) {
391    .year = 2001, .month = 9, .day_of_week = 0, .day_of_month = 9,
392    .hour = 1, .minute = 46, .second = 40, .millisecond = 42};
393  EXPECT_EQ(base::Time::FromUTCExploded(exploded),
394            utils::TimeFromStructTimespec(&ts));
395}
396
397TEST(UtilsTest, DecodeAndStoreBase64String) {
398  base::FilePath path;
399
400  // Ensure we return false on empty strings or invalid base64.
401  EXPECT_FALSE(utils::DecodeAndStoreBase64String("", &path));
402  EXPECT_FALSE(utils::DecodeAndStoreBase64String("not valid base64", &path));
403
404  // Pass known base64 and check that it matches. This string was generated
405  // the following way:
406  //
407  //   $ echo "Update Engine" | base64
408  //   VXBkYXRlIEVuZ2luZQo=
409  EXPECT_TRUE(utils::DecodeAndStoreBase64String("VXBkYXRlIEVuZ2luZQo=",
410                                                &path));
411  ScopedPathUnlinker unlinker(path.value());
412  string expected_contents = "Update Engine\n";
413  string contents;
414  EXPECT_TRUE(utils::ReadFile(path.value(), &contents));
415  EXPECT_EQ(contents, expected_contents);
416  EXPECT_EQ(static_cast<off_t>(expected_contents.size()),
417            utils::FileSize(path.value()));
418}
419
420TEST(UtilsTest, ConvertToOmahaInstallDate) {
421  // The Omaha Epoch starts at Jan 1, 2007 0:00 PST which is a
422  // Monday. In Unix time, this point in time is easily obtained via
423  // the date(1) command like this:
424  //
425  //  $ date +"%s" --date="Jan 1, 2007 0:00 PST"
426  const time_t omaha_epoch = 1167638400;
427  int value;
428
429  // Points in time *on and after* the Omaha epoch should not fail.
430  EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
431      base::Time::FromTimeT(omaha_epoch), &value));
432  EXPECT_GE(value, 0);
433
434  // Anything before the Omaha epoch should fail. We test it for two points.
435  EXPECT_FALSE(utils::ConvertToOmahaInstallDate(
436      base::Time::FromTimeT(omaha_epoch - 1), &value));
437  EXPECT_FALSE(utils::ConvertToOmahaInstallDate(
438      base::Time::FromTimeT(omaha_epoch - 100*24*3600), &value));
439
440  // Check that we jump from 0 to 7 exactly on the one-week mark, e.g.
441  // on Jan 8, 2007 0:00 PST.
442  EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
443      base::Time::FromTimeT(omaha_epoch + 7*24*3600 - 1), &value));
444  EXPECT_EQ(value, 0);
445  EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
446      base::Time::FromTimeT(omaha_epoch + 7*24*3600), &value));
447  EXPECT_EQ(value, 7);
448
449  // Check a couple of more values.
450  EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
451      base::Time::FromTimeT(omaha_epoch + 10*24*3600), &value));
452  EXPECT_EQ(value, 7);
453  EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
454      base::Time::FromTimeT(omaha_epoch + 20*24*3600), &value));
455  EXPECT_EQ(value, 14);
456  EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
457      base::Time::FromTimeT(omaha_epoch + 26*24*3600), &value));
458  EXPECT_EQ(value, 21);
459  EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
460      base::Time::FromTimeT(omaha_epoch + 29*24*3600), &value));
461  EXPECT_EQ(value, 28);
462
463  // The date Jun 4, 2007 0:00 PDT is a Monday and is hence a point
464  // where the Omaha InstallDate jumps 7 days. Its unix time is
465  // 1180940400. Notably, this is a point in time where Daylight
466  // Savings Time (DST) was is in effect (e.g. it's PDT, not PST).
467  //
468  // Note that as utils::ConvertToOmahaInstallDate() _deliberately_
469  // ignores DST (as it's hard to implement in a thread-safe way using
470  // glibc, see comments in utils.h) we have to fudge by the DST
471  // offset which is one hour. Conveniently, if the function were
472  // someday modified to be DST aware, this test would have to be
473  // modified as well.
474  const time_t dst_time = 1180940400;  // Jun 4, 2007 0:00 PDT.
475  const time_t fudge = 3600;
476  int value1, value2;
477  EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
478      base::Time::FromTimeT(dst_time + fudge - 1), &value1));
479  EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
480      base::Time::FromTimeT(dst_time + fudge), &value2));
481  EXPECT_EQ(value1, value2 - 7);
482}
483
484TEST(UtilsTest, GetMinorVersion) {
485  // Test GetMinorVersion by verifying that it parses the conf file and returns
486  // the correct value.
487  uint32_t minor_version;
488
489  brillo::KeyValueStore store;
490  EXPECT_FALSE(utils::GetMinorVersion(store, &minor_version));
491
492  EXPECT_TRUE(store.LoadFromString("PAYLOAD_MINOR_VERSION=one-two-three\n"));
493  EXPECT_FALSE(utils::GetMinorVersion(store, &minor_version));
494
495  EXPECT_TRUE(store.LoadFromString("PAYLOAD_MINOR_VERSION=123\n"));
496  EXPECT_TRUE(utils::GetMinorVersion(store, &minor_version));
497  EXPECT_EQ(123U, minor_version);
498}
499
500static bool BoolMacroTestHelper() {
501  int i = 1;
502  unsigned int ui = 1;
503  bool b = 1;
504  std::unique_ptr<char> cptr(new char);
505
506  TEST_AND_RETURN_FALSE(i);
507  TEST_AND_RETURN_FALSE(ui);
508  TEST_AND_RETURN_FALSE(b);
509  TEST_AND_RETURN_FALSE(cptr);
510
511  TEST_AND_RETURN_FALSE_ERRNO(i);
512  TEST_AND_RETURN_FALSE_ERRNO(ui);
513  TEST_AND_RETURN_FALSE_ERRNO(b);
514  TEST_AND_RETURN_FALSE_ERRNO(cptr);
515
516  return true;
517}
518
519static void VoidMacroTestHelper(bool* ret) {
520  int i = 1;
521  unsigned int ui = 1;
522  bool b = 1;
523  std::unique_ptr<char> cptr(new char);
524
525  *ret = false;
526
527  TEST_AND_RETURN(i);
528  TEST_AND_RETURN(ui);
529  TEST_AND_RETURN(b);
530  TEST_AND_RETURN(cptr);
531
532  TEST_AND_RETURN_ERRNO(i);
533  TEST_AND_RETURN_ERRNO(ui);
534  TEST_AND_RETURN_ERRNO(b);
535  TEST_AND_RETURN_ERRNO(cptr);
536
537  *ret = true;
538}
539
540TEST(UtilsTest, TestMacros) {
541  bool void_test = false;
542  VoidMacroTestHelper(&void_test);
543  EXPECT_TRUE(void_test);
544
545  EXPECT_TRUE(BoolMacroTestHelper());
546}
547
548}  // namespace chromeos_update_engine
549