#include "PlaylistCWrapperMock.h" #include #include using ::testing::Return; using ::testing::ReturnRef; using ::testing::Throw; /** * This suite only tests the API forwarding to the wrapper, not the actual playlist functionality! * * Also note that the playlist wrapper class should never be instantiated directly in production * code. ALWAYS use projectm_playlist_create() to create the instance and only use the C API * functions to access the functionality. The extreme use of reinterpret_cast<>() in this test suite * should make that quite obvious. */ TEST(projectMPlaylistAPI, Create) { auto* playlistHandle = projectm_playlist_create(nullptr); ASSERT_NE(playlistHandle, nullptr); projectm_playlist_destroy(playlistHandle); } TEST(projectMPlaylistAPI, Connect) { PlaylistCWrapperMock mockPlaylist; EXPECT_CALL(mockPlaylist, Connect(nullptr)) .Times(1); projectm_playlist_connect(reinterpret_cast(&mockPlaylist), nullptr); projectm_handle someHandle{reinterpret_cast(2537)}; EXPECT_CALL(mockPlaylist, Connect(someHandle)).Times(1); projectm_playlist_connect(reinterpret_cast(&mockPlaylist), someHandle); } TEST(projectMPlaylistAPI, Size) { PlaylistCWrapperMock mockPlaylist; EXPECT_CALL(mockPlaylist, Size()) .Times(1) .WillOnce(Return(2336)); ASSERT_EQ(projectm_playlist_size(reinterpret_cast(&mockPlaylist)), 2336); } TEST(projectMPlaylistAPI, Clear) { PlaylistCWrapperMock mockPlaylist; EXPECT_CALL(mockPlaylist, Clear()) .Times(1); projectm_playlist_clear(reinterpret_cast(&mockPlaylist)); } TEST(projectMPlaylistAPI, ItemsAll) { PlaylistCWrapperMock mockPlaylist; std::vector items{ libprojectM::Playlist::Item("/some/file"), libprojectM::Playlist::Item("/another/file")}; EXPECT_CALL(mockPlaylist, Items()) .Times(1) .WillOnce(ReturnRef(items)); // Passing INT_MAX as count should make the function always return all elements. auto* returnedItems = projectm_playlist_items(reinterpret_cast(&mockPlaylist), 0, std::numeric_limits::max()); ASSERT_NE(returnedItems, nullptr); ASSERT_NE(*returnedItems, nullptr); EXPECT_STREQ(*returnedItems, items.at(0).Filename().c_str()); ASSERT_NE(*(returnedItems + 1), nullptr); EXPECT_STREQ(*(returnedItems + 1), items.at(1).Filename().c_str()); EXPECT_EQ(*(returnedItems + 2), nullptr); projectm_playlist_free_string_array(returnedItems); } TEST(projectMPlaylistAPI, ItemsPartial) { PlaylistCWrapperMock mockPlaylist; std::vector items{ libprojectM::Playlist::Item("/some/file"), libprojectM::Playlist::Item("/another/file1"), libprojectM::Playlist::Item("/another/file2"), libprojectM::Playlist::Item("/another/file3"), libprojectM::Playlist::Item("/another/file4"), libprojectM::Playlist::Item("/another/file5")}; EXPECT_CALL(mockPlaylist, Items()) .Times(1) .WillOnce(ReturnRef(items)); auto* returnedItems = projectm_playlist_items(reinterpret_cast(&mockPlaylist), 1, 3); ASSERT_NE(returnedItems, nullptr); ASSERT_NE(*returnedItems, nullptr); EXPECT_STREQ(*returnedItems, items.at(1).Filename().c_str()); ASSERT_NE(*(returnedItems + 1), nullptr); EXPECT_STREQ(*(returnedItems + 1), items.at(2).Filename().c_str()); EXPECT_NE(*(returnedItems + 2), nullptr); EXPECT_STREQ(*(returnedItems + 2), items.at(3).Filename().c_str()); EXPECT_EQ(*(returnedItems + 3), nullptr); projectm_playlist_free_string_array(returnedItems); } TEST(projectMPlaylistAPI, ItemsOutOfRange) { PlaylistCWrapperMock mockPlaylist; std::vector items{ libprojectM::Playlist::Item("/some/file"), libprojectM::Playlist::Item("/another/file1"), libprojectM::Playlist::Item("/another/file2"), libprojectM::Playlist::Item("/another/file3"), libprojectM::Playlist::Item("/another/file4"), libprojectM::Playlist::Item("/another/file5")}; EXPECT_CALL(mockPlaylist, Items()) .Times(1) .WillOnce(ReturnRef(items)); auto* returnedItems = projectm_playlist_items(reinterpret_cast(&mockPlaylist), 10, 10); ASSERT_NE(returnedItems, nullptr); ASSERT_EQ(*returnedItems, nullptr); projectm_playlist_free_string_array(returnedItems); } TEST(projectMPlaylistAPI, Item) { PlaylistCWrapperMock mockPlaylist; std::vector items{ libprojectM::Playlist::Item("/some/file"), libprojectM::Playlist::Item("/another/file")}; EXPECT_CALL(mockPlaylist, Empty()) .Times(1) .WillOnce(Return(false)); EXPECT_CALL(mockPlaylist, Size()) .Times(1) .WillOnce(Return(2)); EXPECT_CALL(mockPlaylist, Items()) .Times(1) .WillOnce(ReturnRef(items)); auto* returnedItem = projectm_playlist_item(reinterpret_cast(&mockPlaylist), 1); ASSERT_NE(returnedItem, nullptr); EXPECT_STREQ(returnedItem, items.at(1).Filename().c_str()); projectm_playlist_free_string(returnedItem); } TEST(projectMPlaylistAPI, ItemEmptyPlaylist) { PlaylistCWrapperMock mockPlaylist; std::vector items{ libprojectM::Playlist::Item("/some/file"), libprojectM::Playlist::Item("/another/file")}; EXPECT_CALL(mockPlaylist, Empty()) .Times(1) .WillOnce(Return(true)); EXPECT_EQ(projectm_playlist_item(reinterpret_cast(&mockPlaylist), 1), nullptr); } TEST(projectMPlaylistAPI, ItemIndexOutOfBounds) { PlaylistCWrapperMock mockPlaylist; std::vector items{ libprojectM::Playlist::Item("/some/file"), libprojectM::Playlist::Item("/another/file")}; EXPECT_CALL(mockPlaylist, Empty()) .Times(1) .WillOnce(Return(false)); EXPECT_CALL(mockPlaylist, Size()) .Times(1) .WillOnce(Return(2)); EXPECT_EQ(projectm_playlist_item(reinterpret_cast(&mockPlaylist), 5), nullptr); } TEST(projectMPlaylistAPI, AddPath) { PlaylistCWrapperMock mockPlaylist; EXPECT_CALL(mockPlaylist, AddPath("/some/path", libprojectM::Playlist::Playlist::InsertAtEnd, true, false)) .Times(1) .WillOnce(Return(35)); EXPECT_EQ(projectm_playlist_add_path(reinterpret_cast(&mockPlaylist), "/some/path", true, false), 35); } TEST(projectMPlaylistAPI, InsertPath) { PlaylistCWrapperMock mockPlaylist; EXPECT_CALL(mockPlaylist, AddPath("/some/path", 6782, false, true)) .Times(1) .WillOnce(Return(84)); EXPECT_EQ(projectm_playlist_insert_path(reinterpret_cast(&mockPlaylist), "/some/path", 6782, false, true), 84); } TEST(projectMPlaylistAPI, AddPreset) { PlaylistCWrapperMock mockPlaylist; EXPECT_CALL(mockPlaylist, AddItem("/some/file", libprojectM::Playlist::Playlist::InsertAtEnd, false)) .Times(1) .WillOnce(Return(true)); EXPECT_TRUE(projectm_playlist_add_preset(reinterpret_cast(&mockPlaylist), "/some/file", false)); } TEST(projectMPlaylistAPI, InsertPreset) { PlaylistCWrapperMock mockPlaylist; EXPECT_CALL(mockPlaylist, AddItem("/some/file", 34, true)) .Times(1) .WillOnce(Return(true)); EXPECT_TRUE(projectm_playlist_insert_preset(reinterpret_cast(&mockPlaylist), "/some/file", 34, true)); } TEST(projectMPlaylistAPI, AddPresets) { PlaylistCWrapperMock mockPlaylist; const char firstFile[]{"/some/file"}; const char secondFile[]{"/another/file"}; const char thirdFile[]{"/another/file"}; const char* presetList[]{firstFile, secondFile, thirdFile}; EXPECT_CALL(mockPlaylist, AddItem("/some/file", libprojectM::Playlist::Playlist::InsertAtEnd, false)) .Times(1) .WillOnce(Return(true)); EXPECT_CALL(mockPlaylist, AddItem("/another/file", libprojectM::Playlist::Playlist::InsertAtEnd, false)) .Times(2) .WillOnce(Return(true)) .WillOnce(Return(false)); EXPECT_EQ(projectm_playlist_add_presets(reinterpret_cast(&mockPlaylist), presetList, 3, false), 2); } TEST(projectMPlaylistAPI, InsertPresets) { PlaylistCWrapperMock mockPlaylist; const char firstFile[]{"/some/file"}; const char secondFile[]{"/some/file"}; const char thirdFile[]{"/another/file"}; const char* presetList[]{firstFile, secondFile, thirdFile}; EXPECT_CALL(mockPlaylist, AddItem("/some/file", 34, false)) .Times(1) .WillOnce(Return(true)); EXPECT_CALL(mockPlaylist, AddItem("/some/file", 35, false)) .Times(1) .WillOnce(Return(false)); EXPECT_CALL(mockPlaylist, AddItem("/another/file", 35, false)) // Index not incremented! .Times(1) .WillOnce(Return(true)); EXPECT_EQ(projectm_playlist_insert_presets(reinterpret_cast(&mockPlaylist), presetList, 3, 34, false), 2); } TEST(projectMPlaylistAPI, RemovePreset) { PlaylistCWrapperMock mockPlaylist; EXPECT_CALL(mockPlaylist, RemoveItem(0)) .Times(2) .WillOnce(Return(true)) .WillOnce(Return(false)); EXPECT_TRUE(projectm_playlist_remove_preset(reinterpret_cast(&mockPlaylist), 0)); EXPECT_FALSE(projectm_playlist_remove_preset(reinterpret_cast(&mockPlaylist), 0)); } TEST(projectMPlaylistAPI, RemovePresets) { PlaylistCWrapperMock mockPlaylist; EXPECT_CALL(mockPlaylist, RemoveItem(0)) .Times(3) .WillOnce(Return(true)) .WillOnce(Return(true)) .WillOnce(Return(false)); EXPECT_EQ(projectm_playlist_remove_presets(reinterpret_cast(&mockPlaylist), 0, 3), 2); } TEST(projectMPlaylistAPI, GetShuffle) { PlaylistCWrapperMock mockPlaylist; EXPECT_CALL(mockPlaylist, Shuffle()) .Times(1) .WillOnce(Return(true)); EXPECT_TRUE(projectm_playlist_get_shuffle(reinterpret_cast(&mockPlaylist))); } TEST(projectMPlaylistAPI, SetShuffle) { PlaylistCWrapperMock mockPlaylist; EXPECT_CALL(mockPlaylist, SetShuffle(true)) .Times(1); EXPECT_CALL(mockPlaylist, SetShuffle(false)) .Times(1); projectm_playlist_set_shuffle(reinterpret_cast(&mockPlaylist), true); projectm_playlist_set_shuffle(reinterpret_cast(&mockPlaylist), false); } TEST(projectMPlaylistAPI, Sort) { using libprojectM::Playlist::Playlist; PlaylistCWrapperMock mockPlaylist; EXPECT_CALL(mockPlaylist, Sort(0, 5000, Playlist::SortPredicate::FullPath, Playlist::SortOrder::Ascending)) .Times(3); // Defaults - invalid values should call the Sort() function like this. EXPECT_CALL(mockPlaylist, Sort(0, 5000, Playlist::SortPredicate::FullPath, Playlist::SortOrder::Descending)) .Times(1); EXPECT_CALL(mockPlaylist, Sort(0, 5000, Playlist::SortPredicate::FilenameOnly, Playlist::SortOrder::Ascending)) .Times(1); EXPECT_CALL(mockPlaylist, Sort(0, 5000, Playlist::SortPredicate::FilenameOnly, Playlist::SortOrder::Descending)) .Times(1); projectm_playlist_sort(reinterpret_cast(&mockPlaylist), 0, 5000, SORT_PREDICATE_FULL_PATH, SORT_ORDER_ASCENDING); projectm_playlist_sort(reinterpret_cast(&mockPlaylist), 0, 5000, SORT_PREDICATE_FULL_PATH, SORT_ORDER_DESCENDING); projectm_playlist_sort(reinterpret_cast(&mockPlaylist), 0, 5000, SORT_PREDICATE_FILENAME_ONLY, SORT_ORDER_ASCENDING); projectm_playlist_sort(reinterpret_cast(&mockPlaylist), 0, 5000, SORT_PREDICATE_FILENAME_ONLY, SORT_ORDER_DESCENDING); projectm_playlist_sort(reinterpret_cast(&mockPlaylist), 0, 5000, static_cast(100), SORT_ORDER_ASCENDING); projectm_playlist_sort(reinterpret_cast(&mockPlaylist), 0, 5000, SORT_PREDICATE_FULL_PATH, static_cast(200)); } TEST(projectMPlaylistAPI, GetRetryCount) { PlaylistCWrapperMock mockPlaylist; EXPECT_CALL(mockPlaylist, RetryCount()) .Times(1) .WillOnce(Return(5)); EXPECT_EQ(projectm_playlist_get_retry_count(reinterpret_cast(&mockPlaylist)), 5); } TEST(projectMPlaylistAPI, SetRetryCount) { PlaylistCWrapperMock mockPlaylist; EXPECT_CALL(mockPlaylist, SetRetryCount(5)) .Times(1); projectm_playlist_set_retry_count(reinterpret_cast(&mockPlaylist), 5); } TEST(projectMPlaylistAPI, GetPosition) { PlaylistCWrapperMock mockPlaylist; EXPECT_CALL(mockPlaylist, PresetIndex()) .Times(1) .WillOnce(Return(512)); EXPECT_EQ(projectm_playlist_get_position(reinterpret_cast(&mockPlaylist)), 512); } TEST(projectMPlaylistAPI, GetPositionException) { PlaylistCWrapperMock mockPlaylist; EXPECT_CALL(mockPlaylist, PresetIndex()) .Times(1) .WillOnce(Throw(libprojectM::Playlist::PlaylistEmptyException())); EXPECT_EQ(projectm_playlist_get_position(reinterpret_cast(&mockPlaylist)), 0); } TEST(projectMPlaylistAPI, SetPosition) { PlaylistCWrapperMock mockPlaylist; EXPECT_CALL(mockPlaylist, SetPresetIndex(256)) .Times(2) .WillRepeatedly(Return(512)); EXPECT_CALL(mockPlaylist, PlayPresetIndex(512, true, true)) .Times(1); EXPECT_CALL(mockPlaylist, PlayPresetIndex(512, false, true)) .Times(1); EXPECT_CALL(mockPlaylist, PresetIndex()) .Times(2) .WillRepeatedly(Return(512)); EXPECT_EQ(projectm_playlist_set_position(reinterpret_cast(&mockPlaylist), 256, true), 512); EXPECT_EQ(projectm_playlist_set_position(reinterpret_cast(&mockPlaylist), 256, false), 512); } TEST(projectMPlaylistAPI, SetPositionException) { PlaylistCWrapperMock mockPlaylist; EXPECT_CALL(mockPlaylist, SetPresetIndex(256)) .Times(2) .WillRepeatedly(Throw(libprojectM::Playlist::PlaylistEmptyException())); EXPECT_EQ(projectm_playlist_set_position(reinterpret_cast(&mockPlaylist), 256, true), 0); EXPECT_EQ(projectm_playlist_set_position(reinterpret_cast(&mockPlaylist), 256, false), 0); } TEST(projectMPlaylistAPI, PlayNext) { PlaylistCWrapperMock mockPlaylist; EXPECT_CALL(mockPlaylist, NextPresetIndex()) .Times(2) .WillRepeatedly(Return(512)); EXPECT_CALL(mockPlaylist, PlayPresetIndex(512, true, true)) .Times(1); EXPECT_CALL(mockPlaylist, PlayPresetIndex(512, false, true)) .Times(1); EXPECT_CALL(mockPlaylist, PresetIndex()) .Times(2) .WillRepeatedly(Return(512)); EXPECT_EQ(projectm_playlist_play_next(reinterpret_cast(&mockPlaylist), true), 512); EXPECT_EQ(projectm_playlist_play_next(reinterpret_cast(&mockPlaylist), false), 512); } TEST(projectMPlaylistAPI, PlayNextException) { PlaylistCWrapperMock mockPlaylist; EXPECT_CALL(mockPlaylist, NextPresetIndex()) .Times(2) .WillRepeatedly(Throw(libprojectM::Playlist::PlaylistEmptyException())); EXPECT_EQ(projectm_playlist_play_next(reinterpret_cast(&mockPlaylist), true), 0); EXPECT_EQ(projectm_playlist_play_next(reinterpret_cast(&mockPlaylist), false), 0); } TEST(projectMPlaylistAPI, PlayPrevious) { PlaylistCWrapperMock mockPlaylist; EXPECT_CALL(mockPlaylist, PreviousPresetIndex()) .Times(2) .WillRepeatedly(Return(512)); EXPECT_CALL(mockPlaylist, PlayPresetIndex(512, true, true)) .Times(1); EXPECT_CALL(mockPlaylist, PlayPresetIndex(512, false, true)) .Times(1); EXPECT_CALL(mockPlaylist, PresetIndex()) .Times(2) .WillRepeatedly(Return(512)); EXPECT_EQ(projectm_playlist_play_previous(reinterpret_cast(&mockPlaylist), true), 512); EXPECT_EQ(projectm_playlist_play_previous(reinterpret_cast(&mockPlaylist), false), 512); } TEST(projectMPlaylistAPI, PlayPreviousException) { PlaylistCWrapperMock mockPlaylist; EXPECT_CALL(mockPlaylist, PreviousPresetIndex()) .Times(2) .WillRepeatedly(Throw(libprojectM::Playlist::PlaylistEmptyException())); EXPECT_EQ(projectm_playlist_play_previous(reinterpret_cast(&mockPlaylist), true), 0); EXPECT_EQ(projectm_playlist_play_previous(reinterpret_cast(&mockPlaylist), false), 0); } TEST(projectMPlaylistAPI, PlayLast) { PlaylistCWrapperMock mockPlaylist; EXPECT_CALL(mockPlaylist, PreviousPresetIndex()) .Times(2) .WillRepeatedly(Return(512)); EXPECT_CALL(mockPlaylist, PlayPresetIndex(512, true, true)) .Times(1); EXPECT_CALL(mockPlaylist, PlayPresetIndex(512, false, true)) .Times(1); EXPECT_CALL(mockPlaylist, PresetIndex()) .Times(2) .WillRepeatedly(Return(512)); EXPECT_EQ(projectm_playlist_play_previous(reinterpret_cast(&mockPlaylist), true), 512); EXPECT_EQ(projectm_playlist_play_previous(reinterpret_cast(&mockPlaylist), false), 512); } TEST(projectMPlaylistAPI, PlayLastException) { PlaylistCWrapperMock mockPlaylist; EXPECT_CALL(mockPlaylist, LastPresetIndex()) .Times(2) .WillRepeatedly(Throw(libprojectM::Playlist::PlaylistEmptyException())); EXPECT_EQ(projectm_playlist_play_last(reinterpret_cast(&mockPlaylist), true), 0); EXPECT_EQ(projectm_playlist_play_last(reinterpret_cast(&mockPlaylist), false), 0); } TEST(projectMPlaylistAPI, SetPresetSwitchedCallback) { PlaylistCWrapperMock mockPlaylist; projectm_playlist_preset_switched_event dummyCallback = [](bool, uint32_t, void*) {}; void* dummyData{reinterpret_cast(2973246)}; EXPECT_CALL(mockPlaylist, SetPresetSwitchedCallback(dummyCallback, dummyData)) .Times(1); projectm_playlist_set_preset_switched_event_callback(reinterpret_cast(&mockPlaylist), dummyCallback, dummyData); } TEST(projectMPlaylistAPI, SetPresetSwitchFailedCallback) { PlaylistCWrapperMock mockPlaylist; projectm_playlist_preset_switch_failed_event dummyCallback = [](const char*, const char*, void*) {}; void* dummyData{reinterpret_cast(348564)}; EXPECT_CALL(mockPlaylist, SetPresetSwitchFailedCallback(dummyCallback, dummyData)) .Times(1); projectm_playlist_set_preset_switch_failed_event_callback(reinterpret_cast(&mockPlaylist), dummyCallback, dummyData); } TEST(projectMPlaylistAPI, SetFilter) { PlaylistCWrapperMock mockPlaylist; libprojectM::Playlist::Filter filter; EXPECT_CALL(mockPlaylist, Filter()) .Times(1) .WillOnce(ReturnRef(filter)); const char firstFilter[]{"-/some/BadPreset.milk"}; const char secondFilter[]{"+/another/AwesomePreset.milk"}; const char thirdFilter[]{"-/unwanted/Preset.milk"}; const char* filterList[]{firstFilter, secondFilter, thirdFilter}; projectm_playlist_set_filter(reinterpret_cast(&mockPlaylist), filterList, 3); const auto& internalFilterList = filter.List(); ASSERT_EQ(internalFilterList.size(), 3); EXPECT_EQ(internalFilterList.at(0), "-/some/BadPreset.milk"); EXPECT_EQ(internalFilterList.at(1), "+/another/AwesomePreset.milk"); EXPECT_EQ(internalFilterList.at(2), "-/unwanted/Preset.milk"); } TEST(projectMPlaylistAPI, GetFilter) { PlaylistCWrapperMock mockPlaylist; libprojectM::Playlist::Filter filter; filter.SetList({"-/some/BadPreset.milk", "+/another/AwesomePreset.milk", "-/unwanted/Preset.milk"}); EXPECT_CALL(mockPlaylist, Filter()) .Times(1) .WillOnce(ReturnRef(filter)); size_t count{}; auto filterList = projectm_playlist_get_filter(reinterpret_cast(&mockPlaylist), &count); ASSERT_EQ(count, 3); ASSERT_NE(filterList, nullptr); EXPECT_STREQ(filterList[0], "-/some/BadPreset.milk"); EXPECT_STREQ(filterList[1], "+/another/AwesomePreset.milk"); EXPECT_STREQ(filterList[2], "-/unwanted/Preset.milk"); projectm_playlist_free_string_array(filterList); } TEST(projectMPlaylistAPI, ApplyFilter) { PlaylistCWrapperMock mockPlaylist; EXPECT_CALL(mockPlaylist, ApplyFilter()) .Times(1) .WillOnce(Return(5)); EXPECT_EQ(projectm_playlist_apply_filter(reinterpret_cast(&mockPlaylist)), 5); }