Skip to content

Commit

Permalink
Merge pull request #509 from Cytnx-dev/test-storage-append
Browse files Browse the repository at this point in the history
Add test for `Storage::append()` with reallocation
  • Loading branch information
IvanaGyro authored Nov 19, 2024
2 parents 50c0553 + c7effd2 commit 0b510a6
Show file tree
Hide file tree
Showing 2 changed files with 175 additions and 126 deletions.
229 changes: 103 additions & 126 deletions tests/Storage_test.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
#include "Storage_test.h"
#include "test_tools.h"

#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>

#include "test_tools.h"

TEST_F(StorageTest, dtype_str) {
std::vector<cytnx_complex128> vcd = {cytnx_complex128(1, 2), cytnx_complex128(3, 4),
cytnx_complex128(5, 6)};
Expand Down Expand Up @@ -128,129 +133,101 @@ TYPED_TEST(vector_suite, storage_cpu_to_cpu) {
EXPECT_EQ(is(tar_sd, sd), true);
}

TYPED_TEST(vector_suite, storage_fill_d) {
auto e1 = TypeParam(2);
auto e2 = TypeParam(7);

std::vector<TypeParam> v = {e1, e2};
Storage sd = Storage::from_vector(v);

auto fille = double(10);
sd.fill(fille);

EXPECT_EQ(sd.at<TypeParam>(0), TypeParam(fille));
EXPECT_EQ(sd.at<TypeParam>(1), TypeParam(fille));
}

TYPED_TEST(vector_suite, storage_fill_f) {
auto e1 = TypeParam(2);
auto e2 = TypeParam(7);

std::vector<TypeParam> v = {e1, e2};
Storage sd = Storage::from_vector(v);

auto fille = float(10);
sd.fill(fille);
cout << sd << endl;

EXPECT_EQ(sd.at<TypeParam>(0), TypeParam(fille));
EXPECT_EQ(sd.at<TypeParam>(1), TypeParam(fille));
}

TYPED_TEST(vector_suite, storage_fill_i64) {
auto e1 = TypeParam(2);
auto e2 = TypeParam(7);

std::vector<TypeParam> v = {e1, e2};
Storage sd = Storage::from_vector(v);

auto fille = cytnx_int64(10);
sd.fill(fille);

EXPECT_EQ(sd.at<TypeParam>(0), TypeParam(fille));
EXPECT_EQ(sd.at<TypeParam>(1), TypeParam(fille));
}

TYPED_TEST(vector_suite, storage_fill_u64) {
auto e1 = TypeParam(2);
auto e2 = TypeParam(7);

std::vector<TypeParam> v = {e1, e2};
Storage sd = Storage::from_vector(v);

auto fille = cytnx_uint64(10);
sd.fill(fille);

EXPECT_EQ(sd.at<TypeParam>(0), TypeParam(fille));
EXPECT_EQ(sd.at<TypeParam>(1), TypeParam(fille));
}

TYPED_TEST(vector_suite, storage_fill_i32) {
auto e1 = TypeParam(2);
auto e2 = TypeParam(7);

std::vector<TypeParam> v = {e1, e2};
Storage sd = Storage::from_vector(v);

auto fille = cytnx_int32(10);
sd.fill(fille);

EXPECT_EQ(sd.at<TypeParam>(0), TypeParam(fille));
EXPECT_EQ(sd.at<TypeParam>(1), TypeParam(fille));
}

TYPED_TEST(vector_suite, storage_fill_u32) {
auto e1 = TypeParam(2);
auto e2 = TypeParam(7);

std::vector<TypeParam> v = {e1, e2};
Storage sd = Storage::from_vector(v);

auto fille = cytnx_uint32(10);
sd.fill(fille);

EXPECT_EQ(sd.at<TypeParam>(0), TypeParam(fille));
EXPECT_EQ(sd.at<TypeParam>(1), TypeParam(fille));
}

TYPED_TEST(vector_suite, storage_fill_i16) {
auto e1 = TypeParam(2);
auto e2 = TypeParam(7);

std::vector<TypeParam> v = {e1, e2};
Storage sd = Storage::from_vector(v);

auto fille = cytnx_int16(10);
sd.fill(fille);

EXPECT_EQ(sd.at<TypeParam>(0), TypeParam(fille));
EXPECT_EQ(sd.at<TypeParam>(1), TypeParam(fille));
}

TYPED_TEST(vector_suite, storage_fill_u16) {
auto e1 = TypeParam(2);
auto e2 = TypeParam(7);

std::vector<TypeParam> v = {e1, e2};
Storage sd = Storage::from_vector(v);

auto fille = cytnx_uint16(10);
sd.fill(fille);

EXPECT_EQ(sd.at<TypeParam>(0), TypeParam(fille));
EXPECT_EQ(sd.at<TypeParam>(1), TypeParam(fille));
}

TYPED_TEST(vector_suite, storage_fill_b) {
auto e1 = TypeParam(2);
auto e2 = TypeParam(7);

std::vector<TypeParam> v = {e1, e2};
Storage sd = Storage::from_vector(v);

auto fille = true;
sd.fill(fille);

EXPECT_EQ(sd.at<TypeParam>(0), TypeParam(fille));
EXPECT_EQ(sd.at<TypeParam>(1), TypeParam(fille));
using TestingValueDTypes =
std::tuple<Scalar, cytnx_complex128, cytnx_complex64, cytnx_double, cytnx_float, cytnx_uint64,
cytnx_int64, cytnx_uint32, cytnx_int32, cytnx_uint16, cytnx_int16, cytnx_bool>;

using TestingStorageDTypes =
std::tuple<cytnx_complex128, cytnx_complex64, cytnx_double, cytnx_float, cytnx_uint64,
cytnx_int64, cytnx_uint32, cytnx_int32, cytnx_uint16, cytnx_int16, cytnx_bool>;

using TestingPutValueTypes =
TestTools::TestTypeCombinations<TestingStorageDTypes, TestingValueDTypes>;

template <class TypeParam>
struct StoragePutValue : testing::Test {
using StorageDType = typename TypeParam::first_type;
using ValueDType = typename TypeParam::second_type;

/**
* Try to convert the given value to the data type of the storage.
*
* @return `std::false_type{}` if the given value cannot be converted to the data type of the
* storage, otherwise, return the converted value
*/
auto TryConvertToStorageDType(const ValueDType& value) {
if constexpr (is_complex_v<ValueDType> && is_complex_v<StorageDType>) {
using ValueDTypeInComplex = typename ValueDType::value_type;
using StorageDTypeInComplex = typename StorageDType::value_type;
if constexpr (is_convertible_v<ValueDTypeInComplex, StorageDTypeInComplex>) {
return StorageDType{StorageDTypeInComplex(value.real()),
StorageDTypeInComplex(value.imag())};
} else {
return std::false_type{};
}
} else if constexpr (std::is_same_v<ValueDType, Scalar> &&
std::is_same_v<StorageDType, cytnx_complex128>) {
// There is no conversion function for converting a value from Scalar to complex types.
return complex128(value);
} else if constexpr (std::is_same_v<ValueDType, Scalar> &&
std::is_same_v<StorageDType, cytnx_complex64>) {
return complex64(value);
} else if constexpr (std::is_constructible_v<StorageDType, ValueDType>) {
// handle both implicit conversion and explicit conversion
return StorageDType(value);
} else {
return std::false_type{};
}
}
};
TYPED_TEST_SUITE(StoragePutValue, TestingPutValueTypes);

TYPED_TEST(StoragePutValue, Fill) {
using StorageDType = typename TestFixture::StorageDType;
using ValueDType = typename TestFixture::ValueDType;
if constexpr (std::is_same_v<ValueDType, Scalar>) {
GTEST_SKIP() << "Filling a storage with a Scalar is not supported.";
} else {
auto element1 = StorageDType(2);
auto element2 = StorageDType(7);

std::vector<StorageDType> v = {element1, element2};
Storage storage = Storage::from_vector(v);

auto value_to_fill = ValueDType(10);
auto value_in_storage_dtype = this->TryConvertToStorageDType(value_to_fill);
if constexpr (std::is_same_v<decltype(value_in_storage_dtype), std::false_type>) {
EXPECT_THROW(storage.fill(value_to_fill), std::logic_error);
} else {
storage.fill(value_to_fill);
EXPECT_EQ(storage.at<StorageDType>(0), StorageDType(value_to_fill));
EXPECT_EQ(storage.at<StorageDType>(1), StorageDType(value_to_fill));
}
}
}

TYPED_TEST(StoragePutValue, AppendWithReallocation) {
using StorageDType = typename TestFixture::StorageDType;
using ValueDType = typename TestFixture::ValueDType;

auto element1 = StorageDType(2);
auto element2 = StorageDType(7);

std::vector<StorageDType> v = {element1, element2};
Storage storage = Storage::from_vector(v);

ASSERT_EQ(storage.dtype(), Type.cy_typeid(element1));
ASSERT_EQ(storage.size(), storage.capacity());

auto value_to_append = ValueDType(10);
auto value_in_storage_dtype = this->TryConvertToStorageDType(value_to_append);
constexpr bool is_not_convertible =
std::is_same_v<decltype(value_in_storage_dtype), std::false_type>;
if constexpr (is_not_convertible) {
EXPECT_THROW(storage.append(value_to_append), std::logic_error);
} else {
storage.append(value_to_append);
EXPECT_GE(storage.capacity(), storage.size());
EXPECT_EQ(storage.size(), 3);
}
}
72 changes: 72 additions & 0 deletions tests/test_tools.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,78 @@ namespace TestTools {
// Device.cuda, //currently cuda version still not implement
};

template <typename, typename>
struct TypeCombinationsImpl;

template <typename FirstType, typename... SecondTypes>
struct TypeCombinationsImpl<FirstType, std::tuple<SecondTypes...>> {
using type = std::tuple<std::pair<FirstType, SecondTypes>...>;
};

template <typename... FirstTypes, typename... SecondTypes>
struct TypeCombinationsImpl<std::tuple<FirstTypes...>, std::tuple<SecondTypes...>> {
using type = decltype(std::tuple_cat(
std::declval<
typename TypeCombinationsImpl<FirstTypes, std::tuple<SecondTypes...>>::type>()...));
};

/**
* @brief Generate pairs of all combinations of the types in the given tuples.
*
* @tparam FirstTuple a tuple composed of the types which will be the first type of the pair
* @tparam SecondTuple a tuple composed of the types which will be the second type of the pair
*
*
* @code
* ```cpp
*
* static_assert(
* std::is_same_v<
* TypeCombinations<std::tuple<int, std::string>,
* std::tuple<int, double, std::string>>,
* std::tuple<std::pair<int, int>, std::pair<int, double>,
* std::pair<int, std::string>, std::pair<std::string, int>,
* std::pair<std::string, double>,
* std::pair<std::string, std::string>>>);
*
* ```
* @endcode
*/
template <typename FirstTuple, typename SecondTuple>
using TypeCombinations = typename TypeCombinationsImpl<FirstTuple, SecondTuple>::type;

template <typename... TypesInTuple>
constexpr auto TupleToTestTypesHelper(std::tuple<TypesInTuple...>)
-> testing::Types<TypesInTuple...>;

/**
* @brief Generate pairs of all combinations of the types in the given tuples.
*
* @tparam FirstTuple a tuple composed of the types which will be the first type of the pair
* @tparam SecondTuple a tuple composed of the types which will be the second type of the pair
*
*
* @code
* ```cpp
*
* static_assert(
* std::is_same_v<
* TypeCombinations<std::tuple<int, std::string>,
* std::tuple<int, double, std::string>>,
* testing::Types<std::pair<int, int>,
* std::pair<int, double>,
* std::p<air<int, std::string>,
* std::pair<std::string, int>,
* std::pair<std::string, double>,
* std::pair<std::string, std::string>>>);
*
* ```
* @endcode
*/
template <typename FirstTuple, typename SecondTuple>
using TestTypeCombinations =
decltype(TupleToTestTypesHelper(std::declval<TypeCombinations<FirstTuple, SecondTuple>>()));

// Tensor tools

// given the tensor T with shape and dtype has been initialzed, set its data as random uniform.
Expand Down

0 comments on commit 0b510a6

Please sign in to comment.