github.com/google/go-github/v64@v64.0.0/github/rate_limit_test.go (about)

     1  // Copyright 2023 The go-github AUTHORS. All rights reserved.
     2  //
     3  // Use of this source code is governed by a BSD-style
     4  // license that can be found in the LICENSE file.
     5  
     6  package github
     7  
     8  import (
     9  	"context"
    10  	"fmt"
    11  	"net/http"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/google/go-cmp/cmp"
    16  )
    17  
    18  func TestRateLimits_String(t *testing.T) {
    19  	v := RateLimits{
    20  		Core:                      &Rate{},
    21  		Search:                    &Rate{},
    22  		GraphQL:                   &Rate{},
    23  		IntegrationManifest:       &Rate{},
    24  		SourceImport:              &Rate{},
    25  		CodeScanningUpload:        &Rate{},
    26  		ActionsRunnerRegistration: &Rate{},
    27  		SCIM:                      &Rate{},
    28  		DependencySnapshots:       &Rate{},
    29  		CodeSearch:                &Rate{},
    30  		AuditLog:                  &Rate{},
    31  	}
    32  	want := `github.RateLimits{Core:github.Rate{Limit:0, Remaining:0, Reset:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}}, Search:github.Rate{Limit:0, Remaining:0, Reset:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}}, GraphQL:github.Rate{Limit:0, Remaining:0, Reset:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}}, IntegrationManifest:github.Rate{Limit:0, Remaining:0, Reset:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}}, SourceImport:github.Rate{Limit:0, Remaining:0, Reset:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}}, CodeScanningUpload:github.Rate{Limit:0, Remaining:0, Reset:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}}, ActionsRunnerRegistration:github.Rate{Limit:0, Remaining:0, Reset:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}}, SCIM:github.Rate{Limit:0, Remaining:0, Reset:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}}, DependencySnapshots:github.Rate{Limit:0, Remaining:0, Reset:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}}, CodeSearch:github.Rate{Limit:0, Remaining:0, Reset:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}}, AuditLog:github.Rate{Limit:0, Remaining:0, Reset:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}}}`
    33  	if got := v.String(); got != want {
    34  		t.Errorf("RateLimits.String = %v, want %v", got, want)
    35  	}
    36  }
    37  
    38  func TestRateLimits(t *testing.T) {
    39  	client, mux, _, teardown := setup()
    40  	defer teardown()
    41  
    42  	mux.HandleFunc("/rate_limit", func(w http.ResponseWriter, r *http.Request) {
    43  		testMethod(t, r, "GET")
    44  		fmt.Fprint(w, `{"resources":{
    45  			"core": {"limit":2,"remaining":1,"reset":1372700873},
    46  			"search": {"limit":3,"remaining":2,"reset":1372700874},
    47  			"graphql": {"limit":4,"remaining":3,"reset":1372700875},
    48  			"integration_manifest": {"limit":5,"remaining":4,"reset":1372700876},
    49  			"source_import": {"limit":6,"remaining":5,"reset":1372700877},
    50  			"code_scanning_upload": {"limit":7,"remaining":6,"reset":1372700878},
    51  			"actions_runner_registration": {"limit":8,"remaining":7,"reset":1372700879},
    52  			"scim": {"limit":9,"remaining":8,"reset":1372700880},
    53  			"dependency_snapshots": {"limit":10,"remaining":9,"reset":1372700881},
    54  			"code_search": {"limit":11,"remaining":10,"reset":1372700882},
    55  			"audit_log": {"limit": 12,"remaining":11,"reset":1372700883}
    56  		}}`)
    57  	})
    58  
    59  	ctx := context.Background()
    60  	rate, _, err := client.RateLimit.Get(ctx)
    61  	if err != nil {
    62  		t.Errorf("RateLimits returned error: %v", err)
    63  	}
    64  
    65  	want := &RateLimits{
    66  		Core: &Rate{
    67  			Limit:     2,
    68  			Remaining: 1,
    69  			Reset:     Timestamp{time.Date(2013, time.July, 1, 17, 47, 53, 0, time.UTC).Local()},
    70  		},
    71  		Search: &Rate{
    72  			Limit:     3,
    73  			Remaining: 2,
    74  			Reset:     Timestamp{time.Date(2013, time.July, 1, 17, 47, 54, 0, time.UTC).Local()},
    75  		},
    76  		GraphQL: &Rate{
    77  			Limit:     4,
    78  			Remaining: 3,
    79  			Reset:     Timestamp{time.Date(2013, time.July, 1, 17, 47, 55, 0, time.UTC).Local()},
    80  		},
    81  		IntegrationManifest: &Rate{
    82  			Limit:     5,
    83  			Remaining: 4,
    84  			Reset:     Timestamp{time.Date(2013, time.July, 1, 17, 47, 56, 0, time.UTC).Local()},
    85  		},
    86  		SourceImport: &Rate{
    87  			Limit:     6,
    88  			Remaining: 5,
    89  			Reset:     Timestamp{time.Date(2013, time.July, 1, 17, 47, 57, 0, time.UTC).Local()},
    90  		},
    91  		CodeScanningUpload: &Rate{
    92  			Limit:     7,
    93  			Remaining: 6,
    94  			Reset:     Timestamp{time.Date(2013, time.July, 1, 17, 47, 58, 0, time.UTC).Local()},
    95  		},
    96  		ActionsRunnerRegistration: &Rate{
    97  			Limit:     8,
    98  			Remaining: 7,
    99  			Reset:     Timestamp{time.Date(2013, time.July, 1, 17, 47, 59, 0, time.UTC).Local()},
   100  		},
   101  		SCIM: &Rate{
   102  			Limit:     9,
   103  			Remaining: 8,
   104  			Reset:     Timestamp{time.Date(2013, time.July, 1, 17, 48, 00, 0, time.UTC).Local()},
   105  		},
   106  		DependencySnapshots: &Rate{
   107  			Limit:     10,
   108  			Remaining: 9,
   109  			Reset:     Timestamp{time.Date(2013, time.July, 1, 17, 48, 1, 0, time.UTC).Local()},
   110  		},
   111  		CodeSearch: &Rate{
   112  			Limit:     11,
   113  			Remaining: 10,
   114  			Reset:     Timestamp{time.Date(2013, time.July, 1, 17, 48, 2, 0, time.UTC).Local()},
   115  		},
   116  		AuditLog: &Rate{
   117  			Limit:     12,
   118  			Remaining: 11,
   119  			Reset:     Timestamp{time.Date(2013, time.July, 1, 17, 48, 3, 0, time.UTC).Local()},
   120  		},
   121  	}
   122  	if !cmp.Equal(rate, want) {
   123  		t.Errorf("RateLimits returned %+v, want %+v", rate, want)
   124  	}
   125  	tests := []struct {
   126  		category RateLimitCategory
   127  		rate     *Rate
   128  	}{
   129  		{
   130  			category: CoreCategory,
   131  			rate:     want.Core,
   132  		},
   133  		{
   134  			category: SearchCategory,
   135  			rate:     want.Search,
   136  		},
   137  		{
   138  			category: GraphqlCategory,
   139  			rate:     want.GraphQL,
   140  		},
   141  		{
   142  			category: IntegrationManifestCategory,
   143  			rate:     want.IntegrationManifest,
   144  		},
   145  		{
   146  			category: SourceImportCategory,
   147  			rate:     want.SourceImport,
   148  		},
   149  		{
   150  			category: CodeScanningUploadCategory,
   151  			rate:     want.CodeScanningUpload,
   152  		},
   153  		{
   154  			category: ActionsRunnerRegistrationCategory,
   155  			rate:     want.ActionsRunnerRegistration,
   156  		},
   157  		{
   158  			category: ScimCategory,
   159  			rate:     want.SCIM,
   160  		},
   161  		{
   162  			category: DependencySnapshotsCategory,
   163  			rate:     want.DependencySnapshots,
   164  		},
   165  		{
   166  			category: CodeSearchCategory,
   167  			rate:     want.CodeSearch,
   168  		},
   169  		{
   170  			category: AuditLogCategory,
   171  			rate:     want.AuditLog,
   172  		},
   173  	}
   174  
   175  	for _, tt := range tests {
   176  		if got, want := client.rateLimits[tt.category], *tt.rate; got != want {
   177  			t.Errorf("client.rateLimits[%v] is %+v, want %+v", tt.category, got, want)
   178  		}
   179  	}
   180  }
   181  
   182  func TestRateLimits_coverage(t *testing.T) {
   183  	client, _, _, teardown := setup()
   184  	defer teardown()
   185  
   186  	ctx := context.Background()
   187  
   188  	const methodName = "RateLimits"
   189  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   190  		_, resp, err := client.RateLimit.Get(ctx)
   191  		return resp, err
   192  	})
   193  }
   194  
   195  func TestRateLimits_overQuota(t *testing.T) {
   196  	client, mux, _, teardown := setup()
   197  	defer teardown()
   198  
   199  	client.rateLimits[CoreCategory] = Rate{
   200  		Limit:     1,
   201  		Remaining: 0,
   202  		Reset:     Timestamp{time.Now().Add(time.Hour).Local()},
   203  	}
   204  	mux.HandleFunc("/rate_limit", func(w http.ResponseWriter, r *http.Request) {
   205  		fmt.Fprint(w, `{"resources":{
   206  			"core": {"limit":2,"remaining":1,"reset":1372700873},
   207  			"search": {"limit":3,"remaining":2,"reset":1372700874},
   208  			"graphql": {"limit":4,"remaining":3,"reset":1372700875},
   209  			"integration_manifest": {"limit":5,"remaining":4,"reset":1372700876},
   210  			"source_import": {"limit":6,"remaining":5,"reset":1372700877},
   211  			"code_scanning_upload": {"limit":7,"remaining":6,"reset":1372700878},
   212  			"actions_runner_registration": {"limit":8,"remaining":7,"reset":1372700879},
   213  			"scim": {"limit":9,"remaining":8,"reset":1372700880},
   214  			"dependency_snapshots": {"limit":10,"remaining":9,"reset":1372700881},
   215  			"code_search": {"limit":11,"remaining":10,"reset":1372700882},
   216  			"audit_log": {"limit":12,"remaining":11,"reset":1372700883}
   217  		}}`)
   218  	})
   219  
   220  	ctx := context.Background()
   221  	rate, _, err := client.RateLimit.Get(ctx)
   222  	if err != nil {
   223  		t.Errorf("RateLimits returned error: %v", err)
   224  	}
   225  
   226  	want := &RateLimits{
   227  		Core: &Rate{
   228  			Limit:     2,
   229  			Remaining: 1,
   230  			Reset:     Timestamp{time.Date(2013, time.July, 1, 17, 47, 53, 0, time.UTC).Local()},
   231  		},
   232  		Search: &Rate{
   233  			Limit:     3,
   234  			Remaining: 2,
   235  			Reset:     Timestamp{time.Date(2013, time.July, 1, 17, 47, 54, 0, time.UTC).Local()},
   236  		},
   237  		GraphQL: &Rate{
   238  			Limit:     4,
   239  			Remaining: 3,
   240  			Reset:     Timestamp{time.Date(2013, time.July, 1, 17, 47, 55, 0, time.UTC).Local()},
   241  		},
   242  		IntegrationManifest: &Rate{
   243  			Limit:     5,
   244  			Remaining: 4,
   245  			Reset:     Timestamp{time.Date(2013, time.July, 1, 17, 47, 56, 0, time.UTC).Local()},
   246  		},
   247  		SourceImport: &Rate{
   248  			Limit:     6,
   249  			Remaining: 5,
   250  			Reset:     Timestamp{time.Date(2013, time.July, 1, 17, 47, 57, 0, time.UTC).Local()},
   251  		},
   252  		CodeScanningUpload: &Rate{
   253  			Limit:     7,
   254  			Remaining: 6,
   255  			Reset:     Timestamp{time.Date(2013, time.July, 1, 17, 47, 58, 0, time.UTC).Local()},
   256  		},
   257  		ActionsRunnerRegistration: &Rate{
   258  			Limit:     8,
   259  			Remaining: 7,
   260  			Reset:     Timestamp{time.Date(2013, time.July, 1, 17, 47, 59, 0, time.UTC).Local()},
   261  		},
   262  		SCIM: &Rate{
   263  			Limit:     9,
   264  			Remaining: 8,
   265  			Reset:     Timestamp{time.Date(2013, time.July, 1, 17, 48, 00, 0, time.UTC).Local()},
   266  		},
   267  		DependencySnapshots: &Rate{
   268  			Limit:     10,
   269  			Remaining: 9,
   270  			Reset:     Timestamp{time.Date(2013, time.July, 1, 17, 48, 1, 0, time.UTC).Local()},
   271  		},
   272  		CodeSearch: &Rate{
   273  			Limit:     11,
   274  			Remaining: 10,
   275  			Reset:     Timestamp{time.Date(2013, time.July, 1, 17, 48, 2, 0, time.UTC).Local()},
   276  		},
   277  		AuditLog: &Rate{
   278  			Limit:     12,
   279  			Remaining: 11,
   280  			Reset:     Timestamp{time.Date(2013, time.July, 1, 17, 48, 3, 0, time.UTC).Local()},
   281  		},
   282  	}
   283  	if !cmp.Equal(rate, want) {
   284  		t.Errorf("RateLimits returned %+v, want %+v", rate, want)
   285  	}
   286  
   287  	tests := []struct {
   288  		category RateLimitCategory
   289  		rate     *Rate
   290  	}{
   291  		{
   292  			category: CoreCategory,
   293  			rate:     want.Core,
   294  		},
   295  		{
   296  			category: SearchCategory,
   297  			rate:     want.Search,
   298  		},
   299  		{
   300  			category: GraphqlCategory,
   301  			rate:     want.GraphQL,
   302  		},
   303  		{
   304  			category: IntegrationManifestCategory,
   305  			rate:     want.IntegrationManifest,
   306  		},
   307  		{
   308  			category: SourceImportCategory,
   309  			rate:     want.SourceImport,
   310  		},
   311  		{
   312  			category: CodeScanningUploadCategory,
   313  			rate:     want.CodeScanningUpload,
   314  		},
   315  		{
   316  			category: ActionsRunnerRegistrationCategory,
   317  			rate:     want.ActionsRunnerRegistration,
   318  		},
   319  		{
   320  			category: ScimCategory,
   321  			rate:     want.SCIM,
   322  		},
   323  		{
   324  			category: DependencySnapshotsCategory,
   325  			rate:     want.DependencySnapshots,
   326  		},
   327  		{
   328  			category: CodeSearchCategory,
   329  			rate:     want.CodeSearch,
   330  		},
   331  		{
   332  			category: AuditLogCategory,
   333  			rate:     want.AuditLog,
   334  		},
   335  	}
   336  	for _, tt := range tests {
   337  		if got, want := client.rateLimits[tt.category], *tt.rate; got != want {
   338  			t.Errorf("client.rateLimits[%v] is %+v, want %+v", tt.category, got, want)
   339  		}
   340  	}
   341  }
   342  
   343  func TestRateLimits_Marshal(t *testing.T) {
   344  	testJSONMarshal(t, &RateLimits{}, "{}")
   345  
   346  	u := &RateLimits{
   347  		Core: &Rate{
   348  			Limit:     1,
   349  			Remaining: 1,
   350  			Reset:     Timestamp{referenceTime},
   351  		},
   352  		Search: &Rate{
   353  			Limit:     1,
   354  			Remaining: 1,
   355  			Reset:     Timestamp{referenceTime},
   356  		},
   357  		GraphQL: &Rate{
   358  			Limit:     1,
   359  			Remaining: 1,
   360  			Reset:     Timestamp{referenceTime},
   361  		},
   362  		IntegrationManifest: &Rate{
   363  			Limit:     1,
   364  			Remaining: 1,
   365  			Reset:     Timestamp{referenceTime},
   366  		},
   367  		SourceImport: &Rate{
   368  			Limit:     1,
   369  			Remaining: 1,
   370  			Reset:     Timestamp{referenceTime},
   371  		},
   372  		CodeScanningUpload: &Rate{
   373  			Limit:     1,
   374  			Remaining: 1,
   375  			Reset:     Timestamp{referenceTime},
   376  		},
   377  		ActionsRunnerRegistration: &Rate{
   378  			Limit:     1,
   379  			Remaining: 1,
   380  			Reset:     Timestamp{referenceTime},
   381  		},
   382  		SCIM: &Rate{
   383  			Limit:     1,
   384  			Remaining: 1,
   385  			Reset:     Timestamp{referenceTime},
   386  		},
   387  		DependencySnapshots: &Rate{
   388  			Limit:     1,
   389  			Remaining: 1,
   390  			Reset:     Timestamp{referenceTime},
   391  		},
   392  		CodeSearch: &Rate{
   393  			Limit:     1,
   394  			Remaining: 1,
   395  			Reset:     Timestamp{referenceTime},
   396  		},
   397  		AuditLog: &Rate{
   398  			Limit:     1,
   399  			Remaining: 1,
   400  			Reset:     Timestamp{referenceTime},
   401  		},
   402  	}
   403  
   404  	want := `{
   405  		"core": {
   406  			"limit": 1,
   407  			"remaining": 1,
   408  			"reset": ` + referenceTimeStr + `
   409  		},
   410  		"search": {
   411  			"limit": 1,
   412  			"remaining": 1,
   413  			"reset": ` + referenceTimeStr + `
   414  		},
   415  		"graphql": {
   416  			"limit": 1,
   417  			"remaining": 1,
   418  			"reset": ` + referenceTimeStr + `
   419  		},
   420  		"integration_manifest": {
   421  			"limit": 1,
   422  			"remaining": 1,
   423  			"reset": ` + referenceTimeStr + `
   424  		},
   425  		"source_import": {
   426  			"limit": 1,
   427  			"remaining": 1,
   428  			"reset": ` + referenceTimeStr + `
   429  		},
   430  		"code_scanning_upload": {
   431  			"limit": 1,
   432  			"remaining": 1,
   433  			"reset": ` + referenceTimeStr + `
   434  		},
   435  		"actions_runner_registration": {
   436  			"limit": 1,
   437  			"remaining": 1,
   438  			"reset": ` + referenceTimeStr + `
   439  		},
   440  		"scim": {
   441  			"limit": 1,
   442  			"remaining": 1,
   443  			"reset": ` + referenceTimeStr + `
   444  		},
   445  		"dependency_snapshots": {
   446  			"limit": 1,
   447  			"remaining": 1,
   448  			"reset": ` + referenceTimeStr + `
   449  		},
   450  		"code_search": {
   451  			"limit": 1,
   452  			"remaining": 1,
   453  			"reset": ` + referenceTimeStr + `
   454  		},
   455  		"audit_log": {
   456  			"limit": 1,
   457  			"remaining": 1,
   458  			"reset": ` + referenceTimeStr + `
   459  		}
   460  	}`
   461  
   462  	testJSONMarshal(t, u, want)
   463  }
   464  
   465  func TestRate_Marshal(t *testing.T) {
   466  	testJSONMarshal(t, &Rate{}, "{}")
   467  
   468  	u := &Rate{
   469  		Limit:     1,
   470  		Remaining: 1,
   471  		Reset:     Timestamp{referenceTime},
   472  	}
   473  
   474  	want := `{
   475  		"limit": 1,
   476  		"remaining": 1,
   477  		"reset": ` + referenceTimeStr + `
   478  	}`
   479  
   480  	testJSONMarshal(t, u, want)
   481  }