mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 10:56:10 +01:00 
			
		
		
		
	Fix intermittent CI failure in EmptyQueue (#23753)
The ordering of the final token causing a close of the queue in this test may be out of sync due to concurrency. Instead just use ensure that the queue is closed when everything expected is done. Fixes: https://github.com/go-gitea/gitea/issues/23608 Fixes: https://github.com/go-gitea/gitea/issues/23977 --------- Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: KN4CK3R <admin@oldschoolhack.me>
This commit is contained in:
		| @@ -4,9 +4,9 @@ | |||||||
| package queue | package queue | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"os" |  | ||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"sync" | 	"sync" | ||||||
|  | 	"sync/atomic" | ||||||
| 	"testing" | 	"testing" | ||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
| @@ -16,10 +16,7 @@ import ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| func TestPersistableChannelUniqueQueue(t *testing.T) { | func TestPersistableChannelUniqueQueue(t *testing.T) { | ||||||
| 	if os.Getenv("CI") != "" { | 	// Create a temporary directory for the queue | ||||||
| 		t.Skip("Skipping because test is flaky on CI") |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	tmpDir := t.TempDir() | 	tmpDir := t.TempDir() | ||||||
| 	_ = log.NewLogger(1000, "console", "console", `{"level":"warn","stacktracelevel":"NONE","stderr":true}`) | 	_ = log.NewLogger(1000, "console", "console", `{"level":"warn","stacktracelevel":"NONE","stderr":true}`) | ||||||
|  |  | ||||||
| @@ -100,7 +97,7 @@ func TestPersistableChannelUniqueQueue(t *testing.T) { | |||||||
| 	executedInitial := map[string][]string{} | 	executedInitial := map[string][]string{} | ||||||
| 	hasInitial := map[string][]string{} | 	hasInitial := map[string][]string{} | ||||||
|  |  | ||||||
| 	fillQueue := func(name string, done chan struct{}) { | 	fillQueue := func(name string, done chan int64) { | ||||||
| 		t.Run("Initial Filling: "+name, func(t *testing.T) { | 		t.Run("Initial Filling: "+name, func(t *testing.T) { | ||||||
| 			lock := sync.Mutex{} | 			lock := sync.Mutex{} | ||||||
|  |  | ||||||
| @@ -157,33 +154,39 @@ func TestPersistableChannelUniqueQueue(t *testing.T) { | |||||||
| 			assert.Equal(t, 101, len(executedInitial[name])+len(hasInitial[name])) | 			assert.Equal(t, 101, len(executedInitial[name])+len(hasInitial[name])) | ||||||
| 			mapLock.Unlock() | 			mapLock.Unlock() | ||||||
| 		}) | 		}) | ||||||
|  | 		mapLock.Lock() | ||||||
|  | 		count := int64(len(hasInitial[name])) | ||||||
|  | 		mapLock.Unlock() | ||||||
|  | 		done <- count | ||||||
| 		close(done) | 		close(done) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	doneA := make(chan struct{}) | 	hasQueueAChan := make(chan int64) | ||||||
| 	doneB := make(chan struct{}) | 	hasQueueBChan := make(chan int64) | ||||||
|  |  | ||||||
| 	go fillQueue("QueueA", doneA) | 	go fillQueue("QueueA", hasQueueAChan) | ||||||
| 	go fillQueue("QueueB", doneB) | 	go fillQueue("QueueB", hasQueueBChan) | ||||||
|  |  | ||||||
| 	<-doneA | 	hasA := <-hasQueueAChan | ||||||
| 	<-doneB | 	hasB := <-hasQueueBChan | ||||||
|  |  | ||||||
| 	executedEmpty := map[string][]string{} | 	executedEmpty := map[string][]string{} | ||||||
| 	hasEmpty := map[string][]string{} | 	hasEmpty := map[string][]string{} | ||||||
| 	emptyQueue := func(name string, done chan struct{}) { | 	emptyQueue := func(name string, numInQueue int64, done chan struct{}) { | ||||||
| 		t.Run("Empty Queue: "+name, func(t *testing.T) { | 		t.Run("Empty Queue: "+name, func(t *testing.T) { | ||||||
| 			lock := sync.Mutex{} | 			lock := sync.Mutex{} | ||||||
| 			stop := make(chan struct{}) | 			stop := make(chan struct{}) | ||||||
|  |  | ||||||
| 			// collect the tasks that have been executed | 			// collect the tasks that have been executed | ||||||
|  | 			atomicCount := int64(0) | ||||||
| 			handle := func(data ...Data) []Data { | 			handle := func(data ...Data) []Data { | ||||||
| 				lock.Lock() | 				lock.Lock() | ||||||
| 				for _, datum := range data { | 				for _, datum := range data { | ||||||
| 					mapLock.Lock() | 					mapLock.Lock() | ||||||
| 					executedEmpty[name] = append(executedEmpty[name], datum.(string)) | 					executedEmpty[name] = append(executedEmpty[name], datum.(string)) | ||||||
| 					mapLock.Unlock() | 					mapLock.Unlock() | ||||||
| 					if datum.(string) == "final" { | 					count := atomic.AddInt64(&atomicCount, 1) | ||||||
|  | 					if count >= numInQueue { | ||||||
| 						close(stop) | 						close(stop) | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| @@ -217,11 +220,11 @@ func TestPersistableChannelUniqueQueue(t *testing.T) { | |||||||
| 		close(done) | 		close(done) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	doneA = make(chan struct{}) | 	doneA := make(chan struct{}) | ||||||
| 	doneB = make(chan struct{}) | 	doneB := make(chan struct{}) | ||||||
|  |  | ||||||
| 	go emptyQueue("QueueA", doneA) | 	go emptyQueue("QueueA", hasA, doneA) | ||||||
| 	go emptyQueue("QueueB", doneB) | 	go emptyQueue("QueueB", hasB, doneB) | ||||||
|  |  | ||||||
| 	<-doneA | 	<-doneA | ||||||
| 	<-doneB | 	<-doneB | ||||||
| @@ -237,20 +240,20 @@ func TestPersistableChannelUniqueQueue(t *testing.T) { | |||||||
| 	hasEmpty = map[string][]string{} | 	hasEmpty = map[string][]string{} | ||||||
| 	mapLock.Unlock() | 	mapLock.Unlock() | ||||||
|  |  | ||||||
| 	doneA = make(chan struct{}) | 	hasQueueAChan = make(chan int64) | ||||||
| 	doneB = make(chan struct{}) | 	hasQueueBChan = make(chan int64) | ||||||
|  |  | ||||||
| 	go fillQueue("QueueA", doneA) | 	go fillQueue("QueueA", hasQueueAChan) | ||||||
| 	go fillQueue("QueueB", doneB) | 	go fillQueue("QueueB", hasQueueBChan) | ||||||
|  |  | ||||||
| 	<-doneA | 	hasA = <-hasQueueAChan | ||||||
| 	<-doneB | 	hasB = <-hasQueueBChan | ||||||
|  |  | ||||||
| 	doneA = make(chan struct{}) | 	doneA = make(chan struct{}) | ||||||
| 	doneB = make(chan struct{}) | 	doneB = make(chan struct{}) | ||||||
|  |  | ||||||
| 	go emptyQueue("QueueA", doneA) | 	go emptyQueue("QueueA", hasA, doneA) | ||||||
| 	go emptyQueue("QueueB", doneB) | 	go emptyQueue("QueueB", hasB, doneB) | ||||||
|  |  | ||||||
| 	<-doneA | 	<-doneA | ||||||
| 	<-doneB | 	<-doneB | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user