Skip to content

Commit 67a53d5

Browse files
committed
chore: add tests
1 parent 7ed4a8a commit 67a53d5

File tree

1 file changed

+95
-36
lines changed

1 file changed

+95
-36
lines changed

google/cloud/bigtable/value_test.cc

Lines changed: 95 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "google/cloud/testing_util/is_proto_equal.h"
1919
#include "google/cloud/testing_util/status_matchers.h"
2020
#include "absl/strings/cord.h"
21+
#include "absl/strings/substitute.h"
2122
#include <google/protobuf/text_format.h>
2223
#include <google/type/date.pb.h>
2324
#include <gmock/gmock.h>
@@ -40,6 +41,7 @@ namespace {
4041
using ::google::cloud::testing_util::IsOk;
4142
using ::google::cloud::testing_util::IsOkAndHolds;
4243
using ::google::cloud::testing_util::IsProtoEqual;
44+
using ::google::cloud::testing_util::StatusIs;
4345
using ::google::protobuf::TextFormat;
4446
using ::testing::Not;
4547

@@ -1749,40 +1751,44 @@ TEST(Value, OutputStreamMatchesT) {
17491751
}
17501752

17511753
void TestTypeAndValuesMatch(std::string const& type_text,
1752-
std::string const& value_text, bool expected) {
1754+
std::string const& value_text,
1755+
Status const& expected_status) {
17531756
google::bigtable::v2::Type type;
17541757
ASSERT_TRUE(TextFormat::ParseFromString(type_text, &type));
17551758
google::bigtable::v2::Value value;
17561759
ASSERT_TRUE(TextFormat::ParseFromString(value_text, &value));
17571760
auto result = Value::TypeAndValuesMatch(type, value);
1758-
if (expected) {
1759-
EXPECT_STATUS_OK(result);
1760-
} else {
1761-
EXPECT_THAT(result, Not(IsOk()));
1762-
}
1761+
EXPECT_THAT(result,
1762+
StatusIs(expected_status.code(), expected_status.message()));
17631763
}
17641764

17651765
TEST(Value, TypeAndValuesMatchScalar) {
1766-
TestTypeAndValuesMatch("int64_type {}", "int_value: 123", true);
1767-
TestTypeAndValuesMatch("string_type {}", "string_value: 'hello'", true);
1768-
TestTypeAndValuesMatch("bool_type {}", "bool_value: true", true);
1769-
TestTypeAndValuesMatch("float64_type {}", "float_value: 3.14", true);
1770-
TestTypeAndValuesMatch("float32_type {}", "float_value: 3.14", true);
1771-
TestTypeAndValuesMatch("bytes_type {}", "bytes_value: 'bytes'", true);
1766+
TestTypeAndValuesMatch("int64_type {}", "int_value: 123", Status{});
1767+
TestTypeAndValuesMatch("string_type {}", "string_value: 'hello'", Status{});
1768+
TestTypeAndValuesMatch("bool_type {}", "bool_value: true", Status{});
1769+
TestTypeAndValuesMatch("float64_type {}", "float_value: 3.14", Status{});
1770+
TestTypeAndValuesMatch("float32_type {}", "float_value: 3.14", Status{});
1771+
TestTypeAndValuesMatch("bytes_type {}", "bytes_value: 'bytes'", Status{});
17721772
TestTypeAndValuesMatch("timestamp_type {}",
1773-
"timestamp_value: { seconds: 123 }", true);
1774-
TestTypeAndValuesMatch("date_type {}",
1775-
"date_value: { year: 2025, month: 1, day: 1 }", true);
1773+
"timestamp_value: { seconds: 123 }", Status{});
1774+
TestTypeAndValuesMatch(
1775+
"date_type {}", "date_value: { year: 2025, month: 1, day: 1 }", Status{});
17761776
}
17771777

17781778
TEST(Value, TypeAndValuesMatchScalarMismatch) {
1779-
TestTypeAndValuesMatch("int64_type {}", "string_value: 'mismatch'", false);
1780-
TestTypeAndValuesMatch("string_type {}", "int_value: 123", false);
1779+
TestTypeAndValuesMatch(
1780+
"int64_type {}", "string_value: 'mismatch'",
1781+
internal::InternalError(
1782+
"Value kind must be INT_VALUE for columns of type: INT64"));
1783+
TestTypeAndValuesMatch(
1784+
"string_type {}", "int_value: 123",
1785+
internal::InternalError(
1786+
"Value kind must be STRING_VALUE for columns of type: STRING"));
17811787
}
17821788

17831789
TEST(Value, TypeAndValuesMatchNullScalar) {
1784-
TestTypeAndValuesMatch("int64_type {}", "", true);
1785-
TestTypeAndValuesMatch("string_type {}", "", true);
1790+
TestTypeAndValuesMatch("int64_type {}", "", Status{});
1791+
TestTypeAndValuesMatch("string_type {}", "", Status{});
17861792
}
17871793

17881794
TEST(Value, TypeAndValuesMatchArray) {
@@ -1795,7 +1801,7 @@ TEST(Value, TypeAndValuesMatchArray) {
17951801
values { int_value: 2 }
17961802
}
17971803
)pb";
1798-
TestTypeAndValuesMatch(type, matching_value, true);
1804+
TestTypeAndValuesMatch(type, matching_value, Status{});
17991805
}
18001806

18011807
TEST(Value, TypeAndValuesMatchArrayMismatchElementType) {
@@ -1808,14 +1814,20 @@ TEST(Value, TypeAndValuesMatchArrayMismatchElementType) {
18081814
values { string_value: "2" }
18091815
}
18101816
)pb";
1811-
TestTypeAndValuesMatch(type, mismatched_value, false);
1817+
TestTypeAndValuesMatch(
1818+
type, mismatched_value,
1819+
internal::InternalError(
1820+
"Value kind must be INT_VALUE for columns of type: INT64"));
18121821
}
18131822

18141823
TEST(Value, TypeAndValuesMatchArrayMismatchScalar) {
18151824
auto const* type = R"pb(
18161825
array_type { element_type { int64_type {} } }
18171826
)pb";
1818-
TestTypeAndValuesMatch(type, "int_value: 123", false);
1827+
TestTypeAndValuesMatch(type, "int_value: 123",
1828+
internal::InternalError("Value kind must be "
1829+
"ARRAY_VALUE for columns of "
1830+
"type: MAP"));
18191831
}
18201832

18211833
TEST(Value, TypeAndValuesMatchArrayWithNull) {
@@ -1829,7 +1841,7 @@ TEST(Value, TypeAndValuesMatchArrayWithNull) {
18291841
values { int_value: 3 }
18301842
}
18311843
)pb";
1832-
TestTypeAndValuesMatch(type, value_with_null, true);
1844+
TestTypeAndValuesMatch(type, value_with_null, Status{});
18331845
}
18341846

18351847
TEST(Value, TypeAndValuesMatchStruct) {
@@ -1851,7 +1863,7 @@ TEST(Value, TypeAndValuesMatchStruct) {
18511863
values { int_value: 42 }
18521864
}
18531865
)pb";
1854-
TestTypeAndValuesMatch(type, matching_value, true);
1866+
TestTypeAndValuesMatch(type, matching_value, Status{});
18551867
}
18561868

18571869
TEST(Value, TypeAndValuesMatchStructMismatchFieldType) {
@@ -1873,7 +1885,10 @@ TEST(Value, TypeAndValuesMatchStructMismatchFieldType) {
18731885
values { string_value: "42" }
18741886
}
18751887
)pb";
1876-
TestTypeAndValuesMatch(type, mismatched_value, false);
1888+
TestTypeAndValuesMatch(
1889+
type, mismatched_value,
1890+
internal::InternalError(
1891+
"Value kind must be INT_VALUE for columns of type: INT64"));
18771892
}
18781893

18791894
TEST(Value, TypeAndValuesMatchStructMismatchFieldCount) {
@@ -1886,16 +1901,20 @@ TEST(Value, TypeAndValuesMatchStructMismatchFieldCount) {
18861901
auto const* mismatched_value = R"pb(
18871902
array_value { values { string_value: "John" } }
18881903
)pb";
1889-
// The current implementation has a bug and will return true here.
1890-
// This test will fail until the bug is fixed.
1891-
TestTypeAndValuesMatch(type, mismatched_value, false);
1904+
TestTypeAndValuesMatch(
1905+
type, mismatched_value,
1906+
internal::InternalError(
1907+
"received Struct with 1 values, but metadata has 2 fields"));
18921908
}
18931909

18941910
TEST(Value, TypeAndValuesMatchStructMismatchScalar) {
18951911
auto const* type = R"pb(
18961912
struct_type { fields { type { string_type {} } } }
18971913
)pb";
1898-
TestTypeAndValuesMatch(type, "string_value: 'John'", false);
1914+
TestTypeAndValuesMatch(
1915+
type, "string_value: 'John'",
1916+
internal::InternalError(
1917+
"Value kind must be ARRAY_VALUE for columns of type: STRUCT"));
18991918
}
19001919

19011920
TEST(Value, TypeAndValuesMatchStructWithNull) {
@@ -1911,7 +1930,7 @@ TEST(Value, TypeAndValuesMatchStructWithNull) {
19111930
values {}
19121931
}
19131932
)pb";
1914-
TestTypeAndValuesMatch(type, value_with_null, true);
1933+
TestTypeAndValuesMatch(type, value_with_null, Status{});
19151934
}
19161935

19171936
TEST(Value, TypeAndValuesMatchMap) {
@@ -1931,7 +1950,7 @@ TEST(Value, TypeAndValuesMatchMap) {
19311950
}
19321951
}
19331952
)pb";
1934-
TestTypeAndValuesMatch(type, matching_value, true);
1953+
TestTypeAndValuesMatch(type, matching_value, Status{});
19351954
}
19361955

19371956
TEST(Value, TypeAndValuesMatchMapMismatchKeyType) {
@@ -1951,7 +1970,10 @@ TEST(Value, TypeAndValuesMatchMapMismatchKeyType) {
19511970
}
19521971
}
19531972
)pb";
1954-
TestTypeAndValuesMatch(type, mismatched_value, false);
1973+
TestTypeAndValuesMatch(
1974+
type, mismatched_value,
1975+
internal::InternalError(
1976+
"Value kind must be STRING_VALUE for columns of type: STRING"));
19551977
}
19561978

19571979
TEST(Value, TypeAndValuesMatchMapMismatchValueType) {
@@ -1971,7 +1993,10 @@ TEST(Value, TypeAndValuesMatchMapMismatchValueType) {
19711993
}
19721994
}
19731995
)pb";
1974-
TestTypeAndValuesMatch(type, mismatched_value, false);
1996+
TestTypeAndValuesMatch(
1997+
type, mismatched_value,
1998+
internal::InternalError(
1999+
"Value kind must be INT_VALUE for columns of type: INT64"));
19752000
}
19762001

19772002
TEST(Value, TypeAndValuesMatchMapMismatchScalar) {
@@ -1981,7 +2006,10 @@ TEST(Value, TypeAndValuesMatchMapMismatchScalar) {
19812006
value_type { int64_type {} }
19822007
}
19832008
)pb";
1984-
TestTypeAndValuesMatch(type, "string_value: 'foo'", false);
2009+
TestTypeAndValuesMatch(
2010+
type, "string_value: 'foo'",
2011+
internal::InternalError(
2012+
"Value kind must be ARRAY_VALUE for columns of type: MAP"));
19852013
}
19862014

19872015
TEST(Value, TypeAndValuesMatchMapMalformedEntry) {
@@ -1994,7 +2022,9 @@ TEST(Value, TypeAndValuesMatchMapMalformedEntry) {
19942022
auto const* malformed_value = R"pb(
19952023
array_value { values { array_value { values { string_value: "key1" } } } }
19962024
)pb";
1997-
TestTypeAndValuesMatch(type, malformed_value, false);
2025+
TestTypeAndValuesMatch(
2026+
type, malformed_value,
2027+
internal::InternalError("ARRAY_VALUE must contain entries of 2 values"));
19982028
}
19992029

20002030
TEST(Value, TypeAndValuesMatchMapWithNullValue) {
@@ -2014,7 +2044,36 @@ TEST(Value, TypeAndValuesMatchMapWithNullValue) {
20142044
}
20152045
}
20162046
)pb";
2017-
TestTypeAndValuesMatch(type, value_with_null, true);
2047+
TestTypeAndValuesMatch(type, value_with_null, Status{});
2048+
}
2049+
2050+
TEST(Value, TypeAndValuesMatchDepthExceeded) {
2051+
std::string type_text = "int64_type {}";
2052+
std::string value_text = "int_value: 1";
2053+
2054+
// Each layer of struct nesting increases the depth count. The initial call is
2055+
// at depth 1. With the current implementation, each level of nesting
2056+
// increases the depth by 2. To exceed the limit of 10, we need 5 levels of
2057+
// nesting, which will result in a call with depth 11.
2058+
for (int i = 0; i < 5; ++i) {
2059+
type_text =
2060+
absl::Substitute("struct_type { fields { type { $0 } } }", type_text);
2061+
value_text = absl::Substitute("array_value { values { $0 } }", value_text);
2062+
}
2063+
2064+
TestTypeAndValuesMatch(
2065+
type_text, value_text,
2066+
internal::InternalError("Nested value depth exceeds 10 levels"));
2067+
2068+
// Verify that nesting up to the limit is fine. 4 levels of nesting will
2069+
// result in a maximum depth of 9.
2070+
type_text = "int64_type {}";
2071+
value_text = "int_value: 1";
2072+
for (int i = 0; i < 4; ++i) {
2073+
type_text = "struct_type { fields { type { " + type_text + "} } }";
2074+
value_text = "array_value { values { " + value_text + "} }";
2075+
}
2076+
TestTypeAndValuesMatch(type_text, value_text, Status{});
20182077
}
20192078

20202079
} // namespace

0 commit comments

Comments
 (0)