/* * * Copyright (c) 2020 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @file * This file implements a unit test suite for CHIP SafeInt functions * */ #include #include #include #include using namespace chip; TEST(TestSpan, TestByteSpan) { uint8_t arr[] = { 1, 2, 3 }; ByteSpan s0 = ByteSpan(); EXPECT_EQ(s0.size(), 0u); EXPECT_TRUE(s0.empty()); EXPECT_TRUE(s0.data_equal(s0)); ByteSpan s1(arr, 2); EXPECT_EQ(s1.data(), arr); EXPECT_EQ(s1.size(), 2u); EXPECT_FALSE(s1.empty()); EXPECT_TRUE(s1.data_equal(s1)); EXPECT_FALSE(s1.data_equal(s0)); ByteSpan s2(arr); EXPECT_EQ(s2.data(), arr); EXPECT_EQ(s2.size(), 3u); EXPECT_EQ(s2.data()[2], 3u); EXPECT_FALSE(s2.empty()); EXPECT_TRUE(s2.data_equal(s2)); EXPECT_FALSE(s2.data_equal(s1)); EXPECT_EQ(s2.front(), 1u); EXPECT_EQ(s2.back(), 3u); EXPECT_EQ(s2[0], 1u); EXPECT_EQ(s2[1], 2u); EXPECT_EQ(s2[2], 3u); ByteSpan s3 = s2; EXPECT_EQ(s3.data(), arr); EXPECT_EQ(s3.size(), 3u); EXPECT_EQ(s3.data()[2], 3u); EXPECT_FALSE(s3.empty()); EXPECT_TRUE(s3.data_equal(s2)); uint8_t arr2[] = { 3, 2, 1 }; ByteSpan s4(arr2); EXPECT_FALSE(s4.data_equal(s2)); ByteSpan s5(arr2, 0); EXPECT_NE(s5.data(), nullptr); EXPECT_FALSE(s5.data_equal(s4)); EXPECT_TRUE(s5.data_equal(s0)); EXPECT_TRUE(s0.data_equal(s5)); ByteSpan s6(arr2); s6.reduce_size(2); EXPECT_EQ(s6.size(), 2u); ByteSpan s7(arr2, 2); EXPECT_TRUE(s6.data_equal(s7)); EXPECT_TRUE(s7.data_equal(s6)); } TEST(TestSpan, TestMutableByteSpan) { uint8_t arr[] = { 1, 2, 3 }; MutableByteSpan s0 = MutableByteSpan(); EXPECT_EQ(s0.size(), 0u); EXPECT_TRUE(s0.empty()); EXPECT_TRUE(s0.data_equal(s0)); MutableByteSpan s1(arr, 2); EXPECT_EQ(s1.data(), arr); EXPECT_EQ(s1.size(), 2u); EXPECT_FALSE(s1.empty()); EXPECT_TRUE(s1.data_equal(s1)); EXPECT_FALSE(s1.data_equal(s0)); MutableByteSpan s2(arr); EXPECT_EQ(s2.data(), arr); EXPECT_EQ(s2.size(), 3u); EXPECT_EQ(s2.data()[2], 3u); EXPECT_FALSE(s2.empty()); EXPECT_TRUE(s2.data_equal(s2)); EXPECT_FALSE(s2.data_equal(s1)); MutableByteSpan s3 = s2; EXPECT_EQ(s3.data(), arr); EXPECT_EQ(s3.size(), 3u); EXPECT_EQ(s3.data()[2], 3u); EXPECT_FALSE(s3.empty()); EXPECT_TRUE(s3.data_equal(s2)); uint8_t arr2[] = { 3, 2, 1 }; MutableByteSpan s4(arr2); EXPECT_FALSE(s4.data_equal(s2)); MutableByteSpan s5(arr2, 0); EXPECT_NE(s5.data(), nullptr); EXPECT_FALSE(s5.data_equal(s4)); EXPECT_TRUE(s5.data_equal(s0)); EXPECT_TRUE(s0.data_equal(s5)); MutableByteSpan s6(arr2); s6.reduce_size(2); EXPECT_EQ(s6.size(), 2u); MutableByteSpan s7(arr2, 2); EXPECT_TRUE(s6.data_equal(s7)); EXPECT_TRUE(s7.data_equal(s6)); uint8_t arr3[] = { 1, 2, 3 }; MutableByteSpan s8(arr3); EXPECT_EQ(arr3[1], 2u); s8.data()[1] = 3; EXPECT_EQ(arr3[1], 3u); // Not mutable span on purpose, to test conversion. ByteSpan s9 = s8; EXPECT_TRUE(s9.data_equal(s8)); EXPECT_TRUE(s8.data_equal(s9)); // Not mutable span on purpose. ByteSpan s10(s8); EXPECT_TRUE(s10.data_equal(s8)); EXPECT_TRUE(s8.data_equal(s10)); } TEST(TestSpan, TestFixedByteSpan) { uint8_t arr[] = { 1, 2, 3 }; FixedByteSpan<3> s0 = FixedByteSpan<3>(); EXPECT_NE(s0.data(), nullptr); EXPECT_EQ(s0.size(), 3u); EXPECT_TRUE(s0.data_equal(s0)); EXPECT_EQ(s0[0], 0u); EXPECT_EQ(s0[1], 0u); EXPECT_EQ(s0[2], 0u); FixedByteSpan<2> s1(arr); EXPECT_EQ(s1.data(), arr); EXPECT_EQ(s1.size(), 2u); EXPECT_TRUE(s1.data_equal(s1)); FixedByteSpan<3> s2(arr); EXPECT_EQ(s2.data(), arr); EXPECT_EQ(s2.size(), 3u); EXPECT_EQ(s2.data()[2], 3u); EXPECT_TRUE(s2.data_equal(s2)); EXPECT_EQ(s2.front(), 1u); EXPECT_EQ(s2.back(), 3u); EXPECT_EQ(s2[0], 1u); EXPECT_EQ(s2[1], 2u); EXPECT_EQ(s2[2], 3u); FixedByteSpan<3> s3 = s2; EXPECT_EQ(s3.data(), arr); EXPECT_EQ(s3.size(), 3u); EXPECT_EQ(s3.data()[2], 3u); EXPECT_TRUE(s3.data_equal(s2)); uint8_t arr2[] = { 3, 2, 1 }; FixedSpan s4(arr2); EXPECT_FALSE(s4.data_equal(s2)); size_t idx = 0; for (auto & entry : s4) { EXPECT_EQ(entry, arr2[idx++]); } EXPECT_EQ(idx, 3u); FixedByteSpan<3> s5(arr2); EXPECT_TRUE(s5.data_equal(s4)); EXPECT_TRUE(s4.data_equal(s5)); FixedByteSpan<2> s6(s4); idx = 0; for (auto & entry : s6) { EXPECT_EQ(entry, arr2[idx++]); } EXPECT_EQ(idx, 2u); // Not fixed, to test conversion. ByteSpan s7(s4); EXPECT_TRUE(s7.data_equal(s4)); EXPECT_TRUE(s4.data_equal(s7)); MutableByteSpan s8(s4); EXPECT_TRUE(s8.data_equal(s4)); EXPECT_TRUE(s4.data_equal(s8)); } TEST(TestSpan, TestSpanOfPointers) { uint8_t x = 5; uint8_t * ptrs[] = { &x, &x }; Span s1(ptrs); Span s2(s1); EXPECT_TRUE(s1.data_equal(s2)); EXPECT_TRUE(s2.data_equal(s1)); FixedSpan s3(ptrs); FixedSpan s4(s3); EXPECT_TRUE(s1.data_equal(s3)); EXPECT_TRUE(s3.data_equal(s1)); EXPECT_TRUE(s2.data_equal(s3)); EXPECT_TRUE(s3.data_equal(s2)); EXPECT_TRUE(s1.data_equal(s4)); EXPECT_TRUE(s4.data_equal(s1)); EXPECT_TRUE(s2.data_equal(s4)); EXPECT_TRUE(s4.data_equal(s2)); EXPECT_TRUE(s3.data_equal(s4)); EXPECT_TRUE(s4.data_equal(s3)); Span s5(s3); EXPECT_TRUE(s5.data_equal(s3)); EXPECT_TRUE(s3.data_equal(s5)); } TEST(TestSpan, TestSubSpan) { uint8_t array[16]; ByteSpan span(array); EXPECT_EQ(span.data(), &array[0]); EXPECT_EQ(span.size(), 16u); ByteSpan subspan = span.SubSpan(1, 14); EXPECT_EQ(subspan.data(), &array[1]); EXPECT_EQ(subspan.size(), 14u); subspan = span.SubSpan(1, 0); EXPECT_EQ(subspan.size(), 0u); subspan = span.SubSpan(10); EXPECT_EQ(subspan.data(), &array[10]); EXPECT_EQ(subspan.size(), 6u); subspan = span.SubSpan(16); EXPECT_EQ(subspan.size(), 0u); } TEST(TestSpan, TestFromZclString) { // Purposefully larger size than data. constexpr uint8_t array[16] = { 3, 0x41, 0x63, 0x45 }; static constexpr char str[] = "AcE"; ByteSpan s1 = ByteSpan::fromZclString(array); EXPECT_TRUE(s1.data_equal(ByteSpan(&array[1], 3u))); CharSpan s2 = CharSpan::fromZclString(array); EXPECT_TRUE(s2.data_equal(CharSpan(str, 3))); } TEST(TestSpan, TestFromCharString) { static constexpr char str[] = "AcE"; CharSpan s1 = CharSpan::fromCharString(str); EXPECT_TRUE(s1.data_equal(CharSpan(str, 3))); } TEST(TestSpan, TestLiteral) { constexpr CharSpan literal = "HI!"_span; EXPECT_EQ(literal.size(), 3u); EXPECT_TRUE(literal.data_equal(CharSpan::fromCharString("HI!"))); EXPECT_EQ(""_span.size(), 0u); // These should be compile errors -- if they were allowed they would produce // a CharSpan that includes the trailing '\0' byte in the value. // constexpr CharSpan disallowed1("abcd"); // constexpr CharSpan disallowed2{ "abcd" }; } TEST(TestSpan, TestConversionConstructors) { struct Foo { int member = 0; }; struct Bar : public Foo { }; Bar objects[2]; // Check that various things here compile. Span span1(objects); Span span2(&objects[0], 1); FixedSpan span3(objects); FixedSpan span4(objects); Span testSpan1(objects); FixedSpan testSpan2(objects); Span span5(testSpan1); Span span6(testSpan2); FixedSpan span7(testSpan2); std::array array; const auto & constArray = array; FixedSpan span9(array); FixedSpan span10(constArray); Span span11(array); Span span12(constArray); // Various places around the code base expect these conversions to be implicit ([](FixedSpan f) {})(array); ([](Span f) {})(array); ([](FixedSpan f) {})(constArray); ([](Span f) {})(constArray); EXPECT_TRUE(span10.data_equal(span10)); EXPECT_TRUE(span10.data_equal(span9)); EXPECT_TRUE(span10.data_equal(array)); EXPECT_TRUE(span10.data_equal(constArray)); EXPECT_TRUE(span9.data_equal(span9)); EXPECT_TRUE(span9.data_equal(span10)); EXPECT_TRUE(span9.data_equal(array)); EXPECT_TRUE(span9.data_equal(constArray)); // The following should not compile // Span error1 = std::array(); // Span would point into a temporary value }