test_utils.cc revision 305345001d85ca2282112c2a30fe75c7a4773491
18155d081dc729d407f8ff9e95b4ef91ae14281ceMike Frysinger// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
249fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com// Use of this source code is governed by a BSD-style license that can be
349fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com// found in the LICENSE file.
449fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
5c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com#include "update_engine/test_utils.h"
609e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes
710875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo#include <attr/xattr.h>
86b9e38ef1180efe55e4a82bb18536d1b53fe493dAlex Deymo#include <dirent.h>
9c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com#include <errno.h>
1049fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com#include <stdio.h>
1149fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com#include <stdlib.h>
12161c4a132743f15fc4757112b673085c2a7a7f29Alex Deymo#include <sys/stat.h>
13161c4a132743f15fc4757112b673085c2a7a7f29Alex Deymo#include <sys/types.h>
1449fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com#include <unistd.h>
1509e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes
16c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com#include <set>
1749fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com#include <string>
1849fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com#include <vector>
1909e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes
202b19cfbcdb1aa8c5d1f338d19312fe14b6734bd5Alex Deymo#include <base/files/file_util.h>
21161c4a132743f15fc4757112b673085c2a7a7f29Alex Deymo#include <base/logging.h>
222b19cfbcdb1aa8c5d1f338d19312fe14b6734bd5Alex Deymo#include <base/strings/string_util.h>
23305345001d85ca2282112c2a30fe75c7a4773491Alex Deymo#include <base/strings/stringprintf.h>
24161c4a132743f15fc4757112b673085c2a7a7f29Alex Deymo
2549fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com#include "update_engine/file_writer.h"
26c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com#include "update_engine/utils.h"
2749fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
28161c4a132743f15fc4757112b673085c2a7a7f29Alex Deymousing base::StringPrintf;
29c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.comusing std::set;
3049fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.comusing std::string;
3149fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.comusing std::vector;
3249fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
3349fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.comnamespace chromeos_update_engine {
3449fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com
3552490e776a9d34a94fb18ab1fe7d416425e94ddaAlex Deymovoid PrintTo(const Extent& extent, ::std::ostream* os) {
3652490e776a9d34a94fb18ab1fe7d416425e94ddaAlex Deymo  *os << "(" << extent.start_block() << ", " << extent.num_blocks() << ")";
3752490e776a9d34a94fb18ab1fe7d416425e94ddaAlex Deymo}
3852490e776a9d34a94fb18ab1fe7d416425e94ddaAlex Deymo
3910875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymonamespace test_utils {
4010875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo
41a6742b35938b6f58e24e3f1c550fe92d4d33eb74Gilad Arnoldconst char* const kMountPathTemplate = "UpdateEngineTests_mnt-XXXXXX";
4261d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold
43f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenkoconst uint8_t kRandomString[] = {
4410875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xf2, 0xb7, 0x55, 0x92, 0xea, 0xa6, 0xc9, 0x57,
4510875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xe0, 0xf8, 0xeb, 0x34, 0x93, 0xd9, 0xc4, 0x8f,
4610875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xcb, 0x20, 0xfa, 0x37, 0x4b, 0x40, 0xcf, 0xdc,
4710875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xa5, 0x08, 0x70, 0x89, 0x79, 0x35, 0xe2, 0x3d,
4810875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x56, 0xa4, 0x75, 0x73, 0xa3, 0x6d, 0xd1, 0xd5,
4910875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x26, 0xbb, 0x9c, 0x60, 0xbd, 0x2f, 0x5a, 0xfa,
5010875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xb7, 0xd4, 0x3a, 0x50, 0xa7, 0x6b, 0x3e, 0xfd,
5110875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x61, 0x2b, 0x3a, 0x31, 0x30, 0x13, 0x33, 0x53,
5210875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xdb, 0xd0, 0x32, 0x71, 0x5c, 0x39, 0xed, 0xda,
5310875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xb4, 0x84, 0xca, 0xbc, 0xbd, 0x78, 0x1c, 0x0c,
5410875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xd8, 0x0b, 0x41, 0xe8, 0xe1, 0xe0, 0x41, 0xad,
5510875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x03, 0x12, 0xd3, 0x3d, 0xb8, 0x75, 0x9b, 0xe6,
5610875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xd9, 0x01, 0xd0, 0x87, 0xf4, 0x36, 0xfa, 0xa7,
5710875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x0a, 0xfa, 0xc5, 0x87, 0x65, 0xab, 0x9a, 0x7b,
5810875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xeb, 0x58, 0x23, 0xf0, 0xa8, 0x0a, 0xf2, 0x33,
5910875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x3a, 0xe2, 0xe3, 0x35, 0x74, 0x95, 0xdd, 0x3c,
6010875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x59, 0x5a, 0xd9, 0x52, 0x3a, 0x3c, 0xac, 0xe5,
6110875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x15, 0x87, 0x6d, 0x82, 0xbc, 0xf8, 0x7d, 0xbe,
6210875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xca, 0xd3, 0x2c, 0xd6, 0xec, 0x38, 0xeb, 0xe4,
6310875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x53, 0xb0, 0x4c, 0x3f, 0x39, 0x29, 0xf7, 0xa4,
6410875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x73, 0xa8, 0xcb, 0x32, 0x50, 0x05, 0x8c, 0x1c,
6510875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x1c, 0xca, 0xc9, 0x76, 0x0b, 0x8f, 0x6b, 0x57,
6610875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x1f, 0x24, 0x2b, 0xba, 0x82, 0xba, 0xed, 0x58,
6710875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xd8, 0xbf, 0xec, 0x06, 0x64, 0x52, 0x6a, 0x3f,
6810875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xe4, 0xad, 0xce, 0x84, 0xb4, 0x27, 0x55, 0x14,
6910875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xe3, 0x75, 0x59, 0x73, 0x71, 0x51, 0xea, 0xe8,
7010875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xcc, 0xda, 0x4f, 0x09, 0xaf, 0xa4, 0xbc, 0x0e,
7110875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xa6, 0x1f, 0xe2, 0x3a, 0xf8, 0x96, 0x7d, 0x30,
7210875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x23, 0xc5, 0x12, 0xb5, 0xd8, 0x73, 0x6b, 0x71,
7310875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xab, 0xf1, 0xd7, 0x43, 0x58, 0xa7, 0xc9, 0xf0,
7410875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xe4, 0x85, 0x1c, 0xd6, 0x92, 0x50, 0x2c, 0x98,
7510875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x36, 0xfe, 0x87, 0xaf, 0x43, 0x8f, 0x8f, 0xf5,
7610875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x88, 0x48, 0x18, 0x42, 0xcf, 0x42, 0xc1, 0xa8,
7710875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xe8, 0x05, 0x08, 0xa1, 0x45, 0x70, 0x5b, 0x8c,
7810875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x39, 0x28, 0xab, 0xe9, 0x6b, 0x51, 0xd2, 0xcb,
7910875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x30, 0x04, 0xea, 0x7d, 0x2f, 0x6e, 0x6c, 0x3b,
8010875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0x5f, 0x82, 0xd9, 0x5b, 0x89, 0x37, 0x65, 0x65,
8110875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  0xbe, 0x9f, 0xa3, 0x5d,
8210875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo};
8310875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo
8410875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymobool IsXAttrSupported(const base::FilePath& dir_path) {
8510875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  char *path = strdup(dir_path.Append("xattr_test_XXXXXX").value().c_str());
8610875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo
8710875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  int fd = mkstemp(path);
8810875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  if (fd == -1) {
8910875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    PLOG(ERROR) << "Error creating temporary file in " << dir_path.value();
9010875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    free(path);
9110875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    return false;
9210875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  }
9310875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo
9410875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  if (unlink(path) != 0) {
9510875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    PLOG(ERROR) << "Error unlinking temporary file " << path;
9610875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    close(fd);
9710875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    free(path);
9810875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    return false;
9910875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  }
10010875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo
10110875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  int xattr_res = fsetxattr(fd, "user.xattr-test", "value", strlen("value"), 0);
10210875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  if (xattr_res != 0) {
10310875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    if (errno == ENOTSUP) {
10410875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo      // Leave it to call-sites to warn about non-support.
10510875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    } else {
10610875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo      PLOG(ERROR) << "Error setting xattr on " << path;
10710875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    }
10810875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  }
10910875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  close(fd);
11010875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  free(path);
11110875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  return xattr_res == 0;
11210875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo}
11310875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo
114f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenkobool WriteFileVector(const string& path, const chromeos::Blob& data) {
115f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko  return utils::WriteFile(path.c_str(), data.data(), data.size());
116c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com}
117c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com
118f329b933db41d26644a97afef928eb1b319d6d99Alex Deymobool WriteFileString(const string& path, const string& data) {
119970bb28905b44bf9f2cb986bb412ecda1095b0b1Andrew de los Reyes  return utils::WriteFile(path.c_str(), data.data(), data.size());
120c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com}
121c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com
12219a45f0eda0917b7788b925b501e774208474fdeGilad Arnold// Binds provided |filename| to an unused loopback device, whose name is written
12319a45f0eda0917b7788b925b501e774208474fdeGilad Arnold// to the string pointed to by |lo_dev_name_p|. Returns true on success, false
12419a45f0eda0917b7788b925b501e774208474fdeGilad Arnold// otherwise (along with corresponding test failures), in which case the content
12519a45f0eda0917b7788b925b501e774208474fdeGilad Arnold// of |lo_dev_name_p| is unknown.
12619a45f0eda0917b7788b925b501e774208474fdeGilad Arnoldbool BindToUnusedLoopDevice(const string& filename, string* lo_dev_name_p) {
12719a45f0eda0917b7788b925b501e774208474fdeGilad Arnold  CHECK(lo_dev_name_p);
12819a45f0eda0917b7788b925b501e774208474fdeGilad Arnold
12919a45f0eda0917b7788b925b501e774208474fdeGilad Arnold  // Bind to an unused loopback device, sanity check the device name.
13019a45f0eda0917b7788b925b501e774208474fdeGilad Arnold  lo_dev_name_p->clear();
13119a45f0eda0917b7788b925b501e774208474fdeGilad Arnold  if (!(utils::ReadPipe("losetup --show -f " + filename, lo_dev_name_p) &&
1326a9d3497bcf57b8b9f5765a2909a51c9f8119cd1Alex Vakulenko        base::StartsWithASCII(*lo_dev_name_p, "/dev/loop", true))) {
13319a45f0eda0917b7788b925b501e774208474fdeGilad Arnold    ADD_FAILURE();
13419a45f0eda0917b7788b925b501e774208474fdeGilad Arnold    return false;
135c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com  }
136c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com
13719a45f0eda0917b7788b925b501e774208474fdeGilad Arnold  // Strip anything from the first newline char.
13819a45f0eda0917b7788b925b501e774208474fdeGilad Arnold  size_t newline_pos = lo_dev_name_p->find('\n');
13919a45f0eda0917b7788b925b501e774208474fdeGilad Arnold  if (newline_pos != string::npos)
14019a45f0eda0917b7788b925b501e774208474fdeGilad Arnold    lo_dev_name_p->erase(newline_pos);
141c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com
14219a45f0eda0917b7788b925b501e774208474fdeGilad Arnold  return true;
143c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com}
144c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com
145f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenkobool ExpectVectorsEq(const chromeos::Blob& expected,
146f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko                     const chromeos::Blob& actual) {
1478006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes  EXPECT_EQ(expected.size(), actual.size());
1488006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes  if (expected.size() != actual.size())
149c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com    return false;
150617bbc23d2cf4cba5881ec54607926393f7245c7Gilad Arnold  bool is_all_eq = true;
1518006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes  for (unsigned int i = 0; i < expected.size(); i++) {
1528006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes    EXPECT_EQ(expected[i], actual[i]) << "offset: " << i;
153617bbc23d2cf4cba5881ec54607926393f7245c7Gilad Arnold    is_all_eq = is_all_eq && (expected[i] == actual[i]);
154c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com  }
155617bbc23d2cf4cba5881ec54607926393f7245c7Gilad Arnold  return is_all_eq;
156c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com}
157c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com
158f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenkovoid FillWithData(chromeos::Blob* buffer) {
1598006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes  size_t input_counter = 0;
160f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko  for (uint8_t& b : *buffer) {
161f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko    b = kRandomString[input_counter];
1628006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes    input_counter++;
1638006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes    input_counter %= sizeof(kRandomString);
1648006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes  }
1658006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes}
1668006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes
1675c7d97590b51ae9e85dde1e37a3fd91d06f7991dThieu Levoid CreateEmptyExtImageAtPath(const string& path,
1685c7d97590b51ae9e85dde1e37a3fd91d06f7991dThieu Le                               size_t size,
1695c7d97590b51ae9e85dde1e37a3fd91d06f7991dThieu Le                               int block_size) {
1705c7d97590b51ae9e85dde1e37a3fd91d06f7991dThieu Le  EXPECT_EQ(0, System(StringPrintf("dd if=/dev/zero of=%s"
1711f93d031baa4c0c4f390fcf5784b5179d15f289dAlex Deymo                                   " seek=%zu bs=1 count=1 status=none",
1725c7d97590b51ae9e85dde1e37a3fd91d06f7991dThieu Le                                   path.c_str(), size)));
1736ded6548c4d3606923d606981dd29f224bcfc723Alex Deymo  EXPECT_EQ(0, System(StringPrintf("mkfs.ext3 -q -b %d -F %s",
1745c7d97590b51ae9e85dde1e37a3fd91d06f7991dThieu Le                                   block_size, path.c_str())));
1755c7d97590b51ae9e85dde1e37a3fd91d06f7991dThieu Le}
1765c7d97590b51ae9e85dde1e37a3fd91d06f7991dThieu Le
177c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.comvoid CreateExtImageAtPath(const string& path, vector<string>* out_paths) {
17861d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold  // create 10MiB sparse file, mounted at a unique location.
17961d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold  string mount_path;
18061d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold  CHECK(utils::MakeTempDirectory(kMountPathTemplate, &mount_path));
181a58b62a57eb2fe4070ed7efbf869b37037fbeaa7Alex Deymo  ScopedDirRemover mount_path_unlinker(mount_path);
18261d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold
183c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com  EXPECT_EQ(0, System(StringPrintf("dd if=/dev/zero of=%s"
1841f93d031baa4c0c4f390fcf5784b5179d15f289dAlex Deymo                                   " seek=10485759 bs=1 count=1 status=none",
185c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com                                   path.c_str())));
1866ded6548c4d3606923d606981dd29f224bcfc723Alex Deymo  EXPECT_EQ(0, System(StringPrintf("mkfs.ext3 -q -b 4096 -F %s",
1876ded6548c4d3606923d606981dd29f224bcfc723Alex Deymo                                   path.c_str())));
188c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com  EXPECT_EQ(0, System(StringPrintf("mount -o loop %s %s", path.c_str(),
18961d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold                                   mount_path.c_str())));
19061d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold  EXPECT_EQ(0, System(StringPrintf("echo hi > %s/hi", mount_path.c_str())));
19161d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold  EXPECT_EQ(0, System(StringPrintf("echo hello > %s/hello",
19261d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold                                   mount_path.c_str())));
19361d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold  EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir", mount_path.c_str())));
19461d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold  EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir/empty_dir",
19561d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold                                   mount_path.c_str())));
19661d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold  EXPECT_EQ(0, System(StringPrintf("mkdir %s/some_dir/mnt",
19761d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold                                   mount_path.c_str())));
19861d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold  EXPECT_EQ(0, System(StringPrintf("echo T > %s/some_dir/test",
19961d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold                                   mount_path.c_str())));
20061d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold  EXPECT_EQ(0, System(StringPrintf("mkfifo %s/some_dir/fifo",
20161d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold                                   mount_path.c_str())));
20261d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold  EXPECT_EQ(0, System(StringPrintf("mknod %s/cdev c 2 3", mount_path.c_str())));
20361d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold  EXPECT_EQ(0, System(StringPrintf("ln -s /some/target %s/sym",
20461d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold                                   mount_path.c_str())));
205c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com  EXPECT_EQ(0, System(StringPrintf("ln %s/some_dir/test %s/testlink",
20661d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold                                   mount_path.c_str(), mount_path.c_str())));
20761d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold  EXPECT_EQ(0, System(StringPrintf("echo T > %s/srchardlink0",
20861d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold                                   mount_path.c_str())));
20929da8aafd5da32ebfb57c7f3cf1b89ce3e5d60cbAndrew de los Reyes  EXPECT_EQ(0, System(StringPrintf("ln %s/srchardlink0 %s/srchardlink1",
21061d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold                                   mount_path.c_str(), mount_path.c_str())));
21148a0a4826c47fe097d7ff31ad830911c1f288dbfAndrew de los Reyes  EXPECT_EQ(0, System(StringPrintf("ln -s bogus %s/boguslink",
21261d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold                                   mount_path.c_str())));
21361d9d2c93ffd65818c5aae21791099842a5d4938Gilad Arnold  EXPECT_TRUE(utils::UnmountFilesystem(mount_path.c_str()));
2145c7d97590b51ae9e85dde1e37a3fd91d06f7991dThieu Le
215c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com  if (out_paths) {
216c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com    out_paths->clear();
217c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com    out_paths->push_back("");
218c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com    out_paths->push_back("/hi");
21948a0a4826c47fe097d7ff31ad830911c1f288dbfAndrew de los Reyes    out_paths->push_back("/boguslink");
220c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com    out_paths->push_back("/hello");
221c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com    out_paths->push_back("/some_dir");
222c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com    out_paths->push_back("/some_dir/empty_dir");
223c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com    out_paths->push_back("/some_dir/mnt");
224c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com    out_paths->push_back("/some_dir/test");
225c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com    out_paths->push_back("/some_dir/fifo");
226c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com    out_paths->push_back("/cdev");
227c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com    out_paths->push_back("/testlink");
228c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com    out_paths->push_back("/sym");
22929da8aafd5da32ebfb57c7f3cf1b89ce3e5d60cbAndrew de los Reyes    out_paths->push_back("/srchardlink0");
23029da8aafd5da32ebfb57c7f3cf1b89ce3e5d60cbAndrew de los Reyes    out_paths->push_back("/srchardlink1");
231c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com    out_paths->push_back("/lost+found");
232c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com  }
233c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com}
234c98a7edf648aad88b3f66df3b5a7d43d6a6d7fa9adlr@google.com
23558e8b1f8b32b355d879008572648fd621873711dDon GarrettScopedLoopMounter::ScopedLoopMounter(const string& file_path,
23658e8b1f8b32b355d879008572648fd621873711dDon Garrett                                     string* mnt_path,
237d2779df63aaad8b65fc5d4badee7dbc9bed7f2b6Alex Vakulenko                                     unsigned long flags) {  // NOLINT - long
238a6742b35938b6f58e24e3f1c550fe92d4d33eb74Gilad Arnold  EXPECT_TRUE(utils::MakeTempDirectory("mnt.XXXXXX", mnt_path));
2395c7d97590b51ae9e85dde1e37a3fd91d06f7991dThieu Le  dir_remover_.reset(new ScopedDirRemover(*mnt_path));
2405c7d97590b51ae9e85dde1e37a3fd91d06f7991dThieu Le
24158e8b1f8b32b355d879008572648fd621873711dDon Garrett  string loop_dev;
24258e8b1f8b32b355d879008572648fd621873711dDon Garrett  loop_binder_.reset(new ScopedLoopbackDeviceBinder(file_path, &loop_dev));
2435c7d97590b51ae9e85dde1e37a3fd91d06f7991dThieu Le
2445c7d97590b51ae9e85dde1e37a3fd91d06f7991dThieu Le  EXPECT_TRUE(utils::MountFilesystem(loop_dev, *mnt_path, flags));
2455c7d97590b51ae9e85dde1e37a3fd91d06f7991dThieu Le  unmounter_.reset(new ScopedFilesystemUnmounter(*mnt_path));
2465c7d97590b51ae9e85dde1e37a3fd91d06f7991dThieu Le}
2475c7d97590b51ae9e85dde1e37a3fd91d06f7991dThieu Le
24810875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymonamespace {
24910875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymoclass ScopedDirCloser {
25010875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo public:
25110875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  explicit ScopedDirCloser(DIR** dir) : dir_(dir) {}
25210875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  ~ScopedDirCloser() {
25310875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    if (dir_ && *dir_) {
25410875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo      int r = closedir(*dir_);
25510875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo      TEST_AND_RETURN_ERRNO(r == 0);
25610875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo      *dir_ = nullptr;
25710875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo      dir_ = nullptr;
25810875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    }
25910875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  }
26010875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo private:
26110875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  DIR** dir_;
26210875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo};
26310875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo}  // namespace
26410875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo
26510875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymobool RecursiveUnlinkDir(const string& path) {
26610875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  struct stat stbuf;
26710875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  int r = lstat(path.c_str(), &stbuf);
26810875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  TEST_AND_RETURN_FALSE_ERRNO((r == 0) || (errno == ENOENT));
26910875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  if ((r < 0) && (errno == ENOENT))
27010875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    // path request is missing. that's fine.
27110875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    return true;
27210875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  if (!S_ISDIR(stbuf.st_mode)) {
27310875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    TEST_AND_RETURN_FALSE_ERRNO((unlink(path.c_str()) == 0) ||
27410875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo                                (errno == ENOENT));
27510875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    // success or path disappeared before we could unlink.
27610875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    return true;
27710875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  }
27810875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  {
27910875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    // We have a dir, unlink all children, then delete dir
28010875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    DIR *dir = opendir(path.c_str());
28110875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    TEST_AND_RETURN_FALSE_ERRNO(dir);
28210875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    ScopedDirCloser dir_closer(&dir);
28310875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    struct dirent dir_entry;
28410875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    struct dirent *dir_entry_p;
28510875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    int err = 0;
28610875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    while ((err = readdir_r(dir, &dir_entry, &dir_entry_p)) == 0) {
28710875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo      if (dir_entry_p == nullptr) {
28810875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo        // end of stream reached
28910875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo        break;
29010875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo      }
29110875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo      // Skip . and ..
29210875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo      if (!strcmp(dir_entry_p->d_name, ".") ||
29310875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo          !strcmp(dir_entry_p->d_name, ".."))
29410875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo        continue;
29510875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo      TEST_AND_RETURN_FALSE(RecursiveUnlinkDir(path + "/" +
29610875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo                                               dir_entry_p->d_name));
29710875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    }
29810875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo    TEST_AND_RETURN_FALSE(err == 0);
29910875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  }
30010875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  // unlink dir
30110875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  TEST_AND_RETURN_FALSE_ERRNO((rmdir(path.c_str()) == 0) || (errno == ENOENT));
30210875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo  return true;
30310875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo}
30410875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo
3052b19cfbcdb1aa8c5d1f338d19312fe14b6734bd5Alex Deymobase::FilePath GetBuildArtifactsPath() {
3062b19cfbcdb1aa8c5d1f338d19312fe14b6734bd5Alex Deymo  base::FilePath exe_path;
3072b19cfbcdb1aa8c5d1f338d19312fe14b6734bd5Alex Deymo  base::ReadSymbolicLink(base::FilePath("/proc/self/exe"), &exe_path);
3082b19cfbcdb1aa8c5d1f338d19312fe14b6734bd5Alex Deymo  return exe_path.DirName();
3092b19cfbcdb1aa8c5d1f338d19312fe14b6734bd5Alex Deymo}
3102b19cfbcdb1aa8c5d1f338d19312fe14b6734bd5Alex Deymo
31110875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymo}  // namespace test_utils
31249fdf1889b965be25f929eeebc5b60cd40b9043rspangler@google.com}  // namespace chromeos_update_engine
313