blob: 02f919ecdb3269eac2081641c98cfa700d6a8391 [file] [log] [blame]
Alex Deymoaea4c1c2015-08-19 20:24:43 -07001//
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//
adlr@google.com3defe6a2009-12-04 20:57:17 +000016
Alex Deymo39910dc2015-11-09 17:04:30 -080017#include "update_engine/common/utils.h"
Alex Deymo2c0db7b2014-11-04 12:23:39 -080018
Alex Vakulenko44cab302014-07-23 13:12:15 -070019#include <errno.h>
Ben Chan9abb7632014-08-07 00:10:53 -070020#include <stdint.h>
adlr@google.com3defe6a2009-12-04 20:57:17 +000021#include <sys/stat.h>
22#include <sys/types.h>
Darin Petkov5c0a8af2010-08-24 13:39:13 -070023
Andrew de los Reyescc92cd32010-10-05 16:56:14 -070024#include <map>
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -080025#include <string>
adlr@google.com3defe6a2009-12-04 20:57:17 +000026#include <vector>
Darin Petkov5c0a8af2010-08-24 13:39:13 -070027
Alex Deymoc1711e22014-08-08 13:16:23 -070028#include <base/files/file_path.h>
Alex Deymo2c0db7b2014-11-04 12:23:39 -080029#include <base/files/file_util.h>
Allie Wood78750a42015-02-11 15:42:11 -080030#include <base/files/scoped_temp_dir.h>
Alex Vakulenko75039d72014-03-25 12:36:28 -070031#include <base/strings/string_util.h>
32#include <base/strings/stringprintf.h>
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070033#include <brillo/message_loops/fake_message_loop.h>
34#include <brillo/message_loops/message_loop_utils.h>
Darin Petkovd3f8c892010-10-12 21:38:45 -070035#include <gtest/gtest.h>
36
Alex Deymo39910dc2015-11-09 17:04:30 -080037#include "update_engine/common/test_utils.h"
adlr@google.com3defe6a2009-12-04 20:57:17 +000038
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070039using brillo::FakeMessageLoop;
Andrew de los Reyescc92cd32010-10-05 16:56:14 -070040using std::map;
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -080041using std::string;
adlr@google.com3defe6a2009-12-04 20:57:17 +000042using std::vector;
43
44namespace chromeos_update_engine {
45
46class UtilsTest : public ::testing::Test { };
47
Chris Sosac1972482013-04-30 22:31:10 -070048TEST(UtilsTest, CanParseECVersion) {
Chris Sosac1972482013-04-30 22:31:10 -070049 // Should be able to parse and valid key value line.
J. Richard Barnette63137e52013-10-28 10:57:29 -070050 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(
Chris Sosac1972482013-04-30 22:31:10 -070055 "vendor=\"sam\" fw_version=\"00VFA616\""));
56
57 // For invalid entries, should return the empty string.
J. Richard Barnette63137e52013-10-28 10:57:29 -070058 EXPECT_EQ("", utils::ParseECVersion("b=1231a fw_version a=fasd2"));
Chris Sosac1972482013-04-30 22:31:10 -070059}
60
adlr@google.com3defe6a2009-12-04 20:57:17 +000061TEST(UtilsTest, ReadFileFailure) {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070062 brillo::Blob empty;
adlr@google.com3defe6a2009-12-04 20:57:17 +000063 EXPECT_FALSE(utils::ReadFile("/this/doesn't/exist", &empty));
64}
65
Darin Petkov8e447e02013-04-16 16:23:50 +020066TEST(UtilsTest, ReadFileChunk) {
Alex Vakulenko75039d72014-03-25 12:36:28 -070067 base::FilePath file;
68 EXPECT_TRUE(base::CreateTemporaryFile(&file));
Darin Petkov8e447e02013-04-16 16:23:50 +020069 ScopedPathUnlinker unlinker(file.value());
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070070 brillo::Blob data;
Darin Petkov8e447e02013-04-16 16:23:50 +020071 const size_t kSize = 1024 * 1024;
72 for (size_t i = 0; i < kSize; i++) {
73 data.push_back(i % 255);
74 }
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080075 EXPECT_TRUE(utils::WriteFile(file.value().c_str(), data.data(), data.size()));
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070076 brillo::Blob in_data;
Darin Petkov8e447e02013-04-16 16:23:50 +020077 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));
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070083 EXPECT_TRUE(brillo::Blob(data.begin() + 10, data.begin() + 10 + 20) ==
Darin Petkov8e447e02013-04-16 16:23:50 +020084 in_data);
85}
86
adlr@google.com3defe6a2009-12-04 20:57:17 +000087TEST(UtilsTest, ErrnoNumberAsStringTest) {
88 EXPECT_EQ("No such file or directory", utils::ErrnoNumberAsString(ENOENT));
89}
90
Darin Petkov002b2fe2010-11-22 13:53:22 -080091TEST(UtilsTest, IsSymlinkTest) {
92 string temp_dir;
Gilad Arnolda6742b32014-01-11 00:18:34 -080093 EXPECT_TRUE(utils::MakeTempDirectory("symlink-test.XXXXXX", &temp_dir));
Alex Deymo8d925292014-05-21 19:15:25 -070094 string temp_file = temp_dir + "/temp-file";
Darin Petkov002b2fe2010-11-22 13:53:22 -080095 EXPECT_TRUE(utils::WriteFile(temp_file.c_str(), "", 0));
Alex Deymo8d925292014-05-21 19:15:25 -070096 string temp_symlink = temp_dir + "/temp-symlink";
Darin Petkov002b2fe2010-11-22 13:53:22 -080097 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"));
Alex Deymo110e0302015-10-19 20:35:21 -0700102 EXPECT_TRUE(base::DeleteFile(base::FilePath(temp_dir), true));
Darin Petkov002b2fe2010-11-22 13:53:22 -0800103}
104
Alex Deymo763e7db2015-08-27 21:08:08 -0700105TEST(UtilsTest, SplitPartitionNameTest) {
106 string disk;
107 int part_num;
Darin Petkovf74eb652010-08-04 12:08:38 -0700108
Alex Deymo763e7db2015-08-27 21:08:08 -0700109 EXPECT_TRUE(utils::SplitPartitionName("/dev/sda3", &disk, &part_num));
110 EXPECT_EQ("/dev/sda", disk);
111 EXPECT_EQ(3, part_num);
Darin Petkovf74eb652010-08-04 12:08:38 -0700112
Alex Deymo763e7db2015-08-27 21:08:08 -0700113 EXPECT_TRUE(utils::SplitPartitionName("/dev/sdp1234", &disk, &part_num));
114 EXPECT_EQ("/dev/sdp", disk);
115 EXPECT_EQ(1234, part_num);
Andrew de los Reyesf9714432010-05-04 10:21:23 -0700116
Alex Deymo763e7db2015-08-27 21:08:08 -0700117 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));
Andrew de los Reyesf9714432010-05-04 10:21:23 -0700146}
147
Alex Vakulenkof3f85bb2014-03-26 16:36:35 -0700148TEST(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));
Nam T. Nguyena78b28c2015-03-06 22:30:12 -0800155 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"));
Alex Vakulenkof3f85bb2014-03-26 16:36:35 -0700181}
182
Alex Deymo10875d92014-11-10 21:52:57 -0800183namespace {
184// Compares cpu shares and returns an integer that is less
185// than, equal to or greater than 0 if |shares_lhs| is,
186// respectively, lower than, same as or higher than |shares_rhs|.
187int CompareCpuShares(utils::CpuShares shares_lhs,
188 utils::CpuShares shares_rhs) {
189 return static_cast<int>(shares_lhs) - static_cast<int>(shares_rhs);
190}
191} // namespace
Alex Vakulenkof3f85bb2014-03-26 16:36:35 -0700192
Alex Deymo10875d92014-11-10 21:52:57 -0800193// Tests the CPU shares enum is in the order we expect it.
Chris Sosa4f8ee272012-11-30 13:01:54 -0800194TEST(UtilsTest, CompareCpuSharesTest) {
Alex Deymo10875d92014-11-10 21:52:57 -0800195 EXPECT_LT(CompareCpuShares(utils::kCpuSharesLow,
196 utils::kCpuSharesNormal), 0);
197 EXPECT_GT(CompareCpuShares(utils::kCpuSharesNormal,
198 utils::kCpuSharesLow), 0);
199 EXPECT_EQ(CompareCpuShares(utils::kCpuSharesNormal,
200 utils::kCpuSharesNormal), 0);
201 EXPECT_GT(CompareCpuShares(utils::kCpuSharesHigh,
202 utils::kCpuSharesNormal), 0);
Darin Petkovc6c135c2010-08-11 13:36:18 -0700203}
204
Darin Petkov5c0a8af2010-08-24 13:39:13 -0700205TEST(UtilsTest, FuzzIntTest) {
206 static const unsigned int kRanges[] = { 0, 1, 2, 20 };
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800207 for (unsigned int range : kRanges) {
Darin Petkov5c0a8af2010-08-24 13:39:13 -0700208 const int kValue = 50;
209 for (int tries = 0; tries < 100; ++tries) {
210 int value = utils::FuzzInt(kValue, range);
211 EXPECT_GE(value, kValue - range / 2);
212 EXPECT_LE(value, kValue + range - range / 2);
213 }
214 }
215}
216
Darin Petkovd3f8c892010-10-12 21:38:45 -0700217TEST(UtilsTest, RunAsRootGetFilesystemSizeTest) {
218 string img;
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700219 EXPECT_TRUE(utils::MakeTempFile("img.XXXXXX", &img, nullptr));
Darin Petkovd3f8c892010-10-12 21:38:45 -0700220 ScopedPathUnlinker img_unlinker(img);
Alex Deymo10875d92014-11-10 21:52:57 -0800221 test_utils::CreateExtImageAtPath(img, nullptr);
Darin Petkovd3f8c892010-10-12 21:38:45 -0700222 // Extend the "partition" holding the file system from 10MiB to 20MiB.
Alex Deymo10875d92014-11-10 21:52:57 -0800223 EXPECT_EQ(0, test_utils::System(base::StringPrintf(
Alex Deymo1f93d032015-03-10 18:58:32 -0700224 "dd if=/dev/zero of=%s seek=20971519 bs=1 count=1 status=none",
Darin Petkovd3f8c892010-10-12 21:38:45 -0700225 img.c_str())));
226 EXPECT_EQ(20 * 1024 * 1024, utils::FileSize(img));
227 int block_count = 0;
228 int block_size = 0;
229 EXPECT_TRUE(utils::GetFilesystemSize(img, &block_count, &block_size));
230 EXPECT_EQ(4096, block_size);
231 EXPECT_EQ(10 * 1024 * 1024 / 4096, block_count);
232}
233
Alex Deymo192393b2014-11-10 15:58:38 -0800234// Squashfs example filesystem, generated with:
235// echo hola>hola
236// mksquashfs hola hola.sqfs -noappend -nopad
237// hexdump hola.sqfs -e '16/1 "%02x, " "\n"'
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800238const uint8_t kSquashfsFile[] = {
Alex Deymo192393b2014-11-10 15:58:38 -0800239 0x68, 0x73, 0x71, 0x73, 0x02, 0x00, 0x00, 0x00, // magic, inodes
240 0x3e, 0x49, 0x61, 0x54, 0x00, 0x00, 0x02, 0x00,
241 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x11, 0x00,
242 0xc0, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, // flags, noids, major, minor
243 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // root_inode
244 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // bytes_used
245 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
246 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
247 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
248 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
249 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
250 0xd5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
251 0x68, 0x6f, 0x6c, 0x61, 0x0a, 0x2c, 0x00, 0x78,
252 0xda, 0x63, 0x62, 0x58, 0xc2, 0xc8, 0xc0, 0xc0,
253 0xc8, 0xd0, 0x6b, 0x91, 0x18, 0x02, 0x64, 0xa0,
254 0x00, 0x56, 0x06, 0x90, 0xcc, 0x7f, 0xb0, 0xbc,
255 0x9d, 0x67, 0x62, 0x08, 0x13, 0x54, 0x1c, 0x44,
256 0x4b, 0x03, 0x31, 0x33, 0x10, 0x03, 0x00, 0xb5,
257 0x87, 0x04, 0x89, 0x16, 0x00, 0x78, 0xda, 0x63,
258 0x60, 0x80, 0x00, 0x46, 0x28, 0xcd, 0xc4, 0xc0,
259 0xcc, 0x90, 0x91, 0x9f, 0x93, 0x08, 0x00, 0x04,
260 0x70, 0x01, 0xab, 0x10, 0x80, 0x60, 0x00, 0x00,
261 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
262 0x01, 0x00, 0x00, 0x00, 0x00, 0xab, 0x00, 0x00,
263 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x78,
264 0xda, 0x63, 0x60, 0x80, 0x00, 0x05, 0x28, 0x0d,
265 0x00, 0x01, 0x10, 0x00, 0x21, 0xc5, 0x00, 0x00,
266 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0x99,
267 0xcd, 0x02, 0x00, 0x88, 0x13, 0x00, 0x00, 0xdd,
268 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
269};
270
271TEST(UtilsTest, GetSquashfs4Size) {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800272 uint8_t buffer[sizeof(kSquashfsFile)];
Alex Deymo192393b2014-11-10 15:58:38 -0800273 memcpy(buffer, kSquashfsFile, sizeof(kSquashfsFile));
274
275 int block_count = -1;
276 int block_size = -1;
277 // Not enough bytes passed.
278 EXPECT_FALSE(utils::GetSquashfs4Size(buffer, 10, nullptr, nullptr));
279
280 // The whole file system is passed, which is enough for parsing.
281 EXPECT_TRUE(utils::GetSquashfs4Size(buffer, sizeof(kSquashfsFile),
282 &block_count, &block_size));
283 EXPECT_EQ(4096, block_size);
284 EXPECT_EQ(1, block_count);
285
286 // Modify the major version to 5.
287 uint16_t* s_major = reinterpret_cast<uint16_t*>(buffer + 0x1c);
288 *s_major = 5;
289 EXPECT_FALSE(utils::GetSquashfs4Size(buffer, 10, nullptr, nullptr));
290 memcpy(buffer, kSquashfsFile, sizeof(kSquashfsFile));
291
292 // Modify the bytes_used to have 6 blocks.
293 int64_t* bytes_used = reinterpret_cast<int64_t*>(buffer + 0x28);
294 *bytes_used = 4096 * 5 + 1; // 6 "blocks".
295 EXPECT_TRUE(utils::GetSquashfs4Size(buffer, sizeof(kSquashfsFile),
296 &block_count, &block_size));
297 EXPECT_EQ(4096, block_size);
298 EXPECT_EQ(6, block_count);
299}
300
Andrew de los Reyes712b3ac2011-01-07 13:47:52 -0800301namespace {
Alex Deymo032e7722014-03-25 17:53:56 -0700302void GetFileFormatTester(const string& expected,
Ben Chan9abb7632014-08-07 00:10:53 -0700303 const vector<uint8_t>& contents) {
Alex Deymo10875d92014-11-10 21:52:57 -0800304 test_utils::ScopedTempFile file;
Alex Deymo032e7722014-03-25 17:53:56 -0700305 ASSERT_TRUE(utils::WriteFile(file.GetPath().c_str(),
306 reinterpret_cast<const char*>(contents.data()),
307 contents.size()));
308 EXPECT_EQ(expected, utils::GetFileFormat(file.GetPath()));
309}
Alex Deymo10875d92014-11-10 21:52:57 -0800310} // namespace
Alex Deymo032e7722014-03-25 17:53:56 -0700311
312TEST(UtilsTest, GetFileFormatTest) {
313 EXPECT_EQ("File not found.", utils::GetFileFormat("/path/to/nowhere"));
Ben Chan9abb7632014-08-07 00:10:53 -0700314 GetFileFormatTester("data", vector<uint8_t>{1, 2, 3, 4, 5, 6, 7, 8});
315 GetFileFormatTester("ELF", vector<uint8_t>{0x7f, 0x45, 0x4c, 0x46});
Alex Deymo032e7722014-03-25 17:53:56 -0700316
317 // Real tests from cros_installer on different boards.
318 // ELF 32-bit LSB executable, Intel 80386
319 GetFileFormatTester(
320 "ELF 32-bit little-endian x86",
Ben Chan9abb7632014-08-07 00:10:53 -0700321 vector<uint8_t>{0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00,
322 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
323 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00,
324 0x90, 0x83, 0x04, 0x08, 0x34, 0x00, 0x00, 0x00});
Alex Deymo032e7722014-03-25 17:53:56 -0700325
Alex Deymoc1711e22014-08-08 13:16:23 -0700326 // ELF 32-bit LSB executable, MIPS
327 GetFileFormatTester(
328 "ELF 32-bit little-endian mips",
329 vector<uint8_t>{0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00,
330 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
331 0x03, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00,
332 0xc0, 0x12, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00});
333
Alex Deymo032e7722014-03-25 17:53:56 -0700334 // ELF 32-bit LSB executable, ARM
335 GetFileFormatTester(
336 "ELF 32-bit little-endian arm",
Ben Chan9abb7632014-08-07 00:10:53 -0700337 vector<uint8_t>{0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00,
338 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
339 0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00,
340 0x85, 0x8b, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00});
Alex Deymo032e7722014-03-25 17:53:56 -0700341
342 // ELF 64-bit LSB executable, x86-64
343 GetFileFormatTester(
344 "ELF 64-bit little-endian x86-64",
Ben Chan9abb7632014-08-07 00:10:53 -0700345 vector<uint8_t>{0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00,
346 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
347 0x02, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00,
348 0xb0, 0x04, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00});
Alex Deymo032e7722014-03-25 17:53:56 -0700349}
350
Andrew de los Reyes712b3ac2011-01-07 13:47:52 -0800351TEST(UtilsTest, ScheduleCrashReporterUploadTest) {
352 // Not much to test. At least this tests for memory leaks, crashes,
353 // log errors.
Alex Deymo60ca1a72015-06-18 18:19:15 -0700354 FakeMessageLoop loop(nullptr);
355 loop.SetAsCurrent();
Andrew de los Reyes712b3ac2011-01-07 13:47:52 -0800356 utils::ScheduleCrashReporterUpload();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700357 // Test that we scheduled one callback from the crash reporter.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700358 EXPECT_EQ(1, brillo::MessageLoopRunMaxIterations(&loop, 100));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700359 EXPECT_FALSE(loop.PendingTasks());
Andrew de los Reyes712b3ac2011-01-07 13:47:52 -0800360}
361
David Zeuthen674c3182013-04-18 14:05:20 -0700362TEST(UtilsTest, FormatTimeDeltaTest) {
363 // utils::FormatTimeDelta() is not locale-aware (it's only used for logging
364 // which is not localized) so we only need to test the C locale
365 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromMilliseconds(100)),
366 "0.1s");
367 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(0)),
368 "0s");
369 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(1)),
370 "1s");
371 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(59)),
372 "59s");
373 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(60)),
374 "1m0s");
375 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(61)),
376 "1m1s");
377 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(90)),
378 "1m30s");
379 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(1205)),
380 "20m5s");
381 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(3600)),
382 "1h0m0s");
383 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(3601)),
384 "1h0m1s");
385 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(3661)),
386 "1h1m1s");
387 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(7261)),
388 "2h1m1s");
389 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(86400)),
390 "1d0h0m0s");
391 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(86401)),
392 "1d0h0m1s");
393 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(200000)),
394 "2d7h33m20s");
395 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(200000) +
396 base::TimeDelta::FromMilliseconds(1)),
397 "2d7h33m20.001s");
David Zeuthen973449e2014-08-18 16:18:23 -0400398 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(-1)),
399 "-1s");
David Zeuthen674c3182013-04-18 14:05:20 -0700400}
401
David Zeuthen27a48bc2013-08-06 12:06:29 -0700402TEST(UtilsTest, TimeFromStructTimespecTest) {
403 struct timespec ts;
404
405 // Unix epoch (Thursday 00:00:00 UTC on Jan 1, 1970)
406 ts = (struct timespec) {.tv_sec = 0, .tv_nsec = 0};
407 EXPECT_EQ(base::Time::UnixEpoch(), utils::TimeFromStructTimespec(&ts));
408
409 // 42 ms after the Unix billennium (Sunday 01:46:40 UTC on September 9, 2001)
410 ts = (struct timespec) {.tv_sec = 1000 * 1000 * 1000,
411 .tv_nsec = 42 * 1000 * 1000};
412 base::Time::Exploded exploded = (base::Time::Exploded) {
413 .year = 2001, .month = 9, .day_of_week = 0, .day_of_month = 9,
414 .hour = 1, .minute = 46, .second = 40, .millisecond = 42};
415 EXPECT_EQ(base::Time::FromUTCExploded(exploded),
416 utils::TimeFromStructTimespec(&ts));
417}
418
David Zeuthene7f89172013-10-31 10:21:04 -0700419TEST(UtilsTest, DecodeAndStoreBase64String) {
420 base::FilePath path;
421
422 // Ensure we return false on empty strings or invalid base64.
423 EXPECT_FALSE(utils::DecodeAndStoreBase64String("", &path));
424 EXPECT_FALSE(utils::DecodeAndStoreBase64String("not valid base64", &path));
425
426 // Pass known base64 and check that it matches. This string was generated
427 // the following way:
428 //
429 // $ echo "Update Engine" | base64
430 // VXBkYXRlIEVuZ2luZQo=
431 EXPECT_TRUE(utils::DecodeAndStoreBase64String("VXBkYXRlIEVuZ2luZQo=",
432 &path));
433 ScopedPathUnlinker unlinker(path.value());
434 string expected_contents = "Update Engine\n";
435 string contents;
436 EXPECT_TRUE(utils::ReadFile(path.value(), &contents));
437 EXPECT_EQ(contents, expected_contents);
438 EXPECT_EQ(utils::FileSize(path.value()), expected_contents.size());
439}
440
David Zeuthen639aa362014-02-03 16:23:44 -0800441TEST(UtilsTest, ConvertToOmahaInstallDate) {
442 // The Omaha Epoch starts at Jan 1, 2007 0:00 PST which is a
443 // Monday. In Unix time, this point in time is easily obtained via
444 // the date(1) command like this:
445 //
446 // $ date +"%s" --date="Jan 1, 2007 0:00 PST"
447 const time_t omaha_epoch = 1167638400;
448 int value;
449
450 // Points in time *on and after* the Omaha epoch should not fail.
451 EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
452 base::Time::FromTimeT(omaha_epoch), &value));
453 EXPECT_GE(value, 0);
454
455 // Anything before the Omaha epoch should fail. We test it for two points.
456 EXPECT_FALSE(utils::ConvertToOmahaInstallDate(
457 base::Time::FromTimeT(omaha_epoch - 1), &value));
458 EXPECT_FALSE(utils::ConvertToOmahaInstallDate(
459 base::Time::FromTimeT(omaha_epoch - 100*24*3600), &value));
460
461 // Check that we jump from 0 to 7 exactly on the one-week mark, e.g.
462 // on Jan 8, 2007 0:00 PST.
463 EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
464 base::Time::FromTimeT(omaha_epoch + 7*24*3600 - 1), &value));
465 EXPECT_EQ(value, 0);
466 EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
467 base::Time::FromTimeT(omaha_epoch + 7*24*3600), &value));
468 EXPECT_EQ(value, 7);
469
470 // Check a couple of more values.
471 EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
472 base::Time::FromTimeT(omaha_epoch + 10*24*3600), &value));
473 EXPECT_EQ(value, 7);
474 EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
475 base::Time::FromTimeT(omaha_epoch + 20*24*3600), &value));
476 EXPECT_EQ(value, 14);
477 EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
478 base::Time::FromTimeT(omaha_epoch + 26*24*3600), &value));
479 EXPECT_EQ(value, 21);
480 EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
481 base::Time::FromTimeT(omaha_epoch + 29*24*3600), &value));
482 EXPECT_EQ(value, 28);
483
484 // The date Jun 4, 2007 0:00 PDT is a Monday and is hence a point
485 // where the Omaha InstallDate jumps 7 days. Its unix time is
486 // 1180940400. Notably, this is a point in time where Daylight
487 // Savings Time (DST) was is in effect (e.g. it's PDT, not PST).
488 //
489 // Note that as utils::ConvertToOmahaInstallDate() _deliberately_
490 // ignores DST (as it's hard to implement in a thread-safe way using
491 // glibc, see comments in utils.h) we have to fudge by the DST
492 // offset which is one hour. Conveniently, if the function were
493 // someday modified to be DST aware, this test would have to be
494 // modified as well.
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700495 const time_t dst_time = 1180940400; // Jun 4, 2007 0:00 PDT.
David Zeuthen639aa362014-02-03 16:23:44 -0800496 const time_t fudge = 3600;
497 int value1, value2;
498 EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
499 base::Time::FromTimeT(dst_time + fudge - 1), &value1));
500 EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
501 base::Time::FromTimeT(dst_time + fudge), &value2));
502 EXPECT_EQ(value1, value2 - 7);
503}
504
Allie Wood78750a42015-02-11 15:42:11 -0800505TEST(UtilsTest, GetMinorVersion) {
506 // Test GetMinorVersion by verifying that it parses the conf file and returns
507 // the correct value.
Allie Wood78750a42015-02-11 15:42:11 -0800508 uint32_t minor_version;
509
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700510 brillo::KeyValueStore store;
Alex Deymob42b98d2015-07-06 17:42:38 -0700511 EXPECT_FALSE(utils::GetMinorVersion(store, &minor_version));
Allie Wood78750a42015-02-11 15:42:11 -0800512
Alex Deymob42b98d2015-07-06 17:42:38 -0700513 EXPECT_TRUE(store.LoadFromString("PAYLOAD_MINOR_VERSION=one-two-three\n"));
514 EXPECT_FALSE(utils::GetMinorVersion(store, &minor_version));
Allie Wood78750a42015-02-11 15:42:11 -0800515
Alex Deymob42b98d2015-07-06 17:42:38 -0700516 EXPECT_TRUE(store.LoadFromString("PAYLOAD_MINOR_VERSION=123\n"));
517 EXPECT_TRUE(utils::GetMinorVersion(store, &minor_version));
518 EXPECT_EQ(minor_version, 123);
Allie Wood78750a42015-02-11 15:42:11 -0800519}
520
Nam T. Nguyen2b67a592014-12-03 14:56:00 -0800521static bool BoolMacroTestHelper() {
522 int i = 1;
523 unsigned int ui = 1;
524 bool b = 1;
525 std::unique_ptr<char> cptr(new char);
526
527 TEST_AND_RETURN_FALSE(i);
528 TEST_AND_RETURN_FALSE(ui);
529 TEST_AND_RETURN_FALSE(b);
530 TEST_AND_RETURN_FALSE(cptr);
531
532 TEST_AND_RETURN_FALSE_ERRNO(i);
533 TEST_AND_RETURN_FALSE_ERRNO(ui);
534 TEST_AND_RETURN_FALSE_ERRNO(b);
535 TEST_AND_RETURN_FALSE_ERRNO(cptr);
536
537 return true;
538}
539
540static void VoidMacroTestHelper(bool* ret) {
541 int i = 1;
542 unsigned int ui = 1;
543 bool b = 1;
544 std::unique_ptr<char> cptr(new char);
545
546 *ret = false;
547
548 TEST_AND_RETURN(i);
549 TEST_AND_RETURN(ui);
550 TEST_AND_RETURN(b);
551 TEST_AND_RETURN(cptr);
552
553 TEST_AND_RETURN_ERRNO(i);
554 TEST_AND_RETURN_ERRNO(ui);
555 TEST_AND_RETURN_ERRNO(b);
556 TEST_AND_RETURN_ERRNO(cptr);
557
558 *ret = true;
559}
560
561TEST(UtilsTest, TestMacros) {
562 bool void_test = false;
563 VoidMacroTestHelper(&void_test);
564 EXPECT_TRUE(void_test);
565
566 EXPECT_TRUE(BoolMacroTestHelper());
567}
568
adlr@google.com3defe6a2009-12-04 20:57:17 +0000569} // namespace chromeos_update_engine