This is an automated email from the ASF dual-hosted git repository.
spetz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iggy.git
The following commit(s) were added to refs/heads/master by this push:
new bbdc54ccc fix(cli): resolve server address for ws transport (#4482)
bbdc54ccc is described below
commit bbdc54ccc50dc6fdd6e1963c74971e9c01531811
Author: Alex <[email protected]>
AuthorDate: Sat Oct 10 21:30:27 2026 +0300
fix(cli): resolve server address for ws transport (#4482)
Closes #4444
---
core/cli/src/credentials.rs | 42 ++++++--------
core/cli/src/error.rs | 6 --
core/cli/src/main.rs | 27 +++++----
core/common/src/types/args/mod.rs | 60 ++++++++++++++++----
core/integration/tests/cli/common/mod.rs | 41 ++++++++++++++
core/integration/tests/cli/general/mod.rs | 1 +
.../tests/cli/general/test_unknown_transport.rs | 65 ++++++++++++++++++++++
.../test_pat_create_command.rs | 17 +++++-
.../test_pat_delete_command.rs | 15 ++++-
core/integration/tests/cli/system/mod.rs | 2 +
.../tests/cli/system/test_cli_session_scenario.rs | 42 +++++++++++++-
.../tests/cli/system/test_me_command.rs | 36 ++++--------
.../tests/cli/system/test_session_status_cmd.rs | 65 ++++++++++++++++++++++
13 files changed, 336 insertions(+), 83 deletions(-)
diff --git a/core/cli/src/credentials.rs b/core/cli/src/credentials.rs
index 4b38a77a1..f45067772 100644
--- a/core/cli/src/credentials.rs
+++ b/core/cli/src/credentials.rs
@@ -19,7 +19,7 @@ use crate::args::CliOptions;
use crate::error::{CmdToolError, IggyCmdError};
use anyhow::{Context, bail};
use iggy::clients::client::IggyClient;
-use iggy::prelude::{Args, IggyError, PersonalAccessTokenClient, UserClient};
+use iggy::prelude::{IggyError, PersonalAccessTokenClient, UserClient};
use iggy_cli::commands::binary_system::session::{ServerSession,
ensure_default_store};
use passterm::{Stream, isatty, prompt_password_tty};
use secrecy::{ExposeSecret, SecretString};
@@ -58,7 +58,7 @@ pub(crate) struct IggyCredentials<'a> {
impl<'a> IggyCredentials<'a> {
pub(crate) fn new(
cli_options: &CliOptions,
- iggy_args: &Args,
+ server_address: &str,
login_required: bool,
prefer_explicit_credentials: bool,
) -> anyhow::Result<Self, anyhow::Error> {
@@ -71,11 +71,10 @@ impl<'a> IggyCredentials<'a> {
}
let session_credentials = || -> Option<Credentials> {
- let server_address = iggy_args.get_server_address()?;
- let token =
ServerSession::new(server_address.clone()).get_token()?;
+ let token =
ServerSession::new(server_address.to_string()).get_token()?;
Some(Credentials::SessionWithToken(
SecretString::from(token),
- server_address,
+ server_address.to_string(),
))
};
@@ -93,25 +92,18 @@ impl<'a> IggyCredentials<'a> {
#[cfg(feature = "login-session")]
if let Some(token_name) = &cli_options.token_name {
- return match iggy_args.get_server_address() {
- Some(server_address) => {
- let server_address = format!("iggy:{server_address}");
- event!(target: PRINT_TARGET, Level::DEBUG,"Checking token
presence under service: {} and name: {}",
- server_address, token_name);
- ensure_default_store()?;
- let entry = Entry::new(&server_address, token_name)?;
- let token = entry.get_password()?;
-
- Ok(Self {
- credentials:
Some(Credentials::PersonalAccessToken(SecretString::from(
- token,
- ))),
- iggy_client: None,
- login_required,
- })
- }
- None =>
Err(IggyCmdError::CmdToolError(CmdToolError::MissingServerAddress).into()),
- };
+ let server_address = format!("iggy:{server_address}");
+ event!(target: PRINT_TARGET, Level::DEBUG,"Checking token presence
under service: {} and name: {}",
+ server_address, token_name);
+ ensure_default_store()?;
+ let entry = Entry::new(&server_address, token_name)?;
+ let token = entry.get_password()?;
+
+ return Ok(Self {
+ credentials:
Some(Credentials::PersonalAccessToken(SecretString::from(token))),
+ iggy_client: None,
+ login_required,
+ });
}
if let Some(token) = &cli_options.token {
@@ -154,7 +146,7 @@ impl<'a> IggyCredentials<'a> {
iggy_client: None,
login_required,
})
- } else if let Some(credentials) = session_credentials() {
+ } else if prefer_explicit_credentials && let Some(credentials) =
session_credentials() {
// `iggy login` with no explicit credentials: reuse the cached
// session token so a still-valid session reports "already logged
in"
// instead of demanding credentials for a no-op.
diff --git a/core/cli/src/error.rs b/core/cli/src/error.rs
index 1e51eec72..4ea26fc39 100644
--- a/core/cli/src/error.rs
+++ b/core/cli/src/error.rs
@@ -22,8 +22,6 @@ use thiserror::Error;
pub(crate) enum CmdToolError {
MissingCredentials,
InvalidEncryptionKey,
- #[cfg(feature = "login-session")]
- MissingServerAddress,
}
impl Display for CmdToolError {
@@ -35,10 +33,6 @@ impl Display for CmdToolError {
Self::InvalidEncryptionKey => {
write!(f, "Invalid encryption key provided")
}
- #[cfg(feature = "login-session")]
- Self::MissingServerAddress => {
- write!(f, "Missing iggy server address")
- }
}
}
}
diff --git a/core/cli/src/main.rs b/core/cli/src/main.rs
index d5e8c1710..4fe065eb8 100644
--- a/core/cli/src/main.rs
+++ b/core/cli/src/main.rs
@@ -38,8 +38,8 @@ use args::{CliOptions, IggyMergedConsoleArgs};
use clap::Parser;
use iggy::client_provider::{self, ClientProviderConfig};
use iggy::clients::client::IggyClient;
-use iggy::prelude::{Aes256GcmEncryptor, Args, EncryptorKind,
PersonalAccessTokenExpiry};
-use iggy_cli::commands::binary_context::common::ContextManager;
+use iggy::prelude::{Aes256GcmEncryptor, ClientError, EncryptorKind,
PersonalAccessTokenExpiry};
+use iggy_cli::commands::binary_context::common::{ContextManager,
validate_transport};
use iggy_cli::commands::binary_context::create_context::CreateContextCmd;
use iggy_cli::commands::binary_context::delete_context::DeleteContextCmd;
use iggy_cli::commands::binary_context::show_context::ShowContextCmd;
@@ -107,7 +107,7 @@ use main_login_session::*;
fn get_command(
command: Command,
cli_options: &CliOptions,
- iggy_args: &Args,
+ server_address: &str,
) -> Box<dyn CliCommand> {
#[warn(clippy::let_and_return)]
match command {
@@ -190,13 +190,13 @@ fn get_command(
PersonalAccessTokenExpiry::new(pat_create_args.expiry.clone()),
cli_options.quiet,
pat_create_args.store_token,
- iggy_args.get_server_address().unwrap(),
+ server_address.to_string(),
))
}
PersonalAccessTokenAction::Delete(pat_delete_args) => {
Box::new(DeletePersonalAccessTokenCmd::new(
pat_delete_args.name.clone(),
- iggy_args.get_server_address().unwrap(),
+ server_address.to_string(),
))
}
PersonalAccessTokenAction::List(pat_list_args) => Box::new(
@@ -336,16 +336,14 @@ fn get_command(
},
#[cfg(feature = "login-session")]
Command::Login(login_args) => Box::new(LoginCmd::new(
- iggy_args.get_server_address().unwrap(),
+ server_address.to_string(),
LoginSessionExpiry::new(login_args.expiry.clone()),
)),
#[cfg(feature = "login-session")]
- Command::Logout =>
Box::new(LogoutCmd::new(iggy_args.get_server_address().unwrap())),
+ Command::Logout =>
Box::new(LogoutCmd::new(server_address.to_string())),
#[cfg(feature = "login-session")]
Command::Session(command) => match command {
- SessionAction::Status => Box::new(SessionStatusCmd::new(
- iggy_args.get_server_address().unwrap(),
- )),
+ SessionAction::Status =>
Box::new(SessionStatusCmd::new(server_address.to_string())),
},
}
}
@@ -384,13 +382,18 @@ async fn main() -> Result<(), IggyCmdError> {
let iggy_args = merged_args.iggy;
let cli_options = merged_args.cli;
+ validate_transport(&iggy_args.transport)?;
+ let server_address = iggy_args
+ .get_server_address()
+ .ok_or_else(||
ClientError::InvalidTransport(iggy_args.transport.clone()))?;
+
// Get command based on command line arguments
- let mut command = get_command(command, &cli_options, &iggy_args);
+ let mut command = get_command(command, &cli_options, &server_address);
// Create credentials based on command line arguments and command
let mut credentials = IggyCredentials::new(
&cli_options,
- &iggy_args,
+ &server_address,
command.login_required(),
command.prefer_explicit_credentials(),
)?;
diff --git a/core/common/src/types/args/mod.rs
b/core/common/src/types/args/mod.rs
index 4dc5ff389..1555fc4d2 100644
--- a/core/common/src/types/args/mod.rs
+++ b/core/common/src/types/args/mod.rs
@@ -15,9 +15,11 @@
// specific language governing permissions and limitations
// under the License.
+use crate::TransportProtocol;
use crate::defaults::{DEFAULT_ROOT_PASSWORD, DEFAULT_ROOT_USERNAME};
use clap::Parser;
use serde::{Deserialize, Serialize};
+use std::str::FromStr;
/// The arguments used by the `ClientProviderConfig` to create a client.
/// We are not using default values here because we want to be able to
@@ -353,19 +355,17 @@ pub struct Args {
pub websocket_tls_validate_certificate: bool,
}
-const QUIC_TRANSPORT: &str = "quic";
-const HTTP_TRANSPORT: &str = "http";
-const TCP_TRANSPORT: &str = "tcp";
-const WEBSOCKET_TRANSPORT: &str = "websocket";
-
impl Args {
+ /// Returns the server address for `tcp`, `quic`, `http`, or `ws`.
+ ///
+ /// Transport names are case-sensitive. Returns `None` for an unsupported
name.
+ /// For HTTP, removes `http://` from the API URL.
pub fn get_server_address(&self) -> Option<String> {
- match self.transport.as_str() {
- QUIC_TRANSPORT => Some(self.quic_server_address.clone()),
- HTTP_TRANSPORT =>
Some(self.http_api_url.clone().replace("http://", "")),
- TCP_TRANSPORT => Some(self.tcp_server_address.clone()),
- WEBSOCKET_TRANSPORT => Some(self.websocket_server_address.clone()),
- _ => None,
+ match TransportProtocol::from_str(&self.transport).ok()? {
+ TransportProtocol::Quic => Some(self.quic_server_address.clone()),
+ TransportProtocol::Http =>
Some(self.http_api_url.replace("http://", "")),
+ TransportProtocol::Tcp => Some(self.tcp_server_address.clone()),
+ TransportProtocol::WebSocket =>
Some(self.websocket_server_address.clone()),
}
}
}
@@ -522,3 +522,41 @@ impl From<Vec<ArgsOptional>> for Args {
args
}
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ fn args_with_transport(transport: &str) -> Args {
+ Args {
+ transport: transport.to_string(),
+ ..Args::default()
+ }
+ }
+
+ #[test]
+ fn should_return_server_address_for_each_transport() {
+ assert_eq!(
+ args_with_transport("tcp").get_server_address().as_deref(),
+ Some("127.0.0.1:8090")
+ );
+ assert_eq!(
+ args_with_transport("quic").get_server_address().as_deref(),
+ Some("127.0.0.1:8080")
+ );
+ assert_eq!(
+ args_with_transport("http").get_server_address().as_deref(),
+ Some("localhost:3000")
+ );
+ assert_eq!(
+ args_with_transport("ws").get_server_address().as_deref(),
+ Some("127.0.0.1:8092")
+ );
+ }
+
+ #[test]
+ fn should_return_none_for_unknown_transport() {
+ assert_eq!(args_with_transport("websocket").get_server_address(),
None);
+ assert_eq!(args_with_transport("foo").get_server_address(), None);
+ }
+}
diff --git a/core/integration/tests/cli/common/mod.rs
b/core/integration/tests/cli/common/mod.rs
index 31a04fdf3..2c3c59325 100644
--- a/core/integration/tests/cli/common/mod.rs
+++ b/core/integration/tests/cli/common/mod.rs
@@ -92,6 +92,39 @@ pub(crate) trait IggyCmdTestCase {
}
}
+/// Runs the wrapped test case with `--transport ws` against the server's
WebSocket address.
+pub(crate) struct OverWebSocket<T>(pub(crate) T);
+
+#[async_trait]
+impl<T: IggyCmdTestCase + Send + Sync> IggyCmdTestCase for OverWebSocket<T> {
+ async fn prepare_server_state(&mut self, client: &dyn Client) {
+ self.0.prepare_server_state(client).await;
+ }
+
+ fn get_command(&self) -> IggyCmdCommand {
+ self.0.get_command().opts(vec!["--transport", "ws"])
+ }
+
+ fn provide_stdin_input(&self) -> Option<Vec<String>> {
+ self.0.provide_stdin_input()
+ }
+
+ fn verify_command(&self, command_state: Assert) {
+ self.0.verify_command(command_state);
+ }
+
+ async fn verify_server_state(&self, client: &dyn Client) {
+ self.0.verify_server_state(client).await;
+ }
+
+ fn protocol(&self, server: &ServerHandle) -> Vec<String> {
+ vec![
+ "--websocket-server-address".into(),
+ server.websocket_addr().unwrap().to_string(),
+ ]
+ }
+}
+
pub(crate) struct IggyCmdTest {
harness: TestHarness,
start_server: bool,
@@ -268,6 +301,14 @@ impl IggyCmdTest {
pub(crate) fn get_tcp_server_address(&self) -> Option<String> {
self.harness.server().raw_tcp_addr()
}
+
+ #[cfg(not(target_os = "macos"))]
+ pub(crate) fn get_websocket_server_address(&self) -> Option<String> {
+ self.harness
+ .server()
+ .websocket_addr()
+ .map(|addr| addr.to_string())
+ }
}
impl Default for IggyCmdTest {
diff --git a/core/integration/tests/cli/general/mod.rs
b/core/integration/tests/cli/general/mod.rs
index 0424c963a..802a7ff06 100644
--- a/core/integration/tests/cli/general/mod.rs
+++ b/core/integration/tests/cli/general/mod.rs
@@ -19,3 +19,4 @@ mod test_help_command;
mod test_missing_credentials;
mod test_overview_command;
mod test_quiet_mode;
+mod test_unknown_transport;
diff --git a/core/integration/tests/cli/general/test_unknown_transport.rs
b/core/integration/tests/cli/general/test_unknown_transport.rs
new file mode 100644
index 000000000..0ea6ffba5
--- /dev/null
+++ b/core/integration/tests/cli/general/test_unknown_transport.rs
@@ -0,0 +1,65 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use crate::cli::common::{IggyCmdCommand, IggyCmdTest, IggyCmdTestCase};
+use assert_cmd::assert::Assert;
+use async_trait::async_trait;
+use iggy::prelude::Client;
+use predicates::str::contains;
+use serial_test::parallel;
+
+struct TestUnknownTransportCmd {
+ args: Vec<&'static str>,
+}
+
+#[async_trait]
+impl IggyCmdTestCase for TestUnknownTransportCmd {
+ async fn prepare_server_state(&mut self, _client: &dyn Client) {}
+
+ fn get_command(&self) -> IggyCmdCommand {
+ IggyCmdCommand::new()
+ .opts(vec!["--transport", "foo"])
+ .args(self.args.clone())
+ }
+
+ fn verify_command(&self, command_state: Assert) {
+ command_state.failure().stderr(contains(
+ "invalid transport 'foo' - valid values are: tcp, quic, http, ws",
+ ));
+ }
+
+ async fn verify_server_state(&self, _client: &dyn Client) {}
+}
+
+#[tokio::test]
+#[parallel]
+pub async fn should_fail_with_error_message() {
+ let mut iggy_cmd_test = IggyCmdTest::default();
+
+ iggy_cmd_test.setup().await;
+ for args in [
+ vec!["login"],
+ vec!["logout"],
+ vec!["pat", "create", "name"],
+ vec!["pat", "delete", "name"],
+ vec!["session", "status"],
+ ] {
+ iggy_cmd_test
+ .execute_test(TestUnknownTransportCmd { args })
+ .await;
+ }
+}
diff --git
a/core/integration/tests/cli/personal_access_token/test_pat_create_command.rs
b/core/integration/tests/cli/personal_access_token/test_pat_create_command.rs
index 613e42789..b2629c882 100644
---
a/core/integration/tests/cli/personal_access_token/test_pat_create_command.rs
+++
b/core/integration/tests/cli/personal_access_token/test_pat_create_command.rs
@@ -16,7 +16,8 @@
// under the License.
use crate::cli::common::{
- CLAP_INDENT, IggyCmdCommand, IggyCmdTest, IggyCmdTestCase, TestHelpCmd,
USAGE_PREFIX,
+ CLAP_INDENT, IggyCmdCommand, IggyCmdTest, IggyCmdTestCase, OverWebSocket,
TestHelpCmd,
+ USAGE_PREFIX,
};
use assert_cmd::assert::Assert;
use async_trait::async_trait;
@@ -117,6 +118,20 @@ pub async fn should_be_successful() {
.await;
}
+#[tokio::test]
+#[parallel]
+pub async fn should_be_successful_using_transport_ws() {
+ let mut iggy_cmd_test = IggyCmdTest::default();
+
+ iggy_cmd_test.setup().await;
+ iggy_cmd_test
+ .execute_test(OverWebSocket(TestPatCreateCmd::new(
+ String::from("main"),
+ None,
+ )))
+ .await;
+}
+
#[tokio::test]
#[parallel]
pub async fn should_help_match() {
diff --git
a/core/integration/tests/cli/personal_access_token/test_pat_delete_command.rs
b/core/integration/tests/cli/personal_access_token/test_pat_delete_command.rs
index f76b1ee54..aea59a46b 100644
---
a/core/integration/tests/cli/personal_access_token/test_pat_delete_command.rs
+++
b/core/integration/tests/cli/personal_access_token/test_pat_delete_command.rs
@@ -15,7 +15,9 @@
// specific language governing permissions and limitations
// under the License.
-use crate::cli::common::{IggyCmdCommand, IggyCmdTest, IggyCmdTestCase,
TestHelpCmd, USAGE_PREFIX};
+use crate::cli::common::{
+ IggyCmdCommand, IggyCmdTest, IggyCmdTestCase, OverWebSocket, TestHelpCmd,
USAGE_PREFIX,
+};
use assert_cmd::assert::Assert;
use async_trait::async_trait;
use iggy::prelude::Client;
@@ -86,6 +88,17 @@ pub async fn should_be_successful() {
.await;
}
+#[tokio::test]
+#[parallel]
+pub async fn should_be_successful_using_transport_ws() {
+ let mut iggy_cmd_test = IggyCmdTest::default();
+
+ iggy_cmd_test.setup().await;
+ iggy_cmd_test
+
.execute_test(OverWebSocket(TestPatDeleteCmd::new(String::from("name"))))
+ .await;
+}
+
#[tokio::test]
#[parallel]
pub async fn should_help_match() {
diff --git a/core/integration/tests/cli/system/mod.rs
b/core/integration/tests/cli/system/mod.rs
index 7a3d6066a..4fc3dce6d 100644
--- a/core/integration/tests/cli/system/mod.rs
+++ b/core/integration/tests/cli/system/mod.rs
@@ -29,5 +29,7 @@ mod test_logout_command;
#[cfg(not(any(target_os = "macos", target_env = "musl")))]
mod test_me_command;
mod test_ping_command;
+#[cfg(not(any(target_os = "macos", target_env = "musl")))]
+mod test_session_status_cmd;
mod test_snapshot_cmd;
mod test_stats_command;
diff --git a/core/integration/tests/cli/system/test_cli_session_scenario.rs
b/core/integration/tests/cli/system/test_cli_session_scenario.rs
index 8b7d245af..2c6bc59df 100644
--- a/core/integration/tests/cli/system/test_cli_session_scenario.rs
+++ b/core/integration/tests/cli/system/test_cli_session_scenario.rs
@@ -15,10 +15,11 @@
// specific language governing permissions and limitations
// under the License.
-use crate::cli::common::IggyCmdTest;
+use crate::cli::common::{IggyCmdTest, OverWebSocket};
use crate::cli::system::test_login_cmd::{TestLoginCmd, TestLoginCmdType};
use crate::cli::system::test_logout_cmd::TestLogoutCmd;
use crate::cli::system::test_me_command::{Scenario, TestMeCmd};
+use crate::cli::system::test_session_status_cmd::TestSessionStatusCmd;
use iggy_common::TransportProtocol;
use serial_test::serial;
@@ -105,3 +106,42 @@ pub async fn should_be_successful() {
))
.await;
}
+
+#[tokio::test]
+#[serial]
+pub async fn should_be_successful_using_transport_ws() {
+ let mut iggy_cmd_test = IggyCmdTest::default();
+
+ iggy_cmd_test.setup().await;
+ let server_address = iggy_cmd_test.get_websocket_server_address();
+ assert!(server_address.is_some());
+ let server_address = server_address.unwrap();
+
+ iggy_cmd_test
+ .execute_test(OverWebSocket(TestLoginCmd::new(
+ server_address.clone(),
+ TestLoginCmdType::Success,
+ )))
+ .await;
+ iggy_cmd_test
+ .execute_test(OverWebSocket(TestSessionStatusCmd::new(
+ server_address.clone(),
+ true,
+ )))
+ .await;
+ iggy_cmd_test
+ .execute_test(TestMeCmd::new(
+ TransportProtocol::WebSocket,
+ Scenario::SuccessWithoutCredentials,
+ ))
+ .await;
+ iggy_cmd_test
+
.execute_test(OverWebSocket(TestLogoutCmd::new(server_address.clone())))
+ .await;
+ iggy_cmd_test
+ .execute_test(OverWebSocket(TestSessionStatusCmd::new(
+ server_address,
+ false,
+ )))
+ .await;
+}
diff --git a/core/integration/tests/cli/system/test_me_command.rs
b/core/integration/tests/cli/system/test_me_command.rs
index cb92c9cee..8c1540bb1 100644
--- a/core/integration/tests/cli/system/test_me_command.rs
+++ b/core/integration/tests/cli/system/test_me_command.rs
@@ -33,25 +33,6 @@ pub(super) enum Scenario {
FailureDueToSessionTimeout,
}
-// Helper trait to add command-specific methods to TransportProtocol
-trait TransportProtocolExt {
- fn as_arg(&self) -> Vec<&str>;
-}
-
-impl TransportProtocolExt for TransportProtocol {
- fn as_arg(&self) -> Vec<&str> {
- match self {
- TransportProtocol::Tcp => vec!["--transport", "tcp"],
- TransportProtocol::Quic => vec!["--transport", "quic"],
- TransportProtocol::WebSocket => vec!["--transport", "websocket"],
- // Note: HTTP is not supported for the 'me' command
- TransportProtocol::Http => {
- panic!("HTTP transport is not supported for the 'me' command")
- }
- }
- }
-}
-
#[derive(Debug, Default)]
pub(super) struct TestMeCmd {
protocol: TransportProtocol,
@@ -61,8 +42,8 @@ pub(super) struct TestMeCmd {
impl TestMeCmd {
pub(super) fn new(protocol: TransportProtocol, scenario: Scenario) -> Self
{
assert!(
- protocol == TransportProtocol::Tcp || protocol ==
TransportProtocol::Quic,
- "Only TCP and QUIC protocols are supported for the 'me' command"
+ protocol != TransportProtocol::Http,
+ "HTTP transport is not supported for the 'me' command"
);
Self { protocol, scenario }
}
@@ -73,7 +54,9 @@ impl IggyCmdTestCase for TestMeCmd {
async fn prepare_server_state(&mut self, _client: &dyn Client) {}
fn get_command(&self) -> IggyCmdCommand {
- let command =
IggyCmdCommand::new().opts(self.protocol.as_arg()).arg("me");
+ let command = IggyCmdCommand::new()
+ .opts(vec!["--transport", self.protocol.as_str()])
+ .arg("me");
match &self.scenario {
Scenario::SuccessWithCredentials => command.with_env_credentials(),
@@ -86,13 +69,14 @@ impl IggyCmdTestCase for TestMeCmd {
fn verify_command(&self, command_state: Assert) {
match &self.scenario {
Scenario::SuccessWithCredentials |
Scenario::SuccessWithoutCredentials => {
+ let transport = match self.protocol {
+ TransportProtocol::WebSocket => "WebSocket".to_string(),
+ _ => self.protocol.as_str().to_uppercase(),
+ };
command_state
.success()
.stdout(starts_with("Executing me command\n"))
- .stdout(contains(format!(
- "Transport | {}",
- self.protocol.as_str().to_uppercase()
- )));
+ .stdout(contains(format!("Transport | {transport}")));
}
Scenario::FailureWithoutCredentials => {
command_state
diff --git a/core/integration/tests/cli/system/test_session_status_cmd.rs
b/core/integration/tests/cli/system/test_session_status_cmd.rs
new file mode 100644
index 000000000..a7263c818
--- /dev/null
+++ b/core/integration/tests/cli/system/test_session_status_cmd.rs
@@ -0,0 +1,65 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use crate::cli::common::{IggyCmdCommand, IggyCmdTestCase,
ensure_keyring_store};
+use assert_cmd::assert::Assert;
+use async_trait::async_trait;
+use iggy::prelude::Client;
+use predicates::str::{contains, starts_with};
+
+#[derive(Debug)]
+pub(super) struct TestSessionStatusCmd {
+ server_address: String,
+ active: bool,
+}
+
+impl TestSessionStatusCmd {
+ pub(super) fn new(server_address: String, active: bool) -> Self {
+ ensure_keyring_store();
+ Self {
+ server_address,
+ active,
+ }
+ }
+}
+
+#[async_trait]
+impl IggyCmdTestCase for TestSessionStatusCmd {
+ async fn prepare_server_state(&mut self, _client: &dyn Client) {}
+
+ fn get_command(&self) -> IggyCmdCommand {
+ IggyCmdCommand::new().arg("session").arg("status")
+ }
+
+ fn verify_command(&self, command_state: Assert) {
+ let active = if self.active {
+ "Yes (token presence only, freshness not verified)"
+ } else {
+ "No"
+ };
+ command_state
+ .success()
+ .stdout(starts_with("Executing session status command\n"))
+ .stdout(contains(format!(
+ "Server Address | {}",
+ self.server_address
+ )))
+ .stdout(contains(format!("Session Active | {active}")));
+ }
+
+ async fn verify_server_state(&self, _client: &dyn Client) {}
+}