@@ -25,6 +25,7 @@ import (
2525	"io" 
2626	"net/http" 
2727	"net/http/httptest" 
28+ 	"strings" 
2829	"testing" 
2930	"time" 
3031
@@ -59,6 +60,9 @@ const (
5960	tcLatencyFaultExistsCommandOutput  =  `[{"kind":"netem","handle":"10:","parent":"1:1","options":{"limit":1000,"delay":{"delay":123456789,"jitter":4567,"correlation":0},"ecn":false,"gap":0}}]` 
6061	tcLossFaultExistsCommandOutput     =  `[{"kind":"netem","handle":"10:","dev":"eth0","parent":"1:1","options":{"limit":1000,"loss-random":{"loss":0.06,"correlation":0},"ecn":false,"gap":0}}]` 
6162	tcCommandEmptyOutput               =  `[]` 
63+ 	startEndpoint                      =  "/api/%s/fault/v1/%s/start" 
64+ 	stopEndpoint                       =  "/api/%s/fault/v1/%s/stop" 
65+ 	path                               =  "/some/path" 
6266)
6367
6468var  (
7680
7781	happyNetworkNamespaces  =  []* state.NetworkNamespace {
7882		{
79- 			Path :              "/some/ path" 
83+ 			Path :              path ,
8084			NetworkInterfaces : happyNetworkInterfaces ,
8185		},
8286	}
@@ -2027,9 +2031,13 @@ func generateStopNetworkPacketLossTestCases() []networkFaultInjectionTestCase {
20272031			setExecExpectations : func (exec  * mock_execwrapper.MockExec , ctrl  * gomock.Controller ) {
20282032				ctx , cancel  :=  context .WithTimeout (context .Background (), ctxTimeoutDuration )
20292033				mockCMD  :=  mock_execwrapper .NewMockCmd (ctrl )
2030- 				exec .EXPECT ().NewExecContextWithTimeout (gomock .Any (), gomock .Any ()).Times (1 ).Return (ctx , cancel )
2031- 				exec .EXPECT ().CommandContext (gomock .Any (), gomock .Any (), gomock .Any ()).Times (1 ).Return (mockCMD )
2032- 				mockCMD .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte (tcLatencyFaultExistsCommandOutput ), nil )
2034+ 				gomock .InOrder (
2035+ 					exec .EXPECT ().NewExecContextWithTimeout (gomock .Any (), gomock .Any ()).Times (1 ).Return (ctx , cancel ),
2036+ 					exec .EXPECT ().CommandContext (gomock .Any (), gomock .Any (), gomock .Any ()).Times (1 ).Return (mockCMD ),
2037+ 					mockCMD .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte (tcLossFaultExistsCommandOutput ), nil ),
2038+ 				)
2039+ 				exec .EXPECT ().CommandContext (gomock .Any (), gomock .Any (), gomock .Any ()).Times (2 ).Return (mockCMD )
2040+ 				mockCMD .EXPECT ().CombinedOutput ().Times (2 ).Return ([]byte ("" ), nil )
20332041			},
20342042		},
20352043		{
@@ -2175,3 +2183,297 @@ func TestCheckNetworkPacketLoss(t *testing.T) {
21752183	tcs  :=  generateCheckNetworkPacketLossTestCases ()
21762184	testNetworkFaultInjectionCommon (t , tcs , NetworkFaultPath (types .PacketLossFaultType , types .CheckNetworkFaultPostfix ))
21772185}
2186+ 
2187+ func  TestNetworkFaultRequestOrdering (t  * testing.T ) {
2188+ 	tcs  :=  []struct  {
2189+ 		name                       string 
2190+ 		faultType                  string 
2191+ 		requestBody                interface {}
2192+ 		setAgentStateExpectations  func (agentState  * mock_state.MockAgentState , netConfigClient  * netconfig.NetworkConfigClient )
2193+ 		setExecExpectations        func (exec  * mock_execwrapper.MockExec , ctrl  * gomock.Controller , firstStartExecCmd , firstStopExecCmd  []interface {})
2194+ 	}{
2195+ 		{
2196+ 			name :        types .BlackHolePortFaultType  +  "request ordering" ,
2197+ 			faultType :   types .BlackHolePortFaultType ,
2198+ 			requestBody : happyBlackHolePortReqBody ,
2199+ 			setAgentStateExpectations : func (agentState  * mock_state.MockAgentState , netConfigClient  * netconfig.NetworkConfigClient ) {
2200+ 				agentState .EXPECT ().GetTaskMetadataWithTaskNetworkConfig (endpointId , netConfigClient ).
2201+ 					Return (happyTaskResponse , nil ).
2202+ 					Times (2 )
2203+ 			},
2204+ 			setExecExpectations : func (exec  * mock_execwrapper.MockExec , ctrl  * gomock.Controller , firstStartExecCmd , firstStopExecCmd  []interface {}) {
2205+ 				startCtx , startCancel  :=  context .WithTimeout (context .Background (), ctxTimeoutDuration )
2206+ 				stopCtx , stopCancel  :=  context .WithTimeout (context .Background (), ctxTimeoutDuration )
2207+ 				cmdExec  :=  mock_execwrapper .NewMockCmd (ctrl )
2208+ 				// We want to ensure that the start fault request executes and finishes first before the stop fault request. 
2209+ 				// We can enforce the ordering of exec mock calls. 
2210+ 				gomock .InOrder (
2211+ 					// Exec mocks for start black hole port request 
2212+ 					exec .EXPECT ().NewExecContextWithTimeout (gomock .Any (), gomock .Any ()).Do (func (_ , _  interface {}) {
2213+ 						// Sleep for 2 seconds to mock that the request is taking some time 
2214+ 						time .Sleep (2  *  time .Second )
2215+ 					}).Times (1 ).Return (startCtx , startCancel ),
2216+ 					exec .EXPECT ().CommandContext (gomock .Any (), gomock .Any (), gomock .Any ()).Times (1 ).Return (cmdExec ),
2217+ 					cmdExec .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte (iptablesChainNotFoundError ), errors .New ("exit status 1" )),
2218+ 					exec .EXPECT ().ConvertToExitError (gomock .Any ()).Times (1 ).Return (nil , true ),
2219+ 					exec .EXPECT ().GetExitCode (gomock .Any ()).Times (1 ).Return (1 ),
2220+ 					// Ensuring that the start request is running here by also passing in the expected parameters for the first CommandContext call 
2221+ 					exec .EXPECT ().CommandContext (gomock .Any (), firstStartExecCmd [0 ], firstStartExecCmd [1 :]... ).Times (1 ).Return (cmdExec ),
2222+ 					cmdExec .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte {}, nil ),
2223+ 					exec .EXPECT ().CommandContext (gomock .Any (), gomock .Any (), gomock .Any ()).Times (1 ).Return (cmdExec ),
2224+ 					cmdExec .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte {}, nil ),
2225+ 					exec .EXPECT ().CommandContext (gomock .Any (), gomock .Any (), gomock .Any ()).Times (1 ).Return (cmdExec ),
2226+ 					cmdExec .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte {}, nil ),
2227+ 
2228+ 					// Exec mocks for stop black hole port request 
2229+ 					exec .EXPECT ().NewExecContextWithTimeout (gomock .Any (), gomock .Any ()).Times (1 ).Return (stopCtx , stopCancel ),
2230+ 					exec .EXPECT ().CommandContext (gomock .Any (), gomock .Any (), gomock .Any ()).Times (1 ).Return (cmdExec ),
2231+ 					cmdExec .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte {}, nil ),
2232+ 					// Ensuring that the stop request is running here by also passing in the expected parameters for the first CommandContext call 
2233+ 					exec .EXPECT ().CommandContext (gomock .Any (), firstStopExecCmd [0 ], firstStopExecCmd [1 :]... ).Times (1 ).Return (cmdExec ),
2234+ 					cmdExec .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte {}, nil ),
2235+ 					exec .EXPECT ().CommandContext (gomock .Any (), gomock .Any (), gomock .Any ()).Times (1 ).Return (cmdExec ),
2236+ 					cmdExec .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte {}, nil ),
2237+ 					exec .EXPECT ().CommandContext (gomock .Any (), gomock .Any (), gomock .Any ()).Times (1 ).Return (cmdExec ),
2238+ 					cmdExec .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte {}, nil ),
2239+ 				)
2240+ 			},
2241+ 		},
2242+ 		{
2243+ 			name :        types .LatencyFaultType  +  "request ordering" ,
2244+ 			faultType :   types .LatencyFaultType ,
2245+ 			requestBody : happyNetworkLatencyReqBody ,
2246+ 			setAgentStateExpectations : func (agentState  * mock_state.MockAgentState , netConfigClient  * netconfig.NetworkConfigClient ) {
2247+ 				agentState .EXPECT ().GetTaskMetadataWithTaskNetworkConfig (endpointId , netConfigClient ).
2248+ 					Return (happyTaskResponse , nil ).
2249+ 					Times (2 )
2250+ 			},
2251+ 			setExecExpectations : func (exec  * mock_execwrapper.MockExec , ctrl  * gomock.Controller , firstStartExecCmd , firstStopExecCmd  []interface {}) {
2252+ 				startCtx , startCancel  :=  context .WithTimeout (context .Background (), ctxTimeoutDuration )
2253+ 				stopCtx , stopCancel  :=  context .WithTimeout (context .Background (), ctxTimeoutDuration )
2254+ 				cmdExec  :=  mock_execwrapper .NewMockCmd (ctrl )
2255+ 				// We want to ensure that the start fault request executes and finishes first before the stop fault request. 
2256+ 				// We can enforce the ordering of exec mock calls. 
2257+ 				gomock .InOrder (
2258+ 					// Exec mocks for start latency request 
2259+ 					exec .EXPECT ().NewExecContextWithTimeout (gomock .Any (), gomock .Any ()).Do (func (_ , _  interface {}) {
2260+ 						// Sleep for 2 seconds to mock that the request is taking some time 
2261+ 						time .Sleep (2  *  time .Second )
2262+ 					}).Times (1 ).Return (startCtx , startCancel ),
2263+ 					exec .EXPECT ().CommandContext (gomock .Any (), gomock .Any (), gomock .Any ()).Times (1 ).Return (cmdExec ),
2264+ 					cmdExec .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte (tcCommandEmptyOutput ), nil ),
2265+ 					// Ensuring that the start request is running here by also passing in the expected parameters for the first CommandContext call 
2266+ 					exec .EXPECT ().CommandContext (gomock .Any (), firstStartExecCmd [0 ], firstStartExecCmd [1 :]... ).Times (1 ).Return (cmdExec ),
2267+ 					cmdExec .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte (tcCommandEmptyOutput ), nil ),
2268+ 					exec .EXPECT ().CommandContext (gomock .Any (), gomock .Any (), gomock .Any ()).Times (1 ).Return (cmdExec ),
2269+ 					cmdExec .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte (tcCommandEmptyOutput ), nil ),
2270+ 					exec .EXPECT ().CommandContext (gomock .Any (), gomock .Any (), gomock .Any ()).Times (1 ).Return (cmdExec ),
2271+ 					cmdExec .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte (tcCommandEmptyOutput ), nil ),
2272+ 					exec .EXPECT ().CommandContext (gomock .Any (), gomock .Any (), gomock .Any ()).Times (1 ).Return (cmdExec ),
2273+ 					cmdExec .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte (tcCommandEmptyOutput ), nil ),
2274+ 					exec .EXPECT ().CommandContext (gomock .Any (), gomock .Any (), gomock .Any ()).Times (1 ).Return (cmdExec ),
2275+ 					cmdExec .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte (tcCommandEmptyOutput ), nil ),
2276+ 
2277+ 					// Exec mocks for stop latency request 
2278+ 					exec .EXPECT ().NewExecContextWithTimeout (gomock .Any (), gomock .Any ()).Times (1 ).Return (stopCtx , stopCancel ),
2279+ 					exec .EXPECT ().CommandContext (gomock .Any (), gomock .Any (), gomock .Any ()).Times (1 ).Return (cmdExec ),
2280+ 					cmdExec .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte (tcLatencyFaultExistsCommandOutput ), nil ),
2281+ 					// Ensuring that the stop request is running here by also passing in the expected parameters for the first CommandContext call 
2282+ 					exec .EXPECT ().CommandContext (gomock .Any (), firstStopExecCmd [0 ], firstStopExecCmd [1 :]... ).Times (1 ).Return (cmdExec ),
2283+ 					cmdExec .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte ("" ), nil ),
2284+ 					exec .EXPECT ().CommandContext (gomock .Any (), gomock .Any (), gomock .Any ()).Times (1 ).Return (cmdExec ),
2285+ 					cmdExec .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte ("" ), nil ),
2286+ 				)
2287+ 			},
2288+ 		},
2289+ 		{
2290+ 			name :        types .PacketLossFaultType  +  "request ordering" ,
2291+ 			faultType :   types .PacketLossFaultType ,
2292+ 			requestBody : happyNetworkPacketLossReqBody ,
2293+ 			setAgentStateExpectations : func (agentState  * mock_state.MockAgentState , netConfigClient  * netconfig.NetworkConfigClient ) {
2294+ 				agentState .EXPECT ().GetTaskMetadataWithTaskNetworkConfig (endpointId , netConfigClient ).
2295+ 					Return (happyTaskResponse , nil ).
2296+ 					Times (2 )
2297+ 			},
2298+ 			setExecExpectations : func (exec  * mock_execwrapper.MockExec , ctrl  * gomock.Controller , firstStartExecCmd , firstStopExecCmd  []interface {}) {
2299+ 				startCtx , startCancel  :=  context .WithTimeout (context .Background (), ctxTimeoutDuration )
2300+ 				stopCtx , stopCancel  :=  context .WithTimeout (context .Background (), ctxTimeoutDuration )
2301+ 				cmdExec  :=  mock_execwrapper .NewMockCmd (ctrl )
2302+ 				// We want to ensure that the start fault request executes and finishes first before the stop fault request. 
2303+ 				// We can enforce the ordering of exec mock calls. 
2304+ 				gomock .InOrder (
2305+ 					// Exec mocks for start packet loss request 
2306+ 					exec .EXPECT ().NewExecContextWithTimeout (gomock .Any (), gomock .Any ()).Do (func (_ , _  interface {}) {
2307+ 						// Sleep for 2 seconds to mock that the request is taking some time 
2308+ 						time .Sleep (2  *  time .Second )
2309+ 					}).Times (1 ).Return (startCtx , startCancel ),
2310+ 					exec .EXPECT ().CommandContext (gomock .Any (), gomock .Any (), gomock .Any ()).Times (1 ).Return (cmdExec ),
2311+ 					cmdExec .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte (tcCommandEmptyOutput ), nil ),
2312+ 					// Ensuring that the start request is running here by also passing in the expected parameters for the first CommandContext call 
2313+ 					exec .EXPECT ().CommandContext (gomock .Any (), firstStartExecCmd [0 ], firstStartExecCmd [1 :]... ).Times (1 ).Return (cmdExec ),
2314+ 					cmdExec .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte (tcCommandEmptyOutput ), nil ),
2315+ 					exec .EXPECT ().CommandContext (gomock .Any (), gomock .Any (), gomock .Any ()).Times (1 ).Return (cmdExec ),
2316+ 					cmdExec .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte (tcCommandEmptyOutput ), nil ),
2317+ 					exec .EXPECT ().CommandContext (gomock .Any (), gomock .Any (), gomock .Any ()).Times (1 ).Return (cmdExec ),
2318+ 					cmdExec .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte (tcCommandEmptyOutput ), nil ),
2319+ 					exec .EXPECT ().CommandContext (gomock .Any (), gomock .Any (), gomock .Any ()).Times (1 ).Return (cmdExec ),
2320+ 					cmdExec .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte (tcCommandEmptyOutput ), nil ),
2321+ 					exec .EXPECT ().CommandContext (gomock .Any (), gomock .Any (), gomock .Any ()).Times (1 ).Return (cmdExec ),
2322+ 					cmdExec .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte (tcCommandEmptyOutput ), nil ),
2323+ 
2324+ 					// Exec mocks for stop packet loss request 
2325+ 					exec .EXPECT ().NewExecContextWithTimeout (gomock .Any (), gomock .Any ()).Times (1 ).Return (stopCtx , stopCancel ),
2326+ 					exec .EXPECT ().CommandContext (gomock .Any (), gomock .Any (), gomock .Any ()).Times (1 ).Return (cmdExec ),
2327+ 					cmdExec .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte (tcLossFaultExistsCommandOutput ), nil ),
2328+ 					// Ensuring that the stop request is running here by also passing in the expected parameters for the first CommandContext call 
2329+ 					exec .EXPECT ().CommandContext (gomock .Any (), firstStopExecCmd [0 ], firstStopExecCmd [1 :]... ).Times (1 ).Return (cmdExec ),
2330+ 					cmdExec .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte ("" ), nil ),
2331+ 					exec .EXPECT ().CommandContext (gomock .Any (), gomock .Any (), gomock .Any ()).Times (1 ).Return (cmdExec ),
2332+ 					cmdExec .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte ("" ), nil ),
2333+ 				)
2334+ 			},
2335+ 		},
2336+ 	}
2337+ 
2338+ 	for  _ , tc  :=  range  tcs  {
2339+ 		t .Run (tc .name , func (t  * testing.T ) {
2340+ 			// Mocks 
2341+ 			ctrl  :=  gomock .NewController (t )
2342+ 			defer  ctrl .Finish ()
2343+ 
2344+ 			agentState  :=  mock_state .NewMockAgentState (ctrl )
2345+ 			metricsFactory  :=  mock_metrics .NewMockEntryFactory (ctrl )
2346+ 
2347+ 			router  :=  mux .NewRouter ()
2348+ 			mockExec  :=  mock_execwrapper .NewMockExec (ctrl )
2349+ 			handler  :=  New (agentState , metricsFactory , mockExec )
2350+ 			networkConfigClient  :=  netconfig .NewNetworkConfigClient ()
2351+ 
2352+ 			var  startHandleMethod , stopHandleMethod  func (http.ResponseWriter , * http.Request )
2353+ 			var  firstStartExecCmd , firstStopExecCmd  []string 
2354+ 			nsenterPrefix  :=  fmt .Sprintf (nsenterCommandString , path )
2355+ 			switch  tc .faultType  {
2356+ 			case  types .BlackHolePortFaultType :
2357+ 				chain  :=  fmt .Sprintf ("%s-%s-%d" , trafficType , protocol , port )
2358+ 
2359+ 				newChainCmdString  :=  nsenterPrefix  +  fmt .Sprintf (iptablesNewChainCmd , requestTimeoutSeconds , chain )
2360+ 				firstStartExecCmd  =  strings .Split (newChainCmdString , " " )
2361+ 
2362+ 				clearChainCmdString  :=  nsenterPrefix  +  fmt .Sprintf (iptablesClearChainCmd , requestTimeoutSeconds , chain )
2363+ 				firstStopExecCmd  =  strings .Split (clearChainCmdString , " " )
2364+ 
2365+ 				startHandleMethod  =  handler .StartNetworkBlackholePort ()
2366+ 				stopHandleMethod  =  handler .StopNetworkBlackHolePort ()
2367+ 			case  types .LatencyFaultType :
2368+ 				tcAddQdiscRootCommandComposed  :=  nsenterPrefix  +  fmt .Sprintf (tcAddQdiscRootCommandString , deviceName )
2369+ 				firstStartExecCmd  =  strings .Split (tcAddQdiscRootCommandComposed , " " )
2370+ 
2371+ 				tcDeleteQdiscParentCommandComposed  :=  nsenterPrefix  +  fmt .Sprintf (tcDeleteQdiscParentCommandString , deviceName )
2372+ 				firstStopExecCmd  =  strings .Split (tcDeleteQdiscParentCommandComposed , " " )
2373+ 
2374+ 				startHandleMethod  =  handler .StartNetworkLatency ()
2375+ 				stopHandleMethod  =  handler .StopNetworkLatency ()
2376+ 			case  types .PacketLossFaultType :
2377+ 				tcAddQdiscRootCommandComposed  :=  nsenterPrefix  +  fmt .Sprintf (tcAddQdiscRootCommandString , deviceName )
2378+ 				firstStartExecCmd  =  strings .Split (tcAddQdiscRootCommandComposed , " " )
2379+ 
2380+ 				tcDeleteQdiscParentCommandComposed  :=  nsenterPrefix  +  fmt .Sprintf (tcDeleteQdiscParentCommandString , deviceName )
2381+ 				firstStopExecCmd  =  strings .Split (tcDeleteQdiscParentCommandComposed , " " )
2382+ 
2383+ 				startHandleMethod  =  handler .StartNetworkPacketLoss ()
2384+ 				stopHandleMethod  =  handler .StopNetworkPacketLoss ()
2385+ 			default :
2386+ 				t .Error ("Unrecognized network fault type" )
2387+ 			}
2388+ 
2389+ 			tc .setAgentStateExpectations (agentState , networkConfigClient )
2390+ 			tc .setExecExpectations (mockExec , ctrl , convertToInterfaceList (firstStartExecCmd ), convertToInterfaceList (firstStopExecCmd ))
2391+ 
2392+ 			router .HandleFunc (
2393+ 				NetworkFaultPath (tc .faultType , types .StartNetworkFaultPostfix ),
2394+ 				startHandleMethod ,
2395+ 			).Methods (http .MethodPost )
2396+ 
2397+ 			router .HandleFunc (
2398+ 				NetworkFaultPath (tc .faultType , types .StopNetworkFaultPostfix ),
2399+ 				stopHandleMethod ,
2400+ 			).Methods (http .MethodPost )
2401+ 
2402+ 			var  requestBody  io.Reader 
2403+ 			reqBodyBytes , err  :=  json .Marshal (tc .requestBody )
2404+ 			require .NoError (t , err )
2405+ 			requestBody  =  bytes .NewReader (reqBodyBytes )
2406+ 			startReq , err  :=  http .NewRequest (http .MethodPost , fmt .Sprintf (startEndpoint , endpointId , tc .faultType ), requestBody )
2407+ 			require .NoError (t , err )
2408+ 
2409+ 			ch1  :=  make (chan  struct  {
2410+ 				int 
2411+ 				error 
2412+ 			})
2413+ 
2414+ 			reqBodyBytes , err  =  json .Marshal (tc .requestBody )
2415+ 			require .NoError (t , err )
2416+ 			requestBody  =  bytes .NewReader (reqBodyBytes )
2417+ 			stopReq , err  :=  http .NewRequest (http .MethodPost , fmt .Sprintf (stopEndpoint , endpointId , tc .faultType ), requestBody )
2418+ 			require .NoError (t , err )
2419+ 
2420+ 			ch2  :=  make (chan  struct  {
2421+ 				int 
2422+ 				error 
2423+ 			})
2424+ 
2425+ 			// Make an asynchronous Start request first 
2426+ 			go  makeAsyncRequest (router , startReq , ch1 )
2427+ 
2428+ 			// Waiting a bit before sending the stop request 
2429+ 			time .Sleep (1  *  time .Second )
2430+ 
2431+ 			// Make an asynchronous Stop request second 
2432+ 			go  makeAsyncRequest (router , stopReq , ch2 )
2433+ 
2434+ 			// Waiting to get the status code of the start request 
2435+ 			resp1  :=  <- ch1 
2436+ 			require .NoError (t , resp1 .error )
2437+ 			assert .Equal (t , http .StatusOK , resp1 .int )
2438+ 
2439+ 			// Waiting to get the status code of the stop request 
2440+ 			resp2  :=  <- ch2 
2441+ 			require .NoError (t , resp2 .error )
2442+ 			assert .Equal (t , http .StatusOK , resp2 .int )
2443+ 		})
2444+ 	}
2445+ }
2446+ 
2447+ // Helper function for making asynchronous mock HTTP requests 
2448+ func  makeAsyncRequest (router  * mux.Router , req  * http.Request , ch  chan <-  struct  {
2449+ 	int 
2450+ 	error 
2451+ }) {
2452+ 	defer  close (ch )
2453+ 
2454+ 	// Makes a mock HTTP request 
2455+ 	recorder  :=  httptest .NewRecorder ()
2456+ 	router .ServeHTTP (recorder , req )
2457+ 
2458+ 	var  actualResponseBody  types.NetworkFaultInjectionResponse 
2459+ 	err  :=  json .Unmarshal (recorder .Body .Bytes (), & actualResponseBody )
2460+ 	if  err  !=  nil  {
2461+ 		ch  <-  struct  {
2462+ 			int 
2463+ 			error 
2464+ 		}{- 1 , err }
2465+ 	} else  {
2466+ 		ch  <-  struct  {
2467+ 			int 
2468+ 			error 
2469+ 		}{recorder .Code , nil }
2470+ 	}
2471+ }
2472+ 
2473+ func  convertToInterfaceList (strings  []string ) []interface {} {
2474+ 	interfaces  :=  make ([]interface {}, len (strings ))
2475+ 	for  i , s  :=  range  strings  {
2476+ 		interfaces [i ] =  s 
2477+ 	}
2478+ 	return  interfaces 
2479+ }
0 commit comments