Skip to content

Commit c107c6e

Browse files
authored
Add handling for empty profiles.json. (#5685)
This PR adds handling for empty `profiles.json` files. Closes CORE-417 --- TYPE: IMPROVEMENT DESC: Add handling for empty `profiles.json`.
1 parent bfef224 commit c107c6e

File tree

2 files changed

+63
-16
lines changed

2 files changed

+63
-16
lines changed

tiledb/sm/rest/rest_profile.cc

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -196,30 +196,36 @@ void RestProfile::save_to_file(const bool overwrite) {
196196
// If the file already exists, load it into a json object.
197197
json data;
198198
if (std::filesystem::exists(filepath_)) {
199-
// Read the file into the json object.
200-
data = read_file(filepath_);
201-
202-
// If the file is outdated, throw an error. This behavior will evolve.
203-
if (data["version"] < version_) {
199+
try {
200+
// If the file is empty, treat it as a new json object.
201+
if (std::filesystem::file_size(filepath_) == 0) {
202+
data = json::object();
203+
} else {
204+
data = read_file(filepath_);
205+
}
206+
} catch (const std::filesystem::filesystem_error& e) {
204207
throw RestProfileException(
205-
"The version of your local profile.json file is out of date.");
208+
"Failed to access profile file: " + std::string(e.what()));
206209
}
207210

208-
// Check that this profile hasn't already been saved.
209-
if (data.contains(name_)) {
210-
if (overwrite) {
211-
// If a profile of the given name exists, remove it.
212-
auto it = data.find(name_);
213-
if (it != data.end()) {
214-
data.erase(it);
215-
}
216-
} else {
217-
// If the user doesn't want to overwrite, throw an error.
211+
if (data.empty()) {
212+
data["version"] = version_;
213+
} else {
214+
if (data["version"] < version_) {
215+
throw RestProfileException(
216+
"The version of your local profile.json file is out of date.");
217+
}
218+
219+
if (data.contains(name_) && !overwrite) {
218220
throw RestProfileException(
219221
"Failed to save '" + name_ +
220222
"'; This profile has already been saved "
221223
"and must be explicitly removed in order to be replaced.");
222224
}
225+
226+
if (overwrite) {
227+
data.erase(name_);
228+
}
223229
}
224230
} else {
225231
// Write the version number iff this is the first time opening the file.

tiledb/sm/rest/test/unit_rest_profile.cc

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,3 +230,44 @@ TEST_CASE_METHOD(
230230
p2_check.load_from_file();
231231
CHECK(*p2_check.get_param("rest.token") == "token2");
232232
}
233+
234+
TEST_CASE_METHOD(
235+
RestProfileFx, "REST Profile: Empty file", "[rest_profile][empty_file]") {
236+
SECTION("Save to empty file succeeds") {
237+
// Create an empty profiles.json file.
238+
{
239+
std::ofstream file(filepath_);
240+
file.close();
241+
}
242+
CHECK(std::filesystem::exists(filepath_));
243+
244+
// Create a profile and save it to the empty file.
245+
RestProfile p(create_profile("test_profile"));
246+
p.set_param("rest.token", "test_token");
247+
p.set_param("rest.server_address", "https://test.server");
248+
249+
// This should succeed and treat the empty file as a new file.
250+
REQUIRE_NOTHROW(p.save_to_file());
251+
252+
// Verify we can load the profile back.
253+
RestProfile loaded(create_profile("test_profile"));
254+
REQUIRE_NOTHROW(loaded.load_from_file());
255+
CHECK(*loaded.get_param("rest.token") == "test_token");
256+
CHECK(*loaded.get_param("rest.server_address") == "https://test.server");
257+
}
258+
259+
SECTION("Load from empty file fails") {
260+
// Create an empty profiles.json file.
261+
{
262+
std::ofstream file(filepath_);
263+
file.close();
264+
}
265+
CHECK(std::filesystem::exists(filepath_));
266+
267+
// Try to load from an empty file - should fail with parsing error.
268+
RestProfile p(create_profile("test_profile"));
269+
REQUIRE_THROWS_WITH(
270+
p.load_from_file(),
271+
Catch::Matchers::ContainsSubstring("Error parsing file"));
272+
}
273+
}

0 commit comments

Comments
 (0)