TEST(CLDataPostChannelBySTLqueueMaintainer, FunctionReturnRight)
{
	CLLogger::WriteLogMsg("CLDataPostChannelBySTLqueueMaintainer Test", 0);

	CLSTLqueue *q = new CLSTLqueue();
	CLDataPostChannelBySTLqueueMaintainer maintainer(q);

	CLInitialDataPostChannelNotifier *notifier = new CLInitialDataPostChannelNotifier();
	EXPECT_TRUE(maintainer.Initialize(notifier, 0).IsSuccess());

	CLDataPoster *poster = maintainer.GetDataPoster();
	CLDataPosterBySTLqueue *pq = dynamic_cast<CLDataPosterBySTLqueue *>(poster);
	EXPECT_TRUE(pq != 0);

	delete poster;
}
Esempio n. 2
0
/** \brief Parse a line from a version entry.
 *
 * This function reads the header (one line), a list of logs, and then
 * the footer of a version entry.
 *
 * If a version exists, even if it is wrong, the function returns true.
 * The function returns false if the end of the file is reached.
 *
 * \param[in] s  The state to read from.
 *
 * \return true if the end of the file was not yet reached when this
 *         version was read in full.
 */
bool changelog_file::version::parse(state& s)
{
    f_filename = s.get_filename();
    f_line = s.get_line();

    // the current line must be the header
    if(s.space_count() != 0)
    {
        wpkg_output::log("changelog:%1:%2: a changelog version entry must start with a valid header")
                .arg(f_filename)
                .arg(f_line)
            .level(wpkg_output::level_error)
            .module(wpkg_output::module_build_package)
            .action("changelog");
        return s.next_line();
    }

    bool good_header(true);
    const std::string& header(s.last_line());
    const char *h(header.c_str());
    const char *start(h);

    // *** Package Name ***
    for(; !isspace(*h) && *h != '('; ++h)
    {
        if(*h == '\0')
        {
            wpkg_output::log("changelog:%1:%2: invalid header, expected the project name, version, distributions, and urgency information")
                    .arg(f_filename)
                    .arg(f_line)
                .level(wpkg_output::level_error)
                .module(wpkg_output::module_build_package)
                .action("changelog");
            good_header = false;
            break;
        }
    }
    if(good_header)
    {
        std::string package_name(start, h - start);
        if(!wpkg_util::is_package_name(package_name))
        {
            wpkg_output::log("changelog:%1:%2: the package name %3 is not valid")
                    .arg(f_filename)
                    .arg(f_line)
                    .quoted_arg(package_name)
                .level(wpkg_output::level_error)
                .module(wpkg_output::module_build_package)
                .action("changelog");
        }
        else
        {
            f_package = package_name;
        }

        if(!isspace(*h))
        {
            // this is just a warning, but the user is expected to put a space
            // after the package name and before the version
            wpkg_output::log("changelog:%1:%2: the package name %3 is not followed by a space before the version information")
                    .arg(f_filename)
                    .arg(f_line)
                    .quoted_arg(package_name)
                .level(wpkg_output::level_warning)
                .module(wpkg_output::module_build_package)
                .package(f_package)
                .action("changelog");
            good_header = false;
        }
    }

    // *** Version ***
    if(good_header)
    {
        for(; isspace(*h); ++h);

        if(*h != '(')
        {
            wpkg_output::log("changelog:%1:%2: invalid header, expected the version between parenthesis after the package name")
                    .arg(f_filename)
                    .arg(f_line)
                .level(wpkg_output::level_error)
                .module(wpkg_output::module_build_package)
                .package(f_package)
                .action("changelog");
            good_header = false;
        }
    }
    if(good_header)
    {
        // read the version
        ++h;
        start = h;
        for(; !isspace(*h) && *h != ')' && *h != '\0'; ++h);

        std::string version_str(start, h - start);
        char err[256];
        if(!validate_debian_version(version_str.c_str(), err, sizeof(err)))
        {
            wpkg_output::log("control:%1:%2: %3 is not a valid Debian version")
                    .arg(f_filename)
                    .arg(f_line)
                    .quoted_arg(version_str)
                .level(wpkg_output::level_error)
                .module(wpkg_output::module_changelog)
                .package(f_package)
                .action("changelog");
            good_header = false;
        }
        else
        {
            f_version = version_str;
        }
    }
    if(good_header)
    {
        if(isspace(*h))
        {
            for(; isspace(*h); ++h);
            wpkg_output::log("control:%1:%2: version %3 is not immediately followed by a closing parenthesis")
                    .arg(f_filename)
                    .arg(f_line)
                    .quoted_arg(f_version)
                .level(wpkg_output::level_warning)
                .module(wpkg_output::module_changelog)
                .package(f_package)
                .action("changelog");
        }
        if(*h != ')')
        {
            wpkg_output::log("control:%1:%2: version %3 is not followed by a closing parenthesis: ')'")
                    .arg(f_filename)
                    .arg(f_line)
                    .quoted_arg(f_version)
                .level(wpkg_output::level_error)
                .module(wpkg_output::module_changelog)
                .package(f_package)
                .action("changelog");
            good_header = false;
        }
    }

    // *** Distributions ***
    if(good_header)
    {
        // the first ++h is to skip the ')' from the version
        for(++h; isspace(*h); ++h);
        do
        {
            start = h;
            for(; !isspace(*h) && *h != '\0' && *h != ';' && *h != ','; ++h);
            std::string d(start, h - start);
            wpkg_filename::uri_filename distribution(d);
            if(distribution.is_absolute())
            {
                wpkg_output::log("control:%1:%2: a distribution must be a relative path, %3 is not acceptable")
                        .arg(f_filename)
                        .arg(f_line)
                        .quoted_arg(distribution)
                    .level(wpkg_output::level_error)
                    .module(wpkg_output::module_changelog)
                    .package(f_package)
                    .action("changelog");
                good_header = false;
            }
            else if(distribution.segment_size() < 1)
            {
                // This happens if no distribution is specified
                wpkg_output::log("control:%1:%2: a distribution cannot be the empty string")
                        .arg(f_filename)
                        .arg(f_line)
                    .level(wpkg_output::level_error)
                    .module(wpkg_output::module_changelog)
                    .package(f_package)
                    .action("changelog");
                good_header = false;
            }
            else
            {
                f_distributions.push_back(distribution.original_filename());
            }
            for(; isspace(*h); ++h);
        }
        while(*h != '\0' && *h != ';' && *h != ',');
    }
    // We want to support more than one in source packages, that way a package
    // can be part of stable and unstable (because we view our distributions
    // as separate entities rather than complements.)
    //if(good_header)
    //{
    //    if(f_distributions.size() > 1)
    //    {
    //        wpkg_output::log("control:%1:%2: although the syntax allows for more than one distribution, we do not support more than one at this time")
    //                .arg(f_filename)
    //                .arg(f_line)
    //            .level(wpkg_output::level_error)
    //            .module(wpkg_output::module_changelog)
    //            .package(f_package)
    //            .action("changelog");
    //        good_header = false;
    //    }
    //}

    // *** Parameters ***
    if(good_header)
    {
        for(; isspace(*h); ++h);

        if(*h != ';')
        {
            wpkg_output::log("changelog:%1:%2: invalid header, expected the list of distributions to end with ';'")
                    .arg(f_filename)
                    .arg(f_line)
                .level(wpkg_output::level_error)
                .module(wpkg_output::module_build_package)
                .package(f_package)
                .action("changelog");
            good_header = false;
        }
        else
        {
            for(++h; isspace(*h); ++h);
        }
    }
    while(good_header && *h != '\0')
    {
        start = h;
        const char *e(h);
        const char *equal(NULL);
        for(; *h != ',' && *h != '\0'; ++h)
        {
            if(!isspace(*h))
            {
                e = h + 1;
            }
            if(*h == '=')
            {
                equal = h;
            }
        }
        if(equal == NULL)
        {
            wpkg_output::log("changelog:%1:%2: invalid header, parameter %3 is expected to include an equal sign (=) after the parameter name")
                    .arg(f_filename)
                    .arg(f_line)
                    .quoted_arg(std::string(start, h - start))
                .level(wpkg_output::level_error)
                .module(wpkg_output::module_build_package)
                .package(f_package)
                .action("changelog");
            good_header = false;
        }
        else if(start == equal)
        {
            wpkg_output::log("changelog:%1:%2: invalid header, parameter %3 is missing a name before the equal character")
                    .arg(f_filename)
                    .arg(f_line)
                    .quoted_arg(std::string(start, h - start))
                .level(wpkg_output::level_error)
                .module(wpkg_output::module_build_package)
                .package(f_package)
                .action("changelog");
            good_header = false;
        }
        else
        {
            std::string name(start, equal - start);
            if(f_parameters.find(name) != f_parameters.end())
            {
                wpkg_output::log("changelog:%1:%2: invalid header, parameter %3 is defined twice")
                        .arg(f_filename)
                        .arg(f_line)
                        .quoted_arg(name)
                    .level(wpkg_output::level_error)
                    .module(wpkg_output::module_build_package)
                    .package(f_package)
                    .action("changelog");
                good_header = false;
            }
            else
            {
                ++equal;
                std::string value(equal, e - equal);
                f_parameters[name] = value;
            }
        }

        // skip commas and spaces and repeat for next parameter
        for(; *h == ',' || isspace(*h); ++h);
    }

    // We got the header, now we check for the list of logs
    // the log::parse() function is expected to return false
    // once we reach the end of that list, then we must find
    // a footer that starts with a space and two dashes

    if(!s.next_line())
    {
        wpkg_output::log("changelog:%1:%2: every changelog version entry must have at least one log and end with a valid footer")
                .arg(f_filename)
                .arg(s.get_line())
            .level(wpkg_output::level_error)
            .module(wpkg_output::module_build_package)
            .package(f_package)
            .action("changelog");
        return false;
    }

    bool group(true);
    for(;;)
    {
        log l;
        if(!l.parse(s, group))
        {
            break;
        }
        f_logs.push_back(l);
    }

    // we are at the end of the log stream for this version entry,
    // there has to be a valid footer now

    bool good_footer(true);

    if(s.space_count() != 1)
    {
        wpkg_output::log("changelog:%1:%2: a changelog version entry must end with a valid footer, which must start with exactly one space")
                .arg(f_filename)
                .arg(s.get_line())
            .level(wpkg_output::level_error)
            .module(wpkg_output::module_build_package)
            .package(f_package)
            .action("changelog");
        good_footer = false;
    }

    const std::string& footer(s.last_line());
    const char *f(footer.c_str());

    if(good_footer)
    {
        if(f[0] != '-' || f[1] != '-' || f[2] != ' ')
        {
            wpkg_output::log("changelog:%1:%2: a changelog version entry must end with a valid footer, which must start with two dashes")
                    .arg(f_filename)
                    .arg(s.get_line())
                .level(wpkg_output::level_error)
                .module(wpkg_output::module_build_package)
                .package(f_package)
                .action("changelog");
            good_footer = false;
        }
    }

    if(good_footer)
    {
        // search for two spaces to break the maintainer name/email and date
        f += 3;
        start = f;
        for(; f[0] != '\0' && (f[0] != ' ' || f[1] != ' '); ++f);
        std::string maintainer(start, f - start);

        // TODO: use libtld to verify email

        f_maintainer = maintainer;

        std::string date(f + 2);
        struct tm time_info;
        if(strptime(date.c_str(), "%a, %d %b %Y %H:%M:%S %z", &time_info) == NULL)
        {
            wpkg_output::log("changelog:%1:%2: the footer in this changelog version entry has an invalid date: %3")
                    .arg(f_filename)
                    .arg(s.get_line())
                    .quoted_arg(date)
                .level(wpkg_output::level_error)
                .module(wpkg_output::module_build_package)
                .package(f_package)
                .action("changelog");
            good_footer = false;
        }
        else
        {
            f_date = date;
        }
    }

    // do not read another line in case this one is the next header
    return true;
}