Home | History | Annotate | Download | only in measurements
      1 # Copyright 2014 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 time
      5 import unittest
      6 
      7 from measurements import smooth_gesture_util as sg_util
      8 from telemetry.core.platform import tracing_category_filter
      9 from telemetry.core.platform import tracing_options
     10 from telemetry.page import page as page_module
     11 from telemetry.page import page_test
     12 from telemetry.timeline import async_slice
     13 from telemetry.timeline import model as model_module
     14 from telemetry.unittest import page_test_test_case
     15 from telemetry.web_perf import timeline_interaction_record as tir_module
     16 
     17 
     18 class SmoothGestureUtilTest(unittest.TestCase):
     19   def testGetAdjustedInteractionIfContainGesture(self):
     20     model = model_module.TimelineModel()
     21     renderer_main = model.GetOrCreateProcess(1).GetOrCreateThread(2)
     22     renderer_main.name = 'CrRendererMain'
     23 
     24     #      [          X          ]                   [   Y  ]
     25     #      [  sub_async_slice_X  ]
     26     #          [   record_1]
     27     #          [   record_6]
     28     #  [  record_2 ]          [ record_3 ]
     29     #  [           record_4              ]
     30     #                                [ record_5 ]
     31     #
     32     # Note: X and Y are async slice with name
     33     # SyntheticGestureController::running
     34 
     35     async_slice_X = async_slice.AsyncSlice(
     36       'X', 'SyntheticGestureController::running', 10, duration=20,
     37       start_thread=renderer_main, end_thread=renderer_main)
     38 
     39     sub_async_slice_X = async_slice.AsyncSlice(
     40       'X', 'SyntheticGestureController::running', 10, duration=20,
     41       start_thread=renderer_main, end_thread=renderer_main)
     42     sub_async_slice_X.parent_slice = async_slice_X
     43     async_slice_X.AddSubSlice(sub_async_slice_X)
     44 
     45     async_slice_Y = async_slice.AsyncSlice(
     46       'X', 'SyntheticGestureController::running', 60, duration=20,
     47       start_thread=renderer_main, end_thread=renderer_main)
     48 
     49     renderer_main.AddAsyncSlice(async_slice_X)
     50     renderer_main.AddAsyncSlice(async_slice_Y)
     51 
     52     model.FinalizeImport(shift_world_to_zero=False)
     53 
     54     record_1 = tir_module.TimelineInteractionRecord('Gesture_included', 15, 25)
     55     record_2 = tir_module.TimelineInteractionRecord(
     56       'Gesture_overlapped_left', 5, 25)
     57     record_3 = tir_module.TimelineInteractionRecord(
     58       'Gesture_overlapped_right', 25, 35)
     59     record_4 = tir_module.TimelineInteractionRecord(
     60       'Gesture_containing', 5, 35)
     61     record_5 = tir_module.TimelineInteractionRecord(
     62       'Gesture_non_overlapped', 35, 45)
     63     record_6 = tir_module.TimelineInteractionRecord('Action_included', 15, 25)
     64 
     65     adjusted_record_1 = sg_util.GetAdjustedInteractionIfContainGesture(
     66       model, record_1)
     67     self.assertEquals(adjusted_record_1.start, 10)
     68     self.assertEquals(adjusted_record_1.end, 30)
     69     self.assertTrue(adjusted_record_1 is not record_1)
     70 
     71     adjusted_record_2 = sg_util.GetAdjustedInteractionIfContainGesture(
     72       model, record_2)
     73     self.assertEquals(adjusted_record_2.start, 10)
     74     self.assertEquals(adjusted_record_2.end, 30)
     75 
     76     adjusted_record_3 = sg_util.GetAdjustedInteractionIfContainGesture(
     77       model, record_3)
     78     self.assertEquals(adjusted_record_3.start, 10)
     79     self.assertEquals(adjusted_record_3.end, 30)
     80 
     81     adjusted_record_4 = sg_util.GetAdjustedInteractionIfContainGesture(
     82       model, record_4)
     83     self.assertEquals(adjusted_record_4.start, 10)
     84     self.assertEquals(adjusted_record_4.end, 30)
     85 
     86     adjusted_record_5 = sg_util.GetAdjustedInteractionIfContainGesture(
     87       model, record_5)
     88     self.assertEquals(adjusted_record_5.start, 35)
     89     self.assertEquals(adjusted_record_5.end, 45)
     90     self.assertTrue(adjusted_record_5 is not record_5)
     91 
     92     adjusted_record_6 = sg_util.GetAdjustedInteractionIfContainGesture(
     93       model, record_6)
     94     self.assertEquals(adjusted_record_6.start, 15)
     95     self.assertEquals(adjusted_record_6.end, 25)
     96     self.assertTrue(adjusted_record_6 is not record_6)
     97 
     98 
     99 class ScrollingPage(page_module.Page):
    100   def __init__(self, url, page_set, base_dir):
    101     super(ScrollingPage, self).__init__(url, page_set, base_dir)
    102 
    103   def RunSmoothness(self, action_runner):
    104     interaction = action_runner.BeginGestureInteraction(
    105         'ScrollAction', is_smooth=True)
    106     # Add 0.5s gap between when Gesture records are issued to when we actually
    107     # scroll the page.
    108     time.sleep(0.5)
    109     action_runner.ScrollPage()
    110     time.sleep(0.5)
    111     interaction.End()
    112 
    113 
    114 class SmoothGestureTest(page_test_test_case.PageTestTestCase):
    115   def testSmoothGestureAdjusted(self):
    116     ps = self.CreateEmptyPageSet()
    117     ps.AddPage(ScrollingPage(
    118       'file://scrollable_page.html', ps, base_dir=ps.base_dir))
    119     models = []
    120     tab_ids = []
    121     class ScrollingGestureTestMeasurement(page_test.PageTest):
    122       def __init__(self):
    123         super(ScrollingGestureTestMeasurement, self).__init__(
    124           'RunSmoothness', False)
    125 
    126       def WillRunActions(self, _page, tab):
    127         options = tracing_options.TracingOptions()
    128         options.enable_chrome_trace = True
    129         tab.browser.platform.tracing_controller.Start(
    130           options, tracing_category_filter.TracingCategoryFilter())
    131 
    132       def DidRunActions(self, _page, tab):
    133         models.append(model_module.TimelineModel(
    134           tab.browser.platform.tracing_controller.Stop()))
    135         tab_ids.append(tab.id)
    136 
    137     self.RunMeasurement(ScrollingGestureTestMeasurement(), ps)
    138     timeline_model = models[0]
    139     renderer_thread = timeline_model.GetRendererThreadFromTabId(
    140         tab_ids[0])
    141     smooth_record = None
    142     for e in renderer_thread.async_slices:
    143       if tir_module.IsTimelineInteractionRecord(e.name):
    144         smooth_record = tir_module.TimelineInteractionRecord.FromAsyncEvent(e)
    145     self.assertIsNotNone(smooth_record)
    146     adjusted_smooth_gesture = (
    147       sg_util.GetAdjustedInteractionIfContainGesture(
    148         timeline_model, smooth_record))
    149     # Test that the scroll gesture starts at at least 500ms after the start of
    150     # the interaction record and ends at at least 500ms before the end of
    151     # interaction record.
    152     self.assertLessEqual(
    153       500, adjusted_smooth_gesture.start - smooth_record.start)
    154     self.assertLessEqual(
    155       500, smooth_record.end - adjusted_smooth_gesture.end)
    156