summaryrefslogtreecommitdiff
path: root/libs/ardour/test
diff options
context:
space:
mode:
Diffstat (limited to 'libs/ardour/test')
-rw-r--r--libs/ardour/test/playlist_layering_test.cc384
-rw-r--r--libs/ardour/test/playlist_layering_test.h34
-rw-r--r--libs/ardour/test/playlist_overlap_cache_test.cc119
-rw-r--r--libs/ardour/test/playlist_overlap_cache_test.h20
-rw-r--r--libs/ardour/test/test_needing_session.cc48
-rw-r--r--libs/ardour/test/test_needing_session.h16
-rw-r--r--libs/ardour/test/test_receiver.h37
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);
+ }
+ }
+};