github.com/munnerz/test-infra@v0.0.0-20190108210205-ce3d181dc989/gubernator/github/periodic_sync_test.py (about)

     1  #!/usr/bin/env python
     2  
     3  # Copyright 2018 The Kubernetes Authors.
     4  #
     5  # Licensed under the Apache License, Version 2.0 (the "License");
     6  # you may not use this file except in compliance with the License.
     7  # You may obtain a copy of the License at
     8  #
     9  #     http://www.apache.org/licenses/LICENSE-2.0
    10  #
    11  # Unless required by applicable law or agreed to in writing, software
    12  # distributed under the License is distributed on an "AS IS" BASIS,
    13  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  # See the License for the specific language governing permissions and
    15  # limitations under the License.
    16  
    17  # pylint: disable=no-self-use
    18  
    19  import cPickle as pickle
    20  import json
    21  
    22  import webtest
    23  
    24  from google.appengine.ext import deferred
    25  from google.appengine.ext import testbed
    26  
    27  import main_test
    28  import models
    29  import periodic_sync
    30  import secrets
    31  
    32  app = webtest.TestApp(periodic_sync.app)
    33  
    34  TOKEN = 'gh_auth_secret'
    35  
    36  def pr_data(number):
    37      return {
    38          'number': number,
    39          'state': 'open',
    40          'user': {'login': 'a'},
    41          'assignees': [{'login': 'b'}],
    42          'title': 'some fix %d' % number,
    43          'head': {'sha': 'abcdef'},
    44      }
    45  
    46  class SyncTest(main_test.TestBase):
    47      def setUp(self):
    48          self.init_stubs()
    49          self.taskqueue = self.testbed.get_stub(testbed.TASKQUEUE_SERVICE_NAME)
    50          secrets.put('github_token', TOKEN, per_host=False)
    51          self.gh_data = {}
    52  
    53      def inject_pr(self, repo, number):
    54          models.GHIssueDigest.make(
    55              repo, number, True, True, [],
    56              {'author': 'someone', 'assignees': [], 'title': '#%d' % number},
    57              None).put()
    58  
    59      def get_deferred_funcs(self):
    60          out = []
    61          for task in self.taskqueue.get_filtered_tasks():
    62              func, args, _kwargs = pickle.loads(task.payload)
    63              out.append((func.__name__, args))
    64          return out
    65  
    66      def test_repo_dispatch(self):
    67          self.inject_pr('a/b', 3)
    68          self.inject_pr('a/b', 4)
    69          self.inject_pr('k/t', 90)
    70  
    71          app.get('/sync')
    72  
    73          self.assertEqual(self.get_deferred_funcs(),
    74              [('sync_repo', (TOKEN, 'a/b')),
    75               ('sync_repo', (TOKEN, 'k/t'))])
    76  
    77      def urlfetch_github_stub(self, url, _payload, method,
    78                               headers, _request, response, **_kwargs):
    79          assert method == 'GET'
    80          assert headers[0].key() == 'Authorization'
    81          assert headers[0].value() == 'token ' + TOKEN
    82          path = url[url.find('.com')+4:]
    83          content, response_headers = self.gh_data[path]
    84          response.set_content(json.dumps(content))
    85          response.set_statuscode(200)
    86          for k, v in response_headers.iteritems():
    87              header = response.add_header()
    88              header.set_key(k)
    89              header.set_value(v)
    90  
    91      def init_github_fake(self):
    92          # Theoretically, I should be able to pass this to init_urlfetch_stub.
    93          # Practically, that doesn't work for unknown reasons, and this is fine.
    94          uf = self.testbed.get_stub('urlfetch')
    95          uf._urlmatchers_to_fetch_functions.append(  # pylint: disable=protected-access
    96              (lambda u: u.startswith('https://api.github.com'), self.urlfetch_github_stub))
    97  
    98      def test_get_prs_from_github(self):
    99          self.init_github_fake()
   100  
   101          base_url = '/repos/a/b/pulls?state=open&per_page=100'
   102          def make_headers(page):
   103              frag = '<https://api.github.com%s' % base_url
   104              link = '%s&page=4>; rel="last"' % frag
   105              if page < 4:
   106                  link = '%s&page=%d>; rel="next", %s' % (frag, page + 1, link)
   107              if page > 1:
   108                  link = '%s&page=%d>; rel="prev", %s' % (frag, page - 1, link)
   109              print link
   110              return {'Link': link}
   111  
   112          prs = [pr_data(n) for n in range(400)]
   113          self.gh_data = {
   114              base_url:             (prs[:100], make_headers(1)),
   115              base_url + '&page=2': (prs[100:200], make_headers(2)),
   116              base_url + '&page=3': (prs[200:300], make_headers(3)),
   117              base_url + '&page=4': (prs[300:], make_headers(4)),
   118          }
   119  
   120          got_prs = periodic_sync.get_prs_from_github(TOKEN, 'a/b')
   121          got_pr_nos = [pr['number'] for pr in got_prs]
   122          expected_pr_nos = [pr['number'] for pr in prs]
   123  
   124          self.assertEqual(got_pr_nos, expected_pr_nos)
   125  
   126      def test_sync_repo(self):
   127          self.init_github_fake()
   128          self.gh_data = {
   129              '/repos/a/b/pulls?state=open&per_page=100':
   130                  ([pr_data(11), pr_data(12), pr_data(13)], {}),
   131          }
   132  
   133          # PRs <10 are closed
   134          # PRs >10 are open
   135          self.inject_pr('a/b', 1)
   136          self.inject_pr('a/b', 2)
   137          self.inject_pr('a/b', 3)
   138          self.inject_pr('a/b', 11)
   139          self.inject_pr('a/b', 12)
   140  
   141          periodic_sync.sync_repo(TOKEN, 'a/b')
   142  
   143          for task in self.taskqueue.get_filtered_tasks():
   144              deferred.run(task.payload)
   145  
   146          open_prs = models.GHIssueDigest.find_open_prs().fetch()
   147          open_prs = [pr.number for pr in open_prs]
   148  
   149          self.assertEqual(open_prs, [11, 12, 13])