k8s.io/test-infra@v0.0.0-20240520184403-27c6b4c223d8/kettle/make_json_test.py (about)

     1  #!/usr/bin/env python3
     2  
     3  # Copyright 2017 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  import io as StringIO
    18  import json
    19  import time
    20  import unittest
    21  
    22  from parameterized import parameterized
    23  
    24  import make_json
    25  import model
    26  
    27  
    28  class ValidateBuckets(unittest.TestCase):
    29      def test_buckets(self):
    30          prefixes = set()
    31          for name, options in sorted(make_json.BUCKETS.items()):
    32              if name == 'gs://kubernetes-jenkins/logs/':
    33                  continue  # only bucket without a prefix
    34              prefix = options.get('prefix', '')
    35              self.assertNotEqual(prefix, '', 'bucket %s must have a prefix' % name)
    36              self.assertNotIn(prefix, prefixes, "bucket %s prefix %r isn't unique" % (name, prefix))
    37              self.assertEqual(prefix[-1], ':', "bucket %s prefix should be %s:" % (name, prefix))
    38  
    39  
    40  class BuildObjectTests(unittest.TestCase):
    41      @parameterized.expand([
    42          (
    43              "Empty_Build",
    44              make_json.Build.__new__(make_json.Build),
    45              {},
    46          ),
    47          (
    48              "Base_Build",
    49              make_json.Build("gs://kubernetes-jenkins/pr-logs/path", []),
    50              {"path":"gs://kubernetes-jenkins/pr-logs/path",
    51               "test": [],
    52               "tests_run": 0,
    53               "tests_failed": 0,
    54               "job": "pr:pr-logs",
    55              },
    56          ),
    57          (
    58              "Tests_populate",
    59              make_json.Build(
    60                  "gs://kubernetes-jenkins/pr-logs/path",
    61                  [{'name': 'Test1', 'failed': True}],
    62              ),
    63              {"path":"gs://kubernetes-jenkins/pr-logs/path",
    64               "test": [{'name': 'Test1', 'failed': True}],
    65               "tests_run": 1,
    66               "tests_failed": 1,
    67               "job": "pr:pr-logs",
    68              },
    69          ),
    70      ])
    71      def test_as_dict(self, _, build, expected):
    72          self.assertEqual(build.as_dict(), expected)
    73  
    74      @parameterized.expand([
    75          (
    76              "No started",
    77              {},
    78              {},
    79          ),
    80          (
    81              "CI Decorated",
    82              {
    83                  "timestamp":1595284709,
    84                  "repos":{"kubernetes/kubernetes":"master"},
    85                  "repo-version":"5a529aa3a0dd3a050c5302329681e871ef6c162e",
    86                  "repo-commit":"5a529aa3a0dd3a050c5302329681e871ef6c162e",
    87              },
    88              {
    89                  "started": 1595284709,
    90                  "repo_commit":"5a529aa3a0dd3a050c5302329681e871ef6c162e",
    91                  "repos": '{"kubernetes/kubernetes": "master"}',
    92              },
    93          ),
    94          (
    95              "PR Decorated",
    96              {
    97                  "timestamp":1595277241,
    98                  "pull":"93264",
    99                  "repos":{"kubernetes/kubernetes":"master:5feab0"},
   100                  "repo-version":"30f64c5b1fc57a3beb1476f9beb29280166954d1",
   101                  "repo-commit":"30f64c5b1fc57a3beb1476f9beb29280166954d1",
   102              },
   103              {
   104                  "started": 1595277241,
   105                  "repo_commit":"30f64c5b1fc57a3beb1476f9beb29280166954d1",
   106                  "repos": '{"kubernetes/kubernetes": "master:5feab0"}',
   107              },
   108          ),
   109          (
   110              "PR Bootstrap",
   111              {
   112                  "node": "0790211c-cacb-11ea-a4b9-4a19d9b965b2",
   113                  "pull": "master:5a529",
   114                  "repo-version": "v1.20.0-alpha.0.261+06ea384605f172",
   115                  "timestamp": 1595278460,
   116                  "repos": {"k8s.io/kubernetes": "master:5a529", "k8s.io/release": "master"},
   117                  "version": "v1.20.0-alpha.0.261+06ea384605f172"
   118              },
   119              {
   120                  "started": 1595278460,
   121                  "repo_commit":"v1.20.0-alpha.0.261+06ea384605f172",
   122                  "repos": '{"k8s.io/kubernetes": "master:5a529", "k8s.io/release": "master"}',
   123                  "executor": "0790211c-cacb-11ea-a4b9-4a19d9b965b2",
   124              },
   125          ),
   126          (
   127              "CI Bootstrap",
   128              {
   129                  "timestamp":1595263104,
   130                  "node":"592473ae-caa7-11ea-b130-525df2b76a8d",
   131                  "repos":{
   132                      "k8s.io/kubernetes":"master",
   133                      "k8s.io/release":"master"
   134                  },
   135                  "repo-version":"v1.20.0-alpha.0.255+5feab0aa1e592a",
   136              },
   137              {
   138                  "started": 1595263104,
   139                  "repo_commit":"v1.20.0-alpha.0.255+5feab0aa1e592a",
   140                  "repos": '{"k8s.io/kubernetes": "master", "k8s.io/release": "master"}',
   141                  "executor": "592473ae-caa7-11ea-b130-525df2b76a8d",
   142              },
   143          ),
   144      ])
   145      def test_populate_start(self, _, started, updates):
   146          build = make_json.Build("gs://kubernetes-jenkins/pr-logs/path", [])
   147          attrs = {
   148              "path":"gs://kubernetes-jenkins/pr-logs/path",
   149              "test": [],
   150              "tests_run": 0,
   151              "tests_failed": 0,
   152              "job": "pr:pr-logs",
   153                  }
   154          attrs.update(updates)
   155          build.populate_start(started)
   156          self.assertEqual(build.as_dict(), attrs)
   157  
   158      @parameterized.expand([
   159          (
   160              "No finished",
   161              {},
   162              {},
   163          ),
   164          (
   165              "CI Decorated",
   166              {
   167                  "timestamp":1595286616,
   168                  "passed":True,
   169                  "result":"SUCCESS",
   170                  "revision":"master",
   171              },
   172              {
   173                  "finished": 1595286616,
   174                  "result": "SUCCESS",
   175                  "passed": True,
   176              },
   177          ),
   178          (
   179              "PR Decorated",
   180              {
   181                  "timestamp":1595279434,
   182                  "passed":True,
   183                  "result":"SUCCESS",
   184                  "revision":"5dd9241d43f256984358354d1fec468f274f9ac4"
   185              },
   186              {
   187                  "finished": 1595279434,
   188                  "result": "SUCCESS",
   189                  "passed": True,
   190              },
   191          ),
   192          (
   193              "PR Bootstrap",
   194              {
   195                  "timestamp": 1595282312,
   196                  "version": "v1.20.0-alpha.0.261+06ea384605f172",
   197                  "result": "SUCCESS",
   198                  "passed": True,
   199                  "job-version": "v1.20.0-alpha.0.261+06ea384605f172",
   200              },
   201              {
   202                  "finished": 1595282312,
   203                  "version": "v1.20.0-alpha.0.261+06ea384605f172",
   204                  "result": "SUCCESS",
   205                  "passed": True,
   206              },
   207          ),
   208          (
   209              "CI Bootstrap",
   210              {
   211                  "timestamp": 1595263185,
   212                  "version": "v1.20.0-alpha.0.255+5feab0aa1e592a",
   213                  "result": "SUCCESS",
   214                  "passed": True,
   215                  "job-version": "v1.20.0-alpha.0.255+5feab0aa1e592a",
   216              },
   217              {
   218                  "finished": 1595263185,
   219                  "version": "v1.20.0-alpha.0.255+5feab0aa1e592a",
   220                  "result": "SUCCESS",
   221                  "passed": True,
   222              },
   223          ),
   224      ])
   225      def test_populate_finish(self, _, finished, updates):
   226          build = make_json.Build("gs://kubernetes-jenkins/pr-logs/path", [])
   227          attrs = {"path":"gs://kubernetes-jenkins/pr-logs/path",
   228                   "test": [],
   229                   "tests_run": 0,
   230                   "tests_failed": 0,
   231                   "job": "pr:pr-logs",
   232                  }
   233          build.populate_finish(finished)
   234          attrs.update(updates)
   235          self.assertEqual(build.as_dict(), attrs)
   236  
   237  
   238  class GenerateBuilds(unittest.TestCase):
   239      @parameterized.expand([
   240          (
   241              "Basic_pass",
   242              "gs://kubernetes-jenkins/pr-logs/path",
   243              [{'name': "Test1", 'failed': False}],
   244              None,
   245              None,
   246              None,
   247              None,
   248              {
   249                  'job': 'pr:pr-logs',
   250                  'path': 'gs://kubernetes-jenkins/pr-logs/path',
   251                  'test': [{'name': 'Test1', 'failed': False}],
   252                  'tests_run': 1,
   253                  'tests_failed':0,
   254              },
   255          ),
   256          (
   257              "Basic_fail",
   258              "gs://kubernetes-jenkins/pr-logs/path",
   259              [{'name': "Test1", 'failed': True}],
   260              None,
   261              None,
   262              None,
   263              None,
   264              {
   265                  'job': 'pr:pr-logs',
   266                  'path': 'gs://kubernetes-jenkins/pr-logs/path',
   267                  'test': [{'name': 'Test1', 'failed': True}],
   268                  'tests_run': 1,
   269                  'tests_failed':1,
   270              },
   271          ),
   272          (
   273              "Ci_decorated",
   274              "gs://kubernetes-jenkins/pr-logs/path",
   275              [{'name': "Test1", 'failed': True}],
   276              {
   277                  "timestamp":1595284709,
   278                  "repos":{"kubernetes/kubernetes":"master"},
   279                  "repo-version":"5a529aa3a0dd3a050c5302329681e871ef6c162e",
   280                  "repo-commit":"5a529aa3a0dd3a050c5302329681e871ef6c162e",
   281              },
   282              {
   283                  "timestamp":1595286616,
   284                  "passed":True,
   285                  "result":"SUCCESS",
   286                  "revision":"master",
   287              },
   288              None,
   289              None,
   290              {
   291                  'job': 'pr:pr-logs',
   292                  'path': 'gs://kubernetes-jenkins/pr-logs/path',
   293                  'test': [{'name': 'Test1', 'failed': True}],
   294                  'passed': True,
   295                  'result': 'SUCCESS',
   296                  'elapsed': 1907,
   297                  'tests_run': 1,
   298                  'tests_failed':1,
   299                  'started': 1595284709,
   300                  'finished': 1595286616,
   301                  'repo_commit': '5a529aa3a0dd3a050c5302329681e871ef6c162e',
   302                  'repos': '{"kubernetes/kubernetes": "master"}',
   303              },
   304          ),
   305          (
   306              "Pr_decorated",
   307              "gs://kubernetes-jenkins/pr-logs/path",
   308              [{'name': "Test1", 'failed': True}],
   309              {
   310                  "timestamp":1595277241,
   311                  "pull":"93264",
   312                  "repos":{"kubernetes/kubernetes":"master:5feab0"},
   313                  "repo-version":"30f64c5b1fc57a3beb1476f9beb29280166954d1",
   314                  "repo-commit":"30f64c5b1fc57a3beb1476f9beb29280166954d1",
   315              },
   316              {
   317                  "timestamp":1595279434,
   318                  "passed":True,
   319                  "result":"SUCCESS",
   320                  "revision":"5dd9241d43f256984358354d1fec468f274f9ac4"
   321              },
   322              None,
   323              None,
   324              {
   325                  'job': 'pr:pr-logs',
   326                  'path': 'gs://kubernetes-jenkins/pr-logs/path',
   327                  'test': [{'name': 'Test1', 'failed': True}],
   328                  'passed': True,
   329                  'result': 'SUCCESS',
   330                  'elapsed': 2193,
   331                  'tests_run': 1,
   332                  'tests_failed':1,
   333                  'started': 1595277241,
   334                  'finished': 1595279434,
   335                  'repo_commit': '30f64c5b1fc57a3beb1476f9beb29280166954d1',
   336                  'repos': '{"kubernetes/kubernetes": "master:5feab0"}',
   337              },
   338          ),
   339          (
   340              "Pr_bootstrap",
   341              "gs://kubernetes-jenkins/pr-logs/path",
   342              [{'name': "Test1", 'failed': True}],
   343              {
   344                  "node": "0790211c-cacb-11ea-a4b9-4a19d9b965b2",
   345                  "pull": "master:5a529",
   346                  "repo-version": "v1.20.0-alpha.0.261+06ea384605f172",
   347                  "timestamp": 1595278460,
   348                  "repos": {
   349                      "k8s.io/kubernetes": "master:5a529",
   350                      "k8s.io/release": "master"
   351                  },
   352                  "version": "v1.20.0-alpha.0.261+06ea384605f172"
   353              },
   354              {
   355                  "timestamp": 1595282312,
   356                  "version": "v1.20.0-alpha.0.261+06ea384605f172",
   357                  "result": "SUCCESS",
   358                  "passed": True,
   359                  "job-version": "v1.20.0-alpha.0.261+06ea384605f172",
   360              },
   361              {
   362                  "node_os_image": "cos-81-12871-59-0",
   363                  "infra-commit": "2a9a0f868",
   364                  "repo": "k8s.io/kubernetes",
   365                  "master_os_image": "cos-81-12871-59-0",
   366              },
   367              {
   368                  "k8s.io/kubernetes": "master:5a529",
   369                  "k8s.io/release": "master"
   370              },
   371              {
   372                  'job': 'pr:pr-logs',
   373                  'executor': '0790211c-cacb-11ea-a4b9-4a19d9b965b2',
   374                  'path': 'gs://kubernetes-jenkins/pr-logs/path',
   375                  'test': [{'name': 'Test1', 'failed': True}],
   376                  'passed': True,
   377                  'result': 'SUCCESS',
   378                  'elapsed': 3852,
   379                  'tests_run': 1,
   380                  'tests_failed':1,
   381                  'started': 1595278460,
   382                  'finished': 1595282312,
   383                  'version': 'v1.20.0-alpha.0.261+06ea384605f172',
   384                  'repo_commit': 'v1.20.0-alpha.0.261+06ea384605f172',
   385                  'repos': '{"k8s.io/kubernetes": "master:5a529", "k8s.io/release": "master"}',
   386                  'metadata': {
   387                      "node_os_image": "cos-81-12871-59-0",
   388                      "infra-commit": "2a9a0f868",
   389                      "repo": "k8s.io/kubernetes",
   390                      "master_os_image": "cos-81-12871-59-0",
   391                  },
   392              },
   393          ),
   394          (
   395              "Ci_bootstrap",
   396              "gs://kubernetes-jenkins/pr-logs/path",
   397              [{'name': "Test1", 'failed': True}],
   398              {
   399                  "timestamp":1595263104,
   400                  "node":"592473ae-caa7-11ea-b130-525df2b76a8d",
   401                  "repos":{
   402                      "k8s.io/kubernetes":"master",
   403                      "k8s.io/release":"master"
   404                  },
   405                  "repo-version":"v1.20.0-alpha.0.255+5feab0aa1e592a",
   406              },
   407              {
   408                  "timestamp": 1595263185,
   409                  "version": "v1.20.0-alpha.0.255+5feab0aa1e592a",
   410                  "result": "SUCCESS",
   411                  "passed": True,
   412                  "job-version": "v1.20.0-alpha.0.255+5feab0aa1e592a",
   413              },
   414              {
   415                  "repo": "k8s.io/kubernetes",
   416                  "repos": {
   417                      "k8s.io/kubernetes": "master",
   418                      "k8s.io/release": "master"
   419                  },
   420                  "infra-commit": "5f39b744b",
   421                  "repo-commit": "5feab0aa1e592ab413b461bc3ad08a6b74a427b4"
   422              },
   423              {
   424                  "k8s.io/kubernetes":"master",
   425                  "k8s.io/release":"master"
   426              },
   427              {
   428                  'job': 'pr:pr-logs',
   429                  'executor': '592473ae-caa7-11ea-b130-525df2b76a8d',
   430                  'path': 'gs://kubernetes-jenkins/pr-logs/path',
   431                  'test': [{'name': 'Test1', 'failed': True}],
   432                  'passed': True,
   433                  'result': 'SUCCESS',
   434                  'elapsed': 81,
   435                  'tests_run': 1,
   436                  'tests_failed':1,
   437                  'started': 1595263104,
   438                  'finished': 1595263185,
   439                  'version': 'v1.20.0-alpha.0.255+5feab0aa1e592a',
   440                  'repo_commit': 'v1.20.0-alpha.0.255+5feab0aa1e592a',
   441                  'repos': '{"k8s.io/kubernetes": "master", "k8s.io/release": "master"}',
   442                  'metadata': {
   443                      "repo": "k8s.io/kubernetes",
   444                      "repos": {
   445                          "k8s.io/kubernetes": "master",
   446                          "k8s.io/release": "master"
   447                      },
   448                      "infra-commit": "5f39b744b",
   449                      "repo-commit": "5feab0aa1e592ab413b461bc3ad08a6b74a427b4"
   450                  },
   451              },
   452          ),
   453          (
   454              "Started_no_meta_repo",
   455              "gs://kubernetes-jenkins/pr-logs/path",
   456              [{'name': "Test1", 'failed': False}],
   457              {
   458                  "timestamp":1595263104,
   459                  "node":"592473ae-caa7-11ea-b130-525df2b76a8d",
   460                  "repos":{
   461                      "k8s.io/kubernetes":"master",
   462                      "k8s.io/release":"master"
   463                  },
   464                  "repo-version":"v1.20.0-alpha.0.255+5feab0aa1e592a",
   465              },
   466              None,
   467              None,
   468              None,
   469              {
   470                  'job': 'pr:pr-logs',
   471                  'executor': '592473ae-caa7-11ea-b130-525df2b76a8d',
   472                  'path': 'gs://kubernetes-jenkins/pr-logs/path',
   473                  'test': [{'name': 'Test1', 'failed': False}],
   474                  'tests_run': 1,
   475                  'tests_failed':0,
   476                  'repo_commit': 'v1.20.0-alpha.0.255+5feab0aa1e592a',
   477                  'repos': '{"k8s.io/kubernetes": "master", "k8s.io/release": "master"}',
   478                  'started': 1595263104,
   479              },
   480          ),
   481      ])
   482      def test_gen_build(self, _, path, tests, started, finished, metadata, repos, expected):
   483          self.maxDiff = None
   484          build = make_json.Build.generate(path, tests, started, finished, metadata, repos)
   485          build_dict = build.as_dict()
   486          self.assertEqual(build_dict, expected)
   487  
   488  
   489  class MakeJsonTest(unittest.TestCase):
   490      def setUp(self):
   491          self.db = model.Database(':memory:')
   492  
   493      def test_path_to_job_and_number(self):
   494          def expect(path, job, number):
   495              build = make_json.Build(path, [])
   496              self.assertEqual((build.job, build.number), (job, number))
   497  
   498          expect('gs://kubernetes-jenkins/logs/some-build/123', 'some-build', 123)
   499          expect('gs://kubernetes-jenkins/logs/some-build/123asdf', 'some-build', None)
   500          expect('gs://kubernetes-jenkins/pr-logs/123/e2e-node/456', 'pr:e2e-node', 456)
   501  
   502          with self.assertRaises(ValueError):
   503              expect('gs://unknown-bucket/foo/123', None, None)
   504              expect('gs://unknown-bucket/foo/123/', None, None)
   505  
   506      def test_row_for_build(self):
   507          def expect(path, start, finish, results, **kwargs):
   508              expected = {
   509                  'path': path,
   510                  'test': [],
   511                  'tests_failed': 0,
   512                  'tests_run': 0,
   513              }
   514              if finish:
   515                  expected['passed'] = kwargs.get('result') == 'SUCCESS'
   516              expected.update(kwargs)
   517              row = make_json.row_for_build(path, start, finish, results)
   518              self.assertEqual(row, expected)
   519  
   520          path = 'gs://kubernetes-jenkins/logs/J/123'
   521          expect(path, None, None, [], job='J', number=123)
   522          expect(path, None, None, [], job='J', number=123)
   523          expect(path,
   524                 {'timestamp': 10, 'node': 'agent-34'},
   525                 {'timestamp': 15, 'result': 'SUCCESS', 'version': 'v1.2.3'},
   526                 [],
   527                 job='J', number=123,
   528                 started=10, finished=15, elapsed=5,
   529                 version='v1.2.3', result='SUCCESS', executor='agent-34',
   530                )
   531          expect(path,
   532                 {'timestamp': 10},
   533                 {'timestamp': 15, 'passed': True},
   534                 [],
   535                 job='J', number=123,
   536                 started=10, finished=15, elapsed=5,
   537                 result='SUCCESS',
   538                )
   539          expect(path, None,
   540                 {'timestamp': 15, 'result': 'FAILURE',
   541                  'metadata': {'repo': 'ignored', 'pull': 'asdf'}}, [],
   542                 result='FAILURE', job='J', number=123, finished=15,
   543                 metadata=[{'key': 'pull', 'value': 'asdf'}, {'key': 'repo', 'value': 'ignored'}])
   544          expect(path, None, None, ['''
   545                     <testsuite>
   546                      <properties><property name="test" value="don't crash!"></property></properties>
   547                      <testcase name="t1" time="1.0"><failure>stacktrace</failure></testcase>
   548                      <testcase name="t2" time="2.0"></testcase>
   549                      <testcase name="t2#1" time="2.0"></testcase>
   550                     </testsuite>'''],
   551                 job='J', number=123,
   552                 tests_run=2, tests_failed=1,
   553                 test=[{'name': 't1', 'time': 1.0, 'failed': True, 'failure_text': 'stacktrace'},
   554                       {'name': 't2', 'time': 2.0}])
   555  
   556      def test_main(self):
   557          now = time.time()
   558          last_month = now - (60 * 60 * 24 * 30)
   559          junits = ['<testsuite><testcase name="t1" time="3.0"></testcase></testsuite>']
   560  
   561          def add_build(path, start, finish, result, junits):
   562              path = 'gs://kubernetes-jenkins/logs/%s' % path
   563              self.db.insert_build(
   564                  path, {'timestamp': start}, {'timestamp': finish, 'result': result})
   565              # fake build rowid doesn't matter here
   566              self.db.insert_build_junits(
   567                  hash(path),
   568                  {'%s/artifacts/junit_%d.xml' % (path, n): junit for n, junit in enumerate(junits)})
   569              self.db.commit()
   570  
   571          def expect(args, needles, negneedles, expected_ret=None):
   572              buf = StringIO.StringIO()
   573              opts = make_json.parse_args(args)
   574              ret = make_json.main(self.db, opts, buf)
   575              result = buf.getvalue()
   576  
   577              if expected_ret is not None:
   578                  self.assertEqual(ret, expected_ret)
   579  
   580              # validate that output is newline-delimited JSON
   581              for line in result.split('\n'):
   582                  if line.strip():
   583                      json.loads(line)
   584  
   585              # test for expected patterns / expected missing patterns
   586              for needle in needles:
   587                  self.assertIn(needle, result)
   588              for needle in negneedles:
   589                  # Only match negative needles in the middle of a word, to avoid
   590                  # failures on timestamps that happen to contain a short number.
   591                  self.assertNotRegexpMatches(result, r'\b%s\b' % needle) # pylint: disable=deprecated-method
   592  
   593          add_build('some-job/123', last_month, last_month + 10, 'SUCCESS', junits)
   594          add_build('some-job/456', now - 10, now, 'FAILURE', junits)
   595  
   596          expect([], ['123', '456', 'SUCCESS', 'FAILURE'], [])  # everything
   597          expect([], [], ['123', '456', 'SUCCESS', 'FAILURE'])  # nothing
   598  
   599          expect(['--days=1'], ['456'], [])  # recent
   600          expect(['--days', '1'], [], ['456'])  # nothing (already emitted)
   601  
   602          add_build('some-job/457', now + 1, now + 11, 'SUCCESS', junits)
   603          expect(['--days=1'], ['457'], ['456'])  # latest (day)
   604          expect([], ['457'], ['456'])         # latest (all)
   605  
   606          expect(['--days=1', '--reset-emitted'], ['456', '457'], [])  # both (reset)
   607          expect([], [], ['123', '456', '457'])                     # reset only works for given day
   608  
   609          # verify that direct paths work
   610          expect(['gs://kubernetes-jenkins/logs/some-job/123'], ['123'], [])
   611          expect(['gs://kubernetes-jenkins/logs/some-job/123'], ['123'], [])
   612  
   613          # verify that assert_oldest works
   614          expect(['--days=30'], ['123', '456'], [])
   615          expect(['--days=30', '--assert-oldest=60'], [], [], 0)
   616          expect(['--days=30', '--assert-oldest=25'], [], [], 1)
   617  
   618  
   619  class ParseJsonTest(unittest.TestCase):
   620      @parameterized.expand([
   621          ('Green Path',
   622           'kettle/testdata/standard.xml',
   623           [{'name': 'TearDown Previous', 'time': 2.065e-05},
   624            {'name': 'Up', 'time': 6.342e-06},
   625            {'name': 'test setup', 'time': 5.298e-06},
   626            {'failed': True,
   627             'failure_text': 'error during go run',
   628             'name': 'Node Tests',
   629             'time': 654.279097299},
   630            {'name': 'DumpClusterLogs', 'time': 5.399023835},
   631            {'name': 'TearDown', 'time': 1.21e-05},
   632            {'name': 'Deferred TearDown', 'time': 2.17e-07},
   633            {'name': 'Timeout', 'time': 3900.0}],
   634          ),
   635          ('No Suite Name',
   636           'kettle/testdata/junit_no_suite_name.xml',
   637           [{'failed': True,
   638             'failure_text': 'simple_test.go:186: Running tests in file plumbing',
   639             'name': '<unspecified> TestSimpleFile',
   640             'time': 0.0},
   641            {'name': '<unspecified> TestSimpleFile/plumbing/min/min_program', 'time': 0.0},
   642            {'name': '<unspecified> TestSimpleFile/plumbing/eval_results/error_result',
   643             'time': 0.0}],
   644          ),
   645          ('Failure as Message',
   646           'kettle/testdata/failure_message.xml',
   647           [{'failed': True,
   648             'failure_text': 'simple_test.go:186: Running tests in file plumbing',
   649             'name': '<unspecified> TestSimpleFile',
   650             'time': 0.0}],
   651          ),
   652          ('Failure as Text',
   653           'kettle/testdata/failure_text.xml',
   654           [{'failed': True,
   655             'failure_text': 'simple_test.go:186: Running tests in file plumbing',
   656             'name': '<unspecified> TestSimpleFile',
   657             'time': 0.0}],
   658          ),
   659          ('Malformed XML',
   660           'kettle/testdata/malformed.xml',
   661           [],
   662          ),
   663          ('Malformed Testcase',
   664           'kettle/testdata/malformed_no_testcase_name.xml',
   665           [{'name': 'TearDown Previous', 'time': 2.065e-05},
   666            {'name': 'Up', 'time': 6.342e-06},
   667            {'name': 'test setup', 'time': 5.298e-06},
   668            {'failed': True,
   669             'failure_text': 'error during go run',
   670             'name': 'Node Tests',
   671             'time': 654.279097299},
   672            {'name': '<unspecified>', 'time': 5.399023835},
   673            {'name': '<unspecified>', 'time': 1.21e-05},
   674            {'name': 'Deferred TearDown', 'time': 2.17e-07},
   675            {'name': 'Timeout', 'time': 3900.0}],
   676          )
   677      ])
   678      def test_parse_junit(self, _, path, expected):
   679          self.maxDiff = None
   680          datasource = open(path)
   681          failures = make_json.parse_junit(datasource.read())
   682          self.assertEqual(list(failures), expected)
   683  
   684  if __name__ == '__main__':
   685      unittest.main()