a2d20a840e07785d0ae88d3d27c45f5d5a28ea70
galt
  Tue Jun 21 17:27:13 2016 -0700
improving hgTablesTest output. Now states more info about the machine it is running on, the URL to the hgTables site that it is testing against, and the database that it is connecting to. It also allows randomizing the track and table lists, and an optional seed is reported any can be set on commandline for debugging.

diff --git src/hg/hgTablesTest/hgTablesTest.c src/hg/hgTablesTest/hgTablesTest.c
index f4d4d12..7e7bc96 100644
--- src/hg/hgTablesTest/hgTablesTest.c
+++ src/hg/hgTablesTest/hgTablesTest.c
@@ -4,30 +4,33 @@
  * See README in this or parent directory for licensing information. */
 #include "common.h"
 #include "memalloc.h"
 #include "linefile.h"
 #include "hash.h"
 #include "htmshell.h"
 #include "portable.h"
 #include "options.h"
 #include "errCatch.h"
 #include "ra.h"
 #include "htmlPage.h"
 #include "../hgTables/hgTables.h"
 #include "hdb.h"
 #include "qa.h"
 #include "chromInfo.h"
+#include "obscure.h"
+#include <unistd.h>
+#include <limits.h>
 
 #define MAX_ATTEMPTS 10
 
 
 /* Command line variables. */
 char *clOrg = NULL;	/* Organism from command line. */
 char *clDb = NULL;	/* DB from command line */
 char *clGroup = NULL;	/* Group from command line. */
 char *clTrack = NULL;	/* Track from command line. */
 char *clTable = NULL;	/* Table from command line. */
 int clGroups = BIGNUM;	/* Number of groups to test. */
 int clTracks = 4;	/* Number of track to test. */
 int clTables = 2;	/* Number of tables to test. */
 int clDbs = 1;		/* Number of databases per organism. */
 int clOrgs = 2;		/* Number of organisms to test. */
@@ -43,60 +46,65 @@
   "Where url is something like hgwbeta.cse.ucsc.edu/cgi-bin/hgTables\n"
   "and log is a file where error messages and statistics will be written\n"
   "options:\n"
   "   -org=Human - Restrict to Human (or Mouse, Fruitfly, etc.)\n"
   "   -db=hg17 - Restrict to particular database\n"
   "   -group=genes - Restrict to a particular group\n"
   "   -track=knownGene - Restrict to a particular track\n"
   "   -table=knownGeneMrna - Restrict to a particular table\n"
   "   -orgs=N - Number of organisms to test.  Default %d\n"
   "   -dbs=N - Number of databases per organism to test. Default %d\n"
   "   -groups=N - Number of groups to test (default all)\n"
   "   -tracks=N - Number of tracks per group to test (default %d)\n"
   "   -tables=N - Number of tables per track to test (default %d)\n"
   "   -verbose=N - Set to 0 for silent operation, 2 or 3 for debugging\n"
   "   -appendLog - Append to log file rather than creating it\n"
+  "   -seed flag to specify seed for random number generator as debugging aid.\n"
   , clOrgs, clDbs, clTracks, clTables);
 }
 
 FILE *logFile;	/* Log file. */
+int seed = 0;           /* seed for random number generator */
 
-static struct optionSpec options[] = {
+static struct optionSpec options[] = 
+{
     {"org", OPTION_STRING},
     {"db", OPTION_STRING},
     {"group", OPTION_STRING},
     {"track", OPTION_STRING},
     {"table", OPTION_STRING},
     {"orgs", OPTION_INT},
     {"dbs", OPTION_INT},
     {"search", OPTION_STRING},
     {"groups", OPTION_INT},
     {"tracks", OPTION_INT},
     {"tables", OPTION_INT},
     {"appendLog", OPTION_BOOLEAN},
+    {"seed", OPTION_INT},
     {NULL, 0},
 };
 
 struct tablesTest
 /* Test on one column. */
     {
     struct tablesTest *next;
     struct qaStatus *status;	/* Result of test. */
     char *info[6];
     };
 
-enum tablesTestInfoIx {
+enum tablesTestInfoIx 
+{
     ntiiType,
     ntiiOrg,
     ntiiDb,
     ntiiGroup,
     ntiiTrack,
     ntiiTable,
     ntiiTotalCount,
 };
 
 
 char *tablesTestInfoTypes[] =
    { "type", "organism", "db", "group", "track", "table"};
 
 struct tablesTest *tablesTestList = NULL;	/* List of all tests, latest on top. */
 
@@ -178,30 +186,54 @@
     *pPage = quickSubmit(oldPage, org, db, group, track, table,
     	testName, button, buttonVal);
     htmlPageFree(&oldPage);
     }
 }
 
 int tableSize(char *db, char *table)
 /* Return number of rows in table. */
 {
 struct sqlConnection *conn = sqlConnect(db);
 int size = sqlTableSize(conn, table);
 sqlDisconnect(&conn);
 return size;
 }
 
+void showConnectInfo(char *db)
+/* Show connection info used by this program. */
+{
+struct sqlConnection *conn = sqlConnect(db);
+char *user = sqlQuickString(conn, NOSQLINJ "select current_user()");
+char *hostinfo = sqlHostInfo(conn);
+      verbose(1, "Connecting as %s to database server %s\n", user, hostinfo);
+fprintf(logFile, "Connecting as %s to database server %s\n", user, hostinfo); fflush(logFile);
+sqlDisconnect(&conn);
+}
+
+void showRunningHostName()
+/* Show hostname of the machine we are running on. */
+{
+char hostname[HOST_NAME_MAX];
+if (gethostname(hostname, sizeof hostname))
+    {
+    perror("gethostname");
+    safecpy(hostname, sizeof hostname, "error-reading-hostname");
+    }
+      verbose(1, "Runnng on machine %s\n", hostname);
+fprintf(logFile, "Runnng on machine %s\n", hostname); fflush(logFile);
+}
+
 void quickErrReport()
 /* Report error at head of list if any */
 {
 struct tablesTest *test = tablesTestList;
 if (test->status->errMessage != NULL)
     tablesTestLogOne(test, stderr);
 }
 
 void testSchema(struct htmlPage *tablePage, struct htmlForm *mainForm,
      char *org, char *db, char *group, char *track, char *table)
 /* Make sure schema page comes up. */
 /* mainForm not used */
 {
 struct htmlPage *schemaPage = quickSubmit(tablePage, org, db, group,
         track, table, "schema", hgtaDoSchema, "submit");
@@ -251,31 +283,31 @@
 }
 
 int testAllFields(struct htmlPage *tablePage, struct htmlForm *mainForm,
      char *org, char *db, char *group, char *track, char *table)
 /* Get all fields and return count of rows. */
 /* mainForm not used */
 {
 struct htmlPage *outPage;
 int rowCount = 0;
 
 htmlPageSetVar(tablePage, NULL, hgtaOutputType, "primaryTable");
 outPage = quickSubmit(tablePage, org, db, group, track, table,
     "allFields", hgtaDoTopSubmit, "submit");
 /* check for NULL outPage */
 if (outPage == NULL)
-    errAbort("Null page in testAllFields");
+    errAbort("Null page in testAllFields (%s %s %s %s %s)", org, db, group, track, table);
 rowCount = countNoncommentLines(outPage->htmlText);
 htmlPageFree(&outPage);
 return rowCount;
 }
 
 struct htmlFormVar *findPrefixedVar(struct htmlFormVar *list, char *prefix)
 /* Find first var with given prefix in list. */
 {
 struct htmlFormVar *var;
 for (var = list; var != NULL; var = var->next)
     {
     if (startsWith(prefix, var->name))
         return var;
     }
 return NULL;
@@ -686,61 +718,85 @@
     }
 }
 
 void testOneTrack(struct htmlPage *groupPage, char *org, char *db,
 	char *group, char *track, int maxTables)
 /* Test a little something on up to maxTables in one track. */
 {
 struct htmlPage *trackPage = quickSubmit(groupPage, org, db, group, 
 	track, NULL, "selectTrack", hgtaTrack, track);
 struct htmlForm *mainForm;
 struct htmlFormVar *tableVar;
 struct slName *table;
 int tableIx;
 
 if (trackPage == NULL)
+    {
+    // is this an exception?
+    // exception for bigPsl (2016-06-20), may be short-lived.
+    struct sqlConnection *conn = sqlConnect(db);
+    char query[256];
+    sqlSafef(query, sizeof query, "select type from trackDb where tableName='%s'", track);
+    char *type = sqlQuickString(conn, query);
+    sqlDisconnect(&conn);
+    if (sameString(type, "bigPsl"))
+	{
+    	      verbose(1, "Skipping testing track %s since type bigPsl not supported by hgTables at this time (2016-06-20)\n", track);
+    	fprintf(logFile, "Skipping testing track %s since type bigPsl not supported by hgTables at this time (2016-06-20)\n", track);
+	return;
+	}
+    else
 	errAbort("Couldn't select track %s", track);
+    }
 if ((mainForm = htmlFormGet(trackPage, "mainForm")) == NULL)
     errAbort("Couldn't get main form on trackPage");
 if ((tableVar = htmlFormVarGet(mainForm, hgtaTable)) == NULL)
     errAbort("Can't find table var");
+
+// put the tables in random order:
+shuffleList(&tableVar->values);
+
 for (table = tableVar->values, tableIx = 0; 
 	table != NULL && tableIx < maxTables; 
 	table = table->next, ++tableIx)
     {
     if (clTable == NULL || sameString(clTable, table->name))
 	testOneTable(trackPage, org, db, group, track, table->name);
     }
 /* Clean up. */
 htmlPageFree(&trackPage);
 }
 
 void testOneGroup(struct htmlPage *dbPage, char *org, char *db, char *group, 
 	int maxTracks)
 /* Test a little something on up to maxTracks in one group */
 {
 struct htmlPage *groupPage = quickSubmit(dbPage, org, db, group, NULL, NULL,
 	"selectGroup", hgtaGroup, group);
 struct htmlForm *mainForm;
 struct htmlFormVar *trackVar;
 struct slName *track;
 int trackIx;
 
 if ((mainForm = htmlFormGet(groupPage, "mainForm")) == NULL)
     errAbort("Couldn't get main form on groupPage");
 if ((trackVar = htmlFormVarGet(mainForm, hgtaTrack)) == NULL)
     errAbort("Can't find track var");
+
+// put the tracks in random order:
+shuffleList(&trackVar->values);
+
 for (track = trackVar->values, trackIx = 0; 
 	track != NULL && trackIx < maxTracks; 
 	track = track->next, ++trackIx)
     {
     if (clTrack == NULL || sameString(track->name, clTrack))
 	testOneTrack(groupPage, org, db, group, track->name, clTables);
     }
 
 /* Clean up. */
 htmlPageFree(&groupPage);
 }
 
 void testGroups(struct htmlPage *dbPage, char *org, char *db, int maxGroups)
 /* Test a little something in all groups for dbPage. */
 {
@@ -1111,30 +1167,42 @@
     }
 }
 
 void hgTablesTest(char *url, char *logName)
 /* hgTablesTest - Test hgTables web page. */
 {
 /* Get default page, and open log. */
 struct htmlPage *rootPage = htmlPageGet(url);
 if (appendLog)
     logFile = mustOpen(logName, "a");
 else
     logFile = mustOpen(logName, "w");
 if (! endsWith(url, "hgTables"))
     warn("Warning: first argument should be a complete URL to hgTables, "
 	 "but doesn't look like one (%s)", url);
+
+fprintf(logFile,"seed=%d\n",seed);
+ 
+showRunningHostName();
+
+verbose(1, "Testing URL %s\n", url);
+fprintf(logFile, "Testing URL %s\n", url);
+
+/* Show what database server we are connecting to. 
+Matters for expected rows in tables. */
+showConnectInfo("uniProt");
+
 htmlPageValidateOrAbort(rootPage);
 
 /* Go test what they've specified in command line. */
 if (clDb != NULL)
     {
     testDb(rootPage, NULL, clDb);
     }
 else
     {
     struct htmlForm *mainForm;
     struct htmlFormVar *orgVar;
     if ((mainForm = htmlFormGet(rootPage, "mainForm")) == NULL)
 	errAbort("Couldn't get main form");
     if ((orgVar = htmlFormVarGet(mainForm, "org")) == NULL)
 	errAbort("Couldn't get org var");
@@ -1161,30 +1229,33 @@
 htmlPageFree(&rootPage);
 slReverse(&tablesTestList);
 reportSummary(tablesTestList, stdout);
 reportAll(tablesTestList, logFile);
 fprintf(logFile, "---------------------------------------------\n");
 reportSummary(tablesTestList, logFile);
 }
 
 int main(int argc, char *argv[])
 /* Process command line. */
 {
 pushCarefulMemHandler(500000000);
 optionInit(&argc, argv, options);
 if (argc != 3)
     usage();
+seed = optionInt("seed",time(NULL));
+      verbose(1,"seed=%d\n",seed);
+srand(seed);
 clDb = optionVal("db", clDb);
 clOrg = optionVal("org", clOrg);
 clGroup = optionVal("group", clGroup);
 clTrack = optionVal("track", clTrack);
 clTable = optionVal("table", clTable);
 clDbs = optionInt("dbs", clDbs);
 clOrgs = optionInt("orgs", clOrgs);
 clGroups = optionInt("groups", clGroups);
 clTracks = optionInt("tracks", clTracks);
 clTables = optionInt("tables", clTables);
 appendLog = optionExists("appendLog");
 if (clOrg != NULL)
    clOrgs = BIGNUM;
 hgTablesTest(argv[1], argv[2]);
 carefulCheckHeap();