aboutsummaryrefslogtreecommitdiffstats
path: root/tests/unit
diff options
context:
space:
mode:
authorMarco Bubke <marco.bubke@qt.io>2020-05-26 20:31:41 +0200
committerMarco Bubke <marco.bubke@qt.io>2020-05-27 13:09:27 +0000
commit9c44f8d88d7ad80d22842545925f3e694afed182 (patch)
treec250a2c7cdda840e38d98b119ce933e7dbeda00e /tests/unit
parent22c33fb859a4c0d9d694edca2076708b1cf2f087 (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.h1
-rw-r--r--tests/unit/unittest/gtest-creator-printing.h20
-rw-r--r--tests/unit/unittest/sqlitestatement-test.cpp124
-rw-r--r--tests/unit/unittest/sqlitevalue-test.cpp9
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{};