Release v0.0.2
[abstract.git] / xpunit / nsTestRunner.cpp
blob6f5df83835c24bada12210c22c2a262dccd48764
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 "nsEmbedString.h"
27 #include "nsWeakReference.h"
28 #include "nsIWebProgressListener.h"
29 #include "nsIComponentManager.h"
30 #include "nsComponentManagerUtils.h"
31 #include "nsServiceManagerUtils.h"
32 #include "nsIPrefBranch.h"
33 #include "nsIWindowWatcher.h"
34 #include "nsIDOMWindow.h"
35 #include "nsIInterfaceRequestorUtils.h"
36 #include "nsIWebProgress.h"
37 #include "nsIDOMDocument.h"
38 #include "nsIDOMElement.h"
39 #include "nsIDOMEventTarget.h"
40 #include "nsIDOMDocumentEvent.h"
41 #include "nsIDOMEvent.h"
42 #include "nsIDOMAbstractView.h"
44 /* Unfrozen interfaces */
45 #include "nsITimer.h"
46 #include "nsICommandLineHandler.h"
47 #include "nsDeque.h"
48 #include "nsAutoPtr.h"
49 #include "nsICommandLine.h"
50 #include "nsIWebNavigation.h"
51 #include "nsIAppStartup.h"
52 #include "nsIConsoleListener.h"
53 #include "nsIConsoleService.h"
54 #include "nsIConsoleMessage.h"
55 #include "nsIScriptError.h"
56 #include "jspubtd.h"
57 #include "nsIJSContextStack.h"
58 #include "nsIRDFService.h"
59 #include "nsIRDFDataSource.h"
60 #include "nsIRDFResource.h"
61 #include "nsIDOMXULDocument.h"
62 #include "nsIDOMXULCommandDispatcher.h"
63 #include "nsIDOMXULCommandEvent.h"
64 #include "nsIStringEnumerator.h"
66 /* Project includes */
67 #include "nsITestRunner.h"
68 #include "nsITestResult.h"
69 #include "nsITest.h"
70 #include "nstestjs.h"
71 #include "nsTestRunner.h"
72 #include "nsTestFailure.h"
74 #include "nsTestUtils.h"
76 class nsFormatJSMessage: public nsTestFailure
78 public:
79 nsFormatJSMessage(nsIConsoleMessage *aMessage);
80 nsFormatJSMessage(const char *aFile);
81 ~nsFormatJSMessage() {;}
82 private:
83 nsresult parseScriptError(nsIConsoleMessage *aMessage);
84 nsresult formatErrorMessage(nsIScriptError *error);
85 PRBool parseException(const nsACString &aMessage);
86 nsresult getSourceFile();
87 nsresult parseLocalFile();
88 nsresult parseChrome();
90 nsRefPtr<nsTestRunner> mResolver;
94 /******************** nsTestRunner ***********************************/
95 nsTestRunner::nsTestRunner() : mTestTree(nsnull)
97 mArmed = PR_FALSE;
98 mRunning = PR_FALSE;
101 nsTestRunner::~nsTestRunner()
105 nsTestRunner* nsTestRunner::gTestRunner = nsnull;
107 NS_IMPL_THREADSAFE_ISUPPORTS6(nsTestRunner,
108 nsITestRunner,
109 nsIConsoleListener,
110 nsIWebProgressListener,
111 nsISupportsWeakReference,
112 nsITimerCallback,
113 nsICommandLineHandler)
115 NS_IMETHODIMP
116 nsTestRunner::MarkTestStart()
118 return mTestResult->MarkTestStart();
121 NS_IMETHODIMP
122 nsTestRunner::AddFailure(const char *aFile, PRUint32 aLine, const char *aText)
124 return mTestResult->AddFailure(aFile, aLine, aText, PR_FALSE);
127 NS_IMETHODIMP
128 nsTestRunner::AddJSFailure(const char *aText)
130 nsresult rv;
131 JSContext *cx = nsnull;
132 nsEmbedCString file;
134 if ( ! mJSStack ) {
135 mJSStack = do_GetService("@mozilla.org/js/xpc/ContextStack;1");
136 NS_ENSURE_TRUE(mJSStack, NS_ERROR_FAILURE);
138 rv = mJSStack->Peek( &cx );
139 NS_ENSURE_TRUE(cx, NS_ERROR_FAILURE);
141 nsFormatJSMessage m(ns_test_js_caller_filename(cx));
143 return mTestResult->AddFailure(m.getFile(),
144 ns_test_js_caller_lineno(cx), aText, PR_FALSE);
147 NS_IMETHODIMP
148 nsTestRunner::AddError(PRUint32 aCode, const char *aComment)
150 return mTestResult->AddFailure(nsnull, aCode, aComment, PR_TRUE);
153 NS_IMETHODIMP
154 nsTestRunner::MarkTestEnd(nsITest *aTest)
156 if (aTest != (nsITest *) mTestTree.Peek())
157 return NS_ERROR_ILLEGAL_VALUE;
158 if (mArmed) {
159 mArmed = PR_FALSE;
160 mTimerStop->Cancel();
161 if(NS_FAILED(mTimer->InitWithCallback(this, 0, nsITimer::TYPE_ONE_SHOT)))
162 traverse();
164 return NS_OK;
167 NS_IMETHODIMP
168 nsTestRunner::GetTestWindow(nsIDOMWindow* *aTestWindow)
170 NS_ENSURE_ARG_POINTER( aTestWindow );
171 if ( !mTestWindow ) {
172 *aTestWindow = nsnull;
173 return NS_ERROR_NOT_INITIALIZED;
175 *aTestWindow = mTestWindow;
176 NS_ADDREF( *aTestWindow );
178 return NS_OK;
181 NS_IMETHODIMP
182 nsTestRunner::GetWatchWindow(nsIDOMWindow* *aWatchWindow)
184 NS_ENSURE_ARG_POINTER( aWatchWindow );
185 if ( !mWatchWindow ) {
186 *aWatchWindow = nsnull;
187 return NS_ERROR_NOT_INITIALIZED;
189 *aWatchWindow = mWatchWindow;
190 NS_ADDREF( *aWatchWindow );
192 return NS_OK;
195 NS_IMETHODIMP
196 nsTestRunner::SetWatchWindow(nsIDOMWindow *aWatchWindow)
198 nsresult rv;
200 if (mWatchWindow) {
201 nsCOMPtr<nsIWebNavigation> web(do_GetInterface(mWatchWindow, &rv ));
202 NS_ENSURE_SUCCESS(rv, rv);
204 nsCOMPtr<nsIWebProgress> webProgress(do_QueryInterface(web, &rv));
205 NS_ENSURE_SUCCESS(rv, rv);
207 rv = webProgress->RemoveProgressListener(this);
208 NS_ENSURE_SUCCESS(rv, rv);
211 if (aWatchWindow) {
212 nsCOMPtr<nsIWebNavigation> web(do_GetInterface(aWatchWindow, &rv ));
213 NS_ENSURE_SUCCESS(rv, rv);
215 nsCOMPtr<nsIWebProgress> webProgress(do_QueryInterface(web, &rv));
216 NS_ENSURE_SUCCESS(rv, rv);
218 rv = webProgress->AddProgressListener(this,
219 nsIWebProgress::NOTIFY_STATE_WINDOW);
220 NS_ENSURE_SUCCESS(rv, rv);
222 mWatchWindow = aWatchWindow;
224 return NS_OK;
227 NS_IMETHODIMP
228 nsTestRunner::ArmTimer()
230 nsresult rv;
231 nsITest *test = (nsITest *) mTestTree.Peek();
233 nsCOMPtr<nsITimerCallback> callback(do_QueryInterface(test, &rv));
234 NS_ENSURE_SUCCESS(rv, rv);
235 rv = mTimer->InitWithCallback(callback, 0, nsITimer::TYPE_ONE_SHOT);
236 NS_ENSURE_SUCCESS(rv, rv);
237 if (! mArmed )
238 mRunning = PR_TRUE;
239 return NS_OK;
242 NS_IMETHODIMP
243 nsTestRunner::DoCommand(const nsAString& aCommand)
245 nsresult rv;
246 nsCOMPtr<nsIDOMWindow> wnd(mTestWindow);
247 nsIDOMWindow *next;
248 nsCOMPtr<nsIDOMDocument> doc;
249 nsCOMPtr<nsIDOMXULDocument> xulDoc;
250 nsCOMPtr<nsIDOMXULCommandDispatcher> dispatcher;
251 nsCOMPtr<nsIDOMElement> element;
253 while ( wnd ) {
254 rv = wnd->GetDocument(getter_AddRefs( doc ));
255 NS_ENSURE_SUCCESS(rv, rv);
257 rv = doc->GetElementById(aCommand, getter_AddRefs( element ));
258 if ( element )
259 break;
261 xulDoc = do_QueryInterface(doc, &rv);
262 NS_ENSURE_SUCCESS(rv, NS_ERROR_ILLEGAL_VALUE);
264 rv = xulDoc->GetCommandDispatcher(getter_AddRefs( dispatcher ));
265 NS_ENSURE_SUCCESS(rv, rv);
267 rv = dispatcher->GetFocusedWindow( &next );
268 NS_ENSURE_SUCCESS(rv, rv);
270 if ( wnd == next ) {
271 wnd = nsnull;
272 } else {
273 wnd = getter_AddRefs( next );
277 NS_ENSURE_TRUE(element, NS_ERROR_ILLEGAL_VALUE);
279 PRBool isDisabled;
280 rv = element->HasAttribute(NS_LITERAL_STRING("disabled"), &isDisabled);
281 NS_ENSURE_SUCCESS(rv, rv);
282 if ( isDisabled )
283 return NS_ERROR_NOT_AVAILABLE;
285 nsCOMPtr<nsIDOMEventTarget> evtTgt(do_QueryInterface(element, &rv));
286 NS_ENSURE_SUCCESS(rv, rv);
288 nsCOMPtr<nsIDOMDocumentEvent> docEvent(do_QueryInterface(doc, &rv));
289 NS_ENSURE_SUCCESS(rv, rv);
291 nsCOMPtr<nsIDOMEvent> evt;
292 rv = docEvent->CreateEvent(NS_LITERAL_STRING("XULCommandEvent"),
293 getter_AddRefs(evt));
294 NS_ENSURE_SUCCESS(rv, rv);
296 nsCOMPtr<nsIDOMXULCommandEvent> cmdEvt(do_QueryInterface(evt, &rv));
297 NS_ENSURE_SUCCESS(rv, rv);
299 nsCOMPtr<nsIDOMAbstractView> view(do_QueryInterface(wnd, &rv));
300 NS_ENSURE_SUCCESS(rv, rv);
302 rv = cmdEvt->InitCommandEvent(NS_LITERAL_STRING("command"), PR_TRUE, PR_TRUE,
303 view, 0, 0, 0, 0, 0, nsnull);
304 NS_ENSURE_SUCCESS(rv, rv);
306 PRBool isDefault;
307 rv = evtTgt->DispatchEvent( evt, &isDefault );
308 NS_ENSURE_SUCCESS(rv, rv);
310 return NS_OK;
313 NS_IMETHODIMP
314 nsTestRunner::Observe(nsIConsoleMessage *aMessage)
316 NS_ENSURE_TRUE(mTestResult, NS_ERROR_UNEXPECTED);
318 nsFormatJSMessage m(aMessage);
319 mTestResult->AddFailure(m.getFile(), m.getLine(), m.getText(), PR_TRUE);
320 return NS_OK;
323 nsresult
324 nsTestRunner::openMainWindow()
326 nsresult rv;
327 nsCOMPtr<nsIConsoleService> jsConsole;
328 nsCOMPtr<nsIPrefBranch> pref;
329 nsEmbedCString chromeURI;
330 nsCOMPtr<nsIWindowWatcher> ww;
331 nsCOMPtr<nsIDOMWindow> wnd;
333 pref = do_GetService("@mozilla.org/preferences-service;1", &rv);
334 NS_ENSURE_SUCCESS(rv, rv);
335 rv = pref->GetCharPref("toolkit.defaultChromeURI",getter_Copies(chromeURI));
336 NS_ENSURE_SUCCESS(rv, rv);
337 ww = do_GetService("@mozilla.org/embedcomp/window-watcher;1", &rv);
338 NS_ENSURE_SUCCESS(rv, rv);
339 rv = ww->OpenWindow(0, chromeURI.get(), "_blank", "chrome,dialog=no,all",
340 0, getter_AddRefs(wnd) );
341 NS_ENSURE_SUCCESS(rv, rv);
343 mTestWindow = wnd;
344 jsConsole = do_GetService("@mozilla.org/consoleservice;1", &rv);
345 NS_ENSURE_TRUE(jsConsole, NS_OK);
346 jsConsole->RegisterListener( this );
348 return NS_OK;
351 void
352 nsTestRunner::run()
354 if ( init() != NS_ERROR_ABORT)
355 traverse();
358 nsresult
359 nsTestRunner::init()
361 nsresult rv;
362 nsCOMPtr<nsIPrefBranch> pref;
364 pref = do_GetService("@mozilla.org/preferences-service;1", &rv);
365 NS_ENSURE_SUCCESS(rv, rv);
366 rv = pref->GetCharPref("cxxunit.firstTest",getter_Copies(mTestID));
367 NS_ENSURE_SUCCESS(rv, rv);
369 rv = pushTest( mTestID.get() );
370 NS_ENSURE_SUCCESS(rv, rv);
372 return runCurrentTest();
375 nsresult
376 nsTestRunner::pushTest(const char * aContractID)
378 nsresult rv;
379 void *test;
380 nsCOMPtr<nsIComponentManager> componentManager;
382 rv = NS_GetComponentManager(getter_AddRefs( componentManager ));
383 NS_ENSURE_SUCCESS(rv, rv);
384 rv = componentManager->CreateInstanceByContractID(aContractID, nsnull,
385 NS_GET_IID(nsITest), (void **) &test);
386 if (NS_FAILED(rv)) {
387 AddError(nsITestRunner::errorLoad, aContractID);
388 return rv;
391 mTestTree.Push( (void *) test );
392 return NS_OK;
395 nsresult
396 nsTestRunner::runCurrentTest()
398 nsITest *test = (nsITest *) mTestTree.Peek();
400 test->Test( this );
401 if ( mRunning || mWatchWindow ) {
402 mRunning = PR_FALSE;
403 mArmed = PR_TRUE;
404 mTimerStop->InitWithCallback(this, 1000, nsITimer::TYPE_ONE_SHOT);
405 return NS_ERROR_ABORT;
408 return NS_OK;
411 nsresult
412 nsTestRunner::getNextTest(nsACString &aContractID)
414 nsresult rv;
415 PRBool hasMore;
417 nsITest *test = (nsITest *) mTestTree.Peek();
418 NS_ENSURE_TRUE(test, NS_ERROR_UNEXPECTED);
420 nsCOMPtr<nsIUTF8StringEnumerator> testNode(do_QueryInterface(test, &rv));
421 if (rv == NS_NOINTERFACE)
422 return NS_ERROR_NOT_AVAILABLE;
423 NS_ENSURE_SUCCESS(rv, rv);
425 rv = testNode->HasMore( &hasMore );
426 NS_ENSURE_SUCCESS(rv, rv);
427 if (! hasMore)
428 return NS_ERROR_NOT_AVAILABLE;
430 rv = testNode->GetNext( aContractID );
431 NS_ENSURE_SUCCESS(rv, rv);
433 return NS_OK;
436 void
437 nsTestRunner::traverse()
439 nsresult rv;
440 nsEmbedCString nextContractID(0);
441 nsITest *test;
443 while (mTestTree.GetSize()) {
445 rv = getNextTest( mTestID );
447 if (NS_FAILED(rv)) {
448 test = (nsITest *) mTestTree.Pop();
449 NS_RELEASE(test);
450 } else {
451 if (NS_FAILED( pushTest( mTestID.get() ) ))
452 continue;
453 if (NS_FAILED( runCurrentTest() ))
454 return;
458 if (NS_FAILED( mTimer->InitWithFuncCallback(done, this, 0,
459 nsITimer::TYPE_ONE_SHOT) )) {
460 done(nsnull, this);
464 nsresult
465 nsTestRunner::closeMainWindow()
467 nsresult rv;
468 nsCOMPtr<nsIAppStartup> app;
469 app = do_GetService("@mozilla.org/toolkit/app-startup;1", &rv);
470 NS_ENSURE_SUCCESS(rv, rv);
471 rv = app->Quit(app->eForceQuit);
472 NS_ENSURE_SUCCESS(rv, rv);
473 return NS_OK;
476 void
477 nsTestRunner::done(nsITimer *aTimer, void *aClosure)
479 nsTestRunner *self = static_cast<nsTestRunner*>(aClosure);
480 nsCOMPtr<nsIConsoleService> jsConsole;
482 jsConsole = do_GetService("@mozilla.org/consoleservice;1");
483 if (jsConsole )
484 jsConsole->UnregisterListener( self );
486 self->closeMainWindow();
487 self->mTestResult->Done();
488 self->mTestResult = nsnull;
489 self->mTimer = nsnull;
492 NS_IMETHODIMP
493 nsTestRunner::Handle(nsICommandLine *aCommandLine)
495 nsresult rv;
496 PRBool isTest;
498 rv = aCommandLine->HandleFlag(NS_LITERAL_STRING("test"), PR_TRUE, &isTest);
499 NS_ENSURE_SUCCESS(rv,rv);
500 if (isTest){
501 aCommandLine->SetPreventDefault(PR_TRUE);
503 mTimer = do_CreateInstance("@mozilla.org/timer;1");
504 NS_ENSURE_TRUE(mTimer, NS_ERROR_ABORT);
506 mTimerStop = do_CreateInstance("@mozilla.org/timer;1");
507 NS_ENSURE_TRUE(mTimer, NS_ERROR_ABORT);
509 mTestResult = do_CreateInstance("@aasii.org/cxxunit/testresult", &rv);
510 NS_ENSURE_SUCCESS(rv, NS_ERROR_ABORT);
512 if (NS_FAILED( openMainWindow() )) {
513 rv = NS_ERROR_ABORT;
515 run();
516 return rv;
518 return NS_OK;
521 NS_IMETHODIMP
522 nsTestRunner::GetHelpInfo(nsACString & aHelpInfo)
524 aHelpInfo.Assign(" --test Run unit test collection\n");
525 return NS_OK;
528 nsresult
529 nsTestRunner::resolve(nsACString &aURL, const PRUnichar* *result)
531 nsresult rv;
532 nsCOMPtr<nsIRDFService> rdfSrv;
533 nsCOMPtr<nsIRDFResource> src, prop;
534 nsCOMPtr<nsIRDFNode> target;
535 nsCOMPtr<nsIRDFLiteral> targetLiteral;
537 NS_ENSURE_ARG_POINTER(result);
538 *result = nsnull;
539 rdfSrv = do_GetService("@mozilla.org/rdf/rdf-service;1", &rv);
540 NS_ENSURE_SUCCESS( rv, rv );
542 if ( ! mFileMap ) {
543 nsCOMPtr<nsIPrefBranch> pref;
544 nsEmbedCString url;
546 pref = do_GetService("@mozilla.org/preferences-service;1", &rv);
547 NS_ENSURE_SUCCESS(rv, rv );
548 rv = pref->GetCharPref("cxxunit.fileMap",getter_Copies(url));
549 NS_ENSURE_SUCCESS(rv, rv );
551 rv = rdfSrv->GetDataSourceBlocking(url.get(),
552 getter_AddRefs( mFileMap ));
553 NS_ENSURE_TRUE( mFileMap, rv );
556 rv = rdfSrv->GetResource( aURL, getter_AddRefs( src ));
557 NS_ENSURE_SUCCESS(rv, rv );
558 rv = rdfSrv->GetResource(
559 NS_LITERAL_CSTRING("http://www.aasii.org/AA-rdf#File"),
560 getter_AddRefs( prop ));
561 NS_ENSURE_SUCCESS(rv, rv );
563 rv = mFileMap->GetTarget(src, prop, PR_TRUE, getter_AddRefs( target ));
564 if (! target)
565 return rv;
566 targetLiteral = do_QueryInterface( target, &rv );
567 NS_ENSURE_TRUE( target, rv );
568 targetLiteral->GetValueConst( result );
569 NS_ENSURE_TRUE( target, rv );
571 return NS_OK;
574 NS_IMETHODIMP
575 nsTestRunner::Notify(nsITimer *timer)
577 if (mArmed) {
578 mArmed = PR_FALSE;
579 AddError(nsITestRunner::errorTimeout, mTestID.get());
580 mTimer->Cancel();
582 traverse();
583 return NS_OK;
586 NS_IMETHODIMP
587 nsTestRunner::OnStateChange(nsIWebProgress *aWebProgress,
588 nsIRequest *aRequest, PRUint32 aStateFlags, nsresult aStatus)
590 if (! (aStateFlags & nsIWebProgressListener::STATE_STOP) )
591 return NS_OK;
593 nsCOMPtr<nsIDOMWindow> wnd;
594 aWebProgress->GetDOMWindow(getter_AddRefs( wnd ));
595 if ( wnd != mWatchWindow ) {
596 return NS_OK;
599 mWatchWindow = nsnull;
600 aWebProgress->RemoveProgressListener( this );
602 NS_ENSURE_TRUE(mArmed, NS_ERROR_UNEXPECTED);
604 nsITest *test = (nsITest *) mTestTree.Peek();
605 NS_ENSURE_TRUE(test, NS_ERROR_UNEXPECTED);
607 nsCOMPtr<nsIWebProgressListener> listener(do_QueryInterface(test));
608 NS_ENSURE_TRUE(listener, NS_ERROR_UNEXPECTED);
610 listener->OnStateChange(aWebProgress, aRequest, aStateFlags, aStatus);
612 return NS_OK;
615 NS_IMETHODIMP
616 nsTestRunner::OnProgressChange(nsIWebProgress *aWebProgress,
617 nsIRequest *aRequest, PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress,
618 PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress)
620 return NS_ERROR_NOT_IMPLEMENTED;
623 NS_IMETHODIMP
624 nsTestRunner::OnLocationChange(nsIWebProgress *aWebProgress,
625 nsIRequest *aRequest, nsIURI *aLocation)
627 return NS_ERROR_NOT_IMPLEMENTED;
630 NS_IMETHODIMP
631 nsTestRunner::OnStatusChange(nsIWebProgress *aWebProgress,
632 nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage)
634 return NS_ERROR_NOT_IMPLEMENTED;
637 NS_IMETHODIMP
638 nsTestRunner::OnSecurityChange(nsIWebProgress *aWebProgress,
639 nsIRequest *aRequest, PRUint32 aState)
641 return NS_ERROR_NOT_IMPLEMENTED;
644 nsTestRunner*
645 nsTestRunner::GetTestRunner()
647 if ( nsTestRunner::gTestRunner == nsnull ) {
648 nsTestRunner::gTestRunner = new nsTestRunner;
651 if ( nsTestRunner::gTestRunner != nsnull ) {
652 NS_ADDREF( nsTestRunner::gTestRunner );
655 return nsTestRunner::gTestRunner;
658 /******************** nsFormatJSMessage ***********************************/
659 nsFormatJSMessage::nsFormatJSMessage(nsIConsoleMessage *aMessage)
661 if (NS_SUCCEEDED( parseScriptError( aMessage ) )) {
662 return;
664 nsEmbedString wstr;
665 aMessage->GetMessageMoz(getter_Copies( wstr ));
666 mFile.Assign(nsnull,0);
667 mLine = nsITestRunner::errorNoError;
668 mText.Assign( NS_ConvertUTF16toUTF8(wstr));
671 nsFormatJSMessage::nsFormatJSMessage(const char *aFile)
673 mFile.Assign(aFile);
674 getSourceFile();
677 nsresult
678 nsFormatJSMessage::parseScriptError(nsIConsoleMessage *aMessage)
680 nsresult rv;
681 nsCOMPtr<nsIScriptError> error;
682 nsEmbedString wstr;
684 error = do_QueryInterface( aMessage, &rv );
685 if (NS_FAILED(rv))
686 return rv;
688 rv = formatErrorMessage(error);
689 NS_ENSURE_SUCCESS(rv, rv);
691 if (NS_FAILED( getSourceFile() )) {
692 mFile.Assign(nsnull, 0);
693 mLine = nsITestRunner::errorJS;
696 return NS_OK;
699 nsresult
700 nsFormatJSMessage::formatErrorMessage(nsIScriptError *error)
702 nsresult rv;
703 nsEmbedString wstr;
705 rv = error->GetErrorMessage( wstr );
706 NS_ENSURE_SUCCESS(rv, rv);
708 nsEmbedCString text = NS_ConvertUTF16toUTF8( wstr );
710 rv = error->GetLineNumber( &mLine );
711 if (NS_SUCCEEDED( rv ))
712 rv = error->GetSourceName( wstr );
713 if (NS_SUCCEEDED( rv ))
714 mFile = NS_ConvertUTF16toUTF8(wstr);
716 if ( parseException(text) )
717 return NS_OK;
719 PRUint32 flags;
720 rv = error->GetFlags( &flags );
721 if (NS_FAILED( rv ))
722 flags = 0;
724 if ( flags & nsIScriptError::warningFlag ) {
725 mText.Assign("warning: ");
726 } else {
727 mText.Assign("error: ");
729 mText.Append( text );
730 return NS_OK;
733 PRBool
734 nsFormatJSMessage::parseException(const nsACString &aMessage)
736 const char *head, *pos, *res, *end;
737 nsresult rv;
739 head = aMessage.BeginReading();
740 pos = strstr(head, "[Exception... \"");
741 if (! pos)
742 return PR_FALSE;
744 mText.Assign("exception: ");
746 if (pos[15] == '\'') {
747 end = strchr(&pos[16], '\'');
748 if (end) {
749 mText.Append(&pos[15], end - pos - 14);
751 } else if ( (res = strstr(&pos[15], "nsresult: \"0x")) && strlen(res) > 23) {
752 end = strchr(&res[23], ')');
753 if (end) {
754 mText.Append(&res[23], end - res - 23);
756 } else {
757 mText.Append(&pos[15],strlen(pos) - 16);
760 if ( ! mFile.Length() ) {
761 res = strstr(&pos[15],"location: \"JS frame :: ");
762 if (!res || strlen(res) < 25)
763 return PR_TRUE;
764 end = strstr(&res[23], " :: ");
765 if (! end)
766 return PR_TRUE;
767 mFile.Assign(Substring(&res[23], end - res - 23));
768 res = strstr(&end[4], ":: line ");
769 if (!res && strlen(res) < 10)
770 return PR_TRUE;
771 end = strchr(&res[8], '"');
772 if (! end)
773 return PR_TRUE;
774 mLine = Substring(&res[8], end - res - 8).ToInteger(&rv);
776 return PR_TRUE;
779 nsresult
780 nsFormatJSMessage::getSourceFile()
782 if ( StringHead(mFile, 7).Equals(NS_LITERAL_CSTRING("file://")) ) {
783 return parseLocalFile();
784 } else if (! StringHead(mFile, 9).Equals(NS_LITERAL_CSTRING("chrome://")) ) {
785 return NS_ERROR_FILE_UNRECOGNIZED_PATH;
787 return parseChrome();
790 nsresult
791 nsFormatJSMessage::parseLocalFile()
793 nsEmbedCString leafName;
794 const PRUnichar* resolved;
796 leafName = "file://";
797 leafName += strrchr(mFile.BeginReading(), '/');
798 if (! mResolver) {
799 mResolver = nsTestRunner::GetTestRunner();
800 NS_ENSURE_TRUE( mResolver, NS_OK );
802 mResolver->resolve( leafName, &resolved );
803 if (! resolved )
804 return NS_OK;
805 if ( resolved[0] )
806 mFile.Assign(NS_ConvertUTF16toUTF8( resolved ));
808 return NS_OK;
811 nsresult
812 nsFormatJSMessage::parseChrome()
814 nsEmbedCString head;
815 const char *tail, *ptr = 0;
816 PRUint32 len;
817 const PRUnichar* resolved;
819 len = mFile.Length();
820 tail = strrchr(mFile.BeginReading(), '/');
821 head = StringHead(mFile, len - strlen(tail) );
822 if (! mResolver) {
823 mResolver = nsTestRunner::GetTestRunner();
824 NS_ENSURE_TRUE( mResolver, NS_OK );
826 mResolver->resolve( head, &resolved);
827 while( ! resolved && (head.Length() > 9) ) {
828 ptr = strrchr(head.BeginReading(), '/');
829 tail -= strlen(ptr);
830 head = StringHead(mFile, len - strlen(tail) );
831 mResolver->resolve( head, &resolved);
833 if (! resolved )
834 return NS_OK;
836 head = NS_ConvertUTF16toUTF8(resolved);
837 head += tail;
838 mFile.Assign( head );
840 return NS_OK;