diff --git a/src/libs/sqlite/CMakeLists.txt b/src/libs/sqlite/CMakeLists.txt index 62c8609a7af..af6482e4a32 100644 --- a/src/libs/sqlite/CMakeLists.txt +++ b/src/libs/sqlite/CMakeLists.txt @@ -20,6 +20,7 @@ add_qtc_library(Sqlite sqlitetable.h sqlitetransaction.h sqlitewritestatement.cpp sqlitewritestatement.h + sqlitevalue.h sqlstatementbuilder.cpp sqlstatementbuilder.h sqlstatementbuilderexception.h utf8string.cpp utf8string.h diff --git a/src/libs/sqlite/sqlite-lib.pri b/src/libs/sqlite/sqlite-lib.pri index 4d7f906a199..1ce343b6247 100644 --- a/src/libs/sqlite/sqlite-lib.pri +++ b/src/libs/sqlite/sqlite-lib.pri @@ -32,6 +32,7 @@ HEADERS += \ $$PWD/sqlitereadstatement.h \ $$PWD/sqlitereadwritestatement.h \ $$PWD/sqlitetransaction.h \ + $$PWD/sqlitevalue.h \ $$PWD/sqlitewritestatement.h \ $$PWD/sqlstatementbuilder.h \ $$PWD/sqlstatementbuilderexception.h \ diff --git a/src/libs/sqlite/sqlitebasestatement.cpp b/src/libs/sqlite/sqlitebasestatement.cpp index 87aa3f68b37..85a6db2ddcd 100644 --- a/src/libs/sqlite/sqlitebasestatement.cpp +++ b/src/libs/sqlite/sqlitebasestatement.cpp @@ -190,6 +190,21 @@ void BaseStatement::bind(int index, Utils::SmallStringView text) checkForBindingError(resultCode); } +void BaseStatement::bind(int index, const Value &value) +{ + switch (value.type()) { + case ValueType::Integer: + bind(index, value.toInteger()); + break; + case ValueType::Float: + bind(index, value.toFloat()); + break; + case ValueType::String: + bind(index, value.toStringView()); + break; + } +} + template void BaseStatement::bind(Utils::SmallStringView name, Type value) { @@ -498,12 +513,34 @@ StringType BaseStatement::fetchValue(int column) const return convertToTextForColumn(m_compiledStatement.get(), column); } +template SQLITE_EXPORT Utils::SmallStringView BaseStatement::fetchValue( + int column) const; +template SQLITE_EXPORT Utils::SmallString BaseStatement::fetchValue( + int column) const; +template SQLITE_EXPORT Utils::PathString BaseStatement::fetchValue( + int column) const; + Utils::SmallStringView BaseStatement::fetchSmallStringViewValue(int column) const { return fetchValue(column); } -template SQLITE_EXPORT Utils::SmallStringView BaseStatement::fetchValue(int column) const; -template SQLITE_EXPORT Utils::SmallString BaseStatement::fetchValue(int column) const; -template SQLITE_EXPORT Utils::PathString BaseStatement::fetchValue(int column) const; +ValueView BaseStatement::fetchValueView(int column) const +{ + int dataType = sqlite3_column_type(m_compiledStatement.get(), column); + switch (dataType) { + case SQLITE_INTEGER: + return ValueView::create(fetchLongLongValue(column)); + case SQLITE_FLOAT: + return ValueView::create(fetchDoubleValue(column)); + case SQLITE3_TEXT: + return ValueView::create(fetchValue(column)); + case SQLITE_BLOB: + case SQLITE_NULL: + break; + } + + return ValueView::create(0LL); +} + } // namespace Sqlite diff --git a/src/libs/sqlite/sqlitebasestatement.h b/src/libs/sqlite/sqlitebasestatement.h index 86d03fd8553..aa40e0c6ea2 100644 --- a/src/libs/sqlite/sqlitebasestatement.h +++ b/src/libs/sqlite/sqlitebasestatement.h @@ -28,6 +28,7 @@ #include "sqliteglobal.h" #include "sqliteexception.h" +#include "sqlitevalue.h" #include @@ -67,6 +68,7 @@ public: long long fetchLongLongValue(int column) const; double fetchDoubleValue(int column) const; Utils::SmallStringView fetchSmallStringViewValue(int column) const; + ValueView fetchValueView(int column) const; template Type fetchValue(int column) const; int columnCount() const; @@ -76,11 +78,9 @@ public: void bind(int index, long long fetchValue); void bind(int index, double fetchValue); void bind(int index, Utils::SmallStringView fetchValue); + void bind(int index, const Value &fetchValue); - void bind(int index, uint value) - { - bind(index, static_cast(value)); - } + void bind(int index, uint value) { bind(index, static_cast(value)); } void bind(int index, long value) { @@ -345,34 +345,16 @@ private: struct ValueGetter { ValueGetter(StatementImplementation &statement, int column) - : statement(statement), - column(column) + : statement(statement) + , column(column) {} - operator int() - { - return statement.fetchIntValue(column); - } - - operator long() - { - return statement.fetchLongValue(column); - } - - operator long long() - { - return statement.fetchLongLongValue(column); - } - - operator double() - { - return statement.fetchDoubleValue(column); - } - - operator Utils::SmallStringView() - { - return statement.fetchSmallStringViewValue(column); - } + operator int() { return statement.fetchIntValue(column); } + operator long() { return statement.fetchLongValue(column); } + operator long long() { return statement.fetchLongLongValue(column); } + operator double() { return statement.fetchDoubleValue(column); } + operator Utils::SmallStringView() { return statement.fetchSmallStringViewValue(column); } + operator ValueView() { return statement.fetchValueView(column); } StatementImplementation &statement; int column; diff --git a/src/libs/sqlite/sqliteexception.h b/src/libs/sqlite/sqliteexception.h index 8edfd984ef4..6f898504a4c 100644 --- a/src/libs/sqlite/sqliteexception.h +++ b/src/libs/sqlite/sqliteexception.h @@ -264,4 +264,12 @@ public: } }; +class CannotConvert : public Exception +{ +public: + CannotConvert(const char *whatErrorHasHappen) + : Exception(whatErrorHasHappen) + {} +}; + } // namespace Sqlite diff --git a/src/libs/sqlite/sqlitevalue.h b/src/libs/sqlite/sqlitevalue.h new file mode 100644 index 00000000000..ca576421777 --- /dev/null +++ b/src/libs/sqlite/sqlitevalue.h @@ -0,0 +1,300 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "sqliteexception.h" + +#include +#include + +#include + +#pragma once + +namespace Sqlite { + +enum class ValueType : unsigned char { Integer, Float, String }; + +template +class ValueBase +{ +public: + using VariantType = Utils::variant; + + explicit ValueBase(VariantType &&value) + : value(value) + {} + + explicit ValueBase(const char *value) + : value(Utils::SmallStringView{value}) + {} + + explicit ValueBase(long long value) + : value(value) + {} + explicit ValueBase(int value) + : value(static_cast(value)) + {} + + explicit ValueBase(uint value) + : value(static_cast(value)) + {} + + explicit ValueBase(double value) + : value(value) + {} + + explicit ValueBase(Utils::SmallStringView value) + : value(value) + + {} + + long long toInteger() const { return Utils::get(value); } + + double toFloat() const { return Utils::get(value); } + + Utils::SmallStringView toStringView() const + { + return Utils::get(value); + } + + explicit operator QVariant() const + { + switch (type()) { + case ValueType::Integer: + return QVariant(toInteger()); + case ValueType::Float: + return QVariant(toFloat()); + case ValueType::String: + return QVariant(QString(toStringView())); + } + + return {}; + } + + friend bool operator==(const ValueBase &first, long long second) + { + auto maybeInteger = Utils::get_if(&first.value); + + return maybeInteger && *maybeInteger == second; + } + + friend bool operator==(long long first, const ValueBase &second) { return second == first; } + + friend bool operator==(const ValueBase &first, double second) + { + auto maybeInteger = Utils::get_if(&first.value); + + return maybeInteger && *maybeInteger == second; + } + + friend bool operator==(const ValueBase &first, int second) + { + return first == static_cast(second); + } + + friend bool operator==(int first, const ValueBase &second) { return second == first; } + + friend bool operator==(const ValueBase &first, uint second) + { + return first == static_cast(second); + } + + friend bool operator==(uint first, const ValueBase &second) { return second == first; } + + friend bool operator==(double first, const ValueBase &second) { return second == first; } + + friend bool operator==(const ValueBase &first, Utils::SmallStringView second) + { + auto maybeInteger = Utils::get_if(&first.value); + + return maybeInteger && *maybeInteger == second; + } + + friend bool operator==(Utils::SmallStringView first, const ValueBase &second) + { + return second == first; + } + + friend bool operator==(const ValueBase &first, const QString &second) + { + auto maybeInteger = Utils::get_if(&first.value); + + return maybeInteger + && second == QLatin1String{maybeInteger->data(), int(maybeInteger->size())}; + } + + friend bool operator==(const QString &first, const ValueBase &second) + { + return second == first; + } + + friend bool operator==(const ValueBase &first, const char *second) + { + return first == Utils::SmallStringView{second}; + } + + friend bool operator==(const char *first, const ValueBase &second) { return second == first; } + + friend bool operator==(const ValueBase &first, const ValueBase &second) + { + return first.value == second.value; + } + + friend bool operator!=(const ValueBase &first, const ValueBase &second) + { + return !(first.value == second.value); + } + + ValueType type() const + { + switch (value.index()) { + case 0: + return ValueType::Integer; + case 1: + return ValueType::Float; + case 2: + return ValueType::String; + } + + return {}; + } + +public: + VariantType value; +}; + +class ValueView : public ValueBase +{ +public: + explicit ValueView(ValueBase &&base) + : ValueBase(std::move(base)) + {} + + template + static ValueView create(Type &&value) + { + return ValueView{ValueBase{value}}; + } +}; + +class Value : public ValueBase +{ + using Base = ValueBase; + +public: + using Base::Base; + + explicit Value(ValueView view) + : ValueBase(convert(view)) + {} + + explicit Value(const QVariant &value) + : ValueBase(convert(value)) + {} + + explicit Value(Utils::SmallString &&value) + : ValueBase(VariantType{std::move(value)}) + {} + + explicit Value(const Utils::SmallString &value) + : ValueBase(Utils::SmallStringView(value)) + {} + + explicit Value(const QString &value) + : ValueBase(VariantType{Utils::SmallString(value)}) + {} + + friend bool operator!=(const Value &first, const Value &second) + { + return !(first.value == second.value); + } + + template + friend bool operator!=(const Value &first, const Type &second) + { + return !(first == second); + } + + template + friend bool operator!=(const Type &first, const Value &second) + { + return !(first == second); + } + + friend bool operator==(const Value &first, const ValueView &second) + { + if (first.type() != second.type()) + return false; + + switch (first.type()) { + case ValueType::Integer: + return first.toInteger() == second.toInteger(); + case ValueType::Float: + return first.toFloat() == second.toFloat(); + case ValueType::String: + return first.toStringView() == second.toStringView(); + } + + return false; + } + + friend bool operator==(const ValueView &first, const Value &second) { return second == first; } + +private: + static Base::VariantType convert(const QVariant &value) + { + switch (value.type()) { + case QVariant::Int: + return VariantType{static_cast(value.toInt())}; + case QVariant::LongLong: + return VariantType{value.toLongLong()}; + case QVariant::UInt: + return VariantType{static_cast(value.toUInt())}; + case QVariant::Double: + return VariantType{value.toFloat()}; + case QVariant::String: + return VariantType{value.toString()}; + default: + throw CannotConvert("Cannot convert this QVariant to a ValueBase"); + } + } + + static Base::VariantType convert(ValueView view) + { + switch (view.type()) { + case ValueType::Integer: + return VariantType{view.toInteger()}; + case ValueType::Float: + return VariantType{view.toFloat()}; + case ValueType::String: + return VariantType{view.toStringView()}; + default: + throw CannotConvert("Cannot convert this QVariant to a ValueBase"); + } + } +}; + +using Values = std::vector; +} // namespace Sqlite diff --git a/tests/unit/unittest/CMakeLists.txt b/tests/unit/unittest/CMakeLists.txt index 4e7b97d53b7..904af9b6d16 100644 --- a/tests/unit/unittest/CMakeLists.txt +++ b/tests/unit/unittest/CMakeLists.txt @@ -164,6 +164,14 @@ add_qtc_test(unittest GTEST unittest-utility-functions.h usedmacrofilter-test.cpp utf8-test.cpp + sqlitecolumn-test.cpp + sqlitedatabasebackend-test.cpp + sqlitedatabase-test.cpp + sqlitestatement-test.cpp + sqlitetable-test.cpp + sqlstatementbuilder-test.cpp + createtablesqlstatementbuilder-test.cpp + sqlitevalue-test.cpp ) # Do not work on the source directory data @@ -219,7 +227,6 @@ if (TARGET libclang) codecompleter-test.cpp codecompletionsextractor-test.cpp completionchunkstotextconverter-test.cpp - createtablesqlstatementbuilder-test.cpp cursor-test.cpp diagnosticset-test.cpp diagnostic-test.cpp @@ -228,12 +235,6 @@ if (TARGET libclang) skippedsourceranges-test.cpp sourcelocation-test.cpp sourcerange-test.cpp - sqlitecolumn-test.cpp - sqlitedatabasebackend-test.cpp - sqlitedatabase-test.cpp - sqlitestatement-test.cpp - sqlitetable-test.cpp - sqlstatementbuilder-test.cpp token-test.cpp translationunitupdater-test.cpp unsavedfiles-test.cpp diff --git a/tests/unit/unittest/creator_dependency.pri b/tests/unit/unittest/creator_dependency.pri index 2e84e1cdcab..e5b10f65ae8 100644 --- a/tests/unit/unittest/creator_dependency.pri +++ b/tests/unit/unittest/creator_dependency.pri @@ -14,11 +14,11 @@ include($$PWD/../../../src/tools/clangpchmanagerbackend/source/clangpchmanagerba include($$PWD/../../../src/plugins/clangrefactoring/clangrefactoring-source.pri) include($$PWD/../../../src/plugins/clangpchmanager/clangpchmanager-source.pri) include($$PWD/../../../src/plugins/cpptools/cpptoolsunittestfiles.pri) -include($$PWD/../../../src/plugins/clangtools/clangtoolsunittestfiles.pri) include($$PWD/../../../src/plugins/debugger/debuggerunittestfiles.pri) include($$PWD/../../../src/plugins/compilationdatabaseprojectmanager/compilationdatabaseunittestfiles.pri) include(cplusplus.pri) !isEmpty(LLVM_VERSION) { +include($$PWD/../../../src/plugins/clangtools/clangtoolsunittestfiles.pri) include($$PWD/../../../src/shared/clang/clang_defines.pri) include($$PWD/../../../src/tools/clangbackend/source/clangbackendclangipc-source.pri) include($$PWD/../../../src/plugins/clangcodemodel/clangcodemodelunittestfiles.pri) diff --git a/tests/unit/unittest/gtest-creator-printing.cpp b/tests/unit/unittest/gtest-creator-printing.cpp index 2bbcdbaa45e..6d5f7a2cf34 100644 --- a/tests/unit/unittest/gtest-creator-printing.cpp +++ b/tests/unit/unittest/gtest-creator-printing.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -57,6 +58,7 @@ #include #include #include +#include #include #include #include @@ -64,12 +66,6 @@ #include #include #include -#include -#include -#include -#include -#include -#include namespace { ClangBackEnd::FilePathCaching *filePathCache = nullptr; @@ -306,6 +302,27 @@ void PrintTo(const Utils::PathString &text, ::std::ostream *os) } // namespace Utils +namespace Sqlite { +std::ostream &operator<<(std::ostream &out, const Value &value) +{ + out << "("; + + switch (value.type()) { + case Sqlite::ValueType::Integer: + out << value.toInteger(); + break; + case Sqlite::ValueType::Float: + out << value.toFloat(); + break; + case Sqlite::ValueType::String: + out << "\"" << value.toStringView() << "\""; + break; + } + + return out << ")"; +} +} // namespace Sqlite + namespace ClangBackEnd { std::ostream &operator<<(std::ostream &out, const FilePathId &id) diff --git a/tests/unit/unittest/gtest-creator-printing.h b/tests/unit/unittest/gtest-creator-printing.h index e26809ca519..b91c8d46beb 100644 --- a/tests/unit/unittest/gtest-creator-printing.h +++ b/tests/unit/unittest/gtest-creator-printing.h @@ -64,6 +64,12 @@ void PrintTo(const TextRange &range, ::std::ostream *os); } // namespace TextPosition } // namespace TextPosition +namespace Sqlite { +class Value; + +std::ostream &operator<<(std::ostream &out, const Value &value); +} // namespace Sqlite + namespace ProjectExplorer { enum class MacroType; diff --git a/tests/unit/unittest/sqlitestatement-test.cpp b/tests/unit/unittest/sqlitestatement-test.cpp index cb8206d8757..c7da3971e4f 100644 --- a/tests/unit/unittest/sqlitestatement-test.cpp +++ b/tests/unit/unittest/sqlitestatement-test.cpp @@ -40,11 +40,12 @@ namespace { -using Sqlite::JournalMode; -using Sqlite::Exception; using Sqlite::Database; +using Sqlite::Exception; +using Sqlite::JournalMode; using Sqlite::ReadStatement; using Sqlite::ReadWriteStatement; +using Sqlite::Value; using Sqlite::WriteStatement; MATCHER_P3(HasValues, value1, value2, rowid, @@ -125,7 +126,7 @@ TEST_F(SqliteStatement, CountRows) TEST_F(SqliteStatement, Value) { - SqliteTestStatement statement("SELECT name, number FROM test ORDER BY name", database); + SqliteTestStatement statement("SELECT name, number, value FROM test ORDER BY name", database); statement.next(); statement.next(); @@ -142,6 +143,9 @@ TEST_F(SqliteStatement, Value) ASSERT_THAT(statement.fetchValue(1), "23.3"); ASSERT_THAT(statement.fetchValue(1), "23.3"); ASSERT_THAT(statement.fetchSmallStringViewValue(1), "23.3"); + ASSERT_THAT(statement.fetchValueView(0), Eq("foo")); + ASSERT_THAT(statement.fetchValueView(1), Eq(23.3)); + ASSERT_THAT(statement.fetchValueView(2), Eq(2)); } TEST_F(SqliteStatement, ThrowNoValuesToFetchForNotSteppedStatement) @@ -175,14 +179,14 @@ TEST_F(SqliteStatement, ThrowInvalidColumnFetchedForNotExistingColumn) ASSERT_THROW(statement.fetchValue(2), Sqlite::InvalidColumnFetched); } -TEST_F(SqliteStatement, ToIntergerValue) +TEST_F(SqliteStatement, ToIntegerValue) { auto value = ReadStatement::toValue("SELECT number FROM test WHERE name='foo'", database); ASSERT_THAT(value, 23); } -TEST_F(SqliteStatement, ToLongIntergerValue) +TEST_F(SqliteStatement, ToLongIntegerValue) { ASSERT_THAT(ReadStatement::toValue("SELECT number FROM test WHERE name='foo'", database), Eq(23)); } @@ -319,6 +323,15 @@ TEST_F(SqliteStatement, WriteValues) ASSERT_THAT(statement, HasValues("see", "7.23", 1)); } +TEST_F(SqliteStatement, WriteSqliteValues) +{ + WriteStatement statement("UPDATE test SET name=?, number=? WHERE rowid=?", database); + + statement.write(Value{"see"}, Value{7.23}, Value{1}); + + ASSERT_THAT(statement, HasValues("see", "7.23", 1)); +} + TEST_F(SqliteStatement, BindNamedValues) { SqliteTestStatement statement("UPDATE test SET name=@name, number=@number WHERE rowid=@id", database); @@ -375,6 +388,31 @@ TEST_F(SqliteStatement, GetSingleValuesWithoutArguments) ASSERT_THAT(values, ElementsAre("bar", "foo", "poo")); } +class FooValue +{ +public: + FooValue(Sqlite::ValueView value) + : value(value) + {} + + Sqlite::Value value; + + template + friend bool operator==(const FooValue &value, const Type &other) + { + return value.value == other; + } +}; + +TEST_F(SqliteStatement, GetSingleSqliteValuesWithoutArguments) +{ + ReadStatement statement("SELECT number FROM test", database); + + std::vector values = statement.values(3); + + ASSERT_THAT(values, ElementsAre(Eq("blah"), Eq(23.3), Eq(40))); +} + TEST_F(SqliteStatement, GetStructValuesWithoutArguments) { ReadStatement statement("SELECT name, number, value FROM test", database); diff --git a/tests/unit/unittest/sqlitevalue-test.cpp b/tests/unit/unittest/sqlitevalue-test.cpp new file mode 100644 index 00000000000..e9cc5c9e408 --- /dev/null +++ b/tests/unit/unittest/sqlitevalue-test.cpp @@ -0,0 +1,348 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "googletest.h" + +#include + +namespace { + +TEST(SqliteValue, ConstructLongLong) +{ + Sqlite::Value value{1LL}; + + ASSERT_THAT(value.toInteger(), Eq(1LL)); +} + +TEST(SqliteValue, Construct) +{ + Sqlite::Value value{1}; + + ASSERT_THAT(value.toInteger(), Eq(1LL)); +} + +TEST(SqliteValue, ConstructFloatingPoint) +{ + Sqlite::Value value{1.1}; + + ASSERT_THAT(value.toFloat(), Eq(1.1)); +} + +TEST(SqliteValue, ConstructStringFromCString) +{ + Sqlite::Value value{"foo"}; + + ASSERT_THAT(value.toStringView(), Eq("foo")); +} + +TEST(SqliteValue, ConstructStringFromUtilsString) +{ + Sqlite::Value value{Utils::SmallString{"foo"}}; + + ASSERT_THAT(value.toStringView(), Eq("foo")); +} + +TEST(SqliteValue, ConstructStringFromQString) +{ + Sqlite::Value value{QString{"foo"}}; + + ASSERT_THAT(value.toStringView(), Eq("foo")); +} + +TEST(SqliteValue, ConstructStringFromIntQVariant) +{ + QVariant variant{1}; + + Sqlite::Value value{variant}; + + ASSERT_THAT(value.toInteger(), Eq(1)); +} + +TEST(SqliteValue, ConstructStringFromLongLongQVariant) +{ + QVariant variant{1LL}; + + Sqlite::Value value{variant}; + + ASSERT_THAT(value.toInteger(), Eq(1)); +} + +TEST(SqliteValue, ConstructStringFromUintQVariant) +{ + QVariant variant{1u}; + + Sqlite::Value value{variant}; + + ASSERT_THAT(value.toInteger(), Eq(1)); +} + +TEST(SqliteValue, ConstructStringFromFloatQVariant) +{ + QVariant variant{1.}; + + Sqlite::Value value{variant}; + + ASSERT_THAT(value.toFloat(), Eq(1)); +} + +TEST(SqliteValue, ConstructStringFromStringQVariant) +{ + QVariant variant{QString{"foo"}}; + + Sqlite::Value value{variant}; + + ASSERT_THAT(value.toStringView(), Eq("foo")); +} + +TEST(SqliteValue, ConvertToStringQVariant) +{ + Sqlite::Value value{"foo"}; + + auto variant = QVariant{value}; + + ASSERT_THAT(variant, Eq("foo")); +} + +TEST(SqliteValue, ConvertToIntegerQVariant) +{ + Sqlite::Value value{1}; + + auto variant = QVariant{value}; + + ASSERT_THAT(variant, Eq(1)); +} + +TEST(SqliteValue, ConvertToFloatQVariant) +{ + Sqlite::Value value{1.1}; + + auto variant = QVariant{value}; + + ASSERT_THAT(variant, Eq(1.1)); +} + +TEST(SqliteValue, IntegerEquals) +{ + bool isEqual = Sqlite::Value{1} == 1LL; + + ASSERT_TRUE(isEqual); +} + +TEST(SqliteValue, IntegerEqualsInverse) +{ + bool isEqual = 1LL == Sqlite::Value{1}; + + ASSERT_TRUE(isEqual); +} + +TEST(SqliteValue, FloatEquals) +{ + bool isEqual = Sqlite::Value{1.0} == 1.; + + ASSERT_TRUE(isEqual); +} + +TEST(SqliteValue, FloatEqualsInverse) +{ + bool isEqual = 1. == Sqlite::Value{1.0}; + + ASSERT_TRUE(isEqual); +} + +TEST(SqliteValue, StringEquals) +{ + bool isEqual = Sqlite::Value{"foo"} == "foo"; + + ASSERT_TRUE(isEqual); +} + +TEST(SqliteValue, StringEqualsInverse) +{ + bool isEqual = "foo" == Sqlite::Value{"foo"}; + + ASSERT_TRUE(isEqual); +} + +TEST(SqliteValue, IntegerAndFloatAreNotEquals) +{ + bool isEqual = Sqlite::Value{1} == 1.; + + ASSERT_FALSE(isEqual); +} + +TEST(SqliteValue, IntegerValuesAreEquals) +{ + bool isEqual = Sqlite::Value{1} == Sqlite::Value{1}; + + ASSERT_TRUE(isEqual); +} + +TEST(SqliteValue, IntegerAndFloatValuesAreNotEquals) +{ + bool isEqual = Sqlite::Value{1} == Sqlite::Value{1.}; + + ASSERT_FALSE(isEqual); +} + +TEST(SqliteValue, StringAndQStringAreEquals) +{ + bool isEqual = Sqlite::Value{"foo"} == QString{"foo"}; + + ASSERT_TRUE(isEqual); +} + +TEST(SqliteValue, IntegerAndFloatValuesAreUnequal) +{ + bool isUnequal = Sqlite::Value{1} != Sqlite::Value{1.0}; + + ASSERT_TRUE(isUnequal); +} + +TEST(SqliteValue, IntegerAndFloatAreUnequal) +{ + bool isUnequal = Sqlite::Value{1} != 1.0; + + ASSERT_TRUE(isUnequal); +} + +TEST(SqliteValue, IntegerAndFloatAreUnequalInverse) +{ + bool isUnequal = 1.0 != Sqlite::Value{1}; + + ASSERT_TRUE(isUnequal); +} + +TEST(SqliteValue, IntegersAreUnequal) +{ + bool isUnequal = Sqlite::Value{1} != 2; + + ASSERT_TRUE(isUnequal); +} + +TEST(SqliteValue, IntegersAreUnequalInverse) +{ + bool isUnequal = 2 != Sqlite::Value{1}; + + ASSERT_TRUE(isUnequal); +} + +TEST(SqliteValue, IntegerType) +{ + auto type = Sqlite::Value{1}.type(); + + ASSERT_THAT(type, Sqlite::ValueType::Integer); +} + +TEST(SqliteValue, FloatType) +{ + auto type = Sqlite::Value{1.}.type(); + + ASSERT_THAT(type, Sqlite::ValueType::Float); +} + +TEST(SqliteValue, StringType) +{ + auto type = Sqlite::Value{"foo"}.type(); + + ASSERT_THAT(type, Sqlite::ValueType::String); +} + +TEST(SqliteValue, StringValueAndValueViewEquals) +{ + bool isEqual = Sqlite::ValueView::create("foo") == Sqlite::Value{"foo"}; + + ASSERT_TRUE(isEqual); +} + +TEST(SqliteValue, StringValueAndValueViewEqualsInverse) +{ + bool isEqual = Sqlite::Value{"foo"} == Sqlite::ValueView::create("foo"); + + ASSERT_TRUE(isEqual); +} + +TEST(SqliteValue, IntegerValueAndValueViewEquals) +{ + bool isEqual = Sqlite::ValueView::create(1) == Sqlite::Value{1}; + + ASSERT_TRUE(isEqual); +} + +TEST(SqliteValue, IntegerValueAndValueViewEqualsInverse) +{ + bool isEqual = Sqlite::Value{2} == Sqlite::ValueView::create(2); + + ASSERT_TRUE(isEqual); +} + +TEST(SqliteValue, FloatValueAndValueViewEquals) +{ + bool isEqual = Sqlite::ValueView::create(1.1) == Sqlite::Value{1.1}; + + ASSERT_TRUE(isEqual); +} + +TEST(SqliteValue, FloatValueAndValueViewEqualsInverse) +{ + bool isEqual = Sqlite::Value{1.1} == Sqlite::ValueView::create(1.1); + + ASSERT_TRUE(isEqual); +} + +TEST(SqliteValue, StringValueAndIntergerValueViewAreNotEqual) +{ + bool isEqual = Sqlite::Value{"foo"} == Sqlite::ValueView::create(1); + + ASSERT_FALSE(isEqual); +} + +TEST(SqliteValue, ConvertStringValueViewIntoValue) +{ + auto view = Sqlite::ValueView::create("foo"); + + Sqlite::Value value{view}; + + ASSERT_THAT(value, Eq("foo")); +} + +TEST(SqliteValue, ConvertIntegerValueViewIntoValue) +{ + auto view = Sqlite::ValueView::create(1); + + Sqlite::Value value{view}; + + ASSERT_THAT(value, Eq(1)); +} + +TEST(SqliteValue, ConvertFloatValueViewIntoValue) +{ + auto view = Sqlite::ValueView::create(1.4); + + Sqlite::Value value{view}; + + ASSERT_THAT(value, Eq(1.4)); +} + +} // namespace diff --git a/tests/unit/unittest/unittest.pro b/tests/unit/unittest/unittest.pro index 1db48813e85..6155cf32128 100644 --- a/tests/unit/unittest/unittest.pro +++ b/tests/unit/unittest/unittest.pro @@ -80,6 +80,7 @@ SOURCES += \ smallstring-test.cpp \ sourcerangefilter-test.cpp \ spydummy.cpp \ + sqlitevalue-test.cpp \ symbolindexer-test.cpp \ symbolsfindfilter-test.cpp \ stringcache-test.cpp \ @@ -122,7 +123,13 @@ SOURCES += \ headerpathfilter-test.cpp \ toolchainargumentscache-test.cpp \ modifiedtimechecker-test.cpp \ - readexporteddiagnostics-test.cpp + sqlitecolumn-test.cpp \ + sqlitedatabasebackend-test.cpp \ + sqlitedatabase-test.cpp \ + sqlitestatement-test.cpp \ + sqlitetable-test.cpp \ + sqlstatementbuilder-test.cpp \ + createtablesqlstatementbuilder-test.cpp !isEmpty(LIBCLANG_LIBS) { SOURCES += \ @@ -158,7 +165,6 @@ SOURCES += \ codecompleter-test.cpp \ codecompletionsextractor-test.cpp \ completionchunkstotextconverter-test.cpp \ - createtablesqlstatementbuilder-test.cpp \ cursor-test.cpp \ diagnosticset-test.cpp \ diagnostic-test.cpp \ @@ -168,17 +174,12 @@ SOURCES += \ skippedsourceranges-test.cpp \ sourcelocation-test.cpp \ sourcerange-test.cpp \ - sqlitecolumn-test.cpp \ - sqlitedatabasebackend-test.cpp \ - sqlitedatabase-test.cpp \ - sqlitestatement-test.cpp \ - sqlitetable-test.cpp \ - sqlstatementbuilder-test.cpp \ token-test.cpp \ translationunitupdater-test.cpp \ unsavedfiles-test.cpp \ unsavedfile-test.cpp \ - utf8positionfromlinecolumn-test.cpp + utf8positionfromlinecolumn-test.cpp \ + readexporteddiagnostics-test.cpp } !isEmpty(LIBTOOLING_LIBS) {