|
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #include "TestHarness.h" |
|
7 |
|
8 #include "mozilla/Attributes.h" |
|
9 #include "nsIScriptableBase64Encoder.h" |
|
10 #include "nsIInputStream.h" |
|
11 #include "nsAutoPtr.h" |
|
12 #include "nsStringAPI.h" |
|
13 #include <wchar.h> |
|
14 |
|
15 struct Chunk { |
|
16 Chunk(uint32_t l, const char* c) |
|
17 : mLength(l), mData(c) |
|
18 {} |
|
19 |
|
20 uint32_t mLength; |
|
21 const char* mData; |
|
22 }; |
|
23 |
|
24 struct Test { |
|
25 Test(Chunk* c, const char* r) |
|
26 : mChunks(c), mResult(r) |
|
27 {} |
|
28 |
|
29 Chunk* mChunks; |
|
30 const char* mResult; |
|
31 }; |
|
32 |
|
33 static Chunk kTest1Chunks[] = |
|
34 { |
|
35 Chunk(9, "Hello sir"), |
|
36 Chunk(0, nullptr) |
|
37 }; |
|
38 |
|
39 static Chunk kTest2Chunks[] = |
|
40 { |
|
41 Chunk(3, "Hel"), |
|
42 Chunk(3, "lo "), |
|
43 Chunk(3, "sir"), |
|
44 Chunk(0, nullptr) |
|
45 }; |
|
46 |
|
47 static Chunk kTest3Chunks[] = |
|
48 { |
|
49 Chunk(1, "I"), |
|
50 Chunk(0, nullptr) |
|
51 }; |
|
52 |
|
53 static Chunk kTest4Chunks[] = |
|
54 { |
|
55 Chunk(2, "Hi"), |
|
56 Chunk(0, nullptr) |
|
57 }; |
|
58 |
|
59 static Chunk kTest5Chunks[] = |
|
60 { |
|
61 Chunk(1, "B"), |
|
62 Chunk(2, "ob"), |
|
63 Chunk(0, nullptr) |
|
64 }; |
|
65 |
|
66 static Chunk kTest6Chunks[] = |
|
67 { |
|
68 Chunk(2, "Bo"), |
|
69 Chunk(1, "b"), |
|
70 Chunk(0, nullptr) |
|
71 }; |
|
72 |
|
73 static Chunk kTest7Chunks[] = |
|
74 { |
|
75 Chunk(1, "F"), // Carry over 1 |
|
76 Chunk(4, "iref"), // Carry over 2 |
|
77 Chunk(2, "ox"), // 1 |
|
78 Chunk(4, " is "), // 2 |
|
79 Chunk(2, "aw"), // 1 |
|
80 Chunk(4, "esom"), // 2 |
|
81 Chunk(2, "e!"), |
|
82 Chunk(0, nullptr) |
|
83 }; |
|
84 |
|
85 static Chunk kTest8Chunks[] = |
|
86 { |
|
87 Chunk(5, "ALL T"), |
|
88 Chunk(1, "H"), |
|
89 Chunk(4, "ESE "), |
|
90 Chunk(2, "WO"), |
|
91 Chunk(21, "RLDS ARE YOURS EXCEPT"), |
|
92 Chunk(9, " EUROPA. "), |
|
93 Chunk(25, "ATTEMPT NO LANDING THERE."), |
|
94 Chunk(0, nullptr) |
|
95 }; |
|
96 |
|
97 static Test kTests[] = |
|
98 { |
|
99 // Test 1, test a simple round string in one chunk |
|
100 Test( |
|
101 kTest1Chunks, |
|
102 "SGVsbG8gc2ly" |
|
103 ), |
|
104 // Test 2, test a simple round string split into round chunks |
|
105 Test( |
|
106 kTest2Chunks, |
|
107 "SGVsbG8gc2ly" |
|
108 ), |
|
109 // Test 3, test a single chunk that's 2 short |
|
110 Test( |
|
111 kTest3Chunks, |
|
112 "SQ==" |
|
113 ), |
|
114 // Test 4, test a single chunk that's 1 short |
|
115 Test( |
|
116 kTest4Chunks, |
|
117 "SGk=" |
|
118 ), |
|
119 // Test 5, test a single chunk that's 2 short, followed by a chunk of 2 |
|
120 Test( |
|
121 kTest5Chunks, |
|
122 "Qm9i" |
|
123 ), |
|
124 // Test 6, test a single chunk that's 1 short, followed by a chunk of 1 |
|
125 Test( |
|
126 kTest6Chunks, |
|
127 "Qm9i" |
|
128 ), |
|
129 // Test 7, test alternating carryovers |
|
130 Test( |
|
131 kTest7Chunks, |
|
132 "RmlyZWZveCBpcyBhd2Vzb21lIQ==" |
|
133 ), |
|
134 // Test 8, test a longish string |
|
135 Test( |
|
136 kTest8Chunks, |
|
137 "QUxMIFRIRVNFIFdPUkxEUyBBUkUgWU9VUlMgRVhDRVBUIEVVUk9QQS4gQVRURU1QVCBOTyBMQU5ESU5HIFRIRVJFLg==" |
|
138 ), |
|
139 // Terminator |
|
140 Test( |
|
141 nullptr, |
|
142 nullptr |
|
143 ) |
|
144 }; |
|
145 |
|
146 class FakeInputStream MOZ_FINAL : public nsIInputStream |
|
147 { |
|
148 public: |
|
149 |
|
150 FakeInputStream() |
|
151 : mTestNumber(0), |
|
152 mTest(&kTests[0]), |
|
153 mChunk(&mTest->mChunks[0]), |
|
154 mClosed(false) |
|
155 {} |
|
156 |
|
157 NS_DECL_ISUPPORTS |
|
158 NS_DECL_NSIINPUTSTREAM |
|
159 |
|
160 void Reset(); |
|
161 bool NextTest(); |
|
162 bool CheckTest(nsACString& aResult); |
|
163 bool CheckTest(nsAString& aResult); |
|
164 private: |
|
165 uint32_t mTestNumber; |
|
166 const Test* mTest; |
|
167 const Chunk* mChunk; |
|
168 bool mClosed; |
|
169 }; |
|
170 |
|
171 NS_IMPL_ISUPPORTS(FakeInputStream, nsIInputStream) |
|
172 |
|
173 NS_IMETHODIMP |
|
174 FakeInputStream::Close() |
|
175 { |
|
176 mClosed = true; |
|
177 return NS_OK; |
|
178 } |
|
179 |
|
180 NS_IMETHODIMP |
|
181 FakeInputStream::Available(uint64_t* aAvailable) |
|
182 { |
|
183 *aAvailable = 0; |
|
184 |
|
185 if (mClosed) |
|
186 return NS_BASE_STREAM_CLOSED; |
|
187 |
|
188 const Chunk* chunk = mChunk; |
|
189 while (chunk->mLength) { |
|
190 *aAvailable += chunk->mLength; |
|
191 chunk++; |
|
192 } |
|
193 |
|
194 return NS_OK; |
|
195 } |
|
196 |
|
197 NS_IMETHODIMP |
|
198 FakeInputStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aOut) |
|
199 { |
|
200 return NS_ERROR_NOT_IMPLEMENTED; |
|
201 } |
|
202 |
|
203 NS_IMETHODIMP |
|
204 FakeInputStream::ReadSegments(nsWriteSegmentFun aWriter, |
|
205 void* aClosure, |
|
206 uint32_t aCount, |
|
207 uint32_t* aRead) |
|
208 { |
|
209 *aRead = 0; |
|
210 |
|
211 if (mClosed) |
|
212 return NS_BASE_STREAM_CLOSED; |
|
213 |
|
214 while (mChunk->mLength) { |
|
215 uint32_t written = 0; |
|
216 |
|
217 nsresult rv = (*aWriter)(this, aClosure, mChunk->mData, |
|
218 *aRead, mChunk->mLength, &written); |
|
219 |
|
220 *aRead += written; |
|
221 NS_ENSURE_SUCCESS(rv, rv); |
|
222 |
|
223 mChunk++; |
|
224 } |
|
225 |
|
226 return NS_OK; |
|
227 } |
|
228 |
|
229 NS_IMETHODIMP |
|
230 FakeInputStream::IsNonBlocking(bool* aIsBlocking) |
|
231 { |
|
232 *aIsBlocking = false; |
|
233 return NS_OK; |
|
234 } |
|
235 |
|
236 void |
|
237 FakeInputStream::Reset() |
|
238 { |
|
239 mClosed = false; |
|
240 mChunk = &mTest->mChunks[0]; |
|
241 } |
|
242 |
|
243 bool |
|
244 FakeInputStream::NextTest() |
|
245 { |
|
246 mTestNumber++; |
|
247 mTest = &kTests[mTestNumber]; |
|
248 mChunk = &mTest->mChunks[0]; |
|
249 mClosed = false; |
|
250 |
|
251 return mTest->mChunks ? true : false; |
|
252 } |
|
253 |
|
254 bool |
|
255 FakeInputStream::CheckTest(nsACString& aResult) |
|
256 { |
|
257 return !strcmp(aResult.BeginReading(), mTest->mResult) ? true : false; |
|
258 } |
|
259 |
|
260 #ifdef XP_WIN |
|
261 static inline int NS_tstrcmp(char16ptr_t x, char16ptr_t y) { |
|
262 return wcscmp(x, y); |
|
263 } |
|
264 #else |
|
265 #define NS_tstrcmp strcmp |
|
266 #endif |
|
267 |
|
268 bool |
|
269 FakeInputStream::CheckTest(nsAString& aResult) |
|
270 { |
|
271 return !NS_tstrcmp(aResult.BeginReading(), |
|
272 NS_ConvertASCIItoUTF16(mTest->mResult).BeginReading()) |
|
273 ? true : false; |
|
274 } |
|
275 |
|
276 int main(int argc, char** argv) |
|
277 { |
|
278 ScopedXPCOM xpcom("Base64"); |
|
279 NS_ENSURE_FALSE(xpcom.failed(), 1); |
|
280 |
|
281 nsCOMPtr<nsIScriptableBase64Encoder> encoder = |
|
282 do_CreateInstance("@mozilla.org/scriptablebase64encoder;1"); |
|
283 NS_ENSURE_TRUE(encoder, 1); |
|
284 |
|
285 nsRefPtr<FakeInputStream> stream = new FakeInputStream(); |
|
286 do { |
|
287 nsString wideString; |
|
288 nsCString string; |
|
289 |
|
290 nsresult rv; |
|
291 rv = encoder->EncodeToString(stream, 0, wideString); |
|
292 NS_ENSURE_SUCCESS(rv, 1); |
|
293 |
|
294 stream->Reset(); |
|
295 |
|
296 rv = encoder->EncodeToCString(stream, 0, string); |
|
297 NS_ENSURE_SUCCESS(rv, 1); |
|
298 |
|
299 if (!stream->CheckTest(wideString) || !stream->CheckTest(string)) |
|
300 fail("Failed to convert properly\n"); |
|
301 |
|
302 } while (stream->NextTest()); |
|
303 |
|
304 return 0; |
|
305 } |