예제 #1
0
string TestApplication::readTestfilePathFromEnv()
{
    const char *const testFilesPathEnv = getenv("TEST_FILE_PATH");
    if (!testFilesPathEnv || !*testFilesPathEnv) {
        return string();
    }
    return argsToString(testFilesPathEnv, '/');
}
예제 #2
0
/*!
 * \brief Executes the application to be tested with the specified \a args and stores the standard output and
 *        errors in \a stdout and \a stderr.
 * \throws Throws std::runtime_error when the application can not be executed.
 * \remarks
 *  - The specified \a args must be 0 terminated. The first argument is the application name.
 *  - Currently only supported under UNIX.
 *  - \a stdout and \a stderr are cleared before.
 */
int TestApplication::execApp(const char *const *args, string &output, string &errors, bool suppressLogging, int timeout) const
{
    // increase counter used for giving profiling files unique names
    static unsigned int invocationCount = 0;
    ++invocationCount;

    // determine the path of the application to be tested
    const char *appPath = m_applicationPathArg.firstValue();
    string fallbackAppPath;
    if (!appPath || !*appPath) {
        // try to find the path by removing "_tests"-suffix from own executable path
        // (the own executable path is the path of the test application and its name is usually the name of the application
        //  to be tested with "_tests"-suffix)
        const char *const testAppPath = m_parser.executable();
        const size_t testAppPathLength = strlen(testAppPath);
        if (testAppPathLength > 6 && !strcmp(testAppPath + testAppPathLength - 6, "_tests")) {
            fallbackAppPath.assign(testAppPath, testAppPathLength - 6);
            appPath = fallbackAppPath.data();
            // TODO: it would not hurt to verify whether "fallbackAppPath" actually exists and is executalbe
        } else {
            throw runtime_error("Unable to execute application to be tested: no application path specified");
        }
    }

    // determine new path for profiling output (to not override profiling output of parent and previous invocations)
    string newProfilingPath;
    if (const char *llvmProfileFile = getenv("LLVM_PROFILE_FILE")) {
        // replace eg. "/some/path/tageditor_tests.profraw" with "/some/path/tageditor0.profraw"
        if (const char *llvmProfileFileEnd = strstr(llvmProfileFile, ".profraw")) {
            const string llvmProfileFileWithoutExtension(llvmProfileFile, llvmProfileFileEnd);
            // extract application name from path
            const char *appName = strrchr(appPath, '/');
            appName = appName ? appName + 1 : appPath;
            // concat new path
            newProfilingPath = argsToString(llvmProfileFileWithoutExtension, '_', appName, invocationCount, ".profraw");
            // append path to profiling list file
            if (const char *profrawListFile = getenv("LLVM_PROFILE_LIST_FILE")) {
                ofstream(profrawListFile, ios_base::app) << newProfilingPath << endl;
            }
        }
    }

    return execAppInternal(appPath, args, output, errors, suppressLogging, timeout, newProfilingPath);
}
예제 #3
0
파일: main.cpp 프로젝트: VladOliynyk/cs-b
/*
 * The real main function.
 * Make all instead of us.
 * Gets equation string, prepare it, and solve.
*
 * @param argc - the int number of parameters passed to the main function.
 * @param argv - the array of pointers to parameters strings.
*/
void makeAll(int argc, char** argv) {
    do {
    // in configuration.h
    // show input rules
    if (USAGE)
        showUsage();

    //String of equation.
    string equation = "";

    if (argc > 1) {
        equation = argsToString(argc, argv);
    } else {
        equation = getUserString();
    }

    cout << equation << " = " << calculate(equation) << endl;
    } while (repeat());
    closeProgramManually();

    //system("pause");
}
예제 #4
0
/*!
 * \brief Internally called to make the entry's label unique within the parent.
 * \sa setLabel()
 */
void Entry::makeLabelUnique()
{
    if (!m_parent) {
        return;
    }
    string newLabel(label());
    for (unsigned int index = 2;; ++index) {
        bool needsNewLabel = false;
        for (Entry *const sibling : m_parent->children()) {
            if (sibling == this || newLabel != sibling->label()) {
                continue;
            }
            needsNewLabel = true;
            newLabel = argsToString(label(), ' ', index);
            break;
        }
        if (!needsNewLabel) {
            break;
        }
    }
    m_label.swap(newLabel);
}
예제 #5
0
/*!
 * \brief Parses field information from the specified EbmlElement.
 *
 * The specified atom should be a simple tag element. These elements
 * represents the fields of a MatroskaTag.
 *
 * \throws Throws std::ios_base::failure when an IO error occurs.
 * \throws Throws TagParser::Failure or a derived exception when a parsing
 *         error occurs.
 */
void MatroskaTagField::reparse(EbmlElement &simpleTagElement, Diagnostics &diag, bool parseNestedFields)
{
    string context("parsing Matroska tag field");
    simpleTagElement.parse(diag);
    bool tagDefaultFound = false;
    for (EbmlElement *child = simpleTagElement.firstChild(); child; child = child->nextSibling()) {
        try {
            child->parse(diag);
        } catch (const Failure &) {
            diag.emplace_back(DiagLevel::Critical, "Unable to parse children of \"SimpleTag\"-element.", context);
            break;
        }
        switch (child->id()) {
        case MatroskaIds::TagName:
            if (id().empty()) {
                setId(child->readString());
                context = "parsing Matroska tag field " + id();
            } else {
                diag.emplace_back(DiagLevel::Warning,
                    "\"SimpleTag\"-element contains multiple \"TagName\"-elements. Surplus TagName elements will be ignored.", context);
            }
            break;
        case MatroskaIds::TagString:
        case MatroskaIds::TagBinary:
            if (value().isEmpty()) {
                unique_ptr<char[]> buffer = make_unique<char[]>(child->dataSize());
                child->stream().seekg(static_cast<streamoff>(child->dataOffset()));
                child->stream().read(buffer.get(), static_cast<streamoff>(child->dataSize()));
                switch (child->id()) {
                case MatroskaIds::TagString:
                    value().assignData(move(buffer), child->dataSize(), TagDataType::Text, TagTextEncoding::Utf8);
                    break;
                case MatroskaIds::TagBinary:
                    value().assignData(move(buffer), child->dataSize(), TagDataType::Undefined);
                    break;
                }
            } else {
                diag.emplace_back(DiagLevel::Warning,
                    "\"SimpleTag\"-element contains multiple \"TagString\"/\"TagBinary\"-elements. Surplus \"TagName\"/\"TagBinary\"-elements will "
                    "be ignored.",
                    context);
            }
            break;
        case MatroskaIds::TagLanguage:
            if (value().language().empty() || value().language() == "und") {
                string lng = child->readString();
                if (lng != "und") {
                    value().setLanguage(lng);
                }
            } else {
                diag.emplace_back(DiagLevel::Warning,
                    "\"SimpleTag\"-element contains multiple \"TagLanguage\"-elements. Surplus \"TagLanguage\"-elements will be ignored.", context);
            }
            break;
        case MatroskaIds::TagDefault:
            if (!tagDefaultFound) {
                setDefault(child->readUInteger() > 0);
                tagDefaultFound = true;
            } else {
                diag.emplace_back(DiagLevel::Warning,
                    "\"SimpleTag\"-element contains multiple \"TagDefault\" elements. Surplus \"TagDefault\"-elements will be ignored.", context);
            }
            break;
        case MatroskaIds::SimpleTag:
            if (parseNestedFields) {
                nestedFields().emplace_back();
                nestedFields().back().reparse(*child, diag, true);
            } else {
                diag.emplace_back(DiagLevel::Warning,
                    "Nested fields are currently not supported. Nested tags can not be displayed and will be discarded when rewriting the file.",
                    context);
            }
            break;
        case EbmlIds::Crc32:
        case EbmlIds::Void:
            break;
        default:
            diag.emplace_back(DiagLevel::Warning,
                argsToString(
                    "\"SimpleTag\"-element contains unknown element ", child->idToString(), " at ", child->startOffset(), ". It will be ignored."),
                context);
        }
    }
}
예제 #6
0
/*!
 * \brief Returns a label for the entry.
 */
string MatroskaEditionEntry::label() const
{
    return argsToString("ID: ", id());
}
예제 #7
0
/*!
 * \brief Returns the full path to a working copy of the test file with the specified \a relativeTestFilePath.
 *
 * The specified \a mode controls whether a working copy is actually created or whether just the path is returned. If only the
 * path is returned, the \a relativeTestFilePath is ignored.
 *
 * In contrast to workingCopyPath(), this method allows to adjust the relative path of the working copy within the working copy
 * directory via \a relativeWorkingCopyPath.
 *
 * \remarks
 * - The test file specified via \a relativeTestFilePath is located using testFilePath().
 * - The name of the working copy file specified via \a relativeWorkingCopyPath will be adjusted if it already exists in the file
 *   system and can not be truncated.
 */
string TestApplication::workingCopyPathAs(
    const std::string &relativeTestFilePath, const std::string &relativeWorkingCopyPath, WorkingCopyMode mode) const
{
    // ensure working directory is present
    if (!dirExists(m_workingDir) && !makeDir(m_workingDir)) {
        cerr << Phrases::Error << "Unable to create working copy for \"" << relativeTestFilePath << "\": can't create working directory \""
             << m_workingDir << "\"." << Phrases::EndFlush;
        return string();
    }

    // ensure subdirectory exists
    const auto parts = splitString<vector<string>>(relativeWorkingCopyPath, "/", EmptyPartsTreat::Omit);
    if (!parts.empty()) {
        // create subdirectory level by level
        string currentLevel;
        currentLevel.reserve(m_workingDir.size() + relativeWorkingCopyPath.size() + 1);
        currentLevel.assign(m_workingDir);
        for (auto i = parts.cbegin(), end = parts.end() - 1; i != end; ++i) {
            if (currentLevel.back() != '/') {
                currentLevel += '/';
            }
            currentLevel += *i;

            // continue if subdirectory level already exists or we can successfully create the directory
            if (dirExists(currentLevel) || makeDir(currentLevel)) {
                continue;
            }
            // fail otherwise
            cerr << Phrases::Error << "Unable to create working copy for \"" << relativeWorkingCopyPath << "\": can't create directory \""
                 << currentLevel << "\" (inside working directory)." << Phrases::EndFlush;
            return string();
        }
    }

    // just return the path if we don't want to actually create a copy
    if (mode == WorkingCopyMode::NoCopy) {
        return m_workingDir + relativeWorkingCopyPath;
    }

    // copy the file
    const auto origFilePath(testFilePath(relativeTestFilePath));
    auto workingCopyPath(m_workingDir + relativeWorkingCopyPath);
    size_t workingCopyPathAttempt = 0;
    NativeFileStream origFile, workingCopy;
    origFile.open(origFilePath, ios_base::in | ios_base::binary);
    if (origFile.fail()) {
        cerr << Phrases::Error << "Unable to create working copy for \"" << relativeTestFilePath
             << "\": an IO error occurred when opening original file \"" << origFilePath << "\"." << Phrases::EndFlush;
        cerr << "error: " << strerror(errno) << endl;
        return string();
    }
    workingCopy.open(workingCopyPath, ios_base::out | ios_base::binary | ios_base::trunc);
    while (workingCopy.fail() && fileSystemItemExists(workingCopyPath)) {
        // adjust the working copy path if the target file already exists and can not be truncated
        workingCopyPath = argsToString(m_workingDir, relativeWorkingCopyPath, '.', ++workingCopyPathAttempt);
        workingCopy.clear();
        workingCopy.open(workingCopyPath, ios_base::out | ios_base::binary | ios_base::trunc);
    }
    if (workingCopy.fail()) {
        cerr << Phrases::Error << "Unable to create working copy for \"" << relativeTestFilePath
             << "\": an IO error occurred when opening target file \"" << workingCopyPath << "\"." << Phrases::EndFlush;
        cerr << "error: " << strerror(errno) << endl;
        return string();
    }
    workingCopy << origFile.rdbuf();
    if (!origFile.fail() && !workingCopy.fail()) {
        return workingCopyPath;
    }

    cerr << Phrases::Error << "Unable to create working copy for \"" << relativeTestFilePath << "\": ";
    if (origFile.fail()) {
        cerr << "an IO error occurred when reading original file \"" << origFilePath << "\"";
        return string();
    }
    if (workingCopy.fail()) {
        if (origFile.fail()) {
            cerr << " and ";
        }
        cerr << " an IO error occurred when writing to target file \"" << workingCopyPath << "\".";
    }
    cerr << "error: " << strerror(errno) << endl;
    return string();
}
예제 #8
0
/*!
 * \brief Constructs a TestApplication instance.
 * \throws Throws std::runtime_error if an instance has already been created.
 */
TestApplication::TestApplication(int argc, char **argv)
    : m_helpArg(m_parser)
    , m_testFilesPathArg("test-files-path", 'p', "specifies the path of the directory with test files")
    , m_applicationPathArg("app-path", 'a', "specifies the path of the application to be tested")
    , m_workingDirArg("working-dir", 'w', "specifies the directory to store working copies of test files")
    , m_unitsArg("units", 'u', "specifies the units to test; omit to test all units")
{
    // check whether there is already an instance
    if (m_instance) {
        throw runtime_error("only one TestApplication instance allowed at a time");
    }
    m_instance = this;

    // determine fallback path for testfiles which is used when --test-files-path/-p not present
    // -> read TEST_FILE_PATH environment variable
    m_fallbackTestFilesPath = readTestfilePathFromEnv();
    // -> find source directory if TEST_FILE_PATH not present
    bool fallbackIsSourceDir = m_fallbackTestFilesPath.empty();
    if (fallbackIsSourceDir) {
        m_fallbackTestFilesPath = readTestfilePathFromSrcRef();
    }

    // handle specified arguments (if present)
    if (argc && argv) {
        // setup argument parser
        for (Argument *arg : initializer_list<Argument *>{ &m_testFilesPathArg, &m_applicationPathArg, &m_workingDirArg }) {
            arg->setRequiredValueCount(1);
            arg->setValueNames({ "path" });
            arg->setCombinable(true);
        }
        m_unitsArg.setRequiredValueCount(Argument::varValueCount);
        m_unitsArg.setValueNames({ "unit1", "unit2", "unit3" });
        m_unitsArg.setCombinable(true);
        m_parser.setMainArguments({ &m_testFilesPathArg, &m_applicationPathArg, &m_workingDirArg, &m_unitsArg, &m_helpArg });

        // parse arguments
        try {
            m_parser.parseArgs(argc, argv);
        } catch (const Failure &failure) {
            cerr << failure;
            m_valid = false;
            return;
        }

        // print help
        if (m_helpArg.isPresent()) {
            exit(0);
        }
    }

    // handle path for testfiles and working-copy
    cerr << "Directories used to search for testfiles:" << endl;
    if (m_testFilesPathArg.isPresent()) {
        if (*m_testFilesPathArg.values().front()) {
            cerr << ((m_testFilesPath = m_testFilesPathArg.values().front()) += '/') << endl;
        } else {
            cerr << (m_testFilesPath = "./") << endl;
        }
    } else {
        // use fallback path if --test-files-path/-p not present
        m_testFilesPath.swap(m_fallbackTestFilesPath);
        cerr << m_testFilesPath << endl;
    }
    // if it wasn't already the case, use the source directory as fallback dir
    if (m_fallbackTestFilesPath.empty() && !fallbackIsSourceDir) {
        m_fallbackTestFilesPath = readTestfilePathFromSrcRef();
        fallbackIsSourceDir = true;
    }
    if (!m_fallbackTestFilesPath.empty() && m_testFilesPath != m_fallbackTestFilesPath) {
        cerr << m_fallbackTestFilesPath << endl;
    }
    cerr << "./testfiles/" << endl << endl;
    cerr << "Directory used to store working copies:" << endl;
    if (m_workingDirArg.isPresent()) {
        if (*m_workingDirArg.values().front()) {
            (m_workingDir = m_workingDirArg.values().front()) += '/';
        } else {
            m_workingDir = "./";
        }
    } else if (const char *workingDirEnv = getenv("WORKING_DIR")) {
        if (*workingDirEnv) {
            m_workingDir = argsToString(workingDirEnv, '/');
        }
    } else {
        if (m_testFilesPathArg.isPresent()) {
            m_workingDir = m_testFilesPath + "workingdir/";
        } else if (!m_fallbackTestFilesPath.empty() && !fallbackIsSourceDir) {
            m_workingDir = m_fallbackTestFilesPath + "workingdir/";
        } else {
            m_workingDir = "./testfiles/workingdir/";
        }
    }
    cerr << m_workingDir << endl << endl;

    // clear list of all additional profiling files created when forking the test application
    if (const char *profrawListFile = getenv("LLVM_PROFILE_LIST_FILE")) {
        ofstream(profrawListFile, ios_base::trunc);
    }

    m_valid = true;
    cerr << TextAttribute::Bold << "Executing test cases ..." << Phrases::EndFlush;
}