merge backout. CLOSED TREE
[mozilla-central.git] / netwerk / test / TestFileInput2.cpp
blob96fece20d0af223f7102bf6550322993727c2542
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 #include "nsIServiceManager.h"
39 #include "nsIComponentRegistrar.h"
40 #include "nsIInputStream.h"
41 #include "nsIOutputStream.h"
42 #include "nsIRunnable.h"
43 #include "nsIThread.h"
44 #include "nsCOMArray.h"
45 #include "nsISimpleEnumerator.h"
46 #include "prinrval.h"
47 #include "nsIFileStreams.h"
48 #include "nsIFileChannel.h"
49 #include "nsILocalFile.h"
50 #include "nsNetUtil.h"
51 #include <stdio.h>
53 ////////////////////////////////////////////////////////////////////////////////
55 #include <math.h>
56 #include "prprf.h"
57 #include "nsAutoLock.h"
59 class nsTimeSampler {
60 public:
61 nsTimeSampler();
62 void Reset();
63 void StartTime();
64 void EndTime();
65 void AddTime(PRIntervalTime time);
66 PRIntervalTime LastInterval() { return mLastInterval; }
67 char* PrintStats();
68 protected:
69 PRIntervalTime mStartTime;
70 double mSquares;
71 double mTotalTime;
72 PRUint32 mCount;
73 PRIntervalTime mLastInterval;
76 nsTimeSampler::nsTimeSampler()
78 Reset();
81 void
82 nsTimeSampler::Reset()
84 mStartTime = 0;
85 mSquares = 0;
86 mTotalTime = 0;
87 mCount = 0;
88 mLastInterval = 0;
91 void
92 nsTimeSampler::StartTime()
94 mStartTime = PR_IntervalNow();
97 void
98 nsTimeSampler::EndTime()
100 NS_ASSERTION(mStartTime != 0, "Forgot to call StartTime");
101 PRIntervalTime endTime = PR_IntervalNow();
102 mLastInterval = endTime - mStartTime;
103 AddTime(mLastInterval);
104 mStartTime = 0;
107 void
108 nsTimeSampler::AddTime(PRIntervalTime time)
110 nsAutoCMonitor mon(this);
111 mTotalTime += time;
112 mSquares += (double)time * (double)time;
113 mCount++;
116 char*
117 nsTimeSampler::PrintStats()
119 double mean = mTotalTime / mCount;
120 double variance = fabs(mSquares / mCount - mean * mean);
121 double stddev = sqrt(variance);
122 PRUint32 imean = (PRUint32)mean;
123 PRUint32 istddev = (PRUint32)stddev;
124 return PR_smprintf("%d +/- %d ms",
125 PR_IntervalToMilliseconds(imean),
126 PR_IntervalToMilliseconds(istddev));
129 ////////////////////////////////////////////////////////////////////////////////
131 nsTimeSampler gTimeSampler;
133 typedef nsresult (*CreateFun)(nsIRunnable* *result,
134 nsIFile* inPath,
135 nsIFile* outPath,
136 PRUint32 bufferSize);
138 ////////////////////////////////////////////////////////////////////////////////
140 nsresult
141 Copy(nsIInputStream* inStr, nsIOutputStream* outStr,
142 char* buf, PRUint32 bufSize, PRUint32 *copyCount)
144 nsresult rv;
145 while (PR_TRUE) {
146 PRUint32 count;
147 rv = inStr->Read(buf, bufSize, &count);
148 if (NS_FAILED(rv)) return rv;
149 if (count == 0) break;
151 PRUint32 writeCount;
152 rv = outStr->Write(buf, count, &writeCount);
153 if (NS_FAILED(rv)) return rv;
154 NS_ASSERTION(writeCount == count, "didn't write all the data");
155 *copyCount += writeCount;
157 rv = outStr->Flush();
158 return rv;
161 ////////////////////////////////////////////////////////////////////////////////
163 class FileSpecWorker : public nsIRunnable {
164 public:
166 NS_IMETHOD Run() {
167 nsresult rv;
169 PRIntervalTime startTime = PR_IntervalNow();
170 PRIntervalTime endTime;
171 nsCOMPtr<nsIInputStream> inStr;
172 nsCOMPtr<nsIOutputStream> outStr;
173 PRUint32 copyCount = 0;
175 // Open the input stream:
176 nsCOMPtr<nsIInputStream> fileIn;
177 rv = NS_NewLocalFileInputStream(getter_AddRefs(fileIn), mInPath);
178 if (NS_FAILED(rv)) return rv;
180 rv = NS_NewBufferedInputStream(getter_AddRefs(inStr), fileIn, 65535);
181 if (NS_FAILED(rv)) return rv;
183 // Open the output stream:
184 nsCOMPtr<nsIOutputStream> fileOut;
185 rv = NS_NewLocalFileOutputStream(getter_AddRefs(fileOut),
186 mOutPath,
187 PR_CREATE_FILE | PR_WRONLY | PR_TRUNCATE,
188 0664);
189 if (NS_FAILED(rv)) return rv;
191 rv = NS_NewBufferedOutputStream(getter_AddRefs(outStr), fileOut, 65535);
192 if (NS_FAILED(rv)) return rv;
194 // Copy from one to the other
195 rv = Copy(inStr, outStr, mBuffer, mBufferSize, &copyCount);
196 if (NS_FAILED(rv)) return rv;
198 endTime = PR_IntervalNow();
199 gTimeSampler.AddTime(endTime - startTime);
201 return rv;
204 NS_DECL_ISUPPORTS
206 FileSpecWorker()
207 : mInPath(nsnull), mOutPath(nsnull), mBuffer(nsnull),
208 mBufferSize(0)
212 nsresult Init(nsIFile* inPath, nsIFile* outPath,
213 PRUint32 bufferSize)
215 mInPath = inPath;
216 mOutPath = outPath;
217 mBuffer = new char[bufferSize];
218 mBufferSize = bufferSize;
219 return (mInPath && mOutPath && mBuffer)
220 ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
223 static nsresult Create(nsIRunnable* *result,
224 nsIFile* inPath,
225 nsIFile* outPath,
226 PRUint32 bufferSize)
228 FileSpecWorker* worker = new FileSpecWorker();
229 if (worker == nsnull)
230 return NS_ERROR_OUT_OF_MEMORY;
231 NS_ADDREF(worker);
233 nsresult rv = worker->Init(inPath, outPath, bufferSize);
234 if (NS_FAILED(rv)) {
235 NS_RELEASE(worker);
236 return rv;
238 *result = worker;
239 return NS_OK;
242 virtual ~FileSpecWorker() {
243 delete[] mBuffer;
246 protected:
247 nsCOMPtr<nsIFile> mInPath;
248 nsCOMPtr<nsIFile> mOutPath;
249 char* mBuffer;
250 PRUint32 mBufferSize;
253 NS_IMPL_ISUPPORTS1(FileSpecWorker, nsIRunnable)
255 ////////////////////////////////////////////////////////////////////////////////
257 #include "nsIIOService.h"
258 #include "nsIChannel.h"
260 class FileChannelWorker : public nsIRunnable {
261 public:
263 NS_IMETHOD Run() {
264 nsresult rv;
266 PRIntervalTime startTime = PR_IntervalNow();
267 PRIntervalTime endTime;
268 PRUint32 copyCount = 0;
269 nsCOMPtr<nsIFileChannel> inCh;
270 nsCOMPtr<nsIFileChannel> outCh;
271 nsCOMPtr<nsIInputStream> inStr;
272 nsCOMPtr<nsIOutputStream> outStr;
274 rv = NS_NewLocalFileChannel(getter_AddRefs(inCh), mInPath);
275 if (NS_FAILED(rv)) return rv;
277 rv = inCh->Open(getter_AddRefs(inStr));
278 if (NS_FAILED(rv)) return rv;
280 //rv = NS_NewLocalFileChannel(getter_AddRefs(outCh), mOutPath);
281 //if (NS_FAILED(rv)) return rv;
283 //rv = outCh->OpenOutputStream(0, -1, 0, getter_AddRefs(outStr));
284 //if (NS_FAILED(rv)) return rv;
286 // Copy from one to the other
287 rv = Copy(inStr, outStr, mBuffer, mBufferSize, &copyCount);
288 if (NS_FAILED(rv)) return rv;
290 endTime = PR_IntervalNow();
291 gTimeSampler.AddTime(endTime - startTime);
293 return rv;
296 NS_DECL_ISUPPORTS
298 FileChannelWorker()
299 : mInPath(nsnull), mOutPath(nsnull), mBuffer(nsnull),
300 mBufferSize(0)
304 nsresult Init(nsIFile* inPath, nsIFile* outPath,
305 PRUint32 bufferSize)
307 mInPath = inPath;
308 mOutPath = outPath;
309 mBuffer = new char[bufferSize];
310 mBufferSize = bufferSize;
311 return (mInPath && mOutPath && mBuffer)
312 ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
315 static nsresult Create(nsIRunnable* *result,
316 nsIFile* inPath,
317 nsIFile* outPath,
318 PRUint32 bufferSize)
320 FileChannelWorker* worker = new FileChannelWorker();
321 if (worker == nsnull)
322 return NS_ERROR_OUT_OF_MEMORY;
323 NS_ADDREF(worker);
325 nsresult rv = worker->Init(inPath, outPath, bufferSize);
326 if (NS_FAILED(rv)) {
327 NS_RELEASE(worker);
328 return rv;
330 *result = worker;
331 return NS_OK;
334 virtual ~FileChannelWorker() {
335 delete[] mBuffer;
338 protected:
339 nsCOMPtr<nsIFile> mInPath;
340 nsCOMPtr<nsIFile> mOutPath;
341 char* mBuffer;
342 PRUint32 mBufferSize;
345 NS_IMPL_ISUPPORTS1(FileChannelWorker, nsIRunnable)
347 ////////////////////////////////////////////////////////////////////////////////
349 void
350 Test(CreateFun create, PRUint32 count,
351 nsIFile* inDirSpec, nsIFile* outDirSpec, PRUint32 bufSize)
353 nsresult rv;
354 PRUint32 i;
356 nsCAutoString inDir;
357 nsCAutoString outDir;
358 (void)inDirSpec->GetNativePath(inDir);
359 (void)outDirSpec->GetNativePath(outDir);
360 printf("###########\nTest: from %s to %s, bufSize = %d\n",
361 inDir.get(), outDir.get(), bufSize);
362 gTimeSampler.Reset();
363 nsTimeSampler testTime;
364 testTime.StartTime();
366 nsCOMArray<nsIThread> threads;
368 nsCOMPtr<nsISimpleEnumerator> entries;
369 rv = inDirSpec->GetDirectoryEntries(getter_AddRefs(entries));
370 NS_ASSERTION(NS_SUCCEEDED(rv), "GetDirectoryEntries failed");
372 i = 0;
373 PRBool hasMore;
374 while (i < count && NS_SUCCEEDED(entries->HasMoreElements(&hasMore)) && hasMore) {
375 nsCOMPtr<nsISupports> next;
376 rv = entries->GetNext(getter_AddRefs(next));
377 if (NS_FAILED(rv)) goto done;
379 nsCOMPtr<nsIFile> inSpec = do_QueryInterface(next, &rv);
380 if (NS_FAILED(rv)) goto done;
382 nsCOMPtr<nsIFile> outSpec;
383 rv = outDirSpec->Clone(getter_AddRefs(outSpec)); // don't munge the original
384 if (NS_FAILED(rv)) goto done;
386 nsCAutoString leafName;
387 rv = inSpec->GetNativeLeafName(leafName);
388 if (NS_FAILED(rv)) goto done;
390 rv = outSpec->AppendNative(leafName);
391 if (NS_FAILED(rv)) goto done;
393 PRBool exists;
394 rv = outSpec->Exists(&exists);
395 if (NS_FAILED(rv)) goto done;
397 if (exists) {
398 rv = outSpec->Remove(PR_FALSE);
399 if (NS_FAILED(rv)) goto done;
402 nsCOMPtr<nsIThread> thread;
403 nsCOMPtr<nsIRunnable> worker;
404 rv = create(getter_AddRefs(worker),
405 inSpec,
406 outSpec,
407 bufSize);
408 if (NS_FAILED(rv)) goto done;
410 rv = NS_NewThread(getter_AddRefs(thread), worker, 0, PR_JOINABLE_THREAD);
411 if (NS_FAILED(rv)) goto done;
413 PRBool inserted = threads.InsertObjectAt(thread, i);
414 NS_ASSERTION(inserted, "not inserted");
416 i++;
419 PRUint32 j;
420 for (j = 0; j < i; j++) {
421 nsIThread* thread = threads.ObjectAt(j);
422 thread->Join();
425 done:
426 NS_ASSERTION(rv == NS_OK, "failed");
428 testTime.EndTime();
429 char* testStats = testTime.PrintStats();
430 char* workerStats = gTimeSampler.PrintStats();
431 printf(" threads = %d\n work time = %s,\n test time = %s\n",
432 i, workerStats, testStats);
433 PR_smprintf_free(workerStats);
434 PR_smprintf_free(testStats);
437 ////////////////////////////////////////////////////////////////////////////////
440 main(int argc, char* argv[])
442 nsresult rv;
444 if (argc < 2) {
445 printf("usage: %s <in-dir> <out-dir>\n", argv[0]);
446 return -1;
448 char* inDir = argv[1];
449 char* outDir = argv[2];
452 nsCOMPtr<nsIServiceManager> servMan;
453 NS_InitXPCOM2(getter_AddRefs(servMan), nsnull, nsnull);
454 nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(servMan);
455 NS_ASSERTION(registrar, "Null nsIComponentRegistrar");
456 if (registrar)
457 registrar->AutoRegister(nsnull);
459 nsCOMPtr<nsILocalFile> inDirFile;
460 rv = NS_NewNativeLocalFile(nsDependentCString(inDir), PR_FALSE, getter_AddRefs(inDirFile));
461 if (NS_FAILED(rv)) return rv;
463 nsCOMPtr<nsILocalFile> outDirFile;
464 rv = NS_NewNativeLocalFile(nsDependentCString(outDir), PR_FALSE, getter_AddRefs(outDirFile));
465 if (NS_FAILED(rv)) return rv;
467 CreateFun create = FileChannelWorker::Create;
468 Test(create, 1, inDirFile, outDirFile, 16 * 1024);
469 #if 1
470 printf("FileChannelWorker *****************************\n");
471 Test(create, 20, inDirFile, outDirFile, 16 * 1024);
472 Test(create, 20, inDirFile, outDirFile, 16 * 1024);
473 Test(create, 20, inDirFile, outDirFile, 16 * 1024);
474 Test(create, 20, inDirFile, outDirFile, 16 * 1024);
475 Test(create, 20, inDirFile, outDirFile, 16 * 1024);
476 Test(create, 20, inDirFile, outDirFile, 16 * 1024);
477 Test(create, 20, inDirFile, outDirFile, 16 * 1024);
478 Test(create, 20, inDirFile, outDirFile, 16 * 1024);
479 Test(create, 20, inDirFile, outDirFile, 16 * 1024);
480 #endif
481 create = FileSpecWorker::Create;
482 printf("FileSpecWorker ********************************\n");
483 #if 1
484 Test(create, 20, inDirFile, outDirFile, 16 * 1024);
485 Test(create, 20, inDirFile, outDirFile, 16 * 1024);
486 Test(create, 20, inDirFile, outDirFile, 16 * 1024);
487 Test(create, 20, inDirFile, outDirFile, 16 * 1024);
488 Test(create, 20, inDirFile, outDirFile, 16 * 1024);
489 Test(create, 20, inDirFile, outDirFile, 16 * 1024);
490 Test(create, 20, inDirFile, outDirFile, 16 * 1024);
491 Test(create, 20, inDirFile, outDirFile, 16 * 1024);
492 Test(create, 20, inDirFile, outDirFile, 16 * 1024);
493 #endif
494 #if 1
495 Test(create, 20, inDirFile, outDirFile, 4 * 1024);
496 Test(create, 20, inDirFile, outDirFile, 4 * 1024);
497 Test(create, 20, inDirFile, outDirFile, 4 * 1024);
498 Test(create, 20, inDirFile, outDirFile, 4 * 1024);
499 Test(create, 20, inDirFile, outDirFile, 4 * 1024);
500 Test(create, 20, inDirFile, outDirFile, 4 * 1024);
501 Test(create, 20, inDirFile, outDirFile, 4 * 1024);
502 Test(create, 20, inDirFile, outDirFile, 4 * 1024);
503 Test(create, 20, inDirFile, outDirFile, 4 * 1024);
504 #endif
505 } // this scopes the nsCOMPtrs
506 // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM
507 rv = NS_ShutdownXPCOM(nsnull);
508 NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed");
509 return 0;
512 ////////////////////////////////////////////////////////////////////////////////