diff --git a/src/client.c b/tests/client.c similarity index 100% rename from src/client.c rename to tests/client.c diff --git a/tests/index.html b/tests/index.html new file mode 100644 index 0000000..c7a91ec --- /dev/null +++ b/tests/index.html @@ -0,0 +1,3 @@ + +Welcome to the example.re homepage! + diff --git a/src/main.c b/tests/main.c similarity index 100% rename from src/main.c rename to tests/main.c diff --git a/src/server.c b/tests/server.c similarity index 100% rename from src/server.c rename to tests/server.c diff --git a/tests/test.h b/tests/test.h new file mode 100644 index 0000000..99d59f6 --- /dev/null +++ b/tests/test.h @@ -0,0 +1,18 @@ +#pragma once +#include +#include +#include + +#define ASSERT(cond) \ + do { \ + if (!(cond)) { \ + fprintf(stderr, "FAIL %s:%d %s\n", __FILE__, __LINE__, #cond); \ + exit(1); \ + } \ + } while (0) + +#define ASSERT_EQ(a, b) ASSERT((a) == (b)) +#define ASSERT_NE(a, b) ASSERT((a) != (b)) +#define ASSERT_STR_EQ(a, b) ASSERT(strcmp((a), (b)) == 0) +#define ASSERT_NULL(p) ASSERT((p) == NULL) +#define ASSERT_NOT_NULL(p) ASSERT((p) != NULL) diff --git a/tests/test_enchufe.c b/tests/test_enchufe.c new file mode 100644 index 0000000..c4c521b --- /dev/null +++ b/tests/test_enchufe.c @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include "enchufe.h" +#include "test.h" + +static void test_atob_len(void) { + Buffer b = atob("hello"); + ASSERT_EQ(b.len, 5); +} + +static void test_atob_contents(void) { + Buffer b = atob("hello"); + ASSERT(memcmp(b.buf, "hello", 5) == 0); +} + +static void test_atob_empty(void) { + Buffer b = atob(""); + ASSERT_EQ(b.len, 0); +} + +static void test_nuevo_valid_fd(void) { + FD fd = nuevo(); + ASSERT(fd >= 0); + close(fd); +} + +static void test_receptaculo_fields(void) { + IPv4 ip = {.bytes = {127, 0, 0, 1}}; + Port port = htons(8080); + Receptaculo r = receptaculo(ip, port); + ASSERT_EQ(r.addr.sin_family, AF_INET); + ASSERT_EQ(r.addr.sin_port, port); + ASSERT_EQ(r.addr.sin_addr.s_addr, ip.ip); + ASSERT_EQ(r.addrlen, (socklen_t)sizeof(struct sockaddr_in)); +} + +static void test_aplasta_copies_fields(void) { + FD fd = nuevo(); + IPv4 ip = {.bytes = {127, 0, 0, 1}}; + Port port = htons(9090); + Receptaculo r = receptaculo(ip, port); + Enchufe e = aplasta(fd, r); + ASSERT_EQ(e.fd, fd); + ASSERT_EQ(e.addr.sin_port, r.addr.sin_port); + ASSERT_EQ(e.addr.sin_addr.s_addr, r.addr.sin_addr.s_addr); + ASSERT_EQ(e.addrlen, r.addrlen); + close(fd); +} + +int main(void) { + test_atob_len(); + test_atob_contents(); + test_atob_empty(); + test_nuevo_valid_fd(); + test_receptaculo_fields(); + test_aplasta_copies_fields(); + printf("test_enchufe: all tests passed\n"); + return 0; +} diff --git a/tests/test_network.c b/tests/test_network.c new file mode 100644 index 0000000..96f3ebb --- /dev/null +++ b/tests/test_network.c @@ -0,0 +1,103 @@ +#include +#include +#include +#include +#include +#include "enchufe.h" +#include "test.h" + +#define MSG "ping" + +/* Bind to port 0 (OS picks a free port), return the assigned port in + network byte order via *out_port. */ +static Enchufe bind_ephemeral(IPv4 ip, Port *out_port) { + Enchufe s = enchufa(ip, htons(0)); + amarra(s); + + struct sockaddr_in actual = {0}; + socklen_t alen = sizeof(actual); + getsockname(s.fd, (struct sockaddr *)&actual, &alen); + *out_port = actual.sin_port; /* already network byte order */ + return s; +} + +static void test_send_recv(void) { + IPv4 lo = {.bytes = {127, 0, 0, 1}}; + Port port = 0; + Enchufe server = bind_ephemeral(lo, &port); + escucha(server, 1); + + pid_t pid = fork(); + ASSERT(pid >= 0); + + if (pid == 0) { + Enchufe client = enchufa(lo, port); + conecta(client); + zumba(client, atob(MSG)); + desenchufa(client); + exit(0); + } + + Enchufe peer = acepta(server); + + Byte raw[32] = {0}; + Buffer buf = {.buf = raw, .len = sizeof(raw) - 1}; + size_t n = recibe(peer, buf); + + ASSERT_EQ(n, strlen(MSG)); + ASSERT(memcmp(raw, MSG, n) == 0); + + desenchufa(peer); + desenchufa(server); + + int status = 0; + waitpid(pid, &status, 0); + ASSERT(WIFEXITED(status) && WEXITSTATUS(status) == 0); +} + +static void test_multi_send(void) { + IPv4 lo = {.bytes = {127, 0, 0, 1}}; + Port port = 0; + Enchufe server = bind_ephemeral(lo, &port); + escucha(server, 1); + + pid_t pid = fork(); + ASSERT(pid >= 0); + + if (pid == 0) { + Enchufe client = enchufa(lo, port); + conecta(client); + zumba(client, atob("foo")); + zumba(client, atob("bar")); + desenchufa(client); + exit(0); + } + + Enchufe peer = acepta(server); + + /* Accumulate until EOF (child closes socket). */ + Byte raw[64] = {0}; + size_t total = 0; + while (total < sizeof(raw) - 1) { + Buffer b = {.buf = raw + total, .len = sizeof(raw) - 1 - total}; + size_t n = recibe(peer, b); + if (n == 0) break; + total += n; + } + + ASSERT(memcmp(raw, "foobar", 6) == 0); + + desenchufa(peer); + desenchufa(server); + + int status = 0; + waitpid(pid, &status, 0); + ASSERT(WIFEXITED(status) && WEXITSTATUS(status) == 0); +} + +int main(void) { + test_send_recv(); + test_multi_send(); + printf("test_network: all tests passed\n"); + return 0; +}