Skip to content

Commit

Permalink
Add some tests + change s8_stopper
Browse files Browse the repository at this point in the history
  • Loading branch information
btrkeks committed May 4, 2024
1 parent e2033cc commit 9e187b6
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 74 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ jobs:
- run: clang-format --version

- run: make clean analyse
- run: make tests
- run: ./tests

on:
push:
Expand Down
11 changes: 5 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,9 @@ DEBUG_CFLAGS=-DDEBUG \
-Wall -Wextra -Wpedantic -Wstrict-prototypes -Wdouble-promotion -Wshadow \
-Wno-unused-parameter -Wno-sign-conversion -Wno-unused-function -Wpointer-arith \
-Wmissing-prototypes -Wstrict-prototypes -Wstrict-overflow -Wcast-align \
-Wno-maybe-uninitialized \
-fsanitize=leak,address,undefined -fsanitize-undefined-trap-on-error -fstack-protector-strong \
-Og -ggdb
RELEASE_CFLAGS=-O3 -flto -march=native
-Og -ggdb
RELEASE_CFLAGS=-O3 -flto -march=native -Wmaybe-uninitialized

FILES=dictpopup.c util.c platformdep.c deinflector.c settings.c db.c ankiconnectc.c database.c jppron.c pdjson.c
FILES_H=ankiconnectc.h db.h deinflector.h settings.h util.h platformdep.h database.h jppron.h pdjson.h
Expand All @@ -53,10 +52,10 @@ debug: $(bins)
debug: CFLAGS+=$(DEBUG_CFLAGS)

dictpopup: $(SRC) $(SRC_H)
$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ src/gtk3popup.c $(SRC) $(LDLIBS)
$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(SDIR)/gtk3popup.c $(SRC) $(LDLIBS)

dictpopup-create: $(SRC_CREATE) $(SRC_H_CREATE)
$(CC) $(CFLAGS_CREATE) -o $@ src/dictpopup_create.c $(SRC_CREATE) $(LDLIBS_CREATE)
$(CC) $(CFLAGS_CREATE) -o $@ $(SDIR)/dictpopup_create.c $(SRC_CREATE) $(LDLIBS_CREATE)

release:
version=$$(git describe); prefix=dictpopup-$${version#v}; \
Expand Down Expand Up @@ -90,7 +89,7 @@ clean:
rm -f dictpopup dictpopup-create tests

tests: $(SRC) $(SRC_H)
$(CC) $(CFLAGS) $(DEBUG_CFLAGS) -o $@ $(SDIR)/test.c $(SRC) $(LDLIBS)
$(CC) $(CFLAGS) $(DEBUG_CFLAGS) $(CPPFLAGS) -o $@ $(SDIR)/tests.c $(SRC) $(LDLIBS)

check test: tests
./tests
Expand Down
21 changes: 11 additions & 10 deletions include/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ void *xrealloc(void *ptr, size_t size);
// clang-format on

/* ------------------- Start s8 utils ---------------- */
// This encodes an invalid UTF-8 char to be used as a stopper
// for variable argument length macros
#define S8_STOPPER \
(s8) { \
.s = (u8[]){0xF8}, .len = 1 \
}
#define lengthof(s) (arrlen("" s "") - 1)
#define s8(s) \
{ (u8 *)s, arrlen(s) - 1 }
Expand Down Expand Up @@ -114,16 +120,11 @@ void _nonnull_ frees8buffer(s8 **buf);
*
* Returns: A newly allocated s8 containing the concatenated string
*/
#define concat(...) \
concat_((s8[]){__VA_ARGS__, S("CONCAT_STOPPER")}, S("CONCAT_STOPPER")) // Might be better to use
// a stopper that
// consists of a single
// invalid char
s8 _nonnull_ concat_(s8 *strings, const s8 stopper);

#define buildpath(...) \
buildpath_((s8[]){__VA_ARGS__, S("BUILD_PATH_STOPPER")}, S("BUILD_PATH_STOPPER"))
s8 _nonnull_ buildpath_(s8 *pathcomps, const s8 stopper);
#define concat(...) concat_((s8[]){__VA_ARGS__, S8_STOPPER})
s8 _nonnull_ concat_(s8 *strings);

#define buildpath(...) buildpath_((s8[]){__VA_ARGS__, S8_STOPPER})
s8 _nonnull_ buildpath_(s8 *pathcomps);
/* ------------------- End s8 utils ---------------- */

/* --------------------------- string builder -----------------------_ */
Expand Down
44 changes: 23 additions & 21 deletions src/deinflector.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,39 +142,24 @@ s8 kanji2hira(s8 input) {
* Replaces the last @suffix_len bytes of @word with @replacement.
*/
static void add_replace_suffix(s8 word, s8 replacement, size suffix_len) {
assert(word.s);
assert(word.len >= suffix_len);
assert(replacement.len >= 0);

// TODO: Rewrite this using s8 functions
s8 replstr = {0};
replstr.len = word.len - suffix_len + replacement.len;
replstr.s = new (u8, replstr.len);

memcpy(replstr.s, word.s, (size_t)(word.len - suffix_len));
if (replacement.len)
memcpy(replstr.s + word.len - suffix_len, replacement.s, (size_t)replacement.len);

word.len -= suffix_len;
s8 replstr = concat(word, replacement);
buf_push(deinfs, replstr);
}

/*
* Same as add_replace_suffix but with prefix
*/
static void add_replace_prefix(s8 word, s8 replacement, size prefix_len) {
assert(word.s);
assert(word.len >= prefix_len);
assert(replacement.len >= 0);

s8 retstr = {0};
retstr.len = word.len - prefix_len + replacement.len;
retstr.s = new (u8, retstr.len);

if (replacement.len)
memcpy(retstr.s, replacement.s, (size_t)replacement.len);
memcpy(retstr.s + replacement.len, word.s + prefix_len, (size_t)(word.len - prefix_len));
word.s += prefix_len;
word.len -= prefix_len;
s8 replstr = concat(replacement, word);

buf_push(deinfs, retstr);
buf_push(deinfs, replstr);
}

/*
Expand Down Expand Up @@ -266,6 +251,7 @@ static void check_past(s8 word) {
static void check_masu(s8 word) {
IF_ENDSWITH_CONVERT_ITOU("ます");
IF_ENDSWITH_CONVERT_ITOU("ません");
IF_ENDSWITH_CONVERT_ITOU("ませんでした");
}

static void check_shimau(s8 word) {
Expand Down Expand Up @@ -314,6 +300,7 @@ static void check_potential(s8 word) {

IF_ENDSWITH_REPLACE("せる", "す");
IF_ENDSWITH_REPLACE("ける", "く");
IF_ENDSWITH_REPLACE("げる", "ぐ");
IF_ENDSWITH_REPLACE("べる", "ぶ");
IF_ENDSWITH_REPLACE("てる", "つ");
IF_ENDSWITH_REPLACE("める", "む");
Expand All @@ -338,6 +325,20 @@ static void check_concurrent(s8 word) {
IF_ENDSWITH_CONVERT_ITOU("ながら");
}

static void check_imperative(s8 word) {
// TODO: This is still missing some
IF_ENDSWITH_REPLACE("べろ", "べる");
IF_ENDSWITH_REPLACE("じろ", "じる");
IF_ENDSWITH_REPLACE("せ", "す");
IF_ENDSWITH_REPLACE("け", "く");
IF_ENDSWITH_REPLACE("げ", "ぐ");
IF_ENDSWITH_REPLACE("べ", "ぶ");
IF_ENDSWITH_REPLACE("て", "つ");
IF_ENDSWITH_REPLACE("え", "う");
IF_ENDSWITH_REPLACE("ね", "ぬ");
IF_ENDSWITH_REPLACE("め", "む");
}

static void deinflect_one_iter(s8 word) {
check_shimau(word);
check_adjective(word);
Expand All @@ -350,6 +351,7 @@ static void deinflect_one_iter(s8 word) {
check_potential(word);
check_conditional(word);
check_concurrent(word);
check_imperative(word);
kanjify(word);
}

Expand Down
31 changes: 0 additions & 31 deletions src/test.c

This file was deleted.

97 changes: 97 additions & 0 deletions src/tests.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#include <stdio.h>

#include "deinflector.h"
#include "util.h"

#define passed(cond) ((cond) ? "passed" : "not passed")

static int test_kana_conversion(void) {
const s8 all_kata = S("アイウエオカキクケコサシスセソタチツテトナニヌネノハヒ"
"フヘホマミムメモヤユヨラリルレロワヲン"
"ガギグゲゴザジズゼゾダヂヅデド"
"バビブベボ"
"パピプペポ");
const s8 all_hira = S("あいうえおかきくけこさしすせそたちつてとなにぬねのはひ"
"ふへほまみむめもやゆよらりるれろわをん"
"がぎぐげござじずぜぞだぢづでど"
"ばびぶべぼ"
"ぱぴぷぺぽ");
_drop_(frees8) s8 converted_hira = s8dup(all_kata);
kata2hira(converted_hira);

return s8equals(converted_hira, all_hira);
}

#define DEINFLECT(expected_deinf, ...) \
do { \
char **words = (char *[]){__VA_ARGS__, NULL}; \
for (char **wordptr = words; *wordptr != NULL; wordptr++) { \
s8 *deinfs = deinflect(fromcstr_(*wordptr)); \
i32 contains = 0; \
for (size_t i = 0; i < buf_size(deinfs); i++) { \
if (s8equals(deinfs[i], S(expected_deinf))) { \
contains = 1; \
break; \
} \
} \
if (!contains) { \
printf("(%s) Deinflection test for '%s' FAILED!\n Deinflections are:\n", __func__, \
*wordptr); \
for (size_t i = 0; i < buf_size(deinfs); i++) { \
printf("%.*s\n", (int)deinfs[i].len, (char *)deinfs[i].s); \
} \
return 0; \
} \
} \
} while (0)

static int test_deinflections(void) {
/* -- Ichidan verbs -- */
DEINFLECT("信じる", "信じない", "信じます", "信じません", "信じた", "信じなかった",
"信じました", "信じませんでした", "信じて", "信じなくて", "信じられる",
"信じられない", "信じられる", "信じられない", "信じさせる", "信じさせない",
"信じさせられる", "信じさせられない", "信じろ");

/* -- Godan verbs -- */
/* ku-ending */
DEINFLECT("叩く", "叩かない", "叩きます", "叩きません", "叩いた", "叩かなかった", "叩きました",
"叩きませんでした", "叩いて", "叩かなくて", "叩ける", "叩けない", "叩かれる",
"叩かれない", "叩かせる", "叩かせない", "叩かせられる", "叩かせられない", "叩け");
/* u-ending */
DEINFLECT("買う", "買わない", "買います", "買いません", "買った", "買わなかった", "買いました",
"買いませんでした", "買って", "買わなくて", "買える", "買えない", "買われる", "買われない",
"買わせる", "買わせない", "買わせられる", "買わせられない", "買え");
/* gu-ending */
DEINFLECT("泳ぐ", "泳がない", "泳ぎます", "泳ぎません", "泳いだ", "泳がなかった", "泳ぎました",
"泳ぎませんでした", "泳いで", "泳がなくて", "泳げる", "泳げない", "泳がれる", "泳がれない",
"泳がせる", "泳がせない", "泳がせられる", "泳がせられない", "泳げ");
/* mu-ending */
DEINFLECT("読む", "読まない", "読みます", "読みません", "読んだ", "読まなかった", "読みました",
"読みませんでした", "読んで", "読まなくて", "読める", "読めない", "読まれる", "読まれない",
"読ませる", "読ませない", "読ませられる", "読ませられない", "読め");
/* bu-ending */
DEINFLECT("遊ぶ", "遊べ");
/* tsu-ending */
DEINFLECT("勝つ", "勝て");

/* -- i-adjectives -- */
DEINFLECT("軽い", "軽くない", "軽かった", "軽くなかった");

return 1;
}

#define TEST(call) \
do { \
if ((call) == 0) { \
exit(EXIT_FAILURE); \
} else { \
printf("%s: Success\n", #call); \
} \
} while (0)

int main(int argc, char **argv) {
TEST(test_kana_conversion());
TEST(test_deinflections());

return EXIT_SUCCESS;
}
12 changes: 6 additions & 6 deletions src/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,27 +190,27 @@ s8 unescape(s8 str) {
return str;
}

s8 concat_(s8 *strings, const s8 stopper) {
s8 concat_(s8 *strings) {
size len = 0;
for (s8 *s = strings; !s8equals(*s, stopper); s++)
for (s8 *s = strings; !s8equals(*s, S8_STOPPER); s++)
len += s->len;

s8 ret = news8(len);
s8 p = ret;
for (s8 *s = strings; !s8equals(*s, stopper); s++)
for (s8 *s = strings; !s8equals(*s, S8_STOPPER); s++)
p = s8copy(p, *s);
return ret;
}

s8 buildpath_(s8 *pathcomps, const s8 stopper) {
s8 buildpath_(s8 *pathcomps) {
#ifdef _WIN32
s8 sep = S("\\");
#else
s8 sep = S("/");
#endif
size pathlen = 0;
bool first = true;
for (s8 *pc = pathcomps; !s8equals(*pc, stopper); pc++) {
for (s8 *pc = pathcomps; !s8equals(*pc, S8_STOPPER); pc++) {
if (!first)
pathlen += sep.len;
pathlen += pc->len;
Expand All @@ -222,7 +222,7 @@ s8 buildpath_(s8 *pathcomps, const s8 stopper) {
s8 p = retpath;

first = true;
for (s8 *pc = pathcomps; !s8equals(*pc, stopper); pc++) {
for (s8 *pc = pathcomps; !s8equals(*pc, S8_STOPPER); pc++) {
if (!first)
p = s8copy(p, sep);
p = s8copy(p, *pc);
Expand Down

0 comments on commit 9e187b6

Please sign in to comment.