test: exposes libstorage life-cycle methods

This commit is contained in:
Marcin Czenko 2026-06-29 17:36:37 +02:00
parent 5dd0846015
commit 1a9eb0a662
No known key found for this signature in database
GPG Key ID: F6CB3ED4082ED433
3 changed files with 93 additions and 10 deletions

View File

@ -33,6 +33,37 @@ struct Options {
std::atomic<bool> g_stop{false};
int g_serverFd = -1;
enum class NodeState {
Running,
Stopped,
Closed,
};
std::string stateName(NodeState state) {
switch (state) {
case NodeState::Running: return "RUNNING";
case NodeState::Stopped: return "STOPPED";
case NodeState::Closed: return "CLOSED";
}
return "UNKNOWN";
}
std::string availableCommands(NodeState state) {
switch (state) {
case NodeState::Running:
return "all storage commands, stop, shutdown, destroy";
case NodeState::Stopped:
return "start, close, shutdown, destroy";
case NodeState::Closed:
return "shutdown, destroy";
}
return "shutdown, destroy";
}
std::string unavailableForState(NodeState state) {
return "node is " + stateName(state) + "; available commands: " + availableCommands(state);
}
std::string homeDir() {
const char* home = std::getenv("HOME");
if (!home || std::strlen(home) == 0) {
@ -176,13 +207,56 @@ std::string infoResult(StorageClient& client) {
"\"peer_id\":\"" + jsonEscape(client.peerId()) + "\"}";
}
std::string dispatch(StorageClient& client, const Options& options, const std::string& line) {
std::string dispatch(
StorageClient& client,
const Options& options,
NodeState& state,
const std::string& line) {
const auto parts = splitLine(line);
if (parts.empty()) {
throw std::runtime_error("empty command");
}
const auto& cmd = parts[0];
if (cmd == "shutdown" || cmd == "destroy") {
g_stop = true;
return "shutting down";
}
if (state == NodeState::Closed) {
throw std::runtime_error(unavailableForState(state));
}
if (cmd == "start") {
if (state == NodeState::Running) return "node is already started";
client.start();
state = NodeState::Running;
return "started";
}
if (cmd == "stop") {
if (state == NodeState::Stopped) {
return "node is not started; available commands: " + availableCommands(state);
}
client.stop();
state = NodeState::Stopped;
return "stopped";
}
if (cmd == "close") {
if (state == NodeState::Running) {
throw std::runtime_error("node is RUNNING; call stop before close");
}
client.close();
state = NodeState::Closed;
return "closed";
}
if (state == NodeState::Stopped) {
throw std::runtime_error(unavailableForState(state));
}
if (cmd == "info") return infoResult(client);
if (cmd == "version") return client.version();
if (cmd == "revision") return client.revision();
@ -233,11 +307,6 @@ std::string dispatch(StorageClient& client, const Options& options, const std::s
std::vector<std::string> addresses(parts.begin() + 2, parts.end());
return client.connect(parts[1], addresses);
}
if (cmd == "shutdown") {
g_stop = true;
return "shutting down";
}
throw std::runtime_error("unknown command: " + cmd);
}
@ -310,6 +379,7 @@ int main(int argc, char** argv) {
StorageClient client(configJson(options), options.timeout);
client.start();
NodeState state = NodeState::Running;
g_serverFd = createServerSocket(options.socketPath);
std::cout << "storage_lib listening on " << options.socketPath << "\n";
@ -325,7 +395,7 @@ int main(int argc, char** argv) {
try {
const std::string line = readLine(clientFd);
writeAll(clientFd, okResponse(dispatch(client, options, line)));
writeAll(clientFd, okResponse(dispatch(client, options, state, line)));
} catch (const std::exception& err) {
writeAll(clientFd, errorResponse(err.what()));
}

View File

@ -35,7 +35,11 @@ void printUsage() {
" storage_lib_ctl info\n"
" storage_lib_ctl upload README.md\n"
" storage_lib_ctl download <cid> ./out true\n"
" storage_lib_ctl shutdown\n";
" storage_lib_ctl stop\n"
" storage_lib_ctl start\n"
" storage_lib_ctl close\n"
" storage_lib_ctl shutdown\n"
" storage_lib_ctl destroy\n";
}
struct Options {

View File

@ -68,6 +68,7 @@ Target commands:
Lib-only target commands:
lib spr
lib debug
lib peers
lib manifest <cid>
lib connect <peer-id> [addr...]
@ -453,10 +454,18 @@ lib_only_command() {
local command="$1"
shift
case "$command" in
spr|debug)
spr)
[[ $# -eq 0 ]] || die "$command does not accept arguments"
lib_result "$command"
;;
debug)
[[ $# -eq 0 ]] || die 'debug does not accept arguments'
lib_result debug | jq .
;;
peers)
[[ $# -eq 0 ]] || die 'peers does not accept arguments'
lib_result debug | jq -r '.table.nodes | length'
;;
manifest)
[[ $# -eq 1 ]] || die 'manifest requires <cid>'
lib_result manifest "$1"
@ -785,7 +794,7 @@ target_command() {
space) [[ $# -eq 0 ]] || die 'space does not accept arguments'; target_simple_get "$target" 'space' ;;
peerid) [[ $# -eq 0 ]] || die 'peerid does not accept arguments'; target_simple_get "$target" 'peerid' ;;
test) [[ $# -eq 0 ]] || die 'test does not accept arguments yet'; target_test "$target" ;;
spr|debug|manifest|connect)
spr|debug|peers|manifest|connect)
[[ "$target" == 'lib' ]] || die "$command is currently supported only for lib target"
lib_only_command "$command" "$@"
;;