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