diff options
Diffstat (limited to 'libs/ardour/test')
-rw-r--r-- | libs/ardour/test/playlist_layering_test.cc | 384 | ||||
-rw-r--r-- | libs/ardour/test/playlist_layering_test.h | 34 | ||||
-rw-r--r-- | libs/ardour/test/playlist_overlap_cache_test.cc | 119 | ||||
-rw-r--r-- | libs/ardour/test/playlist_overlap_cache_test.h | 20 | ||||
-rw-r--r-- | libs/ardour/test/test_needing_session.cc | 48 | ||||
-rw-r--r-- | libs/ardour/test/test_needing_session.h | 16 | ||||
-rw-r--r-- | libs/ardour/test/test_receiver.h | 37 |
7 files changed, 556 insertions, 102 deletions
diff --git a/libs/ardour/test/playlist_layering_test.cc b/libs/ardour/test/playlist_layering_test.cc index 1371b0cfae..23b22f9d90 100644 --- a/libs/ardour/test/playlist_layering_test.cc +++ b/libs/ardour/test/playlist_layering_test.cc @@ -1,13 +1,14 @@ -#include "midi++/manager.h" -#include "pbd/textreceiver.h" #include "pbd/compose.h" -#include "ardour/session.h" -#include "ardour/audioengine.h" +#include "midi++/manager.h" #include "ardour/playlist_factory.h" #include "ardour/source_factory.h" #include "ardour/region.h" #include "ardour/region_factory.h" +#include "ardour/session.h" +#include "ardour/audiosource.h" +#include "ardour/audioengine.h" #include "playlist_layering_test.h" +#include "test_receiver.h" CPPUNIT_TEST_SUITE_REGISTRATION (PlaylistLayeringTest); @@ -15,68 +16,28 @@ using namespace std; using namespace ARDOUR; using namespace PBD; -class TestReceiver : public Receiver -{ -protected: - void receive (Transmitter::Channel chn, const char * str) { - const char *prefix = ""; - - switch (chn) { - case Transmitter::Error: - prefix = ": [ERROR]: "; - break; - case Transmitter::Info: - /* ignore */ - return; - case Transmitter::Warning: - prefix = ": [WARNING]: "; - break; - case Transmitter::Fatal: - prefix = ": [FATAL]: "; - break; - case Transmitter::Throw: - /* this isn't supposed to happen */ - abort (); - } - - /* note: iostreams are already thread-safe: no external - lock required. - */ - - cout << prefix << str << endl; - - if (chn == Transmitter::Fatal) { - exit (9); - } - } -}; - -TestReceiver test_receiver; +int const PlaylistLayeringTest::num_regions = 6; void PlaylistLayeringTest::setUp () { - string const test_session_path = "libs/ardour/test/playlist_layering_test"; - string const test_wav_path = "libs/ardour/test/playlist_layering_test/playlist_layering_test.wav"; - system (string_compose ("rm -rf %1", test_session_path).c_str()); + TestNeedingSession::setUp (); + string const test_wav_path = "libs/ardour/test/test.wav"; - init (false, true); - SessionEvent::create_per_thread_pool ("test", 512); - - test_receiver.listen_to (error); - test_receiver.listen_to (info); - test_receiver.listen_to (fatal); - test_receiver.listen_to (warning); - - AudioEngine* engine = new AudioEngine ("test", ""); - MIDI::Manager::create (engine->jack ()); - CPPUNIT_ASSERT (engine->start () == 0); - - _session = new Session (*engine, test_session_path, "playlist_layering_test"); - engine->set_session (_session); - _playlist = PlaylistFactory::create (DataType::AUDIO, *_session, "test"); _source = SourceFactory::createWritable (DataType::AUDIO, *_session, test_wav_path, "", false, 44100); + + system ("pwd"); + + /* Must write some data to our source, otherwise regions which use it will + be limited in whether they can be trimmed or not. + */ + boost::shared_ptr<AudioSource> a = boost::dynamic_pointer_cast<AudioSource> (_source); + Sample silence[512]; + memset (silence, 0, 512 * sizeof (Sample)); + a->write (silence, 512); + + _region = new boost::shared_ptr<Region>[num_regions]; } void @@ -84,68 +45,303 @@ PlaylistLayeringTest::tearDown () { _playlist.reset (); _source.reset (); - for (int i = 0; i < 16; ++i) { + for (int i = 0; i < num_regions; ++i) { _region[i].reset (); } - AudioEngine::instance()->remove_session (); - delete _session; - EnumWriter::destroy (); - MIDI::Manager::destroy (); - AudioEngine::destroy (); + delete[] _region; + + TestNeedingSession::tearDown (); } void -PlaylistLayeringTest::create_three_short_regions () +PlaylistLayeringTest::create_short_regions () { PropertyList plist; plist.add (Properties::start, 0); plist.add (Properties::length, 100); - for (int i = 0; i < 3; ++i) { + for (int i = 0; i < num_regions; ++i) { _region[i] = RegionFactory::create (_source, plist); + _region[i]->set_name (string_compose ("%1", char (int ('A') + i))); } } void -PlaylistLayeringTest::addHigherTest () +PlaylistLayeringTest::laterHigher_relayerOnAll_Test () +{ + _session->config.set_layer_model (LaterHigher); + _session->config.set_relayer_on_all_edits (true); + + create_short_regions (); + + /* three overlapping regions */ + _playlist->add_region (_region[A], 0); + _playlist->add_region (_region[B], 10); + _playlist->add_region (_region[C], 20); + /* and another non-overlapping one */ + _playlist->add_region (_region[D], 200); + + /* LaterHigher means that they should be arranged thus */ + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[A]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[B]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[C]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ()); + + _region[A]->set_position (5); + + /* Region move should have no effect in LaterHigher mode */ + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[A]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[B]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[C]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ()); + + /* C -> bottom should give C A B, not touching D */ + _region[C]->lower_to_bottom (); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[C]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[A]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[B]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ()); + + /* C -> top should go back to A B C, not touching D */ + _region[C]->raise_to_top (); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[A]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[B]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[C]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ()); +} + +void +PlaylistLayeringTest::addHigher_relayerOnAll_Test () { _session->config.set_layer_model (AddHigher); - create_three_short_regions (); + _session->config.set_relayer_on_all_edits (true); + + create_short_regions (); + + /* three overlapping regions */ + _playlist->add_region (_region[A], 0); + _playlist->add_region (_region[B], 10); + _playlist->add_region (_region[C], 20); + /* and another non-overlapping one */ + _playlist->add_region (_region[D], 200); + + /* AddHigher means that they should be arranged thus */ + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[A]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[B]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[C]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ()); - _playlist->add_region (_region[0], 0); - _playlist->add_region (_region[1], 10); - _playlist->add_region (_region[2], 20); + _region[A]->set_position (5); - CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[0]->layer ()); - CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[1]->layer ()); - CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[2]->layer ()); + /* region move should have no effect in AddHigher mode */ + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[A]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[B]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[C]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ()); - _region[0]->set_position (5); + /* C -> bottom should give C A B, not touching D */ + _region[C]->lower_to_bottom (); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[C]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[A]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[B]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ()); - /* region move should have no effect */ - CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[0]->layer ()); - CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[1]->layer ()); - CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[2]->layer ()); + /* C -> top should go back to A B C, not touching D */ + _region[C]->raise_to_top (); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[A]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[B]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[C]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ()); } void -PlaylistLayeringTest::moveAddHigherTest () +PlaylistLayeringTest::addOrBoundsHigher_relayerOnAll_Test () { - _session->config.set_layer_model (MoveAddHigher); - create_three_short_regions (); + _session->config.set_layer_model (AddOrBoundsChangeHigher); + _session->config.set_relayer_on_all_edits (true); + + create_short_regions (); + + /* three overlapping regions */ + _playlist->add_region (_region[A], 0); + _playlist->add_region (_region[B], 10); + _playlist->add_region (_region[C], 20); + /* and another non-overlapping one */ + _playlist->add_region (_region[D], 200); + + /* AddOrBoundsHigher means that they should be arranged thus */ + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[A]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[B]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[C]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ()); + + /* region move should put A on top for B C A, not touching D */ + _region[A]->set_position (5); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[B]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[C]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[A]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ()); + + /* C -> bottom should give C B A, not touching D */ + _region[C]->lower_to_bottom (); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[C]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[B]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[A]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ()); + + /* C -> top should go back to B A C, not touching D */ + _region[C]->raise_to_top (); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[B]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[A]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[C]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ()); + + /* Put C on the bottom */ + _region[C]->lower_to_bottom (); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[C]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[B]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[A]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ()); + + /* Now move it slightly, and it should go back to the top again */ + _region[C]->set_position (21); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[B]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[A]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[C]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ()); + + /* Put C back on the bottom */ + _region[C]->lower_to_bottom (); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[C]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[B]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[A]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ()); + + /* Trim it slightly, and it should go back to the top again */ + _region[C]->trim_front (23); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[B]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[A]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[C]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ()); + + /* Same with the end */ + _region[C]->lower_to_bottom (); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[C]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[B]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[A]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ()); + + _region[C]->trim_end (118); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[B]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[A]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[C]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ()); +} + +void +PlaylistLayeringTest::addOrBoundsHigher_relayerWhenNecessary_Test () +{ + _session->config.set_layer_model (AddOrBoundsChangeHigher); + _session->config.set_relayer_on_all_edits (false); + + create_short_regions (); + + /* three overlapping regions */ + _playlist->add_region (_region[A], 0); + _playlist->add_region (_region[B], 10); + _playlist->add_region (_region[C], 20); + /* and another non-overlapping one */ + _playlist->add_region (_region[D], 200); + + /* AddOrBoundsHigher means that they should be arranged thus */ + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[A]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[B]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[C]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ()); + + _region[A]->set_position (5); + + /* region move should not have changed anything, since in + this mode we only relayer when there is a new overlap + */ + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[A]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[B]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[C]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ()); + + /* C -> bottom should give C A B, not touching D */ + _region[C]->lower_to_bottom (); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[C]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[A]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[B]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ()); + + /* C -> top should go back to A B C, not touching D */ + _region[C]->raise_to_top (); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[A]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[B]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[C]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ()); + + /* Put C on the bottom */ + _region[C]->lower_to_bottom (); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[C]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[A]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[B]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ()); + + /* Now move it slightly, and it should stay where it is */ + _region[C]->set_position (21); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[C]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[A]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[B]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ()); +} + +void +PlaylistLayeringTest::lastLayerOpTest () +{ + create_short_regions (); + + _playlist->add_region (_region[A], 0); + CPPUNIT_ASSERT_EQUAL (_playlist->layer_op_counter, _region[A]->last_layer_op (LayerOpAdd)); + uint64_t const last_add = _region[A]->last_layer_op (LayerOpAdd); + + _region[A]->set_position (42); + CPPUNIT_ASSERT_EQUAL (_playlist->layer_op_counter, _region[A]->last_layer_op (LayerOpBoundsChange)); + CPPUNIT_ASSERT_EQUAL (last_add, _region[A]->last_layer_op (LayerOpAdd)); + + _region[A]->trim_front (46); + CPPUNIT_ASSERT_EQUAL (_playlist->layer_op_counter, _region[A]->last_layer_op (LayerOpBoundsChange)); + CPPUNIT_ASSERT_EQUAL (last_add, _region[A]->last_layer_op (LayerOpAdd)); + + _region[A]->trim_end (102); + CPPUNIT_ASSERT_EQUAL (_playlist->layer_op_counter, _region[A]->last_layer_op (LayerOpBoundsChange)); + CPPUNIT_ASSERT_EQUAL (last_add, _region[A]->last_layer_op (LayerOpAdd)); +} + +void +PlaylistLayeringTest::recursiveRelayerTest () +{ + _session->config.set_layer_model (AddOrBoundsChangeHigher); + _session->config.set_relayer_on_all_edits (false); + + create_short_regions (); - _playlist->add_region (_region[0], 0); - _playlist->add_region (_region[1], 10); - _playlist->add_region (_region[2], 20); + _playlist->add_region (_region[A], 100); + _playlist->add_region (_region[B], 125); + _playlist->add_region (_region[C], 50); + _playlist->add_region (_region[D], 250); - CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[0]->layer ()); - CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[1]->layer ()); - CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[2]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[A]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[B]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[C]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ()); - _region[0]->set_position (5); + _region[A]->set_position (200); - /* region move should have put 0 on top */ - CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[0]->layer ()); - CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[1]->layer ()); - CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[2]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[A]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[B]->layer ()); + CPPUNIT_ASSERT_EQUAL (layer_t (3), _region[C]->layer ()); } diff --git a/libs/ardour/test/playlist_layering_test.h b/libs/ardour/test/playlist_layering_test.h index 7757e017c4..ab5fe701b1 100644 --- a/libs/ardour/test/playlist_layering_test.h +++ b/libs/ardour/test/playlist_layering_test.h @@ -1,5 +1,6 @@ #include <cppunit/TestFixture.h> #include <cppunit/extensions/HelperMacros.h> +#include "test_needing_session.h" namespace ARDOUR { class Session; @@ -7,25 +8,42 @@ namespace ARDOUR { class Source; } -class PlaylistLayeringTest : public CppUnit::TestFixture +class PlaylistLayeringTest : public TestNeedingSession { CPPUNIT_TEST_SUITE (PlaylistLayeringTest); - CPPUNIT_TEST (addHigherTest); - CPPUNIT_TEST (moveAddHigherTest); + CPPUNIT_TEST (lastLayerOpTest); + CPPUNIT_TEST (addHigher_relayerOnAll_Test); + CPPUNIT_TEST (addOrBoundsHigher_relayerOnAll_Test); + CPPUNIT_TEST (laterHigher_relayerOnAll_Test); + CPPUNIT_TEST (addOrBoundsHigher_relayerWhenNecessary_Test); + CPPUNIT_TEST (recursiveRelayerTest); CPPUNIT_TEST_SUITE_END (); public: void setUp (); void tearDown (); - void addHigherTest (); - void moveAddHigherTest (); + void lastLayerOpTest (); + void addHigher_relayerOnAll_Test (); + void addOrBoundsHigher_relayerOnAll_Test (); + void laterHigher_relayerOnAll_Test (); + void addOrBoundsHigher_relayerWhenNecessary_Test (); + void recursiveRelayerTest (); private: - void create_three_short_regions (); + void create_short_regions (); + + static int const num_regions; + enum { + A = 0, + B, + C, + D, + E, + F + }; - ARDOUR::Session* _session; boost::shared_ptr<ARDOUR::Playlist> _playlist; boost::shared_ptr<ARDOUR::Source> _source; - boost::shared_ptr<ARDOUR::Region> _region[16]; + boost::shared_ptr<ARDOUR::Region>* _region; }; diff --git a/libs/ardour/test/playlist_overlap_cache_test.cc b/libs/ardour/test/playlist_overlap_cache_test.cc new file mode 100644 index 0000000000..9263d80d3b --- /dev/null +++ b/libs/ardour/test/playlist_overlap_cache_test.cc @@ -0,0 +1,119 @@ +#include "pbd/compose.h" +#include "ardour/playlist.h" +#include "ardour/playlist_factory.h" +#include "ardour/source_factory.h" +#include "ardour/region.h" +#include "ardour/region_sorters.h" +#include "ardour/region_factory.h" +#include "playlist_overlap_cache_test.h" + +using namespace std; +using namespace PBD; +using namespace ARDOUR; + +CPPUNIT_TEST_SUITE_REGISTRATION (PlaylistOverlapCacheTest); + +void +PlaylistOverlapCacheTest::tearDown () +{ + _playlist.reset (); + _source.reset (); + + TestNeedingSession::tearDown (); +} + +void +PlaylistOverlapCacheTest::basicTest () +{ + string const test_wav_path = "libs/ardour/test/test.wav"; + + _playlist = PlaylistFactory::create (DataType::AUDIO, *_session, "test"); + _source = SourceFactory::createWritable (DataType::AUDIO, *_session, test_wav_path, "", false, 44100); + + PropertyList plist; + plist.add (Properties::length, 256); + + boost::shared_ptr<Region> regionA = RegionFactory::create (_source, plist); + regionA->set_name ("A"); + _playlist->add_region (regionA, 0); + + + { + Playlist::OverlapCache cache (_playlist.get ()); + Playlist::RegionList rl = cache.get (Evoral::Range<framepos_t> (0, 256)); + CPPUNIT_ASSERT_EQUAL (size_t (1), rl.size ()); + CPPUNIT_ASSERT_EQUAL (regionA, rl.front ()); + + rl = cache.get (Evoral::Range<framepos_t> (-1000, 1000)); + CPPUNIT_ASSERT_EQUAL (size_t (1), rl.size ()); + CPPUNIT_ASSERT_EQUAL (regionA, rl.front ()); + } + + boost::shared_ptr<Region> regionB = RegionFactory::create (_source, plist); + regionA->set_name ("B"); + _playlist->add_region (regionB, 53); + + { + Playlist::OverlapCache cache (_playlist.get ()); + Playlist::RegionList rl = cache.get (Evoral::Range<framepos_t> (0, 256)); + CPPUNIT_ASSERT_EQUAL (size_t (2), rl.size ()); + rl.sort (RegionSortByPosition ()); + CPPUNIT_ASSERT_EQUAL (regionA, rl.front ()); + CPPUNIT_ASSERT_EQUAL (regionB, rl.back ()); + + rl = cache.get (Evoral::Range<framepos_t> (260, 274)); + CPPUNIT_ASSERT_EQUAL (size_t (1), rl.size ()); + CPPUNIT_ASSERT_EQUAL (regionB, rl.front ()); + } +} + +void +PlaylistOverlapCacheTest::stressTest () +{ + string const test_wav_path = "libs/ardour/test/test.wav"; + + _playlist = PlaylistFactory::create (DataType::AUDIO, *_session, "test"); + _source = SourceFactory::createWritable (DataType::AUDIO, *_session, test_wav_path, "", false, 44100); + + srand (42); + + int const num_regions = rand () % 256; + + for (int i = 0; i < num_regions; ++i) { + PropertyList plist; + plist.add (Properties::length, rand () % 32768); + boost::shared_ptr<Region> r = RegionFactory::create (_source, plist); + r->set_name (string_compose ("%1", i)); + _playlist->add_region (r, rand() % 32768); + } + + Playlist::OverlapCache cache (_playlist.get ()); + + int const tests = rand () % 256; + + for (int i = 0; i < tests; ++i) { + framepos_t const start = rand () % 32768; + framepos_t const length = rand () % 32768; + framepos_t const end = start + length; + + Playlist::RegionList cached = cache.get (Evoral::Range<framepos_t> (start, end)); + + Playlist::RegionList actual; + Playlist::RegionList regions = _playlist->region_list().rlist(); + for (Playlist::RegionList::iterator j = regions.begin(); j != regions.end(); ++j) { + if ((*j)->coverage (start, end) != OverlapNone) { + actual.push_back (*j); + } + } + + cached.sort (RegionSortByPosition ()); + actual.sort (RegionSortByPosition ()); + + CPPUNIT_ASSERT_EQUAL (actual.size (), cached.size ()); + Playlist::RegionList::iterator j = actual.begin (); + Playlist::RegionList::iterator k = cached.begin (); + for (; j != actual.end(); ++j, ++k) { + CPPUNIT_ASSERT_EQUAL (*j, *k); + } + } +} diff --git a/libs/ardour/test/playlist_overlap_cache_test.h b/libs/ardour/test/playlist_overlap_cache_test.h new file mode 100644 index 0000000000..c75d1691d9 --- /dev/null +++ b/libs/ardour/test/playlist_overlap_cache_test.h @@ -0,0 +1,20 @@ +#include "test_needing_session.h" + +class PlaylistOverlapCacheTest : public TestNeedingSession +{ +public: + CPPUNIT_TEST_SUITE (PlaylistOverlapCacheTest); + CPPUNIT_TEST (basicTest); + CPPUNIT_TEST (stressTest); + CPPUNIT_TEST_SUITE_END (); + +public: + void tearDown (); + + void basicTest (); + void stressTest (); + +private: + boost::shared_ptr<ARDOUR::Playlist> _playlist; + boost::shared_ptr<ARDOUR::Source> _source; +}; diff --git a/libs/ardour/test/test_needing_session.cc b/libs/ardour/test/test_needing_session.cc new file mode 100644 index 0000000000..5981553601 --- /dev/null +++ b/libs/ardour/test/test_needing_session.cc @@ -0,0 +1,48 @@ +#include "midi++/manager.h" +#include "pbd/textreceiver.h" +#include "pbd/compose.h" +#include "pbd/enumwriter.h" +#include "ardour/session.h" +#include "ardour/audioengine.h" +#include "test_needing_session.h" +#include "test_receiver.h" + +using namespace std; +using namespace ARDOUR; +using namespace PBD; + +TestReceiver test_receiver; + +void +TestNeedingSession::setUp () +{ + string const test_session_path = "libs/ardour/test/test_session"; + system (string_compose ("rm -rf %1", test_session_path).c_str()); + + init (false, true); + SessionEvent::create_per_thread_pool ("test", 512); + + test_receiver.listen_to (error); + test_receiver.listen_to (info); + test_receiver.listen_to (fatal); + test_receiver.listen_to (warning); + + AudioEngine* engine = new AudioEngine ("test", ""); + MIDI::Manager::create (engine->jack ()); + CPPUNIT_ASSERT (engine->start () == 0); + + _session = new Session (*engine, test_session_path, "test_session"); + engine->set_session (_session); +} + +void +TestNeedingSession::tearDown () +{ + AudioEngine::instance()->remove_session (); + + delete _session; + + EnumWriter::destroy (); + MIDI::Manager::destroy (); + AudioEngine::destroy (); +} diff --git a/libs/ardour/test/test_needing_session.h b/libs/ardour/test/test_needing_session.h new file mode 100644 index 0000000000..3839855179 --- /dev/null +++ b/libs/ardour/test/test_needing_session.h @@ -0,0 +1,16 @@ +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> + +namespace ARDOUR { + class Session; +} + +class TestNeedingSession : public CppUnit::TestFixture +{ +public: + void setUp (); + void tearDown (); + +protected: + ARDOUR::Session* _session; +}; diff --git a/libs/ardour/test/test_receiver.h b/libs/ardour/test/test_receiver.h new file mode 100644 index 0000000000..537bac3cff --- /dev/null +++ b/libs/ardour/test/test_receiver.h @@ -0,0 +1,37 @@ +#include "pbd/receiver.h" + +class TestReceiver : public Receiver +{ +protected: + void receive (Transmitter::Channel chn, const char * str) { + const char *prefix = ""; + + switch (chn) { + case Transmitter::Error: + prefix = ": [ERROR]: "; + break; + case Transmitter::Info: + /* ignore */ + return; + case Transmitter::Warning: + prefix = ": [WARNING]: "; + break; + case Transmitter::Fatal: + prefix = ": [FATAL]: "; + break; + case Transmitter::Throw: + /* this isn't supposed to happen */ + abort (); + } + + /* note: iostreams are already thread-safe: no external + lock required. + */ + + std::cout << prefix << str << std::endl; + + if (chn == Transmitter::Fatal) { + exit (9); + } + } +}; |