summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorAlbert Cervin <albert@acervin.com>2023-01-26 13:07:07 +0100
committerAlbert Cervin <albert@acervin.com>2023-01-26 13:07:07 +0100
commite65158a0326108d1fc724ee683b7fa900ef2671a (patch)
tree9bad30b377a326e0d0e3101c4f96228ae7a41673 /test
parent9a2b138a03e27d0f04101fe6ae3977d79518c513 (diff)
downloaddged-e65158a0326108d1fc724ee683b7fa900ef2671a.tar.gz
dged-e65158a0326108d1fc724ee683b7fa900ef2671a.tar.xz
dged-e65158a0326108d1fc724ee683b7fa900ef2671a.zip
More tests and documentation
Also, split out platform-specific parts and add mocks for tests.
Diffstat (limited to 'test')
-rw-r--r--test/command.c22
-rw-r--r--test/fake-reactor.c47
-rw-r--r--test/fake-reactor.h13
-rw-r--r--test/keyboard.c208
-rw-r--r--test/main.c17
-rw-r--r--test/test.h1
6 files changed, 307 insertions, 1 deletions
diff --git a/test/command.c b/test/command.c
index 738f5f9..be5fffc 100644
--- a/test/command.c
+++ b/test/command.c
@@ -72,8 +72,30 @@ void test_lookup_command() {
"Expected the found function to have the correct name");
}
+int32_t failing_command(struct command_ctx ctx, int argc, const char *argv[]) {
+ return 100;
+}
+
+void test_execute_command() {
+ struct commands cmds = single_fake_command("fake");
+ struct command *cmd = lookup_command(&cmds, "fake");
+
+ int32_t res = execute_command(cmd, &cmds, NULL, NULL, 0, NULL);
+ ASSERT(res == 0, "Expected to be able to execute command successfully");
+
+ register_command(&cmds, (struct command){
+ .fn = failing_command,
+ .name = "fejl",
+ .userdata = NULL,
+ });
+ struct command *fail_cmd = lookup_command(&cmds, "fejl");
+ int32_t res2 = execute_command(fail_cmd, &cmds, NULL, NULL, 0, NULL);
+ ASSERT(res2 != 0, "Expected failing command to fail");
+}
+
void run_command_tests() {
run_test(test_command_registry_create);
run_test(test_register_command);
run_test(test_lookup_command);
+ run_test(test_execute_command);
}
diff --git a/test/fake-reactor.c b/test/fake-reactor.c
new file mode 100644
index 0000000..aafe8a3
--- /dev/null
+++ b/test/fake-reactor.c
@@ -0,0 +1,47 @@
+#include "fake-reactor.h"
+#include <stdlib.h>
+
+struct reactor {
+ struct fake_reactor_impl *impl;
+};
+
+struct reactor *reactor_create() {
+ return (struct reactor *)calloc(1, sizeof(struct reactor));
+}
+
+void reactor_destroy(struct reactor *reactor) { free(reactor); }
+
+void reactor_update(struct reactor *reactor) {}
+bool reactor_poll_event(struct reactor *reactor, uint32_t ev_id) {
+ if (reactor->impl != NULL) {
+ return reactor->impl->poll_event(reactor->impl->userdata, ev_id);
+ } else {
+ return false;
+ }
+}
+
+uint32_t reactor_register_interest(struct reactor *reactor, int fd,
+ enum interest interest) {
+ if (reactor->impl != NULL) {
+ return reactor->impl->register_interest(reactor->impl->userdata, fd,
+ interest);
+ } else {
+ return 0;
+ }
+}
+
+void reactor_unregister_interest(struct reactor *reactor, uint32_t ev_id) {
+ if (reactor->impl != NULL) {
+ return reactor->impl->unregister_interest(reactor->impl->userdata, ev_id);
+ }
+}
+
+struct reactor *fake_reactor_create(struct fake_reactor_impl *impl) {
+ struct reactor *r = reactor_create();
+ set_reactor_impl(r, impl);
+ return r;
+}
+
+void set_reactor_impl(struct reactor *reactor, struct fake_reactor_impl *impl) {
+ reactor->impl = impl;
+}
diff --git a/test/fake-reactor.h b/test/fake-reactor.h
new file mode 100644
index 0000000..04d8306
--- /dev/null
+++ b/test/fake-reactor.h
@@ -0,0 +1,13 @@
+#include "reactor.h"
+#include <stdbool.h>
+#include <stdint.h>
+
+struct fake_reactor_impl {
+ bool (*poll_event)(void *userdata, uint32_t ev_id);
+ uint32_t (*register_interest)(void *userdata, int fd, enum interest interest);
+ void (*unregister_interest)(void *userdata, uint32_t ev_id);
+ void *userdata;
+};
+
+struct reactor *fake_reactor_create(struct fake_reactor_impl *impl);
+void set_reactor_impl(struct reactor *reactor, struct fake_reactor_impl *impl);
diff --git a/test/keyboard.c b/test/keyboard.c
new file mode 100644
index 0000000..b85c4ad
--- /dev/null
+++ b/test/keyboard.c
@@ -0,0 +1,208 @@
+#include "assert.h"
+#include "fake-reactor.h"
+#include "test.h"
+
+#include "keyboard.h"
+#include "unistd.h"
+#include <stdlib.h>
+#include <string.h>
+
+struct call_count {
+ uint32_t poll;
+ uint32_t reg;
+ uint32_t unreg;
+};
+
+bool fake_poll(void *userdata, uint32_t ev_id) {
+ if (userdata != NULL) {
+ struct call_count *cc = (struct call_count *)userdata;
+ ++cc->poll;
+ }
+ return true;
+}
+uint32_t fake_register_interest(void *userdata, int fd,
+ enum interest interest) {
+ if (userdata != NULL) {
+ struct call_count *cc = (struct call_count *)userdata;
+ ++cc->reg;
+ }
+ return 0;
+}
+
+void fake_unregister_interest(void *userdata, uint32_t ev_id) {
+ if (userdata != NULL) {
+ struct call_count *cc = (struct call_count *)userdata;
+ ++cc->unreg;
+ }
+}
+
+struct fake_keyboard {
+ struct keyboard inner;
+ struct reactor *reactor;
+ int writefd;
+};
+
+struct fake_keyboard create_fake_keyboard(struct fake_reactor_impl *reactor) {
+ struct reactor *r = fake_reactor_create(reactor);
+
+ int pipefd[2];
+ int res = pipe(pipefd);
+ ASSERT(res == 0, "Failed to create a pipe?");
+
+ struct keyboard k = keyboard_create_fd(r, pipefd[0]);
+
+ return (struct fake_keyboard){
+ .inner = k,
+ .reactor = r,
+ .writefd = pipefd[1],
+ };
+}
+
+void fake_keyboard_write(struct fake_keyboard *kbd, const char *s) {
+ write(kbd->writefd, s, strlen(s));
+}
+
+void fake_keyboard_close_write(struct fake_keyboard *kbd) {
+ close(kbd->writefd);
+}
+
+void fake_keyboard_destroy(struct fake_keyboard *kbd) {
+ fake_keyboard_close_write(kbd);
+}
+
+void simple_key() {
+ struct call_count cc = {0};
+ struct fake_reactor_impl fake = {
+ .poll_event = fake_poll,
+ .register_interest = fake_register_interest,
+ .unregister_interest = fake_unregister_interest,
+ .userdata = &cc,
+ };
+ struct fake_keyboard k = create_fake_keyboard(&fake);
+ ASSERT(cc.reg == 1, "Expected keyboard to register read interest");
+
+ fake_keyboard_write(&k, "q");
+ fake_keyboard_close_write(&k);
+
+ struct keyboard_update upd = keyboard_update(&k.inner, k.reactor, malloc);
+
+ ASSERT(upd.nkeys == 1, "Expected to get 1 key from update");
+ ASSERT(cc.poll, "Expected keyboard update to call reactor poll");
+
+ fake_keyboard_destroy(&k);
+ free(upd.keys);
+ free(upd.raw);
+}
+
+void ctrl_key() {
+ struct fake_reactor_impl fake = {
+ .poll_event = fake_poll,
+ .register_interest = fake_register_interest,
+ .unregister_interest = fake_unregister_interest,
+ .userdata = NULL,
+ };
+ struct fake_keyboard k = create_fake_keyboard(&fake);
+ fake_keyboard_write(&k, "");
+ fake_keyboard_close_write(&k);
+
+ struct keyboard_update upd = keyboard_update(&k.inner, k.reactor, malloc);
+ ASSERT(upd.nkeys == 2, "Expected to get 2 keys from update");
+ ASSERT(upd.keys[0].mod == Ctrl && upd.keys[0].key == 'H',
+ "Expected first key to be c-h");
+ ASSERT(upd.keys[1].mod == Ctrl && upd.keys[1].key == 'P',
+ "Expected first key to be c-p");
+
+ fake_keyboard_destroy(&k);
+ free(upd.keys);
+ free(upd.raw);
+}
+
+void meta_key() {
+ struct fake_reactor_impl fake = {
+ .poll_event = fake_poll,
+ .register_interest = fake_register_interest,
+ .unregister_interest = fake_unregister_interest,
+ .userdata = NULL,
+ };
+ struct fake_keyboard k = create_fake_keyboard(&fake);
+ fake_keyboard_write(&k, "d[x");
+ fake_keyboard_close_write(&k);
+
+ struct keyboard_update upd = keyboard_update(&k.inner, k.reactor, malloc);
+ ASSERT(upd.nkeys == 3, "Expected to get 3 keys from update");
+ ASSERT(upd.keys[0].mod == Meta && upd.keys[0].key == 'd',
+ "Expected first key to be m-d");
+ ASSERT(upd.keys[1].mod == Meta && upd.keys[1].key == '[',
+ "Expected second key to be m-[");
+ ASSERT(upd.keys[2].mod == Meta && upd.keys[2].key == 'x',
+ "Expected third key to be m-x");
+
+ fake_keyboard_destroy(&k);
+ free(upd.keys);
+ free(upd.raw);
+}
+
+void spec_key() {
+ struct fake_reactor_impl fake = {
+ .poll_event = fake_poll,
+ .register_interest = fake_register_interest,
+ .unregister_interest = fake_unregister_interest,
+ .userdata = NULL,
+ };
+ struct fake_keyboard k = create_fake_keyboard(&fake);
+ fake_keyboard_write(&k, "[6~");
+ fake_keyboard_close_write(&k);
+
+ struct keyboard_update upd = keyboard_update(&k.inner, k.reactor, malloc);
+ ASSERT(upd.nkeys == 2, "Expected to get 2 keys from update");
+ ASSERT(upd.keys[0].mod == Spec && upd.keys[0].key == 'A',
+ "Expected first key to be up arrow");
+ ASSERT(upd.keys[1].mod == Spec && upd.keys[1].key == '6',
+ "Expected second key to be PgDn");
+
+ fake_keyboard_destroy(&k);
+ free(upd.keys);
+ free(upd.raw);
+}
+
+void test_utf8() {
+ struct fake_reactor_impl fake = {
+ .poll_event = fake_poll,
+ .register_interest = fake_register_interest,
+ .unregister_interest = fake_unregister_interest,
+ .userdata = NULL,
+ };
+ struct fake_keyboard k = create_fake_keyboard(&fake);
+ fake_keyboard_write(&k, "šŸŽ ");
+ fake_keyboard_close_write(&k);
+
+ struct keyboard_update upd = keyboard_update(&k.inner, k.reactor, malloc);
+ ASSERT(upd.nbytes == 4, "Expected there to be four bytes of raw input");
+ ASSERT(upd.nkeys == 1, "Expected to get 1 key from update");
+ ASSERT(upd.keys[0].start == 0 && upd.keys[0].end == 4,
+ "Expected first key to be 4 bytes");
+
+ fake_keyboard_destroy(&k);
+ free(upd.keys);
+ free(upd.raw);
+}
+
+void test_key_equal() {
+ struct key k1 = {.mod = Ctrl, .key = 'A'};
+ ASSERT(key_equal(&k1, &k1), "Expected key to be equal to itself");
+ ASSERT(key_equal_char(&k1, Ctrl, 'A'), "Expected key to be c-a");
+
+ struct key k2 = {.mod = None, .key = 'A'};
+ ASSERT(!key_equal(&k1, &k2), "Expected key to not be equal to different key");
+ ASSERT(!key_equal_char(&k2, Spec, 'A'),
+ "Expected yet another different key to not be the same");
+}
+
+void run_keyboard_tests() {
+ run_test(simple_key);
+ run_test(ctrl_key);
+ run_test(meta_key);
+ run_test(spec_key);
+ run_test(test_utf8);
+ run_test(test_key_equal);
+}
diff --git a/test/main.c b/test/main.c
index 8102a58..68241f9 100644
--- a/test/main.c
+++ b/test/main.c
@@ -1,7 +1,10 @@
#include <locale.h>
#include <signal.h>
+#include <stdint.h>
#include <stdlib.h>
+#include <time.h>
+#include "bits/time.h"
#include "test.h"
void handle_abort() { exit(1); }
@@ -10,6 +13,9 @@ int main() {
setlocale(LC_ALL, "");
signal(SIGABRT, handle_abort);
+ struct timespec test_begin;
+ clock_gettime(CLOCK_MONOTONIC, &test_begin);
+
printf("\nšŸŒ \x1b[1;36mRunning utf8 tests...\x1b[0m\n");
run_utf8_tests();
@@ -22,6 +28,15 @@ int main() {
printf("\nšŸ’ \x1b[1;36mRunning command tests...\x1b[0m\n");
run_command_tests();
- printf("\nšŸŽ‰ \x1b[1;32mDone! All tests successful!\x1b[0m\n");
+ printf("\nšŸ“  \x1b[1;36mRunning keyboard tests...\x1b[0m\n");
+ run_keyboard_tests();
+
+ struct timespec elapsed;
+ clock_gettime(CLOCK_MONOTONIC, &elapsed);
+ uint64_t elapsed_nanos =
+ ((uint64_t)elapsed.tv_sec * 1e9 + (uint64_t)elapsed.tv_nsec) -
+ ((uint64_t)test_begin.tv_sec * 1e9 + (uint64_t)test_begin.tv_nsec);
+ printf("\nšŸŽ‰ \x1b[1;32mDone! All tests successful in %.2f ms!\x1b[0m\n",
+ (double)elapsed_nanos / 1e6);
return 0;
}
diff --git a/test/test.h b/test/test.h
index 3fdcd0d..2d9d8af 100644
--- a/test/test.h
+++ b/test/test.h
@@ -10,3 +10,4 @@ void run_buffer_tests();
void run_utf8_tests();
void run_text_tests();
void run_command_tests();
+void run_keyboard_tests();