blob: 5bc242832a8fbe8229fec393d4e56db61ea98756 [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>
Sen Jiang990c27b2016-03-15 17:09:21 -070020#include <fcntl.h>
Ben Chan9abb7632014-08-07 00:10:53 -070021#include <stdint.h>
adlr@google.com3defe6a2009-12-04 20:57:17 +000022#include <sys/stat.h>
23#include <sys/types.h>
Darin Petkov5c0a8af2010-08-24 13:39:13 -070024
Andrew de los Reyescc92cd32010-10-05 16:56:14 -070025#include <map>
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -080026#include <string>
adlr@google.com3defe6a2009-12-04 20:57:17 +000027#include <vector>
Darin Petkov5c0a8af2010-08-24 13:39:13 -070028
Alex Deymoc1711e22014-08-08 13:16:23 -070029#include <base/files/file_path.h>
Alex Deymo2c0db7b2014-11-04 12:23:39 -080030#include <base/files/file_util.h>
Allie Wood78750a42015-02-11 15:42:11 -080031#include <base/files/scoped_temp_dir.h>
Alex Vakulenko75039d72014-03-25 12:36:28 -070032#include <base/strings/string_util.h>
33#include <base/strings/stringprintf.h>
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070034#include <brillo/message_loops/fake_message_loop.h>
35#include <brillo/message_loops/message_loop_utils.h>
Darin Petkovd3f8c892010-10-12 21:38:45 -070036#include <gtest/gtest.h>
37
Alex Deymo39910dc2015-11-09 17:04:30 -080038#include "update_engine/common/test_utils.h"
adlr@google.com3defe6a2009-12-04 20:57:17 +000039
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070040using brillo::FakeMessageLoop;
Andrew de los Reyescc92cd32010-10-05 16:56:14 -070041using std::map;
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -080042using std::string;
adlr@google.com3defe6a2009-12-04 20:57:17 +000043using std::vector;
44
45namespace chromeos_update_engine {
46
47class UtilsTest : public ::testing::Test { };
48
Chris Sosac1972482013-04-30 22:31:10 -070049TEST(UtilsTest, CanParseECVersion) {
Chris Sosac1972482013-04-30 22:31:10 -070050 // Should be able to parse and valid key value line.
J. Richard Barnette63137e52013-10-28 10:57:29 -070051 EXPECT_EQ("12345", utils::ParseECVersion("fw_version=12345"));
52 EXPECT_EQ("123456", utils::ParseECVersion(
53 "b=1231a fw_version=123456 a=fasd2"));
54 EXPECT_EQ("12345", utils::ParseECVersion("fw_version=12345"));
55 EXPECT_EQ("00VFA616", utils::ParseECVersion(
Chris Sosac1972482013-04-30 22:31:10 -070056 "vendor=\"sam\" fw_version=\"00VFA616\""));
57
58 // For invalid entries, should return the empty string.
J. Richard Barnette63137e52013-10-28 10:57:29 -070059 EXPECT_EQ("", utils::ParseECVersion("b=1231a fw_version a=fasd2"));
Chris Sosac1972482013-04-30 22:31:10 -070060}
61
adlr@google.com3defe6a2009-12-04 20:57:17 +000062TEST(UtilsTest, ReadFileFailure) {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070063 brillo::Blob empty;
adlr@google.com3defe6a2009-12-04 20:57:17 +000064 EXPECT_FALSE(utils::ReadFile("/this/doesn't/exist", &empty));
65}
66
Darin Petkov8e447e02013-04-16 16:23:50 +020067TEST(UtilsTest, ReadFileChunk) {
Alex Vakulenko75039d72014-03-25 12:36:28 -070068 base::FilePath file;
69 EXPECT_TRUE(base::CreateTemporaryFile(&file));
Darin Petkov8e447e02013-04-16 16:23:50 +020070 ScopedPathUnlinker unlinker(file.value());
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070071 brillo::Blob data;
Darin Petkov8e447e02013-04-16 16:23:50 +020072 const size_t kSize = 1024 * 1024;
73 for (size_t i = 0; i < kSize; i++) {
74 data.push_back(i % 255);
75 }
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080076 EXPECT_TRUE(utils::WriteFile(file.value().c_str(), data.data(), data.size()));
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070077 brillo::Blob in_data;
Darin Petkov8e447e02013-04-16 16:23:50 +020078 EXPECT_TRUE(utils::ReadFileChunk(file.value().c_str(), kSize, 10, &in_data));
79 EXPECT_TRUE(in_data.empty());
80 EXPECT_TRUE(utils::ReadFileChunk(file.value().c_str(), 0, -1, &in_data));
81 EXPECT_TRUE(data == in_data);
82 in_data.clear();
83 EXPECT_TRUE(utils::ReadFileChunk(file.value().c_str(), 10, 20, &in_data));
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070084 EXPECT_TRUE(brillo::Blob(data.begin() + 10, data.begin() + 10 + 20) ==
Darin Petkov8e447e02013-04-16 16:23:50 +020085 in_data);
86}
87
adlr@google.com3defe6a2009-12-04 20:57:17 +000088TEST(UtilsTest, ErrnoNumberAsStringTest) {
89 EXPECT_EQ("No such file or directory", utils::ErrnoNumberAsString(ENOENT));
90}
91
Darin Petkov002b2fe2010-11-22 13:53:22 -080092TEST(UtilsTest, IsSymlinkTest) {
93 string temp_dir;
Gilad Arnolda6742b32014-01-11 00:18:34 -080094 EXPECT_TRUE(utils::MakeTempDirectory("symlink-test.XXXXXX", &temp_dir));
Alex Deymo8d925292014-05-21 19:15:25 -070095 string temp_file = temp_dir + "/temp-file";
Darin Petkov002b2fe2010-11-22 13:53:22 -080096 EXPECT_TRUE(utils::WriteFile(temp_file.c_str(), "", 0));
Alex Deymo8d925292014-05-21 19:15:25 -070097 string temp_symlink = temp_dir + "/temp-symlink";
Darin Petkov002b2fe2010-11-22 13:53:22 -080098 EXPECT_EQ(0, symlink(temp_file.c_str(), temp_symlink.c_str()));
99 EXPECT_FALSE(utils::IsSymlink(temp_dir.c_str()));
100 EXPECT_FALSE(utils::IsSymlink(temp_file.c_str()));
101 EXPECT_TRUE(utils::IsSymlink(temp_symlink.c_str()));
102 EXPECT_FALSE(utils::IsSymlink("/non/existent/path"));
Alex Deymo110e0302015-10-19 20:35:21 -0700103 EXPECT_TRUE(base::DeleteFile(base::FilePath(temp_dir), true));
Darin Petkov002b2fe2010-11-22 13:53:22 -0800104}
105
Alex Deymo763e7db2015-08-27 21:08:08 -0700106TEST(UtilsTest, SplitPartitionNameTest) {
107 string disk;
108 int part_num;
Darin Petkovf74eb652010-08-04 12:08:38 -0700109
Alex Deymo763e7db2015-08-27 21:08:08 -0700110 EXPECT_TRUE(utils::SplitPartitionName("/dev/sda3", &disk, &part_num));
111 EXPECT_EQ("/dev/sda", disk);
112 EXPECT_EQ(3, part_num);
Darin Petkovf74eb652010-08-04 12:08:38 -0700113
Alex Deymo763e7db2015-08-27 21:08:08 -0700114 EXPECT_TRUE(utils::SplitPartitionName("/dev/sdp1234", &disk, &part_num));
115 EXPECT_EQ("/dev/sdp", disk);
116 EXPECT_EQ(1234, part_num);
Andrew de los Reyesf9714432010-05-04 10:21:23 -0700117
Alex Deymo763e7db2015-08-27 21:08:08 -0700118 EXPECT_TRUE(utils::SplitPartitionName("/dev/mmcblk0p3", &disk, &part_num));
119 EXPECT_EQ("/dev/mmcblk0", disk);
120 EXPECT_EQ(3, part_num);
121
122 EXPECT_TRUE(utils::SplitPartitionName("/dev/ubiblock3_2", &disk, &part_num));
123 EXPECT_EQ("/dev/ubiblock", disk);
124 EXPECT_EQ(3, part_num);
125
126 EXPECT_TRUE(utils::SplitPartitionName("/dev/loop10", &disk, &part_num));
127 EXPECT_EQ("/dev/loop", disk);
128 EXPECT_EQ(10, part_num);
129
130 EXPECT_TRUE(utils::SplitPartitionName("/dev/loop28p11", &disk, &part_num));
131 EXPECT_EQ("/dev/loop28", disk);
132 EXPECT_EQ(11, part_num);
133
134 EXPECT_TRUE(utils::SplitPartitionName("/dev/loop10_0", &disk, &part_num));
135 EXPECT_EQ("/dev/loop", disk);
136 EXPECT_EQ(10, part_num);
137
138 EXPECT_TRUE(utils::SplitPartitionName("/dev/loop28p11_0", &disk, &part_num));
139 EXPECT_EQ("/dev/loop28", disk);
140 EXPECT_EQ(11, part_num);
141
142 EXPECT_FALSE(utils::SplitPartitionName("/dev/mmcblk0p", &disk, &part_num));
143 EXPECT_FALSE(utils::SplitPartitionName("/dev/sda", &disk, &part_num));
144 EXPECT_FALSE(utils::SplitPartitionName("/dev/foo/bar", &disk, &part_num));
145 EXPECT_FALSE(utils::SplitPartitionName("/", &disk, &part_num));
146 EXPECT_FALSE(utils::SplitPartitionName("", &disk, &part_num));
Andrew de los Reyesf9714432010-05-04 10:21:23 -0700147}
148
Alex Vakulenkof3f85bb2014-03-26 16:36:35 -0700149TEST(UtilsTest, MakePartitionNameTest) {
150 EXPECT_EQ("/dev/sda4", utils::MakePartitionName("/dev/sda", 4));
151 EXPECT_EQ("/dev/sda123", utils::MakePartitionName("/dev/sda", 123));
152 EXPECT_EQ("/dev/mmcblk2", utils::MakePartitionName("/dev/mmcblk", 2));
153 EXPECT_EQ("/dev/mmcblk0p2", utils::MakePartitionName("/dev/mmcblk0", 2));
154 EXPECT_EQ("/dev/loop8", utils::MakePartitionName("/dev/loop", 8));
155 EXPECT_EQ("/dev/loop12p2", utils::MakePartitionName("/dev/loop12", 2));
Nam T. Nguyena78b28c2015-03-06 22:30:12 -0800156 EXPECT_EQ("/dev/ubi5_0", utils::MakePartitionName("/dev/ubiblock", 5));
157 EXPECT_EQ("/dev/mtd4", utils::MakePartitionName("/dev/ubiblock", 4));
158 EXPECT_EQ("/dev/ubi3_0", utils::MakePartitionName("/dev/ubiblock", 3));
159 EXPECT_EQ("/dev/mtd2", utils::MakePartitionName("/dev/ubiblock", 2));
160 EXPECT_EQ("/dev/ubi1_0", utils::MakePartitionName("/dev/ubiblock", 1));
161}
162
163TEST(UtilsTest, MakePartitionNameForMountTest) {
164 EXPECT_EQ("/dev/sda4", utils::MakePartitionNameForMount("/dev/sda4"));
165 EXPECT_EQ("/dev/sda123", utils::MakePartitionNameForMount("/dev/sda123"));
166 EXPECT_EQ("/dev/mmcblk2", utils::MakePartitionNameForMount("/dev/mmcblk2"));
167 EXPECT_EQ("/dev/mmcblk0p2",
168 utils::MakePartitionNameForMount("/dev/mmcblk0p2"));
169 EXPECT_EQ("/dev/loop0", utils::MakePartitionNameForMount("/dev/loop0"));
170 EXPECT_EQ("/dev/loop8", utils::MakePartitionNameForMount("/dev/loop8"));
171 EXPECT_EQ("/dev/loop12p2",
172 utils::MakePartitionNameForMount("/dev/loop12p2"));
173 EXPECT_EQ("/dev/ubiblock5_0",
174 utils::MakePartitionNameForMount("/dev/ubiblock5_0"));
175 EXPECT_EQ("/dev/mtd4",
176 utils::MakePartitionNameForMount("/dev/ubi4_0"));
177 EXPECT_EQ("/dev/ubiblock3_0",
178 utils::MakePartitionNameForMount("/dev/ubiblock3"));
179 EXPECT_EQ("/dev/mtd2", utils::MakePartitionNameForMount("/dev/ubi2"));
180 EXPECT_EQ("/dev/ubi1_0",
181 utils::MakePartitionNameForMount("/dev/ubiblock1"));
Alex Vakulenkof3f85bb2014-03-26 16:36:35 -0700182}
183
Darin Petkov5c0a8af2010-08-24 13:39:13 -0700184TEST(UtilsTest, FuzzIntTest) {
Alex Deymo80f70ff2016-02-10 16:08:11 -0800185 static const uint32_t kRanges[] = { 0, 1, 2, 20 };
186 for (uint32_t range : kRanges) {
Darin Petkov5c0a8af2010-08-24 13:39:13 -0700187 const int kValue = 50;
188 for (int tries = 0; tries < 100; ++tries) {
Alex Deymo80f70ff2016-02-10 16:08:11 -0800189 uint32_t value = utils::FuzzInt(kValue, range);
Darin Petkov5c0a8af2010-08-24 13:39:13 -0700190 EXPECT_GE(value, kValue - range / 2);
191 EXPECT_LE(value, kValue + range - range / 2);
192 }
193 }
194}
195
Sen Jiang990c27b2016-03-15 17:09:21 -0700196TEST(UtilsTest, GetFilesystemSizeTest) {
Darin Petkovd3f8c892010-10-12 21:38:45 -0700197 string img;
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700198 EXPECT_TRUE(utils::MakeTempFile("img.XXXXXX", &img, nullptr));
Darin Petkovd3f8c892010-10-12 21:38:45 -0700199 ScopedPathUnlinker img_unlinker(img);
Sen Jiang990c27b2016-03-15 17:09:21 -0700200 EXPECT_TRUE(base::CopyFile(
201 test_utils::GetBuildArtifactsPath().Append("gen/disk_ext2_4k.img"),
202 base::FilePath(img)));
203 {
204 // Extend the "partition" holding the file system from 4MiB to 10MiB.
205 int fd = HANDLE_EINTR(open(img.c_str(), O_WRONLY));
206 ASSERT_GT(fd, 0);
207 ScopedFdCloser fd_closer(&fd);
208 EXPECT_TRUE(utils::PWriteAll(fd, "\0", 1, 10 * 1024 * 1024 - 1));
209 }
210 EXPECT_EQ(10 * 1024 * 1024, utils::FileSize(img));
Darin Petkovd3f8c892010-10-12 21:38:45 -0700211 int block_count = 0;
212 int block_size = 0;
213 EXPECT_TRUE(utils::GetFilesystemSize(img, &block_count, &block_size));
214 EXPECT_EQ(4096, block_size);
Sen Jiang990c27b2016-03-15 17:09:21 -0700215 EXPECT_EQ(4 * 1024 * 1024 / 4096, block_count);
Darin Petkovd3f8c892010-10-12 21:38:45 -0700216}
217
Alex Deymo192393b2014-11-10 15:58:38 -0800218// Squashfs example filesystem, generated with:
219// echo hola>hola
220// mksquashfs hola hola.sqfs -noappend -nopad
221// hexdump hola.sqfs -e '16/1 "%02x, " "\n"'
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800222const uint8_t kSquashfsFile[] = {
Alex Deymo192393b2014-11-10 15:58:38 -0800223 0x68, 0x73, 0x71, 0x73, 0x02, 0x00, 0x00, 0x00, // magic, inodes
224 0x3e, 0x49, 0x61, 0x54, 0x00, 0x00, 0x02, 0x00,
225 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x11, 0x00,
226 0xc0, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, // flags, noids, major, minor
227 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // root_inode
228 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // bytes_used
229 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
230 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
231 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
232 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
233 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
234 0xd5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
235 0x68, 0x6f, 0x6c, 0x61, 0x0a, 0x2c, 0x00, 0x78,
236 0xda, 0x63, 0x62, 0x58, 0xc2, 0xc8, 0xc0, 0xc0,
237 0xc8, 0xd0, 0x6b, 0x91, 0x18, 0x02, 0x64, 0xa0,
238 0x00, 0x56, 0x06, 0x90, 0xcc, 0x7f, 0xb0, 0xbc,
239 0x9d, 0x67, 0x62, 0x08, 0x13, 0x54, 0x1c, 0x44,
240 0x4b, 0x03, 0x31, 0x33, 0x10, 0x03, 0x00, 0xb5,
241 0x87, 0x04, 0x89, 0x16, 0x00, 0x78, 0xda, 0x63,
242 0x60, 0x80, 0x00, 0x46, 0x28, 0xcd, 0xc4, 0xc0,
243 0xcc, 0x90, 0x91, 0x9f, 0x93, 0x08, 0x00, 0x04,
244 0x70, 0x01, 0xab, 0x10, 0x80, 0x60, 0x00, 0x00,
245 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
246 0x01, 0x00, 0x00, 0x00, 0x00, 0xab, 0x00, 0x00,
247 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x78,
248 0xda, 0x63, 0x60, 0x80, 0x00, 0x05, 0x28, 0x0d,
249 0x00, 0x01, 0x10, 0x00, 0x21, 0xc5, 0x00, 0x00,
250 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0x99,
251 0xcd, 0x02, 0x00, 0x88, 0x13, 0x00, 0x00, 0xdd,
252 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
253};
254
255TEST(UtilsTest, GetSquashfs4Size) {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800256 uint8_t buffer[sizeof(kSquashfsFile)];
Alex Deymo192393b2014-11-10 15:58:38 -0800257 memcpy(buffer, kSquashfsFile, sizeof(kSquashfsFile));
258
259 int block_count = -1;
260 int block_size = -1;
261 // Not enough bytes passed.
262 EXPECT_FALSE(utils::GetSquashfs4Size(buffer, 10, nullptr, nullptr));
263
264 // The whole file system is passed, which is enough for parsing.
265 EXPECT_TRUE(utils::GetSquashfs4Size(buffer, sizeof(kSquashfsFile),
266 &block_count, &block_size));
267 EXPECT_EQ(4096, block_size);
268 EXPECT_EQ(1, block_count);
269
270 // Modify the major version to 5.
271 uint16_t* s_major = reinterpret_cast<uint16_t*>(buffer + 0x1c);
272 *s_major = 5;
273 EXPECT_FALSE(utils::GetSquashfs4Size(buffer, 10, nullptr, nullptr));
274 memcpy(buffer, kSquashfsFile, sizeof(kSquashfsFile));
275
276 // Modify the bytes_used to have 6 blocks.
277 int64_t* bytes_used = reinterpret_cast<int64_t*>(buffer + 0x28);
278 *bytes_used = 4096 * 5 + 1; // 6 "blocks".
279 EXPECT_TRUE(utils::GetSquashfs4Size(buffer, sizeof(kSquashfsFile),
280 &block_count, &block_size));
281 EXPECT_EQ(4096, block_size);
282 EXPECT_EQ(6, block_count);
283}
284
Andrew de los Reyes712b3ac2011-01-07 13:47:52 -0800285namespace {
Alex Deymo032e7722014-03-25 17:53:56 -0700286void GetFileFormatTester(const string& expected,
Ben Chan9abb7632014-08-07 00:10:53 -0700287 const vector<uint8_t>& contents) {
Alex Deymo10875d92014-11-10 21:52:57 -0800288 test_utils::ScopedTempFile file;
Alex Deymobffa0602016-02-12 17:16:29 -0800289 ASSERT_TRUE(utils::WriteFile(file.path().c_str(),
Alex Deymo032e7722014-03-25 17:53:56 -0700290 reinterpret_cast<const char*>(contents.data()),
291 contents.size()));
Alex Deymobffa0602016-02-12 17:16:29 -0800292 EXPECT_EQ(expected, utils::GetFileFormat(file.path()));
Alex Deymo032e7722014-03-25 17:53:56 -0700293}
Alex Deymo10875d92014-11-10 21:52:57 -0800294} // namespace
Alex Deymo032e7722014-03-25 17:53:56 -0700295
296TEST(UtilsTest, GetFileFormatTest) {
297 EXPECT_EQ("File not found.", utils::GetFileFormat("/path/to/nowhere"));
Ben Chan9abb7632014-08-07 00:10:53 -0700298 GetFileFormatTester("data", vector<uint8_t>{1, 2, 3, 4, 5, 6, 7, 8});
299 GetFileFormatTester("ELF", vector<uint8_t>{0x7f, 0x45, 0x4c, 0x46});
Alex Deymo032e7722014-03-25 17:53:56 -0700300
301 // Real tests from cros_installer on different boards.
302 // ELF 32-bit LSB executable, Intel 80386
303 GetFileFormatTester(
304 "ELF 32-bit little-endian x86",
Ben Chan9abb7632014-08-07 00:10:53 -0700305 vector<uint8_t>{0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00,
306 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
307 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00,
308 0x90, 0x83, 0x04, 0x08, 0x34, 0x00, 0x00, 0x00});
Alex Deymo032e7722014-03-25 17:53:56 -0700309
Alex Deymoc1711e22014-08-08 13:16:23 -0700310 // ELF 32-bit LSB executable, MIPS
311 GetFileFormatTester(
312 "ELF 32-bit little-endian mips",
313 vector<uint8_t>{0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00,
314 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
315 0x03, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00,
316 0xc0, 0x12, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00});
317
Alex Deymo032e7722014-03-25 17:53:56 -0700318 // ELF 32-bit LSB executable, ARM
319 GetFileFormatTester(
320 "ELF 32-bit little-endian arm",
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, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00,
324 0x85, 0x8b, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00});
Alex Deymo032e7722014-03-25 17:53:56 -0700325
326 // ELF 64-bit LSB executable, x86-64
327 GetFileFormatTester(
328 "ELF 64-bit little-endian x86-64",
Ben Chan9abb7632014-08-07 00:10:53 -0700329 vector<uint8_t>{0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00,
330 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
331 0x02, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00,
332 0xb0, 0x04, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00});
Alex Deymo032e7722014-03-25 17:53:56 -0700333}
334
Andrew de los Reyes712b3ac2011-01-07 13:47:52 -0800335TEST(UtilsTest, ScheduleCrashReporterUploadTest) {
336 // Not much to test. At least this tests for memory leaks, crashes,
337 // log errors.
Alex Deymo60ca1a72015-06-18 18:19:15 -0700338 FakeMessageLoop loop(nullptr);
339 loop.SetAsCurrent();
Andrew de los Reyes712b3ac2011-01-07 13:47:52 -0800340 utils::ScheduleCrashReporterUpload();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700341 // Test that we scheduled one callback from the crash reporter.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700342 EXPECT_EQ(1, brillo::MessageLoopRunMaxIterations(&loop, 100));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700343 EXPECT_FALSE(loop.PendingTasks());
Andrew de los Reyes712b3ac2011-01-07 13:47:52 -0800344}
345
David Zeuthen674c3182013-04-18 14:05:20 -0700346TEST(UtilsTest, FormatTimeDeltaTest) {
347 // utils::FormatTimeDelta() is not locale-aware (it's only used for logging
348 // which is not localized) so we only need to test the C locale
349 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromMilliseconds(100)),
350 "0.1s");
351 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(0)),
352 "0s");
353 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(1)),
354 "1s");
355 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(59)),
356 "59s");
357 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(60)),
358 "1m0s");
359 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(61)),
360 "1m1s");
361 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(90)),
362 "1m30s");
363 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(1205)),
364 "20m5s");
365 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(3600)),
366 "1h0m0s");
367 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(3601)),
368 "1h0m1s");
369 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(3661)),
370 "1h1m1s");
371 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(7261)),
372 "2h1m1s");
373 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(86400)),
374 "1d0h0m0s");
375 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(86401)),
376 "1d0h0m1s");
377 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(200000)),
378 "2d7h33m20s");
379 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(200000) +
380 base::TimeDelta::FromMilliseconds(1)),
381 "2d7h33m20.001s");
David Zeuthen973449e2014-08-18 16:18:23 -0400382 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(-1)),
383 "-1s");
David Zeuthen674c3182013-04-18 14:05:20 -0700384}
385
David Zeuthen27a48bc2013-08-06 12:06:29 -0700386TEST(UtilsTest, TimeFromStructTimespecTest) {
387 struct timespec ts;
388
389 // Unix epoch (Thursday 00:00:00 UTC on Jan 1, 1970)
390 ts = (struct timespec) {.tv_sec = 0, .tv_nsec = 0};
391 EXPECT_EQ(base::Time::UnixEpoch(), utils::TimeFromStructTimespec(&ts));
392
393 // 42 ms after the Unix billennium (Sunday 01:46:40 UTC on September 9, 2001)
394 ts = (struct timespec) {.tv_sec = 1000 * 1000 * 1000,
395 .tv_nsec = 42 * 1000 * 1000};
396 base::Time::Exploded exploded = (base::Time::Exploded) {
397 .year = 2001, .month = 9, .day_of_week = 0, .day_of_month = 9,
398 .hour = 1, .minute = 46, .second = 40, .millisecond = 42};
399 EXPECT_EQ(base::Time::FromUTCExploded(exploded),
400 utils::TimeFromStructTimespec(&ts));
401}
402
David Zeuthene7f89172013-10-31 10:21:04 -0700403TEST(UtilsTest, DecodeAndStoreBase64String) {
404 base::FilePath path;
405
406 // Ensure we return false on empty strings or invalid base64.
407 EXPECT_FALSE(utils::DecodeAndStoreBase64String("", &path));
408 EXPECT_FALSE(utils::DecodeAndStoreBase64String("not valid base64", &path));
409
410 // Pass known base64 and check that it matches. This string was generated
411 // the following way:
412 //
413 // $ echo "Update Engine" | base64
414 // VXBkYXRlIEVuZ2luZQo=
415 EXPECT_TRUE(utils::DecodeAndStoreBase64String("VXBkYXRlIEVuZ2luZQo=",
416 &path));
417 ScopedPathUnlinker unlinker(path.value());
418 string expected_contents = "Update Engine\n";
419 string contents;
420 EXPECT_TRUE(utils::ReadFile(path.value(), &contents));
421 EXPECT_EQ(contents, expected_contents);
Alex Deymo5fe0c4e2016-02-16 18:46:24 -0800422 EXPECT_EQ(static_cast<off_t>(expected_contents.size()),
423 utils::FileSize(path.value()));
David Zeuthene7f89172013-10-31 10:21:04 -0700424}
425
David Zeuthen639aa362014-02-03 16:23:44 -0800426TEST(UtilsTest, ConvertToOmahaInstallDate) {
427 // The Omaha Epoch starts at Jan 1, 2007 0:00 PST which is a
428 // Monday. In Unix time, this point in time is easily obtained via
429 // the date(1) command like this:
430 //
431 // $ date +"%s" --date="Jan 1, 2007 0:00 PST"
432 const time_t omaha_epoch = 1167638400;
433 int value;
434
435 // Points in time *on and after* the Omaha epoch should not fail.
436 EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
437 base::Time::FromTimeT(omaha_epoch), &value));
438 EXPECT_GE(value, 0);
439
440 // Anything before the Omaha epoch should fail. We test it for two points.
441 EXPECT_FALSE(utils::ConvertToOmahaInstallDate(
442 base::Time::FromTimeT(omaha_epoch - 1), &value));
443 EXPECT_FALSE(utils::ConvertToOmahaInstallDate(
444 base::Time::FromTimeT(omaha_epoch - 100*24*3600), &value));
445
446 // Check that we jump from 0 to 7 exactly on the one-week mark, e.g.
447 // on Jan 8, 2007 0:00 PST.
448 EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
449 base::Time::FromTimeT(omaha_epoch + 7*24*3600 - 1), &value));
450 EXPECT_EQ(value, 0);
451 EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
452 base::Time::FromTimeT(omaha_epoch + 7*24*3600), &value));
453 EXPECT_EQ(value, 7);
454
455 // Check a couple of more values.
456 EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
457 base::Time::FromTimeT(omaha_epoch + 10*24*3600), &value));
458 EXPECT_EQ(value, 7);
459 EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
460 base::Time::FromTimeT(omaha_epoch + 20*24*3600), &value));
461 EXPECT_EQ(value, 14);
462 EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
463 base::Time::FromTimeT(omaha_epoch + 26*24*3600), &value));
464 EXPECT_EQ(value, 21);
465 EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
466 base::Time::FromTimeT(omaha_epoch + 29*24*3600), &value));
467 EXPECT_EQ(value, 28);
468
469 // The date Jun 4, 2007 0:00 PDT is a Monday and is hence a point
470 // where the Omaha InstallDate jumps 7 days. Its unix time is
471 // 1180940400. Notably, this is a point in time where Daylight
472 // Savings Time (DST) was is in effect (e.g. it's PDT, not PST).
473 //
474 // Note that as utils::ConvertToOmahaInstallDate() _deliberately_
475 // ignores DST (as it's hard to implement in a thread-safe way using
476 // glibc, see comments in utils.h) we have to fudge by the DST
477 // offset which is one hour. Conveniently, if the function were
478 // someday modified to be DST aware, this test would have to be
479 // modified as well.
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700480 const time_t dst_time = 1180940400; // Jun 4, 2007 0:00 PDT.
David Zeuthen639aa362014-02-03 16:23:44 -0800481 const time_t fudge = 3600;
482 int value1, value2;
483 EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
484 base::Time::FromTimeT(dst_time + fudge - 1), &value1));
485 EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
486 base::Time::FromTimeT(dst_time + fudge), &value2));
487 EXPECT_EQ(value1, value2 - 7);
488}
489
Allie Wood78750a42015-02-11 15:42:11 -0800490TEST(UtilsTest, GetMinorVersion) {
491 // Test GetMinorVersion by verifying that it parses the conf file and returns
492 // the correct value.
Allie Wood78750a42015-02-11 15:42:11 -0800493 uint32_t minor_version;
494
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700495 brillo::KeyValueStore store;
Alex Deymob42b98d2015-07-06 17:42:38 -0700496 EXPECT_FALSE(utils::GetMinorVersion(store, &minor_version));
Allie Wood78750a42015-02-11 15:42:11 -0800497
Alex Deymob42b98d2015-07-06 17:42:38 -0700498 EXPECT_TRUE(store.LoadFromString("PAYLOAD_MINOR_VERSION=one-two-three\n"));
499 EXPECT_FALSE(utils::GetMinorVersion(store, &minor_version));
Allie Wood78750a42015-02-11 15:42:11 -0800500
Alex Deymob42b98d2015-07-06 17:42:38 -0700501 EXPECT_TRUE(store.LoadFromString("PAYLOAD_MINOR_VERSION=123\n"));
502 EXPECT_TRUE(utils::GetMinorVersion(store, &minor_version));
Alex Deymo80f70ff2016-02-10 16:08:11 -0800503 EXPECT_EQ(123U, minor_version);
Allie Wood78750a42015-02-11 15:42:11 -0800504}
505
Nam T. Nguyen2b67a592014-12-03 14:56:00 -0800506static bool BoolMacroTestHelper() {
507 int i = 1;
508 unsigned int ui = 1;
509 bool b = 1;
510 std::unique_ptr<char> cptr(new char);
511
512 TEST_AND_RETURN_FALSE(i);
513 TEST_AND_RETURN_FALSE(ui);
514 TEST_AND_RETURN_FALSE(b);
515 TEST_AND_RETURN_FALSE(cptr);
516
517 TEST_AND_RETURN_FALSE_ERRNO(i);
518 TEST_AND_RETURN_FALSE_ERRNO(ui);
519 TEST_AND_RETURN_FALSE_ERRNO(b);
520 TEST_AND_RETURN_FALSE_ERRNO(cptr);
521
522 return true;
523}
524
525static void VoidMacroTestHelper(bool* ret) {
526 int i = 1;
527 unsigned int ui = 1;
528 bool b = 1;
529 std::unique_ptr<char> cptr(new char);
530
531 *ret = false;
532
533 TEST_AND_RETURN(i);
534 TEST_AND_RETURN(ui);
535 TEST_AND_RETURN(b);
536 TEST_AND_RETURN(cptr);
537
538 TEST_AND_RETURN_ERRNO(i);
539 TEST_AND_RETURN_ERRNO(ui);
540 TEST_AND_RETURN_ERRNO(b);
541 TEST_AND_RETURN_ERRNO(cptr);
542
543 *ret = true;
544}
545
546TEST(UtilsTest, TestMacros) {
547 bool void_test = false;
548 VoidMacroTestHelper(&void_test);
549 EXPECT_TRUE(void_test);
550
551 EXPECT_TRUE(BoolMacroTestHelper());
552}
553
adlr@google.com3defe6a2009-12-04 20:57:17 +0000554} // namespace chromeos_update_engine