| Index: test/BaseJsTest.h | 
| =================================================================== | 
| --- a/test/BaseJsTest.h | 
| +++ b/test/BaseJsTest.h | 
| @@ -13,16 +13,18 @@ | 
| * | 
| * You should have received a copy of the GNU General Public License | 
| * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. | 
| */ | 
| #ifndef MOCKS_H | 
| #define MOCKS_H | 
| +#include <thread> | 
| + | 
| #include <AdblockPlus.h> | 
| #include <gtest/gtest.h> | 
| #include "../src/Thread.h" | 
| // Strictly speaking in each test there should be a special implementation of | 
| // an interface, which is merely referenced by a wrapper and the latter should | 
| // be injected into JsEngine or what ever. However the everthing a test often | 
| // actually needs is the access to pending tasks. Therefore instantiation of | 
| @@ -97,96 +99,173 @@ | 
| public: | 
| void operator()(LogLevel logLevel, const std::string& message, | 
| const std::string& source) | 
| { | 
| throw std::runtime_error("Unexpected error: " + message); | 
| } | 
| }; | 
| -class ThrowingFileSystem : public AdblockPlus::FileSystem | 
| +class ThrowingFileSystem : public AdblockPlus::IFileSystem, public AdblockPlus::FileSystem | 
| { | 
| public: | 
| std::shared_ptr<std::istream> Read(const std::string& path) const | 
| { | 
| throw std::runtime_error("Not implemented"); | 
| } | 
| + void Read(const std::string& path, | 
| + const ReadCallback& callback) const | 
| + { | 
| + throw std::runtime_error("Not implemented"); | 
| + } | 
| - void Write(const std::string& path, std::istream& content) | 
| + void Write(const std::string& path, std::ostream& content) | 
| + { | 
| + throw std::runtime_error("Not implemented"); | 
| + } | 
| + void Write(const std::string& path, const std::vector<char>& data, | 
| + const Callback& callback) | 
| { | 
| throw std::runtime_error("Not implemented"); | 
| } | 
| void Move(const std::string& fromPath, const std::string& toPath) | 
| { | 
| throw std::runtime_error("Not implemented"); | 
| } | 
| + void Move(const std::string& fromPath, const std::string& toPath, | 
| + const Callback& callback) | 
| + { | 
| + throw std::runtime_error("Not implemented"); | 
| + } | 
| void Remove(const std::string& path) | 
| { | 
| throw std::runtime_error("Not implemented"); | 
| } | 
| + void Remove(const std::string& path, const Callback& callback) | 
| + { | 
| + throw std::runtime_error("Not implemented"); | 
| + } | 
| StatResult Stat(const std::string& path) const | 
| { | 
| throw std::runtime_error("Not implemented"); | 
| } | 
| + void Stat(const std::string& path, | 
| + const StatCallback& callback) const | 
| + { | 
| + throw std::runtime_error("Not implemented"); | 
| + } | 
| std::string Resolve(const std::string& path) const | 
| { | 
| throw std::runtime_error("Not implemented"); | 
| } | 
| - | 
| }; | 
| class ThrowingWebRequest : public AdblockPlus::IWebRequest | 
| { | 
| public: | 
| void GET(const std::string& url, const AdblockPlus::HeaderList& requestHeaders, const GetCallback&) override | 
| { | 
| throw std::runtime_error("Unexpected GET: " + url); | 
| } | 
| }; | 
| -class LazyFileSystem : public AdblockPlus::FileSystem | 
| +class LazyFileSystem : public AdblockPlus::IFileSystem, public AdblockPlus::FileSystem | 
| { | 
| public: | 
| std::shared_ptr<std::istream> Read(const std::string& path) const | 
| { | 
| std::string dummyData(""); | 
| if (path == "patterns.ini") | 
| dummyData = "# Adblock Plus preferences\n[Subscription]\nurl=~fl~"; | 
| else if (path == "prefs.json") | 
| dummyData = "{}"; | 
| return std::shared_ptr<std::istream>(new std::istringstream(dummyData)); | 
| } | 
| - void Write(const std::string& path, std::istream& content) | 
| + void Read(const std::string& path, const ReadCallback& callback) const | 
| { | 
| + std::thread([this, path, callback] | 
| + { | 
| + auto is = Read(path); | 
| + is->seekg(0, std::ios_base::end); | 
| + auto dataSize = is->tellg(); | 
| + is->seekg(0, std::ios_base::beg); | 
| + | 
| + std::vector<char> data(dataSize); | 
| + is->read(data.data(), data.size()); | 
| + callback(std::move(data), ""); | 
| + }).detach(); | 
| + } | 
| + | 
| + void Write(const std::string& path, std::ostream& content) | 
| + { | 
| + } | 
| + | 
| + void Write(const std::string& path, const std::vector<char>& data, | 
| + const Callback& callback) | 
| + { | 
| + std::thread([this, path, data, callback] | 
| + { | 
| + std::stringstream stream; | 
| + stream.write(data.data(), data.size()); | 
| + Write(path, stream); | 
| + callback(""); | 
| + }).detach(); | 
| } | 
| void Move(const std::string& fromPath, const std::string& toPath) | 
| { | 
| } | 
| + void Move(const std::string& fromPath, const std::string& toPath, | 
| + const Callback& callback) | 
| + { | 
| + std::thread([this, fromPath, toPath, callback] | 
| + { | 
| + Move(fromPath, toPath); | 
| + callback(""); | 
| + }).detach(); | 
| + } | 
| + | 
| void Remove(const std::string& path) | 
| { | 
| } | 
| + void Remove(const std::string& path, const Callback& callback) | 
| + { | 
| + std::thread([this, path, callback] | 
| + { | 
| + Remove(path); | 
| + callback(""); | 
| + }).detach(); | 
| + } | 
| + | 
| StatResult Stat(const std::string& path) const | 
| { | 
| StatResult result; | 
| if (path == "patterns.ini") | 
| { | 
| result.exists = true; | 
| result.isFile = true; | 
| } | 
| return result; | 
| } | 
| + void Stat(const std::string& path, const StatCallback& callback) const | 
| + { | 
| + std::thread([this, path, callback] | 
| + { | 
| + callback(Stat(path), ""); | 
| + }).detach(); | 
| + } | 
| + | 
| std::string Resolve(const std::string& path) const | 
| { | 
| return path; | 
| } | 
| }; | 
| class NoopWebRequest : public AdblockPlus::IWebRequest | 
| { |