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