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  }