xpunit: simulate error message in CompareWithFile
[abstract.git] / xpunit / nsTestRunner.cpp
blobd6c6e4c30c777cbfd0004ca685c17df326849050
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 "nsIComponentManager.h"
27 #include "nsComponentManagerUtils.h"
28 #include "nsServiceManagerUtils.h"
29 #include "nsIPrefBranch.h"
30 #include "nsIWindowWatcher.h"
31 #include "nsIDOMWindow.h"
32 #include "nsIDOMWindowCollection.h"
33 #include "nsIInterfaceRequestorUtils.h"
34 #include "nsIWebProgress.h"
35 #include "nsIDOMDocument.h"
36 #include "nsIDOMDocumentView.h"
37 #include "nsIDOMElement.h"
38 #include "nsIDOMEventTarget.h"
39 #include "nsIDOMDocumentEvent.h"
40 #include "nsIDOMEvent.h"
41 #include "nsIDOMAbstractView.h"
43 /* Unfrozen interfaces */
44 #include "nsAutoPtr.h"
45 #include "nsICommandLine.h"
46 #include "nsIWebNavigation.h"
47 #include "nsIAppStartup.h"
48 #include "nsIConsoleService.h"
49 #include "nsIConsoleMessage.h"
50 #include "nsIScriptError.h"
51 #include "jspubtd.h"
52 #include "nsIJSContextStack.h"
53 #include "nsIRDFService.h"
54 #include "nsIRDFDataSource.h"
55 #include "nsIRDFResource.h"
56 #include "nsIDOMXULDocument.h"
57 #include "nsIDOMXULCommandDispatcher.h"
58 #include "nsIDOMXULCommandEvent.h"
59 #include "nsIStringEnumerator.h"
60 #include "nsIURI.h"
62 /* Project includes */
63 #include "nsITestRunner.h"
64 #include "nsITestResult.h"
65 #include "nsITest.h"
66 #include "nstestjs.h"
67 #include "nsTestRunner.h"
68 #include "nsTestFailure.h"
70 #include "nsTestUtils.h"
72 class nsFormatJSMessage: public nsTestFailure
74 public:
75 nsFormatJSMessage(nsIConsoleMessage *aMessage);
76 nsFormatJSMessage(const char *aFile);
77 ~nsFormatJSMessage() {;}
78 private:
79 nsresult parseScriptError(nsIConsoleMessage *aMessage);
80 nsresult formatErrorMessage(nsIScriptError *error);
81 PRBool parseException(const nsACString &aMessage);
82 nsresult getSourceFile();
83 nsresult parseLocalFile();
84 nsresult parseChrome();
86 nsRefPtr<nsTestRunner> mResolver;
90 /******************** nsTestRunner ***********************************/
91 nsTestRunner::nsTestRunner()
92 :mTestTree(nsnull), mArmed(PR_FALSE), mHasWindow(PR_FALSE)
96 nsTestRunner::~nsTestRunner()
100 nsTestRunner* nsTestRunner::gTestRunner = nsnull;
102 NS_IMPL_THREADSAFE_ISUPPORTS7(nsTestRunner,
103 nsITestRunner,
104 nsIConsoleListener,
105 nsIWebProgressListener,
106 nsISupportsWeakReference,
107 nsITimerCallback,
108 nsICommandLineHandler,
109 nsTestRunner)
111 NS_IMETHODIMP
112 nsTestRunner::MarkTestStart()
114 return mTestResult->MarkTestStart();
117 NS_IMETHODIMP
118 nsTestRunner::AddFailure(const char *aFile, PRUint32 aLine, const char *aText)
120 return mTestResult->AddFailure(aFile, aLine, aText, PR_FALSE);
123 NS_IMETHODIMP
124 nsTestRunner::AddJSFailure(const char *aText)
126 nsresult rv;
127 JSContext *cx = nsnull;
128 nsCAutoString file;
130 if ( ! mJSStack ) {
131 mJSStack = do_GetService("@mozilla.org/js/xpc/ContextStack;1");
132 NS_ENSURE_TRUE(mJSStack, NS_ERROR_FAILURE);
134 rv = mJSStack->Peek( &cx );
135 NS_ENSURE_TRUE(cx, NS_ERROR_FAILURE);
137 nsFormatJSMessage m(ns_test_js_caller_filename(cx));
139 return mTestResult->AddFailure(m.getFile(),
140 ns_test_js_caller_lineno(cx), aText, PR_FALSE);
143 NS_IMETHODIMP
144 nsTestRunner::AddError(PRUint32 aCode, const char *aComment)
146 return mTestResult->AddFailure(nsnull, aCode, aComment, PR_TRUE);
149 NS_IMETHODIMP
150 nsTestRunner::MarkTestEnd(nsITest *aTest)
152 if (aTest != (nsITest *) mTestTree.Peek())
153 return NS_ERROR_ILLEGAL_VALUE;
154 if (mArmed) {
155 mArmed = PR_FALSE;
156 mTimer->Cancel();
157 if(NS_FAILED(mTimer->InitWithCallback(this, 0, nsITimer::TYPE_ONE_SHOT)))
158 traverse();
160 return NS_OK;
163 NS_IMETHODIMP
164 nsTestRunner::GetHasWindow(PRBool *aHasWindow)
166 NS_ENSURE_ARG_POINTER(aHasWindow);
167 *aHasWindow = mHasWindow;
168 return NS_OK;
171 NS_IMETHODIMP
172 nsTestRunner::GetTestWindow(nsIDOMWindow* *aTestWindow)
174 NS_ENSURE_ARG_POINTER( aTestWindow );
175 if ( !mTestWindow ) {
176 *aTestWindow = nsnull;
177 return NS_ERROR_NOT_INITIALIZED;
179 *aTestWindow = mTestWindow;
180 NS_ADDREF( *aTestWindow );
182 return NS_OK;
185 NS_IMETHODIMP
186 nsTestRunner::GetWatchWindow(nsIDOMWindow* *aWatchWindow)
188 NS_ENSURE_ARG_POINTER( aWatchWindow );
189 if ( !mWatchWindow ) {
190 *aWatchWindow = nsnull;
191 return NS_ERROR_NOT_INITIALIZED;
193 *aWatchWindow = mWatchWindow;
194 NS_ADDREF( *aWatchWindow );
196 return NS_OK;
199 NS_IMETHODIMP
200 nsTestRunner::SetWatchWindow(nsIDOMWindow *aWatchWindow)
202 nsresult rv;
204 if (mWatchWindow == aWatchWindow)
206 if (mWatchWindow && !mHasWindow)
208 rv = ArmTimer(1000);
209 NS_ENSURE_SUCCESS(rv, rv);
211 return NS_OK;
214 if (mWatchWindow) {
215 nsCOMPtr<nsIWebNavigation> web(do_GetInterface(mWatchWindow, &rv ));
216 NS_ENSURE_SUCCESS(rv, rv);
218 nsCOMPtr<nsIWebProgress> webProgress(do_QueryInterface(web, &rv));
219 NS_ENSURE_SUCCESS(rv, rv);
221 rv = webProgress->RemoveProgressListener(this);
222 NS_ENSURE_SUCCESS(rv, rv);
224 mWatchWindow = nsnull;
227 if (aWatchWindow) {
228 nsCOMPtr<nsIWebNavigation> web(do_GetInterface(aWatchWindow, &rv ));
229 NS_ENSURE_SUCCESS(rv, rv);
231 nsCOMPtr<nsIWebProgress> webProgress(do_QueryInterface(web, &rv));
232 NS_ENSURE_SUCCESS(rv, rv);
234 rv = webProgress->AddProgressListener(this,
235 nsIWebProgress::NOTIFY_STATE_WINDOW);
236 NS_ENSURE_SUCCESS(rv, rv);
238 if (mHasWindow) {
239 rv = ArmTimer(1000);
240 NS_ENSURE_SUCCESS(rv, rv);
243 mWatchWindow = aWatchWindow;
245 return NS_OK;
248 NS_IMETHODIMP
249 nsTestRunner::ArmTimer(PRUint32 aDelay)
251 NS_ENSURE_TRUE(!mArmed, NS_ERROR_ALREADY_INITIALIZED);
253 nsresult rv;
254 rv = mTimer->InitWithCallback(this, aDelay << 1, nsITimer::TYPE_ONE_SHOT);
255 NS_ENSURE_SUCCESS(rv, rv);
257 mArmed = PR_TRUE;
258 return NS_OK;
261 nsresult
262 findElement(const nsAString& aCommand, nsIDOMWindow *wnd,
263 nsIDOMElement **element)
265 nsresult rv;
266 PRUint32 count, i;
267 nsCOMPtr<nsIDOMWindowCollection> list;
268 nsCOMPtr<nsIDOMWindow> next;
269 nsCOMPtr<nsIDOMDocument> doc;
271 while (wnd) {
272 rv = wnd->GetDocument(getter_AddRefs(doc));
273 NS_ENSURE_SUCCESS(rv, rv);
275 rv = doc->GetElementById(aCommand, element);
276 NS_ENSURE_SUCCESS(rv, rv);
277 if (*element)
278 return NS_OK;
280 rv = wnd->GetFrames(getter_AddRefs(list));
281 NS_ENSURE_SUCCESS(rv, rv);
283 rv = list->GetLength(&count);
284 NS_ENSURE_SUCCESS(rv, rv);
286 for (i = 0; i < count; i++) {
287 rv = list->Item(i, getter_AddRefs(next));
288 NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_STATE(next);
290 rv = findElement(aCommand, next, element);
291 NS_ENSURE_SUCCESS(rv, rv);
292 if (*element)
293 return NS_OK;
296 return NS_ERROR_ILLEGAL_VALUE;
300 NS_IMETHODIMP
301 nsTestRunner::DoCommand(const nsAString& aCommand)
303 nsresult rv;
304 nsCOMPtr<nsIDOMElement> element;
306 rv = findElement(aCommand, mTestWindow, getter_AddRefs(element));
307 NS_ENSURE_SUCCESS(rv, rv);
309 PRBool isDisabled;
310 rv = element->HasAttribute(NS_LITERAL_STRING("disabled"), &isDisabled);
311 NS_ENSURE_SUCCESS(rv, rv);
312 if ( isDisabled )
313 return NS_ERROR_NOT_AVAILABLE;
315 nsCOMPtr<nsIDOMEventTarget> evtTgt(do_QueryInterface(element, &rv));
316 NS_ENSURE_SUCCESS(rv, rv);
318 nsCOMPtr<nsIDOMDocument> doc;
319 rv = element->GetOwnerDocument(getter_AddRefs(doc));
320 NS_ENSURE_SUCCESS(rv, rv);
322 nsCOMPtr<nsIDOMDocumentEvent> docEvent(do_QueryInterface(doc, &rv));
323 NS_ENSURE_SUCCESS(rv, rv);
325 nsCOMPtr<nsIDOMEvent> evt;
326 rv = docEvent->CreateEvent(NS_LITERAL_STRING("XULCommandEvent"),
327 getter_AddRefs(evt));
328 NS_ENSURE_SUCCESS(rv, rv);
330 nsCOMPtr<nsIDOMXULCommandEvent> cmdEvt(do_QueryInterface(evt, &rv));
331 NS_ENSURE_SUCCESS(rv, rv);
333 nsCOMPtr<nsIDOMDocumentView> docView(do_QueryInterface(doc, &rv));
334 NS_ENSURE_SUCCESS(rv, rv);
335 nsCOMPtr<nsIDOMAbstractView> view;
336 rv = docView->GetDefaultView(getter_AddRefs(view));
337 NS_ENSURE_SUCCESS(rv, rv);
339 rv = cmdEvt->InitCommandEvent(NS_LITERAL_STRING("command"), PR_TRUE, PR_TRUE,
340 view, 0, 0, 0, 0, 0, nsnull);
341 NS_ENSURE_SUCCESS(rv, rv);
343 PRBool isDefault;
344 rv = evtTgt->DispatchEvent( evt, &isDefault );
345 NS_ENSURE_SUCCESS(rv, rv);
347 return NS_OK;
350 NS_IMETHODIMP
351 nsTestRunner::CompareWithFile(nsIChannel *dataChannel,
352 nsIURI *reference)
354 nsresult rv = NS_OK;
355 NS_TEST_BEGIN(this);
356 nsCAutoString spec;
357 rv = reference->GetSpec(spec);
358 NS_ENSURE_SUCCESS(rv, rv);
360 this->AddFailure(spec.get(), 2, "\"3\"");
361 return NS_OK;
364 NS_IMETHODIMP
365 nsTestRunner::Observe(nsIConsoleMessage *aMessage)
367 NS_ENSURE_TRUE(mTestResult, NS_ERROR_UNEXPECTED);
369 nsFormatJSMessage m(aMessage);
370 mTestResult->AddFailure(m.getFile(), m.getLine(), m.getText(), PR_TRUE);
371 return NS_OK;
374 nsresult
375 nsTestRunner::openMainWindow()
377 nsresult rv;
378 nsCOMPtr<nsIConsoleService> jsConsole;
379 nsCOMPtr<nsIPrefBranch> pref;
380 nsCAutoString chromeURI;
381 nsCOMPtr<nsIWindowWatcher> ww;
382 nsCOMPtr<nsIDOMWindow> wnd;
384 pref = do_GetService("@mozilla.org/preferences-service;1", &rv);
385 NS_ENSURE_SUCCESS(rv, rv);
386 rv = pref->GetCharPref("toolkit.defaultChromeURI",getter_Copies(chromeURI));
387 NS_ENSURE_SUCCESS(rv, rv);
388 ww = do_GetService("@mozilla.org/embedcomp/window-watcher;1", &rv);
389 NS_ENSURE_SUCCESS(rv, rv);
390 rv = ww->OpenWindow(0, chromeURI.get(), "_blank", "chrome,dialog=no,all",
391 0, getter_AddRefs(wnd) );
392 NS_ENSURE_SUCCESS(rv, rv);
394 rv = SetWatchWindow(wnd);
395 NS_ENSURE_SUCCESS(rv, rv);
397 mTestWindow = wnd;
398 jsConsole = do_GetService("@mozilla.org/consoleservice;1", &rv);
399 NS_ENSURE_TRUE(jsConsole, NS_OK);
400 jsConsole->RegisterListener( this );
402 return NS_OK;
405 nsresult
406 nsTestRunner::init()
408 nsresult rv;
409 nsCOMPtr<nsIPrefBranch> pref;
411 pref = do_GetService("@mozilla.org/preferences-service;1", &rv);
412 NS_ENSURE_SUCCESS(rv, rv);
413 (void) pref->GetCharPref("xpunit.firstTest",getter_Copies(mTestID));
414 if (!mTestID.get() || !mTestID.get()[0]) {
415 printf_stderr("Please provide first test contractID in any pref file:\n");
416 printf_stderr("pref(\"xpunit.firstTest\",\"@test.org/contract/id\");\n");
417 return NS_ERROR_NOT_AVAILABLE;
420 mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
421 NS_ENSURE_SUCCESS(rv, rv);
423 mTestResult = do_CreateInstance("@aasii.org/cxxunit/testresult", &rv);
424 NS_ENSURE_SUCCESS(rv, rv);
426 rv = openMainWindow();
427 NS_ENSURE_SUCCESS(rv, rv);
429 rv = pushTest(mTestID.get());
430 NS_ENSURE_SUCCESS(rv, rv);
432 return NS_OK;
435 nsresult
436 nsTestRunner::pushTest(const char * aContractID)
438 nsresult rv;
439 nsCOMPtr<nsITest> test = do_CreateInstance(aContractID, &rv);
441 if (NS_FAILED(rv)) {
442 AddError(nsITestRunner::errorLoad, aContractID);
443 return rv;
446 mTestTree.Push( (void *) test.get() );
448 rv = test->Test(this);
449 if (NS_FAILED(rv)) return rv;
451 test.get()->AddRef();
452 return NS_OK;
455 nsresult
456 nsTestRunner::getNextTest(nsACString &aContractID)
458 nsresult rv;
459 PRBool hasMore;
461 nsITest *test = (nsITest *) mTestTree.Peek();
462 NS_ENSURE_TRUE(test, NS_ERROR_UNEXPECTED);
464 nsCOMPtr<nsIUTF8StringEnumerator> testNode(do_QueryInterface(test, &rv));
465 if (rv == NS_NOINTERFACE)
466 return NS_ERROR_NOT_AVAILABLE;
467 NS_ENSURE_SUCCESS(rv, rv);
469 rv = testNode->HasMore( &hasMore );
470 NS_ENSURE_SUCCESS(rv, rv);
471 if (! hasMore)
472 return NS_ERROR_NOT_AVAILABLE;
474 rv = testNode->GetNext( aContractID );
475 NS_ENSURE_SUCCESS(rv, rv);
477 return NS_OK;
480 void
481 nsTestRunner::traverse()
483 nsresult rv;
484 nsITest *test;
486 while (mTestTree.GetSize()) {
488 rv = getNextTest( mTestID );
490 if (NS_FAILED(rv)) {
491 test = (nsITest *) mTestTree.Pop();
492 NS_RELEASE(test);
493 } else {
494 rv = pushTest(mTestID.get());
495 if (NS_FAILED(rv))
496 mTestTree.Empty();
497 if (mArmed)
498 return;
502 if (mTestWindow) {
503 mTestWindow = nsnull;
504 rv = mTimer->InitWithCallback(this, 0, nsITimer::TYPE_ONE_SHOT);
505 if (NS_SUCCEEDED(rv))
506 return;
509 done();
512 nsresult
513 nsTestRunner::closeMainWindow()
515 nsresult rv;
517 nsCOMPtr<nsIAppStartup> app;
518 app = do_GetService("@mozilla.org/toolkit/app-startup;1", &rv);
519 NS_ENSURE_SUCCESS(rv, rv);
520 rv = app->Quit(app->eForceQuit);
521 NS_ENSURE_SUCCESS(rv, rv);
523 return NS_OK;
526 void
527 nsTestRunner::done()
529 nsCOMPtr<nsIConsoleService> jsConsole;
531 if (!mHasWindow)
533 mTestWindow = nsnull;
534 return;
536 jsConsole = do_GetService("@mozilla.org/consoleservice;1");
537 if (jsConsole )
538 (void) jsConsole->UnregisterListener(this);
540 (void) closeMainWindow();
541 (void) mTestResult->Done();
542 mTestResult = nsnull;
543 mTimer = nsnull;
546 NS_IMETHODIMP
547 nsTestRunner::Handle(nsICommandLine *aCommandLine)
549 nsresult rv;
550 PRBool isTest;
552 rv = aCommandLine->HandleFlag(NS_LITERAL_STRING("test"), PR_TRUE, &isTest);
553 NS_ENSURE_SUCCESS(rv,rv);
554 if (!isTest)
555 return NS_OK;
557 aCommandLine->SetPreventDefault(PR_TRUE);
559 rv = init();
560 if (NS_FAILED(rv)) {
561 printf_stderr("Failed to initialize test framework\n");
562 return NS_ERROR_ABORT;
565 traverse();
566 return NS_OK;
569 NS_IMETHODIMP
570 nsTestRunner::GetHelpInfo(nsACString & aHelpInfo)
572 aHelpInfo.Assign(" --test Run unit test collection\n");
573 return NS_OK;
576 nsresult
577 nsTestRunner::resolve(nsACString &aURL, const PRUnichar* *result)
579 nsresult rv;
580 nsCOMPtr<nsIRDFService> rdfSrv;
581 nsCOMPtr<nsIRDFResource> src, prop;
582 nsCOMPtr<nsIRDFNode> target;
583 nsCOMPtr<nsIRDFLiteral> targetLiteral;
585 NS_ENSURE_ARG_POINTER(result);
586 *result = nsnull;
587 rdfSrv = do_GetService("@mozilla.org/rdf/rdf-service;1", &rv);
588 NS_ENSURE_SUCCESS( rv, rv );
590 if ( ! mFileMap ) {
591 nsCOMPtr<nsIPrefBranch> pref;
592 nsCAutoString url;
594 pref = do_GetService("@mozilla.org/preferences-service;1", &rv);
595 NS_ENSURE_SUCCESS(rv, rv );
596 rv = pref->GetCharPref("xpunit.fileMap",getter_Copies(url));
597 NS_ENSURE_SUCCESS(rv, rv );
599 rv = rdfSrv->GetDataSourceBlocking(url.get(),
600 getter_AddRefs( mFileMap ));
601 NS_ENSURE_TRUE( mFileMap, rv );
604 rv = rdfSrv->GetResource( aURL, getter_AddRefs( src ));
605 NS_ENSURE_SUCCESS(rv, rv );
606 rv = rdfSrv->GetResource(
607 NS_LITERAL_CSTRING("http://www.aasii.org/AA-rdf#File"),
608 getter_AddRefs( prop ));
609 NS_ENSURE_SUCCESS(rv, rv );
611 rv = mFileMap->GetTarget(src, prop, PR_TRUE, getter_AddRefs( target ));
612 if (! target)
613 return rv;
614 targetLiteral = do_QueryInterface( target, &rv );
615 NS_ENSURE_TRUE( target, rv );
616 targetLiteral->GetValueConst( result );
617 NS_ENSURE_TRUE( target, rv );
619 return NS_OK;
622 NS_IMETHODIMP
623 nsTestRunner::Notify(nsITimer *timer)
625 if (mArmed) {
626 mArmed = PR_FALSE;
627 AddError(nsITestRunner::errorTimeout, mTestID.get());
629 traverse();
630 return NS_OK;
633 NS_IMETHODIMP
634 nsTestRunner::OnStateChange(nsIWebProgress *aWebProgress,
635 nsIRequest *aRequest, PRUint32 aStateFlags, nsresult aStatus)
637 if (! (aStateFlags & nsIWebProgressListener::STATE_STOP) )
638 return NS_OK;
640 nsCOMPtr<nsIDOMWindow> wnd;
641 aWebProgress->GetDOMWindow(getter_AddRefs( wnd ));
642 if ( wnd != mWatchWindow ) {
643 return NS_OK;
646 mWatchWindow = nsnull;
647 aWebProgress->RemoveProgressListener( this );
649 if (!mHasWindow)
651 mHasWindow = PR_TRUE;
652 if (!mTestWindow)
653 done();
655 return NS_OK;
657 NS_ENSURE_TRUE(mArmed, NS_ERROR_UNEXPECTED);
659 nsITest *test = (nsITest *) mTestTree.Peek();
660 NS_ENSURE_TRUE(test, NS_ERROR_UNEXPECTED);
662 nsCOMPtr<nsIWebProgressListener> listener(do_QueryInterface(test));
663 NS_ENSURE_TRUE(listener, NS_ERROR_UNEXPECTED);
665 listener->OnStateChange(aWebProgress, aRequest, aStateFlags, aStatus);
667 return NS_OK;
670 NS_IMETHODIMP
671 nsTestRunner::OnProgressChange(nsIWebProgress *aWebProgress,
672 nsIRequest *aRequest, PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress,
673 PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress)
675 return NS_ERROR_NOT_IMPLEMENTED;
678 NS_IMETHODIMP
679 nsTestRunner::OnLocationChange(nsIWebProgress *aWebProgress,
680 nsIRequest *aRequest, nsIURI *aLocation)
682 return NS_ERROR_NOT_IMPLEMENTED;
685 NS_IMETHODIMP
686 nsTestRunner::OnStatusChange(nsIWebProgress *aWebProgress,
687 nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage)
689 return NS_ERROR_NOT_IMPLEMENTED;
692 NS_IMETHODIMP
693 nsTestRunner::OnSecurityChange(nsIWebProgress *aWebProgress,
694 nsIRequest *aRequest, PRUint32 aState)
696 return NS_ERROR_NOT_IMPLEMENTED;
699 nsTestRunner*
700 nsTestRunner::GetTestRunner()
702 if ( nsTestRunner::gTestRunner == nsnull ) {
703 nsTestRunner::gTestRunner = new nsTestRunner;
706 if ( nsTestRunner::gTestRunner != nsnull ) {
707 NS_ADDREF( nsTestRunner::gTestRunner );
710 return nsTestRunner::gTestRunner;
713 /******************** nsFormatJSMessage ***********************************/
714 nsFormatJSMessage::nsFormatJSMessage(nsIConsoleMessage *aMessage)
716 if (NS_SUCCEEDED( parseScriptError( aMessage ) )) {
717 return;
719 nsAutoString wstr;
720 aMessage->GetMessageMoz(getter_Copies( wstr ));
721 mFile.Assign(nsnull,0);
722 mLine = nsITestRunner::errorNoError;
723 mText.Assign( NS_ConvertUTF16toUTF8(wstr));
726 nsFormatJSMessage::nsFormatJSMessage(const char *aFile)
728 mFile.Assign(aFile);
729 getSourceFile();
732 nsresult
733 nsFormatJSMessage::parseScriptError(nsIConsoleMessage *aMessage)
735 nsresult rv;
736 nsCOMPtr<nsIScriptError> error;
737 nsAutoString wstr;
739 error = do_QueryInterface( aMessage, &rv );
740 if (NS_FAILED(rv))
741 return rv;
743 rv = formatErrorMessage(error);
744 NS_ENSURE_SUCCESS(rv, rv);
746 if (NS_FAILED( getSourceFile() )) {
747 mFile.Assign(nsnull, 0);
748 mLine = nsITestRunner::errorJS;
751 return NS_OK;
754 nsresult
755 nsFormatJSMessage::formatErrorMessage(nsIScriptError *error)
757 nsresult rv;
758 nsAutoString wstr;
760 rv = error->GetErrorMessage( wstr );
761 NS_ENSURE_SUCCESS(rv, rv);
763 nsCAutoString text = NS_ConvertUTF16toUTF8( wstr );
765 rv = error->GetLineNumber( &mLine );
766 if (NS_SUCCEEDED( rv ))
767 rv = error->GetSourceName( wstr );
768 if (NS_SUCCEEDED( rv ))
769 mFile = NS_ConvertUTF16toUTF8(wstr);
771 if ( parseException(text) )
772 return NS_OK;
774 PRUint32 flags;
775 rv = error->GetFlags( &flags );
776 if (NS_FAILED( rv ))
777 flags = 0;
779 if ( flags & nsIScriptError::warningFlag ) {
780 mText.Assign("warning: ");
781 } else {
782 mText.Assign("error: ");
784 mText.Append( text );
785 return NS_OK;
788 PRBool
789 nsFormatJSMessage::parseException(const nsACString &aMessage)
791 const char *head, *pos, *res, *end;
792 nsresult rv;
794 head = aMessage.BeginReading();
795 pos = strstr(head, "[Exception... \"");
796 if (! pos)
797 return PR_FALSE;
799 mText.Assign("exception: ");
801 if (pos[15] == '\'') {
802 end = strchr(&pos[16], '\'');
803 if (end) {
804 mText.Append(&pos[15], end - pos - 14);
806 } else if ( (res = strstr(&pos[15], "nsresult: \"0x")) && strlen(res) > 23) {
807 end = strchr(&res[23], ')');
808 if (end) {
809 mText.Append(&res[23], end - res - 23);
811 } else {
812 mText.Append(&pos[15],strlen(pos) - 16);
815 if ( ! mFile.Length() ) {
816 res = strstr(&pos[15],"location: \"JS frame :: ");
817 if (!res || strlen(res) < 25)
818 return PR_TRUE;
819 end = strstr(&res[23], " :: ");
820 if (! end)
821 return PR_TRUE;
822 mFile.Assign(Substring(&res[23], end - res - 23));
823 res = strstr(&end[4], ":: line ");
824 if (!res && strlen(res) < 10)
825 return PR_TRUE;
826 end = strchr(&res[8], '"');
827 if (! end)
828 return PR_TRUE;
829 mLine = Substring(&res[8], end - res - 8).ToInteger(&rv);
831 return PR_TRUE;
834 nsresult
835 nsFormatJSMessage::getSourceFile()
837 if ( StringHead(mFile, 7).Equals(NS_LITERAL_CSTRING("file://")) ) {
838 return parseLocalFile();
839 } else if (! StringHead(mFile, 9).Equals(NS_LITERAL_CSTRING("chrome://")) ) {
840 return NS_ERROR_FILE_UNRECOGNIZED_PATH;
842 return parseChrome();
845 nsresult
846 nsFormatJSMessage::parseLocalFile()
848 nsCAutoString leafName;
849 const PRUnichar* resolved;
851 leafName = "file://";
852 leafName += strrchr(mFile.BeginReading(), '/');
853 if (! mResolver) {
854 mResolver = nsTestRunner::GetTestRunner();
855 NS_ENSURE_TRUE( mResolver, NS_OK );
857 mResolver->resolve( leafName, &resolved );
858 if (! resolved )
859 return NS_OK;
860 if ( resolved[0] )
861 mFile.Assign(NS_ConvertUTF16toUTF8( resolved ));
863 return NS_OK;
866 nsresult
867 nsFormatJSMessage::parseChrome()
869 nsCAutoString head;
870 const char *tail, *ptr = 0;
871 PRUint32 len;
872 const PRUnichar* resolved;
874 len = mFile.Length();
875 tail = strrchr(mFile.BeginReading(), '/');
876 head = StringHead(mFile, len - strlen(tail) );
877 if (! mResolver) {
878 mResolver = nsTestRunner::GetTestRunner();
879 NS_ENSURE_TRUE( mResolver, NS_OK );
881 mResolver->resolve( head, &resolved);
882 while( ! resolved && (head.Length() > 9) ) {
883 ptr = strrchr(head.BeginReading(), '/');
884 tail -= strlen(ptr);
885 head = StringHead(mFile, len - strlen(tail) );
886 mResolver->resolve( head, &resolved);
888 if (! resolved )
889 return NS_OK;
891 head = NS_ConvertUTF16toUTF8(resolved);
892 head += tail;
893 mFile.Assign( head );
895 return NS_OK;