Skip to content

Commit

Permalink
more devopsmastertest scenarios
Browse files Browse the repository at this point in the history
  • Loading branch information
bbrodriges committed Oct 1, 2024
1 parent dc65c3f commit 4bcd447
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 25 deletions.
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@ SHELL=/bin/bash
AUTOTESTS = gophermarttest metricstest devopstest shortenertest shortenertestbeta devopsmastertest
UTILS = random statictest shortenerstress

.PHONY: clear prep perm

all: prep autotests utils perm

clear:
rm -rf bin/*

prep:
go mod tidy

Expand Down
140 changes: 115 additions & 25 deletions cmd/devopsmastertest/lesson01_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,11 @@ func (suite *Lesson01Suite) TestServerStats() {

// генерируем набор сценариев тестирования
suite.T().Log("generating scenarios")
respSet := newResponseSet()

maxRequests := len(respSet)
var stats []serverStat
var setOutputs []string
for _, resp := range respSet {
stats = append(stats, resp.stats)
setOutputs = append(setOutputs, resp.expectedOutput...)
}
scenarios := newScenarios()

suite.T().Log("creating handler")
reqNotifier := make(chan int)
handler := newFaultySrvHandler(stats, reqNotifier)
handler := suite.newFaultySrvHandler(scenarios, reqNotifier)

// запускаем сервер
suite.T().Log("staring HTTP server")
Expand Down Expand Up @@ -72,6 +64,7 @@ func (suite *Lesson01Suite) TestServerStats() {
// ждем завершения
suite.T().Log("waiting scenarios to complete")
var requestsMade int
maxRequests := len(scenarios)
func() {
for {
select {
Expand All @@ -82,7 +75,6 @@ func (suite *Lesson01Suite) TestServerStats() {
// время вышло
return
case requestsMade = <-reqNotifier:
suite.T().Logf("got request %d", requestsMade)
if requestsMade == maxRequests {
// все сценарии были обработаны
return
Expand All @@ -100,7 +92,12 @@ func (suite *Lesson01Suite) TestServerStats() {
}

// сравниваем вывод скрпта в консоль с ожидаемым выводом
expectedOutput := strings.Join(setOutputs, "\n")
var combinedOutput []string
for _, sc := range scenarios {
combinedOutput = append(combinedOutput, sc.expectedOutput...)
}
expectedOutput := strings.Join(combinedOutput, "\n")

if expectedOutput != "" {
expectedOutput += "\n"
}
Expand All @@ -110,27 +107,31 @@ func (suite *Lesson01Suite) TestServerStats() {
suite.Assert().Equal(expectedOutput, string(stdout), "Вывод скрипта отличается от ожидаемого")
}

func newFaultySrvHandler(stats []serverStat, notifier chan<- int) http.HandlerFunc {
func (suite *Lesson01Suite) newFaultySrvHandler(scs scenarios, notifier chan<- int) http.HandlerFunc {
var mu sync.Mutex
var receivedRequestsCount int
return func(w http.ResponseWriter, r *http.Request) {
// не даем делать запросы в многопоточном режиме, чтобы сохранить консистентность обработки/вывода результатов
mu.Lock()
defer mu.Unlock()

if receivedRequestsCount >= len(stats) {
suite.T().Logf("got HTTP request %d", receivedRequestsCount)

if receivedRequestsCount >= len(scs) {
// отвечаем ошибкой если у нас кончились заготовленные ответы,
// а запросы все еще приходят
w.WriteHeader(http.StatusInternalServerError)
return
}
body, err := stats[receivedRequestsCount].MarshalText()
scenario := scs[receivedRequestsCount]
body, err := scenario.stats.MarshalText()
if err != nil {
// почему-то не смогли закодировать данные сервера в строку
w.WriteHeader(http.StatusInternalServerError)
return
}
// отправляем ответ
suite.T().Logf("sending HTTP response body for scenario '%s': %s", scenario.name, string(body))
_, _ = w.Write(body)
// увеличиваем счетчик принятых запросов
receivedRequestsCount++
Expand All @@ -139,9 +140,10 @@ func newFaultySrvHandler(stats []serverStat, notifier chan<- int) http.HandlerFu
}
}

type responseSet []responsePair
type scenarios []serverStateScenario

type responsePair struct {
type serverStateScenario struct {
name string
stats serverStat
expectedOutput []string
}
Expand Down Expand Up @@ -181,7 +183,7 @@ const (
unitGbps = unitMbps * 1000
)

func newResponseSet() (res responseSet) {
func newScenarios() (res scenarios) {
src := rand.NewSource(time.Now().UnixNano())
rnd := rand.New(src)

Expand All @@ -192,35 +194,123 @@ func newResponseSet() (res responseSet) {

{
// сценарий: все в порядке
res = append(res, responsePair{
// добавляем несколько сценариев
for range intInRange(rnd, 1, 5) {
res = append(res, serverStateScenario{
name: "ok",
stats: serverStat{
CurrentLA: intInRange(rnd, 0, 29),
MemBytesAvailable: memBytesAvailable,
MemBytesUsed: intInRange(rnd, memBytesAvailable/3, memBytesAvailable/2),
DiskBytesAvailable: diskBytesAvailable,
DiskBytesUsed: intInRange(rnd, diskBytesAvailable/5, diskBytesAvailable/3),
NetBandwidthAvailable: netBandwidthAvailable,
NetBandwidthUsed: intInRange(rnd, netBandwidthAvailable/8, netBandwidthAvailable/4),
},
expectedOutput: nil,
})
}
}

{
// сценарий: слишком большое LA
currentLA := intInRange(rnd, 30, 99)
res = append(res, serverStateScenario{
name: "high_la",
stats: serverStat{
CurrentLA: intInRange(rnd, 0, 29),
CurrentLA: currentLA,
MemBytesAvailable: memBytesAvailable,
MemBytesUsed: intInRange(rnd, memBytesAvailable/3, memBytesAvailable/2),
DiskBytesAvailable: diskBytesAvailable,
DiskBytesUsed: intInRange(rnd, diskBytesAvailable/5, diskBytesAvailable/3),
NetBandwidthAvailable: netBandwidthAvailable,
NetBandwidthUsed: intInRange(rnd, netBandwidthAvailable/8, netBandwidthAvailable/4),
},
expectedOutput: nil,
expectedOutput: []string{
fmt.Sprintf("Load Average is too high: %d", currentLA),
},
})
}

{
// сценарий: слишком большое LA
currentLA := intInRange(rnd, 30, 99)
res = append(res, responsePair{
// сценарий: слишком большое потребление памяти
memBytesUsed := intInRange(rnd, int(float32(memBytesAvailable)*0.85), memBytesAvailable)
res = append(res, serverStateScenario{
name: "high_mem",
stats: serverStat{
CurrentLA: currentLA,
CurrentLA: intInRange(rnd, 0, 29),
MemBytesAvailable: memBytesAvailable,
MemBytesUsed: memBytesUsed,
DiskBytesAvailable: diskBytesAvailable,
DiskBytesUsed: intInRange(rnd, diskBytesAvailable/5, diskBytesAvailable/3),
NetBandwidthAvailable: netBandwidthAvailable,
NetBandwidthUsed: intInRange(rnd, netBandwidthAvailable/8, netBandwidthAvailable/4),
},
expectedOutput: []string{
fmt.Sprintf("Memory usage too high: %d%%", int(float32(memBytesUsed)/float32(memBytesAvailable)*100)),
},
})
}

{
// сценарий: слишком большое потребление диска
diskBytesUsed := intInRange(rnd, int(float32(diskBytesAvailable)*0.91), diskBytesAvailable)
res = append(res, serverStateScenario{
name: "low_disk",
stats: serverStat{
CurrentLA: intInRange(rnd, 0, 29),
MemBytesAvailable: memBytesAvailable,
MemBytesUsed: intInRange(rnd, memBytesAvailable/3, memBytesAvailable/2),
DiskBytesAvailable: diskBytesAvailable,
DiskBytesUsed: diskBytesUsed,
NetBandwidthAvailable: netBandwidthAvailable,
NetBandwidthUsed: intInRange(rnd, netBandwidthAvailable/8, netBandwidthAvailable/4),
},
expectedOutput: []string{
fmt.Sprintf("Free disk space is too low: %d Mb left", (diskBytesAvailable-diskBytesUsed)/1024/1024),
},
})
}

{
// сценарий: слишком большое потребление сети
netBandwidthUsed := intInRange(rnd, int(float32(netBandwidthAvailable)*0.91), netBandwidthAvailable)
res = append(res, serverStateScenario{
name: "high_net",
stats: serverStat{
CurrentLA: intInRange(rnd, 0, 29),
MemBytesAvailable: memBytesAvailable,
MemBytesUsed: intInRange(rnd, memBytesAvailable/3, memBytesAvailable/2),
DiskBytesAvailable: diskBytesAvailable,
DiskBytesUsed: intInRange(rnd, diskBytesAvailable/5, diskBytesAvailable/3),
NetBandwidthAvailable: netBandwidthAvailable,
NetBandwidthUsed: netBandwidthUsed,
},
expectedOutput: []string{
fmt.Sprintf("Network bandwidth usage high: %d Mbit/s available", (netBandwidthAvailable-netBandwidthUsed)/1000/1000),
},
})
}

{
// сценарий: уходим в swap
currentLA := intInRange(rnd, 50, 90)
diskBytesUsed := intInRange(rnd, int(float32(diskBytesAvailable)*0.91), diskBytesAvailable)
res = append(res, serverStateScenario{
name: "swap",
stats: serverStat{
CurrentLA: currentLA,
MemBytesAvailable: memBytesAvailable,
MemBytesUsed: memBytesAvailable,
DiskBytesAvailable: diskBytesAvailable,
DiskBytesUsed: diskBytesUsed,
NetBandwidthAvailable: netBandwidthAvailable,
NetBandwidthUsed: intInRange(rnd, netBandwidthAvailable/8, netBandwidthAvailable/4),
},
expectedOutput: []string{
fmt.Sprintf("Load Average is too high: %d", currentLA),
fmt.Sprint("Memory usage too high: 100%"),
fmt.Sprintf("Free disk space is too low: %d Mb left", (diskBytesAvailable-diskBytesUsed)/1024/1024),
},
})
}
Expand Down

0 comments on commit 4bcd447

Please sign in to comment.