[XAudio2] avoid leak + fix voice creation for closest match
[xbmc.git] / xbmc / test / TestUtil.cpp
blob08cbca4d4ae71b9a56fb7bbfd84032e5058c86ea
1 /*
2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "Util.h"
11 #include <gtest/gtest.h>
13 using ::testing::Test;
14 using ::testing::ValuesIn;
15 using ::testing::WithParamInterface;
17 TEST(TestUtil, GetQualifiedFilename)
19 std::string file = "../foo";
20 CUtil::GetQualifiedFilename("smb://", file);
21 EXPECT_EQ(file, "foo");
22 file = "C:\\foo\\bar";
23 CUtil::GetQualifiedFilename("smb://", file);
24 EXPECT_EQ(file, "C:\\foo\\bar");
25 file = "../foo/./bar";
26 CUtil::GetQualifiedFilename("smb://my/path", file);
27 EXPECT_EQ(file, "smb://my/foo/bar");
28 file = "smb://foo/bar/";
29 CUtil::GetQualifiedFilename("upnp://", file);
30 EXPECT_EQ(file, "smb://foo/bar/");
33 TEST(TestUtil, MakeLegalPath)
35 std::string path;
36 #ifdef TARGET_WINDOWS
37 path = "C:\\foo\\bar";
38 EXPECT_EQ(CUtil::MakeLegalPath(path), "C:\\foo\\bar");
39 path = "C:\\foo:\\bar\\";
40 EXPECT_EQ(CUtil::MakeLegalPath(path), "C:\\foo_\\bar\\");
41 #else
42 path = "/foo/bar/";
43 EXPECT_EQ(CUtil::MakeLegalPath(path),"/foo/bar/");
44 path = "/foo?/bar";
45 EXPECT_EQ(CUtil::MakeLegalPath(path),"/foo_/bar");
46 #endif
47 path = "smb://foo/bar";
48 EXPECT_EQ(CUtil::MakeLegalPath(path), "smb://foo/bar");
49 path = "smb://foo/bar?/";
50 EXPECT_EQ(CUtil::MakeLegalPath(path), "smb://foo/bar_/");
53 TEST(TestUtil, MakeShortenPath)
55 std::string result;
56 EXPECT_EQ(true, CUtil::MakeShortenPath("smb://test/string/is/long/and/very/much/so", result, 10));
57 EXPECT_EQ("smb:/../so", result);
59 EXPECT_EQ(true, CUtil::MakeShortenPath("smb://test/string/is/long/and/very/much/so", result, 30));
60 EXPECT_EQ("smb://../../../../../../../so", result);
62 EXPECT_EQ(true, CUtil::MakeShortenPath("smb://test//string/is/long/and/very//much/so", result, 30));
63 EXPECT_EQ("smb:/../../../../../so", result);
65 EXPECT_EQ(true, CUtil::MakeShortenPath("//test//string/is/long/and/very//much/so", result, 30));
66 EXPECT_EQ("/../../../../../so", result);
69 TEST(TestUtil, ValidatePath)
71 std::string path;
72 #ifdef TARGET_WINDOWS
73 path = "C:/foo/bar/";
74 EXPECT_EQ(CUtil::ValidatePath(path), "C:\\foo\\bar\\");
75 path = "C:\\\\foo\\\\bar\\";
76 EXPECT_EQ(CUtil::ValidatePath(path, true), "C:\\foo\\bar\\");
77 path = "\\\\foo\\\\bar\\";
78 EXPECT_EQ(CUtil::ValidatePath(path, true), "\\\\foo\\bar\\");
79 #else
80 path = "\\foo\\bar\\";
81 EXPECT_EQ(CUtil::ValidatePath(path), "/foo/bar/");
82 path = "/foo//bar/";
83 EXPECT_EQ(CUtil::ValidatePath(path, true), "/foo/bar/");
84 #endif
85 path = "smb://foo/bar/";
86 EXPECT_EQ(CUtil::ValidatePath(path), "smb://foo/bar/");
87 path = "smb://foo//bar/";
88 EXPECT_EQ(CUtil::ValidatePath(path, true), "smb://foo/bar/");
89 path = "smb:\\\\foo\\\\bar\\";
90 EXPECT_EQ(CUtil::ValidatePath(path, true), "smb://foo/bar/");
93 struct TestUtilCleanStringData
95 std::string input;
96 bool first;
97 std::string expTitle;
98 std::string expTitleYear;
99 std::string expYear;
100 std::string expIdentifierType{};
101 std::string expIdentifier{};
104 std::ostream& operator<<(std::ostream& os, const TestUtilCleanStringData& rhs)
106 return os << "(input: " << rhs.input << "; first: " << (rhs.first ? "true" : "false")
107 << "; expTitle: " << rhs.expTitle << "; expTitleYear: " << rhs.expTitleYear
108 << "; expYear: " << rhs.expYear << ")";
111 class TestUtilCleanString : public Test, public WithParamInterface<TestUtilCleanStringData>
115 TEST_P(TestUtilCleanString, GetFilenameIdentifier)
117 std::string identifierType;
118 std::string identifier;
119 CUtil::GetFilenameIdentifier(GetParam().input, identifierType, identifier);
120 EXPECT_EQ(identifierType, GetParam().expIdentifierType);
121 EXPECT_EQ(identifier, GetParam().expIdentifier);
124 TEST_P(TestUtilCleanString, CleanString)
126 std::string title, titleYear, year;
127 CUtil::CleanString(GetParam().input, title, titleYear, year, true, GetParam().first);
128 EXPECT_EQ(title, GetParam().expTitle);
129 EXPECT_EQ(titleYear, GetParam().expTitleYear);
130 EXPECT_EQ(year, GetParam().expYear);
132 const TestUtilCleanStringData values[] = {
133 {"Some.BDRemux.mkv", true, "Some", "Some", ""},
134 {"SomeMovie.2018.UHD.BluRay.2160p.HEVC.TrueHD.Atmos.7.1-BeyondHD", true, "SomeMovie",
135 "SomeMovie (2018)", "2018"},
136 {"SOME_UHD_HDR10+_DV_2022_remux_dub atmos_soundmovie", true, "SOME", "SOME (2022)", "2022"},
137 // no result because of the . and spaces in movie name
138 {"Some Movie.Some Story.2013.BDRemux.1080p", true, "Some Movie.Some Story",
139 "Some Movie.Some Story (2013)", "2013"},
140 {"Movie.Some.Story.2017.2160p.BDRemux.IMAX.HDR.DV.IVA(ENG.RUS).ExKinoRay", true,
141 "Movie Some Story", "Movie Some Story (2017)", "2017"},
142 {"Some.Movie.1954.BDRip.1080p.mkv", true, "Some Movie", "Some Movie (1954)", "1954"},
143 {"Some «Movie».2021.WEB-DL.2160p.HDR.mkv", true, "Some «Movie»", "Some «Movie» (2021)", "2021"},
144 {"Some Movie (2013).mp4", true, "Some Movie", "Some Movie (2013)", "2013"},
145 {"Some Movie (2013) [imdbid-tt123].mp4", true, "Some Movie", "Some Movie (2013)", "2013",
146 "imdb", "tt123"},
147 {"Some Movie (2013) {tmdb-123}.mp4", true, "Some Movie", "Some Movie (2013)", "2013", "tmdb",
148 "123"},
149 {"Some Movie (2013) {tmdb=123}.mp4", true, "Some Movie", "Some Movie (2013)", "2013", "tmdb",
150 "123"},
151 // no result because of the text (Director Cut), it can also a be a movie translation
152 {"Some (Director Cut).BDRemux.mkv", true, "Some (Director Cut)", "Some (Director Cut)", ""}};
154 INSTANTIATE_TEST_SUITE_P(URL, TestUtilCleanString, ValuesIn(values));
156 struct TestUtilSplitParamsData
158 std::string input;
159 std::vector<std::string> expectedResult;
162 std::ostream& operator<<(std::ostream& os, const TestUtilSplitParamsData& rhs)
164 os << "(input: " << rhs.input << "; expCount: " << rhs.expectedResult.size();
165 for (unsigned int i = 0; i < rhs.expectedResult.size(); ++i)
166 os << "; expParam " << i + 1 << ": " << rhs.expectedResult[i];
168 return os;
171 class TestUtilSplitParams : public Test, public WithParamInterface<TestUtilSplitParamsData>
175 TEST_P(TestUtilSplitParams, SplitParams)
177 std::vector<std::string> actual;
178 CUtil::SplitParams(GetParam().input, actual);
179 EXPECT_EQ(actual.size(), GetParam().expectedResult.size());
180 EXPECT_EQ(actual, GetParam().expectedResult);
183 const TestUtilSplitParamsData valuesSplitParams[] = {
184 {"", {}},
185 {"one", {"one"}},
186 {" one", {"one"}},
187 {"one ", {"one"}},
188 {" one ", {"one"}},
189 // quotes " removed only when at beginning and end of param (after trimming)
190 {R"(" one")", {R"( one)"}},
191 {R"("one ")", {R"(one )"}},
192 {R"("on"e )", {R"("on"e)"}},
193 {R"(o"n"e )", {R"(o"n"e)"}},
194 {R"(o" n"e )", {R"(o" n"e)"}},
195 {R"( "one" )", {R"(one)"}},
196 {R"( " one")", {R"( one)"}},
197 {R"( " one " )", {R"( one )"}},
198 {R"(o" n"e )", {R"(o" n"e)"}},
199 {R"(o"ne" )", {R"(o"ne")"}},
200 {R"(o\"ne")", {R"(o"ne")"}},
201 {R"(\" one")", {R"( one)"}},
202 {R"(\" one\")", {R"( one)"}},
203 {R"("one " one)", {R"("one " one)"}},
204 // function 1 parameter
205 {"fun(p1)", {"fun(p1)"}},
206 {" fun(p1)", {"fun(p1)"}},
207 {"fun(p1) ", {"fun(p1)"}},
208 {"fun(p1 p1) ", {"fun(p1 p1)"}},
209 {"fun( p1 ) ", {"fun( p1 )"}}, // no trim: likely omission of the code?
210 // 2 parameters
211 {"one,", {"one", ""}},
212 {"one,two", {"one", "two"}},
213 {"one ,two", {"one", "two"}},
214 {"one,two ", {"one", "two"}},
215 {"one, two", {"one", "two"}},
216 {"one,two two", {"one", "two two"}},
217 {"one, two two", {"one", "two two"}},
218 {"one,two two ", {"one", "two two"}},
219 {R"(\" one\", two)", {R"( one)", "two"}},
220 //{R"(\" one", two)", {R"( one)", "two"}}, // mixing \" & " not supported for multi param
221 {R"(one, \" two\")", {"one", R"( two)"}},
222 //{R"(one, \" two")", {"one", R"( two)"}}, // mixing \" & " not supported for multi param
224 // function 2 parameters
225 {"fun(p1,p2)", {"fun(p1,p2)"}},
226 {"fun(p1 ,p2)", {"fun(p1 ,p2)"}}, // no trim: omission in the code?
227 {"fun(p1, p2)", {"fun(p1, p2)"}}, // no trim: omission in the code?
228 {"fun(p1 p1 ,p2)", {"fun(p1 p1 ,p2)"}}, // no trim: omission in the code?
229 {"fun(p1,p2), two", {"fun(p1,p2)", "two"}},
230 {"\"fun(p1,p2)\",two", {"fun(p1,p2)", "two"}},
231 {"\"fun(p1,p2)\",\" two\"", {"fun(p1,p2)", " two"}},
232 {"fun(p1,p2),\" two\"", {"fun(p1,p2)", " two"}},
233 {"\\\"fun(p1,p2)\\\",two", {"fun(p1,p2)", "two"}},
234 {"fun(p1,p2),\\\"two\\\"", {"fun(p1,p2)", "two"}},
235 {"fun(fun2(p1,p2),p3),two", {"fun(fun2(p1,p2),p3)", "two"}},
236 {"fun\"ction(p1,p2\",p3,p4)\"", {"fun\"ction(p1,p2\"", "p3", "p4)\""}},
237 // 3 parameters
238 {"one,two,three", {"one", "two", "three"}},
239 {"one,two two,three", {"one", "two two", "three"}},
240 {"one, two, three", {"one", "two", "three"}},
241 {"one, two two, three", {"one", "two two", "three"}},
242 // \ escaping
243 {R"(D:\foo\bar\baz.m2ts)", {R"(D:\foo\bar\baz.m2ts)"}},
244 {R"(D:\foo\bar\)", {R"(D:\foo\bar\)"}},
245 {R"(D:\\foo\bar\)", {R"(D:\foo\bar\)"}},
246 {R"(D:\foo\\bar\)", {R"(D:\foo\bar\)"}},
247 {R"(D:\foo\bar\\)", {R"(D:\foo\bar\)"}},
248 {R"(D:\\\foo\bar\)", {R"(D:\\foo\bar\)"}},
249 {R"(D:\foo\\\bar\)", {R"(D:\foo\\bar\)"}},
250 {R"(D:\foo\bar\\\)", {R"(D:\foo\bar\\)"}},
251 {R"(D:\\\\foo\bar\)", {R"(D:\\foo\bar\)"}},
252 {R"(D:\foo\\\\bar\)", {R"(D:\foo\\bar\)"}},
253 {R"(D:\foo\bar\\\\)", {R"(D:\foo\bar\\)"}},
254 {R"("D:\foo\\bar\\\baz.m2ts\\\\")", {R"(D:\foo\bar\\baz.m2ts\\)"}},
255 {R"(" D:\foo\\bar\\\baz.m2ts\\\\")", {R"( D:\foo\bar\\baz.m2ts\\)"}},
256 {R"(\"D:\foo\\bar\\\baz.m2ts\\\\\")", {R"(D:\foo\bar\\baz.m2ts\\)"}},
257 {R"(\" D:\foo\\bar\\\baz.m2ts\\\\\")", {R"( D:\foo\bar\\baz.m2ts\\)"}},
258 {R"(123,D:\foo\\bar\\\baz.m2ts\\\\,abc)", {"123", R"(D:\foo\bar\\baz.m2ts\\)", "abc"}},
259 {R"(123,"D:\foo\\bar\\\baz.m2ts\\\\",abc)", {"123", R"(D:\foo\bar\\baz.m2ts\\)", "abc"}},
260 {R"(123," D:\foo\\bar\\\baz.m2ts\\\\",abc)", {"123", R"( D:\foo\bar\\baz.m2ts\\)", "abc"}},
261 {R"(123,\"D:\foo\\bar\\\baz.m2ts\\\\\",abc)", {"123", R"(D:\foo\bar\\baz.m2ts\\)", "abc"}},
262 {R"(123,\" D:\foo\\bar\\\baz.m2ts\\\\\",abc)", {"123", R"( D:\foo\bar\\baz.m2ts\\)", "abc"}},
263 // name="value" parameter form
264 {R"(name="value")", {"name=value"}},
265 {R"(name="value1 value2")", {"name=value1 value2"}},
266 {R"(name="value1,value2")", {"name=value1,value2"}},
267 {R"(name="value1, value2")", {"name=value1, value2"}},
268 {R"(name="value1 "value2 " value3")", {R"(name=value1 "value2 " value3)"}},
269 {R"(name="value1 \"value2 \" value 3")", {R"(name=value1 "value2 " value 3)"}},
270 {R"(name=\"value\")", {R"(name=value)"}},
271 {R"("name=\"value\"")", {R"(name="value")"}},
272 {R"(name=value1,value2)", {"name=value1", "value2"}},
273 {R"(foo=bar=value1,value2)", {"foo=bar=value1", "value2"}},
274 {R"(foo=bar="value1,value2")", {"foo=bar=value1,value2"}},
275 {R"("name=value1 value2")", {"name=value1 value2"}},
276 {R"(abc, name="value", cde)", {"abc", "name=value", "cde"}},
279 INSTANTIATE_TEST_SUITE_P(SP, TestUtilSplitParams, ValuesIn(valuesSplitParams));