github.com/line/line-bot-sdk-go/v7@v7.21.0/linebot/get_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 TestGetGroupMemberIDs(t *testing.T) { 31 type want struct { 32 URLPath string 33 ContinuationToken string 34 RequestBody []byte 35 Response *MemberIDsResponse 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 GroupID: "cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 49 ContinuationToken: "xxxxx", 50 ResponseCode: 200, 51 Response: []byte(`{"memberIds": ["U0047556f2e40dba2456887320ba7c76d", "U0047556f2e40dba2456887320ba7c76e"]}`), 52 Want: want{ 53 URLPath: fmt.Sprintf(APIEndpointGetGroupMemberIDs, "cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"), 54 ContinuationToken: "xxxxx", 55 RequestBody: []byte(""), 56 Response: &MemberIDsResponse{ 57 MemberIDs: []string{ 58 "U0047556f2e40dba2456887320ba7c76d", 59 "U0047556f2e40dba2456887320ba7c76e", 60 }, 61 }, 62 }, 63 }, 64 { 65 Label: "Without ContinuationToken", 66 GroupID: "cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 67 ResponseCode: 200, 68 Response: []byte(`{"memberIds": ["U0047556f2e40dba2456887320ba7c76d", "U0047556f2e40dba2456887320ba7c76e"], "next": "xxxxx"}`), 69 Want: want{ 70 URLPath: fmt.Sprintf(APIEndpointGetGroupMemberIDs, "cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"), 71 RequestBody: []byte(""), 72 Response: &MemberIDsResponse{ 73 MemberIDs: []string{ 74 "U0047556f2e40dba2456887320ba7c76d", 75 "U0047556f2e40dba2456887320ba7c76e", 76 }, 77 Next: "xxxxx", 78 }, 79 }, 80 }, 81 { 82 Label: "Internal server error", 83 GroupID: "cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 84 ContinuationToken: "xxxxx", 85 ResponseCode: 500, 86 Response: []byte("500 Internal server error"), 87 Want: want{ 88 URLPath: fmt.Sprintf(APIEndpointGetGroupMemberIDs, "cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"), 89 ContinuationToken: "xxxxx", 90 RequestBody: []byte(""), 91 Error: &APIError{ 92 Code: 500, 93 }, 94 }, 95 }, 96 } 97 98 var currentTestIdx int 99 server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 100 defer r.Body.Close() 101 tc := testCases[currentTestIdx] 102 if r.Method != http.MethodGet { 103 t.Errorf("Method %s; want %s", r.Method, http.MethodGet) 104 } 105 if r.URL.Path != tc.Want.URLPath { 106 t.Errorf("URLPath %s; want %s", r.URL.Path, tc.Want.URLPath) 107 } 108 q := r.URL.Query() 109 if start, want := q.Get("start"), tc.Want.ContinuationToken; start != want { 110 t.Errorf("ContinuationToken: %s; want %s", start, want) 111 } 112 body, err := io.ReadAll(r.Body) 113 if err != nil { 114 t.Fatal(err) 115 } 116 if !reflect.DeepEqual(body, tc.Want.RequestBody) { 117 t.Errorf("RequestBody %s; want %s", body, tc.Want.RequestBody) 118 } 119 w.WriteHeader(tc.ResponseCode) 120 w.Write(tc.Response) 121 })) 122 defer server.Close() 123 124 dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 125 defer r.Body.Close() 126 t.Error("Unexpected Data API call") 127 w.WriteHeader(404) 128 w.Write([]byte(`{"message":"Not found"}`)) 129 })) 130 defer dataServer.Close() 131 132 client, err := mockClient(server, dataServer) 133 if err != nil { 134 t.Fatal(err) 135 } 136 for i, tc := range testCases { 137 currentTestIdx = i 138 t.Run(strconv.Itoa(i)+"/"+tc.Label, func(t *testing.T) { 139 res, err := client.GetGroupMemberIDs(tc.GroupID, tc.ContinuationToken).Do() 140 if tc.Want.Error != nil { 141 if !reflect.DeepEqual(err, tc.Want.Error) { 142 t.Errorf("Error %v; want %v", err, tc.Want.Error) 143 } 144 } else { 145 if err != nil { 146 t.Error(err) 147 } 148 } 149 if !reflect.DeepEqual(res, tc.Want.Response) { 150 t.Errorf("Response %v; want %v", res, tc.Want.Response) 151 } 152 }) 153 } 154 } 155 156 func TestGetGroupMemberIDsWithContext(t *testing.T) { 157 server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 158 defer r.Body.Close() 159 time.Sleep(10 * time.Millisecond) 160 w.Write([]byte("{}")) 161 })) 162 defer server.Close() 163 164 dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 165 defer r.Body.Close() 166 t.Error("Unexpected Data API call") 167 w.WriteHeader(404) 168 w.Write([]byte(`{"message":"Not found"}`)) 169 })) 170 defer dataServer.Close() 171 172 client, err := mockClient(server, dataServer) 173 if err != nil { 174 t.Fatal(err) 175 } 176 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Millisecond) 177 defer cancel() 178 _, err = client.GetGroupMemberIDs("cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "xxxxx").WithContext(ctx).Do() 179 expectCtxDeadlineExceed(ctx, err, t) 180 } 181 182 func BenchmarkGetGroupMemberIDs(b *testing.B) { 183 server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 184 defer r.Body.Close() 185 w.Write([]byte(`{"memberIds": ["U0047556f2e40dba2456887320ba7c76d", "U0047556f2e40dba2456887320ba7c76e"], "next": "xxxxx"}`)) 186 })) 187 defer server.Close() 188 189 dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 190 defer r.Body.Close() 191 b.Error("Unexpected Data API call") 192 w.WriteHeader(404) 193 w.Write([]byte(`{"message":"Not found"}`)) 194 })) 195 defer dataServer.Close() 196 197 client, err := mockClient(server, dataServer) 198 if err != nil { 199 b.Fatal(err) 200 } 201 b.ResetTimer() 202 for i := 0; i < b.N; i++ { 203 client.GetGroupMemberIDs("cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "xxxxx").Do() 204 } 205 } 206 207 func TestGetRoomMemberIDs(t *testing.T) { 208 type want struct { 209 URLPath string 210 ContinuationToken string 211 RequestBody []byte 212 Response *MemberIDsResponse 213 Error error 214 } 215 testCases := []struct { 216 Label string 217 RoomID string 218 ContinuationToken string 219 ResponseCode int 220 Response []byte 221 Want want 222 }{ 223 { 224 Label: "With ContinuationToken", 225 RoomID: "cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 226 ContinuationToken: "xxxxx", 227 ResponseCode: 200, 228 Response: []byte(`{"memberIds": ["U0047556f2e40dba2456887320ba7c76d", "U0047556f2e40dba2456887320ba7c76e"]}`), 229 Want: want{ 230 URLPath: fmt.Sprintf(APIEndpointGetRoomMemberIDs, "cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"), 231 ContinuationToken: "xxxxx", 232 RequestBody: []byte(""), 233 Response: &MemberIDsResponse{ 234 MemberIDs: []string{ 235 "U0047556f2e40dba2456887320ba7c76d", 236 "U0047556f2e40dba2456887320ba7c76e", 237 }, 238 }, 239 }, 240 }, 241 { 242 Label: "Without ContinuationToken", 243 RoomID: "cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 244 ResponseCode: 200, 245 Response: []byte(`{"memberIds": ["U0047556f2e40dba2456887320ba7c76d", "U0047556f2e40dba2456887320ba7c76e"], "next": "xxxxx"}`), 246 Want: want{ 247 URLPath: fmt.Sprintf(APIEndpointGetRoomMemberIDs, "cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"), 248 RequestBody: []byte(""), 249 Response: &MemberIDsResponse{ 250 MemberIDs: []string{ 251 "U0047556f2e40dba2456887320ba7c76d", 252 "U0047556f2e40dba2456887320ba7c76e", 253 }, 254 Next: "xxxxx", 255 }, 256 }, 257 }, 258 { 259 Label: "Internal server error", 260 RoomID: "cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 261 ContinuationToken: "xxxxx", 262 ResponseCode: 500, 263 Response: []byte("500 Internal server error"), 264 Want: want{ 265 URLPath: fmt.Sprintf(APIEndpointGetRoomMemberIDs, "cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"), 266 ContinuationToken: "xxxxx", 267 RequestBody: []byte(""), 268 Error: &APIError{ 269 Code: 500, 270 }, 271 }, 272 }, 273 } 274 275 var currentTestIdx int 276 server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 277 defer r.Body.Close() 278 tc := testCases[currentTestIdx] 279 if r.Method != http.MethodGet { 280 t.Errorf("Method %s; want %s", r.Method, http.MethodGet) 281 } 282 if r.URL.Path != tc.Want.URLPath { 283 t.Errorf("URLPath %s; want %s", r.URL.Path, tc.Want.URLPath) 284 } 285 q := r.URL.Query() 286 if start, want := q.Get("start"), tc.Want.ContinuationToken; start != want { 287 t.Errorf("ContinuationToken: %s; want %s", start, want) 288 } 289 body, err := io.ReadAll(r.Body) 290 if err != nil { 291 t.Fatal(err) 292 } 293 if !reflect.DeepEqual(body, tc.Want.RequestBody) { 294 t.Errorf("RequestBody %s; want %s", body, tc.Want.RequestBody) 295 } 296 w.WriteHeader(tc.ResponseCode) 297 w.Write(tc.Response) 298 })) 299 defer server.Close() 300 301 dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 302 defer r.Body.Close() 303 t.Error("Unexpected Data API call") 304 w.WriteHeader(404) 305 w.Write([]byte(`{"message":"Not found"}`)) 306 })) 307 defer dataServer.Close() 308 309 client, err := mockClient(server, dataServer) 310 if err != nil { 311 t.Fatal(err) 312 } 313 for i, tc := range testCases { 314 currentTestIdx = i 315 t.Run(strconv.Itoa(i)+"/"+tc.Label, func(t *testing.T) { 316 res, err := client.GetRoomMemberIDs(tc.RoomID, tc.ContinuationToken).Do() 317 if tc.Want.Error != nil { 318 if !reflect.DeepEqual(err, tc.Want.Error) { 319 t.Errorf("Error %v; want %v", err, tc.Want.Error) 320 } 321 } else { 322 if err != nil { 323 t.Error(err) 324 } 325 } 326 if !reflect.DeepEqual(res, tc.Want.Response) { 327 t.Errorf("Response %v; want %v", res, tc.Want.Response) 328 } 329 }) 330 } 331 } 332 333 func TestGetRoomMemberIDsWithContext(t *testing.T) { 334 server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 335 defer r.Body.Close() 336 time.Sleep(10 * time.Millisecond) 337 w.Write([]byte("{}")) 338 })) 339 defer server.Close() 340 341 dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 342 defer r.Body.Close() 343 t.Error("Unexpected Data API call") 344 w.WriteHeader(404) 345 w.Write([]byte(`{"message":"Not found"}`)) 346 })) 347 defer dataServer.Close() 348 349 client, err := mockClient(server, dataServer) 350 if err != nil { 351 t.Fatal(err) 352 } 353 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Millisecond) 354 defer cancel() 355 _, err = client.GetRoomMemberIDs("cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "xxxxx").WithContext(ctx).Do() 356 expectCtxDeadlineExceed(ctx, err, t) 357 } 358 359 func BenchmarkGetRoomMemberIDs(b *testing.B) { 360 server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 361 defer r.Body.Close() 362 w.Write([]byte(`{"memberIds": ["U0047556f2e40dba2456887320ba7c76d", "U0047556f2e40dba2456887320ba7c76e"], "next": "xxxxx"}`)) 363 })) 364 defer server.Close() 365 366 dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 367 defer r.Body.Close() 368 b.Error("Unexpected Data API call") 369 w.WriteHeader(404) 370 w.Write([]byte(`{"message":"Not found"}`)) 371 })) 372 defer dataServer.Close() 373 374 client, err := mockClient(server, dataServer) 375 if err != nil { 376 b.Fatal(err) 377 } 378 b.ResetTimer() 379 for i := 0; i < b.N; i++ { 380 client.GetRoomMemberIDs("cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "xxxxx").Do() 381 } 382 } 383 384 func TestGetGroupMemberIDsScanner(t *testing.T) { 385 res1 := &MemberIDsResponse{ 386 MemberIDs: []string{}, 387 Next: "xxxxx", 388 } 389 390 res2 := &MemberIDsResponse{ 391 MemberIDs: []string{}, 392 } 393 394 for i := 0; i < 150; i++ { 395 if i < 100 { 396 res1.MemberIDs = append(res1.MemberIDs, fmt.Sprintf("U%032d", i)) 397 } else { 398 res2.MemberIDs = append(res2.MemberIDs, fmt.Sprintf("U%032d", i)) 399 } 400 } 401 402 under100Res := &MemberIDsResponse{ 403 MemberIDs: []string{}, 404 } 405 406 for i := 0; i < 50; i++ { 407 under100Res.MemberIDs = append(under100Res.MemberIDs, fmt.Sprintf("U%032d", i)) 408 } 409 410 testCases := []struct { 411 FirstResponse *MemberIDsResponse 412 SecondResponse *MemberIDsResponse 413 }{ 414 { 415 FirstResponse: res1, 416 SecondResponse: res2, 417 }, 418 { 419 FirstResponse: under100Res, 420 }, 421 } 422 423 var currentTestIdx int 424 server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 425 defer r.Body.Close() 426 tc := testCases[currentTestIdx] 427 if r.Method != http.MethodGet { 428 t.Errorf("Method %s; want %s", r.Method, http.MethodGet) 429 } 430 q := r.URL.Query() 431 w.WriteHeader(200) 432 if q.Get("start") == res1.Next { 433 if err := json.NewEncoder(w).Encode(tc.SecondResponse); err != nil { 434 t.Fatal(err) 435 } 436 return 437 } 438 if err := json.NewEncoder(w).Encode(tc.FirstResponse); err != nil { 439 t.Fatal(err) 440 } 441 })) 442 defer server.Close() 443 444 dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 445 defer r.Body.Close() 446 t.Error("Unexpected Data API call") 447 w.WriteHeader(404) 448 w.Write([]byte(`{"message":"Not found"}`)) 449 })) 450 defer dataServer.Close() 451 452 client, err := mockClient(server, dataServer) 453 if err != nil { 454 t.Fatal(err) 455 } 456 457 for i := range testCases { 458 currentTestIdx = i 459 t.Run(strconv.Itoa(i), func(t *testing.T) { 460 s := client.GetGroupMemberIDs("cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "").NewScanner() 461 for k := 0; s.Scan(); k++ { 462 if got, want := s.ID(), fmt.Sprintf("U%032d", k); got != want { 463 t.Fatalf("got = %s; want %s; scanner = %#v", got, want, s) 464 } 465 } 466 if err := s.Err(); err != nil { 467 t.Fatal(err) 468 } 469 }) 470 } 471 } 472 473 func TestGetRoomMemberIDsScanner(t *testing.T) { 474 res1 := &MemberIDsResponse{ 475 MemberIDs: []string{}, 476 Next: "xxxxx", 477 } 478 479 res2 := &MemberIDsResponse{ 480 MemberIDs: []string{}, 481 } 482 483 for i := 0; i < 150; i++ { 484 if i < 100 { 485 res1.MemberIDs = append(res1.MemberIDs, fmt.Sprintf("U%032d", i)) 486 } else { 487 res2.MemberIDs = append(res2.MemberIDs, fmt.Sprintf("U%032d", i)) 488 } 489 } 490 491 under100Res := &MemberIDsResponse{ 492 MemberIDs: []string{}, 493 } 494 495 for i := 0; i < 50; i++ { 496 under100Res.MemberIDs = append(under100Res.MemberIDs, fmt.Sprintf("U%032d", i)) 497 } 498 499 testCases := []struct { 500 FirstResponse *MemberIDsResponse 501 SecondResponse *MemberIDsResponse 502 }{ 503 { 504 FirstResponse: res1, 505 SecondResponse: res2, 506 }, 507 { 508 FirstResponse: under100Res, 509 }, 510 } 511 512 var currentTestIdx int 513 server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 514 defer r.Body.Close() 515 tc := testCases[currentTestIdx] 516 if r.Method != http.MethodGet { 517 t.Errorf("Method %s; want %s", r.Method, http.MethodGet) 518 } 519 q := r.URL.Query() 520 w.WriteHeader(200) 521 if q.Get("start") == res1.Next { 522 if err := json.NewEncoder(w).Encode(tc.SecondResponse); err != nil { 523 t.Fatal(err) 524 } 525 return 526 } 527 if err := json.NewEncoder(w).Encode(tc.FirstResponse); err != nil { 528 t.Fatal(err) 529 } 530 })) 531 defer server.Close() 532 533 dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 534 defer r.Body.Close() 535 t.Error("Unexpected Data API call") 536 w.WriteHeader(404) 537 w.Write([]byte(`{"message":"Not found"}`)) 538 })) 539 defer dataServer.Close() 540 541 client, err := mockClient(server, dataServer) 542 if err != nil { 543 t.Fatal(err) 544 } 545 546 for i := range testCases { 547 currentTestIdx = i 548 t.Run(strconv.Itoa(i), func(t *testing.T) { 549 s := client.GetRoomMemberIDs("cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "").NewScanner() 550 for k := 0; s.Scan(); k++ { 551 if got, want := s.ID(), fmt.Sprintf("U%032d", k); got != want { 552 t.Fatalf("got = %s; want %s; scanner = %#v", got, want, s) 553 } 554 } 555 if err := s.Err(); err != nil { 556 t.Fatal(err) 557 } 558 }) 559 } 560 }