blob: 16c9fe38bb3d0712ccfcefd6925d56acef617cc0 [file] [log] [blame]
[email protected]8effd3f62011-03-25 16:29:071// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]2041cf342010-02-19 03:15:592// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
[email protected]21da6eb2008-11-03 17:18:144
[email protected]2041cf342010-02-19 03:15:595#include "base/callback.h"
[email protected]21da6eb2008-11-03 17:18:146#include "base/file_util.h"
[email protected]ad74a592011-01-21 18:40:557#include "base/message_loop.h"
[email protected]21da6eb2008-11-03 17:18:148#include "base/path_service.h"
[email protected]92aad5222009-02-09 22:26:419#include "base/platform_file.h"
[email protected]21da6eb2008-11-03 17:18:1410#include "net/base/file_stream.h"
11#include "net/base/net_errors.h"
12#include "net/base/test_completion_callback.h"
13#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1514#include "testing/platform_test.h"
[email protected]21da6eb2008-11-03 17:18:1415
[email protected]8effd3f62011-03-25 16:29:0716namespace net {
[email protected]96d73822011-10-10 02:11:2417
[email protected]4c2048a2009-03-24 21:02:0118namespace {
19
20const char kTestData[] = "0123456789";
21const int kTestDataSize = arraysize(kTestData) - 1;
[email protected]21da6eb2008-11-03 17:18:1422
[email protected]96d73822011-10-10 02:11:2423} // namespace
24
[email protected]21da6eb2008-11-03 17:18:1425class FileStreamTest : public PlatformTest {
26 public:
27 virtual void SetUp() {
28 PlatformTest::SetUp();
29
[email protected]33edeab2009-08-18 16:07:5530 file_util::CreateTemporaryFile(&temp_file_path_);
[email protected]7ff3f632009-10-13 18:43:3531 file_util::WriteFile(temp_file_path_, kTestData, kTestDataSize);
[email protected]21da6eb2008-11-03 17:18:1432 }
33 virtual void TearDown() {
34 file_util::Delete(temp_file_path_, false);
35
36 PlatformTest::TearDown();
37 }
[email protected]96d73822011-10-10 02:11:2438
[email protected]07167e8f2009-01-26 21:38:1139 const FilePath temp_file_path() const { return temp_file_path_; }
[email protected]96d73822011-10-10 02:11:2440
41 static base::PlatformFile GetFile(const FileStream& stream) {
42 return stream.file_;
43 }
44
[email protected]21da6eb2008-11-03 17:18:1445 private:
[email protected]07167e8f2009-01-26 21:38:1146 FilePath temp_file_path_;
[email protected]21da6eb2008-11-03 17:18:1447};
48
[email protected]96d73822011-10-10 02:11:2449namespace {
50
[email protected]21da6eb2008-11-03 17:18:1451TEST_F(FileStreamTest, BasicOpenClose) {
[email protected]96d73822011-10-10 02:11:2452 base::PlatformFile file = base::kInvalidPlatformFileValue;
53 {
54 FileStream stream;
55 int rv = stream.Open(temp_file_path(),
56 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ);
57 EXPECT_EQ(OK, rv);
58 EXPECT_TRUE(stream.IsOpen());
59 file = GetFile(stream);
60 }
61 EXPECT_NE(base::kInvalidPlatformFileValue, file);
62 base::PlatformFileInfo info;
63 // The file should be closed.
64 EXPECT_FALSE(base::GetPlatformFileInfo(file, &info));
65}
66
67TEST_F(FileStreamTest, FileHandleLeftOpen) {
68 bool created = false;
69 ASSERT_EQ(kTestDataSize,
70 file_util::WriteFile(temp_file_path(), kTestData, kTestDataSize));
71 int flags = base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_READ;
72 base::PlatformFile file = base::CreatePlatformFile(
73 temp_file_path(), flags, &created, NULL);
74
75 {
76 // Seek to the beginning of the file and read.
77 FileStream read_stream(file, flags);
78 EXPECT_TRUE(read_stream.IsOpen());
79 }
80
81 EXPECT_NE(base::kInvalidPlatformFileValue, file);
82 base::PlatformFileInfo info;
83 // The file should still be open.
84 EXPECT_TRUE(base::GetPlatformFileInfo(file, &info));
85 // Clean up.
86 EXPECT_TRUE(base::ClosePlatformFile(file));
[email protected]21da6eb2008-11-03 17:18:1487}
88
[email protected]92aad5222009-02-09 22:26:4189// Test the use of FileStream with a file handle provided at construction.
90TEST_F(FileStreamTest, UseFileHandle) {
91 bool created = false;
92
93 // 1. Test reading with a file handle.
94 ASSERT_EQ(kTestDataSize,
95 file_util::WriteFile(temp_file_path(), kTestData, kTestDataSize));
96 int flags = base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_READ;
97 base::PlatformFile file = base::CreatePlatformFile(
[email protected]ed65fec2010-08-31 19:30:2798 temp_file_path(), flags, &created, NULL);
[email protected]92aad5222009-02-09 22:26:4199
100 // Seek to the beginning of the file and read.
[email protected]8effd3f62011-03-25 16:29:07101 FileStream read_stream(file, flags);
102 ASSERT_EQ(0, read_stream.Seek(FROM_BEGIN, 0));
[email protected]92aad5222009-02-09 22:26:41103 ASSERT_EQ(kTestDataSize, read_stream.Available());
104 // Read into buffer and compare.
105 char buffer[kTestDataSize];
106 ASSERT_EQ(kTestDataSize, read_stream.Read(buffer, kTestDataSize, NULL));
107 ASSERT_EQ(0, memcmp(kTestData, buffer, kTestDataSize));
108 read_stream.Close();
109
110 // 2. Test writing with a file handle.
111 file_util::Delete(temp_file_path(), false);
112 flags = base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_WRITE;
[email protected]ed65fec2010-08-31 19:30:27113 file = base::CreatePlatformFile(temp_file_path(), flags, &created, NULL);
[email protected]92aad5222009-02-09 22:26:41114
[email protected]8effd3f62011-03-25 16:29:07115 FileStream write_stream(file, flags);
116 ASSERT_EQ(0, write_stream.Seek(FROM_BEGIN, 0));
[email protected]92aad5222009-02-09 22:26:41117 ASSERT_EQ(kTestDataSize, write_stream.Write(kTestData, kTestDataSize, NULL));
118 write_stream.Close();
119
120 // Read into buffer and compare to make sure the handle worked fine.
121 ASSERT_EQ(kTestDataSize,
122 file_util::ReadFile(temp_file_path(), buffer, kTestDataSize));
123 ASSERT_EQ(0, memcmp(kTestData, buffer, kTestDataSize));
124}
125
[email protected]21da6eb2008-11-03 17:18:14126TEST_F(FileStreamTest, UseClosedStream) {
[email protected]8effd3f62011-03-25 16:29:07127 FileStream stream;
[email protected]21da6eb2008-11-03 17:18:14128
129 EXPECT_FALSE(stream.IsOpen());
130
131 // Try seeking...
[email protected]8effd3f62011-03-25 16:29:07132 int64 new_offset = stream.Seek(FROM_BEGIN, 5);
133 EXPECT_EQ(ERR_UNEXPECTED, new_offset);
[email protected]21da6eb2008-11-03 17:18:14134
135 // Try available...
136 int64 avail = stream.Available();
[email protected]8effd3f62011-03-25 16:29:07137 EXPECT_EQ(ERR_UNEXPECTED, avail);
[email protected]21da6eb2008-11-03 17:18:14138
139 // Try reading...
140 char buf[10];
[email protected]4c2048a2009-03-24 21:02:01141 int rv = stream.Read(buf, arraysize(buf), NULL);
[email protected]8effd3f62011-03-25 16:29:07142 EXPECT_EQ(ERR_UNEXPECTED, rv);
[email protected]21da6eb2008-11-03 17:18:14143}
144
145TEST_F(FileStreamTest, BasicRead) {
146 int64 file_size;
147 bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
148 EXPECT_TRUE(ok);
149
[email protected]8effd3f62011-03-25 16:29:07150 FileStream stream;
[email protected]f0a51fb52009-03-05 12:46:38151 int flags = base::PLATFORM_FILE_OPEN |
[email protected]21da6eb2008-11-03 17:18:14152 base::PLATFORM_FILE_READ;
153 int rv = stream.Open(temp_file_path(), flags);
[email protected]8effd3f62011-03-25 16:29:07154 EXPECT_EQ(OK, rv);
[email protected]21da6eb2008-11-03 17:18:14155
156 int64 total_bytes_avail = stream.Available();
157 EXPECT_EQ(file_size, total_bytes_avail);
158
[email protected]4c2048a2009-03-24 21:02:01159 int total_bytes_read = 0;
[email protected]21da6eb2008-11-03 17:18:14160
161 std::string data_read;
162 for (;;) {
163 char buf[4];
[email protected]4c2048a2009-03-24 21:02:01164 rv = stream.Read(buf, arraysize(buf), NULL);
[email protected]21da6eb2008-11-03 17:18:14165 EXPECT_LE(0, rv);
166 if (rv <= 0)
167 break;
168 total_bytes_read += rv;
169 data_read.append(buf, rv);
170 }
171 EXPECT_EQ(file_size, total_bytes_read);
[email protected]4c2048a2009-03-24 21:02:01172 EXPECT_EQ(kTestData, data_read);
[email protected]21da6eb2008-11-03 17:18:14173}
174
175TEST_F(FileStreamTest, AsyncRead) {
176 int64 file_size;
177 bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
178 EXPECT_TRUE(ok);
179
[email protected]8effd3f62011-03-25 16:29:07180 FileStream stream;
[email protected]f0a51fb52009-03-05 12:46:38181 int flags = base::PLATFORM_FILE_OPEN |
182 base::PLATFORM_FILE_READ |
[email protected]21da6eb2008-11-03 17:18:14183 base::PLATFORM_FILE_ASYNC;
184 int rv = stream.Open(temp_file_path(), flags);
[email protected]8effd3f62011-03-25 16:29:07185 EXPECT_EQ(OK, rv);
[email protected]21da6eb2008-11-03 17:18:14186
187 int64 total_bytes_avail = stream.Available();
188 EXPECT_EQ(file_size, total_bytes_avail);
189
[email protected]f1f3f0f82011-10-01 20:38:10190 TestOldCompletionCallback callback;
[email protected]21da6eb2008-11-03 17:18:14191
[email protected]4c2048a2009-03-24 21:02:01192 int total_bytes_read = 0;
[email protected]21da6eb2008-11-03 17:18:14193
194 std::string data_read;
195 for (;;) {
196 char buf[4];
[email protected]4c2048a2009-03-24 21:02:01197 rv = stream.Read(buf, arraysize(buf), &callback);
[email protected]8effd3f62011-03-25 16:29:07198 if (rv == ERR_IO_PENDING)
[email protected]21da6eb2008-11-03 17:18:14199 rv = callback.WaitForResult();
200 EXPECT_LE(0, rv);
201 if (rv <= 0)
202 break;
203 total_bytes_read += rv;
204 data_read.append(buf, rv);
205 }
206 EXPECT_EQ(file_size, total_bytes_read);
[email protected]4c2048a2009-03-24 21:02:01207 EXPECT_EQ(kTestData, data_read);
208}
209
210TEST_F(FileStreamTest, AsyncRead_EarlyClose) {
211 int64 file_size;
212 bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
213 EXPECT_TRUE(ok);
214
[email protected]8effd3f62011-03-25 16:29:07215 FileStream stream;
[email protected]4c2048a2009-03-24 21:02:01216 int flags = base::PLATFORM_FILE_OPEN |
217 base::PLATFORM_FILE_READ |
218 base::PLATFORM_FILE_ASYNC;
219 int rv = stream.Open(temp_file_path(), flags);
[email protected]8effd3f62011-03-25 16:29:07220 EXPECT_EQ(OK, rv);
[email protected]4c2048a2009-03-24 21:02:01221
222 int64 total_bytes_avail = stream.Available();
223 EXPECT_EQ(file_size, total_bytes_avail);
224
[email protected]f1f3f0f82011-10-01 20:38:10225 TestOldCompletionCallback callback;
[email protected]4c2048a2009-03-24 21:02:01226
227 char buf[4];
228 rv = stream.Read(buf, arraysize(buf), &callback);
229 stream.Close();
[email protected]3828a752009-06-03 23:05:59230 if (rv < 0) {
[email protected]8effd3f62011-03-25 16:29:07231 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3828a752009-06-03 23:05:59232 // The callback should not be called if the request is cancelled.
233 MessageLoop::current()->RunAllPending();
234 EXPECT_FALSE(callback.have_result());
235 } else {
236 EXPECT_EQ(std::string(kTestData, rv), std::string(buf, rv));
237 }
[email protected]21da6eb2008-11-03 17:18:14238}
239
240TEST_F(FileStreamTest, BasicRead_FromOffset) {
241 int64 file_size;
242 bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
243 EXPECT_TRUE(ok);
244
[email protected]8effd3f62011-03-25 16:29:07245 FileStream stream;
[email protected]f0a51fb52009-03-05 12:46:38246 int flags = base::PLATFORM_FILE_OPEN |
[email protected]21da6eb2008-11-03 17:18:14247 base::PLATFORM_FILE_READ;
248 int rv = stream.Open(temp_file_path(), flags);
[email protected]8effd3f62011-03-25 16:29:07249 EXPECT_EQ(OK, rv);
[email protected]21da6eb2008-11-03 17:18:14250
251 const int64 kOffset = 3;
[email protected]8effd3f62011-03-25 16:29:07252 int64 new_offset = stream.Seek(FROM_BEGIN, kOffset);
[email protected]21da6eb2008-11-03 17:18:14253 EXPECT_EQ(kOffset, new_offset);
254
255 int64 total_bytes_avail = stream.Available();
256 EXPECT_EQ(file_size - kOffset, total_bytes_avail);
257
258 int64 total_bytes_read = 0;
259
260 std::string data_read;
261 for (;;) {
262 char buf[4];
[email protected]4c2048a2009-03-24 21:02:01263 rv = stream.Read(buf, arraysize(buf), NULL);
[email protected]21da6eb2008-11-03 17:18:14264 EXPECT_LE(0, rv);
265 if (rv <= 0)
266 break;
267 total_bytes_read += rv;
268 data_read.append(buf, rv);
269 }
270 EXPECT_EQ(file_size - kOffset, total_bytes_read);
271 EXPECT_TRUE(data_read == kTestData + kOffset);
[email protected]4c2048a2009-03-24 21:02:01272 EXPECT_EQ(kTestData + kOffset, data_read);
[email protected]21da6eb2008-11-03 17:18:14273}
274
275TEST_F(FileStreamTest, AsyncRead_FromOffset) {
276 int64 file_size;
277 bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
278 EXPECT_TRUE(ok);
279
[email protected]8effd3f62011-03-25 16:29:07280 FileStream stream;
[email protected]f0a51fb52009-03-05 12:46:38281 int flags = base::PLATFORM_FILE_OPEN |
282 base::PLATFORM_FILE_READ |
[email protected]21da6eb2008-11-03 17:18:14283 base::PLATFORM_FILE_ASYNC;
284 int rv = stream.Open(temp_file_path(), flags);
[email protected]8effd3f62011-03-25 16:29:07285 EXPECT_EQ(OK, rv);
[email protected]21da6eb2008-11-03 17:18:14286
287 const int64 kOffset = 3;
[email protected]8effd3f62011-03-25 16:29:07288 int64 new_offset = stream.Seek(FROM_BEGIN, kOffset);
[email protected]21da6eb2008-11-03 17:18:14289 EXPECT_EQ(kOffset, new_offset);
290
291 int64 total_bytes_avail = stream.Available();
292 EXPECT_EQ(file_size - kOffset, total_bytes_avail);
293
[email protected]f1f3f0f82011-10-01 20:38:10294 TestOldCompletionCallback callback;
[email protected]21da6eb2008-11-03 17:18:14295
[email protected]4c2048a2009-03-24 21:02:01296 int total_bytes_read = 0;
[email protected]21da6eb2008-11-03 17:18:14297
298 std::string data_read;
299 for (;;) {
300 char buf[4];
[email protected]4c2048a2009-03-24 21:02:01301 rv = stream.Read(buf, arraysize(buf), &callback);
[email protected]8effd3f62011-03-25 16:29:07302 if (rv == ERR_IO_PENDING)
[email protected]21da6eb2008-11-03 17:18:14303 rv = callback.WaitForResult();
304 EXPECT_LE(0, rv);
305 if (rv <= 0)
306 break;
307 total_bytes_read += rv;
308 data_read.append(buf, rv);
309 }
310 EXPECT_EQ(file_size - kOffset, total_bytes_read);
[email protected]4c2048a2009-03-24 21:02:01311 EXPECT_EQ(kTestData + kOffset, data_read);
[email protected]21da6eb2008-11-03 17:18:14312}
313
314TEST_F(FileStreamTest, SeekAround) {
[email protected]8effd3f62011-03-25 16:29:07315 FileStream stream;
[email protected]f0a51fb52009-03-05 12:46:38316 int flags = base::PLATFORM_FILE_OPEN |
[email protected]21da6eb2008-11-03 17:18:14317 base::PLATFORM_FILE_READ;
318 int rv = stream.Open(temp_file_path(), flags);
[email protected]8effd3f62011-03-25 16:29:07319 EXPECT_EQ(OK, rv);
[email protected]21da6eb2008-11-03 17:18:14320
321 const int64 kOffset = 3;
[email protected]8effd3f62011-03-25 16:29:07322 int64 new_offset = stream.Seek(FROM_BEGIN, kOffset);
[email protected]21da6eb2008-11-03 17:18:14323 EXPECT_EQ(kOffset, new_offset);
324
[email protected]8effd3f62011-03-25 16:29:07325 new_offset = stream.Seek(FROM_CURRENT, kOffset);
[email protected]21da6eb2008-11-03 17:18:14326 EXPECT_EQ(2 * kOffset, new_offset);
327
[email protected]8effd3f62011-03-25 16:29:07328 new_offset = stream.Seek(FROM_CURRENT, -kOffset);
[email protected]21da6eb2008-11-03 17:18:14329 EXPECT_EQ(kOffset, new_offset);
330
331 const int kTestDataLen = arraysize(kTestData) - 1;
332
[email protected]8effd3f62011-03-25 16:29:07333 new_offset = stream.Seek(FROM_END, -kTestDataLen);
[email protected]21da6eb2008-11-03 17:18:14334 EXPECT_EQ(0, new_offset);
335}
336
337TEST_F(FileStreamTest, BasicWrite) {
[email protected]8effd3f62011-03-25 16:29:07338 FileStream stream;
[email protected]f0a51fb52009-03-05 12:46:38339 int flags = base::PLATFORM_FILE_CREATE_ALWAYS |
[email protected]21da6eb2008-11-03 17:18:14340 base::PLATFORM_FILE_WRITE;
341 int rv = stream.Open(temp_file_path(), flags);
[email protected]8effd3f62011-03-25 16:29:07342 EXPECT_EQ(OK, rv);
[email protected]21da6eb2008-11-03 17:18:14343
344 int64 file_size;
345 bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
346 EXPECT_TRUE(ok);
347 EXPECT_EQ(0, file_size);
348
349 rv = stream.Write(kTestData, kTestDataSize, NULL);
350 EXPECT_EQ(kTestDataSize, rv);
351 stream.Close();
352
353 ok = file_util::GetFileSize(temp_file_path(), &file_size);
354 EXPECT_TRUE(ok);
355 EXPECT_EQ(kTestDataSize, file_size);
356}
357
358TEST_F(FileStreamTest, AsyncWrite) {
[email protected]8effd3f62011-03-25 16:29:07359 FileStream stream;
[email protected]f0a51fb52009-03-05 12:46:38360 int flags = base::PLATFORM_FILE_CREATE_ALWAYS |
361 base::PLATFORM_FILE_WRITE |
[email protected]21da6eb2008-11-03 17:18:14362 base::PLATFORM_FILE_ASYNC;
363 int rv = stream.Open(temp_file_path(), flags);
[email protected]8effd3f62011-03-25 16:29:07364 EXPECT_EQ(OK, rv);
[email protected]21da6eb2008-11-03 17:18:14365
366 int64 file_size;
367 bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
368 EXPECT_TRUE(ok);
369 EXPECT_EQ(0, file_size);
370
[email protected]f1f3f0f82011-10-01 20:38:10371 TestOldCompletionCallback callback;
[email protected]4c2048a2009-03-24 21:02:01372 int total_bytes_written = 0;
[email protected]21da6eb2008-11-03 17:18:14373
374 while (total_bytes_written != kTestDataSize) {
[email protected]4c2048a2009-03-24 21:02:01375 rv = stream.Write(kTestData + total_bytes_written,
376 kTestDataSize - total_bytes_written,
377 &callback);
[email protected]8effd3f62011-03-25 16:29:07378 if (rv == ERR_IO_PENDING)
[email protected]21da6eb2008-11-03 17:18:14379 rv = callback.WaitForResult();
380 EXPECT_LT(0, rv);
381 if (rv <= 0)
382 break;
383 total_bytes_written += rv;
384 }
385 ok = file_util::GetFileSize(temp_file_path(), &file_size);
386 EXPECT_TRUE(ok);
387 EXPECT_EQ(file_size, total_bytes_written);
388}
389
[email protected]4c2048a2009-03-24 21:02:01390TEST_F(FileStreamTest, AsyncWrite_EarlyClose) {
[email protected]8effd3f62011-03-25 16:29:07391 FileStream stream;
[email protected]4c2048a2009-03-24 21:02:01392 int flags = base::PLATFORM_FILE_CREATE_ALWAYS |
393 base::PLATFORM_FILE_WRITE |
394 base::PLATFORM_FILE_ASYNC;
395 int rv = stream.Open(temp_file_path(), flags);
[email protected]8effd3f62011-03-25 16:29:07396 EXPECT_EQ(OK, rv);
[email protected]4c2048a2009-03-24 21:02:01397
398 int64 file_size;
399 bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
400 EXPECT_TRUE(ok);
401 EXPECT_EQ(0, file_size);
402
[email protected]f1f3f0f82011-10-01 20:38:10403 TestOldCompletionCallback callback;
[email protected]4c2048a2009-03-24 21:02:01404 int total_bytes_written = 0;
405
406 rv = stream.Write(kTestData + total_bytes_written,
407 kTestDataSize - total_bytes_written,
408 &callback);
409 stream.Close();
[email protected]3828a752009-06-03 23:05:59410 if (rv < 0) {
[email protected]8effd3f62011-03-25 16:29:07411 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3828a752009-06-03 23:05:59412 // The callback should not be called if the request is cancelled.
413 MessageLoop::current()->RunAllPending();
414 EXPECT_FALSE(callback.have_result());
415 } else {
416 ok = file_util::GetFileSize(temp_file_path(), &file_size);
417 EXPECT_TRUE(ok);
418 EXPECT_EQ(file_size, rv);
419 }
[email protected]4c2048a2009-03-24 21:02:01420}
421
[email protected]21da6eb2008-11-03 17:18:14422TEST_F(FileStreamTest, BasicWrite_FromOffset) {
[email protected]8effd3f62011-03-25 16:29:07423 FileStream stream;
[email protected]f0a51fb52009-03-05 12:46:38424 int flags = base::PLATFORM_FILE_OPEN |
[email protected]21da6eb2008-11-03 17:18:14425 base::PLATFORM_FILE_WRITE;
426 int rv = stream.Open(temp_file_path(), flags);
[email protected]8effd3f62011-03-25 16:29:07427 EXPECT_EQ(OK, rv);
[email protected]21da6eb2008-11-03 17:18:14428
429 int64 file_size;
430 bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
431 EXPECT_TRUE(ok);
432 EXPECT_EQ(kTestDataSize, file_size);
433
434 const int64 kOffset = 0;
[email protected]8effd3f62011-03-25 16:29:07435 int64 new_offset = stream.Seek(FROM_END, kOffset);
[email protected]21da6eb2008-11-03 17:18:14436 EXPECT_EQ(kTestDataSize, new_offset);
437
438 rv = stream.Write(kTestData, kTestDataSize, NULL);
439 EXPECT_EQ(kTestDataSize, rv);
440 stream.Close();
441
442 ok = file_util::GetFileSize(temp_file_path(), &file_size);
443 EXPECT_TRUE(ok);
444 EXPECT_EQ(kTestDataSize * 2, file_size);
445}
446
447TEST_F(FileStreamTest, AsyncWrite_FromOffset) {
448 int64 file_size;
449 bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
450 EXPECT_TRUE(ok);
451
[email protected]8effd3f62011-03-25 16:29:07452 FileStream stream;
[email protected]f0a51fb52009-03-05 12:46:38453 int flags = base::PLATFORM_FILE_OPEN |
[email protected]21da6eb2008-11-03 17:18:14454 base::PLATFORM_FILE_WRITE |
455 base::PLATFORM_FILE_ASYNC;
456 int rv = stream.Open(temp_file_path(), flags);
[email protected]8effd3f62011-03-25 16:29:07457 EXPECT_EQ(OK, rv);
[email protected]21da6eb2008-11-03 17:18:14458
459 const int64 kOffset = 0;
[email protected]8effd3f62011-03-25 16:29:07460 int64 new_offset = stream.Seek(FROM_END, kOffset);
[email protected]21da6eb2008-11-03 17:18:14461 EXPECT_EQ(kTestDataSize, new_offset);
462
[email protected]f1f3f0f82011-10-01 20:38:10463 TestOldCompletionCallback callback;
[email protected]4c2048a2009-03-24 21:02:01464 int total_bytes_written = 0;
[email protected]21da6eb2008-11-03 17:18:14465
466 while (total_bytes_written != kTestDataSize) {
[email protected]4c2048a2009-03-24 21:02:01467 rv = stream.Write(kTestData + total_bytes_written,
468 kTestDataSize - total_bytes_written,
469 &callback);
[email protected]8effd3f62011-03-25 16:29:07470 if (rv == ERR_IO_PENDING)
[email protected]21da6eb2008-11-03 17:18:14471 rv = callback.WaitForResult();
472 EXPECT_LT(0, rv);
473 if (rv <= 0)
474 break;
475 total_bytes_written += rv;
476 }
477 ok = file_util::GetFileSize(temp_file_path(), &file_size);
478 EXPECT_TRUE(ok);
479 EXPECT_EQ(file_size, kTestDataSize * 2);
480}
481
482TEST_F(FileStreamTest, BasicReadWrite) {
483 int64 file_size;
484 bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
485 EXPECT_TRUE(ok);
486
[email protected]8effd3f62011-03-25 16:29:07487 FileStream stream;
[email protected]f0a51fb52009-03-05 12:46:38488 int flags = base::PLATFORM_FILE_OPEN |
489 base::PLATFORM_FILE_READ |
[email protected]21da6eb2008-11-03 17:18:14490 base::PLATFORM_FILE_WRITE;
491 int rv = stream.Open(temp_file_path(), flags);
[email protected]8effd3f62011-03-25 16:29:07492 EXPECT_EQ(OK, rv);
[email protected]21da6eb2008-11-03 17:18:14493
494 int64 total_bytes_avail = stream.Available();
495 EXPECT_EQ(file_size, total_bytes_avail);
496
[email protected]4c2048a2009-03-24 21:02:01497 int total_bytes_read = 0;
[email protected]21da6eb2008-11-03 17:18:14498
499 std::string data_read;
500 for (;;) {
501 char buf[4];
[email protected]4c2048a2009-03-24 21:02:01502 rv = stream.Read(buf, arraysize(buf), NULL);
[email protected]21da6eb2008-11-03 17:18:14503 EXPECT_LE(0, rv);
504 if (rv <= 0)
505 break;
506 total_bytes_read += rv;
507 data_read.append(buf, rv);
508 }
509 EXPECT_EQ(file_size, total_bytes_read);
510 EXPECT_TRUE(data_read == kTestData);
511
512 rv = stream.Write(kTestData, kTestDataSize, NULL);
513 EXPECT_EQ(kTestDataSize, rv);
514 stream.Close();
515
516 ok = file_util::GetFileSize(temp_file_path(), &file_size);
517 EXPECT_TRUE(ok);
518 EXPECT_EQ(kTestDataSize * 2, file_size);
519}
520
[email protected]4c2048a2009-03-24 21:02:01521TEST_F(FileStreamTest, BasicWriteRead) {
522 int64 file_size;
523 bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
524 EXPECT_TRUE(ok);
525
[email protected]8effd3f62011-03-25 16:29:07526 FileStream stream;
[email protected]4c2048a2009-03-24 21:02:01527 int flags = base::PLATFORM_FILE_OPEN |
528 base::PLATFORM_FILE_READ |
529 base::PLATFORM_FILE_WRITE;
530 int rv = stream.Open(temp_file_path(), flags);
[email protected]8effd3f62011-03-25 16:29:07531 EXPECT_EQ(OK, rv);
[email protected]4c2048a2009-03-24 21:02:01532
533 int64 total_bytes_avail = stream.Available();
534 EXPECT_EQ(file_size, total_bytes_avail);
535
[email protected]8effd3f62011-03-25 16:29:07536 int64 offset = stream.Seek(FROM_END, 0);
[email protected]4c2048a2009-03-24 21:02:01537 EXPECT_EQ(offset, file_size);
538
539 rv = stream.Write(kTestData, kTestDataSize, NULL);
540 EXPECT_EQ(kTestDataSize, rv);
541
[email protected]8effd3f62011-03-25 16:29:07542 offset = stream.Seek(FROM_BEGIN, 0);
[email protected]4c2048a2009-03-24 21:02:01543 EXPECT_EQ(0, offset);
544
545 int64 total_bytes_read = 0;
546
547 std::string data_read;
548 for (;;) {
549 char buf[4];
550 rv = stream.Read(buf, arraysize(buf), NULL);
551 EXPECT_LE(0, rv);
552 if (rv <= 0)
553 break;
554 total_bytes_read += rv;
555 data_read.append(buf, rv);
556 }
557 stream.Close();
558
559 ok = file_util::GetFileSize(temp_file_path(), &file_size);
560 EXPECT_TRUE(ok);
561 EXPECT_EQ(kTestDataSize * 2, file_size);
562 EXPECT_EQ(kTestDataSize * 2, total_bytes_read);
563
564 const std::string kExpectedFileData =
565 std::string(kTestData) + std::string(kTestData);
566 EXPECT_EQ(kExpectedFileData, data_read);
567}
568
569TEST_F(FileStreamTest, BasicAsyncReadWrite) {
570 int64 file_size;
571 bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
572 EXPECT_TRUE(ok);
573
[email protected]8effd3f62011-03-25 16:29:07574 FileStream stream;
[email protected]4c2048a2009-03-24 21:02:01575 int flags = base::PLATFORM_FILE_OPEN |
576 base::PLATFORM_FILE_READ |
577 base::PLATFORM_FILE_WRITE |
578 base::PLATFORM_FILE_ASYNC;
579 int rv = stream.Open(temp_file_path(), flags);
[email protected]8effd3f62011-03-25 16:29:07580 EXPECT_EQ(OK, rv);
[email protected]4c2048a2009-03-24 21:02:01581
582 int64 total_bytes_avail = stream.Available();
583 EXPECT_EQ(file_size, total_bytes_avail);
584
[email protected]f1f3f0f82011-10-01 20:38:10585 TestOldCompletionCallback callback;
[email protected]4c2048a2009-03-24 21:02:01586 int64 total_bytes_read = 0;
587
588 std::string data_read;
589 for (;;) {
590 char buf[4];
591 rv = stream.Read(buf, arraysize(buf), &callback);
[email protected]8effd3f62011-03-25 16:29:07592 if (rv == ERR_IO_PENDING)
[email protected]4c2048a2009-03-24 21:02:01593 rv = callback.WaitForResult();
594 EXPECT_LE(0, rv);
595 if (rv <= 0)
596 break;
597 total_bytes_read += rv;
598 data_read.append(buf, rv);
599 }
600 EXPECT_EQ(file_size, total_bytes_read);
601 EXPECT_TRUE(data_read == kTestData);
602
603 int total_bytes_written = 0;
604
605 while (total_bytes_written != kTestDataSize) {
606 rv = stream.Write(kTestData + total_bytes_written,
607 kTestDataSize - total_bytes_written,
608 &callback);
[email protected]8effd3f62011-03-25 16:29:07609 if (rv == ERR_IO_PENDING)
[email protected]4c2048a2009-03-24 21:02:01610 rv = callback.WaitForResult();
611 EXPECT_LT(0, rv);
612 if (rv <= 0)
613 break;
614 total_bytes_written += rv;
615 }
616
617 stream.Close();
618
619 ok = file_util::GetFileSize(temp_file_path(), &file_size);
620 EXPECT_TRUE(ok);
621 EXPECT_EQ(kTestDataSize * 2, file_size);
622}
623
624TEST_F(FileStreamTest, BasicAsyncWriteRead) {
625 int64 file_size;
626 bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
627 EXPECT_TRUE(ok);
628
[email protected]8effd3f62011-03-25 16:29:07629 FileStream stream;
[email protected]4c2048a2009-03-24 21:02:01630 int flags = base::PLATFORM_FILE_OPEN |
631 base::PLATFORM_FILE_READ |
632 base::PLATFORM_FILE_WRITE |
633 base::PLATFORM_FILE_ASYNC;
634 int rv = stream.Open(temp_file_path(), flags);
[email protected]8effd3f62011-03-25 16:29:07635 EXPECT_EQ(OK, rv);
[email protected]4c2048a2009-03-24 21:02:01636
637 int64 total_bytes_avail = stream.Available();
638 EXPECT_EQ(file_size, total_bytes_avail);
639
[email protected]8effd3f62011-03-25 16:29:07640 int64 offset = stream.Seek(FROM_END, 0);
[email protected]4c2048a2009-03-24 21:02:01641 EXPECT_EQ(offset, file_size);
642
[email protected]f1f3f0f82011-10-01 20:38:10643 TestOldCompletionCallback callback;
[email protected]4c2048a2009-03-24 21:02:01644 int total_bytes_written = 0;
645
646 while (total_bytes_written != kTestDataSize) {
647 rv = stream.Write(kTestData + total_bytes_written,
648 kTestDataSize - total_bytes_written,
649 &callback);
[email protected]8effd3f62011-03-25 16:29:07650 if (rv == ERR_IO_PENDING)
[email protected]4c2048a2009-03-24 21:02:01651 rv = callback.WaitForResult();
652 EXPECT_LT(0, rv);
653 if (rv <= 0)
654 break;
655 total_bytes_written += rv;
656 }
657
658 EXPECT_EQ(kTestDataSize, total_bytes_written);
659
[email protected]8effd3f62011-03-25 16:29:07660 offset = stream.Seek(FROM_BEGIN, 0);
[email protected]4c2048a2009-03-24 21:02:01661 EXPECT_EQ(0, offset);
662
663 int total_bytes_read = 0;
664
665 std::string data_read;
666 for (;;) {
667 char buf[4];
668 rv = stream.Read(buf, arraysize(buf), &callback);
[email protected]8effd3f62011-03-25 16:29:07669 if (rv == ERR_IO_PENDING)
[email protected]4c2048a2009-03-24 21:02:01670 rv = callback.WaitForResult();
671 EXPECT_LE(0, rv);
672 if (rv <= 0)
673 break;
674 total_bytes_read += rv;
675 data_read.append(buf, rv);
676 }
677 stream.Close();
678
679 ok = file_util::GetFileSize(temp_file_path(), &file_size);
680 EXPECT_TRUE(ok);
681 EXPECT_EQ(kTestDataSize * 2, file_size);
682
683 EXPECT_EQ(kTestDataSize * 2, total_bytes_read);
684 const std::string kExpectedFileData =
685 std::string(kTestData) + std::string(kTestData);
686 EXPECT_EQ(kExpectedFileData, data_read);
687}
688
[email protected]f1f3f0f82011-10-01 20:38:10689class TestWriteReadOldCompletionCallback : public Callback1<int>::Type {
[email protected]4c2048a2009-03-24 21:02:01690 public:
[email protected]f1f3f0f82011-10-01 20:38:10691 TestWriteReadOldCompletionCallback(
[email protected]8effd3f62011-03-25 16:29:07692 FileStream* stream,
[email protected]4c2048a2009-03-24 21:02:01693 int* total_bytes_written,
694 int* total_bytes_read,
695 std::string* data_read)
696 : result_(0),
697 have_result_(false),
698 waiting_for_result_(false),
699 stream_(stream),
700 total_bytes_written_(total_bytes_written),
701 total_bytes_read_(total_bytes_read),
702 data_read_(data_read) {}
703
704 int WaitForResult() {
705 DCHECK(!waiting_for_result_);
706 while (!have_result_) {
707 waiting_for_result_ = true;
708 MessageLoop::current()->Run();
709 waiting_for_result_ = false;
710 }
711 have_result_ = false; // auto-reset for next callback
712 return result_;
713 }
714
715 private:
716 virtual void RunWithParams(const Tuple1<int>& params) {
717 DCHECK_LT(0, params.a);
718 *total_bytes_written_ += params.a;
719
720 int rv;
721
722 if (*total_bytes_written_ != kTestDataSize) {
723 // Recurse to finish writing all data.
724 int total_bytes_written = 0, total_bytes_read = 0;
725 std::string data_read;
[email protected]f1f3f0f82011-10-01 20:38:10726 TestWriteReadOldCompletionCallback callback(
[email protected]4c2048a2009-03-24 21:02:01727 stream_, &total_bytes_written, &total_bytes_read, &data_read);
728 rv = stream_->Write(kTestData + *total_bytes_written_,
729 kTestDataSize - *total_bytes_written_,
730 &callback);
[email protected]8effd3f62011-03-25 16:29:07731 DCHECK_EQ(ERR_IO_PENDING, rv);
[email protected]4c2048a2009-03-24 21:02:01732 rv = callback.WaitForResult();
733 *total_bytes_written_ += total_bytes_written;
734 *total_bytes_read_ += total_bytes_read;
735 *data_read_ += data_read;
736 } else { // We're done writing all data. Start reading the data.
[email protected]8effd3f62011-03-25 16:29:07737 stream_->Seek(FROM_BEGIN, 0);
[email protected]4c2048a2009-03-24 21:02:01738
[email protected]f1f3f0f82011-10-01 20:38:10739 TestOldCompletionCallback callback;
[email protected]4c2048a2009-03-24 21:02:01740 for (;;) {
741 char buf[4];
742 rv = stream_->Read(buf, arraysize(buf), &callback);
[email protected]8effd3f62011-03-25 16:29:07743 if (rv == ERR_IO_PENDING) {
[email protected]4c2048a2009-03-24 21:02:01744 bool old_state = MessageLoop::current()->NestableTasksAllowed();
745 MessageLoop::current()->SetNestableTasksAllowed(true);
746 rv = callback.WaitForResult();
747 MessageLoop::current()->SetNestableTasksAllowed(old_state);
748 }
749 EXPECT_LE(0, rv);
750 if (rv <= 0)
751 break;
752 *total_bytes_read_ += rv;
753 data_read_->append(buf, rv);
754 }
755 }
756
757 result_ = *total_bytes_written_;
758 have_result_ = true;
759 if (waiting_for_result_)
760 MessageLoop::current()->Quit();
761 }
762
763 int result_;
764 bool have_result_;
765 bool waiting_for_result_;
[email protected]8effd3f62011-03-25 16:29:07766 FileStream* stream_;
[email protected]4c2048a2009-03-24 21:02:01767 int* total_bytes_written_;
768 int* total_bytes_read_;
769 std::string* data_read_;
770
[email protected]f1f3f0f82011-10-01 20:38:10771 DISALLOW_COPY_AND_ASSIGN(TestWriteReadOldCompletionCallback);
[email protected]4c2048a2009-03-24 21:02:01772};
773
774TEST_F(FileStreamTest, AsyncWriteRead) {
775 int64 file_size;
776 bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
777 EXPECT_TRUE(ok);
778
[email protected]8effd3f62011-03-25 16:29:07779 FileStream stream;
[email protected]4c2048a2009-03-24 21:02:01780 int flags = base::PLATFORM_FILE_OPEN |
781 base::PLATFORM_FILE_READ |
782 base::PLATFORM_FILE_WRITE |
783 base::PLATFORM_FILE_ASYNC;
784 int rv = stream.Open(temp_file_path(), flags);
[email protected]8effd3f62011-03-25 16:29:07785 EXPECT_EQ(OK, rv);
[email protected]4c2048a2009-03-24 21:02:01786
787 int64 total_bytes_avail = stream.Available();
788 EXPECT_EQ(file_size, total_bytes_avail);
789
[email protected]8effd3f62011-03-25 16:29:07790 int64 offset = stream.Seek(FROM_END, 0);
[email protected]4c2048a2009-03-24 21:02:01791 EXPECT_EQ(offset, file_size);
792
793 int total_bytes_written = 0;
794 int total_bytes_read = 0;
795 std::string data_read;
[email protected]f1f3f0f82011-10-01 20:38:10796 TestWriteReadOldCompletionCallback callback(&stream, &total_bytes_written,
[email protected]4c2048a2009-03-24 21:02:01797 &total_bytes_read, &data_read);
798
799 rv = stream.Write(kTestData + total_bytes_written,
800 kTestDataSize - static_cast<int>(total_bytes_written),
801 &callback);
[email protected]8effd3f62011-03-25 16:29:07802 if (rv == ERR_IO_PENDING)
[email protected]4c2048a2009-03-24 21:02:01803 rv = callback.WaitForResult();
804 EXPECT_LT(0, rv);
805 EXPECT_EQ(kTestDataSize, total_bytes_written);
806
807 stream.Close();
808
809 ok = file_util::GetFileSize(temp_file_path(), &file_size);
810 EXPECT_TRUE(ok);
811 EXPECT_EQ(kTestDataSize * 2, file_size);
812
813 EXPECT_EQ(kTestDataSize * 2, total_bytes_read);
814 const std::string kExpectedFileData =
815 std::string(kTestData) + std::string(kTestData);
816 EXPECT_EQ(kExpectedFileData, data_read);
817}
818
[email protected]f1f3f0f82011-10-01 20:38:10819class TestWriteCloseOldCompletionCallback : public Callback1<int>::Type {
[email protected]4c2048a2009-03-24 21:02:01820 public:
[email protected]f1f3f0f82011-10-01 20:38:10821 TestWriteCloseOldCompletionCallback(FileStream* stream, int* total_bytes_written)
[email protected]4c2048a2009-03-24 21:02:01822 : result_(0),
823 have_result_(false),
824 waiting_for_result_(false),
825 stream_(stream),
826 total_bytes_written_(total_bytes_written) {}
827
828 int WaitForResult() {
829 DCHECK(!waiting_for_result_);
830 while (!have_result_) {
831 waiting_for_result_ = true;
832 MessageLoop::current()->Run();
833 waiting_for_result_ = false;
834 }
835 have_result_ = false; // auto-reset for next callback
836 return result_;
837 }
838
839 private:
840 virtual void RunWithParams(const Tuple1<int>& params) {
841 DCHECK_LT(0, params.a);
842 *total_bytes_written_ += params.a;
843
844 int rv;
845
846 if (*total_bytes_written_ != kTestDataSize) {
847 // Recurse to finish writing all data.
848 int total_bytes_written = 0;
[email protected]f1f3f0f82011-10-01 20:38:10849 TestWriteCloseOldCompletionCallback callback(stream_, &total_bytes_written);
[email protected]4c2048a2009-03-24 21:02:01850 rv = stream_->Write(kTestData + *total_bytes_written_,
851 kTestDataSize - *total_bytes_written_,
852 &callback);
[email protected]8effd3f62011-03-25 16:29:07853 DCHECK_EQ(ERR_IO_PENDING, rv);
[email protected]4c2048a2009-03-24 21:02:01854 rv = callback.WaitForResult();
855 *total_bytes_written_ += total_bytes_written;
856 } else { // We're done writing all data. Close the file.
857 stream_->Close();
858 }
859
860 result_ = *total_bytes_written_;
861 have_result_ = true;
862 if (waiting_for_result_)
863 MessageLoop::current()->Quit();
864 }
865
866 int result_;
867 bool have_result_;
868 bool waiting_for_result_;
[email protected]8effd3f62011-03-25 16:29:07869 FileStream* stream_;
[email protected]4c2048a2009-03-24 21:02:01870 int* total_bytes_written_;
871
[email protected]f1f3f0f82011-10-01 20:38:10872 DISALLOW_COPY_AND_ASSIGN(TestWriteCloseOldCompletionCallback);
[email protected]4c2048a2009-03-24 21:02:01873};
874
875TEST_F(FileStreamTest, AsyncWriteClose) {
876 int64 file_size;
877 bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
878 EXPECT_TRUE(ok);
879
[email protected]8effd3f62011-03-25 16:29:07880 FileStream stream;
[email protected]4c2048a2009-03-24 21:02:01881 int flags = base::PLATFORM_FILE_OPEN |
882 base::PLATFORM_FILE_READ |
883 base::PLATFORM_FILE_WRITE |
884 base::PLATFORM_FILE_ASYNC;
885 int rv = stream.Open(temp_file_path(), flags);
[email protected]8effd3f62011-03-25 16:29:07886 EXPECT_EQ(OK, rv);
[email protected]4c2048a2009-03-24 21:02:01887
888 int64 total_bytes_avail = stream.Available();
889 EXPECT_EQ(file_size, total_bytes_avail);
890
[email protected]8effd3f62011-03-25 16:29:07891 int64 offset = stream.Seek(FROM_END, 0);
[email protected]4c2048a2009-03-24 21:02:01892 EXPECT_EQ(offset, file_size);
893
894 int total_bytes_written = 0;
[email protected]f1f3f0f82011-10-01 20:38:10895 TestWriteCloseOldCompletionCallback callback(&stream, &total_bytes_written);
[email protected]4c2048a2009-03-24 21:02:01896
897 rv = stream.Write(kTestData, kTestDataSize, &callback);
[email protected]8effd3f62011-03-25 16:29:07898 if (rv == ERR_IO_PENDING)
[email protected]4c2048a2009-03-24 21:02:01899 total_bytes_written = callback.WaitForResult();
900 EXPECT_LT(0, total_bytes_written);
901 EXPECT_EQ(kTestDataSize, total_bytes_written);
902
903 ok = file_util::GetFileSize(temp_file_path(), &file_size);
904 EXPECT_TRUE(ok);
905 EXPECT_EQ(kTestDataSize * 2, file_size);
906}
907
[email protected]0643a492009-03-09 15:49:20908// Tests truncating a file.
909TEST_F(FileStreamTest, Truncate) {
910 int flags = base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE;
911
[email protected]8effd3f62011-03-25 16:29:07912 FileStream write_stream;
913 ASSERT_EQ(OK, write_stream.Open(temp_file_path(), flags));
[email protected]0643a492009-03-09 15:49:20914
915 // Write some data to the file.
916 const char test_data[] = "0123456789";
917 write_stream.Write(test_data, arraysize(test_data), NULL);
918
919 // Truncate the file.
920 ASSERT_EQ(4, write_stream.Truncate(4));
921
922 // Write again.
923 write_stream.Write(test_data, 4, NULL);
924
925 // Close the stream.
926 write_stream.Close();
927
928 // Read in the contents and make sure we get back what we expected.
929 std::string read_contents;
[email protected]3fc364f92009-08-06 22:35:13930 EXPECT_TRUE(file_util::ReadFileToString(temp_file_path(), &read_contents));
[email protected]0643a492009-03-09 15:49:20931
[email protected]4c2048a2009-03-24 21:02:01932 EXPECT_EQ("01230123", read_contents);
[email protected]0643a492009-03-09 15:49:20933}
934
[email protected]4c2048a2009-03-24 21:02:01935} // namespace
[email protected]96d73822011-10-10 02:11:24936
[email protected]8effd3f62011-03-25 16:29:07937} // namespace net