#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <cups/cups.h>
#include <cups/language.h>
#include <cups/debug.h>
#include <errno.h>
int do_test(const char *server, http_encryption_t encryption,
int requests);
void usage(void);
int
main(int argc,
char *argv[])
{
int i;
const char *server;
http_encryption_t encryption;
int requests;
int children;
int pid;
int status;
time_t start,
end;
double elapsed;
requests = 100;
children = 5;
server = cupsServer();
encryption = HTTP_ENCRYPT_IF_REQUESTED;
for (i = 1; i < argc; i ++)
if (!strcmp(argv[i], "-c"))
{
i ++;
if (i >= argc)
usage();
children = atoi(argv[i]);
}
else if (!strcmp(argv[i], "-r"))
{
i ++;
if (i >= argc)
usage();
requests = atoi(argv[i]);
}
else if (!strcmp(argv[i], "-E"))
encryption = HTTP_ENCRYPT_REQUIRED;
else if (argv[i][0] == '-')
usage();
else
server = argv[i];
printf("testspeed: Simulating %d clients with %d requests to %s with %s encryption...\n",
children, requests, server,
encryption == HTTP_ENCRYPT_IF_REQUESTED ? "no" : "");
start = time(NULL);
for (i = 0; i < children; i ++)
if ((pid = fork()) == 0)
{
exit(do_test(server, encryption, requests));
}
else if (pid < 0)
{
perror("fork failed");
break;
}
else
printf("testspeed(%d): Started...\n", pid);
for (;;)
{
pid = wait(&status);
if (pid < 0 && errno != EINTR)
break;
printf("testspeed(%d): Ended (%d)...\n", pid, status);
}
end = time(NULL);
elapsed = end - start;
i = children * requests;
printf("testspeed: %dx%d=%d requests in %.1fs (%.3fs/r, %.1fr/s)\n",
children, requests, i, elapsed, elapsed / i, i / elapsed);
return (status);
}
int
do_test(const char *server,
http_encryption_t encryption,
int requests)
{
int i;
http_t *http;
ipp_t *request,
*response;
cups_lang_t *language;
struct timeval start,
end;
double elapsed;
static ipp_op_t ops[4] =
{
IPP_PRINT_JOB,
CUPS_GET_PRINTERS,
CUPS_GET_CLASSES,
IPP_GET_JOBS
};
http = httpConnectEncrypt(server, ippPort(), encryption);
if (http == NULL)
{
perror("testspeed: unable to connect to server");
return (1);
}
language = cupsLangDefault();
for (elapsed = 0.0, i = 0; i < requests; i ++)
{
if ((i % 10) == 0)
printf("testspeed(%d): %d%% complete...\n", getpid(), i * 100 / requests);
request = ippNew();
request->request.op.operation_id = ops[i & 3];
request->request.op.request_id = 1;
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
"attributes-charset", NULL, cupsLangEncoding(language));
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
"attributes-natural-language", NULL, language->language);
gettimeofday(&start, NULL);
switch (request->request.op.operation_id)
{
case IPP_GET_JOBS :
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
NULL, "ipp://localhost/printers/");
default :
response = cupsDoRequest(http, request, "/");
break;
case IPP_PRINT_JOB :
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
NULL, "ipp://localhost/printers/test");
response = cupsDoFileRequest(http, request, "/printers/test",
"../data/testprint.ps");
break;
}
gettimeofday(&end, NULL);
if (response != NULL)
ippDelete(response);
elapsed += (end.tv_sec - start.tv_sec) +
0.000001 * (end.tv_usec - start.tv_usec);
}
cupsLangFree(language);
httpClose(http);
printf("testspeed(%d): %d requests in %.1fs (%.3fs/r, %.1fr/s)\n",
getpid(), i, elapsed, elapsed / i, i / elapsed);
return (0);
}
void
usage(void)
{
puts("Usage: testspeed [-c children] [-h] [-r requests] [-E] hostname");
exit(0);
}