| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| #include <gtest/gtest.h> |
| |
| #include <cstdio> |
| #include <cstring> |
| #include <limits> |
| #include <string> |
| |
| #include "cwrapper/tsfile_cwrapper.h" |
| #include "utils/errno_define.h" |
| |
| namespace { |
| |
| const TsFileProperty* FindProperty(const TsFileProperty* properties, |
| uint32_t property_count, |
| const std::string& key) { |
| for (uint32_t i = 0; i < property_count; i++) { |
| if (properties[i].key_len == key.size() && |
| std::memcmp(properties[i].key, key.data(), key.size()) == 0) { |
| return &properties[i]; |
| } |
| } |
| return nullptr; |
| } |
| |
| TEST(CWrapperPropertiesTest, GenericWriterRoundTripsLengthAwareValues) { |
| const char* file_name = "cwrapper_properties_test.tsfile"; |
| std::remove(file_name); |
| |
| ERRNO error_code = common::E_OK; |
| TsFileWriter writer = |
| _tsfile_writer_new(file_name, 128 * 1024 * 1024, &error_code); |
| ASSERT_NE(nullptr, writer); |
| ASSERT_EQ(common::E_OK, error_code); |
| |
| const uint8_t first[] = {'f', 'i', 'r', 's', 't'}; |
| const uint8_t binary[] = {0x00, 0xFF, 0x80, 0x01, 0x00}; |
| const char embedded_null_key[] = {'k', '\0', 'y'}; |
| const uint8_t empty_marker = 0; |
| EXPECT_EQ(common::E_INVALID_ARG, |
| _tsfile_writer_add_tsfile_property(nullptr, "key", 3, binary, |
| sizeof(binary))); |
| EXPECT_EQ(common::E_INVALID_ARG, |
| _tsfile_writer_add_tsfile_property(writer, nullptr, 0, binary, |
| sizeof(binary))); |
| EXPECT_EQ(common::E_INVALID_ARG, |
| _tsfile_writer_add_tsfile_property(writer, "key", 3, nullptr, 1)); |
| const uint32_t oversized_len = |
| static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) + 1U; |
| EXPECT_EQ(common::E_OUT_OF_RANGE, |
| _tsfile_writer_add_tsfile_property(writer, "key", 3, binary, |
| oversized_len)); |
| ASSERT_EQ(common::E_OK, |
| _tsfile_writer_add_tsfile_property(writer, "overwritten", 11, |
| first, sizeof(first))); |
| ASSERT_EQ(common::E_OK, _tsfile_writer_flush(writer)); |
| ASSERT_EQ(common::E_OK, |
| _tsfile_writer_add_tsfile_property(writer, "overwritten", 11, |
| binary, sizeof(binary))); |
| ASSERT_EQ(common::E_OK, |
| _tsfile_writer_add_tsfile_property(writer, embedded_null_key, |
| sizeof(embedded_null_key), |
| binary, sizeof(binary))); |
| ASSERT_EQ(common::E_OK, _tsfile_writer_add_tsfile_property( |
| writer, "empty", 5, &empty_marker, 0)); |
| ASSERT_EQ(common::E_OK, _tsfile_writer_add_tsfile_property(writer, "null", |
| 4, nullptr, 0)); |
| ASSERT_EQ(common::E_OK, _tsfile_writer_close(writer)); |
| |
| TsFileReader reader = tsfile_reader_new(file_name, &error_code); |
| ASSERT_NE(nullptr, reader); |
| ASSERT_EQ(common::E_OK, error_code); |
| TsFileProperty* properties = nullptr; |
| uint32_t property_count = 0; |
| ASSERT_EQ(common::E_OK, tsfile_reader_get_tsfile_properties( |
| reader, &properties, &property_count)); |
| |
| const TsFileProperty* overwritten = |
| FindProperty(properties, property_count, "overwritten"); |
| ASSERT_NE(nullptr, overwritten); |
| EXPECT_FALSE(overwritten->is_null); |
| ASSERT_EQ(sizeof(binary), overwritten->value_len); |
| EXPECT_EQ(0, std::memcmp(binary, overwritten->value, sizeof(binary))); |
| |
| const TsFileProperty* embedded_key_property = |
| FindProperty(properties, property_count, |
| std::string(embedded_null_key, sizeof(embedded_null_key))); |
| ASSERT_NE(nullptr, embedded_key_property); |
| ASSERT_EQ(sizeof(binary), embedded_key_property->value_len); |
| EXPECT_EQ( |
| 0, std::memcmp(binary, embedded_key_property->value, sizeof(binary))); |
| |
| const TsFileProperty* empty = |
| FindProperty(properties, property_count, "empty"); |
| ASSERT_NE(nullptr, empty); |
| EXPECT_FALSE(empty->is_null); |
| EXPECT_EQ(0U, empty->value_len); |
| |
| const TsFileProperty* null_value = |
| FindProperty(properties, property_count, "null"); |
| ASSERT_NE(nullptr, null_value); |
| EXPECT_TRUE(null_value->is_null); |
| EXPECT_EQ(0U, null_value->value_len); |
| |
| tsfile_free_tsfile_properties(properties, property_count); |
| TsFileProperty sentinel{}; |
| properties = &sentinel; |
| property_count = 1; |
| EXPECT_EQ(common::E_INVALID_ARG, |
| tsfile_reader_get_tsfile_properties(nullptr, &properties, |
| &property_count)); |
| EXPECT_EQ(nullptr, properties); |
| EXPECT_EQ(0U, property_count); |
| EXPECT_EQ(common::E_OK, tsfile_reader_close(reader)); |
| EXPECT_EQ(0, std::remove(file_name)); |
| } |
| |
| TEST(CWrapperPropertiesTest, TableWriterSetterUsesExplicitLengths) { |
| const char* file_name = "cwrapper_table_properties_test.tsfile"; |
| std::remove(file_name); |
| |
| ERRNO error_code = common::E_OK; |
| WriteFile file = write_file_new(file_name, &error_code); |
| ASSERT_NE(nullptr, file); |
| ASSERT_EQ(common::E_OK, error_code); |
| |
| ColumnSchema column = {const_cast<char*>("value"), TS_DATATYPE_INT64, |
| FIELD}; |
| TableSchema schema = {const_cast<char*>("table"), &column, 1}; |
| TsFileWriter writer = tsfile_writer_new(file, &schema, &error_code); |
| ASSERT_NE(nullptr, writer); |
| const uint8_t binary[] = {0xAA, 0x00, 0xBB}; |
| const uint32_t oversized_len = |
| static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) + 1U; |
| EXPECT_EQ(common::E_OUT_OF_RANGE, |
| tsfile_writer_add_tsfile_property(writer, "binary", 6, binary, |
| oversized_len)); |
| ASSERT_EQ(common::E_OK, tsfile_writer_add_tsfile_property( |
| writer, "binary", 6, binary, sizeof(binary))); |
| ASSERT_EQ(common::E_OK, tsfile_writer_close(writer)); |
| free_write_file(&file); |
| |
| TsFileReader reader = tsfile_reader_new(file_name, &error_code); |
| ASSERT_NE(nullptr, reader); |
| TsFileProperty* properties = nullptr; |
| uint32_t property_count = 0; |
| ASSERT_EQ(common::E_OK, tsfile_reader_get_tsfile_properties( |
| reader, &properties, &property_count)); |
| const TsFileProperty* property = |
| FindProperty(properties, property_count, "binary"); |
| ASSERT_NE(nullptr, property); |
| ASSERT_EQ(sizeof(binary), property->value_len); |
| EXPECT_EQ(0, std::memcmp(binary, property->value, sizeof(binary))); |
| tsfile_free_tsfile_properties(properties, property_count); |
| EXPECT_EQ(common::E_OK, tsfile_reader_close(reader)); |
| EXPECT_EQ(0, std::remove(file_name)); |
| } |
| |
| } // namespace |