| // Copyright 2015 Google Inc. All Rights Reserved. | 
 | // | 
 | // Licensed under the Apache License, Version 2.0 (the "License"); | 
 | // you may not use this file except in compliance with the License. | 
 | // You may obtain a copy of the License at | 
 | // | 
 | //     http://www.apache.org/licenses/LICENSE-2.0 | 
 | // | 
 | // Unless required by applicable law or agreed to in writing, software | 
 | // distributed under the License is distributed on an "AS IS" BASIS, | 
 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | // See the License for the specific language governing permissions and | 
 | // limitations under the License. | 
 |  | 
 | // Writing is partially tested by some of the file helpers that create files for | 
 | // the tests to operate on. | 
 |  | 
 | #include <string> | 
 |  | 
 | #include "starboard/file.h" | 
 | #include "starboard/nplb/file_helpers.h" | 
 | #include "testing/gtest/include/gtest/gtest.h" | 
 |  | 
 | namespace starboard { | 
 | namespace nplb { | 
 | namespace { | 
 |  | 
 | // Sets up an empty test fixture, required for typed tests. | 
 | template <class SbFileWriteType> | 
 | class SbFileWriteTest : public testing::Test {}; | 
 |  | 
 | class SbFileWriter { | 
 |  public: | 
 |   static int Write(SbFile file, char* data, int size) { | 
 |     return SbFileWrite(file, data, size); | 
 |   } | 
 | }; | 
 |  | 
 | class SbFileWriterAll { | 
 |  public: | 
 |   static int Write(SbFile file, char* data, int size) { | 
 |     return SbFileWriteAll(file, data, size); | 
 |   } | 
 | }; | 
 |  | 
 | typedef testing::Types<SbFileWriter, SbFileWriterAll> SbFileWriteTestTypes; | 
 |  | 
 | TYPED_TEST_CASE(SbFileWriteTest, SbFileWriteTestTypes); | 
 |  | 
 | const int kBufferLength = 16 * 1024; | 
 |  | 
 | TYPED_TEST(SbFileWriteTest, InvalidFileErrors) { | 
 |   char buffer[kBufferLength] = {0}; | 
 |   int result = TypeParam::Write(kSbFileInvalid, buffer, kBufferLength); | 
 |   EXPECT_EQ(-1, result); | 
 | } | 
 |  | 
 | TYPED_TEST(SbFileWriteTest, BasicWriting) { | 
 |   // Choose a file size that is not an even multiple of the buffer size, but | 
 |   // is over several times the size of the buffer. | 
 |   const int kFileSize = kBufferLength * 16 / 3; | 
 |   ScopedRandomFile random_file(0, ScopedRandomFile::kDontCreate); | 
 |   const std::string& filename = random_file.filename(); | 
 |  | 
 |   SbFile file = SbFileOpen(filename.c_str(), | 
 |                            kSbFileCreateAlways | kSbFileWrite | kSbFileRead, | 
 |                            NULL, NULL); | 
 |   ASSERT_TRUE(SbFileIsValid(file)); | 
 |  | 
 |   // Create a bigger buffer than necessary, so we can test the memory around | 
 |   // the portion given to SbFileRead. | 
 |   char buffer[kBufferLength] = {0}; | 
 |  | 
 |   // Initialize to some arbitrary pattern so we can verify it later. | 
 |   for (int i = 0; i < kBufferLength; ++i) { | 
 |     buffer[i] = static_cast<char>(i & 0xFF); | 
 |   } | 
 |  | 
 |   // Read and check the whole file. | 
 |   int total = 0; | 
 |   while (true) { | 
 |     if (total == kFileSize) { | 
 |       break; | 
 |     } | 
 |  | 
 |     int remaining = kFileSize - total; | 
 |     int to_write = remaining < kBufferLength ? remaining : kBufferLength; | 
 |     int bytes_written = TypeParam::Write(file, buffer, to_write); | 
 |  | 
 |     // Check that we didn't write more than the buffer size. | 
 |     EXPECT_GE(to_write, bytes_written); | 
 |  | 
 |     // Check that we didn't get an error. | 
 |     ASSERT_LT(0, bytes_written); | 
 |  | 
 |     total += bytes_written; | 
 |     EXPECT_EQ(total, SbFileSeek(file, kSbFileFromCurrent, 0)); | 
 |   } | 
 |  | 
 |   // Tests reading and writing from same opened file. | 
 |   bool result = SbFileFlush(file); | 
 |   ASSERT_TRUE(result); | 
 |   int position = static_cast<int>(SbFileSeek(file, kSbFileFromBegin, 0)); | 
 |   ASSERT_EQ(0, position); | 
 |  | 
 |   // Read and check the whole file. | 
 |   total = 0; | 
 |   int previous_total = 0; | 
 |   while (true) { | 
 |     int bytes_read = SbFileReadAll(file, buffer, kBufferLength); | 
 |     if (bytes_read == 0) { | 
 |       break; | 
 |     } | 
 |  | 
 |     // Check that we didn't read more than the buffer size. | 
 |     EXPECT_GE(kBufferLength, bytes_read); | 
 |  | 
 |     // Check that we didn't get an error. | 
 |     ASSERT_LT(0, bytes_read); | 
 |  | 
 |     // Do some accounting to check later. | 
 |     previous_total = total; | 
 |     total += bytes_read; | 
 |  | 
 |     ScopedRandomFile::ExpectPattern(previous_total, buffer, bytes_read, | 
 |                                     __LINE__); | 
 |   } | 
 |  | 
 |   // Check that we read the whole file. | 
 |   EXPECT_EQ(kFileSize, total); | 
 |  | 
 |   result = SbFileClose(file); | 
 |   EXPECT_TRUE(result); | 
 | } | 
 |  | 
 | TYPED_TEST(SbFileWriteTest, WriteZeroBytes) { | 
 |   ScopedRandomFile random_file(0, ScopedRandomFile::kDontCreate); | 
 |   const std::string& filename = random_file.filename(); | 
 |  | 
 |   SbFile file = SbFileOpen(filename.c_str(), kSbFileCreateOnly | kSbFileWrite, | 
 |                            NULL, NULL); | 
 |   ASSERT_TRUE(SbFileIsValid(file)); | 
 |  | 
 |   char buffer[kBufferLength] = {0}; | 
 |  | 
 |   // Write zero bytes. | 
 |   for (int i = 0; i < 10; ++i) { | 
 |     int bytes_written = TypeParam::Write(file, buffer, 0); | 
 |     EXPECT_EQ(0, bytes_written); | 
 |   } | 
 |  | 
 |   bool result = SbFileClose(file); | 
 |   EXPECT_TRUE(result); | 
 |  | 
 |   file = | 
 |       SbFileOpen(filename.c_str(), kSbFileOpenOnly | kSbFileRead, NULL, NULL); | 
 |   ASSERT_TRUE(SbFileIsValid(file)); | 
 |   SbFileInfo info; | 
 |   result = SbFileGetInfo(file, &info); | 
 |   EXPECT_TRUE(result); | 
 |   EXPECT_EQ(0, info.size); | 
 |   result = SbFileClose(file); | 
 |   EXPECT_TRUE(result); | 
 | } | 
 |  | 
 | }  // namespace | 
 | }  // namespace nplb | 
 | }  // namespace starboard |