800840c384317435c3ba91ed40bb0aff6d32d0d0
[mat/samba.git] / source4 / torture / rap / printing.c
1 /*
2    Unix SMB/CIFS implementation.
3    test suite for SMB printing operations
4
5    Copyright (C) Guenther Deschner 2010
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "libcli/raw/libcliraw.h"
23 #include "libcli/libcli.h"
24 #include "torture/torture.h"
25 #include "torture/util.h"
26 #include "system/filesys.h"
27
28 #include "torture/smbtorture.h"
29 #include "torture/util.h"
30 #include "libcli/rap/rap.h"
31 #include "torture/rap/proto.h"
32 #include "param/param.h"
33
34 /* TODO:
35
36  printing half the file,
37  finding job
38  delete job
39  try writing 2nd half
40
41  SMBsplretq
42
43 */
44
45 #define TORTURE_PRINT_FILE "torture_print_file"
46
47 static bool print_printjob(struct torture_context *tctx,
48                            struct smbcli_tree *tree)
49 {
50         int fnum;
51         DATA_BLOB data;
52         ssize_t size_written;
53         const char *str;
54
55         torture_comment(tctx, "creating printjob %s\n", TORTURE_PRINT_FILE);
56
57         fnum = smbcli_open(tree, TORTURE_PRINT_FILE, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
58         if (fnum == -1) {
59                 torture_fail(tctx, "failed to open file");
60         }
61
62         str = talloc_asprintf(tctx, "TortureTestPage: %d\nData\n",0);
63
64         data = data_blob_string_const(str);
65
66         size_written = smbcli_write(tree, fnum, 0, data.data, 0, data.length);
67         if (size_written != data.length) {
68                 torture_fail(tctx, "failed to write file");
69         }
70
71         torture_assert_ntstatus_ok(tctx,
72                 smbcli_close(tree, fnum),
73                 "failed to close file");
74
75         return true;
76 }
77
78 static bool test_raw_print(struct torture_context *tctx,
79                            struct smbcli_state *cli)
80 {
81         return print_printjob(tctx, cli->tree);
82 }
83
84 static bool test_netprintqenum(struct torture_context *tctx,
85                                struct smbcli_state *cli)
86 {
87         struct rap_NetPrintQEnum r;
88         int i, q;
89         uint16_t levels[] = { 0, 1, 2, 3, 4, 5 };
90
91         for (i=0; i < ARRAY_SIZE(levels); i++) {
92
93                 r.in.level = levels[i];
94                 r.in.bufsize = 8192;
95
96                 torture_comment(tctx,
97                         "Testing rap_NetPrintQEnum level %d\n", r.in.level);
98
99                 torture_assert_ntstatus_ok(tctx,
100                         smbcli_rap_netprintqenum(cli->tree, tctx, &r),
101                         "smbcli_rap_netprintqenum failed");
102                 torture_assert_werr_ok(tctx, W_ERROR(r.out.status),
103                         "failed to enum printq");
104
105                 for (q=0; q<r.out.count; q++) {
106                         switch (r.in.level) {
107                         case 0:
108                                 printf("%s\n", r.out.info[q].info0.PrintQName);
109                                 break;
110                         }
111                 }
112         }
113
114         return true;
115 }
116
117 static bool test_netprintqgetinfo(struct torture_context *tctx,
118                                   struct smbcli_state *cli)
119 {
120         struct rap_NetPrintQGetInfo r;
121         struct rap_NetPrintQEnum r_enum;
122         int i, p;
123         uint16_t levels[] = { 0, 1, 2, 3, 4, 5 };
124
125         r.in.level = 0;
126         r.in.bufsize = 0;
127         r.in.PrintQueueName = "";
128
129         torture_assert_ntstatus_ok(tctx,
130                 smbcli_rap_netprintqgetinfo(cli->tree, tctx, &r),
131                 "smbcli_rap_netprintqgetinfo failed");
132
133         r_enum.in.level = 5;
134         r_enum.in.bufsize = 8192;
135
136         torture_assert_ntstatus_ok(tctx,
137                 smbcli_rap_netprintqenum(cli->tree, tctx, &r_enum),
138                 "failed to enum printq");
139         torture_assert_werr_ok(tctx, W_ERROR(r_enum.out.status),
140                 "failed to enum printq");
141
142         for (p=0; p < r_enum.out.count; p++) {
143
144                 for (i=0; i < ARRAY_SIZE(levels); i++) {
145
146                         r.in.level = levels[i];
147                         r.in.bufsize = 8192;
148                         r.in.PrintQueueName = r_enum.out.info[p].info5.PrintQueueName;
149
150                         torture_comment(tctx, "Testing rap_NetPrintQGetInfo(%s) level %d\n",
151                                 r.in.PrintQueueName, r.in.level);
152
153                         torture_assert_ntstatus_ok(tctx,
154                                 smbcli_rap_netprintqgetinfo(cli->tree, tctx, &r),
155                                 "smbcli_rap_netprintqgetinfo failed");
156
157                         switch (r.in.level) {
158                         case 0:
159                                 printf("%s\n", r.out.info.info0.PrintQName);
160                                 break;
161                         }
162                 }
163         }
164
165         return true;
166 }
167
168 static bool test_netprintjob_pause(struct torture_context *tctx,
169                                    struct smbcli_state *cli,
170                                    uint16_t job_id)
171 {
172         struct rap_NetPrintJobPause r;
173
174         r.in.JobID = job_id;
175
176         torture_comment(tctx, "Testing rap_NetPrintJobPause(%d)\n", r.in.JobID);
177
178         torture_assert_ntstatus_ok(tctx,
179                 smbcli_rap_netprintjobpause(cli->tree, tctx, &r),
180                 "smbcli_rap_netprintjobpause failed");
181
182         return true;
183 }
184
185 static bool test_netprintjob_continue(struct torture_context *tctx,
186                                       struct smbcli_state *cli,
187                                       uint16_t job_id)
188 {
189         struct rap_NetPrintJobContinue r;
190
191         r.in.JobID = job_id;
192
193         torture_comment(tctx, "Testing rap_NetPrintJobContinue(%d)\n", r.in.JobID);
194
195         torture_assert_ntstatus_ok(tctx,
196                 smbcli_rap_netprintjobcontinue(cli->tree, tctx, &r),
197                 "smbcli_rap_netprintjobcontinue failed");
198
199         return true;
200 }
201
202 static bool test_netprintjob_delete(struct torture_context *tctx,
203                                     struct smbcli_state *cli,
204                                     uint16_t job_id)
205 {
206         struct rap_NetPrintJobDelete r;
207
208         r.in.JobID = job_id;
209
210         torture_comment(tctx, "Testing rap_NetPrintJobDelete(%d)\n", r.in.JobID);
211
212         torture_assert_ntstatus_ok(tctx,
213                 smbcli_rap_netprintjobdelete(cli->tree, tctx, &r),
214                 "smbcli_rap_netprintjobdelete failed");
215
216         return true;
217 }
218
219 static bool test_netprintjob(struct torture_context *tctx,
220                              struct smbcli_state *cli)
221 {
222         uint16_t job_id = 400;
223
224         torture_assert(tctx,
225                 test_netprintjob_pause(tctx, cli, job_id),
226                 "failed to pause job");
227         torture_assert(tctx,
228                 test_netprintjob_continue(tctx, cli, job_id),
229                 "failed to continue job");
230         torture_assert(tctx,
231                 test_netprintjob_delete(tctx, cli, job_id),
232                 "failed to delete job");
233
234         return true;
235 }
236
237 static bool test_netprintq_pause(struct torture_context *tctx,
238                                  struct smbcli_state *cli,
239                                  const char *PrintQueueName)
240 {
241         struct rap_NetPrintQueuePause r;
242
243         r.in.PrintQueueName = PrintQueueName;
244
245         torture_comment(tctx, "Testing rap_NetPrintQueuePause(%s)\n", r.in.PrintQueueName);
246
247         torture_assert_ntstatus_ok(tctx,
248                 smbcli_rap_netprintqueuepause(cli->tree, tctx, &r),
249                 "smbcli_rap_netprintqueuepause failed");
250         torture_assert_werr_ok(tctx, W_ERROR(r.out.status),
251                 "smbcli_rap_netprintqueuepause failed");
252
253         return true;
254 }
255
256 static bool test_netprintq_resume(struct torture_context *tctx,
257                                   struct smbcli_state *cli,
258                                   const char *PrintQueueName)
259 {
260         struct rap_NetPrintQueueResume r;
261
262         r.in.PrintQueueName = PrintQueueName;
263
264         torture_comment(tctx, "Testing rap_NetPrintQueueResume(%s)\n", r.in.PrintQueueName);
265
266         torture_assert_ntstatus_ok(tctx,
267                 smbcli_rap_netprintqueueresume(cli->tree, tctx, &r),
268                 "smbcli_rap_netprintqueueresume failed");
269         torture_assert_werr_ok(tctx, W_ERROR(r.out.status),
270                 "smbcli_rap_netprintqueueresume failed");
271
272         return true;
273 }
274
275 static bool test_netprintq(struct torture_context *tctx,
276                            struct smbcli_state *cli)
277 {
278         struct rap_NetPrintQEnum r;
279         int i;
280
281         r.in.level = 5;
282         r.in.bufsize = 8192;
283
284         torture_assert_ntstatus_ok(tctx,
285                 smbcli_rap_netprintqenum(cli->tree, tctx, &r),
286                 "failed to enum printq");
287         torture_assert_werr_ok(tctx, W_ERROR(r.out.status),
288                 "failed to enum printq");
289
290         for (i=0; i < r.out.count; i++) {
291
292                 const char *printqname = r.out.info[i].info5.PrintQueueName;
293
294                 torture_assert(tctx,
295                         test_netprintq_pause(tctx, cli, printqname),
296                         "failed to pause print queue");
297
298                 torture_assert(tctx,
299                         test_netprintq_resume(tctx, cli, printqname),
300                         "failed to resume print queue");
301         }
302
303         return true;
304 }
305
306 static bool test_netprintjobenum_args(struct torture_context *tctx,
307                                       struct smbcli_state *cli,
308                                       const char *PrintQueueName,
309                                       uint16_t level,
310                                       uint16_t *count_p,
311                                       union rap_printj_info **info_p)
312 {
313         struct rap_NetPrintJobEnum r;
314
315         r.in.PrintQueueName = PrintQueueName;
316         r.in.bufsize = 8192;
317         r.in.level = level;
318
319         torture_comment(tctx,
320                 "Testing rap_NetPrintJobEnum(%s) level %d\n", r.in.PrintQueueName, r.in.level);
321
322         torture_assert_ntstatus_ok(tctx,
323                 smbcli_rap_netprintjobenum(cli->tree, tctx, &r),
324                 "smbcli_rap_netprintjobenum failed");
325
326         if (count_p) {
327                 *count_p = r.out.count;
328         }
329         if (info_p) {
330                 *info_p = r.out.info;
331         }
332
333         return true;
334 }
335
336 static bool test_netprintjobenum_one(struct torture_context *tctx,
337                                      struct smbcli_state *cli,
338                                      const char *PrintQueueName)
339 {
340         struct rap_NetPrintJobEnum r;
341         int i;
342         uint16_t levels[] = { 0, 1, 2 };
343
344         r.in.PrintQueueName = PrintQueueName;
345         r.in.bufsize = 8192;
346
347         for (i=0; i < ARRAY_SIZE(levels); i++) {
348
349                 r.in.level = levels[i];
350
351                 torture_comment(tctx,
352                         "Testing rap_NetPrintJobEnum(%s) level %d\n", r.in.PrintQueueName, r.in.level);
353
354                 torture_assert_ntstatus_ok(tctx,
355                         smbcli_rap_netprintjobenum(cli->tree, tctx, &r),
356                         "smbcli_rap_netprintjobenum failed");
357         }
358
359         return true;
360 }
361
362 static bool test_netprintjobgetinfo_byid(struct torture_context *tctx,
363                                          struct smbcli_state *cli,
364                                          uint16_t JobID)
365 {
366         struct rap_NetPrintJobGetInfo r;
367         uint16_t levels[] = { 0, 1, 2 };
368         int i;
369
370         r.in.JobID = JobID;
371         r.in.bufsize = 8192;
372
373         for (i=0; i < ARRAY_SIZE(levels); i++) {
374
375                 r.in.level = levels[i];
376
377                 torture_comment(tctx, "Testing rap_NetPrintJobGetInfo(%d) level %d\n", r.in.JobID, r.in.level);
378
379                 torture_assert_ntstatus_ok(tctx,
380                         smbcli_rap_netprintjobgetinfo(cli->tree, tctx, &r),
381                         "smbcli_rap_netprintjobgetinfo failed");
382         }
383
384         return true;
385 }
386
387 static bool test_netprintjobsetinfo_byid(struct torture_context *tctx,
388                                          struct smbcli_state *cli,
389                                          uint16_t JobID)
390 {
391         struct rap_NetPrintJobSetInfo r;
392         uint16_t levels[] = { 0, 1, 2 };
393         int i;
394         const char *comment = "tortured by samba";
395
396         r.in.JobID = JobID;
397         r.in.bufsize = strlen(comment);
398         r.in.ParamNum = RAP_PARAM_JOBCOMMENT;
399         r.in.Param.string = comment;
400
401         for (i=0; i < ARRAY_SIZE(levels); i++) {
402
403                 r.in.level = levels[i];
404
405                 torture_comment(tctx, "Testing rap_NetPrintJobSetInfo(%d) level %d\n", r.in.JobID, r.in.level);
406
407                 torture_assert_ntstatus_ok(tctx,
408                         smbcli_rap_netprintjobsetinfo(cli->tree, tctx, &r),
409                         "smbcli_rap_netprintjobsetinfo failed");
410         }
411
412         return true;
413 }
414
415
416 static bool test_netprintjobgetinfo_byqueue(struct torture_context *tctx,
417                                             struct smbcli_state *cli,
418                                             const char *PrintQueueName)
419 {
420         struct rap_NetPrintJobEnum r;
421         int i;
422
423         r.in.PrintQueueName = PrintQueueName;
424         r.in.bufsize = 8192;
425         r.in.level = 0;
426
427         torture_assert_ntstatus_ok(tctx,
428                 smbcli_rap_netprintjobenum(cli->tree, tctx, &r),
429                 "failed to enumerate jobs");
430
431         for (i=0; i < r.out.count; i++) {
432
433                 torture_assert(tctx,
434                         test_netprintjobgetinfo_byid(tctx, cli, r.out.info[i].info0.JobID),
435                         "failed to get job info");
436         }
437
438         return true;
439 }
440
441 static bool test_netprintjobsetinfo_byqueue(struct torture_context *tctx,
442                                             struct smbcli_state *cli,
443                                             const char *PrintQueueName)
444 {
445         struct rap_NetPrintJobEnum r;
446         int i;
447
448         r.in.PrintQueueName = PrintQueueName;
449         r.in.bufsize = 8192;
450         r.in.level = 0;
451
452         torture_assert_ntstatus_ok(tctx,
453                 smbcli_rap_netprintjobenum(cli->tree, tctx, &r),
454                 "failed to enumerate jobs");
455
456         for (i=0; i < r.out.count; i++) {
457
458                 torture_assert(tctx,
459                         test_netprintjobsetinfo_byid(tctx, cli, r.out.info[i].info0.JobID),
460                         "failed to set job info");
461         }
462
463         return true;
464 }
465
466 static bool test_netprintjobenum(struct torture_context *tctx,
467                                  struct smbcli_state *cli)
468 {
469         struct rap_NetPrintQEnum r;
470         int i;
471
472         r.in.level = 5;
473         r.in.bufsize = 8192;
474
475         torture_assert_ntstatus_ok(tctx,
476                 smbcli_rap_netprintqenum(cli->tree, tctx, &r),
477                 "failed to enum printq");
478         torture_assert_werr_ok(tctx, W_ERROR(r.out.status),
479                 "failed to enum printq");
480
481         for (i=0; i < r.out.count; i++) {
482
483                 const char *printqname = r.out.info[i].info5.PrintQueueName;
484
485                 torture_assert(tctx,
486                         test_netprintjobenum_one(tctx, cli, printqname),
487                         "failed to enumerate printjobs on print queue");
488         }
489
490         return true;
491 }
492
493 static bool test_netprintjobgetinfo(struct torture_context *tctx,
494                                     struct smbcli_state *cli)
495 {
496         struct rap_NetPrintQEnum r;
497         int i;
498
499         r.in.level = 5;
500         r.in.bufsize = 8192;
501
502         torture_assert_ntstatus_ok(tctx,
503                 smbcli_rap_netprintqenum(cli->tree, tctx, &r),
504                 "failed to enum printq");
505         torture_assert_werr_ok(tctx, W_ERROR(r.out.status),
506                 "failed to enum printq");
507
508         for (i=0; i < r.out.count; i++) {
509
510                 const char *printqname = r.out.info[i].info5.PrintQueueName;
511
512                 torture_assert(tctx,
513                         test_netprintjobgetinfo_byqueue(tctx, cli, printqname),
514                         "failed to enumerate printjobs on print queue");
515         }
516
517         return true;
518 }
519
520 static bool test_netprintjobsetinfo(struct torture_context *tctx,
521                                     struct smbcli_state *cli)
522 {
523         struct rap_NetPrintQEnum r;
524         int i;
525
526         r.in.level = 5;
527         r.in.bufsize = 8192;
528
529         torture_assert_ntstatus_ok(tctx,
530                 smbcli_rap_netprintqenum(cli->tree, tctx, &r),
531                 "failed to enum printq");
532         torture_assert_werr_ok(tctx, W_ERROR(r.out.status),
533                 "failed to enum printq");
534
535         for (i=0; i < r.out.count; i++) {
536
537                 const char *printqname = r.out.info[i].info5.PrintQueueName;
538
539                 torture_assert(tctx,
540                         test_netprintjobsetinfo_byqueue(tctx, cli, printqname),
541                         "failed to set printjobs on print queue");
542         }
543
544         return true;
545 }
546
547 static bool test_netprintdestenum(struct torture_context *tctx,
548                                   struct smbcli_state *cli)
549 {
550         struct rap_NetPrintDestEnum r;
551         int i;
552         uint16_t levels[] = { 0, 1, 2, 3 };
553
554         for (i=0; i < ARRAY_SIZE(levels); i++) {
555
556                 r.in.level = levels[i];
557                 r.in.bufsize = 8192;
558
559                 torture_comment(tctx,
560                         "Testing rap_NetPrintDestEnum level %d\n", r.in.level);
561
562                 torture_assert_ntstatus_ok(tctx,
563                         smbcli_rap_netprintdestenum(cli->tree, tctx, &r),
564                         "smbcli_rap_netprintdestenum failed");
565         }
566
567         return true;
568 }
569
570 static bool test_netprintdestgetinfo_bydest(struct torture_context *tctx,
571                                             struct smbcli_state *cli,
572                                             const char *PrintDestName)
573 {
574         struct rap_NetPrintDestGetInfo r;
575         int i;
576         uint16_t levels[] = { 0, 1, 2, 3 };
577
578         for (i=0; i < ARRAY_SIZE(levels); i++) {
579
580                 r.in.PrintDestName = PrintDestName;
581                 r.in.level = levels[i];
582                 r.in.bufsize = 8192;
583
584                 torture_comment(tctx,
585                         "Testing rap_NetPrintDestGetInfo(%s) level %d\n", r.in.PrintDestName, r.in.level);
586
587                 torture_assert_ntstatus_ok(tctx,
588                         smbcli_rap_netprintdestgetinfo(cli->tree, tctx, &r),
589                         "smbcli_rap_netprintdestgetinfo failed");
590         }
591
592         return true;
593 }
594
595
596 static bool test_netprintdestgetinfo(struct torture_context *tctx,
597                                      struct smbcli_state *cli)
598 {
599         struct rap_NetPrintDestEnum r;
600         int i;
601
602         r.in.level = 2;
603         r.in.bufsize = 8192;
604
605         torture_comment(tctx,
606                 "Testing rap_NetPrintDestEnum level %d\n", r.in.level);
607
608         torture_assert_ntstatus_ok(tctx,
609                 smbcli_rap_netprintdestenum(cli->tree, tctx, &r),
610                 "smbcli_rap_netprintdestenum failed");
611
612         for (i=0; i < r.out.count; i++) {
613
614                 torture_assert(tctx,
615                         test_netprintdestgetinfo_bydest(tctx, cli, r.out.info[i].info2.PrinterName),
616                         "failed to get printdest info");
617
618         }
619
620         return true;
621 }
622
623 static bool test_rap_print(struct torture_context *tctx,
624                            struct smbcli_state *cli)
625 {
626         struct rap_NetPrintQEnum r;
627         int i;
628
629         r.in.level = 5;
630         r.in.bufsize = 8192;
631
632         torture_assert_ntstatus_ok(tctx,
633                 smbcli_rap_netprintqenum(cli->tree, tctx, &r),
634                 "failed to enum printq");
635         torture_assert_werr_ok(tctx, W_ERROR(r.out.status),
636                 "failed to enum printq");
637
638         for (i=0; i < r.out.count; i++) {
639
640                 const char *printqname = r.out.info[i].info5.PrintQueueName;
641                 struct smbcli_tree *res_queue = NULL;
642                 uint16_t num_jobs;
643                 union rap_printj_info *job_info;
644                 int j;
645
646                 torture_assert(tctx,
647                         test_netprintq_pause(tctx, cli, printqname),
648                         "failed to set printjobs on print queue");
649
650                 torture_assert_ntstatus_ok(tctx,
651                         torture_second_tcon(tctx, cli->session, printqname, &res_queue),
652                         "failed to open 2nd connection");
653
654                 torture_assert(tctx,
655                         print_printjob(tctx, res_queue),
656                         "failed to print job on 2nd connection");
657
658                 talloc_free(res_queue);
659
660                 torture_assert(tctx,
661                         test_netprintjobenum_args(tctx, cli, printqname, 1,
662                         &num_jobs, &job_info),
663                         "failed to enum printjobs on print queue");
664
665                 for (j=0; j < num_jobs; j++) {
666
667                         uint16_t job_id = job_info[j].info1.JobID;
668
669                         torture_assert(tctx,
670                                 test_netprintjobgetinfo_byid(tctx, cli, job_id),
671                                 "failed to getinfo on new printjob");
672
673                         torture_assert(tctx,
674                                 test_netprintjob_delete(tctx, cli, job_id),
675                                 "failed to delete job");
676                 }
677
678                 torture_assert(tctx,
679                         test_netprintq_resume(tctx, cli, printqname),
680                         "failed to resume print queue");
681
682         }
683
684         return true;
685 }
686
687 struct torture_suite *torture_rap_printing(TALLOC_CTX *mem_ctx)
688 {
689         struct torture_suite *suite = torture_suite_create(mem_ctx, "printing");
690
691         torture_suite_add_1smb_test(suite, "raw_print", test_raw_print);
692         torture_suite_add_1smb_test(suite, "rap_print", test_rap_print);
693         torture_suite_add_1smb_test(suite, "rap_printq_enum", test_netprintqenum);
694         torture_suite_add_1smb_test(suite, "rap_printq_getinfo", test_netprintqgetinfo);
695         torture_suite_add_1smb_test(suite, "rap_printq", test_netprintq);
696         torture_suite_add_1smb_test(suite, "rap_printjob_enum", test_netprintjobenum);
697         torture_suite_add_1smb_test(suite, "rap_printjob_getinfo", test_netprintjobgetinfo);
698         torture_suite_add_1smb_test(suite, "rap_printjob_setinfo", test_netprintjobsetinfo);
699         torture_suite_add_1smb_test(suite, "rap_printjob", test_netprintjob);
700         torture_suite_add_1smb_test(suite, "rap_printdest_enum", test_netprintdestenum);
701         torture_suite_add_1smb_test(suite, "rap_printdest_getinfo", test_netprintdestgetinfo);
702
703         return suite;
704 }