Skip to content

Commit

Permalink
acceptance tests
Browse files Browse the repository at this point in the history
  • Loading branch information
oke11o committed Jan 12, 2024
1 parent cca655a commit 1c46c95
Show file tree
Hide file tree
Showing 11 changed files with 289 additions and 18 deletions.
5 changes: 5 additions & 0 deletions .mapping.json
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,11 @@
"main.go":"load/projects/pandora/main.go",
"script/checkfmt.sh":"load/projects/pandora/script/checkfmt.sh",
"script/coverage.sh":"load/projects/pandora/script/coverage.sh",
"tests/acceptance/http_test.go":"load/projects/pandora/tests/acceptance/http_test.go",
"tests/acceptance/testdata/http/http.yaml":"load/projects/pandora/tests/acceptance/testdata/http/http.yaml",
"tests/acceptance/testdata/http/http2.yaml":"load/projects/pandora/tests/acceptance/testdata/http/http2.yaml",
"tests/acceptance/testdata/http/https.yaml":"load/projects/pandora/tests/acceptance/testdata/http/https.yaml",
"tests/acceptance/testdata/http/payload.uri":"load/projects/pandora/tests/acceptance/testdata/http/payload.uri",
"tests/http_scenario/main_test.go":"load/projects/pandora/tests/http_scenario/main_test.go",
"tests/http_scenario/testdata/filter.json":"load/projects/pandora/tests/http_scenario/testdata/filter.json",
"tests/http_scenario/testdata/http_payload.hcl":"load/projects/pandora/tests/http_scenario/testdata/http_payload.hcl",
Expand Down
12 changes: 6 additions & 6 deletions cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ import (
"go.uber.org/zap/zapcore"
)

const Version = "0.5.17"
const Version = "0.5.18"
const defaultConfigFile = "load"
const stdinConfigSelector = "-"

var configSearchDirs = []string{"./", "./config", "/etc/pandora"}

type cliConfig struct {
type CliConfig struct {
Engine engine.Config `config:",squash"`
Log logConfig `config:"log"`
Monitoring monitoringConfig `config:"monitoring"`
Expand All @@ -56,8 +56,8 @@ func newLogger(conf logConfig) *zap.Logger {
return log
}

func defaultConfig() *cliConfig {
return &cliConfig{
func DefaultConfig() *CliConfig {
return &CliConfig{
Log: logConfig{
Level: zap.InfoLevel,
File: "stdout",
Expand Down Expand Up @@ -191,7 +191,7 @@ func runEngine(ctx context.Context, engine *engine.Engine, errs chan error) {
errs <- engine.Run(ctx)
}

func readConfig(args []string) *cliConfig {
func readConfig(args []string) *CliConfig {
log, err := zap.NewDevelopment(zap.AddCaller())
if err != nil {
panic(err)
Expand Down Expand Up @@ -236,7 +236,7 @@ func readConfig(args []string) *cliConfig {
}
}

conf := defaultConfig()
conf := DefaultConfig()
err = config.DecodeAndValidate(v.AllSettings(), conf)
if err != nil {
log.Fatal("Config decode failed", zap.Error(err))
Expand Down
2 changes: 1 addition & 1 deletion components/guns/grpc/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ func (g *Gun) AcceptWarmUpResult(i interface{}) error {
}

func NewGun(conf GunConfig) *Gun {
answLog := answlog.Init(conf.AnswLog.Path)
answLog := answlog.Init(conf.AnswLog.Path, conf.AnswLog.Enabled)
return &Gun{conf: conf, answLog: answLog}
}

Expand Down
4 changes: 2 additions & 2 deletions components/guns/http_scenario/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func (g *gunWrapper) Bind(a core.Aggregator, deps core.GunDeps) error {
func Import(fs afero.Fs) {
register.Gun("http/scenario", func(conf phttp.HTTPGunConfig) func() core.Gun {
targetResolved, _ := PreResolveTargetAddr(&conf.Client, conf.Gun.Target)
answLog := answlog.Init(conf.Gun.Base.AnswLog.Path)
answLog := answlog.Init(conf.Gun.Base.AnswLog.Path, conf.Gun.Base.AnswLog.Enabled)
return func() core.Gun {
gun := NewHTTPGun(conf, answLog, targetResolved)
return WrapGun(gun)
Expand All @@ -44,7 +44,7 @@ func Import(fs afero.Fs) {

register.Gun("http2/scenario", func(conf phttp.HTTP2GunConfig) func() (core.Gun, error) {
targetResolved, _ := PreResolveTargetAddr(&conf.Client, conf.Gun.Target)
answLog := answlog.Init(conf.Gun.Base.AnswLog.Path)
answLog := answlog.Init(conf.Gun.Base.AnswLog.Path, conf.Gun.Base.AnswLog.Enabled)
return func() (core.Gun, error) {
gun, err := NewHTTP2Gun(conf, answLog, targetResolved)
return WrapGun(gun), err
Expand Down
11 changes: 3 additions & 8 deletions components/phttp/import/import.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
// Copyright (c) 2017 Yandex LLC. All rights reserved.
// Use of this source code is governed by a MPL 2.0
// license that can be found in the LICENSE file.
// Author: Vladimir Skipor <[email protected]>

package phttp

import (
Expand All @@ -27,13 +22,13 @@ func Import(fs afero.Fs) {

register.Gun("http", func(conf phttp.HTTPGunConfig) func() core.Gun {
targetResolved, _ := PreResolveTargetAddr(&conf.Client, conf.Gun.Target)
answLog := answlog.Init(conf.Gun.Base.AnswLog.Path)
answLog := answlog.Init(conf.Gun.Base.AnswLog.Path, conf.Gun.Base.AnswLog.Enabled)
return func() core.Gun { return phttp.WrapGun(phttp.NewHTTPGun(conf, answLog, targetResolved)) }
}, phttp.DefaultHTTPGunConfig)

register.Gun("http2", func(conf phttp.HTTP2GunConfig) func() (core.Gun, error) {
targetResolved, _ := PreResolveTargetAddr(&conf.Client, conf.Gun.Target)
answLog := answlog.Init(conf.Gun.Base.AnswLog.Path)
answLog := answlog.Init(conf.Gun.Base.AnswLog.Path, conf.Gun.Base.AnswLog.Enabled)
return func() (core.Gun, error) {
gun, err := phttp.NewHTTP2Gun(conf, answLog, targetResolved)
return phttp.WrapGun(gun), err
Expand All @@ -42,7 +37,7 @@ func Import(fs afero.Fs) {

register.Gun("connect", func(conf phttp.ConnectGunConfig) func() core.Gun {
conf.Target, _ = PreResolveTargetAddr(&conf.Client, conf.Target)
answLog := answlog.Init(conf.BaseGunConfig.AnswLog.Path)
answLog := answlog.Init(conf.BaseGunConfig.AnswLog.Path, conf.BaseGunConfig.AnswLog.Enabled)
return func() core.Gun {
return phttp.WrapGun(phttp.NewConnectGun(conf, answLog))
}
Expand Down
5 changes: 4 additions & 1 deletion lib/answlog/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ import (
"go.uber.org/zap/zapcore"
)

func Init(path string) *zap.Logger {
func Init(path string, enabled bool) *zap.Logger {
if !enabled {
return zap.NewNop()
}
writerSyncer := getAnswWriter(path)
encoder := zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig())
core := zapcore.NewCore(encoder, writerSyncer, zapcore.DebugLevel)
Expand Down
194 changes: 194 additions & 0 deletions tests/acceptance/http_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
package httphttp2

import (
"bytes"
"context"
"net/http"
"net/http/httptest"
"os"
"sync"
"testing"
"text/template"

"github.com/spf13/afero"
"github.com/stretchr/testify/suite"
"github.com/yandex/pandora/cli"
grpc "github.com/yandex/pandora/components/grpc/import"
phttpimport "github.com/yandex/pandora/components/phttp/import"
"github.com/yandex/pandora/core"
"github.com/yandex/pandora/core/config"
"github.com/yandex/pandora/core/engine"
coreimport "github.com/yandex/pandora/core/import"
"github.com/yandex/pandora/lib/monitoring"
"go.uber.org/atomic"
"go.uber.org/zap"
"go.uber.org/zap/zaptest/observer"
"golang.org/x/net/http2"
"gopkg.in/yaml.v2"
)

var testOnce = &sync.Once{}

func TestGunSuite(t *testing.T) {
suite.Run(t, new(PandoraSuite))
}

type PandoraSuite struct {
suite.Suite
fs afero.Fs
log *zap.Logger
metrics engine.Metrics
}

func (s *PandoraSuite) SetupSuite() {
s.fs = afero.NewOsFs()
coreimport.Import(s.fs)
phttpimport.Import(s.fs)
grpc.Import(s.fs)

s.log = setupLogsCapture()
s.metrics = newEngineMetrics()
}

func (s *PandoraSuite) Test_Http() {
var requetsCount atomic.Int64 // Request served by test server.
requetsCount.Store(0)
srv := httptest.NewUnstartedServer(http.HandlerFunc(
func(rw http.ResponseWriter, req *http.Request) {
requetsCount.Inc()
rw.WriteHeader(http.StatusOK)
}))
defer srv.Close()

conf := s.parseConfigFile("testdata/http/http.yaml", srv.Listener.Addr().String())
s.Require().Equal(1, len(conf.Engine.Pools))
aggr := &aggregator{}
conf.Engine.Pools[0].Aggregator = aggr
pandora := engine.New(s.log, s.metrics, conf.Engine)

srv.Start()
err := pandora.Run(context.Background())
s.Assert().Equal(int64(4), requetsCount.Load())
s.Require().NoError(err)
s.Require().Equal(4, len(aggr.samples))
}

func (s *PandoraSuite) Test_Https() {
var requetsCount atomic.Int64 // Request served by test server.
requetsCount.Store(0)
srv := httptest.NewUnstartedServer(http.HandlerFunc(
func(rw http.ResponseWriter, req *http.Request) {
requetsCount.Inc()
rw.WriteHeader(http.StatusOK)
}))
defer srv.Close()

conf := s.parseConfigFile("testdata/http/https.yaml", srv.Listener.Addr().String())
s.Require().Equal(1, len(conf.Engine.Pools))
aggr := &aggregator{}
conf.Engine.Pools[0].Aggregator = aggr
pandora := engine.New(s.log, s.metrics, conf.Engine)

srv.StartTLS()
err := pandora.Run(context.Background())
s.Assert().Equal(int64(4), requetsCount.Load())
s.Require().NoError(err)
s.Require().Equal(4, len(aggr.samples))
}

func (s *PandoraSuite) Test_Http2() {
var requetsCount atomic.Int64 // Request served by test server.
requetsCount.Store(0)
srv := httptest.NewUnstartedServer(http.HandlerFunc(
func(rw http.ResponseWriter, req *http.Request) {
requetsCount.Inc()
rw.WriteHeader(http.StatusOK)
}))
defer srv.Close()

conf := s.parseConfigFile("testdata/http/http2.yaml", srv.Listener.Addr().String())
s.Require().Equal(1, len(conf.Engine.Pools))
aggr := &aggregator{}
conf.Engine.Pools[0].Aggregator = aggr
pandora := engine.New(s.log, s.metrics, conf.Engine)

_ = http2.ConfigureServer(srv.Config, nil)
srv.TLS = srv.Config.TLSConfig
srv.StartTLS()

err := pandora.Run(context.Background())
s.Assert().Equal(int64(4), requetsCount.Load())
s.Require().NoError(err)
s.Require().Equal(4, len(aggr.samples))
}

func (s *PandoraSuite) Test_Http2_UnsupportTarget() {
var requetsCount atomic.Int64 // Request served by test server.
requetsCount.Store(0)
srv := httptest.NewUnstartedServer(http.HandlerFunc(
func(rw http.ResponseWriter, req *http.Request) {
requetsCount.Inc()
rw.WriteHeader(http.StatusOK)
}))
defer srv.Close()

conf := s.parseConfigFile("testdata/http/http2.yaml", srv.Listener.Addr().String())
s.Require().Equal(1, len(conf.Engine.Pools))
aggr := &aggregator{}
conf.Engine.Pools[0].Aggregator = aggr
pandora := engine.New(s.log, s.metrics, conf.Engine)

//_ = http2.ConfigureServer(srv.Config, nil)
//srv.TLS = srv.Config.TLSConfig
srv.StartTLS()

err := pandora.Run(context.Background())
s.Assert().Equal(int64(0), requetsCount.Load())
s.Require().Error(err)
s.Require().Contains(err.Error(), "shoot panic: Non HTTP/2 connection established. Seems that target doesn't support HTTP/2.")
}

func (s *PandoraSuite) parseConfigFile(filename string, serverAddr string) *cli.CliConfig {
f, err := os.ReadFile(filename)
s.Require().NoError(err)
tmpl, err := template.New("x").Parse(string(f))
s.Require().NoError(err)
b := &bytes.Buffer{}
err = tmpl.Execute(b, map[string]string{"target": serverAddr})
s.Require().NoError(err)
mapCfg := map[string]any{}
err = yaml.Unmarshal(b.Bytes(), &mapCfg)
s.Require().NoError(err)

conf := cli.DefaultConfig()
err = config.DecodeAndValidate(mapCfg, conf)
s.Require().NoError(err)

return conf
}

func setupLogsCapture() *zap.Logger {
c, _ := observer.New(zap.InfoLevel)
return zap.New(c)
}

func newEngineMetrics() engine.Metrics {
return engine.Metrics{
Request: monitoring.NewCounter("engine_Requests"),
Response: monitoring.NewCounter("engine_Responses"),
InstanceStart: monitoring.NewCounter("engine_UsersStarted"),
InstanceFinish: monitoring.NewCounter("engine_UsersFinished"),
}
}

type aggregator struct {
samples []core.Sample
}

func (a *aggregator) Run(ctx context.Context, deps core.AggregatorDeps) error {
return nil
}

func (a *aggregator) Report(s core.Sample) {
a.samples = append(a.samples, s)
}
24 changes: 24 additions & 0 deletions tests/acceptance/testdata/http/http.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
pools:
- id: ""
ammo:
file: testdata/http/payload.uri
type: uri
result:
type: discard
gun:
target: {{.target}}
type: http
answlog:
enabled: false
rps-per-instance: false
rps:
- times: 2
type: once
- duration: 0.5s
ops: 4
type: const
startup:
- times: 2
type: once
log:
level: debug
24 changes: 24 additions & 0 deletions tests/acceptance/testdata/http/http2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
pools:
- id: ""
ammo:
file: testdata/http/payload.uri
type: uri
result:
type: discard
gun:
target: {{.target}}
type: http2
answlog:
enabled: false
rps-per-instance: false
rps:
- times: 2
type: once
- duration: 0.5s
ops: 4
type: const
startup:
- times: 2
type: once
log:
level: debug
Loading

0 comments on commit 1c46c95

Please sign in to comment.