| // 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. |
| |
| package tests |
| |
| import ( |
| "context" |
| "errors" |
| "fmt" |
| |
| "github.com/apache/iggy/bdd/go/tests/env" |
| "github.com/apache/iggy/foreign/go/client" |
| "github.com/apache/iggy/foreign/go/client/tcp" |
| iggcon "github.com/apache/iggy/foreign/go/contracts" |
| ierror "github.com/apache/iggy/foreign/go/errors" |
| "github.com/cucumber/godog" |
| ) |
| |
| type rawCommandCtxKey struct{} |
| |
| type rawCommandCtx struct { |
| client iggcon.Client |
| serverAddr string |
| lastResponse []byte |
| lastError error |
| } |
| |
| func getRawCommandCtx(ctx context.Context) *rawCommandCtx { |
| return ctx.Value(rawCommandCtxKey{}).(*rawCommandCtx) |
| } |
| |
| type rawCommandSteps struct{} |
| |
| func (rawCommandSteps) givenRunningServer(ctx context.Context) error { |
| getRawCommandCtx(ctx).serverAddr = env.ServerAddress() |
| return nil |
| } |
| |
| func (rawCommandSteps) givenAuthenticationAsRoot(ctx context.Context) error { |
| state := getRawCommandCtx(ctx) |
| iggyClient, err := client.NewIggyClient(client.WithTcp(tcp.WithServerAddress(state.serverAddr))) |
| if err != nil { |
| return fmt.Errorf("create client: %w", err) |
| } |
| if err = iggyClient.Connect(ctx); err != nil { |
| return fmt.Errorf("connect client: %w", err) |
| } |
| username, password := env.RootCredentials() |
| if _, err = iggyClient.LoginUser(ctx, username, password); err != nil { |
| return fmt.Errorf("authenticate client: %w", err) |
| } |
| state.client = iggyClient |
| return nil |
| } |
| |
| func (rawCommandSteps) whenSendRawCommand(ctx context.Context, code uint32) error { |
| state := getRawCommandCtx(ctx) |
| state.lastResponse, state.lastError = state.client.SendBinaryRequest(ctx, code, nil) |
| return nil |
| } |
| |
| func (rawCommandSteps) thenEmptyResponse(ctx context.Context) error { |
| state := getRawCommandCtx(ctx) |
| if state.lastError != nil { |
| return fmt.Errorf("raw command failed: %w", state.lastError) |
| } |
| if len(state.lastResponse) != 0 { |
| return fmt.Errorf("expected empty response, got %d bytes", len(state.lastResponse)) |
| } |
| return nil |
| } |
| |
| func (rawCommandSteps) thenNonEmptyResponse(ctx context.Context) error { |
| state := getRawCommandCtx(ctx) |
| if state.lastError != nil { |
| return fmt.Errorf("raw command failed: %w", state.lastError) |
| } |
| if len(state.lastResponse) == 0 { |
| return errors.New("expected non-empty response") |
| } |
| return nil |
| } |
| |
| func (rawCommandSteps) thenInvalidCommand(ctx context.Context) error { |
| if !errors.Is(getRawCommandCtx(ctx).lastError, ierror.ErrInvalidCommand) { |
| return fmt.Errorf("expected invalid command error, got %v", getRawCommandCtx(ctx).lastError) |
| } |
| return nil |
| } |
| |
| func initRawCommandScenario(sc *godog.ScenarioContext) { |
| sc.Before(func(context.Context, *godog.Scenario) (context.Context, error) { |
| return context.WithValue(context.Background(), rawCommandCtxKey{}, &rawCommandCtx{}), nil |
| }) |
| steps := rawCommandSteps{} |
| sc.Step(`I have a running Iggy server`, steps.givenRunningServer) |
| sc.Step(`I am authenticated as the root user`, steps.givenAuthenticationAsRoot) |
| sc.Step(`^I send a raw command with code (\d+) and an empty payload$`, steps.whenSendRawCommand) |
| sc.Step(`the raw command should succeed with an empty response`, steps.thenEmptyResponse) |
| sc.Step(`the raw command should succeed with a non-empty response`, steps.thenNonEmptyResponse) |
| sc.Step(`the raw command should fail with an invalid command error`, steps.thenInvalidCommand) |
| sc.After(func(ctx context.Context, _ *godog.Scenario, scenarioError error) (context.Context, error) { |
| state := getRawCommandCtx(ctx) |
| if state.client != nil { |
| scenarioError = errors.Join(scenarioError, state.client.Close()) |
| } |
| return ctx, scenarioError |
| }) |
| } |