Exemplo n.º 1
0
def set_up_device(opt):
    if not opt.wifi_ssid or not opt.wifi_key or not opt.wifi_pass:
        raise ValueError('Missing --wifi options')

    mc = Marionette('localhost', opt.adb_port)
    for i in range(2):
        try:
            mc.start_session()
            break
        except socket.error:
            sh('adb forward tcp:%s tcp:%s' % (opt.adb_port, opt.adb_port))
    if opt.shell:
        from pdb import set_trace
        set_trace()
        return

    # watch out! This is how gaiatest does it.
    mc.__class__ = type('Marionette', (Marionette, MarionetteTouchMixin), {})
    device = GaiaDevice(mc)

    device.restart_b2g()

    apps = GaiaApps(mc)
    data_layer = GaiaData(mc)
    lockscreen = LockScreen(mc)
    mc.setup_touch()

    lockscreen.unlock()
    apps.kill_all()

    data_layer.enable_wifi()
    if opt.wifi_key == 'WPA-PSK':
        pass_key = 'psk'
    elif opt.wifi_key == 'WEP':
        pass_key = 'wep'
    else:
        assert 0, 'unknown key management'
    data = {'ssid': opt.wifi_ssid, 'keyManagement': opt.wifi_key,
            pass_key: opt.wifi_pass}
    data_layer.connect_to_wifi(data)

    mc.switch_to_frame()
    all_apps = set(a['manifest']['name'] for a in get_installed(apps))
    if 'Marketplace Dev' not in all_apps:
        mc.execute_script(
            'navigator.mozApps.install'
            '("https://marketplace-dev.allizom.org/manifest.webapp");')
        wait_for_element_displayed(mc, 'id', 'app-install-install-button')
        yes = mc.find_element('id', 'app-install-install-button')
        mc.tap(yes)
        wait_for_element_displayed(mc, 'id', 'system-banner')

    print 'Pushing payment prefs'
    sh('adb shell stop b2g')
    sh('adb push "%s" /data/local/user.js' % (
        os.path.join(os.path.dirname(__file__), 'payment-prefs.js')))
    sh('adb shell start b2g')

    print 'When your device reboots, Marketplace Dev will be installed'
Exemplo n.º 2
0
    def _StartProcess(self):
        if not self.isEmulatorInitialized:
            print("Starting Emulator ...")
            self.emulatorProcess = subprocess.Popen(
                [self.emulatorStartScript],
                cwd=os.path.dirname(self.emulatorStartScript),
                shell=True)

            # adb shell setprop net.dns1 10.0.2.3

            self._isBootFinished()
            self.monitoringProcessId = self.adb.getPID(
                self.monitoredProcessName)

            print("Forwarding TCP port %d ..." % self.forwardedPortADB)
            self.adb.command([
                "forward",
                "tcp:%d" % self.forwardedPortADB,
                "tcp:%d" % self.forwardedPortADB
            ])

            self.isEmulatorInitialized = True

        time.sleep(20)

        if self.crashSuccess:
            print("Restarting %s ..." % self.monitoredProcessName)
            self.adb.killProcess(self.monitoredProcessName, True)
            time.sleep(40)
            self.monitoringProcessId = self.adb.getPID(
                self.monitoredProcessName)
            self.crashSuccess = False
            self.debugLogData = str()
            self.adb.checkCmd(["logcat", "-c"])

        print("Starting Marionette session ...")
        marionette = Marionette('localhost', self.forwardedPortADB)
        print(marionette.status())
        marionette.start_session()
        marionette.set_script_timeout(self.scriptTimeout)
        marionette.switch_to_frame()

        lock = gaia.LockScreen(marionette)
        lock.unlock()

        apps = gaia.GaiaApps(marionette)
        print(apps.runningApps())

        print("Launching Browser application")
        apps.launch(self.appName, switch_to_frame=True)

        print("Navigating to %s ..." % self.publisherURL)
        marionette.execute_script(
            "return window.wrappedJSObject.Browser.navigate('%s')" %
            self.publisherURL)

        self.isMonitorInitialized = True
Exemplo n.º 3
0
def launch_app(app_name,
               adb_path="adb",
               script_timeout=5000,
               marionette=None,
               device_serial=None):
    """
    Launches the given app
    NOTE: if a marionette session is passed, this function switches to the top-most frame.
    """
    dm = mozdevice.DeviceManagerADB(adbPath=adb_path,
                                    deviceSerial=device_serial)
    installed_app_name = app_name.lower()
    installed_app_name = installed_app_name.replace(" ", "-")
    dm.forward("tcp:2828", "tcp:2828")

    if not marionette:
        m = Marionette()
        m.start_session()
    else:
        m = marionette
        m.switch_to_frame()
    launch_app = """
    var launchWithName = function(name) {
        let apps = window.wrappedJSObject.applications || window.wrappedJSObject.Applications;
        let installedApps = apps.installedApps;
        for (let manifestURL in installedApps) {
          let app = installedApps[manifestURL];
          let origin = null;
          let entryPoints = app.manifest.entry_points;
          if (entryPoints) {
            for (let ep in entryPoints) {
              let currentEntryPoint = entryPoints[ep];
              let appName = currentEntryPoint.name;
              if (name == appName.toLowerCase()) {
                app.launch();
                return true;
              }
            }
          } else {
            let appName = app.manifest.name;
            if (name == appName.toLowerCase()) {
              app.launch();
              return true;
            }
          }
        }
        return false;
      };
    return launchWithName("%s");
    """
    m.set_script_timeout(script_timeout)
    m.execute_script(launch_app % app_name.lower())
    if not marionette:
        m.delete_session()
Exemplo n.º 4
0
def uninstall_app(app_name, adb_path="adb", script_timeout=5000, marionette=None):
    """
    Uninstalls the given app.

    NOTE: if a marionette session is passed, this function switches to the top-most frame.
    """
    dm = mozdevice.DeviceManagerADB(adbPath=adb_path)
    installed_app_name = app_name.lower()
    installed_app_name = installed_app_name.replace(" ", "-")
    if dm.forward("tcp:2828", "tcp:2828") != 0:
        raise Exception("Can't use localhost:2828 for port forwarding." \
                    "Is something else using port 2828?")

    if not marionette:
        m = Marionette()
        m.start_session()
    else: 
        m = marionette
        m.switch_to_frame()
    uninstall_app = """
    var uninstallWithName = function(name) {
        let apps = window.wrappedJSObject.applications || window.wrappedJSObject.Applications;
        let installedApps = apps.installedApps;
        for (let manifestURL in installedApps) {
          let app = installedApps[manifestURL];
          let origin = null;
          let entryPoints = app.manifest.entry_points;
          if (entryPoints) {
            for (let ep in entryPoints) {
              let currentEntryPoint = entryPoints[ep];
              let appName = currentEntryPoint.name;
              if (name == appName.toLowerCase()) {
                window.wrappedJSObject.navigator.mozApps.mgmt.uninstall(app);
                return true;
              }
            }
          } else {
            let appName = app.manifest.name;
            if (name == appName.toLowerCase()) {
              window.wrappedJSObject.navigator.mozApps.mgmt.uninstall(app);
              return true;
            }
          }
        }
        return false;
      };
    return uninstallWithName("%s");
    """
    m.set_script_timeout(script_timeout)
    m.execute_script(uninstall_app % app_name.lower())
    if not marionette:
        m.delete_session()
Exemplo n.º 5
0
def launch_app(app_name, adb_path="adb", script_timeout=5000, marionette=None, device_serial=None):
    """
    Launches the given app
    NOTE: if a marionette session is passed, this function switches to the top-most frame.
    """
    dm = mozdevice.DeviceManagerADB(adbPath=adb_path,deviceSerial=device_serial)
    installed_app_name = app_name.lower()
    installed_app_name = installed_app_name.replace(" ", "-")
    dm.forward("tcp:2828", "tcp:2828")

    if not marionette:
        m = Marionette()
        m.start_session()
    else:
        m = marionette
        m.switch_to_frame()
    launch_app = """
    var launchWithName = function(name) {
        let apps = window.wrappedJSObject.applications || window.wrappedJSObject.Applications;
        let installedApps = apps.installedApps;
        for (let manifestURL in installedApps) {
          let app = installedApps[manifestURL];
          let origin = null;
          let entryPoints = app.manifest.entry_points;
          if (entryPoints) {
            for (let ep in entryPoints) {
              let currentEntryPoint = entryPoints[ep];
              let appName = currentEntryPoint.name;
              if (name == appName.toLowerCase()) {
                app.launch();
                return true;
              }
            }
          } else {
            let appName = app.manifest.name;
            if (name == appName.toLowerCase()) {
              app.launch();
              return true;
            }
          }
        }
        return false;
      };
    return launchWithName("%s");
    """
    m.set_script_timeout(script_timeout)
    m.execute_script(launch_app % app_name.lower())
    if not marionette:
        m.delete_session()
Exemplo n.º 6
0
    def _StartProcess(self):
        if not self.isDeviceInitialized:
            print("Starting ...")
            self.monitoringProcessId = self.adb.getPID(
                self.monitoredProcessName)
            print("Forwarding TCP port %d ..." % self.forwardedPortADB)
            self.adb.command([
                "forward",
                "tcp:%d" % self.forwardedPortADB,
                "tcp:%d" % self.forwardedPortADB
            ])
            self.isDeviceInitialized = True

        print("Sleeping ...")
        time.sleep(20)

        if self.crashSuccess:
            print("Restarting %s" % self.monitoredProcessName)
            self.adb.killProcess(self.monitoredProcessName, True)
            time.sleep(40)
            self.monitoringProcessId = self.adb.getPID(
                self.monitoredProcessName)
            self.crashSuccess = False
            self.debugLogData = str()
            self.adb.checkCmd(["logcat", "-c"])

        print("Starting Marionette session")
        marionette = Marionette('localhost', self.forwardedPortADB)
        print(marionette.status())
        marionette.start_session()
        marionette.set_script_timeout(self.scriptTimeout)
        marionette.switch_to_frame()

        lock = gaia.LockScreen(marionette)
        assert (lock.unlock())

        apps = gaia.GaiaApps(marionette)
        print(apps.runningApps())

        print("Launching Browser application")
        apps.launch(self.appName, switch_to_frame=True)

        print("Navigating to %s ..." % self.publisherURL)
        marionette.execute_script(
            "return window.wrappedJSObject.Browser.navigate('%s')" %
            self.publisherURL)

        self.isMonitorInitialized = True
Exemplo n.º 7
0
Arquivo: b2g.py Projeto: KurSh/peach
    def _StartProcess(self):
        if not self.isEmulatorInitialized:
            print("Starting Emulator ...")
            self.emulatorProcess = subprocess.Popen(
                [self.emulatorStartScript], cwd=os.path.dirname(self.emulatorStartScript), shell=True)

            # adb shell setprop net.dns1 10.0.2.3

            self._isBootFinished()
            self.monitoringProcessId = self.adb.getPID(self.monitoredProcessName)

            print("Forwarding TCP port %d ..." % self.forwardedPortADB)
            self.adb.command(["forward", "tcp:%d" % self.forwardedPortADB, "tcp:%d" % self.forwardedPortADB])

            self.isEmulatorInitialized = True

        time.sleep(20)

        if self.crashSuccess:
            print("Restarting %s ..." % self.monitoredProcessName)
            self.adb.killProcess(self.monitoredProcessName, True)
            time.sleep(40)
            self.monitoringProcessId = self.adb.getPID(self.monitoredProcessName)
            self.crashSuccess = False
            self.debugLogData = str()
            self.adb.checkCmd(["logcat", "-c"])

        print("Starting Marionette session ...")
        marionette = Marionette('localhost', self.forwardedPortADB)
        print(marionette.status())
        marionette.start_session()
        marionette.set_script_timeout(self.scriptTimeout)
        marionette.switch_to_frame()

        lock = gaia.LockScreen(marionette)
        lock.unlock()

        apps = gaia.GaiaApps(marionette)
        print(apps.runningApps())

        print("Launching Browser application")
        apps.launch(self.appName, switch_to_frame=True)

        print("Navigating to %s ..." % self.publisherURL)
        marionette.execute_script("return window.wrappedJSObject.Browser.navigate('%s')" % self.publisherURL)

        self.isMonitorInitialized = True
Exemplo n.º 8
0
Arquivo: b2g.py Projeto: KurSh/peach
    def _StartProcess(self):
        if not self.isDeviceInitialized:
            print("Starting ...")
            self.monitoringProcessId = self.adb.getPID(self.monitoredProcessName)
            print("Forwarding TCP port %d ..." % self.forwardedPortADB)
            self.adb.command(["forward", "tcp:%d" % self.forwardedPortADB, "tcp:%d" % self.forwardedPortADB])
            self.isDeviceInitialized = True

        print("Sleeping ...")
        time.sleep(20)

        if self.crashSuccess:
            print("Restarting %s" % self.monitoredProcessName)
            self.adb.killProcess(self.monitoredProcessName, True)
            time.sleep(40)
            self.monitoringProcessId = self.adb.getPID(self.monitoredProcessName)
            self.crashSuccess = False
            self.debugLogData = str()
            self.adb.checkCmd(["logcat", "-c"])

        print("Starting Marionette session")
        marionette = Marionette('localhost', self.forwardedPortADB)
        print(marionette.status())
        marionette.start_session()
        marionette.set_script_timeout(self.scriptTimeout)
        marionette.switch_to_frame()

        lock = gaia.LockScreen(marionette)
        assert(lock.unlock())

        apps = gaia.GaiaApps(marionette)
        print(apps.runningApps())

        print("Launching Browser application")
        apps.launch(self.appName, switch_to_frame=True)

        print("Navigating to %s ..." % self.publisherURL)
        marionette.execute_script("return window.wrappedJSObject.Browser.navigate('%s')" % self.publisherURL)

        self.isMonitorInitialized = True
Exemplo n.º 9
0
def kill(origin):
    marionette = Marionette(host='localhost', port=2828)
    marionette.start_session()
    marionette.set_context(marionette.CONTEXT_CONTENT)
    marionette.execute_script("window.wrappedJSObject.WindowManager.kill('%s')" % origin)
Exemplo n.º 10
0
class B2gExecutor(Executor):
    def __init__(self, app_name, app_id, device=False):
        self.device = device
        if self.device:
            call(['adb', 'forward', 'tcp:2828', 'tcp:2828'])
        self._app_name = app_name
        self._app_id = app_id
        self._marionette = Marionette()
        self._marionette.start_session()

        # https://github.com/mozilla-b2g/gaia/blob/b568b7ae8adb6ee3651bd75acbaaedff86a08912/tests/python/gaia-ui-tests/gaiatest/gaia_test.py
        js = os.path.abspath(os.path.join(__file__, os.path.pardir, 'atoms', "gaia_apps.js"))
        self._marionette.import_script(js)
        js = os.path.abspath(os.path.join(__file__, os.path.pardir, 'atoms', "gaia_data_layer.js"))
        self._marionette.set_context(self._marionette.CONTEXT_CHROME)
        self._marionette.import_script(js)
        self._marionette.set_context(self._marionette.CONTEXT_CONTENT)

        '''
        # C:\Users\Jun-Wei\Desktop\b2g\battery\manifest.webapp
        #app = GaiaApps(self._marionette).launch(self._app_name)
        #app = GaiaApps(self._marionette).launch('Battery', manifest_url='C:/Users/Jun-Wei/Desktop/b2g/battery/manifest.webapp', entry_point='/index.html')

        app = GaiaApps(self._marionette).launch('Battery')
        print app.frame
        print app.src
        print app.origin
        print app.name
        #print g_app.manifest_url

        #self._app_frame = g_app.frame
        self._app_frame_id = app.frame
        self._app_src = app.src
        self._app_origin = app.origin
        #self.app_manifest_url = g_app.manifest_url

        #self.gaia_apps = GaiaApps(self.__marionette)
        #print self.gaia_apps.displayed_app.name
        #print self.gaia_apps.installed_apps
        #print self.gaia_apps.running_apps()
        #js = os.path.abspath(os.path.join(__file__, os.path.pardir, 'atoms', "gaia_apps.js"))
        #self.__marionette.import_script(js)
        '''

    def fire_event(self, clickable):
        logger.info('fire_event: id: %s (xpath: %s)', clickable.get_id(), clickable.get_xpath())
        try:
            # id staring with DomAnalyzer.serial_prefix is given by our monkey and should be ignored when locating
            if clickable.get_id() and not clickable.get_id().startswith(DomAnalyzer.serial_prefix):
                self._marionette.find_element('id', clickable.get_id()).tap()
            elif clickable.get_xpath():
                self._marionette.find_element('xpath', clickable.get_xpath()).tap()
            else:
                logger.error('No id nor xpath for the clickable: id: %s (xpath: %s)', clickable.get_id(), clickable.get_xpath())
                sys.exit()
        except (ElementNotVisibleException, InvalidElementStateException, NoSuchElementException):
            logger.info('Element is not interactable in fire_event(): id: %s (xpath: %s)', clickable.get_id(), clickable.get_xpath())
        except Exception as e:
            logger.error('Unknown Exception: %s in fire_event(): id: %s (xpath: %s)', str(e), clickable.get_id(), clickable.get_xpath())
            sys.exit()

    def fill_form(self, clickable):
        for f in clickable.get_forms():
            for input_field in f.get_inputs():
                try:
                    if input_field.get_id() and not input_field.get_id().startswith(DomAnalyzer.serial_prefix):
                        self._marionette.find_element('id', input_field.get_id()).send_keys(input_field.get_value())
                    elif input_field.get_xpath():
                        self._marionette.find_element('xpath', input_field.get_xpath()).send_keys(input_field.get_value())
                    else:
                        logger.error('No id nor xpath for an input field in the form id: %s (xpath: %s)', f.get_id(), f.get_xpath())
                        sys.exit()
                except (ElementNotVisibleException, InvalidElementStateException, NoSuchElementException):
                    logger.info('Element is not interactable in fill_form(): id: %s (xpath: %s)', f.get_id(), f.get_xpath())
                except Exception as e:
                    logger.error('Unknown Exception: %s in fill_form(): id: %s (xpath: %s)', str(e), f.get_id(), f.get_xpath())
                    sys.exit()

    def empty_form(self, clickable):
        for f in clickable.get_forms():
            for input_field in f.get_inputs():
                try:
                    if input_field.get_id() and not input_field.get_id().startswith(DomAnalyzer.serial_prefix):
                        self._marionette.find_element('id', input_field.get_id()).clear()
                    elif input_field.get_xpath():
                        self._marionette.find_element('xpath', input_field.get_xpath()).clear()
                    else:
                        logger.error('No id nor xpath for an input field in the form %s (%s)', f.get_id(), f.get_xpath())
                        sys.exit()
                except (ElementNotVisibleException, InvalidElementStateException, NoSuchElementException):
                    logger.info('Element is not interactable in empty_form(): id: %s (xpath: %s)', f.get_id(), f.get_xpath())
                except Exception as e:
                    logger.error('Unknown Exception: %s in empty_form(): id: %s (xpath: %s)', str(e), f.get_id(), f.get_xpath())
                    sys.exit()

    def get_source(self):
        return self._marionette.page_source.encode(sys.stdout.encoding, 'ignore')

    def get_screenshot(self, clickable=None):
        element = None
        if clickable:
            try:
                if clickable.get_id() and not clickable.get_id().startswith(DomAnalyzer.serial_prefix):
                    element = self._marionette.find_element('id', clickable.get_id())
                elif clickable.get_xpath():
                    element = self._marionette.find_element('xpath', clickable.get_xpath())
                else:
                    logger.error('No id nor xpath for the clickable: id: %s (xpath: %s)', clickable.get_id(), clickable.get_xpath())
                    sys.exit()
            except (ElementNotVisibleException, InvalidElementStateException, NoSuchElementException):
                logger.info('Element is not interactable in get_screenshot(): id: %s (xpath: %s)', clickable.get_id(), clickable.get_xpath())
            except Exception as e:
                logger.error('Unknown Exception: %s in get_screenshot(): id: %s (xpath: %s)', str(e), clickable.get_id(), clickable.get_xpath())
                sys.exit()
        if not element:
            # set context to CHROME to capture whole screen
            # system frame e.g. FileNotFound cannot be captured without CONTEXT_CHROME (Don't know why)
            self._marionette.set_context(self._marionette.CONTEXT_CHROME)
        screenshot = self._marionette.screenshot(element)
        self._marionette.set_context(self._marionette.CONTEXT_CONTENT)
        return screenshot

    def switch_to_frame(self, by, frame_str):
        """
        :param by: options: "id", "xpath", "link text", "partial link text", "name",
        "tag name", "class name", "css selector", "anon attribute"
        """
        # self.switch_to_top_frame()
        frame = self._marionette.find_element(by, frame_str)
        self._marionette.switch_to_frame(frame)

    def switch_to_top_frame(self):
        self._marionette.switch_to_frame()  # switch to the top-level frame

    def restart_app(self):
        # remember to disable screen timeout and screen lock before testing
        # todo: open b2g simulator, install app,
        # unlock_screen
        # self._marionette.execute_script('window.wrappedJSObject.lockScreen.unlock();')

        self.kill_all_apps()
        # kill_all_apps() will also kill the 'homescreen app' on real device
        # so trigger a home event to restore homescreen
        if self.device:
            self._dispatch_home_button_event()
        self.clear_data()
        self.touch_home_button()

        # launch the app
        if self.device:
            icon = self._marionette.find_element('xpath', "//li[contains(@aria-label, '" + self._app_name + "')]")
        else:
            icon = self._marionette.find_element('xpath', "//div[contains(@class, 'icon')]//span[contains(text(),'" + self._app_name + "')]")
        icon.tap()
        time.sleep(5)  # wait for app screen
        self._marionette.switch_to_frame()
        # this wait seems not working, need to find another useful one
        Wait(self._marionette).until(lambda m: m.find_element('css selector', "iframe[data-url*='" + self._app_id + "']").is_displayed())
        app_frame = self._marionette.find_element('css selector', "iframe[data-url*='" + self._app_id + "']")
        self._marionette.switch_to_frame(app_frame)

    def touch_home_button(self):
        # ref: https://github.com/mozilla-b2g/gaia/blob/master/tests/python/gaia-ui-tests/gaiatest/gaia_test.py#L751
        apps = GaiaApps(self._marionette)
        if apps.displayed_app.name.lower() != 'homescreen':
            # touching home button will return to homescreen
            self._dispatch_home_button_event()
            Wait(self._marionette).until(
                lambda m: apps.displayed_app.name.lower() == 'homescreen')
            apps.switch_to_displayed_app()
        else:
            apps.switch_to_displayed_app()
            mode = self._marionette.find_element(By.TAG_NAME, 'body').get_attribute('class')
            self._dispatch_home_button_event()
            apps.switch_to_displayed_app()
            if 'edit-mode' in mode:
                # touching home button will exit edit mode
                Wait(self._marionette).until(lambda m: m.find_element(
                    By.TAG_NAME, 'body').get_attribute('class') != mode)
            else:
                # touching home button inside homescreen will scroll it to the top
                Wait(self._marionette).until(lambda m: m.execute_script(
                    "return window.wrappedJSObject.scrollY") == 0)

    def _dispatch_home_button_event(self):
        self._marionette.switch_to_frame()
        self._marionette.execute_script("window.wrappedJSObject.dispatchEvent(new Event('home'));")
        time.sleep(0.5)

    def clear_data(self):
        # for now, clear contact data
        # https://github.com/mozilla-b2g/gaia/blob/v2.2/tests/python/gaia-ui-tests/gaiatest/gaia_test.py#L208
        self._marionette.set_context(self._marionette.CONTEXT_CHROME)
        result = self._marionette.execute_async_script('return GaiaDataLayer.removeAllContacts();')
        assert result, 'Unable to remove all contacts'
        self._marionette.set_context(self._marionette.CONTEXT_CONTENT)
        time.sleep(0.5)

    def kill_all_apps(self):
        self._marionette.switch_to_frame()
        self._marionette.execute_async_script("""
        // Kills all running apps, except the homescreen.
        function killAll() {
          let manager = window.wrappedJSObject.appWindowManager;

          let apps = manager.getApps();
          for (let id in apps) {
            let origin = apps[id].origin;
            if (origin.indexOf('verticalhome') == -1) {
              manager.kill(origin);
            }
          }
        };
        killAll();
        // return true so execute_async_script knows the script is complete
        marionetteScriptFinished(true);
        """)
        time.sleep(0.5)
Exemplo n.º 11
0
 assert(m.start_session())
 assert(m.get_session_capabilities()['javascriptEnabled'] == True)
 assert(m.get_window() == server.TEST_CURRENT_WINDOW)
 assert(m.window == server.TEST_CURRENT_WINDOW)
 assert(m.get_windows() == server.TEST_WINDOW_LIST)
 assert(m.switch_to_window('window2'))
 assert(m.window == 'window2')
 assert(m.close_window('window2'))
 assert(m.set_script_timeout(1000))
 assert(m.set_search_timeout(500))
 assert(m.get_url() == server.TEST_URL)
 assert(m.navigate(server.TEST_URL))
 assert(m.go_back())
 assert(m.go_forward())
 assert(m.refresh())
 assert(m.execute_script(server.TEST_EXECUTE_SCRIPT))
 assert(m.execute_js_script(server.TEST_EXECUTE_SCRIPT))
 assert(m.execute_js_script(server.TEST_EXECUTE_SCRIPT, server.TEST_EXECUTE_SCRIPT_ARGS))
 assert(m.execute_script(server.TEST_EXECUTE_SCRIPT, server.TEST_EXECUTE_SCRIPT_ARGS))
 assert(m.execute_async_script(server.TEST_EXECUTE_SCRIPT))
 assert(m.execute_async_script(server.TEST_EXECUTE_SCRIPT, server.TEST_EXECUTE_SCRIPT_ARGS))
 assert(str(m.find_element(HTMLElement.CLASS, 'heading')) == server.TEST_FIND_ELEMENT)
 assert([str(x) for x in m.find_elements(HTMLElement.TAG, 'p')] == server.TEST_FIND_ELEMENTS)
 assert(str(m.find_element(HTMLElement.CLASS, 'heading').find_element(HTMLElement.TAG, 'h1')) == server.TEST_FIND_ELEMENT)
 assert([str(x) for x in m.find_element(HTMLElement.ID, 'div1').find_elements(HTMLElement.SELECTOR, '.main')] == \
     server.TEST_FIND_ELEMENTS)
 assert(m.find_element(HTMLElement.ID, 'id1').click())
 assert(m.find_element(HTMLElement.ID, 'id2').text() == server.TEST_GET_TEXT)
 assert(m.find_element(HTMLElement.ID, 'id3').send_keys('Mozilla Firefox'))
 assert(m.find_element(HTMLElement.ID, 'id3').value() == server.TEST_GET_VALUE)
 assert(m.find_element(HTMLElement.ID, 'id3').clear())
Exemplo n.º 12
0
class B2GMixin(object):
    profileDir = None
    userJS = "/data/local/user.js"
    marionette = None

    def __init__(self, host=None, marionetteHost=None, marionettePort=2828,
                 **kwargs):

        # (allowing marionneteHost to be specified seems a bit
        # counter-intuitive since we normally get it below from the ip
        # address, however we currently need it to be able to connect
        # via adb port forwarding and localhost)
        if marionetteHost:
            self.marionetteHost = marionetteHost
        elif host:
            self.marionetteHost = host
        self.marionettePort = marionettePort

    def cleanup(self):
        """
        If a user profile was setup on the device, restore it to the original.
        """
        if self.profileDir:
            self.restoreProfile()

    def waitForPort(self, timeout):
        """Waits for the marionette server to respond, until the timeout specified.

	:param timeout: Timeout parameter in seconds.
        """
        print "waiting for port"
        starttime = datetime.datetime.now()
        while datetime.datetime.now() - starttime < datetime.timedelta(seconds=timeout):
            try:
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                print "trying %s %s" % (self.marionettePort, self.marionetteHost)
                sock.connect((self.marionetteHost, self.marionettePort))
                data = sock.recv(16)
                sock.close()
                if '"from"' in data:
                    return True
            except socket.error:
                pass
            except Exception as e:
                raise DMError("Could not connect to marionette: %s" % e)
            time.sleep(1)
        raise DMError("Could not communicate with Marionette port")

    def setupMarionette(self, scriptTimeout=60000):
        """
        Starts a marionette session.
        If no host was given at init, the ip of the device will be retrieved
        and networking will be established.
        """
        if not self.marionetteHost:
            self.setupDHCP()
            self.marionetteHost = self.getIP()
        if not self.marionette:
            self.marionette = Marionette(self.marionetteHost, self.marionettePort)
        if not self.marionette.session:
            self.waitForPort(30)
            self.marionette.start_session()

        self.marionette.set_script_timeout(scriptTimeout)

    def restartB2G(self):
        """
        Restarts the b2g process on the device.
        """
        #restart b2g so we start with a clean slate
        if self.marionette and self.marionette.session:
            self.marionette.delete_session()
        self.shellCheckOutput(['stop', 'b2g'])
        # Wait for a bit to make sure B2G has completely shut down.
        tries = 10
        while "b2g" in self.shellCheckOutput(['ps', 'b2g']) and tries > 0:
            tries -= 1
            time.sleep(1)
        if tries == 0:
            raise DMError("Could not kill b2g process")
        self.shellCheckOutput(['start', 'b2g'])

    def setupProfile(self, prefs=None):
        """Sets up the user profile on the device.

        :param prefs: String of user_prefs to add to the profile. Defaults to a standard b2g testing profile.
        """
        # currently we have no custom prefs to set (when bug 800138 is fixed,
        # we will probably want to enable marionette on an external ip by
        # default)
        if not prefs:
            prefs = ""

        #remove previous user.js if there is one
        if not self.profileDir:
            self.profileDir = tempfile.mkdtemp()
        our_userJS = os.path.join(self.profileDir, "user.js")
        mozfile.remove(our_userJS)
        #copy profile
        try:
            self.getFile(self.userJS, our_userJS)
        except subprocess.CalledProcessError:
            pass
        #if we successfully copied the profile, make a backup of the file
        if os.path.exists(our_userJS):
            self.shellCheckOutput(['dd', 'if=%s' % self.userJS, 'of=%s.orig' % self.userJS])
        with open(our_userJS, 'a') as user_file:
            user_file.write("%s" % prefs)

        self.pushFile(our_userJS, self.userJS)
        self.restartB2G()
        self.setupMarionette()

    def setupDHCP(self, interfaces=['eth0', 'wlan0']):
        """Sets up networking.

        :param interfaces: Network connection types to try. Defaults to eth0 and wlan0.
        """
        all_interfaces = [line.split()[0] for line in \
                          self.shellCheckOutput(['netcfg']).splitlines()[1:]]
        interfaces_to_try = filter(lambda i: i in interfaces, all_interfaces)

        tries = 5
        print "Setting up DHCP..."
        while tries > 0:
            print "attempts left: %d" % tries
            try:
                for interface in interfaces_to_try:
                    self.shellCheckOutput(['netcfg', interface, 'dhcp'],
                                          timeout=10)
                    if self.getIP(interfaces=[interface]):
                        return
            except DMError:
                pass
            time.sleep(1)
            tries -= 1
        raise DMError("Could not set up network connection")

    def restoreProfile(self):
        """
        Restores the original user profile on the device.
        """
        if not self.profileDir:
            raise DMError("There is no profile to restore")
        #if we successfully copied the profile, make a backup of the file
        our_userJS = os.path.join(self.profileDir, "user.js")
        if os.path.exists(our_userJS):
            self.shellCheckOutput(['dd', 'if=%s.orig' % self.userJS, 'of=%s' % self.userJS])
        mozfile.remove(self.profileDir)
        self.profileDir = None

    def getAppInfo(self):
        """
        Returns the appinfo, with an additional "date" key.

        :rtype: dictionary
        """
        if not self.marionette or not self.marionette.session:
            self.setupMarionette()
        self.marionette.set_context("chrome")
        appinfo = self.marionette.execute_script("""
                                var appInfo = Components.classes["@mozilla.org/xre/app-info;1"]
                                .getService(Components.interfaces.nsIXULAppInfo);
                                return appInfo;
                                """)
        (year, month, day) = (appinfo["appBuildID"][0:4], appinfo["appBuildID"][4:6], appinfo["appBuildID"][6:8])
        appinfo['date'] =  "%s-%s-%s" % (year, month, day)
        return appinfo
Exemplo n.º 13
0
Arquivo: gcli.py Projeto: bjacob/gaia
class GCli(object):

    def __init__(self):
        self.commands = {
            'connectwifi': {
                'function': self.connect_to_wifi,
                'args': [
                    {'name': 'ssid',
                     'help': 'SSID of the network to connect to'},
                    {'name': '--security',
                     'choices': ['WPA-PSK', 'WEP'],
                     'help': 'Security model of the network'},
                    {'name': '--password',
                     'help': 'Password to access the network'}],
                'help': 'Connect to a WiFi network'},
            'disablewifi': {
                'function': self.disable_wifi,
                'help': 'Disable WiFi'},
            'enablewifi': {
                'function': self.enable_wifi,
                'help': 'Enable WiFi'},
            'forgetallwifi': {
                'function': self.forget_all_wifi_networks,
                'help': 'Forget all WiFi networks'},
            'getknownwifi': {
                'function': self.known_wifi_networks,
                'help': 'Show known WiFi networks'},
            'getsetting': {
                'function': self.get_setting,
                'args': [{
                    'name': 'name',
                    'help': 'Name of the setting to retrieve'}],
                'help': 'Show the current value of a setting'},
            'holdhome': {
                'function': self.hold_home,
                'help': 'Simulate holding the home button'},
            'holdsleep': {
                'function': self.hold_sleep,
                'help': 'Simulate holding the sleep button'},
            'home': {
                'function': self.home,
                'help': 'Simulate pressing the home button'},
            'killapps': {
                'function': self.kill_all_apps,
                'help': 'Kill all running apps'},
            'launchapp': {
                'function': self.launch_app,
                'args': [
                    {'name': 'name',
                     'nargs': argparse.REMAINDER,
                     'help': 'Name of app to launch'}],
                'help': 'Launch an application'},
            'lock': {
                'function': self.lock,
                'help': 'Lock screen'},
            'screenshot': {
                'function': self.screenshot,
                'help': 'Take a screenshot'},
            'sendsms': {
                'function': self.send_sms,
                'args': [
                    {'name': 'number',
                     'help': 'Phone number of recipient'},
                    {'name': 'message',
                     'help': 'Message content'}],
                'help': 'Send an SMS'},
            'setsetting': {
                'function': self.set_setting,
                'args': [
                    {'name': 'name',
                     'help': 'Name of setting to change'},
                    {'name': 'value',
                     'help': 'New value for setting'}],
                'help': 'Change the value of a setting'},
            'sleep': {
                'function': self.sleep,
                'help': 'Enter sleep mode'},
            'unlock': {
                'function': self.unlock,
                'help': 'Unlock screen'},
            'volume': {
                'function': self.volume,
                'args': [
                    {'name': 'direction',
                     'choices': ['down', 'up'],
                     'help': 'Direction to change the volume'}],
                'help': 'Change the volume'},
            'wake': {
                'function': self.wake,
                'help': 'Wake from sleep mode'}}

        self.parser = argparse.ArgumentParser()
        self.add_options(self.parser)
        self.add_commands(self.parser)

    def run(self, args=sys.argv[1:]):
        args = self.parser.parse_args()

        host, port = args.address.split(':')
        self.marionette = Marionette(host=host, port=int(port))
        self.marionette.start_session()

        self.apps = gaiatest.GaiaApps(self.marionette)
        self.data_layer = gaiatest.GaiaData(self.marionette)
        self.lock_screen = gaiatest.LockScreen(self.marionette)

        ret = args.func(args)
        if ret is None:
            ret = 0

        self.marionette.delete_session()

        sys.exit(ret)

    def add_options(self, parser):
        parser.add_argument(
            '--address',
            default='localhost:2828',
            help='Address (host:port) of running Gecko instance to connect to '
                 '(default: %(default)s)')

    def add_commands(self, parser):
        subparsers = parser.add_subparsers(
            title='Commands', metavar='<command>')
        for (name, props) in sorted(self.commands.iteritems()):
            subparser = subparsers.add_parser(name, help=props['help'])
            if props.get('args'):
                for arg in props['args']:
                    kwargs = {k: v for k, v in arg.items() if k is not 'name'}
                    subparser.add_argument(arg['name'], **kwargs)
            subparser.set_defaults(func=props['function'])

    def connect_to_wifi(self, args):
        network = {
            'ssid': args.ssid,
            'keyManagement': args.security or 'NONE'}
        if args.security == 'WEP':
            network['wep'] = args.password
        elif args.security == 'WPA-PSK':
            network['psk'] = args.password
        self.data_layer.connect_to_wifi(network)

    def disable_wifi(self, args):
        self.data_layer.disable_wifi()

    def enable_wifi(self, args):
        self.data_layer.enable_wifi()

    def forget_all_wifi_networks(self, args):
        self.data_layer.forget_all_networks()

    def get_setting(self, args):
        print '%s: %s' % (
            args.name,
            self.data_layer.get_setting(args.name))

    def home(self, args):
        self.marionette.execute_script(
            "window.wrappedJSObject.dispatchEvent(new Event('home'));")

    def hold_home(self, args):
        self.marionette.execute_script(
            "window.wrappedJSObject.dispatchEvent(new Event('holdhome'));")

    def hold_sleep(self, args):
        self.marionette.execute_script(
            "window.wrappedJSObject.dispatchEvent(new Event('holdsleep'));")

    def kill_all_apps(self, args):
        self.apps.kill_all()

    def known_wifi_networks(self, args):
        networks = [n for n in self.data_layer.known_networks if 'ssid' in n]
        if len(networks) > 0:
            for i, network in enumerate(networks):
                print '%s: %s' % (i + 1, network['ssid'])
        else:
            print 'No known networks.'

    def launch_app(self, args):
        for name in args.name:
            self.apps.launch(name)

    def lock(self, args):
        self.lock_screen.lock()

    def screenshot(self, args):
        self.marionette.execute_script(
            "window.wrappedJSObject.dispatchEvent(new Event('home+sleep'));")

    def send_sms(self, args):
        self.data_layer.send_sms(args.number, args.message)

    def set_setting(self, args):
        self.data_layer.set_setting(args.name, args.value)

    def sleep(self, args):
        self.marionette.execute_script(
            "window.wrappedJSObject.dispatchEvent(new Event('sleep'));")

    def unlock(self, args):
        self.lock_screen.unlock()

    def volume(self, args):
        self.marionette.execute_script(
            "window.wrappedJSObject.dispatchEvent(new Event('volume%s'));" %
            args.direction)

    def wake(self, args):
        self.marionette.execute_script(
            "window.wrappedJSObject.dispatchEvent(new Event('wake'));")
Exemplo n.º 14
0
class B2GMochitest(MochitestUtilsMixin):
    marionette = None

    def __init__(self,
                 marionette_args,
                 out_of_process=True,
                 profile_data_dir=None,
                 locations=os.path.join(here, 'server-locations.txt')):
        super(B2GMochitest, self).__init__()
        self.marionette_args = marionette_args
        self.out_of_process = out_of_process
        self.locations_file = locations
        self.preferences = []
        self.webapps = None
        self.test_script = os.path.join(here, 'b2g_start_script.js')
        self.test_script_args = [self.out_of_process]
        self.product = 'b2g'

        if profile_data_dir:
            self.preferences = [
                os.path.join(profile_data_dir, f)
                for f in os.listdir(profile_data_dir) if f.startswith('pref')
            ]
            self.webapps = [
                os.path.join(profile_data_dir, f)
                for f in os.listdir(profile_data_dir) if f.startswith('webapp')
            ]

        # mozinfo is populated by the parent class
        if mozinfo.info['debug']:
            self.SERVER_STARTUP_TIMEOUT = 180
        else:
            self.SERVER_STARTUP_TIMEOUT = 90

    def setup_common_options(self, options):
        test_url = self.buildTestPath(options)
        # For B2G emulators buildURLOptions has been called
        # without calling buildTestPath first and that
        # causes manifestFile not to be set
        if not "manifestFile=tests.json" in self.urlOpts:
            self.urlOpts.append("manifestFile=%s" % options.manifestFile)

        if len(self.urlOpts) > 0:
            test_url += "?" + "&".join(self.urlOpts)
        self.test_script_args.append(test_url)

    def buildTestPath(self, options):
        if options.manifestFile != 'tests.json':
            super(B2GMochitest, self).buildTestPath(options, disabled=False)
        return self.buildTestURL(options)

    def build_profile(self, options):
        # preferences
        prefs = {}
        for path in self.preferences:
            prefs.update(Preferences.read_prefs(path))

        for v in options.extraPrefs:
            thispref = v.split("=", 1)
            if len(thispref) < 2:
                print "Error: syntax error in --setpref=" + v
                sys.exit(1)
            prefs[thispref[0]] = thispref[1]

        # interpolate the preferences
        interpolation = {
            "server": "%s:%s" % (options.webServer, options.httpPort),
            "OOP": "true" if self.out_of_process else "false"
        }
        prefs = json.loads(json.dumps(prefs) % interpolation)
        for pref in prefs:
            prefs[pref] = Preferences.cast(prefs[pref])

        kwargs = {
            'addons': self.getExtensionsToInstall(options),
            'apps': self.webapps,
            'locations': self.locations_file,
            'preferences': prefs,
            'proxy': {
                "remote": options.webServer
            }
        }

        if options.profile:
            self.profile = Profile.clone(options.profile, **kwargs)
        else:
            self.profile = Profile(**kwargs)

        options.profilePath = self.profile.profile
        # TODO bug 839108 - mozprofile should probably handle this
        manifest = self.addChromeToProfile(options)
        self.copyExtraFilesToProfile(options)
        return manifest

    def run_tests(self, options):
        """ Prepare, configure, run tests and cleanup """

        manifest = self.build_profile(options)
        self.leak_report_file = os.path.join(options.profilePath,
                                             "runtests_leaks.log")

        if options.debugger or not options.autorun:
            timeout = None
        else:
            if not options.timeout:
                if mozinfo.info['debug']:
                    options.timeout = 420
                else:
                    options.timeout = 300
            timeout = options.timeout + 30.0

        log.info("runtestsb2g.py | Running tests: start.")
        status = 0
        try:
            self.marionette_args['profile'] = self.profile
            self.marionette = Marionette(**self.marionette_args)
            self.runner = self.marionette.runner
            self.app_ctx = self.runner.app_ctx

            self.remote_log = posixpath.join(self.app_ctx.remote_test_root,
                                             'log', 'mochitest.log')
            if not self.app_ctx.dm.dirExists(posixpath.dirname(
                    self.remote_log)):
                self.app_ctx.dm.mkDirs(self.remote_log)

            self.startServers(options, None)
            self.buildURLOptions(options, {'MOZ_HIDE_RESULTS_TABLE': '1'})
            self.test_script_args.append(not options.emulator)
            self.test_script_args.append(options.wifi)

            self.runner.start(outputTimeout=timeout)

            self.marionette.wait_for_port()
            self.marionette.start_session()
            self.marionette.set_context(self.marionette.CONTEXT_CHROME)

            # Disable offline status management (bug 777145), otherwise the network
            # will be 'offline' when the mochitests start.  Presumably, the network
            # won't be offline on a real device, so we only do this for emulators.
            self.marionette.execute_script("""
                Components.utils.import("resource://gre/modules/Services.jsm");
                Services.io.manageOfflineStatus = false;
                Services.io.offline = false;
                """)

            if os.path.isfile(self.test_script):
                with open(self.test_script, 'r') as script:
                    self.marionette.execute_script(
                        script.read(), script_args=self.test_script_args)
            else:
                self.marionette.execute_script(
                    self.test_script, script_args=self.test_script_args)
            status = self.runner.wait()
            if status is None:
                # the runner has timed out
                status = 124
        except KeyboardInterrupt:
            log.info("runtests.py | Received keyboard interrupt.\n")
            status = -1
        except:
            traceback.print_exc()
            log.error(
                "Automation Error: Received unexpected exception while running application\n"
            )
            if hasattr(self, 'runner'):
                self.runner.check_for_crashes()
            status = 1

        self.stopServers()

        log.info("runtestsb2g.py | Running tests: end.")

        if manifest is not None:
            self.cleanup(manifest, options)
        return status
Exemplo n.º 15
0
# The Initial Developer of the Original Code is
#   Mozilla Foundation.
# Portions created by the Initial Developer are Copyright (C) 2011
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#  Jonathan Griffin <*****@*****.**>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****

from marionette import Marionette, HTMLElement

if __name__ == '__main__':

    # launch Fennec with Marionette before starting this test!
    m = Marionette(host='localhost', port=2828)
    assert (m.start_session())
    assert (10 == m.execute_script('return 10;'))
Exemplo n.º 16
0
class B2GMixin(object):
    profileDir = None
    userJS = "/data/local/user.js"
    marionette = None

    def __init__(self, host=None, marionette_port=2828, **kwargs):
        self.marionetteHost = host
        self.marionettePort = marionette_port

    def cleanup(self):
        if self.profileDir:
            self.restoreProfile()

    def waitForPort(self, timeout):
        """
        Wait for the marionette server to respond.
        Timeout parameter is in seconds
        """
        print "waiting for port"
        starttime = datetime.datetime.now()
        while datetime.datetime.now() - starttime < datetime.timedelta(
                seconds=timeout):
            try:
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                print "trying %s %s" % (self.marionettePort,
                                        self.marionetteHost)
                sock.connect((self.marionetteHost, self.marionettePort))
                data = sock.recv(16)
                sock.close()
                if '"from"' in data:
                    return True
            except socket.error:
                pass
            except Exception as e:
                raise DMError("Could not connect to marionette: %s" % e)
            time.sleep(1)
        raise DMError("Could not communicate with Marionette port")

    def setupMarionette(self):
        """
        Start a marionette session.
        If no host is given, then this will get the ip
        of the device, and set up networking if needed.
        """
        if not self.marionetteHost:
            self.setupDHCP()
            self.marionetteHost = self.getIP()
        if not self.marionette:
            self.marionette = Marionette(self.marionetteHost,
                                         self.marionettePort)
        if not self.marionette.session:
            self.waitForPort(30)
            self.marionette.start_session()

    def restartB2G(self):
        """
        Restarts the b2g process on the device
        """
        #restart b2g so we start with a clean slate
        if self.marionette and self.marionette.session:
            self.marionette.delete_session()
        self.shellCheckOutput(['stop', 'b2g'])
        # Wait for a bit to make sure B2G has completely shut down.
        tries = 10
        while "b2g" in self.shellCheckOutput(['ps', 'b2g']) and tries > 0:
            tries -= 1
            time.sleep(1)
        if tries == 0:
            raise DMError("Could not kill b2g process")
        self.shellCheckOutput(['start', 'b2g'])

    def setupProfile(self, prefs=None):
        """
        Sets up the user profile on the device,
        The 'prefs' is a string of user_prefs to add to the profile.
        If it is not set, it will default to a standard b2g testing profile.
        """
        if not prefs:
            prefs = """
user_pref("power.screen.timeout", 999999);
user_pref("devtools.debugger.force-local", false);
            """
        #remove previous user.js if there is one
        if not self.profileDir:
            self.profileDir = tempfile.mkdtemp()
        our_userJS = os.path.join(self.profileDir, "user.js")
        if os.path.exists(our_userJS):
            os.remove(our_userJS)
        #copy profile
        try:
            output = self.getFile(self.userJS, our_userJS)
        except subprocess.CalledProcessError:
            pass
        #if we successfully copied the profile, make a backup of the file
        if os.path.exists(our_userJS):
            self.shellCheckOutput(
                ['dd', 'if=%s' % self.userJS,
                 'of=%s.orig' % self.userJS])
        with open(our_userJS, 'a') as user_file:
            user_file.write("%s" % prefs)
        self.pushFile(our_userJS, self.userJS)
        self.restartB2G()
        self.setupMarionette()

    def setupDHCP(self, conn_type='eth0'):
        """
        Sets up networking.

        If conn_type is not set, it will assume eth0.
        """
        tries = 5
        while tries > 0:
            print "attempts left: %d" % tries
            try:
                self.shellCheckOutput(['netcfg', conn_type, 'dhcp'],
                                      timeout=10)
                if self.getIP():
                    return
            except DMError:
                pass
            tries = tries - 1
        raise DMError("Could not set up network connection")

    def restoreProfile(self):
        """
        Restores the original profile
        """
        if not self.profileDir:
            raise DMError("There is no profile to restore")
        #if we successfully copied the profile, make a backup of the file
        our_userJS = os.path.join(self.profileDir, "user.js")
        if os.path.exists(our_userJS):
            self.shellCheckOutput(
                ['dd', 'if=%s.orig' % self.userJS,
                 'of=%s' % self.userJS])
        shutil.rmtree(self.profileDir)
        self.profileDir = None

    def getAppInfo(self):
        """
        Returns the appinfo, with an additional "date" key.
        """
        if not self.marionette or not self.marionette.session:
            self.setupMarionette()
        self.marionette.set_context("chrome")
        appinfo = self.marionette.execute_script("""
                                var appInfo = Components.classes["@mozilla.org/xre/app-info;1"]
                                .getService(Components.interfaces.nsIXULAppInfo);
                                return appInfo;
                                """)
        (year, month,
         day) = (appinfo["appBuildID"][0:4], appinfo["appBuildID"][4:6],
                 appinfo["appBuildID"][6:8])
        appinfo['date'] = "%s-%s-%s" % (year, month, day)
        return appinfo
Exemplo n.º 17
0
Arquivo: gcli.py Projeto: bjacob/gaia
class GCli(object):
    def __init__(self):
        self.commands = {
            "connectwifi": {
                "function": self.connect_to_wifi,
                "args": [
                    {"name": "ssid", "help": "SSID of the network to connect to"},
                    {"name": "--security", "choices": ["WPA-PSK", "WEP"], "help": "Security model of the network"},
                    {"name": "--password", "help": "Password to access the network"},
                ],
                "help": "Connect to a WiFi network",
            },
            "disablewifi": {"function": self.disable_wifi, "help": "Disable WiFi"},
            "enablewifi": {"function": self.enable_wifi, "help": "Enable WiFi"},
            "forgetallwifi": {"function": self.forget_all_wifi_networks, "help": "Forget all WiFi networks"},
            "getknownwifi": {"function": self.known_wifi_networks, "help": "Show known WiFi networks"},
            "getsetting": {
                "function": self.get_setting,
                "args": [{"name": "name", "help": "Name of the setting to retrieve"}],
                "help": "Show the current value of a setting",
            },
            "holdhome": {"function": self.hold_home, "help": "Simulate holding the home button"},
            "holdsleep": {"function": self.hold_sleep, "help": "Simulate holding the sleep button"},
            "home": {"function": self.home, "help": "Simulate pressing the home button"},
            "killapps": {"function": self.kill_all_apps, "help": "Kill all running apps"},
            "launchapp": {
                "function": self.launch_app,
                "args": [{"name": "name", "nargs": argparse.REMAINDER, "help": "Name of app to launch"}],
                "help": "Launch an application",
            },
            "lock": {"function": self.lock, "help": "Lock screen"},
            "screenshot": {"function": self.screenshot, "help": "Take a screenshot"},
            "sendsms": {
                "function": self.send_sms,
                "args": [
                    {"name": "number", "help": "Phone number of recipient"},
                    {"name": "message", "help": "Message content"},
                ],
                "help": "Send an SMS",
            },
            "setsetting": {
                "function": self.set_setting,
                "args": [
                    {"name": "name", "help": "Name of setting to change"},
                    {"name": "value", "help": "New value for setting"},
                ],
                "help": "Change the value of a setting",
            },
            "sleep": {"function": self.sleep, "help": "Enter sleep mode"},
            "unlock": {"function": self.unlock, "help": "Unlock screen"},
            "volume": {
                "function": self.volume,
                "args": [{"name": "direction", "choices": ["down", "up"], "help": "Direction to change the volume"}],
                "help": "Change the volume",
            },
            "wake": {"function": self.wake, "help": "Wake from sleep mode"},
        }

        self.parser = argparse.ArgumentParser()
        self.add_options(self.parser)
        self.add_commands(self.parser)

    def run(self, args=sys.argv[1:]):
        args = self.parser.parse_args()

        host, port = args.address.split(":")
        self.marionette = Marionette(host=host, port=int(port))
        self.marionette.start_session()

        self.apps = gaiatest.GaiaApps(self.marionette)
        self.data_layer = gaiatest.GaiaData(self.marionette)
        self.lock_screen = gaiatest.LockScreen(self.marionette)

        ret = args.func(args)
        if ret is None:
            ret = 0

        self.marionette.delete_session()

        sys.exit(ret)

    def add_options(self, parser):
        parser.add_argument(
            "--address",
            default="localhost:2828",
            help="Address (host:port) of running Gecko instance to connect to " "(default: %(default)s)",
        )

    def add_commands(self, parser):
        subparsers = parser.add_subparsers(title="Commands", metavar="<command>")
        for (name, props) in sorted(self.commands.iteritems()):
            subparser = subparsers.add_parser(name, help=props["help"])
            if props.get("args"):
                for arg in props["args"]:
                    kwargs = {k: v for k, v in arg.items() if k is not "name"}
                    subparser.add_argument(arg["name"], **kwargs)
            subparser.set_defaults(func=props["function"])

    def connect_to_wifi(self, args):
        network = {"ssid": args.ssid, "keyManagement": args.security or "NONE"}
        if args.security == "WEP":
            network["wep"] = args.password
        elif args.security == "WPA-PSK":
            network["psk"] = args.password
        self.data_layer.connect_to_wifi(network)

    def disable_wifi(self, args):
        self.data_layer.disable_wifi()

    def enable_wifi(self, args):
        self.data_layer.enable_wifi()

    def forget_all_wifi_networks(self, args):
        self.data_layer.forget_all_networks()

    def get_setting(self, args):
        print "%s: %s" % (args.name, self.data_layer.get_setting(args.name))

    def home(self, args):
        self.marionette.execute_script("window.wrappedJSObject.dispatchEvent(new Event('home'));")

    def hold_home(self, args):
        self.marionette.execute_script("window.wrappedJSObject.dispatchEvent(new Event('holdhome'));")

    def hold_sleep(self, args):
        self.marionette.execute_script("window.wrappedJSObject.dispatchEvent(new Event('holdsleep'));")

    def kill_all_apps(self, args):
        self.apps.kill_all()

    def known_wifi_networks(self, args):
        networks = [n for n in self.data_layer.known_networks if "ssid" in n]
        if len(networks) > 0:
            for i, network in enumerate(networks):
                print "%s: %s" % (i + 1, network["ssid"])
        else:
            print "No known networks."

    def launch_app(self, args):
        for name in args.name:
            self.apps.launch(name)

    def lock(self, args):
        self.lock_screen.lock()

    def screenshot(self, args):
        self.marionette.execute_script("window.wrappedJSObject.dispatchEvent(new Event('home+sleep'));")

    def send_sms(self, args):
        self.data_layer.send_sms(args.number, args.message)

    def set_setting(self, args):
        self.data_layer.set_setting(args.name, args.value)

    def sleep(self, args):
        self.marionette.execute_script("window.wrappedJSObject.dispatchEvent(new Event('sleep'));")

    def unlock(self, args):
        self.lock_screen.unlock()

    def volume(self, args):
        self.marionette.execute_script("window.wrappedJSObject.dispatchEvent(new Event('volume%s'));" % args.direction)

    def wake(self, args):
        self.marionette.execute_script("window.wrappedJSObject.dispatchEvent(new Event('wake'));")
Exemplo n.º 18
0
def ftu(locale, device_flags, hashes):

  db = get_db(locale)

  app = 'ftu'
  app_categ = 'communications'
  app_type = 'apps'
  gaia_hash = hashes[0]
  hg_hash = hashes[1]
  screenshot_path = app_type + '/' + app_categ + '/' + app

  create_screenshot_dir(locale, screenshot_path)

  client = Marionette('localhost', 2828)
  client.start_session()

  change_screen_timeout(client) 

  ftu_iframe = client.find_element('css selector',"iframe[src='app://communications.gaiamobile.org/ftu/index.html']")

  if client.switch_to_frame(ftu_iframe):

    time.sleep(short_time)

    # app://communications.gaiamobile.org/ftu/index.html#languages 
    file_name = 'languages'
    screenshot_entry = {
      "id" : file_name,
      "script" : app,
      "gaia" : gaia_hash,
      "hg" : hg_hash,
      "changed" : False,
      "path" : screenshot_path}
    test_flags = {}
    if check_flags(test_flags, device_flags):
      screenshot_entry.update(test_flags)
      if take_screenshot(locale, screenshot_path, client, file_name):
        screenshot_entry['changed'] = True
      log_displayed_l10n_strings(client, db, app, app_categ, screenshot_entry, '#activation-screen')


      # switch to app://communications.gaiamobile.org/ftu/index.html#data_3g (unlock-sim-screen screen)
      next = client.find_element('css selector', '#forward')
      next.tap()
      time.sleep(short_time)

    # app://communications.gaiamobile.org/ftu/index.html#data_3g (sim pin screen - unlock-sim-screen - 1st attempt)
    file_name = 'data_3g-unlock_sim_screen-pin_screen'
    screenshot_entry = {
      "id" : file_name,
      "script" : app,
      "gaia" : gaia_hash,
      "hg" : hg_hash,
      "changed" : False,
      "path" : screenshot_path}
    test_flags = {
      "sim": True,
      "no-sim": False}
    if check_flags(test_flags, device_flags):
      screenshot_entry.update(test_flags)
      if take_screenshot(locale, screenshot_path, client, file_name):
        screenshot_entry['changed'] = True
      log_displayed_l10n_strings(client, db, app, app_categ, screenshot_entry, '#unlock-sim-screen')


      # invalid pin -> error about pin characters
      # stay at app://communications.gaiamobile.org/ftu/index.html#data_3g (unlock-sim-screen screen)
      next = client.find_element('css selector', '#unlock-sim-button')
      next.tap()
      time.sleep(short_time)

    # app://communications.gaiamobile.org/ftu/index.html#data_3g (sim pin screen - unlock-sim-screen - pin error)
    file_name = 'data_3g-unlock_sim_screen-pin_screen-invalid_pin'
    screenshot_entry = {
      "id" : file_name,
      "script" : app,
      "gaia" : gaia_hash,
      "hg" : hg_hash,
      "changed" : False,
      "path" : screenshot_path}
    test_flags = {
      "sim": True,
      "no-sim": False}
    if check_flags(test_flags, device_flags):
      screenshot_entry.update(test_flags)
      if take_screenshot(locale, screenshot_path, client, file_name):
        screenshot_entry['changed'] = True
      log_displayed_l10n_strings(client, db, app, app_categ, screenshot_entry, '#unlock-sim-screen')


      # insert wrong pin (attempt 1 of 3)
      pin_input = client.find_element('css selector', '#pin-input')
      pin_input.send_keys(wrong_sim_pin)

      # stay at app://communications.gaiamobile.org/ftu/index.html#data_3g (unlock-sim-screen screen)
      next = client.find_element('css selector', '#unlock-sim-button')
      next.tap()
      time.sleep(short_time)
    
    # app://communications.gaiamobile.org/ftu/index.html#data_3g (sim pin screen - unlock-sim-screen - 2nd attempt)
    file_name = 'data_3g-unlock_sim_screen-pin_screen-wrong_pin-1st_time'
    screenshot_entry = {
      "id" : file_name,
      "script" : app,
      "gaia" : gaia_hash,
      "hg" : hg_hash,
      "changed" : False,
      "path" : screenshot_path}
    test_flags = {
      "sim": True,
      "no-sim": False}
    if check_flags(test_flags, device_flags):
      screenshot_entry.update(test_flags)
      if take_screenshot(locale, screenshot_path, client, file_name):
        screenshot_entry['changed'] = True
      log_displayed_l10n_strings(client, db, app, app_categ, screenshot_entry, '#unlock-sim-screen')


      # insert wrong pin (attempt 2 of 3)
      pin_input = client.find_element('css selector', '#pin-input')
      pin_input.send_keys(wrong_sim_pin)

      # stay at app://communications.gaiamobile.org/ftu/index.html#data_3g (unlock-sim-screen screen)
      next = client.find_element('css selector', '#unlock-sim-button')
      next.tap()
      time.sleep(short_time)

    # app://communications.gaiamobile.org/ftu/index.html#data_3g (sim pin screen - unlock-sim-screen - 3rd attempt)
    file_name = 'data_3g-unlock_sim_screen-pin_screen-wrong_pin-2nd_time'
    screenshot_entry = {
      "id" : file_name,
      "script" : app,
      "gaia" : gaia_hash,
      "hg" : hg_hash,
      "changed" : False,
      "path" : screenshot_path}
    test_flags = {
      "sim": True,
      "no-sim": False}
    if check_flags(test_flags, device_flags):
      screenshot_entry.update(test_flags)
      if take_screenshot(locale, screenshot_path, client, file_name):
        screenshot_entry['changed'] = True
      log_displayed_l10n_strings(client, db, app, app_categ, screenshot_entry, '#unlock-sim-screen')


      # insert wrong pin (atempt 3 of 3) - continues to puk screen
      pin_input = client.find_element('css selector', '#pin-input')
      pin_input.send_keys(wrong_sim_pin)

      # switch to app://communications.gaiamobile.org/ftu/index.html#data_3g (sim puk screen - unlock-sim-screen)
      next = client.find_element('css selector', '#unlock-sim-button')
      next.tap()
      time.sleep(short_time)

      # tap the header in order to hide keyboard and get full screenshot of the puk screen
      header = client.find_element('css selector', '#unlock-sim-header')
      header.tap()

    # app://communications.gaiamobile.org/ftu/index.html#data_3g (sim puk screen - unlock-sim-screen - 1st attempt)
    file_name = 'data_3g-unlock_sim_screen-puk_screen'
    screenshot_entry = {
      "id" : file_name,
      "script" : app,
      "gaia" : gaia_hash,
      "hg" : hg_hash,
      "changed" : False,
      "path" : screenshot_path}
    test_flags = {
      "sim": True,
      "no-sim": False}
    if check_flags(test_flags, device_flags):
      screenshot_entry.update(test_flags)
      if take_screenshot(locale, screenshot_path, client, file_name):
        screenshot_entry['changed'] = True
      log_displayed_l10n_strings(client, db, app, app_categ, screenshot_entry, '#unlock-sim-screen')


      # invalid puk -> error about puk characters
      # stay at app://communications.gaiamobile.org/ftu/index.html#data_3g (sim puk screen - unlock-sim-screen)
      next = client.find_element('css selector', '#unlock-sim-button')
      next.tap()
      time.sleep(short_time)

    # app://communications.gaiamobile.org/ftu/index.html#data_3g (sim puk screen - unlock-sim-screen - puk error)
    file_name = 'data_3g-unlock_sim_screen-puk_screen-invalid_puk'
    screenshot_entry = {
      "id" : file_name,
      "script" : app,
      "gaia" : gaia_hash,
      "hg" : hg_hash,
      "changed" : False,
      "path" : screenshot_path}
    test_flags = {
      "sim": True,
      "no-sim": False}
    if check_flags(test_flags, device_flags):
      screenshot_entry.update(test_flags)
      if take_screenshot(locale, screenshot_path, client, file_name):
        screenshot_entry['changed'] = True
      log_displayed_l10n_strings(client, db, app, app_categ, screenshot_entry, '#unlock-sim-screen')


      # insert wrong puk - invalid new pin -> error about pin characters
      puk_input = client.find_element('css selector', '#puk-input')
      puk_input.send_keys(wrong_sim_puk)

      # stay at app://communications.gaiamobile.org/ftu/index.html#data_3g (sim puk screen - unlock-sim-screen)
      next = client.find_element('css selector', '#unlock-sim-button')
      next.tap()
      time.sleep(short_time)

    # app://communications.gaiamobile.org/ftu/index.html#data_3g (sim puk screen - unlock-sim-screen - pin error)
    file_name = 'data_3g-unlock_sim_screen-puk_screen-invalid_new_pin'
    screenshot_entry = {
      "id" : file_name,
      "script" : app,
      "gaia" : gaia_hash,
      "hg" : hg_hash,
      "changed" : False,
      "path" : screenshot_path}
    test_flags = {
      "sim": True,
      "no-sim": False}
    if check_flags(test_flags, device_flags):
      screenshot_entry.update(test_flags)
      if take_screenshot(locale, screenshot_path, client, file_name):
        screenshot_entry['changed'] = True
      log_displayed_l10n_strings(client, db, app, app_categ, screenshot_entry, '#unlock-sim-screen')


      # insert new pin without confirmed it -> error about pin confirmation (wrong puk is preserved at its input)
      newpin_input = client.find_element('css selector', '#newpin-input')
      newpin_input.send_keys(sim_pin)

      # stay at app://communications.gaiamobile.org/ftu/index.html#data_3g (sim puk screen - unlock-sim-screen)
      next = client.find_element('css selector', '#unlock-sim-button')
      next.tap()
      time.sleep(short_time)

    # app://communications.gaiamobile.org/ftu/index.html#data_3g (sim puk screen - unlock-sim-screen - pin error)
    file_name = 'data_3g-unlock_sim_screen-puk_screen-invalid_new_pin_confirmation'
    screenshot_entry = {
      "id" : file_name,
      "script" : app,
      "gaia" : gaia_hash,
      "hg" : hg_hash,
      "changed" : False,
      "path" : screenshot_path}
    test_flags = {
      "sim": True,
      "no-sim": False}
    if check_flags(test_flags, device_flags):
      screenshot_entry.update(test_flags)
      if take_screenshot(locale, screenshot_path, client, file_name):
        screenshot_entry['changed'] = True
      log_displayed_l10n_strings(client, db, app, app_categ, screenshot_entry, '#unlock-sim-screen')


      # insert confirmation of the new pin (wrong puk and new pin are preserved at their inputs)
      newpin_input = client.find_element('css selector', '#confirm-newpin-input')
      newpin_input.send_keys(sim_pin)

      # wrong puk (attempt 1 of 9)
      # stay at app://communications.gaiamobile.org/ftu/index.html#data_3g (sim puk screen - unlock-sim-screen)
      next = client.find_element('css selector', '#unlock-sim-button')
      next.tap()
      time.sleep(short_time)

    # app://communications.gaiamobile.org/ftu/index.html#data_3g (sim puk screen - unlock-sim-screen - puk error)
    file_name = 'data_3g-unlock_sim_screen-puk_screen-wrong_puk-1st_time'
    screenshot_entry = {
      "id" : file_name,
      "script" : app,
      "gaia" : gaia_hash,
      "hg" : hg_hash,
      "changed" : False,
      "path" : screenshot_path}
    test_flags = {
      "sim": True,
      "no-sim": False}
    if check_flags(test_flags, device_flags):
      screenshot_entry.update(test_flags)
      if take_screenshot(locale, screenshot_path, client, file_name):
        screenshot_entry['changed'] = True
      log_displayed_l10n_strings(client, db, app, app_categ, screenshot_entry, '#unlock-sim-screen')


      # insert wrong puk (attempt 2 of 9) (new pin and its confirmation are preserved at their inputs)
      puk_input = client.find_element('css selector', '#puk-input')
      puk_input.send_keys(wrong_sim_puk)

      # stay at app://communications.gaiamobile.org/ftu/index.html#data_3g (sim puk screen - unlock-sim-screen)
      next = client.find_element('css selector', '#unlock-sim-button')
      next.tap()
      time.sleep(short_time)

    # app://communications.gaiamobile.org/ftu/index.html#data_3g (sim puk screen - unlock-sim-screen - 2nd attempt)
    file_name = 'data_3g-unlock_sim_screen-puk_screen-wrong_puk-2nd_time'
    screenshot_entry = {
      "id" : file_name,
      "script" : app,
      "gaia" : gaia_hash,
      "hg" : hg_hash,
      "changed" : False,
      "path" : screenshot_path}
    test_flags = {
      "sim": True,
      "no-sim": False}
    if check_flags(test_flags, device_flags):
      screenshot_entry.update(test_flags)
      if take_screenshot(locale, screenshot_path, client, file_name):
        screenshot_entry['changed'] = True
      log_displayed_l10n_strings(client, db, app, app_categ, screenshot_entry, '#unlock-sim-screen')


      # insert right puk (attempt 2 of 9) (new pin and its confirmation are preserved at their inputs)
      puk_input = client.find_element('css selector', '#puk-input')
      puk_input.send_keys(sim_puk)

      # switch to app://communications.gaiamobile.org/ftu/index.html#data_3g
      next = client.find_element('css selector', '#unlock-sim-button')
      next.tap()
      time.sleep(short_time)

    # app://communications.gaiamobile.org/ftu/index.html#data_3g
    file_name = 'data_3g'
    screenshot_entry = {
      "id" : file_name,
      "script" : app,
      "gaia" : gaia_hash,
      "hg" : hg_hash,
      "changed" : False,
      "path" : screenshot_path}
    test_flags = {
      "sim": True,
      "no-sim": False}
    if check_flags(test_flags, device_flags):
      screenshot_entry.update(test_flags)
      if take_screenshot(locale, screenshot_path, client, file_name):
        screenshot_entry['changed'] = True
      log_displayed_l10n_strings(client, db, app, app_categ, screenshot_entry, '#activation-screen')


      # switch to app://communications.gaiamobile.org/ftu/index.html#wifi
      next = client.find_element('css selector', '#forward')
      next.tap()
      time.sleep(long_time)

      # enable overlay "scanningNetworks" spinner screen (loading-overlay)
      client.execute_script("window.wrappedJSObject.utils.overlay.show('scanningNetworks', 'spinner');")
      time.sleep(middle_time)
    
    # overlay "scanningNetworks" spinner screen
    file_name = 'wifi-loading_overlay-scanning_networks'
    screenshot_entry = {
      "id" : file_name,
      "script" : app,
      "gaia" : gaia_hash,
      "hg" : hg_hash,
      "changed" : False,
      "path" : screenshot_path}
    test_flags = {}
    if check_flags(test_flags, device_flags):
      screenshot_entry.update(test_flags)
      if take_screenshot(locale, screenshot_path, client, file_name):
        screenshot_entry['changed'] = True
      log_displayed_l10n_strings(client, db, app, app_categ, screenshot_entry, '#loading-overlay')


      # disable overlay "scanningNetworks" spinner screen
      client.execute_script("window.wrappedJSObject.utils.overlay.hide('scanningNetworks', 'spinner');")
      time.sleep(middle_time)

    # app://communications.gaiamobile.org/ftu/index.html#wifi
    file_name = 'wifi'
    screenshot_entry = {
      "id" : file_name,
      "script" : app,
      "gaia" : gaia_hash,
      "hg" : hg_hash,
      "changed" : False,
      "path" : screenshot_path}
    test_flags = {}
    if check_flags(test_flags, device_flags):
      screenshot_entry.update(test_flags)
      if take_screenshot(locale, screenshot_path, client, file_name):
        screenshot_entry['changed'] = True
      log_displayed_l10n_strings(client, db, app, app_categ, screenshot_entry, '#wifi')


      # switch to app://communications.gaiamobile.org/ftu/index.html#date_and_time
      next = client.find_element('css selector', '#forward')
      next.tap()
      time.sleep(short_time)

    # Set time in order to be the same at every screenshot
    set_time(client)

    # app://communications.gaiamobile.org/ftu/index.html#date_and_time
    file_name = 'date_and_time'
    screenshot_entry = {
      "id" : file_name,
      "script" : app,
      "gaia" : gaia_hash,
      "hg" : hg_hash,
      "changed" : False,
      "path" : screenshot_path}
    test_flags = {}
    if check_flags(test_flags, device_flags):
      screenshot_entry.update(test_flags)
      if take_screenshot(locale, screenshot_path, client, file_name):
        screenshot_entry['changed'] = True
      log_displayed_l10n_strings(client, db, app, app_categ, screenshot_entry, '#date_and_time')


      # switch to app://communications.gaiamobile.org/ftu/index.html#geolocation
      next = client.find_element('css selector', '#forward')
      next.tap()
      time.sleep(short_time)

    # app://communications.gaiamobile.org/ftu/index.html#geolocation
    file_name = 'geolocation'
    screenshot_entry = {
      "id" : file_name,
      "script" : app,
      "gaia" : gaia_hash,
      "hg" : hg_hash,
      "changed" : False,
      "path" : screenshot_path}
    test_flags = {}
    if check_flags(test_flags, device_flags):
      screenshot_entry.update(test_flags)
      if take_screenshot(locale, screenshot_path, client, file_name):
        screenshot_entry['changed'] = True
      log_displayed_l10n_strings(client, db, app, app_categ, screenshot_entry, '#geolocation')


      # switch to app://communications.gaiamobile.org/ftu/index.html#import_contacts
      next = client.find_element('css selector', '#forward')
      next.tap()
      time.sleep(middle_time)

    # app://communications.gaiamobile.org/ftu/index.html#import_contacts
    file_name = 'import_contacts'
    screenshot_entry = {
      "id" : file_name,
      "script" : app,
      "gaia" : gaia_hash,
      "hg" : hg_hash,
      "changed" : False,
      "path" : screenshot_path}
    test_flags = {}
    if check_flags(test_flags, device_flags):
      screenshot_entry.update(test_flags)
      if take_screenshot(locale, screenshot_path, client, file_name):
        screenshot_entry['changed'] = True
      log_displayed_l10n_strings(client, db, app, app_categ, screenshot_entry, '#import_contacts')


      # switch to app://communications.gaiamobile.org/ftu/index.html#welcome_browser
      next = client.find_element('css selector', '#forward')
      next.tap()
      time.sleep(short_time)

    # app://communications.gaiamobile.org/ftu/index.html#welcome_browser
    file_name = 'welcome_browser'
    screenshot_entry = {
      "id" : file_name,
      "script" : app,
      "gaia" : gaia_hash,
      "hg" : hg_hash,
      "changed" : False,
      "path" : screenshot_path}
    test_flags = {}
    if check_flags(test_flags, device_flags):
      screenshot_entry.update(test_flags)
      if take_screenshot(locale, screenshot_path, client, file_name):
        screenshot_entry['changed'] = True
      log_displayed_l10n_strings(client, db, app, app_categ, screenshot_entry)


      # switch to app://communications.gaiamobile.org/ftu/index.html#browser_privacy
      next = client.find_element('css selector', '#forward')
      next.tap()
      time.sleep(short_time)

    # app://communications.gaiamobile.org/ftu/index.html#browser_privacy
    file_name = 'browser_privacy'
    screenshot_entry = {
      "id" : file_name,
      "script" : app,
      "gaia" : gaia_hash,
      "hg" : hg_hash,
      "changed" : False,
      "path" : screenshot_path}
    test_flags = {}
    if check_flags(test_flags, device_flags):
      screenshot_entry.update(test_flags)
      if take_screenshot(locale, screenshot_path, client, file_name):
        screenshot_entry['changed'] = True
      log_displayed_l10n_strings(client, db, app, app_categ, screenshot_entry)


      # switch to app://communications.gaiamobile.org/ftu/index.html#step1 (first tutorial screen)
      next = client.find_element('css selector', '#forward')
      next.tap()
      time.sleep(long_time)

    # app://communications.gaiamobile.org/ftu/index.html#step1 (first tutorial screen)
    file_name = 'step1-first_tutorial_screen'
    screenshot_entry = {
      "id" : file_name,
      "script" : app,
      "gaia" : gaia_hash,
      "hg" : hg_hash,
      "changed" : False,
      "path" : screenshot_path}
    test_flags = {}
    if check_flags(test_flags, device_flags):
      screenshot_entry.update(test_flags)
      if take_screenshot(locale, screenshot_path, client, file_name):
        screenshot_entry['changed'] = True
      log_displayed_l10n_strings(client, db, app, app_categ, screenshot_entry)


      # switch to app://communications.gaiamobile.org/ftu/index.html#step1
      next = client.find_element('css selector', '#lets-go-button')
      next.tap()
      time.sleep(long_time)

    # app://communications.gaiamobile.org/ftu/index.html#step1
    file_name = 'step1'
    screenshot_entry = {
      "id" : file_name,
      "script" : app,
      "gaia" : gaia_hash,
      "hg" : hg_hash,
      "changed" : False,
      "path" : screenshot_path}
    test_flags = {}
    if check_flags(test_flags, device_flags):
      screenshot_entry.update(test_flags)
      if take_screenshot(locale, screenshot_path, client, file_name):
        screenshot_entry['changed'] = True
      log_displayed_l10n_strings(client, db, app, app_categ, screenshot_entry)


      # switch to app://communications.gaiamobile.org/ftu/index.html#step2
      next = client.find_element('css selector', '#forwardTutorial')
      next.tap()
      time.sleep(short_time)

    # app://communications.gaiamobile.org/ftu/index.html#step2
    file_name = 'step2'
    screenshot_entry = {
      "id" : file_name,
      "script" : app,
      "gaia" : gaia_hash,
      "hg" : hg_hash,
      "changed" : False,
      "path" : screenshot_path}
    test_flags = {}
    if check_flags(test_flags, device_flags):
      screenshot_entry.update(test_flags)
      if take_screenshot(locale, screenshot_path, client, file_name):
        screenshot_entry['changed'] = True
      log_displayed_l10n_strings(client, db, app, app_categ, screenshot_entry)


      # switch to app://communications.gaiamobile.org/ftu/index.html#step3
      next = client.find_element('css selector', '#forwardTutorial')
      next.tap()
      time.sleep(short_time)

    # app://communications.gaiamobile.org/ftu/index.html#step3
    file_name = 'step3'
    screenshot_entry = {
      "id" : file_name,
      "script" : app,
      "gaia" : gaia_hash,
      "hg" : hg_hash,
      "changed" : False,
      "path" : screenshot_path}
    test_flags = {}
    if check_flags(test_flags, device_flags):
      screenshot_entry.update(test_flags)
      if take_screenshot(locale, screenshot_path, client, file_name):
        screenshot_entry['changed'] = True
      log_displayed_l10n_strings(client, db, app, app_categ, screenshot_entry)


      # switch to app://communications.gaiamobile.org/ftu/index.html#step4
      next = client.find_element('css selector', '#forwardTutorial')
      next.tap()
      time.sleep(short_time)

    # app://communications.gaiamobile.org/ftu/index.html#step4
    file_name = 'step4'
    screenshot_entry = {
      "id" : file_name,
      "script" : app,
      "gaia" : gaia_hash,
      "hg" : hg_hash,
      "changed" : False,
      "path" : screenshot_path}
    test_flags = {}
    if check_flags(test_flags, device_flags):
      screenshot_entry.update(test_flags)
      if take_screenshot(locale, screenshot_path, client, file_name):
        screenshot_entry['changed'] = True
      log_displayed_l10n_strings(client, db, app, app_categ, screenshot_entry)


      # switch to app://communications.gaiamobile.org/ftu/index.html#step4 (last tutorial screen)
      next = client.find_element('css selector', '#forwardTutorial')
      next.tap()
      time.sleep(long_time)

    # app://communications.gaiamobile.org/ftu/index.html#step4 (last tutorial screen)
    file_name = 'step4-last_tutorial_screen'
    screenshot_entry = {
      "id" : file_name,
      "script" : app,
      "gaia" : gaia_hash,
      "hg" : hg_hash,
      "changed" : False,
      "path" : screenshot_path}
    test_flags = {}
    if check_flags(test_flags, device_flags):
      screenshot_entry.update(test_flags)
      if take_screenshot(locale, screenshot_path, client, file_name):
        screenshot_entry['changed'] = True
      log_displayed_l10n_strings(client, db, app, app_categ, screenshot_entry)


      # Close ftu frame
      next = client.find_element('css selector', '#tutorialFinished')
      next.tap()
      time.sleep(short_time)

    set_db(locale, db)

  else:
  #TO DO raise proper error
    print "switch to ftu frame failed"
  waitFor(
    function() {
      window.wrappedJSObject.LockScreen.unlock();
      waitFor(
        function() {
          finish(window.wrappedJSObject.LockScreen.locked);
        },
        function() {
          return !window.wrappedJSObject.LockScreen.locked;
        }
      );
    },
    function() {
      return !!window.wrappedJSObject.LockScreen;
    }
  );
"""

from marionette import Marionette 

marionette = Marionette('localhost', 2828)
marionette.start_session()
marionette.import_script('gaia_apps.js')
marionette.set_script_timeout(60000)

marionette.execute_script(unlock)
result = marionette.execute_async_script("GaiaApps.launchWithName('%s')" % "MozCampAsia-QualityApps")

marionette.switch_to_frame(result.get("frame"))
pdb.set_trace()
#!/usr/bin/python2.7
#
# Script to work around Marionette bug 879816 (cannot click the modal 'ok' button
# following clicking something else).
#
from marionette import Marionette
marionette = Marionette(host='localhost', port=2828)
marionette.start_session()
marionette.switch_to_frame()
marionette.execute_script("document.getElementById('modal-dialog-prompt-ok').click();")

Exemplo n.º 21
0
class B2GRunner(object):
    remote_profile_dir = None

    def __init__(self,
                 dm,
                 url,
                 tmpdir,
                 marionette_host=None,
                 marionette_port=None):
        self.dm = dm
        self.url = url
        self.tmpdir = tmpdir
        self.userJS = "/data/local/user.js"
        self.marionette_host = marionette_host or 'localhost'
        self.marionette_port = marionette_port or 2828
        self.marionette = None

    def wait_for_port(self, timeout):
        starttime = datetime.datetime.now()
        while datetime.datetime.now() - starttime < datetime.timedelta(
                seconds=timeout):
            try:
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                sock.connect(('localhost', self.marionette_port))
                data = sock.recv(16)
                sock.close()
                if '"from"' in data:
                    return True
            except:
                import traceback
                print traceback.format_exc()
            time.sleep(1)
        return False

    def restart_b2g(self):
        #restart b2g so we start with a clean slate
        self.dm.checkCmd(['shell', 'stop', 'b2g'])
        # Wait for a bit to make sure B2G has completely shut down.
        time.sleep(10)
        self.dm.checkCmd(['shell', 'start', 'b2g'])

        #wait for marionette port to come up
        if not self.wait_for_port(30000):
            raise Exception(
                "Could not communicate with Marionette port after restarting B2G"
            )
        self.marionette = Marionette(self.marionette_host,
                                     self.marionette_port)

    def setup_profile(self):
        #remove previous user.js if there is one
        our_user_js = os.path.join(self.tmpdir, "user.js")
        if os.path.exists(our_user_js):
            os.remove(our_user_js)
        #copy profile
        try:
            self.dm.checkCmd(["pull", self.userJS, our_user_js])
        except subprocess.CalledProcessError:
            pass
        #if we successfully copied the profile, make a backup of the file
        if os.path.exists(our_user_js):
            self.dm.checkCmd([
                'shell', 'dd',
                'if=%s' % self.userJS,
                'of=%s.orig' % self.userJS
            ])
        user_js = open(our_user_js, 'a')
        user_js.write("""
user_pref("power.screen.timeout", 999999);
        """)
        user_js.close()
        self.dm.checkCmd(['push', our_user_js, self.userJS])
        self.restart_b2g()

    def start(self):
        #forward the marionette port
        self.dm.checkCmd([
            'forward',
            'tcp:%s' % self.marionette_port,
            'tcp:%s' % self.marionette_port
        ])

        print "Setting up profile"
        self.setup_profile()
        #enable ethernet connection
        print "Running netcfg, it may take some time."
        self.dm.checkCmd(['shell', 'netcfg', 'eth0', 'dhcp'])
        #launch app
        session = self.marionette.start_session()
        if 'b2g' not in session:
            raise Exception("bad session value %s returned by start_session" %
                            session)

        # start the tests by navigating to the mochitest url
        self.marionette.execute_script("window.location.href='%s';" % self.url)

    def stop(self):
        self.marionette.delete_session()
Exemplo n.º 22
0
    def run(self, script, address='localhost:2828', symbols=None,
            treeherder='https://treeherder.mozilla.org/', reset=False,
            **kwargs):
        try:
            host, port = address.split(':')
        except ValueError:
            raise ValueError('--address must be in the format host:port')

        # Check that Orangutan is installed
        self.adb_device = ADBDevice(self.device_serial)
        orng_path = posixpath.join('data', 'local', 'orng')
        if not self.adb_device.exists(orng_path):
            raise Exception('Orangutan not found! Please install it according '
                            'to the documentation.')

        self.runner = B2GDeviceRunner(
            serial=self.device_serial,
            process_args={'stream': None},
            symbols_path=symbols,
            logdir=self.temp_dir)

        if reset:
            self.runner.start()
        else:
            self.runner.device.connect()

        port = self.runner.device.setup_port_forwarding(remote_port=port)
        assert self.runner.device.wait_for_port(port), \
            'Timed out waiting for port!'

        marionette = Marionette(host=host, port=port)
        marionette.start_session()

        try:
            marionette.set_context(marionette.CONTEXT_CHROME)
            self.is_debug = marionette.execute_script(
                'return Components.classes["@mozilla.org/xpcom/debug;1"].'
                'getService(Components.interfaces.nsIDebug2).isDebugBuild;')
            marionette.set_context(marionette.CONTEXT_CONTENT)

            if reset:
                gaia_device = GaiaDevice(marionette)
                gaia_device.wait_for_b2g_ready(timeout=120)
                gaia_device.unlock()
                gaia_apps = GaiaApps(marionette)
                gaia_apps.kill_all()

            # TODO: Disable bluetooth, emergency calls, carrier, etc

            # Run Orangutan script
            remote_script = posixpath.join(self.adb_device.test_root,
                                           'orng.script')
            self.adb_device.push(script, remote_script)
            self.start_time = time.time()
            # TODO: Kill remote process on keyboard interrupt
            self.adb_device.shell('%s %s %s' % (orng_path,
                                                self.device_properties['input'],
                                                remote_script))
            self.end_time = time.time()
            self.adb_device.rm(remote_script)
        except (MarionetteException, IOError):
            if self.runner.crashed:
                # Crash has been detected
                pass
            else:
                raise
        self.runner.check_for_crashes(test_name='b2gmonkey')

        # Report results to Treeherder
        required_envs = ['TREEHERDER_KEY', 'TREEHERDER_SECRET']
        if all([os.environ.get(v) for v in required_envs]):
            self.post_to_treeherder(script, treeherder)
        else:
            self._logger.info(
                'Results will not be posted to Treeherder. Please set the '
                'following environment variables to enable Treeherder '
                'reports: %s' % ', '.join([
                    v for v in required_envs if not os.environ.get(v)]))
Exemplo n.º 23
0
#   Mozilla Foundation. 
# Portions created by the Initial Developer are Copyright (C) 2011
# the Initial Developer. All Rights Reserved. 
# 
# Contributor(s): 
#  Jonathan Griffin <*****@*****.**>
# 
# Alternatively, the contents of this file may be used under the terms of 
# either the GNU General Public License Version 2 or later (the "GPL"), or 
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 
# in which case the provisions of the GPL or the LGPL are applicable instead 
# of those above. If you wish to allow use of your version of this file only 
# under the terms of either the GPL or the LGPL, and not to allow others to 
# use your version of this file under the terms of the MPL, indicate your 
# decision by deleting the provisions above and replace them with the notice 
# and other provisions required by the GPL or the LGPL. If you do not delete 
# the provisions above, a recipient may use your version of this file under 
# the terms of any one of the MPL, the GPL or the LGPL. 
# 
# ***** END LICENSE BLOCK ***** 

from marionette import Marionette, HTMLElement

if __name__ == '__main__':

    # launch Fennec with Marionette before starting this test!
    m = Marionette(host='localhost', port=2828)
    assert(m.start_session())
    assert(10 == m.execute_script('return 10;'))

Exemplo n.º 24
0
def uninstall_app(app_name, adb_path="adb", script_timeout=5000, marionette=None, device_serial=None):
    """
    Uninstalls the given app.

    NOTE: if a marionette session is passed, this function switches to the top-most frame.
    """

    def check_uninstall(marionette):
        uninstall = marionette.execute_script("return window.wrappedJSObject.uninstall;")
        return uninstall != 'none'

    def check_click_uninstall(marionette):
        button = marionette.find_element('css selector', 'gaia-confirm .confirm')
        try:
            button.click()
            not_displayed = not button.is_displayed()
        except StaleElementException:
            not_displayed = True
        return not_displayed

    dm = mozdevice.DeviceManagerADB(adbPath=adb_path, deviceSerial=device_serial)
    installed_app_name = app_name.lower()
    installed_app_name = installed_app_name.replace(" ", "-")
    dm.forward("tcp:2828", "tcp:2828")

    print 'requesting uninstall of app', app_name
    if not marionette:
        m = Marionette()
        m.start_session()
    else:
        m = marionette
        m.switch_to_frame()

    m.set_context("chrome")
    m.execute_script("""
    Components.utils.import("resource://gre/modules/Services.jsm");
    window.wrappedJSObject.uninstall = 'none';
    Services.obs.addObserver(function observer(subject, topic) {
        Services.obs.removeObserver(observer, topic);
        window.wrappedJSObject.uninstall = 'ask';
        }, "webapps-ask-uninstall", false);
    Services.obs.addObserver(function observer(subject, topic) {
        Services.obs.removeObserver(observer, topic);
        window.wrappedJSObject.uninstall = 'uninstall';
        }, "webapps-uninstall", false);
        """)
    m.set_context("content")

    uninstall_app = """
    var uninstallWithName = function(name) {
        let apps = window.wrappedJSObject.applications || window.wrappedJSObject.Applications;
        let installedApps = apps.installedApps;
        for (let manifestURL in installedApps) {
          let app = installedApps[manifestURL];
          let origin = null;
          let entryPoints = app.manifest.entry_points;
          if (entryPoints) {
            for (let ep in entryPoints) {
              let currentEntryPoint = entryPoints[ep];
              let appName = currentEntryPoint.name;
              if (name == appName.toLowerCase()) {
                window.wrappedJSObject.navigator.mozApps.mgmt.uninstall(app);
                return true;
              }
            }
          } else {
            let appName = app.manifest.name;
            if (name == appName.toLowerCase()) {
              window.wrappedJSObject.navigator.mozApps.mgmt.uninstall(app);
              return true;
            }
          }
        }
        return false;
      };
    return uninstallWithName("%s");
    """
    m.set_script_timeout(script_timeout)
    result = m.execute_script(uninstall_app % app_name.lower())

    if result:
        m.set_context("chrome")
        Wait(m, 10).until(check_uninstall)
        uninstall = m.execute_script("return window.wrappedJSObject.uninstall;")
        m.set_context("content")
        if uninstall == 'ask':
            m.switch_to_frame()
            Wait(m, 20).until(element_displayed(m.find_element('css selector', 'gaia-confirm .confirm')))
            Wait(m, 20).until(check_click_uninstall)

    if not marionette:
        m.delete_session()
Exemplo n.º 25
0
class B2GDesktopReftest(RefTest):
    marionette = None

    def __init__(self, marionette_args):
        RefTest.__init__(self)
        self.last_test = os.path.basename(__file__)
        self.marionette_args = marionette_args
        self.profile = None
        self.runner = None
        self.test_script = os.path.join(here, 'b2g_start_script.js')
        self.timeout = None

    def run_marionette_script(self):
        self.marionette = Marionette(**self.marionette_args)
        assert(self.marionette.wait_for_port())
        self.marionette.start_session()
        self.marionette.set_context(self.marionette.CONTEXT_CHROME)

        if os.path.isfile(self.test_script):
            f = open(self.test_script, 'r')
            self.test_script = f.read()
            f.close()
        self.marionette.execute_script(self.test_script)

    def run_tests(self, test_path, options):
        reftestlist = self.getManifestPath(test_path)
        if not reftestlist.startswith('file://'):
            reftestlist = 'file://%s' % reftestlist

        self.profile = self.create_profile(options, reftestlist,
                                           profile_to_clone=options.profile)
        env = self.buildBrowserEnv(options, self.profile.profile)
        kp_kwargs = { 'processOutputLine': [self._on_output],
                      'onTimeout': [self._on_timeout],
                      'kill_on_timeout': False }

        if not options.debugger:
            if not options.timeout:
                if mozinfo.info['debug']:
                    options.timeout = 420
                else:
                    options.timeout = 300
            self.timeout = options.timeout + 30.0

        log.info("%s | Running tests: start.", os.path.basename(__file__))
        cmd, args = self.build_command_line(options.app,
                            ignore_window_size=options.ignoreWindowSize,
                            browser_arg=options.browser_arg)
        self.runner = FirefoxRunner(profile=self.profile,
                                    binary=cmd,
                                    cmdargs=args,
                                    env=env,
                                    process_class=ProcessHandler,
                                    process_args=kp_kwargs,
                                    symbols_path=options.symbolsPath)

        status = 0
        try:
            self.runner.start(outputTimeout=self.timeout)
            log.info("%s | Application pid: %d",
                     os.path.basename(__file__),
                     self.runner.process_handler.pid)

            # kick starts the reftest harness
            self.run_marionette_script()
            status = self.runner.wait()
        finally:
            self.runner.check_for_crashes(test_name=self.last_test)
            self.runner.cleanup()

        if status > 0:
            log.testFail("%s | application terminated with exit code %s",
                         self.last_test, status)
        elif status < 0:
            log.info("%s | application killed with signal %s",
                         self.last_test, -status)

        log.info("%s | Running tests: end.", os.path.basename(__file__))
        return status

    def create_profile(self, options, reftestlist, profile_to_clone=None):
        profile = RefTest.createReftestProfile(self, options, reftestlist,
                                               profile_to_clone=profile_to_clone)

        prefs = {}
        # Turn off the locale picker screen
        prefs["browser.firstrun.show.localepicker"] = False
        prefs["b2g.system_startup_url"] = "app://test-container.gaiamobile.org/index.html"
        prefs["b2g.system_manifest_url"] = "app://test-container.gaiamobile.org/manifest.webapp"
        prefs["dom.ipc.tabs.disabled"] = False
        prefs["dom.mozBrowserFramesEnabled"] = True
        prefs["font.size.inflation.emPerLine"] = 0
        prefs["font.size.inflation.minTwips"] = 0
        prefs["network.dns.localDomains"] = "app://test-container.gaiamobile.org"
        prefs["reftest.browser.iframe.enabled"] = False
        prefs["reftest.remote"] = False
        prefs["reftest.uri"] = "%s" % reftestlist
        # Set a future policy version to avoid the telemetry prompt.
        prefs["toolkit.telemetry.prompted"] = 999
        prefs["toolkit.telemetry.notifiedOptOut"] = 999

        # Set the extra prefs.
        profile.set_preferences(prefs)
        return profile

    def build_command_line(self, app, ignore_window_size=False,
                           browser_arg=None):
        cmd = os.path.abspath(app)
        args = ['-marionette']

        if browser_arg:
            args += [browser_arg]

        if not ignore_window_size:
            args.extend(['--screen', '800x1000'])
        return cmd, args

    def _on_output(self, line):
        print(line)
        # TODO use structured logging
        if "TEST-START" in line and "|" in line:
            self.last_test = line.split("|")[1].strip()

    def _on_timeout(self):
        msg = "%s | application timed out after %s seconds with no output"
        log.testFail(msg % (self.last_test, self.timeout))

        # kill process to get a stack
        self.runner.stop(sig=signal.SIGABRT)
Exemplo n.º 26
0
def ftu(locale, device_flags, hashes):

    db = get_db(locale)

    app = 'ftu'
    app_categ = 'communications'
    app_type = 'apps'
    gaia_hash = hashes[0]
    hg_hash = hashes[1]
    screenshot_path = app_type + '/' + app_categ + '/' + app

    create_screenshot_dir(locale, screenshot_path)

    client = Marionette('localhost', 2828)
    client.start_session()

    change_screen_timeout(client)

    ftu_iframe = client.find_element(
        'css selector',
        "iframe[src='app://communications.gaiamobile.org/ftu/index.html']")

    if client.switch_to_frame(ftu_iframe):

        time.sleep(short_time)

        # app://communications.gaiamobile.org/ftu/index.html#languages
        file_name = 'languages'
        screenshot_entry = {
            "id": file_name,
            "script": app,
            "gaia": gaia_hash,
            "hg": hg_hash,
            "changed": False,
            "path": screenshot_path
        }
        test_flags = {}
        if check_flags(test_flags, device_flags):
            screenshot_entry.update(test_flags)
            if take_screenshot(locale, screenshot_path, client, file_name):
                screenshot_entry['changed'] = True
            log_displayed_l10n_strings(client, db, app, app_categ,
                                       screenshot_entry, '#activation-screen')

            # switch to app://communications.gaiamobile.org/ftu/index.html#data_3g (unlock-sim-screen screen)
            next = client.find_element('css selector', '#forward')
            next.tap()
            time.sleep(short_time)

        # app://communications.gaiamobile.org/ftu/index.html#data_3g (sim pin screen - unlock-sim-screen - 1st attempt)
        file_name = 'data_3g-unlock_sim_screen-pin_screen'
        screenshot_entry = {
            "id": file_name,
            "script": app,
            "gaia": gaia_hash,
            "hg": hg_hash,
            "changed": False,
            "path": screenshot_path
        }
        test_flags = {"sim": True, "no-sim": False}
        if check_flags(test_flags, device_flags):
            screenshot_entry.update(test_flags)
            if take_screenshot(locale, screenshot_path, client, file_name):
                screenshot_entry['changed'] = True
            log_displayed_l10n_strings(client, db, app, app_categ,
                                       screenshot_entry, '#unlock-sim-screen')

            # invalid pin -> error about pin characters
            # stay at app://communications.gaiamobile.org/ftu/index.html#data_3g (unlock-sim-screen screen)
            next = client.find_element('css selector', '#unlock-sim-button')
            next.tap()
            time.sleep(short_time)

        # app://communications.gaiamobile.org/ftu/index.html#data_3g (sim pin screen - unlock-sim-screen - pin error)
        file_name = 'data_3g-unlock_sim_screen-pin_screen-invalid_pin'
        screenshot_entry = {
            "id": file_name,
            "script": app,
            "gaia": gaia_hash,
            "hg": hg_hash,
            "changed": False,
            "path": screenshot_path
        }
        test_flags = {"sim": True, "no-sim": False}
        if check_flags(test_flags, device_flags):
            screenshot_entry.update(test_flags)
            if take_screenshot(locale, screenshot_path, client, file_name):
                screenshot_entry['changed'] = True
            log_displayed_l10n_strings(client, db, app, app_categ,
                                       screenshot_entry, '#unlock-sim-screen')

            # insert wrong pin (attempt 1 of 3)
            pin_input = client.find_element('css selector', '#pin-input')
            pin_input.send_keys(wrong_sim_pin)

            # stay at app://communications.gaiamobile.org/ftu/index.html#data_3g (unlock-sim-screen screen)
            next = client.find_element('css selector', '#unlock-sim-button')
            next.tap()
            time.sleep(short_time)

        # app://communications.gaiamobile.org/ftu/index.html#data_3g (sim pin screen - unlock-sim-screen - 2nd attempt)
        file_name = 'data_3g-unlock_sim_screen-pin_screen-wrong_pin-1st_time'
        screenshot_entry = {
            "id": file_name,
            "script": app,
            "gaia": gaia_hash,
            "hg": hg_hash,
            "changed": False,
            "path": screenshot_path
        }
        test_flags = {"sim": True, "no-sim": False}
        if check_flags(test_flags, device_flags):
            screenshot_entry.update(test_flags)
            if take_screenshot(locale, screenshot_path, client, file_name):
                screenshot_entry['changed'] = True
            log_displayed_l10n_strings(client, db, app, app_categ,
                                       screenshot_entry, '#unlock-sim-screen')

            # insert wrong pin (attempt 2 of 3)
            pin_input = client.find_element('css selector', '#pin-input')
            pin_input.send_keys(wrong_sim_pin)

            # stay at app://communications.gaiamobile.org/ftu/index.html#data_3g (unlock-sim-screen screen)
            next = client.find_element('css selector', '#unlock-sim-button')
            next.tap()
            time.sleep(short_time)

        # app://communications.gaiamobile.org/ftu/index.html#data_3g (sim pin screen - unlock-sim-screen - 3rd attempt)
        file_name = 'data_3g-unlock_sim_screen-pin_screen-wrong_pin-2nd_time'
        screenshot_entry = {
            "id": file_name,
            "script": app,
            "gaia": gaia_hash,
            "hg": hg_hash,
            "changed": False,
            "path": screenshot_path
        }
        test_flags = {"sim": True, "no-sim": False}
        if check_flags(test_flags, device_flags):
            screenshot_entry.update(test_flags)
            if take_screenshot(locale, screenshot_path, client, file_name):
                screenshot_entry['changed'] = True
            log_displayed_l10n_strings(client, db, app, app_categ,
                                       screenshot_entry, '#unlock-sim-screen')

            # insert wrong pin (atempt 3 of 3) - continues to puk screen
            pin_input = client.find_element('css selector', '#pin-input')
            pin_input.send_keys(wrong_sim_pin)

            # switch to app://communications.gaiamobile.org/ftu/index.html#data_3g (sim puk screen - unlock-sim-screen)
            next = client.find_element('css selector', '#unlock-sim-button')
            next.tap()
            time.sleep(short_time)

            # tap the header in order to hide keyboard and get full screenshot of the puk screen
            header = client.find_element('css selector', '#unlock-sim-header')
            header.tap()

        # app://communications.gaiamobile.org/ftu/index.html#data_3g (sim puk screen - unlock-sim-screen - 1st attempt)
        file_name = 'data_3g-unlock_sim_screen-puk_screen'
        screenshot_entry = {
            "id": file_name,
            "script": app,
            "gaia": gaia_hash,
            "hg": hg_hash,
            "changed": False,
            "path": screenshot_path
        }
        test_flags = {"sim": True, "no-sim": False}
        if check_flags(test_flags, device_flags):
            screenshot_entry.update(test_flags)
            if take_screenshot(locale, screenshot_path, client, file_name):
                screenshot_entry['changed'] = True
            log_displayed_l10n_strings(client, db, app, app_categ,
                                       screenshot_entry, '#unlock-sim-screen')

            # invalid puk -> error about puk characters
            # stay at app://communications.gaiamobile.org/ftu/index.html#data_3g (sim puk screen - unlock-sim-screen)
            next = client.find_element('css selector', '#unlock-sim-button')
            next.tap()
            time.sleep(short_time)

        # app://communications.gaiamobile.org/ftu/index.html#data_3g (sim puk screen - unlock-sim-screen - puk error)
        file_name = 'data_3g-unlock_sim_screen-puk_screen-invalid_puk'
        screenshot_entry = {
            "id": file_name,
            "script": app,
            "gaia": gaia_hash,
            "hg": hg_hash,
            "changed": False,
            "path": screenshot_path
        }
        test_flags = {"sim": True, "no-sim": False}
        if check_flags(test_flags, device_flags):
            screenshot_entry.update(test_flags)
            if take_screenshot(locale, screenshot_path, client, file_name):
                screenshot_entry['changed'] = True
            log_displayed_l10n_strings(client, db, app, app_categ,
                                       screenshot_entry, '#unlock-sim-screen')

            # insert wrong puk - invalid new pin -> error about pin characters
            puk_input = client.find_element('css selector', '#puk-input')
            puk_input.send_keys(wrong_sim_puk)

            # stay at app://communications.gaiamobile.org/ftu/index.html#data_3g (sim puk screen - unlock-sim-screen)
            next = client.find_element('css selector', '#unlock-sim-button')
            next.tap()
            time.sleep(short_time)

        # app://communications.gaiamobile.org/ftu/index.html#data_3g (sim puk screen - unlock-sim-screen - pin error)
        file_name = 'data_3g-unlock_sim_screen-puk_screen-invalid_new_pin'
        screenshot_entry = {
            "id": file_name,
            "script": app,
            "gaia": gaia_hash,
            "hg": hg_hash,
            "changed": False,
            "path": screenshot_path
        }
        test_flags = {"sim": True, "no-sim": False}
        if check_flags(test_flags, device_flags):
            screenshot_entry.update(test_flags)
            if take_screenshot(locale, screenshot_path, client, file_name):
                screenshot_entry['changed'] = True
            log_displayed_l10n_strings(client, db, app, app_categ,
                                       screenshot_entry, '#unlock-sim-screen')

            # insert new pin without confirmed it -> error about pin confirmation (wrong puk is preserved at its input)
            newpin_input = client.find_element('css selector', '#newpin-input')
            newpin_input.send_keys(sim_pin)

            # stay at app://communications.gaiamobile.org/ftu/index.html#data_3g (sim puk screen - unlock-sim-screen)
            next = client.find_element('css selector', '#unlock-sim-button')
            next.tap()
            time.sleep(short_time)

        # app://communications.gaiamobile.org/ftu/index.html#data_3g (sim puk screen - unlock-sim-screen - pin error)
        file_name = 'data_3g-unlock_sim_screen-puk_screen-invalid_new_pin_confirmation'
        screenshot_entry = {
            "id": file_name,
            "script": app,
            "gaia": gaia_hash,
            "hg": hg_hash,
            "changed": False,
            "path": screenshot_path
        }
        test_flags = {"sim": True, "no-sim": False}
        if check_flags(test_flags, device_flags):
            screenshot_entry.update(test_flags)
            if take_screenshot(locale, screenshot_path, client, file_name):
                screenshot_entry['changed'] = True
            log_displayed_l10n_strings(client, db, app, app_categ,
                                       screenshot_entry, '#unlock-sim-screen')

            # insert confirmation of the new pin (wrong puk and new pin are preserved at their inputs)
            newpin_input = client.find_element('css selector',
                                               '#confirm-newpin-input')
            newpin_input.send_keys(sim_pin)

            # wrong puk (attempt 1 of 9)
            # stay at app://communications.gaiamobile.org/ftu/index.html#data_3g (sim puk screen - unlock-sim-screen)
            next = client.find_element('css selector', '#unlock-sim-button')
            next.tap()
            time.sleep(short_time)

        # app://communications.gaiamobile.org/ftu/index.html#data_3g (sim puk screen - unlock-sim-screen - puk error)
        file_name = 'data_3g-unlock_sim_screen-puk_screen-wrong_puk-1st_time'
        screenshot_entry = {
            "id": file_name,
            "script": app,
            "gaia": gaia_hash,
            "hg": hg_hash,
            "changed": False,
            "path": screenshot_path
        }
        test_flags = {"sim": True, "no-sim": False}
        if check_flags(test_flags, device_flags):
            screenshot_entry.update(test_flags)
            if take_screenshot(locale, screenshot_path, client, file_name):
                screenshot_entry['changed'] = True
            log_displayed_l10n_strings(client, db, app, app_categ,
                                       screenshot_entry, '#unlock-sim-screen')

            # insert wrong puk (attempt 2 of 9) (new pin and its confirmation are preserved at their inputs)
            puk_input = client.find_element('css selector', '#puk-input')
            puk_input.send_keys(wrong_sim_puk)

            # stay at app://communications.gaiamobile.org/ftu/index.html#data_3g (sim puk screen - unlock-sim-screen)
            next = client.find_element('css selector', '#unlock-sim-button')
            next.tap()
            time.sleep(short_time)

        # app://communications.gaiamobile.org/ftu/index.html#data_3g (sim puk screen - unlock-sim-screen - 2nd attempt)
        file_name = 'data_3g-unlock_sim_screen-puk_screen-wrong_puk-2nd_time'
        screenshot_entry = {
            "id": file_name,
            "script": app,
            "gaia": gaia_hash,
            "hg": hg_hash,
            "changed": False,
            "path": screenshot_path
        }
        test_flags = {"sim": True, "no-sim": False}
        if check_flags(test_flags, device_flags):
            screenshot_entry.update(test_flags)
            if take_screenshot(locale, screenshot_path, client, file_name):
                screenshot_entry['changed'] = True
            log_displayed_l10n_strings(client, db, app, app_categ,
                                       screenshot_entry, '#unlock-sim-screen')

            # insert right puk (attempt 2 of 9) (new pin and its confirmation are preserved at their inputs)
            puk_input = client.find_element('css selector', '#puk-input')
            puk_input.send_keys(sim_puk)

            # switch to app://communications.gaiamobile.org/ftu/index.html#data_3g
            next = client.find_element('css selector', '#unlock-sim-button')
            next.tap()
            time.sleep(short_time)

        # app://communications.gaiamobile.org/ftu/index.html#data_3g
        file_name = 'data_3g'
        screenshot_entry = {
            "id": file_name,
            "script": app,
            "gaia": gaia_hash,
            "hg": hg_hash,
            "changed": False,
            "path": screenshot_path
        }
        test_flags = {"sim": True, "no-sim": False}
        if check_flags(test_flags, device_flags):
            screenshot_entry.update(test_flags)
            if take_screenshot(locale, screenshot_path, client, file_name):
                screenshot_entry['changed'] = True
            log_displayed_l10n_strings(client, db, app, app_categ,
                                       screenshot_entry, '#activation-screen')

            # switch to app://communications.gaiamobile.org/ftu/index.html#wifi
            next = client.find_element('css selector', '#forward')
            next.tap()
            time.sleep(long_time)

            # enable overlay "scanningNetworks" spinner screen (loading-overlay)
            client.execute_script(
                "window.wrappedJSObject.utils.overlay.show('scanningNetworks', 'spinner');"
            )
            time.sleep(middle_time)

        # overlay "scanningNetworks" spinner screen
        file_name = 'wifi-loading_overlay-scanning_networks'
        screenshot_entry = {
            "id": file_name,
            "script": app,
            "gaia": gaia_hash,
            "hg": hg_hash,
            "changed": False,
            "path": screenshot_path
        }
        test_flags = {}
        if check_flags(test_flags, device_flags):
            screenshot_entry.update(test_flags)
            if take_screenshot(locale, screenshot_path, client, file_name):
                screenshot_entry['changed'] = True
            log_displayed_l10n_strings(client, db, app, app_categ,
                                       screenshot_entry, '#loading-overlay')

            # disable overlay "scanningNetworks" spinner screen
            client.execute_script(
                "window.wrappedJSObject.utils.overlay.hide('scanningNetworks', 'spinner');"
            )
            time.sleep(middle_time)

        # app://communications.gaiamobile.org/ftu/index.html#wifi
        file_name = 'wifi'
        screenshot_entry = {
            "id": file_name,
            "script": app,
            "gaia": gaia_hash,
            "hg": hg_hash,
            "changed": False,
            "path": screenshot_path
        }
        test_flags = {}
        if check_flags(test_flags, device_flags):
            screenshot_entry.update(test_flags)
            if take_screenshot(locale, screenshot_path, client, file_name):
                screenshot_entry['changed'] = True
            log_displayed_l10n_strings(client, db, app, app_categ,
                                       screenshot_entry, '#wifi')

            # switch to app://communications.gaiamobile.org/ftu/index.html#date_and_time
            next = client.find_element('css selector', '#forward')
            next.tap()
            time.sleep(short_time)

        # Set time in order to be the same at every screenshot
        set_time(client)

        # app://communications.gaiamobile.org/ftu/index.html#date_and_time
        file_name = 'date_and_time'
        screenshot_entry = {
            "id": file_name,
            "script": app,
            "gaia": gaia_hash,
            "hg": hg_hash,
            "changed": False,
            "path": screenshot_path
        }
        test_flags = {}
        if check_flags(test_flags, device_flags):
            screenshot_entry.update(test_flags)
            if take_screenshot(locale, screenshot_path, client, file_name):
                screenshot_entry['changed'] = True
            log_displayed_l10n_strings(client, db, app, app_categ,
                                       screenshot_entry, '#date_and_time')

            # switch to app://communications.gaiamobile.org/ftu/index.html#geolocation
            next = client.find_element('css selector', '#forward')
            next.tap()
            time.sleep(short_time)

        # app://communications.gaiamobile.org/ftu/index.html#geolocation
        file_name = 'geolocation'
        screenshot_entry = {
            "id": file_name,
            "script": app,
            "gaia": gaia_hash,
            "hg": hg_hash,
            "changed": False,
            "path": screenshot_path
        }
        test_flags = {}
        if check_flags(test_flags, device_flags):
            screenshot_entry.update(test_flags)
            if take_screenshot(locale, screenshot_path, client, file_name):
                screenshot_entry['changed'] = True
            log_displayed_l10n_strings(client, db, app, app_categ,
                                       screenshot_entry, '#geolocation')

            # switch to app://communications.gaiamobile.org/ftu/index.html#import_contacts
            next = client.find_element('css selector', '#forward')
            next.tap()
            time.sleep(middle_time)

        # app://communications.gaiamobile.org/ftu/index.html#import_contacts
        file_name = 'import_contacts'
        screenshot_entry = {
            "id": file_name,
            "script": app,
            "gaia": gaia_hash,
            "hg": hg_hash,
            "changed": False,
            "path": screenshot_path
        }
        test_flags = {}
        if check_flags(test_flags, device_flags):
            screenshot_entry.update(test_flags)
            if take_screenshot(locale, screenshot_path, client, file_name):
                screenshot_entry['changed'] = True
            log_displayed_l10n_strings(client, db, app, app_categ,
                                       screenshot_entry, '#import_contacts')

            # switch to app://communications.gaiamobile.org/ftu/index.html#welcome_browser
            next = client.find_element('css selector', '#forward')
            next.tap()
            time.sleep(short_time)

        # app://communications.gaiamobile.org/ftu/index.html#welcome_browser
        file_name = 'welcome_browser'
        screenshot_entry = {
            "id": file_name,
            "script": app,
            "gaia": gaia_hash,
            "hg": hg_hash,
            "changed": False,
            "path": screenshot_path
        }
        test_flags = {}
        if check_flags(test_flags, device_flags):
            screenshot_entry.update(test_flags)
            if take_screenshot(locale, screenshot_path, client, file_name):
                screenshot_entry['changed'] = True
            log_displayed_l10n_strings(client, db, app, app_categ,
                                       screenshot_entry)

            # switch to app://communications.gaiamobile.org/ftu/index.html#browser_privacy
            next = client.find_element('css selector', '#forward')
            next.tap()
            time.sleep(short_time)

        # app://communications.gaiamobile.org/ftu/index.html#browser_privacy
        file_name = 'browser_privacy'
        screenshot_entry = {
            "id": file_name,
            "script": app,
            "gaia": gaia_hash,
            "hg": hg_hash,
            "changed": False,
            "path": screenshot_path
        }
        test_flags = {}
        if check_flags(test_flags, device_flags):
            screenshot_entry.update(test_flags)
            if take_screenshot(locale, screenshot_path, client, file_name):
                screenshot_entry['changed'] = True
            log_displayed_l10n_strings(client, db, app, app_categ,
                                       screenshot_entry)

            # switch to app://communications.gaiamobile.org/ftu/index.html#step1 (first tutorial screen)
            next = client.find_element('css selector', '#forward')
            next.tap()
            time.sleep(long_time)

        # app://communications.gaiamobile.org/ftu/index.html#step1 (first tutorial screen)
        file_name = 'step1-first_tutorial_screen'
        screenshot_entry = {
            "id": file_name,
            "script": app,
            "gaia": gaia_hash,
            "hg": hg_hash,
            "changed": False,
            "path": screenshot_path
        }
        test_flags = {}
        if check_flags(test_flags, device_flags):
            screenshot_entry.update(test_flags)
            if take_screenshot(locale, screenshot_path, client, file_name):
                screenshot_entry['changed'] = True
            log_displayed_l10n_strings(client, db, app, app_categ,
                                       screenshot_entry)

            # switch to app://communications.gaiamobile.org/ftu/index.html#step1
            next = client.find_element('css selector', '#lets-go-button')
            next.tap()
            time.sleep(long_time)

        # app://communications.gaiamobile.org/ftu/index.html#step1
        file_name = 'step1'
        screenshot_entry = {
            "id": file_name,
            "script": app,
            "gaia": gaia_hash,
            "hg": hg_hash,
            "changed": False,
            "path": screenshot_path
        }
        test_flags = {}
        if check_flags(test_flags, device_flags):
            screenshot_entry.update(test_flags)
            if take_screenshot(locale, screenshot_path, client, file_name):
                screenshot_entry['changed'] = True
            log_displayed_l10n_strings(client, db, app, app_categ,
                                       screenshot_entry)

            # switch to app://communications.gaiamobile.org/ftu/index.html#step2
            next = client.find_element('css selector', '#forwardTutorial')
            next.tap()
            time.sleep(short_time)

        # app://communications.gaiamobile.org/ftu/index.html#step2
        file_name = 'step2'
        screenshot_entry = {
            "id": file_name,
            "script": app,
            "gaia": gaia_hash,
            "hg": hg_hash,
            "changed": False,
            "path": screenshot_path
        }
        test_flags = {}
        if check_flags(test_flags, device_flags):
            screenshot_entry.update(test_flags)
            if take_screenshot(locale, screenshot_path, client, file_name):
                screenshot_entry['changed'] = True
            log_displayed_l10n_strings(client, db, app, app_categ,
                                       screenshot_entry)

            # switch to app://communications.gaiamobile.org/ftu/index.html#step3
            next = client.find_element('css selector', '#forwardTutorial')
            next.tap()
            time.sleep(short_time)

        # app://communications.gaiamobile.org/ftu/index.html#step3
        file_name = 'step3'
        screenshot_entry = {
            "id": file_name,
            "script": app,
            "gaia": gaia_hash,
            "hg": hg_hash,
            "changed": False,
            "path": screenshot_path
        }
        test_flags = {}
        if check_flags(test_flags, device_flags):
            screenshot_entry.update(test_flags)
            if take_screenshot(locale, screenshot_path, client, file_name):
                screenshot_entry['changed'] = True
            log_displayed_l10n_strings(client, db, app, app_categ,
                                       screenshot_entry)

            # switch to app://communications.gaiamobile.org/ftu/index.html#step4
            next = client.find_element('css selector', '#forwardTutorial')
            next.tap()
            time.sleep(short_time)

        # app://communications.gaiamobile.org/ftu/index.html#step4
        file_name = 'step4'
        screenshot_entry = {
            "id": file_name,
            "script": app,
            "gaia": gaia_hash,
            "hg": hg_hash,
            "changed": False,
            "path": screenshot_path
        }
        test_flags = {}
        if check_flags(test_flags, device_flags):
            screenshot_entry.update(test_flags)
            if take_screenshot(locale, screenshot_path, client, file_name):
                screenshot_entry['changed'] = True
            log_displayed_l10n_strings(client, db, app, app_categ,
                                       screenshot_entry)

            # switch to app://communications.gaiamobile.org/ftu/index.html#step4 (last tutorial screen)
            next = client.find_element('css selector', '#forwardTutorial')
            next.tap()
            time.sleep(long_time)

        # app://communications.gaiamobile.org/ftu/index.html#step4 (last tutorial screen)
        file_name = 'step4-last_tutorial_screen'
        screenshot_entry = {
            "id": file_name,
            "script": app,
            "gaia": gaia_hash,
            "hg": hg_hash,
            "changed": False,
            "path": screenshot_path
        }
        test_flags = {}
        if check_flags(test_flags, device_flags):
            screenshot_entry.update(test_flags)
            if take_screenshot(locale, screenshot_path, client, file_name):
                screenshot_entry['changed'] = True
            log_displayed_l10n_strings(client, db, app, app_categ,
                                       screenshot_entry)

            # Close ftu frame
            next = client.find_element('css selector', '#tutorialFinished')
            next.tap()
            time.sleep(short_time)

        set_db(locale, db)

    else:
        #TO DO raise proper error
        print "switch to ftu frame failed"
Exemplo n.º 27
0
class B2GManager(object):

    def __init__(self, dm, tmpdir=None, userJS=None, marionette_host=None, marionette_port=None):
        self.dm = dm
        self.tmpdir = tmpdir
        self.userJS = userJS or "/data/local/user.js"
        self.marionette_host = marionette_host or 'localhost'
        self.marionette_port = marionette_port or 2828
        self.marionette = None

    #timeout in seconds
    def wait_for_port(self, timeout):
        print "waiting for port"
        starttime = datetime.datetime.now()
        while datetime.datetime.now() - starttime < datetime.timedelta(seconds=timeout):
            try:
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                print "trying %s %s" % (self.marionette_port, self.marionette_host)
                sock.connect((self.marionette_host, self.marionette_port))
                data = sock.recv(16)
                sock.close()
                if '"from"' in data:
                    print "got it"
                    return True
            except:
                import traceback
                print traceback.format_exc()
            time.sleep(1)
        return False

    def get_marionette(self):
        self.marionette = Marionette(self.marionette_host, self.marionette_port)

    def restart_b2g(self):
        #restart b2g so we start with a clean slate
        self.dm.checkCmd(['shell', 'stop', 'b2g'])
        # Wait for a bit to make sure B2G has completely shut down.
        time.sleep(10)
        self.dm.checkCmd(['shell', 'start', 'b2g'])

        #wait for marionette port to come up
        print "connect to marionette"
        if not self.wait_for_port(30):
            raise Exception("Could not communicate with Marionette port after restarting B2G")
        self.get_marionette()

    def set_tmpdir(self, tmpdir):
        self.tmpdir = tmpdir

    def setup_profile(self, prefs):
        if not self.tmpdir:
            raise Exception("You must set the tmpdir")
        #remove previous user.js if there is one
        our_user_js = os.path.join(self.tmpdir, "user.js")
        if os.path.exists(our_user_js):
            os.remove(our_user_js)
        #copy profile
        try:
            self.dm.checkCmd(["pull", self.userJS, our_user_js])
        except subprocess.CalledProcessError:
            pass
        #if we successfully copied the profile, make a backup of the file
        if os.path.exists(our_user_js):
            self.dm.checkCmd(['shell', 'dd', 'if=%s' % self.userJS, 'of=%s.orig' % self.userJS])
        print "opening userjs"
        user_js = open(our_user_js, 'a')
        print "Writing: %s" % prefs
        user_js.write("%s" % prefs)
        print "closing"
        user_js.close()
        self.dm.checkCmd(['push', our_user_js, self.userJS])
        self.restart_b2g()

    def forward_port(self):
        self.dm.checkCmd(['forward',
                          'tcp:%s' % self.marionette_port,
                          'tcp:%s' % self.marionette_port])

    def setup_ethernet(self):
        #TODO: need to add timeout
        tries = 3
        while tries > 0:
            print "on try: %d" % tries
            output = StringIO.StringIO()
            self.dm.shell(['ifconfig', 'eth0'], output)
            print "we get back %s" % output.getvalue()
            if "ip" in output.getvalue():
                return
            output.close()
            try:
                self.dm.checkCmd(['shell', 'netcfg', 'eth0', 'dhcp'], timeout=10)
            except DMError:
                pass
            tries = tries - 1
        raise DMError("Could not set up ethernet connection")

    def restore_profile(self):
        if not self.tmpdir:
            raise Exception("You must set the tmpdir")
        #if we successfully copied the profile, make a backup of the file
        our_user_js = os.path.join(self.tmpdir, "user.js")
        if os.path.exists(our_user_js):
            self.dm.checkCmd(['shell', 'dd', 'if=%s.orig' % self.userJS, 'of=%s' % self.userJS])

    def get_appinfo(self):
        if not self.marionette:
            self.forward_port()
            self.wait_for_port(30)
            self.get_marionette()
        self.marionette.start_session()
        self.marionette.set_context("chrome")
        appinfo = self.marionette.execute_script("""
                                var appInfo = Components.classes["@mozilla.org/xre/app-info;1"]
                                .getService(Components.interfaces.nsIXULAppInfo);
                                return appInfo;
                                """)
        (year, month, day) = (appinfo["appBuildID"][0:4], appinfo["appBuildID"][4:6], appinfo["appBuildID"][6:8])
        appinfo['date'] =  "%s-%s-%s" % (year, month, day)
        return appinfo
Exemplo n.º 28
0
class Runner(object):

    _INPUT_NONE = ''
    _INPUT_EXIT_COMMAND = 'exit'
    _INPUT_MULTIPLE_LINE = ' \\'
    _INPUT_COMMAND_PREFIX = ':'
    _INPUT_SYSTEM_APP_KEYWORD = 'system'

    _is_async = False
    _sync_prompt = '>>> '
    _async_prompt = 'a>> '
    _prompt = _sync_prompt

    def __init__(self, **kwargs):
        # Added parser
        parser = OptionParser()
        parser.add_option('-a', '--address',
                          action='store', type='string', dest='address',
                          default='localhost',
                          help='The host address of b2g instance. Default=localhost')
        parser.add_option('-p', '--port',
                          action='store', type='int', dest='port',
                          default=2828,
                          help='The port of b2g instance.')
        parser.add_option('-l', '--list',
                          action='store_true', dest='enable_list',
                          default='False',
                          help='List all apps of b2g instance. Default=False')
        parser.add_option('-c', '--connect',
                          action='store', type='string', dest='connect',
                          default=None,
                          help='Connect to the App iframe.' \
                               'Use # ID or App URL to connect.')

        (options, args) = parser.parse_args()
        self.connect = options.connect

        # start marionette session
        self.m = Marionette(options.address, options.port)
        self.m.start_session()

        # list all iframes
        if options.enable_list:
            self.list_all_iframes()
        # list active iframes
        elif self.connect == None:
            self.list_active_iframes()

        # connect to App
        if self.connect == None:
            exit(0)
        else:
            # connect App
            print 'Start...'
            if self.open_app(self.connect):
                self.start_js()
            else:
                exit(-1)

    def switch_sync_async(self):
        self._is_async = not self._is_async
        self._prompt = self._async_prompt if self._is_async else self._sync_prompt
        print 'Swith to', ('Async' if self._is_async else 'Sync'), 'JS execution'

    def start_js(self):
        print 'Enter \'%s\' or Crtl+D to exit the shell.' % self._INPUT_EXIT_COMMAND
        print 'And enter \':h\' for more commands.'
        try:
            while True:
                input = raw_input(self._prompt)
                # if input is EXIT command, exit this program
                if input.lower() == self._INPUT_EXIT_COMMAND:
                    self.goodbye()
                    break

                # if input is NONE, then do nothing and keep going...
                elif input == self._INPUT_NONE:
                    continue

                # if input start with ":", it should be the command.
                elif input.startswith(self._INPUT_COMMAND_PREFIX):
                    CmdDispatcher(self, input)

                # if the postfix of input is MULTIPLE_LINE, then record this line and wait the next line until no input with MULTIPLE_LINE.
                elif input.endswith(self._INPUT_MULTIPLE_LINE):
                    input_multiple = input[:len(input) - 1] + '; '
                    while True:
                        next_input = raw_input('... ')
                        if next_input.endswith(self._INPUT_MULTIPLE_LINE):
                            input_multiple = input_multiple + next_input[:len(next_input) - 1] + '; '
                            pass
                        else:
                            input_multiple = input_multiple + next_input + '; '
                            print self.execute_script(input_multiple)
                            break

                # if input is NOT above inputs, then run marionette.execute_script(INPUT)/marionette.execute_async_script(INPUT)
                # and print return value.
                else:
                    print self.execute_script(input)

        except EOFError:
            self.goodbye()
            exit()
        except Exception as e:
            print e
            if self.open_app(-1):
                self.start_js()
        exit()

    def execute_script(self, script):
        try:
            if self._is_async:
                return self.m.execute_async_script(script)
            else:
                return self.m.execute_script(script)
        except Exception as ex:
            print str(ex.message)

    def goodbye(self):
        print 'End. Bye!!'

    def open_app(self, input):
        try:
            # connect App by ID
            app_id = int(input)
            if app_id < 0:
                print 'Connect to', self._get_system_URL()
                self.set_current_frame(self._get_system_URL())
                self.m.switch_to_frame()
            else:
                iframes = self.get_all_iframes_id_name_pair()
                print 'Connect to', iframes[str(app_id)]
                self.set_current_frame(iframes[str(app_id)])
                self.m.switch_to_frame(app_id)
            return True

        except(ValueError):
            # connect to System app
            if (input.lower() == self._INPUT_SYSTEM_APP_KEYWORD) or (input.lower() in self._get_system_URL()):
                print 'Connect to', self._get_system_URL()
                self.set_current_frame(self._get_system_URL())
                self.m.switch_to_frame()
                return True

            # connect App by substring
            iframes = self.get_all_iframes_id_name_pair()
            suitable_iframes = {}
            for k, v in iframes.items():
                if input in v:
                    suitable_iframes[k] = v
            # connect to App if there is one fit
            if len(suitable_iframes) == 1:
                target = suitable_iframes.keys()[0]
                print 'Connect to', suitable_iframes.values()[0]
                self.set_current_frame(suitable_iframes.values()[0])
                self.m.switch_to_frame(int(target))
                return True
            # exit if there are more than one app fit the query
            elif len(suitable_iframes) > 1:
                print 'There are more than one Apps fit the query string [', input, '].'
                print '{0:2s} {1:s}'.format('#', 'App URL')
                for k, v in sorted(suitable_iframes.items()):
                    print '{0:2s} {1:s}'.format(k, v)
                return False
            # exit if there is no app fit the query
            else:
                print 'There is no App fit the query string [', input, '].'
                return False

    def set_current_frame(self, frame_name):
        self._current_frame = frame_name

    def get_current_frame(self):
        return self._current_frame

    def switch_to_system_frame(self):
        self.m.switch_to_frame()

    def _get_system_URL(self):
        self.switch_to_system_frame()
        system_URL = self.m.execute_script('return document.URL')
        return system_URL

    def _get_all_iframes(self):
        self.switch_to_system_frame()
        iframes = self.m.execute_script('return document.getElementsByTagName("iframe")')
        return iframes

    def get_all_iframes_id_name_pair(self):
        iframes = self._get_all_iframes()
        result = {}
        for idx in range(0, iframes['length']):
            iframe = iframes[str(idx)]
            result[str(idx)] = iframe.get_attribute('src')
        return result

    def list_all_iframes(self):
        iframes = self._get_all_iframes()
        print '{0:2s} {1:7s} {2:s}'.format('#', 'Status', 'App URL')
        print '{0:2s} {1:7s} {2:s}'.format('-1', '', self._get_system_URL())
        for idx in range(0, iframes['length']):
            iframe = iframes[str(idx)]
            print '{0:2s} {1:7s} {2:s}'.format(str(idx), ('active' if iframe.is_displayed() else ''), iframe.get_attribute('src'))

    def list_active_iframes(self):
        iframes = self._get_all_iframes()
        print '{0:2s} {1:7s} {2:s}'.format('#', 'Status', 'App URL')
        result = {}
        for idx in range(0, iframes['length']):
            iframe = iframes[str(idx)]
            if iframe.is_displayed():
                result[str(idx)] = iframe
        for idx, iframe in result.items():
            print '{0:2s} {1:7s} {2:s}'.format(idx, ('active' if iframe.is_displayed() else ''), iframe.get_attribute('src'))

    # TODO: seems like should using Javascript to get the idx of each iframe!?
    def get_all_iframes_by_marionette(self):
        iframes = self.m.find_elements('css selector', 'iframe')
        return iframes

    def list_all_iframes_by_marionette(self):
        iframes = self.get_all_iframes_by_marionette()
        for iframe in iframes:
            print iframe.get_attribute('src')

    def list_active_iframes_by_marionette(self):
        iframes = self.get_all_iframes_by_marionette()
        result = []
        for iframe in iframes:
            if iframe.is_displayed():
                result.append(iframe)
        for iframe in result:
            print iframe.get_attribute('src')
Exemplo n.º 29
0
class MatsRunner(object):
    def __init__(self, config_file = 'config.ini', url = 'about:blank'):
        self.config_file = config_file
        self.url = url
        
    def start(self):
        '''
        This method starts MATS.
        '''
        
        print 'Using ' + MatsController.__name__ + ' as controller.'
        print 'Loading config from "' + self.config_file + '"...',
        self.config = get_config(self.config_file)   #get_config makes sure that the config makes sense. More details in get_config.py
        self.marionette_port = self.config['Marionette']['port'] 
        print 'OK'
        
        print 'Starting Firefox/Nightly from "' + self.config['Firefox']['binary'] + '" with Marionette on port ' + str(self.marionette_port) + '.'        
        self.FirefoxThread = FirefoxThread(self.config['Firefox']['binary'], self.marionette_port)
        self.FirefoxThread.start()
        
        print 'Creating controller'
        pid = self.FirefoxThread.getPID() # this function blocks until PID is available from FirefoxThread
        self.controller = MatsController(pid)
        
        print 'Starting controller'
        self.controller.start()
        self.controller.wait_for_ready()
        
        print 'Waiting for Marionette port to open (' + str(self.marionette_port) + ')'
        portReady = self.FirefoxThread.waitForMarionettePortOpenReady(self.config['Marionette']['port_timeout'])
        if portReady:
            print 'Marionette port open'
        else:
            print 'Error: timeout, shutting down MATS'
            self.controller.stop()
            self.FirefoxThread.stop()
            return
        
        #TODO: remove line below once https://bugzilla.mozilla.org/show_bug.cgi?id=753273 is fixed
        #sleep(10)
        
        try:
            print 'Starting Marionette'
            self.marionette = Marionette('localhost', self.marionette_port)
            #TODO: move starting session and navigation to separate methods
            print 'Starting session'
            sleep(5) #TODO temporary workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=757078
            self.marionette_session = self.marionette.start_session()
            print 'Navigating to ' + self.url
            print self.marionette.navigate(self.url)
        except Exception as e:
            print 'Error starting Marionette'
            fall(e)
            self.controller.stop()
            self.FirefoxThread.stop()

        print 'MATS up and running. Waiting until Firefox/Nightly stops.'
    
    def wait_for_stop(self):
        self.FirefoxThread.join()
        print 'Stopping controller'
        self.controller.stop()
        self.controller.join()
        print 'MATS runner finishes.'
    
    def stop(self):
        self.FirefoxThread.stop()
        self.FirefoxThread.join()
        print 'Stopping controller'
        self.controller.stop()
        self.controller.join()
        print 'MATS runner finishes.'
    
    def instantiate_a11y(self):
        '''
        runs via marionette script taken from 
        http://dxr.lanedo.com/search.cgi?tree=mozilla-central&string=nsIAccessibleApplication
        to force A11y engine instantiation.
        
        sets context to content after doing it's stuff
        '''
        
        script = \
'''
const nsIAccessibleRetrieval = Components.interfaces.nsIAccessibleRetrieval;
const nsIAccessibleApplication = Components.interfaces.nsIAccessibleApplication;

var gAccRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"].
  getService(nsIAccessibleRetrieval);
app = gAccRetrieval.getApplicationAccessible().
    QueryInterface(nsIAccessibleApplication);
    
return (app) ? true : false;
'''
        self.marionette.set_context("chrome")
        notNull = self.marionette.execute_script(script)
        self.marionette.set_context("content")
        return notNull
    
    def is_a11y_instantiated(self):
        '''
        runs via marionette script that checks if A11y engine is instantiated.
        and returns true if so.
        
        sets context to content after doing it's stuff
        '''
        
        script = \
'''
        var enabled;
        enabled = Components.manager.QueryInterface(Ci.nsIServiceManager)
                    .isServiceInstantiatedByContractID(
                    "@mozilla.org/accessibilityService;1",
                    Ci.nsISupports);

        return enabled;
'''
        self.marionette.set_context('chrome')
        result = self.marionette.execute_script(script)
        self.marionette.set_context('content') 
        return result
    
    def wait_for_event(self, event_string, callable, timeout = 60):
        '''
        this method is the easiest interface to wait for an event.
        First, it registers listener.
        Second, it calls callable (TODO: add arguments)
        Third, it waits for the event or timeouts
        
        it returns True if the event was captured, and False if timeout occured
        
        TODO: abstract it to cross-platform
        '''
        
        arrived = threading.Event()
        
        def callback(event):
            print 'got event! ' + str(event)
            arrived.set()
            
        self.controller.register_event_listener(event_string, callback)
        self.controller.unpause_event_loop()
        
        callable()
        
        result = arrived.wait(timeout)
        
        self.controller.pause_event_loop()
        self.controller.deregister_event_listener(event_string, callback)
        return result
Exemplo n.º 30
0
class GCli(object):

    def __init__(self):
        self.commands = {
            'connectwifi': {
                'function': self.connect_to_wifi,
                'args': [
                    {'name': 'ssid',
                     'help': 'SSID of the network to connect to'},
                    {'name': '--security',
                     'choices': ['WPA-PSK', 'WEP'],
                     'help': 'Security model of the network'},
                    {'name': '--password',
                     'help': 'Password to access the network'}],
                'help': 'Connect to a WiFi network'},
            'disablewifi': {
                'function': self.disable_wifi,
                'help': 'Disable WiFi'},
            'enablewifi': {
                'function': self.enable_wifi,
                'help': 'Enable WiFi'},
            'forgetallwifi': {
                'function': self.forget_all_wifi_networks,
                'help': 'Forget all WiFi networks'},
            'getknownwifi': {
                'function': self.known_wifi_networks,
                'help': 'Show known WiFi networks'},
            'getsetting': {
                'function': self.get_setting,
                'args': [{
                    'name': 'name',
                    'help': 'Name of the setting to retrieve'}],
                'help': 'Show the current value of a setting'},
            'holdhome': {
                'function': self.hold_home,
                'help': 'Simulate holding the home button'},
            'holdsleep': {
                'function': self.hold_sleep,
                'help': 'Simulate holding the sleep button'},
            'home': {
                'function': self.home,
                'help': 'Simulate pressing the home button'},
            'killapps': {
                'function': self.kill_all_apps,
                'help': 'Kill all running apps'},
            'launchapp': {
                'function': self.launch_app,
                'args': [
                    {'name': 'name',
                     'nargs': argparse.REMAINDER,
                     'help': 'Name of app to launch'}],
                'help': 'Launch an application'},
            'listallapps': {
                'function': self.list_all_apps,
                'help': 'List all apps'},
            'listrunningapps': {
                'function': self.list_running_apps,
                'help': 'List the running apps'},
            'lock': {
                'function': self.lock,
                'help': 'Lock screen'},
            'screenshot': {
                'function': self.screenshot,
                'help': 'Take a screenshot'},
            'sendsms': {
                'function': self.send_sms,
                'args': [
                    {'name': 'number',
                     'help': 'Phone number of recipient'},
                    {'name': 'message',
                     'help': 'Message content'}],
                'help': 'Send an SMS'},
            'setsetting': {
                'function': self.set_setting,
                'args': [
                    {'name': 'name',
                     'help': 'Name of setting to change'},
                    {'name': 'value',
                     'help': 'New value for setting'}],
                'help': 'Change the value of a setting'},
            'sleep': {
                'function': self.sleep,
                'help': 'Enter sleep mode'},
            'unlock': {
                'function': self.unlock,
                'help': 'Unlock screen'},
            'volume': {
                'function': self.volume,
                'args': [
                    {'name': 'direction',
                     'choices': ['down', 'up'],
                     'help': 'Direction to change the volume'}],
                'help': 'Change the volume'},
            'wake': {
                'function': self.wake,
                'help': 'Wake from sleep mode'}}

        self.parser = argparse.ArgumentParser()
        self.add_options(self.parser)
        self.add_commands(self.parser)

    def run(self, args=sys.argv[1:]):
        args = self.parser.parse_args()

        host, port = args.address.split(':')
        self.marionette = Marionette(host=host, port=int(port))
        self.marionette.start_session()

        self.apps = gaiatest.GaiaApps(self.marionette)
        self.data_layer = gaiatest.GaiaData(self.marionette)
        self.lock_screen = gaiatest.LockScreen(self.marionette)

        ret = args.func(args)
        if ret is None:
            ret = 0

        self.marionette.delete_session()

        sys.exit(ret)

    def add_options(self, parser):
        parser.add_argument(
            '--address',
            default='localhost:2828',
            help='Address (host:port) of running Gecko instance to connect to '
                 '(default: %(default)s)')

    def add_commands(self, parser):
        subparsers = parser.add_subparsers(
            title='Commands', metavar='<command>')
        for (name, props) in sorted(self.commands.iteritems()):
            subparser = subparsers.add_parser(name, help=props['help'])
            if props.get('args'):
                for arg in props['args']:
                    kwargs = {k: v for k, v in arg.items() if k is not 'name'}
                    subparser.add_argument(arg['name'], **kwargs)
            subparser.set_defaults(func=props['function'])

    def connect_to_wifi(self, args):
        network = {
            'ssid': args.ssid,
            'keyManagement': args.security or 'NONE'}
        if args.security == 'WEP':
            network['wep'] = args.password
        elif args.security == 'WPA-PSK':
            network['psk'] = args.password
        self.data_layer.connect_to_wifi(network)

    def disable_wifi(self, args):
        self.data_layer.disable_wifi()

    def enable_wifi(self, args):
        self.data_layer.enable_wifi()

    def forget_all_wifi_networks(self, args):
        self.data_layer.forget_all_networks()

    def get_setting(self, args):
        print '%s: %s' % (
            args.name,
            self.data_layer.get_setting(args.name))

    def home(self, args):
        self.marionette.execute_script(
            "window.wrappedJSObject.dispatchEvent(new Event('home'));")

    def hold_home(self, args):
        self.marionette.execute_script(
            "window.wrappedJSObject.dispatchEvent(new Event('holdhome'));")

    def hold_sleep(self, args):
        self.marionette.execute_script(
            "window.wrappedJSObject.dispatchEvent(new Event('holdsleep'));")

    def kill_all_apps(self, args):
        self.apps.kill_all()

    def known_wifi_networks(self, args):
        networks = [n for n in self.data_layer.known_networks if 'ssid' in n]
        if len(networks) > 0:
            for i, network in enumerate(networks):
                print '%s: %s' % (i + 1, network['ssid'])
        else:
            print 'No known networks.'

    def launch_app(self, args):
        for name in args.name:
            self.apps.launch(name)

    def list_all_apps(self, args):
        for i, app in enumerate(sorted(self.apps.installed_apps,
                                       key=lambda a: a.name.lower())):
            print '%d: %s' % (i + 1, app.name)

    def list_running_apps(self, args):
        for i, app in enumerate(sorted(self.apps.running_apps,
                                       key=lambda a: a.name.lower())):
            print '%d: %s' % (i + 1, app.name)

    def lock(self, args):
        self.lock_screen.lock()

    def screenshot(self, args):
        self.marionette.execute_script(
            "window.wrappedJSObject.dispatchEvent(new Event('home+sleep'));")

    def send_sms(self, args):
        self.data_layer.send_sms(args.number, args.message)

    def set_setting(self, args):
        self.data_layer.set_setting(args.name, args.value)

    def sleep(self, args):
        self.marionette.execute_script(
            "window.wrappedJSObject.dispatchEvent(new Event('sleep'));")

    def unlock(self, args):
        self.lock_screen.unlock()

    def volume(self, args):
        self.marionette.execute_script(
            "window.wrappedJSObject.dispatchEvent(new Event('volume%s'));" %
            args.direction)

    def wake(self, args):
        self.marionette.execute_script(
            "window.wrappedJSObject.dispatchEvent(new Event('wake'));")
Exemplo n.º 31
0
class B2GMixin(object):
    profileDir = None
    userJS = "/data/local/user.js"
    marionette = None

    def __init__(self, host=None, marionetteHost=None, marionettePort=2828,
                 **kwargs):

        # (allowing marionneteHost to be specified seems a bit
        # counter-intuitive since we normally get it below from the ip
        # address, however we currently need it to be able to connect
        # via adb port forwarding and localhost)
        if marionetteHost:
            self.marionetteHost = marionetteHost
        elif host:
            self.marionetteHost = host
        self.marionettePort = marionettePort

    def cleanup(self):
        if self.profileDir:
            self.restoreProfile()

    def waitForPort(self, timeout):
        """
        Wait for the marionette server to respond.
        Timeout parameter is in seconds
        """
        print "waiting for port"
        starttime = datetime.datetime.now()
        while datetime.datetime.now() - starttime < datetime.timedelta(seconds=timeout):
            try:
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                print "trying %s %s" % (self.marionettePort, self.marionetteHost)
                sock.connect((self.marionetteHost, self.marionettePort))
                data = sock.recv(16)
                sock.close()
                if '"from"' in data:
                    return True
            except socket.error:
                pass
            except Exception as e:
                raise DMError("Could not connect to marionette: %s" % e)
            time.sleep(1)
        raise DMError("Could not communicate with Marionette port")

    def setupMarionette(self):
        """
        Start a marionette session.
        If no host is given, then this will get the ip
        of the device, and set up networking if needed.
        """
        if not self.marionetteHost:
            self.setupDHCP()
            self.marionetteHost = self.getIP()
        if not self.marionette:
            self.marionette = Marionette(self.marionetteHost, self.marionettePort)
        if not self.marionette.session:
            self.waitForPort(30)
            self.marionette.start_session()

    def restartB2G(self):
        """
        Restarts the b2g process on the device
        """
        #restart b2g so we start with a clean slate
        if self.marionette and self.marionette.session:
            self.marionette.delete_session()
        self.shellCheckOutput(['stop', 'b2g'])
        # Wait for a bit to make sure B2G has completely shut down.
        tries = 10
        while "b2g" in self.shellCheckOutput(['ps', 'b2g']) and tries > 0:
            tries -= 1
            time.sleep(1)
        if tries == 0:
            raise DMError("Could not kill b2g process")
        self.shellCheckOutput(['start', 'b2g'])

    def setupProfile(self, prefs=None):
        """
        Sets up the user profile on the device,
        The 'prefs' is a string of user_prefs to add to the profile.
        If it is not set, it will default to a standard b2g testing profile.
        """
        if not prefs:
            prefs = """
user_pref("power.screen.timeout", 999999);
user_pref("devtools.debugger.force-local", false);
            """
        #remove previous user.js if there is one
        if not self.profileDir:
            self.profileDir = tempfile.mkdtemp()
        our_userJS = os.path.join(self.profileDir, "user.js")
        if os.path.exists(our_userJS):
            os.remove(our_userJS)
        #copy profile
        try:
            output = self.getFile(self.userJS, our_userJS)
        except subprocess.CalledProcessError:
            pass
        #if we successfully copied the profile, make a backup of the file
        if os.path.exists(our_userJS):
            self.shellCheckOutput(['dd', 'if=%s' % self.userJS, 'of=%s.orig' % self.userJS])
        with open(our_userJS, 'a') as user_file:
            user_file.write("%s" % prefs)
        self.pushFile(our_userJS, self.userJS)
        self.restartB2G()
        self.setupMarionette()

    def setupDHCP(self, conn_type='eth0'):
        """
        Sets up networking.

        If conn_type is not set, it will assume eth0.
        """
        tries = 5
        while tries > 0:
            print "attempts left: %d" % tries
            try:
                self.shellCheckOutput(['netcfg', conn_type, 'dhcp'], timeout=10)
                if self.getIP():
                    return
            except DMError:
                pass
            tries = tries - 1
        raise DMError("Could not set up network connection")

    def restoreProfile(self):
        """
        Restores the original profile
        """
        if not self.profileDir:
            raise DMError("There is no profile to restore")
        #if we successfully copied the profile, make a backup of the file
        our_userJS = os.path.join(self.profileDir, "user.js")
        if os.path.exists(our_userJS):
            self.shellCheckOutput(['dd', 'if=%s.orig' % self.userJS, 'of=%s' % self.userJS])
        shutil.rmtree(self.profileDir)
        self.profileDir = None

    def getAppInfo(self):
        """
        Returns the appinfo, with an additional "date" key.
        """
        if not self.marionette or not self.marionette.session:
            self.setupMarionette()
        self.marionette.set_context("chrome")
        appinfo = self.marionette.execute_script("""
                                var appInfo = Components.classes["@mozilla.org/xre/app-info;1"]
                                .getService(Components.interfaces.nsIXULAppInfo);
                                return appInfo;
                                """)
        (year, month, day) = (appinfo["appBuildID"][0:4], appinfo["appBuildID"][4:6], appinfo["appBuildID"][6:8])
        appinfo['date'] =  "%s-%s-%s" % (year, month, day)
        return appinfo
Exemplo n.º 32
0
class Runner(object):

    _INPUT_NONE = ''
    _INPUT_EXIT_COMMAND = 'exit'
    _INPUT_MULTIPLE_LINE = ' \\'
    _INPUT_COMMAND_PREFIX = ':'
    _INPUT_SYSTEM_APP_KEYWORD = 'system'

    _KEYBOARD_FRAME_NAME = 'app://keyboard.gaiamobile.org/index.html'

    _is_async = False
    _sync_prompt = '>>> '
    _async_prompt = 'a>> '
    _prompt = _sync_prompt

    def __init__(self, **kwargs):
        # Added parser
        parser = OptionParser()
        parser.add_option(
            '-a',
            '--address',
            action='store',
            type='string',
            dest='address',
            default='localhost',
            help='The host address of b2g instance. Default=localhost')
        parser.add_option('-p',
                          '--port',
                          action='store',
                          type='int',
                          dest='port',
                          default=2828,
                          help='The port of b2g instance.')
        parser.add_option('-l',
                          '--list',
                          action='store_true',
                          dest='enable_list',
                          default='False',
                          help='List all apps of b2g instance. Default=False')
        parser.add_option('-c', '--connect',
                          action='store', type='string', dest='connect',
                          default=None,
                          help='Connect to the App iframe.' \
                               'Use # ID or App URL to connect.')

        (options, args) = parser.parse_args()
        self.connect = options.connect

        # start marionette session
        self.m = Marionette(options.address, options.port)
        self.m.start_session()

        # list all iframes
        if options.enable_list:
            self.list_all_iframes()
        # list active iframes
        elif self.connect == None:
            self.list_active_iframes()

        # connect to App
        if self.connect == None:
            exit(0)
        else:
            # connect App
            print 'Start...'
            if self.open_app(self.connect):
                self.start_js()
            else:
                exit(-1)

    def switch_sync_async(self):
        self._is_async = not self._is_async
        self._prompt = self._async_prompt if self._is_async else self._sync_prompt
        print 'Swith to', ('Async'
                           if self._is_async else 'Sync'), 'JS execution'

    def start_js(self):
        print 'Enter \'%s\' or Crtl+D to exit the shell.' % self._INPUT_EXIT_COMMAND
        print 'And enter \':h\' for more commands.'
        try:
            while True:
                input = raw_input(self._prompt)
                # if input is EXIT command, exit this program
                if input.lower() == self._INPUT_EXIT_COMMAND:
                    self.goodbye()
                    break

                # if input is NONE, then do nothing and keep going...
                elif input == self._INPUT_NONE:
                    continue

                # if input start with ":", it should be the command.
                elif input.startswith(self._INPUT_COMMAND_PREFIX):
                    CmdDispatcher(self, input)

                # if the postfix of input is MULTIPLE_LINE, then record this line and wait the next line until no input with MULTIPLE_LINE.
                elif input.endswith(self._INPUT_MULTIPLE_LINE):
                    input_multiple = input[:len(input) - 1] + '; '
                    while True:
                        next_input = raw_input('... ')
                        if next_input.endswith(self._INPUT_MULTIPLE_LINE):
                            input_multiple = input_multiple + next_input[:len(
                                next_input) - 1] + '; '
                            pass
                        else:
                            input_multiple = input_multiple + next_input + '; '
                            print self.execute_script(input_multiple)
                            break

                # if input is NOT above inputs, then run marionette.execute_script(INPUT)/marionette.execute_async_script(INPUT)
                # and print return value.
                else:
                    print self.execute_script(input)

        except EOFError:
            self.goodbye()
            exit()
        except Exception as e:
            print e
            if self.open_app(-1):
                self.start_js()
        exit()

    def execute_script(self, script):
        try:
            if self._is_async:
                return self.m.execute_async_script(script)
            else:
                return self.m.execute_script(script)
        except Exception as ex:
            print str(ex.message)

    def goodbye(self):
        print 'End. Bye!!'

    def open_app(self, input):
        try:
            # connect App by ID
            app_id = int(input)
            if app_id < 0:
                print 'Connect to', self._get_system_URL()
                self.set_current_frame(self._get_system_URL())
                self.m.switch_to_frame()
            else:
                iframes = self.get_all_iframes_id_name_pair()
                print 'Connect to', iframes[str(app_id)]
                self.set_current_frame(iframes[str(app_id)])
                if iframes[str(app_id)] == self._KEYBOARD_FRAME_NAME:
                    self.m.switch_to_frame(app_id, False)
                else:
                    self.m.switch_to_frame(app_id)
            return True

        except (ValueError):
            # connect to System app
            if (input.lower() == self._INPUT_SYSTEM_APP_KEYWORD) or (
                    input.lower() in self._get_system_URL()):
                print 'Connect to', self._get_system_URL()
                self.set_current_frame(self._get_system_URL())
                self.m.switch_to_frame()
                return True

            # connect App by substring
            iframes = self.get_all_iframes_id_name_pair()
            suitable_iframes = {}
            for k, v in iframes.items():
                if input in v:
                    suitable_iframes[k] = v
            # connect to App if there is one fit
            if len(suitable_iframes) == 1:
                target = suitable_iframes.keys()[0]
                print 'Connect to', suitable_iframes.values()[0]
                self.set_current_frame(suitable_iframes.values()[0])
                if suitable_iframes.values()[0] == self._KEYBOARD_FRAME_NAME:
                    self.m.switch_to_frame(int(target), False)
                else:
                    self.m.switch_to_frame(int(target))
                return True
            # exit if there are more than one app fit the query
            elif len(suitable_iframes) > 1:
                print 'There are more than one Apps fit the query string [', input, '].'
                print '{0:2s} {1:s}'.format('#', 'App URL')
                for k, v in sorted(suitable_iframes.items()):
                    print '{0:2s} {1:s}'.format(k, v)
                return False
            # exit if there is no app fit the query
            else:
                print 'There is no App fit the query string [', input, '].'
                return False

    def set_current_frame(self, frame_name):
        self._current_frame = frame_name

    def get_current_frame(self):
        return self._current_frame

    def switch_to_system_frame(self):
        self.m.switch_to_frame()

    def _get_system_URL(self):
        self.switch_to_system_frame()
        system_URL = self.m.execute_script('return document.URL')
        return system_URL

    def _get_all_iframes(self):
        self.switch_to_system_frame()
        iframes = self.m.execute_script(
            'return document.getElementsByTagName("iframe")')
        return iframes

    def get_all_iframes_id_name_pair(self):
        iframes = self._get_all_iframes()
        result = {}
        for idx in range(0, iframes['length']):
            iframe = iframes[str(idx)]
            result[str(idx)] = iframe.get_attribute('src')
        return result

    def list_all_iframes(self):
        iframes = self._get_all_iframes()
        print '{0:2s} {1:7s} {2:s}'.format('#', 'Status', 'App URL')
        print '{0:2s} {1:7s} {2:s}'.format('-1', '', self._get_system_URL())
        for idx in range(0, iframes['length']):
            iframe = iframes[str(idx)]
            print '{0:2s} {1:7s} {2:s}'.format(
                str(idx), ('active' if iframe.is_displayed() else ''),
                iframe.get_attribute('src'))

    def list_active_iframes(self):
        iframes = self._get_all_iframes()
        print '{0:2s} {1:7s} {2:s}'.format('#', 'Status', 'App URL')
        result = {}
        for idx in range(0, iframes['length']):
            iframe = iframes[str(idx)]
            if iframe.is_displayed():
                result[str(idx)] = iframe
        for idx, iframe in result.items():
            print '{0:2s} {1:7s} {2:s}'.format(
                idx, ('active' if iframe.is_displayed() else ''),
                iframe.get_attribute('src'))

    # TODO: seems like should using Javascript to get the idx of each iframe!?
    def get_all_iframes_by_marionette(self):
        iframes = self.m.find_elements('css selector', 'iframe')
        return iframes

    def list_all_iframes_by_marionette(self):
        iframes = self.get_all_iframes_by_marionette()
        for iframe in iframes:
            print iframe.get_attribute('src')

    def list_active_iframes_by_marionette(self):
        iframes = self.get_all_iframes_by_marionette()
        result = []
        for iframe in iframes:
            if iframe.is_displayed():
                result.append(iframe)
        for iframe in result:
            print iframe.get_attribute('src')
Exemplo n.º 33
0
class B2GMochitest(MochitestUtilsMixin):
    marionette = None

    def __init__(self, marionette_args,
                       out_of_process=True,
                       profile_data_dir=None,
                       locations=os.path.join(here, 'server-locations.txt')):
        super(B2GMochitest, self).__init__()
        self.marionette_args = marionette_args
        self.out_of_process = out_of_process
        self.locations_file = locations
        self.preferences = []
        self.webapps = None
        self.test_script = os.path.join(here, 'b2g_start_script.js')
        self.test_script_args = [self.out_of_process]
        self.product = 'b2g'

        # structured logging
        self.message_logger = MessageLogger(logger=log)

        if profile_data_dir:
            self.preferences = [os.path.join(profile_data_dir, f)
                                 for f in os.listdir(profile_data_dir) if f.startswith('pref')]
            self.webapps = [os.path.join(profile_data_dir, f)
                             for f in os.listdir(profile_data_dir) if f.startswith('webapp')]

        # mozinfo is populated by the parent class
        if mozinfo.info['debug']:
            self.SERVER_STARTUP_TIMEOUT = 180
        else:
            self.SERVER_STARTUP_TIMEOUT = 90

    def setup_common_options(self, options):
        test_url = self.buildTestPath(options)
        # For B2G emulators buildURLOptions has been called
        # without calling buildTestPath first and that
        # causes manifestFile not to be set
        if not "manifestFile=tests.json" in self.urlOpts:
            self.urlOpts.append("manifestFile=%s" % options.manifestFile)

        if len(self.urlOpts) > 0:
            test_url += "?" + "&".join(self.urlOpts)
        self.test_script_args.append(test_url)

    def buildTestPath(self, options, testsToFilter=None):
        if options.manifestFile != 'tests.json':
            super(B2GMochitest, self).buildTestPath(options, testsToFilter, disabled=False)
        return self.buildTestURL(options)

    def build_profile(self, options):
        # preferences
        prefs = {}
        for path in self.preferences:
            prefs.update(Preferences.read_prefs(path))

        for v in options.extraPrefs:
            thispref = v.split("=", 1)
            if len(thispref) < 2:
                print "Error: syntax error in --setpref=" + v
                sys.exit(1)
            prefs[thispref[0]] = thispref[1]

        # interpolate the preferences
        interpolation = { "server": "%s:%s" % (options.webServer, options.httpPort),
                          "OOP": "true" if self.out_of_process else "false" }
        prefs = json.loads(json.dumps(prefs) % interpolation)
        for pref in prefs:
            prefs[pref] = Preferences.cast(prefs[pref])

        kwargs = {
            'addons': self.getExtensionsToInstall(options),
            'apps': self.webapps,
            'locations': self.locations_file,
            'preferences': prefs,
            'proxy': {"remote": options.webServer}
        }

        if options.profile:
            self.profile = Profile.clone(options.profile, **kwargs)
        else:
            self.profile = Profile(**kwargs)

        options.profilePath = self.profile.profile
        # TODO bug 839108 - mozprofile should probably handle this
        manifest = self.addChromeToProfile(options)
        self.copyExtraFilesToProfile(options)
        return manifest

    def run_tests(self, options):
        """ Prepare, configure, run tests and cleanup """

        manifest = self.build_profile(options)
        self.leak_report_file = os.path.join(options.profilePath, "runtests_leaks.log")

        # configuring the message logger's buffering
        self.message_logger.buffering = options.quiet

        if options.debugger or not options.autorun:
            timeout = None
        else:
            if not options.timeout:
                if mozinfo.info['debug']:
                    options.timeout = 420
                else:
                    options.timeout = 300
            timeout = options.timeout + 30.0

        log.info("runtestsb2g.py | Running tests: start.")
        status = 0
        try:
            def on_output(line):
                messages = self.message_logger.write(line)
                for message in messages:
                    if message['action'] == 'test_start':
                        self.runner.last_test = message['test']

            # The logging will be handled by on_output, so we set the stream to None
            process_args = {'processOutputLine': on_output,
                            'stream': None}
            self.marionette_args['process_args'] = process_args
            self.marionette_args['profile'] = self.profile

            self.marionette = Marionette(**self.marionette_args)
            self.runner = self.marionette.runner
            self.app_ctx = self.runner.app_ctx

            self.remote_log = posixpath.join(self.app_ctx.remote_test_root,
                                             'log', 'mochitest.log')
            if not self.app_ctx.dm.dirExists(posixpath.dirname(self.remote_log)):
                self.app_ctx.dm.mkDirs(self.remote_log)

            self.startServers(options, None)
            self.buildURLOptions(options, {'MOZ_HIDE_RESULTS_TABLE': '1'})
            self.test_script_args.append(not options.emulator)
            self.test_script_args.append(options.wifi)


            self.runner.start(outputTimeout=timeout)

            self.marionette.wait_for_port()
            self.marionette.start_session()
            self.marionette.set_context(self.marionette.CONTEXT_CHROME)

            # Disable offline status management (bug 777145), otherwise the network
            # will be 'offline' when the mochitests start.  Presumably, the network
            # won't be offline on a real device, so we only do this for emulators.
            self.marionette.execute_script("""
                Components.utils.import("resource://gre/modules/Services.jsm");
                Services.io.manageOfflineStatus = false;
                Services.io.offline = false;
                """)

            if os.path.isfile(self.test_script):
                with open(self.test_script, 'r') as script:
                    self.marionette.execute_script(script.read(),
                                                   script_args=self.test_script_args)
            else:
                self.marionette.execute_script(self.test_script,
                                               script_args=self.test_script_args)
            status = self.runner.wait()

            if status is None:
                # the runner has timed out
                status = 124
        except KeyboardInterrupt:
            log.info("runtests.py | Received keyboard interrupt.\n");
            status = -1
        except:
            traceback.print_exc()
            log.error("Automation Error: Received unexpected exception while running application\n")
            if hasattr(self, 'runner'):
                self.runner.check_for_crashes()
            status = 1

        self.stopServers()

        log.info("runtestsb2g.py | Running tests: end.")

        if manifest is not None:
            self.cleanup(manifest, options)
        return status

    def getGMPPluginPath(self, options):
        # TODO: bug 1043403
        return None
Exemplo n.º 34
0
    def run(self,
            script,
            address='localhost:2828',
            symbols=None,
            treeherder='https://treeherder.mozilla.org/',
            reset=False,
            **kwargs):
        try:
            host, port = address.split(':')
        except ValueError:
            raise ValueError('--address must be in the format host:port')

        # Check that Orangutan is installed
        self.adb_device = ADBDevice(self.device_serial)
        orng_path = posixpath.join('data', 'local', 'orng')
        if not self.adb_device.exists(orng_path):
            raise Exception('Orangutan not found! Please install it according '
                            'to the documentation.')

        self.runner = B2GDeviceRunner(serial=self.device_serial,
                                      process_args={'stream': None},
                                      symbols_path=symbols,
                                      logdir=self.temp_dir)

        if reset:
            self.runner.start()
        else:
            self.runner.device.connect()

        port = self.runner.device.setup_port_forwarding(remote_port=port)
        assert self.runner.device.wait_for_port(port), \
            'Timed out waiting for port!'

        marionette = Marionette(host=host, port=port)
        marionette.start_session()

        try:
            marionette.set_context(marionette.CONTEXT_CHROME)
            self.is_debug = marionette.execute_script(
                'return Components.classes["@mozilla.org/xpcom/debug;1"].'
                'getService(Components.interfaces.nsIDebug2).isDebugBuild;')
            marionette.set_context(marionette.CONTEXT_CONTENT)

            if reset:
                gaia_device = GaiaDevice(marionette)
                gaia_device.wait_for_b2g_ready(timeout=120)
                gaia_device.unlock()
                gaia_apps = GaiaApps(marionette)
                gaia_apps.kill_all()

            # TODO: Disable bluetooth, emergency calls, carrier, etc

            # Run Orangutan script
            remote_script = posixpath.join(self.adb_device.test_root,
                                           'orng.script')
            self.adb_device.push(script, remote_script)
            self.start_time = time.time()
            # TODO: Kill remote process on keyboard interrupt
            self.adb_device.shell(
                '%s %s %s' %
                (orng_path, self.device_properties['input'], remote_script))
            self.end_time = time.time()
            self.adb_device.rm(remote_script)
        except (MarionetteException, IOError):
            if self.runner.crashed:
                # Crash has been detected
                pass
            else:
                raise
        self.runner.check_for_crashes(test_name='b2gmonkey')

        # Report results to Treeherder
        required_envs = ['TREEHERDER_KEY', 'TREEHERDER_SECRET']
        if all([os.environ.get(v) for v in required_envs]):
            self.post_to_treeherder(script, treeherder)
        else:
            self._logger.info(
                'Results will not be posted to Treeherder. Please set the '
                'following environment variables to enable Treeherder '
                'reports: %s' %
                ', '.join([v for v in required_envs if not os.environ.get(v)]))
Exemplo n.º 35
0
class B2GDesktopReftest(RefTest):
    marionette = None

    def __init__(self, marionette_args):
        RefTest.__init__(self)
        self.last_test = os.path.basename(__file__)
        self.marionette_args = marionette_args
        self.profile = None
        self.runner = None
        self.test_script = os.path.join(here, 'b2g_start_script.js')
        self.timeout = None

    def run_marionette_script(self):
        self.marionette = Marionette(**self.marionette_args)
        assert (self.marionette.wait_for_port())
        self.marionette.start_session()
        self.marionette.set_context(self.marionette.CONTEXT_CHROME)

        if os.path.isfile(self.test_script):
            f = open(self.test_script, 'r')
            self.test_script = f.read()
            f.close()
        self.marionette.execute_script(self.test_script)

    def run_tests(self, test_path, options):
        reftestlist = self.getManifestPath(test_path)
        if not reftestlist.startswith('file://'):
            reftestlist = 'file://%s' % reftestlist

        self.profile = self.create_profile(options,
                                           reftestlist,
                                           profile_to_clone=options.profile)
        env = self.buildBrowserEnv(options, self.profile.profile)
        kp_kwargs = {
            'processOutputLine': [self._on_output],
            'onTimeout': [self._on_timeout],
            'kill_on_timeout': False
        }

        if not options.debugger:
            if not options.timeout:
                if mozinfo.info['debug']:
                    options.timeout = 420
                else:
                    options.timeout = 300
            self.timeout = options.timeout + 30.0

        log.info("%s | Running tests: start.", os.path.basename(__file__))
        cmd, args = self.build_command_line(
            options.app,
            ignore_window_size=options.ignoreWindowSize,
            browser_arg=options.browser_arg)
        self.runner = FirefoxRunner(profile=self.profile,
                                    binary=cmd,
                                    cmdargs=args,
                                    env=env,
                                    process_class=ProcessHandler,
                                    process_args=kp_kwargs,
                                    symbols_path=options.symbolsPath)

        status = 0
        try:
            self.runner.start(outputTimeout=self.timeout)
            log.info("%s | Application pid: %d", os.path.basename(__file__),
                     self.runner.process_handler.pid)

            # kick starts the reftest harness
            self.run_marionette_script()
            status = self.runner.wait()
        finally:
            self.runner.check_for_crashes(test_name=self.last_test)
            self.runner.cleanup()

        if status > 0:
            log.testFail("%s | application terminated with exit code %s",
                         self.last_test, status)
        elif status < 0:
            log.info("%s | application killed with signal %s", self.last_test,
                     -status)

        log.info("%s | Running tests: end.", os.path.basename(__file__))
        return status

    def create_profile(self, options, reftestlist, profile_to_clone=None):
        profile = RefTest.createReftestProfile(
            self, options, reftestlist, profile_to_clone=profile_to_clone)

        prefs = {}
        # Turn off the locale picker screen
        prefs["browser.firstrun.show.localepicker"] = False
        prefs[
            "b2g.system_startup_url"] = "app://test-container.gaiamobile.org/index.html"
        prefs[
            "b2g.system_manifest_url"] = "app://test-container.gaiamobile.org/manifest.webapp"
        prefs["browser.tabs.remote"] = False
        prefs["dom.ipc.tabs.disabled"] = False
        prefs["dom.mozBrowserFramesEnabled"] = True
        prefs["font.size.inflation.emPerLine"] = 0
        prefs["font.size.inflation.minTwips"] = 0
        prefs[
            "network.dns.localDomains"] = "app://test-container.gaiamobile.org"
        prefs["reftest.browser.iframe.enabled"] = False
        prefs["reftest.remote"] = False
        prefs["reftest.uri"] = "%s" % reftestlist
        # Set a future policy version to avoid the telemetry prompt.
        prefs["toolkit.telemetry.prompted"] = 999
        prefs["toolkit.telemetry.notifiedOptOut"] = 999

        # Set the extra prefs.
        profile.set_preferences(prefs)
        return profile

    def build_command_line(self,
                           app,
                           ignore_window_size=False,
                           browser_arg=None):
        cmd = os.path.abspath(app)
        args = ['-marionette']

        if browser_arg:
            args += [browser_arg]

        if not ignore_window_size:
            args.extend(['--screen', '800x1000'])
        return cmd, args

    def _on_output(self, line):
        print(line)
        # TODO use structured logging
        if "TEST-START" in line and "|" in line:
            self.last_test = line.split("|")[1].strip()

    def _on_timeout(self):
        msg = "%s | application timed out after %s seconds with no output"
        log.testFail(msg % (self.last_test, self.timeout))

        # kill process to get a stack
        self.runner.stop(sig=signal.SIGABRT)
class current_frame():
    
    filename_screenshot = ""
    filename_htmldump   = ""
    
    def main(self, LOGDIR):
        #
        # The first variable is the log directory.
        #
        ucount  = 0
        self.marionette = Marionette(host='localhost', port=2828)  
        self.marionette.start_session()
        self.marionette.set_search_timeout(1000)
        
        #
        # Now loop through all the iframes, gathering details about each one.
        #
        print ""
        print "Iframe for 'top level' () ..."
        self.filename_screenshot = LOGDIR + "top_level" + ".png"
        self.filename_htmldump   = LOGDIR + "top_level" + ".html"
        self.marionette.switch_to_frame()
        self.record_frame()
        
        frames = self.marionette.find_elements("tag name", "iframe")
        for fnum in range (0, len(frames)):
          
            #
            # App name is usually in the "src" attribute, so it's worth a shot..
            #
            frame_src = frames[fnum].get_attribute("src")
              
            if frame_src != "":
                startpos = frame_src.index('/') + 2
                stoppos  = frame_src.index('.')
                appname  = frame_src[startpos:stoppos]
                filename = appname
            else:
                ucount = ucount + 1
                appname  = "(unknown)"
                filename = "unknown_" + str(ucount)
            
            #
            # Because we call this script sometimes when we hit a Marionette issue,
            # these filenames may already exist (and we'd overwrite them!), so
            # add 'DEBUG_' to the start of the filename.
            #
            filename = "DEBUG_" + filename
                 
            filename_details         = LOGDIR + filename + "_iframe_details.txt"
            self.filename_screenshot = LOGDIR + filename + ".png"
            self.filename_htmldump   = LOGDIR + filename + ".html"
            
            #
            # This iframe gives me problems sometimes, so I'm ignoring it for now.
            #
            if appname == "costcontrol":
                continue
            
            print ""
            print "Iframe for app \"" + appname + "\" ..."
        
            #
            # Record the iframe details (pretty verbose, but 'execute_script' 
            # wasn't letting me use 'for' loops in js for some reason).
            #
            print "    |_ iframe details saved to : " + filename_details
            f = open(filename_details, 'w')
            f.write("Attributes for this iframe ...\n")
            num_attribs = self.marionette.execute_script("return document.getElementsByTagName('iframe')[" + str(fnum) + "].attributes.length;")
            for i in range(0,num_attribs):
                attrib_name  = self.marionette.execute_script("return document.getElementsByTagName('iframe')[" + str(fnum) + "].attributes[" + str(i) + "].nodeName;")
                attrib_value = self.marionette.execute_script("return document.getElementsByTagName('iframe')[" + str(fnum) + "].attributes[" + str(i) + "].nodeValue;")
        
                f.write("    |_ " + attrib_name.ljust(20) + ": \"" + attrib_value + "\"\n")   
            f.close()
            
            #
            # Switch to this frame.
            #
            self.marionette.switch_to_frame(fnum)
                   
            self.record_frame()
         
            self.marionette.switch_to_frame()


    def record_frame(self):
        #
        # Take the screenshot and save it to the file.
        #
        print "    |_ screenshot saved to     : " + self.filename_screenshot
        screenshot = self.marionette.screenshot()[22:]
        with open(self.filename_screenshot, 'w') as f:
            f.write(base64.decodestring(screenshot))
        f.close()
              
        #
        # Take the html dump and save it to the file.
        #
        print "    |_ html dump saved to      : " + self.filename_htmldump
        f = open(self.filename_htmldump, 'w')
        f.write(self.marionette.page_source.encode('ascii', 'ignore') )
        f.close()
Exemplo n.º 37
0
class B2GMochitest(MochitestUtilsMixin):
    marionette = None

    def __init__(self, marionette_args,
                 logger_options,
                 out_of_process=True,
                 profile_data_dir=None,
                 locations=os.path.join(here, 'server-locations.txt')):
        super(B2GMochitest, self).__init__(logger_options)
        self.marionette_args = marionette_args
        self.out_of_process = out_of_process
        self.locations_file = locations
        self.preferences = []
        self.webapps = None
        self.test_script = os.path.join(here, 'b2g_start_script.js')
        self.test_script_args = [self.out_of_process]
        self.product = 'b2g'
        self.remote_chrome_test_dir = None

        if profile_data_dir:
            self.preferences = [
                os.path.join(
                    profile_data_dir,
                    f) for f in os.listdir(profile_data_dir) if f.startswith('pref')]
            self.webapps = [
                os.path.join(
                    profile_data_dir,
                    f) for f in os.listdir(profile_data_dir) if f.startswith('webapp')]

        # mozinfo is populated by the parent class
        if mozinfo.info['debug']:
            self.SERVER_STARTUP_TIMEOUT = 180
        else:
            self.SERVER_STARTUP_TIMEOUT = 90

    def setup_common_options(self, options):
        test_url = self.buildTestPath(options)
        # For B2G emulators buildURLOptions has been called
        # without calling buildTestPath first and that
        # causes manifestFile not to be set
        if not "manifestFile=tests.json" in self.urlOpts:
            self.urlOpts.append("manifestFile=%s" % options.manifestFile)

        if len(self.urlOpts) > 0:
            test_url += "?" + "&".join(self.urlOpts)
        self.test_script_args.append(test_url)

    def buildTestPath(self, options, testsToFilter=None):
        if options.manifestFile != 'tests.json':
            super(B2GMochitest, self).buildTestPath(options, testsToFilter, disabled=False)
        return self.buildTestURL(options)

    def build_profile(self, options):
        # preferences
        prefs = {}
        for path in self.preferences:
            prefs.update(Preferences.read_prefs(path))

        for v in options.extraPrefs:
            thispref = v.split("=", 1)
            if len(thispref) < 2:
                print "Error: syntax error in --setpref=" + v
                sys.exit(1)
            prefs[thispref[0]] = thispref[1]

        # interpolate the preferences
        interpolation = {
            "server": "%s:%s" %
            (options.webServer,
             options.httpPort),
            "OOP": "true" if self.out_of_process else "false"}
        prefs = json.loads(json.dumps(prefs) % interpolation)
        for pref in prefs:
            prefs[pref] = Preferences.cast(prefs[pref])

        kwargs = {
            'addons': self.getExtensionsToInstall(options),
            'apps': self.webapps,
            'locations': self.locations_file,
            'preferences': prefs,
            'proxy': {"remote": options.webServer}
        }

        if options.profile:
            self.profile = Profile.clone(options.profile, **kwargs)
        else:
            self.profile = Profile(**kwargs)

        options.profilePath = self.profile.profile
        # TODO bug 839108 - mozprofile should probably handle this
        manifest = self.addChromeToProfile(options)
        self.copyExtraFilesToProfile(options)
        return manifest

    def run_tests(self, options):
        """ Prepare, configure, run tests and cleanup """

        self.setTestRoot(options)

        manifest = self.build_profile(options)
        self.logPreamble(self.getActiveTests(options))

        # configuring the message logger's buffering
        self.message_logger.buffering = options.quiet

        if options.debugger or not options.autorun:
            timeout = None
        else:
            if not options.timeout:
                if mozinfo.info['debug']:
                    options.timeout = 420
                else:
                    options.timeout = 300
            timeout = options.timeout + 30.0

        self.log.info("runtestsb2g.py | Running tests: start.")
        status = 0
        try:
            def on_output(line):
                messages = self.message_logger.write(line)
                for message in messages:
                    if message['action'] == 'test_start':
                        self.runner.last_test = message['test']

            # The logging will be handled by on_output, so we set the stream to
            # None
            process_args = {'processOutputLine': on_output,
                            'stream': None}
            self.marionette_args['process_args'] = process_args
            self.marionette_args['profile'] = self.profile

            self.marionette = Marionette(**self.marionette_args)
            self.runner = self.marionette.runner
            self.app_ctx = self.runner.app_ctx

            self.remote_log = posixpath.join(self.app_ctx.remote_test_root,
                                             'log', 'mochitest.log')
            if not self.app_ctx.dm.dirExists(
                posixpath.dirname(
                    self.remote_log)):
                self.app_ctx.dm.mkDirs(self.remote_log)

            if options.chrome:
                # Update chrome manifest file in profile with correct path.
                self.writeChromeManifest(options)

            self.leak_report_file = posixpath.join(
                self.app_ctx.remote_test_root,
                'log',
                'runtests_leaks.log')

            # We don't want to copy the host env onto the device, so pass in an
            # empty env.
            self.browserEnv = self.buildBrowserEnv(options, env={})

            # B2G emulator debug tests still make external connections, so don't
            # pass MOZ_DISABLE_NONLOCAL_CONNECTIONS to them for now (bug
            # 1039019).
            if mozinfo.info[
                    'debug'] and 'MOZ_DISABLE_NONLOCAL_CONNECTIONS' in self.browserEnv:
                del self.browserEnv['MOZ_DISABLE_NONLOCAL_CONNECTIONS']
            self.runner.env.update(self.browserEnv)

            # Despite our efforts to clean up servers started by this script, in practice
            # we still see infrequent cases where a process is orphaned and interferes
            # with future tests, typically because the old server is keeping the port in use.
            # Try to avoid those failures by checking for and killing orphan servers before
            # trying to start new ones.
            self.killNamedOrphans('ssltunnel')
            self.killNamedOrphans('xpcshell')

            self.startServers(options, None)

            # In desktop mochitests buildTestPath is called before buildURLOptions. This
            # means options.manifestFile has already been converted to the proper json
            # style manifest. Not so with B2G, that conversion along with updating the URL
            # option will happen later. So backup and restore options.manifestFile to
            # prevent us from trying to pass in an instance of TestManifest via url param.
            manifestFile = options.manifestFile
            options.manifestFile = None
            self.buildURLOptions(options, {'MOZ_HIDE_RESULTS_TABLE': '1'})
            options.manifestFile = manifestFile

            self.test_script_args.append(not options.emulator)
            self.test_script_args.append(options.wifi)
            self.test_script_args.append(options.chrome)

            self.runner.start(outputTimeout=timeout)

            self.marionette.wait_for_port()
            self.marionette.start_session()
            self.marionette.set_context(self.marionette.CONTEXT_CHROME)

            # Disable offline status management (bug 777145), otherwise the network
            # will be 'offline' when the mochitests start.  Presumably, the network
            # won't be offline on a real device, so we only do this for
            # emulators.
            self.marionette.execute_script("""
                Components.utils.import("resource://gre/modules/Services.jsm");
                Services.io.manageOfflineStatus = false;
                Services.io.offline = false;
                """)

            self.marionette.execute_script("""
                let SECURITY_PREF = "security.turn_off_all_security_so_that_viruses_can_take_over_this_computer";
                Services.prefs.setBoolPref(SECURITY_PREF, true);

                if (!testUtils.hasOwnProperty("specialPowersObserver")) {
                  let loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
                    .getService(Components.interfaces.mozIJSSubScriptLoader);
                  loader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserver.js",
                    testUtils);
                  testUtils.specialPowersObserver = new testUtils.SpecialPowersObserver();
                  testUtils.specialPowersObserver.init();
                  testUtils.specialPowersObserver._loadFrameScript();
                }
                """)

            if options.chrome:
                self.app_ctx.dm.removeDir(self.remote_chrome_test_dir)
                self.app_ctx.dm.mkDir(self.remote_chrome_test_dir)
                local = super(B2GMochitest, self).getChromeTestDir(options)
                local = os.path.join(local, "chrome")
                remote = self.remote_chrome_test_dir
                self.log.info(
                    "pushing %s to %s on device..." %
                    (local, remote))
                self.app_ctx.dm.pushDir(local, remote)

            if os.path.isfile(self.test_script):
                with open(self.test_script, 'r') as script:
                    self.marionette.execute_script(
                        script.read(),
                        script_args=self.test_script_args)
            else:
                self.marionette.execute_script(
                    self.test_script,
                    script_args=self.test_script_args)
            status = self.runner.wait()

            if status is None:
                # the runner has timed out
                status = 124

            local_leak_file = tempfile.NamedTemporaryFile()
            self.app_ctx.dm.getFile(
                self.leak_report_file,
                local_leak_file.name)
            self.app_ctx.dm.removeFile(self.leak_report_file)

            mozleak.process_leak_log(
                local_leak_file.name,
                leak_thresholds=options.leakThresholds,
                ignore_missing_leaks=options.ignoreMissingLeaks,
                log=self.log,
                stack_fixer=get_stack_fixer_function(options.utilityPath,
                                                     options.symbolsPath),
            )
        except KeyboardInterrupt:
            self.log.info("runtests.py | Received keyboard interrupt.\n")
            status = -1
        except:
            traceback.print_exc()
            self.log.error(
                "Automation Error: Received unexpected exception while running application\n")
            if hasattr(self, 'runner'):
                self.runner.check_for_crashes()
            status = 1

        self.stopServers()

        self.log.info("runtestsb2g.py | Running tests: end.")

        if manifest is not None:
            self.cleanup(manifest, options)
        return status

    def getGMPPluginPath(self, options):
        if options.gmp_path:
            return options.gmp_path
        return '/system/b2g/gmp-clearkey/0.1'

    def getChromeTestDir(self, options):
        # The chrome test directory returned here is the remote location
        # of chrome test files. A reference to this directory is requested
        # when building the profile locally, before self.app_ctx is defined.
        # To get around this, return a dummy directory until self.app_ctx
        # is defined; the correct directory will be returned later, over-
        # writing the dummy.
        if hasattr(self, 'app_ctx'):
            self.remote_chrome_test_dir = posixpath.join(
                self.app_ctx.remote_test_root,
                'chrome')
            return self.remote_chrome_test_dir
        return 'dummy-chrome-test-dir'
Exemplo n.º 38
0
class B2GMixin(object):
    profileDir = None
    userJS = "/data/local/user.js"
    marionette = None

    def __init__(self,
                 host=None,
                 marionetteHost=None,
                 marionettePort=2828,
                 **kwargs):

        # (allowing marionneteHost to be specified seems a bit
        # counter-intuitive since we normally get it below from the ip
        # address, however we currently need it to be able to connect
        # via adb port forwarding and localhost)
        if marionetteHost:
            self.marionetteHost = marionetteHost
        elif host:
            self.marionetteHost = host
        self.marionettePort = marionettePort

    def cleanup(self):
        """
        If a user profile was setup on the device, restore it to the original.
        """
        if self.profileDir:
            self.restoreProfile()

    def waitForPort(self, timeout):
        """Waits for the marionette server to respond, until the timeout specified.

	:param timeout: Timeout parameter in seconds.
        """
        print "waiting for port"
        starttime = datetime.datetime.now()
        while datetime.datetime.now() - starttime < datetime.timedelta(
                seconds=timeout):
            try:
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                print "trying %s %s" % (self.marionettePort,
                                        self.marionetteHost)
                sock.connect((self.marionetteHost, self.marionettePort))
                data = sock.recv(16)
                sock.close()
                if '"from"' in data:
                    return True
            except socket.error:
                pass
            except Exception as e:
                raise DMError("Could not connect to marionette: %s" % e)
            time.sleep(1)
        raise DMError("Could not communicate with Marionette port")

    def setupMarionette(self, scriptTimeout=60000):
        """
        Starts a marionette session.
        If no host was given at init, the ip of the device will be retrieved
        and networking will be established.
        """
        if not self.marionetteHost:
            self.setupDHCP()
            self.marionetteHost = self.getIP()
        if not self.marionette:
            self.marionette = Marionette(self.marionetteHost,
                                         self.marionettePort)
        if not self.marionette.session:
            self.waitForPort(30)
            self.marionette.start_session()

        self.marionette.set_script_timeout(scriptTimeout)

    def restartB2G(self):
        """
        Restarts the b2g process on the device.
        """
        #restart b2g so we start with a clean slate
        if self.marionette and self.marionette.session:
            self.marionette.delete_session()
        self.shellCheckOutput(['stop', 'b2g'])
        # Wait for a bit to make sure B2G has completely shut down.
        tries = 10
        while "b2g" in self.shellCheckOutput(['ps', 'b2g']) and tries > 0:
            tries -= 1
            time.sleep(1)
        if tries == 0:
            raise DMError("Could not kill b2g process")
        self.shellCheckOutput(['start', 'b2g'])

    def setupProfile(self, prefs=None):
        """Sets up the user profile on the device.

        :param prefs: String of user_prefs to add to the profile. Defaults to a standard b2g testing profile.
        """
        # currently we have no custom prefs to set (when bug 800138 is fixed,
        # we will probably want to enable marionette on an external ip by
        # default)
        if not prefs:
            prefs = ""

        #remove previous user.js if there is one
        if not self.profileDir:
            self.profileDir = tempfile.mkdtemp()
        our_userJS = os.path.join(self.profileDir, "user.js")
        if os.path.exists(our_userJS):
            os.remove(our_userJS)
        #copy profile
        try:
            self.getFile(self.userJS, our_userJS)
        except subprocess.CalledProcessError:
            pass
        #if we successfully copied the profile, make a backup of the file
        if os.path.exists(our_userJS):
            self.shellCheckOutput(
                ['dd', 'if=%s' % self.userJS,
                 'of=%s.orig' % self.userJS])
        with open(our_userJS, 'a') as user_file:
            user_file.write("%s" % prefs)

        self.pushFile(our_userJS, self.userJS)
        self.restartB2G()
        self.setupMarionette()

    def setupDHCP(self, interfaces=['eth0', 'wlan0']):
        """Sets up networking.

        :param interfaces: Network connection types to try. Defaults to eth0 and wlan0.
        """
        all_interfaces = [line.split()[0] for line in \
                          self.shellCheckOutput(['netcfg']).splitlines()[1:]]
        interfaces_to_try = filter(lambda i: i in interfaces, all_interfaces)

        tries = 5
        print "Setting up DHCP..."
        while tries > 0:
            print "attempts left: %d" % tries
            try:
                for interface in interfaces_to_try:
                    self.shellCheckOutput(['netcfg', interface, 'dhcp'],
                                          timeout=10)
                    if self.getIP(interfaces=[interface]):
                        return
            except DMError:
                pass
            time.sleep(1)
            tries -= 1
        raise DMError("Could not set up network connection")

    def restoreProfile(self):
        """
        Restores the original user profile on the device.
        """
        if not self.profileDir:
            raise DMError("There is no profile to restore")
        #if we successfully copied the profile, make a backup of the file
        our_userJS = os.path.join(self.profileDir, "user.js")
        if os.path.exists(our_userJS):
            self.shellCheckOutput(
                ['dd', 'if=%s.orig' % self.userJS,
                 'of=%s' % self.userJS])
        shutil.rmtree(self.profileDir)
        self.profileDir = None

    def getAppInfo(self):
        """
        Returns the appinfo, with an additional "date" key.

        :rtype: dictionary
        """
        if not self.marionette or not self.marionette.session:
            self.setupMarionette()
        self.marionette.set_context("chrome")
        appinfo = self.marionette.execute_script("""
                                var appInfo = Components.classes["@mozilla.org/xre/app-info;1"]
                                .getService(Components.interfaces.nsIXULAppInfo);
                                return appInfo;
                                """)
        (year, month,
         day) = (appinfo["appBuildID"][0:4], appinfo["appBuildID"][4:6],
                 appinfo["appBuildID"][6:8])
        appinfo['date'] = "%s-%s-%s" % (year, month, day)
        return appinfo
Exemplo n.º 39
0
class B2GMochitest(MochitestUtilsMixin):
    marionette = None

    def __init__(self,
                 marionette_args,
                 logger_options,
                 out_of_process=True,
                 profile_data_dir=None,
                 locations=os.path.join(here, 'server-locations.txt')):
        super(B2GMochitest, self).__init__(logger_options)
        self.marionette_args = marionette_args
        self.out_of_process = out_of_process
        self.locations_file = locations
        self.preferences = []
        self.webapps = None
        self.test_script = os.path.join(here, 'b2g_start_script.js')
        self.test_script_args = [self.out_of_process]
        self.product = 'b2g'
        self.remote_chrome_test_dir = None

        if profile_data_dir:
            self.preferences = [
                os.path.join(profile_data_dir, f)
                for f in os.listdir(profile_data_dir) if f.startswith('pref')
            ]
            self.webapps = [
                os.path.join(profile_data_dir, f)
                for f in os.listdir(profile_data_dir) if f.startswith('webapp')
            ]

        # mozinfo is populated by the parent class
        if mozinfo.info['debug']:
            self.SERVER_STARTUP_TIMEOUT = 180
        else:
            self.SERVER_STARTUP_TIMEOUT = 90

    def setup_common_options(self, options):
        test_url = self.buildTestPath(options)
        # For B2G emulators buildURLOptions has been called
        # without calling buildTestPath first and that
        # causes manifestFile not to be set
        if not "manifestFile=tests.json" in self.urlOpts:
            self.urlOpts.append("manifestFile=%s" % options.manifestFile)

        if len(self.urlOpts) > 0:
            test_url += "?" + "&".join(self.urlOpts)
        self.test_script_args.append(test_url)

    def buildTestPath(self, options, testsToFilter=None):
        if options.manifestFile != 'tests.json':
            super(B2GMochitest, self).buildTestPath(options,
                                                    testsToFilter,
                                                    disabled=False)
        return self.buildTestURL(options)

    def build_profile(self, options):
        # preferences
        prefs = {}
        for path in self.preferences:
            prefs.update(Preferences.read_prefs(path))

        for v in options.extraPrefs:
            thispref = v.split("=", 1)
            if len(thispref) < 2:
                print "Error: syntax error in --setpref=" + v
                sys.exit(1)
            prefs[thispref[0]] = thispref[1]

        # interpolate the preferences
        interpolation = {
            "server": "%s:%s" % (options.webServer, options.httpPort),
            "OOP": "true" if self.out_of_process else "false"
        }
        prefs = json.loads(json.dumps(prefs) % interpolation)
        for pref in prefs:
            prefs[pref] = Preferences.cast(prefs[pref])

        kwargs = {
            'addons': self.getExtensionsToInstall(options),
            'apps': self.webapps,
            'locations': self.locations_file,
            'preferences': prefs,
            'proxy': {
                "remote": options.webServer
            }
        }

        if options.profile:
            self.profile = Profile.clone(options.profile, **kwargs)
        else:
            self.profile = Profile(**kwargs)

        options.profilePath = self.profile.profile
        # TODO bug 839108 - mozprofile should probably handle this
        manifest = self.addChromeToProfile(options)
        self.copyExtraFilesToProfile(options)
        return manifest

    def run_tests(self, options):
        """ Prepare, configure, run tests and cleanup """

        manifest = self.build_profile(options)
        self.logPreamble(self.getActiveTests(options))

        # configuring the message logger's buffering
        self.message_logger.buffering = options.quiet

        if options.debugger or not options.autorun:
            timeout = None
        else:
            if not options.timeout:
                if mozinfo.info['debug']:
                    options.timeout = 420
                else:
                    options.timeout = 300
            timeout = options.timeout + 30.0

        self.log.info("runtestsb2g.py | Running tests: start.")
        status = 0
        try:

            def on_output(line):
                messages = self.message_logger.write(line)
                for message in messages:
                    if message['action'] == 'test_start':
                        self.runner.last_test = message['test']

            # The logging will be handled by on_output, so we set the stream to None
            process_args = {'processOutputLine': on_output, 'stream': None}
            self.marionette_args['process_args'] = process_args
            self.marionette_args['profile'] = self.profile

            self.marionette = Marionette(**self.marionette_args)
            self.runner = self.marionette.runner
            self.app_ctx = self.runner.app_ctx

            self.remote_log = posixpath.join(self.app_ctx.remote_test_root,
                                             'log', 'mochitest.log')
            if not self.app_ctx.dm.dirExists(posixpath.dirname(
                    self.remote_log)):
                self.app_ctx.dm.mkDirs(self.remote_log)

            if options.chrome:
                # Update chrome manifest file in profile with correct path.
                self.writeChromeManifest(options)

            self.leak_report_file = posixpath.join(
                self.app_ctx.remote_test_root, 'log', 'runtests_leaks.log')

            # We don't want to copy the host env onto the device, so pass in an
            # empty env.
            self.browserEnv = self.buildBrowserEnv(options, env={})

            # B2G emulator debug tests still make external connections, so don't
            # pass MOZ_DISABLE_NONLOCAL_CONNECTIONS to them for now (bug 1039019).
            if mozinfo.info[
                    'debug'] and 'MOZ_DISABLE_NONLOCAL_CONNECTIONS' in self.browserEnv:
                del self.browserEnv['MOZ_DISABLE_NONLOCAL_CONNECTIONS']
            self.runner.env.update(self.browserEnv)

            self.startServers(options, None)
            self.buildURLOptions(options, {'MOZ_HIDE_RESULTS_TABLE': '1'})
            self.test_script_args.append(not options.emulator)
            self.test_script_args.append(options.wifi)
            self.test_script_args.append(options.chrome)

            self.runner.start(outputTimeout=timeout)

            self.marionette.wait_for_port()
            self.marionette.start_session()
            self.marionette.set_context(self.marionette.CONTEXT_CHROME)

            # Disable offline status management (bug 777145), otherwise the network
            # will be 'offline' when the mochitests start.  Presumably, the network
            # won't be offline on a real device, so we only do this for emulators.
            self.marionette.execute_script("""
                Components.utils.import("resource://gre/modules/Services.jsm");
                Services.io.manageOfflineStatus = false;
                Services.io.offline = false;
                """)

            if options.chrome:
                self.app_ctx.dm.removeDir(self.remote_chrome_test_dir)
                self.app_ctx.dm.mkDir(self.remote_chrome_test_dir)
                local = super(B2GMochitest, self).getChromeTestDir(options)
                local = os.path.join(local, "chrome")
                remote = self.remote_chrome_test_dir
                self.log.info("pushing %s to %s on device..." %
                              (local, remote))
                self.app_ctx.dm.pushDir(local, remote)

            if os.path.isfile(self.test_script):
                with open(self.test_script, 'r') as script:
                    self.marionette.execute_script(
                        script.read(), script_args=self.test_script_args)
            else:
                self.marionette.execute_script(
                    self.test_script, script_args=self.test_script_args)
            status = self.runner.wait()

            if status is None:
                # the runner has timed out
                status = 124

            local_leak_file = tempfile.NamedTemporaryFile()
            self.app_ctx.dm.getFile(self.leak_report_file,
                                    local_leak_file.name)
            self.app_ctx.dm.removeFile(self.leak_report_file)

            processLeakLog(local_leak_file.name, options)
        except KeyboardInterrupt:
            self.log.info("runtests.py | Received keyboard interrupt.\n")
            status = -1
        except:
            traceback.print_exc()
            self.log.error(
                "Automation Error: Received unexpected exception while running application\n"
            )
            if hasattr(self, 'runner'):
                self.runner.check_for_crashes()
            status = 1

        self.stopServers()

        self.log.info("runtestsb2g.py | Running tests: end.")

        if manifest is not None:
            self.cleanup(manifest, options)
        return status

    def getGMPPluginPath(self, options):
        # TODO: bug 1043403
        return None

    def getChromeTestDir(self, options):
        # The chrome test directory returned here is the remote location
        # of chrome test files. A reference to this directory is requested
        # when building the profile locally, before self.app_ctx is defined.
        # To get around this, return a dummy directory until self.app_ctx
        # is defined; the correct directory will be returned later, over-
        # writing the dummy.
        if hasattr(self, 'app_ctx'):
            self.remote_chrome_test_dir = posixpath.join(
                self.app_ctx.remote_test_root, 'chrome')
            return self.remote_chrome_test_dir
        return 'dummy-chrome-test-dir'
Exemplo n.º 40
0
class B2GRunner(object):
    remote_profile_dir = None

    def __init__(self, dm, url, tmpdir, marionette_host=None, marionette_port=None):
        self.dm = dm
        self.url = url
        self.tmpdir = tmpdir
        self.userJS = "/data/local/user.js"
        self.marionette_host = marionette_host or 'localhost'
        self.marionette_port = marionette_port or 2828
        self.marionette = None

    def wait_for_port(self, timeout):
        starttime = datetime.datetime.now()
        while datetime.datetime.now() - starttime < datetime.timedelta(seconds=timeout):
            try:
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                sock.connect(('localhost', self.marionette_port))
                data = sock.recv(16)
                sock.close()
                if '"from"' in data:
                    return True
            except:
                import traceback
                print traceback.format_exc()
            time.sleep(1)
        return False

    def restart_b2g(self):
        #restart b2g so we start with a clean slate
        self.dm.checkCmd(['shell', 'stop', 'b2g'])
        # Wait for a bit to make sure B2G has completely shut down.
        time.sleep(10)
        self.dm.checkCmd(['shell', 'start', 'b2g'])
        
        #wait for marionette port to come up
        if not self.wait_for_port(30000):
            raise Exception("Could not communicate with Marionette port after restarting B2G")
        self.marionette = Marionette(self.marionette_host, self.marionette_port)
    
    def setup_profile(self):
        #remove previous user.js if there is one
        our_user_js = os.path.join(self.tmpdir, "user.js")
        if os.path.exists(our_user_js):
            os.remove(our_user_js)
        #copy profile
        try:
            self.dm.checkCmd(["pull", self.userJS, our_user_js])
        except subprocess.CalledProcessError:
            pass
        #if we successfully copied the profile, make a backup of the file
        if os.path.exists(our_user_js): 
            self.dm.checkCmd(['shell', 'dd', 'if=%s' % self.userJS, 'of=%s.orig' % self.userJS])
        user_js = open(our_user_js, 'a')
        user_js.write("""
user_pref("power.screen.timeout", 999999);
        """)
        user_js.close()
        self.dm.checkCmd(['push', our_user_js, self.userJS])
        self.restart_b2g()

    def start(self):
        #forward the marionette port
        self.dm.checkCmd(['forward',
                          'tcp:%s' % self.marionette_port,
                          'tcp:%s' % self.marionette_port])

        print "Setting up profile"
        self.setup_profile()
        #enable ethernet connection
        print "Running netcfg, it may take some time."
        self.dm.checkCmd(['shell', 'netcfg', 'eth0', 'dhcp'])
        #launch app
        session = self.marionette.start_session()
        if 'b2g' not in session:
            raise Exception("bad session value %s returned by start_session" % session)

        # start the tests by navigating to the mochitest url
        self.marionette.execute_script("window.location.href='%s';" % self.url)

    def stop(self):
        self.marionette.delete_session()
Exemplo n.º 41
0
class B2GMochitest(MochitestUtilsMixin):
    marionette = None

    def __init__(self,
                 marionette_args,
                 logger_options,
                 out_of_process=True,
                 profile_data_dir=None,
                 locations=os.path.join(here, 'server-locations.txt')):
        super(B2GMochitest, self).__init__(logger_options)
        self.marionette_args = marionette_args
        self.out_of_process = out_of_process
        self.locations_file = locations
        self.preferences = []
        self.webapps = None
        self.test_script = os.path.join(here, 'b2g_start_script.js')
        self.test_script_args = [self.out_of_process]
        self.product = 'b2g'
        self.remote_chrome_test_dir = None

        if profile_data_dir:
            self.preferences = [
                os.path.join(profile_data_dir, f)
                for f in os.listdir(profile_data_dir) if f.startswith('pref')
            ]
            self.webapps = [
                os.path.join(profile_data_dir, f)
                for f in os.listdir(profile_data_dir) if f.startswith('webapp')
            ]

        # mozinfo is populated by the parent class
        if mozinfo.info['debug']:
            self.SERVER_STARTUP_TIMEOUT = 180
        else:
            self.SERVER_STARTUP_TIMEOUT = 90

    def setup_common_options(self, options):
        test_url = self.buildTestPath(options)
        # For B2G emulators buildURLOptions has been called
        # without calling buildTestPath first and that
        # causes manifestFile not to be set
        if not "manifestFile=tests.json" in self.urlOpts:
            self.urlOpts.append("manifestFile=%s" % options.manifestFile)

        if len(self.urlOpts) > 0:
            test_url += "?" + "&".join(self.urlOpts)
        self.test_script_args.append(test_url)

    def buildTestPath(self, options, testsToFilter=None):
        if options.manifestFile != 'tests.json':
            super(B2GMochitest, self).buildTestPath(options,
                                                    testsToFilter,
                                                    disabled=False)
        return self.buildTestURL(options)

    def build_profile(self, options):
        # preferences
        prefs = {}
        for path in self.preferences:
            prefs.update(Preferences.read_prefs(path))

        for v in options.extraPrefs:
            thispref = v.split("=", 1)
            if len(thispref) < 2:
                print "Error: syntax error in --setpref=" + v
                sys.exit(1)
            prefs[thispref[0]] = thispref[1]

        # interpolate the preferences
        interpolation = {
            "server": "%s:%s" % (options.webServer, options.httpPort),
            "OOP": "true" if self.out_of_process else "false"
        }
        prefs = json.loads(json.dumps(prefs) % interpolation)
        for pref in prefs:
            prefs[pref] = Preferences.cast(prefs[pref])

        kwargs = {
            'addons': self.getExtensionsToInstall(options),
            'apps': self.webapps,
            'locations': self.locations_file,
            'preferences': prefs,
            'proxy': {
                "remote": options.webServer
            }
        }

        if options.profile:
            self.profile = Profile.clone(options.profile, **kwargs)
        else:
            self.profile = Profile(**kwargs)

        options.profilePath = self.profile.profile
        # TODO bug 839108 - mozprofile should probably handle this
        manifest = self.addChromeToProfile(options)
        self.copyExtraFilesToProfile(options)
        return manifest

    def run_tests(self, options):
        """ Prepare, configure, run tests and cleanup """

        self.setTestRoot(options)

        manifest = self.build_profile(options)
        self.logPreamble(self.getActiveTests(options))

        # configuring the message logger's buffering
        self.message_logger.buffering = options.quiet

        if options.debugger or not options.autorun:
            timeout = None
        else:
            if not options.timeout:
                if mozinfo.info['debug']:
                    options.timeout = 420
                else:
                    options.timeout = 300
            timeout = options.timeout + 30.0

        self.log.info("runtestsb2g.py | Running tests: start.")
        status = 0
        try:

            def on_output(line):
                messages = self.message_logger.write(line)
                for message in messages:
                    if message['action'] == 'test_start':
                        self.runner.last_test = message['test']

            # The logging will be handled by on_output, so we set the stream to
            # None
            process_args = {'processOutputLine': on_output, 'stream': None}
            self.marionette_args['process_args'] = process_args
            self.marionette_args['profile'] = self.profile

            self.marionette = Marionette(**self.marionette_args)
            self.runner = self.marionette.runner
            self.app_ctx = self.runner.app_ctx

            self.remote_log = posixpath.join(self.app_ctx.remote_test_root,
                                             'log', 'mochitest.log')
            if not self.app_ctx.dm.dirExists(posixpath.dirname(
                    self.remote_log)):
                self.app_ctx.dm.mkDirs(self.remote_log)

            if options.chrome:
                # Update chrome manifest file in profile with correct path.
                self.writeChromeManifest(options)

            self.leak_report_file = posixpath.join(
                self.app_ctx.remote_test_root, 'log', 'runtests_leaks.log')

            # We don't want to copy the host env onto the device, so pass in an
            # empty env.
            self.browserEnv = self.buildBrowserEnv(options, env={})

            # B2G emulator debug tests still make external connections, so don't
            # pass MOZ_DISABLE_NONLOCAL_CONNECTIONS to them for now (bug
            # 1039019).
            if mozinfo.info[
                    'debug'] and 'MOZ_DISABLE_NONLOCAL_CONNECTIONS' in self.browserEnv:
                del self.browserEnv['MOZ_DISABLE_NONLOCAL_CONNECTIONS']
            self.runner.env.update(self.browserEnv)

            # Despite our efforts to clean up servers started by this script, in practice
            # we still see infrequent cases where a process is orphaned and interferes
            # with future tests, typically because the old server is keeping the port in use.
            # Try to avoid those failures by checking for and killing orphan servers before
            # trying to start new ones.
            self.killNamedOrphans('ssltunnel')
            self.killNamedOrphans('xpcshell')

            self.startServers(options, None)

            # In desktop mochitests buildTestPath is called before buildURLOptions. This
            # means options.manifestFile has already been converted to the proper json
            # style manifest. Not so with B2G, that conversion along with updating the URL
            # option will happen later. So backup and restore options.manifestFile to
            # prevent us from trying to pass in an instance of TestManifest via url param.
            manifestFile = options.manifestFile
            options.manifestFile = None
            self.buildURLOptions(options, {'MOZ_HIDE_RESULTS_TABLE': '1'})
            options.manifestFile = manifestFile

            self.test_script_args.append(not options.emulator)
            self.test_script_args.append(options.wifi)
            self.test_script_args.append(options.chrome)

            self.runner.start(outputTimeout=timeout)

            self.marionette.wait_for_port()
            self.marionette.start_session()
            self.marionette.set_context(self.marionette.CONTEXT_CHROME)

            # Disable offline status management (bug 777145), otherwise the network
            # will be 'offline' when the mochitests start.  Presumably, the network
            # won't be offline on a real device, so we only do this for
            # emulators.
            self.marionette.execute_script("""
                Components.utils.import("resource://gre/modules/Services.jsm");
                Services.io.manageOfflineStatus = false;
                Services.io.offline = false;
                """)

            self.marionette.execute_script("""
                let SECURITY_PREF = "security.turn_off_all_security_so_that_viruses_can_take_over_this_computer";
                Services.prefs.setBoolPref(SECURITY_PREF, true);

                if (!testUtils.hasOwnProperty("specialPowersObserver")) {
                  let loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
                    .getService(Components.interfaces.mozIJSSubScriptLoader);
                  loader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserver.js",
                    testUtils);
                  testUtils.specialPowersObserver = new testUtils.SpecialPowersObserver();
                  testUtils.specialPowersObserver.init();
                  testUtils.specialPowersObserver._loadFrameScript();
                }
                """)

            if options.chrome:
                self.app_ctx.dm.removeDir(self.remote_chrome_test_dir)
                self.app_ctx.dm.mkDir(self.remote_chrome_test_dir)
                local = super(B2GMochitest, self).getChromeTestDir(options)
                local = os.path.join(local, "chrome")
                remote = self.remote_chrome_test_dir
                self.log.info("pushing %s to %s on device..." %
                              (local, remote))
                self.app_ctx.dm.pushDir(local, remote)

            if os.path.isfile(self.test_script):
                with open(self.test_script, 'r') as script:
                    self.marionette.execute_script(
                        script.read(), script_args=self.test_script_args)
            else:
                self.marionette.execute_script(
                    self.test_script, script_args=self.test_script_args)
            status = self.runner.wait()

            if status is None:
                # the runner has timed out
                status = 124

            local_leak_file = tempfile.NamedTemporaryFile()
            self.app_ctx.dm.getFile(self.leak_report_file,
                                    local_leak_file.name)
            self.app_ctx.dm.removeFile(self.leak_report_file)

            mozleak.process_leak_log(
                local_leak_file.name,
                leak_thresholds=options.leakThresholds,
                ignore_missing_leaks=options.ignoreMissingLeaks,
                log=self.log,
            )
        except KeyboardInterrupt:
            self.log.info("runtests.py | Received keyboard interrupt.\n")
            status = -1
        except:
            traceback.print_exc()
            self.log.error(
                "Automation Error: Received unexpected exception while running application\n"
            )
            if hasattr(self, 'runner'):
                self.runner.check_for_crashes()
            status = 1

        self.stopServers()

        self.log.info("runtestsb2g.py | Running tests: end.")

        if manifest is not None:
            self.cleanup(manifest, options)
        return status

    def getGMPPluginPath(self, options):
        if options.gmp_path:
            return options.gmp_path
        return '/system/b2g/gmp-clearkey/0.1'

    def getChromeTestDir(self, options):
        # The chrome test directory returned here is the remote location
        # of chrome test files. A reference to this directory is requested
        # when building the profile locally, before self.app_ctx is defined.
        # To get around this, return a dummy directory until self.app_ctx
        # is defined; the correct directory will be returned later, over-
        # writing the dummy.
        if hasattr(self, 'app_ctx'):
            self.remote_chrome_test_dir = posixpath.join(
                self.app_ctx.remote_test_root, 'chrome')
            return self.remote_chrome_test_dir
        return 'dummy-chrome-test-dir'
Exemplo n.º 42
0
def kill(origin):
    marionette = Marionette(host='localhost', port=2828)
    marionette.start_session()
    marionette.set_context(marionette.CONTEXT_CONTENT)
    marionette.execute_script(
        "window.wrappedJSObject.WindowManager.kill('%s')" % origin)