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 &param_info) 2826                          [](const auto &param_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 &param_info) 3226                          [](const auto &param_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 &registry;
3245       },
3246       [](mysql_harness::logging::Registry *) {}  // don't delete our static!
3247   );
3248   mysql_harness::logging::Registry &registry = 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