Skip to content

Commit 5a7a92e

Browse files
Move narrow() & escape_backslashes_for_json() into common code
Because these functions are requied on windows for paths to behave correct, it is good to put them in common code functions (like EnvVarWrapper) instead of requiring all code to remember to call them. Having JsonWriter handle the path fixup means less changes of double application occuring.
1 parent 2171cfa commit 5a7a92e

File tree

7 files changed

+72
-53
lines changed

7 files changed

+72
-53
lines changed

tests/framework/json_writer.h

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,25 @@ struct JsonWriter {
7979
void AddKeyedString(std::string const& key, std::string const& value) {
8080
CommaAndNewLine();
8181
Indent();
82-
output += "\"" + key + "\": \"" + value + "\"";
82+
output += "\"" + key + "\": \"" + escape(value) + "\"";
8383
}
8484
void AddString(std::string const& value) {
8585
CommaAndNewLine();
8686
Indent();
87-
output += "\"" + value + "\"";
87+
output += "\"" + escape(value) + "\"";
8888
}
89+
#if defined(WIN32)
90+
void AddKeyedString(std::string const& key, std::wstring const& value) {
91+
CommaAndNewLine();
92+
Indent();
93+
output += "\"" + key + "\": \"" + escape(narrow(value)) + "\"";
94+
}
95+
void AddString(std::wstring const& value) {
96+
CommaAndNewLine();
97+
Indent();
98+
output += "\"" + escape(narrow(value)) + "\"";
99+
}
100+
#endif
89101

90102
void AddKeyedBool(std::string const& key, bool value) {
91103
CommaAndNewLine();
@@ -98,6 +110,19 @@ struct JsonWriter {
98110
output += std::string(value ? "true" : "false");
99111
}
100112

113+
// Json doesn't allow `\` in strings, it must be escaped. Thus we have to convert '\\' to '\\\\' in strings
114+
static std::string escape(std::string const& in_path) {
115+
std::string out;
116+
for (auto& c : in_path) {
117+
if (c == '\\')
118+
out += "\\\\";
119+
else
120+
out += c;
121+
}
122+
return out;
123+
}
124+
static std::string escape(std::filesystem::path const& in_path) { return escape(narrow(in_path.native())); }
125+
101126
private:
102127
void CommaAndNewLine() {
103128
if (stack.size() > 0) {

tests/framework/test_environment.cpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -528,17 +528,17 @@ TestICD& FrameworkEnvironment::add_icd(TestICDDetails icd_details) noexcept {
528528
break;
529529
case (ManifestDiscoveryType::env_var):
530530
if (icd_details.is_dir) {
531-
env_var_vk_icd_filenames.add_to_list(narrow(folder->location()));
531+
env_var_vk_icd_filenames.add_to_list(folder->location());
532532
} else {
533-
env_var_vk_icd_filenames.add_to_list(narrow(folder->location() / new_manifest_path));
533+
env_var_vk_icd_filenames.add_to_list(folder->location() / new_manifest_path);
534534
}
535535
platform_shim->add_known_path(folder->location());
536536
break;
537537
case (ManifestDiscoveryType::add_env_var):
538538
if (icd_details.is_dir) {
539-
add_env_var_vk_icd_filenames.add_to_list(narrow(folder->location()));
539+
add_env_var_vk_icd_filenames.add_to_list(folder->location());
540540
} else {
541-
add_env_var_vk_icd_filenames.add_to_list(narrow(folder->location() / new_manifest_path));
541+
add_env_var_vk_icd_filenames.add_to_list(folder->location() / new_manifest_path);
542542
}
543543
platform_shim->add_known_path(folder->location());
544544
break;
@@ -590,17 +590,17 @@ void FrameworkEnvironment::add_layer_impl(TestLayerDetails layer_details, Manife
590590
if (category == ManifestCategory::explicit_layer) {
591591
fs_ptr = &get_folder(ManifestLocation::explicit_layer_env_var);
592592
if (layer_details.is_dir) {
593-
env_var_vk_layer_paths.add_to_list(narrow(fs_ptr->location()));
593+
env_var_vk_layer_paths.add_to_list(fs_ptr->location());
594594
} else {
595-
env_var_vk_layer_paths.add_to_list(narrow(fs_ptr->location() / layer_details.json_name));
595+
env_var_vk_layer_paths.add_to_list(fs_ptr->location() / layer_details.json_name);
596596
}
597597
}
598598
if (category == ManifestCategory::implicit_layer) {
599599
fs_ptr = &get_folder(ManifestLocation::implicit_layer_env_var);
600600
if (layer_details.is_dir) {
601-
env_var_vk_implicit_layer_paths.add_to_list(narrow(fs_ptr->location()));
601+
env_var_vk_implicit_layer_paths.add_to_list(fs_ptr->location());
602602
} else {
603-
env_var_vk_implicit_layer_paths.add_to_list(narrow(fs_ptr->location() / layer_details.json_name));
603+
env_var_vk_implicit_layer_paths.add_to_list(fs_ptr->location() / layer_details.json_name);
604604
}
605605
}
606606
platform_shim->add_known_path(fs_ptr->location());
@@ -609,17 +609,17 @@ void FrameworkEnvironment::add_layer_impl(TestLayerDetails layer_details, Manife
609609
if (category == ManifestCategory::explicit_layer) {
610610
fs_ptr = &get_folder(ManifestLocation::explicit_layer_add_env_var);
611611
if (layer_details.is_dir) {
612-
add_env_var_vk_layer_paths.add_to_list(narrow(fs_ptr->location()));
612+
add_env_var_vk_layer_paths.add_to_list(fs_ptr->location());
613613
} else {
614-
add_env_var_vk_layer_paths.add_to_list(narrow(fs_ptr->location() / layer_details.json_name));
614+
add_env_var_vk_layer_paths.add_to_list(fs_ptr->location() / layer_details.json_name);
615615
}
616616
}
617617
if (category == ManifestCategory::implicit_layer) {
618618
fs_ptr = &get_folder(ManifestLocation::implicit_layer_add_env_var);
619619
if (layer_details.is_dir) {
620-
add_env_var_vk_implicit_layer_paths.add_to_list(narrow(fs_ptr->location()));
620+
add_env_var_vk_implicit_layer_paths.add_to_list(fs_ptr->location());
621621
} else {
622-
add_env_var_vk_implicit_layer_paths.add_to_list(narrow(fs_ptr->location() / layer_details.json_name));
622+
add_env_var_vk_implicit_layer_paths.add_to_list(fs_ptr->location() / layer_details.json_name);
623623
}
624624
}
625625
platform_shim->add_known_path(fs_ptr->location());
@@ -740,7 +740,7 @@ std::string get_loader_settings_file_contents(const LoaderSettings& loader_setti
740740
for (const auto& config : setting.layer_configurations) {
741741
writer.StartObject();
742742
writer.AddKeyedString("name", config.name);
743-
writer.AddKeyedString("path", escape_backslashes_for_json(config.path));
743+
writer.AddKeyedString("path", config.path.native());
744744
writer.AddKeyedString("control", config.control);
745745
writer.AddKeyedBool("treat_as_implicit_manifest", config.treat_as_implicit_manifest);
746746
writer.EndObject();

tests/framework/test_util.cpp

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -117,15 +117,15 @@ void print_vector_of_strings(JsonWriter& writer, const char* object_name, std::v
117117
if (strings.size() == 0) return;
118118
writer.StartKeyedArray(object_name);
119119
for (auto const& str : strings) {
120-
writer.AddString(escape_backslashes_for_json(str));
120+
writer.AddString(std::filesystem::path(str).native());
121121
}
122122
writer.EndArray();
123123
}
124124
void print_vector_of_strings(JsonWriter& writer, const char* object_name, std::vector<std::filesystem::path> const& paths) {
125125
if (paths.size() == 0) return;
126126
writer.StartKeyedArray(object_name);
127127
for (auto const& path : paths) {
128-
writer.AddString(escape_backslashes_for_json(path));
128+
writer.AddString(path.native());
129129
}
130130
writer.EndArray();
131131
}
@@ -137,7 +137,7 @@ std::string ManifestICD::get_manifest_str() const {
137137
writer.StartObject();
138138
writer.AddKeyedString("file_format_version", file_format_version.get_version_str());
139139
writer.StartKeyedObject("ICD");
140-
writer.AddKeyedString("library_path", escape_backslashes_for_json(lib_path));
140+
writer.AddKeyedString("library_path", lib_path.native());
141141
writer.AddKeyedString("api_version", version_to_string(api_version));
142142
writer.AddKeyedBool("is_portability_driver", is_portability_driver);
143143
if (!library_arch.empty()) writer.AddKeyedString("library_arch", library_arch);
@@ -159,7 +159,7 @@ void ManifestLayer::LayerDescription::get_manifest_str(JsonWriter& writer) const
159159
writer.AddKeyedString("name", name);
160160
writer.AddKeyedString("type", get_type_str(type));
161161
if (!lib_path.empty()) {
162-
writer.AddKeyedString("library_path", escape_backslashes_for_json(lib_path));
162+
writer.AddKeyedString("library_path", lib_path.native());
163163
}
164164
writer.AddKeyedString("api_version", version_to_string(api_version));
165165
writer.AddKeyedString("implementation_version", std::to_string(implementation_version));
@@ -217,20 +217,6 @@ std::string ManifestLayer::get_manifest_str() const {
217217
return writer.output;
218218
}
219219

220-
// Json doesn't allow `\` in strings, it must be escaped. Thus we have to convert '\\' to '\\\\' in strings
221-
std::string escape_backslashes_for_json(std::string const& in_path) {
222-
std::string out;
223-
for (auto& c : in_path) {
224-
if (c == '\\')
225-
out += "\\\\";
226-
else
227-
out += c;
228-
}
229-
return out;
230-
}
231-
std::string escape_backslashes_for_json(std::filesystem::path const& in_path) {
232-
return escape_backslashes_for_json(narrow(in_path.native()));
233-
}
234220
namespace fs {
235221
// internal implementation helper for per-platform creating & destroying folders
236222
int create_folder(std::filesystem::path const& path) {

tests/framework/test_util.h

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,19 @@
9898
#define FRAMEWORK_EXPORT
9999
#endif
100100

101+
// Define it here so that json_writer.h has access to these functions
102+
#if defined(WIN32)
103+
// Convert an UTF-16 wstring to an UTF-8 string
104+
std::string narrow(const std::wstring& utf16);
105+
// Convert an UTF-8 string to an UTF-16 wstring
106+
std::wstring widen(const std::string& utf8);
107+
#else
108+
// Do nothing passthrough for the sake of Windows & UTF-16
109+
std::string narrow(const std::string& utf16);
110+
// Do nothing passthrough for the sake of Windows & UTF-16
111+
std::string widen(const std::string& utf8);
112+
#endif
113+
101114
#include "json_writer.h"
102115

103116
// get_env_var() - returns a std::string of `name`. if report_failure is true, then it will log to stderr that it didn't find the
@@ -145,6 +158,15 @@ struct EnvVarWrapper {
145158
cur_value += list_item;
146159
set_env_var();
147160
}
161+
#if defined(WIN32)
162+
void add_to_list(std::wstring const& list_item) {
163+
if (!cur_value.empty()) {
164+
cur_value += OS_ENV_VAR_LIST_SEPARATOR;
165+
}
166+
cur_value += narrow(list_item);
167+
set_env_var();
168+
}
169+
#endif
148170
void remove_value() const { remove_env_var(); }
149171
const char* get() const { return name.c_str(); }
150172
const char* value() const { return cur_value.c_str(); }
@@ -176,8 +198,6 @@ void print_error_message(LSTATUS status, const char* function_name, std::string
176198
struct ManifestICD; // forward declaration for FolderManager::write
177199
struct ManifestLayer; // forward declaration for FolderManager::write
178200

179-
std::string escape_backslashes_for_json(std::string const& in_path);
180-
std::string escape_backslashes_for_json(std::filesystem::path const& in_path);
181201
namespace fs {
182202

183203
int create_folder(std::filesystem::path const& path);
@@ -221,18 +241,6 @@ class FolderManager {
221241
// size_dst - number of characters in the dst array
222242
inline void copy_string_to_char_array(std::string const& src, char* dst, size_t size_dst) { dst[src.copy(dst, size_dst - 1)] = 0; }
223243

224-
#if defined(WIN32)
225-
// Convert an UTF-16 wstring to an UTF-8 string
226-
std::string narrow(const std::wstring& utf16);
227-
// Convert an UTF-8 string to an UTF-16 wstring
228-
std::wstring widen(const std::string& utf8);
229-
#else
230-
// Do nothing passthrough for the sake of Windows & UTF-16
231-
std::string narrow(const std::string& utf16);
232-
// Do nothing passthrough for the sake of Windows & UTF-16
233-
std::string widen(const std::string& utf8);
234-
#endif
235-
236244
#if defined(WIN32)
237245
typedef HMODULE loader_platform_dl_handle;
238246
inline loader_platform_dl_handle loader_platform_open_library(const wchar_t* lib_path) {
@@ -993,7 +1001,7 @@ inline std::string test_platform_executable_path() {
9931001
if (ret > buffer.size()) return NULL;
9941002
buffer.resize(ret);
9951003
buffer[ret] = '\0';
996-
return buffer;
1004+
return narrow(std::filesystem::path(buffer).native());
9971005
}
9981006

9991007
#endif

tests/loader_layer_tests.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,7 +1149,7 @@ TEST(ImplicitLayers, DuplicateLayersInVK_ADD_IMPLICIT_LAYER_PATH) {
11491149
auto& layer1 = env.get_test_layer(0);
11501150
layer1.set_description("actually_layer_1");
11511151
layer1.set_make_spurious_log_in_create_instance("actually_layer_1");
1152-
env.add_env_var_vk_implicit_layer_paths.add_to_list(narrow(env.get_folder(ManifestLocation::override_layer).location()));
1152+
env.add_env_var_vk_implicit_layer_paths.add_to_list(env.get_folder(ManifestLocation::override_layer).location());
11531153

11541154
env.add_implicit_layer(TestLayerDetails(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
11551155
.set_name(same_layer_name_1)
@@ -2460,7 +2460,7 @@ TEST(ExplicitLayers, DuplicateLayersInVK_LAYER_PATH) {
24602460
auto& layer1 = env.get_test_layer(0);
24612461
layer1.set_description("actually_layer_1");
24622462
layer1.set_make_spurious_log_in_create_instance("actually_layer_1");
2463-
env.env_var_vk_layer_paths.add_to_list(narrow(env.get_folder(ManifestLocation::override_layer).location()));
2463+
env.env_var_vk_layer_paths.add_to_list(env.get_folder(ManifestLocation::override_layer).location());
24642464

24652465
env.add_explicit_layer(TestLayerDetails(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
24662466
.set_name(same_layer_name_1)
@@ -2534,7 +2534,7 @@ TEST(ExplicitLayers, DuplicateLayersInVK_ADD_LAYER_PATH) {
25342534
auto& layer1 = env.get_test_layer(0);
25352535
layer1.set_description("actually_layer_1");
25362536
layer1.set_make_spurious_log_in_create_instance("actually_layer_1");
2537-
env.add_env_var_vk_layer_paths.add_to_list(narrow(env.get_folder(ManifestLocation::override_layer).location()));
2537+
env.add_env_var_vk_layer_paths.add_to_list(env.get_folder(ManifestLocation::override_layer).location());
25382538

25392539
env.add_explicit_layer(TestLayerDetails(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
25402540
.set_name(same_layer_name_1)

tests/loader_regression_tests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3882,7 +3882,7 @@ TEST(DuplicateRegistryEntries, Drivers) {
38823882
TEST(LibraryLoading, SystemLocations) {
38833883
FrameworkEnvironment env{};
38843884
EnvVarWrapper ld_library_path("LD_LIBRARY_PATH", env.get_folder(ManifestLocation::driver).location().string());
3885-
ld_library_path.add_to_list(narrow(env.get_folder(ManifestLocation::explicit_layer).location()));
3885+
ld_library_path.add_to_list(env.get_folder(ManifestLocation::explicit_layer).location());
38863886

38873887
auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2).set_library_path_type(LibraryPathType::default_search_paths))
38883888
.add_physical_device({});

tests/loader_settings_tests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ TEST(SettingsFile, SupportsMultipleSettingsSimultaneously) {
243243
}
244244
env.debug_log.clear();
245245
// Set one set to contain the current executable path
246-
env.loader_settings.app_specific_settings.at(0).add_app_key(escape_backslashes_for_json(test_platform_executable_path()));
246+
env.loader_settings.app_specific_settings.at(0).add_app_key(test_platform_executable_path());
247247
env.update_loader_settings(env.loader_settings);
248248
{
249249
auto layer_props = env.GetLayerProperties(1);

0 commit comments

Comments
 (0)