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