1 // Copyright 2014 The Kyua Authors. 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are 6 // met: 7 // 8 // * Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // * Redistributions in binary form must reproduce the above copyright 11 // notice, this list of conditions and the following disclaimer in the 12 // documentation and/or other materials provided with the distribution. 13 // * Neither the name of Google Inc. nor the names of its contributors 14 // may be used to endorse or promote products derived from this software 15 // without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29 #include "store/layout.hpp" 30 31 extern "C" { 32 #include <unistd.h> 33 } 34 35 #include <iostream> 36 37 #include <atf-c++.hpp> 38 39 #include "store/exceptions.hpp" 40 #include "store/layout.hpp" 41 #include "utils/datetime.hpp" 42 #include "utils/env.hpp" 43 #include "utils/fs/operations.hpp" 44 #include "utils/fs/path.hpp" 45 46 namespace datetime = utils::datetime; 47 namespace fs = utils::fs; 48 namespace layout = store::layout; 49 50 51 ATF_TEST_CASE_WITHOUT_HEAD(find_results__latest); 52 ATF_TEST_CASE_BODY(find_results__latest) 53 { 54 const fs::path store_dir = layout::query_store_dir(); 55 fs::mkdir_p(store_dir, 0755); 56 57 const std::string test_suite = layout::test_suite_for_path( 58 fs::current_path()); 59 const std::string base = (store_dir / ( 60 "results." + test_suite + ".")).str(); 61 62 atf::utils::create_file(base + "20140613-194515-000000.db", ""); 63 ATF_REQUIRE_EQ(base + "20140613-194515-000000.db", 64 layout::find_results("LATEST").str()); 65 66 atf::utils::create_file(base + "20140614-194515-123456.db", ""); 67 ATF_REQUIRE_EQ(base + "20140614-194515-123456.db", 68 layout::find_results("LATEST").str()); 69 70 atf::utils::create_file(base + "20130614-194515-999999.db", ""); 71 ATF_REQUIRE_EQ(base + "20140614-194515-123456.db", 72 layout::find_results("LATEST").str()); 73 } 74 75 76 ATF_TEST_CASE_WITHOUT_HEAD(find_results__directory); 77 ATF_TEST_CASE_BODY(find_results__directory) 78 { 79 const fs::path store_dir = layout::query_store_dir(); 80 fs::mkdir_p(store_dir, 0755); 81 82 const fs::path dir1("dir1/foo"); 83 fs::mkdir_p(dir1, 0755); 84 const fs::path dir2("dir1/bar"); 85 fs::mkdir_p(dir2, 0755); 86 87 const std::string base1 = (store_dir / ( 88 "results." + layout::test_suite_for_path(dir1) + ".")).str(); 89 const std::string base2 = (store_dir / ( 90 "results." + layout::test_suite_for_path(dir2) + ".")).str(); 91 92 atf::utils::create_file(base1 + "20140613-194515-000000.db", ""); 93 ATF_REQUIRE_EQ(base1 + "20140613-194515-000000.db", 94 layout::find_results(dir1.str()).str()); 95 96 atf::utils::create_file(base2 + "20140615-111111-000000.db", ""); 97 ATF_REQUIRE_EQ(base2 + "20140615-111111-000000.db", 98 layout::find_results(dir2.str()).str()); 99 100 atf::utils::create_file(base1 + "20140614-194515-123456.db", ""); 101 ATF_REQUIRE_EQ(base1 + "20140614-194515-123456.db", 102 layout::find_results(dir1.str()).str()); 103 104 atf::utils::create_file(base1 + "20130614-194515-999999.db", ""); 105 ATF_REQUIRE_EQ(base1 + "20140614-194515-123456.db", 106 layout::find_results(dir1.str()).str()); 107 } 108 109 110 ATF_TEST_CASE_WITHOUT_HEAD(find_results__file); 111 ATF_TEST_CASE_BODY(find_results__file) 112 { 113 const fs::path store_dir = layout::query_store_dir(); 114 fs::mkdir_p(store_dir, 0755); 115 116 atf::utils::create_file("a-file.db", ""); 117 ATF_REQUIRE_EQ(fs::path("a-file.db").to_absolute(), 118 layout::find_results("a-file.db")); 119 } 120 121 122 ATF_TEST_CASE_WITHOUT_HEAD(find_results__id); 123 ATF_TEST_CASE_BODY(find_results__id) 124 { 125 const fs::path store_dir = layout::query_store_dir(); 126 fs::mkdir_p(store_dir, 0755); 127 128 const fs::path dir1("dir1/foo"); 129 fs::mkdir_p(dir1, 0755); 130 const fs::path dir2("dir1/bar"); 131 fs::mkdir_p(dir2, 0755); 132 133 const std::string id1 = layout::test_suite_for_path(dir1); 134 const std::string base1 = (store_dir / ("results." + id1 + ".")).str(); 135 const std::string id2 = layout::test_suite_for_path(dir2); 136 const std::string base2 = (store_dir / ("results." + id2 + ".")).str(); 137 138 atf::utils::create_file(base1 + "20140613-194515-000000.db", ""); 139 ATF_REQUIRE_EQ(base1 + "20140613-194515-000000.db", 140 layout::find_results(id1).str()); 141 142 atf::utils::create_file(base2 + "20140615-111111-000000.db", ""); 143 ATF_REQUIRE_EQ(base2 + "20140615-111111-000000.db", 144 layout::find_results(id2).str()); 145 146 atf::utils::create_file(base1 + "20140614-194515-123456.db", ""); 147 ATF_REQUIRE_EQ(base1 + "20140614-194515-123456.db", 148 layout::find_results(id1).str()); 149 150 atf::utils::create_file(base1 + "20130614-194515-999999.db", ""); 151 ATF_REQUIRE_EQ(base1 + "20140614-194515-123456.db", 152 layout::find_results(id1).str()); 153 } 154 155 156 ATF_TEST_CASE_WITHOUT_HEAD(find_results__id_with_timestamp); 157 ATF_TEST_CASE_BODY(find_results__id_with_timestamp) 158 { 159 const fs::path store_dir = layout::query_store_dir(); 160 fs::mkdir_p(store_dir, 0755); 161 162 const fs::path dir1("dir1/foo"); 163 fs::mkdir_p(dir1, 0755); 164 const fs::path dir2("dir1/bar"); 165 fs::mkdir_p(dir2, 0755); 166 167 const std::string id1 = layout::test_suite_for_path(dir1); 168 const std::string base1 = (store_dir / ("results." + id1 + ".")).str(); 169 const std::string id2 = layout::test_suite_for_path(dir2); 170 const std::string base2 = (store_dir / ("results." + id2 + ".")).str(); 171 172 atf::utils::create_file(base1 + "20140613-194515-000000.db", ""); 173 atf::utils::create_file(base2 + "20140615-111111-000000.db", ""); 174 atf::utils::create_file(base1 + "20140614-194515-123456.db", ""); 175 atf::utils::create_file(base1 + "20130614-194515-999999.db", ""); 176 177 ATF_REQUIRE_MATCH( 178 "_dir1_foo.20140613-194515-000000.db$", 179 layout::find_results(id1 + ".20140613-194515-000000").str()); 180 181 ATF_REQUIRE_MATCH( 182 "_dir1_foo.20140614-194515-123456.db$", 183 layout::find_results(id1 + ".20140614-194515-123456").str()); 184 185 ATF_REQUIRE_MATCH( 186 "_dir1_bar.20140615-111111-000000.db$", 187 layout::find_results(id2 + ".20140615-111111-000000").str()); 188 } 189 190 191 ATF_TEST_CASE_WITHOUT_HEAD(find_results__not_found); 192 ATF_TEST_CASE_BODY(find_results__not_found) 193 { 194 ATF_REQUIRE_THROW_RE( 195 store::error, 196 "No previous results file found for test suite foo_bar", 197 layout::find_results("foo_bar")); 198 199 const fs::path store_dir = layout::query_store_dir(); 200 fs::mkdir_p(store_dir, 0755); 201 ATF_REQUIRE_THROW_RE( 202 store::error, 203 "No previous results file found for test suite foo_bar", 204 layout::find_results("foo_bar")); 205 206 const char* candidates[] = { 207 "results.foo.20140613-194515-012345.db", // Bad test suite. 208 "results.foo_bar.20140613-194515-012345", // Missing extension. 209 "foo_bar.20140613-194515-012345.db", // Missing prefix. 210 "results.foo_bar.2010613-194515-012345.db", // Bad date. 211 "results.foo_bar.20140613-19515-012345.db", // Bad time. 212 "results.foo_bar.20140613-194515-01245.db", // Bad microseconds. 213 NULL, 214 }; 215 for (const char** candidate = candidates; *candidate != NULL; ++candidate) { 216 std::cout << "Current candidate: " << *candidate << '\n'; 217 atf::utils::create_file((store_dir / *candidate).str(), ""); 218 ATF_REQUIRE_THROW_RE( 219 store::error, 220 "No previous results file found for test suite foo_bar", 221 layout::find_results("foo_bar")); 222 } 223 224 atf::utils::create_file( 225 (store_dir / "results.foo_bar.20140613-194515-012345.db").str(), ""); 226 layout::find_results("foo_bar"); // Expected not to throw. 227 } 228 229 230 ATF_TEST_CASE_WITHOUT_HEAD(new_db__new); 231 ATF_TEST_CASE_BODY(new_db__new) 232 { 233 datetime::set_mock_now(2014, 6, 13, 19, 45, 15, 5000); 234 ATF_REQUIRE(!fs::exists(fs::path(".kyua/store"))); 235 const layout::results_id_file_pair results = layout::new_db( 236 "NEW", fs::path("/some/path/to/the/suite")); 237 ATF_REQUIRE( fs::exists(fs::path(".kyua/store"))); 238 ATF_REQUIRE( fs::is_directory(fs::path(".kyua/store"))); 239 240 const std::string id = "some_path_to_the_suite.20140613-194515-005000"; 241 ATF_REQUIRE_EQ(id, results.first); 242 ATF_REQUIRE_EQ(layout::query_store_dir() / ("results." + id + ".db"), 243 results.second); 244 } 245 246 247 ATF_TEST_CASE_WITHOUT_HEAD(new_db__explicit); 248 ATF_TEST_CASE_BODY(new_db__explicit) 249 { 250 ATF_REQUIRE(!fs::exists(fs::path(".kyua/store"))); 251 const layout::results_id_file_pair results = layout::new_db( 252 "foo/results-file.db", fs::path("unused")); 253 ATF_REQUIRE(!fs::exists(fs::path(".kyua/store"))); 254 ATF_REQUIRE(!fs::exists(fs::path("foo"))); 255 256 ATF_REQUIRE(results.first.empty()); 257 ATF_REQUIRE_EQ(fs::path("foo/results-file.db"), results.second); 258 } 259 260 261 ATF_TEST_CASE_WITHOUT_HEAD(new_db_for_migration); 262 ATF_TEST_CASE_BODY(new_db_for_migration) 263 { 264 ATF_REQUIRE(!fs::exists(fs::path(".kyua/store"))); 265 const fs::path results_file = layout::new_db_for_migration( 266 fs::path("/some/root"), 267 datetime::timestamp::from_values(2014, 7, 30, 10, 5, 20, 76500)); 268 ATF_REQUIRE( fs::exists(fs::path(".kyua/store"))); 269 ATF_REQUIRE( fs::is_directory(fs::path(".kyua/store"))); 270 271 ATF_REQUIRE_EQ( 272 layout::query_store_dir() / 273 "results.some_root.20140730-100520-076500.db", 274 results_file); 275 } 276 277 278 ATF_TEST_CASE_WITHOUT_HEAD(query_store_dir__home_absolute); 279 ATF_TEST_CASE_BODY(query_store_dir__home_absolute) 280 { 281 const fs::path home = fs::current_path() / "homedir"; 282 utils::setenv("HOME", home.str()); 283 const fs::path store_dir = layout::query_store_dir(); 284 ATF_REQUIRE(store_dir.is_absolute()); 285 ATF_REQUIRE_EQ(home / ".kyua/store", store_dir); 286 } 287 288 289 ATF_TEST_CASE_WITHOUT_HEAD(query_store_dir__home_relative); 290 ATF_TEST_CASE_BODY(query_store_dir__home_relative) 291 { 292 const fs::path home("homedir"); 293 utils::setenv("HOME", home.str()); 294 const fs::path store_dir = layout::query_store_dir(); 295 ATF_REQUIRE(store_dir.is_absolute()); 296 ATF_REQUIRE_MATCH((home / ".kyua/store").str(), store_dir.str()); 297 } 298 299 300 ATF_TEST_CASE_WITHOUT_HEAD(query_store_dir__no_home); 301 ATF_TEST_CASE_BODY(query_store_dir__no_home) 302 { 303 utils::unsetenv("HOME"); 304 ATF_REQUIRE_EQ(fs::current_path(), layout::query_store_dir()); 305 } 306 307 308 ATF_TEST_CASE_WITHOUT_HEAD(test_suite_for_path__absolute); 309 ATF_TEST_CASE_BODY(test_suite_for_path__absolute) 310 { 311 ATF_REQUIRE_EQ("dir1_dir2_dir3", 312 layout::test_suite_for_path(fs::path("/dir1/dir2/dir3"))); 313 ATF_REQUIRE_EQ("dir1", 314 layout::test_suite_for_path(fs::path("/dir1"))); 315 ATF_REQUIRE_EQ("dir1_dir2", 316 layout::test_suite_for_path(fs::path("/dir1///dir2"))); 317 } 318 319 320 ATF_TEST_CASE_WITHOUT_HEAD(test_suite_for_path__relative); 321 ATF_TEST_CASE_BODY(test_suite_for_path__relative) 322 { 323 const std::string test_suite = layout::test_suite_for_path( 324 fs::path("foo/bar")); 325 ATF_REQUIRE_MATCH("_foo_bar$", test_suite); 326 ATF_REQUIRE_MATCH("^[^_]", test_suite); 327 } 328 329 330 ATF_INIT_TEST_CASES(tcs) 331 { 332 ATF_ADD_TEST_CASE(tcs, find_results__latest); 333 ATF_ADD_TEST_CASE(tcs, find_results__directory); 334 ATF_ADD_TEST_CASE(tcs, find_results__file); 335 ATF_ADD_TEST_CASE(tcs, find_results__id); 336 ATF_ADD_TEST_CASE(tcs, find_results__id_with_timestamp); 337 ATF_ADD_TEST_CASE(tcs, find_results__not_found); 338 339 ATF_ADD_TEST_CASE(tcs, new_db__new); 340 ATF_ADD_TEST_CASE(tcs, new_db__explicit); 341 342 ATF_ADD_TEST_CASE(tcs, new_db_for_migration); 343 344 ATF_ADD_TEST_CASE(tcs, query_store_dir__home_absolute); 345 ATF_ADD_TEST_CASE(tcs, query_store_dir__home_relative); 346 ATF_ADD_TEST_CASE(tcs, query_store_dir__no_home); 347 348 ATF_ADD_TEST_CASE(tcs, test_suite_for_path__absolute); 349 ATF_ADD_TEST_CASE(tcs, test_suite_for_path__relative); 350 } 351