added tests showcasing -fportcosmo capabilities

This commit is contained in:
Gautham 2023-06-17 14:58:57 -05:00
parent f3d3412c3b
commit 21f7552285
8 changed files with 579 additions and 0 deletions

View file

@ -239,6 +239,7 @@ include test/libc/stdio/test.mk
include test/libc/zipos/test.mk include test/libc/zipos/test.mk
include test/libc/release/test.mk include test/libc/release/test.mk
include test/libc/test.mk include test/libc/test.mk
include test/portcosmo/test.mk
include test/net/http/test.mk include test/net/http/test.mk
include test/net/https/test.mk include test/net/https/test.mk
include test/net/finger/test.mk include test/net/finger/test.mk

View file

@ -0,0 +1,51 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
#include "test/portcosmo/constants.h"
const int TWO = 175;
const int THREE = 201;
/* the above int values are unknown at compile-time, but
* ifswitch.c and initstruct.c will both compile without
* raising an error when the -fportcosmo flag is passed
* to a gcc patched with third_party/gcc/portcosmo.patch.
*
* what -fportcosmo does is it modifies the AST so that
* the following errors are intercepted and avoided:
*
* - "case is not constant" -- if there is a switch stmt
* that uses the values TWO or THREE in its cases, it
* will be rewritten into an if-else statement so as
* to prevent this "case is not constant" error.
*
* - "initializer element is not constant" - if there is
* global or static struct that is being initialized
* with the values TWO or THREE, temporaries will be
* used to prevent this error, and a small conditional
* or an __attribute__ ((constructor)) will added to
* the code that later fills the correct struct values.
*/

View file

@ -0,0 +1,14 @@
#ifndef TEST_PORTCOSMO_CONSTANTS_H
#define TEST_PORTCOSMO_CONSTANTS_H
extern const int TWO;
extern const int THREE;
#define TWO TWO
#define THREE THREE
#define __tmpcosmo_TWO -205
#define __tmpcosmo_THREE -209
#endif /* TEST_PORTCOSMO_CONSTANTS_H */

View file

@ -0,0 +1,124 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/isystem/stdio.h"
#include "libc/isystem/string.h"
#include "libc/testlib/testlib.h"
#include "test/portcosmo/constants.h"
/* TODO(ahgamut):
* enumerator values have to be known at compile time,
* currently it is not possible to rewrite the AST to
* handle enums with non-constant values.
*
enum circumstances { extenuating = TWO };
*
*/
static void arbswitch(int value, const char **res) {
*res = NULL;
switch (value) {
case 1: {
*res = "1";
break;
}
case TWO:
*res = "TWO";
break;
case THREE: {
*res = "THREE";
break;
}
/*
* TODO(ahgamut): check if arbitrary expressions in switch-cases
* are a common thing before updating portcosmo.patch, right now
* the below case will cause a compilation error:
*
case (TWO * THREE):
*res = "TWO * THREE";
break;
*/
case 0:
*res = "0";
}
if (*res == NULL) {
*res = "wut";
}
}
TEST(portcosmo, arbitrary_switch) {
const char *r = NULL;
arbswitch(1, &r);
ASSERT_STREQ(r, "1");
arbswitch(TWO, &r);
ASSERT_STREQ(r, "TWO");
arbswitch(THREE, &r);
ASSERT_STREQ(r, "THREE");
arbswitch(20, &r);
ASSERT_STREQ(r, "wut");
arbswitch(0, &r);
ASSERT_STREQ(r, "0");
arbswitch(TWO * THREE, &r);
/* ASSERT_STREQ(r, "TWO * THREE"); */
ASSERT_STREQ(r, "wut");
}
struct toy {
int id;
int value;
};
TEST(portcosmo, initstruct_WRONG) {
/* this is an example of portcosmo initializing structs
* incorrectly. it can only happen if one of the values
* in the struct initializer before the modified value
* JUST SO happens to be equal to the temporary value we
* have #defined somewhere. */
static struct toy w1 = {.id = -205, .value = TWO};
/* here -205 JUST SO happens to be equal to __tmpcosmo_TWO,
* so the struct w1 ends up being initialized with wrong values */
/* this is what WRONGLY happens,
* because in portcosmo we are unable
* to determine the exact (row,col)
* location of struct fields */
ASSERT_EQ(TWO, w1.id); // WRONG!
ASSERT_EQ(-205, w1.value); // WRONG!
/* this is what SHOULD happen */
ASSERT_NE(-205, w1.id); // should be ASSERT_EQ
ASSERT_NE(TWO, w1.value); // should be ASSERT_EQ
}

View file

@ -0,0 +1,162 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/isystem/stdio.h"
#include "libc/isystem/string.h"
#include "libc/testlib/testlib.h"
#include "test/portcosmo/constants.h"
#define CASEMACRO(X) case X:
static void basicswitch(int value, const char **res) {
*res = NULL;
switch (value) {
case 1: {
// might create a variable in this scope
int a = 21;
*res = "1";
break;
}
#ifdef TWO
CASEMACRO(TWO)
*res = "TWO";
// fall-through
#endif
case THREE: {
int c = 22;
*res = "THREE";
break;
}
case -THREE:
*res = "-THREE";
break;
case ~TWO:
int d = 111;
*res = "~TWO";
break;
case 19 ... 27:
*res = "19-27";
break;
case 0:
*res = "0";
// fall-through
default:
int z = 12;
*res = "default";
break;
}
if (*res == NULL) {
*res = "wut";
}
}
TEST(portcosmo, ifswitch) {
const char *r = NULL;
basicswitch(1, &r);
ASSERT_STREQ(r, "1");
basicswitch(TWO, &r);
ASSERT_STREQ(r, "THREE"); // because fallthrough
basicswitch(THREE, &r);
ASSERT_STREQ(r, "THREE");
basicswitch(-THREE, &r);
ASSERT_STREQ(r, "-THREE");
basicswitch(~TWO, &r);
ASSERT_STREQ(r, "~TWO");
basicswitch(20, &r);
ASSERT_STREQ(r, "19-27");
basicswitch(0, &r);
ASSERT_STREQ(r, "default"); // because fallthrough
basicswitch(29, &r);
ASSERT_STREQ(r, "default");
basicswitch(999, &r);
ASSERT_STREQ(r, "default");
}
/* testing switch without default */
static void nodefault(int value, const char **res) {
*res = NULL;
switch (value) {
case 1: {
*res = "1";
break;
}
#ifdef TWO
CASEMACRO(TWO)
*res = "TWO";
break;
#endif
case THREE: {
*res = "THREE";
break;
}
case 0:
*res = "0";
}
if (*res == NULL) {
*res = "wut";
}
}
TEST(portcosmo, ifswitch_nodefault) {
const char *r = NULL;
nodefault(1, &r);
ASSERT_STREQ(r, "1");
nodefault(TWO, &r);
ASSERT_STREQ(r, "TWO");
nodefault(THREE, &r);
ASSERT_STREQ(r, "THREE");
nodefault(0, &r);
ASSERT_STREQ(r, "0");
nodefault(29, &r);
ASSERT_STREQ(r, "wut");
nodefault(999, &r);
ASSERT_STREQ(r, "wut");
}

View file

@ -0,0 +1,164 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/isystem/stdio.h"
#include "libc/isystem/string.h"
#include "libc/testlib/testlib.h"
#include "test/portcosmo/constants.h"
struct toy {
int id;
int value;
};
struct toyroom {
int id;
int value;
struct toy x1;
struct toy x2;
struct toy x3;
struct toy x4;
};
static int v1 = TWO;
static int arr1[] = {TWO, THREE, ~THREE, ~TWO};
struct toy t0 = {.id = 30, .value = THREE};
static struct toy t1 = {.id = 31, .value = TWO};
static struct toy ta[] = {{.id = 1, .value = ~TWO},
{.id = ~THREE, .value = TWO},
{.value = TWO, .id = -THREE},
{.id = THREE, .value = 1},
{.id = 7, .value = THREE}};
static struct toyroom r1 = {
.id = 2,
.value = -TWO,
.x1 = {.id = 1, .value = TWO},
.x2 = {.id = ~TWO, .value = 1},
.x3 = {.value = TWO, .id = -THREE},
.x4 = {.id = THREE, .value = ~THREE},
};
TEST(portcosmo, initstruct_global) {
ASSERT_EQ(v1, TWO);
ASSERT_EQ(arr1[0], TWO);
ASSERT_EQ(arr1[1], THREE);
ASSERT_EQ(arr1[2], ~THREE);
ASSERT_EQ(arr1[3], ~TWO);
ASSERT_EQ(t1.id, 31);
ASSERT_EQ(t1.value, TWO);
ASSERT_EQ(ta[0].id, 1);
ASSERT_EQ(ta[0].value, ~TWO);
ASSERT_EQ(ta[1].id, ~THREE);
ASSERT_EQ(ta[1].value, TWO);
ASSERT_EQ(ta[2].id, -THREE);
ASSERT_EQ(ta[2].value, TWO);
ASSERT_EQ(ta[3].id, THREE);
ASSERT_EQ(ta[3].value, 1);
ASSERT_EQ(ta[4].id, 7);
ASSERT_EQ(ta[4].value, THREE);
ASSERT_EQ(r1.id, 2);
ASSERT_EQ(r1.value, -TWO);
ASSERT_EQ(r1.x1.id, 1);
ASSERT_EQ(r1.x1.value, TWO);
ASSERT_EQ(r1.x2.id, ~TWO);
ASSERT_EQ(r1.x2.value, 1);
ASSERT_EQ(r1.x3.id, -THREE);
ASSERT_EQ(r1.x3.value, TWO);
ASSERT_EQ(r1.x4.id, THREE);
ASSERT_EQ(r1.x4.value, ~THREE);
}
void init_func() {
static struct toy box[] = {
{.id = 1, .value = 1}, {.id = -THREE, .value = THREE},
{.id = THREE, .value = 1}, {.id = -TWO, .value = ~TWO},
{.id = TWO, .value = THREE}, {.id = ~THREE, .value = TWO},
};
static struct toyroom r2 = {
.id = 2,
.value = THREE,
.x1 = {.id = 1, .value = TWO},
.x2 = {.id = ~TWO, .value = 1},
.x3 = {.id = TWO, .value = ~THREE},
.x4 = {.id = THREE, .value = -THREE},
};
static struct toy t = {.id = 22, .value = TWO};
static int v = TWO;
static int vals[] = {1, TWO, -THREE, ~TWO, 1};
static int count = 0;
ASSERT_EQ(box[0].id, 1);
ASSERT_EQ(box[0].value, 1);
ASSERT_EQ(box[1].id, -THREE);
ASSERT_EQ(box[1].value, THREE);
ASSERT_EQ(box[2].id, THREE);
ASSERT_EQ(box[2].value, 1);
ASSERT_EQ(box[3].id, -TWO);
ASSERT_EQ(box[3].value, ~TWO);
ASSERT_EQ(box[4].id, TWO);
ASSERT_EQ(box[4].value, THREE);
ASSERT_EQ(box[5].id, ~THREE);
ASSERT_EQ(box[5].value, TWO);
ASSERT_EQ(r2.id, 2);
ASSERT_EQ(r2.value, THREE);
ASSERT_EQ(r2.x1.id, 1);
ASSERT_EQ(r2.x1.value, TWO);
ASSERT_EQ(r2.x2.id, ~TWO);
ASSERT_EQ(r2.x2.value, 1);
ASSERT_EQ(r2.x3.id, TWO);
ASSERT_EQ(r2.x3.value, ~THREE);
ASSERT_EQ(r2.x4.id, THREE);
ASSERT_EQ(r2.x4.value, -THREE);
ASSERT_EQ(t.id, 22);
ASSERT_EQ(t.value, TWO + count);
ASSERT_EQ(vals[0], 1 + 5 * count);
ASSERT_EQ(vals[1], TWO + 5 * count);
ASSERT_EQ(vals[2], -THREE + 5 * count);
ASSERT_EQ(vals[3], ~TWO + 5 * count);
ASSERT_EQ(vals[4], 1 + 5 * count);
/* when we call this function a second time,
* we can confirm that the values were not
* wrongly initialized twice */
for (int i = 0; i < 5; ++i) {
vals[i] += 5;
}
t.value += 1;
count += 1;
}
TEST(portcosmo, initstruct_local) {
init_func();
init_func();
}

62
test/portcosmo/test.mk Normal file
View file

@ -0,0 +1,62 @@
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
PKGS += TEST_PORTCOSMO
TEST_PORTCOSMO_SRCS := $(wildcard test/portcosmo/*.c)
TEST_PORTCOSMO_SRCS_TEST = $(filter %_test.c,$(TEST_PORTCOSMO_SRCS))
TEST_PORTCOSMO_OBJS = \
$(TEST_PORTCOSMO_SRCS:%.c=o/$(MODE)/%.o)
TEST_PORTCOSMO_COMS = \
$(TEST_PORTCOSMO_SRCS_TEST:%.c=o/$(MODE)/%.com)
TEST_PORTCOSMO_BINS = \
$(TEST_PORTCOSMO_COMS) \
$(TEST_PORTCOSMO_COMS:%=%.dbg)
TEST_PORTCOSMO_TESTS = \
$(TEST_PORTCOSMO_SRCS_TEST:%.c=o/$(MODE)/%.com.ok)
TEST_PORTCOSMO_CHECKS = \
$(TEST_PORTCOSMO_SRCS_TEST:%.c=o/$(MODE)/%.com.runs)
TEST_PORTCOSMO_DIRECTDEPS = \
LIBC_FMT \
LIBC_INTRIN \
LIBC_LOG \
LIBC_MEM \
LIBC_NEXGEN32E \
LIBC_RUNTIME \
LIBC_STDIO \
LIBC_STR \
LIBC_STUBS \
LIBC_SYSV \
LIBC_TESTLIB \
LIBC_X
TEST_PORTCOSMO_DEPS := \
$(call uniq,$(foreach x,$(TEST_PORTCOSMO_DIRECTDEPS),$($(x))))
o/$(MODE)/test/portcosmo/%.o: \
CFLAGS += -fportcosmo
o/$(MODE)/test/portcosmo/portcosmo.pkg: \
$(TEST_PORTCOSMO_OBJS) \
$(foreach x,$(TEST_PORTCOSMO_DIRECTDEPS),$($(x)_A).pkg)
o/$(MODE)/test/portcosmo/%.com.dbg: \
$(TEST_PORTCOSMO_DEPS) \
o/$(MODE)/test/portcosmo/%.o \
o/$(MODE)/test/portcosmo/constants.o \
o/$(MODE)/test/portcosmo/portcosmo.pkg \
$(LIBC_TESTMAIN) \
$(CRT) \
$(APE_NO_MODIFY_SELF)
@$(APELINK)
.PHONY: o/$(MODE)/test/portcosmo
o/$(MODE)/test/portcosmo: \
$(TEST_PORTCOSMO_BINS) \
$(TEST_PORTCOSMO_CHECKS)

View file

@ -4,5 +4,6 @@
.PHONY: o/$(MODE)/test .PHONY: o/$(MODE)/test
o/$(MODE)/test: o/$(MODE)/test/dsp \ o/$(MODE)/test: o/$(MODE)/test/dsp \
o/$(MODE)/test/libc \ o/$(MODE)/test/libc \
o/$(MODE)/test/portcosmo \
o/$(MODE)/test/net \ o/$(MODE)/test/net \
o/$(MODE)/test/tool o/$(MODE)/test/tool