#include <cups/string-private.h>
#include <cups/cups.h>
#include <cups/language.h>
#include <cups/debug-private.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/wait.h>
static int do_test(const char *server, int port,
http_encryption_t encryption, int requests,
const char *opstring, int verbose);
static void usage(void) __attribute__((noreturn));
int
main(int argc,
char *argv[])
{
int i;
char *server,
*ptr;
int port;
http_encryption_t encryption;
int requests;
int children;
int good_children;
int pid;
int status;
time_t start,
end;
double elapsed;
int verbose;
const char *opstring;
requests = 100;
children = 5;
server = (char *)cupsServer();
port = ippPort();
encryption = HTTP_ENCRYPT_IF_REQUESTED;
verbose = 0;
opstring = NULL;
for (i = 1; i < argc; i ++)
if (argv[i][0] == '-')
{
for (ptr = argv[i] + 1; *ptr; ptr ++)
switch (*ptr)
{
case 'E' :
encryption = HTTP_ENCRYPT_REQUIRED;
break;
case 'c' :
i ++;
if (i >= argc)
usage();
children = atoi(argv[i]);
break;
case 'o' :
i ++;
if (i >= argc)
usage();
opstring = argv[i];
break;
case 'r' :
i ++;
if (i >= argc)
usage();
requests = atoi(argv[i]);
break;
case 'v' :
verbose ++;
break;
default :
usage();
break;
}
}
else
{
server = argv[i];
if (server[0] != '/' && (ptr = strrchr(server, ':')) != NULL)
{
*ptr++ = '\0';
port = atoi(ptr);
}
}
if (children > 0)
{
printf("testspeed: Simulating %d clients with %d requests to %s with "
"%sencryption...\n", children, requests, server,
encryption == HTTP_ENCRYPT_IF_REQUESTED ? "no " : "");
}
start = time(NULL);
if (children < 1)
return (do_test(server, port, encryption, requests, opstring, verbose));
else if (children == 1)
good_children = do_test(server, port, encryption, requests, opstring,
verbose) ? 0 : 1;
else
{
char options[255],
reqstr[255],
serverstr[255];
snprintf(reqstr, sizeof(reqstr), "%d", requests);
if (port == 631 || server[0] == '/')
strlcpy(serverstr, server, sizeof(serverstr));
else
snprintf(serverstr, sizeof(serverstr), "%s:%d", server, port);
strlcpy(options, "-cr", sizeof(options));
if (encryption == HTTP_ENCRYPT_REQUIRED)
strlcat(options, "E", sizeof(options));
if (verbose)
strlcat(options, "v", sizeof(options));
for (i = 0; i < children; i ++)
{
fflush(stdout);
if ((pid = fork()) == 0)
{
if (opstring)
execlp(argv[0], argv[0], options, "0", reqstr, "-o", opstring,
serverstr, (char *)NULL);
else
execlp(argv[0], argv[0], options, "0", reqstr, serverstr, (char *)NULL);
exit(errno);
}
else if (pid < 0)
{
printf("testspeed: Fork failed: %s\n", strerror(errno));
break;
}
else
printf("testspeed: Started child %d...\n", pid);
}
puts("testspeed: Waiting for children to finish...");
for (good_children = 0;;)
{
pid = wait(&status);
if (pid < 0 && errno != EINTR)
break;
printf("testspeed: Ended child %d (%d)...\n", pid, status / 256);
if (!status)
good_children ++;
}
}
if (good_children > 0)
{
end = time(NULL);
elapsed = end - start;
i = good_children * requests;
printf("testspeed: %dx%d=%d requests in %.1fs (%.3fs/r, %.1fr/s)\n",
good_children, requests, i, elapsed, elapsed / i, i / elapsed);
}
return (0);
}
static int
do_test(const char *server,
int port,
http_encryption_t encryption,
int requests,
const char *opstring,
int verbose)
{
int i;
http_t *http;
ipp_t *request;
struct timeval start,
end;
double reqtime,
elapsed;
int op;
static ipp_op_t ops[5] =
{
IPP_PRINT_JOB,
CUPS_GET_DEFAULT,
CUPS_GET_PRINTERS,
CUPS_GET_CLASSES,
IPP_GET_JOBS
};
if ((http = httpConnectEncrypt(server, port, encryption)) == NULL)
{
printf("testspeed(%d): unable to connect to server - %s\n", (int)getpid(),
strerror(errno));
return (1);
}
for (elapsed = 0.0, i = 0; i < requests; i ++)
{
if (opstring)
op = ippOpValue(opstring);
else
op = ops[i % (int)(sizeof(ops) / sizeof(ops[0]))];
request = ippNewRequest(op);
gettimeofday(&start, NULL);
if (verbose)
printf("testspeed(%d): %.6f %s ", (int)getpid(), elapsed,
ippOpString(op));
switch (op)
{
case IPP_GET_JOBS :
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
NULL, "ipp://localhost/printers/");
default :
ippDelete(cupsDoRequest(http, request, "/"));
break;
case IPP_PRINT_JOB :
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
NULL, "ipp://localhost/printers/test");
ippDelete(cupsDoFileRequest(http, request, "/printers/test",
"../data/testprint.ps"));
break;
}
gettimeofday(&end, NULL);
reqtime = (end.tv_sec - start.tv_sec) +
0.000001 * (end.tv_usec - start.tv_usec);
elapsed += reqtime;
switch (cupsLastError())
{
case IPP_OK :
case IPP_NOT_FOUND :
if (verbose)
{
printf("succeeded: %s (%.6f)\n", cupsLastErrorString(), reqtime);
fflush(stdout);
}
break;
default :
if (!verbose)
printf("testspeed(%d): %s ", (int)getpid(),
ippOpString(ops[i & 3]));
printf("failed: %s\n", cupsLastErrorString());
httpClose(http);
return (1);
}
}
httpClose(http);
printf("testspeed(%d): %d requests in %.1fs (%.3fs/r, %.1fr/s)\n",
(int)getpid(), i, elapsed, elapsed / i, i / elapsed);
return (0);
}
static void
usage(void)
{
puts("Usage: testspeed [-c children] [-h] [-o operation] [-r requests] [-v] "
"[-E] hostname[:port]");
exit(0);
}