Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(18)

Side by Side Diff: third_party/crazy_linker/crazy_linker/src/crazy_linker_system_mock.cpp

Issue 23717023: Android: Add chrome-specific dynamic linker. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add new 'content_linker_unittests_apk' target + ensure ashmem regions are forced read-only Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2013 The Chromium 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 "crazy_linker_system_mock.h"
6
7 #include <stdarg.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10
11 #include "crazy_linker_util.h"
12 #include "crazy_linker_system.h"
13
14 // Unit-testing support code. This should never be compiled into
15 // the production code.
16
17 namespace {
18
19 using crazy::String;
20 using crazy::Vector;
21
22 void Panic(const char* msg, ...) {
23 va_list args;
24 fprintf(stderr, "PANIC: ");
25 va_start(args, msg);
26 vfprintf(stderr, msg, args);
27 va_end(args);
28 fprintf(stderr, "\n");
29 exit(1);
30 }
31
32 // Models a simple list of pointers to objects, which are owned by the
33 // list itself.
34 template <class T>
35 class List {
36 public:
37 List() : entries_() {}
38
39 ~List() {
40 Reset();
41 }
42
43 void Reset() {
44 for (size_t n = 0; n < entries_.GetCount(); ++n) {
45 T* entry = entries_[n];
46 delete entry;
47 entries_[n] = NULL;
48 }
49 entries_.Resize(0);
50 }
51
52 // Add an item to the list, transfer ownership to it.
53 void PushBack(T* item) {
54 entries_.PushBack(item);
55 }
56
57 size_t GetCount() const { return entries_.GetCount(); }
58
59 T* operator[](size_t index) { return entries_[index]; }
60
61 private:
62 crazy::Vector<T*> entries_;
63 };
64
65 // Models a single file entry in a mock file system.
66 class MockFileEntry {
67 public:
68 MockFileEntry() : path_(), data_() {}
69
70 ~MockFileEntry() {}
71
72 const char* GetPath() const { return path_.c_str(); }
73 const char* GetData() const { return data_.c_str(); }
74 size_t GetDataSize() const { return data_.size(); }
75
76 void SetPath(const char* path) {
77 path_.Assign(path);
78 }
79
80 void SetData(const char* data, size_t data_size) {
81 data_.Assign(data, data_size);
82 }
83
84 private:
85 crazy::String path_;
86 crazy::String data_;
87 };
88
89 // Models a single mock environment variable value.
90 class MockEnvEntry {
91 public:
92 MockEnvEntry(const char* var_name, const char* var_value)
93 : var_name_(var_name), var_value_(var_value) {}
94
95 const String& GetName() const { return var_name_; }
96 const String& GetValue() const { return var_value_; }
97
98 private:
99 crazy::String var_name_;
100 crazy::String var_value_;
101 };
102
103 class MockSystem {
104 public:
105 MockSystem() : files_(), environment_() {}
106
107 ~MockSystem() {
108 Reset();
109 }
110
111 void SetCurrentDir(const char* path) {
112 current_dir_ = path;
113 }
114
115 String GetCurrentDir() const {
116 return current_dir_;
117 }
118
119 void AddFileEntry(MockFileEntry* entry) {
120 files_.PushBack(entry);
121 }
122
123 void AddEnvEntry(MockEnvEntry* entry) {
124 environment_.PushBack(entry);
125 }
126
127 MockFileEntry* FindFileEntry(const char* path) {
128 for (size_t n = 0; n < files_.GetCount(); ++n) {
129 MockFileEntry* entry = files_[n];
130 if (entry->GetPath() && !strcmp(path, entry->GetPath()))
131 return entry;
132 }
133 return NULL;
134 }
135
136 MockEnvEntry* FindEnvEntry(const char* var_name) {
137 for (size_t n = 0; n < environment_.GetCount(); ++n) {
138 MockEnvEntry* entry = environment_[n];
139 if (!strcmp(entry->GetName().c_str(), var_name))
140 return entry;
141 }
142 return NULL;
143 }
144
145 void Reset() {
146 files_.Reset();
147 environment_.Reset();
148 current_dir_ = "/";
149 }
150
151 void Check() {
152 if (!active_)
153 Panic("No mock file system setup!");
154 }
155
156 void Activate() {
157 if (active_)
158 Panic("Double mock file system activation!");
159
160 active_ = true;
161 }
162
163 void Deactivate() {
164 if (!active_)
165 Panic("Double mock file system deactivation!");
166
167 active_ = false;
168 }
169
170 private:
171 List<MockFileEntry> files_;
172 List<MockEnvEntry> environment_;
173 String current_dir_;
174 bool active_;
175 };
176
177 static MockSystem s_mock_fs;
178
179 class MockFileHandle {
180 public:
181 MockFileHandle(MockFileEntry* entry) : entry_(entry), offset_(0) {}
182 ~MockFileHandle() {}
183
184 bool IsEof() const {
185 return offset_ >= entry_->GetDataSize();
186 }
187
188 bool GetString(char* buffer, size_t buffer_size) {
189 const char* data = entry_->GetData();
190 size_t data_size = entry_->GetDataSize();
191
192 if (offset_ >= data_size || buffer_size == 0)
193 return false;
194
195 while (buffer_size > 1) {
196 char ch = data[offset_ ++ ];
197 *buffer++ = ch;
198 buffer_size--;
199 if (ch == '\n')
200 break;
201 }
202 *buffer = '\0';
203 return true;
204 }
205
206 int Read(void* buffer, size_t buffer_size) {
207 if (buffer_size == 0)
208 return 0;
209
210 const char* data = entry_->GetData();
211 size_t data_size = entry_->GetDataSize();
212
213 size_t avail = data_size - offset_;
214 if (avail == 0)
215 return 0;
216
217 if (buffer_size > avail)
218 buffer_size = avail;
219
220 ::memcpy(buffer, data + offset_, buffer_size);
221 offset_ += buffer_size;
222
223 return static_cast<int>(buffer_size);
224 }
225
226 int SeekTo(off_t offset) {
227 if (offset < 0) {
228 errno = EINVAL;
229 return -1;
230 }
231
232 const char* data = entry_->GetData();
233 size_t data_size = entry_->GetDataSize();
234
235 if (offset > static_cast<off_t>(data_size)) {
236 errno = EINVAL;
237 return -1;
238 }
239
240 offset_ = static_cast<size_t>(offset);
241 return 0;
242 }
243
244 void* Map(void* address, size_t length, int prot, int flags,
245 off_t offset) {
246 const char* data = entry_->GetData();
247 size_t data_size = entry_->GetDataSize();
248 if (offset_ >= data_size) {
249 errno = EINVAL;
250 return MAP_FAILED;
251 }
252
253 // Allocate an anonymous memory mapping, then copy the file contents
254 // into it.
255 void* map = mmap(address, length, PROT_WRITE, MAP_ANONYMOUS, -1, 0);
256 if (map == MAP_FAILED) {
257 return map;
258 }
259
260 size_t avail = data_size - offset_;
261 if (avail > length)
262 avail = length;
263
264 ::memcpy(map, data + offset_, avail);
265
266 // Restore desired protection after the write.
267 mprotect(map, length, prot);
268
269 // Done.
270 return map;
271 }
272
273 private:
274 MockFileEntry* entry_;
275 size_t offset_;
276 };
277
278 MockFileHandle* NewMockFileHandle(const char* path,
279 crazy::FileOpenMode open_mode) {
280 // Check that a mock file system instance is active.
281 s_mock_fs.Check();
282
283 // TODO(digit): Add write support.
284 if (open_mode != crazy::FILE_OPEN_READ_ONLY)
285 Panic("Unsupported open mode (%d): %s", open_mode, path);
286
287 MockFileEntry* entry = s_mock_fs.FindFileEntry(path);
288 if (!entry)
289 Panic("Missing mock file entry: %s", path);
290
291 return new MockFileHandle(entry);
292 }
293
294 } // namespace
295
296 namespace crazy {
297
298 #ifdef UNIT_TESTS
299
300 bool PathExists(const char* path) {
301 s_mock_fs.Check();
302 return s_mock_fs.FindFileEntry(path) != NULL;
303 }
304
305 bool PathIsFile(const char* path) {
306 // TODO(digit): Change this when support for mock directories is added.
307 return PathExists(path);
308 }
309
310 String GetCurrentDirectory() {
311 s_mock_fs.Check();
312 return s_mock_fs.GetCurrentDir();
313 }
314
315 const char* GetEnv(const char* var_name) {
316 s_mock_fs.Check();
317 MockEnvEntry* entry = s_mock_fs.FindEnvEntry(var_name);
318 if (!entry)
319 return NULL;
320 else
321 return entry->GetValue().c_str();
322 }
323
324 bool FileDescriptor::OpenReadOnly(const char* path) {
325 fd_ = NewMockFileHandle(path, FILE_OPEN_READ_ONLY);
326 return fd_ != NULL;
327 }
328
329 bool FileDescriptor::OpenReadWrite(const char* path) {
330 // NOT IMPLEMENTED ON PURPOSE.
331 return false;
332 }
333
334 void FileDescriptor::Close() {
335 if (fd_) {
336 MockFileHandle* handle = reinterpret_cast<MockFileHandle*>(fd_);
337 delete handle;
338 fd_ = NULL;
339 }
340 }
341
342 int FileDescriptor::Read(void* buffer, size_t buffer_size) {
343 if (!fd_) {
344 errno = EBADF;
345 return -1;
346 }
347 MockFileHandle* handle = reinterpret_cast<MockFileHandle*>(fd_);
348 return handle->Read(buffer, buffer_size);
349 }
350
351 int FileDescriptor::SeekTo(off_t offset) {
352 if (!fd_) {
353 errno = EBADF;
354 return -1;
355 }
356 MockFileHandle* handle = reinterpret_cast<MockFileHandle*>(fd_);
357 return handle->SeekTo(offset);
358 }
359
360 void* FileDescriptor::Map(void* address, size_t length, int prot,
361 int flags, off_t offset) {
362 if (!fd_ || (offset & 4095) != 0) {
363 errno = EINVAL;
364 return MAP_FAILED;
365 }
366 MockFileHandle* handle = reinterpret_cast<MockFileHandle*>(fd_);
367 return handle->Map(address, length, prot, flags, offset);
368 }
369
370 SystemMock::SystemMock() {
371 s_mock_fs.Activate();
372 }
373
374 SystemMock::~SystemMock() {
375 s_mock_fs.Deactivate();
376 s_mock_fs.Reset();
377 }
378
379 void SystemMock::AddRegularFile(const char* path,
380 const char* data,
381 size_t data_size) {
382 s_mock_fs.Check();
383
384 MockFileEntry* entry = new MockFileEntry();
385 entry->SetPath(path);
386 entry->SetData(data, data_size);
387
388 s_mock_fs.AddFileEntry(entry);
389 }
390
391 void SystemMock::AddEnvVariable(const char* var_name,
392 const char* var_value) {
393 s_mock_fs.Check();
394
395 MockEnvEntry* env = new MockEnvEntry(var_name, var_value);
396 s_mock_fs.AddEnvEntry(env);
397 }
398
399 void SystemMock::SetCurrentDir(const char* path) {
400 s_mock_fs.Check();
401 s_mock_fs.SetCurrentDir(path);
402 }
403
404 #endif // UNIT_TESTS
405
406 } // namespace crazy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698