def test_stbt_control_relay(stbt_control_relay_on_path):  # pylint: disable=unused-argument
    with named_temporary_directory("stbt-control-relay-test.XXXXXX") as tmpdir:
        def t(filename):
            return os.path.join(tmpdir, filename)
        proc = subprocess.Popen(
            ["stbt-control-relay",
             "--socket", t("lircd.sock"),
             "file:" + t("one-file")])
        with scoped_process(proc):
            wait_until(lambda: (
                os.path.exists(t("lircd.sock")) or proc.poll() is not None))
            testcontrol = uri_to_control("lirc:%s:stbt-test" % t("lircd.sock"))

            testcontrol.press("KEY_LEFT")
            testcontrol.press("KEY_RIGHT")
            testcontrol.keydown("KEY_MENU")
            testcontrol.keyup("KEY_MENU")
            expected = dedent("""\
                KEY_LEFT
                KEY_RIGHT
                Holding KEY_MENU
                Released KEY_MENU
                """)

            assert expected == open(t("one-file")).read()
Exemple #2
0
def test_stbt_control_relay(stbt_control_relay_on_path):  # pylint: disable=unused-argument
    with named_temporary_directory("stbt-control-relay-test.XXXXXX") as tmpdir:

        def t(filename):
            return os.path.join(tmpdir, filename)

        proc = subprocess.Popen([
            "stbt-control-relay", "--socket",
            t("lircd.sock"), "file:" + t("one-file")
        ])
        with scoped_process(proc):
            wait_until(lambda: (os.path.exists(t("lircd.sock")) or proc.poll()
                                is not None))
            testcontrol = uri_to_control("lirc:%s:stbt-test" % t("lircd.sock"))

            testcontrol.press("KEY_LEFT")
            testcontrol.press("KEY_RIGHT")
            testcontrol.keydown("KEY_MENU")
            testcontrol.keyup("KEY_MENU")
            expected = dedent("""\
                KEY_LEFT
                KEY_RIGHT
                Holding KEY_MENU
                Released KEY_MENU
                """)

            assert expected == open(t("one-file")).read()
def main(argv):
    parser = argparse.ArgumentParser(
        epilog=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument("--socket",
                        default="/var/run/lirc/lircd",
                        help="""LIRC socket to read
        remote control presses from (defaults to %(default)s).""")
    parser.add_argument("output",
                        help="""Remote control configuration to
        transmit on. Values are the same as stbt run's --control.""")
    _stbt.logging.argparser_add_verbose_argument(parser)
    args = parser.parse_args(argv[1:])

    signal.signal(signal.SIGTERM, lambda _signo, _stack_frame: sys.exit(0))

    if os.environ.get('LISTEN_FDS') == '1' and \
            os.environ.get('LISTEN_PID') == str(os.getpid()):
        s = socket.fromfd(3, socket.AF_UNIX, socket.SOCK_STREAM)
    else:
        s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        s.bind(args.socket)
        s.listen(5)

    control = uri_to_control(args.output)

    while True:
        conn, _ = s.accept()
        f = conn.makefile('r', 0)
        while True:
            cmd = f.readline()
            if not cmd:
                break
            cmd = cmd.rstrip("\n")
            m = re.match(
                r"(?P<action>SEND_ONCE|SEND_START|SEND_STOP) "
                r"(?P<ctrl>\S+) (?P<key>\S+)", cmd)
            if not m:
                debug("Invalid command: %s" % cmd)
                send_response(conn,
                              cmd,
                              success=False,
                              data="Invalid command: %s" % cmd)
                continue
            action = m.groupdict()["action"]
            key = m.groupdict()["key"]
            debug("Received %s %s" % (action, key))
            try:
                if action == "SEND_ONCE":
                    control.press(key)
                elif action == "SEND_START":
                    control.keydown(key)
                elif action == "SEND_STOP":
                    control.keyup(key)
            except Exception as e:  # pylint: disable=broad-except
                debug("Error pressing key %r: %r" % (key, e))
                send_response(conn, cmd, success=False, data=str(e))
                continue
            send_response(conn, cmd, success=True)
def main(argv):
    parser = argparse.ArgumentParser(
        epilog=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument(
        "--socket", default="/var/run/lirc/lircd", help="""LIRC socket to read
        remote control presses from (defaults to %(default)s).""")
    parser.add_argument("output", help="""Remote control configuration to
        transmit on. Values are the same as stbt run's --control.""")
    _stbt.logging.argparser_add_verbose_argument(parser)
    args = parser.parse_args(argv[1:])

    signal.signal(signal.SIGTERM, lambda _signo, _stack_frame: sys.exit(0))

    if os.environ.get('LISTEN_FDS') == '1' and \
            os.environ.get('LISTEN_PID') == str(os.getpid()):
        s = socket.fromfd(3, socket.AF_UNIX, socket.SOCK_STREAM)
    else:
        s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        s.bind(args.socket)
        s.listen(5)

    control = uri_to_control(args.output)

    while True:
        conn, _ = s.accept()
        f = conn.makefile('r', 0)
        while True:
            cmd = f.readline()
            if not cmd:
                break
            cmd = cmd.rstrip("\n")
            m = re.match(r"(?P<action>SEND_ONCE|SEND_START|SEND_STOP) "
                         r"(?P<ctrl>\S+) (?P<key>\S+)", cmd)
            if not m:
                debug("Invalid command: %s" % cmd)
                send_response(conn, cmd, success=False,
                              data="Invalid command: %s" % cmd)
                continue
            action = m.groupdict()["action"]
            key = m.groupdict()["key"]
            debug("Received %s %s" % (action, key))
            try:
                if action == "SEND_ONCE":
                    control.press(key)
                elif action == "SEND_START":
                    control.keydown(key)
                elif action == "SEND_STOP":
                    control.keyup(key)
            except Exception as e:  # pylint: disable=broad-except
                debug("Error pressing key %r: %r" % (key, e))
                send_response(conn, cmd, success=False, data=str(e))
                continue
            send_response(conn, cmd, success=True)
def test_stbt_control_relay_with_socket_passing(stbt_control_relay_on_path):  # pylint: disable=unused-argument
    with NamedTemporaryFile(prefix="stbt-control-relay-test-") as tmpfile:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.bind(('127.0.0.1', 0))
        s.listen(5)

        proc = subprocess.Popen(
            ["stbt-control-relay", "-vv", "file:" + tmpfile.name],
            preexec_fn=socket_passing_setup(s))
        with scoped_process(proc):
            testcontrol = uri_to_control("lirc:%s:%i:stbt" % s.getsockname())

            testcontrol.press("KEY_UP")
            testcontrol.press("KEY_DOWN")
            expected = "KEY_UP\nKEY_DOWN\n"

            assert tmpfile.read() == expected
Exemple #6
0
def new_device_under_test_from_config(parsed_args=None):
    """
    `parsed_args` if present should come from calling argparser().parse_args().
    """
    from _stbt.control import uri_to_control

    if parsed_args is None:
        args = argparser().parse_args([])
    else:
        args = parsed_args

    if args.source_pipeline is None:
        args.source_pipeline = get_config('global', 'source_pipeline')
    if args.sink_pipeline is None:
        args.sink_pipeline = get_config('global', 'sink_pipeline')
    if args.control is None:
        args.control = get_config('global', 'control')
    if args.save_video is None:
        args.save_video = False
    if args.restart_source is None:
        args.restart_source = get_config('global',
                                         'restart_source',
                                         type_=bool)
    source_teardown_eos = get_config('global',
                                     'source_teardown_eos',
                                     type_=bool)

    display = [None]

    def raise_in_user_thread(exception):
        display[0].tell_user_thread(exception)

    mainloop = _mainloop()

    if not args.sink_pipeline and not args.save_video:
        sink_pipeline = NoSinkPipeline()
    else:
        sink_pipeline = SinkPipeline(  # pylint: disable=redefined-variable-type
            args.sink_pipeline, raise_in_user_thread, args.save_video)

    display[0] = Display(args.source_pipeline, sink_pipeline,
                         args.restart_source, source_teardown_eos)
    return DeviceUnderTest(display=display[0],
                           control=uri_to_control(args.control, display[0]),
                           sink_pipeline=sink_pipeline,
                           mainloop=mainloop)
def test_stbt_control_relay_with_socket_passing(stbt_control_relay_on_path):  # pylint: disable=unused-argument
    with NamedTemporaryFile(prefix="stbt-control-relay-test-") as tmpfile:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.bind(('127.0.0.1', 0))
        s.listen(5)

        proc = subprocess.Popen(
            ["stbt-control-relay", "-vv", "file:" + tmpfile.name],
            preexec_fn=socket_passing_setup(s))
        with scoped_process(proc):
            testcontrol = uri_to_control("lirc:%s:%i:stbt" % s.getsockname())

            testcontrol.press("KEY_UP")
            testcontrol.press("KEY_DOWN")
            expected = "KEY_UP\nKEY_DOWN\n"

            assert tmpfile.read() == expected
Exemple #8
0
def new_device_under_test_from_config(parsed_args=None):
    """
    `parsed_args` if present should come from calling argparser().parse_args().
    """
    from _stbt.control import uri_to_control

    if parsed_args is None:
        args = argparser().parse_args([])
    else:
        args = parsed_args

    if args.source_pipeline is None:
        args.source_pipeline = get_config('global', 'source_pipeline')
    if args.sink_pipeline is None:
        args.sink_pipeline = get_config('global', 'sink_pipeline')
    if args.control is None:
        args.control = get_config('global', 'control')
    if args.save_video is None:
        args.save_video = False
    if args.restart_source is None:
        args.restart_source = get_config('global', 'restart_source', type_=bool)
    source_teardown_eos = get_config('global', 'source_teardown_eos',
                                     type_=bool)

    display = [None]

    def raise_in_user_thread(exception):
        display[0].tell_user_thread(exception)
    mainloop = _mainloop()

    if not args.sink_pipeline and not args.save_video:
        sink_pipeline = NoSinkPipeline()
    else:
        sink_pipeline = SinkPipeline(  # pylint: disable=redefined-variable-type
            args.sink_pipeline, raise_in_user_thread, args.save_video)

    display[0] = Display(
        args.source_pipeline, sink_pipeline, args.restart_source,
        source_teardown_eos)
    return DeviceUnderTest(
        display=display[0], control=uri_to_control(args.control, display[0]),
        sink_pipeline=sink_pipeline, mainloop=mainloop)
Exemple #9
0
def main(argv):
    parser = argparse.ArgumentParser(
        epilog=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument("--socket",
                        default="/var/run/lirc/lircd",
                        help="""LIRC socket to read
        remote control presses from (defaults to %(default)s).""")
    parser.add_argument("--timeout",
                        default=0,
                        type=float,
                        help="""
        Timeout, in seconds, before exiting if no commands are received. If not
        specified, never times out.""")
    parser.add_argument("-v", "--verbose", action="store_true")
    parser.add_argument("output",
                        help="""Remote control configuration to
        transmit on. Values are the same as stbt run's --control.""")
    args = parser.parse_args(argv[1:])

    logging.basicConfig(format="%(levelname)s: %(message)s",
                        level=logging.DEBUG if args.verbose else logging.INFO)

    if args.verbose:
        _stbt.logging._debug_level = 1  # pylint:disable=protected-access

    signal.signal(signal.SIGTERM, lambda _signo, _stack_frame: sys.exit(0))

    if os.environ.get('LISTEN_FDS') == '1' and \
            os.environ.get('LISTEN_PID') == str(os.getpid()):
        s = socket.fromfd(3, socket.AF_UNIX, socket.SOCK_STREAM)
    else:
        s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        s.bind(args.socket)
        s.listen(5)

    if args.timeout:
        s.settimeout(args.timeout)

    control = uri_to_control(args.output)

    logging.info("stbt-control-relay started up with output '%s'", args.output)

    while True:
        try:
            conn, _ = s.accept()
        except socket.timeout:
            return 0
        f = conn.makefile('rb', 0)
        while True:
            cmd = f.readline()
            if not cmd:
                break
            cmd = cmd.rstrip(b"\n")
            m = re.match(
                br"(?P<action>SEND_ONCE|SEND_START|SEND_STOP) "
                br"(?P<ctrl>\S+) (?P<key>\S+)", cmd)
            if not m:
                logging.error("Invalid command: %s", cmd)
                send_response(conn,
                              cmd,
                              success=False,
                              data=b"Invalid command: %s" % cmd)
                continue
            action = m.group("action")
            key = m.group("key")
            logging.debug("Received %s %s", action, key)
            try:
                key = key.decode("utf-8")
                if action == b"SEND_ONCE":
                    control.press(key)
                elif action == b"SEND_START":
                    control.keydown(key)
                elif action == b"SEND_STOP":
                    control.keyup(key)
            except Exception as e:  # pylint: disable=broad-except
                logging.error("Error pressing or releasing key %r: %s",
                              key,
                              e,
                              exc_info=True)
                send_response(conn, cmd, success=False, data=to_bytes(str(e)))
                continue
            send_response(conn, cmd, success=True)
Exemple #10
0
def new_device_under_test_from_config(parsed_args=None,
                                      transformation_pipeline=None):
    """
    `parsed_args` if present should come from calling argparser().parse_args().
    """
    from _stbt.control import uri_to_control

    if parsed_args is None:
        args = argparser().parse_args([])
    else:
        args = parsed_args

    if args.source_pipeline is None:
        args.source_pipeline = get_config('global', 'source_pipeline')
    if args.sink_pipeline is None:
        args.sink_pipeline = get_config('global', 'sink_pipeline')
    if args.control is None:
        args.control = get_config('global', 'control')
    if args.save_video is None:
        args.save_video = False
    if args.restart_source is None:
        args.restart_source = get_config('global',
                                         'restart_source',
                                         type_=bool)
    if transformation_pipeline is None:
        transformation_pipeline = get_config('global',
                                             'transformation_pipeline')
    source_teardown_eos = get_config('global',
                                     'source_teardown_eos',
                                     type_=bool)
    use_old_threading_behaviour = get_config('global',
                                             'use_old_threading_behaviour',
                                             type_=bool)
    if use_old_threading_behaviour:
        warn(
            dedent("""\
            global.use_old_threading_behaviour is enabled.  This is intended as
            a stop-gap measure to allow upgrading to stb-tester v28. We
            recommend porting functions that depend on stbt.get_frame()
            returning consecutive frames on each call to use stbt.frames()
            instead.  This should make your functions usable from multiple
            threads.

            If porting to stbt.frames is not suitable please let us know on
            https://github.com/stb-tester/stb-tester/pull/449 otherwise this
            configuration option will be removed in a future release of
            stb-tester.
            """))

    display = [None]

    def raise_in_user_thread(exception):
        display[0].tell_user_thread(exception)

    mainloop = _mainloop()

    if not args.sink_pipeline and not args.save_video:
        sink_pipeline = NoSinkPipeline()
    else:
        sink_pipeline = SinkPipeline(  # pylint: disable=redefined-variable-type
            args.sink_pipeline, raise_in_user_thread, args.save_video)

    display[0] = Display(args.source_pipeline, sink_pipeline,
                         args.restart_source, transformation_pipeline,
                         source_teardown_eos)
    return DeviceUnderTest(
        display=display[0],
        control=uri_to_control(args.control, display[0]),
        sink_pipeline=sink_pipeline,
        mainloop=mainloop,
        use_old_threading_behaviour=use_old_threading_behaviour)
Exemple #11
0
def test_press(lircd):
    control = uri_to_control("lirc:%s:Apple_TV" % lircd.socket)
    control.press("KEY_OK")
    lircd_output = open(lircd.logfile, "r").read()
    expected = dedent("""\
        pulse 9000
        space 4500
        pulse 527
        space 527
        pulse 527
        space 1703
        pulse 527
        space 1703
        pulse 527
        space 1703
        pulse 527
        space 527
        pulse 527
        space 1703
        pulse 527
        space 1703
        pulse 527
        space 1703
        pulse 527
        space 1703
        pulse 527
        space 1703
        pulse 527
        space 1703
        pulse 527
        space 527
        pulse 527
        space 527
        pulse 527
        space 527
        pulse 527
        space 527
        pulse 527
        space 1703
        pulse 527
        space 527
        pulse 527
        space 527
        pulse 527
        space 1703
        pulse 527
        space 1703
        pulse 527
        space 1703
        pulse 527
        space 527
        pulse 527
        space 1703
        pulse 527
        space 527
        pulse 527
        space 527
        pulse 527
        space 1703
        pulse 527
        space 1703
        pulse 527
        space 527
        pulse 527
        space 1703
        pulse 527
        space 1703
        pulse 527
        space 1703
        pulse 527
        space 527
        pulse 527
        space 38000
        """)
    assert expected == lircd_output
Exemple #12
0
def test_press_with_unknown_key(lircd):
    control = uri_to_control("lirc:%s:Apple_TV" % lircd.socket)
    with pytest.raises(RuntimeError) as excinfo:
        control.press("KEY_MAGIC")
    assert 'unknown command: "KEY_MAGIC"' in str(excinfo.value)
Exemple #13
0
def test_press_with_unknown_remote(lircd):
    control = uri_to_control("lirc:%s:roku" % lircd.socket)
    with pytest.raises(RuntimeError) as excinfo:
        control.press("KEY_OK")
    assert 'unknown remote: "roku"' in str(excinfo.value)
def test_press(lircd):
    logfile = open(lircd.logfile)

    # newbytes doesn't play well with parameterize here, so we use a for loop:
    for key in [b'KEY_OK', u'KEY_OK', newbytes(b'KEY_OK'), newstr(u'KEY_OK')]:
        print("key = %r (%s)" % (key, type(key)))  # pylint: disable=superfluous-parens
        control = uri_to_control("lirc:%s:Apple_TV" % lircd.socket)
        control.press(key)
        lircd_output = logfile.read()
        expected = dedent("""\
            pulse 9000
            space 4500
            pulse 527
            space 527
            pulse 527
            space 1703
            pulse 527
            space 1703
            pulse 527
            space 1703
            pulse 527
            space 527
            pulse 527
            space 1703
            pulse 527
            space 1703
            pulse 527
            space 1703
            pulse 527
            space 1703
            pulse 527
            space 1703
            pulse 527
            space 1703
            pulse 527
            space 527
            pulse 527
            space 527
            pulse 527
            space 527
            pulse 527
            space 527
            pulse 527
            space 1703
            pulse 527
            space 527
            pulse 527
            space 527
            pulse 527
            space 1703
            pulse 527
            space 1703
            pulse 527
            space 1703
            pulse 527
            space 527
            pulse 527
            space 1703
            pulse 527
            space 527
            pulse 527
            space 527
            pulse 527
            space 1703
            pulse 527
            space 1703
            pulse 527
            space 527
            pulse 527
            space 1703
            pulse 527
            space 1703
            pulse 527
            space 1703
            pulse 527
            space 527
            pulse 527
            space 38000
            """)
        assert expected == lircd_output