1 // Copyright 2020 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
5 #include "gn/string_output_buffer.h"
6
7 #include "base/files/file_path.h"
8 #include "base/files/file_util.h"
9 #include "base/files/scoped_temp_dir.h"
10 #include "util/test/test.h"
11
12 namespace {
13
14 // Create a test string of |size| characters with pseudo-random ASCII content.
CreateTestString(size_t size,size_t seed=0)15 std::string CreateTestString(size_t size, size_t seed = 0) {
16 std::string result;
17 result.resize(size);
18 for (size_t n = 0; n < size; ++n) {
19 int offset = (size + seed + n * 1337);
20 char ch = ' ' + offset % (127 - 32);
21 result[n] = ch;
22 }
23 return result;
24 }
25
26 } // namespace
27
TEST(StringOutputBuffer,Append)28 TEST(StringOutputBuffer, Append) {
29 const size_t data_size = 100000;
30 std::string data = CreateTestString(data_size);
31
32 const size_t num_spans = 50;
33 const size_t span_size = data_size / num_spans;
34
35 StringOutputBuffer buffer;
36
37 for (size_t n = 0; n < num_spans; ++n) {
38 size_t start_offset = n * span_size;
39 size_t end_offset = std::min(start_offset + span_size, data.size());
40 buffer.Append(&data[start_offset], end_offset - start_offset);
41 }
42
43 EXPECT_EQ(data.size(), buffer.size());
44 ASSERT_STREQ(data.c_str(), buffer.str().c_str());
45 }
46
TEST(StringOutputBuffer,AppendWithPageSizeMultiples)47 TEST(StringOutputBuffer, AppendWithPageSizeMultiples) {
48 const size_t page_size = StringOutputBuffer::GetPageSizeForTesting();
49 const size_t page_count = 100;
50 const size_t data_size = page_size * page_count;
51 std::string data = CreateTestString(data_size);
52
53 StringOutputBuffer buffer;
54
55 for (size_t n = 0; n < page_count; ++n) {
56 size_t start_offset = n * page_size;
57 buffer.Append(&data[start_offset], page_size);
58 }
59
60 EXPECT_EQ(data.size(), buffer.size());
61 ASSERT_STREQ(data.c_str(), buffer.str().c_str());
62 }
63
TEST(StringOutput,WrappedByStdOstream)64 TEST(StringOutput, WrappedByStdOstream) {
65 const size_t data_size = 100000;
66 std::string data = CreateTestString(data_size);
67
68 const size_t num_spans = 50;
69 const size_t span_size = data_size / num_spans;
70
71 StringOutputBuffer buffer;
72 std::ostream out(&buffer);
73
74 for (size_t n = 0; n < num_spans; ++n) {
75 size_t start_offset = n * span_size;
76 size_t end_offset = std::min(start_offset + span_size, data.size());
77 out << std::string_view(&data[start_offset], end_offset - start_offset);
78 }
79
80 EXPECT_EQ(data.size(), buffer.size());
81 ASSERT_STREQ(data.c_str(), buffer.str().c_str());
82 }
83
TEST(StringOutputBuffer,ContentsEqual)84 TEST(StringOutputBuffer, ContentsEqual) {
85 base::ScopedTempDir temp_dir;
86 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
87
88 const size_t data_size = 100000;
89 std::string data = CreateTestString(data_size);
90
91 base::FilePath file_path = temp_dir.GetPath().AppendASCII("foo.txt");
92 base::WriteFile(file_path, data.c_str(), static_cast<int>(data.size()));
93
94 {
95 StringOutputBuffer buffer;
96 buffer.Append(data);
97
98 EXPECT_TRUE(buffer.ContentsEqual(file_path));
99
100 // Different length and contents.
101 buffer << "extra";
102 EXPECT_FALSE(buffer.ContentsEqual(file_path));
103 }
104
105 // The same length, different contents.
106 {
107 StringOutputBuffer buffer;
108 buffer << CreateTestString(data_size, 1);
109
110 EXPECT_FALSE(buffer.ContentsEqual(file_path));
111 }
112 }
113
TEST(StringOutputBuffer,WriteToFile)114 TEST(StringOutputBuffer, WriteToFile) {
115 base::ScopedTempDir temp_dir;
116 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
117
118 const size_t data_size = 100000;
119 std::string data = CreateTestString(data_size);
120
121 // Write if file doesn't exist. Also create directory.
122 base::FilePath file_path =
123 temp_dir.GetPath().AppendASCII("bar").AppendASCII("foo.txt");
124
125 StringOutputBuffer buffer;
126 buffer.Append(data);
127
128 EXPECT_TRUE(buffer.WriteToFile(file_path, nullptr));
129
130 // Verify file was created and has same content.
131 base::File::Info file_info;
132 ASSERT_TRUE(base::GetFileInfo(file_path, &file_info));
133 ASSERT_TRUE(buffer.ContentsEqual(file_path));
134 }
135