github.com/line/line-bot-sdk-go/v7@v7.21.0/linebot/get_follower_ids_test.go (about) 1 // Copyright 2016 LINE Corporation 2 // 3 // LINE Corporation licenses this file to you under the Apache License, 4 // version 2.0 (the "License"); you may not use this file except in compliance 5 // with the License. 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, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations 13 // under the License. 14 15 package linebot 16 17 import ( 18 "context" 19 "encoding/json" 20 "fmt" 21 "io" 22 "net/http" 23 "net/http/httptest" 24 "reflect" 25 "strconv" 26 "testing" 27 "time" 28 ) 29 30 func TestGetFollowerIDs(t *testing.T) { 31 type want struct { 32 URLPath string 33 ContinuationToken string 34 RequestBody []byte 35 Response *UserIDsResponse 36 Error error 37 } 38 testCases := []struct { 39 Label string 40 GroupID string 41 ContinuationToken string 42 ResponseCode int 43 Response []byte 44 Want want 45 }{ 46 { 47 Label: "With ContinuationToken", 48 ContinuationToken: "xxxxx", 49 ResponseCode: 200, 50 Response: []byte(`{"userIds": ["U0047556f2e40dba2456887320ba7c76d", "U0047556f2e40dba2456887320ba7c76e"]}`), 51 Want: want{ 52 URLPath: APIEndpointGetFollowerIDs, 53 ContinuationToken: "xxxxx", 54 RequestBody: []byte(""), 55 Response: &UserIDsResponse{ 56 UserIDs: []string{ 57 "U0047556f2e40dba2456887320ba7c76d", 58 "U0047556f2e40dba2456887320ba7c76e", 59 }, 60 }, 61 }, 62 }, 63 { 64 Label: "Without ContinuationToken", 65 GroupID: "cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 66 ResponseCode: 200, 67 Response: []byte(`{"userIds": ["U0047556f2e40dba2456887320ba7c76d", "U0047556f2e40dba2456887320ba7c76e"], "next": "xxxxx"}`), 68 Want: want{ 69 URLPath: APIEndpointGetFollowerIDs, 70 RequestBody: []byte(""), 71 Response: &UserIDsResponse{ 72 UserIDs: []string{ 73 "U0047556f2e40dba2456887320ba7c76d", 74 "U0047556f2e40dba2456887320ba7c76e", 75 }, 76 Next: "xxxxx", 77 }, 78 }, 79 }, 80 { 81 Label: "Internal server error", 82 GroupID: "cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 83 ContinuationToken: "xxxxx", 84 ResponseCode: 500, 85 Response: []byte("500 Internal server error"), 86 Want: want{ 87 URLPath: APIEndpointGetFollowerIDs, 88 ContinuationToken: "xxxxx", 89 RequestBody: []byte(""), 90 Error: &APIError{ 91 Code: 500, 92 }, 93 }, 94 }, 95 } 96 97 var currentTestIdx int 98 server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 99 defer r.Body.Close() 100 tc := testCases[currentTestIdx] 101 if r.Method != http.MethodGet { 102 t.Errorf("Method %s; want %s", r.Method, http.MethodGet) 103 } 104 if r.URL.Path != tc.Want.URLPath { 105 t.Errorf("URLPath %s; want %s", r.URL.Path, tc.Want.URLPath) 106 } 107 q := r.URL.Query() 108 if start, want := q.Get("start"), tc.Want.ContinuationToken; start != want { 109 t.Errorf("ContinuationToken: %s; want %s", start, want) 110 } 111 body, err := io.ReadAll(r.Body) 112 if err != nil { 113 t.Fatal(err) 114 } 115 if !reflect.DeepEqual(body, tc.Want.RequestBody) { 116 t.Errorf("RequestBody %s; want %s", body, tc.Want.RequestBody) 117 } 118 w.WriteHeader(tc.ResponseCode) 119 w.Write(tc.Response) 120 })) 121 defer server.Close() 122 123 dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 124 defer r.Body.Close() 125 t.Error("Unexpected Data API call") 126 w.WriteHeader(404) 127 w.Write([]byte(`{"message":"Not found"}`)) 128 })) 129 defer dataServer.Close() 130 131 client, err := mockClient(server, dataServer) 132 if err != nil { 133 t.Fatal(err) 134 } 135 for i, tc := range testCases { 136 currentTestIdx = i 137 t.Run(strconv.Itoa(i)+"/"+tc.Label, func(t *testing.T) { 138 res, err := client.GetFollowerIDs(tc.ContinuationToken).Do() 139 if tc.Want.Error != nil { 140 if !reflect.DeepEqual(err, tc.Want.Error) { 141 t.Errorf("Error %v; want %v", err, tc.Want.Error) 142 } 143 } else { 144 if err != nil { 145 t.Error(err) 146 } 147 } 148 if !reflect.DeepEqual(res, tc.Want.Response) { 149 t.Errorf("Response %v; want %v", res, tc.Want.Response) 150 } 151 }) 152 } 153 } 154 155 func TestGetFollowerIDsWithContext(t *testing.T) { 156 server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 157 defer r.Body.Close() 158 time.Sleep(10 * time.Millisecond) 159 w.Write([]byte("{}")) 160 })) 161 defer server.Close() 162 163 dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 164 defer r.Body.Close() 165 t.Error("Unexpected Data API call") 166 w.WriteHeader(404) 167 w.Write([]byte(`{"message":"Not found"}`)) 168 })) 169 defer dataServer.Close() 170 171 client, err := mockClient(server, dataServer) 172 if err != nil { 173 t.Fatal(err) 174 } 175 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Millisecond) 176 defer cancel() 177 _, err = client.GetFollowerIDs("xxxxx").WithContext(ctx).Do() 178 expectCtxDeadlineExceed(ctx, err, t) 179 } 180 181 func BenchmarkGetFollowerIDs(b *testing.B) { 182 server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 183 defer r.Body.Close() 184 w.Write([]byte(`{"userIds": ["U0047556f2e40dba2456887320ba7c76d", "U0047556f2e40dba2456887320ba7c76e"], "next": "xxxxx"}`)) 185 })) 186 defer server.Close() 187 188 dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 189 defer r.Body.Close() 190 b.Error("Unexpected Data API call") 191 w.WriteHeader(404) 192 w.Write([]byte(`{"message":"Not found"}`)) 193 })) 194 defer dataServer.Close() 195 196 client, err := mockClient(server, dataServer) 197 if err != nil { 198 b.Fatal(err) 199 } 200 b.ResetTimer() 201 for i := 0; i < b.N; i++ { 202 client.GetFollowerIDs("xxxxx").Do() 203 } 204 } 205 206 func TestGetFollowerIDsScanner(t *testing.T) { 207 res1 := &UserIDsResponse{ 208 UserIDs: []string{}, 209 Next: "xxxxx", 210 } 211 212 res2 := &UserIDsResponse{ 213 UserIDs: []string{}, 214 } 215 216 for i := 0; i < 450; i++ { 217 if i < 300 { 218 res1.UserIDs = append(res1.UserIDs, fmt.Sprintf("U%032d", i)) 219 } else { 220 res2.UserIDs = append(res2.UserIDs, fmt.Sprintf("U%032d", i)) 221 } 222 } 223 224 under300Res := &UserIDsResponse{ 225 UserIDs: []string{}, 226 } 227 228 for i := 0; i < 50; i++ { 229 under300Res.UserIDs = append(under300Res.UserIDs, fmt.Sprintf("U%032d", i)) 230 } 231 232 testCases := []struct { 233 FirstResponse *UserIDsResponse 234 SecondResponse *UserIDsResponse 235 }{ 236 { 237 FirstResponse: res1, 238 SecondResponse: res2, 239 }, 240 { 241 FirstResponse: under300Res, 242 }, 243 } 244 245 var currentTestIdx int 246 server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 247 defer r.Body.Close() 248 tc := testCases[currentTestIdx] 249 if r.Method != http.MethodGet { 250 t.Errorf("Method %s; want %s", r.Method, http.MethodGet) 251 } 252 q := r.URL.Query() 253 w.WriteHeader(200) 254 if q.Get("start") == res1.Next { 255 if err := json.NewEncoder(w).Encode(tc.SecondResponse); err != nil { 256 t.Fatal(err) 257 } 258 return 259 } 260 if err := json.NewEncoder(w).Encode(tc.FirstResponse); err != nil { 261 t.Fatal(err) 262 } 263 })) 264 defer server.Close() 265 266 dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 267 defer r.Body.Close() 268 t.Error("Unexpected Data API call") 269 w.WriteHeader(404) 270 w.Write([]byte(`{"message":"Not found"}`)) 271 })) 272 defer dataServer.Close() 273 274 client, err := mockClient(server, dataServer) 275 if err != nil { 276 t.Fatal(err) 277 } 278 279 for i := range testCases { 280 currentTestIdx = i 281 t.Run(strconv.Itoa(i), func(t *testing.T) { 282 s := client.GetFollowerIDs("").NewScanner() 283 for k := 0; s.Scan(); k++ { 284 if got, want := s.ID(), fmt.Sprintf("U%032d", k); got != want { 285 t.Fatalf("got = %s; want %s; scanner = %#v", got, want, s) 286 } 287 } 288 if err := s.Err(); err != nil { 289 t.Fatal(err) 290 } 291 }) 292 } 293 }