use std::sync::atomic::{AtomicUsize, Ordering};
use mozjs::jsapi::JSContext;
use mozjs::jsval::JSVal;
use crate::job_queue::set_uncaught_hooks;
static UNCAUGHT_TOUCH_A: AtomicUsize = AtomicUsize::new(0);
static UNCAUGHT_TOUCH_B: AtomicUsize = AtomicUsize::new(0);
static FLUSH_TOUCH_A: AtomicUsize = AtomicUsize::new(0);
static FLUSH_TOUCH_B: AtomicUsize = AtomicUsize::new(0);
unsafe fn uncaught_router_a(_cx: *mut JSContext, _reason: JSVal) {
UNCAUGHT_TOUCH_A.fetch_add(1, Ordering::Relaxed);
}
unsafe fn uncaught_router_b(_cx: *mut JSContext, _reason: JSVal) {
UNCAUGHT_TOUCH_B.fetch_add(1, Ordering::Relaxed);
}
unsafe fn flusher_a(_cx: *mut JSContext) {
FLUSH_TOUCH_A.fetch_add(1, Ordering::Relaxed);
}
unsafe fn flusher_b(_cx: *mut JSContext) {
FLUSH_TOUCH_B.fetch_add(1, Ordering::Relaxed);
}
#[test]
fn hook_contract_uncaught_hook_same_pointer_reregistration_is_idempotent() {
set_uncaught_hooks(uncaught_router_a, flusher_a);
set_uncaught_hooks(uncaught_router_a, flusher_a);
set_uncaught_hooks(uncaught_router_a, flusher_a);
assert_eq!(UNCAUGHT_TOUCH_A.load(Ordering::Relaxed), 0);
assert_eq!(FLUSH_TOUCH_A.load(Ordering::Relaxed), 0);
}
#[test]
fn hook_contract_flush_hook_same_pointer_reregistration_is_idempotent() {
set_uncaught_hooks(uncaught_router_a, flusher_a);
set_uncaught_hooks(uncaught_router_a, flusher_a);
assert_eq!(FLUSH_TOUCH_A.load(Ordering::Relaxed), 0);
assert_eq!(UNCAUGHT_TOUCH_A.load(Ordering::Relaxed), 0);
}
#[test]
#[cfg_attr(
not(debug_assertions),
ignore = "divergence enforcement is debug_assertions-only by contract"
)]
#[should_panic(expected = "UNCAUGHT_HOOK re-registration diverged")]
fn hook_contract_uncaught_hook_divergent_pointer_fails_closed_in_debug() {
set_uncaught_hooks(uncaught_router_a, flusher_a);
set_uncaught_hooks(uncaught_router_b, flusher_a);
}
#[test]
#[cfg_attr(
not(debug_assertions),
ignore = "divergence enforcement is debug_assertions-only by contract"
)]
#[should_panic(expected = "FLUSH_HOOK re-registration diverged")]
fn hook_contract_flush_hook_divergent_pointer_fails_closed_in_debug() {
set_uncaught_hooks(uncaught_router_a, flusher_a);
set_uncaught_hooks(uncaught_router_a, flusher_b);
}