/*! * regTestWritePixAndCheck() * * Input: pix (to be written) * format (of output pix) * &count (index to be written into filename) * rp (regression test params; required here) * Return: 0 if OK, 1 on error (a failure in comparison is not an error) * * Notes: * (1) This function makes it easy to write the pix in a numbered * sequence of files, and either write the golden files (with * the "generate" argument to the regression test) or compare * the written file with an existing golden file. * (2) This function can be called repeatedly in a single reg test. * Each time it is called, the count is incremented. * (3) The canonical format of the local filename is: * /tmp/<root of main name>.<count>.<format extension string> * e.g., for scale_reg, * /tmp/scale.0.png */ l_int32 regTestWritePixAndCheck(PIX *pix, l_int32 format, l_int32 *pcount, L_REGPARAMS *rp) { char *root; char namebuf[256]; PROCNAME("regTestWritePixAndCheck"); if (!pix) return ERROR_INT("pix not defined", procName, 1); if (!pcount) return ERROR_INT("&count not defined", procName, 1); if (format < 0 || format >= NumImageFileFormatExtensions) return ERROR_INT("invalid format", procName, 1); if (!rp) return ERROR_INT("rp not defined", procName, 1); /* Generate the local file name */ if ((root = getRootNameFromArgv0(rp->argv[0])) == NULL) return ERROR_INT("invalid root", procName, 1); snprintf(namebuf, sizeof(namebuf), "/tmp/%s.%d.%s", root, *pcount, ImageFileFormatExtensions[format]); FREE(root); /* Write the local file. Then, either write the golden file * or check the local file against an existing golden file. */ pixWrite(namebuf, pix, format); regTestCheckFile(rp->fp, rp->argv, namebuf, (*pcount)++, &rp->success); return 0; }
/*! * regTestCheckFile() * * Input: stream (for output; use NULL to generate golden files) * argv ([0] == name of reg test) * localname (name of output file from reg test) * index (of the output file under test; 0-based for the reg test) * &success (<return> 0 on failure; input value on success) * Return: 0 if OK, 1 on error (a failure in comparison is not an error) * * Notes: * (1) This function either compares an input file with a "golden" file, * or generates a "golden" file as a copy @localname. * Call with @fp == NULL to generate a new golden file. * (2) This function can be called repeatedly in a single reg test. * (3) The value for @success is initialized to TRUE in the reg test * setup before this function is called for the first time. * A failure in any single file comparison is registered * as a failure of the regression test. * (4) The canonical format of the golden filenames is: * /tmp/<root of main name>_golden.<index>.<ext of localname> * e.g., * /tmp/maze_golden.0.png */ l_int32 regTestCheckFile(FILE *fp, char **argv, const char *localname, l_int32 index, l_int32 *psuccess) { char *root, *ext; char namebuf[64]; l_int32 ret, same; PROCNAME("regTestCheckFile"); if (!psuccess) return ERROR_INT("&success not defined", procName, 1); if (!localname) return ERROR_INT("local name not defined", procName, 1); if (index < 0) return ERROR_INT("index is negative", procName, 1); /* Generate the golden file name */ if ((root = getRootNameFromArgv0(argv[0])) == NULL) return ERROR_INT("invalid root", procName, 1); splitPathAtExtension(localname, NULL, &ext); snprintf(namebuf, sizeof(namebuf), "/tmp/%s_golden.%d%s", root, index, ext); FREE(root); FREE(ext); /* Save the file as a golden file */ if (!fp) { ret = fileCopy(localname, namebuf); if (!ret) fprintf(stderr, "Copy: %s to %s\n", localname, namebuf); return ret; } /* Test and record on failure */ filesAreIdentical(localname, namebuf, &same); if (!same) { fprintf(fp, "Failure in %s: comparing %s with %s\n", argv[0], localname, namebuf); fprintf(stderr, "Failure in %s: comparing %s with %s\n", argv[0], localname, namebuf); *psuccess = 0; } return 0; }
/*! * regTestSetup() * * Input: argc (from invocation; can be either 1 or 2) * argv (to regtest: @argv[1] is one of these: * "generate", "compare", "display") * &rp (<return> all regression params) * Return: 0 if OK, 1 on error * * Notes: * (1) Call this function with the args to the reg test. * There are three cases: * Case 1: * There is either only one arg, or the second arg is "compare". * This is the mode in which you run a regression test * (or a set of them), looking for failures and logging * the results to a file. The output, which includes * logging of all reg test failures plus a SUCCESS or * FAILURE summary for each test, is appended to the file * "/tmp/reg_results.txt. For this case, as in Case 2, * the display field in rp is set to FALSE, preventing * image display. * Case 2: * The second arg is "generate". This will cause * generation of new golden files for the reg test. * The results of the reg test are not recorded, and * the display field in rp is set to FALSE. * Case 3: * The second arg is "display". The test will run and * files will be written. Comparisons with golden files * will not be carried out, so the only notion of success * or failure is with tests that do not involve golden files. * The display field in rp is TRUE, and this is used by * pixDisplayWithTitle(). * (2) See regutils.h for examples of usage. */ l_int32 regTestSetup(l_int32 argc, char **argv, L_REGPARAMS **prp) { char *testname, *vers; char errormsg[64]; L_REGPARAMS *rp; PROCNAME("regTestSetup"); if (argc != 1 && argc != 2) { snprintf(errormsg, sizeof(errormsg), "Syntax: %s [ [generate] | compare | display ]", argv[0]); return ERROR_INT(errormsg, procName, 1); } if ((testname = getRootNameFromArgv0(argv[0])) == NULL) return ERROR_INT("invalid root", procName, 1); if ((rp = (L_REGPARAMS *) CALLOC(1, sizeof(L_REGPARAMS))) == NULL) return ERROR_INT("rp not made", procName, 1); *prp = rp; rp->testname = testname; rp->index = -1; /* increment before each test */ /* Initialize to true. A failure in any test is registered * as a failure of the regression test. */ rp->success = TRUE; /* Make sure the regout subdirectory exists */ lept_mkdir("regout"); /* Only open a stream to a temp file for the 'compare' case */ if (argc == 1 || !strcmp(argv[1], "compare")) { rp->mode = L_REG_COMPARE; rp->tempfile = genPathname("/tmp/regout", "regtest_output.txt"); rp->fp = fopenWriteStream(rp->tempfile, "wb"); if (rp->fp == NULL) { rp->success = FALSE; return ERROR_INT("stream not opened for tempfile", procName, 1); } } else if (!strcmp(argv[1], "generate")) { rp->mode = L_REG_GENERATE; lept_mkdir("golden"); } else if (!strcmp(argv[1], "display")) { rp->mode = L_REG_DISPLAY; rp->display = TRUE; } else { FREE(rp); snprintf(errormsg, sizeof(errormsg), "Syntax: %s [ [generate] | compare | display ]", argv[0]); return ERROR_INT(errormsg, procName, 1); } /* Print out test name and both the leptonica and * image libarary versions */ fprintf(stderr, "\n################ %s_reg ###############\n", rp->testname); vers = getLeptonicaVersion(); fprintf(stderr, "%s\n", vers); FREE(vers); vers = getImagelibVersions(); fprintf(stderr, "%s\n", vers); FREE(vers); rp->tstart = startTimerNested(); return 0; }
/*! * regTestCompareFiles() * * Input: stream (for output; use NULL to generate golden files) * argv ([0] == name of reg test) * index1 (of one output file from reg test) * index2 (of another output file from reg test) * &success (<return> 0 on if different; input value on success) * Return: 0 if OK, 1 on error (a failure in comparison is not an error) * * Notes: * (1) If @fp != NULL, this function compares two golden files to * determine if they are the same. If @fp == NULL, this is a * "generate" operation; don't do the comparison. * (2) This function can be called repeatedly in a single reg test. * (3) The value for @success is initialized to TRUE in the reg test * setup before this function is called for the first time. * A failure in any file comparison is registered as a failure * of the regression test. * (4) The canonical format of the golden filenames is: * /tmp/<root of main name>_golden.<index>.<ext of localname> * e.g., * /tmp/maze_golden.0.png */ l_int32 regTestCompareFiles(FILE *fp, char **argv, l_int32 index1, l_int32 index2, l_int32 *psuccess) { char *root, *name1, *name2; char namebuf[64]; l_int32 error,same; SARRAY *sa; PROCNAME("regTestCompareFiles"); if (!psuccess) return ERROR_INT("&success not defined", procName, 1); if (index1 < 0 || index2 < 0) return ERROR_INT("index1 and/or index2 is negative", procName, 1); if (index1 == index2) return ERROR_INT("index1 must differ from index2", procName, 1); if (!fp) /* no-op */ return 0; /* Generate partial golden file names and find the actual * paths to them. */ error = FALSE; name1 = name2 = NULL; if ((root = getRootNameFromArgv0(argv[0])) == NULL) return ERROR_INT("invalid root", procName, 1); snprintf(namebuf, sizeof(namebuf), "%s_golden.%d.", root, index1); sa = getSortedPathnamesInDirectory("/tmp", namebuf, 0, 0); if (sarrayGetCount(sa) != 1) error = TRUE; else name1 = sarrayGetString(sa, 0, L_COPY); sarrayDestroy(&sa); snprintf(namebuf, sizeof(namebuf), "%s_golden.%d.", root, index2); sa = getSortedPathnamesInDirectory("/tmp", namebuf, 0, 0); if (sarrayGetCount(sa) != 1) error = TRUE; else name2 = sarrayGetString(sa, 0, L_COPY); sarrayDestroy(&sa); FREE(root); if (error == TRUE) { if (name1) FREE(name1); if (name2) FREE(name2); L_ERROR("golden files not found", procName); return 1; } /* Test and record on failure */ filesAreIdentical(name1, name2, &same); if (!same) { fprintf(fp, "Failure in %s: comparing %s with %s\n", argv[0], name1, name2); fprintf(stderr, "Failure in %s: comparing %s with %s\n", argv[0], name1, name2); *psuccess = 0; } FREE(name1); FREE(name2); return 0; }