mirror of https://github.com/mosra/magnum.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
322 lines
11 KiB
322 lines
11 KiB
|
14 years ago
|
/*
|
||
|
|
This file is part of Magnum.
|
||
|
|
|
||
|
13 years ago
|
Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz>
|
||
|
|
|
||
|
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||
|
|
copy of this software and associated documentation files (the "Software"),
|
||
|
|
to deal in the Software without restriction, including without limitation
|
||
|
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||
|
|
and/or sell copies of the Software, and to permit persons to whom the
|
||
|
|
Software is furnished to do so, subject to the following conditions:
|
||
|
|
|
||
|
|
The above copyright notice and this permission notice shall be included
|
||
|
|
in all copies or substantial portions of the Software.
|
||
|
|
|
||
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||
|
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||
|
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||
|
|
DEALINGS IN THE SOFTWARE.
|
||
|
14 years ago
|
*/
|
||
|
|
|
||
|
|
#include <sstream>
|
||
|
14 years ago
|
#include <TestSuite/Tester.h>
|
||
|
14 years ago
|
|
||
|
14 years ago
|
#include "AbstractResourceLoader.h"
|
||
|
14 years ago
|
#include "ResourceManager.h"
|
||
|
|
|
||
|
14 years ago
|
#include "corradeCompatibility.h"
|
||
|
|
|
||
|
14 years ago
|
namespace Magnum { namespace Test {
|
||
|
|
|
||
|
13 years ago
|
class ResourceManagerTest: public TestSuite::Tester {
|
||
|
14 years ago
|
public:
|
||
|
|
ResourceManagerTest();
|
||
|
|
|
||
|
|
void state();
|
||
|
|
void stateFallback();
|
||
|
|
void stateDisallowed();
|
||
|
|
void basic();
|
||
|
|
void residentPolicy();
|
||
|
|
void referenceCountedPolicy();
|
||
|
|
void manualPolicy();
|
||
|
13 years ago
|
void clear();
|
||
|
|
void clearWhileReferenced();
|
||
|
14 years ago
|
void loader();
|
||
|
|
};
|
||
|
|
|
||
|
14 years ago
|
class Data {
|
||
|
|
public:
|
||
|
|
static std::size_t count;
|
||
|
|
|
||
|
13 years ago
|
Data() { ++count; }
|
||
|
|
~Data() { --count; }
|
||
|
14 years ago
|
};
|
||
|
|
|
||
|
13 years ago
|
typedef Magnum::ResourceManager<Int, Data> ResourceManager;
|
||
|
14 years ago
|
|
||
|
14 years ago
|
size_t Data::count = 0;
|
||
|
|
|
||
|
|
ResourceManagerTest::ResourceManagerTest() {
|
||
|
13 years ago
|
addTests({&ResourceManagerTest::state,
|
||
|
|
&ResourceManagerTest::stateFallback,
|
||
|
|
&ResourceManagerTest::stateDisallowed,
|
||
|
|
&ResourceManagerTest::basic,
|
||
|
|
&ResourceManagerTest::residentPolicy,
|
||
|
|
&ResourceManagerTest::referenceCountedPolicy,
|
||
|
|
&ResourceManagerTest::manualPolicy,
|
||
|
13 years ago
|
&ResourceManagerTest::clear,
|
||
|
|
&ResourceManagerTest::clearWhileReferenced,
|
||
|
13 years ago
|
&ResourceManagerTest::loader});
|
||
|
14 years ago
|
}
|
||
|
|
|
||
|
|
void ResourceManagerTest::state() {
|
||
|
14 years ago
|
ResourceManager rm;
|
||
|
|
|
||
|
14 years ago
|
Resource<Data> data = rm.get<Data>("data");
|
||
|
|
CORRADE_VERIFY(!data);
|
||
|
|
CORRADE_COMPARE(data.state(), ResourceState::NotLoaded);
|
||
|
|
CORRADE_COMPARE(rm.state<Data>("data"), ResourceState::NotLoaded);
|
||
|
|
|
||
|
|
rm.set<Data>("data", nullptr, ResourceDataState::Loading, ResourcePolicy::Resident);
|
||
|
|
CORRADE_VERIFY(!data);
|
||
|
|
CORRADE_COMPARE(data.state(), ResourceState::Loading);
|
||
|
|
CORRADE_COMPARE(rm.state<Data>("data"), ResourceState::Loading);
|
||
|
|
|
||
|
|
rm.set<Data>("data", nullptr, ResourceDataState::NotFound, ResourcePolicy::Resident);
|
||
|
|
CORRADE_VERIFY(!data);
|
||
|
|
CORRADE_COMPARE(data.state(), ResourceState::NotFound);
|
||
|
|
CORRADE_COMPARE(rm.state<Data>("data"), ResourceState::NotFound);
|
||
|
|
|
||
|
|
/* Nothing happened at all */
|
||
|
|
CORRADE_COMPARE(Data::count, 0);
|
||
|
|
}
|
||
|
14 years ago
|
|
||
|
14 years ago
|
void ResourceManagerTest::stateFallback() {
|
||
|
|
{
|
||
|
|
ResourceManager rm;
|
||
|
13 years ago
|
rm.setFallback(new Data);
|
||
|
14 years ago
|
|
||
|
|
Resource<Data> data = rm.get<Data>("data");
|
||
|
|
CORRADE_VERIFY(data);
|
||
|
|
CORRADE_COMPARE(data.state(), ResourceState::NotLoadedFallback);
|
||
|
|
CORRADE_COMPARE(rm.state<Data>("data"), ResourceState::NotLoadedFallback);
|
||
|
|
|
||
|
|
rm.set<Data>("data", nullptr, ResourceDataState::Loading, ResourcePolicy::Resident);
|
||
|
|
CORRADE_VERIFY(data);
|
||
|
|
CORRADE_COMPARE(data.state(), ResourceState::LoadingFallback);
|
||
|
|
CORRADE_COMPARE(rm.state<Data>("data"), ResourceState::LoadingFallback);
|
||
|
|
|
||
|
|
rm.set<Data>("data", nullptr, ResourceDataState::NotFound, ResourcePolicy::Resident);
|
||
|
|
CORRADE_VERIFY(data);
|
||
|
|
CORRADE_COMPARE(data.state(), ResourceState::NotFoundFallback);
|
||
|
|
CORRADE_COMPARE(rm.state<Data>("data"), ResourceState::NotFoundFallback);
|
||
|
|
|
||
|
|
/* Only fallback is here */
|
||
|
|
CORRADE_COMPARE(Data::count, 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Fallback gets destroyed */
|
||
|
|
CORRADE_COMPARE(Data::count, 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
void ResourceManagerTest::stateDisallowed() {
|
||
|
|
ResourceManager rm;
|
||
|
|
|
||
|
14 years ago
|
std::ostringstream out;
|
||
|
14 years ago
|
Error::setOutput(&out);
|
||
|
|
|
||
|
13 years ago
|
rm.set("data", Data(), ResourceDataState::Loading, ResourcePolicy::Resident);
|
||
|
14 years ago
|
CORRADE_COMPARE(out.str(), "ResourceManager::set(): data should be null if and only if state is NotFound or Loading\n");
|
||
|
|
|
||
|
13 years ago
|
out.str({});
|
||
|
14 years ago
|
rm.set<Data>("data", nullptr, ResourceDataState::Final, ResourcePolicy::Resident);
|
||
|
|
CORRADE_COMPARE(out.str(), "ResourceManager::set(): data should be null if and only if state is NotFound or Loading\n");
|
||
|
|
}
|
||
|
|
|
||
|
|
void ResourceManagerTest::basic() {
|
||
|
|
ResourceManager rm;
|
||
|
|
|
||
|
|
/* One mutable, one final */
|
||
|
|
ResourceKey questionKey("the-question");
|
||
|
14 years ago
|
ResourceKey answerKey("the-answer");
|
||
|
13 years ago
|
rm.set(questionKey, 10, ResourceDataState::Mutable, ResourcePolicy::Resident);
|
||
|
|
rm.set(answerKey, 42, ResourceDataState::Final, ResourcePolicy::Resident);
|
||
|
13 years ago
|
Resource<Int> theQuestion = rm.get<Int>(questionKey);
|
||
|
|
Resource<Int> theAnswer = rm.get<Int>(answerKey);
|
||
|
14 years ago
|
|
||
|
|
/* Check basic functionality */
|
||
|
|
CORRADE_COMPARE(theQuestion.state(), ResourceState::Mutable);
|
||
|
14 years ago
|
CORRADE_COMPARE(theAnswer.state(), ResourceState::Final);
|
||
|
14 years ago
|
CORRADE_COMPARE(*theQuestion, 10);
|
||
|
14 years ago
|
CORRADE_COMPARE(*theAnswer, 42);
|
||
|
13 years ago
|
CORRADE_COMPARE(rm.count<Int>(), 2);
|
||
|
14 years ago
|
|
||
|
|
/* Cannot change already final resource */
|
||
|
14 years ago
|
std::ostringstream out;
|
||
|
14 years ago
|
Error::setOutput(&out);
|
||
|
13 years ago
|
rm.set(answerKey, 43, ResourceDataState::Mutable, ResourcePolicy::Resident);
|
||
|
14 years ago
|
CORRADE_COMPARE(*theAnswer, 42);
|
||
|
13 years ago
|
CORRADE_COMPARE(out.str(), "ResourceManager::set(): cannot change already final resource " + answerKey.hexString() + '\n');
|
||
|
14 years ago
|
|
||
|
14 years ago
|
/* But non-final can be changed */
|
||
|
13 years ago
|
rm.set(questionKey, 20, ResourceDataState::Final, ResourcePolicy::Resident);
|
||
|
14 years ago
|
CORRADE_COMPARE(theQuestion.state(), ResourceState::Final);
|
||
|
14 years ago
|
CORRADE_COMPARE(*theQuestion, 20);
|
||
|
|
}
|
||
|
|
|
||
|
14 years ago
|
void ResourceManagerTest::residentPolicy() {
|
||
|
|
ResourceManager* rm = new ResourceManager;
|
||
|
|
|
||
|
13 years ago
|
rm->set("blah", new Data, ResourceDataState::Mutable, ResourcePolicy::Resident);
|
||
|
14 years ago
|
CORRADE_COMPARE(Data::count, 1);
|
||
|
|
|
||
|
|
rm->free();
|
||
|
|
CORRADE_COMPARE(Data::count, 1);
|
||
|
|
|
||
|
|
delete rm;
|
||
|
|
CORRADE_COMPARE(Data::count, 0);
|
||
|
|
}
|
||
|
|
|
||
|
14 years ago
|
void ResourceManagerTest::referenceCountedPolicy() {
|
||
|
14 years ago
|
ResourceManager rm;
|
||
|
|
|
||
|
14 years ago
|
ResourceKey dataRefCountKey("dataRefCount");
|
||
|
|
|
||
|
|
/* Reference counted resources must be requested first */
|
||
|
|
{
|
||
|
13 years ago
|
rm.set(dataRefCountKey, new Data, ResourceDataState::Final, ResourcePolicy::ReferenceCounted);
|
||
|
14 years ago
|
CORRADE_COMPARE(rm.count<Data>(), 0);
|
||
|
|
Resource<Data> data = rm.get<Data>(dataRefCountKey);
|
||
|
14 years ago
|
CORRADE_COMPARE(data.state(), ResourceState::NotLoaded);
|
||
|
14 years ago
|
CORRADE_COMPARE(Data::count, 0);
|
||
|
|
} {
|
||
|
14 years ago
|
Resource<Data> data = rm.get<Data>(dataRefCountKey);
|
||
|
|
CORRADE_COMPARE(rm.count<Data>(), 1);
|
||
|
14 years ago
|
CORRADE_COMPARE(data.state(), ResourceState::NotLoaded);
|
||
|
13 years ago
|
rm.set(dataRefCountKey, new Data, ResourceDataState::Final, ResourcePolicy::ReferenceCounted);
|
||
|
14 years ago
|
CORRADE_COMPARE(data.state(), ResourceState::Final);
|
||
|
14 years ago
|
CORRADE_COMPARE(Data::count, 1);
|
||
|
|
}
|
||
|
|
|
||
|
14 years ago
|
CORRADE_COMPARE(rm.count<Data>(), 0);
|
||
|
14 years ago
|
CORRADE_COMPARE(Data::count, 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
void ResourceManagerTest::manualPolicy() {
|
||
|
14 years ago
|
ResourceManager rm;
|
||
|
|
|
||
|
14 years ago
|
ResourceKey dataKey("data");
|
||
|
|
|
||
|
|
/* Manual free */
|
||
|
|
{
|
||
|
13 years ago
|
rm.set(dataKey, new Data, ResourceDataState::Mutable, ResourcePolicy::Manual);
|
||
|
14 years ago
|
Resource<Data> data = rm.get<Data>(dataKey);
|
||
|
|
rm.free();
|
||
|
14 years ago
|
}
|
||
|
|
|
||
|
14 years ago
|
CORRADE_COMPARE(rm.count<Data>(), 1);
|
||
|
14 years ago
|
CORRADE_COMPARE(Data::count, 1);
|
||
|
14 years ago
|
rm.free();
|
||
|
|
CORRADE_COMPARE(rm.count<Data>(), 0);
|
||
|
14 years ago
|
CORRADE_COMPARE(Data::count, 0);
|
||
|
|
|
||
|
13 years ago
|
rm.set(dataKey, new Data, ResourceDataState::Mutable, ResourcePolicy::Manual);
|
||
|
14 years ago
|
CORRADE_COMPARE(rm.count<Data>(), 1);
|
||
|
14 years ago
|
CORRADE_COMPARE(Data::count, 1);
|
||
|
|
}
|
||
|
|
|
||
|
13 years ago
|
void ResourceManagerTest::clear() {
|
||
|
|
ResourceManager rm;
|
||
|
|
|
||
|
|
rm.set("blah", new Data);
|
||
|
|
CORRADE_COMPARE(Data::count, 1);
|
||
|
|
|
||
|
|
rm.free();
|
||
|
|
CORRADE_COMPARE(Data::count, 1);
|
||
|
|
|
||
|
|
rm.clear();
|
||
|
|
CORRADE_COMPARE(Data::count, 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
void ResourceManagerTest::clearWhileReferenced() {
|
||
|
|
/* Should cover also the destruction case */
|
||
|
|
|
||
|
|
std::ostringstream out;
|
||
|
|
Error::setOutput(&out);
|
||
|
|
|
||
|
|
ResourceManager rm;
|
||
|
13 years ago
|
rm.set("blah", Int());
|
||
|
13 years ago
|
/** @todo this will leak, is there any better solution without hitting
|
||
|
|
assertion in decrementReferenceCount()? */
|
||
|
|
new Resource<Int>(rm.get<Int>("blah"));
|
||
|
|
|
||
|
|
rm.clear();
|
||
|
|
CORRADE_COMPARE(out.str(), "ResourceManager: cleared/destroyed while data are still referenced\n");
|
||
|
|
}
|
||
|
|
|
||
|
14 years ago
|
void ResourceManagerTest::loader() {
|
||
|
13 years ago
|
class IntResourceLoader: public AbstractResourceLoader<Int> {
|
||
|
|
public:
|
||
|
13 years ago
|
IntResourceLoader(): resource(ResourceManager::instance().get<Data>("data")) {}
|
||
|
14 years ago
|
|
||
|
13 years ago
|
void load() {
|
||
|
13 years ago
|
set("hello", 773, ResourceDataState::Final, ResourcePolicy::Resident);
|
||
|
13 years ago
|
setNotFound("world");
|
||
|
|
}
|
||
|
|
|
||
|
|
private:
|
||
|
|
void doLoad(ResourceKey) override {}
|
||
|
13 years ago
|
|
||
|
|
std::string doName(ResourceKey key) const override {
|
||
|
|
if(key == ResourceKey("hello")) return "hello";
|
||
|
|
return "";
|
||
|
|
}
|
||
|
13 years ago
|
|
||
|
|
/* To verify that the loader is destroyed before unloading
|
||
|
|
_all types of_ resources */
|
||
|
|
Resource<Data> resource;
|
||
|
13 years ago
|
};
|
||
|
|
|
||
|
|
auto rm = new ResourceManager;
|
||
|
|
auto loader = new IntResourceLoader;
|
||
|
|
rm->setLoader(loader);
|
||
|
|
|
||
|
13 years ago
|
{
|
||
|
|
Resource<Data> data = rm->get<Data>("data");
|
||
|
|
Resource<Int> hello = rm->get<Int>("hello");
|
||
|
|
Resource<Int> world = rm->get<Int>("world");
|
||
|
|
CORRADE_COMPARE(data.state(), ResourceState::NotLoaded);
|
||
|
|
CORRADE_COMPARE(hello.state(), ResourceState::Loading);
|
||
|
|
CORRADE_COMPARE(world.state(), ResourceState::Loading);
|
||
|
|
|
||
|
|
CORRADE_COMPARE(loader->requestedCount(), 2);
|
||
|
|
CORRADE_COMPARE(loader->loadedCount(), 0);
|
||
|
|
CORRADE_COMPARE(loader->notFoundCount(), 0);
|
||
|
|
CORRADE_COMPARE(loader->name(ResourceKey("hello")), "hello");
|
||
|
|
|
||
|
|
loader->load();
|
||
|
|
CORRADE_COMPARE(hello.state(), ResourceState::Final);
|
||
|
|
CORRADE_COMPARE(*hello, 773);
|
||
|
|
CORRADE_COMPARE(world.state(), ResourceState::NotFound);
|
||
|
|
|
||
|
|
CORRADE_COMPARE(loader->requestedCount(), 2);
|
||
|
|
CORRADE_COMPARE(loader->loadedCount(), 1);
|
||
|
|
CORRADE_COMPARE(loader->notFoundCount(), 1);
|
||
|
|
|
||
|
|
/* Verify that the loader is deleted at proper time */
|
||
|
|
rm->set("data", new Data);
|
||
|
|
CORRADE_COMPARE(Data::count, 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
delete rm;
|
||
|
|
CORRADE_COMPARE(Data::count, 0);
|
||
|
14 years ago
|
}
|
||
|
|
|
||
|
14 years ago
|
}}
|
||
|
14 years ago
|
|
||
|
|
CORRADE_TEST_MAIN(Magnum::Test::ResourceManagerTest)
|