1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "file_output_stream.h" 18 #include "vector_output_stream.h" 19 20 #include "base/unix_file/fd_file.h" 21 #include "base/logging.h" 22 #include "base/stl_util.h" 23 #include "buffered_output_stream.h" 24 #include "common_runtime_test.h" 25 26 namespace art { 27 28 class OutputStreamTest : public CommonRuntimeTest { 29 protected: 30 void CheckOffset(off_t expected) { 31 off_t actual = output_stream_->Seek(0, kSeekCurrent); 32 EXPECT_EQ(expected, actual); 33 } 34 35 void SetOutputStream(OutputStream& output_stream) { 36 output_stream_ = &output_stream; 37 } 38 39 void GenerateTestOutput() { 40 EXPECT_EQ(3, output_stream_->Seek(3, kSeekCurrent)); 41 CheckOffset(3); 42 EXPECT_EQ(2, output_stream_->Seek(2, kSeekSet)); 43 CheckOffset(2); 44 uint8_t buf[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 45 EXPECT_TRUE(output_stream_->WriteFully(buf, 2)); 46 CheckOffset(4); 47 EXPECT_EQ(6, output_stream_->Seek(2, kSeekEnd)); 48 CheckOffset(6); 49 EXPECT_TRUE(output_stream_->WriteFully(buf, 4)); 50 CheckOffset(10); 51 EXPECT_TRUE(output_stream_->WriteFully(buf, 6)); 52 EXPECT_TRUE(output_stream_->Flush()); 53 } 54 55 void CheckTestOutput(const std::vector<uint8_t>& actual) { 56 uint8_t expected[] = { 57 0, 0, 1, 2, 0, 0, 1, 2, 3, 4, 1, 2, 3, 4, 5, 6 58 }; 59 EXPECT_EQ(sizeof(expected), actual.size()); 60 EXPECT_EQ(0, memcmp(expected, &actual[0], actual.size())); 61 } 62 63 OutputStream* output_stream_; 64 }; 65 66 TEST_F(OutputStreamTest, File) { 67 ScratchFile tmp; 68 FileOutputStream output_stream(tmp.GetFile()); 69 SetOutputStream(output_stream); 70 GenerateTestOutput(); 71 std::unique_ptr<File> in(OS::OpenFileForReading(tmp.GetFilename().c_str())); 72 EXPECT_TRUE(in.get() != nullptr); 73 std::vector<uint8_t> actual(in->GetLength()); 74 bool readSuccess = in->ReadFully(&actual[0], actual.size()); 75 EXPECT_TRUE(readSuccess); 76 CheckTestOutput(actual); 77 } 78 79 TEST_F(OutputStreamTest, Buffered) { 80 ScratchFile tmp; 81 { 82 BufferedOutputStream buffered_output_stream(MakeUnique<FileOutputStream>(tmp.GetFile())); 83 SetOutputStream(buffered_output_stream); 84 GenerateTestOutput(); 85 } 86 std::unique_ptr<File> in(OS::OpenFileForReading(tmp.GetFilename().c_str())); 87 EXPECT_TRUE(in.get() != nullptr); 88 std::vector<uint8_t> actual(in->GetLength()); 89 bool readSuccess = in->ReadFully(&actual[0], actual.size()); 90 EXPECT_TRUE(readSuccess); 91 CheckTestOutput(actual); 92 } 93 94 TEST_F(OutputStreamTest, Vector) { 95 std::vector<uint8_t> output; 96 VectorOutputStream output_stream("test vector output", &output); 97 SetOutputStream(output_stream); 98 GenerateTestOutput(); 99 CheckTestOutput(output); 100 } 101 102 TEST_F(OutputStreamTest, BufferedFlush) { 103 struct CheckingOutputStream : OutputStream { 104 CheckingOutputStream() 105 : OutputStream("dummy"), 106 flush_called(false) { } 107 ~CheckingOutputStream() OVERRIDE {} 108 109 bool WriteFully(const void* buffer ATTRIBUTE_UNUSED, 110 size_t byte_count ATTRIBUTE_UNUSED) OVERRIDE { 111 LOG(FATAL) << "UNREACHABLE"; 112 UNREACHABLE(); 113 } 114 115 off_t Seek(off_t offset ATTRIBUTE_UNUSED, Whence whence ATTRIBUTE_UNUSED) OVERRIDE { 116 LOG(FATAL) << "UNREACHABLE"; 117 UNREACHABLE(); 118 } 119 120 bool Flush() OVERRIDE { 121 flush_called = true; 122 return true; 123 } 124 125 bool flush_called; 126 }; 127 128 std::unique_ptr<CheckingOutputStream> cos = MakeUnique<CheckingOutputStream>(); 129 CheckingOutputStream* checking_output_stream = cos.get(); 130 BufferedOutputStream buffered(std::move(cos)); 131 ASSERT_FALSE(checking_output_stream->flush_called); 132 bool flush_result = buffered.Flush(); 133 ASSERT_TRUE(flush_result); 134 ASSERT_TRUE(checking_output_stream->flush_called); 135 } 136 137 } // namespace art 138