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
--- a/netwerk/streamconv/converters/ParseFTPList.cpp
+++ b/netwerk/streamconv/converters/ParseFTPList.cpp
@@ -1660,212 +1660,8 @@ int ParseFTPList(const char *line, struc
/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
} /* if (linelen > 0) */
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
--- a/netwerk/test/gtest/moz.build
+++ b/netwerk/test/gtest/moz.build
@@ -8,11 +8,15 @@ UNIFIED_SOURCES += [
'TestHeaders.cpp',
'TestHttpAuthUtils.cpp',
'TestMozURL.cpp',
'TestPartiallySeekableInputStream.cpp',
'TestProtocolProxyService.cpp',
'TestStandardURL.cpp',
]
+TEST_DIRS += [
+ 'parse-ftp',
+]
+
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul-gtest'
new file mode 100644
--- /dev/null
+++ b/netwerk/test/gtest/parse-ftp/TestParseFTPList.cpp
@@ -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);
+ }
+}
+
new file mode 100644
--- /dev/null
+++ b/netwerk/test/gtest/parse-ftp/moz.build
@@ -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'
--- a/testing/cppunittest.ini
+++ b/testing/cppunittest.ini
@@ -23,16 +23,17 @@ skip-if = os != 'win'
[TestIntegerPrintfMacros]
[TestIntegerRange]
[TestJSONWriter]
[TestLinkedList]
[TestMacroArgs]
[TestMacroForEach]
[TestMathAlgorithms]
[TestMaybe]
+[TestParseFTPList]
[TestPLDHash]
skip-if = os == 'b2g' #Bug 1038197
[TestPair]
[TestPoisonArea]
skip-if = os == 'android' # Bug 1147630
[TestRefPtr]
[TestRollingMean]
[TestScopeExit]