test_queue_priority.cxx 5.17 KB
Newer Older
1
#include "config.h"
2
#include "Queue.hxx"
3
#include "Song.hxx"
4
#include "Directory.hxx"
5
#include "util/Macros.hxx"
6

7 8 9 10
#include <cppunit/TestFixture.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/ui/text/TestRunner.h>
#include <cppunit/extensions/HelperMacros.h>
11

12
Directory detached_root;
13

14
Directory::Directory() {}
15 16
Directory::~Directory() {}

17 18
Song *
Song::DupDetached() const
19
{
20
	return const_cast<Song *>(this);
21
}
22 23

void
24
Song::Free()
25 26 27 28
{
}

static void
29
check_descending_priority(const struct queue *queue,
30
			  unsigned start_order)
31
{
32
	assert(start_order < queue->GetLength());
33 34

	uint8_t last_priority = 0xff;
35 36
	for (unsigned order = start_order; order < queue->GetLength(); ++order) {
		unsigned position = queue->OrderToPosition(order);
37 38
		uint8_t priority = queue->items[position].priority;
		assert(priority <= last_priority);
39
		(void)last_priority;
40 41 42 43
		last_priority = priority;
	}
}

44 45 46 47 48 49 50 51 52 53 54
class QueuePriorityTest : public CppUnit::TestFixture {
	CPPUNIT_TEST_SUITE(QueuePriorityTest);
	CPPUNIT_TEST(TestPriority);
	CPPUNIT_TEST_SUITE_END();

public:
	void TestPriority();
};

void
QueuePriorityTest::TestPriority()
55
{
56
	static Song songs[16];
57

58
	struct queue queue(32);
59

60
	for (unsigned i = 0; i < ARRAY_SIZE(songs); ++i)
61
		queue.Append(&songs[i], 0);
62

63
	CPPUNIT_ASSERT_EQUAL(unsigned(ARRAY_SIZE(songs)), queue.GetLength());
64 65 66

	/* priority=10 for 4 items */

67
	queue.SetPriorityRange(4, 8, 10, -1);
68 69

	queue.random = true;
70
	queue.ShuffleOrder();
71 72 73
	check_descending_priority(&queue, 0);

	for (unsigned i = 0; i < 4; ++i) {
74
		assert(queue.PositionToOrder(i) >= 4);
75 76 77
	}

	for (unsigned i = 4; i < 8; ++i) {
78
		assert(queue.PositionToOrder(i) < 4);
79 80
	}

81
	for (unsigned i = 8; i < ARRAY_SIZE(songs); ++i) {
82
		assert(queue.PositionToOrder(i) >= 4);
83 84 85 86
	}

	/* priority=50 one more item */

87
	queue.SetPriorityRange(15, 16, 50, -1);
88 89
	check_descending_priority(&queue, 0);

90
	CPPUNIT_ASSERT_EQUAL(0u, queue.PositionToOrder(15));
91 92

	for (unsigned i = 0; i < 4; ++i) {
93
		assert(queue.PositionToOrder(i) >= 4);
94 95 96
	}

	for (unsigned i = 4; i < 8; ++i) {
97 98
		assert(queue.PositionToOrder(i) >= 1 &&
		       queue.PositionToOrder(i) < 5);
99 100 101
	}

	for (unsigned i = 8; i < 15; ++i) {
102
		assert(queue.PositionToOrder(i) >= 5);
103 104 105 106
	}

	/* priority=20 for one of the 4 priority=10 items */

107
	queue.SetPriorityRange(3, 4, 20, -1);
108 109
	check_descending_priority(&queue, 0);

110 111
	CPPUNIT_ASSERT_EQUAL(1u, queue.PositionToOrder(3));
	CPPUNIT_ASSERT_EQUAL(0u, queue.PositionToOrder(15));
112 113

	for (unsigned i = 0; i < 3; ++i) {
114
		assert(queue.PositionToOrder(i) >= 5);
115 116 117
	}

	for (unsigned i = 4; i < 8; ++i) {
118 119
		assert(queue.PositionToOrder(i) >= 2 &&
		       queue.PositionToOrder(i) < 6);
120 121 122
	}

	for (unsigned i = 8; i < 15; ++i) {
123
		assert(queue.PositionToOrder(i) >= 6);
124 125 126 127 128 129 130 131
	}

	/* priority=20 for another one of the 4 priority=10 items;
	   pass "after_order" (with priority=10) and see if it's moved
	   after that one */

	unsigned current_order = 4;
	unsigned current_position =
132
		queue.OrderToPosition(current_order);
133 134

	unsigned a_order = 3;
135
	unsigned a_position = queue.OrderToPosition(a_order);
136
	CPPUNIT_ASSERT_EQUAL(10u, unsigned(queue.items[a_position].priority));
137
	queue.SetPriority(a_position, 20, current_order);
138

139
	current_order = queue.PositionToOrder(current_position);
140
	CPPUNIT_ASSERT_EQUAL(3u, current_order);
141

142
	a_order = queue.PositionToOrder(a_position);
143
	CPPUNIT_ASSERT_EQUAL(4u, a_order);
144 145 146 147 148 149 150 151

	check_descending_priority(&queue, current_order + 1);

	/* priority=70 for one of the last items; must be inserted
	   right after the current song, before the priority=20 one we
	   just created */

	unsigned b_order = 10;
152
	unsigned b_position = queue.OrderToPosition(b_order);
153
	CPPUNIT_ASSERT_EQUAL(0u, unsigned(queue.items[b_position].priority));
154
	queue.SetPriority(b_position, 70, current_order);
155

156
	current_order = queue.PositionToOrder(current_position);
157
	CPPUNIT_ASSERT_EQUAL(3u, current_order);
158

159
	b_order = queue.PositionToOrder(b_position);
160
	CPPUNIT_ASSERT_EQUAL(4u, b_order);
161 162 163 164 165 166 167 168

	check_descending_priority(&queue, current_order + 1);

	/* priority=60 for the old prio50 item; must not be moved,
	   because it's before the current song, and it's status
	   hasn't changed (it was already higher before) */

	unsigned c_order = 0;
169
	unsigned c_position = queue.OrderToPosition(c_order);
170
	CPPUNIT_ASSERT_EQUAL(50u, unsigned(queue.items[c_position].priority));
171
	queue.SetPriority(c_position, 60, current_order);
172

173
	current_order = queue.PositionToOrder(current_position);
174
	CPPUNIT_ASSERT_EQUAL(3u, current_order);
175

176
	c_order = queue.PositionToOrder(c_position);
177
	CPPUNIT_ASSERT_EQUAL(0u, c_order);
178 179 180

	/* move the prio=20 item back */

181
	a_order = queue.PositionToOrder(a_position);
182 183
	CPPUNIT_ASSERT_EQUAL(5u, a_order);
	CPPUNIT_ASSERT_EQUAL(20u, unsigned(queue.items[a_position].priority));
184
	queue.SetPriority(a_position, 5, current_order);
185

186
	current_order = queue.PositionToOrder(current_position);
187
	CPPUNIT_ASSERT_EQUAL(3u, current_order);
188

189
	a_order = queue.PositionToOrder(a_position);
190 191 192 193 194 195 196 197 198 199 200 201
	CPPUNIT_ASSERT_EQUAL(6u, a_order);
}

CPPUNIT_TEST_SUITE_REGISTRATION(QueuePriorityTest);

int
main(gcc_unused int argc, gcc_unused char **argv)
{
	CppUnit::TextUi::TestRunner runner;
	auto &registry = CppUnit::TestFactoryRegistry::getRegistry();
	runner.addTest(registry.makeTest());
	return runner.run() ? EXIT_SUCCESS : EXIT_FAILURE;
202
}