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