From d1e740d8b25e03a734093bd84b792eaf969649d1 Mon Sep 17 00:00:00 2001 From: jsmall-nvidia Date: Thu, 6 Oct 2022 10:27:50 -0400 Subject: Improvements around absolute paths and file systems (#2433) * #include an absolute path didn't work - because paths were taken to always be relative. * Add handling for root paths. * Fixes around absolute paths. * Add SimplifyStyle * Remove unrequire include. * Fix some details around RelativeFileSystem canonical paths. * For MemoryFileSystem make sure "/a" and "a" maps to same canonical path. * Add test for canonicalPath. * Improve comment. * More testing around canonical paths. --- tools/slang-unit-test/unit-test-file-system.cpp | 141 +++++++++++++++++++++++- 1 file changed, 137 insertions(+), 4 deletions(-) (limited to 'tools/slang-unit-test/unit-test-file-system.cpp') diff --git a/tools/slang-unit-test/unit-test-file-system.cpp b/tools/slang-unit-test/unit-test-file-system.cpp index 1575f4dfd..d7f613f65 100644 --- a/tools/slang-unit-test/unit-test-file-system.cpp +++ b/tools/slang-unit-test/unit-test-file-system.cpp @@ -69,6 +69,23 @@ static SlangResult _checkFile(ISlangFileSystemExt* fileSystem, const char* path, return SLANG_OK; } +static SlangResult _checkFile(ISlangMutableFileSystem* fileSystem, const char* path, const char* contents) +{ + return _checkFile(fileSystem, path, UnownedStringSlice(contents)); +} + +static SlangResult _checkDirectoryExists(ISlangFileSystemExt* fileSystem, const char* path) +{ + SlangPathType pathType; + SLANG_RETURN_ON_FAIL(fileSystem->getPathType(path, &pathType)); + + if (pathType != SLANG_PATH_TYPE_DIRECTORY) + { + return SLANG_FAIL; + } + return SLANG_OK; +} + static SlangResult _createAndCheckFile(ISlangMutableFileSystem* fileSystem, const char* path, const char* contents) { UnownedStringSlice contentsSlice(contents); @@ -95,6 +112,77 @@ static SlangResult _createAndCheckFile(ISlangMutableFileSystem* fileSystem, cons return SLANG_OK; } +static bool _areEqual(ISlangBlob* a, ISlangBlob* b) +{ + if (a == b) + { + return true; + } + if ((!a || !b) || (a->getBufferSize() != b->getBufferSize())) + { + return false; + } + + return ::memcmp(a->getBufferPointer(), b->getBufferPointer(), a->getBufferSize()) == 0; +} + +static SlangResult _checkCanonical(ISlangMutableFileSystem* fileSystem, const char*const* paths, Count count) +{ + if (count <= 0) + { + return SLANG_FAIL; + } + + // The path has to exist to something for canonicalization to be relied upon + SlangPathType pathType; + SLANG_RETURN_ON_FAIL(fileSystem->getPathType(paths[0], &pathType)); + + String canonicalPath; + { + ComPtr blob; + SLANG_RETURN_ON_FAIL(fileSystem->getPath(PathKind::Canonical, paths[0], blob.writeRef())); + canonicalPath = StringUtil::getString(blob); + } + + // The canonicalized path must point to the same thing + SlangPathType canonicalPathType; + SLANG_RETURN_ON_FAIL(fileSystem->getPathType(canonicalPath.getBuffer(), &canonicalPathType)); + + if (canonicalPathType != pathType) + { + return SLANG_FAIL; + } + + // If they are the file, being hte same file, they must hold the same data... + if (pathType == SLANG_PATH_TYPE_FILE) + { + ComPtr blob; + ComPtr canonicalPathBlob; + SLANG_RETURN_ON_FAIL(fileSystem->loadFile(paths[0], blob.writeRef())); + SLANG_RETURN_ON_FAIL(fileSystem->loadFile(canonicalPath.getBuffer(), canonicalPathBlob.writeRef())); + + if (!_areEqual(blob, canonicalPathBlob)) + { + return SLANG_FAIL; + } + } + + for (Index i = 1; i < count; ++i) + { + ComPtr blob; + SLANG_RETURN_ON_FAIL(fileSystem->getPath(PathKind::Canonical, paths[i], blob.writeRef())); + const auto checkPath = StringUtil::getString(blob); + + if (checkPath != canonicalPath) + { + return SLANG_FAIL; + } + } + + return SLANG_OK; +} + + static SlangResult _createAndCheckDirectory(ISlangMutableFileSystem* fileSystem, const char* path) { SLANG_RETURN_ON_FAIL(fileSystem->createDirectory(path)); @@ -309,12 +397,46 @@ static SlangResult _test(FileSystemType type) ComPtr fileSystem; SLANG_RETURN_ON_FAIL(_createFileSystem(type, fileSystem)); - SLANG_RETURN_ON_FAIL(_createAndCheckFile(fileSystem, "a", "someText")); - SLANG_RETURN_ON_FAIL(_createAndCheckFile(fileSystem, "b", "A longer bit of text....")); + const auto aText = "someText"; + const auto bText = "A longer bit of text...."; + const auto d_aText = "Some more silly stuff"; + const auto d_bText = "Lets go!"; + + SLANG_RETURN_ON_FAIL(_createAndCheckFile(fileSystem, "a", aText)); + SLANG_RETURN_ON_FAIL(_createAndCheckFile(fileSystem, "b", bText)); SLANG_RETURN_ON_FAIL(_createAndCheckDirectory(fileSystem, "d")); - SLANG_RETURN_ON_FAIL(_createAndCheckFile(fileSystem, "d/a", "Some more silly stuff")); - SLANG_RETURN_ON_FAIL(_createAndCheckFile(fileSystem, "d\\b", "Lets go empty")); + SLANG_RETURN_ON_FAIL(_createAndCheckFile(fileSystem, "d/a", d_aText)); + SLANG_RETURN_ON_FAIL(_createAndCheckFile(fileSystem, "d\\b", d_bText)); + + // Try and absolute path + SLANG_RETURN_ON_FAIL(_checkFile(fileSystem, "/a", aText)); + SLANG_RETURN_ON_FAIL(_checkFile(fileSystem, "/b", bText)); + SLANG_RETURN_ON_FAIL(_checkFile(fileSystem, "/d/a", d_aText)); + SLANG_RETURN_ON_FAIL(_checkFile(fileSystem, "/d\\b", d_bText)); + + + // Check canonical on files + { + const char* paths[] = { "a", "/a", "./a", "d/../a", ".\\d/.\\..\\a" }; + SLANG_RETURN_ON_FAIL(_checkCanonical(fileSystem, paths, SLANG_COUNT_OF(paths))); + } + + { + const char* paths[] = { "/d/b", "d/./b" }; + SLANG_RETURN_ON_FAIL(_checkCanonical(fileSystem, paths, SLANG_COUNT_OF(paths))); + } + + // Check canonical on directories + { + const char* paths[] = { ".", "/", "/d/..", "d/.." }; + SLANG_RETURN_ON_FAIL(_checkCanonical(fileSystem, paths, SLANG_COUNT_OF(paths))); + } + + { + const char* paths[] = { "d", "./d", "/d", "/d/./../d" }; + SLANG_RETURN_ON_FAIL(_checkCanonical(fileSystem, paths, SLANG_COUNT_OF(paths))); + } // Lets find all the files in the directory @@ -326,6 +448,17 @@ static SlangResult _test(FileSystemType type) { const Entry entries[] = { {SLANG_PATH_TYPE_FILE, "a" }, {SLANG_PATH_TYPE_FILE, "b" }, {SLANG_PATH_TYPE_DIRECTORY, "d" } }; SLANG_RETURN_ON_FAIL(_enumeratePath(fileSystem, ".", makeConstArrayView(entries))); + + // Let's check that / and \ works for the root directory + SLANG_RETURN_ON_FAIL(_enumeratePath(fileSystem, "/", makeConstArrayView(entries))); + SLANG_RETURN_ON_FAIL(_enumeratePath(fileSystem, "\\", makeConstArrayView(entries))); + } + + // Check the root directory exists + { + SLANG_RETURN_ON_FAIL(_checkDirectoryExists(fileSystem, ".")); + SLANG_RETURN_ON_FAIL(_checkDirectoryExists(fileSystem, "/")); + SLANG_RETURN_ON_FAIL(_checkDirectoryExists(fileSystem, "\\")); } { -- cgit v1.2.3