-
Notifications
You must be signed in to change notification settings - Fork 25
adding test cases for snapshot #184
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Saumya-R
wants to merge
5
commits into
eclipse-score:main
from
qorix-group:saumya_snapshot_cpp_test_cases
Closed
Changes from 1 commit
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
fa39281
adding test cases for snapshot
Saumya-R 88d82e8
adding format fixes and copyrights.
Saumya-R 8c5af08
removing the redundant includes in build
Saumya-R ed53085
cleaning the main of test and clang-format applied
Saumya-R 462bcda
removing redundant header inclusion
Saumya-R File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,208 @@ | ||
| /******************************************************************************** | ||
| * Copyright (c) 2025 Contributors to the Eclipse Foundation | ||
| * | ||
| * See the NOTICE file(s) distributed with this work for additional | ||
| * information regarding copyright ownership. | ||
| * | ||
| * This program and the accompanying materials are made available under the | ||
| * terms of the Apache License Version 2.0 which is available at | ||
| * https://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| ********************************************************************************/ | ||
|
|
||
| #include "test_snapshots.hpp" | ||
| #include <iostream> | ||
| #include "../helpers/kvs_instance.hpp" | ||
| #include "../helpers/kvs_parameters.hpp" | ||
| #include "tracing.hpp" | ||
| #include "score/json/json_parser.h" | ||
|
|
||
| uint8_t get_count(const std::string &data){ | ||
| using namespace score::mw::per::kvs; | ||
| using namespace score::json; | ||
|
|
||
| JsonParser parser; | ||
| auto any_res{parser.FromBuffer(data)}; | ||
| if (!any_res) { | ||
| throw ScenarioError(score::mw::per::kvs::ErrorCode::JsonParserError, | ||
| "Failed to parse JSON data"); | ||
| } | ||
| const auto &obj = any_res.value().As<Object>().value().get(); | ||
| auto it = obj.find("count"); | ||
| if (it != obj.end()) { | ||
| // Correct: just use .value() | ||
| return static_cast<uint8_t>(it->second.As<int64_t>().value()); | ||
| } else { | ||
| throw ScenarioError(score::mw::per::kvs::ErrorCode::JsonParserError, | ||
| "'count' key not found in input JSON"); | ||
| } | ||
| } | ||
|
|
||
| const std::string kTargetName{"cpp_test_scenarios::snapshots::count"}; | ||
|
|
||
| std::string SnapshotCount::name() const { | ||
| return "count"; | ||
| } | ||
| /** | ||
| * Requirement not being met: | ||
| - The snapshot is created for each data stored. | ||
| - Max count should be configurable. | ||
| * TestSnapshotCountFirstFlush | ||
| * • Issue: The test expects the final snapshot_count to be min(count, snapshot_max_count) (e.g., 1 for count=1, snapshot_max_count=1/3/10). | ||
| • Observed: C++ emits snapshot_count: 0 after the first flush. | ||
| • Possible Root Cause: In C++, the snapshot count is not incremented after the first flush because the snapshot rotation logic and counting are tied to the hardcoded max (not the parameter). | ||
| * TestSnapshotCountFull | ||
| • Issue: The test expects a sequence of snapshot_count values: [0, 1] for count=2, [0, 1, 2, 3] for count=4, etc. | ||
| • Observed: C++ emits [0, 0, 1] or [0, 0, 1, 2, 3], but the first value is always 0, and the final value is not as expected. | ||
| • Possible Root Cause:The C++ implementation may not accumulating the count correctly , it stores or updates the count only after flush when MAX<3. | ||
Saumya-R marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
Saumya-R marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| */ | ||
| void SnapshotCount::run(const std::string& input) const { | ||
| using namespace score::mw::per::kvs; | ||
| // Print and parse parameters. | ||
| std::cerr << "input" << input << std::endl; | ||
| auto count = get_count(input); | ||
| std::cerr << "count" << static_cast<int>(count) << std::endl; | ||
| KvsParameters params = map_to_params(input); | ||
|
|
||
| for (uint8_t i = 0; i < count; ++i) { | ||
| auto kvs = kvs_instance(params); | ||
| auto set_res = kvs.set_value("counter", KvsValue(static_cast<int64_t>(i))); | ||
| if (!set_res) { | ||
| throw ScenarioError(ErrorCode::UnmappedError, "Failed to set value for counter " + std::to_string(i)); | ||
| } | ||
| auto snap_res = kvs.snapshot_count(); | ||
| TRACING_INFO(kTargetName, std::pair{std::string{"snapshot_count"}, snap_res ? static_cast<int>(snap_res.value()) : -1}); | ||
|
|
||
| auto flush_res = kvs.flush(); | ||
| if (!flush_res) { | ||
| throw ScenarioError(ErrorCode::UnmappedError, "Failed to flush"); | ||
| } | ||
|
|
||
| } | ||
| { | ||
| auto kvs = kvs_instance(params); | ||
| auto snap_res = kvs.snapshot_count(); | ||
| TRACING_INFO(kTargetName, std::pair{std::string{"snapshot_count"}, snap_res ? static_cast<int>(snap_res.value()) : -1}); | ||
| } | ||
| } | ||
| std::string SnapshotMaxCount::name() const { | ||
| return "max_count"; | ||
| } | ||
|
|
||
| /** | ||
| * Requirement not being met: | ||
| - Max count should be configurable. | ||
| * TestSnapshotMaxCount | ||
| - The function snapshot_max_count() returns the preconfigured macro value and not the configured value. | ||
| */ | ||
| void SnapshotMaxCount::run(const std::string& input) const { | ||
| using namespace score::mw::per::kvs; | ||
| KvsParameters params = map_to_params(input); | ||
| auto kvs = kvs_instance(params); | ||
| TRACING_INFO(kTargetName, std::pair{std::string{"max_count"}, kvs.snapshot_max_count()}); | ||
| } | ||
| std::string SnapshotRestore::name() const { | ||
| return "restore"; | ||
| } | ||
|
|
||
| void SnapshotRestore::run(const std::string& input) const { | ||
| using namespace score::mw::per::kvs; | ||
| using namespace score::json; | ||
| KvsParameters params = map_to_params(input); | ||
| JsonParser parser; | ||
| auto any_res{parser.FromBuffer(input)}; | ||
| if (!any_res) { | ||
| throw ScenarioError(score::mw::per::kvs::ErrorCode::JsonParserError, | ||
| "Failed to parse JSON data"); | ||
| } | ||
| const auto &obj = any_res.value().As<Object>().value().get(); | ||
| auto count_it = obj.find("count"); | ||
| auto snapshot_id_it = obj.find("snapshot_id"); | ||
| if (count_it == obj.end() || snapshot_id_it == obj.end()) { | ||
| throw ScenarioError(score::mw::per::kvs::ErrorCode::JsonParserError, | ||
| "Missing 'count' or 'snapshot_id' in input JSON"); | ||
| } | ||
| uint8_t count = static_cast<uint8_t>(count_it->second.As<int64_t>().value()); | ||
| int snapshot_id = static_cast<int>(snapshot_id_it->second.As<int64_t>().value()); | ||
|
|
||
| for (uint8_t i = 0; i < count; ++i) { | ||
| auto kvs = kvs_instance(params); | ||
| auto set_res = kvs.set_value("counter", KvsValue(static_cast<int64_t>(i))); | ||
| if (!set_res) { | ||
| throw ScenarioError(ErrorCode::UnmappedError, "Failed to set value for counter " + std::to_string(i)); | ||
| } | ||
| auto flush_res = kvs.flush(); | ||
| if (!flush_res) { | ||
| throw ScenarioError(ErrorCode::UnmappedError, "Failed to flush"); | ||
| } | ||
| } | ||
| { | ||
| auto kvs = kvs_instance(params); | ||
| auto restore_res = kvs.snapshot_restore(snapshot_id); | ||
| // Emit expected error messages to stderr for test compatibility | ||
|
||
| if (!restore_res) { | ||
| if (snapshot_id == 0) { | ||
| std::cerr << "error: tried to restore current KVS as snapshot" << std::endl; | ||
| } else { | ||
| std::cerr << "error: tried to restore a non-existing snapshot" << std::endl; | ||
| } | ||
| } | ||
| TRACING_INFO(kTargetName, std::pair{std::string{"result"}, restore_res ? "Ok(())" : "Err(InvalidSnapshotId)" }); | ||
| if (restore_res) { | ||
| auto value_res = kvs.get_value("counter"); | ||
| if (value_res) { | ||
| // Emit as integer, not string | ||
| TRACING_INFO(kTargetName, std::pair{std::string{"value"}, static_cast<int>(std::get<int64_t>(value_res.value().getValue())) }); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| } | ||
| std::string SnapshotPaths::name() const { | ||
| return "paths"; | ||
| } | ||
|
|
||
| void SnapshotPaths::run(const std::string& input) const { | ||
| using namespace score::mw::per::kvs; | ||
| using namespace score::json; | ||
| KvsParameters params = map_to_params(input); | ||
| JsonParser parser; | ||
| auto any_res{parser.FromBuffer(input)}; | ||
| if (!any_res) { | ||
| throw ScenarioError(score::mw::per::kvs::ErrorCode::JsonParserError, | ||
| "Failed to parse JSON data"); | ||
| } | ||
| const auto &obj = any_res.value().As<Object>().value().get(); | ||
| auto count_it = obj.find("count"); | ||
| auto snapshot_id_it = obj.find("snapshot_id"); | ||
| if (count_it == obj.end() || snapshot_id_it == obj.end()) { | ||
| throw ScenarioError(score::mw::per::kvs::ErrorCode::JsonParserError, | ||
| "Missing 'count' or 'snapshot_id' in input JSON"); | ||
| } | ||
| uint8_t count = static_cast<uint8_t>(count_it->second.As<int64_t>().value()); | ||
| int snapshot_id = static_cast<int>(snapshot_id_it->second.As<int64_t>().value()); | ||
|
|
||
| for (uint8_t i = 0; i < count; ++i) { | ||
| auto kvs = kvs_instance(params); | ||
| auto set_res = kvs.set_value("counter", KvsValue(static_cast<int64_t>(i))); | ||
| if (!set_res) { | ||
| throw ScenarioError(ErrorCode::UnmappedError, "Failed to set value for counter " + std::to_string(i)); | ||
| } | ||
| auto flush_res = kvs.flush(); | ||
| if (!flush_res) { | ||
| throw ScenarioError(ErrorCode::UnmappedError, "Failed to flush"); | ||
| } | ||
| } | ||
|
|
||
| { | ||
| auto kvs = kvs_instance(params); | ||
| auto kvs_path_res = kvs.get_kvs_filename(snapshot_id); | ||
| auto hash_path_res = kvs.get_hash_filename(snapshot_id); | ||
| // Emit both kvs_path and hash_path as Ok("...") or Err(FileNotFound) | ||
| TRACING_INFO(kTargetName, | ||
| std::make_pair(std::string("kvs_path"), kvs_path_res ? ("Ok(\"" + std::string(kvs_path_res.value()) + "\")") : "Err(FileNotFound)"), | ||
| std::make_pair(std::string("hash_path"), hash_path_res ? ("Ok(\"" + std::string(hash_path_res.value()) + "\")") : "Err(FileNotFound)") | ||
| ); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| /******************************************************************************** | ||
| * Copyright (c) 2025 Contributors to the Eclipse Foundation | ||
| * | ||
| * See the NOTICE file(s) distributed with this work for additional | ||
| * information regarding copyright ownership. | ||
| * | ||
| * This program and the accompanying materials are made available under the | ||
| * terms of the Apache License Version 2.0 which is available at | ||
| * https://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| ********************************************************************************/ | ||
| #ifndef TEST_SNAPSHOT_HPP | ||
| #define TEST_SNAPSHOT_HPP | ||
|
|
||
| #include "scenario.hpp" | ||
|
|
||
| class SnapshotCount : public Scenario { | ||
| public: | ||
| ~SnapshotCount() final = default; | ||
| std::string name() const override; | ||
| void run(const std::string& input) const override; | ||
| }; | ||
|
|
||
| class SnapshotMaxCount : public Scenario { | ||
| public: | ||
| ~SnapshotMaxCount() final = default; | ||
| std::string name() const override; | ||
| void run(const std::string& input) const override; | ||
| }; | ||
|
|
||
| class SnapshotRestore : public Scenario { | ||
| public: | ||
| ~SnapshotRestore() final = default; | ||
| std::string name() const override; | ||
| void run(const std::string& input) const override; | ||
| }; | ||
|
|
||
| class SnapshotPaths : public Scenario { | ||
| public: | ||
| ~SnapshotPaths() final = default; | ||
| std::string name() const override; | ||
| void run(const std::string& input) const override; | ||
| }; | ||
|
|
||
| #endif //TEST_SNAPSHOT_HPP |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| /******************************************************************************** | ||
| * Copyright (c) 2025 Contributors to the Eclipse Foundation | ||
| * | ||
| * See the NOTICE file(s) distributed with this work for additional | ||
| * information regarding copyright ownership. | ||
| * | ||
| * This program and the accompanying materials are made available under the | ||
| * terms of the Apache License Version 2.0 which is available at | ||
| * https://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| ********************************************************************************/ | ||
|
|
||
| #pragma once | ||
| #include "kvs_parameters.hpp" | ||
| #include <kvs.hpp> | ||
| #include <kvsbuilder.hpp> | ||
|
|
||
| static score::mw::per::kvs::Kvs kvs_instance(const KvsParameters ¶ms) { | ||
| using namespace score::mw::per::kvs; | ||
| InstanceId instance_id{params.instance_id}; | ||
| KvsBuilder builder{instance_id}; | ||
| if (params.need_defaults.has_value()) { | ||
| builder = builder.need_defaults_flag(*params.need_defaults); | ||
| } | ||
| if (params.need_kvs.has_value()) { | ||
| builder = builder.need_kvs_flag(*params.need_kvs); | ||
| } | ||
| if (params.dir.has_value()) { | ||
| builder = builder.dir(std::string(*params.dir)); | ||
| } | ||
| auto kvs_ptr = builder.build(); | ||
| if (!kvs_ptr) { | ||
| throw ScenarioError(score::mw::per::kvs::ErrorCode::JsonParserError, | ||
| "KVS creation failed: build() returned null (possible " | ||
| "file not found, JSON parse error, or corruption)"); | ||
| } | ||
| return std::move(*kvs_ptr); | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.