def test_mmap(self): class badfile: def close(self): raise Exception("test close failure handling") import tempfile tmp_dir = tempfile.gettempdir() for mmap, ctx in { "off": DummyContextManager(), "on": silence_info(log), tmp_dir + "/xpra-mmap-test-file-%i" % os.getpid(): silence_info(log), tmp_dir + "/xpra-fail-mmap-test-file-%i" % os.getpid(): silence_error(log), }.items(): opts = AdHocStruct() opts.mmap = mmap opts.mmap_group = False with ctx: m = self._test_mixin_class(MmapClient, opts, { "mmap.enabled": True, }) fail = bool(m.mmap_filename) and m.mmap_filename.find("fail") >= 0 assert m.mmap_enabled == (mmap != "off" and not fail) assert len(self.exit_codes) == int(fail) m.cleanup() #no-op: m.cleanup() m.mmap_tempfile = badfile() m.cleanup()
def test_audio(self): from xpra.server.mixins.audio_server import AudioServer, soundlog from xpra.server.source.audio_mixin import AudioMixin from xpra.sound.gstreamer_util import CODEC_ORDER, log opts = AdHocStruct() opts.sound_source = "" opts.speaker = "on" opts.speaker_codec = CODEC_ORDER opts.microphone = "on" opts.microphone_codec = ["mp3"] opts.pulseaudio = False opts.pulseaudio_command = "/bin/true" opts.pulseaudio_configure_commands = [] opts.av_sync = True with silence_info(soundlog): self._test_mixin_class(AudioServer, opts, { "sound.receive": True, "sound.decoders": CODEC_ORDER, }, AudioMixin) #init runs in a thread, give it time: time.sleep(2) if not self.mixin.speaker_codecs: print("no speaker codecs available, test skipped") return codec = self.mixin.speaker_codecs[0] with silence_info(log): self.handle_packet(("sound-control", "start", codec)) time.sleep(1) self.handle_packet(("sound-control", "fadeout")) time.sleep(1) self.handle_packet(("sound-control", "stop"))
def test_remotelogging(self): from xpra.log import Logger, is_debug_enabled for x in ("network", "crypto"): if is_debug_enabled(x): #remote logging will be disabled, #so we have to skip this test return opts = AdHocStruct() opts.remote_logging = "yes" with silence_info(log): self._test_mixin_class(RemoteLogging, opts, { "remote-logging": True, }) assert len(self.packets) == 0 logger = Logger("util") message = b"hello" logger.info(message) assert len(self.packets) == 1 packet = self.packets[0] assert packet[ 0] == "logging", "expected logging packet but got '%s'" % ( packet[0], ) assert packet[1] == 20, "expected INFO level (20) but got %s" % ( packet[1], ) assert packet[ 2].data == message, "expected message '%s' but got '%s'" % ( message, packet[2].data) #after cleanup, log messages should not be intercepted: self.packets = [] self.mixin.cleanup() with silence_info(log): logger.info("foo") assert len(self.packets) == 0
def test_webcam(self): from xpra.server.mixins.webcam_server import WebcamServer, log as serverlog from xpra.server.source.webcam_mixin import WebcamMixin, log as sourcelog opts = AdHocStruct() opts.webcam = "yes" with silence_info(serverlog): self._test_mixin_class(WebcamServer, opts, {}, WebcamMixin) if self.mixin.get_info(self.protocol).get("webcam", {}).get("virtual-video-devices", 0)>0: with silence_info(sourcelog): self.handle_packet(("webcam-start", 0, 640, 480)) png_hex_data = "89504e470d0a1a0a0000000d4948445200000280000001e00802000000bab34bb3000005f34944415478daedd53101000008c330c0bfe7e1029e44429f769202006e8d040060c00060c00080010380010300060c00060c0018300018300060c00060c00060c00080010380010300060c00060c0018300018300060c00060c00060c00080010380010300060c00060c0018300018300060c00060c00060c00080010380010300060c00060c0018300018300060c00060c00060c00080010380010300060c00060c0018300018300060c00060c00060c00080010380010300060c00060c0018300018300060c00060c00060c00080010380010300060c00060c0018300018300060c00060c00060c00080010380010300060c00060c0018300018300060c00060c00060c00080010380010300060c00060c0018300018300060c00060c00060c00080010380010300060c00060c0018300018300060c00060c00080010380010380010300060c00060c0018300018300060c00060c00080010380010380010300060c00060c0018300018300060c00060c00080010380010380010300060c00060c0018300018300060c00060c00080010380010380010300060c00060c0018300018300060c00060c00080010380010380010300060c00060c0018300018300060c00060c00080010380010380010300060c00060c0018300018300060c00060c00080010380010380010300060c00060c0018300018300060c00060c00080010380010380010300060c00060c0018300018300060c00060c00080010380010380010300060c00060c0018300018300060c00060c00080010380010300060c00060c00060c0018300018300060c00060c00080010380010300060c00060c00060c0018300018300060c00060c00080010380010300060c00060c00060c0018300018300060c00060c00080010380010300060c00060c00060c0018300018300060c00060c00080010380010300060c00060c00060c0018300018300060c00060c00080010380010300060c00060c00060c0018300018300060c00060c00080010380010300060c00060c00060c0018300018300060c00060c00080010380010300060c00060c00060c0018300018300060c00060c00080010380010300060c00060c00060c0018300018300060c00060c00080010380010300060c00060c00062c010018300018300060c00060c00080010380010300060c00060c0018300018300018300060c00060c00080010380010300060c00060c0018300018300018300060c00060c00080010380010300060c00060c0018300018300018300060c00060c00080010380010300060c00060c0018300018300018300060c00060c00080010380010300060c00060c0018300018300018300060c00060c00080010380010300060c00060c0018300018300018300060c00060c00080010380010300060c00060c0018300018300018300060c00060c00080010380010300060c00060c0018300018300018300060c00060c00080010380010300060c00060c0018300018300018300060c00060c00080010380010300060c00060c0018300018300060c00060c00060c00080010380010300060c00060c0018300018300060c00060c00060c00080010380010300060c00060c0018300018300060c00060c00060c00080010380010300060c00060c0018300018300060c00060c00060c00080010380010300060c00060c0018300018300060c00060c00060c00080010380010300060c00060c0018300018300060c00060c00060c00080010380010300060c00060c0018300018300060c00060c00060c00080010380010300060c00060c0018300018300060c00060c00060c00080010380010300060c00060c0018300018300060c00060c00060c00080010380010300060c00060c0018300018300060c00060c00080010380010380010300060c00060c0018300018300060c00060c00080010380010380010300060c00060c0018300018300060c00060c00080010380010380010300060c00060c0018300018300060c00060c00080010380010380010300060c00060c0018300018300060c00060c00080010380010380010300060c00060c0018300018300060c00060c000800103c0bf05fda806bd1bd7b4640000000049454e44ae426082" png_data = binascii.unhexlify(png_hex_data) self.handle_packet(("webcam-frame", 0, 0, "png", 640, 480, png_data)) self.handle_packet(("webcam-stop", 0, "end"))
def test_notification(self): with OSEnvContext(): #remove any existing dbus environment so we don't pollute it: for k in tuple(os.environ.keys()): if k.startswith("DBUS"): del os.environ[k] #start a dbus server: from xpra.server.dbus.dbus_start import start_dbus dbus_pid, dbus_env = start_dbus( "dbus-launch --sh-syntax --close-stderr") try: if dbus_env: os.environ.update(dbus_env) from xpra.server.mixins.notification_forwarder import NotificationForwarder, log opts = AdHocStruct() opts.notifications = "yes" with silence_info(log): self._test_mixin_class(NotificationForwarder, opts) self.verify_packet_error( ("notification-close", 1, "test", "hello")) self.verify_packet_error(("notification-action", 1)) self.handle_packet(("set-notify", False)) self.mixin.cleanup() time.sleep(0.1) finally: if dbus_pid: import signal os.kill(dbus_pid, signal.SIGINT)
def test_display(self): with DisplayContext(): from xpra.client.mixins.display import DisplayClient, log def _DisplayClient(): dc = DisplayClient() def get_root_size(): return 1024, 768 dc.get_root_size = get_root_size def get_screen_sizes(*_args): return ((1024, 768), ) dc.get_screen_sizes = get_screen_sizes return dc opts = AdHocStruct() opts.desktop_fullscreen = False opts.desktop_scaling = False opts.dpi = 144 with silence_info(log): self._test_mixin_class( _DisplayClient, opts, { "display": ":999", "desktop_size": (1024, 768), "max_desktop_size": (3840, 2160), "actual_desktop_size": (1024, 768), "resize_screen": True, })
def test_command_server(self): try: from xpra.platform.xposix.xdg_helper import log c = silence_info(log) except ImportError: c = DummyContextManager() with c: self.do_test_command_server()
def test_fileprint(self): from xpra.server.mixins.fileprint_server import FilePrintServer, printlog opts = AdHocStruct() opts.file_transfer = "yes" opts.file_size_limit = 10 opts.printing = "yes" opts.open_files = "no" opts.open_url = "yes" opts.open_command = "" opts.lpadmin = "/usr/sbin/lpadmin" opts.lpinfo = "/usr/sbin/lpinfo" opts.add_printer_options = "" opts.postscript_printer = "" opts.pdf_printer = "" with silence_info(printlog): self._test_mixin_class(FilePrintServer, opts)
def test_networkstate(self): with OSEnvContext(): os.environ["XPRA_PING_TIMEOUT"] = "1" from xpra.server.mixins.networkstate_server import NetworkStateServer, MAX_BANDWIDTH_LIMIT, log, bandwidthlog from xpra.server.source.networkstate_mixin import NetworkStateMixin assert NetworkStateMixin.is_needed(typedict()) opts = AdHocStruct() opts.pings = 1 opts.bandwidth_limit = "1Gbps" #the limit for all clients: capped_at = 1 * 1000 * 1000 * 1000 #=="1Gbps" with silence_info(log): self._test_mixin_class(NetworkStateServer, opts, {}, NetworkStateMixin) self.assertEqual(capped_at, self.mixin.get_info().get("bandwidth-limit")) self.handle_packet(("ping", 10)) self.handle_packet(("ping", -1000)) self.handle_packet(("ping_echo", 10, 500, 500, 600, 10)) for v in (None, "foo", 1, 2.0, [], (), set()): try: self.handle_packet(("connection-data", v)) except TypeError: pass else: raise Exception( "should not allow %s (%s) as connection-data" % (v, type(v))) self.handle_packet(("connection-data", {})) for v in (None, "foo", 2.0, [], (), set()): try: self.handle_packet(("bandwidth-limit", v)) except TypeError: pass else: raise Exception( "should not allow %s (%s) as connection-data" % (v, type(v))) with silence_info(bandwidthlog): self.handle_packet(("bandwidth-limit", 10 * 1024 * 1024)) def get_limit(): return self.source.get_info().get("bandwidth-limit", {}).get("setting", 0) self.assertEqual(10 * 1024 * 1024, get_limit()) with silence_info(bandwidthlog): self.handle_packet( ("bandwidth-limit", MAX_BANDWIDTH_LIMIT + 1)) self.assertEqual(min(capped_at, MAX_BANDWIDTH_LIMIT), get_limit()) #test source: timeouts = [] def timeout(*args): timeouts.append(args) self.source.disconnect = timeout assert self.source.get_caps() self.source.ping() self.source.check_ping_echo_timeout(0, 0) #give time for the timeout to fire: self.glib.timeout_add(2000, self.main_loop.quit) self.main_loop.run()
def do_test_command_server(self): from xpra.server.mixins.child_command_server import ChildCommandServer, log opts = AdHocStruct() opts.exit_with_children = True opts.terminate_children = True opts.start_new_commands = True opts.start = [] opts.start_child = [] opts.start_after_connect = [] opts.start_child_after_connect = [] opts.start_on_connect = [] opts.start_child_on_connect = [] opts.start_on_last_client_exit = [] opts.start_child_on_last_client_exit = [] opts.exec_wrapper = None opts.start_env = [] opts.source_start = [] #pynotify can cause crashes, #probably due to threading issues? def noop(): pass def _ChildCommandServer(): ccs = ChildCommandServer() ccs.setup_menu_watcher = noop return ccs self._test_mixin_class(_ChildCommandServer, opts) if not POSIX: return #test creating a temp file: import tempfile tmpfile = os.path.join(tempfile.gettempdir(), "xpra-test-start-command-%s" % os.getpid()) assert not os.path.exists(tmpfile) command = (b"touch", tmpfile.encode("utf8")) self.handle_packet(("start-command", b"test", command, True)) time.sleep(1) info = self.mixin.get_info(self.protocol) commands = info.get("commands") assert commands proc_info = commands.get(0) assert proc_info pid = proc_info.get("pid") assert pid assert os.path.exists(tmpfile) os.unlink(tmpfile) #test signals: self.handle_packet(("start-command", b"sleep", b"sleep 10", True)) time.sleep(1) info = self.mixin.get_info(self.protocol) commands = info.get("commands") assert commands proc_info = commands.get(1) assert proc_info pid = proc_info.get("pid") assert pid assert proc_info.get("name") == "sleep" assert proc_info.get("dead") is False #send it a SIGINT: with silence_info(log): self.handle_packet(("command-signal", pid, "SIGINT")) time.sleep(1) self.mixin.child_reaper.poll() info = self.mixin.get_info(self.protocol) commands = info.get("commands") assert commands proc_info = commands.get(1) assert proc_info.get("dead") is True import signal assert proc_info.get("returncode") == -signal.SIGINT
def test_webcam(self): if not POSIX or OSX: get_util_logger().info("webcam test skipped: %s not supported yet", sys.platform) return from xpra.platform.xposix.webcam import get_virtual_video_devices, check_virtual_dir if not check_virtual_dir(): get_util_logger().info("webcam test skipped: no virtual video device directory") return devices = get_virtual_video_devices() if not devices: get_util_logger().info("webcam test skipped: no virtual video devices found") return for need in (False, True): from xpra.server.source import webcam_mixin for enabled in (False, True): wm = self._test_mixin_class(webcam_mixin.WebcamMixin, { "webcam" : need, "webcam_enabled" : enabled, "webcam_device" : None, "webcam_encodings" : ("png", "jpeg"), }) wm.init_state() wm.hello_sent = True packets = [] def send(*args): packets.append(args) #wm.send = send wm.send_async = send try: assert wm.get_info() device_id = 0 w, h = 640, 480 with silence_info(webcam_mixin.log): assert wm.start_virtual_webcam(device_id, w, h) assert wm.get_info().get("webcam", {}).get("active-devices", 0)==1 assert len(packets)==1 #ack sent assert packets[0][0]=="webcam-ack" frame_no = 0 from PIL import Image image = Image.new('RGB', size=(w, h), color=(155, 0, 0)) buf = BytesIO() image.save(buf, "png") data = buf.getvalue() buf.close() assert wm.process_webcam_frame(device_id, frame_no, "png", w, h, data) assert len(packets)==2 #ack sent assert packets[1][0]=="webcam-ack" #now send a jpeg as png, #which should fail and stop: buf = BytesIO() image.save(buf, "jpeg") data = buf.getvalue() buf.close() #suspend error logging to avoid the scary message: from xpra.server.source.webcam_mixin import log as webcam_log elog = webcam_log.error try: webcam_log.error = webcam_log.debug assert not wm.process_webcam_frame(device_id, frame_no, "png", w, h, data) finally: #restore it: webcam_log.error = elog assert len(packets)==3 assert packets[2][0]=="webcam-stop" finally: wm.cleanup()