public inbox for lvm2-cvs@sourceware.org
help / color / mirror / Atom feed
* LVM2/test/lib harness.c
@ 2012-03-12 14:24 zkabelac
0 siblings, 0 replies; 9+ messages in thread
From: zkabelac @ 2012-03-12 14:24 UTC (permalink / raw)
To: lvm-devel, lvm2-cvs
CVSROOT: /cvs/lvm2
Module name: LVM2
Changes by: zkabelac@sourceware.org 2012-03-12 14:24:15
Modified files:
test/lib : harness.c
Log message:
Improve harness code
Support timestamping with harness - using VERBOSE=2
Fix also logging in several situation
(i.e. continue logging multiple test in VERBOSE mode,
do not coredump with empty output).
Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/test/lib/harness.c.diff?cvsroot=lvm2&r1=1.11&r2=1.12
--- LVM2/test/lib/harness.c 2012/02/15 01:31:10 1.11
+++ LVM2/test/lib/harness.c 2012/03/12 14:24:15 1.12
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2011 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2010-2012 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -21,6 +21,7 @@
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
+#include <sys/time.h>
static pid_t pid;
static int fds[2];
@@ -41,7 +42,7 @@
static int readbuf_sz = 0, readbuf_used = 0;
static int die = 0;
-static int verbose = 0;
+static int verbose = 0; /* >1 with timestamps */
struct subst {
const char *key;
@@ -119,8 +120,13 @@
}
}
-static void trickle() {
+static void trickle(void) {
static int counter_last = -1, counter = 0;
+
+ if (counter_last > readbuf_used) {
+ counter_last = -1;
+ counter = 0;
+ }
while ( counter < readbuf_used && counter != counter_last ) {
counter_last = counter;
counter = outline( readbuf, counter, 1 );
@@ -131,25 +137,83 @@
readbuf_used = 0;
}
+static int64_t _get_time_us(void)
+{
+ struct timeval tv;
+
+ (void) gettimeofday(&tv, 0);
+ return (int64_t) tv.tv_sec * 1000000 + (int64_t) tv.tv_usec;
+}
+
+static void _append_buf(const char *buf, size_t len)
+{
+ if ((readbuf_used + len) >= readbuf_sz) {
+ readbuf_sz = readbuf_sz ? 2 * readbuf_sz : 4096;
+ readbuf = realloc(readbuf, readbuf_sz);
+ }
+
+ if (!readbuf)
+ exit(205);
+
+ memcpy(readbuf + readbuf_used, buf, len);
+ readbuf_used += len;
+}
+
+static const char *_append_with_stamp(const char *buf, int stamp)
+{
+ static const char spaces[] = " ";
+ static int64_t t_last;
+ static int64_t t_start = 0;
+ int64_t t_now;
+ char stamp_buf[32]; /* Bigger to always fit both numbers */
+ const char *be;
+ const char *bb = buf;
+ size_t len;
+
+ while ((be = strchr(bb, '\n'))) {
+ if (stamp++ == 0) {
+ t_now = _get_time_us();
+ if (!t_start)
+ t_start = t_last = t_now;
+ len = snprintf(stamp_buf, sizeof(stamp_buf),
+ "%8.3f%8.4f ",
+ (t_now - t_start) / 1000000.f,
+ (t_now - t_last) / 1000000.f);
+ _append_buf(stamp_buf, (len < (sizeof(spaces) - 1)) ?
+ len : (sizeof(spaces) - 1));
+ t_last = t_now;
+ }
+
+ _append_buf(bb, be + 1 - bb);
+ bb = be + 1;
+
+ if (stamp > 0 && bb[0])
+ _append_buf(spaces, sizeof(spaces) - 1);
+ }
+
+ return bb;
+}
+
static void drain(void) {
+ char buf[4096];
+ const char *bp;
+ int stamp = 0;
int sz;
- char buf[2048];
- while (1) {
- sz = read(fds[1], buf, sizeof(buf));
- if (sz <= 0)
- return;
- if (readbuf_used + sz >= readbuf_sz) {
- readbuf_sz = readbuf_sz ? 2 * readbuf_sz : 4096;
- readbuf = realloc(readbuf, readbuf_sz);
- }
+ while ((sz = read(fds[1], buf, sizeof(buf) - 1)) > 0) {
+ buf[sz] = '\0';
+ bp = (verbose < 2) ? buf : _append_with_stamp(buf, stamp);
+
+ if (sz > (bp - buf)) {
+ _append_buf(bp, sz - (bp - buf));
+ stamp = -1; /* unfinished line */
+ } else
+ stamp = 0;
+
+ readbuf[readbuf_used] = 0;
+
if (verbose)
trickle();
- if (!readbuf)
- exit(205);
- memcpy(readbuf + readbuf_used, buf, sz);
- readbuf_used += sz;
- readbuf[readbuf_used] = 0;
}
}
@@ -163,7 +227,7 @@
}
static void passed(int i, char *f, time_t t) {
- if (strstr(readbuf, "TEST WARNING")) {
+ if (readbuf && strstr(readbuf, "TEST WARNING")) {
++s.nwarned;
s.status[i] = WARNED;
printf("warnings %s\n", duration(t));
@@ -252,8 +316,8 @@
exit(1);
}
- if (be_verbose && atoi(be_verbose))
- verbose = 1; // XXX
+ if (be_verbose)
+ verbose = atoi(be_verbose);
if (socketpair(PF_UNIX, SOCK_STREAM, 0, fds)) {
perror("socketpair");
^ permalink raw reply [flat|nested] 9+ messages in thread
* LVM2/test/lib harness.c
@ 2012-02-15 1:31 mornfall
0 siblings, 0 replies; 9+ messages in thread
From: mornfall @ 2012-02-15 1:31 UTC (permalink / raw)
To: lvm-devel, lvm2-cvs
CVSROOT: /cvs/lvm2
Module name: LVM2
Changes by: mornfall@sourceware.org 2012-02-15 01:31:10
Modified files:
test/lib : harness.c
Log message:
In the test harness, do the back-substitution (@TESTDIR@, @PREFIX@) also on the
live VERBOSE output, not just the post-mortem dumps.
Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/test/lib/harness.c.diff?cvsroot=lvm2&r1=1.10&r2=1.11
--- LVM2/test/lib/harness.c 2011/11/23 14:56:47 1.10
+++ LVM2/test/lib/harness.c 2012/02/15 01:31:10 1.11
@@ -119,6 +119,14 @@
}
}
+static void trickle() {
+ static int counter_last = -1, counter = 0;
+ while ( counter < readbuf_used && counter != counter_last ) {
+ counter_last = counter;
+ counter = outline( readbuf, counter, 1 );
+ }
+}
+
static void clear(void) {
readbuf_used = 0;
}
@@ -131,12 +139,12 @@
sz = read(fds[1], buf, sizeof(buf));
if (sz <= 0)
return;
- if (verbose)
- write(1, buf, sz);
if (readbuf_used + sz >= readbuf_sz) {
readbuf_sz = readbuf_sz ? 2 * readbuf_sz : 4096;
readbuf = realloc(readbuf, readbuf_sz);
}
+ if (verbose)
+ trickle();
if (!readbuf)
exit(205);
memcpy(readbuf + readbuf_used, buf, sz);
^ permalink raw reply [flat|nested] 9+ messages in thread
* LVM2/test/lib harness.c
@ 2011-11-07 17:02 mornfall
0 siblings, 0 replies; 9+ messages in thread
From: mornfall @ 2011-11-07 17:02 UTC (permalink / raw)
To: lvm-devel, lvm2-cvs
CVSROOT: /cvs/lvm2
Module name: LVM2
Changes by: mornfall@sourceware.org 2011-11-07 17:02:57
Modified files:
test/lib : harness.c
Log message:
Do not repeat a failed test's output when VERBOSE is in effect.
Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/test/lib/harness.c.diff?cvsroot=lvm2&r1=1.8&r2=1.9
--- LVM2/test/lib/harness.c 2011/09/24 21:12:35 1.8
+++ LVM2/test/lib/harness.c 2011/11/07 17:02:56 1.9
@@ -180,9 +180,11 @@
return;
}
printf("FAILED.\n");
- printf("-- FAILED %s ------------------------------------\n", f);
- dump();
- printf("-- FAILED %s (end) ------------------------------\n", f);
+ if (!verbose) {
+ printf("-- FAILED %s ------------------------------------\n", f);
+ dump();
+ printf("-- FAILED %s (end) ------------------------------\n", f);
+ }
}
static void run(int i, char *f) {
^ permalink raw reply [flat|nested] 9+ messages in thread
* LVM2/test/lib harness.c
@ 2011-09-24 21:12 zkabelac
0 siblings, 0 replies; 9+ messages in thread
From: zkabelac @ 2011-09-24 21:12 UTC (permalink / raw)
To: lvm-devel, lvm2-cvs
CVSROOT: /cvs/lvm2
Module name: LVM2
Changes by: zkabelac@sourceware.org 2011-09-24 21:12:35
Modified files:
test/lib : harness.c
Log message:
Avoid sending garbage to terminal in verbose mode.
When read in drain returned <0 value, terminal content has been trashed.
Remove unneeded memset() and use whole buffer.
Free readbuf before exit (valgrind).
Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/test/lib/harness.c.diff?cvsroot=lvm2&r1=1.7&r2=1.8
--- LVM2/test/lib/harness.c 2011/03/10 14:47:22 1.7
+++ LVM2/test/lib/harness.c 2011/09/24 21:12:35 1.8
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2010-2011 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -126,14 +126,13 @@
static void drain(void) {
int sz;
char buf[2048];
- memset(buf, 0, 2048);
while (1) {
- sz = read(fds[1], buf, 2047);
- if (verbose)
- write(1, buf, sz);
+ sz = read(fds[1], buf, sizeof(buf));
if (sz <= 0)
return;
+ if (verbose)
+ write(1, buf, sz);
if (readbuf_used + sz >= readbuf_sz) {
readbuf_sz = readbuf_sz ? 2 * readbuf_sz : 4096;
readbuf = realloc(readbuf, readbuf_sz);
@@ -291,5 +290,7 @@
return s.nfailed > 0 || die;
}
+ free(readbuf);
+
return die;
}
^ permalink raw reply [flat|nested] 9+ messages in thread
* LVM2/test/lib harness.c
@ 2011-03-10 14:47 zkabelac
0 siblings, 0 replies; 9+ messages in thread
From: zkabelac @ 2011-03-10 14:47 UTC (permalink / raw)
To: lvm-devel, lvm2-cvs
CVSROOT: /cvs/lvm2
Module name: LVM2
Changes by: zkabelac@sourceware.org 2011-03-10 14:47:23
Modified files:
test/lib : harness.c
Log message:
Indent spaces to tabs
Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/test/lib/harness.c.diff?cvsroot=lvm2&r1=1.6&r2=1.7
--- LVM2/test/lib/harness.c 2011/01/28 16:05:38 1.6
+++ LVM2/test/lib/harness.c 2011/03/10 14:47:22 1.7
@@ -44,8 +44,8 @@
static int verbose = 0;
struct subst {
- const char *key;
- char *value;
+ const char *key;
+ char *value;
};
static struct subst subst[2];
@@ -62,52 +62,52 @@
}
static int outline(char *buf, int start, int force) {
- char *from = buf + start;
- char *next = strchr(buf + start, '\n');
+ char *from = buf + start;
+ char *next = strchr(buf + start, '\n');
- if (!next && !force) /* not a complete line yet... */
- return start;
+ if (!next && !force) /* not a complete line yet... */
+ return start;
- if (!next)
- next = from + strlen(from);
- else
- ++next;
-
- if (!strncmp(from, "@TESTDIR=", 9)) {
- subst[0].key = "@TESTDIR@";
- subst[0].value = strndup(from + 9, next - from - 9 - 1);
- } else if (!strncmp(from, "@PREFIX=", 8)) {
- subst[1].key = "@PREFIX@";
- subst[1].value = strndup(from + 8, next - from - 8 - 1);
- } else {
- char *line = strndup(from, next - from);
- char *a = line, *b;
- do {
- int idx = -1;
- int i;
- b = line + strlen(line);
- for ( i = 0; i < 2; ++i ) {
- if (subst[i].key) {
- // printf("trying: %s -> %s\n", subst[i].value, subst[i].key);
- char *stop = strstr(a, subst[i].value);
- if (stop && stop < b) {
- idx = i;
- b = stop;
- }
- }
- }
- fwrite(a, 1, b - a, stdout);
- a = b;
-
- if ( idx >= 0 ) {
- fprintf(stdout, "%s", subst[idx].key);
- a += strlen(subst[idx].value);
- }
- } while (b < line + strlen(line));
- free(line);
- }
+ if (!next)
+ next = from + strlen(from);
+ else
+ ++next;
+
+ if (!strncmp(from, "@TESTDIR=", 9)) {
+ subst[0].key = "@TESTDIR@";
+ subst[0].value = strndup(from + 9, next - from - 9 - 1);
+ } else if (!strncmp(from, "@PREFIX=", 8)) {
+ subst[1].key = "@PREFIX@";
+ subst[1].value = strndup(from + 8, next - from - 8 - 1);
+ } else {
+ char *line = strndup(from, next - from);
+ char *a = line, *b;
+ do {
+ int idx = -1;
+ int i;
+ b = line + strlen(line);
+ for ( i = 0; i < 2; ++i ) {
+ if (subst[i].key) {
+ // printf("trying: %s -> %s\n", subst[i].value, subst[i].key);
+ char *stop = strstr(a, subst[i].value);
+ if (stop && stop < b) {
+ idx = i;
+ b = stop;
+ }
+ }
+ }
+ fwrite(a, 1, b - a, stdout);
+ a = b;
+
+ if ( idx >= 0 ) {
+ fprintf(stdout, "%s", subst[idx].key);
+ a += strlen(subst[idx].value);
+ }
+ } while (b < line + strlen(line));
+ free(line);
+ }
- return next - buf + (force ? 0 : 1);
+ return next - buf + (force ? 0 : 1);
}
static void dump(void) {
@@ -126,7 +126,7 @@
static void drain(void) {
int sz;
char buf[2048];
- memset(buf, 0, 2048);
+ memset(buf, 0, 2048);
while (1) {
sz = read(fds[1], buf, 2047);
@@ -195,8 +195,8 @@
close(0);
dup2(fds[0], 1);
dup2(fds[0], 2);
- close(fds[0]);
- close(fds[1]);
+ close(fds[0]);
+ close(fds[1]);
execlp("bash", "bash", f, NULL);
perror("execlp");
fflush(stderr);
@@ -257,11 +257,11 @@
}
/* set up signal handlers */
- for (i = 0; i <= 32; ++i) {
- if (i == SIGCHLD || i == SIGWINCH || i == SIGURG)
- continue;
- signal(i, handler);
- }
+ for (i = 0; i <= 32; ++i) {
+ if (i == SIGCHLD || i == SIGWINCH || i == SIGURG)
+ continue;
+ signal(i, handler);
+ }
/* run the tests */
for (i = 1; i < argc; ++ i) {
^ permalink raw reply [flat|nested] 9+ messages in thread
* LVM2/test/lib harness.c
@ 2011-01-28 16:05 zkabelac
0 siblings, 0 replies; 9+ messages in thread
From: zkabelac @ 2011-01-28 16:05 UTC (permalink / raw)
To: lvm-devel, lvm2-cvs
CVSROOT: /cvs/lvm2
Module name: LVM2
Changes by: zkabelac@sourceware.org 2011-01-28 16:05:38
Modified files:
test/lib : harness.c
Log message:
Display duration of tests when it passed.
Enhance output with info about the test duration.
Cleanup few declarations in the code.
Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/test/lib/harness.c.diff?cvsroot=lvm2&r1=1.5&r2=1.6
--- LVM2/test/lib/harness.c 2011/01/13 15:03:28 1.5
+++ LVM2/test/lib/harness.c 2011/01/28 16:05:38 1.6
@@ -20,6 +20,7 @@
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
+#include <time.h>
static pid_t pid;
static int fds[2];
@@ -82,9 +83,9 @@
char *line = strndup(from, next - from);
char *a = line, *b;
do {
- b = line + strlen(line);
int idx = -1;
int i;
+ b = line + strlen(line);
for ( i = 0; i < 2; ++i ) {
if (subst[i].key) {
// printf("trying: %s -> %s\n", subst[i].value, subst[i].key);
@@ -145,15 +146,24 @@
}
}
-static void passed(int i, char *f) {
+static const char *duration(time_t start)
+{
+ static char buf[16];
+ int t = (int)(time(NULL) - start);
+
+ sprintf(buf, "%2d:%02d", t / 60, t % 60);
+ return buf;
+}
+
+static void passed(int i, char *f, time_t t) {
if (strstr(readbuf, "TEST WARNING")) {
++s.nwarned;
s.status[i] = WARNED;
- printf("warnings\n");
+ printf("warnings %s\n", duration(t));
} else {
++ s.npassed;
s.status[i] = PASSED;
- printf("passed.\n");
+ printf("passed. %s\n", duration(t));
}
}
@@ -192,12 +202,13 @@
fflush(stderr);
_exit(202);
} else {
+ int st, w;
+ time_t start = time(NULL);
char buf[128];
snprintf(buf, 128, "%s ...", f);
buf[127] = 0;
printf("Running %-40s ", buf);
fflush(stdout);
- int st, w;
while ((w = waitpid(pid, &st, WNOHANG)) == 0) {
drain();
usleep(20000);
@@ -209,7 +220,7 @@
drain();
if (WIFEXITED(st)) {
if (WEXITSTATUS(st) == 0) {
- passed(i, f);
+ passed(i, f, start);
} else if (WEXITSTATUS(st) == 200) {
skipped(i, f);
} else {
@@ -223,6 +234,8 @@
}
int main(int argc, char **argv) {
+ const char *be_verbose = getenv("VERBOSE");
+ time_t start = time(NULL);
int i;
if (argc >= MAX) {
@@ -230,9 +243,6 @@
exit(1);
}
- s.nwarned = s.nfailed = s.npassed = s.nskipped = 0;
-
- char *be_verbose = getenv("VERBOSE");
if (be_verbose && atoi(be_verbose))
verbose = 1; // XXX
@@ -260,8 +270,9 @@
break;
}
- printf("\n## %d tests: %d OK, %d warnings, %d failures; %d skipped\n",
+ printf("\n## %d tests %s : %d OK, %d warnings, %d failures; %d skipped\n",
s.nwarned + s.npassed + s.nfailed + s.nskipped,
+ duration(start),
s.npassed, s.nwarned, s.nfailed, s.nskipped);
/* print out a summary */
@@ -279,5 +290,6 @@
printf("\n");
return s.nfailed > 0 || die;
}
+
return die;
}
^ permalink raw reply [flat|nested] 9+ messages in thread
* LVM2/test/lib harness.c
@ 2011-01-13 15:03 zkabelac
0 siblings, 0 replies; 9+ messages in thread
From: zkabelac @ 2011-01-13 15:03 UTC (permalink / raw)
To: lvm-devel, lvm2-cvs
CVSROOT: /cvs/lvm2
Module name: LVM2
Changes by: zkabelac@sourceware.org 2011-01-13 15:03:28
Modified files:
test/lib : harness.c
Log message:
Set default value to counter_last
Missed in previous commit and could be using some random stack value.
Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/test/lib/harness.c.diff?cvsroot=lvm2&r1=1.4&r2=1.5
--- LVM2/test/lib/harness.c 2011/01/13 11:02:55 1.4
+++ LVM2/test/lib/harness.c 2011/01/13 15:03:28 1.5
@@ -110,7 +110,7 @@
}
static void dump(void) {
- int counter_last, counter = 0;
+ int counter_last = -1, counter = 0;
while ( counter < readbuf_used && counter != counter_last ) {
counter_last = counter;
^ permalink raw reply [flat|nested] 9+ messages in thread
* LVM2/test/lib harness.c
@ 2011-01-13 11:02 zkabelac
0 siblings, 0 replies; 9+ messages in thread
From: zkabelac @ 2011-01-13 11:02 UTC (permalink / raw)
To: lvm-devel, lvm2-cvs
CVSROOT: /cvs/lvm2
Module name: LVM2
Changes by: zkabelac@sourceware.org 2011-01-13 11:02:55
Modified files:
test/lib : harness.c
Log message:
Hotfix to stop harness busylooping
Harness seems to be able to busyloop in while cycle and not moving forward
for certain buffer - so check whethere there was some progress.
This fix allows to continue after failed cluster test.
Fix gcc warning for hiding global variable 's' -> sig.
Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/test/lib/harness.c.diff?cvsroot=lvm2&r1=1.3&r2=1.4
--- LVM2/test/lib/harness.c 2011/01/10 13:25:22 1.3
+++ LVM2/test/lib/harness.c 2011/01/13 11:02:55 1.4
@@ -54,10 +54,10 @@
#define FAILED 2
#define WARNED 3
-static void handler( int s ) {
- signal( s, SIG_DFL );
- kill( pid, s );
- die = s;
+static void handler( int sig ) {
+ signal( sig, SIG_DFL );
+ kill( pid, sig );
+ die = sig;
}
static int outline(char *buf, int start, int force) {
@@ -110,10 +110,12 @@
}
static void dump(void) {
- int counter = 0;
+ int counter_last, counter = 0;
- while ( counter < readbuf_used )
- counter = outline( readbuf, counter, 1 );
+ while ( counter < readbuf_used && counter != counter_last ) {
+ counter_last = counter;
+ counter = outline( readbuf, counter, 1 );
+ }
}
static void clear(void) {
^ permalink raw reply [flat|nested] 9+ messages in thread
* LVM2/test/lib harness.c
@ 2011-01-10 13:25 zkabelac
0 siblings, 0 replies; 9+ messages in thread
From: zkabelac @ 2011-01-10 13:25 UTC (permalink / raw)
To: lvm-devel, lvm2-cvs
CVSROOT: /cvs/lvm2
Module name: LVM2
Changes by: zkabelac@sourceware.org 2011-01-10 13:25:22
Modified files:
test/lib : harness.c
Log message:
Use strndup as GNU extension
strndup needs _GNU_SOURCE defined as it's GNU extension.
Remove duplicate string.h header added in previous harness commit.
Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/test/lib/harness.c.diff?cvsroot=lvm2&r1=1.2&r2=1.3
--- LVM2/test/lib/harness.c 2011/01/05 15:03:43 1.2
+++ LVM2/test/lib/harness.c 2011/01/10 13:25:22 1.3
@@ -12,6 +12,7 @@
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define _GNU_SOURCE
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
@@ -19,7 +20,6 @@
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
-#include <string.h>
static pid_t pid;
static int fds[2];
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2012-03-12 14:24 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-03-12 14:24 LVM2/test/lib harness.c zkabelac
-- strict thread matches above, loose matches on Subject: below --
2012-02-15 1:31 mornfall
2011-11-07 17:02 mornfall
2011-09-24 21:12 zkabelac
2011-03-10 14:47 zkabelac
2011-01-28 16:05 zkabelac
2011-01-13 15:03 zkabelac
2011-01-13 11:02 zkabelac
2011-01-10 13:25 zkabelac
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).