Mercurial > hg > orthanc
changeset 7120:0a8b8890f26d
unit testing DataSourceReader
| author | Sebastien Jodogne <s.jodogne@gmail.com> |
|---|---|
| date | Fri, 14 Aug 2026 13:28:37 +0200 |
| parents | 9bc237efa31a |
| children | cf1f10a22505 |
| files | OrthancFramework/UnitTestsSources/DataSourceTests.cpp |
| diffstat | 1 files changed, 173 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/OrthancFramework/UnitTestsSources/DataSourceTests.cpp Fri Aug 14 12:53:54 2026 +0200 +++ b/OrthancFramework/UnitTestsSources/DataSourceTests.cpp Fri Aug 14 13:28:37 2026 +0200 @@ -27,16 +27,186 @@ # include <OrthancFramework.h> #endif -#include <gtest/gtest.h> - #include "../Sources/DataSource/DataSourceReader.h" #include "../Sources/MultiThreading/SequentialExecutorService.h" +#include "../Sources/MultiThreading/ThreadPool.h" #include "../Sources/OrthancException.h" +#include "../Sources/SystemToolbox.h" +#include <gtest/gtest.h> +#include <boost/lexical_cast.hpp> using namespace Orthanc; -TEST(DataSource, Basic) +namespace { + class IntegerIdentifier : public IDataIdentifier + { + private: + bool fails_; + int value_; + int sleep_; + + public: + IntegerIdentifier(bool fails, + int value, + int sleep) : + fails_(fails), + value_(value), + sleep_(sleep) + { + } + + bool IsFails() const + { + return fails_; + } + + int GetValue() const + { + return value_; + } + + IDynamicObject* Create() const + { + if (sleep_ > 0) + { + SystemToolbox::USleep(1000 * sleep_); + } + + if (fails_) + { + throw OrthancException(ErrorCode_Database /* some random error code */, + "This was value " + boost::lexical_cast<std::string>(value_)); + } + else + { + return new SingleValueObject<int>(value_); + } + } + + virtual bool GetCacheKey(std::string& key) const ORTHANC_OVERRIDE + { + return false; + } + + virtual bool EstimateValueSize(size_t& target) const ORTHANC_OVERRIDE + { + return false; + } + + virtual bool HasUserData() const ORTHANC_OVERRIDE + { + return false; + } + + virtual const IDynamicObject& GetUserData() const ORTHANC_OVERRIDE + { + throw OrthancException(ErrorCode_InternalError); + } + + virtual IDynamicObject* ReleaseUserData() ORTHANC_OVERRIDE + { + throw OrthancException(ErrorCode_InternalError); + } + }; + + + class IntegerDataSource : public IDataSource + { + public: + virtual IDynamicObject* Load(const IDataIdentifier& identifier, + const boost::shared_ptr<SharedObjectCache>& readerCache /* could be NULL */) ORTHANC_OVERRIDE + { + const IntegerIdentifier& id = dynamic_cast<const IntegerIdentifier&>(identifier); + return id.Create(); + } + + virtual size_t GetValueSize(const IDynamicObject& value) const ORTHANC_OVERRIDE + { + return 10; + } + }; } + + +TEST(DataSource, Test) +{ + boost::shared_ptr<ThreadPool> service(new ThreadPool); + service->SetThreadsCount(4); + service->SetDequeueTimeout(5); // Stop the test fast + service->Start(); + + DataSourceReader reader(service, new IntegerDataSource); + + { + std::unique_ptr<DataSourceAnswer::Item> item(reader.ReadSingle(new IntegerIdentifier(false, 10, 0))); + ASSERT_TRUE(item.get() != NULL); + ASSERT_EQ(10u, dynamic_cast<const IntegerIdentifier&>(item->GetId()).GetValue()); + ASSERT_EQ(10u, dynamic_cast<const SingleValueObject<int>&>(*item->GetValue()).GetValue()); + } + + { + std::unique_ptr<DataSourceAnswer::Item> item(reader.ReadSingle(new IntegerIdentifier(true, 20, 0))); + ASSERT_TRUE(item.get() != NULL); + ASSERT_EQ(20u, dynamic_cast<const IntegerIdentifier&>(item->GetId()).GetValue()); + + bool hasThrown = false; + + try + { + dynamic_cast<const SingleValueObject<int>&>(*item->GetValue()).GetValue(); + } + catch (OrthancException& e) + { + hasThrown = true; + ASSERT_EQ(ErrorCode_Database, e.GetErrorCode()); + ASSERT_TRUE(e.HasDetails()); + ASSERT_EQ("This was value 20", std::string(e.GetDetails())); + } + + ASSERT_TRUE(hasThrown); + } + + { + DataSourceReader reader(service, new IntegerDataSource); + + boost::shared_ptr<DataSourceAnswer> answer; + + { + std::unique_ptr<DataSourceRequest> request(new DataSourceRequest); + for (int i = 0; i < 10; i++) + { + request->Enqueue(new IntegerIdentifier(false, 10 + i, 10 - i)); // Produces out-of-order values + } + + answer = reader.Submit(request.release()); + + std::set<int> values; + + while (true) + { + std::unique_ptr<DataSourceAnswer::Item> item(answer->Dequeue()); + if (item) + { + const IntegerIdentifier& id = dynamic_cast<const IntegerIdentifier&>(item->GetId()); + const SingleValueObject<int>& value = dynamic_cast<const SingleValueObject<int>&>(*item->GetValue()); + ASSERT_EQ(id.GetValue(), value.GetValue()); + values.insert(value.GetValue()); + } + else + { + break; + } + } + + ASSERT_EQ(10u, values.size()); + + for (int i = 0; i < 10; i++) + { + ASSERT_TRUE(values.find(10 + i) != values.end()); + } + } + } +}
