<commit_before>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015-2018 Morwenn
 *
 * 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 <algorithm>
#include <array>
#include <atomic>
#include <cstddef>
#include <exception>
#include <functional>
#include <iostream>
#include <iterator>
#include <thread>
#include <type_traits>
#include <utility>
#include <vector>
#include <cpp-sort/detail/bitops.h>
#include <cpp-sort/fixed/sorting_network_sorter.h>
#include <cpp-sort/sort.h>

#define CPPSORT_LIKELY(x) __builtin_expect((x), 1)
#define CPPSORT_UNLIKELY(x) __builtin_expect((x), 0)

////////////////////////////////////////////////////////////
// Dedicated algorithm to find all permutations of an array
// of 0 and 1 and play an algorithm to each permutation,
// notably using a Gray code progression to find every
// permutation

template<typename RandomAccessIterator, typename T, std::size_t N, typename Function>
auto for_each_gray_permutation_inner(RandomAccessIterator first, RandomAccessIterator last,
                                     std::array<T, N>& collection, Function func)
    -> bool
{
    using unsigned_t = std::make_unsigned_t<
        cppsort::detail::difference_type_t<RandomAccessIterator>
    >;
    unsigned_t counter = 0u;

    unsigned_t end = 1 << (last - first);  // 2^n permutations
    for (unsigned_t nb_permutations = 0 ; nb_permutations != end ; nb_permutations += 2) {

        // Flip value for even counter
        if (CPPSORT_UNLIKELY(not func(collection))) {
            return false;
        }
        counter ^= 1u;
        first[0u] = 1 - first[0u];

        // Flip value for odd counter
        if (CPPSORT_UNLIKELY(not func(collection))) {
            return false;
        }
        auto y = counter & -counter;
        counter ^= (y << 1);
        auto to_flip = cppsort::detail::log2(y) + 1;
        first[to_flip] = 1 - first[to_flip];
    }
    return true;
}

template<typename T, std::size_t N, typename Function>
auto for_each_gray_permutation(std::array<T, N>& collection, Function func)
    -> void
{
    using iterator = typename std::array<T, N>::iterator;
    using unsigned_t = std::make_unsigned_t<
        cppsort::detail::difference_type_t<iterator>
    >;

    unsigned_t size = collection.size();
    // Compute the "header" of bits before launching parallel jobs
    unsigned_t header_size = cppsort::detail::log2(std::thread::hardware_concurrency());

    if (size <= 20 || size < header_size) {
        // The problem size is small enough or we can't gain
        // enough from parallel jobs, go full sequential
        for_each_gray_permutation_inner(std::begin(collection), std::end(collection),
                                        collection, std::move(func));
    } else {
        // The goal of the following algorithm is to use a many threads as possible, etc.
        std::vector<std::thread> jobs;

        auto first = std::begin(collection);
        for_each_gray_permutation_inner(first, first + header_size, collection, [&](std::array<T, N>& arr) {
            auto copy = arr;
            jobs.emplace_back(for_each_gray_permutation_inner<iterator, T, N, Function&>,
                              std::begin(copy) + header_size, std::end(copy),
                              std::ref(copy), std::ref(func));
            return true;
        });

        // Join the jobs before exiting
        for (auto& job: jobs) {
            job.join();
        }
    }
}

////////////////////////////////////////////////////////////
// Count the number of comparisons

template<typename T, std::size_t N>
auto validate_sorting_network()
    -> void
{
    if (N < 2) return;

    std::cout << "sorting network of size " << N << ": ";

    cppsort::sorting_network_sorter<N> sorter;
    std::array<T, N> collection;
    std::fill(std::begin(collection), std::end(collection), 0);

    std::atomic<bool> error_occurred(false);
    bool expected = false;
    for_each_gray_permutation(collection, [&](std::array<T, N>& arr) {
        // Copy then sort collection
        std::array<int, N> to_sort = arr;
        sorter(to_sort);

        // Check whether it is sorted
        if (not std::is_sorted(std::begin(to_sort), std::end(to_sort))) {
            if (error_occurred.compare_exchange_strong(expected, true)) {
                // Log the faulty array
                std::cout << "\n  failed to sort the following input:\n  ";
                for (const auto& value: arr) {
                    std::cout << value << ' ';
                }
                std::cout << "\n  got the following output:\n  ";
                for (const auto& value: to_sort) {
                    std::cout << value << ' ';
                }
                std::cout << '\n';
            }
            // Abort for this size
            return false;
        }
        return true;
    });
    std::cout << "ok\n";
}

template<typename T, std::size_t... Indices>
auto validate_sorting_networks(std::index_sequence<Indices...>)
    -> void
{
    // Variadic dispatch only works with expressions
    int dummy[] = {
        (validate_sorting_network<T, Indices + 1>(), 0)...
    };
    (void) dummy;
}

////////////////////////////////////////////////////////////
// Main

int main()
{
    // The zero-one principle states that a sorting network is
    // valid if it can sort all the permutations of 0 and 1 for
    // a given size of array. This program uses this principle
    // to validate the sorting networks in O(2^n) instead of
    // the slower O(n!).

    // Best time to check all sorting networks to date: 536s

    // Sizes of the sorting networks to validate
    using indices = std::make_index_sequence<26>;

    validate_sorting_networks<int>(indices{});
}
<commit_msg>Simplify validate_sorting_networks a bit<commit_after>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015-2020 Morwenn
 *
 * 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 <algorithm>
#include <array>
#include <atomic>
#include <cstddef>
#include <exception>
#include <functional>
#include <iostream>
#include <iterator>
#include <thread>
#include <type_traits>
#include <utility>
#include <vector>
#include <cpp-sort/detail/bitops.h>
#include <cpp-sort/fixed/sorting_network_sorter.h>
#include <cpp-sort/sort.h>

#define CPPSORT_LIKELY(x) __builtin_expect((x), 1)
#define CPPSORT_UNLIKELY(x) __builtin_expect((x), 0)

////////////////////////////////////////////////////////////
// Dedicated algorithm to find all permutations of an array
// of 0 and 1 and play an algorithm to each permutation,
// notably using a Gray code progression to find every
// permutation

template<typename RandomAccessIterator, typename T, std::size_t N, typename Function>
auto for_each_gray_permutation_inner(RandomAccessIterator first, RandomAccessIterator last,
                                     std::array<T, N>& collection, Function func)
    -> bool
{
    using unsigned_t = std::make_unsigned_t<
        cppsort::detail::difference_type_t<RandomAccessIterator>
    >;
    unsigned_t counter = 0u;

    unsigned_t end = 1 << (last - first);  // 2^n permutations
    for (unsigned_t nb_permutations = 0 ; nb_permutations != end ; nb_permutations += 2) {

        // Flip value for even counter
        if (CPPSORT_UNLIKELY(not func(collection))) {
            return false;
        }
        counter ^= 1u;
        first[0u] = 1 - first[0u];

        // Flip value for odd counter
        if (CPPSORT_UNLIKELY(not func(collection))) {
            return false;
        }
        auto y = counter & -counter;
        counter ^= (y << 1);
        auto to_flip = cppsort::detail::log2(y) + 1;
        first[to_flip] = 1 - first[to_flip];
    }
    return true;
}

template<typename T, std::size_t N, typename Function>
auto for_each_gray_permutation(std::array<T, N>& collection, Function func)
    -> void
{
    using iterator = typename std::array<T, N>::iterator;
    using unsigned_t = std::make_unsigned_t<
        cppsort::detail::difference_type_t<iterator>
    >;

    unsigned_t size = collection.size();
    // Compute the "header" of bits before launching parallel jobs
    unsigned_t header_size = cppsort::detail::log2(std::thread::hardware_concurrency());

    if (size <= 20 || size < header_size) {
        // The problem size is small enough or we can't gain
        // enough from parallel jobs, go full sequential
        for_each_gray_permutation_inner(collection.begin(), collection.end(),
                                        collection, std::move(func));
    } else {
        // The goal of the following algorithm is to use a many threads as possible, etc.
        std::vector<std::thread> jobs;

        auto first = collection.begin();
        for_each_gray_permutation_inner(first, first + header_size, collection, [&](std::array<T, N> arr) {
            jobs.emplace_back(for_each_gray_permutation_inner<iterator, T, N, Function&>,
                              arr.begin() + header_size, arr.end(),
                              std::ref(arr), std::ref(func));
            return true;
        });

        // Join the jobs before exiting
        for (auto& job: jobs) {
            job.join();
        }
    }
}

////////////////////////////////////////////////////////////
// Count the number of comparisons

template<typename T, std::size_t N>
auto validate_sorting_network()
    -> void
{
    if (N < 2) return;

    std::cout << "sorting network of size " << N << ": ";

    cppsort::sorting_network_sorter<N> sorter;
    std::array<T, N> collection;
    std::fill(collection.begin(), collection.end(), 0);

    std::atomic<bool> error_occurred(false);
    bool expected = false;
    for_each_gray_permutation(collection, [&](const std::array<T, N>& arr) {
        // Copy then sort collection
        std::array<int, N> to_sort = arr;
        sorter(to_sort);

        // Check whether it is sorted
        if (not std::is_sorted(std::begin(to_sort), std::end(to_sort))) {
            if (error_occurred.compare_exchange_strong(expected, true)) {
                // Log the faulty array
                std::cout << "\n  failed to sort the following input:\n  ";
                for (const auto& value: arr) {
                    std::cout << value << ' ';
                }
                std::cout << "\n  got the following output:\n  ";
                for (const auto& value: to_sort) {
                    std::cout << value << ' ';
                }
                std::cout << '\n';
            }
            // Abort for this size
            return false;
        }
        return true;
    });
    std::cout << "ok\n";
}

template<typename T, std::size_t... Indices>
auto validate_sorting_networks(std::index_sequence<Indices...>)
    -> void
{
    // Variadic dispatch only works with expressions
    int dummy[] = {
        (validate_sorting_network<T, Indices + 1>(), 0)...
    };
    (void) dummy;
}

////////////////////////////////////////////////////////////
// Main

int main()
{
    // The zero-one principle states that a sorting network is
    // valid if it can sort all the permutations of 0 and 1 for
    // a given size of array. This program uses this principle
    // to validate the sorting networks in O(2^n) instead of
    // the slower O(n!).

    // Best time to check all sorting networks to date: 536s

    // Sizes of the sorting networks to validate
    using indices = std::make_index_sequence<26>;

    validate_sorting_networks<int>(indices{});
}
<|endoftext|>


<commit_before><commit_msg>[Bug 11981] inproper "AND" operator in AutoSense.hpp.<commit_after><|endoftext|>


<commit_before><commit_msg>#101785# set transparency to link display bitmaps<commit_after><|endoftext|>


<commit_before><commit_msg>cid#1194914 Overflowed return value<commit_after><|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS loadenv01 (1.4.156); FILE MERGED 2004/03/12 14:47:53 mba 1.4.156.1: #115936#: remove window properties set while loading<commit_after><|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS cellbreak (1.2.322); FILE MERGED 2003/11/14 10:06:55 fme 1.2.322.4: #i2109# Split table rows 2003/11/07 07:22:14 fme 1.2.322.3: #i2109# Feature - Split table rows 2003/10/06 12:52:27 fme 1.2.322.2: #i2109# Feature - Split table rows 2003/09/08 07:46:05 fme 1.2.322.1: #i2109# Feature - Split table rows<commit_after><|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS aw024 (1.18.12); FILE MERGED 2006/09/08 19:40:20 aw 1.18.12.6: RESYNC: (1.20-1.21); FILE MERGED 2006/08/18 08:20:13 od 1.18.12.5: #i68597# - remove unneeded forward declaration of class Region 2006/08/14 17:35:40 aw 1.18.12.4: #i68597# prepare SW for fully buffered Overlay 2006/08/03 16:55:41 aw 1.18.12.3: RESYNC: (1.19-1.20); FILE MERGED 2006/05/12 21:26:16 aw 1.18.12.2: RESYNC: (1.18-1.19); FILE MERGED 2006/03/15 11:20:27 aw 1.18.12.1: #114409# corrected sw overlay problems<commit_after><|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS swqbugfixes16 (1.41.180); FILE MERGED 2005/02/17 09:18:40 fme 1.41.180.1: #i37142# Footnote numbering portion should not take over certain attributes from the paragraph style<commit_after><|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS swundo01 (1.6.126); FILE MERGED 2004/01/06 23:48:48 hbrinkm 1.6.126.2: RESYNC: (1.6-1.7); FILE MERGED 2003/08/15 14:09:55 hbrinkm 1.6.126.1: #111827#<commit_after><|endoftext|>


<commit_before>//
// (c) Copyright 2017 DESY,ESS
//
// This file is part of h5pp.
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
// License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this library; if not, write to the
// Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor
// Boston, MA  02110-1301 USA
// ===========================================================================
//
// Authors:
//   Eugen Wintersberger <eugen.wintersberger@desy.de>
//   Martin Shetty <martin.shetty@esss.se>
// Created on: Aug 23, 2017
//

#include <gtest/gtest.h>
#include <h5cpp/datatype/factory.hpp>
#include <h5cpp/datatype/integer.hpp>

using namespace hdf5;

template<class T>
class Integer : public testing::Test {
 protected:
  Integer() {}
  virtual ~Integer() {}
  T value_;
};

template <class T>
class SignedInteger : public Integer<T> { };

template <class T>
class UnsignedInteger : public Integer<T> { };

using testing::Types;

// The list of types we want to test.
typedef
Types<
    char, unsigned char, signed char,
    short, unsigned short,
    int, unsigned int,
    long, unsigned long,
    long long, unsigned long long>
    test_types;

// The list of unsigned types we want to test.
typedef
Types<
    unsigned char,
    unsigned short,
    unsigned int,
    unsigned long,
    unsigned long long>
    test_unsigned_types;

// The list of signed types we want to test.
typedef
Types<signed char, short, int, long, long long>
    test_signed_types;

TYPED_TEST_CASE(Integer, test_types);
TYPED_TEST_CASE(SignedInteger, test_signed_types);
TYPED_TEST_CASE(UnsignedInteger, test_unsigned_types);

TYPED_TEST(Integer, Exceptions) {
  datatype::Datatype dtype;
  EXPECT_THROW((datatype::Integer(dtype)), std::runtime_error);

  auto ft = datatype::create<double>();
  EXPECT_THROW((datatype::Integer(ft)), std::runtime_error);
}

TYPED_TEST(Integer, General) {
  auto t = datatype::create<decltype(this->value_)>();
  EXPECT_TRUE((std::is_same<decltype(t), datatype::Integer>::value));
  EXPECT_TRUE(t.get_class() == datatype::Class::INTEGER);
  EXPECT_EQ(t.size(), sizeof(this->value_));

  datatype::Datatype &generic = t;
  datatype::Integer new_type(generic);
  EXPECT_EQ(new_type.get_class(), datatype::Class::INTEGER);

  datatype::Datatype default_constructed;
  EXPECT_FALSE(default_constructed.is_valid());
  EXPECT_THROW((datatype::Integer(default_constructed)), std::runtime_error);
}

TYPED_TEST(SignedInteger, Signed) {
  auto t = datatype::create<decltype(this->value_)>();

  ASSERT_EQ(t.is_signed(), true);
  t.make_signed(true);
  ASSERT_EQ(t.is_signed(), true);
  t.make_signed(false);
  ASSERT_EQ(t.is_signed(), false);
}

TYPED_TEST(UnsignedInteger, Signed) {
  auto t = datatype::create<decltype(this->value_)>();

  ASSERT_EQ(t.is_signed(), false);
  t.make_signed(true);
  ASSERT_EQ(t.is_signed(), true);
  t.make_signed(false);
  ASSERT_EQ(t.is_signed(), false);
}

<commit_msg>Update integer_test.cpp<commit_after>//
// (c) Copyright 2017 DESY,ESS
//
// This file is part of h5pp.
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
// License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this library; if not, write to the
// Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor
// Boston, MA  02110-1301 USA
// ===========================================================================
//
// Authors:
//   Eugen Wintersberger <eugen.wintersberger@desy.de>
//   Martin Shetty <martin.shetty@esss.se>
// Created on: Aug 23, 2017
//

#include <gtest/gtest.h>
#include <h5cpp/datatype/factory.hpp>
#include <h5cpp/datatype/integer.hpp>

using namespace hdf5;

template<class T>
class Integer : public testing::Test {
 protected:
  Integer() {}
  virtual ~Integer() {}
  T value_;
};

template <class T>
class SignedInteger : public Integer<T> { };

template <class T>
class UnsignedInteger : public Integer<T> { };

using testing::Types;

// The list of types we want to test.
typedef
Types<
    char, unsigned char, signed char,
    short, unsigned short,
    int, unsigned int,
    long, unsigned long,
    long long, unsigned long long>
    test_types;

// The list of unsigned types we want to test.
typedef
Types<
    unsigned char,
    unsigned short,
    unsigned int,
    unsigned long,
    unsigned long long>
    test_unsigned_types;

// The list of signed types we want to test.
typedef
Types<signed char, short, int, long, long long> test_signed_types;

TYPED_TEST_CASE(Integer, test_types);
TYPED_TEST_CASE(SignedInteger, test_signed_types);
TYPED_TEST_CASE(UnsignedInteger, test_unsigned_types);

TYPED_TEST(Integer, Exceptions) {
  datatype::Datatype dtype;
  EXPECT_THROW((datatype::Integer(dtype)), std::runtime_error);

  auto ft = datatype::create<double>();
  EXPECT_THROW((datatype::Integer(ft)), std::runtime_error);
}

TYPED_TEST(Integer, General) {
  auto t = datatype::create<decltype(this->value_)>();
  EXPECT_TRUE((std::is_same<decltype(t), datatype::Integer>::value));
  EXPECT_TRUE(t.get_class() == datatype::Class::INTEGER);
  EXPECT_EQ(t.size(), sizeof(this->value_));

  datatype::Datatype &generic = t;
  datatype::Integer new_type(generic);
  EXPECT_EQ(new_type.get_class(), datatype::Class::INTEGER);

  datatype::Datatype default_constructed;
  EXPECT_FALSE(default_constructed.is_valid());
  EXPECT_THROW((datatype::Integer(default_constructed)), std::runtime_error);
}

TYPED_TEST(SignedInteger, Signed) {
  auto t = datatype::create<decltype(this->value_)>();

  ASSERT_EQ(t.is_signed(), true);
  t.make_signed(true);
  ASSERT_EQ(t.is_signed(), true);
  t.make_signed(false);
  ASSERT_EQ(t.is_signed(), false);
}

TYPED_TEST(UnsignedInteger, Signed) {
  auto t = datatype::create<decltype(this->value_)>();

  ASSERT_EQ(t.is_signed(), false);
  t.make_signed(true);
  ASSERT_EQ(t.is_signed(), true);
  t.make_signed(false);
  ASSERT_EQ(t.is_signed(), false);
}

<|endoftext|>


<commit_before>// Copyright 2009 Google Inc.  All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: vladl@google.com (Vlad Losev)
//
// The Google C++ Testing Framework (Google Test)
//
// This file contains tests verifying correctness of data provided via
// UnitTest's public methods.

#include "gtest/gtest.h"

#include <string.h>  // For strcmp.
#include <algorithm>
#include <sstream>

using ::testing::InitGoogleTest;

namespace testing {
namespace internal {

template <typename T>
struct LessByName {
  bool operator()(const T* a, const T* b) {
    return strcmp(a->name(), b->name()) < 0;
  }
};

class UnitTestHelper {
 public:
  // Returns the array of pointers to all test cases sorted by the test case
  // name.  The caller is responsible for deleting the array.
  static TestCase const** const GetSortedTestCases() {
    UnitTest& unit_test = *UnitTest::GetInstance();
    TestCase const** const test_cases =
        new const TestCase*[unit_test.total_test_case_count()];

    for (int i = 0; i < unit_test.total_test_case_count(); ++i)
      test_cases[i] = unit_test.GetTestCase(i);

    std::sort(test_cases,
              test_cases + unit_test.total_test_case_count(),
              LessByName<TestCase>());
    return test_cases;
  }

  // Returns the test case by its name.  The caller doesn't own the returned
  // pointer.
  static const TestCase* FindTestCase(const char* name) {
    UnitTest& unit_test = *UnitTest::GetInstance();
    for (int i = 0; i < unit_test.total_test_case_count(); ++i) {
      const TestCase* test_case = unit_test.GetTestCase(i);
      if (0 == strcmp(test_case->name(), name))
        return test_case;
    }
    return NULL;
  }

  // Returns the array of pointers to all tests in a particular test case
  // sorted by the test name.  The caller is responsible for deleting the
  // array.
  static TestInfo const** const GetSortedTests(const TestCase* test_case) {
    TestInfo const** const tests =
        new const TestInfo*[test_case->total_test_count()];

    for (int i = 0; i < test_case->total_test_count(); ++i)
      tests[i] = test_case->GetTestInfo(i);

    std::sort(tests, tests + test_case->total_test_count(),
              LessByName<TestInfo>());
    return tests;
  }
};

#if GTEST_HAS_TYPED_TEST
template <typename T> class TestCaseWithCommentTest : public Test {};
TYPED_TEST_CASE(TestCaseWithCommentTest, Types<int>);
TYPED_TEST(TestCaseWithCommentTest, Dummy) {}

const int kTypedTestCases = 1;
const int kTypedTests = 1;
#else
const int kTypedTestCases = 0;
const int kTypedTests = 0;
#endif  // GTEST_HAS_TYPED_TEST

// We can only test the accessors that do not change value while tests run.
// Since tests can be run in any order, the values the accessors that track
// test execution (such as failed_test_count) can not be predicted.
TEST(ApiTest, UnitTestImmutableAccessorsWork) {
  UnitTest* unit_test = UnitTest::GetInstance();

  ASSERT_EQ(2 + kTypedTestCases, unit_test->total_test_case_count());
  EXPECT_EQ(1 + kTypedTestCases, unit_test->test_case_to_run_count());
  EXPECT_EQ(2, unit_test->disabled_test_count());
  EXPECT_EQ(5 + kTypedTests, unit_test->total_test_count());
  EXPECT_EQ(3 + kTypedTests, unit_test->test_to_run_count());

  const TestCase** const test_cases = UnitTestHelper::GetSortedTestCases();

  EXPECT_STREQ("ApiTest", test_cases[0]->name());
  EXPECT_STREQ("DISABLED_Test", test_cases[1]->name());
#if GTEST_HAS_TYPED_TEST
  EXPECT_STREQ("TestCaseWithCommentTest/0", test_cases[2]->name());
#endif  // GTEST_HAS_TYPED_TEST

  delete[] test_cases;

  // The following lines initiate actions to verify certain methods in
  // FinalSuccessChecker::TearDown.

  // Records a test property to verify TestResult::GetTestProperty().
  RecordProperty("key", "value");
}

AssertionResult IsNull(const char* str) {
  if (str != NULL) {
    return testing::AssertionFailure() << "argument is " << str;
  }
  return AssertionSuccess();
}

TEST(ApiTest, TestCaseImmutableAccessorsWork) {
  const TestCase* test_case = UnitTestHelper::FindTestCase("ApiTest");
  ASSERT_TRUE(test_case != NULL);

  EXPECT_STREQ("ApiTest", test_case->name());
  EXPECT_TRUE(IsNull(test_case->type_param()));
  EXPECT_TRUE(test_case->should_run());
  EXPECT_EQ(1, test_case->disabled_test_count());
  EXPECT_EQ(3, test_case->test_to_run_count());
  ASSERT_EQ(4, test_case->total_test_count());

  const TestInfo** tests = UnitTestHelper::GetSortedTests(test_case);

  EXPECT_STREQ("DISABLED_Dummy1", tests[0]->name());
  EXPECT_STREQ("ApiTest", tests[0]->test_case_name());
  EXPECT_TRUE(IsNull(tests[0]->value_param()));
  EXPECT_TRUE(IsNull(tests[0]->type_param()));
  EXPECT_FALSE(tests[0]->should_run());

  EXPECT_STREQ("TestCaseDisabledAccessorsWork", tests[1]->name());
  EXPECT_STREQ("ApiTest", tests[1]->test_case_name());
  EXPECT_TRUE(IsNull(tests[1]->value_param()));
  EXPECT_TRUE(IsNull(tests[1]->type_param()));
  EXPECT_TRUE(tests[1]->should_run());

  EXPECT_STREQ("TestCaseImmutableAccessorsWork", tests[2]->name());
  EXPECT_STREQ("ApiTest", tests[2]->test_case_name());
  EXPECT_TRUE(IsNull(tests[2]->value_param()));
  EXPECT_TRUE(IsNull(tests[2]->type_param()));
  EXPECT_TRUE(tests[2]->should_run());

  EXPECT_STREQ("UnitTestImmutableAccessorsWork", tests[3]->name());
  EXPECT_STREQ("ApiTest", tests[3]->test_case_name());
  EXPECT_TRUE(IsNull(tests[3]->value_param()));
  EXPECT_TRUE(IsNull(tests[3]->type_param()));
  EXPECT_TRUE(tests[3]->should_run());

  delete[] tests;
  tests = NULL;

#if GTEST_HAS_TYPED_TEST
  test_case = UnitTestHelper::FindTestCase("TestCaseWithCommentTest/0");
  ASSERT_TRUE(test_case != NULL);

  EXPECT_STREQ("TestCaseWithCommentTest/0", test_case->name());
  EXPECT_STREQ(GetTypeName<int>().c_str(), test_case->type_param());
  EXPECT_TRUE(test_case->should_run());
  EXPECT_EQ(0, test_case->disabled_test_count());
  EXPECT_EQ(1, test_case->test_to_run_count());
  ASSERT_EQ(1, test_case->total_test_count());

  tests = UnitTestHelper::GetSortedTests(test_case);

  EXPECT_STREQ("Dummy", tests[0]->name());
  EXPECT_STREQ("TestCaseWithCommentTest/0", tests[0]->test_case_name());
  EXPECT_TRUE(IsNull(tests[0]->value_param()));
  EXPECT_STREQ(GetTypeName<int>().c_str(), tests[0]->type_param());
  EXPECT_TRUE(tests[0]->should_run());

  delete[] tests;
#endif  // GTEST_HAS_TYPED_TEST
}

TEST(ApiTest, TestCaseDisabledAccessorsWork) {
  const TestCase* test_case = UnitTestHelper::FindTestCase("DISABLED_Test");
  ASSERT_TRUE(test_case != NULL);

  EXPECT_STREQ("DISABLED_Test", test_case->name());
  EXPECT_TRUE(IsNull(test_case->type_param()));
  EXPECT_FALSE(test_case->should_run());
  EXPECT_EQ(1, test_case->disabled_test_count());
  EXPECT_EQ(0, test_case->test_to_run_count());
  ASSERT_EQ(1, test_case->total_test_count());

  const TestInfo* const test_info = test_case->GetTestInfo(0);
  EXPECT_STREQ("Dummy2", test_info->name());
  EXPECT_STREQ("DISABLED_Test", test_info->test_case_name());
  EXPECT_TRUE(IsNull(test_info->value_param()));
  EXPECT_TRUE(IsNull(test_info->type_param()));
  EXPECT_FALSE(test_info->should_run());
}

// These two tests are here to provide support for testing
// test_case_to_run_count, disabled_test_count, and test_to_run_count.
TEST(ApiTest, DISABLED_Dummy1) {}
TEST(DISABLED_Test, Dummy2) {}

class FinalSuccessChecker : public Environment {
 protected:
  virtual void TearDown() {
    UnitTest* unit_test = UnitTest::GetInstance();

    EXPECT_EQ(1 + kTypedTestCases, unit_test->successful_test_case_count());
    EXPECT_EQ(3 + kTypedTests, unit_test->successful_test_count());
    EXPECT_EQ(0, unit_test->failed_test_case_count());
    EXPECT_EQ(0, unit_test->failed_test_count());
    EXPECT_TRUE(unit_test->Passed());
    EXPECT_FALSE(unit_test->Failed());
    ASSERT_EQ(2 + kTypedTestCases, unit_test->total_test_case_count());

    const TestCase** const test_cases = UnitTestHelper::GetSortedTestCases();

    EXPECT_STREQ("ApiTest", test_cases[0]->name());
    EXPECT_TRUE(IsNull(test_cases[0]->type_param()));
    EXPECT_TRUE(test_cases[0]->should_run());
    EXPECT_EQ(1, test_cases[0]->disabled_test_count());
    ASSERT_EQ(4, test_cases[0]->total_test_count());
    EXPECT_EQ(3, test_cases[0]->successful_test_count());
    EXPECT_EQ(0, test_cases[0]->failed_test_count());
    EXPECT_TRUE(test_cases[0]->Passed());
    EXPECT_FALSE(test_cases[0]->Failed());

    EXPECT_STREQ("DISABLED_Test", test_cases[1]->name());
    EXPECT_TRUE(IsNull(test_cases[1]->type_param()));
    EXPECT_FALSE(test_cases[1]->should_run());
    EXPECT_EQ(1, test_cases[1]->disabled_test_count());
    ASSERT_EQ(1, test_cases[1]->total_test_count());
    EXPECT_EQ(0, test_cases[1]->successful_test_count());
    EXPECT_EQ(0, test_cases[1]->failed_test_count());

#if GTEST_HAS_TYPED_TEST
    EXPECT_STREQ("TestCaseWithCommentTest/0", test_cases[2]->name());
    EXPECT_STREQ(GetTypeName<int>().c_str(), test_cases[2]->type_param());
    EXPECT_TRUE(test_cases[2]->should_run());
    EXPECT_EQ(0, test_cases[2]->disabled_test_count());
    ASSERT_EQ(1, test_cases[2]->total_test_count());
    EXPECT_EQ(1, test_cases[2]->successful_test_count());
    EXPECT_EQ(0, test_cases[2]->failed_test_count());
    EXPECT_TRUE(test_cases[2]->Passed());
    EXPECT_FALSE(test_cases[2]->Failed());
#endif  // GTEST_HAS_TYPED_TEST

    const TestCase* test_case = UnitTestHelper::FindTestCase("ApiTest");
    const TestInfo** tests = UnitTestHelper::GetSortedTests(test_case);
    EXPECT_STREQ("DISABLED_Dummy1", tests[0]->name());
    EXPECT_STREQ("ApiTest", tests[0]->test_case_name());
    EXPECT_FALSE(tests[0]->should_run());

    EXPECT_STREQ("TestCaseDisabledAccessorsWork", tests[1]->name());
    EXPECT_STREQ("ApiTest", tests[1]->test_case_name());
    EXPECT_TRUE(IsNull(tests[1]->value_param()));
    EXPECT_TRUE(IsNull(tests[1]->type_param()));
    EXPECT_TRUE(tests[1]->should_run());
    EXPECT_TRUE(tests[1]->result()->Passed());
    EXPECT_EQ(0, tests[1]->result()->test_property_count());

    EXPECT_STREQ("TestCaseImmutableAccessorsWork", tests[2]->name());
    EXPECT_STREQ("ApiTest", tests[2]->test_case_name());
    EXPECT_TRUE(IsNull(tests[2]->value_param()));
    EXPECT_TRUE(IsNull(tests[2]->type_param()));
    EXPECT_TRUE(tests[2]->should_run());
    EXPECT_TRUE(tests[2]->result()->Passed());
    EXPECT_EQ(0, tests[2]->result()->test_property_count());

    EXPECT_STREQ("UnitTestImmutableAccessorsWork", tests[3]->name());
    EXPECT_STREQ("ApiTest", tests[3]->test_case_name());
    EXPECT_TRUE(IsNull(tests[3]->value_param()));
    EXPECT_TRUE(IsNull(tests[3]->type_param()));
    EXPECT_TRUE(tests[3]->should_run());
    EXPECT_TRUE(tests[3]->result()->Passed());
    EXPECT_EQ(1, tests[3]->result()->test_property_count());
    const TestProperty& property = tests[3]->result()->GetTestProperty(0);
    EXPECT_STREQ("key", property.key());
    EXPECT_STREQ("value", property.value());

    delete[] tests;

#if GTEST_HAS_TYPED_TEST
    test_case = UnitTestHelper::FindTestCase("TestCaseWithCommentTest/0");
    tests = UnitTestHelper::GetSortedTests(test_case);

    EXPECT_STREQ("Dummy", tests[0]->name());
    EXPECT_STREQ("TestCaseWithCommentTest/0", tests[0]->test_case_name());
    EXPECT_TRUE(IsNull(tests[0]->value_param()));
    EXPECT_STREQ(GetTypeName<int>().c_str(), tests[0]->type_param());
    EXPECT_TRUE(tests[0]->should_run());
    EXPECT_TRUE(tests[0]->result()->Passed());
    EXPECT_EQ(0, tests[0]->result()->test_property_count());

    delete[] tests;
#endif  // GTEST_HAS_TYPED_TEST
    delete[] test_cases;
  }
};

}  // namespace internal
}  // namespace testing

int main(int argc, char **argv) {
  InitGoogleTest(&argc, argv);

  AddGlobalTestEnvironment(new testing::internal::FinalSuccessChecker());

  return RUN_ALL_TESTS();
}
<commit_msg>Removes unused include directive.<commit_after>// Copyright 2009 Google Inc.  All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: vladl@google.com (Vlad Losev)
//
// The Google C++ Testing Framework (Google Test)
//
// This file contains tests verifying correctness of data provided via
// UnitTest's public methods.

#include "gtest/gtest.h"

#include <string.h>  // For strcmp.
#include <algorithm>

using ::testing::InitGoogleTest;

namespace testing {
namespace internal {

template <typename T>
struct LessByName {
  bool operator()(const T* a, const T* b) {
    return strcmp(a->name(), b->name()) < 0;
  }
};

class UnitTestHelper {
 public:
  // Returns the array of pointers to all test cases sorted by the test case
  // name.  The caller is responsible for deleting the array.
  static TestCase const** const GetSortedTestCases() {
    UnitTest& unit_test = *UnitTest::GetInstance();
    TestCase const** const test_cases =
        new const TestCase*[unit_test.total_test_case_count()];

    for (int i = 0; i < unit_test.total_test_case_count(); ++i)
      test_cases[i] = unit_test.GetTestCase(i);

    std::sort(test_cases,
              test_cases + unit_test.total_test_case_count(),
              LessByName<TestCase>());
    return test_cases;
  }

  // Returns the test case by its name.  The caller doesn't own the returned
  // pointer.
  static const TestCase* FindTestCase(const char* name) {
    UnitTest& unit_test = *UnitTest::GetInstance();
    for (int i = 0; i < unit_test.total_test_case_count(); ++i) {
      const TestCase* test_case = unit_test.GetTestCase(i);
      if (0 == strcmp(test_case->name(), name))
        return test_case;
    }
    return NULL;
  }

  // Returns the array of pointers to all tests in a particular test case
  // sorted by the test name.  The caller is responsible for deleting the
  // array.
  static TestInfo const** const GetSortedTests(const TestCase* test_case) {
    TestInfo const** const tests =
        new const TestInfo*[test_case->total_test_count()];

    for (int i = 0; i < test_case->total_test_count(); ++i)
      tests[i] = test_case->GetTestInfo(i);

    std::sort(tests, tests + test_case->total_test_count(),
              LessByName<TestInfo>());
    return tests;
  }
};

#if GTEST_HAS_TYPED_TEST
template <typename T> class TestCaseWithCommentTest : public Test {};
TYPED_TEST_CASE(TestCaseWithCommentTest, Types<int>);
TYPED_TEST(TestCaseWithCommentTest, Dummy) {}

const int kTypedTestCases = 1;
const int kTypedTests = 1;
#else
const int kTypedTestCases = 0;
const int kTypedTests = 0;
#endif  // GTEST_HAS_TYPED_TEST

// We can only test the accessors that do not change value while tests run.
// Since tests can be run in any order, the values the accessors that track
// test execution (such as failed_test_count) can not be predicted.
TEST(ApiTest, UnitTestImmutableAccessorsWork) {
  UnitTest* unit_test = UnitTest::GetInstance();

  ASSERT_EQ(2 + kTypedTestCases, unit_test->total_test_case_count());
  EXPECT_EQ(1 + kTypedTestCases, unit_test->test_case_to_run_count());
  EXPECT_EQ(2, unit_test->disabled_test_count());
  EXPECT_EQ(5 + kTypedTests, unit_test->total_test_count());
  EXPECT_EQ(3 + kTypedTests, unit_test->test_to_run_count());

  const TestCase** const test_cases = UnitTestHelper::GetSortedTestCases();

  EXPECT_STREQ("ApiTest", test_cases[0]->name());
  EXPECT_STREQ("DISABLED_Test", test_cases[1]->name());
#if GTEST_HAS_TYPED_TEST
  EXPECT_STREQ("TestCaseWithCommentTest/0", test_cases[2]->name());
#endif  // GTEST_HAS_TYPED_TEST

  delete[] test_cases;

  // The following lines initiate actions to verify certain methods in
  // FinalSuccessChecker::TearDown.

  // Records a test property to verify TestResult::GetTestProperty().
  RecordProperty("key", "value");
}

AssertionResult IsNull(const char* str) {
  if (str != NULL) {
    return testing::AssertionFailure() << "argument is " << str;
  }
  return AssertionSuccess();
}

TEST(ApiTest, TestCaseImmutableAccessorsWork) {
  const TestCase* test_case = UnitTestHelper::FindTestCase("ApiTest");
  ASSERT_TRUE(test_case != NULL);

  EXPECT_STREQ("ApiTest", test_case->name());
  EXPECT_TRUE(IsNull(test_case->type_param()));
  EXPECT_TRUE(test_case->should_run());
  EXPECT_EQ(1, test_case->disabled_test_count());
  EXPECT_EQ(3, test_case->test_to_run_count());
  ASSERT_EQ(4, test_case->total_test_count());

  const TestInfo** tests = UnitTestHelper::GetSortedTests(test_case);

  EXPECT_STREQ("DISABLED_Dummy1", tests[0]->name());
  EXPECT_STREQ("ApiTest", tests[0]->test_case_name());
  EXPECT_TRUE(IsNull(tests[0]->value_param()));
  EXPECT_TRUE(IsNull(tests[0]->type_param()));
  EXPECT_FALSE(tests[0]->should_run());

  EXPECT_STREQ("TestCaseDisabledAccessorsWork", tests[1]->name());
  EXPECT_STREQ("ApiTest", tests[1]->test_case_name());
  EXPECT_TRUE(IsNull(tests[1]->value_param()));
  EXPECT_TRUE(IsNull(tests[1]->type_param()));
  EXPECT_TRUE(tests[1]->should_run());

  EXPECT_STREQ("TestCaseImmutableAccessorsWork", tests[2]->name());
  EXPECT_STREQ("ApiTest", tests[2]->test_case_name());
  EXPECT_TRUE(IsNull(tests[2]->value_param()));
  EXPECT_TRUE(IsNull(tests[2]->type_param()));
  EXPECT_TRUE(tests[2]->should_run());

  EXPECT_STREQ("UnitTestImmutableAccessorsWork", tests[3]->name());
  EXPECT_STREQ("ApiTest", tests[3]->test_case_name());
  EXPECT_TRUE(IsNull(tests[3]->value_param()));
  EXPECT_TRUE(IsNull(tests[3]->type_param()));
  EXPECT_TRUE(tests[3]->should_run());

  delete[] tests;
  tests = NULL;

#if GTEST_HAS_TYPED_TEST
  test_case = UnitTestHelper::FindTestCase("TestCaseWithCommentTest/0");
  ASSERT_TRUE(test_case != NULL);

  EXPECT_STREQ("TestCaseWithCommentTest/0", test_case->name());
  EXPECT_STREQ(GetTypeName<int>().c_str(), test_case->type_param());
  EXPECT_TRUE(test_case->should_run());
  EXPECT_EQ(0, test_case->disabled_test_count());
  EXPECT_EQ(1, test_case->test_to_run_count());
  ASSERT_EQ(1, test_case->total_test_count());

  tests = UnitTestHelper::GetSortedTests(test_case);

  EXPECT_STREQ("Dummy", tests[0]->name());
  EXPECT_STREQ("TestCaseWithCommentTest/0", tests[0]->test_case_name());
  EXPECT_TRUE(IsNull(tests[0]->value_param()));
  EXPECT_STREQ(GetTypeName<int>().c_str(), tests[0]->type_param());
  EXPECT_TRUE(tests[0]->should_run());

  delete[] tests;
#endif  // GTEST_HAS_TYPED_TEST
}

TEST(ApiTest, TestCaseDisabledAccessorsWork) {
  const TestCase* test_case = UnitTestHelper::FindTestCase("DISABLED_Test");
  ASSERT_TRUE(test_case != NULL);

  EXPECT_STREQ("DISABLED_Test", test_case->name());
  EXPECT_TRUE(IsNull(test_case->type_param()));
  EXPECT_FALSE(test_case->should_run());
  EXPECT_EQ(1, test_case->disabled_test_count());
  EXPECT_EQ(0, test_case->test_to_run_count());
  ASSERT_EQ(1, test_case->total_test_count());

  const TestInfo* const test_info = test_case->GetTestInfo(0);
  EXPECT_STREQ("Dummy2", test_info->name());
  EXPECT_STREQ("DISABLED_Test", test_info->test_case_name());
  EXPECT_TRUE(IsNull(test_info->value_param()));
  EXPECT_TRUE(IsNull(test_info->type_param()));
  EXPECT_FALSE(test_info->should_run());
}

// These two tests are here to provide support for testing
// test_case_to_run_count, disabled_test_count, and test_to_run_count.
TEST(ApiTest, DISABLED_Dummy1) {}
TEST(DISABLED_Test, Dummy2) {}

class FinalSuccessChecker : public Environment {
 protected:
  virtual void TearDown() {
    UnitTest* unit_test = UnitTest::GetInstance();

    EXPECT_EQ(1 + kTypedTestCases, unit_test->successful_test_case_count());
    EXPECT_EQ(3 + kTypedTests, unit_test->successful_test_count());
    EXPECT_EQ(0, unit_test->failed_test_case_count());
    EXPECT_EQ(0, unit_test->failed_test_count());
    EXPECT_TRUE(unit_test->Passed());
    EXPECT_FALSE(unit_test->Failed());
    ASSERT_EQ(2 + kTypedTestCases, unit_test->total_test_case_count());

    const TestCase** const test_cases = UnitTestHelper::GetSortedTestCases();

    EXPECT_STREQ("ApiTest", test_cases[0]->name());
    EXPECT_TRUE(IsNull(test_cases[0]->type_param()));
    EXPECT_TRUE(test_cases[0]->should_run());
    EXPECT_EQ(1, test_cases[0]->disabled_test_count());
    ASSERT_EQ(4, test_cases[0]->total_test_count());
    EXPECT_EQ(3, test_cases[0]->successful_test_count());
    EXPECT_EQ(0, test_cases[0]->failed_test_count());
    EXPECT_TRUE(test_cases[0]->Passed());
    EXPECT_FALSE(test_cases[0]->Failed());

    EXPECT_STREQ("DISABLED_Test", test_cases[1]->name());
    EXPECT_TRUE(IsNull(test_cases[1]->type_param()));
    EXPECT_FALSE(test_cases[1]->should_run());
    EXPECT_EQ(1, test_cases[1]->disabled_test_count());
    ASSERT_EQ(1, test_cases[1]->total_test_count());
    EXPECT_EQ(0, test_cases[1]->successful_test_count());
    EXPECT_EQ(0, test_cases[1]->failed_test_count());

#if GTEST_HAS_TYPED_TEST
    EXPECT_STREQ("TestCaseWithCommentTest/0", test_cases[2]->name());
    EXPECT_STREQ(GetTypeName<int>().c_str(), test_cases[2]->type_param());
    EXPECT_TRUE(test_cases[2]->should_run());
    EXPECT_EQ(0, test_cases[2]->disabled_test_count());
    ASSERT_EQ(1, test_cases[2]->total_test_count());
    EXPECT_EQ(1, test_cases[2]->successful_test_count());
    EXPECT_EQ(0, test_cases[2]->failed_test_count());
    EXPECT_TRUE(test_cases[2]->Passed());
    EXPECT_FALSE(test_cases[2]->Failed());
#endif  // GTEST_HAS_TYPED_TEST

    const TestCase* test_case = UnitTestHelper::FindTestCase("ApiTest");
    const TestInfo** tests = UnitTestHelper::GetSortedTests(test_case);
    EXPECT_STREQ("DISABLED_Dummy1", tests[0]->name());
    EXPECT_STREQ("ApiTest", tests[0]->test_case_name());
    EXPECT_FALSE(tests[0]->should_run());

    EXPECT_STREQ("TestCaseDisabledAccessorsWork", tests[1]->name());
    EXPECT_STREQ("ApiTest", tests[1]->test_case_name());
    EXPECT_TRUE(IsNull(tests[1]->value_param()));
    EXPECT_TRUE(IsNull(tests[1]->type_param()));
    EXPECT_TRUE(tests[1]->should_run());
    EXPECT_TRUE(tests[1]->result()->Passed());
    EXPECT_EQ(0, tests[1]->result()->test_property_count());

    EXPECT_STREQ("TestCaseImmutableAccessorsWork", tests[2]->name());
    EXPECT_STREQ("ApiTest", tests[2]->test_case_name());
    EXPECT_TRUE(IsNull(tests[2]->value_param()));
    EXPECT_TRUE(IsNull(tests[2]->type_param()));
    EXPECT_TRUE(tests[2]->should_run());
    EXPECT_TRUE(tests[2]->result()->Passed());
    EXPECT_EQ(0, tests[2]->result()->test_property_count());

    EXPECT_STREQ("UnitTestImmutableAccessorsWork", tests[3]->name());
    EXPECT_STREQ("ApiTest", tests[3]->test_case_name());
    EXPECT_TRUE(IsNull(tests[3]->value_param()));
    EXPECT_TRUE(IsNull(tests[3]->type_param()));
    EXPECT_TRUE(tests[3]->should_run());
    EXPECT_TRUE(tests[3]->result()->Passed());
    EXPECT_EQ(1, tests[3]->result()->test_property_count());
    const TestProperty& property = tests[3]->result()->GetTestProperty(0);
    EXPECT_STREQ("key", property.key());
    EXPECT_STREQ("value", property.value());

    delete[] tests;

#if GTEST_HAS_TYPED_TEST
    test_case = UnitTestHelper::FindTestCase("TestCaseWithCommentTest/0");
    tests = UnitTestHelper::GetSortedTests(test_case);

    EXPECT_STREQ("Dummy", tests[0]->name());
    EXPECT_STREQ("TestCaseWithCommentTest/0", tests[0]->test_case_name());
    EXPECT_TRUE(IsNull(tests[0]->value_param()));
    EXPECT_STREQ(GetTypeName<int>().c_str(), tests[0]->type_param());
    EXPECT_TRUE(tests[0]->should_run());
    EXPECT_TRUE(tests[0]->result()->Passed());
    EXPECT_EQ(0, tests[0]->result()->test_property_count());

    delete[] tests;
#endif  // GTEST_HAS_TYPED_TEST
    delete[] test_cases;
  }
};

}  // namespace internal
}  // namespace testing

int main(int argc, char **argv) {
  InitGoogleTest(&argc, argv);

  AddGlobalTestEnvironment(new testing::internal::FinalSuccessChecker());

  return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before><commit_msg>Add unit test constructing double with one arg (double). 	modified:   tests/test_constructor_api.cpp<commit_after><|endoftext|>


<commit_before>/****************************************************************************

 Copyright (c) 2014, Hans Robeers
 All rights reserved.

 BSD 2-Clause License

 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

   * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

****************************************************************************/

#include "serialization.h"

#include <memory>
#include <QStringList>
#include <QJsonArray>

using namespace hrlib;

//
// Private methods declared here to keep header file clean
//

static bool findClass(const QJsonObject *jsonObj, QString *className, QString *errorMsg)
{
    int keyCount = jsonObj->keys().count();
    if (keyCount == 1)
    {
        QString type = serialization::toClassName(jsonObj->keys().first());

        if (serialization::isRegistered(&type, errorMsg))
        {
            *className = type;
            return true;
        }
    }
    else if (errorMsg)
    {
        if (keyCount < 1)
            errorMsg->append("\n Empty json object");
        else
            errorMsg->append("\n JsonObj contains multiple keys");
    }

    return false;
}

static QJsonValue serialize(const QVariant var, bool *ok)
{
    QJsonValue v;
    QObject *nestedObj = nullptr;
    QJsonObject nestedJSON;
    QList<QVariant> varList;
    QJsonArray jsArray;

    switch (var.type())
    {
    case QVariant::Invalid:
        *ok = false;
        break;

    case QVariant::UserType:
        nestedObj = qvariant_cast<QObject*>(var);
        if (nestedObj)
        {
            *ok = true;
            nestedJSON = serialization::serialize(nestedObj);
            v = nestedJSON.value(nestedJSON.keys().first());
        }
        break;

    case QVariant::List:
        varList = var.toList();
        foreach (QVariant lvar, varList)
        {
            QJsonObject listItem;

            QObject *qObj = qvariant_cast<QObject*>(lvar);
            if (qObj)
                listItem.insert(serialization::toSerialName(qObj->metaObject()->className()), serialize(lvar, ok));
            else
                listItem.insert(serialization::toSerialName(lvar.typeName()), serialize(lvar, ok));

            jsArray.append(listItem);

            if (!*ok)
                break;
        }
        v = jsArray;
        *ok = !v.isNull();
        break;

    default:
        v = QJsonValue::fromVariant(var);

        if (!v.isNull())
        {
            *ok = true;
        }
        else
        {
            QString msg("Serialization::serialize not implemented for ");
            msg.append(var.typeName());
            throw NotImplementedException(msg);
        }

        break;
    }
    return v;
}

//
// serialization static class methods
//

QJsonObject serialization::serialize(const QObject *qObj)
{
    QJsonObject retVal; // return value
    QJsonValue value;

    QString className = qObj->metaObject()->className();
    QString serialName = toSerialName(className);

    if (serializerMap().contains(className))
    {
        value = serializerMap()[className]->serialize(qObj);
    }
    else
    {
        QJsonObject propObj; // QProperties container

        // The first propetry objectName is skipped
        for (int i = 1; i < qObj->metaObject()->propertyCount(); i++)
        {
            QMetaProperty mp = qObj->metaObject()->property(i);

            QVariant var = mp.read(qObj);

            bool ok = false;

            QJsonValue v = ::serialize(var, &ok);

            if (!ok)
                continue;

            propObj.insert(mp.name(), v);
        }

        value = propObj;
    }

    retVal.insert(serialName, value);

    return retVal;
}

std::unique_ptr<QObject> serialization::deserializeToObject(const QJsonObject *jsonObj)
{
    QString errorMsg;
    std::unique_ptr<QObject> retVal = deserializeToObject(jsonObj, &errorMsg);

    if (!retVal)
        throw SerializationException(errorMsg);

    return retVal;
}

std::unique_ptr<QObject> serialization::deserializeClass(const QJsonObject *jsonObj, QString className)
{
    QString errorMsg;
    std::unique_ptr<QObject> retVal = deserializeClass(jsonObj, className, &errorMsg);

    if (!retVal)
        throw SerializationException(errorMsg);

    return retVal;
}

std::unique_ptr<QObject> serialization::deserializeToObject(const QJsonObject *jsonObj, QString *errorMsg)
{
    QString className;

    if (!findClass(jsonObj, &className, errorMsg))
        return nullptr;

    // Extract the class data
    QJsonValue classValue = jsonObj->value(toSerialName(className));

    // Use custom deserializer if available
    if (serializerMap().contains(className))
        return serializerMap()[className]->deserialize(&classValue, errorMsg);

    QJsonObject classDataObject = classValue.toObject();
    return deserializeClass(&classDataObject, className, errorMsg);
}

std::unique_ptr<QObject> serialization::deserializeClass(const QJsonObject *jsonObj, QString className, QString *errorMsg)
{
    className = className.replace('*', ""); // Properties can be pointer types

    if (!isRegistered(&className, errorMsg))
        return nullptr;

    const QObject *obj = typeMap()[className];
    std::unique_ptr<QObject> retVal(obj->metaObject()->newInstance());
    if (!retVal)
    {
        QString msg = "serialization::deserialize failed for " + className +
                ": the default ctor is not invokable. Add the Q_INVOKABLE macro.";
        throw ImplementationException(msg);
    }

    // Loop over and write class properties
    // The first propetry objectName is skipped
    for (int i = 1; i < retVal->metaObject()->propertyCount(); i++)
    {
        QMetaProperty mp = retVal->metaObject()->property(i);
        QString propName = mp.name();
        className = mp.typeName();
        className = className.replace('*', "");

        if (mp.isWritable())
        {
            // init local variables
            QObject *nestedObj = nullptr;
            QJsonObject nestedJSON;
            QJsonValue nestedJsonValue;
            QJsonArray jsonArray;
            QVariant var;
            QList<QVariant> varList;
            bool writeSucceeded = false;

            switch (mp.type())
            {
            case QVariant::UserType:
                nestedJsonValue = jsonObj->value(propName);
                nestedJSON = nestedJsonValue.toObject();

                // Use custom deserializer if available
                if (serializerMap().contains(className))
                {
                    nestedObj = serializerMap()[className]->deserialize(&nestedJsonValue, errorMsg).release();
                }
                else
                {
                    // get className from nestedJSON if specified
                    findClass(&nestedJSON, &className, nullptr);

                    nestedObj = deserializeClass(&nestedJSON, className, errorMsg).release();
                }

                if (nestedObj)
                {
                    nestedObj->setParent(retVal.get());
                    var.setValue(nestedObj);
                    writeSucceeded = mp.write(retVal.get(), var);
                }
                break;

            case QVariant::List:
                jsonArray = jsonObj->value(propName).toArray();
                foreach (QJsonValue item, jsonArray)
                {
                    QVariant vObj;
                    nestedJSON = item.toObject();

                    // deserialize QVariant supported type
                    QString firstKey = nestedJSON.keys().first();
                    int typeId = QVariant::nameToType(firstKey.toStdString().c_str());
                    if (typeId != QVariant::Invalid && typeId != QVariant::UserType)
                    {
                        QJsonValue val = nestedJSON.value(firstKey);
                        if (!val.isNull())
                        {
                            varList.append(val.toVariant());
                            continue;
                        }
                    }

                    // deserialize custom type
                    vObj.setValue(deserializeToObject(&nestedJSON).release());
                    varList.append(vObj);
                }
                writeSucceeded = mp.write(retVal.get(), varList);
                break;

            default:
                writeSucceeded = mp.write(retVal.get(), jsonObj->value(propName).toVariant());
                break;
            }

            if (!writeSucceeded)
            {
                if (mp.isResettable())
                {
                    mp.reset(retVal.get());
                }
                else
                {
                    if (errorMsg)
                    {
                        errorMsg->append("\n Failed to deserialize ");
                        if (!className.isEmpty()) errorMsg->append(className + "::");
                        errorMsg->append(mp.name());
                        errorMsg->append(" of type: ");
                        errorMsg->append(mp.typeName());
                    }
                    return nullptr;
                }
            }
        }

    }

    return retVal;
}

bool serialization::isRegistered(QString *className, QString *errorMsg)
{
    if (!typeMap().contains(*className))
    {
        if (errorMsg)
            errorMsg->append("\n Class \"" + *className + "\" is not registered for deserialization");
        return false;
    }

    return true;
}

QString serialization::toSerialName(QString className)
{
    className = className.replace('*', "");
    if (nameMap().left.find(className) == nameMap().left.end())
        return className;
    return nameMap().left.at(className);
}

QString serialization::toClassName(QString serialName)
{
    serialName = serialName.replace('*', "");
    if (nameMap().right.find(serialName) == nameMap().right.end())
        return serialName;
    return nameMap().right.at(serialName);
}
<commit_msg>QStringList for more compact uuid history<commit_after>/****************************************************************************

 Copyright (c) 2014, Hans Robeers
 All rights reserved.

 BSD 2-Clause License

 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

   * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

****************************************************************************/

#include "serialization.h"

#include <memory>
#include <QStringList>
#include <QJsonArray>

using namespace hrlib;

//
// Private methods declared here to keep header file clean
//

static bool findClass(const QJsonObject *jsonObj, QString *className, QString *errorMsg)
{
    int keyCount = jsonObj->keys().count();
    if (keyCount == 1)
    {
        QString type = serialization::toClassName(jsonObj->keys().first());

        if (serialization::isRegistered(&type, errorMsg))
        {
            *className = type;
            return true;
        }
    }
    else if (errorMsg)
    {
        if (keyCount < 1)
            errorMsg->append("\n Empty json object");
        else
            errorMsg->append("\n JsonObj contains multiple keys");
    }

    return false;
}

static QJsonValue serialize(const QVariant var, bool *ok)
{
    QJsonValue v;
    QObject *nestedObj = nullptr;
    QJsonObject nestedJSON;
    QList<QVariant> varList;
    QJsonArray jsArray;

    switch (var.type())
    {
    case QVariant::Invalid:
        *ok = false;
        break;

    case QVariant::UserType:
        nestedObj = qvariant_cast<QObject*>(var);
        if (nestedObj)
        {
            *ok = true;
            nestedJSON = serialization::serialize(nestedObj);
            v = nestedJSON.value(nestedJSON.keys().first());
        }
        break;

    case QVariant::StringList:
        varList = var.toList();

        foreach (QVariant lvar, varList)
            jsArray.append(QJsonValue::fromVariant(lvar));

        v = jsArray;
        *ok = !v.isNull();
        break;

    case QVariant::List:
        varList = var.toList();
        foreach (QVariant lvar, varList)
        {
            QJsonObject listItem;

            QObject *qObj = qvariant_cast<QObject*>(lvar);
            if (qObj)
                listItem.insert(serialization::toSerialName(qObj->metaObject()->className()), serialize(lvar, ok));
            else
                listItem.insert(serialization::toSerialName(lvar.typeName()), serialize(lvar, ok));

            jsArray.append(listItem);

            if (!*ok)
                break;
        }
        v = jsArray;
        *ok = !v.isNull();
        break;

    default:
        v = QJsonValue::fromVariant(var);

        if (!v.isNull())
        {
            *ok = true;
        }
        else
        {
            QString msg("Serialization::serialize not implemented for ");
            msg.append(var.typeName());
            throw NotImplementedException(msg);
        }

        break;
    }
    return v;
}

//
// serialization static class methods
//

QJsonObject serialization::serialize(const QObject *qObj)
{
    QJsonObject retVal; // return value
    QJsonValue value;

    QString className = qObj->metaObject()->className();
    QString serialName = toSerialName(className);

    if (serializerMap().contains(className))
    {
        value = serializerMap()[className]->serialize(qObj);
    }
    else
    {
        QJsonObject propObj; // QProperties container

        // The first propetry objectName is skipped
        for (int i = 1; i < qObj->metaObject()->propertyCount(); i++)
        {
            QMetaProperty mp = qObj->metaObject()->property(i);

            QVariant var = mp.read(qObj);

            bool ok = false;

            QJsonValue v = ::serialize(var, &ok);

            if (!ok)
                continue;

            propObj.insert(mp.name(), v);
        }

        value = propObj;
    }

    retVal.insert(serialName, value);

    return retVal;
}

std::unique_ptr<QObject> serialization::deserializeToObject(const QJsonObject *jsonObj)
{
    QString errorMsg;
    std::unique_ptr<QObject> retVal = deserializeToObject(jsonObj, &errorMsg);

    if (!retVal)
        throw SerializationException(errorMsg);

    return retVal;
}

std::unique_ptr<QObject> serialization::deserializeClass(const QJsonObject *jsonObj, QString className)
{
    QString errorMsg;
    std::unique_ptr<QObject> retVal = deserializeClass(jsonObj, className, &errorMsg);

    if (!retVal)
        throw SerializationException(errorMsg);

    return retVal;
}

std::unique_ptr<QObject> serialization::deserializeToObject(const QJsonObject *jsonObj, QString *errorMsg)
{
    QString className;

    if (!findClass(jsonObj, &className, errorMsg))
        return nullptr;

    // Extract the class data
    QJsonValue classValue = jsonObj->value(toSerialName(className));

    // Use custom deserializer if available
    if (serializerMap().contains(className))
        return serializerMap()[className]->deserialize(&classValue, errorMsg);

    QJsonObject classDataObject = classValue.toObject();
    return deserializeClass(&classDataObject, className, errorMsg);
}

std::unique_ptr<QObject> serialization::deserializeClass(const QJsonObject *jsonObj, QString className, QString *errorMsg)
{
    className = className.replace('*', ""); // Properties can be pointer types

    if (!isRegistered(&className, errorMsg))
        return nullptr;

    const QObject *obj = typeMap()[className];
    std::unique_ptr<QObject> retVal(obj->metaObject()->newInstance());
    if (!retVal)
    {
        QString msg = "serialization::deserialize failed for " + className +
                ": the default ctor is not invokable. Add the Q_INVOKABLE macro.";
        throw ImplementationException(msg);
    }

    // Loop over and write class properties
    // The first propetry objectName is skipped
    for (int i = 1; i < retVal->metaObject()->propertyCount(); i++)
    {
        QMetaProperty mp = retVal->metaObject()->property(i);
        QString propName = mp.name();
        className = mp.typeName();
        className = className.replace('*', "");

        if (mp.isWritable())
        {
            // init local variables
            QObject *nestedObj = nullptr;
            QJsonObject nestedJSON;
            QJsonValue nestedJsonValue;
            QJsonArray jsonArray;
            QVariant var;
            QList<QVariant> varList;
            QStringList stringList;
            bool writeSucceeded = false;

            switch (mp.type())
            {
            case QVariant::UserType:
                nestedJsonValue = jsonObj->value(propName);
                nestedJSON = nestedJsonValue.toObject();

                // Use custom deserializer if available
                if (serializerMap().contains(className))
                {
                    nestedObj = serializerMap()[className]->deserialize(&nestedJsonValue, errorMsg).release();
                }
                else
                {
                    // get className from nestedJSON if specified
                    findClass(&nestedJSON, &className, nullptr);

                    nestedObj = deserializeClass(&nestedJSON, className, errorMsg).release();
                }

                if (nestedObj)
                {
                    nestedObj->setParent(retVal.get());
                    var.setValue(nestedObj);
                    writeSucceeded = mp.write(retVal.get(), var);
                }
                break;

            case QVariant::StringList:
                jsonArray = jsonObj->value(propName).toArray();

                foreach (QJsonValue item, jsonArray)
                    stringList.append(item.toString());

                writeSucceeded = mp.write(retVal.get(), stringList);
                break;

            case QVariant::List:
                jsonArray = jsonObj->value(propName).toArray();
                foreach (QJsonValue item, jsonArray)
                {
                    QVariant vObj;
                    nestedJSON = item.toObject();

                    // deserialize QVariant supported type
                    QString firstKey = nestedJSON.keys().first();
                    int typeId = QVariant::nameToType(firstKey.toStdString().c_str());
                    if (typeId != QVariant::Invalid && typeId != QVariant::UserType)
                    {
                        QJsonValue val = nestedJSON.value(firstKey);
                        if (!val.isNull())
                        {
                            varList.append(val.toVariant());
                            continue;
                        }
                    }

                    // deserialize custom type
                    vObj.setValue(deserializeToObject(&nestedJSON).release());
                    varList.append(vObj);
                }
                writeSucceeded = mp.write(retVal.get(), varList);
                break;

            default:
                writeSucceeded = mp.write(retVal.get(), jsonObj->value(propName).toVariant());
                break;
            }

            if (!writeSucceeded)
            {
                if (mp.isResettable())
                {
                    mp.reset(retVal.get());
                }
                else
                {
                    if (errorMsg)
                    {
                        errorMsg->append("\n Failed to deserialize ");
                        if (!className.isEmpty()) errorMsg->append(className + "::");
                        errorMsg->append(mp.name());
                        errorMsg->append(" of type: ");
                        errorMsg->append(mp.typeName());
                    }
                    return nullptr;
                }
            }
        }

    }

    return retVal;
}

bool serialization::isRegistered(QString *className, QString *errorMsg)
{
    if (!typeMap().contains(*className))
    {
        if (errorMsg)
            errorMsg->append("\n Class \"" + *className + "\" is not registered for deserialization");
        return false;
    }

    return true;
}

QString serialization::toSerialName(QString className)
{
    className = className.replace('*', "");
    if (nameMap().left.find(className) == nameMap().left.end())
        return className;
    return nameMap().left.at(className);
}

QString serialization::toClassName(QString serialName)
{
    serialName = serialName.replace('*', "");
    if (nameMap().right.find(serialName) == nameMap().right.end())
        return serialName;
    return nameMap().right.at(serialName);
}
<|endoftext|>


<commit_before>#include <chrono>
#include <cmath>
#include "ps/ps.h"

using namespace ps;

template <typename Val>
void EmptyHandler(const KVMeta &req_meta, const KVPairs<Val> &req_data, KVServer<Val> *server) {
  KVPairs<Val> res;
  if (req_meta.push) {
  } else {
    res.keys = req_data.keys;
    res.vals.resize(req_data.keys.size());
  }
  server->Response(req_meta, res);
}

void StartServer() {
  if (!IsServer()) return;
  auto server = new KVServer<float>(0);
  server->set_request_handle(EmptyHandler<float>);
  RegisterExitCallback([server]() { delete server; });
}

void RunWorker() {
  if (!IsWorker()) return;
  KVWorker<float> kv(0, 0);

  // init
  int num = 1000000;
  std::vector<Key> keys(num);
  std::vector<float> vals(num);

  int rank = MyRank();
  srand(rank + 7);
  for (int i = 0; i < num; ++i) {
    keys[i] = kMaxKey / num * i + rank;
    vals[i] = (rand() % 1000);
  }

  int repeat = 50;

  // push
  auto start = std::chrono::high_resolution_clock::now();
  for (int i = 0; i < repeat; ++i) {
    kv.Wait(kv.Push(keys, vals));
  }
  auto end = std::chrono::high_resolution_clock::now();
  LL << "num = " << num << ", Push average time cost: " << (end - start).count() / 1e6 << "ms";

  // pull
  start = std::chrono::high_resolution_clock::now();
  std::vector<float> rets;
  for (int i = 0; i < repeat; ++i) {
    kv.Wait(kv.Pull(keys, &rets));
  }
  end = std::chrono::high_resolution_clock::now();
  LL << "num = " << num << ", Pull average time cost: " << (end - start).count() / 1e6 << "ms";
}

int main(int argc, char *argv[]) {
  // start system
  Start(0);
  // setup server nodes
  StartServer();
  // run worker nodes
  RunWorker();
  // stop system
  Finalize(0, true);
  return 0;
}
<commit_msg>Update test_kv_app_benchmark.cc to enable in-place memory reuse<commit_after>#include <chrono>
#include <cmath>
#include "ps/ps.h"

using namespace ps;
std::unordered_map<int, KVPairs<float> > mem_map;

template <typename Val>
void EmptyHandler(const KVMeta &req_meta, const KVPairs<Val> &req_data, KVServer<Val> *server) {
  if (req_meta.push) {
    KVPairs<float> res;
    server->Response(req_meta, res);
  } else {
    auto iter = mem_map.find(0);
    if(iter==mem_map.end()){
      LOG(INFO) << "init...";
      KVPairs<float> res;
      res.keys = req_data.keys;
      res.vals.resize(req_data.keys.size());
      server->Response(req_meta, res);
    }else{
      LOG(INFO) << "in-place memory reuse";
      KVPairs<float> *res_ptr = &iter->second;
      res_ptr->keys = req_data.keys;
      res_ptr->vals.resize(req_data.keys.size());
      server->Response(req_meta, *res_ptr);
    }
  }
}

void StartServer() {
  if (!IsServer()) return;
  auto server = new KVServer<float>(0);
  server->set_request_handle(EmptyHandler<float>);
  RegisterExitCallback([server]() { delete server; });
}

void RunWorker() {
  if (!IsWorker()) return;
  KVWorker<float> kv(0, 0);

  // init
  int num = 10000000;
  std::vector<Key> keys(num);
  std::vector<float> vals(num);

  int rank = MyRank();
  srand(rank + 7);
  for (int i = 0; i < num; ++i) {
    keys[i] = kMaxKey / num * i + rank;
    vals[i] = (rand() % 1000);
  }

  int repeat = 1;

  // push
  auto start = std::chrono::high_resolution_clock::now();
  for (int i = 0; i < repeat; ++i) {
    kv.Wait(kv.Push(keys, vals));
  }
  auto end = std::chrono::high_resolution_clock::now();
  LL << "num = " << num << ", Push average time cost: " << (end - start).count() / 1e6 << "ms";

  // pull
  start = std::chrono::high_resolution_clock::now();
  std::vector<float> rets;
  for (int i = 0; i < repeat; ++i) {
    kv.Wait(kv.Pull(keys, &rets));
  }
  end = std::chrono::high_resolution_clock::now();
  LL << "num = " << num << ", Pull average time cost: " << (end - start).count() / 1e6 << "ms";

}

int main(int argc, char *argv[]) {
  // start system
  Start(0);
  // setup server nodes
  StartServer();
  // run worker nodes
  RunWorker();
  // stop system
  Finalize(0, true);
  return 0;
}
<|endoftext|>


<commit_before>#ifndef MY_LEVEL
#define MY_LEVEL

#include <Annwvyn.h>
using namespace Annwvyn;

//Each level you can create hinerits
//from AnnAbstractLevel
class MyLevel : LEVEL
{
public:
	MyLevel();
	void load();
	void runLogic();
};

#endif //MY_LEVEL<commit_msg>correct typo<commit_after>#ifndef MY_LEVEL
#define MY_LEVEL

#include <Annwvyn.h>
using namespace Annwvyn;

//Each level you can create inherits
//from AnnAbstractLevel
class MyLevel : LEVEL
{
public:
	MyLevel();
	void load();
	void runLogic();
};

#endif //MY_LEVEL<|endoftext|>


<commit_before><commit_msg>Single quote strings with '\' to join lines now styled correctly. Bug #3150522.<commit_after><|endoftext|>


<commit_before><commit_msg>New tests<commit_after><|endoftext|>


<commit_before> /*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: filcmd.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-20 05:19:31 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _FILCMD_HXX_
#define _FILCMD_HXX_

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif
#ifndef _CPPUHELPER_WEAK_HXX_
#include <cppuhelper/weak.hxx>
#endif
#ifndef _COM_SUN_STAR_UNO_XINTERFACE_HPP_
#include <com/sun/star/uno/XInterface.hpp>
#endif
#ifndef _COM_SUN_STAR_UCB_XCOMMANDINFO_HPP_
#include <com/sun/star/ucb/XCommandInfo.hpp>
#endif
#ifndef _COM_SUN_STAR_UCB_XCONTENTPROVIDER_HPP_
#include <com/sun/star/ucb/XContentProvider.hpp>
#endif

namespace fileaccess {

    // forward
    class shell;

    class XCommandInfo_impl
        : public cppu::OWeakObject,
          public com::sun::star::ucb::XCommandInfo
    {
    public:

        XCommandInfo_impl( shell* pMyShell );

        virtual ~XCommandInfo_impl();

        // XInterface
        virtual com::sun::star::uno::Any SAL_CALL
        queryInterface(
            const com::sun::star::uno::Type& aType )
            throw( com::sun::star::uno::RuntimeException);

        virtual void SAL_CALL
        acquire(
            void )
            throw();

        virtual void SAL_CALL
        release(
            void )
            throw();

        // XCommandInfo

        virtual com::sun::star::uno::Sequence< com::sun::star::ucb::CommandInfo > SAL_CALL
        getCommands(
            void )
            throw( com::sun::star::uno::RuntimeException);

        virtual com::sun::star::ucb::CommandInfo SAL_CALL
        getCommandInfoByName(
            const rtl::OUString& Name )
            throw( com::sun::star::ucb::UnsupportedCommandException,
                   com::sun::star::uno::RuntimeException);

        virtual com::sun::star::ucb::CommandInfo SAL_CALL
        getCommandInfoByHandle(
            sal_Int32 Handle )
            throw( com::sun::star::ucb::UnsupportedCommandException,
                   com::sun::star::uno::RuntimeException );

        virtual sal_Bool SAL_CALL
        hasCommandByName(
            const rtl::OUString& Name )
            throw( com::sun::star::uno::RuntimeException );

        virtual sal_Bool SAL_CALL
        hasCommandByHandle(
            sal_Int32 Handle )
            throw( com::sun::star::uno::RuntimeException );

    private:

        shell*                                                                  m_pMyShell;
        com::sun::star::uno::Reference< com::sun::star::ucb::XContentProvider > m_xProvider;
    };

}

#endif
<commit_msg>INTEGRATION: CWS changefileheader (1.5.138); FILE MERGED 2008/04/01 16:02:14 thb 1.5.138.3: #i85898# Stripping all external header guards 2008/04/01 12:58:04 thb 1.5.138.2: #i85898# Stripping all external header guards 2008/03/31 15:30:16 rt 1.5.138.1: #i87441# Change license header to LPGL v3.<commit_after> /*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: filcmd.hxx,v $
 * $Revision: 1.6 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef _FILCMD_HXX_
#define _FILCMD_HXX_

#include <rtl/ustring.hxx>
#include <cppuhelper/weak.hxx>
#include <com/sun/star/uno/XInterface.hpp>
#include <com/sun/star/ucb/XCommandInfo.hpp>
#include <com/sun/star/ucb/XContentProvider.hpp>

namespace fileaccess {

    // forward
    class shell;

    class XCommandInfo_impl
        : public cppu::OWeakObject,
          public com::sun::star::ucb::XCommandInfo
    {
    public:

        XCommandInfo_impl( shell* pMyShell );

        virtual ~XCommandInfo_impl();

        // XInterface
        virtual com::sun::star::uno::Any SAL_CALL
        queryInterface(
            const com::sun::star::uno::Type& aType )
            throw( com::sun::star::uno::RuntimeException);

        virtual void SAL_CALL
        acquire(
            void )
            throw();

        virtual void SAL_CALL
        release(
            void )
            throw();

        // XCommandInfo

        virtual com::sun::star::uno::Sequence< com::sun::star::ucb::CommandInfo > SAL_CALL
        getCommands(
            void )
            throw( com::sun::star::uno::RuntimeException);

        virtual com::sun::star::ucb::CommandInfo SAL_CALL
        getCommandInfoByName(
            const rtl::OUString& Name )
            throw( com::sun::star::ucb::UnsupportedCommandException,
                   com::sun::star::uno::RuntimeException);

        virtual com::sun::star::ucb::CommandInfo SAL_CALL
        getCommandInfoByHandle(
            sal_Int32 Handle )
            throw( com::sun::star::ucb::UnsupportedCommandException,
                   com::sun::star::uno::RuntimeException );

        virtual sal_Bool SAL_CALL
        hasCommandByName(
            const rtl::OUString& Name )
            throw( com::sun::star::uno::RuntimeException );

        virtual sal_Bool SAL_CALL
        hasCommandByHandle(
            sal_Int32 Handle )
            throw( com::sun::star::uno::RuntimeException );

    private:

        shell*                                                                  m_pMyShell;
        com::sun::star::uno::Reference< com::sun::star::ucb::XContentProvider > m_xProvider;
    };

}

#endif
<|endoftext|>


<commit_before>//===- llvm/unittest/ADT/DenseMapMap.cpp - DenseMap unit tests --*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "gtest/gtest.h"
#include "llvm/ADT/DenseMap.h"

using namespace llvm;

namespace {

// Test fixture
class DenseMapTest : public testing::Test {
protected:
  DenseMap<uint32_t, uint32_t> uintMap;
  DenseMap<uint32_t *, uint32_t *> uintPtrMap;
  uint32_t dummyInt;
};

// Empty map tests
TEST_F(DenseMapTest, EmptyIntMapTest) {
  // Size tests
  EXPECT_EQ(0u, uintMap.size());
  EXPECT_TRUE(uintMap.empty());

  // Iterator tests
  EXPECT_TRUE(uintMap.begin() == uintMap.end());

  // Lookup tests
  EXPECT_FALSE(uintMap.count(0u));
  EXPECT_TRUE(uintMap.find(0u) == uintMap.end());
  EXPECT_EQ(0u, uintMap.lookup(0u));
}

// Empty map tests for pointer map
TEST_F(DenseMapTest, EmptyPtrMapTest) {
  // Size tests
  EXPECT_EQ(0u, uintPtrMap.size());
  EXPECT_TRUE(uintPtrMap.empty());

  // Iterator tests
  EXPECT_TRUE(uintPtrMap.begin() == uintPtrMap.end());

  // Lookup tests
  EXPECT_FALSE(uintPtrMap.count(&dummyInt));
  EXPECT_TRUE(uintPtrMap.find(&dummyInt) == uintPtrMap.begin());
  EXPECT_EQ(0, uintPtrMap.lookup(&dummyInt));
}

// Constant map tests
TEST_F(DenseMapTest, ConstEmptyMapTest) {
  const DenseMap<uint32_t, uint32_t> & constUintMap = uintMap;
  const DenseMap<uint32_t *, uint32_t *> & constUintPtrMap = uintPtrMap;
  EXPECT_EQ(0u, constUintMap.size());
  EXPECT_EQ(0u, constUintPtrMap.size());
  EXPECT_TRUE(constUintMap.empty());
  EXPECT_TRUE(constUintPtrMap.empty());
  EXPECT_TRUE(constUintMap.begin() == constUintMap.end());
  EXPECT_TRUE(constUintPtrMap.begin() == constUintPtrMap.end());
}

// A map with a single entry
TEST_F(DenseMapTest, SingleEntryMapTest) {
  uintMap[0] = 1;

  // Size tests
  EXPECT_EQ(1u, uintMap.size());
  EXPECT_FALSE(uintMap.begin() == uintMap.end());
  EXPECT_FALSE(uintMap.empty());

  // Iterator tests
  DenseMap<uint32_t, uint32_t>::iterator it = uintMap.begin();
  EXPECT_EQ(0u, it->first);
  EXPECT_EQ(1u, it->second);
  ++it;
  EXPECT_TRUE(it == uintMap.end());

  // Lookup tests
  EXPECT_TRUE(uintMap.count(0u));
  EXPECT_TRUE(uintMap.find(0u) == uintMap.begin());
  EXPECT_EQ(1u, uintMap.lookup(0u));
  EXPECT_EQ(1u, uintMap[0]);
}

// Test clear() method
TEST_F(DenseMapTest, ClearTest) {
  uintMap[0] = 1;
  uintMap.clear();

  EXPECT_EQ(0u, uintMap.size());
  EXPECT_TRUE(uintMap.empty());
  EXPECT_TRUE(uintMap.begin() == uintMap.end());
}

// Test erase(iterator) method
TEST_F(DenseMapTest, EraseTest) {
  uintMap[0] = 1;
  uintMap.erase(uintMap.begin());

  EXPECT_EQ(0u, uintMap.size());
  EXPECT_TRUE(uintMap.empty());
  EXPECT_TRUE(uintMap.begin() == uintMap.end());
}

// Test erase(value) method
TEST_F(DenseMapTest, EraseTest2) {
  uintMap[0] = 1;
  uintMap.erase(0);

  EXPECT_EQ(0u, uintMap.size());
  EXPECT_TRUE(uintMap.empty());
  EXPECT_TRUE(uintMap.begin() == uintMap.end());
}

// Test insert() method
TEST_F(DenseMapTest, InsertTest) {
  uintMap.insert(std::make_pair(0u, 1u));
  EXPECT_EQ(1u, uintMap.size());
  EXPECT_EQ(1u, uintMap[0]);
}

// Test copy constructor method
TEST_F(DenseMapTest, CopyConstructorTest) {
  uintMap[0] = 1;
  DenseMap<uint32_t, uint32_t> copyMap(uintMap);

  EXPECT_EQ(1u, copyMap.size());
  EXPECT_EQ(1u, copyMap[0]);
}

// Test assignment operator method
TEST_F(DenseMapTest, AssignmentTest) {
  uintMap[0] = 1;
  DenseMap<uint32_t, uint32_t> copyMap = uintMap;

  EXPECT_EQ(1u, copyMap.size());
  EXPECT_EQ(1u, copyMap[0]);
}

// A more complex iteration test
TEST_F(DenseMapTest, IterationTest) {
  bool visited[100];

  // Insert 100 numbers into the map
  for (int i = 0; i < 100; ++i) {
    visited[i] = false;
    uintMap[i] = 3;
  }

  // Iterate over all numbers and mark each one found.
  for (DenseMap<uint32_t, uint32_t>::iterator it = uintMap.begin();
      it != uintMap.end(); ++it) {
    visited[it->first] = true;
  }

  // Ensure every number was visited.
  for (int i = 0; i < 100; ++i) {
    ASSERT_TRUE(visited[i]) << "Entry #" << i << " was never visited";
  }
}

// const_iterator test
TEST_F(DenseMapTest, ConstIteratorTest) {
  // Check conversion from iterator to const_iterator.
  DenseMap<uint32_t, uint32_t>::iterator it = uintMap.begin();
  DenseMap<uint32_t, uint32_t>::const_iterator cit(it);
  EXPECT_TRUE(it == cit);

  // Check copying of const_iterators.
  DenseMap<uint32_t, uint32_t>::const_iterator cit2(cit);
  EXPECT_TRUE(cit == cit2);
}

// Key traits that allows lookup with either an unsigned or char* key;
// In the latter case, "a" == 0, "b" == 1 and so on.
struct TestDenseMapInfo {
  static inline unsigned getEmptyKey() { return ~0; }
  static inline unsigned getTombstoneKey() { return ~0U - 1; }
  static unsigned getHashValue(const unsigned& Val) { return Val * 37U; }
  static unsigned getHashValue(const char* Val) {
    return (unsigned)(Val[0] - 'a') * 37U;
  }
  static bool isEqual(const unsigned& LHS, const unsigned& RHS) {
    return LHS == RHS;
  }
  static bool isEqual(const char* LHS, const unsigned& RHS) {
    return (unsigned)(LHS[0] - 'a') == RHS;
  }
};

// find_as() tests
TEST_F(DenseMapTest, FindAsTest) {
  DenseMap<unsigned, unsigned, TestDenseMapInfo> map;
  map[0] = 1;
  map[1] = 2;
  map[2] = 3;

  // Size tests
  EXPECT_EQ(3u, map.size());

  // Normal lookup tests
  EXPECT_EQ(1, map.count(1));
  EXPECT_EQ(1u, map.find(0)->second);
  EXPECT_EQ(2u, map.find(1)->second);
  EXPECT_EQ(3u, map.find(2)->second);
  EXPECT_TRUE(map.find(3) == map.end());

  // find_as() tests
  EXPECT_EQ(1u, map.find_as("a")->second);
  EXPECT_EQ(2u, map.find_as("b")->second);
  EXPECT_EQ(3u, map.find_as("c")->second);
  EXPECT_TRUE(map.find_as("d") == map.end());
}

}
<commit_msg>Type parameterize the DenseMap unit tests.<commit_after>//===- llvm/unittest/ADT/DenseMapMap.cpp - DenseMap unit tests --*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "gtest/gtest.h"
#include "llvm/ADT/DenseMap.h"
#include <map>

using namespace llvm;

namespace {

// Test fixture
template <typename T>
class DenseMapTest : public testing::Test {
protected:
  T Map;

  typename T::key_type getKey(int i = 0);
  typename T::mapped_type getValue(int i = 0);
};

template <>
uint32_t DenseMapTest<DenseMap<uint32_t, uint32_t> >::getKey(int i) {
  return i;
}

template <>
uint32_t DenseMapTest<DenseMap<uint32_t, uint32_t> >::getValue(int i) {
  return 42 + i;
}

template <>
uint32_t *DenseMapTest<DenseMap<uint32_t *, uint32_t *> >::getKey(int i) {
  static uint32_t dummy_arr1[8192];
  assert(i < 8192 && "Only support 8192 dummy keys.");
  return &dummy_arr1[i];
}

template <>
uint32_t *DenseMapTest<DenseMap<uint32_t *, uint32_t *> >::getValue(int i) {
  static uint32_t dummy_arr2[8192];
  assert(i < 8192 && "Only support 8192 dummy values.");
  return &dummy_arr2[i];
}

// Register these types for testing.
typedef ::testing::Types<DenseMap<uint32_t, uint32_t>,
                         DenseMap<uint32_t *, uint32_t *> > DenseMapTestTypes;
TYPED_TEST_CASE(DenseMapTest, DenseMapTestTypes);

// Empty map tests
TYPED_TEST(DenseMapTest, EmptyIntMapTest) {
  // Size tests
  EXPECT_EQ(0u, this->Map.size());
  EXPECT_TRUE(this->Map.empty());

  // Iterator tests
  EXPECT_TRUE(this->Map.begin() == this->Map.end());

  // Lookup tests
  EXPECT_FALSE(this->Map.count(this->getKey()));
  EXPECT_TRUE(this->Map.find(this->getKey()) == this->Map.end());
  EXPECT_EQ(typename TypeParam::mapped_type(),
            this->Map.lookup(this->getKey()));
}

// Constant map tests
TYPED_TEST(DenseMapTest, ConstEmptyMapTest) {
  const TypeParam &ConstMap = this->Map;
  EXPECT_EQ(0u, ConstMap.size());
  EXPECT_TRUE(ConstMap.empty());
  EXPECT_TRUE(ConstMap.begin() == ConstMap.end());
}

// A map with a single entry
TYPED_TEST(DenseMapTest, SingleEntryMapTest) {
  this->Map[this->getKey()] = this->getValue();

  // Size tests
  EXPECT_EQ(1u, this->Map.size());
  EXPECT_FALSE(this->Map.begin() == this->Map.end());
  EXPECT_FALSE(this->Map.empty());

  // Iterator tests
  typename TypeParam::iterator it = this->Map.begin();
  EXPECT_EQ(this->getKey(), it->first);
  EXPECT_EQ(this->getValue(), it->second);
  ++it;
  EXPECT_TRUE(it == this->Map.end());

  // Lookup tests
  EXPECT_TRUE(this->Map.count(this->getKey()));
  EXPECT_TRUE(this->Map.find(this->getKey()) == this->Map.begin());
  EXPECT_EQ(this->getValue(), this->Map.lookup(this->getKey()));
  EXPECT_EQ(this->getValue(), this->Map[this->getKey()]);
}

// Test clear() method
TYPED_TEST(DenseMapTest, ClearTest) {
  this->Map[this->getKey()] = this->getValue();
  this->Map.clear();

  EXPECT_EQ(0u, this->Map.size());
  EXPECT_TRUE(this->Map.empty());
  EXPECT_TRUE(this->Map.begin() == this->Map.end());
}

// Test erase(iterator) method
TYPED_TEST(DenseMapTest, EraseTest) {
  this->Map[this->getKey()] = this->getValue();
  this->Map.erase(this->Map.begin());

  EXPECT_EQ(0u, this->Map.size());
  EXPECT_TRUE(this->Map.empty());
  EXPECT_TRUE(this->Map.begin() == this->Map.end());
}

// Test erase(value) method
TYPED_TEST(DenseMapTest, EraseTest2) {
  this->Map[this->getKey()] = this->getValue();
  this->Map.erase(this->getKey());

  EXPECT_EQ(0u, this->Map.size());
  EXPECT_TRUE(this->Map.empty());
  EXPECT_TRUE(this->Map.begin() == this->Map.end());
}

// Test insert() method
TYPED_TEST(DenseMapTest, InsertTest) {
  this->Map.insert(std::make_pair(this->getKey(), this->getValue()));
  EXPECT_EQ(1u, this->Map.size());
  EXPECT_EQ(this->getValue(), this->Map[this->getKey()]);
}

// Test copy constructor method
TYPED_TEST(DenseMapTest, CopyConstructorTest) {
  this->Map[this->getKey()] = this->getValue();
  TypeParam copyMap(this->Map);

  EXPECT_EQ(1u, copyMap.size());
  EXPECT_EQ(this->getValue(), copyMap[this->getKey()]);
}

// Test assignment operator method
TYPED_TEST(DenseMapTest, AssignmentTest) {
  this->Map[this->getKey()] = this->getValue();
  TypeParam copyMap = this->Map;

  EXPECT_EQ(1u, copyMap.size());
  EXPECT_EQ(this->getValue(), copyMap[this->getKey()]);
}

// A more complex iteration test
TYPED_TEST(DenseMapTest, IterationTest) {
  bool visited[100];
  std::map<typename TypeParam::key_type, unsigned> visitedIndex;

  // Insert 100 numbers into the map
  for (int i = 0; i < 100; ++i) {
    visited[i] = false;
    visitedIndex[this->getKey(i)] = i;

    this->Map[this->getKey(i)] = this->getValue(i);
  }

  // Iterate over all numbers and mark each one found.
  for (typename TypeParam::iterator it = this->Map.begin();
       it != this->Map.end(); ++it)
    visited[visitedIndex[it->first]] = true;

  // Ensure every number was visited.
  for (int i = 0; i < 100; ++i)
    ASSERT_TRUE(visited[i]) << "Entry #" << i << " was never visited";
}

// const_iterator test
TYPED_TEST(DenseMapTest, ConstIteratorTest) {
  // Check conversion from iterator to const_iterator.
  typename TypeParam::iterator it = this->Map.begin();
  typename TypeParam::const_iterator cit(it);
  EXPECT_TRUE(it == cit);

  // Check copying of const_iterators.
  typename TypeParam::const_iterator cit2(cit);
  EXPECT_TRUE(cit == cit2);
}

// Key traits that allows lookup with either an unsigned or char* key;
// In the latter case, "a" == 0, "b" == 1 and so on.
struct TestDenseMapInfo {
  static inline unsigned getEmptyKey() { return ~0; }
  static inline unsigned getTombstoneKey() { return ~0U - 1; }
  static unsigned getHashValue(const unsigned& Val) { return Val * 37U; }
  static unsigned getHashValue(const char* Val) {
    return (unsigned)(Val[0] - 'a') * 37U;
  }
  static bool isEqual(const unsigned& LHS, const unsigned& RHS) {
    return LHS == RHS;
  }
  static bool isEqual(const char* LHS, const unsigned& RHS) {
    return (unsigned)(LHS[0] - 'a') == RHS;
  }
};

// find_as() tests
TEST(DenseMapCustomTest, FindAsTest) {
  DenseMap<unsigned, unsigned, TestDenseMapInfo> map;
  map[0] = 1;
  map[1] = 2;
  map[2] = 3;

  // Size tests
  EXPECT_EQ(3u, map.size());

  // Normal lookup tests
  EXPECT_EQ(1, map.count(1));
  EXPECT_EQ(1u, map.find(0)->second);
  EXPECT_EQ(2u, map.find(1)->second);
  EXPECT_EQ(3u, map.find(2)->second);
  EXPECT_TRUE(map.find(3) == map.end());

  // find_as() tests
  EXPECT_EQ(1u, map.find_as("a")->second);
  EXPECT_EQ(2u, map.find_as("b")->second);
  EXPECT_EQ(3u, map.find_as("c")->second);
  EXPECT_TRUE(map.find_as("d") == map.end());
}

}
<|endoftext|>