472 lines
16 KiB
C++
472 lines
16 KiB
C++
/*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
* UniverseTest.cpp
|
|
* Test fixture for the Universe and UniverseStore classes
|
|
* Copyright (C) 2005-2008 Simon Newton
|
|
*/
|
|
|
|
#include <cppunit/extensions/HelperMacros.h>
|
|
#include <string>
|
|
|
|
#include "ola/DmxBuffer.h"
|
|
#include "olad/Client.h"
|
|
#include "olad/DmxSource.h"
|
|
#include "olad/Port.h"
|
|
#include "olad/PortManager.h"
|
|
#include "olad/Preferences.h"
|
|
#include "olad/TestCommon.h"
|
|
#include "olad/Universe.h"
|
|
#include "olad/UniverseStore.h"
|
|
|
|
using ola::AbstractDevice;
|
|
using ola::DmxBuffer;
|
|
using ola::Clock;
|
|
using ola::TimeStamp;
|
|
using ola::Universe;
|
|
using std::string;
|
|
|
|
static unsigned int TEST_UNIVERSE = 1;
|
|
static const char TEST_DATA[] = "this is some test data";
|
|
|
|
|
|
class UniverseTest: public CppUnit::TestFixture {
|
|
CPPUNIT_TEST_SUITE(UniverseTest);
|
|
CPPUNIT_TEST(testLifecycle);
|
|
CPPUNIT_TEST(testSetGet);
|
|
CPPUNIT_TEST(testSendDmx);
|
|
CPPUNIT_TEST(testReceiveDmx);
|
|
CPPUNIT_TEST(testSourceClients);
|
|
CPPUNIT_TEST(testSinkClients);
|
|
CPPUNIT_TEST(testLtpMerging);
|
|
CPPUNIT_TEST(testHtpMerging);
|
|
CPPUNIT_TEST_SUITE_END();
|
|
|
|
public:
|
|
void setUp();
|
|
void tearDown();
|
|
void testLifecycle();
|
|
void testSetGet();
|
|
void testSendDmx();
|
|
void testReceiveDmx();
|
|
void testSourceClients();
|
|
void testSinkClients();
|
|
void testLtpMerging();
|
|
void testHtpMerging();
|
|
|
|
private:
|
|
ola::MemoryPreferences *m_preferences;
|
|
ola::UniverseStore *m_store;
|
|
DmxBuffer m_buffer;
|
|
};
|
|
|
|
|
|
class MockClient: public ola::Client {
|
|
public:
|
|
MockClient(): ola::Client(NULL), m_dmx_set(false) {}
|
|
bool SendDMX(unsigned int universe_id, const DmxBuffer &buffer) {
|
|
CPPUNIT_ASSERT_EQUAL(TEST_UNIVERSE, universe_id);
|
|
CPPUNIT_ASSERT_EQUAL(string(TEST_DATA), buffer.Get());
|
|
m_dmx_set = true;
|
|
return true;
|
|
}
|
|
bool m_dmx_set;
|
|
};
|
|
|
|
|
|
CPPUNIT_TEST_SUITE_REGISTRATION(UniverseTest);
|
|
|
|
|
|
void UniverseTest::setUp() {
|
|
m_preferences = new ola::MemoryPreferences("foo");
|
|
m_store = new ola::UniverseStore(m_preferences, NULL);
|
|
m_buffer.Set(TEST_DATA);
|
|
}
|
|
|
|
|
|
void UniverseTest::tearDown() {
|
|
delete m_store;
|
|
delete m_preferences;
|
|
}
|
|
|
|
|
|
/*
|
|
* Test that we can create universes and save their settings
|
|
*/
|
|
void UniverseTest::testLifecycle() {
|
|
Universe *universe = m_store->GetUniverse(TEST_UNIVERSE);
|
|
CPPUNIT_ASSERT(!universe);
|
|
|
|
universe = m_store->GetUniverseOrCreate(TEST_UNIVERSE);
|
|
CPPUNIT_ASSERT(universe);
|
|
CPPUNIT_ASSERT_EQUAL(universe->UniverseId(), TEST_UNIVERSE);
|
|
CPPUNIT_ASSERT_EQUAL(m_store->UniverseCount(), (unsigned int) 1);
|
|
CPPUNIT_ASSERT_EQUAL(universe->MergeMode(), Universe::MERGE_LTP);
|
|
CPPUNIT_ASSERT(!universe->IsActive());
|
|
|
|
string universe_name = "New Name";
|
|
universe->SetName(universe_name);
|
|
universe->SetMergeMode(Universe::MERGE_HTP);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(universe->Name(), universe_name);
|
|
CPPUNIT_ASSERT_EQUAL(universe->MergeMode(), Universe::MERGE_HTP);
|
|
|
|
// delete it
|
|
m_store->AddUniverseGarbageCollection(universe);
|
|
m_store->GarbageCollectUniverses();
|
|
CPPUNIT_ASSERT_EQUAL(m_store->UniverseCount(), (unsigned int) 0);
|
|
universe = m_store->GetUniverse(TEST_UNIVERSE);
|
|
CPPUNIT_ASSERT(!universe);
|
|
|
|
// now re-create it
|
|
universe = m_store->GetUniverseOrCreate(TEST_UNIVERSE);
|
|
CPPUNIT_ASSERT(universe);
|
|
CPPUNIT_ASSERT_EQUAL(m_store->UniverseCount(), (unsigned int) 1);
|
|
CPPUNIT_ASSERT_EQUAL(universe->UniverseId(), TEST_UNIVERSE);
|
|
CPPUNIT_ASSERT_EQUAL(universe->Name(), universe_name);
|
|
CPPUNIT_ASSERT_EQUAL(universe->MergeMode(), Universe::MERGE_HTP);
|
|
|
|
m_store->DeleteAll();
|
|
CPPUNIT_ASSERT_EQUAL(m_store->UniverseCount(), (unsigned int) 0);
|
|
}
|
|
|
|
|
|
/*
|
|
* Check that SetDMX/GetDMX works
|
|
*/
|
|
void UniverseTest::testSetGet() {
|
|
Universe *universe = m_store->GetUniverseOrCreate(TEST_UNIVERSE);
|
|
CPPUNIT_ASSERT(universe);
|
|
|
|
// a new universe should be all 0s
|
|
DmxBuffer empty_buffer;
|
|
CPPUNIT_ASSERT(empty_buffer == universe->GetDMX());
|
|
|
|
// check that SetDMX works
|
|
CPPUNIT_ASSERT(universe->SetDMX(m_buffer));
|
|
CPPUNIT_ASSERT(m_buffer == universe->GetDMX());
|
|
}
|
|
|
|
|
|
/*
|
|
* Check that SendDmx updates all ports
|
|
*/
|
|
void UniverseTest::testSendDmx() {
|
|
Universe *universe = m_store->GetUniverseOrCreate(TEST_UNIVERSE);
|
|
CPPUNIT_ASSERT(universe);
|
|
|
|
TestMockOutputPort port(NULL, 1); // output port
|
|
universe->AddPort(&port);
|
|
CPPUNIT_ASSERT_EQUAL(universe->InputPortCount(), (unsigned int) 0);
|
|
CPPUNIT_ASSERT_EQUAL(universe->OutputPortCount(), (unsigned int) 1);
|
|
CPPUNIT_ASSERT(universe->IsActive());
|
|
|
|
// send some data to the universe and check the port gets it
|
|
CPPUNIT_ASSERT(universe->SetDMX(m_buffer));
|
|
CPPUNIT_ASSERT(m_buffer == port.ReadDMX());
|
|
|
|
// remove the port from the universe
|
|
universe->RemovePort(&port);
|
|
CPPUNIT_ASSERT_EQUAL(universe->InputPortCount(), (unsigned int) 0);
|
|
CPPUNIT_ASSERT_EQUAL(universe->OutputPortCount(), (unsigned int) 0);
|
|
CPPUNIT_ASSERT(!universe->IsActive());
|
|
}
|
|
|
|
|
|
/*
|
|
* Check that we update when ports have new data
|
|
*/
|
|
void UniverseTest::testReceiveDmx() {
|
|
ola::PortManager port_manager(m_store);
|
|
|
|
MockDevice device(NULL, "foo");
|
|
TimeStamp time_stamp;
|
|
TestMockInputPort port(&device, 1, &time_stamp); // input port
|
|
port_manager.PatchPort(&port, TEST_UNIVERSE);
|
|
|
|
Universe *universe = m_store->GetUniverseOrCreate(TEST_UNIVERSE);
|
|
CPPUNIT_ASSERT(universe);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(universe->InputPortCount(), (unsigned int) 1);
|
|
CPPUNIT_ASSERT_EQUAL(universe->OutputPortCount(), (unsigned int) 0);
|
|
CPPUNIT_ASSERT(universe->IsActive());
|
|
|
|
// Setup the port with some data, and check that signalling the universe
|
|
// works.
|
|
Clock::CurrentTime(&time_stamp);
|
|
port.WriteDMX(m_buffer);
|
|
port.DmxChanged();
|
|
CPPUNIT_ASSERT_EQUAL(ola::DmxSource::PRIORITY_DEFAULT,
|
|
universe->ActivePriority());
|
|
CPPUNIT_ASSERT_EQUAL(m_buffer.Size(), universe->GetDMX().Size());
|
|
CPPUNIT_ASSERT(m_buffer == universe->GetDMX());
|
|
|
|
// Remove the port from the universe
|
|
universe->RemovePort(&port);
|
|
CPPUNIT_ASSERT(!universe->IsActive());
|
|
CPPUNIT_ASSERT_EQUAL(universe->InputPortCount(), (unsigned int) 0);
|
|
CPPUNIT_ASSERT_EQUAL(universe->OutputPortCount(), (unsigned int) 0);
|
|
}
|
|
|
|
|
|
/*
|
|
* Check that we can add/remove source clients from this universes
|
|
*/
|
|
void UniverseTest::testSourceClients() {
|
|
Universe *universe = m_store->GetUniverseOrCreate(TEST_UNIVERSE);
|
|
CPPUNIT_ASSERT(universe);
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int) 0, universe->SourceClientCount());
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int) 0, universe->SinkClientCount());
|
|
|
|
// test that we can add a source client
|
|
MockClient client;
|
|
universe->AddSourceClient(&client);
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int) 1, universe->SourceClientCount());
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int) 0, universe->SinkClientCount());
|
|
CPPUNIT_ASSERT(universe->ContainsSourceClient(&client));
|
|
CPPUNIT_ASSERT(!universe->ContainsSinkClient(&client));
|
|
CPPUNIT_ASSERT(universe->IsActive());
|
|
|
|
// Setting DMX now does nothing
|
|
CPPUNIT_ASSERT(!client.m_dmx_set);
|
|
universe->SetDMX(m_buffer);
|
|
CPPUNIT_ASSERT(!client.m_dmx_set);
|
|
|
|
// now remove it
|
|
universe->RemoveSourceClient(&client);
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int) 0, universe->SourceClientCount());
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int) 0, universe->SinkClientCount());
|
|
CPPUNIT_ASSERT(!universe->ContainsSourceClient(&client));
|
|
CPPUNIT_ASSERT(!universe->ContainsSinkClient(&client));
|
|
CPPUNIT_ASSERT(!universe->IsActive());
|
|
|
|
// try to remove it again
|
|
CPPUNIT_ASSERT(!universe->RemoveSourceClient(&client));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int) 0, universe->SourceClientCount());
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int) 0, universe->SinkClientCount());
|
|
CPPUNIT_ASSERT(!universe->ContainsSourceClient(&client));
|
|
CPPUNIT_ASSERT(!universe->ContainsSinkClient(&client));
|
|
CPPUNIT_ASSERT(!universe->IsActive());
|
|
}
|
|
|
|
|
|
/*
|
|
* Check that we can add/remove sink clients from this universes
|
|
*/
|
|
void UniverseTest::testSinkClients() {
|
|
Universe *universe = m_store->GetUniverseOrCreate(TEST_UNIVERSE);
|
|
CPPUNIT_ASSERT(universe);
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int) 0, universe->SourceClientCount());
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int) 0, universe->SinkClientCount());
|
|
|
|
// test that we can add a source client
|
|
MockClient client;
|
|
universe->AddSinkClient(&client);
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int) 1, universe->SinkClientCount());
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int) 0, universe->SourceClientCount());
|
|
CPPUNIT_ASSERT(universe->ContainsSinkClient(&client));
|
|
CPPUNIT_ASSERT(!universe->ContainsSourceClient(&client));
|
|
CPPUNIT_ASSERT(universe->IsActive());
|
|
|
|
// Setting DMX now should update the client
|
|
CPPUNIT_ASSERT(!client.m_dmx_set);
|
|
universe->SetDMX(m_buffer);
|
|
CPPUNIT_ASSERT(client.m_dmx_set);
|
|
|
|
// now remove it
|
|
universe->RemoveSinkClient(&client);
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int) 0, universe->SinkClientCount());
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int) 0, universe->SourceClientCount());
|
|
CPPUNIT_ASSERT(!universe->ContainsSinkClient(&client));
|
|
CPPUNIT_ASSERT(!universe->ContainsSourceClient(&client));
|
|
CPPUNIT_ASSERT(!universe->IsActive());
|
|
|
|
// try to remove it again
|
|
CPPUNIT_ASSERT(!universe->RemoveSinkClient(&client));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int) 0, universe->SinkClientCount());
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int) 0, universe->SourceClientCount());
|
|
CPPUNIT_ASSERT(!universe->ContainsSinkClient(&client));
|
|
CPPUNIT_ASSERT(!universe->ContainsSourceClient(&client));
|
|
CPPUNIT_ASSERT(!universe->IsActive());
|
|
}
|
|
|
|
|
|
/*
|
|
* Check that LTP merging works correctly
|
|
*/
|
|
void UniverseTest::testLtpMerging() {
|
|
DmxBuffer buffer1, buffer2, htp_buffer;
|
|
buffer1.SetFromString("1,0,0,10");
|
|
buffer2.SetFromString("0,255,0,5,6,7");
|
|
|
|
ola::PortManager port_manager(m_store);
|
|
|
|
TimeStamp time_stamp;
|
|
MockDevice device(NULL, "foo");
|
|
MockDevice device2(NULL, "bar");
|
|
TestMockInputPort port(&device, 1, &time_stamp); // input port
|
|
TestMockInputPort port2(&device2, 1, &time_stamp); // input port
|
|
port_manager.PatchPort(&port, TEST_UNIVERSE);
|
|
port_manager.PatchPort(&port2, TEST_UNIVERSE);
|
|
|
|
Universe *universe = m_store->GetUniverseOrCreate(TEST_UNIVERSE);
|
|
CPPUNIT_ASSERT(universe);
|
|
universe->SetMergeMode(Universe::MERGE_LTP);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(universe->InputPortCount(), (unsigned int) 2);
|
|
CPPUNIT_ASSERT_EQUAL(universe->OutputPortCount(), (unsigned int) 0);
|
|
CPPUNIT_ASSERT(universe->IsActive());
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int) 0, universe->GetDMX().Size());
|
|
|
|
// Setup the ports with some data, and check that signalling the universe
|
|
// works.
|
|
Clock::CurrentTime(&time_stamp);
|
|
port.WriteDMX(buffer1);
|
|
port.DmxChanged();
|
|
CPPUNIT_ASSERT_EQUAL(ola::DmxSource::PRIORITY_DEFAULT,
|
|
universe->ActivePriority());
|
|
CPPUNIT_ASSERT_EQUAL(buffer1.Size(), universe->GetDMX().Size());
|
|
CPPUNIT_ASSERT(buffer1 == universe->GetDMX());
|
|
|
|
// Now the second port gets data
|
|
Clock::CurrentTime(&time_stamp);
|
|
port2.WriteDMX(buffer2);
|
|
port2.DmxChanged();
|
|
CPPUNIT_ASSERT_EQUAL(ola::DmxSource::PRIORITY_DEFAULT,
|
|
universe->ActivePriority());
|
|
CPPUNIT_ASSERT_EQUAL(buffer2.Size(), universe->GetDMX().Size());
|
|
CPPUNIT_ASSERT(buffer2 == universe->GetDMX());
|
|
|
|
// now resend the first port
|
|
Clock::CurrentTime(&time_stamp);
|
|
port.WriteDMX(buffer1);
|
|
port.DmxChanged();
|
|
CPPUNIT_ASSERT_EQUAL(ola::DmxSource::PRIORITY_DEFAULT,
|
|
universe->ActivePriority());
|
|
CPPUNIT_ASSERT_EQUAL(buffer1.Size(), universe->GetDMX().Size());
|
|
CPPUNIT_ASSERT(buffer1 == universe->GetDMX());
|
|
|
|
// now check a client
|
|
DmxBuffer client_buffer;
|
|
client_buffer.SetFromString("255,0,0,255,10");
|
|
Clock::CurrentTime(&time_stamp);
|
|
ola::DmxSource source(client_buffer, time_stamp,
|
|
ola::DmxSource::PRIORITY_DEFAULT);
|
|
MockClient input_client;
|
|
input_client.DMXRecieved(TEST_UNIVERSE, source);
|
|
universe->SourceClientDataChanged(&input_client);
|
|
|
|
DmxBuffer client_htp_merge_result;
|
|
client_htp_merge_result.SetFromString("255,255,0,255,10,7");
|
|
CPPUNIT_ASSERT_EQUAL(ola::DmxSource::PRIORITY_DEFAULT,
|
|
universe->ActivePriority());
|
|
CPPUNIT_ASSERT_EQUAL(client_buffer.Size(), universe->GetDMX().Size());
|
|
CPPUNIT_ASSERT(client_buffer == universe->GetDMX());
|
|
|
|
// clean up
|
|
universe->RemoveSourceClient(&input_client);
|
|
universe->RemovePort(&port);
|
|
universe->RemovePort(&port2);
|
|
CPPUNIT_ASSERT(!universe->IsActive());
|
|
}
|
|
|
|
|
|
/*
|
|
* Check that HTP merging works correctly
|
|
*/
|
|
void UniverseTest::testHtpMerging() {
|
|
DmxBuffer buffer1, buffer2, htp_buffer;
|
|
buffer1.SetFromString("1,0,0,10");
|
|
buffer2.SetFromString("0,255,0,5,6,7");
|
|
htp_buffer.SetFromString("1,255,0,10,6,7");
|
|
|
|
ola::PortManager port_manager(m_store);
|
|
|
|
TimeStamp time_stamp;
|
|
MockDevice device(NULL, "foo");
|
|
MockDevice device2(NULL, "bar");
|
|
TestMockInputPort port(&device, 1, &time_stamp); // input port
|
|
TestMockInputPort port2(&device2, 1, &time_stamp); // input port
|
|
port_manager.PatchPort(&port, TEST_UNIVERSE);
|
|
port_manager.PatchPort(&port2, TEST_UNIVERSE);
|
|
|
|
Universe *universe = m_store->GetUniverseOrCreate(TEST_UNIVERSE);
|
|
CPPUNIT_ASSERT(universe);
|
|
universe->SetMergeMode(Universe::MERGE_HTP);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(universe->InputPortCount(), (unsigned int) 2);
|
|
CPPUNIT_ASSERT_EQUAL(universe->OutputPortCount(), (unsigned int) 0);
|
|
CPPUNIT_ASSERT(universe->IsActive());
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int) 0, universe->GetDMX().Size());
|
|
|
|
// Setup the ports with some data, and check that signalling the universe
|
|
// works.
|
|
Clock::CurrentTime(&time_stamp);
|
|
port.WriteDMX(buffer1);
|
|
port.DmxChanged();
|
|
CPPUNIT_ASSERT_EQUAL(ola::DmxSource::PRIORITY_DEFAULT,
|
|
universe->ActivePriority());
|
|
CPPUNIT_ASSERT_EQUAL(buffer1.Size(), universe->GetDMX().Size());
|
|
CPPUNIT_ASSERT(buffer1 == universe->GetDMX());
|
|
|
|
// Now the second port gets data
|
|
Clock::CurrentTime(&time_stamp);
|
|
port2.WriteDMX(buffer2);
|
|
port2.DmxChanged();
|
|
CPPUNIT_ASSERT_EQUAL(ola::DmxSource::PRIORITY_DEFAULT,
|
|
universe->ActivePriority());
|
|
CPPUNIT_ASSERT_EQUAL(htp_buffer.Size(), universe->GetDMX().Size());
|
|
CPPUNIT_ASSERT(htp_buffer == universe->GetDMX());
|
|
|
|
// now raise the priority of the second port
|
|
uint8_t new_priority = 120;
|
|
port2.SetPriority(new_priority);
|
|
Clock::CurrentTime(&time_stamp);
|
|
port2.DmxChanged();
|
|
CPPUNIT_ASSERT_EQUAL(new_priority, universe->ActivePriority());
|
|
CPPUNIT_ASSERT_EQUAL(buffer2.Size(), universe->GetDMX().Size());
|
|
CPPUNIT_ASSERT(buffer2 == universe->GetDMX());
|
|
|
|
// raise the priority of the first port
|
|
port.SetPriority(new_priority);
|
|
Clock::CurrentTime(&time_stamp);
|
|
port.DmxChanged();
|
|
CPPUNIT_ASSERT_EQUAL(new_priority, universe->ActivePriority());
|
|
CPPUNIT_ASSERT_EQUAL(htp_buffer.Size(), universe->GetDMX().Size());
|
|
CPPUNIT_ASSERT(htp_buffer == universe->GetDMX());
|
|
|
|
// now check a client
|
|
DmxBuffer client_buffer;
|
|
client_buffer.SetFromString("255,0,0,255,10");
|
|
Clock::CurrentTime(&time_stamp);
|
|
ola::DmxSource source(client_buffer, time_stamp, new_priority);
|
|
MockClient input_client;
|
|
input_client.DMXRecieved(TEST_UNIVERSE, source);
|
|
universe->SourceClientDataChanged(&input_client);
|
|
|
|
DmxBuffer client_htp_merge_result;
|
|
client_htp_merge_result.SetFromString("255,255,0,255,10,7");
|
|
CPPUNIT_ASSERT_EQUAL(new_priority, universe->ActivePriority());
|
|
CPPUNIT_ASSERT_EQUAL(client_htp_merge_result.Size(),
|
|
universe->GetDMX().Size());
|
|
CPPUNIT_ASSERT(client_htp_merge_result == universe->GetDMX());
|
|
|
|
// clean up
|
|
universe->RemoveSourceClient(&input_client);
|
|
universe->RemovePort(&port);
|
|
universe->RemovePort(&port2);
|
|
CPPUNIT_ASSERT(!universe->IsActive());
|
|
}
|