blob: 597f13d069fcd32f4e557d5ad776720787064f07 [file] [log] [blame]
# Copyright 2020 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import collections
from mock import patch
import os
import unittest
import shard_util
DEBUG_APP_OTOOL_OUTPUT = '\n'.join([
'Meta Class', 'name 0x1064b8438 CacheTestCase',
'baseMethods 0x1068586d8 (struct method_list_t *)',
'imp 0x1075e6887 -[CacheTestCase testA]', 'types 0x1064cc3e1',
'imp 0x1075e6887 -[CacheTestCase testB]',
'imp 0x1075e6887 -[CacheTestCase testc]', 'name 0x1064b8438 TabUITestCase',
'baseMethods 0x1068586d8 (struct method_list_t *)',
'imp 0x1075e6887 -[TabUITestCase testD]', 'types 0x1064cc3e1 v16@0:8',
'imp 0x1075e6887 -[TabUITestCase testE]',
'name 0x1064b8438 KeyboardTestCase',
'imp 0x1075e6887 -[KeyboardTestCase testF]',
'name 0x1064b8438 PasswordsTestCase',
'imp 0x1075e6887 -[PasswordsTestCase testG]',
'name 0x1064b8438 ToolBarTestCase',
'imp 0x1075e6887 -[ToolBarTestCase testH]',
'imp 0x1075e6887 -[ToolBarTestCase DISABLED_testI]',
'imp 0x1075e6887 -[ToolBarTestCase FLAKY_testJ]', 'version 0'
])
# Debug app otool output format in Xcode 11.4 toolchain.
DEBUG_APP_OTOOL_OUTPUT_114 = '\n'.join([
'Meta Class', 'name 0x1064b8438 CacheTestCase',
'baseMethods 0x1068586d8 (struct method_list_t *)',
' imp 0x1075e6887 -[CacheTestCase testA]', ' types 0x1064cc3e1',
' imp 0x1075e6887 -[CacheTestCase testB]',
' imp 0x1075e6887 -[CacheTestCase testc]',
' name 0x1064b8438 TabUITestCase',
'baseMethods 0x1068586d8 (struct method_list_t *)',
' imp 0x1075e6887 -[TabUITestCase testD]',
' types 0x1064cc3e1 v16@0:8',
' imp 0x1075e6887 -[TabUITestCase testE]',
' name 0x1064b8438 KeyboardTestCase',
' imp 0x1075e6887 -[KeyboardTestCase testF]',
' name 0x1064b8438 PasswordsTestCase',
' imp 0x1075e6887 -[PasswordsTestCase testG]',
' name 0x1064b8438 ToolBarTestCase',
' imp 0x1075e6887 -[ToolBarTestCase testH]',
' imp 0x1075e6887 -[ToolBarTestCase DISABLED_testI]',
' imp 0x1075e6887 -[ToolBarTestCase FLAKY_testJ]', 'version 0'
])
RELEASE_APP_OTOOL_OUTPUT = '\n'.join([
'Meta Class', 'name 0x1064b8438 CacheTestCase',
'baseMethods 0x1068586d8 (struct method_list_t *)',
'name 0x1075e6887 testA', 'types 0x1064cc3e1', 'name 0x1075e6887 testB',
'name 0x1075e6887 testc', 'baseProtocols 0x0', 'Meta Class',
'name 0x1064b8438 TabUITestCase',
'baseMethods 0x1068586d8 (struct method_list_t *)',
'name 0x1064b8438 KeyboardTest', 'name 0x1075e6887 testD',
'types 0x1064cc3e1 v16@0:8', 'name 0x1075e6887 testE',
'name 0x1075e6887 testF', 'baseProtocols 0x0',
'name 0x1064b8438 ChromeTestCase', 'name 0x1064b8438 setUp',
'baseProtocols 0x0', 'name 0x1064b8438 ToolBarTestCase',
'name 0x1075e6887 testG', 'name 0x1075e6887 testH',
'name 0x1075e6887 DISABLED_testI', 'name 0x1075e6887 FLAKY_testJ',
'baseProtocols 0x0', 'version 0'
])
# Release app otool output format in Xcode 11.4 toolchain.
RELEASE_APP_OTOOL_OUTPUT_114 = '\n'.join([
'Meta Class', 'name 0x1064b8438 CacheTestCase',
'baseMethods 0x1068586d8 (struct method_list_t *)',
' name 0x1075e6887 testA', ' types 0x1064cc3e1',
' name 0x1075e6887 testB', ' name 0x1075e6887 testc',
'baseProtocols 0x0', 'Meta Class', ' name 0x1064b8438 TabUITestCase',
'baseMethods 0x1068586d8 (struct method_list_t *)',
' name 0x1064b8438 KeyboardTest', ' name 0x1075e6887 testD',
' types 0x1064cc3e1 v16@0:8', ' name 0x1075e6887 testE',
' name 0x1075e6887 testF', 'baseProtocols 0x0',
' name 0x1064b8438 ChromeTestCase', ' name 0x1064b8438 setUp',
'baseProtocols 0x0', ' name 0x1064b8438 ToolBarTestCase',
' name 0x1075e6887 testG', ' name 0x1075e6887 testH',
' name 0x1075e6893 DISABLED_testI',
' name 0x1075e723f FLAKY_testJ', 'baseProtocols 0x0', 'version 0'
])
class TestShardUtil(unittest.TestCase):
"""Test cases for shard_util.py"""
@patch('shard_util.os.path.abspath')
def test_determine_path_non_eg2(self, mock_abspath):
mock_abspath.return_value = '/b/s/w/ir/ios/build/bots/scripts/share_util.py'
app = 'some_ios_test.app'
actual_path = shard_util.determine_app_path(app)
expected_path = os.path.join('/b/s/w/ir', 'out/Debug', app, 'some_ios_test')
self.assertEqual(actual_path, expected_path)
@patch('shard_util.os.path.abspath')
def test_determine_path_eg2(self, mock_abspath):
mock_abspath.return_value = '/b/s/w/ir/ios/build/bots/scripts/share_util.py'
app = 'some_ios_test-Runner.app'
host = 'some_host.app'
actual_path = shard_util.determine_app_path(app, host)
expected_path = os.path.join('/b/s/w/ir', 'out/Debug', app, 'PlugIns',
'some_ios_test.xctest', 'some_ios_test')
self.assertEqual(actual_path, expected_path)
@patch('shard_util.os.path.abspath')
def test_determine_path_eg2_release(self, mock_abspath):
mock_abspath.return_value = '/b/s/w/ir/ios/build/bots/scripts/share_util.py'
app = 'some_ios_test-Runner.app'
host = 'some_host.app'
actual_path = shard_util.determine_app_path(app, host, True)
expected_path = os.path.join('/b/s/w/ir', 'out/Release', app, 'PlugIns',
'some_ios_test.xctest', 'some_ios_test')
self.assertEqual(actual_path, expected_path)
def test_fetch_test_names_debug(self):
"""Ensures that the debug output is formatted correctly"""
resp = shard_util.fetch_test_names_for_debug(DEBUG_APP_OTOOL_OUTPUT)
self.assertEqual(len(resp), 10)
expected_test_names = [
('CacheTestCase', 'testA'),
('CacheTestCase', 'testB'),
('CacheTestCase', 'testc'),
('TabUITestCase', 'testD'),
('TabUITestCase', 'testE'),
('KeyboardTestCase', 'testF'),
('PasswordsTestCase', 'testG'),
('ToolBarTestCase', 'testH'),
('ToolBarTestCase', 'DISABLED_testI'),
('ToolBarTestCase', 'FLAKY_testJ'),
]
for test_name in expected_test_names:
self.assertTrue(test_name in resp)
test_cases = map(lambda (test_case, test_method): test_case, resp)
# ({'CacheTestCase': 3, 'TabUITestCase': 2, 'PasswordsTestCase': 1,
# 'KeyboardTestCase': 1, 'ToolBarTestCase': 3})
counts = collections.Counter(test_cases).most_common()
name, _ = counts[0]
self.assertEqual(name, 'ToolBarTestCase')
def test_fetch_test_counts_release(self):
"""Ensures that the release output is formatted correctly"""
resp = shard_util.fetch_test_names_for_release(RELEASE_APP_OTOOL_OUTPUT)
self.assertEqual(len(resp), 10)
expected_test_names = [
('CacheTestCase', 'testA'),
('CacheTestCase', 'testB'),
('CacheTestCase', 'testc'),
('KeyboardTest', 'testD'),
('KeyboardTest', 'testE'),
('KeyboardTest', 'testF'),
('ToolBarTestCase', 'testG'),
('ToolBarTestCase', 'testH'),
('ToolBarTestCase', 'DISABLED_testI'),
('ToolBarTestCase', 'FLAKY_testJ'),
]
for test_name in expected_test_names:
self.assertTrue(test_name in resp)
test_cases = map(lambda (test_case, test_method): test_case, resp)
# ({'KeyboardTest': 3, 'CacheTestCase': 3,
# 'ToolBarTestCase': 4})
counts = collections.Counter(test_cases).most_common()
name, _ = counts[0]
self.assertEqual(name, 'ToolBarTestCase')
def test_fetch_test_names_debug_114(self):
"""Test the debug output from otool in Xcode 11.4"""
resp = shard_util.fetch_test_names_for_debug(DEBUG_APP_OTOOL_OUTPUT_114)
self.assertEqual(len(resp), 10)
expected_test_names = [
('CacheTestCase', 'testA'),
('CacheTestCase', 'testB'),
('CacheTestCase', 'testc'),
('TabUITestCase', 'testD'),
('TabUITestCase', 'testE'),
('KeyboardTestCase', 'testF'),
('PasswordsTestCase', 'testG'),
('ToolBarTestCase', 'testH'),
('ToolBarTestCase', 'DISABLED_testI'),
('ToolBarTestCase', 'FLAKY_testJ'),
]
for test_name in expected_test_names:
self.assertTrue(test_name in resp)
test_cases = map(lambda (test_case, test_method): test_case, resp)
# ({'CacheTestCase': 3, 'TabUITestCase': 2, 'PasswordsTestCase': 1,
# 'KeyboardTestCase': 1, 'ToolBarTestCase': 3})
counts = collections.Counter(test_cases).most_common()
name, _ = counts[0]
self.assertEqual(name, 'ToolBarTestCase')
def test_fetch_test_counts_release_114(self):
"""Test the release output from otool in Xcode 11.4"""
resp = shard_util.fetch_test_names_for_release(RELEASE_APP_OTOOL_OUTPUT_114)
self.assertEqual(len(resp), 10)
expected_test_names = [
('CacheTestCase', 'testA'),
('CacheTestCase', 'testB'),
('CacheTestCase', 'testc'),
('KeyboardTest', 'testD'),
('KeyboardTest', 'testE'),
('KeyboardTest', 'testF'),
('ToolBarTestCase', 'testG'),
('ToolBarTestCase', 'testH'),
('ToolBarTestCase', 'DISABLED_testI'),
('ToolBarTestCase', 'FLAKY_testJ'),
]
for test_name in expected_test_names:
self.assertTrue(test_name in resp)
test_cases = map(lambda (test_case, test_method): test_case, resp)
# ({'KeyboardTest': 3, 'CacheTestCase': 3,
# 'ToolBarTestCase': 4})
counts = collections.Counter(test_cases).most_common()
name, _ = counts[0]
self.assertEqual(name, 'ToolBarTestCase')
def test_balance_into_sublists_debug(self):
"""Ensure the balancing algorithm works"""
resp = shard_util.fetch_test_names_for_debug(DEBUG_APP_OTOOL_OUTPUT)
test_cases = map(lambda (test_case, test_method): test_case, resp)
test_counts = collections.Counter(test_cases)
sublists_1 = shard_util.balance_into_sublists(test_counts, 1)
self.assertEqual(len(sublists_1), 1)
self.assertEqual(len(sublists_1[0]), 5)
sublists_3 = shard_util.balance_into_sublists(test_counts, 3)
self.assertEqual(len(sublists_3), 3)
# CacheTestCase has 3,
# TabUITestCase has 2, ToolBarTestCase has 4
# PasswordsTestCase has 1, KeyboardTestCase has 1
# They will be balanced into:
# [[ToolBarTestCase], [CacheTestCase, PasswordsTestCase],
# [TabUITestCase, KeyboardTestCase]]
self.assertEqual(
sorted([len(sublists_3[0]),
len(sublists_3[1]),
len(sublists_3[2])]), [1, 2, 2])
def test_balance_into_sublists_release(self):
"""Ensure the balancing algorithm works"""
resp = shard_util.fetch_test_names_for_release(RELEASE_APP_OTOOL_OUTPUT)
test_cases = map(lambda (test_case, test_method): test_case, resp)
test_counts = collections.Counter(test_cases)
sublists_3 = shard_util.balance_into_sublists(test_counts, 3)
self.assertEqual(len(sublists_3), 3)
# KeyboardTest has 3
# CacheTestCase has 3
# ToolbarTest Case has 4
# They will be balanced as one in each shard.
self.assertEqual(len(sublists_3[0]), 1)
self.assertEqual(len(sublists_3[1]), 1)
self.assertEqual(len(sublists_3[2]), 1)
if __name__ == '__main__':
unittest.main()