mirror of
https://github.com/open-goal/jak-project.git
synced 2024-12-03 11:50:58 +00:00
Cleanup goalc tests, fix jak2 kernel bugs (#1669)
* Cleanup goalc tests, fix jak2 kernel bugs * fix warnings on linux * spelling is hard
This commit is contained in:
parent
12fd8a09b1
commit
e9567a6e4b
@ -426,21 +426,25 @@
|
||||
:flag-assert #x90000000c
|
||||
)
|
||||
|
||||
;; a "catch" frame is a frame that can be "thrown" to.
|
||||
;; the "throw" is a nonlocal control flow back to the state before the "catch" block.
|
||||
(deftype catch-frame (stack-frame)
|
||||
((sp int32 :offset-assert 12)
|
||||
(ra int32 :offset-assert 16)
|
||||
(freg float 6 :offset-assert 20) ;; guessed by decompiler
|
||||
(rreg uint128 8 :offset-assert 48) ;; guessed by decompiler
|
||||
((sp int32 :offset-assert 12)
|
||||
(ra int32 :offset-assert 16)
|
||||
; (freg float 6 :offset-assert 20)
|
||||
; (rreg uint128 8 :offset-assert 48)
|
||||
;; In OpenGOAL, we swap a rreg for 4 more fregs.
|
||||
(freg float 10 :offset-assert 20) ;; only use 8
|
||||
(rreg uint128 7) ;; only use 5
|
||||
)
|
||||
(:methods
|
||||
(new (symbol type symbol function (pointer uint64)) object 0)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #xb0
|
||||
:flag-assert #x9000000b0
|
||||
(:methods
|
||||
(new (symbol type symbol function (pointer uint64)) object 0)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
(deftype protect-frame (stack-frame)
|
||||
((exit (function none) :offset-assert 12) ;; guessed by decompiler
|
||||
)
|
||||
|
@ -112,10 +112,6 @@ bool HasError() {
|
||||
}
|
||||
}
|
||||
|
||||
void FocusCallback(GLFWwindow* window, int focused) {
|
||||
glfwSetWindowAttrib(window, GLFW_FLOATING, focused);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
static bool gl_inited = false;
|
||||
|
@ -1038,14 +1038,14 @@ u64 call_method_of_type(u64 arg, Ptr<Type> type, u32 method_id) {
|
||||
if (((type.offset < SymbolTable2.offset || 0x7ffffff < type.offset) && // not in normal memory
|
||||
(type.offset < 0x84000 || 0x100000 <= type.offset)) // not in kernel memory
|
||||
|| ((type.offset & OFFSET_MASK) != BASIC_OFFSET)) { // invalid type
|
||||
cprintf("#<#%x has invalid type ptr #x%x>\n", arg, type.offset);
|
||||
cprintf("#<#%x has invalid type ptr #x%x>\n", (u32)arg, type.offset);
|
||||
} else {
|
||||
auto type_tag = Ptr<Ptr<Type>>(type.offset - 4);
|
||||
if ((*type_tag).offset == *(s7 + FIX_SYM_TYPE_TYPE)) {
|
||||
auto f = type->get_method(method_id);
|
||||
return call_goal(f, arg, 0, 0, s7.offset, g_ee_main_mem);
|
||||
} else {
|
||||
cprintf("#<#x%x has invalid type ptr #x%x, bad type #x%x>\n", arg, type.offset,
|
||||
cprintf("#<#x%x has invalid type ptr #x%x, bad type #x%x>\n", (u32)arg, type.offset,
|
||||
(*type_tag).offset);
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,3 @@
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
|
||||
#elif defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunused-but-set-variable"
|
||||
#endif
|
||||
|
||||
//--------------------------MIPS2C---------------------
|
||||
#include "common/dma/gs.h"
|
||||
|
||||
@ -3284,9 +3276,3 @@ void link() {
|
||||
|
||||
} // namespace method_9_collide_puss_work
|
||||
} // namespace Mips2C
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic pop
|
||||
#elif defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
@ -1,11 +1,3 @@
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
|
||||
#elif defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunused-but-set-variable"
|
||||
#endif
|
||||
|
||||
//--------------------------MIPS2C---------------------
|
||||
#include "game/kernel/jak1/kscheme.h"
|
||||
#include "game/mips2c/mips2c_private.h"
|
||||
@ -1016,11 +1008,4 @@ void link() {
|
||||
}
|
||||
|
||||
} // namespace method_18_collide_edge_work
|
||||
} // namespace Mips2C
|
||||
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic pop
|
||||
#elif defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
} // namespace Mips2C
|
@ -400,12 +400,15 @@
|
||||
)
|
||||
|
||||
;; a "catch" frame is a frame that can be "thrown" to.
|
||||
;; the "throw" is a nonlocal control flow back to the state befor the "catch" block.
|
||||
;; the "throw" is a nonlocal control flow back to the state before the "catch" block.
|
||||
(deftype catch-frame (stack-frame)
|
||||
((sp int32 :offset-assert 12)
|
||||
(ra int32 :offset-assert 16)
|
||||
(freg float 6 :offset-assert 20)
|
||||
(rreg uint128 8 :offset-assert 48)
|
||||
; (freg float 6 :offset-assert 20)
|
||||
; (rreg uint128 8 :offset-assert 48)
|
||||
;; In OpenGOAL, we swap a rreg for 4 more fregs.
|
||||
(freg float 10 :offset-assert 20) ;; only use 8
|
||||
(rreg uint128 7) ;; only use 5
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #xb0
|
||||
@ -688,4 +691,11 @@
|
||||
((-> (the cpu-thread pp) suspend-hook) (the cpu-thread 0))
|
||||
;; the kernel will set pp (possibly to a new value, if we've been relocated) on resume.
|
||||
)
|
||||
)
|
||||
|
||||
(defmacro process-deactivate ()
|
||||
"deactivate (kill) the current process"
|
||||
`(rlet ((pp :reg r13 :reset-here #t :type process))
|
||||
(deactivate pp)
|
||||
)
|
||||
)
|
@ -38,49 +38,6 @@ struct BBox {
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
* Make the bounding box hold this node and all its children.
|
||||
*/
|
||||
void add_to_bbox_recursive(const CNode& node, BBox& bbox) {
|
||||
if (node.faces.empty()) {
|
||||
for (auto& child : node.child_nodes) {
|
||||
add_to_bbox_recursive(child, bbox);
|
||||
}
|
||||
} else {
|
||||
for (auto& face : node.faces) {
|
||||
for (auto& vert : face.v) {
|
||||
bbox.mins.min_in_place(vert);
|
||||
bbox.maxs.max_in_place(vert);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BBox bbox_of_node(const CNode& node) {
|
||||
BBox bbox;
|
||||
bbox.mins.fill(std::numeric_limits<float>::max());
|
||||
bbox.maxs.fill(-std::numeric_limits<float>::max());
|
||||
add_to_bbox_recursive(node, bbox);
|
||||
return bbox;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Make the bsphere hold this node and all its children.
|
||||
*/
|
||||
void update_bsphere_recursive(const CNode& node, const math::Vector3f& origin, float& r_squared) {
|
||||
if (node.faces.empty()) {
|
||||
for (auto& child : node.child_nodes) {
|
||||
update_bsphere_recursive(child, origin, r_squared);
|
||||
}
|
||||
} else {
|
||||
for (auto& face : node.faces) {
|
||||
for (auto& vert : face.v) {
|
||||
r_squared = std::max(r_squared, (vert - origin).squared_length());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void collect_vertices(const CNode& node, std::vector<math::Vector3f>& verts) {
|
||||
for (auto& child : node.child_nodes) {
|
||||
collect_vertices(child, verts);
|
||||
@ -125,22 +82,6 @@ void compute_my_bsphere_ritters(CNode& node) {
|
||||
node.bsphere.w() = std::sqrt(max_squared);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Compute the bsphere of a single node.
|
||||
*/
|
||||
BBox compute_my_bsphere_bad(CNode& node) {
|
||||
// first compute bbox.
|
||||
BBox bbox = bbox_of_node(node);
|
||||
float r = 0;
|
||||
math::Vector3f origin = (bbox.maxs + bbox.mins) * 0.5;
|
||||
update_bsphere_recursive(node, origin, r);
|
||||
node.bsphere.x() = origin.x();
|
||||
node.bsphere.y() = origin.y();
|
||||
node.bsphere.z() = origin.z();
|
||||
node.bsphere.w() = std::sqrt(r);
|
||||
return bbox;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Split faces in two along a coordinate plane.
|
||||
* Will clear the input faces
|
||||
|
@ -1,8 +1,18 @@
|
||||
set(GOALC_TEST_CASES
|
||||
${CMAKE_CURRENT_LIST_DIR}/all_goalc_template_tests.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/test_arithmetic.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/test_collections.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/test_compiler.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/test_control_statements.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/test_debugger.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/test_game_no_debug.cpp
|
||||
)
|
||||
${CMAKE_CURRENT_LIST_DIR}/test_goal_kernel.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/test_goal_kernel2.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/test_jak2_compiler.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/test_variables.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/test_with_game.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/test_type_consistency.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/test_vector_float.cpp
|
||||
)
|
||||
|
||||
set(GOALC_TEST_FRAMEWORK_SOURCES
|
||||
${CMAKE_CURRENT_LIST_DIR}/framework/test_runner.cpp
|
||||
|
@ -1,6 +0,0 @@
|
||||
#include "test_arithmetic.cpp"
|
||||
#include "test_collections.cpp"
|
||||
#include "test_compiler.cpp"
|
||||
#include "test_control_statements.cpp"
|
||||
#include "test_variables.cpp"
|
||||
#include "test_with_game.cpp"
|
@ -51,6 +51,14 @@ void CompilerTestRunner::run_static_test(inja::Environment& env,
|
||||
run_test(testCategory, test_file, expected, truncate);
|
||||
}
|
||||
|
||||
void CompilerTestRunner::run_static_test(std::string& testCategory,
|
||||
const std::string& test_file,
|
||||
const std::vector<std::string>& expected,
|
||||
std::optional<int> truncate) {
|
||||
auto env = getInjaEnvironment(testCategory);
|
||||
run_static_test(env, testCategory, test_file, expected, truncate);
|
||||
}
|
||||
|
||||
void CompilerTestRunner::run_test(const std::string& test_category,
|
||||
const std::string& test_file,
|
||||
const std::vector<std::string>& expected,
|
||||
@ -98,7 +106,7 @@ void CompilerTestRunner::run_always_pass(const std::string& test_category,
|
||||
tests.push_back({{}, {}, test_file, true});
|
||||
}
|
||||
|
||||
void runtime_no_kernel() {
|
||||
void runtime_no_kernel_jak1() {
|
||||
constexpr int argc = 6;
|
||||
const char* argv[argc] = {"", "-fakeiso", "-debug", "-nokernel", "-nodisplay", "-nosound"};
|
||||
exec_runtime(argc, const_cast<char**>(argv));
|
||||
@ -111,12 +119,18 @@ void runtime_no_kernel_jak2() {
|
||||
exec_runtime(argc, const_cast<char**>(argv));
|
||||
}
|
||||
|
||||
void runtime_with_kernel() {
|
||||
void runtime_with_kernel_jak1() {
|
||||
constexpr int argc = 5;
|
||||
const char* argv[argc] = {"", "-fakeiso", "-debug", "-nodisplay", "-nosound"};
|
||||
exec_runtime(argc, const_cast<char**>(argv));
|
||||
}
|
||||
|
||||
void runtime_with_kernel_jak2() {
|
||||
constexpr int argc = 6;
|
||||
const char* argv[argc] = {"", "-fakeiso", "-debug", "-nodisplay", "-nosound", "-jak2"};
|
||||
exec_runtime(argc, const_cast<char**>(argv));
|
||||
}
|
||||
|
||||
void runtime_with_kernel_no_debug_segment() {
|
||||
constexpr int argc = 5;
|
||||
const char* argv[argc] = {"", "-fakeiso", "-debug-mem", "-nodisplay", "-nosound"};
|
||||
@ -137,4 +151,9 @@ std::string getGeneratedDir(const std::string& category) {
|
||||
std::string getFailedDir(const std::string& category) {
|
||||
return file_util::get_file_path({"test/goalc/source_generated/failed", category + "/"});
|
||||
}
|
||||
|
||||
inja::Environment getInjaEnvironment(const std::string& category) {
|
||||
return inja::Environment(getTemplateDir(category), getGeneratedDir(category));
|
||||
}
|
||||
|
||||
} // namespace GoalTest
|
||||
|
@ -4,10 +4,12 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "inja.hpp"
|
||||
|
||||
#include "goalc/compiler/Compiler.h"
|
||||
|
||||
namespace inja {
|
||||
class Environment;
|
||||
}
|
||||
|
||||
namespace GoalTest {
|
||||
|
||||
std::string escaped_string(const std::string& in);
|
||||
@ -32,19 +34,23 @@ struct CompilerTestRunner {
|
||||
const std::vector<std::string>& expected,
|
||||
std::optional<int> truncate = {});
|
||||
|
||||
void run_static_test(std::string& testCategory,
|
||||
const std::string& test_file,
|
||||
const std::vector<std::string>& expected,
|
||||
std::optional<int> truncate = {});
|
||||
|
||||
void run_test(const std::string& test_category,
|
||||
const std::string& test_file,
|
||||
const std::vector<std::string>& expected,
|
||||
std::optional<int> truncate = {});
|
||||
|
||||
void run_always_pass(const std::string& test_category, const std::string& test_file);
|
||||
|
||||
void print_summary();
|
||||
};
|
||||
|
||||
void runtime_no_kernel();
|
||||
void runtime_no_kernel_jak1();
|
||||
void runtime_no_kernel_jak2();
|
||||
void runtime_with_kernel();
|
||||
void runtime_with_kernel_jak1();
|
||||
void runtime_with_kernel_jak2();
|
||||
void runtime_with_kernel_no_debug_segment();
|
||||
|
||||
void createDirIfAbsent(const std::string& path);
|
||||
@ -52,4 +58,6 @@ std::string getTemplateDir(const std::string& category);
|
||||
std::string getGeneratedDir(const std::string& category);
|
||||
std::string getFailedDir(const std::string& category);
|
||||
|
||||
inja::Environment getInjaEnvironment(const std::string& category);
|
||||
|
||||
} // namespace GoalTest
|
||||
|
227
test/goalc/source_templates/jak2/kernel-test.gc
Normal file
227
test/goalc/source_templates/jak2/kernel-test.gc
Normal file
@ -0,0 +1,227 @@
|
||||
|
||||
(defun target-function ((a0 uint) (a1 uint) (a2 uint) (a3 uint) (a4 uint) (a5 uint))
|
||||
(format #t "TARGET FUNCTION ~D ~D ~D~%" a0 a1 a2)
|
||||
(format #t "~D ~D ~D~%" a3 a4 a5)
|
||||
|
||||
(let ((stack-arr (new 'stack-no-clear 'array 'uint8 12)))
|
||||
(format #t "Stack Alignemnt ~D/16~%" (logand 15 (the uint stack-arr)))
|
||||
)
|
||||
|
||||
(dotimes (i 10)
|
||||
(format #t "proc1: ~D~%" i)
|
||||
(when (> i 4)
|
||||
(format #t "DEACTIVATE PROC 1~%")
|
||||
(process-deactivate)
|
||||
)
|
||||
(suspend)
|
||||
)
|
||||
)
|
||||
|
||||
(define-extern recurse (function int (pointer int32) int))
|
||||
(defun recurse ((i int) (ptr (pointer int32)))
|
||||
(if (> i 0)
|
||||
(recurse (- i 1) ptr)
|
||||
(suspend)
|
||||
)
|
||||
(set! (-> ptr) (+ (-> ptr) 1))
|
||||
1
|
||||
)
|
||||
|
||||
(defun target-function-2 ()
|
||||
(let ((stack-var (new 'stack-no-clear 'array 'int32 1)))
|
||||
(set! (-> stack-var) 0)
|
||||
(countdown (i 10)
|
||||
(format #t "proc2: ~D~%" (-> stack-var))
|
||||
(recurse 5 stack-var)
|
||||
)
|
||||
)
|
||||
|
||||
)
|
||||
|
||||
(defun kernel-test ()
|
||||
(define test-process (get-process *nk-dead-pool* process 1024))
|
||||
|
||||
(activate test-process *active-pool* "test-proc" *kernel-dram-stack*)
|
||||
|
||||
|
||||
(set-to-run (-> test-process main-thread)
|
||||
target-function
|
||||
1 2 3 4 5 6
|
||||
)
|
||||
|
||||
(define test-process-2 (get-process *nk-dead-pool* process 1024))
|
||||
;; test that the kernel fakes having process stacks on the scratchpad.
|
||||
(activate test-process-2 *active-pool* "test-2" (the pointer #x70004000))
|
||||
(set-to-run (-> test-process-2 main-thread)
|
||||
target-function-2
|
||||
0 0 0 0 0 0)
|
||||
0
|
||||
)
|
||||
|
||||
(defun check-current-proc-catch-rbx ()
|
||||
;; (format 0 "last rbx = ~X~%" *last-rbx*)
|
||||
(with-pp
|
||||
(format 0 "PP = ~X~%" pp)
|
||||
(let ((frame (-> pp stack-frame-top)))
|
||||
(format 0 "FRAME0: ~A~%" frame)
|
||||
|
||||
(while frame
|
||||
(format 0 "FRAME: ~A~%" frame)
|
||||
(when (= (-> frame type) catch-frame)
|
||||
(format 0 "found upcoming protect frame! ~A: ~X~%"
|
||||
(-> (the catch-frame frame) name)
|
||||
(-> (the catch-frame frame) rreg 0)
|
||||
)
|
||||
)
|
||||
(set! frame (-> frame next))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
(defun init-child-proc (a0 a1 a2 a3 a4 a5)
|
||||
(format #t "Args: ~D ~D ~D~%" a0 a1 a2)
|
||||
(format #t "~D ~D ~D~%" a3 a4 a5)
|
||||
(let ((stack-arr (new 'stack-no-clear 'array 'uint8 12)))
|
||||
(format #t "Stack Alignemnt ~D/16~%" (logand 15 (the uint stack-arr)))
|
||||
)
|
||||
(when (eq? a0 (the int 0))
|
||||
(format 0 "doing child proc deactivate~%")
|
||||
(check-current-proc-catch-rbx)
|
||||
(process-deactivate)
|
||||
)
|
||||
'init-child-proc-result
|
||||
)
|
||||
|
||||
|
||||
(defun initializer-process-function (a0)
|
||||
(format 0 "ipf: ~D~%" a0)
|
||||
(let ((child-proc (get-process *nk-dead-pool* process 1024)))
|
||||
;; let's go
|
||||
(activate child-proc *active-pool* "child-proc" *kernel-dram-stack*)
|
||||
(format 0 "child-proc activated...~%")
|
||||
(let ((result (run-function-in-process child-proc init-child-proc a0 2 3 4 5 6)))
|
||||
(format 0 "child-proc reuslt: ~D~%" result)
|
||||
(format #t "run-function-in-process result: ~A~%" result)
|
||||
)
|
||||
)
|
||||
|
||||
(format 0 "proc-deactivate ~D~%" a0)
|
||||
(rlet ((pp :reg r13 :reset-here #t :type process))
|
||||
;; (deactivate pp)
|
||||
(format 0 " proc is: #x~X~%" pp)
|
||||
)
|
||||
(check-current-proc-catch-rbx)
|
||||
(process-deactivate)
|
||||
(format 0 "proc-deactivate end?~%")
|
||||
|
||||
)
|
||||
|
||||
(defun kernel-test-2 ()
|
||||
(define initalizer-process (get-process *nk-dead-pool* process 1024))
|
||||
(activate initalizer-process *active-pool* "initializer-proc" *kernel-dram-stack*)
|
||||
(set-to-run (-> initalizer-process main-thread)
|
||||
initializer-process-function
|
||||
0 0 0 0 0 0
|
||||
)
|
||||
(define initalizer-process-2 (get-process *nk-dead-pool* process 1024))
|
||||
(activate initalizer-process-2 *active-pool* "initializer-proc-2" *kernel-dram-stack*)
|
||||
(set-to-run (-> initalizer-process-2 main-thread)
|
||||
initializer-process-function
|
||||
1 0 0 0 0 0
|
||||
)
|
||||
(format 0 "kt2 return~%")
|
||||
0
|
||||
)
|
||||
|
||||
|
||||
(defstate die-state (process)
|
||||
:enter (lambda () (format #t "enter die~%") (none))
|
||||
:exit (lambda () (format #t "exit die~%") (none))
|
||||
:code (lambda ()
|
||||
(format #t "time to die!~%")
|
||||
(process-deactivate)
|
||||
(format #t "don't see me~%")
|
||||
)
|
||||
)
|
||||
|
||||
(defun xmm-check-code (ax ay az aw)
|
||||
"This function relies on saved xmm register being backed up on a context switch"
|
||||
;; (declare (print-asm))
|
||||
;; compiler will put these in xmm8 and xmm9 to keep them from being clobbered
|
||||
(let ((x 12.34)
|
||||
(y 45.63))
|
||||
(dotimes (i 3)
|
||||
(format #t "run xmm-check ~f ~f ~D ~D ~D ~D~%" x y ax ay az aw)
|
||||
;; should preserve xmm8 and xmm9
|
||||
(suspend)
|
||||
)
|
||||
;; get the wreck process and make it go to die state.
|
||||
(go-process (process-by-name "wreck-proc" *active-pool*) die-state)
|
||||
(go die-state)
|
||||
(format #t "unreachable~%")
|
||||
)
|
||||
)
|
||||
|
||||
(defun xmm-wreck-code (ax ay az aw)
|
||||
"This function intentionally overwrites xmm8 and xmm9 and suspends"
|
||||
(while #t
|
||||
(rlet ((x :class fpr :type float :reg xmm8)
|
||||
(y :class fpr :type float :reg xmm9))
|
||||
(set! x 99.0)
|
||||
(set! y 101.0)
|
||||
(format #t "wreck: ~D ~D ~D ~D~%" ax ay az aw)
|
||||
(suspend)
|
||||
(set! x (+ x 1.0))
|
||||
(set! y (+ y 1.0))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; a state.
|
||||
(defstate xmm-check-state (process)
|
||||
:enter (lambda (x y z w) (format #t "enter check: ~D ~D ~D ~D~%" x y z w) (none))
|
||||
:exit (lambda () (format #t "exit check~%") (none))
|
||||
:code xmm-check-code
|
||||
)
|
||||
|
||||
(defstate xmm-wreck-state (process)
|
||||
:enter (lambda (x y z w) (format #t "enter wreck: ~D ~D ~D ~D~%" x y z w) (none))
|
||||
:exit (lambda () (format #t "exit wreck~%") (none))
|
||||
:code xmm-wreck-code
|
||||
)
|
||||
|
||||
(defun state-test ()
|
||||
(let ((proc (get-process *nk-dead-pool* process 1024)))
|
||||
(activate proc *active-pool* "check-proc" *kernel-dram-stack*)
|
||||
(run-now-in-process proc (lambda (x y z w) (go xmm-check-state x y z w))
|
||||
9 8 7 6)
|
||||
)
|
||||
|
||||
(let ((proc (get-process *nk-dead-pool* process 1024)))
|
||||
(activate proc *active-pool* "wreck-proc" *kernel-dram-stack*)
|
||||
(run-next-time-in-process proc (lambda (x y z w) (go xmm-wreck-state x y z w))
|
||||
3 4 5 6)
|
||||
)
|
||||
0
|
||||
)
|
||||
|
||||
(defun throw-backup-test ()
|
||||
(rlet ((x :reg xmm10 :class fpr :type float))
|
||||
(set! x 10.10)
|
||||
(let ((proc (get-process *nk-dead-pool* process 1024)))
|
||||
(activate proc *active-pool* "asdf" *kernel-dram-stack*)
|
||||
(format #t "value now is ~f~%" x)
|
||||
(run-now-in-process proc (lambda ()
|
||||
(rlet ((x2 :reg xmm10 :class fpr :type float))
|
||||
(set! x2 -1.0)
|
||||
)
|
||||
;; this will throw back.
|
||||
(process-deactivate)
|
||||
)
|
||||
)
|
||||
(format #t "now its ~f~%" x)
|
||||
|
||||
)
|
||||
)
|
||||
)
|
@ -1,7 +1,6 @@
|
||||
// https://github.com/google/googletest/blob/master/googletest/docs/advanced.md#value-parameterized-tests
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <sstream>
|
||||
@ -119,7 +118,7 @@ class ArithmeticTests : public testing::TestWithParam<IntegerParam> {
|
||||
// Per-test-suite set-up.
|
||||
// Called before the first test in this test suite.
|
||||
static void SetUpTestSuite() {
|
||||
runtime_thread = std::make_unique<std::thread>(std::thread((GoalTest::runtime_no_kernel)));
|
||||
runtime_thread = std::make_unique<std::thread>(std::thread(GoalTest::runtime_no_kernel_jak1));
|
||||
compiler = std::make_unique<Compiler>(GameVersion::Jak1);
|
||||
runner = std::make_unique<GoalTest::CompilerTestRunner>();
|
||||
runner->c = compiler.get();
|
||||
|
@ -1,21 +1,11 @@
|
||||
#include <chrono>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
#include "inja.hpp"
|
||||
|
||||
#include "game/runtime.h"
|
||||
#include "goalc/compiler/Compiler.h"
|
||||
#include "goalc/listener/Listener.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "test/goalc/framework/test_runner.h"
|
||||
|
||||
#include "third-party/json.hpp"
|
||||
|
||||
struct CollectionParam {
|
||||
// TODO - Not Needed Yet
|
||||
};
|
||||
@ -23,7 +13,7 @@ struct CollectionParam {
|
||||
class CollectionTests : public testing::TestWithParam<CollectionParam> {
|
||||
public:
|
||||
static void SetUpTestSuite() {
|
||||
runtime_thread = std::make_unique<std::thread>(std::thread((GoalTest::runtime_no_kernel)));
|
||||
runtime_thread = std::make_unique<std::thread>(std::thread(GoalTest::runtime_no_kernel_jak1));
|
||||
compiler = std::make_unique<Compiler>(GameVersion::Jak1);
|
||||
runner = std::make_unique<GoalTest::CompilerTestRunner>();
|
||||
runner->c = compiler.get();
|
||||
@ -50,8 +40,6 @@ class CollectionTests : public testing::TestWithParam<CollectionParam> {
|
||||
static std::unique_ptr<GoalTest::CompilerTestRunner> runner;
|
||||
|
||||
std::string testCategory = "collections";
|
||||
inja::Environment env{GoalTest::getTemplateDir(testCategory),
|
||||
GoalTest::getGeneratedDir(testCategory)};
|
||||
};
|
||||
|
||||
std::unique_ptr<std::thread> CollectionTests::runtime_thread;
|
||||
@ -59,22 +47,22 @@ std::unique_ptr<Compiler> CollectionTests::compiler;
|
||||
std::unique_ptr<GoalTest::CompilerTestRunner> CollectionTests::runner;
|
||||
|
||||
TEST_F(CollectionTests, Pairs) {
|
||||
runner->run_static_test(env, testCategory, "empty-pair.static.gc", {"()\n0\n"});
|
||||
runner->run_static_test(env, testCategory, "pair-check.static.gc", {"#t#f\n0\n"});
|
||||
runner->run_static_test(testCategory, "empty-pair.static.gc", {"()\n0\n"});
|
||||
runner->run_static_test(testCategory, "pair-check.static.gc", {"#t#f\n0\n"});
|
||||
}
|
||||
|
||||
TEST_F(CollectionTests, Lists) {
|
||||
runner->run_static_test(env, testCategory, "list.static.gc", {"(a b c d)\n0\n"});
|
||||
runner->run_static_test(testCategory, "list.static.gc", {"(a b c d)\n0\n"});
|
||||
}
|
||||
|
||||
TEST_F(CollectionTests, InlineArray) {
|
||||
runner->run_static_test(env, testCategory, "inline-array-field.static.gc", {"16\n"});
|
||||
runner->run_static_test(testCategory, "inline-array-field.static.gc", {"16\n"});
|
||||
}
|
||||
|
||||
TEST_F(CollectionTests, Operations) {
|
||||
runner->run_static_test(env, testCategory, "cons.static.gc", {"(a . b)\n0\n"});
|
||||
runner->run_static_test(env, testCategory, "car-cdr-get.static.gc", {"ab\n0\n"});
|
||||
runner->run_static_test(env, testCategory, "car-cdr-set.static.gc", {"(c . d)\n0\n"});
|
||||
runner->run_static_test(env, testCategory, "nested-car-cdr-set.static.gc",
|
||||
runner->run_static_test(testCategory, "cons.static.gc", {"(a . b)\n0\n"});
|
||||
runner->run_static_test(testCategory, "car-cdr-get.static.gc", {"ab\n0\n"});
|
||||
runner->run_static_test(testCategory, "car-cdr-set.static.gc", {"(c . d)\n0\n"});
|
||||
runner->run_static_test(testCategory, "nested-car-cdr-set.static.gc",
|
||||
{"efgh\n((e . g) f . h)\n0\n"});
|
||||
}
|
||||
|
@ -1,65 +1,7 @@
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
#include "game/runtime.h"
|
||||
#include "goalc/compiler/Compiler.h"
|
||||
#include "goalc/listener/Listener.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
TEST(CompilerAndRuntime, ConstructCompiler) {
|
||||
Compiler compiler1(GameVersion::Jak1);
|
||||
Compiler compiler2(GameVersion::Jak2);
|
||||
}
|
||||
|
||||
struct Jak2Param {
|
||||
// TODO - Not Needed Yet
|
||||
};
|
||||
|
||||
class Jak2GoalcTests : public testing::TestWithParam<Jak2Param> {
|
||||
public:
|
||||
static void SetUpTestSuite() {
|
||||
runtime_thread = std::make_unique<std::thread>(std::thread((GoalTest::runtime_no_kernel_jak2)));
|
||||
compiler = std::make_unique<Compiler>(GameVersion::Jak2);
|
||||
runner = std::make_unique<GoalTest::CompilerTestRunner>();
|
||||
runner->c = compiler.get();
|
||||
}
|
||||
|
||||
static void TearDownTestSuite() {
|
||||
compiler->shutdown_target();
|
||||
runtime_thread->join();
|
||||
|
||||
runtime_thread.reset();
|
||||
compiler.reset();
|
||||
runner.reset();
|
||||
}
|
||||
|
||||
void SetUp() {
|
||||
GoalTest::createDirIfAbsent(GoalTest::getTemplateDir(testCategory));
|
||||
GoalTest::createDirIfAbsent(GoalTest::getGeneratedDir(testCategory));
|
||||
}
|
||||
|
||||
void TearDown() {}
|
||||
|
||||
static std::unique_ptr<std::thread> runtime_thread;
|
||||
static std::unique_ptr<Compiler> compiler;
|
||||
static std::unique_ptr<GoalTest::CompilerTestRunner> runner;
|
||||
|
||||
std::string testCategory = "jak2";
|
||||
inja::Environment env{GoalTest::getTemplateDir(testCategory),
|
||||
GoalTest::getGeneratedDir(testCategory)};
|
||||
};
|
||||
|
||||
std::unique_ptr<std::thread> Jak2GoalcTests::runtime_thread;
|
||||
std::unique_ptr<Compiler> Jak2GoalcTests::compiler;
|
||||
std::unique_ptr<GoalTest::CompilerTestRunner> Jak2GoalcTests::runner;
|
||||
|
||||
TEST_F(Jak2GoalcTests, All) {
|
||||
runner->run_static_test(env, testCategory, "jak2-mega-test.gc",
|
||||
{"empty pair: () () () #t #f\n"
|
||||
"empty pair type: pair\n"
|
||||
"non-empty pair: (a b -12) a pair (a . b)\n"
|
||||
"basic types: type symbol string function\n"
|
||||
"bools: #t #f #t #f #f #t\n"
|
||||
"zero: 0\n"
|
||||
"parent of type: basic structure object object\n0\n"});
|
||||
}
|
@ -1,21 +1,11 @@
|
||||
#include <chrono>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
#include "inja.hpp"
|
||||
|
||||
#include "game/runtime.h"
|
||||
#include "goalc/compiler/Compiler.h"
|
||||
#include "goalc/listener/Listener.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "test/goalc/framework/test_runner.h"
|
||||
|
||||
#include "third-party/json.hpp"
|
||||
|
||||
struct ControlStatementParam {
|
||||
// TODO - Not Needed Yet
|
||||
};
|
||||
@ -23,7 +13,7 @@ struct ControlStatementParam {
|
||||
class ControlStatementTests : public testing::TestWithParam<ControlStatementParam> {
|
||||
public:
|
||||
static void SetUpTestSuite() {
|
||||
runtime_thread = std::make_unique<std::thread>(std::thread((GoalTest::runtime_no_kernel)));
|
||||
runtime_thread = std::make_unique<std::thread>(std::thread(GoalTest::runtime_no_kernel_jak1));
|
||||
compiler = std::make_unique<Compiler>(GameVersion::Jak1);
|
||||
runner = std::make_unique<GoalTest::CompilerTestRunner>();
|
||||
runner->c = compiler.get();
|
||||
@ -50,8 +40,6 @@ class ControlStatementTests : public testing::TestWithParam<ControlStatementPara
|
||||
static std::unique_ptr<GoalTest::CompilerTestRunner> runner;
|
||||
|
||||
std::string testCategory = "control-statements";
|
||||
inja::Environment env{GoalTest::getTemplateDir(testCategory),
|
||||
GoalTest::getGeneratedDir(testCategory)};
|
||||
};
|
||||
|
||||
std::unique_ptr<std::thread> ControlStatementTests::runtime_thread;
|
||||
@ -59,50 +47,50 @@ std::unique_ptr<Compiler> ControlStatementTests::compiler;
|
||||
std::unique_ptr<GoalTest::CompilerTestRunner> ControlStatementTests::runner;
|
||||
|
||||
TEST_F(ControlStatementTests, ConditionalCompilation) {
|
||||
runner->run_static_test(env, testCategory, "conditional-compilation.static.gc", {"3\n"});
|
||||
runner->run_static_test(testCategory, "conditional-compilation.static.gc", {"3\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, Blocks) {
|
||||
runner->run_static_test(env, testCategory, "nested-blocks-1.static.gc", {"7\n"});
|
||||
runner->run_static_test(env, testCategory, "nested-blocks-2.static.gc", {"8\n"});
|
||||
runner->run_static_test(env, testCategory, "nested-blocks-3.static.gc", {"7\n"});
|
||||
runner->run_static_test(testCategory, "nested-blocks-1.static.gc", {"7\n"});
|
||||
runner->run_static_test(testCategory, "nested-blocks-2.static.gc", {"8\n"});
|
||||
runner->run_static_test(testCategory, "nested-blocks-3.static.gc", {"7\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, GoTo) {
|
||||
runner->run_static_test(env, testCategory, "goto.static.gc", {"3\n"});
|
||||
runner->run_static_test(testCategory, "goto.static.gc", {"3\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, Branch) {
|
||||
runner->run_static_test(env, testCategory, "return-value-of-if.static.gc", {"123\n"});
|
||||
runner->run_static_test(testCategory, "return-value-of-if.static.gc", {"123\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, DoTimes) {
|
||||
runner->run_static_test(env, testCategory, "dotimes.static.gc", {"4950\n"});
|
||||
runner->run_static_test(testCategory, "dotimes.static.gc", {"4950\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, Factorial) {
|
||||
runner->run_static_test(env, testCategory, "factorial-recursive.static.gc", {"3628800\n"});
|
||||
runner->run_static_test(env, testCategory, "factorial-iterative.static.gc", {"3628800\n"});
|
||||
runner->run_static_test(testCategory, "factorial-recursive.static.gc", {"3628800\n"});
|
||||
runner->run_static_test(testCategory, "factorial-iterative.static.gc", {"3628800\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, Definitions) {
|
||||
runner->run_static_test(env, testCategory, "defun-return-constant.static.gc", {"12\n"});
|
||||
runner->run_static_test(env, testCategory, "defun-return-symbol.static.gc", {"42\n"});
|
||||
runner->run_static_test(testCategory, "defun-return-constant.static.gc", {"12\n"});
|
||||
runner->run_static_test(testCategory, "defun-return-symbol.static.gc", {"42\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, ReturnValue) {
|
||||
runner->run_static_test(env, testCategory, "return.static.gc", {"77\n"});
|
||||
runner->run_static_test(env, testCategory, "return-arg.static.gc", {"23\n"});
|
||||
runner->run_static_test(env, testCategory, "return-colors.static.gc", {"77\n"});
|
||||
runner->run_static_test(testCategory, "return.static.gc", {"77\n"});
|
||||
runner->run_static_test(testCategory, "return-arg.static.gc", {"23\n"});
|
||||
runner->run_static_test(testCategory, "return-colors.static.gc", {"77\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, Calling) {
|
||||
runner->run_static_test(env, testCategory, "nested-call.static.gc", {"2\n"});
|
||||
runner->run_static_test(env, testCategory, "simple-call.static.gc", {"30\n"});
|
||||
runner->run_static_test(testCategory, "nested-call.static.gc", {"2\n"});
|
||||
runner->run_static_test(testCategory, "simple-call.static.gc", {"30\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, Anonymous) {
|
||||
runner->run_static_test(env, testCategory, "lambda-1.static.gc", {"2\n"});
|
||||
runner->run_static_test(testCategory, "lambda-1.static.gc", {"2\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, InlineIsInline) {
|
||||
@ -121,7 +109,7 @@ TEST_F(ControlStatementTests, InlineIsInline) {
|
||||
}
|
||||
}
|
||||
EXPECT_TRUE(got_mult);
|
||||
runner->run_static_test(env, testCategory, "declare-inline.static.gc", {"32\n"});
|
||||
runner->run_static_test(testCategory, "declare-inline.static.gc", {"32\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, AllowInline) {
|
||||
@ -143,54 +131,54 @@ TEST_F(ControlStatementTests, AllowInline) {
|
||||
}
|
||||
EXPECT_EQ(got_mult, 1);
|
||||
EXPECT_EQ(got_call, 1);
|
||||
runner->run_static_test(env, testCategory, "inline-call.static.gc", {"44\n"});
|
||||
runner->run_static_test(testCategory, "inline-call.static.gc", {"44\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, ReturnNone) {
|
||||
runner->run_static_test(env, testCategory, "function-returning-none.static.gc", {"1\n"});
|
||||
runner->run_static_test(testCategory, "function-returning-none.static.gc", {"1\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, InlineBlock1) {
|
||||
runner->run_static_test(env, testCategory, "inline-with-block-1.static.gc", {"1\n"});
|
||||
runner->run_static_test(testCategory, "inline-with-block-1.static.gc", {"1\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, InlineBlock2) {
|
||||
runner->run_static_test(env, testCategory, "inline-with-block-2.static.gc", {"3\n"});
|
||||
runner->run_static_test(testCategory, "inline-with-block-2.static.gc", {"3\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, InlineBlock3) {
|
||||
runner->run_static_test(env, testCategory, "inline-with-block-3.static.gc", {"4\n"});
|
||||
runner->run_static_test(testCategory, "inline-with-block-3.static.gc", {"4\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, InlineBlock4) {
|
||||
runner->run_static_test(env, testCategory, "inline-with-block-4.static.gc", {"3.0000\n0\n"});
|
||||
runner->run_static_test(testCategory, "inline-with-block-4.static.gc", {"3.0000\n0\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, ReturnFromTrick) {
|
||||
runner->run_static_test(env, testCategory, "return-from-trick.static.gc", {"1\n"});
|
||||
runner->run_static_test(testCategory, "return-from-trick.static.gc", {"1\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, Set) {
|
||||
runner->run_static_test(env, testCategory, "set-symbol.static.gc", {"22\n"});
|
||||
runner->run_static_test(testCategory, "set-symbol.static.gc", {"22\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, Protect) {
|
||||
runner->run_static_test(env, testCategory, "protect.static.gc", {"33\n"});
|
||||
runner->run_static_test(testCategory, "protect.static.gc", {"33\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, Align) {
|
||||
runner->run_static_test(env, testCategory, "align16-1.static.gc", {"80\n"});
|
||||
runner->run_static_test(env, testCategory, "align16-2.static.gc", {"64\n"});
|
||||
runner->run_static_test(testCategory, "align16-1.static.gc", {"80\n"});
|
||||
runner->run_static_test(testCategory, "align16-2.static.gc", {"64\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, Defsmacro) {
|
||||
runner->run_static_test(env, testCategory, "defsmacro-defgmacro.static.gc", {"20\n"});
|
||||
runner->run_static_test(testCategory, "defsmacro-defgmacro.static.gc", {"20\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, Desfun) {
|
||||
runner->run_static_test(env, testCategory, "desfun.static.gc", {"4\n"});
|
||||
runner->run_static_test(testCategory, "desfun.static.gc", {"4\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, DeReference) {
|
||||
runner->run_static_test(env, testCategory, "methods.static.gc", {"#t#t\n0\n"});
|
||||
runner->run_static_test(testCategory, "methods.static.gc", {"#t#t\n0\n"});
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
#include "common/log/log.h"
|
||||
#include "common/util/Timer.h"
|
||||
|
||||
#include "goalc/compiler/Compiler.h"
|
||||
#include "gtest/gtest.h"
|
||||
@ -38,7 +37,7 @@ TEST(Jak1Debugger, DebuggerBasicConnect) {
|
||||
// evidently you can't ptrace threads in your own process, so we need to run the runtime in a
|
||||
// separate process.
|
||||
if (!fork()) {
|
||||
GoalTest::runtime_no_kernel();
|
||||
GoalTest::runtime_no_kernel_jak1();
|
||||
exit(0);
|
||||
} else {
|
||||
connect_compiler_and_debugger(compiler, true);
|
||||
@ -55,7 +54,7 @@ TEST(Jak1Debugger, DebuggerBreakAndContinue) {
|
||||
// evidently you can't ptrace threads in your own process, so we need to run the runtime in a
|
||||
// separate process.
|
||||
if (!fork()) {
|
||||
GoalTest::runtime_no_kernel();
|
||||
GoalTest::runtime_no_kernel_jak1();
|
||||
exit(0);
|
||||
} else {
|
||||
connect_compiler_and_debugger(compiler, true);
|
||||
@ -77,7 +76,7 @@ TEST(Jak1Debugger, DebuggerReadMemory) {
|
||||
// evidently you can't ptrace threads in your own process, so we need to run the runtime in a
|
||||
// separate process.
|
||||
if (!fork()) {
|
||||
GoalTest::runtime_no_kernel();
|
||||
GoalTest::runtime_no_kernel_jak1();
|
||||
exit(0);
|
||||
} else {
|
||||
connect_compiler_and_debugger(compiler, true);
|
||||
@ -101,7 +100,7 @@ TEST(Jak1Debugger, DebuggerWriteMemory) {
|
||||
// evidently you can't ptrace threads in your own process, so we need to run the runtime in a
|
||||
// separate process.
|
||||
if (!fork()) {
|
||||
GoalTest::runtime_no_kernel();
|
||||
GoalTest::runtime_no_kernel_jak1();
|
||||
exit(0);
|
||||
} else {
|
||||
connect_compiler_and_debugger(compiler, true);
|
||||
@ -132,7 +131,7 @@ TEST(Jak1Debugger, Symbol) {
|
||||
// evidently you can't ptrace threads in your own process, so we need to run the runtime in a
|
||||
// separate process.
|
||||
if (!fork()) {
|
||||
GoalTest::runtime_no_kernel();
|
||||
GoalTest::runtime_no_kernel_jak1();
|
||||
exit(0);
|
||||
} else {
|
||||
connect_compiler_and_debugger(compiler, true);
|
||||
@ -162,7 +161,7 @@ TEST(Jak1Debugger, SimpleBreakpoint) {
|
||||
Compiler compiler(GameVersion::Jak1);
|
||||
|
||||
if (!fork()) {
|
||||
GoalTest::runtime_no_kernel();
|
||||
GoalTest::runtime_no_kernel_jak1();
|
||||
exit(0);
|
||||
} else {
|
||||
connect_compiler_and_debugger(compiler, false);
|
||||
|
@ -19,7 +19,7 @@ class Jak1KernelTest : public testing::Test {
|
||||
}
|
||||
|
||||
printf("Starting GOAL Kernel...\n");
|
||||
shared_compiler->runtime_thread = std::thread(GoalTest::runtime_with_kernel);
|
||||
shared_compiler->runtime_thread = std::thread(GoalTest::runtime_with_kernel_jak1);
|
||||
shared_compiler->runner.c = &shared_compiler->compiler;
|
||||
shared_compiler->compiler.run_test_from_string("(set! *use-old-listener-print* #t)");
|
||||
}
|
||||
|
151
test/goalc/test_goal_kernel2.cpp
Normal file
151
test/goalc/test_goal_kernel2.cpp
Normal file
@ -0,0 +1,151 @@
|
||||
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
#include "goalc/compiler/Compiler.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "test/goalc/framework/test_runner.h"
|
||||
|
||||
class Jak2KernelTest : public testing::Test {
|
||||
public:
|
||||
static void SetUpTestSuite() {
|
||||
shared_compiler = std::make_unique<SharedCompiler>(GameVersion::Jak2);
|
||||
printf("Building kernel...\n");
|
||||
try {
|
||||
// a macro in goal-lib.gc
|
||||
shared_compiler->compiler.run_front_end_on_string("(build-kernel)");
|
||||
} catch (std::exception& e) {
|
||||
fprintf(stderr, "caught exception %s\n", e.what());
|
||||
EXPECT_TRUE(false);
|
||||
}
|
||||
|
||||
printf("Starting GOAL Kernel...\n");
|
||||
shared_compiler->runtime_thread = std::thread(GoalTest::runtime_with_kernel_jak2);
|
||||
shared_compiler->runner.c = &shared_compiler->compiler;
|
||||
shared_compiler->compiler.run_test_from_string("(set! *use-old-listener-print* #t)");
|
||||
}
|
||||
|
||||
static void TearDownTestSuite() {
|
||||
// send message to shutdown
|
||||
shared_compiler->compiler.shutdown_target();
|
||||
// wait for shutdown.
|
||||
shared_compiler->runtime_thread.join();
|
||||
shared_compiler.reset();
|
||||
}
|
||||
|
||||
void SetUp() {}
|
||||
|
||||
void TearDown() {}
|
||||
|
||||
struct SharedCompiler {
|
||||
SharedCompiler(GameVersion v) : compiler(v) {}
|
||||
std::thread runtime_thread;
|
||||
Compiler compiler;
|
||||
GoalTest::CompilerTestRunner runner;
|
||||
};
|
||||
|
||||
static std::unique_ptr<SharedCompiler> shared_compiler;
|
||||
};
|
||||
|
||||
std::unique_ptr<Jak2KernelTest::SharedCompiler> Jak2KernelTest::shared_compiler;
|
||||
|
||||
namespace {
|
||||
std::string send_code_and_get_multiple_responses(const std::string& code,
|
||||
int n_responses,
|
||||
GoalTest::CompilerTestRunner* runner) {
|
||||
auto& listener = runner->c->listener();
|
||||
// record all print messages
|
||||
listener.record_messages(ListenerMessageKind::MSG_PRINT);
|
||||
|
||||
// run the test.
|
||||
runner->c->compile_and_send_from_string(code);
|
||||
std::string result;
|
||||
while (listener.get_received_message_count() < n_responses) {
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(1000));
|
||||
}
|
||||
|
||||
auto messages = listener.stop_recording_messages();
|
||||
for (auto& m : messages) {
|
||||
result += m;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST_F(Jak2KernelTest, Basic) {
|
||||
shared_compiler->runner.c->run_test_from_string(
|
||||
"(ml \"test/goalc/source_templates/jak2/kernel-test.gc\")");
|
||||
std::string result =
|
||||
send_code_and_get_multiple_responses("(kernel-test)", 10, &shared_compiler->runner);
|
||||
|
||||
std::string expected =
|
||||
"0\n"
|
||||
"proc2: 0\n"
|
||||
"TARGET FUNCTION 1 2 3\n"
|
||||
"4 5 6\n"
|
||||
"Stack Alignemnt 0/16\n"
|
||||
"proc1: 0\n"
|
||||
"proc2: 6\n"
|
||||
"proc1: 1\n"
|
||||
"proc2: 12\n"
|
||||
"proc1: 2\n"
|
||||
"proc2: 18\n"
|
||||
"proc1: 3\n"
|
||||
"proc2: 24\n"
|
||||
"proc1: 4\n"
|
||||
"proc2: 30\n"
|
||||
"proc1: 5\n"
|
||||
"DEACTIVATE PROC 1\n"
|
||||
"proc2: 36\n"
|
||||
"proc2: 42\n"
|
||||
"proc2: 48\n"
|
||||
"proc2: 54\n";
|
||||
|
||||
EXPECT_EQ(expected, result);
|
||||
}
|
||||
|
||||
TEST_F(Jak2KernelTest, RunFunctionInProcess) {
|
||||
shared_compiler->runner.c->run_test_from_string(
|
||||
"(ml \"test/goalc/source_templates/jak2/kernel-test.gc\")");
|
||||
std::string result =
|
||||
send_code_and_get_multiple_responses("(kernel-test-2)", 1, &shared_compiler->runner);
|
||||
|
||||
std::string expected =
|
||||
"0\n"
|
||||
"Args: 1 2 3\n"
|
||||
"4 5 6\n"
|
||||
"Stack Alignemnt 0/16\n"
|
||||
"run-function-in-process result: init-child-proc-result\n"
|
||||
"Args: 0 2 3\n"
|
||||
"4 5 6\n"
|
||||
"Stack Alignemnt 0/16\n"
|
||||
"run-function-in-process result: #f\n";
|
||||
EXPECT_EQ(expected, result);
|
||||
}
|
||||
|
||||
TEST_F(Jak2KernelTest, StateAndXmm) {
|
||||
shared_compiler->runner.c->run_test_from_string(
|
||||
"(ml \"test/goalc/source_templates/jak2/kernel-test.gc\")");
|
||||
std::string result =
|
||||
send_code_and_get_multiple_responses("(state-test)", 5, &shared_compiler->runner);
|
||||
|
||||
std::string expected =
|
||||
"0\nenter wreck: 3 4 5 6\nwreck: 3 4 5 6\nenter check: 9 8 7 6\nrun xmm-check 12.3400 "
|
||||
"45.6300 9 8 7 6\nwreck: 3 4 5 6\nrun xmm-check 12.3400 45.6300 9 8 7 6\nwreck: 3 4 5 6\nrun "
|
||||
"xmm-check 12.3400 45.6300 9 8 7 6\nwreck: 3 4 5 6\nexit check\nenter die\ntime to "
|
||||
"die!\nexit die\nexit wreck\nenter die\ntime to die!\nexit die\n";
|
||||
EXPECT_EQ(expected, result);
|
||||
}
|
||||
|
||||
TEST_F(Jak2KernelTest, ThrowXmm) {
|
||||
shared_compiler->runner.c->run_test_from_string(
|
||||
"(ml \"test/goalc/source_templates/jak2/kernel-test.gc\")");
|
||||
std::string result =
|
||||
send_code_and_get_multiple_responses("(throw-backup-test)", 1, &shared_compiler->runner);
|
||||
|
||||
std::string expected =
|
||||
"value now is 10.1000\n"
|
||||
"now its 10.1000\n"
|
||||
"0\n";
|
||||
EXPECT_EQ(expected, result);
|
||||
}
|
55
test/goalc/test_jak2_compiler.cpp
Normal file
55
test/goalc/test_jak2_compiler.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "test/goalc/framework/test_runner.h"
|
||||
|
||||
// Tests for Jak 2's compiler/runtime, without game-specific code (ENGINE/GAME)
|
||||
|
||||
struct Jak2Param {
|
||||
// TODO - Not Needed Yet
|
||||
};
|
||||
|
||||
class Jak2GoalcTests : public testing::TestWithParam<Jak2Param> {
|
||||
public:
|
||||
static void SetUpTestSuite() {
|
||||
runtime_thread = std::make_unique<std::thread>(std::thread(GoalTest::runtime_no_kernel_jak2));
|
||||
compiler = std::make_unique<Compiler>(GameVersion::Jak2);
|
||||
runner = std::make_unique<GoalTest::CompilerTestRunner>();
|
||||
runner->c = compiler.get();
|
||||
}
|
||||
|
||||
static void TearDownTestSuite() {
|
||||
compiler->shutdown_target();
|
||||
runtime_thread->join();
|
||||
|
||||
runtime_thread.reset();
|
||||
compiler.reset();
|
||||
runner.reset();
|
||||
}
|
||||
|
||||
void SetUp() {
|
||||
GoalTest::createDirIfAbsent(GoalTest::getTemplateDir(testCategory));
|
||||
GoalTest::createDirIfAbsent(GoalTest::getGeneratedDir(testCategory));
|
||||
}
|
||||
|
||||
void TearDown() {}
|
||||
|
||||
static std::unique_ptr<std::thread> runtime_thread;
|
||||
static std::unique_ptr<Compiler> compiler;
|
||||
static std::unique_ptr<GoalTest::CompilerTestRunner> runner;
|
||||
|
||||
std::string testCategory = "jak2";
|
||||
};
|
||||
|
||||
std::unique_ptr<std::thread> Jak2GoalcTests::runtime_thread;
|
||||
std::unique_ptr<Compiler> Jak2GoalcTests::compiler;
|
||||
std::unique_ptr<GoalTest::CompilerTestRunner> Jak2GoalcTests::runner;
|
||||
|
||||
TEST_F(Jak2GoalcTests, All) {
|
||||
runner->run_static_test(testCategory, "jak2-mega-test.gc",
|
||||
{"empty pair: () () () #t #f\n"
|
||||
"empty pair type: pair\n"
|
||||
"non-empty pair: (a b -12) a pair (a . b)\n"
|
||||
"basic types: type symbol string function\n"
|
||||
"bools: #t #f #t #f #f #t\n"
|
||||
"zero: 0\n"
|
||||
"parent of type: basic structure object object\n0\n"});
|
||||
}
|
34
test/goalc/test_type_consistency.cpp
Normal file
34
test/goalc/test_type_consistency.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
#include "goalc/compiler/Compiler.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
void add_expected_type_mismatches(Compiler& c) {
|
||||
c.add_ignored_define_extern_symbol("draw-drawable-tree-tfrag");
|
||||
c.add_ignored_define_extern_symbol("draw-drawable-tree-trans-tfrag");
|
||||
c.add_ignored_define_extern_symbol("draw-drawable-tree-dirt-tfrag");
|
||||
c.add_ignored_define_extern_symbol("draw-drawable-tree-ice-tfrag");
|
||||
c.add_ignored_define_extern_symbol("tfrag-init-buffer");
|
||||
}
|
||||
|
||||
TEST(Jak1TypeConsistency, MANUAL_TEST_TypeConsistencyWithBuildFirst) {
|
||||
Compiler compiler(GameVersion::Jak1);
|
||||
compiler.enable_throw_on_redefines();
|
||||
add_expected_type_mismatches(compiler);
|
||||
compiler.run_test_no_load("test/goalc/source_templates/with_game/test-build-all-code.gc");
|
||||
compiler.run_test_no_load("decompiler/config/all-types.gc");
|
||||
}
|
||||
|
||||
TEST(Jak1TypeConsistency, TypeConsistency) {
|
||||
Compiler compiler(GameVersion::Jak1);
|
||||
compiler.enable_throw_on_redefines();
|
||||
add_expected_type_mismatches(compiler);
|
||||
compiler.run_test_no_load("decompiler/config/all-types.gc");
|
||||
compiler.run_test_no_load("test/goalc/source_templates/with_game/test-build-all-code.gc");
|
||||
}
|
||||
|
||||
TEST(Jak2TypeConsistency, TypeConsistency) {
|
||||
Compiler compiler(GameVersion::Jak2);
|
||||
compiler.enable_throw_on_redefines();
|
||||
add_expected_type_mismatches(compiler);
|
||||
compiler.run_test_no_load("decompiler/config/jak2/all-types.gc");
|
||||
compiler.run_test_no_load("test/goalc/source_templates/with_game/test-build-all-code.gc");
|
||||
}
|
@ -1,21 +1,11 @@
|
||||
#include <chrono>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
#include "inja.hpp"
|
||||
|
||||
#include "game/runtime.h"
|
||||
#include "goalc/compiler/Compiler.h"
|
||||
#include "goalc/listener/Listener.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "test/goalc/framework/test_runner.h"
|
||||
|
||||
#include "third-party/json.hpp"
|
||||
|
||||
struct VariableParam {
|
||||
// TODO - Not Needed Yet
|
||||
};
|
||||
@ -24,7 +14,7 @@ class VariableTests : public testing::TestWithParam<VariableParam> {
|
||||
public:
|
||||
static void SetUpTestSuite() {
|
||||
shared_compiler = std::make_unique<SharedCompiler>(GameVersion::Jak1);
|
||||
shared_compiler->runtime_thread = std::thread((GoalTest::runtime_no_kernel));
|
||||
shared_compiler->runtime_thread = std::thread(GoalTest::runtime_no_kernel_jak1);
|
||||
shared_compiler->runner.c = &shared_compiler->compiler;
|
||||
}
|
||||
|
||||
@ -51,91 +41,85 @@ class VariableTests : public testing::TestWithParam<VariableParam> {
|
||||
static std::unique_ptr<SharedCompiler> shared_compiler;
|
||||
|
||||
std::string testCategory = "variables";
|
||||
inja::Environment env{GoalTest::getTemplateDir(testCategory),
|
||||
GoalTest::getGeneratedDir(testCategory)};
|
||||
};
|
||||
|
||||
std::unique_ptr<VariableTests::SharedCompiler> VariableTests::shared_compiler;
|
||||
|
||||
TEST_F(VariableTests, Globals) {
|
||||
shared_compiler->runner.run_static_test(env, testCategory, "defglobalconstant-1.static.gc",
|
||||
{"17\n"});
|
||||
shared_compiler->runner.run_static_test(env, testCategory, "defglobalconstant-2.static.gc",
|
||||
{"18\n"});
|
||||
shared_compiler->runner.run_static_test(testCategory, "defglobalconstant-1.static.gc", {"17\n"});
|
||||
shared_compiler->runner.run_static_test(testCategory, "defglobalconstant-2.static.gc", {"18\n"});
|
||||
}
|
||||
|
||||
TEST_F(VariableTests, Definitions) {
|
||||
shared_compiler->runner.run_static_test(env, testCategory, "define.static.gc", {"17\n"});
|
||||
shared_compiler->runner.run_static_test(testCategory, "define.static.gc", {"17\n"});
|
||||
}
|
||||
|
||||
TEST_F(VariableTests, Let) {
|
||||
shared_compiler->runner.run_static_test(env, testCategory, "let.static.gc", {"30\n"});
|
||||
shared_compiler->runner.run_static_test(env, testCategory, "let-star.static.gc", {"30\n"});
|
||||
shared_compiler->runner.run_static_test(env, testCategory, "mlet.static.gc", {"10\n"});
|
||||
shared_compiler->runner.run_static_test(testCategory, "let.static.gc", {"30\n"});
|
||||
shared_compiler->runner.run_static_test(testCategory, "let-star.static.gc", {"30\n"});
|
||||
shared_compiler->runner.run_static_test(testCategory, "mlet.static.gc", {"10\n"});
|
||||
}
|
||||
|
||||
TEST_F(VariableTests, StackVars) {
|
||||
shared_compiler->runner.run_static_test(env, testCategory, "stack-ints.gc", {"12\n"});
|
||||
shared_compiler->runner.run_static_test(env, testCategory, "stack-ints-2.gc", {"1\n"});
|
||||
shared_compiler->runner.run_static_test(testCategory, "stack-ints.gc", {"12\n"});
|
||||
shared_compiler->runner.run_static_test(testCategory, "stack-ints-2.gc", {"1\n"});
|
||||
}
|
||||
|
||||
TEST_F(VariableTests, Bitfields) {
|
||||
shared_compiler->runner.run_static_test(env, testCategory, "bitfield-enums.gc", {"5\n"});
|
||||
shared_compiler->runner.run_static_test(env, testCategory, "integer-enums.gc", {"11\n"});
|
||||
shared_compiler->runner.run_static_test(testCategory, "bitfield-enums.gc", {"5\n"});
|
||||
shared_compiler->runner.run_static_test(testCategory, "integer-enums.gc", {"11\n"});
|
||||
}
|
||||
|
||||
TEST_F(VariableTests, InlineAsm) {
|
||||
shared_compiler->runner.run_static_test(env, testCategory, "inline-asm.static.gc", {"1\n"});
|
||||
shared_compiler->runner.run_static_test(testCategory, "inline-asm.static.gc", {"1\n"});
|
||||
}
|
||||
|
||||
TEST_F(VariableTests, StaticBitfieldField) {
|
||||
shared_compiler->runner.run_static_test(env, testCategory, "static-bitfield-field.gc", {"22\n"});
|
||||
shared_compiler->runner.run_static_test(testCategory, "static-bitfield-field.gc", {"22\n"});
|
||||
}
|
||||
|
||||
TEST_F(VariableTests, StackArrayAlignment) {
|
||||
shared_compiler->runner.run_static_test(env, testCategory, "stack-array-align.gc", {"3\n"});
|
||||
shared_compiler->runner.run_static_test(testCategory, "stack-array-align.gc", {"3\n"});
|
||||
}
|
||||
|
||||
TEST_F(VariableTests, StackStructureAlignment) {
|
||||
shared_compiler->runner.run_static_test(env, testCategory, "stack-structure-align.gc",
|
||||
{"1234\n"});
|
||||
shared_compiler->runner.run_static_test(testCategory, "stack-structure-align.gc", {"1234\n"});
|
||||
}
|
||||
|
||||
TEST_F(VariableTests, GetSymbol) {
|
||||
shared_compiler->runner.run_static_test(env, testCategory, "get-symbol-1.static.gc",
|
||||
shared_compiler->runner.run_static_test(testCategory, "get-symbol-1.static.gc",
|
||||
{"1375524\n"}); // 0x14fd24 in hex
|
||||
shared_compiler->runner.run_static_test(env, testCategory, "get-symbol-2.static.gc",
|
||||
shared_compiler->runner.run_static_test(testCategory, "get-symbol-2.static.gc",
|
||||
{"1375532\n"}); // 0x14fd2c in hex
|
||||
}
|
||||
|
||||
TEST_F(VariableTests, Constants) {
|
||||
// TODO - shared_compiler->runner.run_static_test(env, testCategory,
|
||||
// TODO - shared_compiler->runner.run_static_test(testCategory,
|
||||
// "string-constant-1.static.gc");
|
||||
std::string expected = "\"test string!\"";
|
||||
shared_compiler->runner.run_static_test(env, testCategory, "string-constant-2.static.gc",
|
||||
{expected}, expected.size());
|
||||
shared_compiler->runner.run_static_test(testCategory, "string-constant-2.static.gc", {expected},
|
||||
expected.size());
|
||||
}
|
||||
|
||||
TEST_F(VariableTests, Symbols) {
|
||||
shared_compiler->runner.run_static_test(env, testCategory, "quote-symbol.static.gc",
|
||||
{"banana\n0\n"});
|
||||
shared_compiler->runner.run_static_test(testCategory, "quote-symbol.static.gc", {"banana\n0\n"});
|
||||
std::string expected = "test-string";
|
||||
shared_compiler->runner.run_static_test(env, testCategory, "string-symbol.static.gc", {expected},
|
||||
shared_compiler->runner.run_static_test(testCategory, "string-symbol.static.gc", {expected},
|
||||
expected.size());
|
||||
}
|
||||
|
||||
TEST_F(VariableTests, Formatting) {
|
||||
shared_compiler->runner.run_static_test(env, testCategory, "format-reg-order.static.gc",
|
||||
shared_compiler->runner.run_static_test(testCategory, "format-reg-order.static.gc",
|
||||
{"test 1 2 3 4 5 6\n0\n"});
|
||||
}
|
||||
|
||||
TEST_F(VariableTests, DeReference) {
|
||||
shared_compiler->runner.run_static_test(env, testCategory, "deref-simple.static.gc",
|
||||
shared_compiler->runner.run_static_test(testCategory, "deref-simple.static.gc",
|
||||
{"structure\n0\n"});
|
||||
}
|
||||
|
||||
TEST_F(VariableTests, Pointers) {
|
||||
shared_compiler->runner.run_static_test(env, testCategory, "pointers.static.gc", {"13\n"});
|
||||
shared_compiler->runner.run_static_test(testCategory, "pointers.static.gc", {"13\n"});
|
||||
}
|
||||
|
||||
// expected =
|
||||
|
584
test/goalc/test_vector_float.cpp
Normal file
584
test/goalc/test_vector_float.cpp
Normal file
@ -0,0 +1,584 @@
|
||||
#include <regex>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
#include "inja.hpp"
|
||||
|
||||
#include "goalc/compiler/Compiler.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "test/goalc/framework/test_runner.h"
|
||||
|
||||
#include "third-party/fmt/core.h"
|
||||
#include "third-party/json.hpp"
|
||||
|
||||
class WithMinimalGameTests : public ::testing::Test {
|
||||
public:
|
||||
static void SetUpTestSuite() {
|
||||
shared_compiler = std::make_unique<SharedCompiler>(GameVersion::Jak1);
|
||||
try {
|
||||
shared_compiler->compiler.run_front_end_on_string("(build-kernel)");
|
||||
} catch (std::exception& e) {
|
||||
fprintf(stderr, "caught exception %s\n", e.what());
|
||||
EXPECT_TRUE(false);
|
||||
}
|
||||
shared_compiler->runtime_thread = std::thread(GoalTest::runtime_with_kernel_jak1);
|
||||
shared_compiler->runner.c = &shared_compiler->compiler;
|
||||
|
||||
shared_compiler->compiler.run_test_from_string(
|
||||
"(dgo-load \"kernel\" global (link-flag output-load-msg output-load-true-msg execute-login "
|
||||
"print-login) #x200000)");
|
||||
|
||||
const auto minimal_files = {"goal_src/jak1/engine/math/vector-h.gc"};
|
||||
for (auto& file : minimal_files) {
|
||||
shared_compiler->compiler.run_test_from_string(fmt::format("(ml \"{}\")", file));
|
||||
}
|
||||
|
||||
shared_compiler->compiler.run_test_from_string("(set! *use-old-listener-print* #t)");
|
||||
}
|
||||
|
||||
static void TearDownTestSuite() {
|
||||
shared_compiler->compiler.shutdown_target();
|
||||
shared_compiler->runtime_thread.join();
|
||||
shared_compiler.reset();
|
||||
}
|
||||
|
||||
void SetUp() {
|
||||
GoalTest::createDirIfAbsent(GoalTest::getTemplateDir(testCategory));
|
||||
GoalTest::createDirIfAbsent(GoalTest::getGeneratedDir(testCategory));
|
||||
}
|
||||
|
||||
void TearDown() {}
|
||||
|
||||
struct SharedCompiler {
|
||||
SharedCompiler(GameVersion v) : compiler(v) {}
|
||||
std::thread runtime_thread;
|
||||
Compiler compiler;
|
||||
GoalTest::CompilerTestRunner runner;
|
||||
};
|
||||
|
||||
static std::unique_ptr<SharedCompiler> shared_compiler;
|
||||
|
||||
std::string testCategory = "with_game";
|
||||
inja::Environment env{GoalTest::getTemplateDir(testCategory),
|
||||
GoalTest::getGeneratedDir(testCategory)};
|
||||
};
|
||||
|
||||
std::unique_ptr<WithMinimalGameTests::SharedCompiler> WithMinimalGameTests::shared_compiler;
|
||||
|
||||
struct VectorFloatRegister {
|
||||
float x = 0;
|
||||
float y = 0;
|
||||
float z = 0;
|
||||
float w = 0;
|
||||
|
||||
void setJson(nlohmann::json& data, std::string vectorKey) {
|
||||
data[fmt::format("{}x", vectorKey)] = x;
|
||||
data[fmt::format("{}y", vectorKey)] = y;
|
||||
data[fmt::format("{}z", vectorKey)] = z;
|
||||
data[fmt::format("{}w", vectorKey)] = w;
|
||||
}
|
||||
|
||||
float getBroadcastElement(emitter::Register::VF_ELEMENT bc, float defValue) {
|
||||
switch (bc) {
|
||||
case emitter::Register::VF_ELEMENT::X:
|
||||
return x;
|
||||
case emitter::Register::VF_ELEMENT::Y:
|
||||
return y;
|
||||
case emitter::Register::VF_ELEMENT::Z:
|
||||
return z;
|
||||
case emitter::Register::VF_ELEMENT::W:
|
||||
return w;
|
||||
default:
|
||||
return defValue;
|
||||
}
|
||||
}
|
||||
|
||||
std::string toGOALFormat() {
|
||||
std::string answer = fmt::format("({:.4f}, {:.4f}, {:.4f}, {:.4f})", x, y, z, w);
|
||||
// {fmt} formats negative 0 as "-0.000", just going to flip any negative zeros to positives as I
|
||||
// don't think is an OpenGOAL issue
|
||||
// Additionally, GOAL doesn't have -/+ Inf it seems, so replace with NaN. -nan is also just NaN
|
||||
return std::regex_replace(std::regex_replace(answer, std::regex("-0.0000"), "0.0000"),
|
||||
std::regex("nan|inf|-nan|-inf"), "NaN");
|
||||
}
|
||||
|
||||
std::string toGOALFormat(float) {
|
||||
std::string answer = fmt::format("{:.4f}", x);
|
||||
// {fmt} formats negative 0 as "-0.000", just going to flip any negative zeros to positives as I
|
||||
// don't think is an OpenGOAL issue
|
||||
// Additionally, GOAL doesn't have -/+ Inf it seems, so replace with NaN
|
||||
return std::regex_replace(std::regex_replace(answer, std::regex("-0.0000"), "0.0000"),
|
||||
std::regex("nan|inf|-nan|-inf"), "NaN");
|
||||
}
|
||||
};
|
||||
|
||||
struct VectorFloatTestCase {
|
||||
VectorFloatRegister dest = {11, 22, 33, 44};
|
||||
int destinationMask = -1;
|
||||
emitter::Register::VF_ELEMENT bc = emitter::Register::VF_ELEMENT::NONE;
|
||||
|
||||
std::string getOperationBroadcast() {
|
||||
switch (bc) {
|
||||
case emitter::Register::VF_ELEMENT::X:
|
||||
return ".x";
|
||||
case emitter::Register::VF_ELEMENT::Y:
|
||||
return ".y";
|
||||
case emitter::Register::VF_ELEMENT::Z:
|
||||
return ".z";
|
||||
case emitter::Register::VF_ELEMENT::W:
|
||||
return ".w";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
virtual VectorFloatRegister getExpectedResult() = 0;
|
||||
virtual void setJson(nlohmann::json& data, std::string func) = 0;
|
||||
|
||||
virtual ~VectorFloatTestCase() = default;
|
||||
};
|
||||
|
||||
struct VectorFloatTestCase_TwoOperand : VectorFloatTestCase {
|
||||
VectorFloatRegister input1 = {1.5, -1.5, 0.0, 100.5};
|
||||
VectorFloatRegister input2 = {-5.5, -0.0, 10.0, 7.5};
|
||||
|
||||
std::function<float(float, float)> operation;
|
||||
|
||||
VectorFloatRegister getExpectedResult() {
|
||||
VectorFloatRegister expectedResult;
|
||||
expectedResult.x = destinationMask & 0b0001
|
||||
? operation(input1.x, input2.getBroadcastElement(bc, input2.x))
|
||||
: dest.x;
|
||||
expectedResult.y = destinationMask & 0b0010
|
||||
? operation(input1.y, input2.getBroadcastElement(bc, input2.y))
|
||||
: dest.y;
|
||||
expectedResult.z = destinationMask & 0b0100
|
||||
? operation(input1.z, input2.getBroadcastElement(bc, input2.z))
|
||||
: dest.z;
|
||||
expectedResult.w = destinationMask & 0b1000
|
||||
? operation(input1.w, input2.getBroadcastElement(bc, input2.w))
|
||||
: dest.w;
|
||||
return expectedResult;
|
||||
}
|
||||
|
||||
void setJson(nlohmann::json& data, std::string func) {
|
||||
input1.setJson(data, "v1");
|
||||
input2.setJson(data, "v2");
|
||||
dest.setJson(data, "dest");
|
||||
data["operation"] = fmt::format(func);
|
||||
if (destinationMask == -1) {
|
||||
data["destinationMask"] = false;
|
||||
} else {
|
||||
data["destinationMask"] = fmt::format("{:b}", destinationMask);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<VectorFloatTestCase_TwoOperand> vectorMathCaseGen_TwoOperand() {
|
||||
std::vector<VectorFloatTestCase_TwoOperand> cases = {};
|
||||
for (int i = 0; i <= 15; i++) {
|
||||
VectorFloatTestCase_TwoOperand testCase = VectorFloatTestCase_TwoOperand();
|
||||
testCase.destinationMask = i;
|
||||
cases.push_back(testCase);
|
||||
// Re-add each case with each broadcast variant
|
||||
for (int j = 0; j < 4; j++) {
|
||||
VectorFloatTestCase_TwoOperand testCaseBC = VectorFloatTestCase_TwoOperand();
|
||||
testCaseBC.destinationMask = i;
|
||||
testCaseBC.bc = static_cast<emitter::Register::VF_ELEMENT>(j);
|
||||
cases.push_back(testCaseBC);
|
||||
}
|
||||
}
|
||||
return cases;
|
||||
}
|
||||
|
||||
class VectorFloatParameterizedTestFixtureWithRunner_TwoOperand
|
||||
: public WithMinimalGameTests,
|
||||
public ::testing::WithParamInterface<VectorFloatTestCase_TwoOperand> {
|
||||
protected:
|
||||
std::string templateFile = "test-vector-math-2-operand.template.gc";
|
||||
};
|
||||
|
||||
// NOTE - an excellent article -
|
||||
// https://www.sandordargo.com/blog/2019/04/24/parameterized-testing-with-gtest
|
||||
|
||||
// --- 2 Operand VF Operations
|
||||
|
||||
TEST_P(VectorFloatParameterizedTestFixtureWithRunner_TwoOperand, VF_ADD_XYZW_DEST) {
|
||||
VectorFloatTestCase_TwoOperand testCase = GetParam();
|
||||
testCase.operation = [](float x, float y) { return x + y; };
|
||||
|
||||
nlohmann::json data;
|
||||
testCase.setJson(data, fmt::format(".add{}.vf", testCase.getOperationBroadcast()));
|
||||
|
||||
std::string outFile = shared_compiler->runner.test_file_name(
|
||||
fmt::format("vector-math-add{}-{{}}.generated.gc", testCase.getOperationBroadcast()));
|
||||
env.write(templateFile, data, outFile);
|
||||
shared_compiler->runner.run_test(
|
||||
testCategory, outFile, {fmt::format("{}\n0\n", testCase.getExpectedResult().toGOALFormat())});
|
||||
}
|
||||
|
||||
TEST_P(VectorFloatParameterizedTestFixtureWithRunner_TwoOperand, VF_SUB_XYZW_DEST) {
|
||||
VectorFloatTestCase_TwoOperand testCase = GetParam();
|
||||
testCase.operation = [](float x, float y) { return x - y; };
|
||||
|
||||
nlohmann::json data;
|
||||
testCase.setJson(data, fmt::format(".sub{}.vf", testCase.getOperationBroadcast()));
|
||||
|
||||
std::string outFile = shared_compiler->runner.test_file_name(
|
||||
fmt::format("vector-math-sub{}-{{}}.generated.gc", testCase.getOperationBroadcast()));
|
||||
env.write(templateFile, data, outFile);
|
||||
shared_compiler->runner.run_test(
|
||||
testCategory, outFile, {fmt::format("{}\n0\n", testCase.getExpectedResult().toGOALFormat())});
|
||||
}
|
||||
|
||||
TEST_P(VectorFloatParameterizedTestFixtureWithRunner_TwoOperand, VF_MUL_XYZW_DEST) {
|
||||
VectorFloatTestCase_TwoOperand testCase = GetParam();
|
||||
testCase.operation = [](float x, float y) { return x * y; };
|
||||
|
||||
nlohmann::json data;
|
||||
testCase.setJson(data, fmt::format(".mul{}.vf", testCase.getOperationBroadcast()));
|
||||
|
||||
std::string outFile = shared_compiler->runner.test_file_name(
|
||||
fmt::format("vector-math-mul{}-{{}}.generated.gc", testCase.getOperationBroadcast()));
|
||||
env.write(templateFile, data, outFile);
|
||||
shared_compiler->runner.run_test(
|
||||
testCategory, outFile, {fmt::format("{}\n0\n", testCase.getExpectedResult().toGOALFormat())});
|
||||
}
|
||||
|
||||
TEST_P(VectorFloatParameterizedTestFixtureWithRunner_TwoOperand, VF_MIN_XYZW_DEST) {
|
||||
VectorFloatTestCase_TwoOperand testCase = GetParam();
|
||||
testCase.operation = [](float x, float y) { return fmin(x, y); };
|
||||
|
||||
nlohmann::json data;
|
||||
testCase.setJson(data, fmt::format(".min{}.vf", testCase.getOperationBroadcast()));
|
||||
|
||||
std::string outFile = shared_compiler->runner.test_file_name(
|
||||
fmt::format("vector-math-min{}-{{}}.generated.gc", testCase.getOperationBroadcast()));
|
||||
env.write(templateFile, data, outFile);
|
||||
shared_compiler->runner.run_test(
|
||||
testCategory, outFile, {fmt::format("{}\n0\n", testCase.getExpectedResult().toGOALFormat())});
|
||||
}
|
||||
|
||||
TEST_P(VectorFloatParameterizedTestFixtureWithRunner_TwoOperand, VF_MAX_XYZW_DEST) {
|
||||
VectorFloatTestCase_TwoOperand testCase = GetParam();
|
||||
testCase.operation = [](float x, float y) { return fmax(x, y); };
|
||||
|
||||
nlohmann::json data;
|
||||
testCase.setJson(data, fmt::format(".max{}.vf", testCase.getOperationBroadcast()));
|
||||
|
||||
std::string outFile = shared_compiler->runner.test_file_name(
|
||||
fmt::format("vector-math-max{}-{{}}.generated.gc", testCase.getOperationBroadcast()));
|
||||
env.write(templateFile, data, outFile);
|
||||
shared_compiler->runner.run_test(
|
||||
testCategory, outFile, {fmt::format("{}\n0\n", testCase.getExpectedResult().toGOALFormat())});
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(WithGameTests_VectorFloatTests,
|
||||
VectorFloatParameterizedTestFixtureWithRunner_TwoOperand,
|
||||
::testing::ValuesIn(vectorMathCaseGen_TwoOperand()));
|
||||
|
||||
// --- 1 Operand VF Operations
|
||||
|
||||
struct VectorFloatTestCase_SingleOperand : VectorFloatTestCase {
|
||||
VectorFloatRegister input1 = {1.5, -1.5, 0.0, 100.5};
|
||||
|
||||
std::function<float(float)> operation;
|
||||
|
||||
VectorFloatRegister getExpectedResult() {
|
||||
VectorFloatRegister expectedResult;
|
||||
expectedResult.x =
|
||||
destinationMask & 0b0001 ? operation(input1.getBroadcastElement(bc, input1.x)) : dest.x;
|
||||
expectedResult.y =
|
||||
destinationMask & 0b0010 ? operation(input1.getBroadcastElement(bc, input1.y)) : dest.y;
|
||||
expectedResult.z =
|
||||
destinationMask & 0b0100 ? operation(input1.getBroadcastElement(bc, input1.z)) : dest.z;
|
||||
expectedResult.w =
|
||||
destinationMask & 0b1000 ? operation(input1.getBroadcastElement(bc, input1.w)) : dest.w;
|
||||
return expectedResult;
|
||||
}
|
||||
|
||||
void setJson(nlohmann::json& data, std::string func) {
|
||||
input1.setJson(data, "v1");
|
||||
dest.setJson(data, "dest");
|
||||
data["operation"] = fmt::format(func);
|
||||
if (destinationMask == -1) {
|
||||
data["destinationMask"] = false;
|
||||
} else {
|
||||
data["destinationMask"] = fmt::format("{:b}", destinationMask);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<VectorFloatTestCase_SingleOperand> vectorMathCaseGen_SingleOperand_NoBroadcast() {
|
||||
std::vector<VectorFloatTestCase_SingleOperand> cases = {};
|
||||
for (int i = 0; i <= 15; i++) {
|
||||
VectorFloatTestCase_SingleOperand testCase = VectorFloatTestCase_SingleOperand();
|
||||
testCase.destinationMask = i;
|
||||
cases.push_back(testCase);
|
||||
}
|
||||
return cases;
|
||||
}
|
||||
|
||||
class VectorFloatParameterizedTestFixtureWithRunner_SingleOperand
|
||||
: public WithMinimalGameTests,
|
||||
public ::testing::WithParamInterface<VectorFloatTestCase_SingleOperand> {
|
||||
protected:
|
||||
std::string templateFile = "test-vector-math-1-operand.template.gc";
|
||||
};
|
||||
|
||||
TEST_P(VectorFloatParameterizedTestFixtureWithRunner_SingleOperand, VF_ABS_DEST) {
|
||||
VectorFloatTestCase_SingleOperand testCase = GetParam();
|
||||
testCase.operation = [](float x) { return fabs(x); };
|
||||
|
||||
nlohmann::json data;
|
||||
testCase.setJson(data, ".abs.vf");
|
||||
|
||||
std::string outFile = shared_compiler->runner.test_file_name("vector-math-abs-{}.generated.gc");
|
||||
env.write(templateFile, data, outFile);
|
||||
shared_compiler->runner.run_test(
|
||||
testCategory, outFile, {fmt::format("{}\n0\n", testCase.getExpectedResult().toGOALFormat())});
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(WithGameTests_VectorFloatTests,
|
||||
VectorFloatParameterizedTestFixtureWithRunner_SingleOperand,
|
||||
::testing::ValuesIn(vectorMathCaseGen_SingleOperand_NoBroadcast()));
|
||||
|
||||
// --- 2 Operand With ACC VF Operations
|
||||
// TODO - these pollute tests, it would be nicer long-term to move these into the framework
|
||||
// namespace
|
||||
|
||||
struct VectorFloatTestCase_TwoOperandACC : VectorFloatTestCase {
|
||||
VectorFloatRegister input1 = {1.5, -1.5, 0.0, 100.5};
|
||||
VectorFloatRegister input2 = {-5.5, -0.0, 10.0, 7.5};
|
||||
VectorFloatRegister acc = {-15.5, -0.0, 20.0, 70.5};
|
||||
|
||||
std::function<float(float, float, float)> operation;
|
||||
|
||||
VectorFloatRegister getExpectedResult() {
|
||||
VectorFloatRegister expectedResult;
|
||||
expectedResult.x = destinationMask & 0b0001
|
||||
? operation(input1.x, input2.getBroadcastElement(bc, input2.x), acc.x)
|
||||
: dest.x;
|
||||
expectedResult.y = destinationMask & 0b0010
|
||||
? operation(input1.y, input2.getBroadcastElement(bc, input2.y), acc.y)
|
||||
: dest.y;
|
||||
expectedResult.z = destinationMask & 0b0100
|
||||
? operation(input1.z, input2.getBroadcastElement(bc, input2.z), acc.z)
|
||||
: dest.z;
|
||||
expectedResult.w = destinationMask & 0b1000
|
||||
? operation(input1.w, input2.getBroadcastElement(bc, input2.w), acc.w)
|
||||
: dest.w;
|
||||
return expectedResult;
|
||||
}
|
||||
|
||||
void setJson(nlohmann::json& data, std::string func) {
|
||||
input1.setJson(data, "v1");
|
||||
input2.setJson(data, "v2");
|
||||
acc.setJson(data, "acc");
|
||||
dest.setJson(data, "dest");
|
||||
data["operation"] = fmt::format(func);
|
||||
if (destinationMask == -1) {
|
||||
data["destinationMask"] = false;
|
||||
} else {
|
||||
data["destinationMask"] = fmt::format("{:b}", destinationMask);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// TODO - unnecessary duplication for these generation methods, use some templates (only the type
|
||||
// changes)
|
||||
std::vector<VectorFloatTestCase_TwoOperandACC> vectorMathCaseGen_TwoOperandACC() {
|
||||
std::vector<VectorFloatTestCase_TwoOperandACC> cases = {};
|
||||
for (int i = 0; i <= 15; i++) {
|
||||
VectorFloatTestCase_TwoOperandACC testCase = VectorFloatTestCase_TwoOperandACC();
|
||||
testCase.destinationMask = i;
|
||||
cases.push_back(testCase);
|
||||
// Re-add each case with each broadcast variant
|
||||
for (int j = 0; j < 4; j++) {
|
||||
VectorFloatTestCase_TwoOperandACC testCaseBC = VectorFloatTestCase_TwoOperandACC();
|
||||
testCaseBC.destinationMask = i;
|
||||
testCaseBC.bc = static_cast<emitter::Register::VF_ELEMENT>(j);
|
||||
cases.push_back(testCaseBC);
|
||||
}
|
||||
}
|
||||
return cases;
|
||||
}
|
||||
|
||||
class VectorFloatParameterizedTestFixtureWithRunner_TwoOperandACC
|
||||
: public WithMinimalGameTests,
|
||||
public ::testing::WithParamInterface<VectorFloatTestCase_TwoOperandACC> {
|
||||
protected:
|
||||
std::string templateFile = "test-vector-math-2-operand-acc.template.gc";
|
||||
};
|
||||
|
||||
TEST_P(VectorFloatParameterizedTestFixtureWithRunner_TwoOperandACC, VF_MUL_ADD_XYZW_DEST) {
|
||||
VectorFloatTestCase_TwoOperandACC testCase = GetParam();
|
||||
testCase.operation = [](float x, float y, float acc) { return (x * y) + acc; };
|
||||
|
||||
nlohmann::json data;
|
||||
testCase.setJson(data, fmt::format(".add.mul{}.vf", testCase.getOperationBroadcast()));
|
||||
|
||||
std::string outFile = shared_compiler->runner.test_file_name(
|
||||
fmt::format("vector-math-add-mul{}-{{}}.generated.gc", testCase.getOperationBroadcast()));
|
||||
env.write(templateFile, data, outFile);
|
||||
shared_compiler->runner.run_test(
|
||||
testCategory, outFile, {fmt::format("{}\n0\n", testCase.getExpectedResult().toGOALFormat())});
|
||||
}
|
||||
|
||||
TEST_P(VectorFloatParameterizedTestFixtureWithRunner_TwoOperandACC, VF_MUL_SUB_XYZW_DEST) {
|
||||
VectorFloatTestCase_TwoOperandACC testCase = GetParam();
|
||||
testCase.operation = [](float x, float y, float acc) { return acc - (x * y); };
|
||||
|
||||
nlohmann::json data;
|
||||
testCase.setJson(data, fmt::format(".sub.mul{}.vf", testCase.getOperationBroadcast()));
|
||||
|
||||
std::string outFile = shared_compiler->runner.test_file_name(
|
||||
fmt::format("vector-math-sub-mul{}-{{}}.generated.gc", testCase.getOperationBroadcast()));
|
||||
env.write(templateFile, data, outFile);
|
||||
shared_compiler->runner.run_test(
|
||||
testCategory, outFile, {fmt::format("{}\n0\n", testCase.getExpectedResult().toGOALFormat())});
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(WithGameTests_VectorFloatTests,
|
||||
VectorFloatParameterizedTestFixtureWithRunner_TwoOperandACC,
|
||||
::testing::ValuesIn(vectorMathCaseGen_TwoOperandACC()));
|
||||
|
||||
// ---- Two Operand Quotient Register Operations
|
||||
|
||||
struct VectorFloatTestCase_TwoOperandQuotient : VectorFloatTestCase {
|
||||
VectorFloatRegister input1 = {1.5, -1.5, 0.0, 100.5};
|
||||
VectorFloatRegister input2 = {-5.5, -0.0, 10.0, 10.0};
|
||||
|
||||
int fsf = 0;
|
||||
int ftf = 0;
|
||||
|
||||
std::function<float(float, float)> operation;
|
||||
|
||||
VectorFloatRegister getExpectedResult() {
|
||||
float operand1 =
|
||||
input1.getBroadcastElement(static_cast<emitter::Register::VF_ELEMENT>(fsf), input1.x);
|
||||
float operand2 =
|
||||
input2.getBroadcastElement(static_cast<emitter::Register::VF_ELEMENT>(ftf), input2.x);
|
||||
float result = operation(operand1, operand2);
|
||||
VectorFloatRegister expectedResult;
|
||||
expectedResult.x = result;
|
||||
expectedResult.y = result;
|
||||
expectedResult.z = result;
|
||||
expectedResult.w = result;
|
||||
return expectedResult;
|
||||
}
|
||||
|
||||
void setJson(nlohmann::json& data, std::string func) {
|
||||
input1.setJson(data, "v1");
|
||||
input2.setJson(data, "v2");
|
||||
dest.setJson(data, "dest");
|
||||
data["operation"] = fmt::format(func);
|
||||
data["ftf"] = fmt::format("{:b}", ftf);
|
||||
data["fsf"] = fmt::format("{:b}", fsf);
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<VectorFloatTestCase_TwoOperandQuotient> vectorMathCaseGen_TwoOperandQuotient() {
|
||||
std::vector<VectorFloatTestCase_TwoOperandQuotient> cases = {};
|
||||
for (int i = 0; i <= 3; i++) {
|
||||
VectorFloatTestCase_TwoOperandQuotient testCase = VectorFloatTestCase_TwoOperandQuotient();
|
||||
testCase.fsf = i;
|
||||
for (int j = 0; j <= 3; j++) {
|
||||
testCase.ftf = j;
|
||||
cases.push_back(testCase);
|
||||
}
|
||||
}
|
||||
return cases;
|
||||
}
|
||||
|
||||
class VectorFloatParameterizedTestFixtureWithRunner_TwoOperandQuotient
|
||||
: public WithMinimalGameTests,
|
||||
public ::testing::WithParamInterface<VectorFloatTestCase_TwoOperandQuotient> {
|
||||
protected:
|
||||
std::string templateFile = "test-vector-math-division.template.gc";
|
||||
};
|
||||
|
||||
TEST_P(VectorFloatParameterizedTestFixtureWithRunner_TwoOperandQuotient, VF_DIV_FTF_FSF) {
|
||||
VectorFloatTestCase_TwoOperandQuotient testCase = GetParam();
|
||||
testCase.operation = [](float x, float y) { return x / y; };
|
||||
|
||||
nlohmann::json data;
|
||||
testCase.setJson(data, ".div.vf");
|
||||
|
||||
std::string outFile = shared_compiler->runner.test_file_name("vector-math-div-{}.generated.gc");
|
||||
env.write(templateFile, data, outFile);
|
||||
shared_compiler->runner.run_test(
|
||||
testCategory, outFile,
|
||||
{fmt::format("{}\n0\n",
|
||||
testCase.getExpectedResult().toGOALFormat(testCase.getExpectedResult().x))});
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(WithGameTests_VectorFloatTests,
|
||||
VectorFloatParameterizedTestFixtureWithRunner_TwoOperandQuotient,
|
||||
::testing::ValuesIn(vectorMathCaseGen_TwoOperandQuotient()));
|
||||
|
||||
// ---- Single Operand Quotient Register Operations
|
||||
|
||||
struct VectorFloatTestCase_OneOperandQuotient : VectorFloatTestCase {
|
||||
VectorFloatRegister input1 = {2, -2, 0.0, 100};
|
||||
|
||||
int ftf = 0;
|
||||
|
||||
std::function<float(float)> operation;
|
||||
|
||||
VectorFloatRegister getExpectedResult() {
|
||||
float operand1 =
|
||||
input1.getBroadcastElement(static_cast<emitter::Register::VF_ELEMENT>(ftf), input1.x);
|
||||
float result = operation(operand1);
|
||||
VectorFloatRegister expectedResult;
|
||||
expectedResult.x = result;
|
||||
expectedResult.y = result;
|
||||
expectedResult.z = result;
|
||||
expectedResult.w = result;
|
||||
return expectedResult;
|
||||
}
|
||||
|
||||
void setJson(nlohmann::json& data, std::string func) {
|
||||
input1.setJson(data, "v1");
|
||||
dest.setJson(data, "dest");
|
||||
data["operation"] = fmt::format(func);
|
||||
data["ftf"] = fmt::format("{:b}", ftf);
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<VectorFloatTestCase_OneOperandQuotient> vectorMathCaseGen_OneOperandQuotient() {
|
||||
std::vector<VectorFloatTestCase_OneOperandQuotient> cases = {};
|
||||
for (int i = 0; i <= 3; i++) {
|
||||
VectorFloatTestCase_OneOperandQuotient testCase = VectorFloatTestCase_OneOperandQuotient();
|
||||
testCase.ftf = i;
|
||||
cases.push_back(testCase);
|
||||
}
|
||||
return cases;
|
||||
}
|
||||
|
||||
class VectorFloatParameterizedTestFixtureWithRunner_OneOperandQuotient
|
||||
: public WithMinimalGameTests,
|
||||
public ::testing::WithParamInterface<VectorFloatTestCase_OneOperandQuotient> {
|
||||
protected:
|
||||
std::string templateFile = "test-vector-math-sqrt.template.gc";
|
||||
};
|
||||
|
||||
TEST_P(VectorFloatParameterizedTestFixtureWithRunner_OneOperandQuotient, VF_SQRT_FTF) {
|
||||
VectorFloatTestCase_OneOperandQuotient testCase = GetParam();
|
||||
testCase.operation = [](float x) { return sqrt(x); };
|
||||
|
||||
nlohmann::json data;
|
||||
testCase.setJson(data, ".sqrt.vf");
|
||||
|
||||
std::string outFile = shared_compiler->runner.test_file_name("vector-math-sqrt-{}.generated.gc");
|
||||
env.write(templateFile, data, outFile);
|
||||
shared_compiler->runner.run_test(
|
||||
testCategory, outFile,
|
||||
{fmt::format("{}\n0\n",
|
||||
testCase.getExpectedResult().toGOALFormat(testCase.getExpectedResult().x))});
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(WithGameTests_VectorFloatTests,
|
||||
VectorFloatParameterizedTestFixtureWithRunner_OneOperandQuotient,
|
||||
::testing::ValuesIn(vectorMathCaseGen_OneOperandQuotient()));
|
File diff suppressed because it is too large
Load Diff
8
third-party/xdelta3/xdelta3/xdelta3.h
generated
vendored
8
third-party/xdelta3/xdelta3/xdelta3.h
generated
vendored
@ -22,9 +22,17 @@
|
||||
#ifndef _XDELTA3_H_
|
||||
#define _XDELTA3_H_
|
||||
|
||||
#ifndef _POSIX_SOURCE
|
||||
#define _POSIX_SOURCE 200112L
|
||||
#endif
|
||||
|
||||
#ifndef _ISOC99_SOURCE
|
||||
#define _ISOC99_SOURCE
|
||||
#endif
|
||||
|
||||
#ifndef _C99_SOURCE
|
||||
#define _C99_SOURCE
|
||||
#endif
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
|
Loading…
Reference in New Issue
Block a user