PageRenderTime 42ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/tools/perf/cli_tools/soundwave/tables/timeseries_test.py

https://github.com/chromium/chromium
Python | 247 lines | 227 code | 13 blank | 7 comment | 6 complexity | 20e41c2358df2f2920ce7686882fbe02 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, Apache-2.0, BSD-3-Clause
  1. # Copyright 2018 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. import datetime
  5. import unittest
  6. from cli_tools.soundwave import pandas_sqlite
  7. from cli_tools.soundwave import tables
  8. from core.external_modules import pandas
  9. def SamplePoint(point_id, value, timestamp=None, missing_commit_pos=False):
  10. """Build a sample point as returned by timeseries2 API."""
  11. revisions = {
  12. 'r_commit_pos': str(point_id),
  13. 'r_chromium': 'chromium@%d' % point_id,
  14. }
  15. annotations = {
  16. 'a_tracing_uri': 'http://example.com/trace/%d' % point_id
  17. }
  18. if timestamp is None:
  19. timestamp = datetime.datetime.utcfromtimestamp(
  20. 1234567890 + 60 * point_id).isoformat()
  21. if missing_commit_pos:
  22. # Some data points have a missing commit position.
  23. revisions['r_commit_pos'] = None
  24. return [
  25. point_id,
  26. revisions,
  27. value,
  28. timestamp,
  29. annotations,
  30. ]
  31. class TestKey(unittest.TestCase):
  32. def testKeyFromDict_typical(self):
  33. key1 = tables.timeseries.Key.FromDict({
  34. 'test_suite': 'loading.mobile',
  35. 'bot': 'ChromiumPerf:android-nexus5',
  36. 'measurement': 'timeToFirstInteractive',
  37. 'test_case': 'Wikipedia'})
  38. key2 = tables.timeseries.Key(
  39. test_suite='loading.mobile',
  40. measurement='timeToFirstInteractive',
  41. bot='ChromiumPerf:android-nexus5',
  42. test_case='Wikipedia')
  43. self.assertEqual(key1, key2)
  44. def testKeyFromDict_defaultTestCase(self):
  45. key1 = tables.timeseries.Key.FromDict({
  46. 'test_suite': 'loading.mobile',
  47. 'bot': 'ChromiumPerf:android-nexus5',
  48. 'measurement': 'timeToFirstInteractive'})
  49. key2 = tables.timeseries.Key(
  50. test_suite='loading.mobile',
  51. measurement='timeToFirstInteractive',
  52. bot='ChromiumPerf:android-nexus5',
  53. test_case='')
  54. self.assertEqual(key1, key2)
  55. def testKeyFromDict_invalidArgsRaises(self):
  56. with self.assertRaises(TypeError):
  57. tables.timeseries.Key.FromDict({
  58. 'test_suite': 'loading.mobile',
  59. 'bot': 'ChromiumPerf:android-nexus5'})
  60. @unittest.skipIf(pandas is None, 'pandas not available')
  61. class TestTimeSeries(unittest.TestCase):
  62. def testDataFrameFromJsonV1(self):
  63. test_path = ('ChromiumPerf/android-nexus5/loading.mobile'
  64. '/timeToFirstInteractive/PageSet/Google')
  65. data = {
  66. 'test_path': test_path,
  67. 'improvement_direction': 1,
  68. 'timeseries': [
  69. ['revision', 'value', 'timestamp', 'r_commit_pos', 'r_chromium'],
  70. [547397, 2300.3, '2018-04-01T14:16:32.000', '547397', 'adb123'],
  71. [547398, 2750.9, '2018-04-01T18:24:04.000', '547398', 'cde456'],
  72. [547423, 2342.2, '2018-04-02T02:19:00.000', '547423', 'fab789'],
  73. # Some timeseries have a missing commit position.
  74. [547836, 2402.5, '2018-04-02T02:20:00.000', None, 'acf147'],
  75. ]
  76. }
  77. timeseries = tables.timeseries.DataFrameFromJson(test_path, data)
  78. # Check the integrity of the index: there should be no duplicates.
  79. self.assertFalse(timeseries.index.duplicated().any())
  80. self.assertEqual(len(timeseries), 4)
  81. # Check values on the first point of the series.
  82. point = timeseries.reset_index().iloc[0]
  83. self.assertEqual(point['test_suite'], 'loading.mobile')
  84. self.assertEqual(point['measurement'], 'timeToFirstInteractive')
  85. self.assertEqual(point['bot'], 'ChromiumPerf/android-nexus5')
  86. self.assertEqual(point['test_case'], 'PageSet/Google')
  87. self.assertEqual(point['improvement_direction'], 'down')
  88. self.assertEqual(point['point_id'], 547397)
  89. self.assertEqual(point['value'], 2300.3)
  90. self.assertEqual(point['timestamp'], datetime.datetime(
  91. year=2018, month=4, day=1, hour=14, minute=16, second=32))
  92. self.assertEqual(point['commit_pos'], 547397)
  93. self.assertEqual(point['chromium_rev'], 'adb123')
  94. self.assertEqual(point['clank_rev'], None)
  95. def testDataFrameFromJsonV2(self):
  96. test_path = tables.timeseries.Key(
  97. test_suite='loading.mobile',
  98. measurement='timeToFirstInteractive',
  99. bot='ChromiumPerf:android-nexus5',
  100. test_case='Wikipedia')
  101. data = {
  102. 'improvement_direction': 'down',
  103. 'units': 'ms',
  104. 'data': [
  105. SamplePoint(547397, 2300.3, timestamp='2018-04-01T14:16:32.000'),
  106. SamplePoint(547398, 2750.9),
  107. SamplePoint(547423, 2342.2),
  108. SamplePoint(547836, 2402.5, missing_commit_pos=True),
  109. ]
  110. }
  111. timeseries = tables.timeseries.DataFrameFromJson(test_path, data)
  112. # Check the integrity of the index: there should be no duplicates.
  113. self.assertFalse(timeseries.index.duplicated().any())
  114. self.assertEqual(len(timeseries), 4)
  115. # Check values on the first point of the series.
  116. point = timeseries.reset_index().iloc[0]
  117. self.assertEqual(point['test_suite'], 'loading.mobile')
  118. self.assertEqual(point['measurement'], 'timeToFirstInteractive')
  119. self.assertEqual(point['bot'], 'ChromiumPerf:android-nexus5')
  120. self.assertEqual(point['test_case'], 'Wikipedia')
  121. self.assertEqual(point['improvement_direction'], 'down')
  122. self.assertEqual(point['units'], 'ms')
  123. self.assertEqual(point['point_id'], 547397)
  124. self.assertEqual(point['value'], 2300.3)
  125. self.assertEqual(point['timestamp'], datetime.datetime(
  126. year=2018, month=4, day=1, hour=14, minute=16, second=32))
  127. self.assertEqual(point['commit_pos'], 547397)
  128. self.assertEqual(point['chromium_rev'], 'chromium@547397')
  129. self.assertEqual(point['clank_rev'], None)
  130. def testDataFrameFromJson_withSummaryMetric(self):
  131. test_path = tables.timeseries.Key(
  132. test_suite='loading.mobile',
  133. measurement='timeToFirstInteractive',
  134. bot='ChromiumPerf:android-nexus5',
  135. test_case='')
  136. data = {
  137. 'improvement_direction': 'down',
  138. 'units': 'ms',
  139. 'data': [
  140. SamplePoint(547397, 2300.3),
  141. SamplePoint(547398, 2750.9),
  142. ],
  143. }
  144. timeseries = tables.timeseries.DataFrameFromJson(
  145. test_path, data).reset_index()
  146. self.assertTrue((timeseries['test_case'] == '').all())
  147. def testGetTimeSeries(self):
  148. test_path = tables.timeseries.Key(
  149. test_suite='loading.mobile',
  150. measurement='timeToFirstInteractive',
  151. bot='ChromiumPerf:android-nexus5',
  152. test_case='Wikipedia')
  153. data = {
  154. 'improvement_direction': 'down',
  155. 'units': 'ms',
  156. 'data': [
  157. SamplePoint(547397, 2300.3),
  158. SamplePoint(547398, 2750.9),
  159. SamplePoint(547423, 2342.2),
  160. ]
  161. }
  162. timeseries_in = tables.timeseries.DataFrameFromJson(test_path, data)
  163. with tables.DbSession(':memory:') as con:
  164. pandas_sqlite.InsertOrReplaceRecords(con, 'timeseries', timeseries_in)
  165. timeseries_out = tables.timeseries.GetTimeSeries(con, test_path)
  166. # Both DataFrame's should be equal, except the one we get out of the db
  167. # does not have an index defined.
  168. timeseries_in = timeseries_in.reset_index()
  169. self.assertTrue(timeseries_in.equals(timeseries_out))
  170. def testGetTimeSeries_withSummaryMetric(self):
  171. test_path = tables.timeseries.Key(
  172. test_suite='loading.mobile',
  173. measurement='timeToFirstInteractive',
  174. bot='ChromiumPerf:android-nexus5',
  175. test_case='')
  176. data = {
  177. 'improvement_direction': 'down',
  178. 'units': 'ms',
  179. 'data': [
  180. SamplePoint(547397, 2300.3),
  181. SamplePoint(547398, 2750.9),
  182. SamplePoint(547423, 2342.2),
  183. ]
  184. }
  185. timeseries_in = tables.timeseries.DataFrameFromJson(test_path, data)
  186. with tables.DbSession(':memory:') as con:
  187. pandas_sqlite.InsertOrReplaceRecords(con, 'timeseries', timeseries_in)
  188. timeseries_out = tables.timeseries.GetTimeSeries(con, test_path)
  189. # Both DataFrame's should be equal, except the one we get out of the db
  190. # does not have an index defined.
  191. timeseries_in = timeseries_in.reset_index()
  192. self.assertTrue(timeseries_in.equals(timeseries_out))
  193. def testGetMostRecentPoint_success(self):
  194. test_path = tables.timeseries.Key(
  195. test_suite='loading.mobile',
  196. measurement='timeToFirstInteractive',
  197. bot='ChromiumPerf:android-nexus5',
  198. test_case='Wikipedia')
  199. data = {
  200. 'improvement_direction': 'down',
  201. 'units': 'ms',
  202. 'data': [
  203. SamplePoint(547397, 2300.3),
  204. SamplePoint(547398, 2750.9),
  205. SamplePoint(547423, 2342.2),
  206. ]
  207. }
  208. timeseries = tables.timeseries.DataFrameFromJson(test_path, data)
  209. with tables.DbSession(':memory:') as con:
  210. pandas_sqlite.InsertOrReplaceRecords(con, 'timeseries', timeseries)
  211. point = tables.timeseries.GetMostRecentPoint(con, test_path)
  212. self.assertEqual(point['point_id'], 547423)
  213. def testGetMostRecentPoint_empty(self):
  214. test_path = tables.timeseries.Key(
  215. test_suite='loading.mobile',
  216. measurement='timeToFirstInteractive',
  217. bot='ChromiumPerf:android-nexus5',
  218. test_case='Wikipedia')
  219. with tables.DbSession(':memory:') as con:
  220. point = tables.timeseries.GetMostRecentPoint(con, test_path)
  221. self.assertIsNone(point)