pebble/tests/fw/javascript/test_rocky_common.h
2025-01-27 11:38:16 -08:00

296 lines
8.6 KiB
C

/*
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "applib/graphics/gtypes.h"
#include "applib/graphics/gcontext.h"
#include "applib/graphics/graphics_circle.h"
#include "applib/rockyjs/api/rocky_api_util.h"
#include "applib/tick_timer_service.h"
#include "applib/ui/layer.h"
#include "kernel/events.h"
#include "syscall/syscall.h"
#include <clar.h>
#include <util/attributes.h>
#include <string.h>
#define ASSERT_JS_GLOBAL_EQUALS_B(name, value) \
cl_assert_equal_i(prv_js_global_get_boolean(name), value);
#define ASSERT_JS_GLOBAL_EQUALS_I(name, value) \
cl_assert_equal_i(prv_js_global_get_double(name), value);
#define ASSERT_JS_GLOBAL_EQUALS_D(name, value) \
cl_assert_equal_d(prv_js_global_get_double(name), value);
#define ASSERT_JS_GLOBAL_EQUALS_S(name, value) \
do { \
char str_buffer[1024] = {}; \
prv_js_global_get_string(name, str_buffer, sizeof(str_buffer)); \
cl_assert_equal_s(str_buffer, value); \
} while(0)
#define JS_GLOBAL_GET_VALUE(name) \
prv_js_global_get_value(name)
#define ASSERT_JS_ERROR(error_value, expected_error_string) \
do { \
const bool expects_error = (expected_error_string) != NULL; \
const bool is_error = jerry_value_has_error_flag(error_value); \
if (is_error) { \
if (expects_error) { \
jerry_char_t buffer[100] = {0}; \
jerry_object_to_string_to_utf8_char_buffer(error_value, buffer, sizeof(buffer)); \
cl_assert_equal_s((char *)(expected_error_string), (char *)buffer); \
} else {\
rocky_log_exception("ASSERT_JS_ERROR", error_value); \
cl_fail("Error value while no error was expected!"); \
} \
} else { \
if (expects_error) { \
cl_fail("expected error during JS execution did not occur"); \
} \
} \
} while(0)
#define EXECUTE_SCRIPT_EXPECT_UNDEFINED(script) \
do { \
JS_VAR rv = jerry_eval((jerry_char_t *)script, \
strlen(script), \
false /* is_strict */); \
cl_assert_equal_b(true, jerry_value_is_undefined(rv)); \
} while(0)
#define EXECUTE_SCRIPT_EXPECT_ERROR(script, expected_error) \
do { \
JS_VAR rv = jerry_eval((jerry_char_t *)script, \
strlen(script), \
false /* is_strict */); \
ASSERT_JS_ERROR(rv, expected_error); \
} while(0)
#define EXECUTE_SCRIPT(script) EXECUTE_SCRIPT_EXPECT_ERROR((script), NULL)
#define EXECUTE_SCRIPT_AND_ASSERT_RV_EQUALS_S(script, expected_c_string) \
do { \
JS_VAR rv = jerry_eval((jerry_char_t *)script, \
strlen(script), false /* is_strict */); \
ASSERT_JS_ERROR(rv, NULL); \
JS_VAR rv_string = jerry_value_to_string(rv); \
jerry_size_t sz = jerry_get_utf8_string_size(rv_string); \
cl_assert(sz); \
jerry_char_t *buffer = malloc(sz + 1); \
memset(buffer, 0, sz + 1); \
cl_assert(buffer); \
cl_assert_equal_i(sz, jerry_string_to_utf8_char_buffer(rv_string, buffer, sz)); \
cl_assert_equal_s((char *)buffer, expected_c_string); \
free(buffer); \
} while(0)
#ifndef DO_NOT_STUB_LEGACY2
UNUSED bool process_manager_compiled_with_legacy2_sdk(void) {
return false;
}
#endif
UNUSED static jerry_value_t prv_js_global_get_value(char *name) {
JS_VAR global_obj = jerry_get_global_object();
cl_assert_equal_b(jerry_value_is_undefined(global_obj), false);
JS_VAR val = jerry_get_object_field(global_obj, name);
cl_assert_equal_b(jerry_value_is_undefined(val), false);
return jerry_acquire_value(val);
}
UNUSED static bool prv_js_global_get_boolean(char *name) {
JS_VAR val = prv_js_global_get_value(name);
cl_assert(jerry_value_is_boolean(val));
double rv = jerry_get_boolean_value(val);
return rv;
}
UNUSED static double prv_js_global_get_double(char *name) {
JS_VAR val = prv_js_global_get_value(name);
cl_assert(jerry_value_is_number(val));
double rv = jerry_get_number_value(val);
return rv;
}
UNUSED static void prv_js_global_get_string(char *name, char *buffer, size_t buffer_size) {
JS_VAR val = prv_js_global_get_value(name);
cl_assert(jerry_value_is_string(val));
ssize_t num_bytes = jerry_string_to_char_buffer(val, (jerry_char_t *)buffer, buffer_size);
cl_assert(num_bytes <= buffer_size);
}
void (*s_app_event_loop_callback)(void);
void app_event_loop_common(void) {
if (s_app_event_loop_callback) {
s_app_event_loop_callback();
}
}
#define cl_assert_equal_point(a, b) \
do { \
const GPoint __pt_a = (a); \
const GPoint __pt_b = (b); \
cl_assert_equal_i(__pt_a.x, __pt_b.x); \
cl_assert_equal_i(__pt_a.y, __pt_b.y); \
} while(0)
#define cl_assert_equal_point_precise(a, b) \
do { \
const GPointPrecise __pt_a = (a); \
const GPointPrecise __pt_b = (b); \
cl_assert_equal_i(__pt_a.x.raw_value, __pt_b.x.raw_value); \
cl_assert_equal_i(__pt_a.y.raw_value, __pt_b.y.raw_value); \
} while(0)
#define cl_assert_equal_vector_precise(a, b) \
do { \
const GVectorPrecise __a = (a); \
const GVectorPrecise __b = (b); \
cl_assert_equal_i(__a.dx.raw_value, __b.dx.raw_value); \
cl_assert_equal_i(__a.dy.raw_value, __b.dy.raw_value); \
} while(0)
#define cl_assert_equal_size(a, b) \
do { \
const GSize __sz_a = (a); \
const GSize __sz_b = (b); \
cl_assert_equal_i(__sz_a.w, __sz_b.w); \
cl_assert_equal_i(__sz_a.h, __sz_b.h); \
} while(0)
#define cl_assert_equal_size_precise(a, b) \
do { \
const GSizePrecise __sz_a = (a); \
const GSizePrecise __sz_b = (b); \
cl_assert_equal_i(__sz_a.w.raw_value, __sz_b.w.raw_value); \
cl_assert_equal_i(__sz_a.h.raw_value, __sz_b.h.raw_value); \
} while(0)
#define cl_assert_equal_rect(a, b) \
do { \
const GRect __a = (a); \
const GRect __b = (b); \
cl_assert_equal_point(__a.origin, __b.origin); \
cl_assert_equal_size(__a.size, __b.size); \
} while(0)
#define cl_assert_equal_rect_precise(a, b) \
do { \
const GRectPrecise __a = (a); \
const GRectPrecise __b = (b); \
cl_assert_equal_point_precise(__a.origin, __b.origin); \
cl_assert_equal_size_precise(__a.size, __b.size); \
} while(0)
typedef struct {
union {
Layer *layer;
GContext *ctx;
};
union {
GColor color;
uint8_t width;
struct {
GPoint p0;
GPoint p1;
};
struct {
GPointPrecise pp0;
GPointPrecise pp1;
};
struct {
GPointPrecise center;
Fixed_S16_3 radius;
int32_t angle_start;
int32_t angle_end;
} draw_arc;
struct {
GRect rect;
uint16_t radius;
GCornerMask corner_mask;
};
struct {
GRectPrecise prect;
};
TimeUnits tick_units;
const char *font_key;
struct {
char text[200];
GRect box;
GColor color;
} draw_text;
struct {
char text[200];
GFont font;
GRect box;
GTextOverflowMode overflow_mode;
GTextAlignment alignment;
} max_used_size;
struct {
GPoint points[200];
size_t num_points;
} path;
struct {
GPointPrecise center;
Fixed_S16_3 radius_inner;
Fixed_S16_3 radius_outer;
int32_t angle_start;
int32_t angle_end;
} fill_radial_precise;
};
} MockCallRecording;
typedef struct {
int call_count;
MockCallRecording last_call;
} MockCallRecordings;
#define record_mock_call(var) \
var.call_count++; \
var.last_call = (MockCallRecording)
// Handy for poking at .js things when debugging a unit test with gdb, for example:
// (gdb) call js_eval("1 + 1")
// 2
// (gdb) call js_eval("Date()")
// Thu Jan 01 1970 00:00:00 GMT+00:00
void js_eval(const char *src) {
JS_VAR rv = jerry_eval((const jerry_char_t *)src, strlen(src), false);
char buf[256] = {};
jerry_object_to_string_to_utf8_char_buffer(rv, (jerry_char_t *)buf, sizeof(buf));
printf("%s\n", buf);
}
static void (*s_process_manager_callback)(void *data);
static void *s_process_manager_callback_data;
void sys_current_process_schedule_callback(CallbackEventCallback async_cb,
void *ctx) {
s_process_manager_callback = async_cb;
s_process_manager_callback_data = ctx;
}