test_file_io.cc 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370
  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
  3. // found in the LICENSE file.
  4. #include "ppapi/tests/test_file_io.h"
  5. #include <errno.h>
  6. #include <fcntl.h>
  7. #include <stddef.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <sys/stat.h>
  11. #include <sys/types.h>
  12. #include <algorithm>
  13. #include <vector>
  14. #include "ppapi/c/pp_errors.h"
  15. #include "ppapi/c/ppb_file_io.h"
  16. #include "ppapi/c/private/pp_file_handle.h"
  17. #include "ppapi/c/private/ppb_testing_private.h"
  18. #include "ppapi/cpp/file_io.h"
  19. #include "ppapi/cpp/file_ref.h"
  20. #include "ppapi/cpp/file_system.h"
  21. #include "ppapi/cpp/instance.h"
  22. #include "ppapi/cpp/module.h"
  23. #include "ppapi/cpp/private/file_io_private.h"
  24. #include "ppapi/cpp/private/pass_file_handle.h"
  25. #include "ppapi/tests/test_utils.h"
  26. #include "ppapi/tests/testing_instance.h"
  27. #if defined(PPAPI_OS_WIN)
  28. # include <io.h>
  29. # include <windows.h>
  30. // TODO(hamaji): Use standard windows APIs instead of compatibility layer?
  31. # define lseek _lseek
  32. # define read _read
  33. # define write _write
  34. # define ssize_t int
  35. #else
  36. # include <sys/mman.h>
  37. # include <unistd.h>
  38. #endif
  39. REGISTER_TEST_CASE(FileIO);
  40. namespace {
  41. std::string ReportMismatch(const std::string& method_name,
  42. const std::string& returned_result,
  43. const std::string& expected_result) {
  44. return method_name + " returned '" + returned_result + "'; '" +
  45. expected_result + "' expected.";
  46. }
  47. std::string ReportOpenError(int32_t open_flags) {
  48. static const char* kFlagNames[] = {
  49. "PP_FILEOPENFLAG_READ",
  50. "PP_FILEOPENFLAG_WRITE",
  51. "PP_FILEOPENFLAG_CREATE",
  52. "PP_FILEOPENFLAG_TRUNCATE",
  53. "PP_FILEOPENFLAG_EXCLUSIVE"
  54. };
  55. std::string result = "FileIO:Open had unexpected behavior with flags: ";
  56. bool first_flag = true;
  57. for (int32_t mask = 1, index = 0; mask <= PP_FILEOPENFLAG_EXCLUSIVE;
  58. mask <<= 1, ++index) {
  59. if (mask & open_flags) {
  60. if (first_flag) {
  61. first_flag = false;
  62. } else {
  63. result += " | ";
  64. }
  65. result += kFlagNames[index];
  66. }
  67. }
  68. if (first_flag)
  69. result += "[None]";
  70. return result;
  71. }
  72. int32_t ReadEntireFile(PP_Instance instance,
  73. pp::FileIO* file_io,
  74. int32_t offset,
  75. std::string* data,
  76. CallbackType callback_type) {
  77. TestCompletionCallback callback(instance, callback_type);
  78. char buf[256];
  79. int32_t read_offset = offset;
  80. for (;;) {
  81. callback.WaitForResult(
  82. file_io->Read(read_offset, buf, sizeof(buf), callback.GetCallback()));
  83. if (callback.result() < 0)
  84. return callback.result();
  85. if (callback.result() == 0)
  86. break;
  87. read_offset += callback.result();
  88. data->append(buf, callback.result());
  89. }
  90. return PP_OK;
  91. }
  92. int32_t ReadToArrayEntireFile(PP_Instance instance,
  93. pp::FileIO* file_io,
  94. int32_t offset,
  95. std::string* data,
  96. CallbackType callback_type) {
  97. TestCompletionCallbackWithOutput< std::vector<char> > callback(
  98. instance, callback_type);
  99. for (;;) {
  100. callback.WaitForResult(file_io->Read(offset, 256, callback.GetCallback()));
  101. int32_t rv = callback.result();
  102. if (rv < 0)
  103. return rv;
  104. if (rv == 0)
  105. break;
  106. const std::vector<char>& output = callback.output();
  107. assert(rv == static_cast<int32_t>(output.size()));
  108. offset += rv;
  109. data->append(output.begin(), output.end());
  110. }
  111. return PP_OK;
  112. }
  113. #if !defined(PPAPI_OS_WIN)
  114. bool ReadEntireFileFromFileHandle(int fd, std::string* data) {
  115. if (lseek(fd, 0, SEEK_SET) < 0)
  116. return false;
  117. data->clear();
  118. int ret;
  119. do {
  120. char buf[8192];
  121. ret = read(fd, buf, sizeof(buf));
  122. if (ret > 0)
  123. data->append(buf, ret);
  124. } while (ret > 0);
  125. return ret == 0;
  126. }
  127. #endif // !defined(PPAPI_OS_WIN)
  128. int32_t WriteEntireBuffer(PP_Instance instance,
  129. pp::FileIO* file_io,
  130. int32_t offset,
  131. const std::string& data,
  132. CallbackType callback_type) {
  133. TestCompletionCallback callback(instance, callback_type);
  134. int32_t write_offset = offset;
  135. const char* buf = data.c_str();
  136. int32_t size = static_cast<int32_t>(data.size());
  137. while (write_offset < offset + size) {
  138. callback.WaitForResult(file_io->Write(write_offset,
  139. &buf[write_offset - offset],
  140. size - write_offset + offset,
  141. callback.GetCallback()));
  142. if (callback.result() < 0)
  143. return callback.result();
  144. if (callback.result() == 0)
  145. return PP_ERROR_FAILED;
  146. write_offset += callback.result();
  147. }
  148. return PP_OK;
  149. }
  150. } // namespace
  151. bool TestFileIO::Init() {
  152. return CheckTestingInterface() && EnsureRunningOverHTTP();
  153. }
  154. void TestFileIO::RunTests(const std::string& filter) {
  155. RUN_CALLBACK_TEST(TestFileIO, Open, filter);
  156. RUN_CALLBACK_TEST(TestFileIO, OpenDirectory, filter);
  157. RUN_CALLBACK_TEST(TestFileIO, ReadWriteSetLength, filter);
  158. RUN_CALLBACK_TEST(TestFileIO, ReadToArrayWriteSetLength, filter);
  159. RUN_CALLBACK_TEST(TestFileIO, TouchQuery, filter);
  160. RUN_CALLBACK_TEST(TestFileIO, AbortCalls, filter);
  161. RUN_CALLBACK_TEST(TestFileIO, ParallelReads, filter);
  162. RUN_CALLBACK_TEST(TestFileIO, ParallelWrites, filter);
  163. RUN_CALLBACK_TEST(TestFileIO, NotAllowMixedReadWrite, filter);
  164. RUN_CALLBACK_TEST(TestFileIO, RequestOSFileHandle, filter);
  165. RUN_CALLBACK_TEST(TestFileIO, RequestOSFileHandleWithOpenExclusive, filter);
  166. RUN_CALLBACK_TEST(TestFileIO, Mmap, filter);
  167. // TODO(viettrungluu): add tests:
  168. // - that PP_ERROR_PENDING is correctly returned
  169. // - that operations respect the file open modes (flags)
  170. }
  171. std::string TestFileIO::TestOpen() {
  172. TestCompletionCallback callback(instance_->pp_instance(), callback_type());
  173. pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
  174. pp::FileRef file_ref(file_system, "/file_open");
  175. callback.WaitForResult(file_system.Open(1024, callback.GetCallback()));
  176. CHECK_CALLBACK_BEHAVIOR(callback);
  177. ASSERT_EQ(PP_OK, callback.result());
  178. std::string result;
  179. result = MatchOpenExpectations(
  180. &file_system,
  181. PP_FILEOPENFLAG_READ,
  182. DONT_CREATE_IF_DOESNT_EXIST | OPEN_IF_EXISTS | DONT_TRUNCATE_IF_EXISTS);
  183. if (!result.empty())
  184. return result;
  185. // Test the behavior of the power set of
  186. // { PP_FILEOPENFLAG_CREATE,
  187. // PP_FILEOPENFLAG_TRUNCATE,
  188. // PP_FILEOPENFLAG_EXCLUSIVE }.
  189. // First of all, none of them are specified.
  190. result = MatchOpenExpectations(
  191. &file_system,
  192. PP_FILEOPENFLAG_WRITE,
  193. DONT_CREATE_IF_DOESNT_EXIST | OPEN_IF_EXISTS | DONT_TRUNCATE_IF_EXISTS);
  194. if (!result.empty())
  195. return result;
  196. result = MatchOpenExpectations(
  197. &file_system,
  198. PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_CREATE,
  199. CREATE_IF_DOESNT_EXIST | OPEN_IF_EXISTS | DONT_TRUNCATE_IF_EXISTS);
  200. if (!result.empty())
  201. return result;
  202. result = MatchOpenExpectations(
  203. &file_system,
  204. PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_EXCLUSIVE,
  205. DONT_CREATE_IF_DOESNT_EXIST | OPEN_IF_EXISTS | DONT_TRUNCATE_IF_EXISTS);
  206. if (!result.empty())
  207. return result;
  208. result = MatchOpenExpectations(
  209. &file_system,
  210. PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_TRUNCATE,
  211. DONT_CREATE_IF_DOESNT_EXIST | OPEN_IF_EXISTS | TRUNCATE_IF_EXISTS);
  212. if (!result.empty())
  213. return result;
  214. result = MatchOpenExpectations(
  215. &file_system,
  216. PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_CREATE |
  217. PP_FILEOPENFLAG_EXCLUSIVE,
  218. CREATE_IF_DOESNT_EXIST | DONT_OPEN_IF_EXISTS | DONT_TRUNCATE_IF_EXISTS);
  219. if (!result.empty())
  220. return result;
  221. result = MatchOpenExpectations(
  222. &file_system,
  223. PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_CREATE | PP_FILEOPENFLAG_TRUNCATE,
  224. CREATE_IF_DOESNT_EXIST | OPEN_IF_EXISTS | TRUNCATE_IF_EXISTS);
  225. if (!result.empty())
  226. return result;
  227. result = MatchOpenExpectations(
  228. &file_system,
  229. PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_EXCLUSIVE |
  230. PP_FILEOPENFLAG_TRUNCATE,
  231. DONT_CREATE_IF_DOESNT_EXIST | OPEN_IF_EXISTS | TRUNCATE_IF_EXISTS);
  232. if (!result.empty())
  233. return result;
  234. result = MatchOpenExpectations(
  235. &file_system,
  236. PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_CREATE |
  237. PP_FILEOPENFLAG_EXCLUSIVE | PP_FILEOPENFLAG_TRUNCATE,
  238. CREATE_IF_DOESNT_EXIST | DONT_OPEN_IF_EXISTS | DONT_TRUNCATE_IF_EXISTS);
  239. if (!result.empty())
  240. return result;
  241. // Invalid combination: PP_FILEOPENFLAG_TRUNCATE without
  242. // PP_FILEOPENFLAG_WRITE.
  243. result = MatchOpenExpectations(
  244. &file_system,
  245. PP_FILEOPENFLAG_READ | PP_FILEOPENFLAG_TRUNCATE,
  246. INVALID_FLAG_COMBINATION);
  247. if (!result.empty())
  248. return result;
  249. PASS();
  250. }
  251. std::string TestFileIO::TestOpenDirectory() {
  252. TestCompletionCallback callback(instance_->pp_instance(), callback_type());
  253. pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
  254. callback.WaitForResult(file_system.Open(1024, callback.GetCallback()));
  255. CHECK_CALLBACK_BEHAVIOR(callback);
  256. ASSERT_EQ(PP_OK, callback.result());
  257. // Make a directory.
  258. pp::FileRef dir_ref(file_system, "/test_dir_open_directory");
  259. callback.WaitForResult(dir_ref.MakeDirectory(
  260. PP_MAKEDIRECTORYFLAG_NONE, callback.GetCallback()));
  261. CHECK_CALLBACK_BEHAVIOR(callback);
  262. ASSERT_EQ(PP_OK, callback.result());
  263. // Open the directory. This is expected to fail since directories cannot be
  264. // opened.
  265. pp::FileIO file_io(instance_);
  266. callback.WaitForResult(file_io.Open(dir_ref, PP_FILEOPENFLAG_READ,
  267. callback.GetCallback()));
  268. CHECK_CALLBACK_BEHAVIOR(callback);
  269. ASSERT_EQ(PP_ERROR_NOTAFILE, callback.result());
  270. PASS();
  271. }
  272. std::string TestFileIO::TestReadWriteSetLength() {
  273. TestCompletionCallback callback(instance_->pp_instance(), callback_type());
  274. pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
  275. pp::FileRef file_ref(file_system, "/file_read_write_setlength");
  276. callback.WaitForResult(file_system.Open(1024, callback.GetCallback()));
  277. CHECK_CALLBACK_BEHAVIOR(callback);
  278. ASSERT_EQ(PP_OK, callback.result());
  279. pp::FileIO file_io(instance_);
  280. callback.WaitForResult(file_io.Open(file_ref,
  281. PP_FILEOPENFLAG_CREATE |
  282. PP_FILEOPENFLAG_TRUNCATE |
  283. PP_FILEOPENFLAG_READ |
  284. PP_FILEOPENFLAG_WRITE,
  285. callback.GetCallback()));
  286. CHECK_CALLBACK_BEHAVIOR(callback);
  287. ASSERT_EQ(PP_OK, callback.result());
  288. // Write something to the file.
  289. int32_t rv = WriteEntireBuffer(instance_->pp_instance(), &file_io, 0,
  290. "test_test", callback_type());
  291. ASSERT_EQ(PP_OK, rv);
  292. // Attempt to read a negative number of bytes; it should fail.
  293. char buf[256];
  294. callback.WaitForResult(file_io.Read(0,
  295. buf,
  296. -1,
  297. callback.GetCallback()));
  298. CHECK_CALLBACK_BEHAVIOR(callback);
  299. ASSERT_EQ(PP_ERROR_FAILED, callback.result());
  300. // Read the entire file.
  301. std::string read_buffer;
  302. rv = ReadEntireFile(instance_->pp_instance(), &file_io, 0, &read_buffer,
  303. callback_type());
  304. ASSERT_EQ(PP_OK, rv);
  305. ASSERT_EQ(std::string("test_test"), read_buffer);
  306. // Truncate the file.
  307. callback.WaitForResult(file_io.SetLength(4, callback.GetCallback()));
  308. CHECK_CALLBACK_BEHAVIOR(callback);
  309. ASSERT_EQ(PP_OK, callback.result());
  310. // Check the file contents.
  311. read_buffer.clear();
  312. rv = ReadEntireFile(instance_->pp_instance(), &file_io, 0, &read_buffer,
  313. callback_type());
  314. ASSERT_EQ(PP_OK, rv);
  315. ASSERT_EQ(std::string("test"), read_buffer);
  316. // Try to read past the end of the file.
  317. read_buffer.clear();
  318. rv = ReadEntireFile(instance_->pp_instance(), &file_io, 100, &read_buffer,
  319. callback_type());
  320. ASSERT_EQ(PP_OK, rv);
  321. ASSERT_TRUE(read_buffer.empty());
  322. // Write past the end of the file. The file should be zero-padded.
  323. rv = WriteEntireBuffer(instance_->pp_instance(), &file_io, 8, "test",
  324. callback_type());
  325. ASSERT_EQ(PP_OK, rv);
  326. // Check the contents of the file.
  327. read_buffer.clear();
  328. rv = ReadEntireFile(instance_->pp_instance(), &file_io, 0, &read_buffer,
  329. callback_type());
  330. ASSERT_EQ(PP_OK, rv);
  331. ASSERT_EQ(std::string("test\0\0\0\0test", 12), read_buffer);
  332. // Extend the file.
  333. callback.WaitForResult(file_io.SetLength(16, callback.GetCallback()));
  334. CHECK_CALLBACK_BEHAVIOR(callback);
  335. ASSERT_EQ(PP_OK, callback.result());
  336. // Check the contents of the file.
  337. read_buffer.clear();
  338. rv = ReadEntireFile(instance_->pp_instance(), &file_io, 0, &read_buffer,
  339. callback_type());
  340. ASSERT_EQ(PP_OK, rv);
  341. ASSERT_EQ(std::string("test\0\0\0\0test\0\0\0\0", 16), read_buffer);
  342. // Write in the middle of the file.
  343. rv = WriteEntireBuffer(instance_->pp_instance(), &file_io, 4, "test",
  344. callback_type());
  345. ASSERT_EQ(PP_OK, rv);
  346. // Check the contents of the file.
  347. read_buffer.clear();
  348. rv = ReadEntireFile(instance_->pp_instance(), &file_io, 0, &read_buffer,
  349. callback_type());
  350. ASSERT_EQ(PP_OK, rv);
  351. ASSERT_EQ(std::string("testtesttest\0\0\0\0", 16), read_buffer);
  352. // Read from the middle of the file.
  353. read_buffer.clear();
  354. rv = ReadEntireFile(instance_->pp_instance(), &file_io, 4, &read_buffer,
  355. callback_type());
  356. ASSERT_EQ(PP_OK, rv);
  357. ASSERT_EQ(std::string("testtest\0\0\0\0", 12), read_buffer);
  358. // Append to the end of the file.
  359. pp::FileIO file_io2(instance_);
  360. callback.WaitForResult(file_io2.Open(file_ref,
  361. PP_FILEOPENFLAG_CREATE |
  362. PP_FILEOPENFLAG_READ |
  363. PP_FILEOPENFLAG_APPEND,
  364. callback.GetCallback()));
  365. rv = WriteEntireBuffer(instance_->pp_instance(), &file_io2, 0, "appended",
  366. callback_type());
  367. ASSERT_EQ(PP_OK, rv);
  368. read_buffer.clear();
  369. rv = ReadEntireFile(instance_->pp_instance(), &file_io2, 0, &read_buffer,
  370. callback_type());
  371. ASSERT_EQ(PP_OK, rv);
  372. ASSERT_EQ(std::string("testtesttest\0\0\0\0appended", 24), read_buffer);
  373. PASS();
  374. }
  375. // This is basically a copy of TestReadWriteSetLength, but with the new Read
  376. // API. With this test case, we can make sure the two Read's have the same
  377. // behavior.
  378. std::string TestFileIO::TestReadToArrayWriteSetLength() {
  379. if (callback_type() == PP_BLOCKING) {
  380. // This test does not make sense for blocking callbacks.
  381. PASS();
  382. }
  383. TestCompletionCallback callback(instance_->pp_instance(), callback_type());
  384. pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
  385. pp::FileRef file_ref(file_system, "/file_read_write_setlength");
  386. callback.WaitForResult(file_system.Open(1024, callback.GetCallback()));
  387. CHECK_CALLBACK_BEHAVIOR(callback);
  388. ASSERT_EQ(PP_OK, callback.result());
  389. pp::FileIO file_io(instance_);
  390. callback.WaitForResult(file_io.Open(file_ref,
  391. PP_FILEOPENFLAG_CREATE |
  392. PP_FILEOPENFLAG_TRUNCATE |
  393. PP_FILEOPENFLAG_READ |
  394. PP_FILEOPENFLAG_WRITE,
  395. callback.GetCallback()));
  396. CHECK_CALLBACK_BEHAVIOR(callback);
  397. ASSERT_EQ(PP_OK, callback.result());
  398. // Write something to the file.
  399. int32_t rv = WriteEntireBuffer(instance_->pp_instance(), &file_io, 0,
  400. "test_test", callback_type());
  401. ASSERT_EQ(PP_OK, rv);
  402. TestCompletionCallbackWithOutput< std::vector<char> > callback2(
  403. instance_->pp_instance(), callback_type());
  404. // Attempt to read a negative number of bytes; it should fail.
  405. callback2.WaitForResult(file_io.Read(0, -1, callback2.GetCallback()));
  406. CHECK_CALLBACK_BEHAVIOR(callback2);
  407. ASSERT_EQ(PP_ERROR_FAILED, callback2.result());
  408. // Read the entire file.
  409. std::string read_buffer;
  410. read_buffer.reserve(10);
  411. rv = ReadToArrayEntireFile(instance_->pp_instance(), &file_io, 0,
  412. &read_buffer, callback_type());
  413. ASSERT_EQ(PP_OK, rv);
  414. ASSERT_EQ(std::string("test_test"), read_buffer);
  415. // Truncate the file.
  416. callback.WaitForResult(file_io.SetLength(4, callback.GetCallback()));
  417. CHECK_CALLBACK_BEHAVIOR(callback);
  418. ASSERT_EQ(PP_OK, rv);
  419. // Check the file contents.
  420. read_buffer.clear();
  421. rv = ReadToArrayEntireFile(instance_->pp_instance(), &file_io, 0,
  422. &read_buffer, callback_type());
  423. ASSERT_EQ(PP_OK, rv);
  424. ASSERT_EQ(std::string("test"), read_buffer);
  425. // Try to read past the end of the file.
  426. read_buffer.clear();
  427. rv = ReadToArrayEntireFile(instance_->pp_instance(), &file_io, 100,
  428. &read_buffer, callback_type());
  429. ASSERT_EQ(PP_OK, rv);
  430. ASSERT_TRUE(read_buffer.empty());
  431. // Write past the end of the file. The file should be zero-padded.
  432. rv = WriteEntireBuffer(instance_->pp_instance(), &file_io, 8, "test",
  433. callback_type());
  434. ASSERT_EQ(PP_OK, rv);
  435. // Check the contents of the file.
  436. read_buffer.clear();
  437. rv = ReadToArrayEntireFile(instance_->pp_instance(), &file_io, 0,
  438. &read_buffer, callback_type());
  439. ASSERT_EQ(PP_OK, rv);
  440. ASSERT_EQ(std::string("test\0\0\0\0test", 12), read_buffer);
  441. // Extend the file.
  442. callback.WaitForResult(file_io.SetLength(16, callback.GetCallback()));
  443. CHECK_CALLBACK_BEHAVIOR(callback);
  444. ASSERT_EQ(PP_OK, callback.result());
  445. // Check the contents of the file.
  446. read_buffer.clear();
  447. rv = ReadToArrayEntireFile(instance_->pp_instance(), &file_io, 0,
  448. &read_buffer, callback_type());
  449. ASSERT_EQ(PP_OK, rv);
  450. ASSERT_EQ(std::string("test\0\0\0\0test\0\0\0\0", 16), read_buffer);
  451. // Write in the middle of the file.
  452. rv = WriteEntireBuffer(instance_->pp_instance(), &file_io, 4, "test",
  453. callback_type());
  454. ASSERT_EQ(PP_OK, rv);
  455. // Check the contents of the file.
  456. read_buffer.clear();
  457. rv = ReadToArrayEntireFile(instance_->pp_instance(), &file_io, 0,
  458. &read_buffer, callback_type());
  459. ASSERT_EQ(PP_OK, rv);
  460. ASSERT_EQ(std::string("testtesttest\0\0\0\0", 16), read_buffer);
  461. // Read from the middle of the file.
  462. read_buffer.clear();
  463. rv = ReadToArrayEntireFile(instance_->pp_instance(), &file_io, 4,
  464. &read_buffer, callback_type());
  465. ASSERT_EQ(PP_OK, rv);
  466. ASSERT_EQ(std::string("testtest\0\0\0\0", 12), read_buffer);
  467. PASS();
  468. }
  469. std::string TestFileIO::TestTouchQuery() {
  470. TestCompletionCallback callback(instance_->pp_instance(), callback_type());
  471. pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
  472. callback.WaitForResult(file_system.Open(1024, callback.GetCallback()));
  473. CHECK_CALLBACK_BEHAVIOR(callback);
  474. ASSERT_EQ(PP_OK, callback.result());
  475. pp::FileRef file_ref(file_system, "/file_touch");
  476. pp::FileIO file_io(instance_);
  477. callback.WaitForResult(file_io.Open(file_ref,
  478. PP_FILEOPENFLAG_CREATE |
  479. PP_FILEOPENFLAG_TRUNCATE |
  480. PP_FILEOPENFLAG_WRITE,
  481. callback.GetCallback()));
  482. CHECK_CALLBACK_BEHAVIOR(callback);
  483. ASSERT_EQ(PP_OK, callback.result());
  484. // Write some data to have a non-zero file size.
  485. callback.WaitForResult(file_io.Write(0, "test", 4, callback.GetCallback()));
  486. CHECK_CALLBACK_BEHAVIOR(callback);
  487. ASSERT_EQ(4, callback.result());
  488. const PP_Time last_access_time = 123 * 24 * 3600.0;
  489. // last_modified_time's granularity is 2 seconds
  490. // NOTE: In NaCl on Windows, NaClDescIO uses _fstat64 to retrieve file info.
  491. // This function returns strange values for very small time values (near the
  492. // Unix Epoch). For a value like 246.0, it returns -1. For larger values, it
  493. // returns values that are exactly an hour less. The value below is handled
  494. // correctly, and is only 100 days after the start of Unix time.
  495. const PP_Time last_modified_time = 100 * 24 * 3600.0;
  496. callback.WaitForResult(file_io.Touch(last_access_time, last_modified_time,
  497. callback.GetCallback()));
  498. CHECK_CALLBACK_BEHAVIOR(callback);
  499. ASSERT_EQ(PP_OK, callback.result());
  500. PP_FileInfo info;
  501. callback.WaitForResult(file_io.Query(&info, callback.GetCallback()));
  502. CHECK_CALLBACK_BEHAVIOR(callback);
  503. ASSERT_EQ(PP_OK, callback.result());
  504. if ((info.size != 4) ||
  505. (info.type != PP_FILETYPE_REGULAR) ||
  506. (info.system_type != PP_FILESYSTEMTYPE_LOCALTEMPORARY))
  507. // Disabled due to DST-related failure: crbug.com/314579
  508. //(info.last_access_time != last_access_time) ||
  509. //(info.last_modified_time != last_modified_time))
  510. return "FileIO::Query() has returned bad data.";
  511. // Call |Query()| again, to make sure it works a second time.
  512. callback.WaitForResult(file_io.Query(&info, callback.GetCallback()));
  513. CHECK_CALLBACK_BEHAVIOR(callback);
  514. ASSERT_EQ(PP_OK, callback.result());
  515. PASS();
  516. }
  517. std::string TestFileIO::TestAbortCalls() {
  518. TestCompletionCallback callback(instance_->pp_instance(), callback_type());
  519. pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
  520. pp::FileRef file_ref(file_system, "/file_abort_calls");
  521. callback.WaitForResult(file_system.Open(1024, callback.GetCallback()));
  522. CHECK_CALLBACK_BEHAVIOR(callback);
  523. ASSERT_EQ(PP_OK, callback.result());
  524. int32_t rv = PP_ERROR_FAILED;
  525. // First, create a file on which to do ops.
  526. {
  527. pp::FileIO file_io(instance_);
  528. callback.WaitForResult(
  529. file_io.Open(file_ref,
  530. PP_FILEOPENFLAG_CREATE | PP_FILEOPENFLAG_WRITE,
  531. callback.GetCallback()));
  532. CHECK_CALLBACK_BEHAVIOR(callback);
  533. ASSERT_EQ(PP_OK, callback.result());
  534. // N.B.: Should write at least 3 bytes.
  535. rv = WriteEntireBuffer(instance_->pp_instance(), &file_io, 0,
  536. "foobarbazquux", callback_type());
  537. ASSERT_EQ(PP_OK, rv);
  538. }
  539. // Abort |Open()|.
  540. {
  541. rv = pp::FileIO(instance_)
  542. .Open(file_ref, PP_FILEOPENFLAG_READ, callback.GetCallback());
  543. }
  544. callback.WaitForAbortResult(rv);
  545. CHECK_CALLBACK_BEHAVIOR(callback);
  546. // Abort |Query()|.
  547. {
  548. PP_FileInfo info = { 0 };
  549. // Save a copy and make sure |info| doesn't get written to if it is aborted.
  550. PP_FileInfo info_copy;
  551. memcpy(&info_copy, &info, sizeof(info));
  552. {
  553. pp::FileIO file_io(instance_);
  554. callback.WaitForResult(file_io.Open(file_ref, PP_FILEOPENFLAG_READ,
  555. callback.GetCallback()));
  556. CHECK_CALLBACK_BEHAVIOR(callback);
  557. ASSERT_EQ(PP_OK, callback.result());
  558. rv = file_io.Query(&info, callback.GetCallback());
  559. } // Destroy |file_io|.
  560. callback.WaitForResult(rv);
  561. CHECK_CALLBACK_BEHAVIOR(callback);
  562. if (callback_type() == PP_BLOCKING) {
  563. ASSERT_EQ(PP_OK, callback.result());
  564. // The operation completed synchronously, so |info| should have changed.
  565. ASSERT_NE(0, memcmp(&info_copy, &info, sizeof(info)));
  566. } else {
  567. ASSERT_EQ(PP_ERROR_ABORTED, callback.result());
  568. ASSERT_EQ(0, memcmp(&info_copy, &info, sizeof(info)));
  569. }
  570. }
  571. // Abort |Touch()|.
  572. {
  573. {
  574. pp::FileIO file_io(instance_);
  575. callback.WaitForResult(file_io.Open(file_ref, PP_FILEOPENFLAG_WRITE,
  576. callback.GetCallback()));
  577. CHECK_CALLBACK_BEHAVIOR(callback);
  578. ASSERT_EQ(PP_OK, callback.result());
  579. rv = file_io.Touch(0, 0, callback.GetCallback());
  580. } // Destroy |file_io|.
  581. callback.WaitForAbortResult(rv);
  582. CHECK_CALLBACK_BEHAVIOR(callback);
  583. }
  584. // Abort |Read()|.
  585. {
  586. char buf[3] = { 0 };
  587. {
  588. pp::FileIO file_io(instance_);
  589. callback.WaitForResult(file_io.Open(file_ref, PP_FILEOPENFLAG_READ,
  590. callback.GetCallback()));
  591. CHECK_CALLBACK_BEHAVIOR(callback);
  592. ASSERT_EQ(PP_OK, callback.result());
  593. rv = file_io.Read(0, buf, sizeof(buf), callback.GetCallback());
  594. } // Destroy |file_io|.
  595. // Save a copy to make sure buf isn't written to in the async case.
  596. char buf_copy[3];
  597. memcpy(&buf_copy, &buf, sizeof(buf));
  598. callback.WaitForResult(rv);
  599. CHECK_CALLBACK_BEHAVIOR(callback);
  600. if (callback_type() == PP_BLOCKING) {
  601. ASSERT_EQ(callback.result(), sizeof(buf));
  602. } else {
  603. ASSERT_EQ(PP_ERROR_ABORTED, callback.result());
  604. ASSERT_EQ(0, memcmp(&buf_copy, &buf, sizeof(buf)));
  605. }
  606. }
  607. // Abort |Write()|.
  608. {
  609. char buf[3] = { 0 };
  610. {
  611. pp::FileIO file_io(instance_);
  612. callback.WaitForResult(file_io.Open(file_ref, PP_FILEOPENFLAG_WRITE,
  613. callback.GetCallback()));
  614. CHECK_CALLBACK_BEHAVIOR(callback);
  615. ASSERT_EQ(PP_OK, callback.result());
  616. rv = file_io.Write(0, buf, sizeof(buf), callback.GetCallback());
  617. } // Destroy |file_io|.
  618. callback.WaitForResult(rv);
  619. CHECK_CALLBACK_BEHAVIOR(callback);
  620. if (callback_type() == PP_BLOCKING)
  621. ASSERT_EQ(callback.result(), sizeof(buf));
  622. else
  623. ASSERT_EQ(PP_ERROR_ABORTED, callback.result());
  624. }
  625. // Abort |SetLength()|.
  626. {
  627. {
  628. pp::FileIO file_io(instance_);
  629. callback.WaitForResult(file_io.Open(file_ref, PP_FILEOPENFLAG_WRITE,
  630. callback.GetCallback()));
  631. CHECK_CALLBACK_BEHAVIOR(callback);
  632. ASSERT_EQ(PP_OK, callback.result());
  633. rv = file_io.SetLength(3, callback.GetCallback());
  634. } // Destroy |file_io|.
  635. callback.WaitForAbortResult(rv);
  636. CHECK_CALLBACK_BEHAVIOR(callback);
  637. }
  638. // Abort |Flush|.
  639. {
  640. {
  641. pp::FileIO file_io(instance_);
  642. callback.WaitForResult(file_io.Open(file_ref, PP_FILEOPENFLAG_WRITE,
  643. callback.GetCallback()));
  644. CHECK_CALLBACK_BEHAVIOR(callback);
  645. ASSERT_EQ(PP_OK, callback.result());
  646. rv = file_io.Flush(callback.GetCallback());
  647. } // Destroy |file_io|.
  648. callback.WaitForAbortResult(rv);
  649. CHECK_CALLBACK_BEHAVIOR(callback);
  650. }
  651. PASS();
  652. }
  653. std::string TestFileIO::TestParallelReads() {
  654. TestCompletionCallback callback(instance_->pp_instance(), callback_type());
  655. pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
  656. pp::FileRef file_ref(file_system, "/file_parallel_reads");
  657. callback.WaitForResult(file_system.Open(1024, callback.GetCallback()));
  658. CHECK_CALLBACK_BEHAVIOR(callback);
  659. ASSERT_EQ(PP_OK, callback.result());
  660. pp::FileIO file_io(instance_);
  661. callback.WaitForResult(file_io.Open(file_ref,
  662. PP_FILEOPENFLAG_CREATE |
  663. PP_FILEOPENFLAG_TRUNCATE |
  664. PP_FILEOPENFLAG_READ |
  665. PP_FILEOPENFLAG_WRITE,
  666. callback.GetCallback()));
  667. CHECK_CALLBACK_BEHAVIOR(callback);
  668. ASSERT_EQ(PP_OK, callback.result());
  669. // Set up testing contents.
  670. int32_t rv = WriteEntireBuffer(instance_->pp_instance(), &file_io, 0,
  671. "abcdefghijkl", callback_type());
  672. ASSERT_EQ(PP_OK, rv);
  673. // Parallel read operations.
  674. const char* border = "__border__";
  675. const int32_t border_size = static_cast<int32_t>(strlen(border));
  676. TestCompletionCallback callback_1(instance_->pp_instance(), callback_type());
  677. int32_t read_offset_1 = 0;
  678. int32_t size_1 = 3;
  679. std::vector<char> extended_buf_1(border_size * 2 + size_1);
  680. char* buf_1 = &extended_buf_1[border_size];
  681. memcpy(&extended_buf_1[0], border, border_size);
  682. memcpy(buf_1 + size_1, border, border_size);
  683. TestCompletionCallback callback_2(instance_->pp_instance(), callback_type());
  684. int32_t read_offset_2 = size_1;
  685. int32_t size_2 = 9;
  686. std::vector<char> extended_buf_2(border_size * 2 + size_2);
  687. char* buf_2 = &extended_buf_2[border_size];
  688. memcpy(&extended_buf_2[0], border, border_size);
  689. memcpy(buf_2 + size_2, border, border_size);
  690. int32_t rv_1 = PP_OK;
  691. int32_t rv_2 = PP_OK;
  692. while (size_1 >= 0 && size_2 >= 0 && size_1 + size_2 > 0) {
  693. if (size_1 > 0) {
  694. rv_1 = file_io.Read(read_offset_1, buf_1, size_1,
  695. callback_1.GetCallback());
  696. }
  697. if (size_2 > 0) {
  698. rv_2 = file_io.Read(read_offset_2, buf_2, size_2,
  699. callback_2.GetCallback());
  700. }
  701. if (size_1 > 0) {
  702. callback_1.WaitForResult(rv_1);
  703. CHECK_CALLBACK_BEHAVIOR(callback_1);
  704. ASSERT_TRUE(callback_1.result() > 0);
  705. read_offset_1 += callback_1.result();
  706. buf_1 += callback_1.result();
  707. size_1 -= callback_1.result();
  708. }
  709. if (size_2 > 0) {
  710. callback_2.WaitForResult(rv_2);
  711. CHECK_CALLBACK_BEHAVIOR(callback_2);
  712. ASSERT_TRUE(callback_2.result() > 0);
  713. read_offset_2 += callback_2.result();
  714. buf_2 += callback_2.result();
  715. size_2 -= callback_2.result();
  716. }
  717. }
  718. // If |size_1| or |size_2| is not 0, we have invoked wrong callback(s).
  719. ASSERT_EQ(0, size_1);
  720. ASSERT_EQ(0, size_2);
  721. // Make sure every read operation writes into the correct buffer.
  722. const char expected_result_1[] = "__border__abc__border__";
  723. const char expected_result_2[] = "__border__defghijkl__border__";
  724. ASSERT_TRUE(strncmp(&extended_buf_1[0], expected_result_1,
  725. strlen(expected_result_1)) == 0);
  726. ASSERT_TRUE(strncmp(&extended_buf_2[0], expected_result_2,
  727. strlen(expected_result_2)) == 0);
  728. PASS();
  729. }
  730. std::string TestFileIO::TestParallelWrites() {
  731. TestCompletionCallback callback(instance_->pp_instance(), callback_type());
  732. pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
  733. pp::FileRef file_ref(file_system, "/file_parallel_writes");
  734. callback.WaitForResult(file_system.Open(1024, callback.GetCallback()));
  735. CHECK_CALLBACK_BEHAVIOR(callback);
  736. ASSERT_EQ(PP_OK, callback.result());
  737. pp::FileIO file_io(instance_);
  738. callback.WaitForResult(file_io.Open(file_ref,
  739. PP_FILEOPENFLAG_CREATE |
  740. PP_FILEOPENFLAG_TRUNCATE |
  741. PP_FILEOPENFLAG_READ |
  742. PP_FILEOPENFLAG_WRITE,
  743. callback.GetCallback()));
  744. CHECK_CALLBACK_BEHAVIOR(callback);
  745. ASSERT_EQ(PP_OK, callback.result());
  746. // Parallel write operations.
  747. TestCompletionCallback callback_1(instance_->pp_instance(), callback_type());
  748. int32_t write_offset_1 = 0;
  749. const char* buf_1 = "abc";
  750. int32_t size_1 = static_cast<int32_t>(strlen(buf_1));
  751. TestCompletionCallback callback_2(instance_->pp_instance(), callback_type());
  752. int32_t write_offset_2 = size_1;
  753. const char* buf_2 = "defghijkl";
  754. int32_t size_2 = static_cast<int32_t>(strlen(buf_2));
  755. int32_t rv_1 = PP_OK;
  756. int32_t rv_2 = PP_OK;
  757. while (size_1 >= 0 && size_2 >= 0 && size_1 + size_2 > 0) {
  758. if (size_1 > 0) {
  759. // Copy the buffer so we can erase it below.
  760. std::string str_1(buf_1);
  761. rv_1 = file_io.Write(
  762. write_offset_1, &str_1[0], static_cast<int32_t>(str_1.size()),
  763. callback_1.GetCallback());
  764. // Erase the buffer to test that async writes copy it.
  765. std::fill(str_1.begin(), str_1.end(), 0);
  766. }
  767. if (size_2 > 0) {
  768. // Copy the buffer so we can erase it below.
  769. std::string str_2(buf_2);
  770. rv_2 = file_io.Write(
  771. write_offset_2, &str_2[0], static_cast<int32_t>(str_2.size()),
  772. callback_2.GetCallback());
  773. // Erase the buffer to test that async writes copy it.
  774. std::fill(str_2.begin(), str_2.end(), 0);
  775. }
  776. if (size_1 > 0) {
  777. callback_1.WaitForResult(rv_1);
  778. CHECK_CALLBACK_BEHAVIOR(callback_1);
  779. ASSERT_TRUE(callback_1.result() > 0);
  780. write_offset_1 += callback_1.result();
  781. buf_1 += callback_1.result();
  782. size_1 -= callback_1.result();
  783. }
  784. if (size_2 > 0) {
  785. callback_2.WaitForResult(rv_2);
  786. CHECK_CALLBACK_BEHAVIOR(callback_2);
  787. ASSERT_TRUE(callback_2.result() > 0);
  788. write_offset_2 += callback_2.result();
  789. buf_2 += callback_2.result();
  790. size_2 -= callback_2.result();
  791. }
  792. }
  793. // If |size_1| or |size_2| is not 0, we have invoked wrong callback(s).
  794. ASSERT_EQ(0, size_1);
  795. ASSERT_EQ(0, size_2);
  796. // Check the file contents.
  797. std::string read_buffer;
  798. int32_t rv = ReadEntireFile(instance_->pp_instance(), &file_io, 0,
  799. &read_buffer, callback_type());
  800. ASSERT_EQ(PP_OK, rv);
  801. ASSERT_EQ(std::string("abcdefghijkl"), read_buffer);
  802. PASS();
  803. }
  804. std::string TestFileIO::TestNotAllowMixedReadWrite() {
  805. if (callback_type() == PP_BLOCKING) {
  806. // This test does not make sense for blocking callbacks.
  807. PASS();
  808. }
  809. TestCompletionCallback callback(instance_->pp_instance(), callback_type());
  810. pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
  811. pp::FileRef file_ref(file_system, "/file_not_allow_mixed_read_write");
  812. callback.WaitForResult(file_system.Open(1024, callback.GetCallback()));
  813. CHECK_CALLBACK_BEHAVIOR(callback);
  814. ASSERT_EQ(PP_OK, callback.result());
  815. pp::FileIO file_io(instance_);
  816. callback.WaitForResult(file_io.Open(file_ref,
  817. PP_FILEOPENFLAG_CREATE |
  818. PP_FILEOPENFLAG_TRUNCATE |
  819. PP_FILEOPENFLAG_READ |
  820. PP_FILEOPENFLAG_WRITE,
  821. callback.GetCallback()));
  822. CHECK_CALLBACK_BEHAVIOR(callback);
  823. ASSERT_EQ(PP_OK, callback.result());
  824. TestCompletionCallback callback_1(instance_->pp_instance(), PP_REQUIRED);
  825. int32_t write_offset_1 = 0;
  826. const char* buf_1 = "mnopqrstuvw";
  827. int32_t rv_1 = file_io.Write(write_offset_1, buf_1,
  828. static_cast<int32_t>(strlen(buf_1)),
  829. callback_1.GetCallback());
  830. ASSERT_EQ(PP_OK_COMPLETIONPENDING, rv_1);
  831. TestCompletionCallback callback_2(instance_->pp_instance(), callback_type());
  832. int32_t read_offset_2 = 4;
  833. char buf_2[3];
  834. callback_2.WaitForResult(file_io.Read(read_offset_2, buf_2, sizeof(buf_2),
  835. callback_2.GetCallback()));
  836. CHECK_CALLBACK_BEHAVIOR(callback_2);
  837. ASSERT_EQ(PP_ERROR_INPROGRESS, callback_2.result());
  838. callback_1.WaitForResult(rv_1);
  839. CHECK_CALLBACK_BEHAVIOR(callback_1);
  840. // Cannot query while a write is pending.
  841. rv_1 = file_io.Write(write_offset_1, buf_1,
  842. static_cast<int32_t>(strlen(buf_1)),
  843. callback_1.GetCallback());
  844. ASSERT_EQ(PP_OK_COMPLETIONPENDING, rv_1);
  845. PP_FileInfo info;
  846. callback_2.WaitForResult(file_io.Query(&info, callback_2.GetCallback()));
  847. CHECK_CALLBACK_BEHAVIOR(callback_2);
  848. ASSERT_EQ(PP_ERROR_INPROGRESS, callback_2.result());
  849. callback_1.WaitForResult(rv_1);
  850. CHECK_CALLBACK_BEHAVIOR(callback_1);
  851. // Cannot touch while a write is pending.
  852. rv_1 = file_io.Write(write_offset_1, buf_1,
  853. static_cast<int32_t>(strlen(buf_1)),
  854. callback_1.GetCallback());
  855. ASSERT_EQ(PP_OK_COMPLETIONPENDING, rv_1);
  856. callback_2.WaitForResult(file_io.Touch(1234.0, 5678.0,
  857. callback_2.GetCallback()));
  858. CHECK_CALLBACK_BEHAVIOR(callback_2);
  859. ASSERT_EQ(PP_ERROR_INPROGRESS, callback_2.result());
  860. callback_1.WaitForResult(rv_1);
  861. CHECK_CALLBACK_BEHAVIOR(callback_1);
  862. // Cannot set length while a write is pending.
  863. rv_1 = file_io.Write(write_offset_1, buf_1,
  864. static_cast<int32_t>(strlen(buf_1)),
  865. callback_1.GetCallback());
  866. ASSERT_EQ(PP_OK_COMPLETIONPENDING, rv_1);
  867. callback_2.WaitForResult(file_io.SetLength(123, callback_2.GetCallback()));
  868. CHECK_CALLBACK_BEHAVIOR(callback_2);
  869. ASSERT_EQ(PP_ERROR_INPROGRESS, callback_2.result());
  870. callback_1.WaitForResult(rv_1);
  871. CHECK_CALLBACK_BEHAVIOR(callback_1);
  872. PASS();
  873. }
  874. std::string TestFileIO::TestRequestOSFileHandle() {
  875. TestCompletionCallback callback(instance_->pp_instance(), callback_type());
  876. pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
  877. pp::FileRef file_ref(file_system, "/file_os_fd");
  878. callback.WaitForResult(file_system.Open(1024, callback.GetCallback()));
  879. ASSERT_EQ(PP_OK, callback.result());
  880. pp::FileIO_Private file_io(instance_);
  881. callback.WaitForResult(file_io.Open(file_ref,
  882. PP_FILEOPENFLAG_CREATE |
  883. PP_FILEOPENFLAG_TRUNCATE |
  884. PP_FILEOPENFLAG_READ |
  885. PP_FILEOPENFLAG_WRITE,
  886. callback.GetCallback()));
  887. ASSERT_EQ(PP_OK, callback.result());
  888. TestCompletionCallbackWithOutput<pp::PassFileHandle> output_callback(
  889. instance_->pp_instance(), callback_type());
  890. output_callback.WaitForResult(
  891. file_io.RequestOSFileHandle(output_callback.GetCallback()));
  892. PP_FileHandle handle = output_callback.output().Release();
  893. ASSERT_EQ(PP_OK, output_callback.result());
  894. if (handle == PP_kInvalidFileHandle)
  895. return "FileIO::RequestOSFileHandle() returned a bad file handle.";
  896. #if defined(PPAPI_OS_WIN)
  897. int fd = _open_osfhandle(reinterpret_cast<intptr_t>(handle),
  898. _O_RDWR | _O_BINARY);
  899. #else
  900. int fd = handle;
  901. #endif
  902. if (fd < 0)
  903. return "FileIO::RequestOSFileHandle() returned a bad file descriptor.";
  904. // Check write(2) for the native FD.
  905. const std::string msg = "foobar";
  906. ssize_t cnt = write(fd, msg.data(), static_cast<unsigned>(msg.size()));
  907. if (cnt < 0)
  908. return ReportError("write for native FD returned error", errno);
  909. if (cnt != static_cast<ssize_t>(msg.size()))
  910. return ReportError("write for native FD count mismatch", cnt);
  911. // Check lseek(2) for the native FD.
  912. off_t off = lseek(fd, 0, SEEK_CUR);
  913. if (off == static_cast<off_t>(-1))
  914. return ReportError("lseek for native FD returned error", errno);
  915. if (off != static_cast<off_t>(msg.size()))
  916. return ReportError("lseek for native FD offset mismatch", off);
  917. off = lseek(fd, 0, SEEK_SET);
  918. if (off == static_cast<off_t>(-1))
  919. return ReportError("lseek for native FD returned error", errno);
  920. if (off != 0)
  921. return ReportError("lseek for native FD offset mismatch", off);
  922. // Check read(2) for the native FD.
  923. std::string buf(msg.size(), '\0');
  924. cnt = read(fd, &buf[0], static_cast<unsigned>(msg.size()));
  925. if (cnt < 0)
  926. return ReportError("read for native FD returned error", errno);
  927. if (cnt != static_cast<ssize_t>(msg.size()))
  928. return ReportError("read for native FD count mismatch", cnt);
  929. if (msg != buf)
  930. return ReportMismatch("read for native FD", buf, msg);
  931. PASS();
  932. }
  933. // Calling RequestOSFileHandle with the FileIO that is opened with
  934. // PP_FILEOPENFLAG_EXCLUSIVE used to cause NaCl module to crash while loading.
  935. // This is a regression test for crbug.com/243241.
  936. std::string TestFileIO::TestRequestOSFileHandleWithOpenExclusive() {
  937. TestCompletionCallback callback(instance_->pp_instance(), callback_type());
  938. pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
  939. pp::FileRef file_ref(file_system, "/file_os_fd2");
  940. callback.WaitForResult(file_system.Open(1024, callback.GetCallback()));
  941. ASSERT_EQ(PP_OK, callback.result());
  942. // Open with PP_FILEOPENFLAG_CREATE and PP_FILEOPENFLAG_EXCLUSIVE will fail
  943. // if the file already exists. Delete it here to make sure it does not.
  944. callback.WaitForResult(file_ref.Delete(callback.GetCallback()));
  945. pp::FileIO_Private file_io(instance_);
  946. callback.WaitForResult(file_io.Open(file_ref,
  947. PP_FILEOPENFLAG_CREATE |
  948. PP_FILEOPENFLAG_READ |
  949. PP_FILEOPENFLAG_WRITE |
  950. PP_FILEOPENFLAG_EXCLUSIVE,
  951. callback.GetCallback()));
  952. ASSERT_EQ(PP_OK, callback.result());
  953. TestCompletionCallbackWithOutput<pp::PassFileHandle> output_callback(
  954. instance_->pp_instance(), callback_type());
  955. output_callback.WaitForResult(
  956. file_io.RequestOSFileHandle(output_callback.GetCallback()));
  957. PP_FileHandle handle = output_callback.output().Release();
  958. if (handle == PP_kInvalidFileHandle)
  959. return "FileIO::RequestOSFileHandle() returned a bad file handle.";
  960. ASSERT_EQ(PP_OK, output_callback.result());
  961. PASS();
  962. }
  963. std::string TestFileIO::TestMmap() {
  964. #if !defined(PPAPI_OS_WIN)
  965. TestCompletionCallback callback(instance_->pp_instance(), callback_type());
  966. pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
  967. pp::FileRef file_ref(file_system, "/file_os_fd");
  968. callback.WaitForResult(file_system.Open(1024, callback.GetCallback()));
  969. ASSERT_EQ(PP_OK, callback.result());
  970. pp::FileIO_Private file_io(instance_);
  971. callback.WaitForResult(file_io.Open(file_ref,
  972. PP_FILEOPENFLAG_CREATE |
  973. PP_FILEOPENFLAG_TRUNCATE |
  974. PP_FILEOPENFLAG_READ |
  975. PP_FILEOPENFLAG_WRITE,
  976. callback.GetCallback()));
  977. ASSERT_EQ(PP_OK, callback.result());
  978. TestCompletionCallbackWithOutput<pp::PassFileHandle> output_callback(
  979. instance_->pp_instance(), callback_type());
  980. output_callback.WaitForResult(
  981. file_io.RequestOSFileHandle(output_callback.GetCallback()));
  982. PP_FileHandle handle = output_callback.output().Release();
  983. ASSERT_EQ(PP_OK, output_callback.result());
  984. if (handle == PP_kInvalidFileHandle)
  985. return "FileIO::RequestOSFileHandle() returned a bad file handle.";
  986. int fd = handle;
  987. if (fd < 0)
  988. return "FileIO::RequestOSFileHandle() returned a bad file descriptor.";
  989. // Check write(2) for the native FD.
  990. const std::string msg = "foobar";
  991. ssize_t cnt = write(fd, msg.data(), msg.size());
  992. if (cnt < 0)
  993. return ReportError("write for native FD returned error", errno);
  994. if (cnt != static_cast<ssize_t>(msg.size()))
  995. return ReportError("write for native FD count mismatch", cnt);
  996. // BEGIN mmap(2) test with a file handle opened in READ-WRITE mode.
  997. // Check mmap(2) for read.
  998. {
  999. char* mapped = reinterpret_cast<char*>(
  1000. mmap(NULL, msg.size(), PROT_READ, MAP_PRIVATE, fd, 0));
  1001. if (mapped == MAP_FAILED)
  1002. return ReportError("mmap(r) for native FD returned errno", errno);
  1003. // Make sure the buffer is cleared.
  1004. std::string buf = std::string(msg.size(), '\0');
  1005. memcpy(&buf[0], mapped, msg.size());
  1006. if (msg != buf)
  1007. return ReportMismatch("mmap(r) for native FD", buf, msg);
  1008. int r = munmap(mapped, msg.size());
  1009. if (r < 0)
  1010. return ReportError("munmap for native FD returned error", errno);
  1011. }
  1012. // Check mmap(2) for write with MAP_PRIVATE
  1013. {
  1014. char* mapped = reinterpret_cast<char*>(
  1015. mmap(NULL, msg.size(), PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0));
  1016. if (mapped == MAP_FAILED)
  1017. return ReportError("mmap(r) for native FD returned errno", errno);
  1018. // Make sure the file is not polluted by writing to privage mmap.
  1019. strncpy(mapped, "baz", 3);
  1020. std::string read_buffer;
  1021. ASSERT_TRUE(ReadEntireFileFromFileHandle(fd, &read_buffer));
  1022. if (msg != read_buffer)
  1023. return ReportMismatch("file content != msg", read_buffer, msg);
  1024. int r = munmap(mapped, msg.size());
  1025. if (r < 0)
  1026. return ReportError("munmap for native FD returned error", errno);
  1027. }
  1028. // Check mmap(2) for write with MAP_SHARED.
  1029. {
  1030. char* mapped = reinterpret_cast<char*>(
  1031. mmap(NULL, msg.size(), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
  1032. if (mapped == MAP_FAILED)
  1033. return ReportError("mmap(w) for native FD returned errno", errno);
  1034. // s/foo/baz/
  1035. strncpy(mapped, "baz", 3);
  1036. std::string read_buffer;
  1037. ASSERT_TRUE(ReadEntireFileFromFileHandle(fd, &read_buffer));
  1038. if (read_buffer != "bazbar")
  1039. return ReportMismatch("file content != msg", read_buffer, "bazbar");
  1040. int r = munmap(mapped, msg.size());
  1041. if (r < 0)
  1042. return ReportError("munmap for native FD returned error", errno);
  1043. }
  1044. // END mmap(2) test with a file handle opened in READ-WRITE mode.
  1045. if (close(fd) < 0)
  1046. return ReportError("close for native FD returned error", errno);
  1047. // BEGIN mmap(2) test with a file handle opened in READONLY mode.
  1048. file_io = pp::FileIO_Private(instance_);
  1049. callback.WaitForResult(file_io.Open(file_ref,
  1050. PP_FILEOPENFLAG_READ,
  1051. callback.GetCallback()));
  1052. ASSERT_EQ(PP_OK, callback.result());
  1053. output_callback = TestCompletionCallbackWithOutput<pp::PassFileHandle>(
  1054. instance_->pp_instance(), callback_type());
  1055. output_callback.WaitForResult(
  1056. file_io.RequestOSFileHandle(output_callback.GetCallback()));
  1057. handle = output_callback.output().Release();
  1058. ASSERT_EQ(PP_OK, output_callback.result());
  1059. if (handle == PP_kInvalidFileHandle)
  1060. return "FileIO::RequestOSFileHandle() returned a bad file handle.";
  1061. fd = handle;
  1062. if (fd < 0)
  1063. return "FileIO::RequestOSFileHandle() returned a bad file descriptor.";
  1064. const std::string msg2 = "bazbar";
  1065. // Check mmap(2) for read.
  1066. {
  1067. char* mapped = reinterpret_cast<char*>(
  1068. mmap(NULL, msg2.size(), PROT_READ, MAP_PRIVATE, fd, 0));
  1069. if (mapped == MAP_FAILED)
  1070. return ReportError("mmap(r) for native FD returned errno", errno);
  1071. // Make sure the buffer is cleared.
  1072. std::string buf = std::string(msg2.size(), '\0');
  1073. memcpy(&buf[0], mapped, msg2.size());
  1074. if (msg2 != buf)
  1075. return ReportMismatch("mmap(r) for native FD", buf, msg2);
  1076. int r = munmap(mapped, msg2.size());
  1077. if (r < 0)
  1078. return ReportError("munmap for native FD returned error", errno);
  1079. }
  1080. // Check mmap(2) for write with MAP_PRIVATE
  1081. {
  1082. char* mapped = reinterpret_cast<char*>(
  1083. mmap(NULL, msg2.size(), PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0));
  1084. if (mapped == MAP_FAILED)
  1085. return ReportError("mmap(r) for native FD returned errno", errno);
  1086. // Make sure the file is not polluted by writing to privage mmap.
  1087. strncpy(mapped, "baz", 3);
  1088. std::string read_buffer;
  1089. ASSERT_TRUE(ReadEntireFileFromFileHandle(fd, &read_buffer));
  1090. if (msg2 != read_buffer)
  1091. return ReportMismatch("file content != msg2", read_buffer, msg2);
  1092. int r = munmap(mapped, msg2.size());
  1093. if (r < 0)
  1094. return ReportError("munmap for native FD returned error", errno);
  1095. }
  1096. // Check mmap(2) for write with MAP_SHARED.
  1097. {
  1098. char* mapped = reinterpret_cast<char*>(
  1099. mmap(NULL, msg2.size(), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
  1100. if (mapped != MAP_FAILED)
  1101. return ReportError("mmap(w) for native FD must fail when opened readonly",
  1102. -1);
  1103. }
  1104. // END mmap(2) test with a file handle opened in READONLY mode.
  1105. if (close(fd) < 0)
  1106. return ReportError("close for native FD returned error", errno);
  1107. #endif // !defined(PPAPI_OS_WIN)
  1108. PASS();
  1109. }
  1110. std::string TestFileIO::MatchOpenExpectations(pp::FileSystem* file_system,
  1111. int32_t open_flags,
  1112. int32_t expectations) {
  1113. std::string bad_argument =
  1114. "TestFileIO::MatchOpenExpectations has invalid input arguments.";
  1115. bool invalid_combination = !!(expectations & INVALID_FLAG_COMBINATION);
  1116. if (invalid_combination) {
  1117. if (expectations != INVALID_FLAG_COMBINATION)
  1118. return bad_argument;
  1119. } else {
  1120. // Validate that one and only one of <some_expectation> and
  1121. // DONT_<some_expectation> is specified.
  1122. for (size_t remains = expectations, end = END_OF_OPEN_EXPECATION_PAIRS;
  1123. end != 0; remains >>= 2, end >>= 2) {
  1124. if (!!(remains & 1) == !!(remains & 2))
  1125. return bad_argument;
  1126. }
  1127. }
  1128. bool create_if_doesnt_exist = !!(expectations & CREATE_IF_DOESNT_EXIST);
  1129. bool open_if_exists = !!(expectations & OPEN_IF_EXISTS);
  1130. bool truncate_if_exists = !!(expectations & TRUNCATE_IF_EXISTS);
  1131. TestCompletionCallback callback(instance_->pp_instance(), callback_type());
  1132. pp::FileRef existent_file_ref(
  1133. *file_system, "/match_open_expectation_existent_non_empty_file");
  1134. pp::FileRef nonexistent_file_ref(
  1135. *file_system, "/match_open_expectation_nonexistent_file");
  1136. // Setup files for test.
  1137. {
  1138. callback.WaitForResult(existent_file_ref.Delete(callback.GetCallback()));
  1139. CHECK_CALLBACK_BEHAVIOR(callback);
  1140. ASSERT_TRUE(callback.result() == PP_OK ||
  1141. callback.result() == PP_ERROR_FILENOTFOUND);
  1142. callback.WaitForResult(nonexistent_file_ref.Delete(callback.GetCallback()));
  1143. CHECK_CALLBACK_BEHAVIOR(callback);
  1144. ASSERT_TRUE(callback.result() == PP_OK ||
  1145. callback.result() == PP_ERROR_FILENOTFOUND);
  1146. pp::FileIO existent_file_io(instance_);
  1147. callback.WaitForResult(existent_file_io.Open(
  1148. existent_file_ref,
  1149. PP_FILEOPENFLAG_CREATE | PP_FILEOPENFLAG_WRITE,
  1150. callback.GetCallback()));
  1151. CHECK_CALLBACK_BEHAVIOR(callback);
  1152. ASSERT_EQ(PP_OK, callback.result());
  1153. int32_t rv = WriteEntireBuffer(instance_->pp_instance(), &existent_file_io,
  1154. 0, "foobar", callback_type());
  1155. ASSERT_EQ(PP_OK, rv);
  1156. }
  1157. pp::FileIO existent_file_io(instance_);
  1158. callback.WaitForResult(existent_file_io.Open(existent_file_ref, open_flags,
  1159. callback.GetCallback()));
  1160. CHECK_CALLBACK_BEHAVIOR(callback);
  1161. if ((invalid_combination && callback.result() == PP_OK) ||
  1162. (!invalid_combination &&
  1163. ((callback.result() == PP_OK) != open_if_exists))) {
  1164. return ReportOpenError(open_flags);
  1165. }
  1166. if (!invalid_combination && open_if_exists) {
  1167. PP_FileInfo info;
  1168. callback.WaitForResult(existent_file_io.Query(&info,
  1169. callback.GetCallback()));
  1170. CHECK_CALLBACK_BEHAVIOR(callback);
  1171. ASSERT_EQ(PP_OK, callback.result());
  1172. if (truncate_if_exists != (info.size == 0))
  1173. return ReportOpenError(open_flags);
  1174. }
  1175. pp::FileIO nonexistent_file_io(instance_);
  1176. callback.WaitForResult(nonexistent_file_io.Open(nonexistent_file_ref,
  1177. open_flags,
  1178. callback.GetCallback()));
  1179. CHECK_CALLBACK_BEHAVIOR(callback);
  1180. if ((invalid_combination && callback.result() == PP_OK) ||
  1181. (!invalid_combination &&
  1182. ((callback.result() == PP_OK) != create_if_doesnt_exist))) {
  1183. return ReportOpenError(open_flags);
  1184. }
  1185. return std::string();
  1186. }
  1187. // TODO(viettrungluu): Test Close(). crbug.com/69457