]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/nowide/test/test_system.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / nowide / test / test_system.cpp
1 //
2 // Copyright (c) 2012 Artyom Beilis (Tonkikh)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //
8 #ifdef _MSC_VER
9 #define _CRT_SECURE_NO_WARNINGS
10 #endif
11
12 #include <boost/nowide/args.hpp>
13 #include <boost/nowide/cstdlib.hpp>
14 #include <boost/nowide/utf/convert.hpp>
15 #include <boost/nowide/utf/utf.hpp>
16 #include "test.hpp"
17 #include <algorithm>
18 #include <cassert>
19 #include <cstdlib>
20 #include <cstring>
21 #include <iostream>
22 #include <string>
23 #include <vector>
24
25 bool is_ascii(const std::string& s)
26 {
27 return std::find_if(s.begin(), s.end(), [](const char c) { return static_cast<unsigned char>(c) > 0x7F; })
28 == s.end();
29 }
30
31 std::string replace_non_ascii(const std::string& s) // LCOV_EXCL_LINE
32 {
33 std::string::const_iterator it = s.begin();
34 namespace utf = boost::nowide::utf;
35 using utf8 = utf::utf_traits<char>;
36 std::string result;
37 result.reserve(s.size());
38 while(it != s.end())
39 {
40 utf::code_point c = utf8::decode(it, s.end());
41 TEST(c != utf::illegal && c != utf::incomplete);
42 if(c > 0x7F)
43 c = '?'; // WinAPI seems to do this
44 result.push_back(static_cast<char>(c));
45 }
46 return result;
47 }
48
49 void compare_string_arrays(char** main_val, char** utf8_val, bool sort)
50 {
51 std::vector<std::string> vec_main, vec_utf8;
52 for(; *main_val; ++main_val)
53 vec_main.push_back(std::string(*main_val));
54 for(; *utf8_val; ++utf8_val)
55 vec_utf8.push_back(std::string(*utf8_val));
56 // Same number of strings
57 TEST_EQ(vec_main.size(), vec_utf8.size());
58 if(sort)
59 {
60 // Order doesn't matter
61 std::sort(vec_main.begin(), vec_main.end());
62 std::sort(vec_utf8.begin(), vec_utf8.end());
63 }
64 for(size_t i = 0; i < vec_main.size(); ++i)
65 {
66 // Skip strings with non-ascii chars
67 if(is_ascii(vec_main[i]) && vec_main[i] != vec_utf8[i])
68 TEST_EQ(vec_main[i], replace_non_ascii(vec_utf8[i]));
69 }
70 }
71
72 void compare_getenv(char** env)
73 {
74 // For all all variables in env check against getenv
75 for(char** e = env; *e != 0; e++)
76 {
77 const char* key_begin = *e;
78 const char* key_end = strchr(key_begin, '=');
79 TEST(key_end);
80 std::string key = std::string(key_begin, key_end);
81 const char* std_value = std::getenv(key.c_str());
82 const char* bnw_value = boost::nowide::getenv(key.c_str());
83 assert(std_value);
84 TEST(bnw_value);
85 // Compare only if ascii
86 if(is_ascii(std_value) && std::string(std_value) != std::string(bnw_value))
87 TEST_EQ(std_value, replace_non_ascii(bnw_value));
88 }
89 }
90
91 const std::string example = "\xd7\xa9-\xd0\xbc-\xce\xbd";
92
93 void run_child(int argc, char** argv, char** env)
94 {
95 // Test arguments
96 TEST_EQ(argc, 2);
97 TEST_EQ(argv[1], example);
98 TEST(argv[2] == NULL);
99
100 // Test getenv
101 TEST(boost::nowide::getenv("BOOST_NOWIDE_TEST"));
102 TEST_EQ(boost::nowide::getenv("BOOST_NOWIDE_TEST"), example);
103 TEST(boost::nowide::getenv("BOOST_NOWIDE_TEST_NONE") == NULL);
104 // Empty variables are unreliable on windows, hence skip. E.g. using "set FOO=" unsets FOO
105 #ifndef BOOST_WINDOWS
106 TEST(boost::nowide::getenv("BOOST_NOWIDE_EMPTY"));
107 TEST_EQ(boost::nowide::getenv("BOOST_NOWIDE_EMPTY"), std::string());
108 #endif // !_WIN32
109
110 // This must be contained in env
111 std::string sample = "BOOST_NOWIDE_TEST=" + example;
112 bool found = false;
113 for(char** e = env; *e != 0; e++)
114 {
115 if(*e == sample)
116 found = true;
117 }
118 TEST(found);
119
120 std::cout << "Subprocess ok" << std::endl;
121 }
122
123 void run_parent(const char* exe_path)
124 {
125 TEST(boost::nowide::system(nullptr) != 0);
126 const std::string command = "\"" + std::string(exe_path) + "\" " + example;
127 #if BOOST_NOWIDE_TEST_USE_NARROW
128 TEST_EQ(boost::nowide::setenv("BOOST_NOWIDE_TEST", example.c_str(), 1), 0);
129 TEST_EQ(boost::nowide::setenv("BOOST_NOWIDE_TEST_NONE", example.c_str(), 1), 0);
130 TEST_EQ(boost::nowide::unsetenv("BOOST_NOWIDE_TEST_NONE"), 0);
131 TEST_EQ(boost::nowide::setenv("BOOST_NOWIDE_EMPTY", "", 1), 0);
132 TEST(boost::nowide::getenv("BOOST_NOWIDE_EMPTY"));
133 TEST_EQ(boost::nowide::system(command.c_str()), 0);
134 std::cout << "Parent ok" << std::endl;
135 #else
136 const std::wstring envVar = L"BOOST_NOWIDE_TEST=" + boost::nowide::widen(example);
137 TEST_EQ(_wputenv(envVar.c_str()), 0);
138 const std::wstring wcommand = boost::nowide::widen(command);
139 TEST_EQ(_wsystem(wcommand.c_str()), 0);
140 std::cout << "Wide Parent ok" << std::endl;
141 #endif
142 }
143
144 // coverity [root_function]
145 void test_main(int argc, char** argv, char** env)
146 {
147 const int old_argc = argc;
148 char** old_argv = argv;
149 char** old_env = env;
150 {
151 boost::nowide::args _(argc, argv, env);
152 TEST_EQ(argc, old_argc);
153 std::cout << "Checking arguments" << std::endl;
154 compare_string_arrays(old_argv, argv, false);
155 std::cout << "Checking env" << std::endl;
156 compare_string_arrays(old_env, env, true);
157 compare_getenv(env);
158 }
159 // When `args` is destructed the old values must be restored
160 TEST_EQ(argc, old_argc);
161 TEST(argv == old_argv);
162 TEST(env == old_env);
163
164 boost::nowide::args a(argc, argv, env);
165 if(argc == 1)
166 run_parent(argv[0]);
167 else
168 run_child(argc, argv, env);
169 }