gpt4 book ai didi

并发模式帮助 - 扇入并返回结果?

转载 作者:数据小太阳 更新时间:2023-10-29 03:37:41 26 4
gpt4 key购买 nike

我正在编写一个快速并发集成测试包。我已经编写了 POC,现在我正在尝试为它想出一个新模式。我希望遵守以下规则:

  • 一个测试套件可能有很多测试
  • 一个测试套件必须有 n 个 worker 来运行 TestPreppers
  • 一个测试套件必须有 n 个 worker 来运行 TestValidators
  • 测试必须通过准备才能运行验证
  • 一个测试可能有很多 child
  • 在运行子测试之前,测试必须通过验证

结构如下:

package conctest

func New() *TestSuite {
return &TestSuite{nil, 1, 1, make(chan TestPrepper), make(chan TestValidator)}
}

type TestSuite struct {
Tests []*Test
ConcurrentPreppers int
ConcurrentValidators int

prepperChan chan TestPrepper
validatorChan chan TestValidator
}

type TestPrepper func() error
type TestValidator func() ValidatorResult

type ValidatorResult struct {
Pass bool
Error error
}

type Test struct {
Convey string
Details string
Prepper TestPrepper
Validator TestValidator
MaxRuns int
Children []*Test

runs int
errors []error
}

我无法提出满足要求的并发设计。我需要从 TestSuite 公开一个可供测试使用的方法,该方法将允许它将其工作发送给 TestSuites 工作人员并将结果返回给测试。

最佳答案

这是我想出的解决方案。我欢迎任何批评或更好的方法,并将接受该答案。我创建了一个私有(private)传输结构,其中包含我的函数和一个返回结果的 channel :

package conctest

import (
"sync"
"time"
)

func New() *ConcTest {
return &ConcTest{nil, 1, 1, make(chan *prepperTransport), make(chan *validatorTransport), nil}
}

type ConcTest struct {
Tests []*Test
ConcurrentPreppers int
ConcurrentValidators int

prepperChan chan *prepperTransport
validatorChan chan *validatorTransport

testSync *sync.WaitGroup
}

func (ct *ConcTest) Run() {
// start up prepper workers
for i := 0; i < ct.ConcurrentPreppers; i++ {
go func() {
for p := range ct.prepperChan {
time.Sleep(time.Second)
p.Result <- p.Prepper()
}
}()
}

// start up validator workers
for i := 0; i < ct.ConcurrentValidators; i++ {
go func() {
for v := range ct.validatorChan {
time.Sleep(time.Second)
v.Result <- v.Validator()
}
}()
}

// start parent tests, child tests will be called recursively
ct.testSync = &sync.WaitGroup{}
for _, t := range ct.Tests {
ct.testSync.Add(1)
go ct.runTest(t)
}

// wait for all tests to complete
ct.testSync.Wait()
}

func (ct *ConcTest) runTest(t *Test) {
// test is a pass until failure encountered
t.Pass = true

// run and wait for prep to finish
pt := &prepperTransport{t.Prepper, make(chan PrepperResult)}
ct.prepperChan <- pt
pr := <-pt.Result

// return on prep failure
if pr != nil {
t.Pass = false
t.Errors = append(t.Errors, pr)
ct.testSync.Done()
return
}

// run the validator until pass or max runs reached
for {
// sleep for given frequency
time.Sleep(t.Frequency)

// send the validator to the queue
t.Runs++
vt := &validatorTransport{t.Validator, make(chan ValidatorResult)}
ct.validatorChan <- vt

// wait for validator response
vr := <-vt.Result

// append error to the test
if vr.Error != nil {
t.Errors = append(t.Errors, vr.Error)
}

// break on pass
if vr.Pass {
break
}

// break on max attempts
if t.MaxRuns == t.Runs {
t.Pass = false
break
}
}

// break on validator failure
if !t.Pass {
ct.testSync.Done()
return
}

// run all children tests
for _, c := range t.Children {
ct.testSync.Add(1)
go ct.runTest(c)
}

ct.testSync.Done()
return
}

type Prepper func() PrepperResult
type PrepperResult error
type prepperTransport struct {
Prepper Prepper
Result chan PrepperResult
}

type Validator func() ValidatorResult
type ValidatorResult struct {
Pass bool
Error error
}
type validatorTransport struct {
Validator Validator
Result chan ValidatorResult
}

type Test struct {
Convey string
Details string
Frequency time.Duration
MaxRuns int

Prepper Prepper
Validator Validator
Children []*Test

Runs int
Errors []error
Pass bool
}

关于并发模式帮助 - 扇入并返回结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29101909/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com