package server import ( "bytes" "context" "encoding/json" "errors" "fmt" "io" "net/http" "net/http/httptest" "strings" "testing" "time" "edge-infra.dev/pkg/sds/emergencyaccess/eaconst" "edge-infra.dev/pkg/sds/emergencyaccess/eagateway" "edge-infra.dev/pkg/sds/emergencyaccess/msgdata" "edge-infra.dev/pkg/sds/emergencyaccess/remotecli" "edge-infra.dev/pkg/sds/emergencyaccess/types" "github.com/gin-gonic/gin" "github.com/stretchr/testify/assert" ) type endSessionTestRCLI struct { eagateway.RemoteCLI cache map[string]remotecli.Target } func (rcli *endSessionTestRCLI) StartSession(_ context.Context, sessionID string, _ chan<- msgdata.CommandResponse, target remotecli.Target, _ ...remotecli.RCLIOption) error { rcli.cache[sessionID] = target return nil } func (rcli *endSessionTestRCLI) EndSession(_ context.Context, sessionID string) error { if sessionID == "fail" { return errors.New(sessionID) } delete(rcli.cache, sessionID) return nil } func TestEndSessionSuccess(t *testing.T) { r := httptest.NewRecorder() gin.SetMode(gin.TestMode) c, ginEngine := gin.CreateTestContext(r) // Setup authServer, authServerURL := authserviceServer(http.StatusOK) defer authServer.Close() rcli := &endSessionTestRCLI{} rcli.cache = make(map[string]remotecli.Target) config := eagateway.Config{AuthServiceHost: authServerURL} server, err := New(config, ginEngine, newLogger(), rcli, nil) assert.NoError(t, err) // Test for i := 0; i <= 2; i++ { sessionID := fmt.Sprint(i) target := defaultTarget target.Terminalid = fmt.Sprint(i) err = server.rcli.StartSession(c, sessionID, nil, target) assert.NoError(t, err) } for i := 0; i < 2; i++ { sessionID := fmt.Sprint(i) payload := types.EndSessionPayload{SessionID: sessionID} message, err := json.Marshal(payload) assert.NoError(t, err) req, err := http.NewRequestWithContext(c, http.MethodPost, "/ea/endSession", bytes.NewReader(message)) assert.NoError(t, err) req.Header.Set(eaconst.HeaderAuthKeyRoles, "role") ginEngine.ServeHTTP(r, req) assert.Eventually(t, func() bool { return r.Result().StatusCode == http.StatusOK }, 100*time.Millisecond, 10*time.Millisecond) assert.Nil(t, rcli.cache[sessionID]) for j := i + 1; j <= 2; j++ { assert.NotNil(t, rcli.cache[fmt.Sprint(j)]) } } } func TestEndSessionFail(t *testing.T) { tests := map[string]struct { sessionID string target types.Target expStatusCode int expOut string }{ "Invalid Payload": { sessionID: "", target: types.Target{}, expStatusCode: http.StatusBadRequest, expOut: `{"details":["Payload missing Session ID"], "errorCode":60202, "errorMessage":"Request Error - Invalid payload properties"}`, }, "RCLI Fail": { sessionID: "fail", target: defaultTarget, expStatusCode: http.StatusInternalServerError, expOut: `{"errorCode": 63101, "errorMessage": "End Session Failure - Failed to end session"}`, }, // TODO invalid json fail } for name, tc := range tests { t.Run(name, func(t *testing.T) { r := httptest.NewRecorder() gin.SetMode(gin.TestMode) c, ginEngine := gin.CreateTestContext(r) // Setup authServer, authServerURL := authserviceServer(http.StatusOK) defer authServer.Close() rcli := &endSessionTestRCLI{} rcli.cache = make(map[string]remotecli.Target) server, err := New(eagateway.Config{AuthServiceHost: authServerURL}, ginEngine, newLogger(), rcli, nil) assert.NoError(t, err) // Test err = server.rcli.StartSession(c, tc.sessionID, nil, tc.target) assert.NoError(t, err) payload := types.EndSessionPayload{SessionID: tc.sessionID} message, err := json.Marshal(payload) assert.NoError(t, err) req, err := http.NewRequestWithContext(c, http.MethodPost, "/ea/endSession", bytes.NewReader(message)) assert.NoError(t, err) req.Header.Set(eaconst.HeaderAuthKeyRoles, "role") ginEngine.ServeHTTP(r, req) assert.Equal(t, tc.expStatusCode, r.Result().StatusCode) buf := strings.Builder{} _, err = io.Copy(&buf, r.Result().Body) assert.NoError(t, err) assert.JSONEq(t, tc.expOut, buf.String()) }) } }