github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/engine/executor/openapi_test.go (about) 1 // Copyright 2022 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package executor 15 16 import ( 17 "context" 18 "encoding/json" 19 "net/http" 20 "net/http/httptest" 21 "sync" 22 "testing" 23 "time" 24 25 "github.com/gin-gonic/gin" 26 engineModel "github.com/pingcap/tiflow/engine/model" 27 "github.com/pingcap/tiflow/engine/pkg/openapi" 28 "github.com/pingcap/tiflow/pkg/errors" 29 "github.com/stretchr/testify/require" 30 ) 31 32 func TestJobAPIServer(t *testing.T) { 33 jobAPISrv := newJobAPIServer() 34 35 jobAPISrv.initialize("job1", func(apiGroup *gin.RouterGroup) { 36 apiGroup.GET("/status", func(c *gin.Context) { 37 c.String(http.StatusOK, "job1 status") 38 }) 39 }) 40 jobAPISrv.initialize("job2", func(apiGroup *gin.RouterGroup) { 41 apiGroup.GET("/status", func(c *gin.Context) { 42 c.String(http.StatusOK, "job2 status") 43 }) 44 }) 45 46 ensureNotRunning := func(w *httptest.ResponseRecorder) { 47 require.Equal(t, errors.HTTPStatusCode(errors.ErrJobNotRunning), w.Code) 48 var httpErr openapi.HTTPError 49 require.NoError(t, json.Unmarshal(w.Body.Bytes(), &httpErr)) 50 require.Equal(t, string(errors.ErrJobNotRunning.RFCCode()), httpErr.Code) 51 } 52 53 // test job1 54 { 55 w := httptest.NewRecorder() 56 r := httptest.NewRequest("GET", "/api/v1/jobs/job1/status", nil) 57 jobAPISrv.ServeHTTP(w, r) 58 require.Equal(t, http.StatusOK, w.Code) 59 require.Equal(t, "job1 status", w.Body.String()) 60 } 61 // test job2 62 { 63 w := httptest.NewRecorder() 64 r := httptest.NewRequest("GET", "/api/v1/jobs/job2/status", nil) 65 jobAPISrv.ServeHTTP(w, r) 66 require.Equal(t, http.StatusOK, w.Code) 67 require.Equal(t, "job2 status", w.Body.String()) 68 } 69 // test not running job 70 { 71 w := httptest.NewRecorder() 72 r := httptest.NewRequest("GET", "/api/v1/jobs/job3/status", nil) 73 jobAPISrv.ServeHTTP(w, r) 74 ensureNotRunning(w) 75 } 76 77 wg := sync.WaitGroup{} 78 stoppedJobs := make(chan engineModel.JobID, 16) 79 wg.Add(1) 80 go func() { 81 defer wg.Done() 82 err := jobAPISrv.listenStoppedJobs(context.Background(), stoppedJobs) 83 require.NoError(t, err) 84 }() 85 86 stoppedJobs <- "job1" 87 require.Eventually(t, func() bool { 88 w := httptest.NewRecorder() 89 r := httptest.NewRequest("GET", "/api/v1/jobs/job1/status", nil) 90 jobAPISrv.ServeHTTP(w, r) 91 if w.Code/100 != 2 { 92 ensureNotRunning(w) 93 return true 94 } 95 return false 96 }, time.Second, time.Millisecond*100) 97 98 stoppedJobs <- "job2" 99 require.Eventually(t, func() bool { 100 w := httptest.NewRecorder() 101 r := httptest.NewRequest("GET", "/api/v1/jobs/job2/status", nil) 102 jobAPISrv.ServeHTTP(w, r) 103 if w.Code/100 != 2 { 104 ensureNotRunning(w) 105 return true 106 } 107 return false 108 }, time.Second, time.Millisecond*100) 109 110 close(stoppedJobs) 111 wg.Wait() 112 }