Private
Public Access
Release 0.13.0
This commit is contained in:
1 parent
7f6eeab39e
commit
c0d891b372
49 files changed
+1523
-478
No files matched your search
@@ -0,0 +1,162 @@
|
||||
#define DEV_MODE "/tmp/hyperdrm-lifecycle-marker"
|
||||
#define main service_entry_point
|
||||
#include "service.c"
|
||||
#undef main
|
||||
#include <assert.h>
|
||||
static unsigned initializes, finalizes;
|
||||
static int fake_handle;
|
||||
static char answer[8192];
|
||||
static bool fake_reply(void *h, void *m, const char *s, LSError *e) {
|
||||
(void)h;
|
||||
(void)m;
|
||||
(void)e;
|
||||
snprintf(answer, sizeof(answer), "%s", s);
|
||||
return true;
|
||||
}
|
||||
static const char *fake_payload(void *m) {
|
||||
return m;
|
||||
}
|
||||
static bool fake_error_init(LSError *e) {
|
||||
memset(e, 0, sizeof(*e));
|
||||
return true;
|
||||
}
|
||||
static void fake_error_free(LSError *e) {
|
||||
(void)e;
|
||||
}
|
||||
static bool fake_call(void *h, const char *u, const char *p, Callback cb, void *ctx,
|
||||
unsigned long *t, LSError *e) {
|
||||
(void)h;
|
||||
(void)u;
|
||||
(void)p;
|
||||
(void)cb;
|
||||
(void)ctx;
|
||||
(void)t;
|
||||
(void)e;
|
||||
return false;
|
||||
}
|
||||
static bool fake_cancel(void *h, unsigned long t, LSError *e) {
|
||||
(void)h;
|
||||
(void)t;
|
||||
(void)e;
|
||||
return true;
|
||||
}
|
||||
static void *fake_init(bool (*p)(void)) {
|
||||
(void)p;
|
||||
initializes++;
|
||||
return &fake_handle;
|
||||
}
|
||||
static int fake_preset(void *h, int p) {
|
||||
assert(h == &fake_handle);
|
||||
(void)p;
|
||||
return 0;
|
||||
}
|
||||
static int fake_get(void *h, Histogram *hist) {
|
||||
assert(h == &fake_handle);
|
||||
for (unsigned r = 0; r < 16; r++)
|
||||
for (unsigned c = 0; c < 3; c++)
|
||||
hist[r].bins[c][80 + c * 20] = 100;
|
||||
return 0;
|
||||
}
|
||||
static int fake_finish(void *h) {
|
||||
assert(h == &fake_handle);
|
||||
finalizes++;
|
||||
return 0;
|
||||
}
|
||||
static unsigned request_id(const char *line) {
|
||||
const char *p = strstr(line, "\"tan\":");
|
||||
assert(p);
|
||||
return strtoul(p + 6, NULL, 10);
|
||||
}
|
||||
static void success(int fd, unsigned id, bool layout) {
|
||||
char data[256];
|
||||
int n = snprintf(data, sizeof(data),
|
||||
layout ? "{\"success\":true,\"tan\":%u,\"info\":{\"leds\":[{\"hmin\":0,"
|
||||
"\"hmax\":1,\"vmin\":0,\"vmax\":0.1}]}}\n"
|
||||
: "{\"success\":true,\"tan\":%u}\n",
|
||||
id);
|
||||
assert(send(fd, data, n, MSG_NOSIGNAL) == n);
|
||||
}
|
||||
int main(void) {
|
||||
assert(access(DEV_MODE, F_OK) != 0);
|
||||
reply = fake_reply;
|
||||
payload = fake_payload;
|
||||
error_init = fake_error_init;
|
||||
error_free = fake_error_free;
|
||||
call_once = fake_call;
|
||||
cancel_call = fake_cancel;
|
||||
vt_init = fake_init;
|
||||
vt_preset = fake_preset;
|
||||
vt_get = fake_get;
|
||||
vt_finish = fake_finish;
|
||||
assert(playback_json_init(&playback_json));
|
||||
next_layout_check = UINT64_MAX;
|
||||
calibration.kind = CAL_G4;
|
||||
int server = socket(AF_INET, SOCK_STREAM, 0);
|
||||
assert(server >= 0);
|
||||
struct sockaddr_in address = {.sin_family = AF_INET, .sin_addr = {htonl(INADDR_LOOPBACK)}};
|
||||
assert(!bind(server, (void *)&address, sizeof(address)) && !listen(server, 2));
|
||||
socklen_t size = sizeof(address);
|
||||
assert(!getsockname(server, (void *)&address, &size));
|
||||
target.port = ntohs(address.sin_port);
|
||||
assert(start((void *)1, "{}", NULL) && strstr(answer, "connecting"));
|
||||
assert(receiver_runtime.starting && !capture_ctx.handle && !initializes);
|
||||
assert(stop((void *)1, "{}", NULL));
|
||||
assert(!receiver_runtime.starting && receiver_runtime.output.fd < 0 && !initializes);
|
||||
int cancelled = accept(server, NULL, NULL);
|
||||
assert(cancelled >= 0);
|
||||
close(cancelled);
|
||||
tick(NULL);
|
||||
assert(!initializes && retries.paused);
|
||||
pid_t child = fork();
|
||||
assert(child >= 0);
|
||||
if (!child) {
|
||||
int fd = accept(server, NULL, NULL);
|
||||
assert(fd >= 0);
|
||||
FILE *input = fdopen(dup(fd), "r");
|
||||
char line[2048];
|
||||
assert(fgets(line, sizeof(line), input) && strstr(line, "serverinfo"));
|
||||
success(fd, request_id(line), true);
|
||||
assert(fgets(line, sizeof(line), input) && strstr(line, "color"));
|
||||
unsigned id = request_id(line);
|
||||
usleep(200000);
|
||||
success(fd, id, false);
|
||||
assert(fgets(line, sizeof(line), input) && strstr(line, "clear"));
|
||||
success(fd, request_id(line), false);
|
||||
usleep(20000);
|
||||
fclose(input);
|
||||
close(fd);
|
||||
close(server);
|
||||
_exit(0);
|
||||
}
|
||||
assert(start((void *)1, "{}", NULL));
|
||||
for (unsigned i = 0; i < 1000 && !receiver_runtime.output.awaiting; i++) {
|
||||
tick(NULL);
|
||||
usleep(1000);
|
||||
}
|
||||
for (unsigned i = 0; i < 1000 && (!capture_ctx.handle || !receiver_runtime.output.awaiting);
|
||||
i++) {
|
||||
tick(NULL);
|
||||
usleep(1000);
|
||||
}
|
||||
assert(capture_ctx.handle && initializes == 1 && receiver_runtime.output.awaiting);
|
||||
uint64_t before = milliseconds();
|
||||
assert(status((void *)1, "{}", NULL));
|
||||
assert(milliseconds() - before < 100 && strstr(answer, "\"running\":true"));
|
||||
before = milliseconds();
|
||||
assert(stop((void *)1, "{}", NULL));
|
||||
assert(milliseconds() - before < 100);
|
||||
assert(!capture_ctx.handle && finalizes == 1 && retries.paused);
|
||||
for (unsigned i = 0; i < 1000 && receiver_runtime.output.stage != OUTPUT_IDLE; i++) {
|
||||
tick(NULL);
|
||||
usleep(1000);
|
||||
}
|
||||
assert(receiver_runtime.output.stage == OUTPUT_IDLE && initializes == 1 && finalizes == 1);
|
||||
int result;
|
||||
waitpid(child, &result, 0);
|
||||
assert(WIFEXITED(result) && !WEXITSTATUS(result));
|
||||
assert(access(DEV_MODE, F_OK) != 0);
|
||||
close(server);
|
||||
dlclose(playback_json.lib);
|
||||
puts("PASS: service Start/Stop during connect, delayed receiver ACK leaves Status/Stop "
|
||||
"responsive, fake capture lifecycle, asynchronous clear and no restart after Stop");
|
||||
}
|
||||
Reference in new issue
Block a user