mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-11-04 07:02:24 -06:00 
			
		
		
		
	
		
			
	
	
		
			107 lines
		
	
	
	
		
			2.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			107 lines
		
	
	
	
		
			2.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								   GoToSocial
							 | 
						||
| 
								 | 
							
								   Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   This program is free software: you can redistribute it and/or modify
							 | 
						||
| 
								 | 
							
								   it under the terms of the GNU Affero General Public License as published by
							 | 
						||
| 
								 | 
							
								   the Free Software Foundation, either version 3 of the License, or
							 | 
						||
| 
								 | 
							
								   (at your option) any later version.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   This program is distributed in the hope that it will be useful,
							 | 
						||
| 
								 | 
							
								   but WITHOUT ANY WARRANTY; without even the implied warranty of
							 | 
						||
| 
								 | 
							
								   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
							 | 
						||
| 
								 | 
							
								   GNU Affero General Public License for more details.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   You should have received a copy of the GNU Affero General Public License
							 | 
						||
| 
								 | 
							
								   along with this program.  If not, see <http://www.gnu.org/licenses/>.
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								package httpclient
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import (
							 | 
						||
| 
								 | 
							
									"net/http"
							 | 
						||
| 
								 | 
							
									"testing"
							 | 
						||
| 
								 | 
							
									"time"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									"github.com/stretchr/testify/suite"
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								type QueueTestSuite struct {
							 | 
						||
| 
								 | 
							
									suite.Suite
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (suite *QueueTestSuite) TestQueue() {
							 | 
						||
| 
								 | 
							
									maxOpenConns := 5
							 | 
						||
| 
								 | 
							
									waitTimeout := 1 * time.Second
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									rc := &requestQueue{
							 | 
						||
| 
								 | 
							
										maxOpenConns: maxOpenConns,
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// fill all the open connections
							 | 
						||
| 
								 | 
							
									var release func()
							 | 
						||
| 
								 | 
							
									for i, n := range make([]interface{}, maxOpenConns) {
							 | 
						||
| 
								 | 
							
										w, r := rc.getWaitSpot("example.org", http.MethodPost)
							 | 
						||
| 
								 | 
							
										w <- n
							 | 
						||
| 
								 | 
							
										if i == maxOpenConns-1 {
							 | 
						||
| 
								 | 
							
											// save the last release function
							 | 
						||
| 
								 | 
							
											release = r
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// try to wait again for the same host/method combo, it should timeout
							 | 
						||
| 
								 | 
							
									waitAgain, _ := rc.getWaitSpot("example.org", "post")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									select {
							 | 
						||
| 
								 | 
							
									case waitAgain <- struct{}{}:
							 | 
						||
| 
								 | 
							
										suite.FailNow("first wait did not time out")
							 | 
						||
| 
								 | 
							
									case <-time.After(waitTimeout):
							 | 
						||
| 
								 | 
							
										break
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// now close the final release that we derived earlier
							 | 
						||
| 
								 | 
							
									release()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// try waiting again, it should work this time
							 | 
						||
| 
								 | 
							
									select {
							 | 
						||
| 
								 | 
							
									case waitAgain <- struct{}{}:
							 | 
						||
| 
								 | 
							
										break
							 | 
						||
| 
								 | 
							
									case <-time.After(waitTimeout):
							 | 
						||
| 
								 | 
							
										suite.FailNow("second wait timed out")
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// the POST queue is now sitting on full
							 | 
						||
| 
								 | 
							
									suite.Len(waitAgain, maxOpenConns)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// we should still be able to make a GET for the same host though
							 | 
						||
| 
								 | 
							
									getWait, getRelease := rc.getWaitSpot("example.org", http.MethodGet)
							 | 
						||
| 
								 | 
							
									select {
							 | 
						||
| 
								 | 
							
									case getWait <- struct{}{}:
							 | 
						||
| 
								 | 
							
										break
							 | 
						||
| 
								 | 
							
									case <-time.After(waitTimeout):
							 | 
						||
| 
								 | 
							
										suite.FailNow("get wait timed out")
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// the GET queue has one request waiting
							 | 
						||
| 
								 | 
							
									suite.Len(getWait, 1)
							 | 
						||
| 
								 | 
							
									// clear it...
							 | 
						||
| 
								 | 
							
									getRelease()
							 | 
						||
| 
								 | 
							
									suite.Empty(getWait)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// even though the POST queue for example.org is full, we
							 | 
						||
| 
								 | 
							
									// should still be able to make a POST request to another host :)
							 | 
						||
| 
								 | 
							
									waitForAnotherHost, _ := rc.getWaitSpot("somewhere.else", http.MethodPost)
							 | 
						||
| 
								 | 
							
									select {
							 | 
						||
| 
								 | 
							
									case waitForAnotherHost <- struct{}{}:
							 | 
						||
| 
								 | 
							
										break
							 | 
						||
| 
								 | 
							
									case <-time.After(waitTimeout):
							 | 
						||
| 
								 | 
							
										suite.FailNow("get wait timed out")
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									suite.Len(waitForAnotherHost, 1)
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func TestQueueTestSuite(t *testing.T) {
							 | 
						||
| 
								 | 
							
									suite.Run(t, &QueueTestSuite{})
							 | 
						||
| 
								 | 
							
								}
							 |