summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbinji@chromium.org <binji@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-20 23:30:44 +0000
committerbinji@chromium.org <binji@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-20 23:30:44 +0000
commit8c587afa858ba02a00693af360085bb79dd5849a (patch)
tree90fef351b20d3b0761466bc6e81027fba3fae002
parent7f74766f9d3ad8a7d1bc2485bceb6dcc1867f614 (diff)
downloadchromium_src-8c587afa858ba02a00693af360085bb79dd5849a.zip
chromium_src-8c587afa858ba02a00693af360085bb79dd5849a.tar.gz
chromium_src-8c587afa858ba02a00693af360085bb79dd5849a.tar.bz2
[NaCl SDK] Add URLLoader fake pepper interface.
BUG=244313,245431 R=sbc@chromium.org Review URL: https://codereview.chromium.org/77423002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@236343 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_http.h7
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_node_http.cc52
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_node_http.h7
-rw-r--r--native_client_sdk/src/tests/nacl_io_test/example.dsc2
-rw-r--r--native_client_sdk/src/tests/nacl_io_test/fake_pepper_interface_html5fs.h76
-rw-r--r--native_client_sdk/src/tests/nacl_io_test/fake_pepper_interface_url_loader.cc502
-rw-r--r--native_client_sdk/src/tests/nacl_io_test/fake_pepper_interface_url_loader.h151
-rw-r--r--native_client_sdk/src/tests/nacl_io_test/fake_resource_manager.cc14
-rw-r--r--native_client_sdk/src/tests/nacl_io_test/fake_resource_manager.h16
-rw-r--r--native_client_sdk/src/tests/nacl_io_test/mount_http_test.cc654
10 files changed, 933 insertions, 548 deletions
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_http.h b/native_client_sdk/src/libraries/nacl_io/mount_http.h
index 21d688e..4946d9f 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_http.h
+++ b/native_client_sdk/src/libraries/nacl_io/mount_http.h
@@ -11,12 +11,8 @@
#include "nacl_io/pepper_interface.h"
#include "nacl_io/typed_mount_factory.h"
-class MountHttpMock;
-
namespace nacl_io {
-class MountNode;
-
std::string NormalizeHeaderKey(const std::string& s);
class MountHttp : public Mount {
@@ -44,6 +40,8 @@ class MountHttp : public Mount {
Error LoadManifest(const std::string& path, char** out_manifest);
Error ParseManifest(const char *text);
+ NodeMap_t* GetNodeCacheForTesting() { return &node_cache_; }
+
private:
// Gets the URL to fetch for |path|.
// |path| is relative to the mount point for the HTTP filesystem.
@@ -59,7 +57,6 @@ class MountHttp : public Mount {
friend class TypedMountFactory<MountHttp>;
friend class MountNodeHttp;
- friend class ::MountHttpMock;
};
} // namespace nacl_io
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_http.cc b/native_client_sdk/src/libraries/nacl_io/mount_node_http.cc
index 5a65d41..25135e4 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_http.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_http.cc
@@ -151,14 +151,14 @@ void MountNodeHttp::SetCachedSize(off_t size) {
stat_.st_size = size;
}
-Error MountNodeHttp::FSync() { return ENOSYS; }
+Error MountNodeHttp::FSync() { return EACCES; }
Error MountNodeHttp::GetDents(size_t offs,
struct dirent* pdir,
size_t count,
int* out_bytes) {
*out_bytes = 0;
- return ENOSYS;
+ return EACCES;
}
Error MountNodeHttp::GetStat(struct stat* stat) {
@@ -193,10 +193,8 @@ Error MountNodeHttp::GetStat(struct stat* stat) {
SetCachedSize(static_cast<off_t>(entity_length));
} else if (cache_content_ && !has_cached_size_) {
error = DownloadToCache();
- // TODO(binji): this error should not be dropped, but it requires a bit
- // of a refactor of the tests. See crbug.com/245431
- // if (error)
- // return error;
+ if (error)
+ return error;
} else {
// Don't use SetCachedSize here -- it is actually unknown.
stat_.st_size = 0;
@@ -230,13 +228,13 @@ Error MountNodeHttp::Read(const HandleAttr& attr,
return error;
}
- return ReadPartialFromCache(attr.offs, buf, count, out_bytes);
+ return ReadPartialFromCache(attr, buf, count, out_bytes);
}
- return DownloadPartial(attr.offs, buf, count, out_bytes);
+ return DownloadPartial(attr, buf, count, out_bytes);
}
-Error MountNodeHttp::FTruncate(off_t size) { return ENOSYS; }
+Error MountNodeHttp::FTruncate(off_t size) { return EACCES; }
Error MountNodeHttp::Write(const HandleAttr& attr,
const void* buf,
@@ -244,7 +242,7 @@ Error MountNodeHttp::Write(const HandleAttr& attr,
int* out_bytes) {
// TODO(binji): support POST?
*out_bytes = 0;
- return ENOSYS;
+ return EACCES;
}
Error MountNodeHttp::GetSize(size_t* out_size) {
@@ -342,6 +340,8 @@ Error MountNodeHttp::OpenUrl(const char* method,
*out_response_headers =
ParseHeaders(response_headers_str, response_headers_length);
+ var_interface->Release(response_headers_var);
+
return 0;
}
@@ -404,23 +404,25 @@ Error MountNodeHttp::DownloadToCache() {
}
}
-Error MountNodeHttp::ReadPartialFromCache(size_t offs,
+Error MountNodeHttp::ReadPartialFromCache(const HandleAttr& attr,
void* buf,
int count,
int* out_bytes) {
*out_bytes = 0;
+ size_t size = cached_data_.size();
- if (offs > cached_data_.size())
- return EINVAL;
+ if (attr.offs + count > size)
+ count = size - attr.offs;
- count = std::min(count, static_cast<int>(cached_data_.size() - offs));
- memcpy(buf, &cached_data_.data()[offs], count);
+ if (count <= 0)
+ return 0;
+ memcpy(buf, &cached_data_.data()[attr.offs], count);
*out_bytes = count;
return 0;
}
-Error MountNodeHttp::DownloadPartial(size_t offs,
+Error MountNodeHttp::DownloadPartial(const HandleAttr& attr,
void* buf,
size_t count,
int* out_bytes) {
@@ -433,8 +435,8 @@ Error MountNodeHttp::DownloadPartial(size_t offs,
snprintf(&buffer[0],
sizeof(buffer),
"bytes=%" PRIuS "-%" PRIuS,
- offs,
- offs + count - 1);
+ attr.offs,
+ attr.offs + count - 1);
headers["Range"] = buffer;
PP_Resource loader;
@@ -462,12 +464,12 @@ Error MountNodeHttp::DownloadPartial(size_t offs,
// No partial result, read everything starting from the part we care about.
size_t content_length;
if (ParseContentLength(response_headers, &content_length)) {
- if (offs >= content_length)
+ if (attr.offs >= content_length)
return EINVAL;
// Clamp count, if trying to read past the end of the file.
- if (offs + count > content_length) {
- count = content_length - offs;
+ if (attr.offs + count > content_length) {
+ count = content_length - attr.offs;
}
}
} else if (statuscode == STATUSCODE_PARTIAL_CONTENT) {
@@ -476,7 +478,7 @@ Error MountNodeHttp::DownloadPartial(size_t offs,
size_t entity_length;
if (ParseContentRange(
response_headers, &read_start, &read_end, &entity_length)) {
- if (read_start > offs || read_start > read_end) {
+ if (read_start > attr.offs || read_start > read_end) {
// If this error occurs, the server is returning bogus values.
return EINVAL;
}
@@ -488,14 +490,14 @@ Error MountNodeHttp::DownloadPartial(size_t offs,
// exactly what we asked for. This can happen even when the server
// returns 200 -- the cache may return 206 in this case, but not modify
// the headers.
- read_start = offs;
+ read_start = attr.offs;
}
}
- if (read_start < offs) {
+ if (read_start < attr.offs) {
// We aren't yet at the location where we want to start reading. Read into
// our dummy buffer until then.
- size_t bytes_to_read = offs - read_start;
+ size_t bytes_to_read = attr.offs - read_start;
if (buffer_.size() < bytes_to_read)
buffer_.resize(std::min(bytes_to_read, MAX_READ_BUFFER_SIZE));
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_http.h b/native_client_sdk/src/libraries/nacl_io/mount_node_http.h
index 0e083b4..9ea5f14 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_http.h
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_http.h
@@ -52,11 +52,14 @@ class MountNodeHttp : public MountNode {
StringMap_t* out_response_headers);
Error DownloadToCache();
- Error ReadPartialFromCache(size_t offs,
+ Error ReadPartialFromCache(const HandleAttr& attr,
void* buf,
int count,
int* out_bytes);
- Error DownloadPartial(size_t offs, void* buf, size_t count, int* out_bytes);
+ Error DownloadPartial(const HandleAttr& attr,
+ void* buf,
+ size_t count,
+ int* out_bytes);
Error DownloadToBuffer(PP_Resource loader,
void* buf,
int count,
diff --git a/native_client_sdk/src/tests/nacl_io_test/example.dsc b/native_client_sdk/src/tests/nacl_io_test/example.dsc
index 059c389..908ef17 100644
--- a/native_client_sdk/src/tests/nacl_io_test/example.dsc
+++ b/native_client_sdk/src/tests/nacl_io_test/example.dsc
@@ -12,6 +12,8 @@
'fake_core_interface.h',
'fake_pepper_interface_html5fs.cc',
'fake_pepper_interface_html5fs.h',
+ 'fake_pepper_interface_url_loader.cc',
+ 'fake_pepper_interface_url_loader.h',
'fake_resource_manager.cc',
'fake_resource_manager.h',
'fake_var_interface.cc',
diff --git a/native_client_sdk/src/tests/nacl_io_test/fake_pepper_interface_html5fs.h b/native_client_sdk/src/tests/nacl_io_test/fake_pepper_interface_html5fs.h
index 6e10844..9903c30 100644
--- a/native_client_sdk/src/tests/nacl_io_test/fake_pepper_interface_html5fs.h
+++ b/native_client_sdk/src/tests/nacl_io_test/fake_pepper_interface_html5fs.h
@@ -98,29 +98,29 @@ class FakeFileIoInterface : public nacl_io::FileIoInterface {
public:
explicit FakeFileIoInterface(FakeCoreInterface* core_interface);
- PP_Resource Create(PP_Resource instance);
- int32_t Open(PP_Resource file_io,
- PP_Resource file_ref,
- int32_t open_flags,
- PP_CompletionCallback callback);
- int32_t Query(PP_Resource file_io,
- PP_FileInfo* info,
- PP_CompletionCallback callback);
- int32_t Read(PP_Resource file_io,
- int64_t offset,
- char* buffer,
- int32_t bytes_to_read,
- PP_CompletionCallback callback);
- int32_t Write(PP_Resource file_io,
- int64_t offset,
- const char* buffer,
- int32_t bytes_to_write,
- PP_CompletionCallback callback);
- int32_t SetLength(PP_Resource file_io,
- int64_t length,
- PP_CompletionCallback callback);
- int32_t Flush(PP_Resource file_io, PP_CompletionCallback callback);
- void Close(PP_Resource file_io);
+ virtual PP_Resource Create(PP_Resource instance);
+ virtual int32_t Open(PP_Resource file_io,
+ PP_Resource file_ref,
+ int32_t open_flags,
+ PP_CompletionCallback callback);
+ virtual int32_t Query(PP_Resource file_io,
+ PP_FileInfo* info,
+ PP_CompletionCallback callback);
+ virtual int32_t Read(PP_Resource file_io,
+ int64_t offset,
+ char* buffer,
+ int32_t bytes_to_read,
+ PP_CompletionCallback callback);
+ virtual int32_t Write(PP_Resource file_io,
+ int64_t offset,
+ const char* buffer,
+ int32_t bytes_to_write,
+ PP_CompletionCallback callback);
+ virtual int32_t SetLength(PP_Resource file_io,
+ int64_t length,
+ PP_CompletionCallback callback);
+ virtual int32_t Flush(PP_Resource file_io, PP_CompletionCallback callback);
+ virtual void Close(PP_Resource file_io);
private:
FakeCoreInterface* core_interface_; // Weak reference.
@@ -133,18 +133,18 @@ class FakeFileRefInterface : public nacl_io::FileRefInterface {
FakeFileRefInterface(FakeCoreInterface* core_interface,
FakeVarInterface* var_interface);
- PP_Resource Create(PP_Resource file_system, const char* path);
- PP_Var GetName(PP_Resource file_ref);
- int32_t MakeDirectory(PP_Resource directory_ref,
- PP_Bool make_ancestors,
+ virtual PP_Resource Create(PP_Resource file_system, const char* path);
+ virtual PP_Var GetName(PP_Resource file_ref);
+ virtual int32_t MakeDirectory(PP_Resource directory_ref,
+ PP_Bool make_ancestors,
+ PP_CompletionCallback callback);
+ virtual int32_t Delete(PP_Resource file_ref, PP_CompletionCallback callback);
+ virtual int32_t Query(PP_Resource file_ref,
+ PP_FileInfo* info,
PP_CompletionCallback callback);
- int32_t Delete(PP_Resource file_ref, PP_CompletionCallback callback);
- int32_t Query(PP_Resource file_ref,
- PP_FileInfo* info,
- PP_CompletionCallback callback);
- int32_t ReadDirectoryEntries(PP_Resource file_ref,
- const PP_ArrayOutput& output,
- PP_CompletionCallback callback);
+ virtual int32_t ReadDirectoryEntries(PP_Resource file_ref,
+ const PP_ArrayOutput& output,
+ PP_CompletionCallback callback);
private:
FakeCoreInterface* core_interface_; // Weak reference.
@@ -157,10 +157,10 @@ class FakeFileSystemInterface : public nacl_io::FileSystemInterface {
public:
FakeFileSystemInterface(FakeCoreInterface* core_interface);
- PP_Resource Create(PP_Instance instance, PP_FileSystemType type);
- int32_t Open(PP_Resource file_system,
- int64_t expected_size,
- PP_CompletionCallback callback);
+ virtual PP_Resource Create(PP_Instance instance, PP_FileSystemType type);
+ virtual int32_t Open(PP_Resource file_system,
+ int64_t expected_size,
+ PP_CompletionCallback callback);
private:
FakeCoreInterface* core_interface_; // Weak reference.
diff --git a/native_client_sdk/src/tests/nacl_io_test/fake_pepper_interface_url_loader.cc b/native_client_sdk/src/tests/nacl_io_test/fake_pepper_interface_url_loader.cc
new file mode 100644
index 0000000..1b6b92c
--- /dev/null
+++ b/native_client_sdk/src/tests/nacl_io_test/fake_pepper_interface_url_loader.cc
@@ -0,0 +1,502 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "fake_pepper_interface_url_loader.h"
+
+#include <string.h>
+#include <strings.h>
+
+#include <algorithm>
+#include <sstream>
+
+#include "gtest/gtest.h"
+
+namespace {
+
+bool GetHeaderValue(const std::string& headers, const std::string& key,
+ std::string* out_value) {
+ out_value->clear();
+
+ size_t offset = 0;
+ while (offset != std::string::npos) {
+ // Find the next colon; this separates the key from the value.
+ size_t colon = headers.find(':', offset);
+ if (colon == std::string::npos)
+ return false;
+
+ // Find the newline; this separates the value from the next header.
+ size_t newline = headers.find('\n', offset);
+ if (strncasecmp(key.c_str(), &headers.data()[offset], key.size()) != 0) {
+ // Key doesn't match, skip to next header.
+ offset = newline;
+ continue;
+ }
+
+ // Key matches, extract value. First, skip leading spaces.
+ size_t nonspace = headers.find_first_not_of(' ', colon + 1);
+ if (nonspace == std::string::npos)
+ return false;
+
+ out_value->assign(headers, nonspace, newline - nonspace);
+ return true;
+ }
+
+ return false;
+}
+
+class FakeInstanceResource : public FakeResource {
+ public:
+ FakeInstanceResource() : server_template(NULL) {}
+ static const char* classname() { return "FakeInstanceResource"; }
+
+ FakeURLLoaderServer* server_template; // Weak reference.
+};
+
+class FakeURLLoaderResource : public FakeResource {
+ public:
+ FakeURLLoaderResource()
+ : manager(NULL),
+ server(NULL),
+ entity(NULL),
+ response(0),
+ read_offset(0) {}
+
+ virtual void Destroy() {
+ EXPECT_TRUE(manager != NULL);
+ if (response != 0)
+ manager->Release(response);
+ }
+
+ static const char* classname() { return "FakeURLLoaderResource"; }
+
+ FakeResourceManager* manager; // Weak reference.
+ FakeURLLoaderServer* server; // Weak reference.
+ FakeURLLoaderEntity* entity; // Weak reference.
+ PP_Resource response;
+ size_t read_offset;
+ size_t read_end;
+};
+
+class FakeURLRequestInfoResource : public FakeResource {
+ public:
+ FakeURLRequestInfoResource() {}
+ static const char* classname() { return "FakeURLRequestInfoResource"; }
+
+ std::string url;
+ std::string method;
+ std::string headers;
+};
+
+class FakeURLResponseInfoResource : public FakeResource {
+ public:
+ FakeURLResponseInfoResource() : status_code(0) {}
+ static const char* classname() { return "FakeURLResponseInfoResource"; }
+
+ int status_code;
+ std::string url;
+ std::string headers;
+};
+
+// Helper function to call the completion callback if it is defined (an
+// asynchronous call), or return the result directly if it isn't (a synchronous
+// call).
+//
+// Use like this:
+// if (<some error condition>)
+// return RunCompletionCallback(callback, PP_ERROR_FUBAR);
+//
+// /* Everything worked OK */
+// return RunCompletionCallback(callback, PP_OK);
+int32_t RunCompletionCallback(PP_CompletionCallback* callback, int32_t result) {
+ if (callback->func) {
+ PP_RunCompletionCallback(callback, result);
+ return PP_OK_COMPLETIONPENDING;
+ }
+ return result;
+}
+
+} // namespace
+
+FakeURLLoaderEntity::FakeURLLoaderEntity(const std::string& body)
+ : body_(body) {}
+
+FakeURLLoaderServer::FakeURLLoaderServer()
+ : max_read_size_(0), send_content_length_(false), allow_partial_(false) {}
+
+void FakeURLLoaderServer::Clear() {
+ entity_map_.clear();
+}
+
+bool FakeURLLoaderServer::AddEntity(const std::string& url,
+ const std::string& body,
+ FakeURLLoaderEntity** out_entity) {
+ EntityMap::iterator iter = entity_map_.find(url);
+ if (iter != entity_map_.end()) {
+ if (out_entity)
+ *out_entity = NULL;
+ return false;
+ }
+
+ FakeURLLoaderEntity entity(body);
+ std::pair<EntityMap::iterator, bool> result =
+ entity_map_.insert(EntityMap::value_type(url, entity));
+
+ EXPECT_EQ(true, result.second);
+ if (out_entity)
+ *out_entity = &result.first->second;
+ return true;
+}
+
+bool FakeURLLoaderServer::AddError(const std::string& url,
+ int http_status_code) {
+ ErrorMap::iterator iter = error_map_.find(url);
+ if (iter != error_map_.end())
+ return false;
+
+ error_map_[url] = http_status_code;
+ return true;
+}
+
+FakeURLLoaderEntity* FakeURLLoaderServer::GetEntity(const std::string& url) {
+ EntityMap::iterator iter = entity_map_.find(url);
+ if (iter == entity_map_.end())
+ return NULL;
+ return &iter->second;
+}
+
+int FakeURLLoaderServer::GetError(const std::string& url) {
+ ErrorMap::iterator iter = error_map_.find(url);
+ if (iter != error_map_.end())
+ return 0;
+ return iter->second;
+}
+
+FakeURLLoaderInterface::FakeURLLoaderInterface(
+ FakeCoreInterface* core_interface)
+ : core_interface_(core_interface) {}
+
+PP_Resource FakeURLLoaderInterface::Create(PP_Instance instance) {
+ FakeInstanceResource* instance_resource =
+ core_interface_->resource_manager()->Get<FakeInstanceResource>(instance);
+ if (instance_resource == NULL)
+ return PP_ERROR_BADRESOURCE;
+
+ FakeURLLoaderResource* loader_resource = new FakeURLLoaderResource;
+ loader_resource->manager = core_interface_->resource_manager();
+ loader_resource->server =
+ new FakeURLLoaderServer(*instance_resource->server_template);
+
+ return CREATE_RESOURCE(core_interface_->resource_manager(),
+ FakeURLLoaderResource,
+ loader_resource);
+}
+
+int32_t FakeURLLoaderInterface::Open(PP_Resource loader,
+ PP_Resource request_info,
+ PP_CompletionCallback callback) {
+ FakeURLLoaderResource* loader_resource =
+ core_interface_->resource_manager()->Get<FakeURLLoaderResource>(loader);
+ if (loader_resource == NULL)
+ return PP_ERROR_BADRESOURCE;
+
+ FakeURLRequestInfoResource* request_info_resource =
+ core_interface_->resource_manager()->Get<FakeURLRequestInfoResource>(
+ request_info);
+ if (request_info_resource == NULL)
+ return PP_ERROR_BADRESOURCE;
+
+ // Create a response resource.
+ FakeURLResponseInfoResource* response = new FakeURLResponseInfoResource;
+ loader_resource->response =
+ CREATE_RESOURCE(core_interface_->resource_manager(),
+ FakeURLResponseInfoResource,
+ response);
+
+ loader_resource->entity = NULL;
+ loader_resource->read_offset = 0;
+ loader_resource->read_end = 0;
+
+ // Get the URL from the request info.
+ std::string url = request_info_resource->url;
+ std::string method = request_info_resource->method;
+
+ response->url = url;
+ // TODO(binji): allow this to be set?
+ response->headers.clear();
+
+ // Check the error map first, to see if this URL should produce an error.
+ EXPECT_TRUE(NULL != loader_resource->server);
+ int http_status_code = loader_resource->server->GetError(url);
+ if (http_status_code != 0) {
+ // Got an error, return that in the response.
+ response->status_code = http_status_code;
+ } else {
+ // Look up the URL in the loader resource entity map.
+ FakeURLLoaderEntity* entity = loader_resource->server->GetEntity(url);
+ response->status_code = entity ? 200 : 404;
+
+ if (method == "GET") {
+ loader_resource->entity = entity;
+ } else if (method == "HEAD") {
+ // Do nothing, we only set the status code.
+ } else {
+ response->status_code = 405; // Method not allowed.
+ }
+
+ if (entity != NULL) {
+ size_t content_length = entity->body().size();
+ loader_resource->read_end = content_length;
+
+ if (loader_resource->server->send_content_length()) {
+ std::ostringstream ss;
+ ss << "Content-Length: " << content_length << "\n";
+ response->headers += ss.str();
+ }
+
+ if (loader_resource->server->allow_partial()) {
+ std::string headers = request_info_resource->headers;
+ std::string range;
+ if (GetHeaderValue(headers, "Range", &range)) {
+ // We don't support all range requests, just bytes=<num>-<num>
+ int lo;
+ int hi;
+ if (sscanf(range.c_str(), "bytes=%d-%d", &lo, &hi) == 2) {
+ // The range is a closed interval; e.g. 0-10 is 11 bytes. We'll
+ // store it as a half-open interval instead--it's more natural in
+ // C that way.
+ loader_resource->read_offset = lo;
+ loader_resource->read_end = hi + 1;
+
+ // Also add a "Content-Range" response header.
+ std::ostringstream ss;
+ ss << "Content-Range: "
+ << lo << "-" << hi << "/" << content_length << "\n";
+ response->headers += ss.str();
+
+ response->status_code = 206; // Partial content
+ } else {
+ // Couldn't parse the range.
+ response->status_code = 416; // Request range not satisfiable.
+ }
+ }
+ }
+ }
+ }
+
+ // Call the callback.
+ return RunCompletionCallback(&callback, PP_OK);
+}
+
+PP_Resource FakeURLLoaderInterface::GetResponseInfo(PP_Resource loader) {
+ FakeURLLoaderResource* loader_resource =
+ core_interface_->resource_manager()->Get<FakeURLLoaderResource>(loader);
+ if (loader_resource == NULL)
+ return 0;
+
+ // Returned resources have an implicit AddRef.
+ core_interface_->resource_manager()->AddRef(loader_resource->response);
+ return loader_resource->response;
+}
+
+int32_t FakeURLLoaderInterface::ReadResponseBody(
+ PP_Resource loader,
+ void* buffer,
+ int32_t bytes_to_read,
+ PP_CompletionCallback callback) {
+ FakeURLLoaderResource* loader_resource =
+ core_interface_->resource_manager()->Get<FakeURLLoaderResource>(loader);
+ if (loader_resource == NULL)
+ return PP_ERROR_BADRESOURCE;
+
+ if (loader_resource->entity == NULL)
+ // TODO(binji): figure out the correct error here.
+ return PP_ERROR_FAILED;
+
+ const std::string& body = loader_resource->entity->body();
+ size_t offset = loader_resource->read_offset;
+ // Never read more than is available.
+ size_t max_readable = std::max<size_t>(0, body.length() - offset);
+ size_t server_max_read_size = loader_resource->server->max_read_size();
+ // Allow the test to specify how much the "server" should send in each call
+ // to ReadResponseBody. A max_read_size of 0 means read as much as the
+ // buffer will allow.
+ if (server_max_read_size != 0)
+ max_readable = std::min(max_readable, server_max_read_size);
+
+ bytes_to_read = std::min(static_cast<size_t>(bytes_to_read), max_readable);
+ memcpy(buffer, &body.data()[offset], bytes_to_read);
+ loader_resource->read_offset += bytes_to_read;
+
+ return RunCompletionCallback(&callback, bytes_to_read);
+}
+
+void FakeURLLoaderInterface::Close(PP_Resource loader) {
+ FakeURLLoaderResource* loader_resource =
+ core_interface_->resource_manager()->Get<FakeURLLoaderResource>(loader);
+ if (loader_resource == NULL)
+ return;
+
+ core_interface_->resource_manager()->Release(loader_resource->response);
+
+ loader_resource->server = NULL;
+ loader_resource->entity = NULL;
+ loader_resource->response = 0;
+ loader_resource->read_offset = 0;
+}
+
+FakeURLRequestInfoInterface::FakeURLRequestInfoInterface(
+ FakeCoreInterface* core_interface,
+ FakeVarInterface* var_interface)
+ : core_interface_(core_interface), var_interface_(var_interface) {}
+
+PP_Resource FakeURLRequestInfoInterface::Create(PP_Instance instance) {
+ FakeInstanceResource* instance_resource =
+ core_interface_->resource_manager()->Get<FakeInstanceResource>(instance);
+ if (instance_resource == NULL)
+ return PP_ERROR_BADRESOURCE;
+
+ return CREATE_RESOURCE(core_interface_->resource_manager(),
+ FakeURLRequestInfoResource,
+ new FakeURLRequestInfoResource);
+}
+
+PP_Bool FakeURLRequestInfoInterface::SetProperty(PP_Resource request,
+ PP_URLRequestProperty property,
+ PP_Var value) {
+ FakeURLRequestInfoResource* request_resource =
+ core_interface_->resource_manager()->Get<FakeURLRequestInfoResource>(
+ request);
+ if (request_resource == NULL)
+ return PP_FALSE;
+
+ switch (property) {
+ case PP_URLREQUESTPROPERTY_URL: {
+ if (value.type != PP_VARTYPE_STRING)
+ return PP_FALSE;
+
+ uint32_t len;
+ const char* url = var_interface_->VarToUtf8(value, &len);
+ if (url == NULL)
+ return PP_FALSE;
+
+ request_resource->url = url;
+ var_interface_->Release(value);
+ return PP_TRUE;
+ }
+ case PP_URLREQUESTPROPERTY_METHOD: {
+ if (value.type != PP_VARTYPE_STRING)
+ return PP_FALSE;
+
+ uint32_t len;
+ const char* url = var_interface_->VarToUtf8(value, &len);
+ if (url == NULL)
+ return PP_FALSE;
+
+ request_resource->method = url;
+ var_interface_->Release(value);
+ return PP_TRUE;
+ }
+ case PP_URLREQUESTPROPERTY_HEADERS: {
+ if (value.type != PP_VARTYPE_STRING)
+ return PP_FALSE;
+
+ uint32_t len;
+ const char* url = var_interface_->VarToUtf8(value, &len);
+ if (url == NULL)
+ return PP_FALSE;
+
+ request_resource->headers = url;
+ var_interface_->Release(value);
+ return PP_TRUE;
+ }
+ case PP_URLREQUESTPROPERTY_ALLOWCROSSORIGINREQUESTS: {
+ if (value.type != PP_VARTYPE_BOOL)
+ return PP_FALSE;
+ // Throw the value away for now. TODO(binji): add tests for this.
+ return PP_TRUE;
+ }
+ case PP_URLREQUESTPROPERTY_ALLOWCREDENTIALS: {
+ if (value.type != PP_VARTYPE_BOOL)
+ return PP_FALSE;
+ // Throw the value away for now. TODO(binji): add tests for this.
+ return PP_TRUE;
+ }
+ default:
+ EXPECT_TRUE(false) << "Unimplemented property " << property
+ << " in "
+ "FakeURLRequestInfoInterface::SetProperty";
+ return PP_FALSE;
+ }
+}
+
+FakeURLResponseInfoInterface::FakeURLResponseInfoInterface(
+ FakeCoreInterface* core_interface,
+ FakeVarInterface* var_interface)
+ : core_interface_(core_interface), var_interface_(var_interface) {}
+
+PP_Var FakeURLResponseInfoInterface::GetProperty(
+ PP_Resource response,
+ PP_URLResponseProperty property) {
+ FakeURLResponseInfoResource* response_resource =
+ core_interface_->resource_manager()->Get<FakeURLResponseInfoResource>(
+ response);
+ if (response_resource == NULL)
+ return PP_Var();
+
+ switch (property) {
+ case PP_URLRESPONSEPROPERTY_URL:
+ return var_interface_->VarFromUtf8(response_resource->url.data(),
+ response_resource->url.size());
+
+ case PP_URLRESPONSEPROPERTY_STATUSCODE:
+ return PP_MakeInt32(response_resource->status_code);
+
+ case PP_URLRESPONSEPROPERTY_HEADERS:
+ return var_interface_->VarFromUtf8(response_resource->headers.data(),
+ response_resource->headers.size());
+ default:
+ EXPECT_TRUE(false) << "Unimplemented property " << property
+ << " in "
+ "FakeURLResponseInfoInterface::GetProperty";
+ return PP_Var();
+ }
+}
+
+FakePepperInterfaceURLLoader::FakePepperInterfaceURLLoader()
+ : url_loader_interface_(&core_interface_),
+ url_request_info_interface_(&core_interface_, &var_interface_),
+ url_response_info_interface_(&core_interface_, &var_interface_) {
+ FakeInstanceResource* instance_resource = new FakeInstanceResource;
+ instance_resource->server_template = &server_template_;
+ instance_ = CREATE_RESOURCE(core_interface_.resource_manager(),
+ FakeInstanceResource,
+ instance_resource);
+}
+
+FakePepperInterfaceURLLoader::~FakePepperInterfaceURLLoader() {
+ core_interface_.ReleaseResource(instance_);
+}
+
+nacl_io::CoreInterface* FakePepperInterfaceURLLoader::GetCoreInterface() {
+ return &core_interface_;
+}
+
+nacl_io::VarInterface* FakePepperInterfaceURLLoader::GetVarInterface() {
+ return &var_interface_;
+}
+
+nacl_io::URLLoaderInterface*
+FakePepperInterfaceURLLoader::GetURLLoaderInterface() {
+ return &url_loader_interface_;
+}
+
+nacl_io::URLRequestInfoInterface*
+FakePepperInterfaceURLLoader::GetURLRequestInfoInterface() {
+ return &url_request_info_interface_;
+}
+
+nacl_io::URLResponseInfoInterface*
+FakePepperInterfaceURLLoader::GetURLResponseInfoInterface() {
+ return &url_response_info_interface_;
+}
diff --git a/native_client_sdk/src/tests/nacl_io_test/fake_pepper_interface_url_loader.h b/native_client_sdk/src/tests/nacl_io_test/fake_pepper_interface_url_loader.h
new file mode 100644
index 0000000..5945d13
--- /dev/null
+++ b/native_client_sdk/src/tests/nacl_io_test/fake_pepper_interface_url_loader.h
@@ -0,0 +1,151 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef LIBRARIES_NACL_IO_TEST_FAKE_PEPPER_INTERFACE_URL_LOADER_H_
+#define LIBRARIES_NACL_IO_TEST_FAKE_PEPPER_INTERFACE_URL_LOADER_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "fake_core_interface.h"
+#include "fake_var_interface.h"
+#include "nacl_io/pepper_interface_dummy.h"
+#include "sdk_util/macros.h"
+
+class FakeURLLoaderEntity {
+ public:
+ explicit FakeURLLoaderEntity(const std::string& body);
+
+ const std::string& body() const { return body_; }
+
+ private:
+ std::string body_;
+};
+
+class FakeURLLoaderServer {
+ public:
+ FakeURLLoaderServer();
+
+ void Clear();
+ bool AddEntity(const std::string& url,
+ const std::string& body,
+ FakeURLLoaderEntity** out_entity);
+ bool AddError(const std::string& url,
+ int http_status_code);
+ FakeURLLoaderEntity* GetEntity(const std::string& url);
+ // Returns 0 if the url is not in the error map.
+ int GetError(const std::string& url);
+
+ // The maximum number of bytes that ReadResponseBody will send. If 0, then
+ // send as many as are requested.
+ void set_max_read_size(size_t max_read_size) {
+ max_read_size_ = max_read_size;
+ }
+
+ // Whether to add the "Content-Length" header.
+ void set_send_content_length(bool send_content_length) {
+ send_content_length_ = send_content_length;
+ }
+
+ // Whether to allow partial reads (via the "Range" request header).
+ void set_allow_partial(bool allow_partial) { allow_partial_ = allow_partial; }
+
+ size_t max_read_size() const { return max_read_size_; }
+ bool send_content_length() const { return send_content_length_; }
+ bool allow_partial() const { return allow_partial_; }
+
+ private:
+ typedef std::map<std::string, FakeURLLoaderEntity> EntityMap;
+ typedef std::map<std::string, int> ErrorMap;
+ EntityMap entity_map_;
+ ErrorMap error_map_;
+ size_t max_read_size_;
+ bool send_content_length_;
+ bool allow_partial_;
+};
+
+class FakeURLLoaderInterface : public nacl_io::URLLoaderInterface {
+ public:
+ explicit FakeURLLoaderInterface(FakeCoreInterface* core_interface);
+
+ virtual PP_Resource Create(PP_Instance instance);
+ virtual int32_t Open(PP_Resource loader,
+ PP_Resource request_info,
+ PP_CompletionCallback callback);
+ virtual PP_Resource GetResponseInfo(PP_Resource loader);
+ virtual int32_t ReadResponseBody(PP_Resource loader,
+ void* buffer,
+ int32_t bytes_to_read,
+ PP_CompletionCallback callback);
+ virtual void Close(PP_Resource loader);
+
+ private:
+ FakeCoreInterface* core_interface_; // Weak reference.
+
+ DISALLOW_COPY_AND_ASSIGN(FakeURLLoaderInterface);
+};
+
+class FakeURLRequestInfoInterface : public nacl_io::URLRequestInfoInterface {
+ public:
+ FakeURLRequestInfoInterface(FakeCoreInterface* core_interface,
+ FakeVarInterface* var_interface);
+
+ virtual PP_Resource Create(PP_Instance instance);
+ virtual PP_Bool SetProperty(PP_Resource request,
+ PP_URLRequestProperty property,
+ PP_Var value);
+
+ private:
+ FakeCoreInterface* core_interface_; // Weak reference.
+ FakeVarInterface* var_interface_; // Weak reference.
+
+ DISALLOW_COPY_AND_ASSIGN(FakeURLRequestInfoInterface);
+};
+
+class FakeURLResponseInfoInterface : public nacl_io::URLResponseInfoInterface {
+ public:
+ FakeURLResponseInfoInterface(FakeCoreInterface* core_interface,
+ FakeVarInterface* var_interface);
+
+ virtual PP_Var GetProperty(PP_Resource response,
+ PP_URLResponseProperty property);
+
+ private:
+ FakeCoreInterface* core_interface_; // Weak reference.
+ FakeVarInterface* var_interface_; // Weak reference.
+
+ DISALLOW_COPY_AND_ASSIGN(FakeURLResponseInfoInterface);
+};
+
+class FakePepperInterfaceURLLoader : public nacl_io::PepperInterfaceDummy {
+ public:
+ FakePepperInterfaceURLLoader();
+ FakePepperInterfaceURLLoader(const FakeURLLoaderServer& server);
+ ~FakePepperInterfaceURLLoader();
+
+ virtual PP_Instance GetInstance() { return instance_; }
+ virtual nacl_io::CoreInterface* GetCoreInterface();
+ virtual nacl_io::VarInterface* GetVarInterface();
+ virtual nacl_io::URLLoaderInterface* GetURLLoaderInterface();
+ virtual nacl_io::URLRequestInfoInterface* GetURLRequestInfoInterface();
+ virtual nacl_io::URLResponseInfoInterface* GetURLResponseInfoInterface();
+
+ FakeURLLoaderServer* server_template() { return &server_template_; }
+
+ private:
+ void Init();
+
+ FakeCoreInterface core_interface_;
+ FakeVarInterface var_interface_;
+ FakeURLLoaderServer server_template_;
+ FakeURLLoaderInterface url_loader_interface_;
+ FakeURLRequestInfoInterface url_request_info_interface_;
+ FakeURLResponseInfoInterface url_response_info_interface_;
+ PP_Instance instance_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakePepperInterfaceURLLoader);
+};
+
+#endif // LIBRARIES_NACL_IO_TEST_FAKE_PEPPER_INTERFACE_URL_LOADER_H_
diff --git a/native_client_sdk/src/tests/nacl_io_test/fake_resource_manager.cc b/native_client_sdk/src/tests/nacl_io_test/fake_resource_manager.cc
index b87248f..ccb2993 100644
--- a/native_client_sdk/src/tests/nacl_io_test/fake_resource_manager.cc
+++ b/native_client_sdk/src/tests/nacl_io_test/fake_resource_manager.cc
@@ -57,7 +57,7 @@ void FakeResourceManager::AddRef(PP_Resource handle) {
}
void FakeResourceManager::Release(PP_Resource handle) {
- AUTO_LOCK(lock_);
+ sdk_util::AutoLock lock(lock_);
ResourceMap::iterator iter = resource_map_.find(handle);
ASSERT_NE(resource_map_.end(), iter) << "Releasing unknown resource "
<< handle;
@@ -70,6 +70,18 @@ void FakeResourceManager::Release(PP_Resource handle) {
<< resource_tracker->file() << ":"
<< resource_tracker->line();
resource_tracker->Release();
+ // It's OK to access the tracker when its refcount is zero; it doesn't
+ // actually destroy the object until the manager is destroyed.
+ if (resource_tracker->ref_count() == 0) {
+ // Remove the resource from this tracker.
+ FakeResource* resource = resource_tracker->Pass();
+ // Release the lock before we call Destroy; resources can call
+ // FakeResourceManager::Release(), which will deadlock if we are already
+ // holding the lock.
+ lock.Unlock();
+
+ resource->Destroy();
+ }
}
FakeResourceTracker* FakeResourceManager::Get(PP_Resource handle) {
diff --git a/native_client_sdk/src/tests/nacl_io_test/fake_resource_manager.h b/native_client_sdk/src/tests/nacl_io_test/fake_resource_manager.h
index f545e91..33c4444 100644
--- a/native_client_sdk/src/tests/nacl_io_test/fake_resource_manager.h
+++ b/native_client_sdk/src/tests/nacl_io_test/fake_resource_manager.h
@@ -55,6 +55,14 @@ class FakeResourceTracker {
void Release() { sdk_util::AtomicAddFetch(&ref_count_, -1); }
int32_t ref_count() const { return ref_count_; }
+ // Give up ownership of this resource. It is the responsibility of the caller
+ // to delete this FakeResource.
+ FakeResource* Pass() {
+ FakeResource* result = resource_;
+ resource_ = NULL;
+ return result;
+ }
+
template <typename T>
T* resource() {
if (!CheckType(T::classname()))
@@ -63,6 +71,8 @@ class FakeResourceTracker {
return static_cast<T*>(resource_);
}
+ FakeResource* resource() { return resource_; }
+
const char* classname() const { return classname_; }
const char* file() const { return file_; }
int line() const { return line_; }
@@ -82,7 +92,11 @@ class FakeResourceTracker {
class FakeResource {
public:
FakeResource() {}
+ // Called when the resource is destroyed. For debugging purposes, this does
+ // not happen until the resource manager is destroyed.
virtual ~FakeResource() {}
+ // Called when the last reference to the resource is released.
+ virtual void Destroy() {}
private:
DISALLOW_COPY_AND_ASSIGN(FakeResource);
@@ -94,6 +108,6 @@ inline T* FakeResourceManager::Get(PP_Resource handle) {
}
#define CREATE_RESOURCE(MANAGER, TYPE, RESOURCE) \
- (MANAGER)->Create(RESOURCE, #TYPE, __FILE__, __LINE__)
+ (MANAGER)->Create((RESOURCE), #TYPE, __FILE__, __LINE__)
#endif // LIBRARIES_NACL_IO_TEST_FAKE_RESOURCE_MANAGER_H_
diff --git a/native_client_sdk/src/tests/nacl_io_test/mount_http_test.cc b/native_client_sdk/src/tests/nacl_io_test/mount_http_test.cc
index 8ec27db..79a2fcb 100644
--- a/native_client_sdk/src/tests/nacl_io_test/mount_http_test.cc
+++ b/native_client_sdk/src/tests/nacl_io_test/mount_http_test.cc
@@ -10,36 +10,26 @@
#include <sys/stat.h>
#include <sys/types.h>
-#include "mock_util.h"
+#include "fake_pepper_interface_url_loader.h"
+
#include "nacl_io/kernel_handle.h"
#include "nacl_io/kernel_intercept.h"
#include "nacl_io/mount_http.h"
#include "nacl_io/mount_node_dir.h"
#include "nacl_io/osdirent.h"
#include "nacl_io/osunistd.h"
-#include "pepper_interface_mock.h"
using namespace nacl_io;
-using ::testing::_;
-using ::testing::DoAll;
-using ::testing::Mock;
-using ::testing::Return;
-using ::testing::SetArgPointee;
-using ::testing::StrEq;
+namespace {
-class MountHttpMock : public MountHttp {
+class MountHttpForTesting : public MountHttp {
public:
- MountHttpMock(StringMap_t map, PepperInterfaceMock* ppapi) {
+ MountHttpForTesting(StringMap_t map, PepperInterface* ppapi) {
EXPECT_EQ(0, Init(1, map, ppapi));
}
- ~MountHttpMock() {
- Destroy();
- }
-
- NodeMap_t& GetMap() { return node_cache_; }
-
+ using MountHttp::GetNodeCacheForTesting;
using MountHttp::ParseManifest;
using MountHttp::FindOrCreateDir;
};
@@ -47,103 +37,186 @@ class MountHttpMock : public MountHttp {
class MountHttpTest : public ::testing::Test {
public:
MountHttpTest();
- ~MountHttpTest();
protected:
- PepperInterfaceMock ppapi_;
- MountHttpMock* mnt_;
+ FakePepperInterfaceURLLoader ppapi_;
+ MountHttpForTesting mnt_;
+};
+
+MountHttpTest::MountHttpTest() : mnt_(StringMap_t(), &ppapi_) {}
+
+StringMap_t StringMap_NoCache() {
+ StringMap_t smap;
+ smap["cache_content"] = "false";
+ return smap;
+}
+
+class MountHttpNoCacheTest : public ::testing::Test {
+ public:
+ MountHttpNoCacheTest();
- static const PP_Instance instance_ = 123;
+ protected:
+ FakePepperInterfaceURLLoader ppapi_;
+ MountHttpForTesting mnt_;
};
-MountHttpTest::MountHttpTest()
- : ppapi_(instance_),
- mnt_(NULL) {
+MountHttpNoCacheTest::MountHttpNoCacheTest() :
+ mnt_(StringMap_NoCache(), &ppapi_) {}
+
+} // namespace
+
+
+TEST_F(MountHttpTest, Access) {
+ ASSERT_TRUE(ppapi_.server_template()->AddEntity("foo", "", NULL));
+
+ ASSERT_EQ(0, mnt_.Access(Path("/foo"), R_OK));
+ ASSERT_EQ(EACCES, mnt_.Access(Path("/foo"), W_OK));
+ ASSERT_EQ(EACCES, mnt_.Access(Path("/foo"), X_OK));
+ ASSERT_EQ(ENOENT, mnt_.Access(Path("/bar"), F_OK));
+}
+
+TEST_F(MountHttpTest, Read) {
+ const char contents[] = "contents";
+ ASSERT_TRUE(ppapi_.server_template()->AddEntity("file", contents, NULL));
+
+ ScopedMountNode node;
+ ASSERT_EQ(0, mnt_.Open(Path("/file"), O_RDONLY, &node));
+
+ char buffer[10] = {0};
+ int bytes_read = 0;
+ HandleAttr attr;
+ EXPECT_EQ(0, node->Read(attr, &buffer[0], sizeof(buffer), &bytes_read));
+ EXPECT_EQ(strlen(contents), bytes_read);
+ EXPECT_STREQ(contents, buffer);
+
+ // Read nothing past the end of the file.
+ attr.offs = 100;
+ EXPECT_EQ(0, node->Read(attr, &buffer[0], sizeof(buffer), &bytes_read));
+ EXPECT_EQ(0, bytes_read);
+
+ // Read part of the data.
+ attr.offs = 4;
+ EXPECT_EQ(0, node->Read(attr, &buffer[0], sizeof(buffer), &bytes_read));
+ ASSERT_EQ(strlen(contents) - 4, bytes_read);
+ buffer[bytes_read] = 0;
+ EXPECT_STREQ("ents", buffer);
+}
+
+TEST_F(MountHttpTest, Write) {
+ const char contents[] = "contents";
+ ASSERT_TRUE(ppapi_.server_template()->AddEntity("file", contents, NULL));
+
+ ScopedMountNode node;
+ ASSERT_EQ(0, mnt_.Open(Path("/file"), O_WRONLY, &node));
+
+ // Writing always fails.
+ HandleAttr attr;
+ attr.offs = 3;
+ int bytes_written = 1; // Set to a non-zero value.
+ EXPECT_EQ(EACCES, node->Write(attr, "struct", 6, &bytes_written));
+ EXPECT_EQ(0, bytes_written);
}
-MountHttpTest::~MountHttpTest() {
- delete mnt_;
+TEST_F(MountHttpTest, GetStat) {
+ const char contents[] = "contents";
+ ASSERT_TRUE(ppapi_.server_template()->AddEntity("file", contents, NULL));
+
+ ScopedMountNode node;
+ ASSERT_EQ(0, mnt_.Open(Path("/file"), O_RDONLY, &node));
+
+ struct stat statbuf;
+ EXPECT_EQ(0, node->GetStat(&statbuf));
+ EXPECT_EQ(S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH,
+ statbuf.st_mode);
+ EXPECT_EQ(strlen(contents), statbuf.st_size);
+ // These are not currently set.
+ EXPECT_EQ(0, statbuf.st_atime);
+ EXPECT_EQ(0, statbuf.st_ctime);
+ EXPECT_EQ(0, statbuf.st_mtime);
}
+TEST_F(MountHttpTest, FTruncate) {
+ const char contents[] = "contents";
+ ASSERT_TRUE(ppapi_.server_template()->AddEntity("file", contents, NULL));
-TEST_F(MountHttpTest, MountEmpty) {
- StringMap_t args;
- mnt_ = new MountHttpMock(args, &ppapi_);
+ ScopedMountNode node;
+ ASSERT_EQ(0, mnt_.Open(Path("/file"), O_RDWR, &node));
+ EXPECT_EQ(EACCES, node->FTruncate(4));
}
-TEST_F(MountHttpTest, Mkdir) {
+TEST(MountHttpDirTest, Mkdir) {
StringMap_t args;
- mnt_ = new MountHttpMock(args, &ppapi_);
+ MountHttpForTesting mnt(args, NULL);
char manifest[] = "-r-- 123 /mydir/foo\n-rw- 234 /thatdir/bar\n";
- EXPECT_EQ(0, mnt_->ParseManifest(manifest));
+ ASSERT_EQ(0, mnt.ParseManifest(manifest));
// mkdir of existing directories should give "File exists".
- EXPECT_EQ(EEXIST, mnt_->Mkdir(Path("/"), 0));
- EXPECT_EQ(EEXIST, mnt_->Mkdir(Path("/mydir"), 0));
+ EXPECT_EQ(EEXIST, mnt.Mkdir(Path("/"), 0));
+ EXPECT_EQ(EEXIST, mnt.Mkdir(Path("/mydir"), 0));
// mkdir of non-existent directories should give "Permission denied".
- EXPECT_EQ(EACCES, mnt_->Mkdir(Path("/non_existent"), 0));
+ EXPECT_EQ(EACCES, mnt.Mkdir(Path("/non_existent"), 0));
}
-TEST_F(MountHttpTest, Rmdir) {
+TEST(MountHttpDirTest, Rmdir) {
StringMap_t args;
- mnt_ = new MountHttpMock(args, &ppapi_);
+ MountHttpForTesting mnt(args, NULL);
char manifest[] = "-r-- 123 /mydir/foo\n-rw- 234 /thatdir/bar\n";
- EXPECT_EQ(0, mnt_->ParseManifest(manifest));
+ ASSERT_EQ(0, mnt.ParseManifest(manifest));
// Rmdir on existing dirs should give "Permission Denied"
- EXPECT_EQ(EACCES, mnt_->Rmdir(Path("/")));
- EXPECT_EQ(EACCES, mnt_->Rmdir(Path("/mydir")));
+ EXPECT_EQ(EACCES, mnt.Rmdir(Path("/")));
+ EXPECT_EQ(EACCES, mnt.Rmdir(Path("/mydir")));
// Rmdir on existing files should give "Not a direcotory"
- EXPECT_EQ(ENOTDIR, mnt_->Rmdir(Path("/mydir/foo")));
+ EXPECT_EQ(ENOTDIR, mnt.Rmdir(Path("/mydir/foo")));
// Rmdir on non-existent files should give "No such file or directory"
- EXPECT_EQ(ENOENT, mnt_->Rmdir(Path("/non_existent")));
+ EXPECT_EQ(ENOENT, mnt.Rmdir(Path("/non_existent")));
}
-TEST_F(MountHttpTest, Unlink) {
+TEST(MountHttpDirTest, Unlink) {
StringMap_t args;
- mnt_ = new MountHttpMock(args, &ppapi_);
+ MountHttpForTesting mnt(args, NULL);
char manifest[] = "-r-- 123 /mydir/foo\n-rw- 234 /thatdir/bar\n";
- EXPECT_EQ(0, mnt_->ParseManifest(manifest));
+ ASSERT_EQ(0, mnt.ParseManifest(manifest));
// Unlink of existing files should give "Permission Denied"
- EXPECT_EQ(EACCES, mnt_->Unlink(Path("/mydir/foo")));
+ EXPECT_EQ(EACCES, mnt.Unlink(Path("/mydir/foo")));
// Unlink of existing directory should give "Is a directory"
- EXPECT_EQ(EISDIR, mnt_->Unlink(Path("/mydir")));
+ EXPECT_EQ(EISDIR, mnt.Unlink(Path("/mydir")));
// Unlink of non-existent files should give "No such file or directory"
- EXPECT_EQ(ENOENT, mnt_->Unlink(Path("/non_existent")));
+ EXPECT_EQ(ENOENT, mnt.Unlink(Path("/non_existent")));
}
-TEST_F(MountHttpTest, Remove) {
+TEST(MountHttpDirTest, Remove) {
StringMap_t args;
- mnt_ = new MountHttpMock(args, &ppapi_);
+ MountHttpForTesting mnt(args, NULL);
char manifest[] = "-r-- 123 /mydir/foo\n-rw- 234 /thatdir/bar\n";
- EXPECT_EQ(0, mnt_->ParseManifest(manifest));
+ ASSERT_EQ(0, mnt.ParseManifest(manifest));
// Remove of existing files should give "Permission Denied"
- EXPECT_EQ(EACCES, mnt_->Remove(Path("/mydir/foo")));
+ EXPECT_EQ(EACCES, mnt.Remove(Path("/mydir/foo")));
// Remove of existing directory should give "Permission Denied"
- EXPECT_EQ(EACCES, mnt_->Remove(Path("/mydir")));
+ EXPECT_EQ(EACCES, mnt.Remove(Path("/mydir")));
// Unlink of non-existent files should give "No such file or directory"
- EXPECT_EQ(ENOENT, mnt_->Remove(Path("/non_existent")));
+ EXPECT_EQ(ENOENT, mnt.Remove(Path("/non_existent")));
}
-TEST_F(MountHttpTest, ParseManifest) {
+TEST(MountHttpDirTest, ParseManifest) {
StringMap_t args;
size_t result_size = 0;
- mnt_ = new MountHttpMock(args, &ppapi_);
+ MountHttpForTesting mnt(args, NULL);
// Multiple consecutive newlines or spaces should be ignored.
char manifest[] = "-r-- 123 /mydir/foo\n\n-rw- 234 /thatdir/bar\n";
- EXPECT_EQ(0, mnt_->ParseManifest(manifest));
+ ASSERT_EQ(0, mnt.ParseManifest(manifest));
ScopedMountNode root;
- EXPECT_EQ(0, mnt_->FindOrCreateDir(Path("/"), &root));
+ EXPECT_EQ(0, mnt.FindOrCreateDir(Path("/"), &root));
ASSERT_NE((MountNode*)NULL, root.get());
EXPECT_EQ(2, root->ChildCount());
ScopedMountNode dir;
- EXPECT_EQ(0, mnt_->FindOrCreateDir(Path("/mydir"), &dir));
+ EXPECT_EQ(0, mnt.FindOrCreateDir(Path("/mydir"), &dir));
ASSERT_NE((MountNode*)NULL, dir.get());
EXPECT_EQ(1, dir->ChildCount());
- MountNode* node = mnt_->GetMap()["/mydir/foo"].get();
+ MountNode* node = (*mnt.GetNodeCacheForTesting())["/mydir/foo"].get();
EXPECT_NE((MountNode*)NULL, node);
EXPECT_EQ(0, node->GetSize(&result_size));
EXPECT_EQ(123, result_size);
@@ -151,10 +224,10 @@ TEST_F(MountHttpTest, ParseManifest) {
// Since these files are cached thanks to the manifest, we can open them
// without accessing the PPAPI URL API.
ScopedMountNode foo;
- EXPECT_EQ(0, mnt_->Open(Path("/mydir/foo"), O_RDONLY, &foo));
+ ASSERT_EQ(0, mnt.Open(Path("/mydir/foo"), O_RDONLY, &foo));
ScopedMountNode bar;
- EXPECT_EQ(0, mnt_->Open(Path("/thatdir/bar"), O_RDWR, &bar));
+ ASSERT_EQ(0, mnt.Open(Path("/thatdir/bar"), O_RDWR, &bar));
struct stat sfoo;
struct stat sbar;
@@ -169,459 +242,88 @@ TEST_F(MountHttpTest, ParseManifest) {
EXPECT_EQ(S_IFREG | S_IRALL | S_IWALL, sbar.st_mode);
}
+TEST_F(MountHttpNoCacheTest, OpenAndClose) {
+ const char contents[] = "contents";
+ ASSERT_TRUE(ppapi_.server_template()->AddEntity("file", contents, NULL));
-class MountHttpNodeTest : public MountHttpTest {
- public:
- MountHttpNodeTest();
- virtual void TearDown();
-
- void SetMountArgs(const StringMap_t& args);
- void ExpectOpen(const char* method);
- void ExpectHeaders(const char* headers);
- void OpenNode();
- void SetResponse(int status_code, const char* headers);
- // Set a response code, but expect the request to fail. Certain function calls
- // expected by SetResponse are not expected here.
- void SetResponseExpectFail(int status_code, const char* headers);
- void SetResponseBody(const char* body);
- void ResetMocks();
-
- protected:
- MountHttpMock* mnt_;
- ScopedMountNode node_;
-
- CoreInterfaceMock* core_;
- VarInterfaceMock* var_;
- URLLoaderInterfaceMock* loader_;
- URLRequestInfoInterfaceMock* request_;
- URLResponseInfoInterfaceMock* response_;
- size_t response_body_offset_;
-
- static const char path_[];
- static const char rel_path_[];
- static const PP_Resource loader_resource_ = 235;
- static const PP_Resource request_resource_ = 236;
- static const PP_Resource response_resource_ = 237;
-};
-
-// static
-const char MountHttpNodeTest::path_[] = "/foo";
-// static
-const char MountHttpNodeTest::rel_path_[] = "foo";
-
-MountHttpNodeTest::MountHttpNodeTest()
- : mnt_(NULL),
- node_(NULL) {
-}
-
-static PP_Var MakeString(PP_Resource resource) {
- PP_Var result = { PP_VARTYPE_STRING, 0, {PP_FALSE} };
- result.value.as_id = resource;
- return result;
-}
-
-void MountHttpNodeTest::SetMountArgs(const StringMap_t& args) {
- mnt_ = new MountHttpMock(args, &ppapi_);
-}
-
-void MountHttpNodeTest::ExpectOpen(const char* method) {
- core_ = ppapi_.GetCoreInterface();
- loader_ = ppapi_.GetURLLoaderInterface();
- request_ = ppapi_.GetURLRequestInfoInterface();
- response_ = ppapi_.GetURLResponseInfoInterface();
- var_ = ppapi_.GetVarInterface();
-
- ON_CALL(*request_, SetProperty(request_resource_, _, _))
- .WillByDefault(Return(PP_TRUE));
- ON_CALL(*var_, VarFromUtf8(_, _)).WillByDefault(Return(PP_MakeUndefined()));
-
- EXPECT_CALL(*loader_, Create(instance_)).WillOnce(Return(loader_resource_));
- EXPECT_CALL(*request_, Create(instance_)).WillOnce(Return(request_resource_));
-
- PP_Var var_head = MakeString(345);
- PP_Var var_url = MakeString(346);
- EXPECT_CALL(*var_, VarFromUtf8(StrEq(method), _)).WillOnce(Return(var_head));
- EXPECT_CALL(*var_, VarFromUtf8(StrEq(rel_path_), _))
- .WillOnce(Return(var_url));
-
-#define EXPECT_SET_PROPERTY(NAME, VAR) \
- EXPECT_CALL(*request_, SetProperty(request_resource_, NAME, VAR))
-
- EXPECT_SET_PROPERTY(PP_URLREQUESTPROPERTY_URL, IsEqualToVar(var_url));
- EXPECT_SET_PROPERTY(PP_URLREQUESTPROPERTY_METHOD, IsEqualToVar(var_head));
- EXPECT_SET_PROPERTY(PP_URLREQUESTPROPERTY_ALLOWCROSSORIGINREQUESTS, _);
- EXPECT_SET_PROPERTY(PP_URLREQUESTPROPERTY_ALLOWCREDENTIALS, _);
-
-#undef EXPECT_SET_PROPERTY
-
- EXPECT_CALL(*loader_, Open(loader_resource_, request_resource_, _))
- .WillOnce(DoAll(CallCallback<2>(int32_t(PP_OK)),
- Return(int32_t(PP_OK_COMPLETIONPENDING))));
- EXPECT_CALL(*loader_, GetResponseInfo(loader_resource_))
- .WillOnce(Return(response_resource_));
-
- EXPECT_CALL(*core_, ReleaseResource(loader_resource_));
- EXPECT_CALL(*core_, ReleaseResource(request_resource_));
- EXPECT_CALL(*core_, ReleaseResource(response_resource_));
-}
-
-void MountHttpNodeTest::ExpectHeaders(const char* headers) {
- PP_Var var_headers = MakeString(347);
- var_ = ppapi_.GetVarInterface();
- EXPECT_CALL(*var_, VarFromUtf8(StrEq(headers), _))
- .WillOnce(Return(var_headers));
-
- EXPECT_CALL(*request_, SetProperty(request_resource_,
- PP_URLREQUESTPROPERTY_HEADERS,
- IsEqualToVar(var_headers))).Times(1);
+ ScopedMountNode node;
+ ASSERT_EQ(0, mnt_.Open(Path("/file"), O_RDONLY, &node));
}
-void MountHttpNodeTest::SetResponse(int status_code, const char* headers) {
- ON_CALL(*response_, GetProperty(response_resource_, _))
- .WillByDefault(Return(PP_MakeUndefined()));
-
- PP_Var var_headers = MakeString(348);
- EXPECT_CALL(*response_,
- GetProperty(response_resource_,
- PP_URLRESPONSEPROPERTY_STATUSCODE))
- .WillOnce(Return(PP_MakeInt32(status_code)));
- EXPECT_CALL(*response_,
- GetProperty(response_resource_, PP_URLRESPONSEPROPERTY_HEADERS))
- .WillOnce(Return(var_headers));
- EXPECT_CALL(*var_, VarToUtf8(IsEqualToVar(var_headers), _))
- .WillOnce(DoAll(SetArgPointee<1>(strlen(headers)),
- Return(headers)));
-}
-
-void MountHttpNodeTest::SetResponseExpectFail(int status_code,
- const char* headers) {
- ON_CALL(*response_, GetProperty(response_resource_, _))
- .WillByDefault(Return(PP_MakeUndefined()));
-
- EXPECT_CALL(*response_,
- GetProperty(response_resource_,
- PP_URLRESPONSEPROPERTY_STATUSCODE))
- .WillOnce(Return(PP_MakeInt32(status_code)));
+TEST_F(MountHttpNoCacheTest, OpenAndCloseNotFound) {
+ ScopedMountNode node;
+ ASSERT_EQ(ENOENT, mnt_.Open(Path("/file"), O_RDONLY, &node));
}
-ACTION_P3(ReadResponseBodyAction, offset, body, body_length) {
- char* buf = static_cast<char*>(arg1);
- size_t read_length = arg2;
- PP_CompletionCallback callback = arg3;
- if (*offset >= body_length)
- return 0;
-
- read_length = std::min(read_length, body_length - *offset);
- memcpy(buf, body + *offset, read_length);
- *offset += read_length;
-
- // Also call the callback.
- if (callback.func)
- (*callback.func)(callback.user_data, PP_OK);
-
- return read_length;
-}
+TEST_F(MountHttpNoCacheTest, OpenAndCloseServerError) {
+ ASSERT_TRUE(ppapi_.server_template()->AddError("file", 500));
-void MountHttpNodeTest::SetResponseBody(const char* body) {
- response_body_offset_ = 0;
- EXPECT_CALL(*loader_, ReadResponseBody(loader_resource_, _, _, _))
- .WillRepeatedly(ReadResponseBodyAction(
- &response_body_offset_, body, strlen(body)));
-}
-
-void MountHttpNodeTest::OpenNode() {
- ASSERT_EQ(0, mnt_->Open(Path(path_), O_RDONLY, &node_));
- ASSERT_NE((MountNode*)NULL, node_.get());
-}
-
-void MountHttpNodeTest::ResetMocks() {
- Mock::VerifyAndClearExpectations(&ppapi_);
- Mock::VerifyAndClearExpectations(loader_);
- Mock::VerifyAndClearExpectations(request_);
- Mock::VerifyAndClearExpectations(response_);
- Mock::VerifyAndClearExpectations(var_);
-}
-
-void MountHttpNodeTest::TearDown() {
- node_.reset();
- delete mnt_;
-}
-
-// TODO(binji): These tests are all broken now. In another CL, I'll reimplement
-// these tests using an HTTP fake.
-TEST_F(MountHttpNodeTest, DISABLED_OpenAndCloseNoCache) {
- StringMap_t smap;
- smap["cache_content"] = "false";
- SetMountArgs(StringMap_t());
- ExpectOpen("HEAD");
- ExpectHeaders("");
- SetResponse(200, "");
- OpenNode();
-}
-
-TEST_F(MountHttpNodeTest, DISABLED_OpenAndCloseNotFound) {
- StringMap_t smap;
- smap["cache_content"] = "false";
- SetMountArgs(StringMap_t());
- ExpectOpen("HEAD");
- ExpectHeaders("");
- SetResponseExpectFail(404, "");
- ASSERT_EQ(ENOENT, mnt_->Open(Path(path_), O_RDONLY, &node_));
-}
-
-TEST_F(MountHttpNodeTest, DISABLED_OpenAndCloseServerError) {
- StringMap_t smap;
- smap["cache_content"] = "false";
- SetMountArgs(StringMap_t());
- ExpectOpen("HEAD");
- ExpectHeaders("");
- SetResponseExpectFail(500, "");
- ASSERT_EQ(EIO, mnt_->Open(Path(path_), O_RDONLY, &node_));
+ ScopedMountNode node;
+ ASSERT_EQ(ENOENT, mnt_.Open(Path("/file"), O_RDONLY, &node));
}
-TEST_F(MountHttpNodeTest, DISABLED_GetStat) {
- StringMap_t smap;
- smap["cache_content"] = "false";
- SetMountArgs(StringMap_t());
- ExpectOpen("HEAD");
- ExpectHeaders("");
- SetResponse(200, "Content-Length: 42\n");
- OpenNode();
-
- struct stat stat;
- EXPECT_EQ(0, node_->GetStat(&stat));
- EXPECT_EQ(42, stat.st_size);
-}
+TEST_F(MountHttpNoCacheTest, GetSize) {
+ const char contents[] = "contents";
+ ASSERT_TRUE(ppapi_.server_template()->AddEntity("file", contents, NULL));
+ ppapi_.server_template()->set_send_content_length(true);
-TEST_F(MountHttpNodeTest, DISABLED_Access) {
- StringMap_t smap;
- smap["cache_content"] = "false";
- SetMountArgs(StringMap_t());
- ExpectOpen("HEAD");
- ExpectHeaders("");
- SetResponse(200, "");
- ASSERT_EQ(0, mnt_->Access(Path(path_), R_OK));
+ ScopedMountNode node;
+ struct stat statbuf;
+ ASSERT_EQ(0, mnt_.Open(Path("/file"), O_RDONLY, &node));
+ EXPECT_EQ(0, node->GetStat(&statbuf));
+ EXPECT_EQ(strlen(contents), statbuf.st_size);
}
-TEST_F(MountHttpNodeTest, DISABLED_AccessWrite) {
- StringMap_t smap;
- smap["cache_content"] = "false";
- SetMountArgs(StringMap_t());
- ExpectOpen("HEAD");
- ExpectHeaders("");
- SetResponse(200, "");
- ASSERT_EQ(EACCES, mnt_->Access(Path(path_), W_OK));
-}
+TEST_F(MountHttpNoCacheTest, Access) {
+ ASSERT_TRUE(ppapi_.server_template()->AddEntity("file", "", NULL));
-TEST_F(MountHttpNodeTest, DISABLED_AccessNotFound) {
- StringMap_t smap;
- smap["cache_content"] = "false";
- SetMountArgs(StringMap_t());
- ExpectOpen("HEAD");
- ExpectHeaders("");
- SetResponseExpectFail(404, "");
- ASSERT_EQ(ENOENT, mnt_->Access(Path(path_), R_OK));
+ ASSERT_EQ(0, mnt_.Access(Path("/file"), R_OK));
+ ASSERT_EQ(EACCES, mnt_.Access(Path("/file"), W_OK));
+ ASSERT_EQ(ENOENT, mnt_.Access(Path("/bar"), R_OK));
}
-TEST_F(MountHttpNodeTest, DISABLED_ReadCached) {
- size_t result_size = 0;
- int result_bytes = 0;
-
- SetMountArgs(StringMap_t());
- ExpectOpen("HEAD");
- ExpectHeaders("");
- SetResponse(200, "Content-Length: 42\n");
- OpenNode();
- ResetMocks();
-
- EXPECT_EQ(0, node_->GetSize(&result_size));
- EXPECT_EQ(42, result_size);
-
- char buf[10];
- memset(&buf[0], 0, sizeof(buf));
-
- ExpectOpen("GET");
- ExpectHeaders("");
- SetResponse(200, "Content-Length: 42\n");
- SetResponseBody("Here is some response text. And some more.");
- HandleAttr attr;
- EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes));
- EXPECT_STREQ("Here is s", &buf[0]);
- ResetMocks();
+TEST_F(MountHttpNoCacheTest, ReadPartial) {
+ const char contents[] = "0123456789abcdefghi";
+ ASSERT_TRUE(ppapi_.server_template()->AddEntity("file", contents, NULL));
+ ppapi_.server_template()->set_allow_partial(true);
- // Further reads should be cached.
- EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes));
- EXPECT_STREQ("Here is s", &buf[0]);
- attr.offs = 10;
- EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes));
- EXPECT_STREQ("me respon", &buf[0]);
-
- EXPECT_EQ(0, node_->GetSize(&result_size));
- EXPECT_EQ(42, result_size);
-}
-
-TEST_F(MountHttpNodeTest, DISABLED_ReadCachedNoContentLength) {
- size_t result_size = 0;
int result_bytes = 0;
- SetMountArgs(StringMap_t());
- ExpectOpen("HEAD");
- ExpectHeaders("");
- SetResponse(200, "");
- OpenNode();
- ResetMocks();
-
- ExpectOpen("GET");
- ExpectHeaders("");
- SetResponse(200, ""); // No Content-Length response here.
- SetResponseBody("Here is some response text. And some more.");
-
- // GetSize will Read() because it didn't get the content length from the HEAD
- // request.
- EXPECT_EQ(0, node_->GetSize(&result_size));
- EXPECT_EQ(42, result_size);
-
char buf[10];
memset(&buf[0], 0, sizeof(buf));
+ ScopedMountNode node;
+ ASSERT_EQ(0, mnt_.Open(Path("/file"), O_RDONLY, &node));
HandleAttr attr;
- EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes));
- EXPECT_STREQ("Here is s", &buf[0]);
- ResetMocks();
+ EXPECT_EQ(0, node->Read(attr, buf, sizeof(buf) - 1, &result_bytes));
+ EXPECT_EQ(sizeof(buf) - 1, result_bytes);
+ EXPECT_STREQ("012345678", &buf[0]);
- // Further reads should be cached.
- EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes));
- EXPECT_STREQ("Here is s", &buf[0]);
attr.offs = 10;
- EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes));
- EXPECT_STREQ("me respon", &buf[0]);
-
- EXPECT_EQ(0, node_->GetSize(&result_size));
- EXPECT_EQ(42, result_size);
-}
-
-TEST_F(MountHttpNodeTest, DISABLED_ReadCachedUnderrun) {
- size_t result_size = 0;
- int result_bytes = 0;
-
- SetMountArgs(StringMap_t());
- ExpectOpen("HEAD");
- ExpectHeaders("");
- SetResponse(200, "Content-Length: 100\n");
- OpenNode();
- ResetMocks();
-
- EXPECT_EQ(0, node_->GetSize(&result_size));
- EXPECT_EQ(100, result_size);
-
- char buf[10];
- memset(&buf[0], 0, sizeof(buf));
-
- ExpectOpen("GET");
- ExpectHeaders("");
- SetResponse(200, "Content-Length: 100\n");
- SetResponseBody("abcdefghijklmnopqrstuvwxyz");
- HandleAttr attr;
- EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes));
+ EXPECT_EQ(0, node->Read(attr, buf, sizeof(buf) - 1, &result_bytes));
EXPECT_EQ(sizeof(buf) - 1, result_bytes);
EXPECT_STREQ("abcdefghi", &buf[0]);
- ResetMocks();
-
- EXPECT_EQ(0, node_->GetSize(&result_size));
- EXPECT_EQ(26, result_size);
}
-TEST_F(MountHttpNodeTest, DISABLED_ReadCachedOverrun) {
- size_t result_size = 0;
- int result_bytes = 0;
-
- SetMountArgs(StringMap_t());
- ExpectOpen("HEAD");
- ExpectHeaders("");
- SetResponse(200, "Content-Length: 15\n");
- OpenNode();
- ResetMocks();
-
- EXPECT_EQ(0, node_->GetSize(&result_size));
- EXPECT_EQ(15, result_size);
-
- char buf[10];
- memset(&buf[0], 0, sizeof(buf));
+TEST_F(MountHttpNoCacheTest, ReadPartialNoServerSupport) {
+ const char contents[] = "0123456789abcdefghi";
+ ASSERT_TRUE(ppapi_.server_template()->AddEntity("file", contents, NULL));
+ ppapi_.server_template()->set_allow_partial(false);
- ExpectOpen("GET");
- ExpectHeaders("");
- SetResponse(200, "Content-Length: 15\n");
- SetResponseBody("01234567890123456789");
- HandleAttr attr;
- attr.offs = 10;
- EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes));
- EXPECT_EQ(5, result_bytes);
- EXPECT_STREQ("01234", &buf[0]);
- ResetMocks();
-
- EXPECT_EQ(0, node_->GetSize(&result_size));
- EXPECT_EQ(15, result_size);
-}
-
-TEST_F(MountHttpNodeTest, DISABLED_ReadPartial) {
int result_bytes = 0;
- StringMap_t args;
- args["cache_content"] = "false";
- SetMountArgs(args);
- ExpectOpen("HEAD");
- ExpectHeaders("");
- SetResponse(200, "");
- OpenNode();
- ResetMocks();
-
char buf[10];
memset(&buf[0], 0, sizeof(buf));
- ExpectOpen("GET");
- ExpectHeaders("Range: bytes=0-8\n");
- SetResponse(206, "Content-Length: 9\nContent-Range: bytes=0-8\n");
- SetResponseBody("012345678");
+ ScopedMountNode node;
+ ASSERT_EQ(0, mnt_.Open(Path("/file"), O_RDONLY, &node));
HandleAttr attr;
- EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes));
+ EXPECT_EQ(0, node->Read(attr, buf, sizeof(buf) - 1, &result_bytes));
EXPECT_EQ(sizeof(buf) - 1, result_bytes);
EXPECT_STREQ("012345678", &buf[0]);
- ResetMocks();
- // Another read is another request.
- ExpectOpen("GET");
- ExpectHeaders("Range: bytes=10-18\n");
- SetResponse(206, "Content-Length: 9\nContent-Range: bytes=10-18\n");
- SetResponseBody("abcdefghi");
attr.offs = 10;
- EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes));
+ EXPECT_EQ(0, node->Read(attr, buf, sizeof(buf) - 1, &result_bytes));
EXPECT_EQ(sizeof(buf) - 1, result_bytes);
EXPECT_STREQ("abcdefghi", &buf[0]);
}
-
-TEST_F(MountHttpNodeTest, DISABLED_ReadPartialNoServerSupport) {
- int result_bytes = 0;
-
- StringMap_t args;
- args["cache_content"] = "false";
- SetMountArgs(args);
- ExpectOpen("HEAD");
- ExpectHeaders("");
- SetResponse(200, "");
- OpenNode();
- ResetMocks();
-
- char buf[10];
- memset(&buf[0], 0, sizeof(buf));
-
- ExpectOpen("GET");
- ExpectHeaders("Range: bytes=10-18\n");
- SetResponse(200, "Content-Length: 20\n");
- SetResponseBody("0123456789abcdefghij");
- HandleAttr attr;
- attr.offs = 10;
- EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes));
- EXPECT_EQ(sizeof(buf) - 1, result_bytes);
- EXPECT_STREQ("abcdefghi", &buf[0]);
-}
-