// Copyright 2020 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "gn/string_output_buffer.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "util/test/test.h" namespace { // Create a test string of |size| characters with pseudo-random ASCII content. std::string CreateTestString(size_t size, size_t seed = 0) { std::string result; result.resize(size); for (size_t n = 0; n < size; ++n) { int offset = (size + seed + n * 1337); char ch = ' ' + offset % (127 - 32); result[n] = ch; } return result; } } // namespace TEST(StringOutputBuffer, Append) { const size_t data_size = 100000; std::string data = CreateTestString(data_size); const size_t num_spans = 50; const size_t span_size = data_size / num_spans; StringOutputBuffer buffer; for (size_t n = 0; n < num_spans; ++n) { size_t start_offset = n * span_size; size_t end_offset = std::min(start_offset + span_size, data.size()); buffer.Append(&data[start_offset], end_offset - start_offset); } EXPECT_EQ(data.size(), buffer.size()); ASSERT_STREQ(data.c_str(), buffer.str().c_str()); } TEST(StringOutputBuffer, AppendWithPageSizeMultiples) { const size_t page_size = StringOutputBuffer::GetPageSizeForTesting(); const size_t page_count = 100; const size_t data_size = page_size * page_count; std::string data = CreateTestString(data_size); StringOutputBuffer buffer; for (size_t n = 0; n < page_count; ++n) { size_t start_offset = n * page_size; buffer.Append(&data[start_offset], page_size); } EXPECT_EQ(data.size(), buffer.size()); ASSERT_STREQ(data.c_str(), buffer.str().c_str()); } TEST(StringOutput, WrappedByStdOstream) { const size_t data_size = 100000; std::string data = CreateTestString(data_size); const size_t num_spans = 50; const size_t span_size = data_size / num_spans; StringOutputBuffer buffer; std::ostream out(&buffer); for (size_t n = 0; n < num_spans; ++n) { size_t start_offset = n * span_size; size_t end_offset = std::min(start_offset + span_size, data.size()); out << std::string_view(&data[start_offset], end_offset - start_offset); } EXPECT_EQ(data.size(), buffer.size()); ASSERT_STREQ(data.c_str(), buffer.str().c_str()); } TEST(StringOutputBuffer, ContentsEqual) { base::ScopedTempDir temp_dir; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); const size_t data_size = 100000; std::string data = CreateTestString(data_size); base::FilePath file_path = temp_dir.GetPath().AppendASCII("foo.txt"); base::WriteFile(file_path, data.c_str(), static_cast(data.size())); { StringOutputBuffer buffer; buffer.Append(data); EXPECT_TRUE(buffer.ContentsEqual(file_path)); // Different length and contents. buffer << "extra"; EXPECT_FALSE(buffer.ContentsEqual(file_path)); } // The same length, different contents. { StringOutputBuffer buffer; buffer << CreateTestString(data_size, 1); EXPECT_FALSE(buffer.ContentsEqual(file_path)); } } TEST(StringOutputBuffer, WriteToFile) { base::ScopedTempDir temp_dir; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); const size_t data_size = 100000; std::string data = CreateTestString(data_size); // Write if file doesn't exist. Also create directory. base::FilePath file_path = temp_dir.GetPath().AppendASCII("bar").AppendASCII("foo.txt"); StringOutputBuffer buffer; buffer.Append(data); EXPECT_TRUE(buffer.WriteToFile(file_path, nullptr)); // Verify file was created and has same content. base::File::Info file_info; ASSERT_TRUE(base::GetFileInfo(file_path, &file_info)); ASSERT_TRUE(buffer.ContentsEqual(file_path)); }