Last active
June 2, 2020 12:17
-
-
Save antonsoroko/db160e36551d61dfdc844f7c614753b2 to your computer and use it in GitHub Desktop.
мой main_test.go для задачи E https://contest.yandex.ru/contest/17728
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"log" | |
"math/rand" | |
"runtime" | |
"sync" | |
"testing" | |
"time" | |
) | |
func init() { | |
log.Println("GOMAXPROCS was", runtime.GOMAXPROCS(0)) | |
runtime.GOMAXPROCS(1) | |
} | |
func TestNil(t *testing.T) { | |
repeats := -999 | |
var in1 chan int | |
var in2 chan int | |
var out chan int | |
log.Println("Run Merge2Channels") | |
Merge2Channels(fRandomSpeed, in1, in2, out, repeats) | |
} | |
func TestMerge2Channels3TimesSameChannelsFillInAfterRun(t *testing.T) { | |
rand.Seed(time.Now().UnixNano()) | |
// repeats := rand.Intn(400) | |
repeats := 999999 | |
log.Printf("Repeats=%d", repeats) | |
in1 := make(chan int, repeats) | |
in2 := make(chan int, repeats) | |
out := make(chan int, repeats) | |
log.Println("Run Merge2Channels 2 times with half of N") | |
Merge2Channels(fRandomSpeed, in1, in2, out, repeats/3) | |
Merge2Channels(fRandomSpeed, in1, in2, out, repeats/3) | |
Merge2Channels(fRandomSpeed, in1, in2, out, repeats/3) | |
results := make([]int, repeats) | |
go func() { | |
for i := 1; i < repeats+1; i++ { | |
i1 := rand.Intn(200) | |
i2 := rand.Intn(200) | |
// to avoid data race in next range | |
results[i-1] = fFast(i1) + fFast(i2) | |
in1 <- i1 | |
in2 <- i2 | |
} | |
log.Println("Sent all inputs, closing channel") | |
close(in1) | |
close(in2) | |
}() | |
log.Println("Reading through out channel") | |
for i := 0; i < repeats; i++ { | |
got, ok := <-out | |
if !ok { | |
t.Fatal("out channel is closed!") | |
} | |
if results[i] != got { | |
t.Errorf("got %d, want %d", got, results[i]) | |
} | |
//log.Println("result =", results[i]) | |
//log.Println("out =", got) | |
} | |
log.Println("Got all results, closing out channel") | |
//close(out) | |
// log.Println("results =", results) | |
} | |
func TestMerge2ChannelsNTimesDefferentChannelsFillInBeforeRun(t *testing.T) { | |
rand.Seed(time.Now().UnixNano()) | |
repeats := 10000 | |
log.Printf("Repeats=%d", repeats) | |
runTimes := 100 | |
//done := make(chan struct{}, runTimes) | |
var wg sync.WaitGroup | |
for r := 0; r < runTimes; r++ { | |
wg.Add(1) | |
rr := r | |
go func() { | |
in1 := make(chan int, repeats*2) | |
in2 := make(chan int, repeats*2) | |
out := make(chan int, repeats*2) | |
results := make([]int, repeats) | |
for i := 1; i < repeats+1; i++ { | |
in1 <- i | |
in2 <- i | |
results[i-1] = fFast(i) * 2 | |
//log.Println("Wrote input", rr, i) | |
} | |
// add extra input | |
for i := repeats + 1; i < repeats*2+1; i++ { | |
in1 <- 1 | |
in2 <- 1 | |
} | |
log.Println("Run Merge2Channels") | |
Merge2Channels(fFast, in1, in2, out, repeats) | |
go func(wg *sync.WaitGroup) { | |
log.Println("Reading through out channel", rr) | |
for i := 0; i < repeats; i++ { | |
v := results[i] | |
r := <-out | |
if v != r { | |
t.Errorf("got %d, want %d", r, v) | |
} | |
} | |
log.Println("Done reading through out channel", rr) | |
wg.Done() | |
//done <- struct{}{} | |
}(&wg) | |
}() | |
} | |
wg.Wait() | |
/*for i := 0; i < runTimes; i++ { | |
<-done | |
}*/ | |
} | |
func fFast(n int) int { | |
return n + n | |
} | |
func fRandomSpeed(n int) int { | |
time.Sleep(time.Duration(rand.Int31n(500)) * time.Millisecond) | |
return fFast(n) | |
} | |
func fSlow(n int) int { | |
time.Sleep(1000 * time.Millisecond) | |
return fFast(n) | |
} | |
func TestNonBlocking(t *testing.T) { | |
capacity := 100 | |
portion := capacity / 10 | |
ch1 := make(chan int, capacity) | |
ch2 := make(chan int, capacity) | |
chOut := make(chan int, capacity) | |
// fill only portion in case if function blocks on channels read | |
for i := 0; i < portion; i++ { | |
ch1 <- i | |
ch2 <- i | |
} | |
done := make(chan struct{}) | |
go func() { | |
Merge2Channels(fSlow, ch1, ch2, chOut, capacity) | |
close(done) | |
}() | |
select { | |
case <-done: | |
close(ch1) | |
close(ch2) | |
//close(chOut) | |
return | |
case <-time.After(time.Millisecond * 100): | |
t.Fatal("Function should be non-blocking") | |
} | |
} | |
//check for reading extra input | |
//check for returning extra output | |
func TestMerge2ChannelsExtraData(t *testing.T) { | |
capacity := 100 | |
portion := capacity / 2 | |
ch1 := make(chan int, capacity) | |
ch2 := make(chan int, capacity) | |
chOut := make(chan int, capacity) | |
results := make([]int, capacity) | |
i := 0 | |
for i < capacity { | |
ch1 <- i + 42 | |
ch2 <- i * 42 | |
results[i] = fFast(i+42) + fFast(i*42) | |
i++ | |
} | |
done := make(chan struct{}) | |
go func() { | |
Merge2Channels(fSlow, ch1, ch2, chOut, portion) | |
close(done) | |
}() | |
<-done | |
i = 0 | |
for i < portion { | |
ans, ok := <-chOut | |
if !ok { | |
t.Fatal("Output channel should not be closed") | |
} | |
if ans != results[i] { | |
t.Fatalf("Got %d from output channel, should be %d", ans, results[i]) | |
} | |
i++ | |
} | |
if len(ch1) != capacity-portion { | |
t.Fatalf("First channel has %d numbers in it, should have %d", len(ch1), capacity-portion) | |
} | |
if len(ch2) != capacity-portion { | |
t.Fatalf("Second channel has %d numbers in it, should have %d", len(ch2), capacity-portion) | |
} | |
if len(chOut) != 0 { | |
t.Fatalf("Output channel has %d numbers in it, should have %d", len(chOut), 0) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment