at 23.11-pre 4.2 kB view raw
1# Test printing via CUPS. 2 3import ./make-test-python.nix ( 4{ pkgs 5, socket ? true # whether to use socket activation 6, ... 7}: 8 9{ 10 name = "printing"; 11 meta = with pkgs.lib.maintainers; { 12 maintainers = [ domenkozar eelco matthewbauer ]; 13 }; 14 15 nodes.server = { ... }: { 16 services.printing = { 17 enable = true; 18 stateless = true; 19 startWhenNeeded = socket; 20 listenAddresses = [ "*:631" ]; 21 defaultShared = true; 22 extraConf = '' 23 <Location /> 24 Order allow,deny 25 Allow from all 26 </Location> 27 ''; 28 }; 29 networking.firewall.allowedTCPPorts = [ 631 ]; 30 # Add a HP Deskjet printer connected via USB to the server. 31 hardware.printers.ensurePrinters = [{ 32 name = "DeskjetLocal"; 33 deviceUri = "usb://foobar/printers/foobar"; 34 model = "drv:///sample.drv/deskjet.ppd"; 35 }]; 36 }; 37 38 nodes.client = { ... }: { 39 services.printing.enable = true; 40 services.printing.startWhenNeeded = socket; 41 # Add printer to the client as well, via IPP. 42 hardware.printers.ensurePrinters = [{ 43 name = "DeskjetRemote"; 44 deviceUri = "ipp://server/printers/DeskjetLocal"; 45 model = "drv:///sample.drv/deskjet.ppd"; 46 }]; 47 hardware.printers.ensureDefaultPrinter = "DeskjetRemote"; 48 }; 49 50 testScript = '' 51 import os 52 import re 53 54 start_all() 55 56 with subtest("Make sure that cups is up on both sides and printers are set up"): 57 server.wait_for_unit("cups.${if socket then "socket" else "service"}") 58 client.wait_for_unit("cups.${if socket then "socket" else "service"}") 59 60 assert "scheduler is running" in client.succeed("lpstat -r") 61 62 with subtest("UNIX socket is used for connections"): 63 assert "/var/run/cups/cups.sock" in client.succeed("lpstat -H") 64 65 with subtest("HTTP server is available too"): 66 client.succeed("curl --fail http://localhost:631/") 67 client.succeed(f"curl --fail http://{server.name}:631/") 68 server.fail(f"curl --fail --connect-timeout 2 http://{client.name}:631/") 69 70 with subtest("LP status checks"): 71 assert "DeskjetRemote accepting requests" in client.succeed("lpstat -a") 72 assert "DeskjetLocal accepting requests" in client.succeed( 73 f"lpstat -h {server.name}:631 -a" 74 ) 75 client.succeed("cupsdisable DeskjetRemote") 76 out = client.succeed("lpq") 77 print(out) 78 assert re.search( 79 "DeskjetRemote is not ready.*no entries", 80 client.succeed("lpq"), 81 flags=re.DOTALL, 82 ) 83 client.succeed("cupsenable DeskjetRemote") 84 assert re.match( 85 "DeskjetRemote is ready.*no entries", client.succeed("lpq"), flags=re.DOTALL 86 ) 87 88 # Test printing various file types. 89 for file in [ 90 "${pkgs.groff.doc}/share/doc/*/examples/mom/penguin.pdf", 91 "${pkgs.groff.doc}/share/doc/*/meref.ps", 92 "${pkgs.cups.out}/share/doc/cups/images/cups.png", 93 "${pkgs.pcre.doc}/share/doc/pcre/pcre.txt", 94 ]: 95 file_name = os.path.basename(file) 96 with subtest(f"print {file_name}"): 97 # Print the file on the client. 98 print(client.succeed("lpq")) 99 client.succeed(f"lp {file}") 100 client.wait_until_succeeds( 101 f"lpq; lpq | grep -q -E 'active.*root.*{file_name}'" 102 ) 103 104 # Ensure that a raw PCL file appeared in the server's queue 105 # (showing that the right filters have been applied). Of 106 # course, since there is no actual USB printer attached, the 107 # file will stay in the queue forever. 108 server.wait_for_file("/var/spool/cups/d*-001") 109 server.wait_until_succeeds(f"lpq -a | grep -q -E '{file_name}'") 110 111 # Delete the job on the client. It should disappear on the 112 # server as well. 113 client.succeed("lprm") 114 client.wait_until_succeeds("lpq -a | grep -q -E 'no entries'") 115 116 retry(lambda _: "no entries" in server.succeed("lpq -a")) 117 118 # The queue is empty already, so this should be safe. 119 # Otherwise, pairs of "c*"-"d*-001" files might persist. 120 server.execute("rm /var/spool/cups/*") 121 ''; 122})