1# Copyright 2015 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import unittest 6 7import webapp2 8import webtest 9 10from google.appengine.api import users 11 12from dashboard import edit_anomaly_configs 13from dashboard import edit_config_handler 14from dashboard import list_tests 15from dashboard import put_entities_task 16from dashboard import testing_common 17from dashboard import xsrf 18from dashboard.models import anomaly_config 19from dashboard.models import graph_data 20 21 22class EditAnomalyConfigsTest(testing_common.TestCase): 23 24 # This test case tests post requests to /edit_anomaly_configs. 25 # Each post request is either a request to add an entity or to edit one. 26 27 def setUp(self): 28 super(EditAnomalyConfigsTest, self).setUp() 29 app = webapp2.WSGIApplication( 30 [ 31 ('/edit_anomaly_configs', 32 edit_anomaly_configs.EditAnomalyConfigsHandler), 33 ('/put_entities_task', put_entities_task.PutEntitiesTaskHandler), 34 ]) 35 self.testapp = webtest.TestApp(app) 36 37 def tearDown(self): 38 super(EditAnomalyConfigsTest, self).tearDown() 39 self.UnsetCurrentUser() 40 41 def testAdd(self): 42 """Tests changing the config property of an existing AnomalyConfig.""" 43 self.SetCurrentUser('qyearsley@chromium.org', is_admin=True) 44 45 self.testapp.post('/edit_anomaly_configs', { 46 'add-edit': 'add', 47 'add-name': 'New Config', 48 'config': '{"foo": 10}', 49 'patterns': 'M/b/ts/*\nM/b/ts/*/*\n', 50 'xsrf_token': xsrf.GenerateToken(users.get_current_user()), 51 }) 52 53 anomaly_configs = anomaly_config.AnomalyConfig.query().fetch() 54 self.assertEqual(len(anomaly_configs), 1) 55 config = anomaly_configs[0] 56 self.assertEqual('New Config', config.key.string_id()) 57 self.assertEqual({'foo': 10}, config.config) 58 self.assertEqual(['M/b/ts/*', 'M/b/ts/*/*'], config.patterns) 59 60 def testEdit(self): 61 """Tests changing the config property of an existing AnomalyConfig.""" 62 self.SetCurrentUser('sullivan@chromium.org', is_admin=True) 63 anomaly_config.AnomalyConfig( 64 id='Existing Config', config={'old': 11}, 65 patterns=['MyMaster/*/*/*']).put() 66 67 self.testapp.post('/edit_anomaly_configs', { 68 'add-edit': 'edit', 69 'edit-name': 'Existing Config', 70 'config': '{"new": 10}', 71 'patterns': 'MyMaster/*/*/*', 72 'xsrf_token': xsrf.GenerateToken(users.get_current_user()), 73 }) 74 75 anomaly_configs = anomaly_config.AnomalyConfig.query().fetch() 76 self.assertEqual(len(anomaly_configs), 1) 77 self.assertEqual('Existing Config', anomaly_configs[0].key.string_id()) 78 self.assertEqual({'new': 10}, anomaly_configs[0].config) 79 self.assertEqual(['MyMaster/*/*/*'], anomaly_configs[0].patterns) 80 81 def testEdit_AddPattern(self): 82 """Tests changing the patterns list of an existing AnomalyConfig.""" 83 self.SetCurrentUser('sullivan@chromium.org', is_admin=True) 84 master = graph_data.Master(id='TheMaster').put() 85 bot = graph_data.Bot(id='TheBot', parent=master).put() 86 suite1 = graph_data.Test(id='Suite1', parent=bot).put() 87 suite2 = graph_data.Test(id='Suite2', parent=bot).put() 88 test_aaa = graph_data.Test(id='aaa', parent=suite1, has_rows=True).put() 89 test_bbb = graph_data.Test(id='bbb', parent=suite1, has_rows=True).put() 90 test_ccc = graph_data.Test(id='ccc', parent=suite1, has_rows=True).put() 91 test_ddd = graph_data.Test(id='ddd', parent=suite2, has_rows=True).put() 92 anomaly_config.AnomalyConfig(id='1-Suite1-specific', config={'a': 10}).put() 93 anomaly_config.AnomalyConfig(id='2-Suite1-general', config={'b': 20}).put() 94 95 self.testapp.post('/edit_anomaly_configs', { 96 'add-edit': 'edit', 97 'edit-name': '1-Suite1-specific', 98 'config': '{"a": 10}', 99 'patterns': '*/*/Suite1/aaa', 100 'xsrf_token': xsrf.GenerateToken(users.get_current_user()), 101 }) 102 self.ExecuteTaskQueueTasks( 103 '/put_entities_task', edit_config_handler._TASK_QUEUE_NAME) 104 self.testapp.post('/edit_anomaly_configs', { 105 'add-edit': 'edit', 106 'edit-name': '2-Suite1-general', 107 'config': '{"b": 20}', 108 'patterns': '*/*/Suite1/*', 109 'xsrf_token': xsrf.GenerateToken(users.get_current_user()), 110 }) 111 self.ExecuteTaskQueueTasks( 112 '/put_entities_task', edit_config_handler._TASK_QUEUE_NAME) 113 114 # The lists of test patterns in the AnomalyConfig entities in the datastore 115 # should be set based on what was added in the two requests above. 116 self.assertEqual( 117 ['*/*/Suite1/*'], 118 anomaly_config.AnomalyConfig.get_by_id('2-Suite1-general').patterns) 119 self.assertEqual( 120 ['*/*/Suite1/aaa'], 121 anomaly_config.AnomalyConfig.get_by_id('1-Suite1-specific').patterns) 122 123 # The 1-Suite1-specific config applies instead of the other config 124 # because its name comes first according to sort order. 125 self.assertEqual( 126 '1-Suite1-specific', 127 test_aaa.get().overridden_anomaly_config.string_id()) 128 # The 2-Suite1-specific config applies to the other tests under Suite1. 129 self.assertEqual( 130 '2-Suite1-general', 131 test_bbb.get().overridden_anomaly_config.string_id()) 132 self.assertEqual( 133 '2-Suite1-general', 134 test_ccc.get().overridden_anomaly_config.string_id()) 135 136 # Note that Suite2/ddd has no config, and nor do the parent tests. 137 self.assertIsNone(test_ddd.get().overridden_anomaly_config) 138 self.assertIsNone(suite1.get().overridden_anomaly_config) 139 self.assertIsNone(suite2.get().overridden_anomaly_config) 140 141 def testEdit_RemovePattern(self): 142 """Tests removing a pattern from an AnomalyConfig.""" 143 self.SetCurrentUser('sullivan@chromium.org', is_admin=True) 144 anomaly_config_key = anomaly_config.AnomalyConfig( 145 id='Test Config', config={'a': 10}, 146 patterns=['*/*/one', '*/*/two']).put() 147 master = graph_data.Master(id='TheMaster').put() 148 bot = graph_data.Bot(id='TheBot', parent=master).put() 149 test_one = graph_data.Test( 150 id='one', parent=bot, overridden_anomaly_config=anomaly_config_key, 151 has_rows=True).put() 152 test_two = graph_data.Test( 153 id='two', parent=bot, overridden_anomaly_config=anomaly_config_key, 154 has_rows=True).put() 155 156 # Verify the state of the data before making the request. 157 self.assertEqual(['*/*/one', '*/*/two'], anomaly_config_key.get().patterns) 158 self.assertEqual( 159 ['TheMaster/TheBot/one'], 160 list_tests.GetTestsMatchingPattern('*/*/one')) 161 162 self.testapp.post('/edit_anomaly_configs', { 163 'add-edit': 'edit', 164 'edit-name': 'Test Config', 165 'config': '{"a": 10}', 166 'patterns': ['*/*/two'], 167 'xsrf_token': xsrf.GenerateToken(users.get_current_user()), 168 }) 169 self.ExecuteTaskQueueTasks( 170 '/put_entities_task', edit_config_handler._TASK_QUEUE_NAME) 171 172 self.assertEqual(['*/*/two'], anomaly_config_key.get().patterns) 173 self.assertIsNone(test_one.get().overridden_anomaly_config) 174 self.assertEqual( 175 'Test Config', test_two.get().overridden_anomaly_config.string_id()) 176 177 178if __name__ == '__main__': 179 unittest.main() 180