diff options
author | Marco Bubke <marco.bubke@qt.io> | 2020-05-26 20:31:41 +0200 |
---|---|---|
committer | Marco Bubke <marco.bubke@qt.io> | 2020-05-27 13:09:27 +0000 |
commit | 9c44f8d88d7ad80d22842545925f3e694afed182 (patch) | |
tree | c250a2c7cdda840e38d98b119ce933e7dbeda00e /tests/unit | |
parent | 22c33fb859a4c0d9d694edca2076708b1cf2f087 (diff) |
Sqlite: Add blob support
Change-Id: Ic2ec5f20c8585241b9e9aaa8465e70b6ab4f004c
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
Diffstat (limited to 'tests/unit')
-rw-r--r-- | tests/unit/unittest/google-using-declarations.h | 1 | ||||
-rw-r--r-- | tests/unit/unittest/gtest-creator-printing.h | 20 | ||||
-rw-r--r-- | tests/unit/unittest/sqlitestatement-test.cpp | 124 | ||||
-rw-r--r-- | tests/unit/unittest/sqlitevalue-test.cpp | 9 |
4 files changed, 149 insertions, 5 deletions
diff --git a/tests/unit/unittest/google-using-declarations.h b/tests/unit/unittest/google-using-declarations.h index a1975ae7a8..1a92ff3388 100644 --- a/tests/unit/unittest/google-using-declarations.h +++ b/tests/unit/unittest/google-using-declarations.h @@ -58,6 +58,7 @@ using testing::Ne; using testing::NiceMock; using testing::Not; using testing::NotNull; +using testing::Optional; using testing::Pair; using testing::PrintToString; using testing::Property; diff --git a/tests/unit/unittest/gtest-creator-printing.h b/tests/unit/unittest/gtest-creator-printing.h index b91c8d46be..ea33bc9d49 100644 --- a/tests/unit/unittest/gtest-creator-printing.h +++ b/tests/unit/unittest/gtest-creator-printing.h @@ -348,4 +348,24 @@ std::ostream &operator<<(std::ostream &out, const Diagnostic &diag); } // namespace Internal } // namespace CppTools +namespace std { +template<typename T> +ostream &operator<<(ostream &out, const vector<T> &vector) +{ + out << "["; + + for (auto current = vector.begin(); current != vector.end(); ++current) { + out << *current; + + if (std::next(current) != vector.end()) + out << ", "; + } + + out << "]"; + + return out; +} + +} // namespace std + void setFilePathCache(ClangBackEnd::FilePathCaching *filePathCache); diff --git a/tests/unit/unittest/sqlitestatement-test.cpp b/tests/unit/unittest/sqlitestatement-test.cpp index 94eb003c4d..ce40e0c3d8 100644 --- a/tests/unit/unittest/sqlitestatement-test.cpp +++ b/tests/unit/unittest/sqlitestatement-test.cpp @@ -38,6 +38,14 @@ #include <vector> +namespace Sqlite { +bool operator==(Utils::span<const byte> first, Utils::span<const byte> second) +{ + return first.size() == second.size() + && std::memcmp(first.data(), second.data(), first.size()) == 0; +} +} // namespace Sqlite + namespace { using Sqlite::Database; @@ -288,6 +296,30 @@ TEST_F(SqliteStatement, BindPointer) ASSERT_THAT(statement.fetchIntValue(0), 1); } +TEST_F(SqliteStatement, BindBlob) +{ + SqliteTestStatement statement("WITH T(blob) AS (VALUES (?)) SELECT blob FROM T", database); + const unsigned char chars[] = "aaafdfdlll"; + auto bytePointer = reinterpret_cast<const Sqlite::byte *>(chars); + Utils::span<const Sqlite::byte> bytes{bytePointer, sizeof(chars) - 1}; + + statement.bind(1, bytes); + statement.next(); + + ASSERT_THAT(statement.fetchBlobValue(0), Eq(bytes)); +} + +TEST_F(SqliteStatement, BindEmptyBlob) +{ + SqliteTestStatement statement("WITH T(blob) AS (VALUES (?)) SELECT blob FROM T", database); + Utils::span<const Sqlite::byte> bytes; + + statement.bind(1, bytes); + statement.next(); + + ASSERT_THAT(statement.fetchBlobValue(0), IsEmpty()); +} + TEST_F(SqliteStatement, BindIntegerByParameter) { SqliteTestStatement statement("SELECT name, number FROM test WHERE number=@number", database); @@ -332,41 +364,49 @@ TEST_F(SqliteStatement, BindIndexIsZeroIsThrowingBindingIndexIsOutOfBoundNull) ASSERT_THROW(statement.bind(0, Sqlite::NullValue{}), Sqlite::BindingIndexIsOutOfRange); } -TEST_F(SqliteStatement, BindIndexIsTpLargeIsThrowingBindingIndexIsOutOfBoundLongLong) +TEST_F(SqliteStatement, BindIndexIsToLargeIsThrowingBindingIndexIsOutOfBoundLongLong) { SqliteTestStatement statement("SELECT name, number FROM test WHERE number=$1", database); ASSERT_THROW(statement.bind(2, 40LL), Sqlite::BindingIndexIsOutOfRange); } -TEST_F(SqliteStatement, BindIndexIsTpLargeIsThrowingBindingIndexIsOutOfBoundStringView) +TEST_F(SqliteStatement, BindIndexIsToLargeIsThrowingBindingIndexIsOutOfBoundStringView) { SqliteTestStatement statement("SELECT name, number FROM test WHERE number=$1", database); ASSERT_THROW(statement.bind(2, "foo"), Sqlite::BindingIndexIsOutOfRange); } -TEST_F(SqliteStatement, BindIndexIsTpLargeIsThrowingBindingIndexIsOutOfBoundStringFloat) +TEST_F(SqliteStatement, BindIndexIsToLargeIsThrowingBindingIndexIsOutOfBoundStringFloat) { SqliteTestStatement statement("SELECT name, number FROM test WHERE number=$1", database); ASSERT_THROW(statement.bind(2, 2.), Sqlite::BindingIndexIsOutOfRange); } -TEST_F(SqliteStatement, BindIndexIsTpLargeIsThrowingBindingIndexIsOutOfBoundPointer) +TEST_F(SqliteStatement, BindIndexIsToLargeIsThrowingBindingIndexIsOutOfBoundPointer) { SqliteTestStatement statement("SELECT name, number FROM test WHERE number=$1", database); ASSERT_THROW(statement.bind(2, nullptr), Sqlite::BindingIndexIsOutOfRange); } -TEST_F(SqliteStatement, BindIndexIsTpLargeIsThrowingBindingIndexIsOutOfBoundValue) +TEST_F(SqliteStatement, BindIndexIsToLargeIsThrowingBindingIndexIsOutOfBoundValue) { SqliteTestStatement statement("SELECT name, number FROM test WHERE number=$1", database); ASSERT_THROW(statement.bind(2, Sqlite::Value{1}), Sqlite::BindingIndexIsOutOfRange); } +TEST_F(SqliteStatement, BindIndexIsToLargeIsThrowingBindingIndexIsOutOfBoundBlob) +{ + SqliteTestStatement statement("WITH T(blob) AS (VALUES (?)) SELECT blob FROM T", database); + Utils::span<const Sqlite::byte> bytes; + + ASSERT_THROW(statement.bind(2, bytes), Sqlite::BindingIndexIsOutOfRange); +} + TEST_F(SqliteStatement, WrongBindingNameThrowingBindingIndexIsOutOfBound) { SqliteTestStatement statement("SELECT name, number FROM test WHERE number=@name", database); @@ -431,6 +471,40 @@ TEST_F(SqliteStatement, WriteSqliteValues) ASSERT_THAT(statement, HasValues("see", "7.23", 1)); } +TEST_F(SqliteStatement, WriteEmptyBlobs) +{ + SqliteTestStatement statement("WITH T(blob) AS (VALUES (?)) SELECT blob FROM T", database); + + Utils::span<const Sqlite::byte> bytes; + + statement.write(bytes); + + ASSERT_THAT(statement.fetchBlobValue(0), IsEmpty()); +} + +class Blob +{ +public: + Blob(Utils::span<const Sqlite::byte> bytes) + : bytes(bytes.begin(), bytes.end()) + {} + + std::vector<Sqlite::byte> bytes; +}; + +TEST_F(SqliteStatement, WriteBlobs) +{ + SqliteTestStatement statement("INSERT INTO test VALUES ('blob', 40, ?)", database); + SqliteTestStatement readStatement("SELECT value FROM test WHERE name = 'blob'", database); + const unsigned char chars[] = "aaafdfdlll"; + auto bytePointer = reinterpret_cast<const Sqlite::byte *>(chars); + Utils::span<const Sqlite::byte> bytes{bytePointer, sizeof(chars) - 1}; + + statement.write(bytes); + + ASSERT_THAT(readStatement.template value<Blob>(), Optional(Field(&Blob::bytes, Eq(bytes)))); +} + TEST_F(SqliteStatement, BindNamedValues) { SqliteTestStatement statement("UPDATE test SET name=@name, number=@number WHERE rowid=@id", database); @@ -633,6 +707,46 @@ TEST_F(SqliteStatement, GetStructOutputValuesAndContainerQueryTupleValues) Output{"bar", "blah", 1})); } +TEST_F(SqliteStatement, GetBlobValues) +{ + database.execute("INSERT INTO test VALUES ('blob', 40, x'AABBCCDD')"); + ReadStatement statement("SELECT value FROM test WHERE name='blob'", database); + const int value = 0xDDCCBBAA; + auto bytePointer = reinterpret_cast<const Sqlite::byte *>(&value); + Utils::span<const Sqlite::byte> bytes{bytePointer, 4}; + + auto values = statement.values<Blob>(1); + + ASSERT_THAT(values, ElementsAre(Field(&Blob::bytes, Eq(bytes)))); +} + +TEST_F(SqliteStatement, GetEmptyBlobValueForInteger) +{ + ReadStatement statement("SELECT value FROM test WHERE name='poo'", database); + + auto value = statement.value<Blob>(); + + ASSERT_THAT(value, Optional(Field(&Blob::bytes, IsEmpty()))); +} + +TEST_F(SqliteStatement, GetEmptyBlobValueForFloat) +{ + ReadStatement statement("SELECT number FROM test WHERE name='foo'", database); + + auto value = statement.value<Blob>(); + + ASSERT_THAT(value, Optional(Field(&Blob::bytes, IsEmpty()))); +} + +TEST_F(SqliteStatement, GetEmptyBlobValueForText) +{ + ReadStatement statement("SELECT number FROM test WHERE name='bar'", database); + + auto value = statement.value<Blob>(); + + ASSERT_THAT(value, Optional(Field(&Blob::bytes, IsEmpty()))); +} + TEST_F(SqliteStatement, GetOptionalSingleValueAndMultipleQueryValue) { ReadStatement statement("SELECT name FROM test WHERE name=? AND number=? AND value=?", database); diff --git a/tests/unit/unittest/sqlitevalue-test.cpp b/tests/unit/unittest/sqlitevalue-test.cpp index ab4d628ec8..1a90c330f0 100644 --- a/tests/unit/unittest/sqlitevalue-test.cpp +++ b/tests/unit/unittest/sqlitevalue-test.cpp @@ -85,6 +85,15 @@ TEST(SqliteValue, ConstructStringFromQString) ASSERT_THAT(value.toStringView(), Eq("foo")); } +TEST(SqliteValue, ConstructStringFromBlob) +{ + // Utils::span<const Sqlite::byte> bytes{reinterpret_cast<const Sqlite::byte *>("abcd"), 4}; + + // Sqlite::Value value{bytes}; + + //ASSERT_THAT(value.toBlob(), Eq(bytes)); +} + TEST(SqliteValue, ConstructNullFromNullQVariant) { QVariant variant{}; |