--- a/js/src/jsapi-tests/testBinASTReader.cpp
+++ b/js/src/jsapi-tests/testBinASTReader.cpp
@@ -5,16 +5,18 @@
* 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/. */
#if defined(XP_UNIX)
#include <dirent.h>
#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
#elif defined(XP_WIN)
#include <windows.h>
#endif
#include "jsapi.h"
@@ -46,111 +48,142 @@ readFull(JSContext* cx, const char* path
js::Vector<uint8_t> intermediate(cx);
readFull(path, intermediate);
if (!buf.appendAll(intermediate))
MOZ_CRASH("Couldn't read data");
}
-BEGIN_TEST(testBinASTReaderECMAScript2)
+// Invariant: `path` must end with directory separator.
+void
+runTestFromPath(JSContext* cx, const char* path)
{
const char BIN_SUFFIX[] = ".binjs";
const char TXT_SUFFIX[] = ".js";
-
- CompileOptions options(cx);
- options.setIntroductionType("unit test parse")
- .setFileAndLine("<string>", 1);
+ fprintf(stderr, "runTestFromPath: entering directory '%s'\n", path);
+ const size_t pathlen = strlen(path);
#if defined(XP_UNIX)
- const char PATH[] = "jsapi-tests/binast/parser/tester/";
-
// Read the list of files in the directory.
enterJsDirectory();
- DIR* dir = opendir(PATH);
+ DIR* dir = opendir(path);
exitJsDirectory();
if (!dir)
MOZ_CRASH("Couldn't open directory");
while (auto entry = readdir(dir)) {
- // Find files whose name ends with ".binjs".
const char* d_name = entry->d_name;
+ const bool isDirectory = entry->d_type == DT_DIR;
+
#elif defined(XP_WIN)
- const char PATTERN[] = "jsapi-tests\\binast\\parser\\tester\\*.binjs";
- const char PATH[] = "jsapi-tests\\binast\\parser\\tester\\";
+ const char PATTERN[] = "*";
WIN32_FIND_DATA FindFileData;
enterJsDirectory();
HANDLE hFind = FindFirstFile(PATTERN, &FindFileData);
exitJsDirectory();
for (bool found = (hFind != INVALID_HANDLE_VALUE);
found;
found = FindNextFile(hFind, &FindFileData))
{
const char* d_name = FindFileData.cFileName;
+ const bool isDirectory = FindFileData.dwFileAttributes | FILE_ATTRIBUTE_DIRECTORY);
#endif // defined(XP_UNIX) || defined(XP_WIN)
const size_t namlen = strlen(d_name);
+
+ // Recurse through subdirectories.
+ if (isDirectory) {
+ if (strcmp(d_name, ".") == 0) {
+ continue;
+ }
+ if (strcmp(d_name, "..") == 0) {
+ continue;
+ }
+ UniqueChars subPath(static_cast<char*>(js_malloc(pathlen + /* separator */ 1 + namlen + /* NUL */1)));
+ strncpy(subPath.get(), path, pathlen); // Assuming that `path` ends with a directory separator.
+ strncpy(subPath.get() + pathlen, d_name, namlen);
+ subPath.get()[pathlen + namlen] = path[pathlen - 1]; // Directory separator.
+ subPath.get()[pathlen + namlen + 1 ] = '\0';
+ runTestFromPath(cx, subPath.get());
+ continue;
+ }
+
+ {
+ JS::PrepareForFullGC(cx);
+ cx->runtime()->gc.gc(GC_NORMAL, JS::gcreason::NO_REASON);
+ }
+ LifoAllocScope allocScope(&cx->tempLifoAlloc());
+
+ // Find files whose name ends with ".binjs".
+ fprintf(stderr, "Considering %s\n", d_name);
if (namlen < sizeof(BIN_SUFFIX))
continue;
if (strncmp(d_name + namlen - (sizeof(BIN_SUFFIX) - 1), BIN_SUFFIX, sizeof(BIN_SUFFIX)) != 0)
continue;
// Find text file.
- UniqueChars txtPath(static_cast<char*>(js_malloc(namlen + sizeof(PATH) + 1)));
- strncpy(txtPath.get(), PATH, sizeof(PATH));
- strncpy(txtPath.get() + sizeof(PATH) - 1, d_name, namlen);
- strncpy(txtPath.get() + sizeof(PATH) + namlen - sizeof(BIN_SUFFIX), TXT_SUFFIX, sizeof(TXT_SUFFIX));
- txtPath[sizeof(PATH) + namlen - sizeof(BIN_SUFFIX) + sizeof(TXT_SUFFIX) - 1] = 0;
+ UniqueChars txtPath(static_cast<char*>(js_malloc(namlen + pathlen + 1)));
+ strncpy(txtPath.get(), path, pathlen);
+ strncpy(txtPath.get() + pathlen, d_name, namlen);
+ strncpy(txtPath.get() + pathlen + namlen + 1 - sizeof(BIN_SUFFIX), TXT_SUFFIX, sizeof(TXT_SUFFIX));
+ txtPath[pathlen + namlen - sizeof(BIN_SUFFIX) + sizeof(TXT_SUFFIX)] = 0;
fprintf(stderr, "Testing %s\n", txtPath.get());
// Read text file.
js::Vector<char16_t> txtSource(cx);
readFull(cx, txtPath.get(), txtSource);
// Parse text file.
+ CompileOptions txtOptions(cx);
+ txtOptions.setIntroductionType(txtPath.get());
+
UsedNameTracker txtUsedNames(cx);
if (!txtUsedNames.init())
MOZ_CRASH("Couldn't initialize used names");
- js::frontend::Parser<js::frontend::FullParseHandler, char16_t> parser(cx, cx->tempLifoAlloc(), options, txtSource.begin(), txtSource.length(),
+ js::frontend::Parser<js::frontend::FullParseHandler, char16_t> txtParser(cx, allocScope.alloc(), txtOptions, txtSource.begin(), txtSource.length(),
/* foldConstants = */ false, txtUsedNames, nullptr,
nullptr);
- if (!parser.checkOptions())
+ if (!txtParser.checkOptions())
MOZ_CRASH("Bad options");
- auto txtParsed = parser.parse(); // Will be deallocated once `parser` goes out of scope.
+ auto txtParsed = txtParser.parse(); // Will be deallocated once `parser` goes out of scope.
RootedValue txtExn(cx);
if (!txtParsed) {
// Save exception for more detailed error message, if necessary.
if (!js::GetAndClearException(cx, &txtExn))
MOZ_CRASH("Couldn't clear exception");
}
// Read binary file.
- UniqueChars binPath(static_cast<char*>(js_malloc(namlen + sizeof(PATH) + 1)));
- strncpy(binPath.get(), PATH, sizeof(PATH));
- strncpy(binPath.get() + sizeof(PATH) - 1, d_name, namlen);
- binPath[namlen + sizeof(PATH) - 1] = 0;
+ UniqueChars binPath(static_cast<char*>(js_malloc(namlen + pathlen + 1)));
+ strncpy(binPath.get(), path, pathlen);
+ strncpy(binPath.get() + pathlen, d_name, namlen);
+ binPath[namlen + pathlen] = 0;
js::Vector<uint8_t> binSource(cx);
readFull(binPath.get(), binSource);
// Parse binary file.
+ CompileOptions binOptions(cx);
+ binOptions.setIntroductionType(txtPath.get());
+
js::frontend::UsedNameTracker binUsedNames(cx);
if (!binUsedNames.init())
MOZ_CRASH("Couldn't initialized binUsedNames");
- js::frontend::BinASTParser reader(cx, cx->tempLifoAlloc(), binUsedNames, options);
+ js::frontend::BinASTParser binParser(cx, allocScope.alloc(), binUsedNames, binOptions);
- auto binParsed = reader.parse(binSource); // Will be deallocated once `reader` goes out of scope.
+ auto binParsed = binParser.parse(binSource); // Will be deallocated once `reader` goes out of scope.
RootedValue binExn(cx);
if (binParsed.isErr()) {
// Save exception for more detailed error message, if necessary.
if (!js::GetAndClearException(cx, &binExn))
MOZ_CRASH("Couldn't clear binExn");
}
// The binary parser should accept the file iff the text parser has.
@@ -189,28 +222,57 @@ BEGIN_TEST(testBinASTReaderECMAScript2)
DumpParseTree(binParsed.unwrap(), binPrinter);
Sprinter txtPrinter(cx);
if (!txtPrinter.init())
MOZ_CRASH("Couldn't display txtParsed");
DumpParseTree(txtParsed, txtPrinter);
if (strcmp(binPrinter.string(), txtPrinter.string()) != 0) {
- fprintf(stderr, "Got distinct ASTs when parsing %s:\n\tBINARY\n%s\n\n\tTEXT\n%s\n", txtPath.get(), binPrinter.string(), txtPrinter.string());
+ fprintf(stderr, "Got distinct ASTs when parsing %s (%lu/%lu):\n\tBINARY\n%s\n\n\tTEXT\n%s\n",
+ txtPath.get(),
+ binPrinter.getOffset(), txtPrinter.getOffset(),
+ binPrinter.string(), txtPrinter.string());
+#if 0 // Not for release
+ auto fd = open("/tmp/bin.ast", O_CREAT | O_TRUNC | O_WRONLY, 0666);
+ if (!fd)
+ MOZ_CRASH("Could not open bin.ast");
+ auto result = write(fd, binPrinter.string(), binPrinter.stringEnd() - binPrinter.string());
+ if (result <= 0)
+ MOZ_CRASH("Could not write to bin.ast");
+ result = close(fd);
+ if (result != 0)
+ MOZ_CRASH("Could not close bin.ast");
+
+ fd = open("/tmp/txt.ast", O_CREAT | O_TRUNC | O_WRONLY, 0666);
+ if (!fd)
+ MOZ_CRASH("Could not open txt.ast");
+ result = write(fd, txtPrinter.string(), txtPrinter.stringEnd() - txtPrinter.string());
+ if (result <= 0)
+ MOZ_CRASH("Could not write to txt.ast");
+ result = close(fd);
+ if (result != 0)
+ MOZ_CRASH("Could not close txt.ast");
+#endif // 0
MOZ_CRASH("Got distinct ASTs");
}
- fprintf(stderr, "Got the same AST when parsing %s\n", txtPath.get());
+ fprintf(stderr, "Got the same AST when parsing %s\n%s\n", txtPath.get(), binPrinter.string());
#endif // defined(DEBUG)
}
#if defined(XP_WIN)
if (!FindClose(hFind))
MOZ_CRASH("Could not close Find");
#elif defined(XP_UNIX)
if (closedir(dir) != 0)
MOZ_CRASH("Could not close dir");
#endif // defined(XP_WIN)
+}
+
+BEGIN_TEST(testBinASTReaderECMAScript2)
+{
+ runTestFromPath(cx, "jsapi-tests/binast/parser/tester/");
return true;
}
END_TEST(testBinASTReaderECMAScript2)