OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <fcntl.h> | 5 #include <fcntl.h> |
6 #include <gmock/gmock.h> | 6 #include <gmock/gmock.h> |
7 #include <ppapi/c/ppb_file_io.h> | 7 #include <ppapi/c/ppb_file_io.h> |
8 #include <ppapi/c/pp_errors.h> | 8 #include <ppapi/c/pp_errors.h> |
9 #include <ppapi/c/pp_instance.h> | 9 #include <ppapi/c/pp_instance.h> |
10 #include <sys/stat.h> | 10 #include <sys/stat.h> |
11 #include <sys/types.h> | 11 #include <sys/types.h> |
12 | 12 |
13 #include "mock_util.h" | 13 #include "fake_pepper_interface_url_loader.h" |
14 | |
14 #include "nacl_io/kernel_handle.h" | 15 #include "nacl_io/kernel_handle.h" |
15 #include "nacl_io/kernel_intercept.h" | 16 #include "nacl_io/kernel_intercept.h" |
16 #include "nacl_io/mount_http.h" | 17 #include "nacl_io/mount_http.h" |
17 #include "nacl_io/mount_node_dir.h" | 18 #include "nacl_io/mount_node_dir.h" |
18 #include "nacl_io/osdirent.h" | 19 #include "nacl_io/osdirent.h" |
19 #include "nacl_io/osunistd.h" | 20 #include "nacl_io/osunistd.h" |
20 #include "pepper_interface_mock.h" | |
21 | 21 |
22 using namespace nacl_io; | 22 using namespace nacl_io; |
23 | 23 |
24 using ::testing::_; | 24 namespace { |
25 using ::testing::DoAll; | |
26 using ::testing::Mock; | |
27 using ::testing::Return; | |
28 using ::testing::SetArgPointee; | |
29 using ::testing::StrEq; | |
30 | 25 |
31 class MountHttpMock : public MountHttp { | 26 class MountHttpForTesting : public MountHttp { |
32 public: | 27 public: |
33 MountHttpMock(StringMap_t map, PepperInterfaceMock* ppapi) { | 28 MountHttpForTesting(StringMap_t map, PepperInterface* ppapi) { |
34 EXPECT_EQ(0, Init(1, map, ppapi)); | 29 EXPECT_EQ(0, Init(1, map, ppapi)); |
35 } | 30 } |
36 | 31 |
37 ~MountHttpMock() { | 32 using MountHttp::GetNodeCacheForTesting; |
38 Destroy(); | |
39 } | |
40 | |
41 NodeMap_t& GetMap() { return node_cache_; } | |
42 | |
43 using MountHttp::ParseManifest; | 33 using MountHttp::ParseManifest; |
44 using MountHttp::FindOrCreateDir; | 34 using MountHttp::FindOrCreateDir; |
45 }; | 35 }; |
46 | 36 |
47 class MountHttpTest : public ::testing::Test { | 37 class MountHttpTest : public ::testing::Test { |
48 public: | 38 public: |
49 MountHttpTest(); | 39 MountHttpTest(); |
50 ~MountHttpTest(); | |
51 | 40 |
52 protected: | 41 protected: |
53 PepperInterfaceMock ppapi_; | 42 FakePepperInterfaceURLLoader ppapi_; |
54 MountHttpMock* mnt_; | 43 MountHttpForTesting mnt_; |
55 | |
56 static const PP_Instance instance_ = 123; | |
57 }; | 44 }; |
58 | 45 |
59 MountHttpTest::MountHttpTest() | 46 MountHttpTest::MountHttpTest() : mnt_(StringMap_t(), &ppapi_) {} |
60 : ppapi_(instance_), | 47 |
61 mnt_(NULL) { | 48 StringMap_t StringMap_NoCache() { |
49 StringMap_t smap; | |
50 smap["cache_content"] = "false"; | |
51 return smap; | |
62 } | 52 } |
63 | 53 |
64 MountHttpTest::~MountHttpTest() { | 54 class MountHttpNoCacheTest : public ::testing::Test { |
65 delete mnt_; | 55 public: |
56 MountHttpNoCacheTest(); | |
57 | |
58 protected: | |
59 FakePepperInterfaceURLLoader ppapi_; | |
60 MountHttpForTesting mnt_; | |
61 }; | |
62 | |
63 MountHttpNoCacheTest::MountHttpNoCacheTest() : | |
64 mnt_(StringMap_NoCache(), &ppapi_) {} | |
65 | |
66 } // namespace | |
67 | |
68 | |
69 TEST_F(MountHttpTest, Access) { | |
70 EXPECT_TRUE(ppapi_.server_template()->AddEntity("foo", "", NULL)); | |
71 | |
72 ASSERT_EQ(0, mnt_.Access(Path("/foo"), R_OK)); | |
73 ASSERT_EQ(EACCES, mnt_.Access(Path("/foo"), W_OK)); | |
74 ASSERT_EQ(EACCES, mnt_.Access(Path("/foo"), X_OK)); | |
75 ASSERT_EQ(ENOENT, mnt_.Access(Path("/bar"), F_OK)); | |
66 } | 76 } |
67 | 77 |
78 TEST_F(MountHttpTest, Read) { | |
79 const char contents[] = "contents"; | |
80 EXPECT_TRUE(ppapi_.server_template()->AddEntity("file", contents, NULL)); | |
68 | 81 |
69 TEST_F(MountHttpTest, MountEmpty) { | 82 ScopedMountNode node; |
70 StringMap_t args; | 83 ASSERT_EQ(0, mnt_.Open(Path("/file"), O_RDONLY, &node)); |
71 mnt_ = new MountHttpMock(args, &ppapi_); | 84 |
85 char buffer[10] = {0}; | |
86 int bytes_read = 0; | |
87 HandleAttr attr; | |
88 EXPECT_EQ(0, node->Read(attr, &buffer[0], sizeof(buffer), &bytes_read)); | |
89 EXPECT_EQ(strlen(contents), bytes_read); | |
90 EXPECT_STREQ(contents, buffer); | |
91 | |
92 // Read nothing past the end of the file. | |
93 attr.offs = 100; | |
94 EXPECT_EQ(0, node->Read(attr, &buffer[0], sizeof(buffer), &bytes_read)); | |
95 EXPECT_EQ(0, bytes_read); | |
96 | |
97 // Read part of the data. | |
98 attr.offs = 4; | |
99 EXPECT_EQ(0, node->Read(attr, &buffer[0], sizeof(buffer), &bytes_read)); | |
100 ASSERT_EQ(strlen(contents) - 4, bytes_read); | |
101 buffer[bytes_read] = 0; | |
102 EXPECT_STREQ("ents", buffer); | |
72 } | 103 } |
73 | 104 |
74 TEST_F(MountHttpTest, Mkdir) { | 105 TEST_F(MountHttpTest, Write) { |
75 StringMap_t args; | 106 const char contents[] = "contents"; |
76 mnt_ = new MountHttpMock(args, &ppapi_); | 107 EXPECT_TRUE(ppapi_.server_template()->AddEntity("file", contents, NULL)); |
77 char manifest[] = "-r-- 123 /mydir/foo\n-rw- 234 /thatdir/bar\n"; | 108 |
78 EXPECT_EQ(0, mnt_->ParseManifest(manifest)); | 109 ScopedMountNode node; |
79 // mkdir of existing directories should give "File exists". | 110 ASSERT_EQ(0, mnt_.Open(Path("/file"), O_WRONLY, &node)); |
80 EXPECT_EQ(EEXIST, mnt_->Mkdir(Path("/"), 0)); | 111 |
81 EXPECT_EQ(EEXIST, mnt_->Mkdir(Path("/mydir"), 0)); | 112 // Writing always fails. |
82 // mkdir of non-existent directories should give "Permission denied". | 113 HandleAttr attr; |
83 EXPECT_EQ(EACCES, mnt_->Mkdir(Path("/non_existent"), 0)); | 114 attr.offs = 3; |
115 int bytes_written = 1; // Set to a non-zero value. | |
116 EXPECT_EQ(EACCES, node->Write(attr, "struct", 6, &bytes_written)); | |
117 EXPECT_EQ(0, bytes_written); | |
84 } | 118 } |
85 | 119 |
86 TEST_F(MountHttpTest, Rmdir) { | 120 TEST_F(MountHttpTest, GetStat) { |
87 StringMap_t args; | 121 const char contents[] = "contents"; |
88 mnt_ = new MountHttpMock(args, &ppapi_); | 122 EXPECT_TRUE(ppapi_.server_template()->AddEntity("file", contents, NULL)); |
89 char manifest[] = "-r-- 123 /mydir/foo\n-rw- 234 /thatdir/bar\n"; | 123 |
90 EXPECT_EQ(0, mnt_->ParseManifest(manifest)); | 124 ScopedMountNode node; |
91 // Rmdir on existing dirs should give "Permission Denied" | 125 ASSERT_EQ(0, mnt_.Open(Path("/file"), O_RDONLY, &node)); |
92 EXPECT_EQ(EACCES, mnt_->Rmdir(Path("/"))); | 126 |
93 EXPECT_EQ(EACCES, mnt_->Rmdir(Path("/mydir"))); | 127 struct stat statbuf; |
94 // Rmdir on existing files should give "Not a direcotory" | 128 EXPECT_EQ(0, node->GetStat(&statbuf)); |
95 EXPECT_EQ(ENOTDIR, mnt_->Rmdir(Path("/mydir/foo"))); | 129 EXPECT_EQ(S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, |
96 // Rmdir on non-existent files should give "No such file or directory" | 130 statbuf.st_mode); |
97 EXPECT_EQ(ENOENT, mnt_->Rmdir(Path("/non_existent"))); | 131 EXPECT_EQ(strlen(contents), statbuf.st_size); |
132 // These are not currently set. | |
133 EXPECT_EQ(0, statbuf.st_atime); | |
134 EXPECT_EQ(0, statbuf.st_ctime); | |
135 EXPECT_EQ(0, statbuf.st_mtime); | |
98 } | 136 } |
99 | 137 |
100 TEST_F(MountHttpTest, Unlink) { | 138 TEST_F(MountHttpTest, FTruncate) { |
101 StringMap_t args; | 139 const char contents[] = "contents"; |
102 mnt_ = new MountHttpMock(args, &ppapi_); | 140 EXPECT_TRUE(ppapi_.server_template()->AddEntity("file", contents, NULL)); |
103 char manifest[] = "-r-- 123 /mydir/foo\n-rw- 234 /thatdir/bar\n"; | 141 |
104 EXPECT_EQ(0, mnt_->ParseManifest(manifest)); | 142 ScopedMountNode node; |
105 // Unlink of existing files should give "Permission Denied" | 143 ASSERT_EQ(0, mnt_.Open(Path("/file"), O_RDWR, &node)); |
106 EXPECT_EQ(EACCES, mnt_->Unlink(Path("/mydir/foo"))); | 144 EXPECT_EQ(EACCES, node->FTruncate(4)); |
107 // Unlink of existing directory should give "Is a directory" | |
108 EXPECT_EQ(EISDIR, mnt_->Unlink(Path("/mydir"))); | |
109 // Unlink of non-existent files should give "No such file or directory" | |
110 EXPECT_EQ(ENOENT, mnt_->Unlink(Path("/non_existent"))); | |
111 } | 145 } |
112 | 146 |
113 TEST_F(MountHttpTest, Remove) { | 147 TEST(MountHttpDirTest, Mkdir) { |
114 StringMap_t args; | 148 StringMap_t args; |
115 mnt_ = new MountHttpMock(args, &ppapi_); | 149 MountHttpForTesting mnt(args, NULL); |
116 char manifest[] = "-r-- 123 /mydir/foo\n-rw- 234 /thatdir/bar\n"; | 150 char manifest[] = "-r-- 123 /mydir/foo\n-rw- 234 /thatdir/bar\n"; |
117 EXPECT_EQ(0, mnt_->ParseManifest(manifest)); | 151 EXPECT_EQ(0, mnt.ParseManifest(manifest)); |
118 // Remove of existing files should give "Permission Denied" | 152 // mkdir of existing directories should give "File exists". |
119 EXPECT_EQ(EACCES, mnt_->Remove(Path("/mydir/foo"))); | 153 EXPECT_EQ(EEXIST, mnt.Mkdir(Path("/"), 0)); |
120 // Remove of existing directory should give "Permission Denied" | 154 EXPECT_EQ(EEXIST, mnt.Mkdir(Path("/mydir"), 0)); |
121 EXPECT_EQ(EACCES, mnt_->Remove(Path("/mydir"))); | 155 // mkdir of non-existent directories should give "Permission denied". |
122 // Unlink of non-existent files should give "No such file or directory" | 156 EXPECT_EQ(EACCES, mnt.Mkdir(Path("/non_existent"), 0)); |
123 EXPECT_EQ(ENOENT, mnt_->Remove(Path("/non_existent"))); | |
124 } | 157 } |
125 | 158 |
126 TEST_F(MountHttpTest, ParseManifest) { | 159 TEST(MountHttpDirTest, Rmdir) { |
160 StringMap_t args; | |
161 MountHttpForTesting mnt(args, NULL); | |
162 char manifest[] = "-r-- 123 /mydir/foo\n-rw- 234 /thatdir/bar\n"; | |
163 EXPECT_EQ(0, mnt.ParseManifest(manifest)); | |
164 // Rmdir on existing dirs should give "Permission Denied" | |
165 EXPECT_EQ(EACCES, mnt.Rmdir(Path("/"))); | |
166 EXPECT_EQ(EACCES, mnt.Rmdir(Path("/mydir"))); | |
167 // Rmdir on existing files should give "Not a direcotory" | |
168 EXPECT_EQ(ENOTDIR, mnt.Rmdir(Path("/mydir/foo"))); | |
169 // Rmdir on non-existent files should give "No such file or directory" | |
170 EXPECT_EQ(ENOENT, mnt.Rmdir(Path("/non_existent"))); | |
171 } | |
172 | |
173 TEST(MountHttpDirTest, Unlink) { | |
174 StringMap_t args; | |
175 MountHttpForTesting mnt(args, NULL); | |
176 char manifest[] = "-r-- 123 /mydir/foo\n-rw- 234 /thatdir/bar\n"; | |
177 EXPECT_EQ(0, mnt.ParseManifest(manifest)); | |
178 // Unlink of existing files should give "Permission Denied" | |
179 EXPECT_EQ(EACCES, mnt.Unlink(Path("/mydir/foo"))); | |
180 // Unlink of existing directory should give "Is a directory" | |
181 EXPECT_EQ(EISDIR, mnt.Unlink(Path("/mydir"))); | |
182 // Unlink of non-existent files should give "No such file or directory" | |
183 EXPECT_EQ(ENOENT, mnt.Unlink(Path("/non_existent"))); | |
184 } | |
185 | |
186 TEST(MountHttpDirTest, Remove) { | |
187 StringMap_t args; | |
188 MountHttpForTesting mnt(args, NULL); | |
189 char manifest[] = "-r-- 123 /mydir/foo\n-rw- 234 /thatdir/bar\n"; | |
190 EXPECT_EQ(0, mnt.ParseManifest(manifest)); | |
Sam Clegg
2013/11/20 20:00:54
Assert here and other places there ParseManifest i
binji
2013/11/20 20:34:17
Done.
| |
191 // Remove of existing files should give "Permission Denied" | |
192 EXPECT_EQ(EACCES, mnt.Remove(Path("/mydir/foo"))); | |
193 // Remove of existing directory should give "Permission Denied" | |
194 EXPECT_EQ(EACCES, mnt.Remove(Path("/mydir"))); | |
195 // Unlink of non-existent files should give "No such file or directory" | |
196 EXPECT_EQ(ENOENT, mnt.Remove(Path("/non_existent"))); | |
197 } | |
198 | |
199 TEST(MountHttpDirTest, ParseManifest) { | |
127 StringMap_t args; | 200 StringMap_t args; |
128 size_t result_size = 0; | 201 size_t result_size = 0; |
129 | 202 |
130 mnt_ = new MountHttpMock(args, &ppapi_); | 203 MountHttpForTesting mnt(args, NULL); |
131 | 204 |
132 // Multiple consecutive newlines or spaces should be ignored. | 205 // Multiple consecutive newlines or spaces should be ignored. |
133 char manifest[] = "-r-- 123 /mydir/foo\n\n-rw- 234 /thatdir/bar\n"; | 206 char manifest[] = "-r-- 123 /mydir/foo\n\n-rw- 234 /thatdir/bar\n"; |
134 EXPECT_EQ(0, mnt_->ParseManifest(manifest)); | 207 EXPECT_EQ(0, mnt.ParseManifest(manifest)); |
135 | 208 |
136 ScopedMountNode root; | 209 ScopedMountNode root; |
137 EXPECT_EQ(0, mnt_->FindOrCreateDir(Path("/"), &root)); | 210 EXPECT_EQ(0, mnt.FindOrCreateDir(Path("/"), &root)); |
138 ASSERT_NE((MountNode*)NULL, root.get()); | 211 ASSERT_NE((MountNode*)NULL, root.get()); |
139 EXPECT_EQ(2, root->ChildCount()); | 212 EXPECT_EQ(2, root->ChildCount()); |
140 | 213 |
141 ScopedMountNode dir; | 214 ScopedMountNode dir; |
142 EXPECT_EQ(0, mnt_->FindOrCreateDir(Path("/mydir"), &dir)); | 215 EXPECT_EQ(0, mnt.FindOrCreateDir(Path("/mydir"), &dir)); |
143 ASSERT_NE((MountNode*)NULL, dir.get()); | 216 ASSERT_NE((MountNode*)NULL, dir.get()); |
144 EXPECT_EQ(1, dir->ChildCount()); | 217 EXPECT_EQ(1, dir->ChildCount()); |
145 | 218 |
146 MountNode* node = mnt_->GetMap()["/mydir/foo"].get(); | 219 MountNode* node = (*mnt.GetNodeCacheForTesting())["/mydir/foo"].get(); |
147 EXPECT_NE((MountNode*)NULL, node); | 220 EXPECT_NE((MountNode*)NULL, node); |
148 EXPECT_EQ(0, node->GetSize(&result_size)); | 221 EXPECT_EQ(0, node->GetSize(&result_size)); |
149 EXPECT_EQ(123, result_size); | 222 EXPECT_EQ(123, result_size); |
150 | 223 |
151 // Since these files are cached thanks to the manifest, we can open them | 224 // Since these files are cached thanks to the manifest, we can open them |
152 // without accessing the PPAPI URL API. | 225 // without accessing the PPAPI URL API. |
153 ScopedMountNode foo; | 226 ScopedMountNode foo; |
154 EXPECT_EQ(0, mnt_->Open(Path("/mydir/foo"), O_RDONLY, &foo)); | 227 ASSERT_EQ(0, mnt.Open(Path("/mydir/foo"), O_RDONLY, &foo)); |
155 | 228 |
156 ScopedMountNode bar; | 229 ScopedMountNode bar; |
157 EXPECT_EQ(0, mnt_->Open(Path("/thatdir/bar"), O_RDWR, &bar)); | 230 ASSERT_EQ(0, mnt.Open(Path("/thatdir/bar"), O_RDWR, &bar)); |
158 | 231 |
159 struct stat sfoo; | 232 struct stat sfoo; |
160 struct stat sbar; | 233 struct stat sbar; |
161 | 234 |
162 EXPECT_FALSE(foo->GetStat(&sfoo)); | 235 EXPECT_FALSE(foo->GetStat(&sfoo)); |
163 EXPECT_FALSE(bar->GetStat(&sbar)); | 236 EXPECT_FALSE(bar->GetStat(&sbar)); |
164 | 237 |
165 EXPECT_EQ(123, sfoo.st_size); | 238 EXPECT_EQ(123, sfoo.st_size); |
166 EXPECT_EQ(S_IFREG | S_IRALL, sfoo.st_mode); | 239 EXPECT_EQ(S_IFREG | S_IRALL, sfoo.st_mode); |
167 | 240 |
168 EXPECT_EQ(234, sbar.st_size); | 241 EXPECT_EQ(234, sbar.st_size); |
169 EXPECT_EQ(S_IFREG | S_IRALL | S_IWALL, sbar.st_mode); | 242 EXPECT_EQ(S_IFREG | S_IRALL | S_IWALL, sbar.st_mode); |
170 } | 243 } |
171 | 244 |
245 TEST_F(MountHttpNoCacheTest, OpenAndClose) { | |
246 const char contents[] = "contents"; | |
247 EXPECT_TRUE(ppapi_.server_template()->AddEntity("file", contents, NULL)); | |
172 | 248 |
173 class MountHttpNodeTest : public MountHttpTest { | 249 ScopedMountNode node; |
174 public: | 250 ASSERT_EQ(0, mnt_.Open(Path("/file"), O_RDONLY, &node)); |
175 MountHttpNodeTest(); | |
176 virtual void TearDown(); | |
177 | |
178 void SetMountArgs(const StringMap_t& args); | |
179 void ExpectOpen(const char* method); | |
180 void ExpectHeaders(const char* headers); | |
181 void OpenNode(); | |
182 void SetResponse(int status_code, const char* headers); | |
183 // Set a response code, but expect the request to fail. Certain function calls | |
184 // expected by SetResponse are not expected here. | |
185 void SetResponseExpectFail(int status_code, const char* headers); | |
186 void SetResponseBody(const char* body); | |
187 void ResetMocks(); | |
188 | |
189 protected: | |
190 MountHttpMock* mnt_; | |
191 ScopedMountNode node_; | |
192 | |
193 CoreInterfaceMock* core_; | |
194 VarInterfaceMock* var_; | |
195 URLLoaderInterfaceMock* loader_; | |
196 URLRequestInfoInterfaceMock* request_; | |
197 URLResponseInfoInterfaceMock* response_; | |
198 size_t response_body_offset_; | |
199 | |
200 static const char path_[]; | |
201 static const char rel_path_[]; | |
202 static const PP_Resource loader_resource_ = 235; | |
203 static const PP_Resource request_resource_ = 236; | |
204 static const PP_Resource response_resource_ = 237; | |
205 }; | |
206 | |
207 // static | |
208 const char MountHttpNodeTest::path_[] = "/foo"; | |
209 // static | |
210 const char MountHttpNodeTest::rel_path_[] = "foo"; | |
211 | |
212 MountHttpNodeTest::MountHttpNodeTest() | |
213 : mnt_(NULL), | |
214 node_(NULL) { | |
215 } | 251 } |
216 | 252 |
217 static PP_Var MakeString(PP_Resource resource) { | 253 TEST_F(MountHttpNoCacheTest, OpenAndCloseNotFound) { |
218 PP_Var result = { PP_VARTYPE_STRING, 0, {PP_FALSE} }; | 254 ScopedMountNode node; |
219 result.value.as_id = resource; | 255 ASSERT_EQ(ENOENT, mnt_.Open(Path("/file"), O_RDONLY, &node)); |
220 return result; | |
221 } | 256 } |
222 | 257 |
223 void MountHttpNodeTest::SetMountArgs(const StringMap_t& args) { | 258 TEST_F(MountHttpNoCacheTest, OpenAndCloseServerError) { |
224 mnt_ = new MountHttpMock(args, &ppapi_); | 259 EXPECT_TRUE(ppapi_.server_template()->AddError("file", 500)); |
260 | |
261 ScopedMountNode node; | |
262 ASSERT_EQ(ENOENT, mnt_.Open(Path("/file"), O_RDONLY, &node)); | |
225 } | 263 } |
226 | 264 |
227 void MountHttpNodeTest::ExpectOpen(const char* method) { | 265 TEST_F(MountHttpNoCacheTest, GetSize) { |
228 core_ = ppapi_.GetCoreInterface(); | 266 const char contents[] = "contents"; |
229 loader_ = ppapi_.GetURLLoaderInterface(); | 267 EXPECT_TRUE(ppapi_.server_template()->AddEntity("file", contents, NULL)); |
230 request_ = ppapi_.GetURLRequestInfoInterface(); | 268 ppapi_.server_template()->set_send_content_length(true); |
231 response_ = ppapi_.GetURLResponseInfoInterface(); | |
232 var_ = ppapi_.GetVarInterface(); | |
233 | 269 |
234 ON_CALL(*request_, SetProperty(request_resource_, _, _)) | 270 ScopedMountNode node; |
235 .WillByDefault(Return(PP_TRUE)); | 271 struct stat statbuf; |
236 ON_CALL(*var_, VarFromUtf8(_, _)).WillByDefault(Return(PP_MakeUndefined())); | 272 ASSERT_EQ(0, mnt_.Open(Path("/file"), O_RDONLY, &node)); |
237 | 273 EXPECT_EQ(0, node->GetStat(&statbuf)); |
238 EXPECT_CALL(*loader_, Create(instance_)).WillOnce(Return(loader_resource_)); | 274 EXPECT_EQ(strlen(contents), statbuf.st_size); |
239 EXPECT_CALL(*request_, Create(instance_)).WillOnce(Return(request_resource_)); | |
240 | |
241 PP_Var var_head = MakeString(345); | |
242 PP_Var var_url = MakeString(346); | |
243 EXPECT_CALL(*var_, VarFromUtf8(StrEq(method), _)).WillOnce(Return(var_head)); | |
244 EXPECT_CALL(*var_, VarFromUtf8(StrEq(rel_path_), _)) | |
245 .WillOnce(Return(var_url)); | |
246 | |
247 #define EXPECT_SET_PROPERTY(NAME, VAR) \ | |
248 EXPECT_CALL(*request_, SetProperty(request_resource_, NAME, VAR)) | |
249 | |
250 EXPECT_SET_PROPERTY(PP_URLREQUESTPROPERTY_URL, IsEqualToVar(var_url)); | |
251 EXPECT_SET_PROPERTY(PP_URLREQUESTPROPERTY_METHOD, IsEqualToVar(var_head)); | |
252 EXPECT_SET_PROPERTY(PP_URLREQUESTPROPERTY_ALLOWCROSSORIGINREQUESTS, _); | |
253 EXPECT_SET_PROPERTY(PP_URLREQUESTPROPERTY_ALLOWCREDENTIALS, _); | |
254 | |
255 #undef EXPECT_SET_PROPERTY | |
256 | |
257 EXPECT_CALL(*loader_, Open(loader_resource_, request_resource_, _)) | |
258 .WillOnce(DoAll(CallCallback<2>(int32_t(PP_OK)), | |
259 Return(int32_t(PP_OK_COMPLETIONPENDING)))); | |
260 EXPECT_CALL(*loader_, GetResponseInfo(loader_resource_)) | |
261 .WillOnce(Return(response_resource_)); | |
262 | |
263 EXPECT_CALL(*core_, ReleaseResource(loader_resource_)); | |
264 EXPECT_CALL(*core_, ReleaseResource(request_resource_)); | |
265 EXPECT_CALL(*core_, ReleaseResource(response_resource_)); | |
266 } | 275 } |
267 | 276 |
268 void MountHttpNodeTest::ExpectHeaders(const char* headers) { | 277 TEST_F(MountHttpNoCacheTest, Access) { |
269 PP_Var var_headers = MakeString(347); | 278 EXPECT_TRUE(ppapi_.server_template()->AddEntity("file", "", NULL)); |
270 var_ = ppapi_.GetVarInterface(); | |
271 EXPECT_CALL(*var_, VarFromUtf8(StrEq(headers), _)) | |
272 .WillOnce(Return(var_headers)); | |
273 | 279 |
274 EXPECT_CALL(*request_, SetProperty(request_resource_, | 280 ASSERT_EQ(0, mnt_.Access(Path("/file"), R_OK)); |
275 PP_URLREQUESTPROPERTY_HEADERS, | 281 ASSERT_EQ(EACCES, mnt_.Access(Path("/file"), W_OK)); |
276 IsEqualToVar(var_headers))).Times(1); | 282 ASSERT_EQ(ENOENT, mnt_.Access(Path("/bar"), R_OK)); |
277 } | 283 } |
278 | 284 |
279 void MountHttpNodeTest::SetResponse(int status_code, const char* headers) { | 285 TEST_F(MountHttpNoCacheTest, ReadPartial) { |
280 ON_CALL(*response_, GetProperty(response_resource_, _)) | 286 const char contents[] = "0123456789abcdefghi"; |
281 .WillByDefault(Return(PP_MakeUndefined())); | 287 EXPECT_TRUE(ppapi_.server_template()->AddEntity("file", contents, NULL)); |
Sam Clegg
2013/11/20 20:00:54
Assert rather than expect here and other places wh
binji
2013/11/20 20:34:17
Done.
| |
288 ppapi_.server_template()->set_allow_partial(true); | |
282 | 289 |
283 PP_Var var_headers = MakeString(348); | |
284 EXPECT_CALL(*response_, | |
285 GetProperty(response_resource_, | |
286 PP_URLRESPONSEPROPERTY_STATUSCODE)) | |
287 .WillOnce(Return(PP_MakeInt32(status_code))); | |
288 EXPECT_CALL(*response_, | |
289 GetProperty(response_resource_, PP_URLRESPONSEPROPERTY_HEADERS)) | |
290 .WillOnce(Return(var_headers)); | |
291 EXPECT_CALL(*var_, VarToUtf8(IsEqualToVar(var_headers), _)) | |
292 .WillOnce(DoAll(SetArgPointee<1>(strlen(headers)), | |
293 Return(headers))); | |
294 } | |
295 | |
296 void MountHttpNodeTest::SetResponseExpectFail(int status_code, | |
297 const char* headers) { | |
298 ON_CALL(*response_, GetProperty(response_resource_, _)) | |
299 .WillByDefault(Return(PP_MakeUndefined())); | |
300 | |
301 EXPECT_CALL(*response_, | |
302 GetProperty(response_resource_, | |
303 PP_URLRESPONSEPROPERTY_STATUSCODE)) | |
304 .WillOnce(Return(PP_MakeInt32(status_code))); | |
305 } | |
306 | |
307 ACTION_P3(ReadResponseBodyAction, offset, body, body_length) { | |
308 char* buf = static_cast<char*>(arg1); | |
309 size_t read_length = arg2; | |
310 PP_CompletionCallback callback = arg3; | |
311 if (*offset >= body_length) | |
312 return 0; | |
313 | |
314 read_length = std::min(read_length, body_length - *offset); | |
315 memcpy(buf, body + *offset, read_length); | |
316 *offset += read_length; | |
317 | |
318 // Also call the callback. | |
319 if (callback.func) | |
320 (*callback.func)(callback.user_data, PP_OK); | |
321 | |
322 return read_length; | |
323 } | |
324 | |
325 void MountHttpNodeTest::SetResponseBody(const char* body) { | |
326 response_body_offset_ = 0; | |
327 EXPECT_CALL(*loader_, ReadResponseBody(loader_resource_, _, _, _)) | |
328 .WillRepeatedly(ReadResponseBodyAction( | |
329 &response_body_offset_, body, strlen(body))); | |
330 } | |
331 | |
332 void MountHttpNodeTest::OpenNode() { | |
333 ASSERT_EQ(0, mnt_->Open(Path(path_), O_RDONLY, &node_)); | |
334 ASSERT_NE((MountNode*)NULL, node_.get()); | |
335 } | |
336 | |
337 void MountHttpNodeTest::ResetMocks() { | |
338 Mock::VerifyAndClearExpectations(&ppapi_); | |
339 Mock::VerifyAndClearExpectations(loader_); | |
340 Mock::VerifyAndClearExpectations(request_); | |
341 Mock::VerifyAndClearExpectations(response_); | |
342 Mock::VerifyAndClearExpectations(var_); | |
343 } | |
344 | |
345 void MountHttpNodeTest::TearDown() { | |
346 node_.reset(); | |
347 delete mnt_; | |
348 } | |
349 | |
350 // TODO(binji): These tests are all broken now. In another CL, I'll reimplement | |
351 // these tests using an HTTP fake. | |
352 TEST_F(MountHttpNodeTest, DISABLED_OpenAndCloseNoCache) { | |
353 StringMap_t smap; | |
354 smap["cache_content"] = "false"; | |
355 SetMountArgs(StringMap_t()); | |
356 ExpectOpen("HEAD"); | |
357 ExpectHeaders(""); | |
358 SetResponse(200, ""); | |
359 OpenNode(); | |
360 } | |
361 | |
362 TEST_F(MountHttpNodeTest, DISABLED_OpenAndCloseNotFound) { | |
363 StringMap_t smap; | |
364 smap["cache_content"] = "false"; | |
365 SetMountArgs(StringMap_t()); | |
366 ExpectOpen("HEAD"); | |
367 ExpectHeaders(""); | |
368 SetResponseExpectFail(404, ""); | |
369 ASSERT_EQ(ENOENT, mnt_->Open(Path(path_), O_RDONLY, &node_)); | |
370 } | |
371 | |
372 TEST_F(MountHttpNodeTest, DISABLED_OpenAndCloseServerError) { | |
373 StringMap_t smap; | |
374 smap["cache_content"] = "false"; | |
375 SetMountArgs(StringMap_t()); | |
376 ExpectOpen("HEAD"); | |
377 ExpectHeaders(""); | |
378 SetResponseExpectFail(500, ""); | |
379 ASSERT_EQ(EIO, mnt_->Open(Path(path_), O_RDONLY, &node_)); | |
380 } | |
381 | |
382 TEST_F(MountHttpNodeTest, DISABLED_GetStat) { | |
383 StringMap_t smap; | |
384 smap["cache_content"] = "false"; | |
385 SetMountArgs(StringMap_t()); | |
386 ExpectOpen("HEAD"); | |
387 ExpectHeaders(""); | |
388 SetResponse(200, "Content-Length: 42\n"); | |
389 OpenNode(); | |
390 | |
391 struct stat stat; | |
392 EXPECT_EQ(0, node_->GetStat(&stat)); | |
393 EXPECT_EQ(42, stat.st_size); | |
394 } | |
395 | |
396 TEST_F(MountHttpNodeTest, DISABLED_Access) { | |
397 StringMap_t smap; | |
398 smap["cache_content"] = "false"; | |
399 SetMountArgs(StringMap_t()); | |
400 ExpectOpen("HEAD"); | |
401 ExpectHeaders(""); | |
402 SetResponse(200, ""); | |
403 ASSERT_EQ(0, mnt_->Access(Path(path_), R_OK)); | |
404 } | |
405 | |
406 TEST_F(MountHttpNodeTest, DISABLED_AccessWrite) { | |
407 StringMap_t smap; | |
408 smap["cache_content"] = "false"; | |
409 SetMountArgs(StringMap_t()); | |
410 ExpectOpen("HEAD"); | |
411 ExpectHeaders(""); | |
412 SetResponse(200, ""); | |
413 ASSERT_EQ(EACCES, mnt_->Access(Path(path_), W_OK)); | |
414 } | |
415 | |
416 TEST_F(MountHttpNodeTest, DISABLED_AccessNotFound) { | |
417 StringMap_t smap; | |
418 smap["cache_content"] = "false"; | |
419 SetMountArgs(StringMap_t()); | |
420 ExpectOpen("HEAD"); | |
421 ExpectHeaders(""); | |
422 SetResponseExpectFail(404, ""); | |
423 ASSERT_EQ(ENOENT, mnt_->Access(Path(path_), R_OK)); | |
424 } | |
425 | |
426 TEST_F(MountHttpNodeTest, DISABLED_ReadCached) { | |
427 size_t result_size = 0; | |
428 int result_bytes = 0; | 290 int result_bytes = 0; |
429 | 291 |
430 SetMountArgs(StringMap_t()); | |
431 ExpectOpen("HEAD"); | |
432 ExpectHeaders(""); | |
433 SetResponse(200, "Content-Length: 42\n"); | |
434 OpenNode(); | |
435 ResetMocks(); | |
436 | |
437 EXPECT_EQ(0, node_->GetSize(&result_size)); | |
438 EXPECT_EQ(42, result_size); | |
439 | |
440 char buf[10]; | 292 char buf[10]; |
441 memset(&buf[0], 0, sizeof(buf)); | 293 memset(&buf[0], 0, sizeof(buf)); |
442 | 294 |
443 ExpectOpen("GET"); | 295 ScopedMountNode node; |
444 ExpectHeaders(""); | 296 ASSERT_EQ(0, mnt_.Open(Path("/file"), O_RDONLY, &node)); |
445 SetResponse(200, "Content-Length: 42\n"); | |
446 SetResponseBody("Here is some response text. And some more."); | |
447 HandleAttr attr; | 297 HandleAttr attr; |
448 EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes)); | 298 EXPECT_EQ(0, node->Read(attr, buf, sizeof(buf) - 1, &result_bytes)); |
449 EXPECT_STREQ("Here is s", &buf[0]); | 299 EXPECT_EQ(sizeof(buf) - 1, result_bytes); |
450 ResetMocks(); | 300 EXPECT_STREQ("012345678", &buf[0]); |
451 | 301 |
452 // Further reads should be cached. | |
453 EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes)); | |
454 EXPECT_STREQ("Here is s", &buf[0]); | |
455 attr.offs = 10; | 302 attr.offs = 10; |
456 EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes)); | 303 EXPECT_EQ(0, node->Read(attr, buf, sizeof(buf) - 1, &result_bytes)); |
457 EXPECT_STREQ("me respon", &buf[0]); | 304 EXPECT_EQ(sizeof(buf) - 1, result_bytes); |
458 | 305 EXPECT_STREQ("abcdefghi", &buf[0]); |
459 EXPECT_EQ(0, node_->GetSize(&result_size)); | |
460 EXPECT_EQ(42, result_size); | |
461 } | 306 } |
462 | 307 |
463 TEST_F(MountHttpNodeTest, DISABLED_ReadCachedNoContentLength) { | 308 TEST_F(MountHttpNoCacheTest, ReadPartialNoServerSupport) { |
464 size_t result_size = 0; | 309 const char contents[] = "0123456789abcdefghi"; |
310 EXPECT_TRUE(ppapi_.server_template()->AddEntity("file", contents, NULL)); | |
Sam Clegg
2013/11/20 20:00:54
Assert here?
binji
2013/11/20 20:34:17
Done.
| |
311 ppapi_.server_template()->set_allow_partial(false); | |
312 | |
465 int result_bytes = 0; | 313 int result_bytes = 0; |
466 | 314 |
467 SetMountArgs(StringMap_t()); | |
468 ExpectOpen("HEAD"); | |
469 ExpectHeaders(""); | |
470 SetResponse(200, ""); | |
471 OpenNode(); | |
472 ResetMocks(); | |
473 | |
474 ExpectOpen("GET"); | |
475 ExpectHeaders(""); | |
476 SetResponse(200, ""); // No Content-Length response here. | |
477 SetResponseBody("Here is some response text. And some more."); | |
478 | |
479 // GetSize will Read() because it didn't get the content length from the HEAD | |
480 // request. | |
481 EXPECT_EQ(0, node_->GetSize(&result_size)); | |
482 EXPECT_EQ(42, result_size); | |
483 | |
484 char buf[10]; | 315 char buf[10]; |
485 memset(&buf[0], 0, sizeof(buf)); | 316 memset(&buf[0], 0, sizeof(buf)); |
486 | 317 |
318 ScopedMountNode node; | |
319 ASSERT_EQ(0, mnt_.Open(Path("/file"), O_RDONLY, &node)); | |
487 HandleAttr attr; | 320 HandleAttr attr; |
488 EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes)); | 321 EXPECT_EQ(0, node->Read(attr, buf, sizeof(buf) - 1, &result_bytes)); |
489 EXPECT_STREQ("Here is s", &buf[0]); | |
490 ResetMocks(); | |
491 | |
492 // Further reads should be cached. | |
493 EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes)); | |
494 EXPECT_STREQ("Here is s", &buf[0]); | |
495 attr.offs = 10; | |
496 EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes)); | |
497 EXPECT_STREQ("me respon", &buf[0]); | |
498 | |
499 EXPECT_EQ(0, node_->GetSize(&result_size)); | |
500 EXPECT_EQ(42, result_size); | |
501 } | |
502 | |
503 TEST_F(MountHttpNodeTest, DISABLED_ReadCachedUnderrun) { | |
504 size_t result_size = 0; | |
505 int result_bytes = 0; | |
506 | |
507 SetMountArgs(StringMap_t()); | |
508 ExpectOpen("HEAD"); | |
509 ExpectHeaders(""); | |
510 SetResponse(200, "Content-Length: 100\n"); | |
511 OpenNode(); | |
512 ResetMocks(); | |
513 | |
514 EXPECT_EQ(0, node_->GetSize(&result_size)); | |
515 EXPECT_EQ(100, result_size); | |
516 | |
517 char buf[10]; | |
518 memset(&buf[0], 0, sizeof(buf)); | |
519 | |
520 ExpectOpen("GET"); | |
521 ExpectHeaders(""); | |
522 SetResponse(200, "Content-Length: 100\n"); | |
523 SetResponseBody("abcdefghijklmnopqrstuvwxyz"); | |
524 HandleAttr attr; | |
525 EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes)); | |
526 EXPECT_EQ(sizeof(buf) - 1, result_bytes); | |
527 EXPECT_STREQ("abcdefghi", &buf[0]); | |
528 ResetMocks(); | |
529 | |
530 EXPECT_EQ(0, node_->GetSize(&result_size)); | |
531 EXPECT_EQ(26, result_size); | |
532 } | |
533 | |
534 TEST_F(MountHttpNodeTest, DISABLED_ReadCachedOverrun) { | |
535 size_t result_size = 0; | |
536 int result_bytes = 0; | |
537 | |
538 SetMountArgs(StringMap_t()); | |
539 ExpectOpen("HEAD"); | |
540 ExpectHeaders(""); | |
541 SetResponse(200, "Content-Length: 15\n"); | |
542 OpenNode(); | |
543 ResetMocks(); | |
544 | |
545 EXPECT_EQ(0, node_->GetSize(&result_size)); | |
546 EXPECT_EQ(15, result_size); | |
547 | |
548 char buf[10]; | |
549 memset(&buf[0], 0, sizeof(buf)); | |
550 | |
551 ExpectOpen("GET"); | |
552 ExpectHeaders(""); | |
553 SetResponse(200, "Content-Length: 15\n"); | |
554 SetResponseBody("01234567890123456789"); | |
555 HandleAttr attr; | |
556 attr.offs = 10; | |
557 EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes)); | |
558 EXPECT_EQ(5, result_bytes); | |
559 EXPECT_STREQ("01234", &buf[0]); | |
560 ResetMocks(); | |
561 | |
562 EXPECT_EQ(0, node_->GetSize(&result_size)); | |
563 EXPECT_EQ(15, result_size); | |
564 } | |
565 | |
566 TEST_F(MountHttpNodeTest, DISABLED_ReadPartial) { | |
567 int result_bytes = 0; | |
568 | |
569 StringMap_t args; | |
570 args["cache_content"] = "false"; | |
571 SetMountArgs(args); | |
572 ExpectOpen("HEAD"); | |
573 ExpectHeaders(""); | |
574 SetResponse(200, ""); | |
575 OpenNode(); | |
576 ResetMocks(); | |
577 | |
578 char buf[10]; | |
579 memset(&buf[0], 0, sizeof(buf)); | |
580 | |
581 ExpectOpen("GET"); | |
582 ExpectHeaders("Range: bytes=0-8\n"); | |
583 SetResponse(206, "Content-Length: 9\nContent-Range: bytes=0-8\n"); | |
584 SetResponseBody("012345678"); | |
585 HandleAttr attr; | |
586 EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes)); | |
587 EXPECT_EQ(sizeof(buf) - 1, result_bytes); | 322 EXPECT_EQ(sizeof(buf) - 1, result_bytes); |
588 EXPECT_STREQ("012345678", &buf[0]); | 323 EXPECT_STREQ("012345678", &buf[0]); |
589 ResetMocks(); | |
590 | 324 |
591 // Another read is another request. | |
592 ExpectOpen("GET"); | |
593 ExpectHeaders("Range: bytes=10-18\n"); | |
594 SetResponse(206, "Content-Length: 9\nContent-Range: bytes=10-18\n"); | |
595 SetResponseBody("abcdefghi"); | |
596 attr.offs = 10; | 325 attr.offs = 10; |
597 EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes)); | 326 EXPECT_EQ(0, node->Read(attr, buf, sizeof(buf) - 1, &result_bytes)); |
598 EXPECT_EQ(sizeof(buf) - 1, result_bytes); | 327 EXPECT_EQ(sizeof(buf) - 1, result_bytes); |
599 EXPECT_STREQ("abcdefghi", &buf[0]); | 328 EXPECT_STREQ("abcdefghi", &buf[0]); |
600 } | 329 } |
601 | |
602 TEST_F(MountHttpNodeTest, DISABLED_ReadPartialNoServerSupport) { | |
603 int result_bytes = 0; | |
604 | |
605 StringMap_t args; | |
606 args["cache_content"] = "false"; | |
607 SetMountArgs(args); | |
608 ExpectOpen("HEAD"); | |
609 ExpectHeaders(""); | |
610 SetResponse(200, ""); | |
611 OpenNode(); | |
612 ResetMocks(); | |
613 | |
614 char buf[10]; | |
615 memset(&buf[0], 0, sizeof(buf)); | |
616 | |
617 ExpectOpen("GET"); | |
618 ExpectHeaders("Range: bytes=10-18\n"); | |
619 SetResponse(200, "Content-Length: 20\n"); | |
620 SetResponseBody("0123456789abcdefghij"); | |
621 HandleAttr attr; | |
622 attr.offs = 10; | |
623 EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes)); | |
624 EXPECT_EQ(sizeof(buf) - 1, result_bytes); | |
625 EXPECT_STREQ("abcdefghi", &buf[0]); | |
626 } | |
627 | |
OLD | NEW |