mirror of
https://github.com/safing/portbase
synced 2025-09-10 15:34:26 +00:00
Finish modules/tasks revamp
This commit is contained in:
parent
4e99dd2153
commit
71dabc1f23
11 changed files with 542 additions and 296 deletions
|
@ -1,60 +1,97 @@
|
|||
package modules
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
mtTestName = "microtask test"
|
||||
mtModule = initNewModule("microtask test module", nil, nil, nil)
|
||||
)
|
||||
|
||||
func init() {
|
||||
go microTaskScheduler()
|
||||
}
|
||||
|
||||
// test waiting
|
||||
func TestMicroTaskWaiting(t *testing.T) {
|
||||
|
||||
// skip
|
||||
if testing.Short() {
|
||||
t.Skip("skipping test in short mode.")
|
||||
t.Skip("skipping test in short mode, as it is not fully deterministic")
|
||||
}
|
||||
|
||||
// init
|
||||
mtwWaitGroup := new(sync.WaitGroup)
|
||||
mtwOutputChannel := make(chan string, 100)
|
||||
mtwExpectedOutput := "123456"
|
||||
mtwExpectedOutput := "1234567"
|
||||
mtwSleepDuration := 10 * time.Millisecond
|
||||
|
||||
// TEST
|
||||
mtwWaitGroup.Add(3)
|
||||
mtwWaitGroup.Add(4)
|
||||
|
||||
// ensure we only execute one microtask at once
|
||||
atomic.StoreInt32(microTasksThreshhold, 1)
|
||||
|
||||
// High Priority - slot 1-5
|
||||
go func() {
|
||||
defer mtwWaitGroup.Done()
|
||||
StartMicroTask()
|
||||
mtwOutputChannel <- "1"
|
||||
time.Sleep(mtwSleepDuration * 5)
|
||||
mtwOutputChannel <- "2"
|
||||
EndMicroTask()
|
||||
// exec at slot 1
|
||||
_ = mtModule.StartMicroTask(&mtTestName, func(ctx context.Context) error {
|
||||
mtwOutputChannel <- "1" // slot 1
|
||||
time.Sleep(mtwSleepDuration * 5)
|
||||
mtwOutputChannel <- "2" // slot 5
|
||||
return nil
|
||||
})
|
||||
}()
|
||||
|
||||
time.Sleep(mtwSleepDuration * 2)
|
||||
time.Sleep(mtwSleepDuration * 1)
|
||||
|
||||
// clear clearances
|
||||
_ = mtModule.StartMicroTask(&mtTestName, func(ctx context.Context) error {
|
||||
return nil
|
||||
})
|
||||
|
||||
// Low Priority - slot 16
|
||||
go func() {
|
||||
defer mtwWaitGroup.Done()
|
||||
// exec at slot 2
|
||||
_ = mtModule.StartLowPriorityMicroTask(&mtTestName, func(ctx context.Context) error {
|
||||
mtwOutputChannel <- "7" // slot 16
|
||||
return nil
|
||||
})
|
||||
}()
|
||||
|
||||
time.Sleep(mtwSleepDuration * 1)
|
||||
|
||||
// High Priority - slot 10-15
|
||||
go func() {
|
||||
defer mtwWaitGroup.Done()
|
||||
time.Sleep(mtwSleepDuration * 8)
|
||||
StartMicroTask()
|
||||
mtwOutputChannel <- "4"
|
||||
time.Sleep(mtwSleepDuration * 5)
|
||||
mtwOutputChannel <- "6"
|
||||
EndMicroTask()
|
||||
// exec at slot 10
|
||||
_ = mtModule.StartMicroTask(&mtTestName, func(ctx context.Context) error {
|
||||
mtwOutputChannel <- "4" // slot 10
|
||||
time.Sleep(mtwSleepDuration * 5)
|
||||
mtwOutputChannel <- "6" // slot 15
|
||||
return nil
|
||||
})
|
||||
}()
|
||||
|
||||
// Medium Priority - Waits at slot 3, should execute in slot 6-13
|
||||
// Medium Priority - slot 6-13
|
||||
go func() {
|
||||
defer mtwWaitGroup.Done()
|
||||
<-StartMediumPriorityMicroTask()
|
||||
mtwOutputChannel <- "3"
|
||||
time.Sleep(mtwSleepDuration * 7)
|
||||
mtwOutputChannel <- "5"
|
||||
EndMicroTask()
|
||||
// exec at slot 3
|
||||
_ = mtModule.StartMediumPriorityMicroTask(&mtTestName, func(ctx context.Context) error {
|
||||
mtwOutputChannel <- "3" // slot 6
|
||||
time.Sleep(mtwSleepDuration * 7)
|
||||
mtwOutputChannel <- "5" // slot 13
|
||||
return nil
|
||||
})
|
||||
}()
|
||||
|
||||
// wait for test to finish
|
||||
|
@ -67,6 +104,7 @@ func TestMicroTaskWaiting(t *testing.T) {
|
|||
completeOutput += s
|
||||
}
|
||||
// check if test succeeded
|
||||
t.Logf("microTask wait order: %s", completeOutput)
|
||||
if completeOutput != mtwExpectedOutput {
|
||||
t.Errorf("MicroTask waiting test failed, expected sequence %s, got %s", mtwExpectedOutput, completeOutput)
|
||||
}
|
||||
|
@ -78,34 +116,27 @@ func TestMicroTaskWaiting(t *testing.T) {
|
|||
// globals
|
||||
var mtoWaitGroup sync.WaitGroup
|
||||
var mtoOutputChannel chan string
|
||||
var mtoWaitCh chan bool
|
||||
var mtoWaitCh chan struct{}
|
||||
|
||||
// functions
|
||||
func mediumPrioTaskTester() {
|
||||
defer mtoWaitGroup.Done()
|
||||
<-mtoWaitCh
|
||||
<-StartMediumPriorityMicroTask()
|
||||
mtoOutputChannel <- "1"
|
||||
time.Sleep(2 * time.Millisecond)
|
||||
EndMicroTask()
|
||||
_ = mtModule.StartMediumPriorityMicroTask(&mtTestName, func(ctx context.Context) error {
|
||||
mtoOutputChannel <- "1"
|
||||
time.Sleep(2 * time.Millisecond)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func lowPrioTaskTester() {
|
||||
defer mtoWaitGroup.Done()
|
||||
<-mtoWaitCh
|
||||
<-StartLowPriorityMicroTask()
|
||||
mtoOutputChannel <- "2"
|
||||
time.Sleep(2 * time.Millisecond)
|
||||
EndMicroTask()
|
||||
}
|
||||
|
||||
func veryLowPrioTaskTester() {
|
||||
defer mtoWaitGroup.Done()
|
||||
<-mtoWaitCh
|
||||
<-StartVeryLowPriorityMicroTask()
|
||||
mtoOutputChannel <- "3"
|
||||
time.Sleep(2 * time.Millisecond)
|
||||
EndMicroTask()
|
||||
_ = mtModule.StartLowPriorityMicroTask(&mtTestName, func(ctx context.Context) error {
|
||||
mtoOutputChannel <- "2"
|
||||
time.Sleep(2 * time.Millisecond)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// test
|
||||
|
@ -113,53 +144,51 @@ func TestMicroTaskOrdering(t *testing.T) {
|
|||
|
||||
// skip
|
||||
if testing.Short() {
|
||||
t.Skip("skipping test in short mode.")
|
||||
t.Skip("skipping test in short mode, as it is not fully deterministic")
|
||||
}
|
||||
|
||||
// init
|
||||
mtoOutputChannel = make(chan string, 100)
|
||||
mtoWaitCh = make(chan bool, 0)
|
||||
mtoWaitCh = make(chan struct{})
|
||||
|
||||
// TEST
|
||||
mtoWaitGroup.Add(30)
|
||||
mtoWaitGroup.Add(20)
|
||||
|
||||
// ensure we only execute one microtask at once
|
||||
atomic.StoreInt32(microTasksThreshhold, 1)
|
||||
|
||||
// kick off
|
||||
go mediumPrioTaskTester()
|
||||
go mediumPrioTaskTester()
|
||||
go lowPrioTaskTester()
|
||||
go lowPrioTaskTester()
|
||||
go veryLowPrioTaskTester()
|
||||
go veryLowPrioTaskTester()
|
||||
go lowPrioTaskTester()
|
||||
go veryLowPrioTaskTester()
|
||||
go mediumPrioTaskTester()
|
||||
go veryLowPrioTaskTester()
|
||||
go lowPrioTaskTester()
|
||||
go mediumPrioTaskTester()
|
||||
go veryLowPrioTaskTester()
|
||||
go lowPrioTaskTester()
|
||||
go mediumPrioTaskTester()
|
||||
go mediumPrioTaskTester()
|
||||
go mediumPrioTaskTester()
|
||||
go lowPrioTaskTester()
|
||||
go mediumPrioTaskTester()
|
||||
go lowPrioTaskTester()
|
||||
go mediumPrioTaskTester()
|
||||
go veryLowPrioTaskTester()
|
||||
go veryLowPrioTaskTester()
|
||||
go lowPrioTaskTester()
|
||||
go mediumPrioTaskTester()
|
||||
go veryLowPrioTaskTester()
|
||||
go lowPrioTaskTester()
|
||||
go lowPrioTaskTester()
|
||||
go mediumPrioTaskTester()
|
||||
go veryLowPrioTaskTester()
|
||||
go lowPrioTaskTester()
|
||||
go veryLowPrioTaskTester()
|
||||
|
||||
// wait for all goroutines to be ready
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
// sync all goroutines
|
||||
close(mtoWaitCh)
|
||||
// trigger
|
||||
select {
|
||||
case microTaskFinished <- struct{}{}:
|
||||
default:
|
||||
}
|
||||
|
||||
// wait for test to finish
|
||||
mtoWaitGroup.Wait()
|
||||
|
@ -171,7 +200,8 @@ func TestMicroTaskOrdering(t *testing.T) {
|
|||
completeOutput += s
|
||||
}
|
||||
// check if test succeeded
|
||||
if !strings.Contains(completeOutput, "11111") || !strings.Contains(completeOutput, "22222") || !strings.Contains(completeOutput, "33333") {
|
||||
t.Logf("microTask exec order: %s", completeOutput)
|
||||
if !strings.Contains(completeOutput, "11111") || !strings.Contains(completeOutput, "22222") {
|
||||
t.Errorf("MicroTask ordering test failed, output was %s. This happens occasionally, please run the test multiple times to verify", completeOutput)
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue