1 /*
2  * Copyright 2003-2021 The Music Player Daemon Project
3  * http://www.musicpd.org
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 #include "MakeTag.hxx"
21 #include "song/TagSongFilter.hxx"
22 #include "song/LightSong.hxx"
23 #include "tag/Type.h"
24 
25 #include <gtest/gtest.h>
26 
27 static bool
InvokeFilter(const TagSongFilter & f,const Tag & tag)28 InvokeFilter(const TagSongFilter &f, const Tag &tag) noexcept
29 {
30 	return f.Match(LightSong("dummy", tag));
31 }
32 
TEST(TagSongFilter,Basic)33 TEST(TagSongFilter, Basic)
34 {
35 	const TagSongFilter f(TAG_TITLE,
36 			      StringFilter("needle", false, false, false));
37 
38 	EXPECT_TRUE(InvokeFilter(f, MakeTag(TAG_TITLE, "needle")));
39 	EXPECT_TRUE(InvokeFilter(f, MakeTag(TAG_TITLE, "foo", TAG_TITLE, "needle")));
40 	EXPECT_TRUE(InvokeFilter(f, MakeTag(TAG_TITLE, "needle", TAG_TITLE, "foo")));
41 	EXPECT_TRUE(InvokeFilter(f, MakeTag(TAG_ARTIST, "foo", TAG_TITLE, "needle", TAG_ALBUM, "bar")));
42 
43 	EXPECT_FALSE(InvokeFilter(f, MakeTag()));
44 	EXPECT_FALSE(InvokeFilter(f, MakeTag(TAG_TITLE, "foo")));
45 	EXPECT_FALSE(InvokeFilter(f, MakeTag(TAG_TITLE, "foo", TAG_TITLE, "bar")));
46 	EXPECT_FALSE(InvokeFilter(f, MakeTag(TAG_TITLE, "foo", TAG_ARTIST, "needle")));
47 	EXPECT_FALSE(InvokeFilter(f, MakeTag(TAG_TITLE, "FOOneedleBAR")));
48 }
49 
50 /**
51  * Test with empty string.  This matches tags where the given tag type
52  * does not exist.
53  */
TEST(TagSongFilter,Empty)54 TEST(TagSongFilter, Empty)
55 {
56 	const TagSongFilter f(TAG_TITLE,
57 			      StringFilter("", false, false, false));
58 
59 	EXPECT_TRUE(InvokeFilter(f, MakeTag()));
60 
61 	EXPECT_FALSE(InvokeFilter(f, MakeTag(TAG_TITLE, "foo")));
62 	EXPECT_FALSE(InvokeFilter(f, MakeTag(TAG_TITLE, "foo", TAG_TITLE, "bar")));
63 }
64 
TEST(TagSongFilter,Substring)65 TEST(TagSongFilter, Substring)
66 {
67 	const TagSongFilter f(TAG_TITLE,
68 			      StringFilter("needle", false, true, false));
69 
70 	EXPECT_TRUE(InvokeFilter(f, MakeTag(TAG_TITLE, "needle")));
71 	EXPECT_TRUE(InvokeFilter(f, MakeTag(TAG_TITLE, "needleBAR")));
72 	EXPECT_TRUE(InvokeFilter(f, MakeTag(TAG_TITLE, "FOOneedle")));
73 	EXPECT_TRUE(InvokeFilter(f, MakeTag(TAG_TITLE, "FOOneedleBAR")));
74 
75 	EXPECT_FALSE(InvokeFilter(f, MakeTag()));
76 	EXPECT_FALSE(InvokeFilter(f, MakeTag(TAG_TITLE, "eedle")));
77 }
78 
TEST(TagSongFilter,Negated)79 TEST(TagSongFilter, Negated)
80 {
81 	const TagSongFilter f(TAG_TITLE,
82 			      StringFilter("needle", false, false, true));
83 
84 	EXPECT_TRUE(InvokeFilter(f, MakeTag()));
85 	EXPECT_FALSE(InvokeFilter(f, MakeTag(TAG_TITLE, "needle")));
86 	EXPECT_TRUE(InvokeFilter(f, MakeTag(TAG_TITLE, "foo")));
87 }
88 
89 /**
90  * Combine the "Empty" and "Negated" tests.
91  */
TEST(TagSongFilter,EmptyNegated)92 TEST(TagSongFilter, EmptyNegated)
93 {
94 	const TagSongFilter f(TAG_TITLE,
95 			      StringFilter("", false, false, true));
96 
97 	EXPECT_FALSE(InvokeFilter(f, MakeTag()));
98 	EXPECT_TRUE(InvokeFilter(f, MakeTag(TAG_TITLE, "foo")));
99 }
100 
101 /**
102  * Negation with multiple tag values.
103  */
TEST(TagSongFilter,MultiNegated)104 TEST(TagSongFilter, MultiNegated)
105 {
106 	const TagSongFilter f(TAG_TITLE,
107 			      StringFilter("needle", false, false, true));
108 
109 	EXPECT_TRUE(InvokeFilter(f, MakeTag(TAG_TITLE, "foo", TAG_TITLE, "bar")));
110 	EXPECT_FALSE(InvokeFilter(f, MakeTag(TAG_TITLE, "needle", TAG_TITLE, "bar")));
111 	EXPECT_FALSE(InvokeFilter(f, MakeTag(TAG_TITLE, "foo", TAG_TITLE, "needle")));
112 }
113 
114 /**
115  * Check whether fallback tags work, e.g. AlbumArtist falls back to
116  * just Artist if there is no AlbumArtist.
117  */
TEST(TagSongFilter,Fallback)118 TEST(TagSongFilter, Fallback)
119 {
120 	const TagSongFilter f(TAG_ALBUM_ARTIST,
121 			      StringFilter("needle", false, false, false));
122 
123 	EXPECT_TRUE(InvokeFilter(f, MakeTag(TAG_ALBUM_ARTIST, "needle")));
124 	EXPECT_TRUE(InvokeFilter(f, MakeTag(TAG_ARTIST, "needle")));
125 
126 	EXPECT_FALSE(InvokeFilter(f, MakeTag()));
127 	EXPECT_FALSE(InvokeFilter(f, MakeTag(TAG_ALBUM_ARTIST, "foo")));
128 	EXPECT_FALSE(InvokeFilter(f, MakeTag(TAG_ARTIST, "foo")));
129 
130 	/* no fallback, thus the Artist tag isn't used and this must
131 	   be a mismatch */
132 	EXPECT_FALSE(InvokeFilter(f, MakeTag(TAG_ARTIST, "needle", TAG_ALBUM_ARTIST, "foo")));
133 }
134 
135 /**
136  * Combine the "Empty" and "Fallback" tests.
137  */
TEST(TagSongFilter,EmptyFallback)138 TEST(TagSongFilter, EmptyFallback)
139 {
140 	const TagSongFilter f(TAG_ALBUM_ARTIST,
141 			      StringFilter("", false, false, false));
142 
143 	EXPECT_TRUE(InvokeFilter(f, MakeTag()));
144 
145 	EXPECT_FALSE(InvokeFilter(f, MakeTag(TAG_ALBUM_ARTIST, "foo")));
146 	EXPECT_FALSE(InvokeFilter(f, MakeTag(TAG_ARTIST, "foo")));
147 }
148 
149 /**
150  * Combine the "Negated" and "Fallback" tests.
151  */
TEST(TagSongFilter,NegatedFallback)152 TEST(TagSongFilter, NegatedFallback)
153 {
154 	const TagSongFilter f(TAG_ALBUM_ARTIST,
155 			      StringFilter("needle", false, false, true));
156 
157 	EXPECT_TRUE(InvokeFilter(f, MakeTag()));
158 	EXPECT_TRUE(InvokeFilter(f, MakeTag(TAG_ALBUM_ARTIST, "foo")));
159 	EXPECT_FALSE(InvokeFilter(f, MakeTag(TAG_ALBUM_ARTIST, "needle")));
160 	EXPECT_TRUE(InvokeFilter(f, MakeTag(TAG_ARTIST, "foo")));
161 	EXPECT_FALSE(InvokeFilter(f, MakeTag(TAG_ARTIST, "needle")));
162 	EXPECT_TRUE(InvokeFilter(f, MakeTag(TAG_ARTIST, "needle", TAG_ALBUM_ARTIST, "foo")));
163 }
164