e70152e44cc66cc599ff6b699eb8adc07f3e656a
kent
  Sat May 24 21:09:34 2014 -0700
Adding Copyright NNNN Regents of the University of California to all files I believe with reasonable certainty were developed under UCSC employ or as part of Genome Browser copyright assignment.
diff --git src/lib/qa.c src/lib/qa.c
index 65f171f..d919f96 100644
--- src/lib/qa.c
+++ src/lib/qa.c
@@ -1,219 +1,222 @@
 /* qa - Modules to help do testing, especially on html based apps. */
 
+/* Copyright (C) 2011 The Regents of the University of California 
+ * See README in this or parent directory for licensing information. */
+
 #include "common.h"
 #include "hash.h"
 #include "dystring.h"
 #include "portable.h"
 #include "htmlPage.h"
 #include "errabort.h"
 #include "errCatch.h"
 #include "htmshell.h"
 #include "qa.h"
 
 
 char *qaStringBetween(char *text, char *startPattern, char *endPattern)
 /* Return text that occurs between startPattern and endPattern,
  * or NULL if no startPattern.  (Will return up to 100 characters
  * after startPattern if there is no endPattern) */
 {
 char *startMid = stringIn(startPattern, text);
 if (startMid != NULL)
     {
     char *endMid;
     int midSize;
     startMid += strlen(startPattern);
     endMid = stringIn(startMid, endPattern);
     if (endMid == NULL)
         {
 	midSize = strlen(startMid);
 	if (midSize > 100)
 	    midSize = 100;
 	}
     else
         midSize = endMid - startMid;
     return cloneStringZ(startMid, midSize);
     }
 return NULL;
 }
 
 char *qaScanForErrorMessage(char *text)
 /* Scan text for error message.  If one exists then
  * return copy of it.  Else return NULL. */
 {
 return qaStringBetween(text, htmlWarnStartPattern(), htmlWarnEndPattern());
 }
 
 int qaCountBetween(char *s, char *startPattern, char *endPattern, 
 	char *midPattern)
 /* Count the number of midPatterns that occur between start and end pattern. */
 {
 int count = 0;
 char *e;
 s = stringIn(startPattern, s);
 if (s != NULL)
     {
     s += strlen(startPattern);
     e = stringIn(endPattern, s);
     while (s < e)
         {
 	if (startsWith(midPattern, s))
 	    ++count;
 	s += 1;
 	}
     }
 return count;
 }
 
 void qaStatusReportOne(FILE *f, struct qaStatus *qs, char *format, ...)
 /* Report status */
 {
 char *errMessage = qs->errMessage;
 char *severity = "ok";
 va_list args;
 va_start(args, format);
 if (errMessage == NULL)
     errMessage = "";
 else
     {
     if (qs->hardError)
         severity = "hard";
     else
         severity = "soft";
     }
   
 vfprintf(f, format, args);
 fprintf(f, " %4.3fs (%s) %s\n", 0.001*qs->milliTime, severity, errMessage);
 va_end(args);
 }
 
 static struct qaStatus *qaStatusOnPage(struct errCatch *errCatch, 
 	struct htmlPage *page, long startTime, struct htmlPage **retPage)
 /* Assuming you have fetched page with the given error catcher,
  * starting the fetch at the given startTime, then create a
  * qaStatus that describes how the fetch went.  If *retPage is non-null
  * then return the page there, otherwise free it. */
 {
 char *errMessage = NULL;
 struct qaStatus *qs;
 AllocVar(qs);
 if (errCatch->gotError || page == NULL)
     {
     errMessage = errCatch->message->string;
     qs->hardError = TRUE;
     }
 else
     {
     if (page->status->status != 200)
 	{
 	dyStringPrintf(errCatch->message, "HTTP status code %d\n", 
 		page->status->status);
 	errMessage = errCatch->message->string;
 	qs->hardError = TRUE;
 	htmlPageFree(&page);
 	}
     else
         {
 	errMessage = qaScanForErrorMessage(page->fullText);
 	}
     }
 qs->errMessage = cloneString(errMessage);
 if (qs->errMessage != NULL)
     subChar(qs->errMessage, '\n', ' ');
 qs->milliTime = clock1000() - startTime;
 if (retPage != NULL)
     *retPage = page;
 else
     htmlPageFree(&page);
 return qs;
 }
 
 struct qaStatus *qaPageGet(char *url, struct htmlPage **retPage)
 /* Get info on given url, (and return page if retPage non-null). */
 {
 struct errCatch *errCatch = errCatchNew();
 struct qaStatus *qs;
 struct htmlPage *page = NULL;
 long startTime = clock1000();
 if (errCatchStart(errCatch))
     {
     page = htmlPageGet(url);
     htmlPageValidateOrAbort(page);
     }
 else
     {
     htmlPageFree(&page);
     }
 errCatchEnd(errCatch);
 qs = qaStatusOnPage(errCatch, page, startTime, retPage);
 errCatchFree(&errCatch);
 return qs;
 }
 
 struct qaStatus *qaPageFromForm(struct htmlPage *origPage, struct htmlForm *form, 
 	char *buttonName, char *buttonVal, struct htmlPage **retPage)
 /* Get update to form based on pressing a button. */
 {
 struct errCatch *errCatch = errCatchNew();
 struct qaStatus *qs;
 struct htmlPage *page = NULL;
 long startTime = clock1000();
 if (errCatchStart(errCatch))
     {
     page = htmlPageFromForm(origPage, form, buttonName, buttonVal);
     htmlPageValidateOrAbort(page);
     }
 else
     {
     htmlPageFree(&page);
     }
 errCatchEnd(errCatch);
 qs = qaStatusOnPage(errCatch, page, startTime, retPage);
 errCatchFree(&errCatch);
 return qs;
 }
 
 void qaStatusSoftError(struct qaStatus *qs, char *format, ...)
 /* Add error message for something less than a crash. */
 {
 struct dyString *dy = dyStringNew(0);
 va_list args, args2;
 va_start(args, format);
 /* args can't be reused, so vaWarn needs its own va_list: */
 va_start(args2, format);
 vaWarn(format, args2);
 if (qs->errMessage)
     {
     dyStringAppend(dy, qs->errMessage);
     dyStringAppendC(dy, '\n');
     }
 dyStringVaPrintf(dy, format, args);
 va_end(args);
 va_end(args2);
 freez(&qs->errMessage);
 qs->errMessage = cloneString(dy->string);
 dyStringFree(&dy);
 }
 
 void qaStatisticsAdd(struct qaStatistics *stats, struct qaStatus *qs)
 /* Add test results to totals */
 {
 stats->testCount += 1;
 stats->milliTotal += qs->milliTime;
 if (qs->errMessage)
     {
     if (qs->hardError)
         stats->hardCount += 1;
     else
         stats->softCount += 1;
     }
 }
 
 void qaStatisticsReport(struct qaStatistics *stats, char *label, FILE *f)
 /* Write a line of stats to file. */
 {
 fprintf(f, "%20s:  %3d tests, %2d soft errors, %2d hard errors, %5.2f seconds\n",
 	label, stats->testCount, stats->softCount, stats->hardCount, 
 	0.001 * stats->milliTotal);
 }