Add HW 3
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
package hw3test
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"strings"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// LargePutPolicy keeps a small number of guaranteed successful writes above
|
||||
// the solution's memory limit, while bounding the remaining PUT bodies.
|
||||
type LargePutPolicy struct {
|
||||
RunSeed int64
|
||||
LargeSizes []int64
|
||||
OtherMaxBytes int64
|
||||
}
|
||||
|
||||
// QueriesGen contains config for generating queries.
|
||||
type QueriesGen struct {
|
||||
// Number of queries to generate.
|
||||
Count int
|
||||
|
||||
GetFile bool // Allow GET requests for files.
|
||||
GetFileNoErrors bool // Disable requests for non-existing files.
|
||||
GetDirectory bool // Allow GET requests for directories.
|
||||
Compression bool // Allow compression in GET requests.
|
||||
Post bool // Allow POST requests.
|
||||
Put bool // Allow PUT requests.
|
||||
Delete bool // Allow DELETE requests.
|
||||
AllHeaders bool // Allow extra headers.
|
||||
LargePuts *LargePutPolicy
|
||||
}
|
||||
|
||||
func (g *QueriesGen) Generate(t *TC, env *Env, gen *EnvGen, seeds []int64, opts RunOpts, runSeed int64) []Query {
|
||||
env = env.Clone()
|
||||
largePuts := 0
|
||||
|
||||
stats := &Stats{}
|
||||
env.RootDir.Stats("", stats)
|
||||
stats.Normalize()
|
||||
|
||||
var methods []string
|
||||
if g.GetFile || g.GetDirectory {
|
||||
methods = append(methods, "GET")
|
||||
}
|
||||
if g.Post {
|
||||
methods = append(methods, "POST")
|
||||
}
|
||||
if g.Put {
|
||||
methods = append(methods, "PUT")
|
||||
}
|
||||
if g.Delete {
|
||||
methods = append(methods, "DELETE")
|
||||
}
|
||||
|
||||
var queries []Query
|
||||
for _, seed := range seeds {
|
||||
r := rand.New(rand.NewSource(seed))
|
||||
method := methods[r.Intn(len(methods))]
|
||||
|
||||
var genPaths []string
|
||||
if len(stats.DirPaths) > 0 && !(method == "GET" && !g.GetDirectory) {
|
||||
genPaths = append(genPaths, stats.DirPaths[r.Intn(len(stats.DirPaths))])
|
||||
genPaths = append(genPaths, stats.DirPaths[r.Intn(len(stats.DirPaths))])
|
||||
}
|
||||
if len(stats.FilePaths) > 0 && !(method == "GET" && !g.GetFile) {
|
||||
genPaths = append(genPaths, stats.FilePaths[r.Intn(len(stats.FilePaths))])
|
||||
genPaths = append(genPaths, stats.FilePaths[r.Intn(len(stats.FilePaths))])
|
||||
}
|
||||
if !(method == "GET" && g.GetFileNoErrors) {
|
||||
// TODO: better non-existing path generator
|
||||
randomPath := gen.FilenameGen(r) + "/" + gen.FilenameGen(r)
|
||||
genPaths = append(genPaths, randomPath)
|
||||
|
||||
if len(stats.DirPaths) > 0 {
|
||||
randomDir := stats.DirPaths[r.Intn(len(stats.DirPaths))]
|
||||
num := 2
|
||||
if method == "POST" {
|
||||
num = 4
|
||||
}
|
||||
|
||||
for i := 0; i < num; i++ {
|
||||
genPaths = append(genPaths, randomDir+"/"+gen.FilenameGen(r))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(genPaths) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
hostHeader := opts.ServerDomain
|
||||
if g.AllHeaders && r.Intn(5) == 0 {
|
||||
// to get 400
|
||||
hostHeader = "hse.ru"
|
||||
}
|
||||
|
||||
path := strings.TrimPrefix(genPaths[r.Intn(len(genPaths))], "/")
|
||||
if path == "" && method != "GET" {
|
||||
// Keep the existing large-file scenarios and RNG sequence.
|
||||
// Requests targeting the root are covered on a small tree in contract.go.
|
||||
path = "MISSING_ROOT_TARGET"
|
||||
}
|
||||
gzipRequested := g.Compression && r.Intn(2) == 1
|
||||
query := Query{
|
||||
Seed: seed,
|
||||
Method: method,
|
||||
Path: path,
|
||||
Gzip: method == "GET" && gzipRequested,
|
||||
CreateDirectory: method == "POST" && (r.Intn(2) == 1),
|
||||
RemoveDirectory: method == "DELETE" && (r.Intn(2) == 1),
|
||||
HostHeader: hostHeader,
|
||||
VerifyHeaders: g.AllHeaders,
|
||||
}
|
||||
|
||||
if (method == "POST" && !query.CreateDirectory) || method == "PUT" {
|
||||
query.FileContent = gen.GenerateFile(r)
|
||||
}
|
||||
|
||||
action := query.Action(env, &opts)
|
||||
if query.Method == "PUT" && g.LargePuts != nil {
|
||||
policy := g.LargePuts
|
||||
if _, ok := action.(ReplaceFileAction); ok && runSeed == policy.RunSeed && largePuts < len(policy.LargeSizes) {
|
||||
query.FileContent.Size = policy.LargeSizes[largePuts]
|
||||
largePuts++
|
||||
} else if query.FileContent.Size > policy.OtherMaxBytes {
|
||||
query.FileContent.Size = policy.OtherMaxBytes
|
||||
}
|
||||
}
|
||||
queries = append(queries, query)
|
||||
|
||||
if action != nil {
|
||||
changed := action.ApplyEnv(t, env)
|
||||
if changed {
|
||||
stats = &Stats{}
|
||||
env.RootDir.Stats("", stats)
|
||||
stats.Normalize()
|
||||
}
|
||||
}
|
||||
}
|
||||
if g.LargePuts != nil && runSeed == g.LargePuts.RunSeed {
|
||||
require.Equal(t, len(g.LargePuts.LargeSizes), largePuts, "not enough successful PUT queries for large-file coverage")
|
||||
}
|
||||
|
||||
return queries
|
||||
}
|
||||
Reference in New Issue
Block a user