transport: pass correct channel
[abstract.git] / xpunit / nsTestRunner.cpp
blob09fea3534c0e944291c3f9791e83102708e17795
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent tw=79 ft=cpp: */
3 /*
4 * Copyright (C) 2007 Sergey Yanovich <ynvich@gmail.com>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public
17 * License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
22 #include "xpcom-config.h"
24 #include "nsXPCOM.h"
25 #include "nsStringAPI.h"
26 #include "nsNetUtil.h"
27 #include "nsIComponentManager.h"
28 #include "nsComponentManagerUtils.h"
29 #include "nsServiceManagerUtils.h"
30 #include "nsIPrefBranch.h"
31 #include "nsIWindowWatcher.h"
32 #include "nsIDOMWindow.h"
33 #include "nsIDOMWindowCollection.h"
34 #include "nsIInterfaceRequestorUtils.h"
35 #include "nsIWebProgress.h"
36 #include "nsIDOMDocument.h"
37 #include "nsIDOMDocumentView.h"
38 #include "nsIDOMElement.h"
39 #include "nsIDOMEventTarget.h"
40 #include "nsIDOMDocumentEvent.h"
41 #include "nsIDOMEvent.h"
42 #include "nsIDOMAbstractView.h"
43 #include "nsIThreadManager.h"
44 #include "nsIThread.h"
45 #include "nsILineInputStream.h"
46 #include "nsIComponentRegistrar.h"
47 #include "nsDirectoryServiceDefs.h"
49 /* Unfrozen interfaces */
50 #include "nsAutoPtr.h"
51 #include "nsICommandLine.h"
52 #include "nsIWebNavigation.h"
53 #include "nsIAppStartup.h"
54 #include "nsIConsoleService.h"
55 #include "nsIConsoleMessage.h"
56 #include "nsIScriptError.h"
57 #include "jspubtd.h"
58 #include "nsIJSContextStack.h"
59 #include "nsIRDFService.h"
60 #include "nsIRDFDataSource.h"
61 #include "nsIRDFResource.h"
62 #include "nsIDOMXULDocument.h"
63 #include "nsIDOMXULCommandDispatcher.h"
64 #include "nsIDOMXULCommandEvent.h"
65 #include "nsIStringEnumerator.h"
66 #include "nsIURI.h"
68 /* Project includes */
69 #include "nsITestRunner.h"
70 #include "nsITestResult.h"
71 #include "nsITest.h"
72 #include "nstestjs.h"
73 #include "nsTestRunner.h"
74 #include "nsTestFailure.h"
75 #include "nsOneLineDiff.h"
76 #include "nsTestXmlFactory.h"
78 #include "nsTestUtils.h"
80 class nsFormatJSMessage: public nsTestFailure
82 public:
83 nsFormatJSMessage(nsIConsoleMessage *aMessage);
84 nsFormatJSMessage(const char *aFile);
85 ~nsFormatJSMessage() {;}
86 private:
87 nsresult parseScriptError(nsIConsoleMessage *aMessage);
88 nsresult formatErrorMessage(nsIScriptError *error);
89 PRBool parseException(const nsACString &aMessage);
90 nsresult getSourceFile();
91 nsresult parseLocalFile();
92 nsresult parseChrome();
94 nsRefPtr<nsTestRunner> mResolver;
98 /******************** nsTestRunner ***********************************/
99 nsTestRunner::nsTestRunner()
100 :mTestTree(nsnull), mArmed(PR_FALSE), mHasWindow(PR_FALSE)
104 nsTestRunner::~nsTestRunner()
108 nsTestRunner* nsTestRunner::gTestRunner = nsnull;
110 NS_IMPL_THREADSAFE_ISUPPORTS8(nsTestRunner,
111 nsITestRunner,
112 nsIConsoleListener,
113 nsIWebProgressListener,
114 nsISupportsWeakReference,
115 nsITimerCallback,
116 nsICommandLineHandler,
117 nsICompareListener,
118 nsTestRunner)
120 NS_IMETHODIMP
121 nsTestRunner::MarkTestStart()
123 return mTestResult->MarkTestStart();
126 NS_IMETHODIMP
127 nsTestRunner::AddFailure(const char *aFile, PRUint32 aLine, const char *aText)
129 return mTestResult->AddFailure(aFile, aLine, aText, PR_FALSE);
132 NS_IMETHODIMP
133 nsTestRunner::AddJSFailure(const char *aText)
135 nsresult rv;
136 JSContext *cx = nsnull;
137 nsCAutoString file;
139 if ( ! mJSStack ) {
140 mJSStack = do_GetService("@mozilla.org/js/xpc/ContextStack;1");
141 NS_ENSURE_TRUE(mJSStack, NS_ERROR_FAILURE);
143 rv = mJSStack->Peek( &cx );
144 NS_ENSURE_TRUE(cx, NS_ERROR_FAILURE);
146 nsFormatJSMessage m(ns_test_js_caller_filename(cx));
148 return mTestResult->AddFailure(m.getFile(),
149 ns_test_js_caller_lineno(cx), aText, PR_FALSE);
152 NS_IMETHODIMP
153 nsTestRunner::AddError(PRUint32 aCode, const char *aComment)
155 return mTestResult->AddFailure(nsnull, aCode, aComment, PR_TRUE);
158 NS_IMETHODIMP
159 nsTestRunner::MarkTestEnd(nsITest *aTest)
161 if (aTest != (nsITest *) mTestTree.Peek())
162 return NS_ERROR_ILLEGAL_VALUE;
163 if (mArmed) {
164 mArmed = PR_FALSE;
165 mTimer->Cancel();
166 if(NS_FAILED(mTimer->InitWithCallback(this, 0, nsITimer::TYPE_ONE_SHOT)))
167 traverse();
169 return NS_OK;
172 NS_IMETHODIMP
173 nsTestRunner::GetHasWindow(PRBool *aHasWindow)
175 NS_ENSURE_ARG_POINTER(aHasWindow);
176 *aHasWindow = mHasWindow;
177 return NS_OK;
180 NS_IMETHODIMP
181 nsTestRunner::GetTestWindow(nsIDOMWindow* *aTestWindow)
183 NS_ENSURE_ARG_POINTER( aTestWindow );
184 if ( !mTestWindow ) {
185 *aTestWindow = nsnull;
186 return NS_ERROR_NOT_INITIALIZED;
188 *aTestWindow = mTestWindow;
189 NS_ADDREF( *aTestWindow );
191 return NS_OK;
194 NS_IMETHODIMP
195 nsTestRunner::GetWatchWindow(nsIDOMWindow* *aWatchWindow)
197 NS_ENSURE_ARG_POINTER( aWatchWindow );
198 if ( !mWatchWindow ) {
199 *aWatchWindow = nsnull;
200 return NS_ERROR_NOT_INITIALIZED;
202 *aWatchWindow = mWatchWindow;
203 NS_ADDREF( *aWatchWindow );
205 return NS_OK;
208 NS_IMETHODIMP
209 nsTestRunner::SetWatchWindow(nsIDOMWindow *aWatchWindow)
211 nsresult rv;
213 if (mWatchWindow == aWatchWindow)
215 if (mWatchWindow && !mHasWindow)
217 rv = ArmTimer(1000);
218 NS_ENSURE_SUCCESS(rv, rv);
220 return NS_OK;
223 if (mWatchWindow) {
224 nsCOMPtr<nsIWebNavigation> web(do_GetInterface(mWatchWindow, &rv ));
225 NS_ENSURE_SUCCESS(rv, rv);
227 nsCOMPtr<nsIWebProgress> webProgress(do_QueryInterface(web, &rv));
228 NS_ENSURE_SUCCESS(rv, rv);
230 rv = webProgress->RemoveProgressListener(this);
231 NS_ENSURE_SUCCESS(rv, rv);
233 mWatchWindow = nsnull;
236 if (aWatchWindow) {
237 nsCOMPtr<nsIWebNavigation> web(do_GetInterface(aWatchWindow, &rv ));
238 NS_ENSURE_SUCCESS(rv, rv);
240 nsCOMPtr<nsIWebProgress> webProgress(do_QueryInterface(web, &rv));
241 NS_ENSURE_SUCCESS(rv, rv);
243 rv = webProgress->AddProgressListener(this,
244 nsIWebProgress::NOTIFY_STATE_WINDOW);
245 NS_ENSURE_SUCCESS(rv, rv);
247 if (mHasWindow) {
248 rv = ArmTimer(1000);
249 NS_ENSURE_SUCCESS(rv, rv);
252 mWatchWindow = aWatchWindow;
254 return NS_OK;
257 NS_IMETHODIMP
258 nsTestRunner::ArmTimer(PRUint32 aDelay)
260 NS_ENSURE_TRUE(!mArmed, NS_ERROR_ALREADY_INITIALIZED);
262 nsresult rv;
263 rv = mTimer->InitWithCallback(this, aDelay << 1, nsITimer::TYPE_ONE_SHOT);
264 NS_ENSURE_SUCCESS(rv, rv);
266 mArmed = PR_TRUE;
267 return NS_OK;
270 nsresult
271 findElement(const nsAString& aCommand, nsIDOMWindow *wnd,
272 nsIDOMElement **element)
274 nsresult rv;
275 PRUint32 count, i;
276 nsCOMPtr<nsIDOMWindowCollection> list;
277 nsCOMPtr<nsIDOMWindow> next;
278 nsCOMPtr<nsIDOMDocument> doc;
280 while (wnd) {
281 rv = wnd->GetDocument(getter_AddRefs(doc));
282 NS_ENSURE_SUCCESS(rv, rv);
284 rv = doc->GetElementById(aCommand, element);
285 NS_ENSURE_SUCCESS(rv, rv);
286 if (*element)
287 return NS_OK;
289 rv = wnd->GetFrames(getter_AddRefs(list));
290 NS_ENSURE_SUCCESS(rv, rv);
292 rv = list->GetLength(&count);
293 NS_ENSURE_SUCCESS(rv, rv);
295 for (i = 0; i < count; i++) {
296 rv = list->Item(i, getter_AddRefs(next));
297 NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_STATE(next);
299 rv = findElement(aCommand, next, element);
300 NS_ENSURE_SUCCESS(rv, rv);
301 if (*element)
302 return NS_OK;
305 return NS_ERROR_ILLEGAL_VALUE;
309 NS_IMETHODIMP
310 nsTestRunner::DoCommand(const nsAString& aCommand)
312 nsresult rv;
313 nsCOMPtr<nsIDOMElement> element;
315 rv = findElement(aCommand, mTestWindow, getter_AddRefs(element));
316 NS_ENSURE_SUCCESS(rv, rv);
318 PRBool isDisabled;
319 rv = element->HasAttribute(NS_LITERAL_STRING("disabled"), &isDisabled);
320 NS_ENSURE_SUCCESS(rv, rv);
321 if ( isDisabled )
322 return NS_ERROR_NOT_AVAILABLE;
324 nsCOMPtr<nsIDOMEventTarget> evtTgt(do_QueryInterface(element, &rv));
325 NS_ENSURE_SUCCESS(rv, rv);
327 nsCOMPtr<nsIDOMDocument> doc;
328 rv = element->GetOwnerDocument(getter_AddRefs(doc));
329 NS_ENSURE_SUCCESS(rv, rv);
331 nsCOMPtr<nsIDOMDocumentEvent> docEvent(do_QueryInterface(doc, &rv));
332 NS_ENSURE_SUCCESS(rv, rv);
334 nsCOMPtr<nsIDOMEvent> evt;
335 rv = docEvent->CreateEvent(NS_LITERAL_STRING("XULCommandEvent"),
336 getter_AddRefs(evt));
337 NS_ENSURE_SUCCESS(rv, rv);
339 nsCOMPtr<nsIDOMXULCommandEvent> cmdEvt(do_QueryInterface(evt, &rv));
340 NS_ENSURE_SUCCESS(rv, rv);
342 nsCOMPtr<nsIDOMDocumentView> docView(do_QueryInterface(doc, &rv));
343 NS_ENSURE_SUCCESS(rv, rv);
344 nsCOMPtr<nsIDOMAbstractView> view;
345 rv = docView->GetDefaultView(getter_AddRefs(view));
346 NS_ENSURE_SUCCESS(rv, rv);
348 rv = cmdEvt->InitCommandEvent(NS_LITERAL_STRING("command"), PR_TRUE, PR_TRUE,
349 view, 0, 0, 0, 0, 0, nsnull);
350 NS_ENSURE_SUCCESS(rv, rv);
352 PRBool isDefault;
353 rv = evtTgt->DispatchEvent( evt, &isDefault );
354 NS_ENSURE_SUCCESS(rv, rv);
356 return NS_OK;
359 NS_IMETHODIMP
360 nsTestRunner::CompareWithFile(const char* aFile, PRUint32 aLine,
361 nsIChannel *dataChannel, nsIURI *reference)
363 nsresult rv = NS_OK;
364 NS_TEST_BEGIN(this);
366 nsCOMPtr<nsOneLineDiff> differ = new nsOneLineDiff();
367 NS_ENSURE_TRUE(differ, NS_ERROR_OUT_OF_MEMORY);
369 nsCOMPtr<nsIChannel> refChannel;
370 rv = NS_NewChannel(getter_AddRefs(refChannel), reference);
371 NS_ENSURE_SUCCESS(rv, rv);
373 nsCOMPtr<nsIThreadManager> threadMngr =
374 do_GetService("@mozilla.org/thread-manager;1", &rv);
375 NS_ENSURE_SUCCESS(rv, rv);
377 nsCOMPtr<nsIThread> thread;
378 rv = threadMngr->GetCurrentThread(getter_AddRefs(thread));
379 NS_ENSURE_SUCCESS(rv, rv);
381 mCompareURI = reference;
382 mCompareFile = aFile;
383 mCompareLine = aLine;
384 rv = differ->Compare(refChannel, dataChannel, this);
385 NS_ENSURE_SUCCESS(rv, rv);
387 while (mCompareURI)
389 PRBool isProcessed = PR_FALSE;
390 rv = thread->ProcessNextEvent(PR_TRUE, &isProcessed);
391 NS_ENSURE_SUCCESS(rv, rv);
394 return NS_OK;
397 NS_IMETHODIMP
398 nsTestRunner::Observe(nsIConsoleMessage *aMessage)
400 NS_ENSURE_TRUE(mTestResult, NS_ERROR_UNEXPECTED);
402 nsFormatJSMessage m(aMessage);
403 mTestResult->AddFailure(m.getFile(), m.getLine(), m.getText(), PR_TRUE);
404 return NS_OK;
407 nsresult
408 nsTestRunner::openMainWindow()
410 nsresult rv;
411 nsCOMPtr<nsIConsoleService> jsConsole;
412 nsCOMPtr<nsIPrefBranch> pref;
413 nsCAutoString chromeURI;
414 nsCOMPtr<nsIWindowWatcher> ww;
415 nsCOMPtr<nsIDOMWindow> wnd;
417 pref = do_GetService("@mozilla.org/preferences-service;1", &rv);
418 NS_ENSURE_SUCCESS(rv, rv);
419 rv = pref->GetCharPref("toolkit.defaultChromeURI",getter_Copies(chromeURI));
420 NS_ENSURE_SUCCESS(rv, rv);
421 ww = do_GetService("@mozilla.org/embedcomp/window-watcher;1", &rv);
422 NS_ENSURE_SUCCESS(rv, rv);
423 rv = ww->OpenWindow(0, chromeURI.get(), "_blank", "chrome,dialog=no,all",
424 0, getter_AddRefs(wnd) );
425 NS_ENSURE_SUCCESS(rv, rv);
427 rv = SetWatchWindow(wnd);
428 NS_ENSURE_SUCCESS(rv, rv);
430 mTestWindow = wnd;
431 jsConsole = do_GetService("@mozilla.org/consoleservice;1", &rv);
432 NS_ENSURE_TRUE(jsConsole, NS_OK);
433 jsConsole->RegisterListener( this );
435 return NS_OK;
438 nsresult
439 nsTestRunner::init()
441 nsresult rv;
442 nsCOMPtr<nsIPrefBranch> pref;
444 pref = do_GetService("@mozilla.org/preferences-service;1", &rv);
445 NS_ENSURE_SUCCESS(rv, rv);
446 (void) pref->GetCharPref("xpunit.firstTest",getter_Copies(mTestID));
447 if (!mTestID.get() || !mTestID.get()[0]) {
448 printf_stderr("Please provide first test contractID in any pref file:\n");
449 printf_stderr("pref(\"xpunit.firstTest\",\"@test.org/contract/id\");\n");
450 return NS_ERROR_NOT_AVAILABLE;
453 mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
454 NS_ENSURE_SUCCESS(rv, rv);
456 mTestResult = do_CreateInstance("@aasii.org/cxxunit/testresult", &rv);
457 NS_ENSURE_SUCCESS(rv, rv);
459 rv = openMainWindow();
460 NS_ENSURE_SUCCESS(rv, rv);
462 rv = registerXmlTests();
463 NS_ENSURE_SUCCESS(rv, rv);
465 rv = pushTest(mTestID.get());
466 NS_ENSURE_SUCCESS(rv, rv);
468 return NS_OK;
471 nsresult
472 nsTestRunner::pushTest(const char * aContractID)
474 nsresult rv;
475 nsCOMPtr<nsITest> test = do_CreateInstance(aContractID, &rv);
477 if (NS_FAILED(rv)) {
478 AddError(nsITestRunner::errorLoad, aContractID);
479 return rv;
482 mTestTree.Push( (void *) test.get() );
484 rv = test->Test(this);
485 if (NS_FAILED(rv)) return rv;
487 test.get()->AddRef();
488 return NS_OK;
491 nsresult
492 nsTestRunner::getNextTest(nsACString &aContractID)
494 nsresult rv;
495 PRBool hasMore;
497 nsITest *test = (nsITest *) mTestTree.Peek();
498 NS_ENSURE_TRUE(test, NS_ERROR_UNEXPECTED);
500 nsCOMPtr<nsIUTF8StringEnumerator> testNode(do_QueryInterface(test, &rv));
501 if (rv == NS_NOINTERFACE)
502 return NS_ERROR_NOT_AVAILABLE;
503 NS_ENSURE_SUCCESS(rv, rv);
505 rv = testNode->HasMore( &hasMore );
506 NS_ENSURE_SUCCESS(rv, rv);
507 if (! hasMore)
508 return NS_ERROR_NOT_AVAILABLE;
510 rv = testNode->GetNext( aContractID );
511 NS_ENSURE_SUCCESS(rv, rv);
513 return NS_OK;
516 void
517 nsTestRunner::traverse()
519 nsresult rv;
520 nsITest *test;
522 while (mTestTree.GetSize()) {
524 rv = getNextTest( mTestID );
526 if (NS_FAILED(rv)) {
527 test = (nsITest *) mTestTree.Pop();
528 NS_RELEASE(test);
529 } else {
530 rv = pushTest(mTestID.get());
531 if (NS_FAILED(rv))
532 mTestTree.Empty();
533 if (mArmed)
534 return;
538 if (mTestWindow) {
539 mTestWindow = nsnull;
540 rv = mTimer->InitWithCallback(this, 0, nsITimer::TYPE_ONE_SHOT);
541 if (NS_SUCCEEDED(rv))
542 return;
545 done();
548 nsresult
549 nsTestRunner::closeMainWindow()
551 nsresult rv;
553 nsCOMPtr<nsIAppStartup> app;
554 app = do_GetService("@mozilla.org/toolkit/app-startup;1", &rv);
555 NS_ENSURE_SUCCESS(rv, rv);
556 rv = app->Quit(app->eForceQuit);
557 NS_ENSURE_SUCCESS(rv, rv);
559 return NS_OK;
562 void
563 nsTestRunner::done()
565 nsCOMPtr<nsIConsoleService> jsConsole;
567 if (!mHasWindow)
569 mTestWindow = nsnull;
570 return;
572 jsConsole = do_GetService("@mozilla.org/consoleservice;1");
573 if (jsConsole )
574 (void) jsConsole->UnregisterListener(this);
576 (void) closeMainWindow();
577 (void) mTestResult->Done();
578 mTestResult = nsnull;
579 mTimer = nsnull;
582 NS_IMETHODIMP
583 nsTestRunner::Handle(nsICommandLine *aCommandLine)
585 nsresult rv;
586 PRBool isTest;
588 rv = aCommandLine->HandleFlag(NS_LITERAL_STRING("test"), PR_TRUE, &isTest);
589 NS_ENSURE_SUCCESS(rv,rv);
590 if (!isTest)
591 return NS_OK;
593 aCommandLine->SetPreventDefault(PR_TRUE);
595 rv = init();
596 if (NS_FAILED(rv)) {
597 printf_stderr("Failed to initialize test framework\n");
598 return NS_ERROR_ABORT;
601 traverse();
602 return NS_OK;
605 NS_IMETHODIMP
606 nsTestRunner::GetHelpInfo(nsACString & aHelpInfo)
608 aHelpInfo.Assign(" --test Run unit test collection\n");
609 return NS_OK;
612 nsresult
613 nsTestRunner::resolve(nsACString &aURL, const PRUnichar* *result)
615 nsresult rv;
616 nsCOMPtr<nsIRDFService> rdfSrv;
617 nsCOMPtr<nsIRDFResource> src, prop;
618 nsCOMPtr<nsIRDFNode> target;
619 nsCOMPtr<nsIRDFLiteral> targetLiteral;
621 NS_ENSURE_ARG_POINTER(result);
622 *result = nsnull;
623 rdfSrv = do_GetService("@mozilla.org/rdf/rdf-service;1", &rv);
624 NS_ENSURE_SUCCESS( rv, rv );
626 if ( ! mFileMap ) {
627 nsCOMPtr<nsIPrefBranch> pref;
628 nsCAutoString url;
630 pref = do_GetService("@mozilla.org/preferences-service;1", &rv);
631 NS_ENSURE_SUCCESS(rv, rv );
632 rv = pref->GetCharPref("xpunit.fileMap",getter_Copies(url));
633 NS_ENSURE_SUCCESS(rv, rv );
635 rv = rdfSrv->GetDataSourceBlocking(url.get(),
636 getter_AddRefs( mFileMap ));
637 NS_ENSURE_TRUE( mFileMap, rv );
640 rv = rdfSrv->GetResource( aURL, getter_AddRefs( src ));
641 NS_ENSURE_SUCCESS(rv, rv );
642 rv = rdfSrv->GetResource(
643 NS_LITERAL_CSTRING("http://www.aasii.org/AA-rdf#File"),
644 getter_AddRefs( prop ));
645 NS_ENSURE_SUCCESS(rv, rv );
647 rv = mFileMap->GetTarget(src, prop, PR_TRUE, getter_AddRefs( target ));
648 if (! target)
649 return rv;
650 targetLiteral = do_QueryInterface( target, &rv );
651 NS_ENSURE_TRUE( target, rv );
652 targetLiteral->GetValueConst( result );
653 NS_ENSURE_TRUE( target, rv );
655 return NS_OK;
658 NS_IMETHODIMP
659 nsTestRunner::Notify(nsITimer *timer)
661 if (mArmed) {
662 mArmed = PR_FALSE;
663 AddError(nsITestRunner::errorTimeout, mTestID.get());
665 traverse();
666 return NS_OK;
669 NS_IMETHODIMP
670 nsTestRunner::OnStateChange(nsIWebProgress *aWebProgress,
671 nsIRequest *aRequest, PRUint32 aStateFlags, nsresult aStatus)
673 if (! (aStateFlags & nsIWebProgressListener::STATE_STOP) )
674 return NS_OK;
676 nsCOMPtr<nsIDOMWindow> wnd;
677 aWebProgress->GetDOMWindow(getter_AddRefs( wnd ));
678 if ( wnd != mWatchWindow ) {
679 return NS_OK;
682 mWatchWindow = nsnull;
683 aWebProgress->RemoveProgressListener( this );
685 if (!mHasWindow)
687 mHasWindow = PR_TRUE;
688 if (!mTestWindow)
689 done();
691 return NS_OK;
693 NS_ENSURE_TRUE(mArmed, NS_ERROR_UNEXPECTED);
695 nsITest *test = (nsITest *) mTestTree.Peek();
696 NS_ENSURE_TRUE(test, NS_ERROR_UNEXPECTED);
698 nsCOMPtr<nsIWebProgressListener> listener(do_QueryInterface(test));
699 NS_ENSURE_TRUE(listener, NS_ERROR_UNEXPECTED);
701 listener->OnStateChange(aWebProgress, aRequest, aStateFlags, aStatus);
703 return NS_OK;
706 NS_IMETHODIMP
707 nsTestRunner::OnProgressChange(nsIWebProgress *aWebProgress,
708 nsIRequest *aRequest, PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress,
709 PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress)
711 return NS_ERROR_NOT_IMPLEMENTED;
714 NS_IMETHODIMP
715 nsTestRunner::OnLocationChange(nsIWebProgress *aWebProgress,
716 nsIRequest *aRequest, nsIURI *aLocation)
718 return NS_ERROR_NOT_IMPLEMENTED;
721 NS_IMETHODIMP
722 nsTestRunner::OnStatusChange(nsIWebProgress *aWebProgress,
723 nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage)
725 return NS_ERROR_NOT_IMPLEMENTED;
728 NS_IMETHODIMP
729 nsTestRunner::OnSecurityChange(nsIWebProgress *aWebProgress,
730 nsIRequest *aRequest, PRUint32 aState)
732 return NS_ERROR_NOT_IMPLEMENTED;
735 NS_IMETHODIMP
736 nsTestRunner::OnMismatch(const nsACString& aText, PRUint32 aLine)
738 nsresult rv = NS_OK;
739 nsCOMPtr<nsIURI> reference = mCompareURI;
741 mCompareURI = nsnull;
743 nsCAutoString spec;
744 rv = reference->GetSpec(spec);
745 NS_ENSURE_SUCCESS(rv, rv);
747 nsCAutoString message;
748 message.AssignLiteral("\"");
749 message.Append(aText);
750 message.AppendLiteral("\"");
751 rv = AddFailure(spec.get(), aLine, message.get());
752 NS_ENSURE_SUCCESS(rv, rv);
753 rv = AddFailure(mCompareFile, mCompareLine, "included from here");
754 NS_ENSURE_SUCCESS(rv, rv);
755 mCompareFile = nsnull;
756 mCompareLine = 0;
758 return NS_OK;
761 NS_IMETHODIMP
762 nsTestRunner::OnError(const nsACString& aText, PRUint32 aLine)
764 nsresult rv = NS_OK;
765 nsCOMPtr<nsIURI> reference = mCompareURI;
767 mCompareURI = nsnull;
769 nsCAutoString spec;
770 rv = reference->GetSpec(spec);
771 NS_ENSURE_SUCCESS(rv, rv);
773 nsCAutoString message;
774 message.Append(aText);
775 rv = AddFailure(spec.get(), aLine, message.get());
776 NS_ENSURE_SUCCESS(rv, rv);
777 rv = AddFailure(mCompareFile, mCompareLine, "included from here");
778 NS_ENSURE_SUCCESS(rv, rv);
779 mCompareFile = nsnull;
780 mCompareLine = 0;
782 return NS_OK;
785 NS_IMETHODIMP
786 nsTestRunner::OnSuccess()
788 mCompareURI = nsnull;
789 mCompareFile = nsnull;
790 mCompareLine = 0;
791 return NS_OK;
794 nsresult
795 nsTestRunner::registerXmlTests()
797 nsresult rv = NS_OK;
799 nsCOMPtr<nsIComponentRegistrar> compReg;
800 rv = NS_GetComponentRegistrar(getter_AddRefs(compReg));
801 NS_ENSURE_SUCCESS(rv, rv);
803 nsCOMPtr<nsIProperties> procDirProp(
804 do_CreateInstance("@mozilla.org/file/directory_service;1", &rv));
805 NS_ENSURE_SUCCESS(rv, rv);
807 nsCOMPtr<nsIFile> testDir;
808 rv = procDirProp->Get(NS_OS_CURRENT_PROCESS_DIR, NS_GET_IID(nsIFile),
809 getter_AddRefs(testDir));
810 NS_ENSURE_SUCCESS(rv, rv);
812 rv = testDir->Append(NS_LITERAL_STRING("tests"));
813 NS_ENSURE_SUCCESS(rv, rv);
815 PRBool dirExist = PR_FALSE;
816 rv = testDir->Exists(&dirExist);
817 NS_ENSURE_SUCCESS(rv, rv);
819 PRBool testIsDir = PR_FALSE;
820 rv = testDir->IsDirectory(&testIsDir);
821 NS_ENSURE_SUCCESS(rv, rv);
823 if (dirExist && testIsDir)
825 rv = testDir->Append(NS_LITERAL_STRING("xml"));
826 NS_ENSURE_SUCCESS(rv, rv);
828 rv = testDir->Exists(&dirExist);
829 NS_ENSURE_SUCCESS(rv, rv);
831 rv = testDir->IsDirectory(&testIsDir);
832 NS_ENSURE_SUCCESS(rv, rv);
834 if (dirExist && testIsDir)
836 nsCOMPtr<nsISimpleEnumerator> entries;
837 rv = testDir->GetDirectoryEntries(getter_AddRefs(entries));
838 NS_ENSURE_SUCCESS(rv, rv);
840 PRBool hasMore = PR_FALSE;
841 while (NS_SUCCEEDED(rv = entries->HasMoreElements(&hasMore)) && hasMore)
843 nsCOMPtr<nsISupports> item;
844 rv = entries->GetNext(getter_AddRefs(item));
845 NS_ENSURE_SUCCESS(rv, rv);
847 nsCOMPtr<nsILocalFile> file(do_QueryInterface(item, &rv));
848 NS_ENSURE_SUCCESS(rv, rv);
850 PRBool fileIsFile = PR_FALSE;
851 rv = file->IsFile(&fileIsFile);
852 NS_ENSURE_SUCCESS(rv, rv);
854 if (fileIsFile)
856 nsCAutoString leafName;
857 rv = file->GetNativeLeafName(leafName);
858 NS_ENSURE_SUCCESS(rv, rv);
860 nsCAutoString baseUri;
861 baseUri.AssignLiteral("resource:///tests/xml/");
862 baseUri.Append(leafName);
864 nsCOMPtr<nsIURI> uri;
865 rv = NS_NewURI(getter_AddRefs(uri), baseUri.get());
866 NS_ENSURE_SUCCESS(rv, rv);
868 nsCOMPtr<nsTestXmlFactory> xmlFactory =
869 do_CreateInstance(NS_TEST_XML_FACTORY_CONTRACT, &rv);
870 NS_ENSURE_SUCCESS(rv, rv);
871 NS_ENSURE_TRUE(!!(xmlFactory), NS_ERROR_OUT_OF_MEMORY);
873 rv = xmlFactory->RegisterSelf(uri, compReg);
874 NS_ENSURE_SUCCESS(rv, rv);
880 return NS_OK;
883 nsTestRunner*
884 nsTestRunner::GetTestRunner()
886 if ( nsTestRunner::gTestRunner == nsnull ) {
887 nsTestRunner::gTestRunner = new nsTestRunner;
890 if ( nsTestRunner::gTestRunner != nsnull ) {
891 NS_ADDREF( nsTestRunner::gTestRunner );
894 return nsTestRunner::gTestRunner;
897 /******************** nsFormatJSMessage ***********************************/
898 nsFormatJSMessage::nsFormatJSMessage(nsIConsoleMessage *aMessage)
900 if (NS_SUCCEEDED( parseScriptError( aMessage ) )) {
901 return;
903 nsAutoString wstr;
904 aMessage->GetMessageMoz(getter_Copies( wstr ));
905 mFile.Assign(nsnull,0);
906 mLine = nsITestRunner::errorNoError;
907 mText.Assign( NS_ConvertUTF16toUTF8(wstr));
910 nsFormatJSMessage::nsFormatJSMessage(const char *aFile)
912 mFile.Assign(aFile);
913 getSourceFile();
916 nsresult
917 nsFormatJSMessage::parseScriptError(nsIConsoleMessage *aMessage)
919 nsresult rv;
920 nsCOMPtr<nsIScriptError> error;
921 nsAutoString wstr;
923 error = do_QueryInterface( aMessage, &rv );
924 if (NS_FAILED(rv))
925 return rv;
927 rv = formatErrorMessage(error);
928 NS_ENSURE_SUCCESS(rv, rv);
930 if (NS_FAILED( getSourceFile() )) {
931 mFile.Assign(nsnull, 0);
932 mLine = nsITestRunner::errorJS;
935 return NS_OK;
938 nsresult
939 nsFormatJSMessage::formatErrorMessage(nsIScriptError *error)
941 nsresult rv;
942 nsAutoString wstr;
944 rv = error->GetErrorMessage( wstr );
945 NS_ENSURE_SUCCESS(rv, rv);
947 nsCAutoString text = NS_ConvertUTF16toUTF8( wstr );
949 rv = error->GetLineNumber( &mLine );
950 if (NS_SUCCEEDED( rv ))
951 rv = error->GetSourceName( wstr );
952 if (NS_SUCCEEDED( rv ))
953 mFile = NS_ConvertUTF16toUTF8(wstr);
955 if ( parseException(text) )
956 return NS_OK;
958 PRUint32 flags;
959 rv = error->GetFlags( &flags );
960 if (NS_FAILED( rv ))
961 flags = 0;
963 if ( flags & nsIScriptError::warningFlag ) {
964 mText.Assign("warning: ");
965 } else {
966 mText.Assign("error: ");
968 mText.Append( text );
969 return NS_OK;
972 PRBool
973 nsFormatJSMessage::parseException(const nsACString &aMessage)
975 const char *head, *pos, *res, *end;
976 nsresult rv;
978 head = aMessage.BeginReading();
979 pos = strstr(head, "[Exception... \"");
980 if (! pos)
981 return PR_FALSE;
983 mText.Assign("exception: ");
985 if (pos[15] == '\'') {
986 end = strchr(&pos[16], '\'');
987 if (end) {
988 mText.Append(&pos[15], end - pos - 14);
990 } else if ( (res = strstr(&pos[15], "nsresult: \"0x")) && strlen(res) > 23) {
991 end = strchr(&res[23], ')');
992 if (end) {
993 mText.Append(&res[23], end - res - 23);
995 } else {
996 mText.Append(&pos[15],strlen(pos) - 16);
999 if ( ! mFile.Length() ) {
1000 res = strstr(&pos[15],"location: \"JS frame :: ");
1001 if (!res || strlen(res) < 25)
1002 return PR_TRUE;
1003 end = strstr(&res[23], " :: ");
1004 if (! end)
1005 return PR_TRUE;
1006 mFile.Assign(Substring(&res[23], end - res - 23));
1007 res = strstr(&end[4], ":: line ");
1008 if (!res && strlen(res) < 10)
1009 return PR_TRUE;
1010 end = strchr(&res[8], '"');
1011 if (! end)
1012 return PR_TRUE;
1013 mLine = Substring(&res[8], end - res - 8).ToInteger(&rv);
1015 return PR_TRUE;
1018 nsresult
1019 nsFormatJSMessage::getSourceFile()
1021 if ( StringHead(mFile, 7).Equals(NS_LITERAL_CSTRING("file://")) ) {
1022 return parseLocalFile();
1023 } else if (! StringHead(mFile, 9).Equals(NS_LITERAL_CSTRING("chrome://")) ) {
1024 return NS_ERROR_FILE_UNRECOGNIZED_PATH;
1026 return parseChrome();
1029 nsresult
1030 nsFormatJSMessage::parseLocalFile()
1032 nsCAutoString leafName;
1033 const PRUnichar* resolved;
1035 leafName = "file://";
1036 leafName += strrchr(mFile.BeginReading(), '/');
1037 if (! mResolver) {
1038 mResolver = nsTestRunner::GetTestRunner();
1039 NS_ENSURE_TRUE( mResolver, NS_OK );
1041 mResolver->resolve( leafName, &resolved );
1042 if (! resolved )
1043 return NS_OK;
1044 if ( resolved[0] )
1045 mFile.Assign(NS_ConvertUTF16toUTF8( resolved ));
1047 return NS_OK;
1050 nsresult
1051 nsFormatJSMessage::parseChrome()
1053 nsCAutoString head;
1054 const char *tail, *ptr = 0;
1055 PRUint32 len;
1056 const PRUnichar* resolved;
1058 len = mFile.Length();
1059 tail = strrchr(mFile.BeginReading(), '/');
1060 head = StringHead(mFile, len - strlen(tail) );
1061 if (! mResolver) {
1062 mResolver = nsTestRunner::GetTestRunner();
1063 NS_ENSURE_TRUE( mResolver, NS_OK );
1065 mResolver->resolve( head, &resolved);
1066 while( ! resolved && (head.Length() > 9) ) {
1067 ptr = strrchr(head.BeginReading(), '/');
1068 tail -= strlen(ptr);
1069 head = StringHead(mFile, len - strlen(tail) );
1070 mResolver->resolve( head, &resolved);
1072 if (! resolved )
1073 return NS_OK;
1075 head = NS_ConvertUTF16toUTF8(resolved);
1076 head += tail;
1077 mFile.Assign( head );
1079 return NS_OK;