test: added new unit tests

Signed-off-by: Janos SUTO <sj@acts.hu>
This commit is contained in:
Janos SUTO 2018-01-11 10:20:02 +01:00
parent 7e3367d04d
commit e03a9f2982
8 changed files with 1206 additions and 3 deletions

View File

@ -27,6 +27,7 @@ char *split(char *str, int ch, char *buf, int buflen, int *result);
char *split_str(char *row, char *what, char *s, int size); char *split_str(char *row, char *what, char *s, int size);
int trimBuffer(char *s); int trimBuffer(char *s);
int extractEmail(char *rawmail, char *email); int extractEmail(char *rawmail, char *email);
int extract_verp_address(char *email);
void make_random_string(char *buf, int buflen); void make_random_string(char *buf, int buflen);
void create_id(char *id, unsigned char server_id); void create_id(char *id, unsigned char server_id);
int get_random_bytes(unsigned char *buf, int len, unsigned char server_id); int get_random_bytes(unsigned char *buf, int len, unsigned char server_id);

View File

@ -24,7 +24,7 @@ RUNNING_GROUP = `@id_bin@ -gn $(RUNNING_USER)`
INSTALL = @INSTALL@ INSTALL = @INSTALL@
all: check_parser_utils check_rules check_digest check_mydomains check_parser smtp all: check_parser_utils check_rules check_digest check_mydomains check_parser check_decoder check_hash check_misc smtp
check_parser_utils: check_parser_utils.c ../src/libpiler.a check_parser_utils: check_parser_utils.c ../src/libpiler.a
$(CC) $(CFLAGS) $(INCDIR) $(DEFS) -o $@ $< -lpiler $(LIBS) $(LIBDIR) $(CC) $(CFLAGS) $(INCDIR) $(DEFS) -o $@ $< -lpiler $(LIBS) $(LIBDIR)
@ -41,6 +41,15 @@ check_mydomains: check_mydomains.c ../src/libpiler.a
check_parser: check_parser.c ../src/libpiler.a check_parser: check_parser.c ../src/libpiler.a
$(CC) $(CFLAGS) $(INCDIR) $(DEFS) -o $@ $< -lpiler $(LIBS) $(LIBDIR) $(CC) $(CFLAGS) $(INCDIR) $(DEFS) -o $@ $< -lpiler $(LIBS) $(LIBDIR)
check_decoder: check_decoder.c ../src/libpiler.a
$(CC) $(CFLAGS) $(INCDIR) $(DEFS) -o $@ $< -lpiler $(LIBS) $(LIBDIR)
check_hash: check_hash.c ../src/libpiler.a
$(CC) $(CFLAGS) $(INCDIR) $(DEFS) -o $@ $< -lpiler $(LIBS) $(LIBDIR)
check_misc: check_misc.c ../src/libpiler.a
$(CC) $(CFLAGS) $(INCDIR) $(DEFS) -o $@ $< -lpiler $(LIBS) $(LIBDIR)
smtp: smtp.c ../src/libpiler.a smtp: smtp.c ../src/libpiler.a
$(CC) $(CFLAGS) $(INCDIR) $(DEFS) -o $@ $< -lpiler $(LIBS) $(LIBDIR) $(CC) $(CFLAGS) $(INCDIR) $(DEFS) -o $@ $< -lpiler $(LIBS) $(LIBDIR)
@ -48,7 +57,7 @@ install:
@echo @echo
clean: clean:
rm -f check_parser_utils check_rules check_digest check_mydomains check_parser smtp rm -f check_parser_utils check_rules check_digest check_mydomains check_parser check_decoder check_hash check_misc smtp
distclean: clean distclean: clean
rm -f Makefile rm -f Makefile

130
unit_tests/check_decoder.c Normal file
View File

@ -0,0 +1,130 @@
/*
* check_decoder.c, SJ
*/
#include "test.h"
struct config cfg;
static void test_decodeBase64(){
unsigned int i;
struct test_data_s_s test_strings[] = {
{ "Zm9vYmFy", "foobar" },
{ "Zm9vYmE=", "fooba" },
{ "Zm9vYg==", "foob" },
{ "Zm9v", "foo" },
{ "Zm8=", "fo" },
{ "Zg==", "f" },
{ "", "" },
};
TEST_HEADER();
for(i=0; i<sizeof(test_strings)/sizeof(struct test_data_s_s); i++){
decodeBase64(test_strings[i].s);
ASSERT(strcmp(test_strings[i].s, test_strings[i].result) == 0, test_strings[i].result);
}
TEST_FOOTER();
}
static void test_decode_base64_to_buffer(){
unsigned int i;
unsigned char puf[MAXBUFSIZE];
struct test_data_s_s test_strings[] = {
{ "Zm9vYmFy", "foobar" },
{ "Zm9vYmE=", "fooba" },
{ "Zm9vYg==", "foob" },
{ "Zm9v", "foo" },
{ "Zm8=", "fo" },
{ "Zg==", "f" },
{ "", "" },
};
TEST_HEADER();
for(i=0; i<sizeof(test_strings)/sizeof(struct test_data_s_s); i++){
memset(puf, 0, sizeof(puf));
decode_base64_to_buffer(test_strings[i].s, strlen(test_strings[i].s), &puf[0], sizeof(puf)-1);
ASSERT(strcmp((char*)puf, test_strings[i].result) == 0, test_strings[i].result);
}
TEST_FOOTER();
}
static void test_decodeURL(){
unsigned int i;
struct test_data_s_s test_strings[] = {
{ "%2fhello%3dworld", "/hello=world" },
{ "hello+world%21", "hello world!" },
{ "%3F%21%3D%25", "?!=%" },
{ "%C3%A9ljen+m%C3%A1jus+elseje", "éljen május elseje" },
{ "", "" },
};
TEST_HEADER();
for(i=0; i<sizeof(test_strings)/sizeof(struct test_data_s_s); i++){
decodeURL(test_strings[i].s);
ASSERT(strcmp(test_strings[i].s, test_strings[i].result) == 0, test_strings[i].result);
}
TEST_FOOTER();
}
static void test_decodeQP(){
unsigned int i;
struct test_data_s_s test_strings[] = {
{ "=2fhello=3dworld", "/hello=world" },
{ "hello=20world=21", "hello world!" },
{ "=3F=21=3D=25", "?!=%" },
{ "=C3=A9ljen=20m=C3=A1jus=20elseje", "éljen május elseje" },
{ "", "" },
};
TEST_HEADER();
for(i=0; i<sizeof(test_strings)/sizeof(struct test_data_s_s); i++){
decodeQP(test_strings[i].s);
ASSERT(strcmp(test_strings[i].s, test_strings[i].result) == 0, test_strings[i].result);
}
TEST_FOOTER();
}
static void test_decodeHTML(){
unsigned int i;
struct test_data_s_s test_strings[] = {
{ "1&gt;2", "1>2" },
{ "&eacute;ljen m&aacute;jus elseje!", "éljen május elseje!" },
{ "boni&amp;kl&aacute;jd", "boni&klájd" },
};
TEST_HEADER();
for(i=0; i<sizeof(test_strings)/sizeof(struct test_data_s_s); i++){
decodeHTML(test_strings[i].s, 1);
ASSERT(strcmp(test_strings[i].s, test_strings[i].result) == 0, test_strings[i].result);
}
TEST_FOOTER();
}
int main(){
cfg = read_config("test.conf");
cfg.server_id = 0;
test_decode_base64_to_buffer();
test_decodeBase64();
test_decodeURL();
test_decodeQP();
test_decodeHTML();
return 0;
}

135
unit_tests/check_hash.c Normal file
View File

@ -0,0 +1,135 @@
/*
* check_hash.c, SJ
*/
#include "test.h"
#include "words.h"
struct node *node[MAXHASH];
struct test_data_s_i test_words[] = {
{ "aaatelergic", 1},
{ "aaatelescopic", 1},
{ "aaateleseismic", 1},
{ "telesiurgicbbb", 1},
{ "telesmaticbbb", 1},
{ "telesomaticbbb", 1},
{ "telXesXthetXic", 0},
{ "aaatelesticbbb", 1},
{ "aaateleutosporicbbb", 1},
{ "telXfairic", 0},
{ "telhXarmonic", 0},
{ "telXic", 0},
{ "aaaa", 0},
{ "aaa_bbb", 0},
{ "ajaj iii", 0},
{ "aaa@bbb", 0},
{ "ahah+uuu", 0},
{ "ccc&aa", 0}
};
struct test_data_s_uinti test_words_hash[] = {
{ "aaatelergic", 2391918743},
{ "aaatelescopic", 2083954803},
{ "aaateleseismic", 122299487},
{ "telesiurgicbbb", 1265893195},
{ "telesmaticbbb", 3159428598},
{ "telesomaticbbb", 2785346981},
{ "telXesXthetXic", 2996605099},
{ "aaatelesticbbb", 708743179},
{ "aaateleutosporicbbb", 78891264},
{ "telXfairic", 375384208},
{ "telhXarmonic", 2664510067},
{ "telXic", 500553166},
{ "aaaa", 2090068425},
{ "aaa_bbb", 400954957},
{ "ajaj iii", 3390570070},
{ "aaa@bbb", 399840910},
{ "ahah+uuu", 805671073},
{ "ccc&aa", 4127468790}
};
static void test_init_hash(){
unsigned int i;
TEST_HEADER();
inithash(node);
for(i=0; i<MAXHASH; i++){
ASSERT(node[i] == NULL, "not null");
}
TEST_FOOTER();
}
static void test_clear_hash(){
unsigned int i;
TEST_HEADER();
clearhash(node);
for(i=0; i<MAXHASH; i++){
ASSERT(node[i] == NULL, "not null");
}
TEST_FOOTER();
}
static void test_addnode(){
unsigned int i, nwords = sizeof(words)/sizeof(char*);
TEST_HEADER();
for(i=0; i<nwords; i++){
addnode(node, words[i]);
}
for(i=0; i<nwords; i++){
ASSERT(findnode(node, words[i]) != NULL, words[i]);
}
TEST_FOOTER();
}
static void test_is_substr_in_hash(){
unsigned int i;
TEST_HEADER();
for(i=0; i<sizeof(test_words)/sizeof(struct test_data_s_i); i++){
ASSERT(is_substr_in_hash(node, test_words[i].s) == test_words[i].result, test_words[i].s);
}
TEST_FOOTER();
}
static void test_DJBHash(){
unsigned int i;
TEST_HEADER();
for(i=0; i<sizeof(test_words_hash)/sizeof(struct test_data_s_uinti); i++){
ASSERT(DJBHash(test_words_hash[i].s, strlen(test_words_hash[i].s)) == test_words_hash[i].result, test_words_hash[i].s);
}
TEST_FOOTER();
}
int main(){
test_init_hash();
test_addnode();
test_is_substr_in_hash();
test_clear_hash();
test_DJBHash();
return 0;
}

241
unit_tests/check_misc.c Normal file
View File

@ -0,0 +1,241 @@
/*
* check_misc.c, SJ
*/
#include "test.h"
struct config cfg;
struct smtp_session session;
struct data data;
static void test_strtolower(){
unsigned int i;
struct test_data_s_s test_data_s_s[] = {
{ "aaaa", "aaaa"},
{ "aBhu+18", "abhu+18"},
{ "u Uj i", "u uj i"},
{ "eee?", "eee?"},
{ "EEE?E", "eee?e"},
};
TEST_HEADER();
for(i=0; i<sizeof(test_data_s_s)/sizeof(struct test_data_s_s); i++){
strtolower(test_data_s_s[i].s);
ASSERT(strcmp(test_data_s_s[i].s, test_data_s_s[i].result) == 0, test_data_s_s[i].result);
}
TEST_FOOTER();
}
static void test_extract_verp_address(){
unsigned int i;
struct test_data_s_s test_data_s_s[] = {
{ "archive+user=domain.com@myarchive.local", "user@domain.com"},
};
TEST_HEADER();
for(i=0; i<sizeof(test_data_s_s)/sizeof(struct test_data_s_s); i++){
extract_verp_address(test_data_s_s[i].s);
ASSERT(strcmp(test_data_s_s[i].s, test_data_s_s[i].result) == 0, test_data_s_s[i].result);
}
TEST_FOOTER();
}
static void test_extract_email(){
unsigned int i;
char s[SMALLBUFSIZE];
struct test_data_s_s test_data_s_s[] = {
{ "MAIL FROM:<aaa@aaa.fu>\r\n", "aaa@aaa.fu" },
{ "MAIL FROM: <aaa@aaa.fu>\r\n", "aaa@aaa.fu" },
{ "RCPT TO: <aaa@aaa.fu>\r\n", "aaa@aaa.fu" },
{ "<aaa@aaa.fu>", "aaa@aaa.fu" },
};
TEST_HEADER();
for(i=0; i<sizeof(test_data_s_s)/sizeof(struct test_data_s_s); i++){
extractEmail(test_data_s_s[i].s, s);
ASSERT(strcmp(s, test_data_s_s[i].result) == 0, test_data_s_s[i].result);
}
TEST_FOOTER();
}
static void test_trim_buffer(){
unsigned int i;
struct test_data_s_s test_data_s_s[] = {
{ "auaua\r\n", "auaua" },
{ "hello\n", "hello" },
{ "qqq\r", "qqq" },
{ "akaka\nkkk", "akaka" },
{ "qqq\r\naaa", "qqq" },
};
TEST_HEADER();
for(i=0; i<sizeof(test_data_s_s)/sizeof(struct test_data_s_s); i++){
trimBuffer(test_data_s_s[i].s);
ASSERT(strcmp(test_data_s_s[i].s, test_data_s_s[i].result) == 0, test_data_s_s[i].result);
}
TEST_FOOTER();
}
static void test_search_string_in_buffer(){
unsigned int i;
int pos;
struct test_data_s_s_i test_data_s_s_i[] = {
{ "ajaja\r\n.\r\n", SMTP_CMD_PERIOD, 5 },
{ "ajaja\r\n.\r\ndhdjdhj", SMTP_CMD_PERIOD, 5 },
{ "ajajadjdhj", "a", 0 },
{ "ajajadjdhj", "aja", 0 },
{ "ajajadjdhj", "jaja", 1 },
{ "ajajadjdhj", "qqq", -1 },
};
TEST_HEADER();
for(i=0; i<sizeof(test_data_s_s_i)/sizeof(struct test_data_s_s_i); i++){
pos = searchStringInBuffer(test_data_s_s_i[i].s1, strlen(test_data_s_s_i[i].s1), test_data_s_s_i[i].s2, strlen(test_data_s_s_i[i].s2));
//printf("%s %s %d, %d\n", test_data_s_s_i[i].s1, test_data_s_s_i[i].s2, pos, test_data_s_s_i[i].result);
ASSERT(pos == test_data_s_s_i[i].result, test_data_s_s_i[i].s1);
}
TEST_FOOTER();
}
static void test_search_char_backward(){
unsigned int i;
int pos;
struct test_data_s_s_i test_data_s_s_i[] = {
{ "abcdefghij\r\n.\r\n", "\r", 10 },
{ "abcdefghij\n\n.\r\n", "\r", 13 },
{ "abcdefghij\n\n.\n\n", "\r", -1 },
};
TEST_HEADER();
for(i=0; i<sizeof(test_data_s_s_i)/sizeof(struct test_data_s_s_i); i++){
pos = search_char_backward(test_data_s_s_i[i].s1, strlen(test_data_s_s_i[i].s1), test_data_s_s_i[i].s2[0]);
ASSERT(pos == test_data_s_s_i[i].result, test_data_s_s_i[i].s1);
}
TEST_FOOTER();
}
static void test_make_random_string(){
unsigned int i;
char buf[SMALLBUFSIZE];
TEST_HEADER();
for(i=0; i<10; i++){
make_random_string(buf, sizeof(buf)-1);
printf("%s ", buf);
}
TEST_FOOTER();
}
static void test_create_id(){
unsigned int i;
char buf[SMALLBUFSIZE];
TEST_HEADER();
for(i=0; i<10; i++){
create_id(buf, 0xf);
ASSERT(strncmp(buf, "40000000", strlen("40000000")) == 0, buf);
ASSERT(buf[24] == '0' && buf[25] == 'f', buf);
}
TEST_FOOTER();
}
static void test_split(){
unsigned int i;
int result;
char *p, buf[SMALLBUFSIZE];
struct test_data_s_s_i test_data_s_s_i[] = {
{ "hello\nworld\n", "world\n", 1 },
{ "hello\nworld", "world", 1 },
{ "hello\n", "", 1 },
{ "helloworld", "", 0 },
};
TEST_HEADER();
for(i=0; i<sizeof(test_data_s_s_i)/sizeof(struct test_data_s_s_i); i++){
p = split(test_data_s_s_i[i].s1, '\n', buf, sizeof(buf)-1, &result);
if(p){ ASSERT(strcmp(buf, "hello") == 0 && strcmp(p, test_data_s_s_i[i].s2) == 0 && result == test_data_s_s_i[i].result, test_data_s_s_i[i].s1); }
else { ASSERT(p == NULL && result == test_data_s_s_i[i].result, test_data_s_s_i[i].s1); }
}
TEST_FOOTER();
}
static void test_split_str(){
unsigned int i;
char *p, buf[SMALLBUFSIZE];
struct test_data_s_s test_data_s_s[] = {
{ "aaaXXbbbXX", "bbbXX" },
{ "aaaXXbbb", "bbb" },
{ "aaaXX", "" },
{ "aaa", "" },
};
TEST_HEADER();
for(i=0; i<sizeof(test_data_s_s)/sizeof(struct test_data_s_s); i++){
p = split_str(test_data_s_s[i].s, "XX", buf, sizeof(buf)-1);
if(p){ ASSERT(strcmp(buf, "aaa") == 0 && strcmp(test_data_s_s[i].result, p) == 0, test_data_s_s[i].s); }
else { ASSERT(strcmp(buf, "aaa") == 0 && p == NULL, test_data_s_s[i].s); }
}
TEST_FOOTER();
}
int main(){
if(!can_i_write_directory(NULL)) __fatal("cannot write current directory!");
(void) openlog("mydomains_test", LOG_PID, LOG_MAIL);
cfg = read_config("test.conf");
cfg.server_id = 0;
session.cfg = &cfg;
setlocale(LC_MESSAGES, cfg.locale);
setlocale(LC_CTYPE, cfg.locale);
test_strtolower();
test_extract_verp_address();
test_extract_email();
test_trim_buffer();
test_search_string_in_buffer();
test_search_char_backward();
test_make_random_string();
test_create_id();
test_split();
test_split_str();
return 0;
}

View File

@ -3,7 +3,6 @@
set -o errexit set -o errexit
set -o pipefail set -o pipefail
set -o nounset set -o nounset
set -x
export LD_LIBRARY_PATH=../src export LD_LIBRARY_PATH=../src
@ -12,3 +11,6 @@ export LD_LIBRARY_PATH=../src
./check_rules ./check_rules
./check_digest ./check_digest
./check_mydomains ./check_mydomains
./check_misc
./check_hash
./check_decoder

View File

@ -18,6 +18,34 @@
#include "../src/piler.h" #include "../src/piler.h"
struct test_data_s_i {
char s[SMALLBUFSIZE];
int result;
};
struct test_data_s_uinti {
char s[SMALLBUFSIZE];
unsigned int result;
};
struct test_data_s_s {
char s[SMALLBUFSIZE];
char result[SMALLBUFSIZE];
};
struct test_data_s_s_i {
char s1[SMALLBUFSIZE];
char s2[SMALLBUFSIZE];
int result;
};
struct digest_test {
char s[SMALLBUFSIZE];
char *digest1;
char *digest2;
};
#define ASSERT(expr, value) if (!(expr)) { printf("assert failed: '%s'\n", value); abort(); } else { printf("."); } #define ASSERT(expr, value) if (!(expr)) { printf("assert failed: '%s'\n", value); abort(); } else { printf("."); }
#define TEST_HEADER() printf("%s() ", __func__); #define TEST_HEADER() printf("%s() ", __func__);
#define TEST_FOOTER() printf(" OK\n"); #define TEST_FOOTER() printf(" OK\n");

657
unit_tests/words.h Normal file
View File

@ -0,0 +1,657 @@
char *words[] = {
"tabac",
"tabetic",
"tabic",
"tabific",
"taboparetic",
"tacamahac",
"tacheometric",
"tachyauxetic",
"tachycardiac",
"tachygenetic",
"tachygenic",
"tachygraphic",
"tachylytic",
"tachymetric",
"tachyphylactic",
"tachypneic",
"tachypnoeic",
"tachistoscopic",
"tachytelic",
"tachometric",
"tactic",
"tagmemic",
"talaric",
"talc",
"talionic",
"talipedic",
"talismanic",
"talonic",
"tamasic",
"tambac",
"tanistic",
"tannaic",
"tannaitic",
"tannic",
"tannocaffeic",
"tannogallic",
"tanrec",
"tantric",
"tapeinocephalic",
"tapinocephalic",
"tariric",
"taririnic",
"taroc",
"tartralic",
"tartramic",
"tartratoferric",
"tartrazinic",
"tartrelic",
"tartrylic",
"tartronic",
"tasimetric",
"taurylic",
"taurocholic",
"tauromachic",
"tauromorphic",
"tautologic",
"tautomeric",
"tautometric",
"tautonymic",
"tautophonic",
"tautopodic",
"tautosyllabic",
"taxemic",
"taxidermic",
"taxinomic",
"taxitic",
"taxonomic",
"technetronic",
"technic",
"technocratic",
"technographic",
"technolithic",
"technologic",
"technonomic",
"tectocephalic",
"tectonic",
"tectospondylic",
"tektitic",
"telacoustic",
"telaesthetic",
"telangiectatic",
"telautographic",
"telautomatic",
"telechemic",
"telegenic",
"telegnostic",
"telegonic",
"telegrammatic",
"telegrammic",
"telegraphic",
"telekinetic",
"telelectric",
"telemechanic",
"telemeteorographic",
"telemetric",
"telemetrographic",
"telencephalic",
"telenergic",
"teleologic",
"teleorganic",
"teleozoic",
"telepathic",
"telephonic",
"telephonographic",
"telephotographic",
"teleplasmic",
"teleplastic",
"telergic",
"telescopic",
"teleseismic",
"telesiurgic",
"telesmatic",
"telesomatic",
"telesthetic",
"telestic",
"teleutosporic",
"telfairic",
"telharmonic",
"telic",
"teliosporic",
"tellurhydric",
"telluric",
"teloblastic",
"telocentric",
"telodynamic",
"telomic",
"telomitic",
"telophasic",
"teloptic",
"telosynaptic",
"teloteropathic",
"telotrophic",
"telpheric",
"telsonic",
"temporozygomatic",
"tendrac",
"tenebrific",
"tenesmic",
"tenoplastic",
"tenrec",
"tensiometric",
"tephritic",
"tephromyelitic",
"teratic",
"teratogenetic",
"teratogenic",
"teratologic",
"terbic",
"terebenic",
"terebic",
"terebilic",
"terebinic",
"terebinthic",
"terephthalic",
"terephthallic",
"tergitic",
"termatic",
"terministic",
"termitic",
"terpenic",
"terrific",
"terrorific",
"terroristic",
"tesseraic",
"tesseratomic",
"tetanic",
"tetrabasic",
"tetraboric",
"tetracarboxylic",
"tetrachoric",
"tetrachromatic",
"tetrachromic",
"tetracyclic",
"tetracolic",
"tetradecanoic",
"tetradic",
"tetraglottic",
"tetragrammatic",
"tetragrammatonic",
"tetrahedric",
"tetrahydric",
"tetralogic",
"tetrameric",
"tetramorphic",
"tetraploidic",
"tetrapodic",
"tetrarchic",
"tetrasemic",
"tetrasyllabic",
"tetrasomic",
"tetraspheric",
"tetrasporic",
"tetrastichic",
"tetrastylic",
"tetrathionic",
"tetratomic",
"tetric",
"tetrolic",
"tetronic",
"thalamencephalic",
"thalamic",
"thalassic",
"thalassographic",
"thallic",
"thallodic",
"thallogenic",
"thallophytic",
"thalpotic",
"thanatobiologic",
"thanatognomonic",
"thanatomantic",
"thanatophobiac",
"thaumaturgic",
"thaumoscopic",
"theandric",
"theanthropic",
"thearchic",
"theatric",
"theatromaniac",
"theatrophonic",
"theistic",
"thelyblastic",
"thelytonic",
"thematic",
"theoanthropomorphic",
"theobromic",
"theocentric",
"theochristic",
"theocratic",
"theodolitic",
"theognostic",
"theogonic",
"theoktonic",
"theoleptic",
"theologastric",
"theologic",
"theomagic",
"theomaniac",
"theomantic",
"theomorphic",
"theopathetic",
"theopathic",
"theophagic",
"theophanic",
"theophilanthropic",
"theophilosophic",
"theophoric",
"theopneustic",
"theorematic",
"theoremic",
"theoretic",
"theoric",
"theosophic",
"theosophistic",
"theotechnic",
"theriac",
"therianthropic",
"theriodic",
"theriomaniac",
"theriomorphic",
"theriozoic",
"thermaic",
"thermantic",
"thermatologic",
"thermic",
"thermionic",
"thermochemic",
"thermochroic",
"thermodynamic",
"thermoduric",
"thermoelastic",
"thermoelectric",
"thermoelectronic",
"thermogenetic",
"thermogenic",
"thermographic",
"thermolytic",
"thermomagnetic",
"thermometamorphic",
"thermometric",
"thermonastic",
"thermoperiodic",
"thermophilic",
"thermoplastic",
"thermopolypneic",
"thermoscopic",
"thermosystaltic",
"thermospheric",
"thermostatic",
"thermotactic",
"thermotaxic",
"thermotelephonic",
"thermotic",
"thermotypic",
"thermotropic",
"thermovoltaic",
"therologic",
"theromorphic",
"thetic",
"theurgic",
"thiacetic",
"thigmotactic",
"thigmotropic",
"thymelic",
"thymetic",
"thymic",
"thymicolymphatic",
"thymylic",
"thymogenic",
"thymonucleic",
"thymoprivic",
"thymotactic",
"thymotic",
"thymotinic",
"thioacetic",
"thioarsenic",
"thiocarbamic",
"thiocarbonic",
"thiocyanic",
"thiogycolic",
"thiolacetic",
"thiolactic",
"thiolic",
"thionamic",
"thionic",
"thionobenzoic",
"thionthiolic",
"thiophenic",
"thiophosphoric",
"thiostannic",
"thiosulfuric",
"thiosulphonic",
"thiosulphuric",
"thiotungstic",
"thyreoepiglottic",
"thyreogenic",
"thyreotropic",
"thyrocardiac",
"thyroepiglottic",
"thyrogenic",
"thyroprivic",
"thyrotoxic",
"thyrotrophic",
"thyrotropic",
"thyroxinic",
"thixotropic",
"tholeiitic",
"thoracic",
"thoric",
"thranitic",
"thrasonic",
"threnetic",
"threnodic",
"threptic",
"thrombocytic",
"thrombocytopenic",
"thromboclastic",
"thromboembolic",
"thrombogenic",
"thrombolytic",
"thromboplastic",
"thrombotic",
"thuoc",
"tychistic",
"tychopotamic",
"tictac",
"tictic",
"tictoc",
"tiglic",
"tiglinic",
"tigrolytic",
"tylotic",
"timbromaniac",
"timbrophilic",
"timocratic",
"tympanic",
"tympanitic",
"tympanoperiotic",
"tinc",
"tinguaitic",
"tintometric",
"typhic",
"typhlitic",
"typhogenic",
"typic",
"typographic",
"typolithographic",
"typologic",
"typonymic",
"tyrannic",
"tyronic",
"tisic",
"titanitic",
"tithonic",
"tithonographic",
"titrimetric",
"tocogenetic",
"toc-toc",
"tolfraedic",
"toluic",
"toluylic",
"tombac",
"tombic",
"tomographic",
"tonemic",
"tonetic",
"tonic",
"tonicobalsamic",
"tonicoclonic",
"tonoclonic",
"tonometric",
"tonotactic",
"tonsilitic",
"tonsillectomic",
"tonsillitic",
"too-hectic",
"tophetic",
"topic",
"topocentric",
"topographic",
"topographometric",
"topologic",
"toponymic",
"topotactic",
"topotypic",
"torbanitic",
"torc",
"toreutic",
"toric",
"tornadic",
"torporific",
"totalistic",
"totemic",
"totemistic",
"toufic",
"touristic",
"tourmalinic",
"toxaemic",
"toxalbumic",
"toxemic",
"toxic",
"toxicogenic",
"toxicologic",
"toxicopathic",
"toxicotraumatic",
"toxidermic",
"toxigenic",
"toxiphobiac",
"toxiphoric",
"toxophilitic",
"toxophoric",
"toxoplasmic",
"trachelobregmatic",
"tracheochromatic",
"tracheoscopic",
"trachychromatic",
"trachytic",
"traditionalistic",
"traducianistic",
"traffic",
"tragic",
"tragicoheroicomic",
"tragicomic",
"tragi-comic",
"tragicoromantic",
"transaquatic",
"transarctic",
"transatlantic",
"transcendentalistic",
"transdermic",
"transdiaphragmatic",
"transformistic",
"transiliac",
"transischiac",
"transoceanic",
"trans-oceanic",
"transonic",
"transpacific",
"trans-pacific",
"transpanamic",
"transpyloric",
"transsonic",
"trans-sonic",
"transthalamic",
"transthoracic",
"transuranic",
"traumatic",
"traumatotactic",
"traumatropic",
"tremolitic",
"treponemiatic",
"triac",
"triadic",
"triarctic",
"triatic",
"triatomic",
"triazoic",
"triazolic",
"tribadic",
"tribadistic",
"tribasic",
"triblastic",
"triboelectric",
"tribrac",
"tribrachic",
"tribromacetic",
"tricalcic",
"tricarballylic",
"tricarboxylic",
"tricephalic",
"trichinotic",
"trichitic",
"trichloroacetic",
"trichocystic",
"trichogynic",
"trichomic",
"trichopathic",
"trichophytic",
"trichophoric",
"trichorrhexic",
"trichoschistic",
"trichothallic",
"trichotomic",
"trichroic",
"trichromatic",
"trichromic",
"tricyclic",
"triclinic",
"triclinohedric",
"tricolic",
"tricosylic",
"tricrotic",
"trictrac",
"tric-trac",
"tridecylic",
"tridecoic",
"tridermic",
"trierarchic",
"trieteric",
"trigeneric",
"triglyphic",
"trigoneutic",
"trigonic",
"trigonocephalic",
"trigonometric",
"trigrammatic",
"trigrammic",
"trigraphic",
"trihydric",
"trihypostatic",
"trilithic",
"trilobitic",
"trilogic",
"trimellic",
"trimellitic",
"trimercuric",
"trimeric",
"trimesic",
"trimesinic",
"trimesitic",
"trimesitinic",
"trimetallic",
"trimethylacetic",
"trimetric",
"trimoric",
"trimorphic",
"trinitrocarbolic",
"trioleic",
"trypanolytic",
"trypanosomatic",
"trypanosomic",
"triphasic",
"triphyletic",
"triplasic",
"triploblastic",
"triploidic",
"triplumbic",
"tripodic",
"trypographic",
"tryptic",
"triquetric",
"trisemic",
"trisylabic",
"trisilicic",
"trisyllabic",
"trismegistic",
"trismic",
"trisomic",
"trisplanchnic",
"trisporic",
"tristichic",
"tristigmatic",
"trisulc",
"trisulphonic",
"tritactic",
"tritanopic",
"tritanoptic",
"tritheistic",
"trithiocarbonic",
"trithionic",
"trizoic",
"trochanteric",
"trochilic",
"trochitic",
"trochocephalic",
"trochozoic",
"troglodytic",
"tromometric",
"tronc",
"troostitic",
"tropeic",
"trophallactic",
"trophic",
"trophobiotic",
"trophoblastic",
"trophodynamic",
"trophodisc",
"trophogenic",
"trophoneurotic",
"trophoplasmatic",
"trophoplasmic",
"trophotropic",
"tropic",
"tropismatic",
"tropistic",
"tropologic",
"tropophytic",
"tropospheric",
"true-heroic",
"truismatic",
"truistic",
"truxillic",
"tsaristic",
"tsunamic",
"tuberculinic",
"tuberculotrophic",
"tularaemic",
"tularemic",
"tuliac",
"tulipomaniac",
"tulnic",
"tumeric",
"tumorigenic",
"tungstenic",
"tungstic",
"tungstosilicic",
"tunic",
"turbidimetric",
"turboelectric",
"turbo-electric",
"turmeric",
"turnicomorphic",
"turpentinic",
"two-pointic",
"tzaristic",
};