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