1 /*
2 Copyright (c) 2019, 2020, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 /**
26 * Test the mysqlrouter_keyring tool.
27 */
28 #include "keyring_frontend.h"
29
30 #include <array>
31 #include <bitset>
32 #include <fstream>
33 #include <iostream>
34 #include <numeric>
35 #include <sstream>
36 #include <string>
37 #include <tuple>
38 #include <vector>
39
40 #include <gmock/gmock.h>
41
42 #include "dim.h"
43 #include "mysql/harness/filesystem.h"
44 #include "mysql/harness/loader_config.h"
45 #include "mysql/harness/logging/registry.h"
46 #include "mysql/harness/string_utils.h" // mysql_harness::split_string
47 #include "mysql/harness/utility/string.h" // mysql_harness::join
48 #include "mysqlrouter/utils.h"
49 #include "print_version.h" // build_version
50 #include "welcome_copyright_notice.h" // ORACLE_WELCOME_COPYRIGHT_NOTICE
51
52 constexpr const char kAppExeFileName[]{"mysqlrouter_keyring"};
53
54 using namespace std::string_literals;
55 using mysql_harness::join;
56
57 mysql_harness::Path g_origin_path;
58
59 constexpr size_t kOptIndent = 2;
60 constexpr size_t kDescIndent = 6;
61
ParamPrinter(const std::vector<std::pair<std::string,std::string>> & fields,std::ostream * os)62 static void ParamPrinter(
63 const std::vector<std::pair<std::string, std::string>> &fields,
64 std::ostream *os) {
65 *os << "(";
66 bool is_first{true};
67 for (const auto &kv : fields) {
68 if (is_first) {
69 is_first = false;
70 } else {
71 *os << ", ";
72 }
73 *os << kv.first << ": " << kv.second;
74 }
75 *os << ")";
76 }
77
78 struct Option {
79 std::vector<std::string> opts;
80 std::string arg;
81 std::string desc;
82 };
83
84 std::vector<Option> cmdline_opts{
85 // should be alphabetically ordered
86 {{"-?", "--help"}, "", "Display this help and exit."},
87 {{"-V", "--version"}, "", "Display version information and exit."},
88 {{"--master-key-file"}, "<VALUE>", "Filename of the master keyfile."},
89 {{"--master-key-reader"},
90 "<VALUE>",
91 "Executable which provides the master key for the keyfile."},
92 {{"--master-key-writer"},
93 "<VALUE>",
94 "Executable which can store the master key for the keyfile."},
95 };
96
97 std::vector<std::pair<std::string, std::string>> cmdline_cmds{
98 {"init", "initialize a keyring."},
99 {"set", "add or overwrite account of <username> in <filename>."},
100 {"delete", "delete entry from keyring."},
101 {"list", "list all entries in keyring."},
102 {"export", "export all entries of keyring as JSON."},
103 {"get", "field from keyring entry"},
104 {"master-delete", "keyring from master-keyfile"},
105 {"master-list", "list entries from master-keyfile"},
106 {"master-rename", "renames and entry in a master-keyfile"},
107 };
108
109 // build param of description
format_desc_opt(const Option & opt)110 static std::string format_desc_opt(const Option &opt) {
111 auto val = opt.arg;
112 return join(std::accumulate(
113 opt.opts.begin(), opt.opts.end(), std::vector<std::string>(),
114 [&val](std::vector<std::string> &acc, std::string cur) {
115 acc.push_back(cur + (val.empty() ? "" : " " + val));
116
117 return acc;
118 }),
119 ", ");
120 }
121
122 // build help-text from options
help_builder(const std::vector<Option> & opts)123 static std::string help_builder(const std::vector<Option> &opts) {
124 std::vector<std::string> out;
125
126 {
127 out.push_back("Usage");
128 out.push_back("");
129
130 // opts
131 std::vector<std::string> formatted_options;
132 formatted_options.push_back(kAppExeFileName);
133 formatted_options.push_back("[opts]");
134 formatted_options.push_back("<cmd>");
135 formatted_options.push_back("<filename>");
136 formatted_options.push_back("[<username>]");
137
138 std::string line{" "};
139 for (const auto &opt : formatted_options) {
140 if (line.size() + 1 + opt.size() > 93) {
141 out.push_back(line);
142
143 // prepare next line
144 line = " ";
145 }
146 line += " " + opt;
147 }
148
149 out.push_back(line);
150
151 // --help
152 formatted_options.clear();
153 formatted_options.push_back(kAppExeFileName);
154 formatted_options.push_back("--help");
155
156 line = " ";
157 for (const auto &opt : formatted_options) {
158 if (line.size() + 1 + opt.size() > 93) {
159 out.push_back(line);
160
161 // prepare next line
162 line = " ";
163 }
164 line += " " + opt;
165 }
166
167 out.push_back(line);
168
169 // --version
170 formatted_options.clear();
171 formatted_options.push_back(kAppExeFileName);
172 formatted_options.push_back("--version");
173
174 line = " ";
175 for (const auto &opt : formatted_options) {
176 if (line.size() + 1 + opt.size() > 93) {
177 out.push_back(line);
178
179 // prepare next line
180 line = " ";
181 }
182 line += " " + opt;
183 }
184
185 out.push_back(line);
186 }
187
188 if (!cmdline_cmds.empty()) {
189 out.push_back("");
190 out.push_back("Commands");
191 out.push_back("");
192 for (const auto &opt : cmdline_cmds) {
193 out.push_back(std::string(kOptIndent, ' ') + opt.first);
194 out.push_back(std::string(kDescIndent, ' ') + opt.second);
195 }
196 }
197
198 if (!opts.empty()) {
199 out.push_back("");
200 out.push_back("Options");
201 out.push_back("");
202
203 for (const auto &opt : opts) {
204 out.push_back(std::string(kOptIndent, ' ') + format_desc_opt(opt));
205 out.push_back(std::string(kDescIndent, ' ') + opt.desc);
206 }
207 }
208
209 // enforce a newline at the end
210 out.push_back("");
211 return join(out, "\n");
212 }
213
version_builder()214 static std::string version_builder() {
215 std::string version_string;
216 build_version(MYSQL_ROUTER_PACKAGE_NAME, &version_string);
217
218 std::stringstream os;
219 os << version_string << std::endl
220 << ORACLE_WELCOME_COPYRIGHT_NOTICE("2019") << std::endl;
221
222 return os.str();
223 }
224
225 const std::string kHelpText(help_builder(cmdline_opts));
226 const std::string kVersionText(version_builder());
227
228 // placehoder in the opts to replace by the temp-filename
229 const std::string kKeyringPlaceholder("@keyringfile@");
230 const std::string kMasterKeyfilePlaceholder("@masterkeyringfile@");
231 const std::string kMasterKeyWriterPlaceholder("@masterkeywriter@");
232 const std::string kMasterKeyReaderPlaceholder("@masterkeyreader@");
233
234 const std::string kMasterKeyReaderSucceeding(
235 #ifndef _WIN32
236 "#!/bin/sh\n"
237 "echo foobar\n"
238 "exit 0"
239 #else
240 "@echo off\n"
241 "echo foobar\n"
242 "exit 0"
243 #endif
244 );
245
246 const std::string kMasterKeyReaderKeyNotFound(
247 #ifndef _WIN32
248 "#!/bin/sh\n"
249 "exit 0"
250 #else
251 "@echo off\n"
252 "exit 0"
253 #endif
254 );
255
256 const std::string kMasterKeyReaderFailing(
257 #ifndef _WIN32
258 "#!/bin/sh\n"
259 "exit -1"
260 #else
261 "@echo off\n"
262 "exit 1"
263 #endif
264 );
265
266 const std::string kMasterKeyWriterSucceeding(
267 #ifndef _WIN32
268 "#!/bin/sh\n"
269 "exit 0"
270 #else
271 "@echo off\n"
272 "exit 0"
273 #endif
274 );
275 const std::string kMasterKeyWriterFailing(
276 #ifndef _WIN32
277 "#!/bin/sh\n"
278 "exit -1"
279 #else
280 "@echo off\n"
281 "exit 1"
282 #endif
283 );
284
285 // count how many bits are required to represent 'max_value'
max_bits(size_t max_value)286 constexpr size_t max_bits(size_t max_value) {
287 size_t used_bits{0};
288 while (max_value) {
289 used_bits++;
290 max_value >>= 1;
291 }
292
293 return used_bits;
294 }
295
296 static_assert(max_bits(0) == 0, "");
297 static_assert(max_bits(1) == 1, "");
298 static_assert(max_bits(2) == 2, "");
299 static_assert(max_bits(3) == 2, "");
300 static_assert(max_bits(4) == 3, "");
301 static_assert(max_bits(7) == 3, "");
302 static_assert(max_bits(8) == 4, "");
303
304 template <class T, class Values, class Prev, size_t max_value>
305 class ChainedBitset {
306 public:
307 using prev = Prev;
308 using bitset_type = uint64_t;
309 using value_type = Values;
310
from_bitset(uint64_t v)311 static constexpr value_type from_bitset(uint64_t v) {
312 return static_cast<value_type>((v & bit_mask) >> bit_shift);
313 }
314
to_bitset(value_type v)315 static constexpr bitset_type to_bitset(value_type v) {
316 if (static_cast<bitset_type>(v) > max_value)
317 throw std::out_of_range("value is larger than announced max_value");
318 auto r = static_cast<bitset_type>(v) << bit_shift;
319
320 return r;
321 }
322
323 static constexpr size_t bit_shift{prev::bit_shift + prev::bit_mask_width};
324 static constexpr size_t bit_mask_width{max_bits(max_value)};
325 static constexpr uint64_t bit_mask{((1 << bit_mask_width) - 1) << bit_shift};
326 };
327
328 struct StartingPoint {
329 static constexpr size_t bit_shift{0};
330 static constexpr size_t bit_mask_width{0};
331 };
332
333 namespace PreCond {
334 enum class KeyringValues {
335 none,
336 empty,
337 minimal,
338 one_user_one_property,
339 many_user_one_property,
340 long_property,
341 long_username,
342 special_properties,
343 no_entries,
344 one_entry,
345 inited,
346 };
347
348 struct Keyring
349 : public ChainedBitset<Keyring, KeyringValues, StartingPoint,
350 static_cast<uint64_t>(KeyringValues::inited)> {
351 using Values = KeyringValues;
nonePreCond::Keyring352 static constexpr uint64_t none() { return to_bitset(Values::none); }
emptyPreCond::Keyring353 static constexpr uint64_t empty() { return to_bitset(Values::empty); }
minimalPreCond::Keyring354 static constexpr uint64_t minimal() { return to_bitset(Values::minimal); }
one_user_one_propertyPreCond::Keyring355 static constexpr uint64_t one_user_one_property() {
356 return to_bitset(Values::one_user_one_property);
357 }
many_user_one_propertyPreCond::Keyring358 static constexpr uint64_t many_user_one_property() {
359 return to_bitset(Values::many_user_one_property);
360 }
long_propertyPreCond::Keyring361 static constexpr uint64_t long_property() {
362 return to_bitset(Values::long_property);
363 }
long_usernamePreCond::Keyring364 static constexpr uint64_t long_username() {
365 return to_bitset(Values::long_username);
366 }
special_propertiesPreCond::Keyring367 static constexpr uint64_t special_properties() {
368 return to_bitset(Values::special_properties);
369 }
no_entriesPreCond::Keyring370 static constexpr uint64_t no_entries() {
371 return to_bitset(Values::no_entries);
372 }
one_entryPreCond::Keyring373 static constexpr uint64_t one_entry() { return to_bitset(Values::one_entry); }
initedPreCond::Keyring374 static constexpr uint64_t inited() { return to_bitset(Values::inited); }
375 };
376
377 enum class KeyringFilenameValues {
378 none, // just tmpdir/keyring
379 special_chars, // tmpdir/key ring
380 with_directory, // make filename with subdir, create subdir
381 with_no_exist_directory, // make filename with subdir, but don't create
382 // subdir
383 absolute, // make filename absolute
384 };
385
386 struct KeyringFilename
387 : public ChainedBitset<KeyringFilename, KeyringFilenameValues, Keyring,
388 static_cast<uint64_t>(
389 KeyringFilenameValues::absolute)> {
390 using Values = KeyringFilenameValues;
nonePreCond::KeyringFilename391 static constexpr uint64_t none() { return to_bitset(Values::none); }
special_charsPreCond::KeyringFilename392 static constexpr uint64_t special_chars() {
393 return to_bitset(Values::special_chars);
394 }
with_directoryPreCond::KeyringFilename395 static constexpr uint64_t with_directory() {
396 return to_bitset(Values::with_directory);
397 }
with_no_exist_directoryPreCond::KeyringFilename398 static constexpr uint64_t with_no_exist_directory() {
399 return to_bitset(Values::with_no_exist_directory);
400 }
absolutePreCond::KeyringFilename401 static constexpr uint64_t absolute() { return to_bitset(Values::absolute); }
402 };
403
404 enum class MasterKeyfileValues {
405 none,
406 empty,
407 minimal,
408 valid_one_entry, // one entry, foo.key
409 valid_foo_bar_baz, // three entries: foo.key, bar.key, and baz.key
410 insecure,
411 };
412
413 struct MasterKeyfile
414 : public ChainedBitset<MasterKeyfile, MasterKeyfileValues, KeyringFilename,
415 static_cast<uint64_t>(
416 MasterKeyfileValues::insecure)> {
417 using Values = MasterKeyfileValues;
418
nonePreCond::MasterKeyfile419 static constexpr uint64_t none() { return to_bitset(Values::none); }
emptyPreCond::MasterKeyfile420 static constexpr uint64_t empty() { return to_bitset(Values::empty); }
minimalPreCond::MasterKeyfile421 static constexpr uint64_t minimal() { return to_bitset(Values::minimal); }
valid_one_entryPreCond::MasterKeyfile422 static constexpr uint64_t valid_one_entry() {
423 return to_bitset(Values::valid_one_entry);
424 }
valid_foo_bar_bazPreCond::MasterKeyfile425 static constexpr uint64_t valid_foo_bar_baz() {
426 return to_bitset(Values::valid_foo_bar_baz);
427 }
insecurePreCond::MasterKeyfile428 static constexpr uint64_t insecure() { return to_bitset(Values::insecure); }
429 };
430
431 enum class MasterKeyfileFilenameValues {
432 none,
433 special_chars,
434 with_directory,
435 with_no_exist_directory,
436 };
437
438 struct MasterKeyfileFilename
439 : public ChainedBitset<
440 MasterKeyfileFilename, MasterKeyfileFilenameValues, MasterKeyfile,
441 static_cast<uint64_t>(
442 MasterKeyfileFilenameValues::with_no_exist_directory)> {
443 using Values = MasterKeyfileFilenameValues;
nonePreCond::MasterKeyfileFilename444 static constexpr uint64_t none() { return to_bitset(Values::none); }
special_charsPreCond::MasterKeyfileFilename445 static constexpr uint64_t special_chars() {
446 return to_bitset(Values::special_chars);
447 }
with_directoryPreCond::MasterKeyfileFilename448 static constexpr uint64_t with_directory() {
449 return to_bitset(Values::with_directory);
450 }
with_no_exist_directoryPreCond::MasterKeyfileFilename451 static constexpr uint64_t with_no_exist_directory() {
452 return to_bitset(Values::with_no_exist_directory);
453 }
454 };
455
456 enum class MasterKeyReaderValues {
457 none,
458 succeeding,
459 failing,
460 not_executable,
461 key_not_found,
462 };
463
464 struct MasterKeyReader
465 : public ChainedBitset<
466 MasterKeyReader, MasterKeyReaderValues, MasterKeyfileFilename,
467 static_cast<uint64_t>(MasterKeyReaderValues::key_not_found)> {
468 using Values = MasterKeyReaderValues;
469
nonePreCond::MasterKeyReader470 static constexpr uint64_t none() { return to_bitset(Values::none); }
succeedingPreCond::MasterKeyReader471 static constexpr uint64_t succeeding() {
472 return to_bitset(Values::succeeding);
473 }
failingPreCond::MasterKeyReader474 static constexpr uint64_t failing() { return to_bitset(Values::failing); }
not_executablePreCond::MasterKeyReader475 static constexpr uint64_t not_executable() {
476 return to_bitset(Values::not_executable);
477 }
key_not_foundPreCond::MasterKeyReader478 static constexpr uint64_t key_not_found() {
479 return to_bitset(Values::key_not_found);
480 }
481 };
482
483 enum class MasterKeyWriterValues {
484 none,
485 succeeding,
486 failing,
487 not_executable,
488 };
489
490 struct MasterKeyWriter
491 : public ChainedBitset<
492 MasterKeyWriter, MasterKeyWriterValues, MasterKeyReader,
493 static_cast<uint64_t>(MasterKeyWriterValues::not_executable)> {
494 using Values = MasterKeyWriterValues;
495
nonePreCond::MasterKeyWriter496 static constexpr uint64_t none() { return to_bitset(Values::none); }
succeedingPreCond::MasterKeyWriter497 static constexpr uint64_t succeeding() {
498 return to_bitset(Values::succeeding);
499 }
failingPreCond::MasterKeyWriter500 static constexpr uint64_t failing() { return to_bitset(Values::failing); }
not_executablePreCond::MasterKeyWriter501 static constexpr uint64_t not_executable() {
502 return to_bitset(Values::not_executable);
503 }
504 };
505 } // namespace PreCond
506
507 namespace PostCond {
508 enum class KeyringValues {
509 none,
510 exists_and_secure,
511 not_exists,
512 };
513 struct Keyring
514 : public ChainedBitset<Keyring, KeyringValues, PreCond::MasterKeyWriter,
515 static_cast<uint64_t>(KeyringValues::not_exists)> {
516 using Values = KeyringValues;
517
nonePostCond::Keyring518 static constexpr uint64_t none() { return to_bitset(Values::none); }
exists_and_securePostCond::Keyring519 static constexpr uint64_t exists_and_secure() {
520 return to_bitset(Values::exists_and_secure);
521 }
not_existsPostCond::Keyring522 static constexpr uint64_t not_exists() {
523 return to_bitset(Values::not_exists);
524 }
525 };
526
527 enum class MasterKeyfileValues {
528 none,
529 exists,
530 exists_and_secure,
531 not_exists,
532 };
533
534 struct MasterKeyfile
535 : public ChainedBitset<MasterKeyfile, MasterKeyfileValues, Keyring,
536 static_cast<uint64_t>(
537 MasterKeyfileValues::not_exists)> {
538 using Values = MasterKeyfileValues;
539
nonePostCond::MasterKeyfile540 static constexpr uint64_t none() { return to_bitset(Values::none); }
existsPostCond::MasterKeyfile541 static constexpr uint64_t exists() { return to_bitset(Values::exists); }
exists_and_securePostCond::MasterKeyfile542 static constexpr uint64_t exists_and_secure() {
543 return to_bitset(Values::exists_and_secure);
544 }
not_existsPostCond::MasterKeyfile545 static constexpr uint64_t not_exists() {
546 return to_bitset(Values::not_exists);
547 }
548 };
549
550 enum class KeyringExportValues {
551 none,
552 empty_keys,
553 user_a_password_stdin_value,
554 user_a_password_foo,
555 user_a_password_other,
556 many_user_one_property,
557 many_user_one_property_no_c_password,
558 many_user_one_property_b_removed,
559 };
560
561 struct KeyringExport
562 : public ChainedBitset<
563 KeyringExport, KeyringExportValues, MasterKeyfile,
564 static_cast<uint64_t>(
565 KeyringExportValues::many_user_one_property_b_removed)> {
566 using Values = KeyringExportValues;
567
nonePostCond::KeyringExport568 static constexpr uint64_t none() { return to_bitset(Values::none); }
empty_keysPostCond::KeyringExport569 static constexpr uint64_t empty_keys() {
570 return to_bitset(Values::empty_keys);
571 }
user_a_password_stdin_valuePostCond::KeyringExport572 static constexpr uint64_t user_a_password_stdin_value() {
573 return to_bitset(Values::user_a_password_stdin_value);
574 }
user_a_password_fooPostCond::KeyringExport575 static constexpr uint64_t user_a_password_foo() {
576 return to_bitset(Values::user_a_password_foo);
577 }
user_a_password_otherPostCond::KeyringExport578 static constexpr uint64_t user_a_password_other() {
579 return to_bitset(Values::user_a_password_other);
580 }
many_user_one_propertyPostCond::KeyringExport581 static constexpr uint64_t many_user_one_property() {
582 return to_bitset(Values::many_user_one_property);
583 }
many_user_one_property_no_c_passwordPostCond::KeyringExport584 static constexpr uint64_t many_user_one_property_no_c_password() {
585 return to_bitset(Values::many_user_one_property_no_c_password);
586 }
many_user_one_property_b_removedPostCond::KeyringExport587 static constexpr uint64_t many_user_one_property_b_removed() {
588 return to_bitset(Values::many_user_one_property_b_removed);
589 }
590 };
591
592 enum class MasterListValues {
593 none, // no checks
594 empty, // no output
595 one_entry, // foo.key
596 contains_keyfile, // contains keyfile, maybe others
597 contains_keyfile_and_one_more, // contains keyfile + one more
598 bar_baz, // bar.key, baz.key
599 };
600
601 struct MasterList
602 : public ChainedBitset<MasterList, MasterListValues, KeyringExport,
603 static_cast<uint64_t>(MasterListValues::bar_baz)> {
604 using Values = MasterListValues;
605
nonePostCond::MasterList606 static constexpr uint64_t none() { return to_bitset(Values::none); }
emptyPostCond::MasterList607 static constexpr uint64_t empty() { return to_bitset(Values::empty); }
one_entryPostCond::MasterList608 static constexpr uint64_t one_entry() { return to_bitset(Values::one_entry); }
contains_keyfilePostCond::MasterList609 static constexpr uint64_t contains_keyfile() {
610 return to_bitset(Values::contains_keyfile);
611 }
contains_keyfile_and_one_morePostCond::MasterList612 static constexpr uint64_t contains_keyfile_and_one_more() {
613 return to_bitset(Values::contains_keyfile_and_one_more);
614 }
bar_bazPostCond::MasterList615 static constexpr uint64_t bar_baz() { return to_bitset(Values::bar_baz); }
616 };
617 } // namespace PostCond
618
619 struct KeyringFrontendTestParam {
620 std::string test_name;
621 std::string test_scenario_id;
622
623 std::vector<std::string> cmdline_args;
624 int exit_code;
625 std::string stdin_content;
626 std::string stdout_content;
627 std::string stderr_content;
628 uint64_t options;
629
PrintTo(const KeyringFrontendTestParam & p,std::ostream * os)630 friend void PrintTo(const KeyringFrontendTestParam &p, std::ostream *os) {
631 ParamPrinter(
632 {
633 {"cmdline", ::testing::PrintToString(p.cmdline_args)},
634 },
635 os);
636 }
637 };
638
639 class KeyringFrontendTest
640 : public ::testing::Test,
641 public ::testing::WithParamInterface<KeyringFrontendTestParam> {};
642
643 class TempDirectory {
644 public:
TempDirectory(const std::string & prefix="router")645 explicit TempDirectory(const std::string &prefix = "router")
646 : name_{mysql_harness::get_tmp_dir(prefix)} {}
647
~TempDirectory()648 ~TempDirectory() { mysql_harness::delete_dir_recursive(name_); }
649
name() const650 std::string name() const { return name_; }
651
652 private:
653 std::string name_;
654 };
655
656 const std::array<unsigned char, 8> kKeyringMinimal = {
657 0x4d, 0x52, 0x4b, 0x52, 0x00, 0x00, 0x00, 0x00,
658 };
659
660 // keyring with no entries, but with header
661 const std::array<unsigned char, 56> kKeyringNoEntry = {
662 #if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
663 0x4d, 0x52, 0x4b, 0x52, 0x00, 0x00, 0x00, 0x20, 0x2f, 0x59, 0x62, 0x58,
664 #else
665 0x4d, 0x52, 0x4b, 0x52, 0x20, 0x00, 0x00, 0x00, 0x2f, 0x59, 0x62, 0x58,
666 #endif
667 0x23, 0x50, 0x74, 0x66, 0x5e, 0x3c, 0x29, 0x6a, 0x33, 0x50, 0x36, 0x5a,
668 0x44, 0x3a, 0x4e, 0x73, 0x51, 0x58, 0x79, 0x49, 0x5e, 0x2b, 0x42, 0x3a,
669 0x38, 0x6d, 0x4f, 0x39, 0x95, 0x96, 0x74, 0x76, 0x97, 0xaa, 0xcf, 0xbd,
670 0xd1, 0x5c, 0xce, 0xdb, 0x6f, 0xa1, 0xcf, 0xaf};
671
672 const std::array<unsigned char, 88> kKeyringOneEntry = {
673 #if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
674 0x4d, 0x52, 0x4b, 0x52, 0x00, 0x00, 0x00, 0x20, 0x2f, 0x59, 0x62,
675 #else
676 0x4d, 0x52, 0x4b, 0x52, 0x20, 0x00, 0x00, 0x00, 0x2f, 0x59, 0x62,
677 #endif
678 0x58, 0x23, 0x50, 0x74, 0x66, 0x5e, 0x3c, 0x29, 0x6a, 0x33, 0x50,
679 0x36, 0x5a, 0x44, 0x3a, 0x4e, 0x73, 0x51, 0x58, 0x79, 0x49, 0x5e,
680 0x2b, 0x42, 0x3a, 0x38, 0x6d, 0x4f, 0x39, 0x01, 0x77, 0x33, 0xb8,
681 0x6a, 0x70, 0x91, 0x3d, 0x46, 0x1b, 0xeb, 0x17, 0x62, 0x8e, 0xe1,
682 0x55, 0x53, 0xdf, 0x11, 0x08, 0x04, 0x42, 0x51, 0xc3, 0x8c, 0x67,
683 0xc8, 0x88, 0xaa, 0xe1, 0xbd, 0x02, 0xa5, 0x60, 0x2b, 0x75, 0xbb,
684 0x59, 0x63, 0xba, 0x5d, 0xaf, 0xfb, 0x71, 0xf1, 0xfd, 0xeb, 0x14};
685
686 // valid, one entry (for "foo.key"), masterkeyfile.
687 //
688 // the master-key-ring is not endian-ness-safe:
689 //
690 // - master-key-file created on sparc can't be read on x86
691 const std::array<unsigned char, 65> kMasterKeyfileOneEntry = {
692 #if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
693 0x4d, 0x52, 0x4b, 0x46, 0x00, 0x00, 0x00, 0x00, 0x38, 0x66, 0x6f,
694 #else
695 0x4d, 0x52, 0x4b, 0x46, 0x00, 0x38, 0x00, 0x00, 0x00, 0x66, 0x6f,
696 #endif
697 0x6f, 0x2e, 0x6b, 0x65, 0x79, 0x00, 0x30, 0x37, 0xf2, 0x4b, 0xc0,
698 0xd6, 0x8d, 0x33, 0xb8, 0xd9, 0x39, 0xa2, 0x07, 0xa5, 0xc8, 0xc4,
699 0xe2, 0x0a, 0x2e, 0xb9, 0x4f, 0x4a, 0x34, 0xa4, 0x39, 0xe8, 0x12,
700 0xc1, 0x03, 0x52, 0xc7, 0x73, 0x71, 0x79, 0x04, 0xb9, 0x01, 0x53,
701 0x54, 0x11, 0x3d, 0x8e, 0xa9, 0xd4, 0xe8, 0x99, 0x8a, 0x91};
702
703 const std::array<unsigned char, 185> kMasterKeyfileFooBarBaz = {
704 #if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
705 0x4d, 0x52, 0x4b, 0x46, 0x00, 0x00, 0x00, 0x00, 0x38, 0x66, 0x6f, 0x6f,
706 #else
707 0x4d, 0x52, 0x4b, 0x46, 0x00, 0x38, 0x00, 0x00, 0x00, 0x66, 0x6f, 0x6f,
708 #endif
709 0x2e, 0x6b, 0x65, 0x79, 0x00, 0x07, 0x85, 0x1a, 0xed, 0xa7, 0x1d, 0xc8,
710 0xe7, 0x10, 0x37, 0x88, 0xd5, 0x92, 0x8b, 0xcc, 0xfd, 0xe6, 0xbe, 0xa0,
711 0x81, 0xf4, 0xfe, 0x40, 0x97, 0xd1, 0x95, 0xec, 0xc8, 0x10, 0x47, 0xd6,
712 0xa7, 0x77, 0xb6, 0x5a, 0xa8, 0xe1, 0x02, 0x0a, 0x7d, 0xd0, 0x08, 0x70,
713 #if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
714 0x6f, 0x9a, 0xc9, 0xd6, 0x38, 0x00, 0x00, 0x00, 0x38, 0x62, 0x61, 0x72,
715 #else
716 0x6f, 0x9a, 0xc9, 0xd6, 0x38, 0x38, 0x00, 0x00, 0x00, 0x62, 0x61, 0x72,
717 #endif
718 0x2e, 0x6b, 0x65, 0x79, 0x00, 0x80, 0xc9, 0x16, 0x02, 0x75, 0x4f, 0xd1,
719 0xc2, 0x36, 0x1f, 0x89, 0x24, 0x31, 0x5d, 0x60, 0x78, 0xc7, 0x92, 0xa0,
720 0xc0, 0xcb, 0xc2, 0xdc, 0xe7, 0x03, 0x85, 0x72, 0x53, 0x8c, 0x41, 0xee,
721 0x9b, 0xe5, 0x38, 0x75, 0x81, 0xb0, 0xe8, 0x1e, 0xbb, 0x67, 0x3d, 0x7a,
722 #if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
723 0x86, 0xda, 0x7f, 0x3c, 0x33, 0x00, 0x00, 0x00, 0x38, 0x62, 0x61, 0x7a,
724 #else
725 0x86, 0xda, 0x7f, 0x3c, 0x33, 0x38, 0x00, 0x00, 0x00, 0x62, 0x61, 0x7a,
726 #endif
727 0x2e, 0x6b, 0x65, 0x79, 0x00, 0x1f, 0xfa, 0x59, 0x74, 0xcd, 0x23, 0x0c,
728 0x9b, 0x05, 0x51, 0xcf, 0xed, 0x26, 0xb0, 0x2c, 0xb9, 0x18, 0x4c, 0x7a,
729 0x53, 0xb9, 0x2a, 0x11, 0x9d, 0xe2, 0x3a, 0x0d, 0x1c, 0x18, 0x77, 0xc6,
730 0xf0, 0x8d, 0x69, 0x3c, 0x03, 0xc2, 0x00, 0x19, 0xbd, 0x7a, 0xcd, 0x54,
731 0x21, 0xc8, 0x91, 0x90, 0x7d};
732
733 // valid, empty masterkeyfile
734 const std::array<unsigned char, 5> kMasterKeyfileInitialized = {
735 0x4d, 0x52, 0x4b, 0x46, 0x00,
736 };
737
738 template <class T, size_t N>
operator <<(std::ostream & os,const std::array<T,N> & arr)739 std::ostream &operator<<(std::ostream &os, const std::array<T, N> &arr) {
740 std::copy(arr.begin(), arr.end(), std::ostream_iterator<T>(os));
741 return os;
742 }
743
run(const std::vector<std::string> & args,const std::string & stdin_content,std::string & out,std::string & err,int expected_exit_code=0)744 static void run(const std::vector<std::string> &args,
745 const std::string &stdin_content, std::string &out,
746 std::string &err, int expected_exit_code = 0) {
747 std::istringstream cin(stdin_content);
748 std::ostringstream cout;
749 std::ostringstream cerr;
750
751 SCOPED_TRACE("// running "s + kAppExeFileName + " " +
752 mysql_harness::join(args, " "));
753 int exit_code = 0;
754 try {
755 exit_code = KeyringFrontend(kAppExeFileName, args, cin, cout, cerr).run();
756 } catch (const FrontendError &e) {
757 cerr << e.what() << std::endl;
758 exit_code = EXIT_FAILURE;
759 } catch (const std::exception &e) {
760 FAIL() << e.what();
761 }
762
763 out = cout.str();
764 err = cerr.str();
765
766 // success, empty json-object and no error
767 ASSERT_EQ(exit_code, expected_exit_code) << err;
768 }
769
build_master_list_cmd_args(const std::vector<std::string> & args,std::vector<std::string> & out_args)770 void build_master_list_cmd_args(const std::vector<std::string> &args,
771 std::vector<std::string> &out_args) {
772 out_args.push_back("master-list");
773
774 bool copy_next{false};
775 for (const auto &arg : args) {
776 ASSERT_NE(arg, "--version");
777 ASSERT_NE(arg, "--help");
778
779 if (arg == "--master-key-file") {
780 out_args.push_back(arg);
781
782 copy_next = true;
783 } else if (copy_next) {
784 out_args.push_back(arg);
785 copy_next = false;
786 }
787 }
788 }
789
build_export_cmd_args(const std::vector<std::string> & args,std::vector<std::string> & out_args)790 void build_export_cmd_args(const std::vector<std::string> &args,
791 std::vector<std::string> &out_args) {
792 out_args.push_back("export");
793
794 size_t no_opt_arg{0};
795 bool copy_next{false};
796 for (const auto &arg : args) {
797 ASSERT_NE(arg, "--version");
798 ASSERT_NE(arg, "--help");
799
800 if (arg == "--master-key-reader" || arg == "--master-key-writer" ||
801 arg == "--master-key-file") {
802 copy_next = true;
803 out_args.push_back(arg);
804 } else if (copy_next) {
805 out_args.push_back(arg);
806 copy_next = false;
807 } else if (arg.substr(0, 2) == "--") {
808 // do we have to capture that arg too?
809 EXPECT_TRUE(false) << arg;
810 } else {
811 if (no_opt_arg == 1) {
812 // only capture the keyfile, the first non-opt-arg (the one
813 // after the cmd)
814 out_args.push_back(arg);
815 }
816 ++no_opt_arg;
817 }
818 }
819 }
820 template <class T, size_t N>
create_file(const std::string & filename,const std::array<T,N> & data)821 static void create_file(const std::string &filename,
822 const std::array<T, N> &data) {
823 std::fstream kr(filename, std::ios::out | std::ios::binary);
824 ASSERT_TRUE(kr.is_open());
825 kr << data;
826 kr.close();
827 }
828
create_file(const std::string & filename,const std::string & data)829 static void create_file(const std::string &filename, const std::string &data) {
830 std::fstream kr(filename, std::ios::out | std::ios::binary);
831 ASSERT_TRUE(kr.is_open());
832 kr << data;
833 kr.close();
834 }
835
create_file(const std::string & filename)836 static void create_file(const std::string &filename) {
837 std::fstream kr(filename, std::ios::out | std::ios::binary);
838 ASSERT_TRUE(kr.is_open());
839 kr.close();
840 }
841
842 template <class T, size_t N>
create_private_file(const std::string & filename,const std::array<T,N> & data)843 static void create_private_file(const std::string &filename,
844 const std::array<T, N> &data) {
845 create_file(filename, data);
846
847 mysql_harness::make_file_private(filename);
848 }
849
850 template <class T, size_t N>
create_executable_file(std::string & filename,const std::array<T,N> & data)851 static void create_executable_file(std::string &filename,
852 const std::array<T, N> &data) {
853 #ifdef _WIN32
854 // append .bat to make the file "executable"
855 filename.append(".bat");
856 #endif
857
858 create_file(filename, data);
859 #ifndef _WIN32
860 ::chmod(filename.c_str(), 0700);
861 #endif
862 }
863
create_executable_file(std::string & filename,const std::string & data)864 static void create_executable_file(std::string &filename,
865 const std::string &data) {
866 #ifdef _WIN32
867 // append .bat to make the file "executable"
868 filename.append(".bat");
869 #endif
870
871 create_file(filename, data);
872
873 #ifndef _WIN32
874 ::chmod(filename.c_str(), 0700);
875 #endif
876 }
877
create_private_file(const std::string & filename)878 static void create_private_file(const std::string &filename) {
879 create_file(filename);
880
881 mysql_harness::make_file_private(filename);
882 }
883
create_insecure_file(const std::string & filename)884 static void create_insecure_file(const std::string &filename) {
885 create_file(filename);
886
887 mysql_harness::make_file_public(filename);
888 }
889
890 /**
891 * @test ensure PasswordFrontend behaves correctly.
892 */
TEST_P(KeyringFrontendTest,ensure)893 TEST_P(KeyringFrontendTest, ensure) {
894 // record the test-scenario from the test-plan in the --gtest-output file
895 RecordProperty("scenario", GetParam().test_scenario_id);
896
897 TempDirectory tmpdir;
898
899 // use spaces in names to test special characters all the time
900 std::string keyring_filename(
901 mysql_harness::Path(tmpdir.name()).join("keyring").str());
902 std::string master_keyring_filename(
903 mysql_harness::Path(tmpdir.name()).join("master_keyring").str());
904 std::string master_key_reader(
905 mysql_harness::Path(tmpdir.name()).join("master key reader").str());
906 std::string master_key_writer(
907 mysql_harness::Path(tmpdir.name()).join("master key writer").str());
908
909 SCOPED_TRACE("// applying pre-conditions");
910 switch (PreCond::KeyringFilename::from_bitset(GetParam().options)) {
911 case PreCond::KeyringFilename::Values::none:
912 break;
913 case PreCond::KeyringFilename::Values::special_chars:
914 keyring_filename =
915 mysql_harness::Path(tmpdir.name()).join("Key ring").str();
916 break;
917 case PreCond::KeyringFilename::Values::with_directory: {
918 mysql_harness::Path subdir(tmpdir.name());
919 subdir = subdir.join("subdir");
920 mysql_harness::mkdir(subdir.c_str(), 0700);
921 keyring_filename = subdir.join("Key ring").str();
922 } break;
923 case PreCond::KeyringFilename::Values::with_no_exist_directory: {
924 mysql_harness::Path subdir(tmpdir.name());
925 subdir = subdir.join("subdir");
926 keyring_filename = subdir.join("Key ring").str();
927 } break;
928 case PreCond::KeyringFilename::Values::absolute: {
929 bool is_absolute{false};
930 #ifdef _WIN32
931 // c:/
932 is_absolute = tmpdir.name().at(1) == ':';
933 #else
934 is_absolute = tmpdir.name().at(0) == '/';
935 #endif
936 if (!is_absolute) {
937 #ifdef _WIN32
938 std::array<char, MAX_PATH> cwd;
939 #else
940 std::array<char, PATH_MAX> cwd;
941 #endif
942 if (nullptr == getcwd(cwd.data(), cwd.size())) {
943 throw std::system_error(errno, std::generic_category(),
944 "getcwd() failed");
945 }
946 keyring_filename = mysql_harness::Path(cwd.data())
947 .join(tmpdir.name())
948 .join("Key ring")
949 .str();
950 } else {
951 keyring_filename =
952 mysql_harness::Path(tmpdir.name()).join("Key ring").str();
953 }
954 } break;
955 }
956
957 switch (PreCond::MasterKeyfileFilename::from_bitset(GetParam().options)) {
958 case PreCond::MasterKeyfileFilename::Values::none:
959 break;
960 case PreCond::MasterKeyfileFilename::Values::special_chars:
961 master_keyring_filename =
962 mysql_harness::Path(tmpdir.name()).join("master Key ring").str();
963 break;
964 case PreCond::MasterKeyfileFilename::Values::with_directory: {
965 mysql_harness::Path subdir(tmpdir.name());
966 subdir = subdir.join("subdir");
967 mysql_harness::mkdir(subdir.c_str(), 0700);
968 master_keyring_filename = subdir.join("master Key ring").str();
969 } break;
970 case PreCond::MasterKeyfileFilename::Values::with_no_exist_directory: {
971 mysql_harness::Path subdir(tmpdir.name());
972 subdir = subdir.join("subdir");
973 master_keyring_filename = subdir.join("master Key ring").str();
974 } break;
975 }
976
977 switch (PreCond::Keyring::from_bitset(GetParam().options)) {
978 case PreCond::Keyring::Values::none:
979 break;
980 case PreCond::Keyring::Values::empty:
981 create_private_file(keyring_filename);
982 break;
983 case PreCond::Keyring::Values::no_entries:
984 create_private_file(keyring_filename, kKeyringNoEntry);
985 break;
986 case PreCond::Keyring::Values::one_entry:
987 create_private_file(keyring_filename, kKeyringOneEntry);
988 break;
989 case PreCond::Keyring::Values::inited: {
990 std::string out;
991 std::string err;
992 ASSERT_NO_FATAL_FAILURE(
993 run({"init", keyring_filename, "--master-key-file",
994 master_keyring_filename},
995 "", out, err));
996 ASSERT_EQ(out, "");
997 ASSERT_EQ(err, "");
998 } break;
999 case PreCond::Keyring::Values::minimal:
1000 create_private_file(keyring_filename, kKeyringMinimal);
1001 break;
1002 case PreCond::Keyring::Values::one_user_one_property: {
1003 std::string out;
1004 std::string err;
1005
1006 ASSERT_NO_FATAL_FAILURE(
1007 run({"init", keyring_filename, "--master-key-file",
1008 master_keyring_filename},
1009 "", out, err));
1010 ASSERT_EQ(out, "");
1011 ASSERT_EQ(err, "");
1012
1013 std::vector<std::tuple<std::string, std::string, std::string>> props{
1014 std::make_tuple("a", "password", "foo"),
1015 };
1016
1017 for (auto const &prop : props) {
1018 ASSERT_NO_FATAL_FAILURE(
1019 run({"set", keyring_filename, "--master-key-file",
1020 master_keyring_filename, std::get<0>(prop), std::get<1>(prop),
1021 std::get<2>(prop)},
1022 "", out, err));
1023 ASSERT_EQ(out, "");
1024 ASSERT_EQ(err, "");
1025 }
1026
1027 } break;
1028 case PreCond::Keyring::Values::many_user_one_property: {
1029 std::string out;
1030 std::string err;
1031
1032 ASSERT_NO_FATAL_FAILURE(
1033 run({"init", keyring_filename, "--master-key-file",
1034 master_keyring_filename},
1035 "", out, err));
1036 ASSERT_EQ(out, "");
1037 ASSERT_EQ(err, "");
1038
1039 std::vector<std::tuple<std::string, std::string, std::string>> props{
1040 std::make_tuple("a", "password", "foo"),
1041 std::make_tuple("b", "password", "bar"),
1042 std::make_tuple("c", "password", "baz"),
1043 std::make_tuple("c", "Key1", "fuu"),
1044 std::make_tuple("c", "key1", "fuU"),
1045 };
1046
1047 for (auto const &prop : props) {
1048 ASSERT_NO_FATAL_FAILURE(
1049 run({"set", keyring_filename, "--master-key-file",
1050 master_keyring_filename, std::get<0>(prop), std::get<1>(prop),
1051 std::get<2>(prop)},
1052 "", out, err));
1053 ASSERT_EQ(out, "");
1054 ASSERT_EQ(err, "");
1055 }
1056
1057 } break;
1058 case PreCond::Keyring::Values::long_property: {
1059 std::string out;
1060 std::string err;
1061
1062 ASSERT_NO_FATAL_FAILURE(
1063 run({"init", keyring_filename, "--master-key-file",
1064 master_keyring_filename},
1065 "", out, err));
1066 ASSERT_EQ(out, "");
1067 ASSERT_EQ(err, "");
1068
1069 std::vector<std::tuple<std::string, std::string, std::string>> props{
1070 std::make_tuple("a", "password", "foo"),
1071 std::make_tuple("b", "password", "bar"),
1072 std::make_tuple("c", "password", "baz"),
1073 std::make_tuple("c", "Key1", "fuu"),
1074 std::make_tuple("c", "key1", "fuU"),
1075 std::make_tuple("long", "long", std::string(128 * 1024, 'a')),
1076 };
1077
1078 for (auto const &prop : props) {
1079 ASSERT_NO_FATAL_FAILURE(
1080 run({"set", keyring_filename, "--master-key-file",
1081 master_keyring_filename, std::get<0>(prop), std::get<1>(prop),
1082 std::get<2>(prop)},
1083 "", out, err));
1084 ASSERT_EQ(out, "");
1085 ASSERT_EQ(err, "");
1086 }
1087
1088 } break;
1089 case PreCond::Keyring::Values::long_username: {
1090 std::string out;
1091 std::string err;
1092
1093 ASSERT_NO_FATAL_FAILURE(
1094 run({"init", keyring_filename, "--master-key-file",
1095 master_keyring_filename},
1096 "", out, err));
1097 ASSERT_EQ(out, "");
1098 ASSERT_EQ(err, "");
1099
1100 std::vector<std::tuple<std::string, std::string, std::string>> props{
1101 std::make_tuple(std::string(128 * 1024, 'a'), "password", "foo"),
1102 };
1103
1104 for (auto const &prop : props) {
1105 ASSERT_NO_FATAL_FAILURE(
1106 run({"set", keyring_filename, "--master-key-file",
1107 master_keyring_filename, std::get<0>(prop), std::get<1>(prop),
1108 std::get<2>(prop)},
1109 "", out, err));
1110 ASSERT_EQ(out, "");
1111 ASSERT_EQ(err, "");
1112 }
1113
1114 } break;
1115 case PreCond::Keyring::Values::special_properties: {
1116 std::string out;
1117 std::string err;
1118
1119 ASSERT_NO_FATAL_FAILURE(
1120 run({"init", keyring_filename, "--master-key-file",
1121 master_keyring_filename},
1122 "", out, err));
1123 ASSERT_EQ(out, "");
1124 ASSERT_EQ(err, "");
1125
1126 std::vector<std::tuple<std::string, std::string, std::string>> props{
1127 std::make_tuple("A", "<", ">"),
1128 std::make_tuple("A", "\n", std::string("\0", 1)),
1129 std::make_tuple("A", "name", ""),
1130 std::make_tuple("B", "password", "bar"),
1131 std::make_tuple("{", "password", "baz"),
1132 std::make_tuple("\"", "Key1", "fuu"),
1133 std::make_tuple("\n", "key1", "fuU"),
1134 std::make_tuple("\r", "key1", "fuU"),
1135 std::make_tuple("\t", "key1", "fuU"),
1136 std::make_tuple(std::string("\0", 1), "key1", "fuU"),
1137 std::make_tuple("'", "key1", "fuU"),
1138 std::make_tuple("\"NULL\"", "key1", "fuU"),
1139 };
1140
1141 for (auto const &prop : props) {
1142 ASSERT_NO_FATAL_FAILURE(
1143 run({"set", keyring_filename, "--master-key-file",
1144 master_keyring_filename, std::get<0>(prop), std::get<1>(prop),
1145 std::get<2>(prop)},
1146 "", out, err));
1147 ASSERT_EQ(out, "");
1148 ASSERT_EQ(err, "");
1149 }
1150
1151 } break;
1152 default:
1153 ASSERT_TRUE(false);
1154 }
1155
1156 switch (PreCond::MasterKeyfile::from_bitset(GetParam().options)) {
1157 case PreCond::MasterKeyfile::Values::none:
1158 break;
1159 case PreCond::MasterKeyfile::Values::empty:
1160 create_private_file(master_keyring_filename);
1161 break;
1162 case PreCond::MasterKeyfile::Values::insecure:
1163 create_insecure_file(master_keyring_filename);
1164 break;
1165 case PreCond::MasterKeyfile::Values::minimal:
1166 create_private_file(master_keyring_filename, kMasterKeyfileInitialized);
1167 break;
1168 case PreCond::MasterKeyfile::Values::valid_one_entry:
1169 create_private_file(master_keyring_filename, kMasterKeyfileOneEntry);
1170 break;
1171 case PreCond::MasterKeyfile::Values::valid_foo_bar_baz:
1172 create_private_file(master_keyring_filename, kMasterKeyfileFooBarBaz);
1173 break;
1174 }
1175
1176 switch (PreCond::MasterKeyReader::from_bitset(GetParam().options)) {
1177 case PreCond::MasterKeyReader::Values::none:
1178 break;
1179 case PreCond::MasterKeyReader::Values::succeeding:
1180 // may modify master_key_reader
1181 create_executable_file(master_key_reader, kMasterKeyReaderSucceeding);
1182 break;
1183 case PreCond::MasterKeyReader::Values::key_not_found:
1184 // may modify master_key_reader
1185 create_executable_file(master_key_reader, kMasterKeyReaderKeyNotFound);
1186 break;
1187 case PreCond::MasterKeyReader::Values::failing:
1188 // may modify master_key_reader
1189 create_executable_file(master_key_reader, kMasterKeyReaderFailing);
1190 break;
1191 case PreCond::MasterKeyReader::Values::not_executable:
1192 create_file(master_key_reader, kMasterKeyReaderSucceeding);
1193 break;
1194 }
1195
1196 switch (PreCond::MasterKeyWriter::from_bitset(GetParam().options)) {
1197 case PreCond::MasterKeyWriter::Values::none:
1198 break;
1199 case PreCond::MasterKeyWriter::Values::succeeding:
1200 // may modify master_key_writer
1201 create_executable_file(master_key_writer, kMasterKeyWriterSucceeding);
1202 break;
1203 case PreCond::MasterKeyWriter::Values::failing:
1204 // may modify master_key_writer
1205 create_executable_file(master_key_writer, kMasterKeyWriterFailing);
1206 break;
1207 case PreCond::MasterKeyWriter::Values::not_executable:
1208 create_file(master_key_writer, kMasterKeyWriterFailing);
1209 break;
1210 }
1211
1212 // replace the placeholder with the name of the temp passwd-file
1213 std::vector<std::string> args{GetParam().cmdline_args};
1214 for (auto &arg : args) {
1215 if (arg == kKeyringPlaceholder) {
1216 arg = keyring_filename;
1217 } else if (arg == kMasterKeyfilePlaceholder) {
1218 arg = master_keyring_filename;
1219 } else if (arg == kMasterKeyReaderPlaceholder) {
1220 arg = master_key_reader;
1221 } else if (arg == kMasterKeyWriterPlaceholder) {
1222 arg = master_key_writer;
1223 }
1224 }
1225
1226 SCOPED_TRACE("// running test");
1227 // do what keyring_cli.cc's main() does
1228 {
1229 std::istringstream cin(GetParam().stdin_content);
1230 std::ostringstream cout;
1231 std::ostringstream cerr;
1232
1233 mysqlrouter::set_prompt_password([&cin](const std::string &) {
1234 std::string s;
1235 std::getline(cin, s);
1236 return s;
1237 });
1238
1239 int exit_code = 0;
1240 try {
1241 exit_code = KeyringFrontend(kAppExeFileName, args, cin, cout, cerr).run();
1242 } catch (const FrontendError &e) {
1243 cerr << e.what() << std::endl;
1244 exit_code = EXIT_FAILURE;
1245 } catch (const std::exception &e) {
1246 FAIL() << e.what();
1247 }
1248
1249 EXPECT_EQ(exit_code, GetParam().exit_code);
1250 EXPECT_EQ(GetParam().stdout_content, cout.str());
1251 EXPECT_THAT(cerr.str(),
1252 ::testing::ContainsRegex(GetParam().stderr_content));
1253 }
1254
1255 SCOPED_TRACE("// checking post-conditions");
1256 switch (PostCond::Keyring::from_bitset(GetParam().options)) {
1257 case PostCond::Keyring::Values::none:
1258 break;
1259 case PostCond::Keyring::Values::not_exists:
1260 EXPECT_FALSE(mysql_harness::Path(keyring_filename).exists());
1261
1262 break;
1263 case PostCond::Keyring::Values::exists_and_secure:
1264 EXPECT_TRUE(mysql_harness::Path(keyring_filename).exists());
1265 EXPECT_NO_THROW(
1266 mysql_harness::check_file_access_rights(keyring_filename));
1267 break;
1268 }
1269
1270 switch (PostCond::KeyringExport::from_bitset(GetParam().options)) {
1271 case PostCond::KeyringExport::Values::none:
1272 break;
1273 case PostCond::KeyringExport::Values::empty_keys: {
1274 std::vector<std::string> export_args;
1275 build_export_cmd_args(args, export_args);
1276
1277 std::string cout;
1278 std::string cerr;
1279 EXPECT_NO_FATAL_FAILURE(
1280 run(export_args, GetParam().stdin_content, cout, cerr));
1281
1282 // success, empty json-object and no error
1283 EXPECT_EQ("{}\n"s, cout);
1284 EXPECT_EQ(""s, cerr);
1285 }
1286
1287 break;
1288 case PostCond::KeyringExport::Values::user_a_password_stdin_value: {
1289 std::vector<std::string> export_args;
1290 build_export_cmd_args(args, export_args);
1291
1292 std::string cout;
1293 std::string cerr;
1294 EXPECT_NO_FATAL_FAILURE(
1295 run(export_args, GetParam().stdin_content, cout, cerr));
1296
1297 EXPECT_EQ(
1298 "{\n"
1299 " \"a\": {\n"
1300 " \"password\": \"" +
1301 GetParam().stdin_content +
1302 "\"\n"
1303 " }\n"
1304 "}\n",
1305 cout);
1306 EXPECT_EQ(""s, cerr);
1307 } break;
1308 case PostCond::KeyringExport::Values::user_a_password_foo: {
1309 std::vector<std::string> export_args;
1310 build_export_cmd_args(args, export_args);
1311
1312 std::string cout;
1313 std::string cerr;
1314 EXPECT_NO_FATAL_FAILURE(
1315 run(export_args, GetParam().stdin_content, cout, cerr));
1316
1317 EXPECT_EQ(
1318 "{\n"
1319 " \"a\": {\n"
1320 " \"password\": \"foo\"\n"
1321 " }\n"
1322 "}\n",
1323 cout);
1324 EXPECT_EQ(""s, cerr);
1325 } break;
1326 case PostCond::KeyringExport::Values::user_a_password_other: {
1327 std::vector<std::string> export_args;
1328 build_export_cmd_args(args, export_args);
1329
1330 std::string cout;
1331 std::string cerr;
1332 EXPECT_NO_FATAL_FAILURE(
1333 run(export_args, GetParam().stdin_content, cout, cerr));
1334
1335 EXPECT_EQ(
1336 "{\n"
1337 " \"a\": {\n"
1338 " \"password\": \"other\"\n"
1339 " }\n"
1340 "}\n",
1341 cout);
1342 EXPECT_EQ(""s, cerr);
1343 } break;
1344 case PostCond::KeyringExport::Values::
1345 many_user_one_property_no_c_password: {
1346 std::vector<std::string> export_args;
1347 build_export_cmd_args(args, export_args);
1348
1349 std::string cout;
1350 std::string cerr;
1351 EXPECT_NO_FATAL_FAILURE(
1352 run(export_args, GetParam().stdin_content, cout, cerr));
1353
1354 EXPECT_EQ(
1355 "{\n"
1356 " \"a\": {\n"
1357 " \"password\": \"foo\"\n"
1358 " },\n"
1359 " \"b\": {\n"
1360 " \"password\": \"bar\"\n"
1361 " },\n"
1362 " \"c\": {\n"
1363 " \"Key1\": \"fuu\",\n"
1364 " \"key1\": \"fuU\"\n"
1365 " }\n"
1366 "}\n",
1367 cout);
1368 EXPECT_EQ(""s, cerr);
1369 } break;
1370 case PostCond::KeyringExport::Values::many_user_one_property_b_removed: {
1371 std::vector<std::string> export_args;
1372 build_export_cmd_args(args, export_args);
1373
1374 std::string cout;
1375 std::string cerr;
1376 EXPECT_NO_FATAL_FAILURE(
1377 run(export_args, GetParam().stdin_content, cout, cerr));
1378
1379 EXPECT_EQ(
1380 "{\n"
1381 " \"a\": {\n"
1382 " \"password\": \"foo\"\n"
1383 " },\n"
1384 " \"c\": {\n"
1385 " \"Key1\": \"fuu\",\n"
1386 " \"key1\": \"fuU\",\n"
1387 " \"password\": \"baz\"\n"
1388 " }\n"
1389 "}\n",
1390 cout);
1391 EXPECT_EQ(""s, cerr);
1392 } break;
1393 case PostCond::KeyringExport::Values::many_user_one_property: {
1394 std::vector<std::string> export_args;
1395 build_export_cmd_args(args, export_args);
1396
1397 std::string cout;
1398 std::string cerr;
1399 EXPECT_NO_FATAL_FAILURE(
1400 run(export_args, GetParam().stdin_content, cout, cerr));
1401
1402 EXPECT_EQ(
1403 "{\n"
1404 " \"a\": {\n"
1405 " \"password\": \"foo\"\n"
1406 " },\n"
1407 " \"b\": {\n"
1408 " \"password\": \"bar\"\n"
1409 " },\n"
1410 " \"c\": {\n"
1411 " \"Key1\": \"fuu\",\n"
1412 " \"key1\": \"fuU\",\n"
1413 " \"password\": \"baz\"\n"
1414 " }\n"
1415 "}\n",
1416 cout);
1417 EXPECT_EQ(""s, cerr);
1418 } break;
1419 }
1420
1421 switch (PostCond::MasterKeyfile::from_bitset(GetParam().options)) {
1422 case PostCond::MasterKeyfile::Values::none:
1423 break;
1424 case PostCond::MasterKeyfile::Values::exists:
1425 EXPECT_TRUE(mysql_harness::Path(master_keyring_filename).exists());
1426 break;
1427 case PostCond::MasterKeyfile::Values::not_exists:
1428 EXPECT_FALSE(mysql_harness::Path(master_keyring_filename).exists());
1429 break;
1430 case PostCond::MasterKeyfile::Values::exists_and_secure:
1431 EXPECT_TRUE(mysql_harness::Path(master_keyring_filename).exists());
1432
1433 EXPECT_NO_THROW(
1434 mysql_harness::check_file_access_rights(master_keyring_filename));
1435 break;
1436 }
1437
1438 switch (PostCond::MasterList::from_bitset(GetParam().options)) {
1439 case PostCond::MasterList::Values::none:
1440 break;
1441 case PostCond::MasterList::Values::empty: {
1442 std::vector<std::string> cmd_args;
1443 ASSERT_NO_FATAL_FAILURE(build_master_list_cmd_args(args, cmd_args));
1444
1445 std::string cout;
1446 std::string cerr;
1447 EXPECT_NO_FATAL_FAILURE(
1448 run(cmd_args, GetParam().stdin_content, cout, cerr));
1449
1450 EXPECT_EQ(""s, cout);
1451 EXPECT_EQ(""s, cerr);
1452 } break;
1453 case PostCond::MasterList::Values::one_entry: {
1454 std::vector<std::string> cmd_args;
1455 ASSERT_NO_FATAL_FAILURE(build_master_list_cmd_args(args, cmd_args));
1456
1457 std::string cout;
1458 std::string cerr;
1459 EXPECT_NO_FATAL_FAILURE(
1460 run(cmd_args, GetParam().stdin_content, cout, cerr));
1461
1462 EXPECT_EQ("foo.key\n"s, cout);
1463 EXPECT_EQ(""s, cerr);
1464 } break;
1465 case PostCond::MasterList::Values::contains_keyfile: {
1466 std::vector<std::string> cmd_args;
1467 ASSERT_NO_FATAL_FAILURE(build_master_list_cmd_args(args, cmd_args));
1468
1469 std::string cout;
1470 std::string cerr;
1471 EXPECT_NO_FATAL_FAILURE(
1472 run(cmd_args, GetParam().stdin_content, cout, cerr));
1473
1474 EXPECT_THAT(mysql_harness::split_string(cout, '\n'),
1475 ::testing::Contains(keyring_filename));
1476 EXPECT_EQ(""s, cerr);
1477 } break;
1478 case PostCond::MasterList::Values::contains_keyfile_and_one_more: {
1479 std::vector<std::string> cmd_args;
1480 ASSERT_NO_FATAL_FAILURE(build_master_list_cmd_args(args, cmd_args));
1481
1482 std::string cout;
1483 std::string cerr;
1484 EXPECT_NO_FATAL_FAILURE(
1485 run(cmd_args, GetParam().stdin_content, cout, cerr));
1486
1487 EXPECT_THAT(mysql_harness::split_string(cout, '\n'),
1488 ::testing::AllOf(::testing::Contains(keyring_filename),
1489 ::testing::Contains("foo.key")));
1490 EXPECT_EQ(""s, cerr);
1491 } break;
1492 case PostCond::MasterList::Values::bar_baz: {
1493 std::vector<std::string> cmd_args;
1494 ASSERT_NO_FATAL_FAILURE(build_master_list_cmd_args(args, cmd_args));
1495
1496 std::string cout;
1497 std::string cerr;
1498 EXPECT_NO_FATAL_FAILURE(
1499 run(cmd_args, GetParam().stdin_content, cout, cerr));
1500
1501 EXPECT_THAT(mysql_harness::split_string(cout, '\n'),
1502 ::testing::AllOf(::testing::Contains("bar.key"),
1503 ::testing::Contains("baz.key")));
1504 EXPECT_EQ(""s, cerr);
1505 } break;
1506 }
1507 }
1508
1509 // cleanup test-names to satisfy googletest's requirements
1510 const KeyringFrontendTestParam password_frontend_param[]{
1511 {"dashdash_help",
1512 "WL12974::TS_H_1",
1513 {"--help"},
1514 EXIT_SUCCESS,
1515 "",
1516 kHelpText + "\n",
1517 "",
1518 PreCond::Keyring::none()},
1519
1520 {"dash_questionmark",
1521 "WL12974::TS_H_2",
1522 {"-?"},
1523 EXIT_SUCCESS,
1524 "",
1525 kHelpText + "\n",
1526 "^$",
1527 PreCond::Keyring::none()},
1528
1529 {"dash_questionmark_and_dashdash_help",
1530 "WL12974::TS_H_4",
1531 {"-?", "--help"},
1532 EXIT_SUCCESS,
1533 "",
1534 kHelpText + "\n",
1535 "^$",
1536 PreCond::Keyring::none()},
1537
1538 {"dashdash_version",
1539 "WL12974::TS_V_1",
1540 {"--version"},
1541 EXIT_SUCCESS,
1542 "",
1543 kVersionText + "\n",
1544 "^$",
1545 PreCond::Keyring::none()},
1546
1547 {"dash_V",
1548 "WL12974::TS_V_2",
1549 {"-V"},
1550 EXIT_SUCCESS,
1551 "",
1552 kVersionText + "\n",
1553 "^$",
1554 PreCond::Keyring::none()},
1555
1556 {"dash_V_and_dash_questionmark",
1557 "",
1558 {"-V", "-?"},
1559 EXIT_SUCCESS,
1560 "",
1561 kVersionText + "\n",
1562 "^$",
1563 PreCond::Keyring::none()},
1564
1565 {"dash_questionmark_and_dash_V",
1566 "",
1567 {"-?", "-V"},
1568 EXIT_SUCCESS,
1569 "",
1570 kHelpText + "\n",
1571 "^$",
1572 PreCond::Keyring::none()},
1573
1574 {"dash_version_and_dash_v",
1575 "WL12974::TS_V_4",
1576 {"-V", "--version"},
1577 EXIT_SUCCESS,
1578 "",
1579 kVersionText + "\n",
1580 "^$",
1581 PreCond::Keyring::none()},
1582
1583 {"dashdash_version_and_unknown_options",
1584 "WL12974::TS_AS_1",
1585 {"--version", "--unknown-option"},
1586 EXIT_FAILURE,
1587 "",
1588 "",
1589 "unknown option '--unknown-option'",
1590 PreCond::Keyring::none()},
1591
1592 {"dashdash_version_and_unknown_command",
1593 "",
1594 {"unknown-command", "--version"},
1595 EXIT_FAILURE,
1596 "",
1597 "",
1598 "expected no extra arguments",
1599 PreCond::Keyring::none()},
1600
1601 {"list_master_key_writer_empty",
1602 "",
1603 {"list", "keyring", "--master-key-writer", ""},
1604 EXIT_FAILURE,
1605 "",
1606 "",
1607 "^expected --master-key-writer to be not empty",
1608 PreCond::Keyring::none()},
1609
1610 {"list_master_key_reader_empty",
1611 "",
1612 {"list", "keyring", "--master-key-reader", ""},
1613 EXIT_FAILURE,
1614 "",
1615 "",
1616 "^expected --master-key-reader to be not empty",
1617 PreCond::Keyring::none()},
1618
1619 {"list_master_key_file_empty",
1620 "",
1621 {"list", "keyring", "--master-key-file", ""},
1622 EXIT_FAILURE,
1623 "",
1624 "",
1625 "^expected --master-key-file to be not empty",
1626 PreCond::Keyring::none()},
1627
1628 {
1629 "init_create_keyring",
1630 "WL12974::TS_FR6_1",
1631 {
1632 "init",
1633 kKeyringPlaceholder,
1634 "--master-key-file",
1635 kMasterKeyfilePlaceholder,
1636 },
1637 EXIT_SUCCESS,
1638 "",
1639 "",
1640 "^$",
1641 PreCond::Keyring::none() | PreCond::MasterKeyfile::none() |
1642 PostCond::Keyring::exists_and_secure() |
1643 PostCond::MasterKeyfile::exists_and_secure() |
1644 PostCond::MasterList::contains_keyfile(),
1645 },
1646
1647 {"init_create_keyring_subdir_no_exist",
1648 "WL12974::TS_FR6_1",
1649 {
1650 "init",
1651 kKeyringPlaceholder,
1652 "--master-key-file",
1653 kMasterKeyfilePlaceholder,
1654 },
1655 EXIT_FAILURE,
1656 "",
1657 "",
1658 "^failed saving keyring: Failed to open keyring file for writing: .*",
1659 PreCond::Keyring::none() | PreCond::MasterKeyfile::none() |
1660 PreCond::KeyringFilename::with_no_exist_directory() |
1661 PostCond::Keyring::not_exists()},
1662
1663 {"init_create_keyring_masterkeyfile_subdir_no_exist",
1664 "WL12974::TS_FR6_1",
1665 {
1666 "init",
1667 kKeyringPlaceholder,
1668 "--master-key-file",
1669 kMasterKeyfilePlaceholder,
1670 },
1671 EXIT_FAILURE,
1672 "",
1673 "",
1674 "^failed saving master-key-file: Could not open master key file",
1675 PreCond::Keyring::none() | PreCond::MasterKeyfile::none() |
1676 PreCond::MasterKeyfileFilename::with_no_exist_directory() |
1677 PostCond::Keyring::not_exists()},
1678
1679 {"init_update_keyring_create_master_keyfile",
1680 "WL12974::TS_FR6_2",
1681 {
1682 "init",
1683 "--master-key-file",
1684 kMasterKeyfilePlaceholder,
1685 kKeyringPlaceholder,
1686 },
1687 EXIT_SUCCESS,
1688 "",
1689 "",
1690 "^$",
1691 PreCond::Keyring::minimal() | PreCond::MasterKeyfile::none() |
1692 PostCond::Keyring::exists_and_secure() |
1693 PostCond::MasterKeyfile::exists_and_secure()},
1694
1695 // TS_FR6_3 tested by routertest_component_bootstrap
1696
1697 {"init_keyring_with_master_reader",
1698 "WL12974::TS_FR6_4",
1699 {
1700 "init",
1701 kKeyringPlaceholder,
1702 "--master-key-reader",
1703 kMasterKeyReaderPlaceholder,
1704 "--master-key-writer",
1705 kMasterKeyWriterPlaceholder,
1706 },
1707 EXIT_SUCCESS,
1708 "",
1709 "",
1710 "^$",
1711 PreCond::Keyring::none() | PreCond::MasterKeyfile::none() |
1712 PreCond::MasterKeyReader::succeeding() |
1713 PreCond::MasterKeyWriter::succeeding() |
1714 PostCond::Keyring::exists_and_secure() |
1715 PostCond::KeyringExport::empty_keys() |
1716 PostCond::MasterKeyfile::not_exists()},
1717
1718 {"init_without_keyring_with_master_reader",
1719 "WL12974::TS_FR6_5",
1720 {
1721 "init",
1722 "--master-key-file",
1723 kMasterKeyfilePlaceholder,
1724 },
1725 EXIT_FAILURE,
1726 "",
1727 "",
1728 "expected .*<filename>, got ",
1729 PreCond::Keyring::none() | PreCond::MasterKeyfile::minimal() |
1730 PostCond::Keyring::not_exists() |
1731 PostCond::MasterKeyfile::exists_and_secure()},
1732
1733 // TS_FR6_6 (same as TS_FR6_1)
1734
1735 // TS_FR7_1 tested by TS_FR6_1
1736 // TS_FR8_1 tested by TS_FR6_1
1737
1738 {
1739 "init_create_keyring_with_existing_master_key_file_with_one_entry",
1740 "WL12974::TS_FR8_2",
1741 {
1742 "init",
1743 kKeyringPlaceholder,
1744 "--master-key-file",
1745 kMasterKeyfilePlaceholder,
1746 },
1747 EXIT_SUCCESS,
1748 "",
1749 "",
1750 "^$",
1751 PreCond::Keyring::none() | PreCond::MasterKeyfile::valid_one_entry() |
1752 PostCond::Keyring::exists_and_secure() |
1753 PostCond::MasterKeyfile::exists_and_secure() |
1754 PostCond::MasterList::contains_keyfile(),
1755 },
1756
1757 // TS_FR8_3 tested by routertest_component_bootstrap
1758
1759 {
1760 "init_create_keyring_with_invalid_master_key_file",
1761 "WL12974::TS_FR8_4",
1762 {
1763 "init",
1764 kKeyringPlaceholder,
1765 "--master-key-file",
1766 kMasterKeyfilePlaceholder,
1767 },
1768 EXIT_FAILURE,
1769 "",
1770 "",
1771 "opening master-key-file failed: Master key file '.*' has invalid "
1772 "file signature",
1773 PreCond::Keyring::none() | PreCond::MasterKeyfile::empty() |
1774 PostCond::Keyring::not_exists() |
1775 PostCond::MasterKeyfile::exists_and_secure(),
1776 },
1777
1778 {"init_one_entry_keyring_without_master_key_file",
1779 "Bug#29949336",
1780 {
1781 "init",
1782 kKeyringPlaceholder,
1783 "--master-key-file",
1784 kMasterKeyfilePlaceholder,
1785 },
1786 EXIT_FAILURE,
1787 "",
1788 "",
1789 "^keyfile '.*' already exists and has entries",
1790 PreCond::Keyring::one_entry() | PreCond::MasterKeyfile::none() |
1791 PostCond::MasterKeyfile::not_exists()},
1792
1793 {"init_no_entry_keyring_without_master_key_file",
1794 "Bug#29949336",
1795 {
1796 "init",
1797 kKeyringPlaceholder,
1798 "--master-key-file",
1799 kMasterKeyfilePlaceholder,
1800 },
1801 EXIT_SUCCESS,
1802 "",
1803 "",
1804 "^$",
1805 PreCond::Keyring::no_entries() | PreCond::MasterKeyfile::none() |
1806 PostCond::MasterKeyfile::exists_and_secure()},
1807
1808 {
1809 "init_create_keyring_with_insecure_master_key_file",
1810 "WL12974::TS_FR8_4",
1811 {
1812 "init",
1813 kKeyringPlaceholder,
1814 "--master-key-file",
1815 kMasterKeyfilePlaceholder,
1816 },
1817 EXIT_FAILURE,
1818 "",
1819 "",
1820 "^opening master-key-file failed: '.*' has insecure permissions. "
1821 ".*: " +
1822 make_error_code(std::errc::permission_denied).message(),
1823 PreCond::Keyring::none() | PreCond::MasterKeyfile::insecure() |
1824 PostCond::Keyring::not_exists() | PostCond::MasterKeyfile::exists(),
1825 },
1826
1827 // Expectation of TS_FR8_6 is invalid:
1828 //
1829 // - "init" creates keyring if it doesn't exist.
1830
1831 {
1832 "init_create_keyring_with_master_key_writer",
1833 "WL12974::TS_FR9_1",
1834 {
1835 "init",
1836 kKeyringPlaceholder,
1837 "--master-key-writer",
1838 kMasterKeyWriterPlaceholder,
1839 "--master-key-reader",
1840 kMasterKeyReaderPlaceholder,
1841 },
1842 EXIT_SUCCESS,
1843 "",
1844 "",
1845 "^$",
1846 PreCond::Keyring::none() | PreCond::MasterKeyfile::none() |
1847 PreCond::MasterKeyReader::succeeding() |
1848 PreCond::MasterKeyWriter::succeeding() |
1849 PostCond::Keyring::exists_and_secure(),
1850 },
1851
1852 {
1853 "init_update_broken_keyring_master_with_key_writer",
1854 "WL12974::TS_FR9_2",
1855 {
1856 "init",
1857 kKeyringPlaceholder,
1858 "--master-key-writer",
1859 kMasterKeyWriterPlaceholder,
1860 "--master-key-reader",
1861 kMasterKeyReaderPlaceholder,
1862 },
1863 EXIT_FAILURE,
1864 "",
1865 "",
1866 "reading file-header of '.*' failed: File is too small",
1867 PreCond::Keyring::empty() | PreCond::MasterKeyfile::none() |
1868 PreCond::MasterKeyReader::succeeding() |
1869 PreCond::MasterKeyWriter::succeeding() |
1870 PostCond::Keyring::exists_and_secure() |
1871 PostCond::MasterKeyfile::not_exists(),
1872 },
1873
1874 {
1875 "init_with_empty_keyring_filename",
1876 "",
1877 {
1878 "init",
1879 "",
1880 "--master-key-file",
1881 kMasterKeyfilePlaceholder,
1882 },
1883 EXIT_FAILURE,
1884 "",
1885 "",
1886 "^expected <keyring> to be not empty",
1887 PreCond::MasterKeyfile::none() | PostCond::Keyring::not_exists() |
1888 PostCond::MasterKeyfile::not_exists(),
1889 },
1890
1891 {
1892 "init_with_subdirs",
1893 "WL12974::TS_IN_2",
1894 {
1895 "init",
1896 kKeyringPlaceholder,
1897 "--master-key-file",
1898 kMasterKeyfilePlaceholder,
1899 },
1900 EXIT_SUCCESS,
1901 "",
1902 "",
1903 "^$",
1904 PreCond::KeyringFilename::with_directory() | PreCond::Keyring::none() |
1905 PreCond::MasterKeyfileFilename::with_directory() |
1906 PreCond::MasterKeyfile::none() |
1907 PostCond::Keyring::exists_and_secure() |
1908 PostCond::MasterKeyfile::exists_and_secure() |
1909 PostCond::MasterList::contains_keyfile(),
1910 },
1911
1912 {
1913 "list_broken_master_key_reader",
1914 "WL12974::TS_FR10_xxx",
1915 {
1916 "list",
1917 kKeyringPlaceholder,
1918 "--master-key-writer",
1919 kMasterKeyWriterPlaceholder,
1920 "--master-key-reader",
1921 kMasterKeyReaderPlaceholder,
1922 },
1923 EXIT_FAILURE,
1924 "",
1925 "",
1926 "failed reading master-key for '.*' from master-key-reader '.*'",
1927 PreCond::Keyring::minimal() | PreCond::MasterKeyfile::none() |
1928 PreCond::MasterKeyReader::not_executable() |
1929 PostCond::Keyring::exists_and_secure() |
1930 PostCond::MasterKeyfile::not_exists(),
1931 },
1932
1933 {
1934 "list_insecure_master_key_file",
1935 "WL12974::TS_FR10_1",
1936 {
1937 "list",
1938 kKeyringPlaceholder,
1939 "--master-key-file",
1940 kMasterKeyfilePlaceholder,
1941 },
1942 EXIT_FAILURE,
1943 "",
1944 "",
1945 "^opening master-key-file failed: '.*' has insecure permissions.",
1946 PreCond::Keyring::minimal() | PreCond::MasterKeyfile::insecure() |
1947 PostCond::Keyring::exists_and_secure() |
1948 PostCond::MasterKeyfile::exists(),
1949 },
1950
1951 {
1952 "list_broken_master_key_file",
1953 "WL12974::TS_FR10_2",
1954 {
1955 "list",
1956 kKeyringPlaceholder,
1957 "--master-key-file",
1958 kMasterKeyfilePlaceholder,
1959 },
1960 EXIT_FAILURE,
1961 "",
1962 "",
1963 "^opening master-key-file failed: Master key file '.*' has invalid "
1964 "file signature",
1965 PreCond::Keyring::minimal() | PreCond::MasterKeyfile::empty() |
1966 PostCond::Keyring::exists_and_secure() |
1967 PostCond::MasterKeyfile::exists_and_secure(),
1968 },
1969
1970 {"list_multiple_users_with_master_key_file",
1971 "WL12974::TS_FR11_1",
1972 {
1973 "list",
1974 kKeyringPlaceholder,
1975 "--master-key-file",
1976 kMasterKeyfilePlaceholder,
1977 },
1978 EXIT_SUCCESS,
1979 "",
1980 "a\nb\nc\n",
1981 "^$",
1982 PreCond::Keyring::many_user_one_property() |
1983 PreCond::MasterKeyfile::none() |
1984 PostCond::Keyring::exists_and_secure()},
1985
1986 {"list_properties_of_user_with_master_key_file",
1987 "WL12974::TS_FR12_1",
1988 {
1989 "list",
1990 kKeyringPlaceholder,
1991 "c",
1992 "--master-key-file",
1993 kMasterKeyfilePlaceholder,
1994 },
1995 EXIT_SUCCESS,
1996 "",
1997 "Key1\nkey1\npassword\n",
1998 "^$",
1999 PreCond::Keyring::many_user_one_property() |
2000 PreCond::MasterKeyfile::none() |
2001 PostCond::Keyring::exists_and_secure()},
2002
2003 {"list_unknown_user_with_master_key_file",
2004 "WL12974::TS_FR13_1",
2005 {
2006 "list",
2007 kKeyringPlaceholder,
2008 "d",
2009 "--master-key-file",
2010 kMasterKeyfilePlaceholder,
2011 },
2012 EXIT_FAILURE,
2013 "",
2014 "",
2015 "^$",
2016 PreCond::Keyring::many_user_one_property() |
2017 PreCond::MasterKeyfile::none() |
2018 PostCond::Keyring::exists_and_secure()},
2019
2020 {"list_unknown_property_with_master_key_file",
2021 "WL12974::TS_FR13_1",
2022 {
2023 "list",
2024 kKeyringPlaceholder,
2025 "d",
2026 "--master-key-file",
2027 kMasterKeyfilePlaceholder,
2028 },
2029 EXIT_FAILURE,
2030 "",
2031 "",
2032 "^$",
2033 PreCond::Keyring::many_user_one_property() |
2034 PreCond::MasterKeyfile::none() |
2035 PostCond::Keyring::exists_and_secure()},
2036
2037 {"list_long_username_with_master_key_file",
2038 "WL12974::TS_LI_1",
2039 {
2040 "list",
2041 kKeyringPlaceholder,
2042 std::string(128 * 1024, 'a'),
2043 "--master-key-file",
2044 kMasterKeyfilePlaceholder,
2045 },
2046 EXIT_SUCCESS,
2047 "",
2048 "password\n",
2049 "^$",
2050 PreCond::Keyring::long_username() |
2051 PostCond::MasterKeyfile::exists_and_secure() |
2052 PostCond::Keyring::exists_and_secure()},
2053
2054 {"get_property_of_user_with_master_key_file",
2055 "WL12974::TS_FR14_1",
2056 {
2057 "get",
2058 kKeyringPlaceholder,
2059 "c",
2060 "password",
2061 "--master-key-file",
2062 kMasterKeyfilePlaceholder,
2063 },
2064 EXIT_SUCCESS,
2065 "",
2066 "baz\n",
2067 "^$",
2068 PreCond::Keyring::many_user_one_property() |
2069 PreCond::MasterKeyfile::none() |
2070 PostCond::Keyring::exists_and_secure()},
2071
2072 {"get_long_property_of_user_with_master_key_file",
2073 "WL12974::TS_FR14_2", // and TS_FR18_2
2074 {
2075 "get",
2076 kKeyringPlaceholder,
2077 "long",
2078 "long",
2079 "--master-key-file",
2080 kMasterKeyfilePlaceholder,
2081 },
2082 EXIT_SUCCESS,
2083 "",
2084 std::string(128 * 1024, 'a') + "\n",
2085 "^$",
2086 PreCond::Keyring::long_property() | PreCond::MasterKeyfile::none() |
2087 PostCond::Keyring::exists_and_secure()},
2088
2089 {"get_unknown_property_of_user_with_master_key_file",
2090 "WL12974::TS_FR15_1",
2091 {
2092 "get",
2093 kKeyringPlaceholder,
2094 "long",
2095 "unknown",
2096 "--master-key-file",
2097 kMasterKeyfilePlaceholder,
2098 },
2099 EXIT_FAILURE,
2100 "",
2101 "",
2102 "^'unknown' not found for user 'long'",
2103 PreCond::Keyring::long_property() | PreCond::MasterKeyfile::none() |
2104 PostCond::Keyring::exists_and_secure()},
2105
2106 {"get_unknown_user_with_master_key_file",
2107 "WL12974::TS_FR16_1",
2108 {
2109 "get",
2110 kKeyringPlaceholder,
2111 "unknown",
2112 "unknown",
2113 "--master-key-file",
2114 kMasterKeyfilePlaceholder,
2115 },
2116 EXIT_FAILURE,
2117 "",
2118 "",
2119 "^'unknown' not found for user 'unknown'",
2120 PreCond::Keyring::many_user_one_property() |
2121 PreCond::MasterKeyfile::none() |
2122 PostCond::Keyring::exists_and_secure()},
2123
2124 {"get_property_of_user_with_master_key_file_and_broken_keyfile",
2125 "WL12974::TS_GE_1",
2126 {
2127 "get",
2128 kKeyringPlaceholder,
2129 "c",
2130 "password",
2131 "--master-key-file",
2132 kMasterKeyfilePlaceholder,
2133 },
2134 EXIT_FAILURE,
2135 "",
2136 "",
2137 "^opening keyring failed: reading file-header of '.*' failed: File is "
2138 "too "
2139 "small",
2140 PreCond::Keyring::empty() | PreCond::MasterKeyfile::none() |
2141 PostCond::Keyring::exists_and_secure()},
2142
2143 {"export_with_master_key_file",
2144 "WL12974::TS_FR17_1",
2145 {
2146 "export",
2147 kKeyringPlaceholder,
2148 "--master-key-file",
2149 kMasterKeyfilePlaceholder,
2150 },
2151 EXIT_SUCCESS,
2152 "",
2153 "{\n"
2154 " \"\\u0000\": {\n"
2155 " \"key1\": \"fuU\"\n"
2156 " },\n"
2157 " \"\\t\": {\n"
2158 " \"key1\": \"fuU\"\n"
2159 " },\n"
2160 " \"\\n\": {\n"
2161 " \"key1\": \"fuU\"\n"
2162 " },\n"
2163 " \"\\r\": {\n"
2164 " \"key1\": \"fuU\"\n"
2165 " },\n"
2166 " \"\\\"\": {\n"
2167 " \"Key1\": \"fuu\"\n"
2168 " },\n"
2169 " \"\\\"NULL\\\"\": {\n"
2170 " \"key1\": \"fuU\"\n"
2171 " },\n"
2172 " \"'\": {\n"
2173 " \"key1\": \"fuU\"\n"
2174 " },\n"
2175 " \"A\": {\n"
2176 " \"\\n\": \"\\u0000\",\n"
2177 " \"<\": \">\",\n"
2178 " \"name\": \"\"\n"
2179 " },\n"
2180 " \"B\": {\n"
2181 " \"password\": \"bar\"\n"
2182 " },\n"
2183 " \"{\": {\n"
2184 " \"password\": \"baz\"\n"
2185 " }\n"
2186 "}\n",
2187 "^$",
2188 PreCond::Keyring::special_properties() | PreCond::MasterKeyfile::none() |
2189 PostCond::Keyring::exists_and_secure()},
2190
2191 {"export_with_broken_keyring_and_master_key_file",
2192 "WL12974::TS_EX_1",
2193 {
2194 "export",
2195 kKeyringPlaceholder,
2196 "--master-key-file",
2197 kMasterKeyfilePlaceholder,
2198 },
2199 EXIT_FAILURE,
2200 "",
2201 "",
2202 "^opening keyring failed: reading file-header of '.*' failed: File is "
2203 "too "
2204 "small",
2205 PreCond::Keyring::empty() | PreCond::MasterKeyfile::none() |
2206 PostCond::Keyring::exists_and_secure()},
2207
2208 {"set_with_master_key_file",
2209 "WL12974::TS_FR18_1",
2210 {
2211 // set is tested but preparing the right keyring
2212 "export",
2213 kKeyringPlaceholder,
2214 "--master-key-file",
2215 kMasterKeyfilePlaceholder,
2216 },
2217 EXIT_SUCCESS,
2218 "",
2219 "{\n"
2220 " \"a\": {\n"
2221 " \"password\": \"foo\"\n"
2222 " },\n"
2223 " \"b\": {\n"
2224 " \"password\": \"bar\"\n"
2225 " },\n"
2226 " \"c\": {\n"
2227 " \"Key1\": \"fuu\",\n"
2228 " \"key1\": \"fuU\",\n"
2229 " \"password\": \"baz\"\n"
2230 " }\n"
2231 "}\n",
2232
2233 "^$",
2234 PreCond::Keyring::many_user_one_property() |
2235 PreCond::MasterKeyfile::none() |
2236 PostCond::Keyring::exists_and_secure()},
2237
2238 {"set_with_value_from_stdin_master_key_file",
2239 "WL12974::TS_FR18_3",
2240 {
2241 "set",
2242 kKeyringPlaceholder,
2243 "a",
2244 "password",
2245 "--master-key-file",
2246 kMasterKeyfilePlaceholder,
2247 },
2248 EXIT_SUCCESS,
2249 "somevalue",
2250 "",
2251 "^$",
2252 PreCond::Keyring::inited() | PostCond::Keyring::exists_and_secure() |
2253 PostCond::KeyringExport::user_a_password_stdin_value()},
2254
2255 {"set_with_empty_value_from_stdin_master_key_file",
2256 "WL12974::TS_FR18_4",
2257 {
2258 "set",
2259 kKeyringPlaceholder,
2260 "a",
2261 "password",
2262 "--master-key-file",
2263 kMasterKeyfilePlaceholder,
2264 },
2265 EXIT_SUCCESS,
2266 "",
2267 "",
2268 "^$",
2269 PreCond::Keyring::inited() | PostCond::Keyring::exists_and_secure() |
2270 PostCond::KeyringExport::user_a_password_stdin_value()},
2271
2272 {"set_same_with_master_key_file",
2273 "WL12974::TS_FR18_5",
2274 {
2275 "set",
2276 kKeyringPlaceholder,
2277 "a",
2278 "password",
2279 "foo",
2280 "--master-key-file",
2281 kMasterKeyfilePlaceholder,
2282 },
2283 EXIT_SUCCESS,
2284 "",
2285 "",
2286 "^$",
2287 PreCond::Keyring::one_user_one_property() |
2288 PostCond::Keyring::exists_and_secure() |
2289 PostCond::KeyringExport::user_a_password_foo()},
2290
2291 {"set_other_password_with_master_key_file",
2292 "WL12974::TS_FR18_6",
2293 {
2294 "set",
2295 kKeyringPlaceholder,
2296 "a",
2297 "password",
2298 "other",
2299 "--master-key-file",
2300 kMasterKeyfilePlaceholder,
2301 },
2302 EXIT_SUCCESS,
2303 "",
2304 "",
2305 "^$",
2306 PreCond::Keyring::one_user_one_property() |
2307 PostCond::Keyring::exists_and_secure() |
2308 PostCond::KeyringExport::user_a_password_other()},
2309
2310 {"set_value_in_empty_keyring_with_master_key_file",
2311 "WL12974::TS_FR18_7",
2312 {
2313 "set",
2314 kKeyringPlaceholder,
2315 "a",
2316 "password",
2317 "other",
2318 "--master-key-file",
2319 kMasterKeyfilePlaceholder,
2320 },
2321 EXIT_SUCCESS,
2322 "",
2323 "",
2324 "^$",
2325 PreCond::Keyring::inited() | PostCond::Keyring::exists_and_secure() |
2326 PostCond::KeyringExport::user_a_password_other()},
2327
2328 // TS_SE_1 can't be implemented
2329 // TS_SE_2 can't be implemented
2330
2331 {"delete_value_with_master_key_file",
2332 "WL12974::TS_FR19_1",
2333 {
2334 "delete",
2335 kKeyringPlaceholder,
2336 "c",
2337 "password",
2338 "--master-key-file",
2339 kMasterKeyfilePlaceholder,
2340 },
2341 EXIT_SUCCESS,
2342 "",
2343 "",
2344 "^$",
2345 PreCond::Keyring::many_user_one_property() |
2346 PostCond::Keyring::exists_and_secure() |
2347 PostCond::KeyringExport::many_user_one_property_no_c_password()},
2348
2349 {"delete_value_empty_prop_with_master_key_file",
2350 "WL12974::TS_FR19_2",
2351 {
2352 "delete",
2353 kKeyringPlaceholder,
2354 "b",
2355 "password",
2356 "--master-key-file",
2357 kMasterKeyfilePlaceholder,
2358 },
2359 EXIT_SUCCESS,
2360 "",
2361 "",
2362 "^$",
2363 PreCond::Keyring::many_user_one_property() |
2364 PostCond::Keyring::exists_and_secure() |
2365 PostCond::KeyringExport::many_user_one_property_b_removed()},
2366
2367 {"delete_unknown_user_with_property_with_master_key_file",
2368 "WL12974::TS_FR20_1",
2369 {
2370 "delete",
2371 kKeyringPlaceholder,
2372 "unknown",
2373 "password",
2374 "--master-key-file",
2375 kMasterKeyfilePlaceholder,
2376 },
2377 EXIT_FAILURE,
2378 "",
2379 "",
2380 "^$",
2381 PreCond::Keyring::many_user_one_property() |
2382 PostCond::Keyring::exists_and_secure() |
2383 PostCond::KeyringExport::many_user_one_property()},
2384
2385 {"delete_unknown_prop_with_master_key_file",
2386 "WL12974::TS_FR20_2",
2387 {
2388 "delete",
2389 kKeyringPlaceholder,
2390 "a",
2391 "unknown",
2392 "--master-key-file",
2393 kMasterKeyfilePlaceholder,
2394 },
2395 EXIT_FAILURE,
2396 "",
2397 "",
2398 "^$",
2399 PreCond::Keyring::many_user_one_property() |
2400 PostCond::Keyring::exists_and_secure() |
2401 PostCond::KeyringExport::many_user_one_property()},
2402
2403 {"delete_user_from_one_entry_keyring_with_master_key_file",
2404 "WL12974::TS_FR21_1",
2405 {
2406 "delete",
2407 kKeyringPlaceholder,
2408 "a",
2409 "--master-key-file",
2410 kMasterKeyfilePlaceholder,
2411 },
2412 EXIT_SUCCESS,
2413 "",
2414 "",
2415 "^$",
2416 PreCond::Keyring::one_user_one_property() |
2417 PostCond::Keyring::exists_and_secure() |
2418 PostCond::KeyringExport::empty_keys()},
2419
2420 {"delete_user_from_many_entry_keyring_with_master_key_file",
2421 "WL12974::TS_FR21_2",
2422 {
2423 "delete",
2424 kKeyringPlaceholder,
2425 "b",
2426 "--master-key-file",
2427 kMasterKeyfilePlaceholder,
2428 },
2429 EXIT_SUCCESS,
2430 "",
2431 "",
2432 "^$",
2433 PreCond::Keyring::many_user_one_property() |
2434 PostCond::Keyring::exists_and_secure() |
2435 PostCond::KeyringExport::many_user_one_property_b_removed()},
2436
2437 // TS_FR21_3 is implicitely tested by all
2438 {"delete_unknown_user_with_master_key_file",
2439 "WL12974::TS_FR21_2",
2440 {
2441 "delete",
2442 kKeyringPlaceholder,
2443 "unknown",
2444 "--master-key-file",
2445 kMasterKeyfilePlaceholder,
2446 },
2447 EXIT_FAILURE,
2448 "",
2449 "",
2450 "^$",
2451 PreCond::Keyring::many_user_one_property() |
2452 PostCond::Keyring::exists_and_secure() |
2453 PostCond::KeyringExport::many_user_one_property()},
2454
2455 {"delete_unknown_user_empty_keyring_with_master_key_file",
2456 "WL12974::TS_FR22_1",
2457 {
2458 "delete",
2459 kKeyringPlaceholder,
2460 "unknown",
2461 "--master-key-file",
2462 kMasterKeyfilePlaceholder,
2463 },
2464 EXIT_FAILURE,
2465 "",
2466 "",
2467 "^$",
2468 PreCond::Keyring::inited() | PostCond::Keyring::exists_and_secure() |
2469 PostCond::KeyringExport::empty_keys()},
2470
2471 {"delete_unknown_user_one_entry_keyring_with_master_key_file",
2472 "WL12974::TS_FR22_2",
2473 {
2474 "delete",
2475 kKeyringPlaceholder,
2476 "unknown",
2477 "--master-key-file",
2478 kMasterKeyfilePlaceholder,
2479 },
2480 EXIT_FAILURE,
2481 "",
2482 "",
2483 "^$",
2484 PreCond::Keyring::one_user_one_property() |
2485 PostCond::Keyring::exists_and_secure() |
2486 PostCond::KeyringExport::user_a_password_foo()},
2487
2488 {"master_list_with_subdir_keyring",
2489 "WL12974::TS_FR23_1",
2490 {
2491 "init",
2492 kKeyringPlaceholder,
2493 "--master-key-file",
2494 kMasterKeyfilePlaceholder,
2495 },
2496 EXIT_SUCCESS,
2497 "",
2498 "",
2499 "^$",
2500 PreCond::KeyringFilename::with_directory() |
2501 PreCond::MasterKeyfile::none() |
2502 PostCond::MasterList::contains_keyfile()},
2503
2504 {"master_list_with_two_entry_master_key_file",
2505 "WL12974::TS_FR23_2",
2506 {
2507 "init",
2508 kKeyringPlaceholder,
2509 "--master-key-file",
2510 kMasterKeyfilePlaceholder,
2511 },
2512 EXIT_SUCCESS,
2513 "",
2514 "",
2515 "^$",
2516 PreCond::MasterKeyfile::valid_one_entry() |
2517 PostCond::MasterList::contains_keyfile_and_one_more()},
2518
2519 {"master_list_with_two_entry_master_key_file_no_keyrings",
2520 "WL12974::TS_FR23_3",
2521 {
2522 "master-list",
2523 "--master-key-file",
2524 kMasterKeyfilePlaceholder,
2525 },
2526 EXIT_SUCCESS,
2527 "",
2528 "foo.key\n",
2529 "^$",
2530 PreCond::MasterKeyfile::valid_one_entry()},
2531
2532 {"master_list_with_empty_master_key_file",
2533 "WL12974::TS_FR23_4",
2534 {
2535 "master-list",
2536 "--master-key-file",
2537 kMasterKeyfilePlaceholder,
2538 },
2539 EXIT_SUCCESS,
2540 "",
2541 "",
2542 "^$",
2543 PreCond::MasterKeyfile::minimal()},
2544
2545 {"master_list_with_broken_master_key_file",
2546 "WL12974::TS_MKL_1",
2547 {
2548 "master-list",
2549 "--master-key-file",
2550 kMasterKeyfilePlaceholder,
2551 },
2552 EXIT_FAILURE,
2553 "",
2554 "",
2555 "^opening master-key-file failed: Master key file '.*' has invalid file "
2556 "signature",
2557 PreCond::MasterKeyfile::empty()},
2558
2559 {"master_delete_with_master_key_file",
2560 "WL12974::TS_FR24_1",
2561 {
2562 "master-delete",
2563 "foo.key",
2564 "--master-key-file",
2565 kMasterKeyfilePlaceholder,
2566 },
2567 EXIT_SUCCESS,
2568 "",
2569 "",
2570 "^$",
2571 PreCond::MasterKeyfile::valid_one_entry() | PostCond::MasterList::none()},
2572
2573 {"master_delete_with_empty_master_key_file",
2574 "WL12974::TS_FR24_2",
2575 {
2576 "master-delete",
2577 "foo.key",
2578 "--master-key-file",
2579 kMasterKeyfilePlaceholder,
2580 },
2581 EXIT_FAILURE,
2582 "",
2583 "",
2584 "^Keyring '.*' not found in master-key-file '.*'",
2585 PreCond::MasterKeyfile::minimal() | PostCond::MasterList::none()},
2586
2587 {"master_delete_from_many_with_master_key_file",
2588 "WL12974::TS_FR24_3",
2589 {
2590 "master-delete",
2591 "foo.key",
2592 "--master-key-file",
2593 kMasterKeyfilePlaceholder,
2594 },
2595 EXIT_SUCCESS,
2596 "",
2597 "",
2598 "^$",
2599 PreCond::MasterKeyfile::valid_foo_bar_baz() |
2600 PostCond::MasterList::bar_baz()},
2601
2602 {"master_delete_with_broken_master_key_file",
2603 "WL12974::TS_FR24_4",
2604 {
2605 "master-delete",
2606 "foo.key",
2607 "--master-key-file",
2608 kMasterKeyfilePlaceholder,
2609 },
2610 EXIT_FAILURE,
2611 "",
2612 "",
2613 "^opening master-key-file failed: Master key file '.*' has invalid file "
2614 "signature",
2615 PreCond::MasterKeyfile::empty() | PostCond::MasterList::none()},
2616
2617 {"master_delete_unknown_with_master_key_file",
2618 "WL12974::TS_FR24_5",
2619 {
2620 "master-delete",
2621 "unknown",
2622 "--master-key-file",
2623 kMasterKeyfilePlaceholder,
2624 },
2625 EXIT_FAILURE,
2626 "",
2627 "",
2628 "^Keyring 'unknown' not found in master-key-file '.*'",
2629 PreCond::MasterKeyfile::valid_one_entry()},
2630
2631 {"master_delete_absolute_path_with_master_key_file",
2632 "WL12974::TS_FR24_6",
2633 {
2634 "master-delete",
2635 kKeyringPlaceholder,
2636 "--master-key-file",
2637 kMasterKeyfilePlaceholder,
2638 },
2639 EXIT_SUCCESS,
2640 "",
2641 "",
2642 "^$",
2643 PreCond::KeyringFilename::absolute() | PreCond::Keyring::inited() |
2644 PostCond::MasterList::empty()},
2645
2646 {"master_delete_missing_keyring_with_master_key_file",
2647 "WL12974::TS_FR24_7",
2648 {
2649 "master-delete",
2650 "--master-key-file",
2651 kMasterKeyfilePlaceholder,
2652 },
2653 EXIT_FAILURE,
2654 "",
2655 "",
2656 "^expected .*<filename>.*, got",
2657 PreCond::MasterKeyfile::valid_one_entry()},
2658
2659 {"master_delete_keyring_with_master_key_reader",
2660 "WL12974::TS_FR24_8",
2661 {
2662 "master-delete",
2663 "foo.key",
2664 "--master-key-reader",
2665 kMasterKeyReaderPlaceholder,
2666 "--master-key-writer",
2667 kMasterKeyWriterPlaceholder,
2668 },
2669 EXIT_FAILURE,
2670 "",
2671 "",
2672 "^expected --master-key-file to be not empty",
2673 PreCond::MasterKeyfile::valid_one_entry()},
2674
2675 {"master_rename",
2676 "WL12974::TS_FR25_1",
2677 {
2678 "master-rename",
2679 kKeyringPlaceholder,
2680 "foo.key",
2681 "--master-key-file",
2682 kMasterKeyfilePlaceholder,
2683 },
2684 EXIT_SUCCESS,
2685 "",
2686 "",
2687 "^$",
2688 PreCond::Keyring::inited() | PostCond::MasterList::one_entry() |
2689 PostCond::MasterKeyfile::exists_and_secure()},
2690
2691 {"master_rename_keyring_not_exists",
2692 "WL12974::TS_FR25_2",
2693 {
2694 "master-rename",
2695 "foo.key",
2696 kKeyringPlaceholder,
2697 "--master-key-file",
2698 kMasterKeyfilePlaceholder,
2699 },
2700 EXIT_SUCCESS,
2701 "",
2702 "",
2703 "^$",
2704 PreCond::MasterKeyfile::valid_one_entry() |
2705 PostCond::MasterList::contains_keyfile() |
2706 PostCond::MasterKeyfile::exists_and_secure()},
2707
2708 {"master_rename_0_char",
2709 "WL12974::TS_FR25_2.2",
2710 {
2711 "master-rename",
2712 "foo.key",
2713 std::string("\0", 1),
2714 "--master-key-file",
2715 kMasterKeyfilePlaceholder,
2716 },
2717 EXIT_FAILURE,
2718 "",
2719 "",
2720 "^expected <new-key> to contain only printable characters",
2721 PreCond::MasterKeyfile::valid_one_entry() |
2722 PostCond::MasterList::one_entry() |
2723 PostCond::MasterKeyfile::exists_and_secure()},
2724
2725 {"master_rename_empty_new_key",
2726 "WL12974::TS_FR25_2.3",
2727 {
2728 "master-rename",
2729 "foo.key",
2730 "",
2731 "--master-key-file",
2732 kMasterKeyfilePlaceholder,
2733 },
2734 EXIT_FAILURE,
2735 "",
2736 "",
2737 "^expected <new-key> to be not empty",
2738 PreCond::MasterKeyfile::valid_one_entry() |
2739 PostCond::MasterList::one_entry() |
2740 PostCond::MasterKeyfile::exists_and_secure()},
2741
2742 {"master_rename_missing_new_key",
2743 "WL12974::TS_FR25_3",
2744 {
2745 "master-rename",
2746 "foo.key",
2747 "--master-key-file",
2748 kMasterKeyfilePlaceholder,
2749 },
2750 EXIT_FAILURE,
2751 "",
2752 "",
2753 "^expected 2 arguments <old-key> <new-key>, got 1",
2754 PreCond::MasterKeyfile::valid_one_entry() |
2755 PostCond::MasterList::one_entry() |
2756 PostCond::MasterKeyfile::exists_and_secure()},
2757
2758 {"master_rename_unknown_old_key",
2759 "WL12974::TS_FR25_4",
2760 {
2761 "master-rename",
2762 "unknown",
2763 "foo.key",
2764 "--master-key-file",
2765 kMasterKeyfilePlaceholder,
2766 },
2767 EXIT_FAILURE,
2768 "",
2769 "",
2770 "^old-key 'unknown' not found in master-key-file '.*'",
2771 PreCond::MasterKeyfile::valid_one_entry() |
2772 PostCond::MasterKeyfile::exists_and_secure()},
2773
2774 {"master_rename_same_key",
2775 "WL12974::TS_FR25_5",
2776 {
2777 "master-rename",
2778 "foo.key",
2779 "foo.key",
2780 "--master-key-file",
2781 kMasterKeyfilePlaceholder,
2782 },
2783 EXIT_FAILURE,
2784 "",
2785 "",
2786 "^new-key 'foo.key' already exists in master-key-file '.*'",
2787 PreCond::MasterKeyfile::valid_one_entry() |
2788 PostCond::MasterKeyfile::exists_and_secure()},
2789
2790 {"master_rename_broken_master_key_file",
2791 "WL12974::TS_FR25_6",
2792 {
2793 "master-rename",
2794 "foo.key",
2795 "bar.key",
2796 "--master-key-file",
2797 kMasterKeyfilePlaceholder,
2798 },
2799 EXIT_FAILURE,
2800 "",
2801 "",
2802 "^opening master-key-file failed: Master key file '.*' has invalid file "
2803 "signature",
2804 PreCond::MasterKeyfile::empty() |
2805 PostCond::MasterKeyfile::exists_and_secure()},
2806
2807 {"master_rename_missing_new_key_and_old_key",
2808 "WL12974::TS_FR25_7",
2809 {
2810 "master-rename",
2811 "--master-key-file",
2812 kMasterKeyfilePlaceholder,
2813 },
2814 EXIT_FAILURE,
2815 "",
2816 "",
2817 "^expected 2 arguments <old-key> <new-key>, got 0",
2818 PreCond::MasterKeyfile::valid_one_entry() |
2819 PostCond::MasterList::one_entry() |
2820 PostCond::MasterKeyfile::exists_and_secure()},
2821
2822 };
2823
2824 INSTANTIATE_TEST_SUITE_P(Spec, KeyringFrontendTest,
2825 ::testing::ValuesIn(password_frontend_param),
__anonc49a43500302(const auto ¶m_info) 2826 [](const auto ¶m_info) {
2827 return param_info.param.test_name +
2828 (param_info.param.exit_code == EXIT_SUCCESS
2829 ? "_succeeds"s
2830 : "_fails"s);
2831 });
2832
2833 #define TS_FR1_1(CMD, ...) \
2834 { \
2835 CMD "_with_master_key_file_and_master_key_reader", "WL12974::TS-FR1_1", \
2836 { \
2837 CMD, __VA_ARGS__, "--master-key-file", \
2838 "foo", "--master-key-reader", "bar", \
2839 }, \
2840 EXIT_FAILURE, "", "", \
2841 "--master-key-file and --master-key-reader can't be used together", {} \
2842 }
2843
2844 #define TS_FR1_2(CMD, ...) \
2845 { \
2846 CMD "_with_master_key_file_and_master_key_writer", "WL12974::TS-FR1_2", \
2847 { \
2848 CMD, __VA_ARGS__, "--master-key-file", \
2849 "foo", "--master-key-writer", "bar", \
2850 }, \
2851 EXIT_FAILURE, "", "", \
2852 "--master-key-file and --master-key-writer can't be used together", {} \
2853 }
2854
2855 #define TS_FR1_3(CMD, ...) \
2856 { \
2857 CMD "_with_master_key_file_and_master_key_reader_and_master_key_writer", \
2858 "WL12974::TS-FR1_3", \
2859 { \
2860 CMD, \
2861 __VA_ARGS__, \
2862 "--master-key-file", \
2863 "foo", \
2864 "--master-key-writer", \
2865 "bar", \
2866 "--master-key-reader", \
2867 "baz", \
2868 \
2869 }, \
2870 EXIT_FAILURE, "", "", \
2871 "--master-key-file and --master-key-reader can't be used together", {} \
2872 }
2873
2874 #define TS_FR1_4(CMD, ...) \
2875 { \
2876 CMD "_empty_master_key", "WL12974::TS-FR1_4", \
2877 { \
2878 CMD, \
2879 __VA_ARGS__, \
2880 }, \
2881 EXIT_FAILURE, "", "", "expected master-key for '.*' to be not empty", \
2882 {} \
2883 }
2884
2885 #define TS_H_3(CMD, ...) \
2886 { \
2887 "dashdash_help_and_" CMD, "WL12974::TS_H_3", \
2888 { \
2889 "--help", \
2890 CMD, \
2891 __VA_ARGS__, \
2892 }, \
2893 EXIT_FAILURE, "", "", "expected no extra arguments", {} \
2894 }
2895
2896 #define TS_V_3(CMD, ...) \
2897 { \
2898 "dashdash_version_and_" CMD, "WL12974::TS_V_3", \
2899 { \
2900 "--version", \
2901 CMD, \
2902 __VA_ARGS__, \
2903 }, \
2904 EXIT_FAILURE, "", "", "expected no extra arguments", {} \
2905 }
2906
2907 #define TS_KR_1(CMD, ...) \
2908 { \
2909 CMD "_with_master_key_reader_empty_and_master_key_writer", \
2910 "WL12974::TS_KR_1", \
2911 { \
2912 CMD, __VA_ARGS__, "--master-key-writer", \
2913 "bar", "--master-key-reader", "", \
2914 \
2915 }, \
2916 EXIT_FAILURE, "", "", "^expected --master-key-reader to be not empty", \
2917 {} \
2918 }
2919
2920 #define TS_KR_2(CMD, ...) \
2921 { \
2922 CMD "_with_broken_master_key_reader_empty_and_master_key_writer", \
2923 "WL12974::TS_KR_2", \
2924 { \
2925 CMD, \
2926 __VA_ARGS__, \
2927 "--master-key-writer", \
2928 kMasterKeyWriterPlaceholder, \
2929 "--master-key-reader", \
2930 kMasterKeyReaderPlaceholder, \
2931 \
2932 }, \
2933 EXIT_FAILURE, "", "", \
2934 "failed reading master-key for '.*' from master-key-reader '.*'", \
2935 PreCond::MasterKeyReader::failing() \
2936 }
2937
2938 #define TS_KR_3(CMD, ...) \
2939 { \
2940 CMD "_with_not_executable_master_key_reader_empty_and_master_key_writer", \
2941 "WL12974::TS_KR_3", \
2942 { \
2943 CMD, \
2944 __VA_ARGS__, \
2945 "--master-key-writer", \
2946 kMasterKeyWriterPlaceholder, \
2947 "--master-key-reader", \
2948 kMasterKeyReaderPlaceholder, \
2949 \
2950 }, \
2951 EXIT_FAILURE, "", "", \
2952 "failed reading master-key for '.*' from master-key-reader '.*'", \
2953 PreCond::MasterKeyReader::not_executable() \
2954 }
2955
2956 #define TS_KW_1(CMD, ...) \
2957 { \
2958 CMD "_with_master_key_writer_empty_and_master_key_reader", \
2959 "WL12974::TS_KW_1", \
2960 { \
2961 CMD, __VA_ARGS__, "--master-key-writer", \
2962 "", "--master-key-reader", kMasterKeyReaderPlaceholder, \
2963 \
2964 }, \
2965 EXIT_FAILURE, "", "", "^expected --master-key-writer to be not empty", \
2966 PreCond::MasterKeyReader::succeeding() \
2967 }
2968
2969 #define TS_KW_2(CMD, ...) \
2970 { \
2971 CMD "_with_broken_master_key_writer_and_master_key_reader", \
2972 "WL12974::TS_KW_2", \
2973 { \
2974 CMD, \
2975 __VA_ARGS__, \
2976 "--master-key-writer", \
2977 kMasterKeyWriterPlaceholder, \
2978 "--master-key-reader", \
2979 kMasterKeyReaderPlaceholder, \
2980 \
2981 }, \
2982 EXIT_FAILURE, "", "", \
2983 "failed writing master-key for '.*' to master-key-writer '.*'", \
2984 PreCond::MasterKeyReader::key_not_found() | \
2985 PreCond::MasterKeyWriter::failing() \
2986 }
2987
2988 #define TS_KW_3(CMD, ...) \
2989 { \
2990 CMD "_with_not_executable_master_key_writer_and_master_key_reader", \
2991 "WL12974::TS_KW_3", \
2992 { \
2993 CMD, \
2994 __VA_ARGS__, \
2995 "--master-key-writer", \
2996 kMasterKeyWriterPlaceholder, \
2997 "--master-key-reader", \
2998 kMasterKeyReaderPlaceholder, \
2999 \
3000 }, \
3001 EXIT_FAILURE, "", "", \
3002 "failed writing master-key for '.*' to master-key-writer '.*'", \
3003 PreCond::MasterKeyReader::key_not_found() | \
3004 PreCond::MasterKeyWriter::not_executable() \
3005 }
3006
3007 #define TS_KF_1(CMD, ...) \
3008 { \
3009 CMD "_with_not_existing_master_key_file", "WL12974::TS_KF_1", \
3010 { \
3011 CMD, \
3012 __VA_ARGS__, \
3013 "--master-key-file", \
3014 kMasterKeyfilePlaceholder, \
3015 }, \
3016 EXIT_FAILURE, "", "", \
3017 "opening master-key-file failed: Can't open file ", \
3018 PreCond::Keyring::minimal() \
3019 }
3020
3021 #define TS_KF_1_no_args(CMD) \
3022 { \
3023 CMD "_with_not_existing_master_key_file", "WL12974::TS_KF_1", \
3024 { \
3025 CMD, \
3026 "--master-key-file", \
3027 kMasterKeyfilePlaceholder, \
3028 }, \
3029 EXIT_FAILURE, "", "", \
3030 "opening master-key-file failed: Can't open file ", \
3031 PreCond::Keyring::minimal() \
3032 }
3033
3034 #define TS_KF_2(CMD, ...) \
3035 { \
3036 CMD "_with_master_key_file_empty", "WL12974::TS_KF_2", \
3037 { \
3038 CMD, \
3039 __VA_ARGS__, \
3040 "--master-key-file", \
3041 "", \
3042 }, \
3043 EXIT_FAILURE, "", "", "^expected --master-key-file to be not empty", \
3044 PreCond::Keyring::minimal() \
3045 }
3046
3047 #define TS_KF_2_no_args(CMD) \
3048 { \
3049 CMD "_with_master_key_file_empty", "WL12974::TS_KF_2", \
3050 { \
3051 CMD, \
3052 "--master-key-file", \
3053 "", \
3054 }, \
3055 EXIT_FAILURE, "", "", "^expected --master-key-file to be not empty", \
3056 PreCond::Keyring::minimal() \
3057 }
3058
3059 #define TS_KF_3(CMD, ...) \
3060 { \
3061 CMD "_with_no_master_key_file", "WL12974::TS_KF_3", \
3062 { \
3063 CMD, \
3064 __VA_ARGS__, \
3065 }, \
3066 EXIT_FAILURE, "", "", "^expected --master-key-file to be not empty", \
3067 PreCond::Keyring::minimal() \
3068 }
3069
3070 #define TS_KF_3_no_args(CMD) \
3071 { \
3072 CMD "_with_no_master_key_file", "WL12974::TS_KF_3", \
3073 { \
3074 CMD, \
3075 }, \
3076 EXIT_FAILURE, "", "", "^expected --master-key-file to be not empty", \
3077 PreCond::Keyring::minimal() \
3078 }
3079
3080 #define TS_AS_3(CMD, ...) \
3081 { \
3082 CMD "_with_unknown_option", "WL12974::TS_AS_3", \
3083 { \
3084 CMD, \
3085 __VA_ARGS__, \
3086 "--unknown-option", \
3087 }, \
3088 EXIT_FAILURE, "", "", "unknown option '--unknown-option'", \
3089 PreCond::Keyring::minimal() \
3090 }
3091
3092 #define TS_AS_4(CMD, ...) \
3093 { \
3094 CMD "_with_extra_argument", "WL12974::TS_AS_4", \
3095 { \
3096 CMD, __VA_ARGS__, "some", "extra", "args", \
3097 }, \
3098 EXIT_FAILURE, "", "", "^expected .*<filename>.*, got", \
3099 PreCond::Keyring::minimal(), \
3100 }
3101
3102 const KeyringFrontendTestParam frontend_fail_param[]{
3103 {"list_without_filename",
3104 "WL12974::TS-1_2",
3105 {
3106 "list",
3107 "--master-key-file",
3108 kMasterKeyfilePlaceholder,
3109 },
3110 EXIT_FAILURE,
3111 "",
3112 "",
3113 "^expected <filename> and optionally <username>",
3114 {}},
3115 TS_FR1_1("init", kKeyringPlaceholder),
3116 TS_FR1_1("list", kKeyringPlaceholder),
3117 TS_FR1_1("get", kKeyringPlaceholder, "someuser", "somekey"),
3118 TS_FR1_1("export", kKeyringPlaceholder),
3119 TS_FR1_1("set", kKeyringPlaceholder, "someuser", "somekey", "somevalue"),
3120 TS_FR1_1("delete", kKeyringPlaceholder, "someuser"),
3121
3122 TS_FR1_2("init", kKeyringPlaceholder),
3123 TS_FR1_2("list", kKeyringPlaceholder),
3124 TS_FR1_2("get", kKeyringPlaceholder, "someuser", "somekey"),
3125 TS_FR1_2("export", kKeyringPlaceholder),
3126 TS_FR1_2("set", kKeyringPlaceholder, "someuser", "somekey", "somevalue"),
3127 TS_FR1_2("delete", kKeyringPlaceholder, "someuser"),
3128
3129 TS_FR1_3("init", kKeyringPlaceholder),
3130 TS_FR1_3("list", kKeyringPlaceholder),
3131 TS_FR1_3("get", kKeyringPlaceholder, "someuser", "somekey"),
3132 TS_FR1_3("export", kKeyringPlaceholder),
3133 TS_FR1_3("set", kKeyringPlaceholder, "someuser", "somekey", "somevalue"),
3134 TS_FR1_3("delete", kKeyringPlaceholder, "someuser"),
3135
3136 TS_FR1_4("init", kKeyringPlaceholder),
3137 TS_FR1_4("list", kKeyringPlaceholder),
3138 TS_FR1_4("get", kKeyringPlaceholder, "someuser", "somekey"),
3139 TS_FR1_4("export", kKeyringPlaceholder),
3140 TS_FR1_4("set", kKeyringPlaceholder, "someuser", "somekey", "somevalue"),
3141 TS_FR1_4("delete", kKeyringPlaceholder, "someuser"),
3142
3143 TS_H_3("init", kKeyringPlaceholder),
3144 TS_H_3("list", kKeyringPlaceholder),
3145 TS_H_3("get", kKeyringPlaceholder, "someuser", "somekey"),
3146 TS_H_3("export", kKeyringPlaceholder),
3147 TS_H_3("set", kKeyringPlaceholder, "someuser", "somekey", "somevalue"),
3148 TS_H_3("delete", kKeyringPlaceholder, "someuser"),
3149
3150 TS_V_3("init", kKeyringPlaceholder),
3151 TS_V_3("list", kKeyringPlaceholder),
3152 TS_V_3("get", kKeyringPlaceholder, "someuser", "somekey"),
3153 TS_V_3("export", kKeyringPlaceholder),
3154 TS_V_3("set", kKeyringPlaceholder, "someuser", "somekey", "somevalue"),
3155 TS_V_3("delete", kKeyringPlaceholder, "someuser"),
3156
3157 TS_KR_1("init", kKeyringPlaceholder),
3158 TS_KR_1("list", kKeyringPlaceholder),
3159 TS_KR_1("get", kKeyringPlaceholder, "someuser", "somekey"),
3160 TS_KR_1("export", kKeyringPlaceholder),
3161 TS_KR_1("set", kKeyringPlaceholder, "someuser", "somekey", "somevalue"),
3162 TS_KR_1("delete", kKeyringPlaceholder, "someuser"),
3163
3164 TS_KR_2("init", kKeyringPlaceholder),
3165 TS_KR_2("list", kKeyringPlaceholder),
3166 TS_KR_2("get", kKeyringPlaceholder, "someuser", "somekey"),
3167 TS_KR_2("export", kKeyringPlaceholder),
3168 TS_KR_2("set", kKeyringPlaceholder, "someuser", "somekey", "somevalue"),
3169 TS_KR_2("delete", kKeyringPlaceholder, "someuser"),
3170
3171 TS_KR_3("init", kKeyringPlaceholder),
3172 TS_KR_3("list", kKeyringPlaceholder),
3173 TS_KR_3("get", kKeyringPlaceholder, "someuser", "somekey"),
3174 TS_KR_3("export", kKeyringPlaceholder),
3175 TS_KR_3("set", kKeyringPlaceholder, "someuser", "somekey", "somevalue"),
3176 TS_KR_3("delete", kKeyringPlaceholder, "someuser"),
3177
3178 TS_KW_1("init", kKeyringPlaceholder),
3179
3180 TS_KW_2("init", kKeyringPlaceholder),
3181
3182 TS_KW_3("init", kKeyringPlaceholder),
3183
3184 // TS_KF_1("init", kKeyringPlaceholder),
3185 TS_KF_1("list", kKeyringPlaceholder),
3186 TS_KF_1("get", kKeyringPlaceholder, "someuser", "somekey"),
3187 TS_KF_1("export", kKeyringPlaceholder),
3188 TS_KF_1("set", kKeyringPlaceholder, "someuser", "somekey", "somevalue"),
3189 TS_KF_1("delete", kKeyringPlaceholder, "someuser"),
3190 TS_KF_1_no_args("master-list"),
3191 TS_KF_1("master-rename", kKeyringPlaceholder, "new"),
3192 TS_KF_1("master-delete", kKeyringPlaceholder),
3193
3194 TS_KF_2("init", kKeyringPlaceholder),
3195 TS_KF_2("list", kKeyringPlaceholder),
3196 TS_KF_2("get", kKeyringPlaceholder, "someuser", "somekey"),
3197 TS_KF_2("export", kKeyringPlaceholder),
3198 TS_KF_2("set", kKeyringPlaceholder, "someuser", "somekey", "somevalue"),
3199 TS_KF_2("delete", kKeyringPlaceholder, "someuser"),
3200 TS_KF_2_no_args("master-list"),
3201 TS_KF_2("master-rename", kKeyringPlaceholder, "new"),
3202 TS_KF_2("master-delete", kKeyringPlaceholder),
3203
3204 TS_KF_3_no_args("master-list"),
3205 TS_KF_3("master-rename", kKeyringPlaceholder, "new"),
3206 TS_KF_3("master-delete", kKeyringPlaceholder),
3207
3208 TS_AS_3("init", kKeyringPlaceholder),
3209 TS_AS_3("list", kKeyringPlaceholder),
3210 TS_AS_3("get", kKeyringPlaceholder, "someuser", "somekey"),
3211 TS_AS_3("export", kKeyringPlaceholder),
3212 TS_AS_3("set", kKeyringPlaceholder, "someuser", "somekey", "somevalue"),
3213 TS_AS_3("delete", kKeyringPlaceholder, "someuser"),
3214
3215 TS_AS_4("init", kKeyringPlaceholder),
3216 TS_AS_4("list", kKeyringPlaceholder),
3217 TS_AS_4("get", kKeyringPlaceholder, "someuser", "somekey"),
3218 TS_AS_4("export", kKeyringPlaceholder),
3219 TS_AS_4("set", kKeyringPlaceholder, "someuser", "somekey", "somevalue"),
3220 TS_AS_4("delete", kKeyringPlaceholder, "someuser"),
3221
3222 };
3223
3224 INSTANTIATE_TEST_SUITE_P(Fail, KeyringFrontendTest,
3225 ::testing::ValuesIn(frontend_fail_param),
__anonc49a43500402(const auto ¶m_info) 3226 [](const auto ¶m_info) {
3227 std::string test_name = param_info.param.test_name;
3228 for (auto &c : test_name) {
3229 if (c == '-') c = '_';
3230 }
3231 return test_name +
3232 (param_info.param.exit_code == EXIT_SUCCESS
3233 ? "_succeeds"s
3234 : "_fails"s);
3235 });
3236
init_DIM()3237 static void init_DIM() {
3238 mysql_harness::DIM &dim = mysql_harness::DIM::instance();
3239
3240 // logging facility
3241 dim.set_LoggingRegistry(
3242 []() {
3243 static mysql_harness::logging::Registry registry;
3244 return ®istry;
3245 },
3246 [](mysql_harness::logging::Registry *) {} // don't delete our static!
3247 );
3248 mysql_harness::logging::Registry ®istry = dim.get_LoggingRegistry();
3249
3250 mysql_harness::logging::create_module_loggers(
3251 registry, mysql_harness::logging::LogLevel::kWarning,
3252 {mysql_harness::logging::kMainLogger, "sql"},
3253 mysql_harness::logging::kMainLogger);
3254 mysql_harness::logging::create_main_log_handler(registry, "", "", true);
3255
3256 registry.set_ready();
3257 }
3258
main(int argc,char * argv[])3259 int main(int argc, char *argv[]) {
3260 init_DIM();
3261 g_origin_path = mysql_harness::Path(argv[0]).dirname();
3262 ::testing::InitGoogleTest(&argc, argv);
3263 return RUN_ALL_TESTS();
3264 }
3265