Click here to Skip to main content
15,897,704 members
Articles / Programming Languages / C++

Error Detection Based on Check Digit Schemes

Rate me:
Please Sign up or sign in to vote.
4.72/5 (27 votes)
27 Nov 2007CPOL12 min read 91.3K   3K   50  
A Survey of Popular Check Digit Schemes
/* @author Edward Hieatt, edward@jsunit.net */

function jsUnitTestManager()
{
  this._windowForAllProblemMessages = null;


  this.container            = top.frames.testContainer
  this.documentLoader       = top.frames.documentLoader;
  this.mainFrame            = top.frames.mainFrame;

  this.containerController = this.container.frames.testContainerController;
  this.containerTestFrame  = this.container.frames.testFrame;

  var mainData             = this.mainFrame.frames.mainData;

  // form elements on mainData frame
  this.testFileName        = mainData.document.testRunnerForm.testFileName;
  this.runButton           = mainData.document.testRunnerForm.runButton;
  this.traceLevel          = mainData.document.testRunnerForm.traceLevel;
  this.closeTraceWindowOnNewRun = mainData.document.testRunnerForm.closeTraceWindowOnNewRun;
  this.timeout             = mainData.document.testRunnerForm.timeout;
  this.setUpPageTimeout      = mainData.document.testRunnerForm.setUpPageTimeout;

  // image output
  this.progressBar         = this.mainFrame.frames.mainProgress.document.progress;

  this.problemsListField           = this.mainFrame.frames.mainErrors.document.testRunnerForm.problemsList;
  this.testCaseResultsField        = this.mainFrame.frames.mainResults.document.resultsForm.testCases;  
  this.resultsTimeField			   = this.mainFrame.frames.mainResults.document.resultsForm.time;  

  // 'layer' output frames
  this.uiFrames                    = new Object();
  this.uiFrames.mainStatus         = this.mainFrame.frames.mainStatus;

  var mainCounts                   = this.mainFrame.frames.mainCounts;

  this.uiFrames.mainCountsErrors   = mainCounts.frames.mainCountsErrors;
  this.uiFrames.mainCountsFailures = mainCounts.frames.mainCountsFailures;
  this.uiFrames.mainCountsRuns     = mainCounts.frames.mainCountsRuns;
  this._baseURL = "";

  this.setup();
}

// seconds to wait for each test page to load
jsUnitTestManager.TESTPAGE_WAIT_SEC  = 20;
jsUnitTestManager.TIMEOUT_LENGTH     = 20;

// seconds to wait for setUpPage to complete
jsUnitTestManager.SETUPPAGE_TIMEOUT    = 60; 

// milliseconds to wait between polls on setUpPages
jsUnitTestManager.SETUPPAGE_INTERVAL   = 100;

jsUnitTestManager.prototype.setup = function ()
{
  this.totalCount    = 0;
  this.errorCount    = 0;
  this.failureCount  = 0;
  this._suiteStack   = Array();


  var initialSuite   = new top.jsUnitTestSuite();
  push(this._suiteStack, initialSuite);
}

jsUnitTestManager.prototype.start = function () 
{
  this._baseURL = this.resolveUserEnteredTestFileName();
  var firstQuery = this._baseURL.indexOf("?");
  if (firstQuery >= 0) {
       this._baseURL = this._baseURL.substring(0, firstQuery);
  }
  var lastSlash = this._baseURL.lastIndexOf("/");
  var lastRevSlash = this._baseURL.lastIndexOf("\\");
  if (lastRevSlash > lastSlash) {
     lastSlash = lastRevSlash;
  }
  if (lastSlash > 0) {
     this._baseURL = this._baseURL.substring(0, lastSlash + 1);
  }

  this._timeRunStarted = new Date();
  this.initialize();
  setTimeout('top.testManager._nextPage();', jsUnitTestManager.TIMEOUT_LENGTH);
}

jsUnitTestManager.prototype.getBaseURL = function () {
  return this._baseURL;
}

jsUnitTestManager.prototype.doneLoadingPage = function (pageName) 
{
  //this.containerTestFrame.setTracer(top.tracer);
  this._testFileName = pageName;
  if (this.isTestPageSuite()) 
    this._handleNewSuite();
  else
  {
    this._testIndex   = 0;
    this._testsInPage = this.getTestFunctionNames();
    this._numberOfTestsInPage = this._testsInPage.length;
    this._runTest();
  }
}

jsUnitTestManager.prototype._handleNewSuite = function () 
{
  var allegedSuite = this.containerTestFrame.suite();
  if (allegedSuite.isjsUnitTestSuite) {
    var newSuite = allegedSuite.clone();
    if (newSuite.containsTestPages())
      push(this._suiteStack, newSuite);
    this._nextPage();
  }
  else {
    alert('Invalid test suite in file ' + this._testFileName);
    this.abort();
  }
}

jsUnitTestManager.prototype._runTest = function () 
{
  if (this._testIndex + 1 > this._numberOfTestsInPage)
  {
    this._nextPage();
    return;
  }

  if (this._testIndex == 0 && typeof(this.containerTestFrame.setUpPage) == 'function')
  {
    // first test for this page and a setUpPage is defined
    if (typeof(this.containerTestFrame.setUpPageStatus) == 'undefined')
    {
      // setUpPage() not called yet, so call it
      this.containerTestFrame.setUpPageStatus = false;
      this.containerTestFrame.startTime = new Date();
      this.containerTestFrame.setUpPage();
      // try test again later
      setTimeout('top.testManager._runTest()', jsUnitTestManager.SETUPPAGE_INTERVAL);
      return;
    }

    if (this.containerTestFrame.setUpPageStatus != 'complete')
    {
      // setUpPage called, but not complete yet
      top.status = 'setUpPage not completed... ' + this.containerTestFrame.setUpPageStatus + ' ' + (new Date());
      if ((new Date() - this.containerTestFrame.startTime) /1000 > this.getsetUpPageTimeout()) {
        alert('setUpPage timed out without completing.');
        if (prompt('Retry or Cancel ?', 'Retry') != 'Retry')
        {
          this.abort();
          return;
        }
        this.containerTestFrame.startTime = (new Date());
      }
      // try test again later
      setTimeout('top.testManager._runTest()', jsUnitTestManager.SETUPPAGE_INTERVAL);
      return;
    }
  }

  top.status = '';
  // either not first test, or no setUpPage defined, or setUpPage completed
  this.executeTestFunction(this._testsInPage[this._testIndex]);
  this.totalCount++;
  this.updateProgressIndicators();
  this._testIndex++;
  setTimeout('top.testManager._runTest()', jsUnitTestManager.TIMEOUT_LENGTH);
}

jsUnitTestManager.prototype._done = function () 
{
  var secondsSinceRunBegan=(new Date() - this._timeRunStarted)/1000;
  this.setStatus('Done (' + secondsSinceRunBegan + ' seconds)');
  this._cleanUp();
  if (top.shouldSubmitResults()) {
    this.resultsTimeField.value = secondsSinceRunBegan;
  	top.submitResults();
  }
}

jsUnitTestManager.prototype._nextPage = function () 
{
  if (this._currentSuite().hasMorePages()) {
    this.loadPage(this._currentSuite().nextPage());
  }
  else {
    pop(this._suiteStack);
    if (this._currentSuite() == null)
      this._done();
    else
      this._nextPage();
  }
}

jsUnitTestManager.prototype._currentSuite = function () 
{
  var suite = null;

  if (this._suiteStack && this._suiteStack.length > 0)
    suite = this._suiteStack[this._suiteStack.length-1];

  return suite;
}

jsUnitTestManager.prototype.calculateProgressBarProportion = function () 
{
  if (this.totalCount == 0) 
    return 0;
  var currentDivisor = 1;
  var result         = 0;
  
  for (var i = 0; i < this._suiteStack.length; i++) {
    var aSuite     = this._suiteStack[i];
    currentDivisor *= aSuite.testPages.length;
    result += (aSuite.pageIndex - 1)/currentDivisor;
  }
  result += (this._testIndex + 1)/(this._numberOfTestsInPage * currentDivisor);
  return result;
}

jsUnitTestManager.prototype._cleanUp = function () 
{
  this.containerController.setTestPage('./app/emptyPage.html');
  this.finalize();
  top.tracer.finalize();
}

jsUnitTestManager.prototype.abort = function () 
{
  this.setStatus('Aborted');
  this._cleanUp();
}

jsUnitTestManager.prototype.getTimeout = function () 
{
  var result = jsUnitTestManager.TESTPAGE_WAIT_SEC;
  try {
    result = eval(this.timeout.value);
  } 
  catch (e) {
  }
  return result;
}

jsUnitTestManager.prototype.getsetUpPageTimeout = function () 
{
  var result = jsUnitTestManager.SETUPPAGE_TIMEOUT;
  try {
    result = eval(this.setUpPageTimeout.value);
  } 
  catch (e) {
  }
  return result;
}

jsUnitTestManager.prototype.isTestPageSuite = function () 
{
  var result = false;
  if (typeof(this.containerTestFrame.suite) == 'function')
  {
    result = true;
  }
  return result;
}

jsUnitTestManager.prototype.getTestFunctionNames = function () 
{
  var testFrame         = this.containerTestFrame;
  var testFunctionNames = new Array();
  var i;
  
  if (testFrame && typeof(testFrame.exposeTestFunctionNames) == 'function')
        return testFrame.exposeTestFunctionNames();
  
  if (testFrame && 
      testFrame.document && 
      typeof(testFrame.document.scripts) != 'undefined') { // IE5 and up
    var scriptsInTestFrame = testFrame.document.scripts;
    
    for (i = 0; i < scriptsInTestFrame.length; i++) {
      var someNames = this._extractTestFunctionNamesFromScript(scriptsInTestFrame[i]);
      if (someNames)
        testFunctionNames=testFunctionNames.concat(someNames);
    }
  } 
  else {
    for (i in testFrame) {
      if (i.substring(0, 4) == 'test' && typeof(testFrame[i]) == 'function')
        push(testFunctionNames, i);
    }
  }
  return testFunctionNames;
}

jsUnitTestManager.prototype._extractTestFunctionNamesFromScript = function (aScript) 
{
  var result;
  var remainingScriptToInspect = aScript.text;
  var currentIndex             = remainingScriptToInspect.indexOf('function test');
  while (currentIndex != -1) {
    if (!result) 
      result=new Array();
      
    var fragment = remainingScriptToInspect.substring(currentIndex, remainingScriptToInspect.length);
    result       = result.concat(fragment.substring('function '.length, fragment.indexOf('(')));
                remainingScriptToInspect=remainingScriptToInspect.substring(currentIndex+12, remainingScriptToInspect.length);
                currentIndex=remainingScriptToInspect.indexOf('function test');
  }
  return result;
}

jsUnitTestManager.prototype.loadPage = function (testFileName) 
{
  this._testFileName         = testFileName;
  this._loadAttemptStartTime = new Date();
  this.setStatus('Opening Test Page "' + this._testFileName + '"');
  this.containerController.setTestPage(this._testFileName);
  this._callBackWhenPageIsLoaded();
}

jsUnitTestManager.prototype._callBackWhenPageIsLoaded = function () 
{
  if ((new Date() - this._loadAttemptStartTime) / 1000 > this.getTimeout()) {
    alert('Reading Test Page ' + this._testFileName + ' timed out.\nMake sure that the file exists and is a Test Page.');
    if (prompt('Retry or Cancel ?', 'Retry') != 'Retry')
    {
      this.abort();
      return;
    }
  }
  if (!this._isTestFrameLoaded()) {
    setTimeout('top.testManager._callBackWhenPageIsLoaded();', jsUnitTestManager.TIMEOUT_LENGTH);
    return;
  }
  this.doneLoadingPage(this._testFileName);
}

jsUnitTestManager.prototype._isTestFrameLoaded = function () 
{
  try {
    return this.containerController.isPageLoaded();
  } 
  catch (e) {
  }
  return false;
}

jsUnitTestManager.prototype.executeTestFunction = function (functionName) 
{
  this._testFunctionName=functionName;
  this.setStatus('Running test "' + this._testFunctionName + '"');
  var excep=null;
  var timeBefore = new Date();  
  try {
    this.containerTestFrame.setUp();
    eval('this.containerTestFrame.' + this._testFunctionName + '();');
  } 
  catch (e1) {
    excep = e1;
  }
  finally {
    try {
      this.containerTestFrame.tearDown();
    } 
    catch (e2) {
      excep = e2;
    }
  }
  var timeTaken = (new Date() - timeBefore) / 1000;
  if (excep != null)
    this._handleTestException(excep);
  var serializedTestCaseString = this._fullyQualifiedCurrentTestFunctionName()+"|"+timeTaken+"|";
  if (excep==null)
  	serializedTestCaseString+="S||";
  else {
  	if (typeof(excep.isJsUnitException) != 'undefined' && excep.isJsUnitException)
  		serializedTestCaseString+="F|";
  	else {
  		serializedTestCaseString+="E|";
  	}
  	serializedTestCaseString+=this._problemDetailMessageFor(excep);
  }  	
  var newOption = new Option(serializedTestCaseString);
  this.testCaseResultsField[this.testCaseResultsField.length]=newOption;  
}

jsUnitTestManager.prototype._fullyQualifiedCurrentTestFunctionName = function() {
    var testURL = this.containerTestFrame.location.href;
    var testQuery = testURL.indexOf("?");
    if (testQuery >= 0) {
        testURL = testURL.substring(0, testQuery);
    }
    if (testURL.substring(0, this._baseURL.length) == this._baseURL) {
          testURL = testURL.substring(this._baseURL.length);
    }
    return testURL + ':' + this._testFunctionName;
}


jsUnitTestManager.prototype._handleTestException = function (excep) 
{
  var problemMessage = this._fullyQualifiedCurrentTestFunctionName() + ' ';
  var errOption;
  if (typeof(excep.isJsUnitException) == 'undefined' || !excep.isJsUnitException) {
    problemMessage += 'had an error';
    this.errorCount++;
  } 
  else {
    problemMessage += 'failed';
    this.failureCount++;
  }
  var listField = this.problemsListField;
  var problemDocument = this.mainFrame.frames.mainErrors.document;
  if (typeof(problemDocument.createElement) != 'undefined') {
    // DOM Level 2 HTML method.
    // this is required for Opera 7 since appending to the end of the 
    // options array does not work, and adding an Option created by new Option()
    // and appended by listField.options.add() fails due to WRONG_DOCUMENT_ERR
    errOption = problemDocument.createElement('option');
    errOption.setAttribute('value', this._problemDetailMessageFor(excep));
    errOption.appendChild(problemDocument.createTextNode(problemMessage));
    listField.appendChild(errOption);
  }
  else {
    // new Option() is DOM 0
    errOption = new Option(problemMessage, this._problemDetailMessageFor(excep));
    if (typeof(listField.add) != 'undefined') {
      // DOM 2 HTML 
      listField.add( errOption , null);
    }
    else if (typeof(listField.options.add) != 'undefined') {
      // DOM 0
      listField.options.add( errOption, null);
    }
    else {
      // DOM 0
      listField.options[listField.length]= errOption;
    }
  }
}

jsUnitTestManager.prototype._problemDetailMessageFor = function (excep) 
{
  var result=null;
  if (typeof(excep.isJsUnitException) != 'undefined' && excep.isJsUnitException) {
    result = '';
    if (excep.comment != null)
      result+=('"'+excep.comment+'"\n');
    
    result += excep.jsUnitMessage;
    
    if (excep.stackTrace)
      result+='\n\nStack trace follows:\n'+excep.stackTrace;
  }
  else {
    result = 'Error message is:\n"';
    result +=
      (typeof(excep.description) == 'undefined') ?
      excep :
      excep.description;
    result += '"';
    if (typeof(excep.stack) != 'undefined') // Mozilla only
      result+='\n\nStack trace follows:\n'+excep.stack;
  }
  return result;
}

jsUnitTestManager.prototype._setTextOnLayer = function (layerName, str)
{
  var html = '';
  html += '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">';
  html += '<html><head><link rel="stylesheet" type="text/css" href="css/jsUnitStyle.css"><\/head>';
  html += '<body><div>';
  html += str;
  html += '<\/div><\/body>';
  html += '<\/html>';
  this.uiFrames[layerName].document.write(html);
  this.uiFrames[layerName].document.close();
}

jsUnitTestManager.prototype.setStatus = function (str)
{
  this._setTextOnLayer('mainStatus', '<b>Status:<\/b> '+str);
}

jsUnitTestManager.prototype._setErrors = function (n)
{
  this._setTextOnLayer('mainCountsErrors', '<b>Errors: <\/b>' + n);
}

jsUnitTestManager.prototype._setFailures = function (n)
{
  this._setTextOnLayer('mainCountsFailures', '<b>Failures:<\/b> ' + n);
}

jsUnitTestManager.prototype._setTotal = function (n)
{
  this._setTextOnLayer('mainCountsRuns', '<b>Runs:<\/b> ' + n);
}

jsUnitTestManager.prototype._setProgressBarImage = function (imgName)
{
  this.progressBar.src=imgName;
}

jsUnitTestManager.prototype._setProgressBarWidth = function (w)
{
  this.progressBar.width=w;
}

jsUnitTestManager.prototype.updateProgressIndicators = function ()
{
  this._setTotal(this.totalCount);
  this._setErrors(this.errorCount);
  this._setFailures(this.failureCount);
  this._setProgressBarWidth(300 * this.calculateProgressBarProportion());

  if (this.errorCount > 0 || this.failureCount > 0)
    this._setProgressBarImage('../images/red.gif');
  else
    this._setProgressBarImage('../images/green.gif');
}

jsUnitTestManager.prototype.showMessageForSelectedProblemTest = function ()
{
  var problemTestIndex = this.problemsListField.selectedIndex;
  if (problemTestIndex != -1)
    alert(this.problemsListField[problemTestIndex].value);
}

jsUnitTestManager.prototype.showMessagesForAllProblemTests = function ()
{
   if (this.problemsListField.length == 0) 
     return;

   try
   {
     if (this._windowForAllProblemMessages && !this._windowForAllProblemMessages.closed)
       this._windowForAllProblemMessages.close();
   }
   catch(e)
   {
   }

   this._windowForAllProblemMessages = window.open('','','width=600, height=350,status=no,resizable=yes,scrollbars=yes');
   var resDoc = this._windowForAllProblemMessages.document;
   resDoc.write('<html><head><link rel="stylesheet" href="../css/jsUnitStyle.css"><title>Tests with problems - JsUnit<\/title><head><body>');
   resDoc.write('<p class="jsUnitSubHeading">Tests with problems (' + this.problemsListField.length + ' total) - JsUnit<\/p>');
   resDoc.write('<p class="jsUnitSubSubHeading"><i>Running on '+navigator.userAgent+'</i></p>');
   for (var i = 0; i < this.problemsListField.length; i++)
   {
     resDoc.write('<p class="jsUnitDefault">');
     resDoc.write('<b>' + (i + 1) + '. ');
     resDoc.write(this.problemsListField[i].text);
     resDoc.write('<\/b><\/p><p><pre>');
     resDoc.write(this.problemsListField[i].value);
     resDoc.write('<\/pre><\/p>');
   }

   resDoc.write('<\/body><\/html>');
   resDoc.close();
}

jsUnitTestManager.prototype._clearProblemsList = function ()
{
  var listField = this.problemsListField;
  var initialLength=listField.options.length;

  for (var i = 0; i < initialLength; i++)
    listField.remove(0);
}

jsUnitTestManager.prototype.initialize = function ()
{
  this.setStatus('Initializing...');
  this._setRunButtonEnabled(false);
  this._clearProblemsList();
  this.updateProgressIndicators();
  this.setStatus('Done initializing');
}

jsUnitTestManager.prototype.finalize = function ()
{
  this._setRunButtonEnabled(true);
}

jsUnitTestManager.prototype._setRunButtonEnabled = function (b)
{
  this.runButton.disabled = !b;
}

jsUnitTestManager.prototype.getTestFileName = function () 
{
  var rawEnteredFileName = this.testFileName.value;
  var result             = rawEnteredFileName;

  while (result.indexOf('\\') != -1)
    result = result.replace('\\', '/');

  return result;
}

jsUnitTestManager.prototype.resolveUserEnteredTestFileName = function (rawText) 
{
  var userEnteredTestFileName = top.testManager.getTestFileName();
  
  // only test for file:// since Opera uses a different format
  if (userEnteredTestFileName.indexOf('http://') == 0 || userEnteredTestFileName.indexOf('https://') == 0 || userEnteredTestFileName.indexOf('file://') == 0)
    return userEnteredTestFileName;
    
  return getTestFileProtocol() + this.getTestFileName();
}

function getTestFileProtocol()
{
  return getDocumentProtocol();
}

function getDocumentProtocol() 
{
  var protocol = top.document.location.protocol;
    
  if (protocol == "file:") 
    return "file:///";

  if (protocol == "http:") 
    return "http://";
    
  if (protocol == 'https:') 
    return 'https://';    
    
  if (protocol == "chrome:") 
    return "chrome://";

  return null;
}

function isBeingRunOverHTTP() {
	return getDocumentProtocol()=="http://";
}   

function getWebserver() {
	if (isBeingRunOverHTTP()) {
		var myUrl = location.href;
		var myUrlWithProtocolStripped = myUrl.substring(myUrl.indexOf("/") + 2);
		return myUrlWithProtocolStripped.substring(0, myUrlWithProtocolStripped.indexOf("/"));
	}
	return null;
}

// the functions push(anArray, anObject) and pop(anArray) 
// exist because the JavaScript Array.push(anObject) and Array.pop() 
// functions are not available in IE 5.0

function push(anArray, anObject) 
{
  anArray[anArray.length]=anObject;
}

function pop(anArray) 
{
  if (anArray.length>=1) {
    delete anArray[anArray.length - 1];
    anArray.length--;
  }
}

if (xbDEBUG.on)
{
  xbDebugTraceObject('window', 'jsUnitTestManager');
  xbDebugTraceFunction('window', 'getTestFileProtocol');
  xbDebugTraceFunction('window', 'getDocumentProtocol');
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Systems / Hardware Administrator
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions