summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--internal/clients/connectors/serverconnection_test.go30
-rw-r--r--internal/clients/interactive_control_test.go43
2 files changed, 73 insertions, 0 deletions
diff --git a/internal/clients/connectors/serverconnection_test.go b/internal/clients/connectors/serverconnection_test.go
index 76c4eb6..01fe4af 100644
--- a/internal/clients/connectors/serverconnection_test.go
+++ b/internal/clients/connectors/serverconnection_test.go
@@ -333,6 +333,36 @@ func TestServerConnectionApplySessionSpecRejectsUnexpectedAck(t *testing.T) {
}
}
+func TestServerConnectionApplySessionSpecTimesOutWaitingForAck(t *testing.T) {
+ resetClientLogger(t)
+
+ mock := &mockHandler{
+ waitForCapabilities: true,
+ capabilities: map[string]bool{
+ protocol.CapabilityQueryUpdateV1: true,
+ },
+ }
+ conn := &ServerConnection{
+ server: "srv1",
+ handler: mock,
+ }
+
+ err := conn.ApplySessionSpec(sessionspec.Spec{
+ Mode: omode.TailClient,
+ Files: []string{"/var/log/app.log"},
+ Regex: "ERROR",
+ }, 10*time.Millisecond)
+ if !errors.Is(err, ErrSessionAckTimeout) {
+ t.Fatalf("expected ErrSessionAckTimeout, got %v", err)
+ }
+ if len(mock.commands) != 1 {
+ t.Fatalf("expected session command to be sent before timeout, got %d", len(mock.commands))
+ }
+ if _, _, ok := conn.CommittedSession(); ok {
+ t.Fatalf("unexpected committed session after missing ack")
+ }
+}
+
type testSSHSettings struct {
port int
timeout time.Duration
diff --git a/internal/clients/interactive_control_test.go b/internal/clients/interactive_control_test.go
index 1cc31ec..a8b5aa0 100644
--- a/internal/clients/interactive_control_test.go
+++ b/internal/clients/interactive_control_test.go
@@ -169,6 +169,49 @@ func TestApplyInteractiveReloadCommitsSharedState(t *testing.T) {
}
}
+func TestApplyInteractiveReloadRejectsMismatchedCommittedGenerations(t *testing.T) {
+ connA := &interactiveReloadConnector{server: "srv1", supported: true, generation: 4}
+ connB := &interactiveReloadConnector{server: "srv2", supported: true, generation: 5}
+ maker := &interactiveReloadMaker{}
+
+ client := &baseClient{
+ Args: config.Args{
+ Mode: omode.GrepClient,
+ What: "/var/log/app.log",
+ RegexStr: "ERROR",
+ },
+ sessionSpec: SessionSpec{
+ Mode: omode.GrepClient,
+ Files: []string{"/var/log/app.log"},
+ Regex: "ERROR",
+ },
+ connections: []connectors.Connector{connA, connB},
+ maker: maker,
+ }
+
+ nextArgs := config.Args{
+ Mode: omode.GrepClient,
+ What: "/tmp/new.log",
+ RegexStr: "WARN",
+ }
+ nextSpec := SessionSpec{
+ Mode: omode.GrepClient,
+ Files: []string{"/tmp/new.log"},
+ Regex: "WARN",
+ }
+
+ err := client.applyInteractiveReload(nextArgs, nextSpec)
+ if err == nil || err.Error() != "mismatched committed generations: got 4 and 5" {
+ t.Fatalf("expected mismatched generation error, got %v", err)
+ }
+ if client.Args.What != "/var/log/app.log" || client.sessionSpec.Regex != "ERROR" {
+ t.Fatalf("client state changed on mismatched generations: args=%#v spec=%#v", client.Args, client.sessionSpec)
+ }
+ if len(maker.commits) != 0 {
+ t.Fatalf("expected no committed shared state, got %#v", maker.commits)
+ }
+}
+
type interactiveReloadConnector struct {
appliedSpec sessionspec.Spec
applyErr error