void VFSNodeUnit::_writeKnownDirectoryTestFile(VFSNode::KnownDirectoryIdentifier id, const VString& fileName) {
    VFSNode folder = VFSNode::getKnownDirectoryNode(id, "BombayDigital", "unittest-temp");

    VFSNode fileNode;
    folder.getChildNode(fileName, fileNode);

    VBufferedFileStream fs(fileNode);
    fs.openWrite();

    VTextIOStream out(fs);

    VInstant now;
    out.writeLine(now.getLocalString());
    out.flush();

    this->logStatus(VSTRING_FORMAT("Wrote to file '%s'.", fileNode.getPath().chars()));
}
// static
VFSNode VFSNode::_platform_getKnownDirectoryNode(KnownDirectoryIdentifier id, const VString& companyName, const VString& appName) {
    if (id == CURRENT_WORKING_DIRECTORY) {
        return VFSNode(VPlatformAPI::getcwd());
    }

    if (id == EXECUTABLE_DIRECTORY) {
        /*
        This depends on the structure of the application or tool.
        If it's an iOS application, it's a bundle where we have:
            /...../wanted-dir/AppName.app/executable
            (2 levels up, wanted-dir is a randomized serial number at some path)
        If it's built as a Mac OS X application bundle we have:
            /...../wanted-dir/AppName.app/Contents/MacOS/executable
            (4 levels up, typically wanted-dir is /Applications if installed, but doesn't have to be)
        If it's built as a simple Unix-y tool we have:
            /...../wanted-dir/executable
            (1 level up, wanted-dir is wherever the tool has been placed)
        */
#ifdef VPLATFORM_MAC_IOS
        const int NUM_LEVELS_UP = 2;
#else
#ifdef VAULT_MACOSX_APP_IS_BUNDLE
        const int NUM_LEVELS_UP = 4;
#else
        const int NUM_LEVELS_UP = 1;
#endif
#endif
        VFSNode node = VFSNode::getExecutable();
        for (int i = 0; i < NUM_LEVELS_UP; ++i) {
            VFSNode parentNode;
            node.getParentNode(parentNode);
            node = parentNode;
        }

        return node;
    }

    VFSNode currentUserFolder(_V_NSHomeDirectory());

    if (id == USER_HOME_DIRECTORY) {
        return currentUserFolder;
    }

    VFSNode libraryFolder;
    currentUserFolder.getChildNode("Library", libraryFolder);
    libraryFolder.mkdir();

    VFSNode subFolder;

    switch (id) {
        case USER_HOME_DIRECTORY:
            // handled earlier; we returned above
            break;

        case LOG_FILES_DIRECTORY:
            libraryFolder.getChildNode("Logs", subFolder);
            break;

        case USER_PREFERENCES_DIRECTORY:
            libraryFolder.getChildNode("Preferences", subFolder);
            break;

        case CACHED_DATA_DIRECTORY:
            libraryFolder.getChildNode("Caches", subFolder);
            break;

        case APPLICATION_DATA_DIRECTORY:
            subFolder = libraryFolder;
            break;

        case CURRENT_WORKING_DIRECTORY:
            // handled earlier; we returned above
            break;

        case EXECUTABLE_DIRECTORY:
            // handled earlier; we returned above
            break;

        default:
            throw VStackTraceException(VSTRING_FORMAT("VFSNode::_platform_getKnownDirectoryNode: Requested invalid directory ID %d.", (int) id));
            break;
    }

    subFolder.mkdir();

    VFSNode companyFolder;
    if (companyName.isEmpty()) {
        companyFolder = subFolder;
    } else {
        subFolder.getChildNode(companyName, companyFolder);
        companyFolder.mkdir();
    }

    VFSNode resultNode;
    if (appName.isEmpty()) {
        resultNode = companyFolder;
    } else {
        companyFolder.getChildNode(appName, resultNode);
        resultNode.mkdir();
    }

    return resultNode;
}
// static
VFSNode VFSNode::_platform_getKnownDirectoryNode(KnownDirectoryIdentifier id, const VString& companyName, const VString& appName) {
    if (id == CURRENT_WORKING_DIRECTORY) {
        return VFSNode(VSystemAPI::getcwd());
    }

    if (id == EXECUTABLE_DIRECTORY) {
        VFSNode executable = VFSNode::getExecutable();
        VFSNode executableDirectory;
        executable.getParentNode(executableDirectory);
        return executableDirectory;
    }

    struct passwd* pwInfo = ::getpwuid(::getuid()); // Get info about the current user.
    if (pwInfo == NULL) {
        throw VStackTraceException(
            // Oddity: errno 0 can occur and means "no such user".
            (errno == 0 ? VSystemError(0, "No such user") : VSystemError()),
            "VFSNode::_platform_getKnownDirectoryNode failed to get current user info from getpwuid()."
        );
    }

    const VString homePath(pwInfo->pw_dir);

    if (id == USER_HOME_DIRECTORY) {
        return VFSNode(homePath);
    }

    VString basePath;
    VString companyFolderName(companyName);

    switch (id) {
        case USER_HOME_DIRECTORY:
            // handled earlier; we returned above
            break;

        case LOG_FILES_DIRECTORY:
            basePath = homePath + "/log";
            break;

        case USER_PREFERENCES_DIRECTORY:
            basePath = homePath;
            if (companyName.isNotEmpty()) {
                companyFolderName.format(".%s", companyName.chars());
            }
            break;

        case CACHED_DATA_DIRECTORY:
            basePath = homePath + "/cache";
            break;

        case APPLICATION_DATA_DIRECTORY:
            basePath = homePath + "/data";
            break;

        case CURRENT_WORKING_DIRECTORY:
            // handled earlier; we returned above
            break;

        case EXECUTABLE_DIRECTORY:
            // handled earlier; we returned above
            break;

        default:
            throw VStackTraceException(VSTRING_FORMAT("VFSNode::_platform_getKnownDirectoryNode: Requested invalid directory ID %d.", (int) id));
            break;
    }

    VFSNode baseDir(basePath);
    baseDir.mkdir();

    VFSNode companyFolder;
    if (companyFolderName.isEmpty()) {
        companyFolder = baseDir;
    } else {
        baseDir.getChildNode(companyFolderName, companyFolder);
        companyFolder.mkdir();
    }

    VFSNode resultNode;
    if (appName.isEmpty()) {
        resultNode = companyFolder;
    } else {
        companyFolder.getChildNode(appName, resultNode);
        resultNode.mkdir();
    }

    return resultNode;
}
Example #4
0
VFSNode::VFSNode(const VFSNode& directory, const VString& childName)
    : mPath()
    {
    directory.getChildNode(childName, *this);
}
void VFSNodeUnit::_testDirectoryIteration(const VFSNode& dir) {
    const int NUM_FILES_TO_CREATE = 5;
    const int NUM_FILES_TO_CHECK = NUM_FILES_TO_CREATE + 3; // we'll verify we don't have these extras

    // Test directory listing, iteration, find.
    // Create 5 files in the deep directory, then test that we can find them.
    for (int i = 0; i < NUM_FILES_TO_CREATE; ++i) {
        VString testIterFileName(VSTRING_ARGS("iter_test_%d.txt", i));
        VFSNode testIterFileNode;
        dir.getChildNode(testIterFileName, testIterFileNode);
        VBufferedFileStream testIterStream(testIterFileNode);
        testIterStream.openWrite();
        VTextIOStream out(testIterStream);
        out.writeLine(testIterFileName);
    }

    {
        // find() test
        VFSNode testIterNode;
        for (int i = 0; i < NUM_FILES_TO_CHECK; ++i) {
            VString testIterFileName(VSTRING_ARGS("iter_test_%d.txt", i));
            if (i < NUM_FILES_TO_CREATE)
                VUNIT_ASSERT_TRUE_LABELED(dir.find(testIterFileName, testIterNode), VSTRING_FORMAT("find() found #%d", i)); // this file should exist
            else
                VUNIT_ASSERT_FALSE_LABELED(dir.find(testIterFileName, testIterNode), VSTRING_FORMAT("find() did not find #%d", i)); // this file should not exist
        }
    }

    // There is no guarantee that the list() and iterate() methods will return the directory
    // listing in any particular order. We either need to sort them ourself, or verify without
    // regard to order. Here, we'll sort the returned string list, since we know that our
    // file names are sortable because they are single-digit-number-based strings, e.g. "iter_test_3.txt".
    // Note that the result of sorting is ultimately dependent on strcmp().

    {
        // list() names test
        int index = 0;
        VStringVector fileNames;
        dir.list(fileNames);
        std::sort(fileNames.begin(), fileNames.end());
        VUNIT_ASSERT_EQUAL_LABELED(static_cast<int>(fileNames.size()), NUM_FILES_TO_CREATE, "list names size");
        for (VStringVector::const_iterator i = fileNames.begin(); i != fileNames.end(); ++i, ++index) {
            VString testIterFileName(VSTRING_ARGS("iter_test_%d.txt", index));
            VUNIT_ASSERT_EQUAL_LABELED(*i, testIterFileName, VSTRING_FORMAT("list names #%d", index));
        }
    }

    {
        // list() nodes test
        int index = 0;
        VFSNodeVector fileNodes;
        dir.list(fileNodes);
        std::sort(fileNodes.begin(), fileNodes.end());
        VUNIT_ASSERT_EQUAL_LABELED(static_cast<int>(fileNodes.size()), NUM_FILES_TO_CREATE, "list nodes size");
        for (VFSNodeVector::const_iterator i = fileNodes.begin(); i != fileNodes.end(); ++i, ++index) {
            VString testIterFileName(VSTRING_ARGS("iter_test_%d.txt", index));
            VString nodeFileName;
            i->getName(nodeFileName);
            VUNIT_ASSERT_EQUAL_LABELED(nodeFileName, testIterFileName, VSTRING_FORMAT("list nodes #%d", index));
        }
    }

    {
        // iterate() test
        int index = 0;
        VFSNodeIterateTestCallback callback;
        dir.iterate(callback);
        std::sort(callback.mNodeNames.begin(), callback.mNodeNames.end());
        VUNIT_ASSERT_EQUAL_LABELED(static_cast<int>(callback.mNodeNames.size()), NUM_FILES_TO_CREATE, "iterate size");
        for (VStringVector::const_iterator i = callback.mNodeNames.begin(); i != callback.mNodeNames.end(); ++i, ++index) {
            VString testIterFileName(VSTRING_ARGS("iter_test_%d.txt", index));
            VUNIT_ASSERT_EQUAL_LABELED(*i, testIterFileName, VSTRING_FORMAT("iterate nodes #%d", index));
        }
    }

}