blob: b0beff985f8962c5089b417f2c6054fadb498dcf [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>
Alex Deymoc603c572016-08-22 19:51:59 -070020#include <fcntl.h>
Ben Chan9abb7632014-08-07 00:10:53 -070021#include <stdint.h>
Alex Deymoc603c572016-08-22 19:51:59 -070022#include <sys/mount.h>
adlr@google.com3defe6a2009-12-04 20:57:17 +000023#include <sys/stat.h>
24#include <sys/types.h>
Darin Petkov5c0a8af2010-08-24 13:39:13 -070025
Andrew de los Reyescc92cd32010-10-05 16:56:14 -070026#include <map>
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -080027#include <string>
adlr@google.com3defe6a2009-12-04 20:57:17 +000028#include <vector>
Darin Petkov5c0a8af2010-08-24 13:39:13 -070029
Alex Deymoc1711e22014-08-08 13:16:23 -070030#include <base/files/file_path.h>
Alex Deymo2c0db7b2014-11-04 12:23:39 -080031#include <base/files/file_util.h>
Allie Wood78750a42015-02-11 15:42:11 -080032#include <base/files/scoped_temp_dir.h>
Alex Vakulenko75039d72014-03-25 12:36:28 -070033#include <base/strings/string_util.h>
34#include <base/strings/stringprintf.h>
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070035#include <brillo/message_loops/fake_message_loop.h>
36#include <brillo/message_loops/message_loop_utils.h>
Darin Petkovd3f8c892010-10-12 21:38:45 -070037#include <gtest/gtest.h>
38
Alex Deymo39910dc2015-11-09 17:04:30 -080039#include "update_engine/common/test_utils.h"
adlr@google.com3defe6a2009-12-04 20:57:17 +000040
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070041using brillo::FakeMessageLoop;
Andrew de los Reyescc92cd32010-10-05 16:56:14 -070042using std::map;
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -080043using std::string;
adlr@google.com3defe6a2009-12-04 20:57:17 +000044using std::vector;
45
46namespace chromeos_update_engine {
47
48class UtilsTest : public ::testing::Test { };
49
Chris Sosac1972482013-04-30 22:31:10 -070050TEST(UtilsTest, CanParseECVersion) {
Chris Sosac1972482013-04-30 22:31:10 -070051 // Should be able to parse and valid key value line.
J. Richard Barnette63137e52013-10-28 10:57:29 -070052 EXPECT_EQ("12345", utils::ParseECVersion("fw_version=12345"));
53 EXPECT_EQ("123456", utils::ParseECVersion(
54 "b=1231a fw_version=123456 a=fasd2"));
55 EXPECT_EQ("12345", utils::ParseECVersion("fw_version=12345"));
56 EXPECT_EQ("00VFA616", utils::ParseECVersion(
Chris Sosac1972482013-04-30 22:31:10 -070057 "vendor=\"sam\" fw_version=\"00VFA616\""));
58
59 // For invalid entries, should return the empty string.
J. Richard Barnette63137e52013-10-28 10:57:29 -070060 EXPECT_EQ("", utils::ParseECVersion("b=1231a fw_version a=fasd2"));
Chris Sosac1972482013-04-30 22:31:10 -070061}
62
adlr@google.com3defe6a2009-12-04 20:57:17 +000063TEST(UtilsTest, ReadFileFailure) {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070064 brillo::Blob empty;
adlr@google.com3defe6a2009-12-04 20:57:17 +000065 EXPECT_FALSE(utils::ReadFile("/this/doesn't/exist", &empty));
66}
67
Darin Petkov8e447e02013-04-16 16:23:50 +020068TEST(UtilsTest, ReadFileChunk) {
Alex Vakulenko75039d72014-03-25 12:36:28 -070069 base::FilePath file;
70 EXPECT_TRUE(base::CreateTemporaryFile(&file));
Darin Petkov8e447e02013-04-16 16:23:50 +020071 ScopedPathUnlinker unlinker(file.value());
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070072 brillo::Blob data;
Darin Petkov8e447e02013-04-16 16:23:50 +020073 const size_t kSize = 1024 * 1024;
74 for (size_t i = 0; i < kSize; i++) {
75 data.push_back(i % 255);
76 }
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080077 EXPECT_TRUE(utils::WriteFile(file.value().c_str(), data.data(), data.size()));
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070078 brillo::Blob in_data;
Darin Petkov8e447e02013-04-16 16:23:50 +020079 EXPECT_TRUE(utils::ReadFileChunk(file.value().c_str(), kSize, 10, &in_data));
80 EXPECT_TRUE(in_data.empty());
81 EXPECT_TRUE(utils::ReadFileChunk(file.value().c_str(), 0, -1, &in_data));
82 EXPECT_TRUE(data == in_data);
83 in_data.clear();
84 EXPECT_TRUE(utils::ReadFileChunk(file.value().c_str(), 10, 20, &in_data));
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070085 EXPECT_TRUE(brillo::Blob(data.begin() + 10, data.begin() + 10 + 20) ==
Darin Petkov8e447e02013-04-16 16:23:50 +020086 in_data);
87}
88
adlr@google.com3defe6a2009-12-04 20:57:17 +000089TEST(UtilsTest, ErrnoNumberAsStringTest) {
90 EXPECT_EQ("No such file or directory", utils::ErrnoNumberAsString(ENOENT));
91}
92
Darin Petkov002b2fe2010-11-22 13:53:22 -080093TEST(UtilsTest, IsSymlinkTest) {
94 string temp_dir;
Gilad Arnolda6742b32014-01-11 00:18:34 -080095 EXPECT_TRUE(utils::MakeTempDirectory("symlink-test.XXXXXX", &temp_dir));
Alex Deymo8d925292014-05-21 19:15:25 -070096 string temp_file = temp_dir + "/temp-file";
Darin Petkov002b2fe2010-11-22 13:53:22 -080097 EXPECT_TRUE(utils::WriteFile(temp_file.c_str(), "", 0));
Alex Deymo8d925292014-05-21 19:15:25 -070098 string temp_symlink = temp_dir + "/temp-symlink";
Darin Petkov002b2fe2010-11-22 13:53:22 -080099 EXPECT_EQ(0, symlink(temp_file.c_str(), temp_symlink.c_str()));
100 EXPECT_FALSE(utils::IsSymlink(temp_dir.c_str()));
101 EXPECT_FALSE(utils::IsSymlink(temp_file.c_str()));
102 EXPECT_TRUE(utils::IsSymlink(temp_symlink.c_str()));
103 EXPECT_FALSE(utils::IsSymlink("/non/existent/path"));
Alex Deymo110e0302015-10-19 20:35:21 -0700104 EXPECT_TRUE(base::DeleteFile(base::FilePath(temp_dir), true));
Darin Petkov002b2fe2010-11-22 13:53:22 -0800105}
106
Alex Deymo763e7db2015-08-27 21:08:08 -0700107TEST(UtilsTest, SplitPartitionNameTest) {
108 string disk;
109 int part_num;
Darin Petkovf74eb652010-08-04 12:08:38 -0700110
Alex Deymo763e7db2015-08-27 21:08:08 -0700111 EXPECT_TRUE(utils::SplitPartitionName("/dev/sda3", &disk, &part_num));
112 EXPECT_EQ("/dev/sda", disk);
113 EXPECT_EQ(3, part_num);
Darin Petkovf74eb652010-08-04 12:08:38 -0700114
Alex Deymo763e7db2015-08-27 21:08:08 -0700115 EXPECT_TRUE(utils::SplitPartitionName("/dev/sdp1234", &disk, &part_num));
116 EXPECT_EQ("/dev/sdp", disk);
117 EXPECT_EQ(1234, part_num);
Andrew de los Reyesf9714432010-05-04 10:21:23 -0700118
Alex Deymo763e7db2015-08-27 21:08:08 -0700119 EXPECT_TRUE(utils::SplitPartitionName("/dev/mmcblk0p3", &disk, &part_num));
120 EXPECT_EQ("/dev/mmcblk0", disk);
121 EXPECT_EQ(3, part_num);
122
123 EXPECT_TRUE(utils::SplitPartitionName("/dev/ubiblock3_2", &disk, &part_num));
124 EXPECT_EQ("/dev/ubiblock", disk);
125 EXPECT_EQ(3, part_num);
126
127 EXPECT_TRUE(utils::SplitPartitionName("/dev/loop10", &disk, &part_num));
128 EXPECT_EQ("/dev/loop", disk);
129 EXPECT_EQ(10, part_num);
130
131 EXPECT_TRUE(utils::SplitPartitionName("/dev/loop28p11", &disk, &part_num));
132 EXPECT_EQ("/dev/loop28", disk);
133 EXPECT_EQ(11, part_num);
134
135 EXPECT_TRUE(utils::SplitPartitionName("/dev/loop10_0", &disk, &part_num));
136 EXPECT_EQ("/dev/loop", disk);
137 EXPECT_EQ(10, part_num);
138
139 EXPECT_TRUE(utils::SplitPartitionName("/dev/loop28p11_0", &disk, &part_num));
140 EXPECT_EQ("/dev/loop28", disk);
141 EXPECT_EQ(11, part_num);
142
143 EXPECT_FALSE(utils::SplitPartitionName("/dev/mmcblk0p", &disk, &part_num));
144 EXPECT_FALSE(utils::SplitPartitionName("/dev/sda", &disk, &part_num));
145 EXPECT_FALSE(utils::SplitPartitionName("/dev/foo/bar", &disk, &part_num));
146 EXPECT_FALSE(utils::SplitPartitionName("/", &disk, &part_num));
147 EXPECT_FALSE(utils::SplitPartitionName("", &disk, &part_num));
Andrew de los Reyesf9714432010-05-04 10:21:23 -0700148}
149
Alex Vakulenkof3f85bb2014-03-26 16:36:35 -0700150TEST(UtilsTest, MakePartitionNameTest) {
151 EXPECT_EQ("/dev/sda4", utils::MakePartitionName("/dev/sda", 4));
152 EXPECT_EQ("/dev/sda123", utils::MakePartitionName("/dev/sda", 123));
153 EXPECT_EQ("/dev/mmcblk2", utils::MakePartitionName("/dev/mmcblk", 2));
154 EXPECT_EQ("/dev/mmcblk0p2", utils::MakePartitionName("/dev/mmcblk0", 2));
155 EXPECT_EQ("/dev/loop8", utils::MakePartitionName("/dev/loop", 8));
156 EXPECT_EQ("/dev/loop12p2", utils::MakePartitionName("/dev/loop12", 2));
Nam T. Nguyena78b28c2015-03-06 22:30:12 -0800157 EXPECT_EQ("/dev/ubi5_0", utils::MakePartitionName("/dev/ubiblock", 5));
158 EXPECT_EQ("/dev/mtd4", utils::MakePartitionName("/dev/ubiblock", 4));
159 EXPECT_EQ("/dev/ubi3_0", utils::MakePartitionName("/dev/ubiblock", 3));
160 EXPECT_EQ("/dev/mtd2", utils::MakePartitionName("/dev/ubiblock", 2));
161 EXPECT_EQ("/dev/ubi1_0", utils::MakePartitionName("/dev/ubiblock", 1));
162}
163
164TEST(UtilsTest, MakePartitionNameForMountTest) {
165 EXPECT_EQ("/dev/sda4", utils::MakePartitionNameForMount("/dev/sda4"));
166 EXPECT_EQ("/dev/sda123", utils::MakePartitionNameForMount("/dev/sda123"));
167 EXPECT_EQ("/dev/mmcblk2", utils::MakePartitionNameForMount("/dev/mmcblk2"));
168 EXPECT_EQ("/dev/mmcblk0p2",
169 utils::MakePartitionNameForMount("/dev/mmcblk0p2"));
170 EXPECT_EQ("/dev/loop0", utils::MakePartitionNameForMount("/dev/loop0"));
171 EXPECT_EQ("/dev/loop8", utils::MakePartitionNameForMount("/dev/loop8"));
172 EXPECT_EQ("/dev/loop12p2",
173 utils::MakePartitionNameForMount("/dev/loop12p2"));
174 EXPECT_EQ("/dev/ubiblock5_0",
175 utils::MakePartitionNameForMount("/dev/ubiblock5_0"));
176 EXPECT_EQ("/dev/mtd4",
177 utils::MakePartitionNameForMount("/dev/ubi4_0"));
178 EXPECT_EQ("/dev/ubiblock3_0",
179 utils::MakePartitionNameForMount("/dev/ubiblock3"));
180 EXPECT_EQ("/dev/mtd2", utils::MakePartitionNameForMount("/dev/ubi2"));
181 EXPECT_EQ("/dev/ubi1_0",
182 utils::MakePartitionNameForMount("/dev/ubiblock1"));
Alex Vakulenkof3f85bb2014-03-26 16:36:35 -0700183}
184
Darin Petkov5c0a8af2010-08-24 13:39:13 -0700185TEST(UtilsTest, FuzzIntTest) {
Alex Deymo80f70ff2016-02-10 16:08:11 -0800186 static const uint32_t kRanges[] = { 0, 1, 2, 20 };
187 for (uint32_t range : kRanges) {
Darin Petkov5c0a8af2010-08-24 13:39:13 -0700188 const int kValue = 50;
189 for (int tries = 0; tries < 100; ++tries) {
Alex Deymo80f70ff2016-02-10 16:08:11 -0800190 uint32_t value = utils::FuzzInt(kValue, range);
Darin Petkov5c0a8af2010-08-24 13:39:13 -0700191 EXPECT_GE(value, kValue - range / 2);
192 EXPECT_LE(value, kValue + range - range / 2);
193 }
194 }
195}
196
Darin Petkovd3f8c892010-10-12 21:38:45 -0700197TEST(UtilsTest, RunAsRootGetFilesystemSizeTest) {
198 string img;
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700199 EXPECT_TRUE(utils::MakeTempFile("img.XXXXXX", &img, nullptr));
Darin Petkovd3f8c892010-10-12 21:38:45 -0700200 ScopedPathUnlinker img_unlinker(img);
Alex Deymo10875d92014-11-10 21:52:57 -0800201 test_utils::CreateExtImageAtPath(img, nullptr);
Darin Petkovd3f8c892010-10-12 21:38:45 -0700202 // Extend the "partition" holding the file system from 10MiB to 20MiB.
Alex Deymo10875d92014-11-10 21:52:57 -0800203 EXPECT_EQ(0, test_utils::System(base::StringPrintf(
Alex Deymo1f93d032015-03-10 18:58:32 -0700204 "dd if=/dev/zero of=%s seek=20971519 bs=1 count=1 status=none",
Darin Petkovd3f8c892010-10-12 21:38:45 -0700205 img.c_str())));
206 EXPECT_EQ(20 * 1024 * 1024, utils::FileSize(img));
207 int block_count = 0;
208 int block_size = 0;
209 EXPECT_TRUE(utils::GetFilesystemSize(img, &block_count, &block_size));
210 EXPECT_EQ(4096, block_size);
211 EXPECT_EQ(10 * 1024 * 1024 / 4096, block_count);
212}
213
Alex Deymo192393b2014-11-10 15:58:38 -0800214// Squashfs example filesystem, generated with:
215// echo hola>hola
216// mksquashfs hola hola.sqfs -noappend -nopad
217// hexdump hola.sqfs -e '16/1 "%02x, " "\n"'
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800218const uint8_t kSquashfsFile[] = {
Alex Deymo192393b2014-11-10 15:58:38 -0800219 0x68, 0x73, 0x71, 0x73, 0x02, 0x00, 0x00, 0x00, // magic, inodes
220 0x3e, 0x49, 0x61, 0x54, 0x00, 0x00, 0x02, 0x00,
221 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x11, 0x00,
222 0xc0, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, // flags, noids, major, minor
223 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // root_inode
224 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // bytes_used
225 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
226 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
227 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
228 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
229 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
230 0xd5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
231 0x68, 0x6f, 0x6c, 0x61, 0x0a, 0x2c, 0x00, 0x78,
232 0xda, 0x63, 0x62, 0x58, 0xc2, 0xc8, 0xc0, 0xc0,
233 0xc8, 0xd0, 0x6b, 0x91, 0x18, 0x02, 0x64, 0xa0,
234 0x00, 0x56, 0x06, 0x90, 0xcc, 0x7f, 0xb0, 0xbc,
235 0x9d, 0x67, 0x62, 0x08, 0x13, 0x54, 0x1c, 0x44,
236 0x4b, 0x03, 0x31, 0x33, 0x10, 0x03, 0x00, 0xb5,
237 0x87, 0x04, 0x89, 0x16, 0x00, 0x78, 0xda, 0x63,
238 0x60, 0x80, 0x00, 0x46, 0x28, 0xcd, 0xc4, 0xc0,
239 0xcc, 0x90, 0x91, 0x9f, 0x93, 0x08, 0x00, 0x04,
240 0x70, 0x01, 0xab, 0x10, 0x80, 0x60, 0x00, 0x00,
241 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
242 0x01, 0x00, 0x00, 0x00, 0x00, 0xab, 0x00, 0x00,
243 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x78,
244 0xda, 0x63, 0x60, 0x80, 0x00, 0x05, 0x28, 0x0d,
245 0x00, 0x01, 0x10, 0x00, 0x21, 0xc5, 0x00, 0x00,
246 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0x99,
247 0xcd, 0x02, 0x00, 0x88, 0x13, 0x00, 0x00, 0xdd,
248 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
249};
250
251TEST(UtilsTest, GetSquashfs4Size) {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800252 uint8_t buffer[sizeof(kSquashfsFile)];
Alex Deymo192393b2014-11-10 15:58:38 -0800253 memcpy(buffer, kSquashfsFile, sizeof(kSquashfsFile));
254
255 int block_count = -1;
256 int block_size = -1;
257 // Not enough bytes passed.
258 EXPECT_FALSE(utils::GetSquashfs4Size(buffer, 10, nullptr, nullptr));
259
260 // The whole file system is passed, which is enough for parsing.
261 EXPECT_TRUE(utils::GetSquashfs4Size(buffer, sizeof(kSquashfsFile),
262 &block_count, &block_size));
263 EXPECT_EQ(4096, block_size);
264 EXPECT_EQ(1, block_count);
265
266 // Modify the major version to 5.
267 uint16_t* s_major = reinterpret_cast<uint16_t*>(buffer + 0x1c);
268 *s_major = 5;
269 EXPECT_FALSE(utils::GetSquashfs4Size(buffer, 10, nullptr, nullptr));
270 memcpy(buffer, kSquashfsFile, sizeof(kSquashfsFile));
271
272 // Modify the bytes_used to have 6 blocks.
273 int64_t* bytes_used = reinterpret_cast<int64_t*>(buffer + 0x28);
274 *bytes_used = 4096 * 5 + 1; // 6 "blocks".
275 EXPECT_TRUE(utils::GetSquashfs4Size(buffer, sizeof(kSquashfsFile),
276 &block_count, &block_size));
277 EXPECT_EQ(4096, block_size);
278 EXPECT_EQ(6, block_count);
279}
280
Andrew de los Reyes712b3ac2011-01-07 13:47:52 -0800281namespace {
Alex Deymo032e7722014-03-25 17:53:56 -0700282void GetFileFormatTester(const string& expected,
Ben Chan9abb7632014-08-07 00:10:53 -0700283 const vector<uint8_t>& contents) {
Alex Deymo10875d92014-11-10 21:52:57 -0800284 test_utils::ScopedTempFile file;
Alex Deymobffa0602016-02-12 17:16:29 -0800285 ASSERT_TRUE(utils::WriteFile(file.path().c_str(),
Alex Deymo032e7722014-03-25 17:53:56 -0700286 reinterpret_cast<const char*>(contents.data()),
287 contents.size()));
Alex Deymobffa0602016-02-12 17:16:29 -0800288 EXPECT_EQ(expected, utils::GetFileFormat(file.path()));
Alex Deymo032e7722014-03-25 17:53:56 -0700289}
Alex Deymo10875d92014-11-10 21:52:57 -0800290} // namespace
Alex Deymo032e7722014-03-25 17:53:56 -0700291
292TEST(UtilsTest, GetFileFormatTest) {
293 EXPECT_EQ("File not found.", utils::GetFileFormat("/path/to/nowhere"));
Ben Chan9abb7632014-08-07 00:10:53 -0700294 GetFileFormatTester("data", vector<uint8_t>{1, 2, 3, 4, 5, 6, 7, 8});
295 GetFileFormatTester("ELF", vector<uint8_t>{0x7f, 0x45, 0x4c, 0x46});
Alex Deymo032e7722014-03-25 17:53:56 -0700296
297 // Real tests from cros_installer on different boards.
298 // ELF 32-bit LSB executable, Intel 80386
299 GetFileFormatTester(
300 "ELF 32-bit little-endian x86",
Ben Chan9abb7632014-08-07 00:10:53 -0700301 vector<uint8_t>{0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00,
302 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
303 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00,
304 0x90, 0x83, 0x04, 0x08, 0x34, 0x00, 0x00, 0x00});
Alex Deymo032e7722014-03-25 17:53:56 -0700305
Alex Deymoc1711e22014-08-08 13:16:23 -0700306 // ELF 32-bit LSB executable, MIPS
307 GetFileFormatTester(
308 "ELF 32-bit little-endian mips",
309 vector<uint8_t>{0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00,
310 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
311 0x03, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00,
312 0xc0, 0x12, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00});
313
Alex Deymo032e7722014-03-25 17:53:56 -0700314 // ELF 32-bit LSB executable, ARM
315 GetFileFormatTester(
316 "ELF 32-bit little-endian arm",
Ben Chan9abb7632014-08-07 00:10:53 -0700317 vector<uint8_t>{0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00,
318 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
319 0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00,
320 0x85, 0x8b, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00});
Alex Deymo032e7722014-03-25 17:53:56 -0700321
322 // ELF 64-bit LSB executable, x86-64
323 GetFileFormatTester(
324 "ELF 64-bit little-endian x86-64",
Ben Chan9abb7632014-08-07 00:10:53 -0700325 vector<uint8_t>{0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00,
326 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
327 0x02, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00,
328 0xb0, 0x04, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00});
Alex Deymo032e7722014-03-25 17:53:56 -0700329}
330
Andrew de los Reyes712b3ac2011-01-07 13:47:52 -0800331TEST(UtilsTest, ScheduleCrashReporterUploadTest) {
332 // Not much to test. At least this tests for memory leaks, crashes,
333 // log errors.
Alex Deymo60ca1a72015-06-18 18:19:15 -0700334 FakeMessageLoop loop(nullptr);
335 loop.SetAsCurrent();
Andrew de los Reyes712b3ac2011-01-07 13:47:52 -0800336 utils::ScheduleCrashReporterUpload();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700337 // Test that we scheduled one callback from the crash reporter.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700338 EXPECT_EQ(1, brillo::MessageLoopRunMaxIterations(&loop, 100));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700339 EXPECT_FALSE(loop.PendingTasks());
Andrew de los Reyes712b3ac2011-01-07 13:47:52 -0800340}
341
David Zeuthen674c3182013-04-18 14:05:20 -0700342TEST(UtilsTest, FormatTimeDeltaTest) {
343 // utils::FormatTimeDelta() is not locale-aware (it's only used for logging
344 // which is not localized) so we only need to test the C locale
345 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromMilliseconds(100)),
346 "0.1s");
347 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(0)),
348 "0s");
349 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(1)),
350 "1s");
351 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(59)),
352 "59s");
353 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(60)),
354 "1m0s");
355 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(61)),
356 "1m1s");
357 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(90)),
358 "1m30s");
359 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(1205)),
360 "20m5s");
361 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(3600)),
362 "1h0m0s");
363 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(3601)),
364 "1h0m1s");
365 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(3661)),
366 "1h1m1s");
367 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(7261)),
368 "2h1m1s");
369 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(86400)),
370 "1d0h0m0s");
371 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(86401)),
372 "1d0h0m1s");
373 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(200000)),
374 "2d7h33m20s");
375 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(200000) +
376 base::TimeDelta::FromMilliseconds(1)),
377 "2d7h33m20.001s");
David Zeuthen973449e2014-08-18 16:18:23 -0400378 EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(-1)),
379 "-1s");
David Zeuthen674c3182013-04-18 14:05:20 -0700380}
381
David Zeuthen27a48bc2013-08-06 12:06:29 -0700382TEST(UtilsTest, TimeFromStructTimespecTest) {
383 struct timespec ts;
384
385 // Unix epoch (Thursday 00:00:00 UTC on Jan 1, 1970)
386 ts = (struct timespec) {.tv_sec = 0, .tv_nsec = 0};
387 EXPECT_EQ(base::Time::UnixEpoch(), utils::TimeFromStructTimespec(&ts));
388
389 // 42 ms after the Unix billennium (Sunday 01:46:40 UTC on September 9, 2001)
390 ts = (struct timespec) {.tv_sec = 1000 * 1000 * 1000,
391 .tv_nsec = 42 * 1000 * 1000};
392 base::Time::Exploded exploded = (base::Time::Exploded) {
393 .year = 2001, .month = 9, .day_of_week = 0, .day_of_month = 9,
394 .hour = 1, .minute = 46, .second = 40, .millisecond = 42};
395 EXPECT_EQ(base::Time::FromUTCExploded(exploded),
396 utils::TimeFromStructTimespec(&ts));
397}
398
David Zeuthene7f89172013-10-31 10:21:04 -0700399TEST(UtilsTest, DecodeAndStoreBase64String) {
400 base::FilePath path;
401
402 // Ensure we return false on empty strings or invalid base64.
403 EXPECT_FALSE(utils::DecodeAndStoreBase64String("", &path));
404 EXPECT_FALSE(utils::DecodeAndStoreBase64String("not valid base64", &path));
405
406 // Pass known base64 and check that it matches. This string was generated
407 // the following way:
408 //
409 // $ echo "Update Engine" | base64
410 // VXBkYXRlIEVuZ2luZQo=
411 EXPECT_TRUE(utils::DecodeAndStoreBase64String("VXBkYXRlIEVuZ2luZQo=",
412 &path));
413 ScopedPathUnlinker unlinker(path.value());
414 string expected_contents = "Update Engine\n";
415 string contents;
416 EXPECT_TRUE(utils::ReadFile(path.value(), &contents));
417 EXPECT_EQ(contents, expected_contents);
Alex Deymo5fe0c4e2016-02-16 18:46:24 -0800418 EXPECT_EQ(static_cast<off_t>(expected_contents.size()),
419 utils::FileSize(path.value()));
David Zeuthene7f89172013-10-31 10:21:04 -0700420}
421
David Zeuthen639aa362014-02-03 16:23:44 -0800422TEST(UtilsTest, ConvertToOmahaInstallDate) {
423 // The Omaha Epoch starts at Jan 1, 2007 0:00 PST which is a
424 // Monday. In Unix time, this point in time is easily obtained via
425 // the date(1) command like this:
426 //
427 // $ date +"%s" --date="Jan 1, 2007 0:00 PST"
428 const time_t omaha_epoch = 1167638400;
429 int value;
430
431 // Points in time *on and after* the Omaha epoch should not fail.
432 EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
433 base::Time::FromTimeT(omaha_epoch), &value));
434 EXPECT_GE(value, 0);
435
436 // Anything before the Omaha epoch should fail. We test it for two points.
437 EXPECT_FALSE(utils::ConvertToOmahaInstallDate(
438 base::Time::FromTimeT(omaha_epoch - 1), &value));
439 EXPECT_FALSE(utils::ConvertToOmahaInstallDate(
440 base::Time::FromTimeT(omaha_epoch - 100*24*3600), &value));
441
442 // Check that we jump from 0 to 7 exactly on the one-week mark, e.g.
443 // on Jan 8, 2007 0:00 PST.
444 EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
445 base::Time::FromTimeT(omaha_epoch + 7*24*3600 - 1), &value));
446 EXPECT_EQ(value, 0);
447 EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
448 base::Time::FromTimeT(omaha_epoch + 7*24*3600), &value));
449 EXPECT_EQ(value, 7);
450
451 // Check a couple of more values.
452 EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
453 base::Time::FromTimeT(omaha_epoch + 10*24*3600), &value));
454 EXPECT_EQ(value, 7);
455 EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
456 base::Time::FromTimeT(omaha_epoch + 20*24*3600), &value));
457 EXPECT_EQ(value, 14);
458 EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
459 base::Time::FromTimeT(omaha_epoch + 26*24*3600), &value));
460 EXPECT_EQ(value, 21);
461 EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
462 base::Time::FromTimeT(omaha_epoch + 29*24*3600), &value));
463 EXPECT_EQ(value, 28);
464
465 // The date Jun 4, 2007 0:00 PDT is a Monday and is hence a point
466 // where the Omaha InstallDate jumps 7 days. Its unix time is
467 // 1180940400. Notably, this is a point in time where Daylight
468 // Savings Time (DST) was is in effect (e.g. it's PDT, not PST).
469 //
470 // Note that as utils::ConvertToOmahaInstallDate() _deliberately_
471 // ignores DST (as it's hard to implement in a thread-safe way using
472 // glibc, see comments in utils.h) we have to fudge by the DST
473 // offset which is one hour. Conveniently, if the function were
474 // someday modified to be DST aware, this test would have to be
475 // modified as well.
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700476 const time_t dst_time = 1180940400; // Jun 4, 2007 0:00 PDT.
David Zeuthen639aa362014-02-03 16:23:44 -0800477 const time_t fudge = 3600;
478 int value1, value2;
479 EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
480 base::Time::FromTimeT(dst_time + fudge - 1), &value1));
481 EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
482 base::Time::FromTimeT(dst_time + fudge), &value2));
483 EXPECT_EQ(value1, value2 - 7);
484}
485
Allie Wood78750a42015-02-11 15:42:11 -0800486TEST(UtilsTest, GetMinorVersion) {
487 // Test GetMinorVersion by verifying that it parses the conf file and returns
488 // the correct value.
Allie Wood78750a42015-02-11 15:42:11 -0800489 uint32_t minor_version;
490
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700491 brillo::KeyValueStore store;
Alex Deymob42b98d2015-07-06 17:42:38 -0700492 EXPECT_FALSE(utils::GetMinorVersion(store, &minor_version));
Allie Wood78750a42015-02-11 15:42:11 -0800493
Alex Deymob42b98d2015-07-06 17:42:38 -0700494 EXPECT_TRUE(store.LoadFromString("PAYLOAD_MINOR_VERSION=one-two-three\n"));
495 EXPECT_FALSE(utils::GetMinorVersion(store, &minor_version));
Allie Wood78750a42015-02-11 15:42:11 -0800496
Alex Deymob42b98d2015-07-06 17:42:38 -0700497 EXPECT_TRUE(store.LoadFromString("PAYLOAD_MINOR_VERSION=123\n"));
498 EXPECT_TRUE(utils::GetMinorVersion(store, &minor_version));
Alex Deymo80f70ff2016-02-10 16:08:11 -0800499 EXPECT_EQ(123U, minor_version);
Allie Wood78750a42015-02-11 15:42:11 -0800500}
501
Nam T. Nguyen2b67a592014-12-03 14:56:00 -0800502static bool BoolMacroTestHelper() {
503 int i = 1;
504 unsigned int ui = 1;
505 bool b = 1;
506 std::unique_ptr<char> cptr(new char);
507
508 TEST_AND_RETURN_FALSE(i);
509 TEST_AND_RETURN_FALSE(ui);
510 TEST_AND_RETURN_FALSE(b);
511 TEST_AND_RETURN_FALSE(cptr);
512
513 TEST_AND_RETURN_FALSE_ERRNO(i);
514 TEST_AND_RETURN_FALSE_ERRNO(ui);
515 TEST_AND_RETURN_FALSE_ERRNO(b);
516 TEST_AND_RETURN_FALSE_ERRNO(cptr);
517
518 return true;
519}
520
521static void VoidMacroTestHelper(bool* ret) {
522 int i = 1;
523 unsigned int ui = 1;
524 bool b = 1;
525 std::unique_ptr<char> cptr(new char);
526
527 *ret = false;
528
529 TEST_AND_RETURN(i);
530 TEST_AND_RETURN(ui);
531 TEST_AND_RETURN(b);
532 TEST_AND_RETURN(cptr);
533
534 TEST_AND_RETURN_ERRNO(i);
535 TEST_AND_RETURN_ERRNO(ui);
536 TEST_AND_RETURN_ERRNO(b);
537 TEST_AND_RETURN_ERRNO(cptr);
538
539 *ret = true;
540}
541
542TEST(UtilsTest, TestMacros) {
543 bool void_test = false;
544 VoidMacroTestHelper(&void_test);
545 EXPECT_TRUE(void_test);
546
547 EXPECT_TRUE(BoolMacroTestHelper());
548}
549
Alex Deymoc603c572016-08-22 19:51:59 -0700550TEST(UtilsTest, UnmountFilesystemFailureTest) {
551 EXPECT_FALSE(utils::UnmountFilesystem("/path/to/non-existing-dir"));
552}
553
554TEST(UtilsTest, UnmountFilesystemBusyFailureTest) {
555 string tmp_image;
556 EXPECT_TRUE(utils::MakeTempFile("img.XXXXXX", &tmp_image, nullptr));
557 ScopedPathUnlinker tmp_image_unlinker(tmp_image);
558
559 EXPECT_TRUE(base::CopyFile(
560 test_utils::GetBuildArtifactsPath().Append("gen/disk_ext2_4k.img"),
561 base::FilePath(tmp_image)));
562
563 base::ScopedTempDir mnt_dir;
564 EXPECT_TRUE(mnt_dir.CreateUniqueTempDir());
565
566 string loop_dev;
567 test_utils::ScopedLoopbackDeviceBinder loop_binder(
568 tmp_image, true, &loop_dev);
569
570 // This is the actual test part. While we hold a file descriptor open for the
571 // mounted filesystem, umount should still succeed.
572 EXPECT_TRUE(utils::MountFilesystem(
573 loop_dev, mnt_dir.path().value(), MS_RDONLY, "ext4", ""));
574 string target_file = mnt_dir.path().Append("empty-file").value();
575 int fd = HANDLE_EINTR(open(target_file.c_str(), O_RDONLY));
576 EXPECT_GE(fd, 0);
577 EXPECT_TRUE(utils::UnmountFilesystem(mnt_dir.path().value()));
578 IGNORE_EINTR(close(fd));
579 // The filesystem was already unmounted so this call should fail.
580 EXPECT_FALSE(utils::UnmountFilesystem(mnt_dir.path().value()));
581}
582
adlr@google.com3defe6a2009-12-04 20:57:17 +0000583} // namespace chromeos_update_engine