Initial import
[samba] / source / stf / spoolss.py
1 #!/usr/bin/python
2
3 import re
4 import comfychair, stf
5 from samba import spoolss
6
7 class PrintServerTest(comfychair.TestCase):
8     """An abstract class requiring a print server."""
9     def setUp(self):
10         # TODO: create a test printer
11         self.server = stf.get_server(platform = "nt")
12         self.require(self.server != None, "print server required")
13         # TODO: remove hardcoded printer name
14         self.printername = "p"
15         self.uncname = "\\\\%s\\%s" % \
16                            (self.server["hostname"], self.printername)
17
18 class W2kPrintServerTest(comfychair.TestCase):
19     """An abstract class requiring a print server."""
20     def setUp(self):
21         # TODO: create a test printer
22         self.server = stf.get_server(platform = "nt5")
23         self.require(self.server != None, "print server required")
24         # TODO: remove hardcoded printer name
25         self.printername = "p"
26         self.uncname = "\\\\%s\\%s" % \
27                            (self.server["hostname"], self.printername)
28
29 class CredentialTest(PrintServerTest):
30     """An class that calls a function with various sets of credentials."""
31     def runTest(self):
32
33         bad_user_creds = {"username": "spotty",
34                           "domain": "dog",
35                           "password": "bone"}
36                         
37         cases = ((self.server["administrator"], "Admin credentials", 1),
38                  (bad_user_creds,               "Bad credentials",   0))
39
40         # TODO: add unpriv user case
41
42         for creds, testname, result in cases:
43             try:
44                 self.runTestArg(creds)
45             except:
46                 if result:
47                     import traceback
48                     traceback.print_exc()
49                     self.fail("rpc with creds %s failed when it "
50                               "should have suceeded" % creds)
51                 return
52
53             if not result:
54                 self.fail("rpc with creds %s suceeded when it should "
55                           "have failed" % creds)
56         
57 class ArgTestServer(PrintServerTest):
58     """Test a RPC that takes a UNC print server name."""
59     def runTest(self):
60
61         # List of test cases, %s substituted for server name
62
63         cases = (("",             "No server name",          0),
64                  ("\\\\%s",       "Valid server name",       1),
65                  ("\\%s",         "Invalid unc server name", 0),
66                  ("\\\\%s__",     "Invalid unc server name", 0))
67
68         for unc, testname, result in cases:
69             unc = re.sub("%s", self.server["hostname"], unc)
70             try:
71                 self.runTestArg(unc)
72             except:
73                 if result:
74                     self.fail("rpc(\"%s\") failed when it should have "
75                               "suceeded" % unc)
76                 return
77
78             if not result:
79                 # Suceeded when we should have failed
80                 self.fail("rpc(\"%s\") suceeded when it should have "
81                           "failed" % unc)
82
83 class ArgTestServerAndPrinter(ArgTestServer):
84     """Test a RPC that takes a UNC print server or UNC printer name."""
85     def runTest(self):
86
87         ArgTestServer.runTest(self)
88         
89         # List of test cases, %s substituted for server name, %p substituted
90         # for printer name.
91
92         cases = (("\\\\%s\\%p",   "Valid server and printer name",      1),
93                  ("\\\\%s\\%p__", "Valid server, invalid printer name", 0),
94                  ("\\\\%s__\\%p", "Invalid server, valid printer name", 0))
95
96         for unc, testname, result in cases:
97             unc = re.sub("%s", self.server["hostname"], unc)
98             unc = re.sub("%p", self.printername, unc)
99             try:
100                 self.runTestArg(unc)
101             except:
102                 if result:
103                     self.fail("openprinter(\"%s\") failed when it should have "
104                               "suceeded" % unc)
105                 return
106
107             if not result:
108                 # Suceeded when we should have failed
109                 self.fail("openprinter(\"%s\") suceeded when it should have "
110                           "failed" % unc)
111
112 class OpenPrinterArg(ArgTestServerAndPrinter):
113     """Test the OpenPrinter RPC with combinations of valid and invalid
114     server and printer names."""
115     def runTestArg(self, unc):
116         spoolss.openprinter(unc)
117
118 class OpenPrinterCred(CredentialTest):
119     """Test opening printer with good and bad credentials."""
120     def runTestArg(self, creds):
121         spoolss.openprinter(self.uncname, creds = creds)
122
123 class ClosePrinter(PrintServerTest):
124     """Test the ClosePrinter RPC on a printer handle."""
125     def runTest(self):
126         hnd = spoolss.openprinter(self.uncname)
127         spoolss.closeprinter(hnd)
128         
129 class ClosePrinterServer(PrintServerTest):
130     """Test the ClosePrinter RPC on a print server handle."""
131     def runTest(self):
132         hnd = spoolss.openprinter("\\\\%s" % self.server["hostname"])
133         spoolss.closeprinter(hnd)
134         
135 class GetPrinterInfo(PrintServerTest):
136     """Retrieve printer info at various levels."""
137
138     # Sample printer data
139
140     sample_info = {
141         0: {'printer_errors': 0, 'unknown18': 0, 'unknown13': 0, 'unknown26': 0, 'cjobs': 0, 'unknown11': 0, 'server_name': '\\\\win2kdc1', 'total_pages': 0, 'unknown15': 586, 'unknown16': 0, 'month': 2, 'unknown20': 0, 'second': 23, 'unknown22': 983040, 'unknown25': 0, 'total_bytes': 0, 'unknown27': 0, 'year': 2003, 'build_version': 2195, 'unknown28': 0, 'global_counter': 4, 'day': 13, 'minute': 53, 'total_jobs': 0, 'unknown29': 1114112, 'name': '\\\\win2kdc1\\p', 'hour': 2, 'level': 0, 'c_setprinter': 0, 'change_id': 522454169, 'major_version': 5, 'unknown23': 15, 'day_of_week': 4, 'unknown14': 1, 'session_counter': 2, 'status': 1, 'unknown7': 1, 'unknown8': 0, 'unknown9': 0, 'milliseconds': 421, 'unknown24': 0},
142         1: {'comment': "I'm a teapot!", 'level': 1, 'flags': 8388608, 'name': '\\\\win2kdc1\\p', 'description': '\\\\win2kdc1\\p,HP LaserJet 4,Canberra office'},
143         2: {'comment': "I'm a teapot!", 'status': 1, 'print_processor': 'WinPrint', 'until_time': 0, 'share_name': 'p', 'start_time': 0, 'device_mode': {'icm_method': 1, 'bits_per_pel': 0, 'log_pixels': 0, 'orientation': 1, 'panning_width': 0, 'color': 2, 'pels_width': 0, 'print_quality': 600, 'driver_version': 24, 'display_flags': 0, 'y_resolution': 600, 'media_type': 0, 'display_frequency': 0, 'icm_intent': 0, 'pels_height': 0, 'reserved1': 0, 'size': 220, 'scale': 100, 'dither_type': 0, 'panning_height': 0, 'default_source': 7, 'duplex': 1, 'fields': 16131, 'spec_version': 1025, 'copies': 1, 'device_name': '\\\\win2kdc1\\p', 'paper_size': 1, 'paper_length': 0, 'private': 'private', 'collate': 0, 'paper_width': 0, 'form_name': 'Letter', 'reserved2': 0, 'tt_option': 0}, 'port_name': 'LPT1:', 'sepfile': '', 'parameters': '', 'security_descriptor': {'group_sid': 'S-1-5-21-1606980848-1677128483-854245398-513', 'sacl': None, 'dacl': {'ace_list': [{'flags': 0, 'type': 0, 'mask': 983052, 'trustee': 'S-1-5-32-544'}, {'flags': 9, 'type': 0, 'mask': 983056, 'trustee': 'S-1-5-32-544'}, {'flags': 0, 'type': 0, 'mask': 131080, 'trustee': 'S-1-5-21-1606980848-1677128483-854245398-1121'}, {'flags': 10, 'type': 0, 'mask': 131072, 'trustee': 'S-1-3-0'}, {'flags': 9, 'type': 0, 'mask': 983056, 'trustee': 'S-1-3-0'}, {'flags': 0, 'type': 0, 'mask': 131080, 'trustee': 'S-1-5-21-1606980848-1677128483-854245398-1124'}, {'flags': 0, 'type': 0, 'mask': 131080, 'trustee': 'S-1-1-0'}, {'flags': 0, 'type': 0, 'mask': 983052, 'trustee': 'S-1-5-32-550'}, {'flags': 9, 'type': 0, 'mask': 983056, 'trustee': 'S-1-5-32-550'}, {'flags': 0, 'type': 0, 'mask': 983052, 'trustee': 'S-1-5-32-549'}, {'flags': 9, 'type': 0, 'mask': 983056, 'trustee': 'S-1-5-32-549'}, {'flags': 0, 'type': 0, 'mask': 983052, 'trustee': 'S-1-5-21-1606980848-1677128483-854245398-1106'}], 'revision': 2}, 'owner_sid': 'S-1-5-32-544', 'revision': 1}, 'name': '\\\\win2kdc1\\p', 'server_name': '\\\\win2kdc1', 'level': 2, 'datatype': 'RAW', 'cjobs': 0, 'average_ppm': 0, 'priority': 1, 'driver_name': 'HP LaserJet 4', 'location': 'Canberra office', 'attributes': 8776, 'default_priority': 0},
144         3: {'flags': 4, 'security_descriptor': {'group_sid': 'S-1-5-21-1606980848-1677128483-854245398-513', 'sacl': None, 'dacl': {'ace_list': [{'flags': 0, 'type': 0, 'mask': 983052, 'trustee': 'S-1-5-32-544'}, {'flags': 9, 'type': 0, 'mask': 983056, 'trustee': 'S-1-5-32-544'}, {'flags': 0, 'type': 0, 'mask': 131080, 'trustee': 'S-1-5-21-1606980848-1677128483-854245398-1121'}, {'flags': 10, 'type': 0, 'mask': 131072, 'trustee': 'S-1-3-0'}, {'flags': 9, 'type': 0, 'mask': 983056, 'trustee': 'S-1-3-0'}, {'flags': 0, 'type': 0, 'mask': 131080, 'trustee': 'S-1-5-21-1606980848-1677128483-854245398-1124'}, {'flags': 0, 'type': 0, 'mask': 131080, 'trustee': 'S-1-1-0'}, {'flags': 0, 'type': 0, 'mask': 983052, 'trustee': 'S-1-5-32-550'}, {'flags': 9, 'type': 0, 'mask': 983056, 'trustee': 'S-1-5-32-550'}, {'flags': 0, 'type': 0, 'mask': 983052, 'trustee': 'S-1-5-32-549'}, {'flags': 9, 'type': 0, 'mask': 983056, 'trustee': 'S-1-5-32-549'}, {'flags': 0, 'type': 0, 'mask': 983052, 'trustee': 'S-1-5-21-1606980848-1677128483-854245398-1106'}], 'revision': 2}, 'owner_sid': 'S-1-5-32-544', 'revision': 1}, 'level': 3}
145         }
146
147     def runTest(self):
148         self.hnd = spoolss.openprinter(self.uncname)
149
150         # Everyone should have getprinter levels 0-3
151
152         for i in (0, 1, 2, 3):
153             info = self.hnd.getprinter(level = i)
154             try:
155                 stf.dict_check(self.sample_info[i], info)
156             except ValueError, msg:
157                 raise "info%d: %s" % (i, msg)
158
159 class EnumPrinters(PrintServerTest):
160     """Enumerate print info at various levels."""
161
162     sample_info = {
163
164         0: {'q': {'printer_errors': 0, 'unknown18': 0, 'unknown13': 0, 'unknown26': 0, 'cjobs': 0, 'unknown11': 0, 'server_name': '', 'total_pages': 0, 'unknown15': 586, 'unknown16': 0, 'month': 2, 'unknown20': 0, 'second': 23, 'unknown22': 983040, 'unknown25': 0, 'total_bytes': 0, 'unknown27': 0, 'year': 2003, 'build_version': 2195, 'unknown28': 0, 'global_counter': 4, 'day': 13, 'minute': 53, 'total_jobs': 0, 'unknown29': -1833435136, 'name': 'q', 'hour': 2, 'level': 0, 'c_setprinter': 0, 'change_id': 522454169, 'major_version': 5, 'unknown23': 15, 'day_of_week': 4, 'unknown14': 1, 'session_counter': 1, 'status': 0, 'unknown7': 1, 'unknown8': 0, 'unknown9': 0, 'milliseconds': 421, 'unknown24': 0}, 'p': {'printer_errors': 0, 'unknown18': 0, 'unknown13': 0, 'unknown26': 0, 'cjobs': 0, 'unknown11': 0, 'server_name': '', 'total_pages': 0, 'unknown15': 586, 'unknown16': 0, 'month': 2, 'unknown20': 0, 'second': 23, 'unknown22': 983040, 'unknown25': 0, 'total_bytes': 0, 'unknown27': 0, 'year': 2003, 'build_version': 2195, 'unknown28': 0, 'global_counter': 4, 'day': 13, 'minute': 53, 'total_jobs': 0, 'unknown29': -1831337984, 'name': 'p', 'hour': 2, 'level': 0, 'c_setprinter': 0, 'change_id': 522454169, 'major_version': 5, 'unknown23': 15, 'day_of_week': 4, 'unknown14': 1, 'session_counter': 1, 'status': 1, 'unknown7': 1, 'unknown8': 0, 'unknown9': 0, 'milliseconds': 421, 'unknown24': 0}, 'magpie': {'printer_errors': 0, 'unknown18': 0, 'unknown13': 0, 'unknown26': 0, 'cjobs': 0, 'unknown11': 0, 'server_name': '', 'total_pages': 0, 'unknown15': 586, 'unknown16': 0, 'month': 2, 'unknown20': 0, 'second': 23, 'unknown22': 983040, 'unknown25': 0, 'total_bytes': 0, 'unknown27': 0, 'year': 2003, 'build_version': 2195, 'unknown28': 0, 'global_counter': 4, 'day': 13, 'minute': 53, 'total_jobs': 0, 'unknown29': 1114112, 'name': 'magpie', 'hour': 2, 'level': 0, 'c_setprinter': 0, 'change_id': 522454169, 'major_version': 5, 'unknown23': 15, 'day_of_week': 4, 'unknown14': 1, 'session_counter': 1, 'status': 0, 'unknown7': 1, 'unknown8': 0, 'unknown9': 0, 'milliseconds': 421, 'unknown24': 0}},
165
166         1: {'q': {'comment': 'cheepy birds', 'level': 1, 'flags': 8388608, 'name': 'q', 'description': 'q,HP LaserJet 4,'}, 'p': {'comment': "I'm a teapot!", 'level': 1, 'flags': 8388608, 'name': 'p', 'description': 'p,HP LaserJet 4,Canberra office'}, 'magpie': {'comment': '', 'level': 1, 'flags': 8388608, 'name': 'magpie', 'description': 'magpie,Generic / Text Only,'}}
167         }
168
169     def runTest(self):
170         for i in (0, 1):
171             info = spoolss.enumprinters(
172                 "\\\\%s" % self.server["hostname"], level = i)
173             try:
174                 stf.dict_check(self.sample_info[i], info)
175             except ValueError, msg:
176                 raise "info%d: %s" % (i, msg)
177
178 class EnumPrintersArg(ArgTestServer):
179     def runTestArg(self, unc):
180         spoolss.enumprinters(unc)
181
182 class EnumPrintersCred(CredentialTest):
183     """Test opening printer with good and bad credentials."""
184     def runTestArg(self, creds):
185         spoolss.enumprinters(
186             "\\\\%s" % self.server["hostname"], creds = creds)
187
188 class EnumPrinterdrivers(PrintServerTest):
189
190     sample_info = {
191         1: {'Okipage 10ex (PCL5E) : STANDARD': {'name': 'Okipage 10ex (PCL5E) : STANDARD', 'level': 1}, 'Generic / Text Only': {'name': 'Generic / Text Only', 'level': 1}, 'Brother HL-1030 series': {'name': 'Brother HL-1030 series', 'level': 1}, 'Brother HL-1240 series': {'name': 'Brother HL-1240 series', 'level': 1}, 'HP DeskJet 1220C Printer': {'name': 'HP DeskJet 1220C Printer', 'level': 1}, 'HP LaserJet 4100 PCL 6': {'name': 'HP LaserJet 4100 PCL 6', 'level': 1}, 'HP LaserJet 4': {'name': 'HP LaserJet 4', 'level': 1}},
192         2: {'Okipage 10ex (PCL5E) : STANDARD': {'version': 2, 'config_file': '\\\\WIN2KDC1\\print$\\W32X86\\2\\RASDDUI.DLL', 'name': 'Okipage 10ex (PCL5E) : STANDARD', 'driver_path': '\\\\WIN2KDC1\\print$\\W32X86\\2\\RASDD.DLL', 'data_file': '\\\\WIN2KDC1\\print$\\W32X86\\2\\OKIPAGE.DLL', 'level': 2, 'architecture': 'Windows NT x86'}, 'Generic / Text Only': {'version': 3, 'config_file': '\\\\WIN2KDC1\\print$\\W32X86\\3\\UNIDRVUI.DLL', 'name': 'Generic / Text Only', 'driver_path': '\\\\WIN2KDC1\\print$\\W32X86\\3\\UNIDRV.DLL', 'data_file': '\\\\WIN2KDC1\\print$\\W32X86\\3\\TTY.GPD', 'level': 2, 'architecture': 'Windows NT x86'}, 'Brother HL-1030 series': {'version': 3, 'config_file': '\\\\WIN2KDC1\\print$\\W32X86\\3\\BRUHL99A.DLL', 'name': 'Brother HL-1030 series', 'driver_path': '\\\\WIN2KDC1\\print$\\W32X86\\3\\BROHL99A.DLL', 'data_file': '\\\\WIN2KDC1\\print$\\W32X86\\3\\BROHL103.PPD', 'level': 2, 'architecture': 'Windows NT x86'}, 'Brother HL-1240 series': {'version': 3, 'config_file': '\\\\WIN2KDC1\\print$\\W32X86\\3\\BRUHL99A.DLL', 'name': 'Brother HL-1240 series', 'driver_path': '\\\\WIN2KDC1\\print$\\W32X86\\3\\BROHL99A.DLL', 'data_file': '\\\\WIN2KDC1\\print$\\W32X86\\3\\BROHL124.PPD', 'level': 2, 'architecture': 'Windows NT x86'}, 'HP DeskJet 1220C Printer': {'version': 3, 'config_file': '\\\\WIN2KDC1\\print$\\W32X86\\3\\HPW8KMD.DLL', 'name': 'HP DeskJet 1220C Printer', 'driver_path': '\\\\WIN2KDC1\\print$\\W32X86\\3\\HPW8KMD.DLL', 'data_file': '\\\\WIN2KDC1\\print$\\W32X86\\3\\HPW8KMD.DLL', 'level': 2, 'architecture': 'Windows NT x86'}, 'HP LaserJet 4100 PCL 6': {'version': 3, 'config_file': '\\\\WIN2KDC1\\print$\\W32X86\\3\\HPBF042E.DLL', 'name': 'HP LaserJet 4100 PCL 6', 'driver_path': '\\\\WIN2KDC1\\print$\\W32X86\\3\\HPBF042G.DLL', 'data_file': '\\\\WIN2KDC1\\print$\\W32X86\\3\\HPBF042I.PMD', 'level': 2, 'architecture': 'Windows NT x86'}, 'HP LaserJet 4': {'version': 2, 'config_file': '\\\\WIN2KDC1\\print$\\W32X86\\2\\hpblff0.dll', 'name': 'HP LaserJet 4', 'driver_path': '\\\\WIN2KDC1\\print$\\W32X86\\2\\hpblff2.dll', 'data_file': '\\\\WIN2KDC1\\print$\\W32X86\\2\\hpblff39.pmd', 'level': 2, 'architecture': 'Windows NT x86'}}
193         }
194
195     def runTest(self):
196         for i in (1, 2):
197             info = spoolss.enumprinterdrivers(
198                 "\\\\%s" % self.server["hostname"], level = i)
199             try:
200                 if not self.sample_info.has_key(i):
201                     self.log("%s" % info)
202                     self.fail()
203                 stf.dict_check(self.sample_info[i], info)
204             except ValueError, msg:
205                 raise "info%d: %s" % (i, msg)
206
207 class EnumPrinterdriversArg(ArgTestServer):
208     def runTestArg(self, unc):
209         spoolss.enumprinterdrivers(unc)
210
211 class EnumPrinterdriversCred(CredentialTest):
212     """Test opening printer with good and bad credentials."""
213     def runTestArg(self, creds):
214         spoolss.enumprinterdrivers(
215             "\\\\%s" % self.server["hostname"], creds = creds)
216
217 def usage():
218     print "Usage: spoolss.py [options] [test1[,test2...]]"
219     print "\t -v/--verbose     Display debugging information"
220     print "\t -l/--list-tests  List available tests"
221     print
222     print "A list of comma separated test names or regular expressions"
223     print "can be used to filter the tests performed."
224             
225 def test_match(subtest_list, test_name):
226     """Return true if a test matches a comma separated list of regular
227     expression of test names."""
228     # re.match does an implicit ^ at the start of the pattern.
229     # Explicitly anchor to end to avoid matching substrings.
230     for s in string.split(subtest_list, ","):
231         if re.match(s + "$", test_name):
232             return 1
233     return 0
234            
235 if __name__ == "__main__":
236     import os, sys, string
237     import getopt
238     
239     try:
240         opts, args = getopt.getopt(sys.argv[1:], "vl", \
241                                    ["verbose", "list-tests"])
242     except getopt.GetoptError:
243         usage()
244         sys.exit(0)
245
246     verbose = 0
247     list_tests = 0
248
249     for opt, arg in opts:
250         if opt in ("-v", "--verbose"):
251             verbose = 1
252         if opt in ("-l", "--list-tests"):
253             list_tests = 1
254
255     if len(args) > 1:
256         usage()
257         sys.exit(0)
258
259     test_list = [
260         OpenPrinterArg,
261         OpenPrinterCred,
262         ClosePrinter,
263         ClosePrinterServer,
264         GetPrinterInfo,
265         EnumPrinters,
266         EnumPrintersCred,
267         EnumPrintersArg,
268         EnumPrinterdrivers,
269         EnumPrinterdriversCred,
270         EnumPrinterdriversArg,
271         ]
272
273     if len(args):
274         t = []
275         for test in test_list:
276             if test_match(args[0], test.__name__):
277                 t.append(test)
278         test_list = t
279
280     if os.environ.has_key("SAMBA_DEBUG"):
281         spoolss.setup_logging(interactive = 1)
282         spoolss.set_debuglevel(10)
283
284     if list_tests:
285         for test in test_list:
286             print test.__name__
287     else:
288         comfychair.runtests(test_list, verbose = verbose)