This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
#include "../accel.h"
|
||||
#include "test_utils.h"
|
||||
#include <stdio.h>
|
||||
|
||||
static int test_acceleration(const char *filename, struct accel_args args) {
|
||||
const int LINE_LEN = 26;
|
||||
const int MIN = -128;
|
||||
const int MAX = 127;
|
||||
|
||||
char content[256 * 256 * LINE_LEN + 1];
|
||||
strcpy(content, ""); // initialize as an empty string
|
||||
|
||||
for (int x = MIN; x < MAX; x++) {
|
||||
for (int y = MIN; y < MAX; y++) {
|
||||
|
||||
int x_out = x;
|
||||
int y_out = y;
|
||||
|
||||
f_accelerate(&x_out, &y_out, FIXEDPT_ONE, args);
|
||||
|
||||
char curr_debug_print[LINE_LEN];
|
||||
|
||||
sprintf(curr_debug_print, "(%d, %d) => (%d, %d)\n", x, y, x_out, y_out);
|
||||
|
||||
strcat(content, curr_debug_print);
|
||||
}
|
||||
}
|
||||
|
||||
assert_snapshot(filename, content);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_linear_acceleration(const char *filename, fpt param_sens_mult,
|
||||
fpt param_yx_ratio, fpt param_accel,
|
||||
fpt param_offset, fpt param_output_cap) {
|
||||
struct linear_curve_args _args =
|
||||
(struct linear_curve_args){.accel = param_accel,
|
||||
.offset = param_offset,
|
||||
.output_cap = param_output_cap};
|
||||
|
||||
struct accel_args args = {
|
||||
.sens_mult = param_sens_mult,
|
||||
.yx_ratio = param_yx_ratio,
|
||||
.input_dpi = fpt_fromint(1000),
|
||||
.tag = linear,
|
||||
.args = (union __accel_args){.linear = _args},
|
||||
};
|
||||
|
||||
return test_acceleration(filename, args);
|
||||
}
|
||||
|
||||
static int test_natural_acceleration(const char *filename, fpt param_sens_mult,
|
||||
fpt param_yx_ratio, fpt param_decay_rate,
|
||||
fpt param_offset, fpt param_limit) {
|
||||
struct natural_curve_args _args =
|
||||
(struct natural_curve_args){.decay_rate = param_decay_rate,
|
||||
.offset = param_offset,
|
||||
.limit = param_limit};
|
||||
|
||||
struct accel_args args = {
|
||||
.sens_mult = param_sens_mult,
|
||||
.yx_ratio = param_yx_ratio,
|
||||
.input_dpi = fpt_fromint(1000),
|
||||
.tag = natural,
|
||||
.args = (union __accel_args){.natural = _args},
|
||||
};
|
||||
|
||||
return test_acceleration(filename, args);
|
||||
}
|
||||
|
||||
static int test_synchronous_acceleration(const char *filename,
|
||||
fpt param_sens_mult,
|
||||
fpt param_yx_ratio, fpt param_gamma,
|
||||
fpt param_smooth, fpt param_motivity,
|
||||
fpt param_sync_speed) {
|
||||
struct synchronous_curve_args _args =
|
||||
(struct synchronous_curve_args){.gamma = param_gamma,
|
||||
.smooth = param_smooth,
|
||||
.motivity = param_motivity,
|
||||
.sync_speed = param_sync_speed};
|
||||
|
||||
struct accel_args args = {
|
||||
.sens_mult = param_sens_mult,
|
||||
.yx_ratio = param_yx_ratio,
|
||||
.input_dpi = fpt_fromint(1000),
|
||||
.tag = synchronous,
|
||||
.args = (union __accel_args){.synchronous = _args},
|
||||
};
|
||||
|
||||
return test_acceleration(filename, args);
|
||||
}
|
||||
|
||||
static int test_no_accel_acceleration(const char *filename, fpt param_sens_mult,
|
||||
fpt param_yx_ratio) {
|
||||
struct no_accel_curve_args _args = (struct no_accel_curve_args){};
|
||||
|
||||
struct accel_args args = {
|
||||
.sens_mult = param_sens_mult,
|
||||
.yx_ratio = param_yx_ratio,
|
||||
.input_dpi = fpt_fromint(1000),
|
||||
.tag = no_accel,
|
||||
.args = (union __accel_args){.no_accel = _args},
|
||||
};
|
||||
|
||||
return test_acceleration(filename, args);
|
||||
}
|
||||
|
||||
static int test_rotation_no_accel(const char *filename, fpt param_sens_mult,
|
||||
fpt param_angle_deg) {
|
||||
struct no_accel_curve_args _args = (struct no_accel_curve_args){};
|
||||
|
||||
struct accel_args args = {
|
||||
.sens_mult = param_sens_mult,
|
||||
.yx_ratio = FIXEDPT_ONE,
|
||||
.input_dpi = fpt_fromint(1000),
|
||||
.angle_rotation_deg = param_angle_deg,
|
||||
.tag = no_accel,
|
||||
.args = (union __accel_args){.no_accel = _args},
|
||||
};
|
||||
|
||||
return test_acceleration(filename, args);
|
||||
}
|
||||
|
||||
#define test_linear(sens_mult, yx_ratio, accel, offset, cap) \
|
||||
assert(test_linear_acceleration( \
|
||||
"SENS_MULT-" #sens_mult "-ACCEL-" #accel "-OFFSET" #offset \
|
||||
"-OUTPUT_CAP-" #cap ".snapshot", \
|
||||
fpt_rconst(sens_mult), fpt_rconst(yx_ratio), fpt_rconst(accel), \
|
||||
fpt_rconst(offset), fpt_rconst(cap)) == 0);
|
||||
|
||||
#define test_natural(sens_mult, yx_ratio, decay_rate, offset, limit) \
|
||||
assert(test_natural_acceleration( \
|
||||
"Natural__SENS_MULT-" #sens_mult "-DECAY_RATE-" #decay_rate \
|
||||
"-OFFSET" #offset "-LIMIT-" #limit ".snapshot", \
|
||||
fpt_rconst(sens_mult), fpt_rconst(yx_ratio), \
|
||||
fpt_rconst(decay_rate), fpt_rconst(offset), \
|
||||
fpt_rconst(limit)) == 0);
|
||||
|
||||
#define test_synchronous(sens_mult, yx_ratio, gamma, smooth, motivity, \
|
||||
sync_speed) \
|
||||
assert(test_synchronous_acceleration( \
|
||||
"Synchronous__SENS_MULT-" #sens_mult "-GAMMA-" #gamma \
|
||||
"-SMOOTH" #smooth "-MOTIVITY-" #motivity \
|
||||
"-SYNC_SPEED-" #sync_speed ".snapshot", \
|
||||
fpt_rconst(sens_mult), fpt_rconst(yx_ratio), fpt_rconst(gamma), \
|
||||
fpt_rconst(smooth), fpt_rconst(motivity), \
|
||||
fpt_rconst(sync_speed)) == 0);
|
||||
|
||||
#define test_no_accel(sens_mult, yx_ratio) \
|
||||
assert(test_no_accel_acceleration( \
|
||||
"NoAccel__SENS_MULT-" #sens_mult "-YX_RATIO-" #yx_ratio \
|
||||
".snapshot", \
|
||||
fpt_rconst(sens_mult), fpt_rconst(yx_ratio)) == 0);
|
||||
|
||||
#define test_rotation(sens_mult, angle_deg) \
|
||||
assert(test_rotation_no_accel( \
|
||||
"Rotation__SENS_MULT-" #sens_mult "-ANGLE-" #angle_deg \
|
||||
".snapshot", \
|
||||
fpt_rconst(sens_mult), fpt_rconst(angle_deg)) == 0);
|
||||
|
||||
int main(void) {
|
||||
test_linear(1, 1, 0, 0, 0);
|
||||
test_linear(1, 1, 0.3, 2, 2);
|
||||
test_linear(0.1325, 1, 0.3, 21.333333, 2);
|
||||
test_linear(0.1875, 1, 0.05625, 10.6666666, 2);
|
||||
test_linear(0.0917, 1, 0.002048, 78.125, 2.0239);
|
||||
test_linear(0.07, 1.15, 0.055, 21, 3);
|
||||
|
||||
test_natural(1, 1, 0, 0, 0);
|
||||
test_natural(1, 1, 0.1, 0, 0);
|
||||
test_natural(1, 1, 0.1, 8, 0);
|
||||
test_natural(1, 1, 0.03, 8, 1.5);
|
||||
|
||||
test_synchronous(1, 1.15, 0.8, 0.5, 1.5, 32);
|
||||
|
||||
test_no_accel(1, 1);
|
||||
test_no_accel(0.5, 1.5);
|
||||
|
||||
/* Rotation tests: verify cross-axis output when one axis is 0.
|
||||
* At 45 degrees, (10, 0) should produce roughly (7, 7) - not (10, 0).
|
||||
* At 90 degrees, (10, 0) should produce roughly (0, 10). */
|
||||
test_rotation(1, 45);
|
||||
test_rotation(1, 90);
|
||||
|
||||
print_success;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
#include "../fixedptc.h"
|
||||
#include "./test_utils.h"
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
void test_eq(char *value, double expected) {
|
||||
fpt n = atofp(value);
|
||||
double actual = fpt_todouble(n);
|
||||
dbg("actual: (%li) %.15f, vs expected: %.15f\n", n, actual, expected);
|
||||
assert(actual == expected);
|
||||
}
|
||||
|
||||
void super_tiny_micro_minuscule_bench() {
|
||||
int iterations = 100000;
|
||||
double sum = 0;
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
struct timespec begin, end;
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &begin);
|
||||
|
||||
fpt n = atofp("1826512586328");
|
||||
dbg("atofp(\"1826512586328\") = %li\n", n);
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &end);
|
||||
sum += (double)(end.tv_nsec - begin.tv_nsec);
|
||||
}
|
||||
|
||||
double avg = sum / iterations;
|
||||
printf(" Avg run time is %fns\n", avg);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
test_eq("1073741824", 0.25);
|
||||
test_eq("536870912", 0.125);
|
||||
test_eq("1342177280", 0.3125);
|
||||
test_eq("-335007449088", -78);
|
||||
|
||||
print_success;
|
||||
|
||||
super_tiny_micro_minuscule_bench();
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#include "../dbg.h"
|
||||
#include "../fixedptc.h"
|
||||
#include "test_utils.h"
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void test_custom_division_against_fixedpt(double a, double b) {
|
||||
#if FIXEDPT_BITS == 32
|
||||
return;
|
||||
#else
|
||||
|
||||
fpt n = fpt_rconst(a);
|
||||
fpt divisor = fpt_rconst(b);
|
||||
|
||||
fpt quotient = div128_s64_s64(n, divisor);
|
||||
fpt quotient1 = fpt_xdiv(n, divisor);
|
||||
|
||||
double actual = fpt_todouble(quotient);
|
||||
double expected = fpt_todouble(quotient1);
|
||||
|
||||
dbg("actual = (%li) -> %.10f", quotient, actual);
|
||||
dbg("expect = (%li) -> %.10f", quotient1, expected);
|
||||
|
||||
assert(actual == expected);
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
|
||||
test_custom_division_against_fixedpt(57, 5.5);
|
||||
|
||||
test_custom_division_against_fixedpt(0, 2.57);
|
||||
|
||||
test_custom_division_against_fixedpt(-1, 3);
|
||||
|
||||
test_custom_division_against_fixedpt(-128, 4);
|
||||
|
||||
test_custom_division_against_fixedpt(127, 1.5);
|
||||
|
||||
/* test_custom_division_against_fixedpth(135, 0); */ // You only crash once!
|
||||
|
||||
print_success;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#include "../fixedptc.h"
|
||||
#include "test_utils.h"
|
||||
#include <assert.h>
|
||||
#include <linux/limits.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int assert_string_value(char *filename, double value) {
|
||||
fpt v = fpt_rconst(value);
|
||||
char *_v = fptoa(v);
|
||||
|
||||
dbg("to_string %f = %s", value, _v);
|
||||
|
||||
assert_snapshot(filename, _v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define test_str(value) \
|
||||
assert(assert_string_value(__FILE_NAME__ "_" #value ".snapshot", value) == 0)
|
||||
|
||||
int main(void) {
|
||||
test_str(0.25);
|
||||
test_str(0.125);
|
||||
test_str(0.3125);
|
||||
test_str(-785);
|
||||
|
||||
print_success;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
#include "../speed.h"
|
||||
#include "./test_utils.h"
|
||||
#include <stdio.h>
|
||||
|
||||
int assert_string_value(char *filename, double x, double y, double t) {
|
||||
fpt dx = fpt_rconst(x);
|
||||
fpt dy = fpt_rconst(y);
|
||||
fpt dt = fpt_rconst(t);
|
||||
|
||||
dbg("in (%f, %f)", x, y);
|
||||
dbg("in: x (fpt conversion) %s", fptoa(x));
|
||||
dbg("in: y (fpt conversion) %s", fptoa(y));
|
||||
|
||||
fpt s = input_speed(dx, dy, dt);
|
||||
|
||||
double res = fpt_todouble(s);
|
||||
dbg("(%f, %f) dt = %f -> %f\n", x, y, t, res);
|
||||
|
||||
char content[100];
|
||||
sprintf(content, "(sqrt(%f, %f) / %f) = %f\n", x, y, t, res);
|
||||
|
||||
assert_snapshot(filename, content);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define test(x, y, time) \
|
||||
assert(assert_string_value(__FILE_NAME__ "_sqrt_" #x "_" #y "_" #time \
|
||||
".snapshot", \
|
||||
x, y, time) == 0)
|
||||
|
||||
int main(void) {
|
||||
test(1, 1, 1);
|
||||
test(1, 21, 1);
|
||||
test(64, -37, 1);
|
||||
test(1, 4, 1);
|
||||
|
||||
test(-1, 1, 4);
|
||||
|
||||
test(1, 0, 100);
|
||||
|
||||
test(1, -1, 100);
|
||||
|
||||
test(-1, -24, 1);
|
||||
|
||||
print_success;
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
for test in tests/*.test.c; do
|
||||
if [[ ! $test =~ $TEST_NAME ]]; then
|
||||
continue
|
||||
fi
|
||||
gcc ${test} -o maccel_test -lm $DRIVER_CFLAGS || exit 1
|
||||
./maccel_test || exit 1
|
||||
rm maccel_test
|
||||
done
|
||||
@@ -0,0 +1 @@
|
||||
-785.000000000
|
||||
@@ -0,0 +1 @@
|
||||
0.125000000
|
||||
@@ -0,0 +1 @@
|
||||
0.250000000
|
||||
@@ -0,0 +1 @@
|
||||
0.312500000
|
||||
@@ -0,0 +1 @@
|
||||
(sqrt(-1.000000, -24.000000) / 1.000000) = 24.020824
|
||||
@@ -0,0 +1 @@
|
||||
(sqrt(-1.000000, 1.000000) / 4.000000) = 0.353553
|
||||
@@ -0,0 +1 @@
|
||||
(sqrt(1.000000, -1.000000) / 100.000000) = 0.014142
|
||||
@@ -0,0 +1 @@
|
||||
(sqrt(1.000000, 0.000000) / 100.000000) = 0.010000
|
||||
@@ -0,0 +1 @@
|
||||
(sqrt(1.000000, 1.000000) / 1.000000) = 1.414214
|
||||
@@ -0,0 +1 @@
|
||||
(sqrt(1.000000, 21.000000) / 1.000000) = 21.023796
|
||||
@@ -0,0 +1 @@
|
||||
(sqrt(1.000000, 4.000000) / 1.000000) = 4.123106
|
||||
@@ -0,0 +1 @@
|
||||
(sqrt(64.000000, -37.000000) / 1.000000) = 73.925638
|
||||
@@ -0,0 +1,137 @@
|
||||
#include <assert.h>
|
||||
#include <linux/limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static int diff(const char *content, const char *filename) {
|
||||
|
||||
int pipe_fd[2];
|
||||
pid_t child_pid;
|
||||
|
||||
// Create a pipe for communication
|
||||
if (pipe(pipe_fd) == -1) {
|
||||
perror("Pipe creation failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Fork the process
|
||||
if ((child_pid = fork()) == -1) {
|
||||
perror("Fork failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (child_pid == 0) { // Child process
|
||||
// Close the write end of the pipe
|
||||
close(pipe_fd[1]);
|
||||
|
||||
// Redirect stdin to read from the pipe
|
||||
dup2(pipe_fd[0], STDIN_FILENO);
|
||||
|
||||
// Execute a command (e.g., "wc -l")
|
||||
execlp("diff", "diff", "-u", "--color", filename, "-", NULL);
|
||||
|
||||
// If execlp fails
|
||||
perror("Exec failed");
|
||||
exit(EXIT_FAILURE);
|
||||
} else { // Parent process
|
||||
// Close the read end of the pipe
|
||||
close(pipe_fd[0]);
|
||||
|
||||
// Write data to the child process
|
||||
if (write(pipe_fd[1], content, strlen(content)) == -1) {
|
||||
perror("failed to write content to the pipe for diff");
|
||||
}
|
||||
|
||||
close(pipe_fd[1]);
|
||||
|
||||
// Wait for the child process to finish
|
||||
wait(NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_current_working_dir(char *buf, size_t buf_size) {
|
||||
if (getcwd(buf, buf_size) != NULL) {
|
||||
return 0;
|
||||
}
|
||||
perror("getcwd() error");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static char *create_snapshot_file_path(const char *filename) {
|
||||
char cwd[PATH_MAX];
|
||||
if (get_current_working_dir(cwd, PATH_MAX)) {
|
||||
return NULL;
|
||||
};
|
||||
|
||||
static char filepath[PATH_MAX];
|
||||
sprintf(filepath, "%s/tests/snapshots/%s", cwd, filename);
|
||||
return filepath;
|
||||
}
|
||||
|
||||
static void assert_snapshot(const char *__filename, const char *content) {
|
||||
char *filename = create_snapshot_file_path(__filename);
|
||||
if (filename == NULL) {
|
||||
fprintf(stderr, "failed to create snapshot file: %s\n", filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int snapshot_file_exists = access(filename, F_OK) != -1;
|
||||
FILE *snapshot_file;
|
||||
|
||||
if (snapshot_file_exists) {
|
||||
snapshot_file = fopen(filename, "r");
|
||||
} else {
|
||||
snapshot_file = fopen(filename, "w");
|
||||
}
|
||||
|
||||
if (snapshot_file == NULL) {
|
||||
fprintf(stderr, "failed to open or create the snapshot file: %s\n",
|
||||
filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (snapshot_file_exists) {
|
||||
struct stat stats;
|
||||
int file_size;
|
||||
|
||||
stat(filename, &stats);
|
||||
file_size = stats.st_size;
|
||||
char *snapshot = (char *)malloc(stats.st_size + 1);
|
||||
|
||||
if (snapshot == NULL) {
|
||||
fprintf(stderr,
|
||||
"failed to allocate %zd bytes of a string for the snapshot "
|
||||
"content in file: %s\n",
|
||||
stats.st_size, filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
size_t bytes_read = fread(snapshot, 1, file_size, snapshot_file);
|
||||
if (bytes_read != file_size) {
|
||||
fprintf(stderr, "failed to read a snapshot file %s\n", filename);
|
||||
exit(1);
|
||||
}
|
||||
snapshot[file_size] = 0; // null byte terminator
|
||||
|
||||
int string_test_diff = strcmp(snapshot, content);
|
||||
|
||||
diff(content, filename);
|
||||
|
||||
/* dbg("diff in content = %d: snapshot '%s' vs now '%s'", string_test, */
|
||||
/* snapshot, content); */
|
||||
assert(string_test_diff == 0);
|
||||
} else {
|
||||
fprintf(snapshot_file, "%s", content);
|
||||
printf("created a snapshot file %s\n", filename);
|
||||
}
|
||||
|
||||
fclose(snapshot_file);
|
||||
}
|
||||
|
||||
#define print_success printf("[%s]\t\tAll tests passed!\n", __FILE_NAME__)
|
||||
Reference in New Issue
Block a user