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  }