blob: b7540e6ddbf71f07759eaa540a976805e0f19450 [file] [log] [blame]
Alex Deymoa5cff222015-04-08 14:10:30 -07001// Copyright 2015 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "test_utils.h"
6
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10#include <unistd.h>
11
12#include <gtest/gtest.h>
13#include <vector>
14
15using std::string;
16using std::vector;
17
18namespace {
19
20// If |path| is absolute, or explicit relative to the current working directory,
21// leaves it as is. Otherwise, if TMPDIR is defined in the environment and is
22// non-empty, prepends it to |path|. Otherwise, prepends /tmp. Returns the
23// resulting path.
24const string PrependTmpdir(const string& path) {
25 if (path[0] == '/')
26 return path;
27
28 const char *tmpdir = getenv("TMPDIR");
29 const string prefix = (tmpdir && *tmpdir ? tmpdir : "/tmp");
30 return prefix + "/" + path;
31}
32
33bool MakeTempFile(const string& base_filename_template,
34 string* filename) {
35 const string filename_template = PrependTmpdir(base_filename_template);
36 vector<char> result(filename_template.size() + 1, '\0');
37 memcpy(result.data(), filename_template.data(), filename_template.size());
38
39 int mkstemp_fd = mkstemp(result.data());
40 if (mkstemp_fd < 0) {
41 perror("mkstemp()");
42 return false;
43 }
44 close(mkstemp_fd);
45
46 if (filename)
47 *filename = result.data();
48 return true;
49}
50
51} // namespace
52
53namespace test_utils {
54
55bool ReadFile(const string& path, vector<uint8_t>* out) {
56 FILE* fp = fopen(path.c_str(), "r");
57 if (!fp)
58 return false;
59 out->clear();
60
61 uint8_t buf[16 * 1024];
62 while (true) {
63 size_t bytes_read = fread(buf, 1, sizeof(buf), fp);
64 if (!bytes_read)
65 break;
66 out->insert(out->end(), buf, buf + bytes_read);
67 }
68 bool result = !ferror(fp);
69 fclose(fp);
70 return result;
71}
72
73bool WriteFile(const string& path, vector<uint8_t> contents) {
74 FILE* fp = fopen(path.c_str(), "r");
75 if (!fp)
76 return false;
77 size_t written = fwrite(contents.data(), 1, contents.size(), fp);
78 bool result = written == contents.size() && !ferror(fp);
79 fclose(fp);
80 return result;
81}
82
83ScopedTempFile::ScopedTempFile(const string& pattern) {
84 EXPECT_TRUE(MakeTempFile(pattern, &filename_));
85}
86
87ScopedTempFile::~ScopedTempFile() {
88 if (!filename_.empty() && unlink(filename_.c_str()) < 0) {
89 perror("Unable to remove temporary file");
90 }
91}
92
93bool BsdiffPatchFile::LoadFromFile(const string& filename) {
94 vector<uint8_t> contents;
95 if (!ReadFile(filename, &contents))
96 return false;
97 file_size = contents.size();
98 // Check that the file includes at least the header.
99 TEST_AND_RETURN_FALSE(contents.size() >= kHeaderSize);
100 magic = string(contents.data(), contents.data() + 8);
101 memcpy(&ctrl_len, contents.data() + 8, sizeof(ctrl_len));
102 memcpy(&diff_len, contents.data() + 16, sizeof(diff_len));
103 memcpy(&new_file_len, contents.data() + 24, sizeof(new_file_len));
104
105 TEST_AND_RETURN_FALSE(file_size >= kHeaderSize + ctrl_len + diff_len);
106 extra_len = file_size - kHeaderSize - ctrl_len - diff_len;
107
108 // Sanity check before we attempt to parse the bz2 streams.
109 TEST_AND_RETURN_FALSE(ctrl_len >= 0);
110 TEST_AND_RETURN_FALSE(diff_len >= 0);
111
112 uint8_t* ptr = contents.data() + kHeaderSize;
113 bz2_ctrl = vector<uint8_t>(ptr, ptr + ctrl_len);
114 ptr += ctrl_len;
115 bz2_diff = vector<uint8_t>(ptr, ptr + diff_len);
116 ptr += diff_len;
117 bz2_extra = vector<uint8_t>(ptr, ptr + extra_len);
118
119 return true;
120}
121
122bool BsdiffPatchFile::IsValid() const {
123 TEST_AND_RETURN_FALSE(ctrl_len >= 0);
124 TEST_AND_RETURN_FALSE(diff_len >= 0);
125 TEST_AND_RETURN_FALSE(new_file_len >= 0);
126
127 // TODO(deymo): Test that the length of the decompressed bz2 streams |diff|
128 // plus |extra| are equal to the |new_file_len|.
129 // TODO(deymo): Test that all the |bz2_ctrl| triplets (x, y, z) have a "x"
130 // and "y" value >= 0 ("z" can be negative).
131 return true;
132}
133
134} // namespace test_utils