<commit_before>/* Copyright (C) 2015-2016 INRA
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include "prediction.hpp"
#include "problem.hpp"
#include "post.hpp"
#include "solver-stack.hpp"
#include "model.hpp"
#include "context.hpp"
#include "exception.hpp"
#include "utils.hpp"
#include "options.hpp"
#include <iterator>
#include <fstream>
#include <chrono>
#include <thread>
#include <cmath>

namespace efyj {

struct compute_prediction_0
{
    std::shared_ptr<Context> m_context;
    const Model& m_model;
    const Options& m_options;

    std::chrono::time_point<std::chrono::system_clock> m_start, m_end;
    std::vector <int> m_globalsimulated;
    std::vector <std::tuple<int, int, int>> m_globalupdaters, m_updaters;
    std::vector <std::vector<scale_id>> m_globalfunctions, m_functions;

    unsigned long long int m_loop = 0;
    double m_kappa = 0.0;

    compute_prediction_0(std::shared_ptr<Context> context,
                         const Model& model,
                         const Options& options)
        : m_context(context)
        , m_model(model)
        , m_options(options)
        , m_globalsimulated(options.observed.size(), 0)
        , m_loop(0)
        , m_kappa(0)
    {
    }

    void run()
    {
        m_context->info() << m_context->info().cyanb()
                          << "[Computation start]"
                          << m_context->info().def() << '\n';

        std::vector<int> simulated(m_options.options.rows());
        std::vector<int> observed(m_options.options.rows());
        for_each_model_solver solver(m_context, m_model);
        weighted_kappa_calculator kappa_c(m_model.attributes[0].scale.size());
        // solver.reduce(m_options);

        std::size_t max_step = solver.get_attribute_line_tuple_limit();
        std::size_t step = 1;

        m_context->info() << m_context->info().cyanb()
                          << "[Computation starts 1/"
                          << max_step << "]"
                          << m_context->info().def() << '\n';

        const std::size_t optmax = m_options.ordered.size();

        {
            m_start = std::chrono::system_clock::now();
            for (std::size_t opt = 0; opt != optmax; ++opt)
                m_globalsimulated[opt] = solver.solve(m_options.options.row(opt));

            auto ret = kappa_c.squared(m_options.observed, m_globalsimulated);

            m_end = std::chrono::system_clock::now();

            m_context->info() << "| line updated | kappa | kappa computed " \
                "| time (s) | tuple (attribute, line, value) updated |\n";

            m_context->info().printf("| %d | %13.10f | %" PRIuMAX
                                     " | %f | [] |\n", 0, ret, 1,
                                     std::chrono::duration<double>(
                                         m_end - m_start).count());
        }

        while (step < max_step) {
            m_start = std::chrono::system_clock::now();
            m_loop = 0;

            // std::vector<std::vector <std::tuple<int, int, int>>> to_explore;
            std::fill(std::begin(m_globalsimulated), std::end(m_globalsimulated), 0);

            for (std::size_t opt = 0; opt != optmax; ++opt) {
                solver.init_walkers(step);
                m_kappa = 0;

                do {
                    solver.init_next_value();

                    do {
                        simulated.resize(m_options.ordered[opt].size(), 0);
                        observed.resize(m_options.ordered[opt].size(), 0);

                        // { // DEBUGMODE
                        //     if (opt == 0 and step == 1) {
                        //         std::printf("numero lignes: ");
                        //         for (auto x : m_options.ordered[opt])
                        //             std::printf("%d ", x);
                        //         std::printf("\n");

                        //         std::printf("valeur observée: ");
                        //         for (auto x : m_options.ordered[opt])
                        //             std::printf("%c ", 'A' + m_options.observed[x]);
                        //         std::printf("\n");

                        //         for (long int att = 0, atte = m_options.options.cols();
                        //              att != atte; ++att) {
                        //             std::printf("column %ld: ", att);
                        //             for (auto x : m_options.ordered[opt])
                        //                 std::printf("%d ", m_options.options(x, att));
                        //             std::printf("\n");
                        //         }

                        //         std::printf("valeur simulée: ");
                        //         for (auto x : m_options.ordered[opt])
                        //             std::printf("%c ", 'A' + solver.solve(m_options.options.row(x)));
                        //         std::printf("\n");

                        //     }
                        // } // DEBUGMODE

                        {
                            int i = 0;
                            for (auto x : m_options.ordered[opt]) {
                                observed[i] = m_options.observed[x];
                                simulated[i] = solver.solve(m_options.options.row(x));
                                ++i;
                            }
                        }

                        auto ret = kappa_c.squared(observed, simulated);

                        std::printf("kappa: %f\n", ret);
                        return;

                        m_loop++;

                        // { // DEBUGMODE
                        //     if (opt == 0 && step == 1) {
                        //         auto updater = solver.updaters();

                        //         m_context->info() << "   " << updater << ' '
                        //                           << ret << ' ' << solver.string_functions()
                        //                           << '\n';
                        //     }
                        // } // DEBUGMODE

                        // if (ret >= m_kappa) {
                        // if (ret == m_kappa) {
                        //     if (to_explore.end() == std::find(std::begin(to_explore),
                        //                                       std::end(to_explore),
                        //                                       solver.updaters()))
                        //         to_explore.emplace_back(solver.updaters());
                        // } else {
                        // to_explore.clear();

                        if (ret > m_kappa) {
                            solver.get_functions(m_functions);
                            m_updaters = solver.updaters();
                            m_kappa = ret;
                        }
                    } while (solver.next_value() == true);
                } while (solver.next_line() == true);

                solver.set_functions(m_functions);
                m_globalsimulated[opt] = solver.solve(m_options.options.row(opt));
            }

            m_kappa = kappa_c.squared(m_options.observed, m_globalsimulated);
            m_loop++;
            m_end = std::chrono::system_clock::now();

            m_context->info().printf("| %d | %13.10f | %" PRIuMAX
                            " | %f | %ld | ",
                            step, m_kappa, m_loop,
                            std::chrono::duration<double>(
                                m_end - m_start).count());

            m_context->info() << m_updaters << " |\n";
            step++;
        }
    };
};

void prediction_0(std::shared_ptr<Context> context,
                  const Model& model,
                  const Options& options)
{
    compute_prediction_0 computer(context, model, options);

    computer.run();
}

} // namespace efyj
<commit_msg>prediction: fix reinitialization of solver between line computation<commit_after>/* Copyright (C) 2015-2016 INRA
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include "prediction.hpp"
#include "problem.hpp"
#include "post.hpp"
#include "solver-stack.hpp"
#include "model.hpp"
#include "context.hpp"
#include "exception.hpp"
#include "utils.hpp"
#include "options.hpp"
#include <iterator>
#include <fstream>
#include <chrono>
#include <thread>
#include <cmath>

namespace efyj {

struct compute_prediction_0
{
    std::shared_ptr<Context> m_context;
    const Model& m_model;
    const Options& m_options;

    std::chrono::time_point<std::chrono::system_clock> m_start, m_end;
    std::vector <int> m_globalsimulated;
    std::vector <std::tuple<int, int, int>> m_updaters;
    std::vector <std::vector<scale_id>> m_globalfunctions, m_functions;

    unsigned long long int m_loop = 0;
    double m_kappa = 0.0;

    compute_prediction_0(std::shared_ptr<Context> context,
                         const Model& model,
                         const Options& options)
        : m_context(context)
        , m_model(model)
        , m_options(options)
        , m_globalsimulated(options.observed.size(), 0)
        , m_loop(0)
        , m_kappa(0)
    {
        assert(m_options.options.rows() > 0 and "prediction: empty option");
    }

    void run()
    {
        m_context->info() << m_context->info().cyanb()
                          << "[Computation start]"
                          << m_context->info().def() << '\n';

        std::vector<int> simulated(m_options.options.rows());
        std::vector<int> observed(m_options.options.rows());
        for_each_model_solver solver(m_context, m_model);
        weighted_kappa_calculator kappa_c(m_model.attributes[0].scale.size());
        solver.reduce(m_options);

        solver.get_functions(m_globalfunctions);
        assert(not m_globalfunctions.empty()
               and "prediction can not determine function");

        const std::size_t max_step = solver.get_attribute_line_tuple_limit();
        assert(max_step > 0 and "prediction: can not determine limit");

        m_context->info() << m_context->info().cyanb()
                          << "[Computation starts 1/"
                          << max_step << "]"
                          << m_context->info().def() << '\n';

        const std::size_t optmax = m_options.ordered.size();

        {
            m_start = std::chrono::system_clock::now();
            for (std::size_t opt = 0; opt != optmax; ++opt)
                m_globalsimulated[opt] = solver.solve(m_options.options.row(opt));

            auto ret = kappa_c.squared(m_options.observed, m_globalsimulated);

            m_end = std::chrono::system_clock::now();

            m_context->info() << "| line updated | kappa | kappa computed " \
                "| time (s) | tuple (attribute, line, value) updated |\n";

            m_context->info().printf("| %d | %13.10f | %" PRIuMAX
                                     " | %f | [] |\n", 0, ret, 1,
                                     std::chrono::duration<double>(
                                         m_end - m_start).count());
        }

        for (std::size_t step = 1; step < max_step; ++step) {
            m_start = std::chrono::system_clock::now();
            m_loop = 0;

            std::fill(std::begin(m_globalsimulated), std::end(m_globalsimulated), 0);

            for (std::size_t opt = 0; opt != optmax; ++opt) {
                solver.set_functions(m_globalfunctions);
                solver.init_walkers(step);
                m_kappa = 0;

                do {
                    solver.init_next_value();

                    do {
                        const std::size_t size = m_options.ordered[opt].size();
                        simulated.resize(size, 0);
                        observed.resize(size, 0);

                        for (std::size_t i = 0; i != size; ++i) {
                            auto id = m_options.ordered[opt][i];
                            observed[i] = m_options.observed[id];
                            simulated[i] = solver.solve(m_options.options.row(id));
                        }

                        auto ret = kappa_c.squared(observed, simulated);
                        m_loop++;

                        if (ret > m_kappa) {
                            solver.get_functions(m_functions);
                            m_updaters = solver.updaters();
                            m_kappa = ret;
                        }
                    } while (solver.next_value() == true);
                } while (solver.next_line() == true);

                solver.set_functions(m_functions);
                m_globalsimulated[opt] = solver.solve(m_options.options.row(opt));
            }

            m_kappa = kappa_c.squared(m_options.observed, m_globalsimulated);
            m_loop++;
            m_end = std::chrono::system_clock::now();

            m_context->info().printf("| %d | %13.10f | %" PRIuMAX
                            " | %f | ",
                            step, m_kappa, m_loop,
                            std::chrono::duration<double>(
                                m_end - m_start).count());

            m_context->info() << m_updaters << " |\n";
        }
    };
};

void prediction_0(std::shared_ptr<Context> context,
                  const Model& model,
                  const Options& options)
{
    compute_prediction_0 computer(context, model, options);

    computer.run();
}

} // namespace efyj
<|endoftext|>


<commit_before>// Time:  O(max(m, n))
// Space: O(1)

// TLE, test case #15 it never returns
// even if the function directly returns the answer peak "{1, 2}" without computing.
// But Python works with the same solution. There might be some problem with test runners of c++ and java.
class Solution {
public:
    /**
     * @param A: An integer matrix
     * @return: The index of the peak
     */
    vector<int> findPeakII(vector<vector<int> > A) {
        int upper = 0, down = A.size() - 1;
        int left = 0, right = A[0].size() - 1;

        while (upper < down && left < right) {
            int height = down - upper + 1;
            int width = right - left + 1;

            // T(m, n) = T(m, n / 2) + O(m) = T(m / 2, n / 2) + O(m) + O(n / 2) = ... = O(2m) + O(2n) = O(max(m, n))
            if (width > height) { // Vertical split.
                int mid_j = left + (right - left) / 2;
                int left_max = 0, central_max = 0, right_max = 0;
                int max_i = -1, max_j = -1;
                for (int i = upper + 1; i < down; ++i) {
                    if (A[i][mid_j] > central_max) {
                        max_i = i, max_j = mid_j;
                        central_max = A[i][mid_j];
                    }
                    left_max = max(left_max, A[i][mid_j - 1]);
                    right_max = max(right_max, A[i][mid_j +  1]);
                }
                if (left_max > central_max && left_max > right_max) { // Find left.
                    right = mid_j;
                } else if (right_max > central_max && right_max > left_max) { // Find right.
                    left = mid_j;
                } else { // Find one peak.
                    return {max_i, max_j};
                }
            } else { // Horizontal split.
                int mid_i = upper + (down - upper) / 2;
                int upper_max = 0, central_max = 0, down_max = 0;
                int max_i = -1, max_j = -1;
                for (int j = left + 1; j < right; ++j) {
                    if (A[mid_i][j] > central_max) {
                        max_i = mid_i, max_j = j;
                        central_max = A[mid_i][j];
                    }
                    upper_max = max(upper_max, A[mid_i - 1][j]);
                    down_max = max(down_max, A[mid_i + 1][j]);
                }
                if (upper_max > central_max && upper_max > down_max) { // Find upper.
                    down = mid_i;
                } else if (down_max > central_max && down_max > upper_max) { // Find down.
                    upper = mid_i;
                } else { // Find one peak.
                    return {max_i, max_j};
                }
            }

        }
        return {-1, -1}; // Not found.
    }
};
<commit_msg>Update find-peak-element-ii.cpp<commit_after>// Time:  O(max(m, n))
// Space: O(1)

// Currently (2015-05-14), there might be some problem with test runners of C++ and Java.
// Because whenever running test case #15 it always shows TLE.
// Even if the function directly returns the answer peak "{1, 2}" without any computing cost, it still gets TLE or MLE.
// But the same solution really works in Python.
class Solution {
public:
    /**
     * @param A: An integer matrix
     * @return: The index of the peak
     */
    vector<int> findPeakII(vector<vector<int> > A) {
        int upper = 0, down = A.size() - 1;
        int left = 0, right = A[0].size() - 1;

        while (upper < down && left < right) {
            int height = down - upper + 1;
            int width = right - left + 1;

            // T(m, n) = T(m, n / 2) + O(m) = T(m / 2, n / 2) + O(m) + O(n / 2) = ... = O(2m) + O(2n) = O(max(m, n))
            if (width > height) { // Vertical split.
                int mid_j = left + (right - left) / 2;
                int left_max = 0, central_max = 0, right_max = 0;
                int max_i = -1, max_j = -1;
                for (int i = upper + 1; i < down; ++i) {
                    if (A[i][mid_j] > central_max) {
                        max_i = i, max_j = mid_j;
                        central_max = A[i][mid_j];
                    }
                    left_max = max(left_max, A[i][mid_j - 1]);
                    right_max = max(right_max, A[i][mid_j +  1]);
                }
                if (left_max > central_max && left_max > right_max) { // Find left.
                    right = mid_j;
                } else if (right_max > central_max && right_max > left_max) { // Find right.
                    left = mid_j;
                } else { // Find one peak.
                    return {max_i, max_j};
                }
            } else { // Horizontal split.
                int mid_i = upper + (down - upper) / 2;
                int upper_max = 0, central_max = 0, down_max = 0;
                int max_i = -1, max_j = -1;
                for (int j = left + 1; j < right; ++j) {
                    if (A[mid_i][j] > central_max) {
                        max_i = mid_i, max_j = j;
                        central_max = A[mid_i][j];
                    }
                    upper_max = max(upper_max, A[mid_i - 1][j]);
                    down_max = max(down_max, A[mid_i + 1][j]);
                }
                if (upper_max > central_max && upper_max > down_max) { // Find upper.
                    down = mid_i;
                } else if (down_max > central_max && down_max > upper_max) { // Find down.
                    upper = mid_i;
                } else { // Find one peak.
                    return {max_i, max_j};
                }
            }

        }
        return {-1, -1}; // Not found.
    }
};
<|endoftext|>


<commit_before><commit_msg>Q_OS_WIN -> Q_WS_WIN to include WinCE as well.<commit_after><|endoftext|>


<commit_before>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2019 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <common.cxx>
#include <net/ip6/stateful_addr.hpp>

static uint64_t my_time = 0;

static uint64_t get_time()
{ return my_time; }

#include <delegate>
extern delegate<uint64_t()> systime_override;

using namespace net::ip6;

CASE("Stateful_addr basic and lifetime")
{
  // setup RTC to use my_time
  systime_override = get_time;
  my_time = 0;

  const Addr local{"fe80::1337:1"};
  const uint8_t prefix = 64;

  Stateful_addr addr{local, prefix, 2400, 3600};

  EXPECT(addr.addr() == local);
  EXPECT(addr.prefix() == prefix);
  EXPECT(addr.valid());
  EXPECT(addr.preferred());
  EXPECT(not addr.always_valid());
  EXPECT(addr.remaining_valid_time() == 3600);
  EXPECT(addr.valid_ts() == 3600);
  EXPECT(addr.preferred_ts() == 2400);

  my_time += 2400;

  EXPECT(addr.valid());
  EXPECT(not addr.preferred()); // deprecated
  EXPECT(addr.remaining_valid_time() == 3600-2400);

  my_time += 1200;

  EXPECT(not addr.valid());
  EXPECT(not addr.preferred());
  EXPECT(addr.remaining_valid_time() == 0);

  my_time += 1200;

  EXPECT(not addr.valid());
  EXPECT(not addr.preferred());
  EXPECT(addr.remaining_valid_time() == 0);
  EXPECT(addr.valid_ts() == 3600);
  EXPECT(addr.preferred_ts() == 2400);

  addr.update_valid_lifetime(3600);

  EXPECT(addr.valid());
  EXPECT(not addr.preferred());
  EXPECT(addr.valid_ts() == 3600 + my_time);

  addr.update_preferred_lifetime(3600);

  EXPECT(addr.valid());
  EXPECT(addr.preferred());
  EXPECT(addr.preferred_ts() == 3600 + my_time);

  addr.update_valid_lifetime(0);

  EXPECT(not addr.valid());
  EXPECT(not addr.preferred());
  EXPECT(addr.valid_ts() == my_time);

  my_time += 1200;

  EXPECT(addr.remaining_valid_time() == 0);

  EXPECT(addr.to_string() == std::string("fe80:0:0:0:0:0:1337:1/64"));

}

CASE("Stateful_addr infinite lifetime")
{
  // setup RTC to use my_time
  systime_override = get_time;
  my_time = 0;

  const Addr local{"fe80::1337:1"};
  const uint8_t prefix = 64;

  Stateful_addr addr{local, prefix};

  EXPECT(addr.always_valid());
  EXPECT(addr.valid());
  EXPECT(addr.preferred());
  EXPECT(addr.remaining_valid_time() == Stateful_addr::infinite_lifetime);
  EXPECT(addr.valid_ts() == Stateful_addr::infinite_lifetime);
  EXPECT(addr.preferred_ts() == Stateful_addr::infinite_lifetime);

  my_time += 6000;

  EXPECT(addr.valid());
  EXPECT(addr.preferred());
  EXPECT(addr.remaining_valid_time() == Stateful_addr::infinite_lifetime);

  addr.update_valid_lifetime(0);
  EXPECT(not addr.valid());
  EXPECT(not addr.always_valid());
  EXPECT(addr.valid_ts() == my_time);
}
<commit_msg>ip6: Test stateful addr matches<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2019 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <common.cxx>
#include <net/ip6/stateful_addr.hpp>

static uint64_t my_time = 0;

static uint64_t get_time()
{ return my_time; }

#include <delegate>
extern delegate<uint64_t()> systime_override;

using namespace net::ip6;

CASE("Stateful_addr basic and lifetime")
{
  // setup RTC to use my_time
  systime_override = get_time;
  my_time = 0;

  const Addr local{"fe80::1337:1"};
  const uint8_t prefix = 64;

  Stateful_addr addr{local, prefix, 2400, 3600};

  EXPECT(addr.addr() == local);
  EXPECT(addr.prefix() == prefix);
  EXPECT(addr.valid());
  EXPECT(addr.preferred());
  EXPECT(not addr.always_valid());
  EXPECT(addr.remaining_valid_time() == 3600);
  EXPECT(addr.valid_ts() == 3600);
  EXPECT(addr.preferred_ts() == 2400);

  my_time += 2400;

  EXPECT(addr.valid());
  EXPECT(not addr.preferred()); // deprecated
  EXPECT(addr.remaining_valid_time() == 3600-2400);

  my_time += 1200;

  EXPECT(not addr.valid());
  EXPECT(not addr.preferred());
  EXPECT(addr.remaining_valid_time() == 0);

  my_time += 1200;

  EXPECT(not addr.valid());
  EXPECT(not addr.preferred());
  EXPECT(addr.remaining_valid_time() == 0);
  EXPECT(addr.valid_ts() == 3600);
  EXPECT(addr.preferred_ts() == 2400);

  addr.update_valid_lifetime(3600);

  EXPECT(addr.valid());
  EXPECT(not addr.preferred());
  EXPECT(addr.valid_ts() == 3600 + my_time);

  addr.update_preferred_lifetime(3600);

  EXPECT(addr.valid());
  EXPECT(addr.preferred());
  EXPECT(addr.preferred_ts() == 3600 + my_time);

  addr.update_valid_lifetime(0);

  EXPECT(not addr.valid());
  EXPECT(not addr.preferred());
  EXPECT(addr.valid_ts() == my_time);

  my_time += 1200;

  EXPECT(addr.remaining_valid_time() == 0);

  EXPECT(addr.to_string() == std::string("fe80:0:0:0:0:0:1337:1/64"));

}

CASE("Stateful_addr infinite lifetime")
{
  // setup RTC to use my_time
  systime_override = get_time;
  my_time = 0;

  const Addr local{"fe80::1337:1"};
  const uint8_t prefix = 64;

  Stateful_addr addr{local, prefix};

  EXPECT(addr.always_valid());
  EXPECT(addr.valid());
  EXPECT(addr.preferred());
  EXPECT(addr.remaining_valid_time() == Stateful_addr::infinite_lifetime);
  EXPECT(addr.valid_ts() == Stateful_addr::infinite_lifetime);
  EXPECT(addr.preferred_ts() == Stateful_addr::infinite_lifetime);

  my_time += 6000;

  EXPECT(addr.valid());
  EXPECT(addr.preferred());
  EXPECT(addr.remaining_valid_time() == Stateful_addr::infinite_lifetime);

  addr.update_valid_lifetime(0);
  EXPECT(not addr.valid());
  EXPECT(not addr.always_valid());
  EXPECT(addr.valid_ts() == my_time);
}

CASE("Stateful_addr matches")
{
  const Stateful_addr addr1{{"fe80::1337:0:0:1337"}, 64};
  const Stateful_addr addr2{{"fe80::1337:0:42:1337"}, 64};
  const Stateful_addr router1{{"fe80::1337:1337:0:0:1"}, 48};
  const Stateful_addr router2{{"fe80::1337:0:0:1"}, 112};

  EXPECT(router1.match(addr1.addr()));
  EXPECT(router1.match(addr2.addr()));
  EXPECT(router2.match(addr1.addr()));
  EXPECT(not router2.match(addr2.addr()));
}
<|endoftext|>


<commit_before>#include <gtest/gtest.h>
#include "../../include/SQLiteDatabase.h"

#include <iostream>
#include <fstream>
#include <vector>

bool fexists(const std::string& filename) {
  std::ifstream ifile(filename.c_str());
  return ifile;
};

class SQLiteDatabaseTestFixture : public ::testing::Test {
public:
    SQLiteDatabaseTestFixture( ) {
        test_database_filename_ = "test.db";
    }

    void SetUp( ) {
        // code here will execute just before the test ensues
    }

    void TearDown( ) {
        // code here will be called just after the test completes
        // ok to through exceptions from here if need be
    }

    ~SQLiteDatabaseTestFixture( )  {
        remove("test.db");
    }

    // Test Member Variables
    std::string test_database_filename_;
};

TEST_F(SQLiteDatabaseTestFixture, create_database_test) {

    sqlite::SQLiteDatabase db;

    try{
        db.open(test_database_filename_, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
        db.close();
    }
    catch (const std::exception & e) {
        std::cout << e.what() << std::endl;
    }

    ASSERT_TRUE(fexists(test_database_filename_));
}

TEST_F(SQLiteDatabaseTestFixture, database_version_test) {

    sqlite::SQLiteDatabase db;
    try{
        db.open(test_database_filename_, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
    }
    catch (const std::exception & e){
        std::cout << e.what() << std::endl;
    }

    int expected_version = 1;
    db.setVersion(expected_version);
    auto version = db.getVersion();

    db.close();

    EXPECT_EQ(expected_version, version);
}

TEST_F(SQLiteDatabaseTestFixture, get_readonly_database_test) {

    sqlite::SQLiteDatabase db;

    int expected_version = 1;
    int version = 0;

    try{
        db.open(test_database_filename_, SQLITE_OPEN_READONLY);

        EXPECT_ANY_THROW(db.setVersion(expected_version));

        db.close();
    }
    catch (const std::exception & e){
        std::cout << e.what() << std::endl;
    }
}

TEST_F(SQLiteDatabaseTestFixture, query_test) {

    sqlite::SQLiteDatabase db;

    try{
        db.open(test_database_filename_, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);

        // Create Cars table test data
        const std::string kCreateTable =
                "CREATE TABLE IF NOT EXISTS cars "
                        "(mpg text, "
                        "weight text)";

        db.execQuery(kCreateTable);

        db.execQuery("INSERT INTO cars "
                             "VALUES('34', '2000')");

        db.execQuery("INSERT INTO cars "
                             "VALUES('27', '25000')");

        db.execQuery("INSERT INTO cars "
                             "VALUES('16', '5000')");

        std::vector<std::string> columns;
        columns.push_back("mpg");
        columns.push_back("weight");

        std::string selection;

        std::vector<std::string> selectionArgs;

        auto c = db.query(true, "cars", columns, selection, selectionArgs, "", "", "");

        c.next();
        EXPECT_STREQ(c.getString(1).c_str(), "34");
        EXPECT_STREQ(c.getString(2).c_str(), "2000");
        c.next();
        EXPECT_STREQ(c.getString(1).c_str(), "27");
        EXPECT_STREQ(c.getString(2).c_str(), "25000");
        c.next();
        EXPECT_STREQ(c.getString(1).c_str(), "16");
        EXPECT_STREQ(c.getString(2).c_str(), "5000");

        db.close();
    }
    catch (const std::exception & e){
        std::cout << e.what() << std::endl;
    }
}

TEST_F(SQLiteDatabaseTestFixture, insert_test) {

    sqlite::SQLiteDatabase db;

    try{
        db.open(test_database_filename_, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);

        // Create Cars table test data
        const std::string kCreateTable =
                "CREATE TABLE IF NOT EXISTS cars "
                        "(mpg text, "
                        "weight text)";

        db.execQuery(kCreateTable);

        const std::string table = "cars";
        long id = db.insert(table, std::vector<std::string>{"mpg", "weight"}, std::vector<std::string>{"34", "2000"}, "", std::vector<std::string>{});
        long id2 = db.insert(table, std::vector<std::string>{"mpg", "weight"}, std::vector<std::string>{"20", "1500"}, "", std::vector<std::string>{});

        EXPECT_EQ(id, 1);
        EXPECT_EQ(id2, 2);

        db.close();
    }
        catch (const std::exception & e){
        std::cout << e.what() << std::endl;
    }
}

TEST_F(SQLiteDatabaseTestFixture, update_test) {

    sqlite::SQLiteDatabase db;

    try{
        db.open(test_database_filename_, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);

        // Create Cars table test data
        const std::string kCreateTable =
            "CREATE TABLE IF NOT EXISTS cars "
                "(mpg text, "
                "weight text)";

        db.execQuery(kCreateTable);

        const std::string table = "cars";
        long id = db.insert(table, std::vector<std::string>{"mpg", "weight"}, std::vector<std::string>{"34", "2000"}, "", std::vector<std::string>{});
        long id2 = db.insert(table, std::vector<std::string>{"mpg", "weight"}, std::vector<std::string>{"20", "1500"}, "", std::vector<std::string>{});

        int updated_rows = db.update(table, std::vector<std::string>{"mpg", "weight"}, std::vector<std::string>{"1", "1"}, "", std::vector<std::string>{});

        EXPECT_EQ(updated_rows, 2);

        db.close();
    }
    catch (const std::exception & e){
        std::cout << e.what() << std::endl;
    }
}
<commit_msg>removed unused variables<commit_after>#include <gtest/gtest.h>
#include "../../include/SQLiteDatabase.h"

#include <iostream>
#include <fstream>
#include <vector>

bool fexists(const std::string& filename) {
  std::ifstream ifile(filename.c_str());
  return ifile;
};

class SQLiteDatabaseTestFixture : public ::testing::Test {
public:
    SQLiteDatabaseTestFixture( ) {
        test_database_filename_ = "test.db";
    }

    void SetUp( ) {
        // code here will execute just before the test ensues
    }

    void TearDown( ) {
        // code here will be called just after the test completes
        // ok to through exceptions from here if need be
    }

    ~SQLiteDatabaseTestFixture( )  {
        remove("test.db");
    }

    // Test Member Variables
    std::string test_database_filename_;
};

TEST_F(SQLiteDatabaseTestFixture, create_database_test) {

    sqlite::SQLiteDatabase db;

    try{
        db.open(test_database_filename_, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
        db.close();
    }
    catch (const std::exception & e) {
        std::cout << e.what() << std::endl;
    }

    ASSERT_TRUE(fexists(test_database_filename_));
}

TEST_F(SQLiteDatabaseTestFixture, database_version_test) {

    sqlite::SQLiteDatabase db;
    try{
        db.open(test_database_filename_, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
    }
    catch (const std::exception & e){
        std::cout << e.what() << std::endl;
    }

    int expected_version = 1;
    db.setVersion(expected_version);
    auto version = db.getVersion();

    db.close();

    EXPECT_EQ(expected_version, version);
}

TEST_F(SQLiteDatabaseTestFixture, get_readonly_database_test) {

    sqlite::SQLiteDatabase db;

    try{
        db.open(test_database_filename_, SQLITE_OPEN_READONLY);

        EXPECT_ANY_THROW(db.setVersion(expected_version));

        db.close();
    }
    catch (const std::exception & e){
        std::cout << e.what() << std::endl;
    }
}

TEST_F(SQLiteDatabaseTestFixture, query_test) {

    sqlite::SQLiteDatabase db;

    try{
        db.open(test_database_filename_, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);

        // Create Cars table test data
        const std::string kCreateTable =
                "CREATE TABLE IF NOT EXISTS cars "
                        "(mpg text, "
                        "weight text)";

        db.execQuery(kCreateTable);

        db.execQuery("INSERT INTO cars "
                             "VALUES('34', '2000')");

        db.execQuery("INSERT INTO cars "
                             "VALUES('27', '25000')");

        db.execQuery("INSERT INTO cars "
                             "VALUES('16', '5000')");

        std::vector<std::string> columns;
        columns.push_back("mpg");
        columns.push_back("weight");

        std::string selection;

        std::vector<std::string> selectionArgs;

        auto c = db.query(true, "cars", columns, selection, selectionArgs, "", "", "");

        c.next();
        EXPECT_STREQ(c.getString(1).c_str(), "34");
        EXPECT_STREQ(c.getString(2).c_str(), "2000");
        c.next();
        EXPECT_STREQ(c.getString(1).c_str(), "27");
        EXPECT_STREQ(c.getString(2).c_str(), "25000");
        c.next();
        EXPECT_STREQ(c.getString(1).c_str(), "16");
        EXPECT_STREQ(c.getString(2).c_str(), "5000");

        db.close();
    }
    catch (const std::exception & e){
        std::cout << e.what() << std::endl;
    }
}

TEST_F(SQLiteDatabaseTestFixture, insert_test) {

    sqlite::SQLiteDatabase db;

    try{
        db.open(test_database_filename_, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);

        // Create Cars table test data
        const std::string kCreateTable =
                "CREATE TABLE IF NOT EXISTS cars "
                        "(mpg text, "
                        "weight text)";

        db.execQuery(kCreateTable);

        const std::string table = "cars";
        long id = db.insert(table, std::vector<std::string>{"mpg", "weight"}, std::vector<std::string>{"34", "2000"}, "", std::vector<std::string>{});
        long id2 = db.insert(table, std::vector<std::string>{"mpg", "weight"}, std::vector<std::string>{"20", "1500"}, "", std::vector<std::string>{});

        EXPECT_EQ(id, 1);
        EXPECT_EQ(id2, 2);

        db.close();
    }
        catch (const std::exception & e){
        std::cout << e.what() << std::endl;
    }
}

TEST_F(SQLiteDatabaseTestFixture, update_test) {

    sqlite::SQLiteDatabase db;

    try{
        db.open(test_database_filename_, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);

        // Create Cars table test data
        const std::string kCreateTable =
            "CREATE TABLE IF NOT EXISTS cars "
                "(mpg text, "
                "weight text)";

        db.execQuery(kCreateTable);

        const std::string table = "cars";
        long id = db.insert(table, std::vector<std::string>{"mpg", "weight"}, std::vector<std::string>{"34", "2000"}, "", std::vector<std::string>{});
        long id2 = db.insert(table, std::vector<std::string>{"mpg", "weight"}, std::vector<std::string>{"20", "1500"}, "", std::vector<std::string>{});

        int updated_rows = db.update(table, std::vector<std::string>{"mpg", "weight"}, std::vector<std::string>{"1", "1"}, "", std::vector<std::string>{});

        EXPECT_EQ(updated_rows, 2);

        db.close();
    }
    catch (const std::exception & e){
        std::cout << e.what() << std::endl;
    }
}
<|endoftext|>


<commit_before>#include <turbo/threading/shared_mutex.hpp>
#include <turbo/threading/shared_lock.hpp>
#include <turbo/threading/shared_lock.hxx>
#include <gtest/gtest.h>
#include <asio/io_service.hpp>
#include <functional>
#include <memory>
#include <string>
#include <thread>
#include <utility>

namespace tth = turbo::threading;

class write_task
{
public:
    write_task(tth::shared_mutex& mutex, std::string& shared_value);
    ~write_task();
    bool is_running() const { return thread_ != nullptr; }
    void start();
    void stop();
    template <typename then_f>
    void write(const std::string& value, then_f&& then_func);
private:
    void run();
    void exec_stop();
    template <typename then_f>
    void exec_write(std::string value, then_f&& then_func);
    tth::shared_mutex& mutex_;
    std::string& shared_value_;
    std::thread* thread_;
    asio::io_service service_;
};

write_task::write_task(tth::shared_mutex& mutex, std::string& shared_value)
    :
	mutex_(mutex),
	shared_value_(shared_value),
	thread_(nullptr),
	service_()
{ }

write_task::~write_task()
{
    stop();
    if (is_running())
    {
	thread_->join();
	delete thread_;
    }
}

void write_task::start()
{
    if (!is_running())
    {
	thread_ = new std::thread(std::bind(&write_task::run, this));
    }
}

void write_task::stop()
{
    service_.post(std::bind(&write_task::exec_stop, this));
}

void write_task::run()
{
    EXPECT_TRUE(1U <= service_.run());
    service_.reset();
}

template <typename then_f>
void write_task::write(const std::string& value, then_f&& then_func)
{
    service_.post([&]() -> void
    {
	this->exec_write<then_f>(value, std::forward<then_f&&>(then_func));
    });
}

void write_task::exec_stop()
{
    service_.stop();
}

template <typename then_f>
void write_task::exec_write(std::string value, then_f&& then_func)
{
    {
	std::unique_lock<tth::shared_mutex> lock(mutex_);
	shared_value_ = value;
    }
    then_func();
}

class read_task
{
public:
    read_task(tth::shared_mutex& mutex, std::string& shared_value, const std::string& expected_value);
    ~read_task();
    bool is_running() const { return thread_ != nullptr; }
    void start();
    void stop();
    void read();
private:
    void run();
    void exec_stop();
    void exec_read();
    tth::shared_mutex& mutex_;
    std::string& shared_value_;
    std::thread* thread_;
    asio::io_service service_;
    std::string expected_;
};

read_task::read_task(tth::shared_mutex& mutex, std::string& shared_value, const std::string& expected_value)
    :
	mutex_(mutex),
	shared_value_(shared_value),
	thread_(nullptr),
	service_(),
	expected_(expected_value)
{ }

read_task::~read_task()
{
    stop();
    if (is_running())
    {
	thread_->join();
	delete thread_;
    }
}

void read_task::start()
{
    if (!is_running())
    {
	thread_ = new std::thread(std::bind(&read_task::run, this));
    }
}

void read_task::stop()
{
    service_.post(std::bind(&read_task::exec_stop, this));
}

void read_task::run()
{
    EXPECT_TRUE(1U <= service_.run());
    service_.reset();
}

void read_task::read()
{
    service_.post([&]() -> void
    {
	this->exec_read();
    });
}

void read_task::exec_stop()
{
    service_.stop();
}

void read_task::exec_read()
{
    std::string value;
    {
	tth::shared_lock<tth::shared_mutex> lock(mutex_);
	value = shared_value_;
    }
    if (expected_ != value)
    {
	this->read();
    }
    else
    {
	EXPECT_EQ(expected_, value) << "read failed";
    }
}

TEST(shared_mutex_test, basic_read)
{
    tth::shared_mutex mutex1;
    std::string value1("foo");
    {
	read_task reader1(mutex1, value1, "foo");
	read_task reader2(mutex1, value1, "foo");
	read_task reader3(mutex1, value1, "foo");
	reader1.read();
	reader2.read();
	reader3.read();
	reader1.start();
	reader2.start();
	reader3.start();
    }
}

TEST(shared_mutex_test, basic_write)
{
    tth::shared_mutex mutex1;
    std::string value1("foo");
    {
	read_task reader1(mutex1, value1, "bar");
	read_task reader2(mutex1, value1, "bar");
	read_task reader3(mutex1, value1, "bar");
	write_task writer1(mutex1, value1);
	write_task writer2(mutex1, value1);
	reader1.read();
	reader2.read();
	reader3.read();
	writer1.write("bar", [&]() -> void { });
	writer2.write("bar", [&]() -> void { });
	reader1.start();
	reader2.start();
	reader3.start();
	writer1.start();
	writer2.start();
    }
}
<commit_msg>fixed a stale pointer read in the write member function because the lambda captured the value argument by reference but when the lambda is executed by io_service the value argument doesn't exist anymore<commit_after>#include <turbo/threading/shared_mutex.hpp>
#include <turbo/threading/shared_lock.hpp>
#include <turbo/threading/shared_lock.hxx>
#include <gtest/gtest.h>
#include <asio/io_service.hpp>
#include <algorithm>
#include <functional>
#include <memory>
#include <string>
#include <thread>
#include <utility>

namespace tth = turbo::threading;

class write_task
{
public:
    write_task(tth::shared_mutex& mutex, std::string& shared_value);
    ~write_task();
    bool is_running() const { return thread_ != nullptr; }
    void start();
    void stop();
    template <typename then_f>
    void write(const std::string& value, then_f&& then_func);
private:
    void run();
    void exec_stop();
    template <typename then_f>
    void exec_write(const std::string& value, then_f&& then_func);
    tth::shared_mutex& mutex_;
    std::string& shared_value_;
    std::thread* thread_;
    asio::io_service service_;
};

write_task::write_task(tth::shared_mutex& mutex, std::string& shared_value)
    :
	mutex_(mutex),
	shared_value_(shared_value),
	thread_(nullptr),
	service_()
{ }

write_task::~write_task()
{
    stop();
    if (is_running())
    {
	thread_->join();
	delete thread_;
    }
}

void write_task::start()
{
    if (!is_running())
    {
	thread_ = new std::thread(std::bind(&write_task::run, this));
    }
}

void write_task::stop()
{
    service_.post(std::bind(&write_task::exec_stop, this));
}

void write_task::run()
{
    EXPECT_TRUE(1U <= service_.run());
    service_.reset();
}

template <typename then_f>
void write_task::write(const std::string& value, then_f&& then_func)
{
    service_.post([this, value, &then_func]() -> void
    {
	this->exec_write<then_f>(value, std::forward<then_f&&>(then_func));
    });
}

void write_task::exec_stop()
{
    service_.stop();
}

template <typename then_f>
void write_task::exec_write(const std::string& value, then_f&& then_func)
{
    {
	std::unique_lock<tth::shared_mutex> lock(mutex_);
	shared_value_ = value;
    }
    then_func();
}

class read_task
{
public:
    read_task(tth::shared_mutex& mutex, std::string& shared_value, const std::string& expected_value);
    ~read_task();
    bool is_running() const { return thread_ != nullptr; }
    void start();
    void stop();
    void read();
private:
    void run();
    void exec_stop();
    void exec_read();
    tth::shared_mutex& mutex_;
    std::string& shared_value_;
    std::thread* thread_;
    asio::io_service service_;
    std::string expected_;
};

read_task::read_task(tth::shared_mutex& mutex, std::string& shared_value, const std::string& expected_value)
    :
	mutex_(mutex),
	shared_value_(shared_value),
	thread_(nullptr),
	service_(),
	expected_(expected_value)
{ }

read_task::~read_task()
{
    stop();
    if (is_running())
    {
	thread_->join();
	delete thread_;
    }
}

void read_task::start()
{
    if (!is_running())
    {
	thread_ = new std::thread(std::bind(&read_task::run, this));
    }
}

void read_task::stop()
{
    service_.post(std::bind(&read_task::exec_stop, this));
}

void read_task::run()
{
    EXPECT_TRUE(1U <= service_.run());
    service_.reset();
}

void read_task::read()
{
    service_.post([&]() -> void
    {
	this->exec_read();
    });
}

void read_task::exec_stop()
{
    service_.stop();
}

void read_task::exec_read()
{
    std::string value;
    {
	tth::shared_lock<tth::shared_mutex> lock(mutex_);
	value = shared_value_;
    }
    auto result = std::search(value.cbegin(), value.cend(), expected_.cbegin(), expected_.cend());
    if (result == value.cend())
    {
	this->read();
    }
    else
    {
	EXPECT_EQ(value.cbegin(), result) << "read failed";
    }
}

TEST(shared_mutex_test, basic_read)
{
    tth::shared_mutex mutex1;
    std::string value1("foo");
    {
	read_task reader1(mutex1, value1, "foo");
	read_task reader2(mutex1, value1, "foo");
	read_task reader3(mutex1, value1, "foo");
	reader1.read();
	reader2.read();
	reader3.read();
	reader1.start();
	reader2.start();
	reader3.start();
    }
}

TEST(shared_mutex_test, basic_write)
{
    tth::shared_mutex mutex1;
    std::string value1("foo");
    {
	read_task reader1(mutex1, value1, "bar");
	read_task reader2(mutex1, value1, "bar");
	read_task reader3(mutex1, value1, "bar");
	write_task writer1(mutex1, value1);
	write_task writer2(mutex1, value1);
	reader1.read();
	reader2.read();
	reader3.read();
	writer1.write("bar1", [&]() -> void { });
	writer2.write("bar2", [&]() -> void { });
	reader1.start();
	reader2.start();
	reader3.start();
	writer1.start();
	writer2.start();
    }
}
<|endoftext|>


<commit_before>///
/// @file      ar/test_utilities/tmp_file.cpp
/// @copyright (c) 2015 by Petr Zemek (s3rvac@gmail.com) and contributors
/// @license   MIT, see the @c LICENSE file for more details
/// @brief     Implementation of the temporary-file utilities.
///

#include <cstdio>
#include <fstream>
#include <random>

#include "ar/test_utilities/tmp_file.h"

namespace ar {
namespace tests {

namespace {

///
/// Returns a path to a unique, temporary file.
///
std::string getUniqueTemporaryFilePath() {
	// As the creation of a temporary file with accessible name in the standard
	// C++ is painful, simply create the temporary file in the current
	// directory. After all, this function is only used in tests.
	std::random_device rd;
	std::mt19937 mt{rd()};
	std::uniform_int_distribution<std::size_t> dist;
	return "ar-cpp-" + std::to_string(dist(mt)) + ".tmp";
}

} // anonymous namespace

///
/// Creates a temporary file with the given content.
///
TmpFile::TmpFile(const std::string& content):
		path{getUniqueTemporaryFilePath()} {
	std::ofstream file{path, std::ios::binary};
	file << content;
}

///
/// Removes the temporary file from the filesystem.
///
TmpFile::~TmpFile() {
	std::remove(path.c_str());
}

///
/// Returns a path to the file.
///
std::string TmpFile::getPath() const {
	return path;
}

///
/// Creates a temporary file with the given content.
///
std::unique_ptr<TmpFile> TmpFile::createWithContent(const std::string& content) {
	return std::make_unique<TmpFile>(content);
}

RemoveFileOnDestruction::RemoveFileOnDestruction(const std::string& path):
	path(path) {}

RemoveFileOnDestruction::~RemoveFileOnDestruction() {
	std::remove(path.c_str());
}

} // namespace tests
} // namespace ar
<commit_msg>Ensure that the created temporary files in tests are unique.<commit_after>///
/// @file      ar/test_utilities/tmp_file.cpp
/// @copyright (c) 2015 by Petr Zemek (s3rvac@gmail.com) and contributors
/// @license   MIT, see the @c LICENSE file for more details
/// @brief     Implementation of the temporary-file utilities.
///

#include <cstdio>
#include <fstream>
#include <random>

#include "ar/test_utilities/tmp_file.h"

namespace ar {
namespace tests {

namespace {

///
/// Returns a path to a unique, temporary file.
///
std::string getUniqueTemporaryFilePath() {
	// As the creation of a temporary file with accessible name in the standard
	// C++ is painful, simply create the temporary file in the current
	// directory. After all, this function is only used in tests.
	//
	// The use of static variables makes the code unsafe for threads, but since
	// we do not use threads in tests, it is OK. The problem is that at least
	// on Windows (MSYS2), std::random_device is only a pseudo-random number
	// generator that always generates the same sequence. Therefore, we
	// initialize the random number generator when the tests start (when
	// getUniqueTemporaryFilePath() is first called) and use it for all tests.
	static std::random_device rd;
	static std::mt19937 mt{rd()};
	static std::uniform_int_distribution<std::size_t> dist;
	return "ar-cpp-" + std::to_string(dist(mt)) + ".tmp";
}

} // anonymous namespace

///
/// Creates a temporary file with the given content.
///
TmpFile::TmpFile(const std::string& content):
		path{getUniqueTemporaryFilePath()} {
	std::ofstream file{path, std::ios::binary};
	file << content;
}

///
/// Removes the temporary file from the filesystem.
///
TmpFile::~TmpFile() {
	std::remove(path.c_str());
}

///
/// Returns a path to the file.
///
std::string TmpFile::getPath() const {
	return path;
}

///
/// Creates a temporary file with the given content.
///
std::unique_ptr<TmpFile> TmpFile::createWithContent(const std::string& content) {
	return std::make_unique<TmpFile>(content);
}

RemoveFileOnDestruction::RemoveFileOnDestruction(const std::string& path):
	path(path) {}

RemoveFileOnDestruction::~RemoveFileOnDestruction() {
	std::remove(path.c_str());
}

} // namespace tests
} // namespace ar
<|endoftext|>


<commit_before>/** @file
    @brief Test Implementation

    @date 2014

    @author
    Ryan Pavlik
    <ryan@sensics.com>
    <http://sensics.com>

*/

// Copyright 2014 Sensics, Inc.
//
// All rights reserved.
//
// (Final version intended to be licensed under
// the Apache License, Version 2.0)

// Internal Includes
#include <osvr/Routing/PathTreeFull.h>
#include <osvr/Routing/PathElementTools.h>
#include <osvr/Routing/PathElementTypes.h>

// Library/third-party includes
#include "gtest/gtest.h"

// Standard includes
// - none

using std::string;
using namespace osvr::routing;
// using osvr::routing::PathTree;
// namespace elements = osvr::routing::elements;

TEST(PathTree, create) { ASSERT_NO_THROW(PathTree()); }

TEST(PathTree, getPath) {
    PathTree tree;
    ASSERT_NO_THROW(tree.getNodeByPath("/test"));
    ASSERT_STREQ(getTypeName(tree.getNodeByPath("/test")), "NullElement");
    ASSERT_STREQ(elements::getTypeName<elements::NullElement>(), "NullElement");
    ASSERT_EQ(tree.getNodeByPath("/test").getName(), string("test"));
}<commit_msg>More tests.<commit_after>/** @file
    @brief Test Implementation

    @date 2014

    @author
    Ryan Pavlik
    <ryan@sensics.com>
    <http://sensics.com>

*/

// Copyright 2014 Sensics, Inc.
//
// All rights reserved.
//
// (Final version intended to be licensed under
// the Apache License, Version 2.0)

// Internal Includes
#include <osvr/Routing/PathTreeFull.h>
#include <osvr/Routing/PathElementTools.h>
#include <osvr/Routing/PathElementTypes.h>

// Library/third-party includes
#include "gtest/gtest.h"

// Standard includes
// - none

using std::string;
using namespace osvr::routing;
// using osvr::routing::PathTree;
// namespace elements = osvr::routing::elements;

TEST(PathTree, create) { ASSERT_NO_THROW(PathTree()); }

TEST(PathTree, getPath) {
    PathTree tree;
    ASSERT_NO_THROW(tree.getNodeByPath("/test"));
    ASSERT_STREQ(getTypeName(tree.getNodeByPath("/test")), "NullElement");
    ASSERT_STREQ(elements::getTypeName<elements::NullElement>(), "NullElement");
    ASSERT_EQ(tree.getNodeByPath("/test").getName(), "test");

    PathNode *result = NULL;
    ASSERT_NO_THROW(result = &tree.getNodeByPath("/test1/test2"));
    ASSERT_EQ(result->getName(), "test2");
}<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/QtCore>
#include <QtTest/QtTest>

class tst_Headers: public QObject
{
    Q_OBJECT
private slots:
    void initTestCase();

    void privateSlots_data() { allHeadersData(); }
    void privateSlots();

    void macros_data() { allHeadersData(); }
    void macros();

private:
    static QStringList getHeaders(const QString &path);
    static QString explainPrivateSlot(const QString &line);

    void allHeadersData();
    QStringList headers;
    QString qtModuleDir;
};

QStringList tst_Headers::getHeaders(const QString &path)
{
    QStringList result;

    QProcess git;
    git.setWorkingDirectory(path);
    git.start("git", QStringList() << "ls-files");

    // Wait for git to start
    if (!git.waitForStarted())
        qFatal("Error running 'git': %s", qPrintable(git.errorString()));

    // Continue reading the data until EOF reached
    QByteArray data;
    while (git.waitForReadyRead(-1))
        data.append(git.readAll());

    // wait until the process has finished
    if ((git.state() != QProcess::NotRunning) && !git.waitForFinished(30000))
        qFatal("'git ls-files' did not complete within 30 seconds: %s", qPrintable(git.errorString()));

    // Check for the git's exit code
    if (0 != git.exitCode())
        qFatal("Error running 'git ls-files': %s", qPrintable(git.readAllStandardError()));

    // Create a QStringList of files out of the standard output
    QString string(data);
    QStringList entries = string.split( "\n" );

    // We just want to check header files
    entries = entries.filter(QRegExp("\\.h$"));
    entries = entries.filter(QRegExp("^(?!ui_)"));

    // Recreate the whole file path so we can open the file from disk
    foreach (QString entry, entries)
        result += path + "/" + entry;

    return result;
}

void tst_Headers::initTestCase()
{
    qtModuleDir = QString::fromLocal8Bit(qgetenv("QT_MODULE_TO_TEST"));
    if (qtModuleDir.isEmpty()) {
        QSKIP("$QT_MODULE_TO_TEST is unset - nothing to test.  Set QT_MODULE_TO_TEST to the path "
              "of a Qt module to test.");
    }

    QDir dir(qtModuleDir);
    QString module = dir.dirName(); // git module name, e.g. qtbase, qtdeclarative

    if (module != "phonon" && module != "qttools") {
        if (dir.exists("src")) {

            /*
                Let all paths be relative to the directory containing the module.
                For example, if the full path is:

                    /home/qt/build/qt5/qtbase/src/corelib/tools/qstring.h

                ... the first part of the path is useless noise, and causes the
                test log to look different on different machines.
                Cut it down to only the important part:

                    qtbase/src/corelib/tools/qstring.h

            */

            QVERIFY(QDir::setCurrent(dir.absolutePath() + "/.."));

            headers = getHeaders(module + "/src");
        }
        if (headers.isEmpty()) {
            QSKIP("It seems there are no headers in this module; this test is "
                  "not applicable");
        }
    } else {
        QWARN("Some test functions will be skipped, because we ignore them for phonon and qttools.");
    }
}

void tst_Headers::allHeadersData()
{
    QTest::addColumn<QString>("header");

    if (headers.isEmpty())
        QSKIP("can't find any headers in your $QT_MODULE_TO_TEST/src.");

    foreach (QString hdr, headers) {
        if (hdr.contains("/3rdparty/") || hdr.endsWith("/src/tools/uic/qclass_lib_map.h"))
            continue;

        QTest::newRow(qPrintable(hdr)) << hdr;
    }
}

QString tst_Headers::explainPrivateSlot(const QString& line)
{
    // Extract private slot from a line like:
    //  Q_PRIVATE_SLOT(d_func(), void fooBar(...))
    QRegExp re("^\\s+Q_PRIVATE_SLOT\\([^,]+,\\s*(.+)\\)\\s*$");
    QString slot = line;
    if (re.indexIn(slot) != -1) {
        slot = re.cap(1).simplified();
    }

    return QString(
        "Private slot `%1' should be named starting with _q_, to reduce the risk of collisions "
        "with signals/slots in user classes"
    ).arg(slot);
}

void tst_Headers::privateSlots()
{
    QFETCH(QString, header);

    QFile f(header);
    QVERIFY2(f.open(QIODevice::ReadOnly), qPrintable(f.errorString()));

    QStringList content = QString::fromLocal8Bit(f.readAll()).split("\n");
    foreach (QString line, content) {
        if (line.contains("Q_PRIVATE_SLOT(") && !line.contains("define Q_PRIVATE_SLOT"))
            QVERIFY2(line.contains("_q_"), qPrintable(explainPrivateSlot(line)));
    }
}

void tst_Headers::macros()
{
    QFETCH(QString, header);

    if (header.endsWith("_p.h") || header.endsWith("_pch.h")
        || header.contains("global/qconfig-") || header.endsWith("/qconfig.h")
        || header.contains("/src/tools/") || header.contains("/src/plugins/")
        || header.contains("/src/imports/")
        || header.contains("/src/uitools/")
        || header.endsWith("/qiconset.h") || header.endsWith("/qfeatures.h")
        || header.endsWith("qt_windows.h"))
        return;

    QFile f(header);
    QVERIFY2(f.open(QIODevice::ReadOnly), qPrintable(f.errorString()));

    QByteArray data = f.readAll();
    QStringList content = QString::fromLocal8Bit(data.replace('\r', "")).split("\n");

    int beginHeader = content.indexOf("QT_BEGIN_HEADER");
    int endHeader = content.lastIndexOf("QT_END_HEADER");

    QVERIFY(beginHeader >= 0);
    QVERIFY(endHeader >= 0);
    QVERIFY(beginHeader < endHeader);

    // "signals" and "slots" should be banned in public headers
    // headers which use signals/slots wouldn't compile if Qt is configured with QT_NO_KEYWORDS
    QVERIFY2(content.indexOf(QRegExp("\\bslots\\s*:")) == -1, "Header contains `slots' - use `Q_SLOTS' instead!");
    QVERIFY2(content.indexOf(QRegExp("\\bsignals\\s*:")) == -1, "Header contains `signals' - use `Q_SIGNALS' instead!");

    if (header.contains("/sql/drivers/") || header.contains("/arch/qatomic")
        || header.endsWith("qglobal.h")
        || header.endsWith("qwindowdefs_win.h"))
        return;

    int qtmodule = content.indexOf(QRegExp("^QT_MODULE\\(.*\\)$"));
    QVERIFY(qtmodule != -1);
    QVERIFY(qtmodule > beginHeader);
    QVERIFY(qtmodule < endHeader);

    int beginNamespace = content.indexOf("QT_BEGIN_NAMESPACE");
    int endNamespace = content.lastIndexOf("QT_END_NAMESPACE");
    QVERIFY(beginNamespace != -1);
    QVERIFY(endNamespace != -1);
    QVERIFY(beginHeader < beginNamespace);
    QVERIFY(beginNamespace < endNamespace);
    QVERIFY(endNamespace < endHeader);
}

QTEST_MAIN(tst_Headers)
#include "tst_headers.moc"
<commit_msg>tst_headers: exclude internal class from privateSlots() check<commit_after>/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/QtCore>
#include <QtTest/QtTest>

class tst_Headers: public QObject
{
    Q_OBJECT
private slots:
    void initTestCase();

    void privateSlots_data() { allHeadersData(); }
    void privateSlots();

    void macros_data() { allHeadersData(); }
    void macros();

private:
    static QStringList getHeaders(const QString &path);
    static QString explainPrivateSlot(const QString &line);

    void allHeadersData();
    QStringList headers;
    QString qtModuleDir;
};

QStringList tst_Headers::getHeaders(const QString &path)
{
    QStringList result;

    QProcess git;
    git.setWorkingDirectory(path);
    git.start("git", QStringList() << "ls-files");

    // Wait for git to start
    if (!git.waitForStarted())
        qFatal("Error running 'git': %s", qPrintable(git.errorString()));

    // Continue reading the data until EOF reached
    QByteArray data;
    while (git.waitForReadyRead(-1))
        data.append(git.readAll());

    // wait until the process has finished
    if ((git.state() != QProcess::NotRunning) && !git.waitForFinished(30000))
        qFatal("'git ls-files' did not complete within 30 seconds: %s", qPrintable(git.errorString()));

    // Check for the git's exit code
    if (0 != git.exitCode())
        qFatal("Error running 'git ls-files': %s", qPrintable(git.readAllStandardError()));

    // Create a QStringList of files out of the standard output
    QString string(data);
    QStringList entries = string.split( "\n" );

    // We just want to check header files
    entries = entries.filter(QRegExp("\\.h$"));
    entries = entries.filter(QRegExp("^(?!ui_)"));

    // Recreate the whole file path so we can open the file from disk
    foreach (QString entry, entries)
        result += path + "/" + entry;

    return result;
}

void tst_Headers::initTestCase()
{
    qtModuleDir = QString::fromLocal8Bit(qgetenv("QT_MODULE_TO_TEST"));
    if (qtModuleDir.isEmpty()) {
        QSKIP("$QT_MODULE_TO_TEST is unset - nothing to test.  Set QT_MODULE_TO_TEST to the path "
              "of a Qt module to test.");
    }

    QDir dir(qtModuleDir);
    QString module = dir.dirName(); // git module name, e.g. qtbase, qtdeclarative

    if (module != "phonon" && module != "qttools") {
        if (dir.exists("src")) {

            /*
                Let all paths be relative to the directory containing the module.
                For example, if the full path is:

                    /home/qt/build/qt5/qtbase/src/corelib/tools/qstring.h

                ... the first part of the path is useless noise, and causes the
                test log to look different on different machines.
                Cut it down to only the important part:

                    qtbase/src/corelib/tools/qstring.h

            */

            QVERIFY(QDir::setCurrent(dir.absolutePath() + "/.."));

            headers = getHeaders(module + "/src");
        }
        if (headers.isEmpty()) {
            QSKIP("It seems there are no headers in this module; this test is "
                  "not applicable");
        }
    } else {
        QWARN("Some test functions will be skipped, because we ignore them for phonon and qttools.");
    }
}

void tst_Headers::allHeadersData()
{
    QTest::addColumn<QString>("header");

    if (headers.isEmpty())
        QSKIP("can't find any headers in your $QT_MODULE_TO_TEST/src.");

    foreach (QString hdr, headers) {
        if (hdr.contains("/3rdparty/") || hdr.endsWith("/src/tools/uic/qclass_lib_map.h"))
            continue;

        QTest::newRow(qPrintable(hdr)) << hdr;
    }
}

QString tst_Headers::explainPrivateSlot(const QString& line)
{
    // Extract private slot from a line like:
    //  Q_PRIVATE_SLOT(d_func(), void fooBar(...))
    QRegExp re("^\\s+Q_PRIVATE_SLOT\\([^,]+,\\s*(.+)\\)\\s*$");
    QString slot = line;
    if (re.indexIn(slot) != -1) {
        slot = re.cap(1).simplified();
    }

    return QString(
        "Private slot `%1' should be named starting with _q_, to reduce the risk of collisions "
        "with signals/slots in user classes"
    ).arg(slot);
}

void tst_Headers::privateSlots()
{
    QFETCH(QString, header);

    if (header.endsWith("_p.h"))
        return;

    QFile f(header);
    QVERIFY2(f.open(QIODevice::ReadOnly), qPrintable(f.errorString()));

    QStringList content = QString::fromLocal8Bit(f.readAll()).split("\n");
    foreach (QString line, content) {
        if (line.contains("Q_PRIVATE_SLOT(") && !line.contains("define Q_PRIVATE_SLOT"))
            QVERIFY2(line.contains("_q_"), qPrintable(explainPrivateSlot(line)));
    }
}

void tst_Headers::macros()
{
    QFETCH(QString, header);

    if (header.endsWith("_p.h") || header.endsWith("_pch.h")
        || header.contains("global/qconfig-") || header.endsWith("/qconfig.h")
        || header.contains("/src/tools/") || header.contains("/src/plugins/")
        || header.contains("/src/imports/")
        || header.contains("/src/uitools/")
        || header.endsWith("/qiconset.h") || header.endsWith("/qfeatures.h")
        || header.endsWith("qt_windows.h"))
        return;

    QFile f(header);
    QVERIFY2(f.open(QIODevice::ReadOnly), qPrintable(f.errorString()));

    QByteArray data = f.readAll();
    QStringList content = QString::fromLocal8Bit(data.replace('\r', "")).split("\n");

    int beginHeader = content.indexOf("QT_BEGIN_HEADER");
    int endHeader = content.lastIndexOf("QT_END_HEADER");

    QVERIFY(beginHeader >= 0);
    QVERIFY(endHeader >= 0);
    QVERIFY(beginHeader < endHeader);

    // "signals" and "slots" should be banned in public headers
    // headers which use signals/slots wouldn't compile if Qt is configured with QT_NO_KEYWORDS
    QVERIFY2(content.indexOf(QRegExp("\\bslots\\s*:")) == -1, "Header contains `slots' - use `Q_SLOTS' instead!");
    QVERIFY2(content.indexOf(QRegExp("\\bsignals\\s*:")) == -1, "Header contains `signals' - use `Q_SIGNALS' instead!");

    if (header.contains("/sql/drivers/") || header.contains("/arch/qatomic")
        || header.endsWith("qglobal.h")
        || header.endsWith("qwindowdefs_win.h"))
        return;

    int qtmodule = content.indexOf(QRegExp("^QT_MODULE\\(.*\\)$"));
    QVERIFY(qtmodule != -1);
    QVERIFY(qtmodule > beginHeader);
    QVERIFY(qtmodule < endHeader);

    int beginNamespace = content.indexOf("QT_BEGIN_NAMESPACE");
    int endNamespace = content.lastIndexOf("QT_END_NAMESPACE");
    QVERIFY(beginNamespace != -1);
    QVERIFY(endNamespace != -1);
    QVERIFY(beginHeader < beginNamespace);
    QVERIFY(beginNamespace < endNamespace);
    QVERIFY(endNamespace < endHeader);
}

QTEST_MAIN(tst_Headers)
#include "tst_headers.moc"
<|endoftext|>


<commit_before>#include "NWUnitTest.h"

#include <locale.h>

#ifdef __linux
#include "NanoWinStrConvert.h"
#else
#include <windows.h>
#endif

NW_BEGIN_TEST_GROUP(NanoWinStrConvertTestGroup)
NW_BEGIN_SETUP_TEARDOWN
NW_SETUP_METHOD()
 {
  setlocale(LC_CTYPE,"en_US.UTF-8");
 }
NW_END_SETUP_TEARDOWN

NW_TEST(NanoWinStrConvertTestGroup,TestW2AASCIIOnlyConversion)
 {
  std::string result = NanoWin::StrConverter::Convert(std::wstring(L"hello"));

  NW_CHECK_EQUAL_STRCMP("hello",result.c_str());
 }

NW_TEST(NanoWinStrConvertTestGroup,TestW2AEmptyStringConversion)
 {
  std::string result = NanoWin::StrConverter::Convert(std::wstring(L""));

  NW_CHECK_EQUAL_STRCMP("",result.c_str());
 }

NW_TEST(NanoWinStrConvertTestGroup,TestW2ACyrillicStringConversion)
 {
  std::string result;

  try
   {
    result = NanoWin::StrConverter::Convert(std::wstring(L"привет"));
   }
  catch (...)
   {
   }

  NW_CHECK_EQUAL_STRCMP("привет",result.c_str());
 }

NW_TEST(NanoWinStrConvertTestGroup,TestA2WASCIIOnlyConversion)
 {
  std::wstring result = NanoWin::StrConverter::Convert(std::string("hello"));

  size_t len = wcslen(L"hello");

  NW_CHECK_EQUAL_ULONGS(len,result.length());

  NW_CHECK_EQUAL_MEMCMP(L"hello",result.c_str(),len * sizeof(wchar_t));
 }

NW_TEST(NanoWinStrConvertTestGroup,TestA2WEmptyStringConversion)
 {
  std::wstring result = NanoWin::StrConverter::Convert(std::string(""));

  NW_CHECK_EQUAL_ULONGS(0,result.length());
 }

NW_TEST(NanoWinStrConvertTestGroup,TestA2WCyrillicStringConversion)
 {
  std::wstring result;

  try
   {
    result = NanoWin::StrConverter::Convert(std::string("привет"));
   }
  catch (...)
   {
   }

  size_t len = wcslen(L"привет");

  NW_CHECK_EQUAL_ULONGS(len,result.length());

  NW_CHECK_EQUAL_MEMCMP(L"привет",result.c_str(),len * sizeof(wchar_t));
 }

NW_TEST(NanoWinStrConvertTestGroup,TestA2WCoreanStringConversion)
 {
  std::wstring result;

  try
   {
    result = NanoWin::StrConverter::Convert(std::string("안녕"));
   }
  catch (...)
   {
   }

  size_t len = wcslen(L"안녕");

  NW_CHECK_EQUAL_ULONGS(len,result.length());

  NW_CHECK_EQUAL_MEMCMP(L"안녕",result.c_str(),len * sizeof(wchar_t));
 }

NW_TEST(NanoWinStrConvertTestGroup,TestW2ACoreanStringConversion)
 {
  std::string result;

  try
   {
    result = NanoWin::StrConverter::Convert(std::wstring(L"안녕"));
   }
  catch (...)
   {
   }

  NW_CHECK_EQUAL_STRCMP("안녕",result.c_str());
 }

NW_TEST(NanoWinStrConvertTestGroup,TestA2WHebrewStringConversion)
 {
  std::wstring result;

  try
   {
    result = NanoWin::StrConverter::Convert(std::string("ד'ש"));
   }
  catch (...)
   {
   }

  size_t len = wcslen(L"ד'ש");

  NW_CHECK_EQUAL_ULONGS(len,result.length());

  NW_CHECK_EQUAL_MEMCMP(L"ד'ש",result.c_str(),len * sizeof(wchar_t));
 }

NW_TEST(NanoWinStrConvertTestGroup,TestW2AHebrewStringConversion)
 {
  std::string result;

  try
   {
    result = NanoWin::StrConverter::Convert(std::wstring(L"ד'ש"));
   }
  catch (...)
   {
   }

  NW_CHECK_EQUAL_STRCMP("ד'ש",result.c_str());
 }

NW_END_TEST_GROUP()
<commit_msg>unit tests for MultiByteToWideChar and WideCharToMultiByte functions added<commit_after>#include "NWUnitTest.h"

#include <locale.h>
#include <string.h>

#include "NanoWinStrConvert.h"

#ifdef __linux
#else
#include <windows.h>
#endif

#ifdef LINUX // linux-only tests

NW_BEGIN_TEST_GROUP(NanoWinStrConvertTestGroup)
NW_BEGIN_SETUP_TEARDOWN
NW_SETUP_METHOD()
 {
  setlocale(LC_CTYPE,"en_US.UTF-8");
 }
NW_END_SETUP_TEARDOWN

NW_TEST(NanoWinStrConvertTestGroup,TestW2AASCIIOnlyConversion)
 {
  std::string result = NanoWin::StrConverter::Convert(std::wstring(L"hello"));

  NW_CHECK_EQUAL_STRCMP("hello",result.c_str());
 }

NW_TEST(NanoWinStrConvertTestGroup,TestW2AEmptyStringConversion)
 {
  std::string result = NanoWin::StrConverter::Convert(std::wstring(L""));

  NW_CHECK_EQUAL_STRCMP("",result.c_str());
 }

NW_TEST(NanoWinStrConvertTestGroup,TestW2ACyrillicStringConversion)
 {
  std::string result;

  try
   {
    result = NanoWin::StrConverter::Convert(std::wstring(L"привет"));
   }
  catch (...)
   {
   }

  NW_CHECK_EQUAL_STRCMP("привет",result.c_str());
 }

NW_TEST(NanoWinStrConvertTestGroup,TestA2WASCIIOnlyConversion)
 {
  std::wstring result = NanoWin::StrConverter::Convert(std::string("hello"));

  size_t len = wcslen(L"hello");

  NW_CHECK_EQUAL_ULONGS(len,result.length());

  NW_CHECK_EQUAL_MEMCMP(L"hello",result.c_str(),len * sizeof(wchar_t));
 }

NW_TEST(NanoWinStrConvertTestGroup,TestA2WEmptyStringConversion)
 {
  std::wstring result = NanoWin::StrConverter::Convert(std::string(""));

  NW_CHECK_EQUAL_ULONGS(0,result.length());
 }

NW_TEST(NanoWinStrConvertTestGroup,TestA2WCyrillicStringConversion)
 {
  std::wstring result;

  try
   {
    result = NanoWin::StrConverter::Convert(std::string("привет"));
   }
  catch (...)
   {
   }

  size_t len = wcslen(L"привет");

  NW_CHECK_EQUAL_ULONGS(len,result.length());

  NW_CHECK_EQUAL_MEMCMP(L"привет",result.c_str(),len * sizeof(wchar_t));
 }

NW_TEST(NanoWinStrConvertTestGroup,TestA2WCoreanStringConversion)
 {
  std::wstring result;

  try
   {
    result = NanoWin::StrConverter::Convert(std::string("안녕"));
   }
  catch (...)
   {
   }

  size_t len = wcslen(L"안녕");

  NW_CHECK_EQUAL_ULONGS(len,result.length());

  NW_CHECK_EQUAL_MEMCMP(L"안녕",result.c_str(),len * sizeof(wchar_t));
 }

NW_TEST(NanoWinStrConvertTestGroup,TestW2ACoreanStringConversion)
 {
  std::string result;

  try
   {
    result = NanoWin::StrConverter::Convert(std::wstring(L"안녕"));
   }
  catch (...)
   {
   }

  NW_CHECK_EQUAL_STRCMP("안녕",result.c_str());
 }

NW_TEST(NanoWinStrConvertTestGroup,TestA2WHebrewStringConversion)
 {
  std::wstring result;

  try
   {
    result = NanoWin::StrConverter::Convert(std::string("ד'ש"));
   }
  catch (...)
   {
   }

  size_t len = wcslen(L"ד'ש");

  NW_CHECK_EQUAL_ULONGS(len,result.length());

  NW_CHECK_EQUAL_MEMCMP(L"ד'ש",result.c_str(),len * sizeof(wchar_t));
 }

NW_TEST(NanoWinStrConvertTestGroup,TestW2AHebrewStringConversion)
 {
  std::string result;

  try
   {
    result = NanoWin::StrConverter::Convert(std::wstring(L"ד'ש"));
   }
  catch (...)
   {
   }

  NW_CHECK_EQUAL_STRCMP("ד'ש",result.c_str());
 }

NW_END_TEST_GROUP()

#endif // linux only

NW_BEGIN_TEST_GROUP(NanoWinStrConvertWin32APITestGroup)
NW_BEGIN_SETUP_TEARDOWN
NW_SETUP_METHOD()
 {
//  setlocale(LC_CTYPE,"en_US.UTF-8");
 }
NW_END_SETUP_TEARDOWN

NW_TEST(NanoWinStrConvertWin32APITestGroup,MultiByteToWideCharImplicitSize)
 {
  #define LEN (128)

  const char helloStr[] = "hello";
  const wchar_t helloWStr[] = L"hello";

  wchar_t dest[LEN];

  memset(dest,'z',sizeof(dest));

  int result = MultiByteToWideChar(CP_ACP,0,helloStr,-1,dest,LEN);

  NW_CHECK_EQUAL_INTS(6,result);
  NW_CHECK_EQUAL_MEMCMP(helloWStr,dest,sizeof(helloWStr));

  #undef LEN
 }

NW_TEST(NanoWinStrConvertWin32APITestGroup,MultiByteToWideCharExplicitSizeWithNullTerminator)
 {
  #define LEN (128)

  const char helloStr[] = "hello";
  const wchar_t helloWStr[] = L"hello";

  wchar_t dest[LEN];

  memset(dest,'z',sizeof(dest));

  int result = MultiByteToWideChar(CP_ACP,0,helloStr,6,dest,LEN);

  NW_CHECK_EQUAL_INTS(6,result);
  NW_CHECK_EQUAL_MEMCMP(helloWStr,dest,sizeof(helloWStr));

  #undef LEN
 }

NW_TEST(NanoWinStrConvertWin32APITestGroup,MultiByteToWideCharExplicitSizeNoNullTerminator)
 {
  #define LEN (128)

  const char helloStr[] = "hello";
  const wchar_t helloWStr[] = L"hello";

  wchar_t dest[LEN];
  unsigned char *dest_bytes = (unsigned char*)dest;

  memset(dest,'z',sizeof(dest));

  int result = MultiByteToWideChar(CP_ACP,0,helloStr,2,dest,LEN);

  NW_CHECK_EQUAL_INTS(2,result);
  NW_CHECK_EQUAL_MEMCMP(helloWStr,dest,2 * sizeof(wchar_t));

  NW_CHECK_EQUAL_BYTES('z',dest_bytes[2 * sizeof(wchar_t)]);

  #undef LEN
 }

NW_TEST(NanoWinStrConvertWin32APITestGroup,MultiByteToWideCharCbMultiByteIsZeroFails)
 {
  #define LEN (128)

  const char helloStr[] = "hello";

  wchar_t dest[LEN];
  unsigned char *dest_bytes = (unsigned char*)dest;

  memset(dest,'z',sizeof(dest));

  int result = MultiByteToWideChar(CP_ACP,0,helloStr,0,dest,LEN);

  NW_CHECK_EQUAL_INTS(0,result);
  NW_CHECK_EQUAL_BYTES('z',dest_bytes[0]);

  #undef LEN
 }

NW_TEST(NanoWinStrConvertWin32APITestGroup,MultiByteToWideCharCchWideCharIsZeroSucceeds)
 {
  #define LEN (128)

  const char helloStr[] = "hello";

  wchar_t dest[LEN];
  unsigned char *dest_bytes = (unsigned char*)dest;

  memset(dest,'z',sizeof(dest));

  int result = MultiByteToWideChar(CP_ACP,0,helloStr,-1,dest,0);

  NW_CHECK_EQUAL_INTS(6,result);
  NW_CHECK_EQUAL_BYTES('z',dest_bytes[0]);

  #undef LEN
 }

NW_TEST(NanoWinStrConvertWin32APITestGroup,MultiByteToWideCharSmallBufferFails)
 {
  #define LEN (128)

  const char helloStr[] = "hello";

  wchar_t dest[LEN];

  memset(dest,'z',sizeof(dest));

  int result = MultiByteToWideChar(CP_ACP,0,helloStr,-1,dest,2);

  NW_CHECK_EQUAL_INTS(0,result);

  #undef LEN
 }

NW_TEST(NanoWinStrConvertWin32APITestGroup,WideCharToMultiByteImplicitSize)
 {
  #define LEN (128)

  const char helloStr[] = "hello";
  const wchar_t helloWStr[] = L"hello";

  char dest[LEN];

  memset(dest,'z',sizeof(dest));

  int result = WideCharToMultiByte(CP_ACP,0,helloWStr,-1,dest,LEN,NULL,NULL);

  NW_CHECK_EQUAL_INTS(6,result);
  NW_CHECK_EQUAL_STRCMP(helloStr,dest);

  #undef LEN
 }

NW_TEST(NanoWinStrConvertWin32APITestGroup,WideCharToMultiByteExplicitSizeWithNullTerminator)
 {
  #define LEN (128)

  const char helloStr[] = "hello";
  const wchar_t helloWStr[] = L"hello";

  char dest[LEN];

  memset(dest,'z',sizeof(dest));

  int result = WideCharToMultiByte(CP_ACP,0,helloWStr,6,dest,LEN,NULL,NULL);

  NW_CHECK_EQUAL_INTS(6,result);
  NW_CHECK_EQUAL_STRCMP(helloStr,dest);

  #undef LEN
 }

NW_TEST(NanoWinStrConvertWin32APITestGroup,WideCharToMultiByteExplicitSizeNoNullTerminator)
 {
  #define LEN (128)

  const char helloStr[] = "hello";
  const wchar_t helloWStr[] = L"hello";

  char dest[LEN];

  memset(dest,'z',sizeof(dest));

  int result = WideCharToMultiByte(CP_ACP,0,helloWStr,2,dest,LEN,NULL,NULL);

  NW_CHECK_EQUAL_INTS(2,result);
  NW_CHECK_EQUAL_MEMCMP(helloStr,dest,2);

  NW_CHECK_EQUAL_BYTES('z',dest[2]);

  #undef LEN
 }

NW_TEST(NanoWinStrConvertWin32APITestGroup,WideCharToMultiByteCchWideCharIsZeroFails)
 {
  #define LEN (128)

  const wchar_t helloWStr[] = L"hello";

  char dest[LEN];

  memset(dest,'z',sizeof(dest));

  int result = WideCharToMultiByte(CP_ACP,0,helloWStr,0,dest,LEN,NULL,NULL);

  NW_CHECK_EQUAL_INTS(0,result);
  NW_CHECK_EQUAL_BYTES('z',dest[0]);

  #undef LEN
 }

NW_TEST(NanoWinStrConvertWin32APITestGroup,WideCharToMultiByteCbMultiByteIsZeroSucceeds)
 {
  #define LEN (128)

  const wchar_t helloWStr[] = L"hello";

  char dest[LEN];

  memset(dest,'z',sizeof(dest));

  int result = WideCharToMultiByte(CP_ACP,0,helloWStr,-1,dest,0,NULL,NULL);

  NW_CHECK_EQUAL_INTS(6,result);
  NW_CHECK_EQUAL_BYTES('z',dest[0]);

  #undef LEN
 }

NW_TEST(NanoWinStrConvertWin32APITestGroup,WideCharToMultiByteSmallBufferFails)
 {
  #define LEN (128)

  const wchar_t helloWStr[] = L"hello";

  char dest[LEN];

  memset(dest,'z',sizeof(dest));

  int result = WideCharToMultiByte(CP_ACP,0,helloWStr,-1,dest,2,NULL,NULL);

  NW_CHECK_EQUAL_INTS(0,result);

  #undef LEN
 }

NW_END_TEST_GROUP()

<|endoftext|>