📄 ptypes_test.cxx
字号:
void testthread::cleanup()
{
diag->postdiag(myname, "terminates");
}
int thread_test()
{
pout.put("\n--- THREAD AND SEMAPHORE CLASSES\n");
int v = 0;
showint(0, pexchange(&v, 5));
showint(5, pexchange(&v, 10));
showint(11, pincrement(&v));
showint(10, pdecrement(&v));
diagthread diag;
testthread thr(&diag);
string myname = "main";
diag.start();
thr.start();
diag.postdiag(myname, "waits 5 secs for the timed semaphore (actually wakes up after a second)");
thr.tsem.wait(5000); // must exit after 1 second instead of 5
diag.postdiag(myname, "waits for the semaphore");
thr.sem.wait();
diag.postdiag(myname, "now waits for testthread to terminate");
thr.waitfor();
diag.postquit();
diag.waitfor();
return 0;
}
//
// trigger test
//
class trigthread: public thread
{
protected:
diagthread* diag;
string myname;
virtual void execute();
public:
trigger trig;
trigthread(diagthread* idiag)
: thread(false), diag(idiag), myname("trigthread"), trig(true, false) {}
virtual ~trigthread() { waitfor(); }
};
void trigthread::execute()
{
diag->postdiag(myname, "waits on the trigger");
trig.wait();
psleep(2000);
diag->postdiag(myname, "waits on the trigger");
trig.wait();
diag->postdiag(myname, "terminates");
}
int trigger_test()
{
pout.put("\n--- TRIGGER\n");
diagthread diag;
trigthread thr(&diag);
string myname = "main";
diag.start();
thr.start();
psleep(1000);
diag.postdiag(myname, "posts the trigger");
thr.trig.post();
psleep(1000);
diag.postdiag(myname, "posts the trigger again");
thr.trig.post();
thr.waitfor();
diag.postquit();
diag.waitfor();
return 0;
}
#endif // PTYPES_ST
//
// md5 test
//
static md5_digest digest;
char* md5str(string data)
{
outmd5 m;
m.open();
m.put(data);
memcpy(digest, m.get_bindigest(), sizeof(md5_digest));
return (char*)digest;
}
string cryptpw(string username, string password)
{
outmd5 m;
m.open();
m.put(username);
m.put(password);
m.close();
return m.get_digest();
}
void md5_test()
{
pout.put("\n--- MD5 OUTPUT STREAM\n");
// MD5 test suite from RFC1321
showhex("d41d8cd98f00b204e9800998ecf8427e", md5str(""), md5_digsize);
showhex("0cc175b9c0f1b6a831c399e269772661", md5str("a"), md5_digsize);
showhex("900150983cd24fb0d6963f7d28e17f72", md5str("abc"), md5_digsize);
showhex("f96b697d7cb7938d525a2f31aaf161d0", md5str("message digest"), md5_digsize);
showhex("c3fcd3d76192e4007dfb496cca67e13b", md5str("abcdefghijklmnopqrstuvwxyz"), md5_digsize);
showhex("d174ab98d277d9f5a5611c2c9f419d9f", md5str("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), md5_digsize);
showhex("57edf4a22be3c955ac49da2e2107b67a", md5str("12345678901234567890123456789012345678901234567890123456789012345678901234567890"), md5_digsize);
showstr("t0htL.C9vunX8SPPsJjDmk", cryptpw("hovik", "myfavoritelonglonglongpassword"));
}
//
// outstm::putf() test
//
void putf_test()
{
pout.put("\n--- PUTF TEST\n");
outmemory m;
m.open();
m.putf("%s, %c, %d, %llx", "string", 'A', 1234, large(-1));
showstr("string, A, 1234, ffffffffffffffff", string(m.get_data(), m.tell()));
m.open();
m.putf(" %%, %#o, %+010d", 0765, -3);
showstr("%, 0765, -000000003", string(m.get_data(), m.tell()));
}
//
// pinet/socket tests
//
void inet_test1()
{
try
{
pout.put("\n--- INET SOCKET & UTILITIES\n");
ipaddress ip(127, 0, 0, 1);
// as a test target host we use the one that would never be down! :)
string testname = "www.apache.org";
ip = phostbyname(testname);
string ips = iptostring(ip);
pout.putf("IP address of %s: %s\n", pconst(testname), (ip == ipnone) ? "failed" : pconst(ips));
if (ip != ipnone)
{
string hs = phostbyaddr(ip);
pout.putf("Name of %s: %s\n", pconst(ips), pconst(hs));
}
pout.putf("Canonical name of your local www: %s\n", pconst(phostcname("www")));
testname = "www.melikyan.com";
pout.putf("\nTrying %s:80...\n", pconst(testname));
ipstream s(testname, 80);
const char* request =
"GET /ptypes/test.txt HTTP/1.1\r\n"
"Accept: * /*\r\n"
"User-Agent: ptypes_test/1.7\r\n"
"Host: www.melikyan.com\r\n"
"Connection: close\r\n\r\n";
s.open();
s.put(request);
s.flush();
while (!s.get_eof())
{
char buf[16];
int r = s.read(buf, sizeof(buf));
pout.write(buf, r);
}
pout.put("\n");
s.close();
}
catch(estream* e)
{
perr.putf("Socket error: %s\n", pconst(e->get_message()));
delete e;
}
}
#ifndef PTYPES_ST
const int testport = 8085;
class svthread: public thread, protected ipstmserver
{
protected:
virtual void execute(); // override thread::execute()
virtual void cleanup(); // override thread::cleanup()
public:
svthread(): thread(false) {}
virtual ~svthread();
};
svthread::~svthread()
{
waitfor();
}
void svthread::execute()
{
ipstream client; // a socket object to communicate with the client
try
{
bindall(testport); // listen to all local addresses on port 8081
serve(client); // wait infinitely for a connection request
if (client.get_active())
{
// read one line from the stream; note that theoretically the line can be long,
// so calling client.line(buf, sizeof(buf)) here is a much better idea
string req = lowercase(client.line());
if (req == "hello")
{
// try to reverse-lookup the client's IP
string host = phostbyaddr(client.get_ip());
if (isempty(host))
host = iptostring(client.get_ip());
// now send our greeting to the client
client.putf("Hello, %s (%a), nice to see you!\n",
pconst(host), long(client.get_ip()));
client.flush();
}
// close() should be called explicitly to shut down the socket
// *gracefully*; otherwise ipstream's destructor may close the
// socket but in a less polite manner
client.close();
}
}
catch(estream* e)
{
perr.putf("Server error: %s\n", pconst(e->get_message()));
delete e;
}
// a real server could enter an infinite loop serving requests
// and producing separate threads for each connection
}
void svthread::cleanup()
{
}
void inet_test2()
{
pout.put("\n--- INET CLIENT/SERVER\n");
// we run the server in a separate thread in order to be able
// to imitate a client connection from the main thread
svthread server;
pout.put("\nStarting the server thread...\n");
server.start(); // it's that easy! :)
// sleep some time to let the server start its job
psleep(1000);
try
{
// now create a client socket and send a greeting to our server
ipstream client(ipaddress(127, 0, 0, 1), testport);
client.open();
pout.put("Sending a request to the server...\n");
client.putline("Hello");
client.flush();
string rsp = client.line();
pout.putf("Received: %s\n", pconst(rsp));
pout.putf("My address and port: %s:%d\n",
pconst(iptostring(client.get_myip())), client.get_myport());
client.close();
}
catch(estream* e)
{
perr.putf("Error: %s\n", pconst(e->get_message()));
delete e;
}
}
//
// UDP test
//
class msgsvthread: public thread
{
protected:
void execute();
public:
msgsvthread(): thread(false) {}
virtual ~msgsvthread() { waitfor(); }
};
void msgsvthread::execute()
{
ipmsgserver s;
s.bindall(testport);
try
{
string req = s.receive(1024);
pout.putf("Server received: %s\n", pconst(req));
string rsp = "gotcha";
s.send(rsp);
}
catch(estream* e)
{
perr.putf("Server error: %s\n", pconst(e->get_message()));
delete e;
}
}
void inet_test3()
{
pout.put("\n--- INET MESSAGE CLIENT/SERVER\n");
msgsvthread sv;
sv.start();
psleep(1000);
ipmessage m(ipbcast /* ipaddress(127, 0, 0, 1) */, testport);
try
{
string msg = "hello";
m.send(msg);
string rsp = m.receive(1024);
pout.putf("Client received: %s\n", pconst(rsp));
}
catch(estream* e)
{
perr.putf("Client error: %s\n", pconst(e->get_message()));
delete e;
}
}
//
// named pipes test
//
#define TEST_PIPE "ptypes.test"
class npthread: public thread, protected npserver
{
protected:
virtual void execute();
virtual void cleanup();
public:
npthread(): thread(false), npserver(TEST_PIPE) {}
virtual ~npthread();
};
npthread::~npthread()
{
waitfor();
}
void npthread::execute()
{
namedpipe client;
try
{
serve(client);
if (client.get_active())
{
string req = lowercase(client.line());
if (req == "hello")
{
client.putline("Hello, nice to see you!");
client.flush();
}
client.close();
}
}
catch(estream* e)
{
perr.putf("Pipe server error: %s\n", pconst(e->get_message()));
delete e;
}
}
void npthread::cleanup()
{
}
void pipe_test()
{
npthread server;
pout.put("\n--- NAMED PIPES\n");
pout.put("Starting the pipe server thread...\n");
server.start();
psleep(1000);
namedpipe client(TEST_PIPE);
try
{
client.open();
pout.put("Sending a request to the server...\n");
client.putline("Hello");
client.flush();
string rsp = client.line();
pout.putf("Received: %s\n", pconst(rsp));
client.close();
}
catch(estream* e)
{
perr.putf("Error: %s\n", pconst(e->get_message()));
delete e;
}
}
#endif // PTYPES_ST
//
// date/time/calendar
//
void time_test()
{
pout.put("\n--- DATE/TIME/CALENDAR\n");
tzupdate();
int year, month, day;
datetime d = encodedate(9999, 12, 31);
decodedate(d, year, month, day);
d = encodedate(1970, 1, 1);
decodedate(d, year, month, day);
datetime dt;
dt = invdatetime;
int hour, min, sec, msec;
dt = encodetime(23, 59, 59, 998);
decodetime(dt, hour, min, sec, msec);
dt = encodedate(2001, 8, 27) + encodetime(14, 33, 10);
d = encodedate(2001, 8, 28) + encodetime(14, 33, 10, 500);
dayofweek(dt);
dt = now(false);
pout.putf("Local time: %s\n", pconst(dttostring(dt, "%x %X %Z")));
datetime utc = now();
pout.putf("UTC time: %t GMT\n", utc);
time_t ut;
time(&ut);
pout.putline(dttostring(utodatetime(ut), "%c"));
int t = tzoffset();
bool neg = t < 0;
if (neg)
t = -t;
pout.putf("Time zone offset: %c%02d%02d\n", neg ? '-' : '+', t / 60, t % 60);
{
// PTypes' birthday (birth moment, if you wish)
datetime d = encodedate(2000, 3, 30) + encodetime(13, 24, 58, 995);
pout.putf("PTypes' birth moment: %T GMT\n", d);
// now see how old is PTypes in days, hours, minutes, etc
datetime diff = now() - d;
int hours, mins, secs, msecs;
decodetime(diff, hours, mins, secs, msecs);
pout.putf("PTypes' life time: %d days %d hours %d minutes %d seconds and %d milliseconds\n",
days(diff), hours, mins, secs, msecs);
#ifndef PTYPES_ST
// measure the difference in milliseconds between two calls to now()
datetime m = now();
psleep(17); // sleep for 17 milliseconds
pout.putf("A 17 millisecond dream lasted actually %d milliseconds\n", int(now() - m));
// this will show the actual precision of the clock on the given platform;
// Windows, f.ex., always shows the difference in 10 msec increments
#endif
}
}
//
// streams documentation example #2
//
const cset letters("_A-Za-z");
const cset digits("0-9");
const cset identchars = letters + digits;
const cset otherchars = !letters;
void doc_example()
{
strlist dic(SL_SORTED);
infile f("../src/ptypes_test.cxx");
try
{
f.open();
while (!f.get_eof())
{
char c = f.preview();
// a C identifier starts with a letter
if (c & letters)
{
// ... and may contain letters and digits
string ident = f.token(identchars);
int i;
if (!search(dic, ident, i))
add(dic, ident, 0);
}
else
f.skiptoken(otherchars);
}
}
catch (estream* e)
{
pout.putf("Error: %s\n", pconst(e->get_message()));
delete e;
}
// now print the dictionary
for (int i = 0; i < length(dic); i++)
pout.putline(getstr(dic, i));
}
//
// variant
//
void variant_test()
{
pout.put("\n--- VARIANT\n");
variant v0 = 'A';
variant v1 = short(33);
variant v2 = "456";
variant v3 = int(v1) + int(v2);
variant v4 = string(v1) + " cows";
string s = v4;
// s = v4;
variant v5 = new component();
variant v6;
put(v6, 291, v1);
put(v6, "key", v2);
put(v6, "another-key", "another-value");
showstr("33 cows", v4);
showint(456, v6["key"]);
showstr("33", v1);
showint(1, bool(v6));
v2 = aclone(v6);
v5 = v6;
variant vi;
int i;
for (i = 0; anext(v6, i, vi);)
pout.putf("%d\n", int(vi));
variant v7;
aadd(v7, v1);
aadd(v7, v3);
aadd(v7, v4);
adel(v7, 2);
for (i = 0; i < alength(v7); i++)
pout.putf("%s\n", pconst(string(aget(v7, i))));
}
//
// main
//
int main()
{
try
{
string_test1();
string_test2();
string_benchmarks();
cset_test();
objlist_test();
strlist_test();
strmap_test();
textmap_test();
mem_test();
outfile_test();
infile_test();
md5_test();
putf_test();
time_test();
variant_test();
inet_test1();
#ifndef PTYPES_ST
pipe_test();
thread_test();
rwlock_test();
trigger_test();
inet_test2();
inet_test3();
#endif
}
catch (estream* e)
{
perr.putf("\nError: %s\n", pconst(e->get_message()));
exit(1);
delete e;
}
#ifdef DEBUG
if (stralloc != 0 || objalloc != 0)
{
perr.putf("DBG stralloc: %d, objalloc: %d\n", stralloc, objalloc);
fatal(255, "Allocation problems");
}
#endif
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -