Bug 1402151, part 9 - Implement gtest for FTP directory listing parsing. r=michal

This test turns the existing stand alone test for the FTP directory
listing parser into a gtest.

MozReview-Commit-ID: 7n60TfcTXTJ

--HG--
extra : rebase_source : 79c88708a9bf9bee6c27a82f2c93a95016e063dd
This commit is contained in:
Andrew McCreight 2017-09-25 11:19:33 -07:00
parent c617e8ebd2
commit 95785a8675
5 changed files with 242 additions and 204 deletions

View File

@ -1665,207 +1665,3 @@ int ParseFTPList(const char *line, struct list_state *state,
return ParsingFailed(state);
}
/* ==================================================================== */
/* standalone testing */
/* ==================================================================== */
#if 0
#include <stdio.h>
static int do_it(FILE *outfile,
char *line, size_t linelen, struct list_state *state,
char **cmnt_buf, unsigned int *cmnt_buf_sz,
char **list_buf, unsigned int *list_buf_sz )
{
struct list_result result;
char *p;
int rc;
rc = ParseFTPList( line, state, &result );
if (!outfile)
{
outfile = stdout;
if (rc == '?')
fprintf(outfile, "junk: %.*s\n", (int)linelen, line );
else if (rc == '"')
fprintf(outfile, "cmnt: %.*s\n", (int)linelen, line );
else
fprintf(outfile,
"list: %02u-%02u-%02u %02u:%02u%cM %20s %.*s%s%.*s\n",
(result.fe_time.tm_mday ? (result.fe_time.tm_month + 1) : 0),
result.fe_time.tm_mday,
(result.fe_time.tm_mday ? (result.fe_time.tm_year % 100) : 0),
result.fe_time.tm_hour -
((result.fe_time.tm_hour > 12)?(12):(0)),
result.fe_time.tm_min,
((result.fe_time.tm_hour >= 12) ? 'P' : 'A'),
(rc == 'd' ? "<DIR> " :
(rc == 'l' ? "<JUNCTION> " : result.fe_size)),
(int)result.fe_fnlen, result.fe_fname,
((rc == 'l' && result.fe_lnlen) ? " -> " : ""),
(int)((rc == 'l' && result.fe_lnlen) ? result.fe_lnlen : 0),
((rc == 'l' && result.fe_lnlen) ? result.fe_lname : "") );
}
else if (rc != '?') /* NOT junk */
{
char **bufp = list_buf;
unsigned int *bufz = list_buf_sz;
if (rc == '"') /* comment - make it a 'result' */
{
memset( &result, 0, sizeof(result));
result.fe_fname = line;
result.fe_fnlen = linelen;
result.fe_type = 'f';
if (line[linelen-1] == '/')
{
result.fe_type = 'd';
result.fe_fnlen--;
}
bufp = cmnt_buf;
bufz = cmnt_buf_sz;
rc = result.fe_type;
}
linelen = 80 + result.fe_fnlen + result.fe_lnlen;
p = (char *)realloc( *bufp, *bufz + linelen );
if (!p)
return -1;
sprintf( &p[*bufz],
"%02u-%02u-%04u %02u:%02u:%02u %20s %.*s%s%.*s\n",
(result.fe_time.tm_mday ? (result.fe_time.tm_month + 1) : 0),
result.fe_time.tm_mday,
(result.fe_time.tm_mday ? (result.fe_time.tm_year + 1900) : 0),
result.fe_time.tm_hour,
result.fe_time.tm_min,
result.fe_time.tm_sec,
(rc == 'd' ? "<DIR> " :
(rc == 'l' ? "<JUNCTION> " : result.fe_size)),
(int)result.fe_fnlen, result.fe_fname,
((rc == 'l' && result.fe_lnlen) ? " -> " : ""),
(int)((rc == 'l' && result.fe_lnlen) ? result.fe_lnlen : 0),
((rc == 'l' && result.fe_lnlen) ? result.fe_lname : "") );
linelen = strlen(&p[*bufz]);
*bufp = p;
*bufz = *bufz + linelen;
}
return 0;
}
int main(int argc, char *argv[])
{
FILE *infile = (FILE *)0;
FILE *outfile = (FILE *)0;
int need_close_in = 0;
int need_close_out = 0;
if (argc > 1)
{
infile = stdin;
if (strcmp(argv[1], "-") == 0)
need_close_in = 0;
else if ((infile = fopen(argv[1], "r")) != ((FILE *)0))
need_close_in = 1;
else
fprintf(stderr, "Unable to open input file '%s'\n", argv[1]);
}
if (infile && argc > 2)
{
outfile = stdout;
if (strcmp(argv[2], "-") == 0)
need_close_out = 0;
else if ((outfile = fopen(argv[2], "w")) != ((FILE *)0))
need_close_out = 1;
else
{
fprintf(stderr, "Unable to open output file '%s'\n", argv[2]);
fclose(infile);
infile = (FILE *)0;
}
}
if (!infile)
{
char *appname = &(argv[0][strlen(argv[0])]);
while (appname > argv[0])
{
appname--;
if (*appname == '/' || *appname == '\\' || *appname == ':')
{
appname++;
break;
}
}
fprintf(stderr,
"Usage: %s <inputfilename> [<outputfilename>]\n"
"\nIf an outout file is specified the results will be"
"\nbe post-processed, and only the file entries will appear"
"\n(or all comments if there are no file entries)."
"\nNot specifying an output file causes %s to run in \"debug\""
"\nmode, ie results are printed as lines are parsed."
"\nIf a filename is a single dash ('-'), stdin/stdout is used."
"\n", appname, appname );
}
else
{
char *cmnt_buf = (char *)0;
unsigned int cmnt_buf_sz = 0;
char *list_buf = (char *)0;
unsigned int list_buf_sz = 0;
struct list_state state;
char line[512];
memset( &state, 0, sizeof(state) );
while (fgets(line, sizeof(line), infile))
{
size_t linelen = strlen(line);
if (linelen < (sizeof(line)-1))
{
if (linelen > 0 && line[linelen-1] == '\n')
linelen--;
if (do_it( outfile, line, linelen, &state,
&cmnt_buf, &cmnt_buf_sz, &list_buf, &list_buf_sz) != 0)
{
fprintf(stderr, "Insufficient memory. Listing may be incomplete.\n");
break;
}
}
else
{
/* no '\n' found. drop this and everything up to the next '\n' */
fprintf(stderr, "drop: %.*s", (int)linelen, line );
while (linelen == sizeof(line))
{
if (!fgets(line, sizeof(line), infile))
break;
linelen = 0;
while (linelen < sizeof(line) && line[linelen] != '\n')
linelen++;
fprintf(stderr, "%.*s", (int)linelen, line );
}
fprintf(stderr, "\n");
}
}
if (outfile)
{
if (list_buf)
fwrite( list_buf, 1, list_buf_sz, outfile );
else if (cmnt_buf)
fwrite( cmnt_buf, 1, cmnt_buf_sz, outfile );
}
if (list_buf)
free(list_buf);
if (cmnt_buf)
free(cmnt_buf);
if (need_close_in)
fclose(infile);
if (outfile && need_close_out)
fclose(outfile);
}
return 0;
}
#endif

View File

@ -13,6 +13,10 @@ UNIFIED_SOURCES += [
'TestStandardURL.cpp',
]
TEST_DIRS += [
'parse-ftp',
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul-gtest'

View File

@ -0,0 +1,169 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "gtest/gtest.h"
#include "mozilla/ArrayUtils.h"
#include "nsPrintfCString.h"
#include <stdio.h>
#include "ParseFTPList.h"
PRTime gTestTime = 0;
// Pretend this is the current time for the purpose of running the
// test. The day and year matter because they are used to figure out a
// default value when no year is specified. Tests will fail if this is
// changed too much.
const char* kDefaultTestTime = "01-Aug-2002 00:00:00 GMT";
static PRTime
TestTime()
{
return gTestTime;
}
static void
ParseFTPLine(char* inputLine,
FILE* resultFile,
list_state* state)
{
struct list_result result;
int rc = ParseFTPList(inputLine, state, &result, PR_GMTParameters, TestTime);
if (rc == '?' || rc == '"') {
// Ignore junk and comments.
return;
}
if (!resultFile) {
// No result file was passed in, so there's nothing to check.
return;
}
char resultLine[512];
ASSERT_NE(fgets(resultLine, sizeof(resultLine), resultFile), nullptr);
nsPrintfCString parsed("%02u-%02u-%04u %02u:%02u:%02u %20s %.*s%s%.*s\n",
(result.fe_time.tm_mday ? (result.fe_time.tm_month + 1) : 0),
result.fe_time.tm_mday,
(result.fe_time.tm_mday ? result.fe_time.tm_year : 0),
result.fe_time.tm_hour,
result.fe_time.tm_min,
result.fe_time.tm_sec,
(rc == 'd' ? "<DIR> " :
(rc == 'l' ? "<JUNCTION> " : result.fe_size)),
(int)result.fe_fnlen, result.fe_fname,
((rc == 'l' && result.fe_lnlen) ? " -> " : ""),
(int)((rc == 'l' && result.fe_lnlen) ? result.fe_lnlen : 0),
((rc == 'l' && result.fe_lnlen) ? result.fe_lname : ""));
ASSERT_STREQ(parsed.get(), resultLine);
}
FILE*
OpenResultFile(const char* resultFileName)
{
if (!resultFileName) {
return nullptr;
}
FILE* resultFile = fopen(resultFileName, "r");
EXPECT_NE(resultFile, nullptr);
// Ignore anything in the expected result file before and including the first blank line.
char resultLine[512];
while (fgets(resultLine, sizeof(resultLine), resultFile)) {
size_t lineLen = strlen(resultLine);
EXPECT_LT(lineLen, sizeof(resultLine) - 1);
if (lineLen > 0 && resultLine[lineLen - 1] == '\n') {
lineLen--;
}
if (lineLen == 0) {
break;
}
}
// There must be a blank line somewhere in the result file.
EXPECT_EQ(strcmp(resultLine, "\n"), 0);
return resultFile;
}
void
ParseFTPFile(const char* inputFileName,
const char* resultFileName)
{
printf("Checking %s\n", inputFileName);
FILE* inFile = fopen(inputFileName, "r");
ASSERT_NE(inFile, nullptr);
FILE* resultFile = OpenResultFile(resultFileName);
char inputLine[512];
struct list_state state;
memset(&state, 0, sizeof(state));
while (fgets(inputLine, sizeof(inputLine), inFile)) {
size_t lineLen = strlen(inputLine);
EXPECT_LT(lineLen, sizeof(inputLine) - 1);
if (lineLen > 0 && inputLine[lineLen - 1] == '\n') {
lineLen--;
}
ParseFTPLine(inputLine, resultFile, &state);
}
// Make sure there are no extra lines in the result file.
if (resultFile) {
char resultLine[512];
EXPECT_EQ(fgets(resultLine, sizeof(resultLine), resultFile), nullptr) <<
"There should not be more lines in the expected results file than in the parser output.";
fclose(resultFile);
}
fclose(inFile);
}
static const char* testFiles[] = {
"3-guess",
"C-VMold",
"C-zVM",
"D-WinNT",
"E-EPLF",
"O-guess",
"R-dls",
"U-HellSoft",
"U-hethmon",
"U-murksw",
"U-ncFTPd",
"U-NetPresenz",
"U-NetWare",
"U-nogid",
"U-no_ug",
"U-Novonyx",
"U-proftpd",
"U-Surge",
"U-WarFTPd",
"U-WebStar",
"U-WinNT",
"U-wu",
"V-MultiNet",
"V-VMS-mix",
};
TEST(ParseFTPTest, Check)
{
PRStatus result = PR_ParseTimeString(kDefaultTestTime, true, &gTestTime);
ASSERT_EQ(PR_SUCCESS, result);
char inputFileName[200];
char resultFileName[200];
for (size_t test = 0; test < mozilla::ArrayLength(testFiles); ++test) {
snprintf(inputFileName, mozilla::ArrayLength(inputFileName), "%s.in", testFiles[test]);
snprintf(resultFileName, mozilla::ArrayLength(inputFileName), "%s.out", testFiles[test]);
ParseFTPFile(inputFileName, resultFileName);
}
}

View File

@ -0,0 +1,68 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
UNIFIED_SOURCES += [
'TestParseFTPList.cpp',
]
TEST_HARNESS_FILES.gtest += [
'3-guess.in',
'3-guess.out',
'C-VMold.in',
'C-VMold.out',
'C-zVM.in',
'C-zVM.out',
'D-WinNT.in',
'D-WinNT.out',
'E-EPLF.in',
'E-EPLF.out',
'O-guess.in',
'O-guess.out',
'R-dls.in',
'R-dls.out',
'U-HellSoft.in',
'U-HellSoft.out',
'U-hethmon.in',
'U-hethmon.out',
'U-murksw.in',
'U-murksw.out',
'U-ncFTPd.in',
'U-ncFTPd.out',
'U-NetPresenz.in',
'U-NetPresenz.out',
'U-NetWare.in',
'U-NetWare.out',
'U-no_ug.in',
'U-no_ug.out',
'U-nogid.in',
'U-nogid.out',
'U-Novonyx.in',
'U-Novonyx.out',
'U-proftpd.in',
'U-proftpd.out',
'U-Surge.in',
'U-Surge.out',
'U-WarFTPd.in',
'U-WarFTPd.out',
'U-WebStar.in',
'U-WebStar.out',
'U-WinNT.in',
'U-WinNT.out',
'U-wu.in',
'U-wu.out',
'V-MultiNet.in',
'V-MultiNet.out',
'V-VMS-mix.in',
'V-VMS-mix.out',
]
include('/ipc/chromium/chromium-config.mozbuild')
LOCAL_INCLUDES += [
'/netwerk/streamconv/converters',
]
FINAL_LIBRARY = 'xul-gtest'

View File

@ -28,6 +28,7 @@ skip-if = os != 'win'
[TestMacroForEach]
[TestMathAlgorithms]
[TestMaybe]
[TestParseFTPList]
[TestPLDHash]
skip-if = os == 'b2g' #Bug 1038197
[TestPair]