1// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "bin/dartutils.h"
6#include "bin/directory.h"
7#include "bin/file.h"
8#include "platform/assert.h"
9#include "platform/globals.h"
10#include "vm/unit_test.h"
11
12namespace dart {
13
14// Helper method to be able to run the test from the runtime
15// directory, or the top directory.
16static const char* GetFileName(const char* name) {
17 if (bin::File::Exists(NULL, name)) {
18 return name;
19 } else {
20 static const int kRuntimeLength = strlen("runtime/");
21 return name + kRuntimeLength;
22 }
23}
24
25TEST_CASE(Read) {
26 const char* kFilename = GetFileName("runtime/bin/file_test.cc");
27 bin::File* file = bin::File::Open(NULL, kFilename, bin::File::kRead);
28 EXPECT(file != NULL);
29 char buffer[16];
30 buffer[0] = '\0';
31 EXPECT(file->ReadFully(buffer, 13)); // ReadFully returns true.
32 buffer[13] = '\0';
33 EXPECT_STREQ("// Copyright ", buffer);
34 EXPECT(!file->WriteByte(1)); // Cannot write to a read-only file.
35 file->Release();
36}
37
38TEST_CASE(OpenUri_RelativeFilename) {
39 const char* kFilename = GetFileName("runtime/bin/file_test.cc");
40 char* encoded = reinterpret_cast<char*>(bin::DartUtils::ScopedCString(
41 strlen(kFilename) * 3 + 1));
42 char* t = encoded;
43 // percent-encode all characters 'c'
44 for (const char* p = kFilename; *p != '\0'; p++) {
45 if (*p == 'c') {
46 *t++ = '%';
47 *t++ = '6';
48 *t++ = '3';
49 } else {
50 *t++ = *p;
51 }
52 }
53 *t = 0;
54 bin::File* file = bin::File::OpenUri(NULL, encoded, bin::File::kRead);
55 EXPECT(file != NULL);
56 char buffer[16];
57 buffer[0] = '\0';
58 EXPECT(file->ReadFully(buffer, 13)); // ReadFully returns true.
59 buffer[13] = '\0';
60 EXPECT_STREQ("// Copyright ", buffer);
61 EXPECT(!file->WriteByte(1)); // Cannot write to a read-only file.
62 file->Release();
63}
64
65TEST_CASE(OpenUri_AbsoluteFilename) {
66 const char* kRelativeFilename = GetFileName("runtime/bin/file_test.cc");
67 const char* kFilename = bin::File::GetCanonicalPath(NULL, kRelativeFilename);
68 EXPECT_NOTNULL(kFilename);
69 char* encoded = reinterpret_cast<char*>(bin::DartUtils::ScopedCString(
70 strlen(kFilename) * 3 + 1));
71 char* t = encoded;
72 // percent-encode all characters 'c'
73 for (const char* p = kFilename; *p != '\0'; p++) {
74 if (*p == 'c') {
75 *t++ = '%';
76 *t++ = '6';
77 *t++ = '3';
78 } else {
79 *t++ = *p;
80 }
81 }
82 *t = 0;
83 bin::File* file = bin::File::OpenUri(NULL, encoded, bin::File::kRead);
84 EXPECT(file != NULL);
85 char buffer[16];
86 buffer[0] = '\0';
87 EXPECT(file->ReadFully(buffer, 13)); // ReadFully returns true.
88 buffer[13] = '\0';
89 EXPECT_STREQ("// Copyright ", buffer);
90 EXPECT(!file->WriteByte(1)); // Cannot write to a read-only file.
91 file->Release();
92}
93
94static const char* Concat(const char* a, const char* b) {
95 const intptr_t len = strlen(a) + strlen(b);
96 char* c = bin::DartUtils::ScopedCString(len + 1);
97 EXPECT_NOTNULL(c);
98 snprintf(c, len + 1, "%s%s", a, b);
99 return c;
100}
101
102TEST_CASE(OpenUri_ValidUri) {
103 const char* kRelativeFilename = GetFileName("runtime/bin/file_test.cc");
104 const char* kAbsoluteFilename = bin::File::GetCanonicalPath(NULL,
105 kRelativeFilename);
106 EXPECT_NOTNULL(kAbsoluteFilename);
107 const char* kFilename = Concat("file:///", kAbsoluteFilename);
108
109 char* encoded = reinterpret_cast<char*>(bin::DartUtils::ScopedCString(
110 strlen(kFilename) * 3 + 1));
111 char* t = encoded;
112 // percent-encode all characters 'c'
113 for (const char* p = kFilename; *p != '\0'; p++) {
114 if (*p == 'c') {
115 *t++ = '%';
116 *t++ = '6';
117 *t++ = '3';
118 } else {
119 *t++ = *p;
120 }
121 }
122 *t = 0;
123 bin::File* file = bin::File::OpenUri(NULL, encoded, bin::File::kRead);
124 EXPECT(file != NULL);
125 char buffer[16];
126 buffer[0] = '\0';
127 EXPECT(file->ReadFully(buffer, 13)); // ReadFully returns true.
128 buffer[13] = '\0';
129 EXPECT_STREQ("// Copyright ", buffer);
130 EXPECT(!file->WriteByte(1)); // Cannot write to a read-only file.
131 file->Release();
132}
133
134TEST_CASE(OpenUri_UriWithSpaces) {
135 const char* kRelativeFilename = GetFileName("runtime/bin/file_test.cc");
136 const char* strSystemTemp = bin::Directory::SystemTemp(NULL);
137 EXPECT_NOTNULL(strSystemTemp);
138 const char* kTempDir = Concat(strSystemTemp, "/foo bar");
139 const char* strTempDir = bin::Directory::CreateTemp(NULL, kTempDir);
140 EXPECT_NOTNULL(strTempDir);
141 const char* kTargetFilename = Concat(strTempDir, "/file test.cc");
142 bool result = bin::File::Copy(NULL, kRelativeFilename, kTargetFilename);
143 EXPECT(result);
144
145 const char* kAbsoluteFilename = bin::File::GetCanonicalPath(NULL,
146 kTargetFilename);
147 EXPECT_NOTNULL(kAbsoluteFilename);
148 const char* kFilename = Concat("file:///", kAbsoluteFilename);
149
150 char* encoded = reinterpret_cast<char*>(bin::DartUtils::ScopedCString(
151 strlen(kFilename) * 3 + 1));
152 char* t = encoded;
153 // percent-encode all spaces
154 for (const char* p = kFilename; *p != '\0'; p++) {
155 if (*p == ' ') {
156 *t++ = '%';
157 *t++ = '2';
158 *t++ = '0';
159 } else {
160 *t++ = *p;
161 }
162 }
163 *t = 0;
164 printf("encoded: %s\n", encoded);
165 bin::File* file = bin::File::OpenUri(NULL, encoded, bin::File::kRead);
166 EXPECT(file != NULL);
167 char buffer[16];
168 buffer[0] = '\0';
169 EXPECT(file->ReadFully(buffer, 13)); // ReadFully returns true.
170 buffer[13] = '\0';
171 EXPECT_STREQ("// Copyright ", buffer);
172 EXPECT(!file->WriteByte(1)); // Cannot write to a read-only file.
173 file->Release();
174 bin::Directory::Delete(NULL, strTempDir, /* recursive= */ true);
175}
176
177TEST_CASE(OpenUri_InvalidUriPercentEncoding) {
178 const char* kFilename = GetFileName("runtime/bin/file_test.cc");
179 char* encoded = reinterpret_cast<char*>(bin::DartUtils::ScopedCString(
180 strlen(kFilename) * 3 + 1));
181 char* t = encoded;
182 // percent-encode all characters 'c'
183 for (const char* p = kFilename; *p != '\0'; p++) {
184 if (*p == 'c') {
185 *t++ = '%';
186 *t++ = 'f';
187 *t++ = 'o';
188 } else {
189 *t++ = *p;
190 }
191 }
192 *t = 0;
193 bin::File* file = bin::File::OpenUri(NULL, encoded, bin::File::kRead);
194 EXPECT(file == NULL);
195}
196
197TEST_CASE(OpenUri_TruncatedUriPercentEncoding) {
198 const char* kFilename = GetFileName("runtime/bin/file_test.cc");
199 char* encoded = reinterpret_cast<char*>(bin::DartUtils::ScopedCString(
200 strlen(kFilename) * 3 + 1));
201 char* t = encoded;
202 // percent-encode all characters 'c'
203 for (const char* p = kFilename; *p != '\0'; p++) {
204 if (*p == 'c') {
205 *t++ = '%';
206 *t++ = 'f';
207 *t++ = 'o';
208 } else {
209 *t++ = *p;
210 }
211 }
212 *(t - 1) = 0; // truncate last uri encoding
213 bin::File* file = bin::File::OpenUri(NULL, encoded, bin::File::kRead);
214 EXPECT(file == NULL);
215}
216
217TEST_CASE(FileLength) {
218 const char* kFilename =
219 GetFileName("runtime/tests/vm/data/fixed_length_file");
220 bin::File* file = bin::File::Open(NULL, kFilename, bin::File::kRead);
221 EXPECT(file != NULL);
222 EXPECT_EQ(42, file->Length());
223 file->Release();
224}
225
226TEST_CASE(FilePosition) {
227 char buf[42];
228 const char* kFilename =
229 GetFileName("runtime/tests/vm/data/fixed_length_file");
230 bin::File* file = bin::File::Open(NULL, kFilename, bin::File::kRead);
231 EXPECT(file != NULL);
232 EXPECT(file->ReadFully(buf, 12));
233 EXPECT_EQ(12, file->Position());
234 EXPECT(file->ReadFully(buf, 6));
235 EXPECT_EQ(18, file->Position());
236 file->Release();
237}
238
239} // namespace dart
240