···11# Test printing via CUPS.
22+{
33+ pkgs,
44+ socket ? true, # whether to use socket activation
55+ listenTcp ? true, # whether to open port 631 on client
66+ ...
77+}:
2833-import ./make-test-python.nix (
44- {
55- pkgs,
66- socket ? true, # whether to use socket activation
77- listenTcp ? true, # whether to open port 631 on client
88- ...
99- }:
99+let
1010+ inherit (pkgs) lib;
1111+in
10121111- let
1212- inherit (pkgs) lib;
1313- in
1313+{
1414+ name = "printing";
1515+ meta = with lib.maintainers; {
1616+ maintainers = [
1717+ domenkozar
1818+ matthewbauer
1919+ ];
2020+ };
14211515- {
1616- name = "printing";
1717- meta = with lib.maintainers; {
1818- maintainers = [
1919- domenkozar
2020- matthewbauer
2222+ nodes.server =
2323+ { ... }:
2424+ {
2525+ services.printing = {
2626+ enable = true;
2727+ stateless = true;
2828+ startWhenNeeded = socket;
2929+ listenAddresses = [ "*:631" ];
3030+ defaultShared = true;
3131+ openFirewall = true;
3232+ extraConf = ''
3333+ <Location />
3434+ Order allow,deny
3535+ Allow from all
3636+ </Location>
3737+ '';
3838+ };
3939+ # Add a HP Deskjet printer connected via USB to the server.
4040+ hardware.printers.ensurePrinters = [
4141+ {
4242+ name = "DeskjetLocal";
4343+ deviceUri = "usb://foobar/printers/foobar";
4444+ model = "drv:///sample.drv/deskjet.ppd";
4545+ }
2146 ];
2247 };
23482424- nodes.server =
2525- { ... }:
2626- {
2727- services.printing = {
2828- enable = true;
2929- stateless = true;
3030- startWhenNeeded = socket;
3131- listenAddresses = [ "*:631" ];
3232- defaultShared = true;
3333- openFirewall = true;
3434- extraConf = ''
3535- <Location />
3636- Order allow,deny
3737- Allow from all
3838- </Location>
3939- '';
4040- };
4141- # Add a HP Deskjet printer connected via USB to the server.
4242- hardware.printers.ensurePrinters = [
4343- {
4444- name = "DeskjetLocal";
4545- deviceUri = "usb://foobar/printers/foobar";
4646- model = "drv:///sample.drv/deskjet.ppd";
4747- }
4848- ];
4949- };
4949+ nodes.client =
5050+ { lib, ... }:
5151+ {
5252+ services.printing.enable = true;
5353+ services.printing.startWhenNeeded = socket;
5454+ services.printing.listenAddresses = lib.mkIf (!listenTcp) [ ];
5555+ # Add printer to the client as well, via IPP.
5656+ hardware.printers.ensurePrinters = [
5757+ {
5858+ name = "DeskjetRemote";
5959+ deviceUri = "ipp://server/printers/DeskjetLocal";
6060+ model = "drv:///sample.drv/deskjet.ppd";
6161+ }
6262+ ];
6363+ hardware.printers.ensureDefaultPrinter = "DeskjetRemote";
6464+ };
50655151- nodes.client =
5252- { lib, ... }:
5353- {
5454- services.printing.enable = true;
5555- services.printing.startWhenNeeded = socket;
5656- services.printing.listenAddresses = lib.mkIf (!listenTcp) [ ];
5757- # Add printer to the client as well, via IPP.
5858- hardware.printers.ensurePrinters = [
5959- {
6060- name = "DeskjetRemote";
6161- deviceUri = "ipp://server/printers/DeskjetLocal";
6262- model = "drv:///sample.drv/deskjet.ppd";
6363- }
6464- ];
6565- hardware.printers.ensureDefaultPrinter = "DeskjetRemote";
6666- };
6666+ testScript = ''
6767+ import os
6868+ import re
67696868- testScript = ''
6969- import os
7070- import re
7070+ start_all()
71717272- start_all()
7272+ with subtest("Make sure that cups is up on both sides and printers are set up"):
7373+ server.wait_for_unit("ensure-printers.service")
7474+ client.wait_for_unit("ensure-printers.service")
73757474- with subtest("Make sure that cups is up on both sides and printers are set up"):
7575- server.wait_for_unit("ensure-printers.service")
7676- client.wait_for_unit("ensure-printers.service")
7676+ assert "scheduler is running" in client.succeed("lpstat -r")
77777878- assert "scheduler is running" in client.succeed("lpstat -r")
7979-8080- with subtest("UNIX socket is used for connections"):
8181- assert "/var/run/cups/cups.sock" in client.succeed("lpstat -H")
7878+ with subtest("UNIX socket is used for connections"):
7979+ assert "/var/run/cups/cups.sock" in client.succeed("lpstat -H")
82808383- with subtest("HTTP server is available too"):
8484- ${lib.optionalString listenTcp ''client.succeed("curl --fail http://localhost:631/")''}
8585- client.succeed(f"curl --fail http://{server.name}:631/")
8686- server.fail(f"curl --fail --connect-timeout 2 http://{client.name}:631/")
8181+ with subtest("HTTP server is available too"):
8282+ ${lib.optionalString listenTcp ''client.succeed("curl --fail http://localhost:631/")''}
8383+ client.succeed(f"curl --fail http://{server.name}:631/")
8484+ server.fail(f"curl --fail --connect-timeout 2 http://{client.name}:631/")
87858888- with subtest("LP status checks"):
8989- assert "DeskjetRemote accepting requests" in client.succeed("lpstat -a")
9090- assert "DeskjetLocal accepting requests" in client.succeed(
9191- f"lpstat -h {server.name}:631 -a"
9292- )
9393- client.succeed("cupsdisable DeskjetRemote")
9494- out = client.succeed("lpq")
9595- print(out)
9696- assert re.search(
9797- "DeskjetRemote is not ready.*no entries",
9898- client.succeed("lpq"),
9999- flags=re.DOTALL,
100100- )
101101- client.succeed("cupsenable DeskjetRemote")
102102- assert re.match(
103103- "DeskjetRemote is ready.*no entries", client.succeed("lpq"), flags=re.DOTALL
104104- )
8686+ with subtest("LP status checks"):
8787+ assert "DeskjetRemote accepting requests" in client.succeed("lpstat -a")
8888+ assert "DeskjetLocal accepting requests" in client.succeed(
8989+ f"lpstat -h {server.name}:631 -a"
9090+ )
9191+ client.succeed("cupsdisable DeskjetRemote")
9292+ out = client.succeed("lpq")
9393+ print(out)
9494+ assert re.search(
9595+ "DeskjetRemote is not ready.*no entries",
9696+ client.succeed("lpq"),
9797+ flags=re.DOTALL,
9898+ )
9999+ client.succeed("cupsenable DeskjetRemote")
100100+ assert re.match(
101101+ "DeskjetRemote is ready.*no entries", client.succeed("lpq"), flags=re.DOTALL
102102+ )
105103106106- # Test printing various file types.
107107- for file in [
108108- "${pkgs.groff.doc}/share/doc/*/examples/mom/penguin.pdf",
109109- "${pkgs.groff.doc}/share/doc/*/meref.ps",
110110- "${pkgs.cups.out}/share/doc/cups/images/cups.png",
111111- "${pkgs.pcre.doc}/share/doc/pcre/pcre.txt",
112112- ]:
113113- file_name = os.path.basename(file)
114114- with subtest(f"print {file_name}"):
115115- # Print the file on the client.
116116- print(client.succeed("lpq"))
117117- client.succeed(f"lp {file}")
118118- client.wait_until_succeeds(
119119- f"lpq; lpq | grep -q -E 'active.*root.*{file_name}'"
120120- )
104104+ # Test printing various file types.
105105+ for file in [
106106+ "${pkgs.groff.doc}/share/doc/*/examples/mom/penguin.pdf",
107107+ "${pkgs.groff.doc}/share/doc/*/meref.ps",
108108+ "${pkgs.cups.out}/share/doc/cups/images/cups.png",
109109+ "${pkgs.pcre.doc}/share/doc/pcre/pcre.txt",
110110+ ]:
111111+ file_name = os.path.basename(file)
112112+ with subtest(f"print {file_name}"):
113113+ # Print the file on the client.
114114+ print(client.succeed("lpq"))
115115+ client.succeed(f"lp {file}")
116116+ client.wait_until_succeeds(
117117+ f"lpq; lpq | grep -q -E 'active.*root.*{file_name}'"
118118+ )
121119122122- # Ensure that a raw PCL file appeared in the server's queue
123123- # (showing that the right filters have been applied). Of
124124- # course, since there is no actual USB printer attached, the
125125- # file will stay in the queue forever.
126126- server.wait_for_file("/var/spool/cups/d*-001")
127127- server.wait_until_succeeds(f"lpq -a | grep -q -E '{file_name}'")
120120+ # Ensure that a raw PCL file appeared in the server's queue
121121+ # (showing that the right filters have been applied). Of
122122+ # course, since there is no actual USB printer attached, the
123123+ # file will stay in the queue forever.
124124+ server.wait_for_file("/var/spool/cups/d*-001")
125125+ server.wait_until_succeeds(f"lpq -a | grep -q -E '{file_name}'")
128126129129- # Delete the job on the client. It should disappear on the
130130- # server as well.
131131- client.succeed("lprm")
132132- client.wait_until_succeeds("lpq -a | grep -q -E 'no entries'")
127127+ # Delete the job on the client. It should disappear on the
128128+ # server as well.
129129+ client.succeed("lprm")
130130+ client.wait_until_succeeds("lpq -a | grep -q -E 'no entries'")
133131134134- retry(lambda _: "no entries" in server.succeed("lpq -a"))
132132+ retry(lambda _: "no entries" in server.succeed("lpq -a"))
135133136136- # The queue is empty already, so this should be safe.
137137- # Otherwise, pairs of "c*"-"d*-001" files might persist.
138138- server.execute("rm /var/spool/cups/*")
139139- '';
140140- }
141141-)
134134+ # The queue is empty already, so this should be safe.
135135+ # Otherwise, pairs of "c*"-"d*-001" files might persist.
136136+ server.execute("rm /var/spool/cups/*")
137137+ '';
138138+}