use super::{abi::*, prepare::*};
fn max_job() -> CudaClassicCodeBlockJob {
CudaClassicCodeBlockJob {
payload_offset: 0,
payload_len: 7,
segment_start: 0,
segment_count: 1,
width: 64,
height: 64,
output_stride: 64,
output_offset: 0,
missing_bitplanes: 0,
total_bitplanes: 31,
number_of_coding_passes: 91,
sub_band_type: 3,
style_flags: 0,
strict: true,
irreversible_midpoint: false,
roi_shift: 0,
dequantization_step: 1.0,
}
}
#[test]
fn classic_preflight_accepts_roi_maxshift_and_rejects_bitplane_overflow() {
let segments = [CudaClassicSegment {
data_offset: 0,
data_length: 7,
start_coding_pass: 0,
end_coding_pass: 91,
use_arithmetic: true,
}];
let mut job = max_job();
job.total_bitplanes = 24;
job.roi_shift = 7;
validate_classic_job(7, &segments, 64 * 64, &job).expect("valid ROI maxshift");
job.roi_shift = 8;
assert!(validate_classic_job(7, &segments, 64 * 64, &job).is_err());
}
#[test]
fn classic_preflight_accepts_maximum_contract() {
let segments = [CudaClassicSegment {
data_offset: 0,
data_length: 7,
start_coding_pass: 0,
end_coding_pass: 91,
use_arithmetic: true,
}];
validate_classic_job(7, &segments, 64 * 64, &max_job())
.expect("maximum classic Tier-1 contract");
}
#[test]
fn classic_preflight_accepts_zero_length_prefix_segment() {
let mut job = max_job();
job.number_of_coding_passes = 1;
job.style_flags = STYLE_TERMALL;
job.segment_count = 2;
let segments = [
CudaClassicSegment {
data_offset: 0,
data_length: 0,
start_coding_pass: 0,
end_coding_pass: 0,
use_arithmetic: true,
},
CudaClassicSegment {
data_offset: 0,
data_length: 7,
start_coding_pass: 0,
end_coding_pass: 1,
use_arithmetic: true,
},
];
validate_classic_job(7, &segments, 64 * 64, &job).expect("zero-length classic prefix");
}
#[test]
fn classic_preflight_rejects_noncontiguous_segments_and_output_overrun() {
let mut job = max_job();
let segments = [CudaClassicSegment {
data_offset: 1,
data_length: 6,
start_coding_pass: 0,
end_coding_pass: 91,
use_arithmetic: true,
}];
assert!(validate_classic_job(7, &segments, 64 * 64, &job).is_err());
job.output_offset = 1;
let segments = [CudaClassicSegment {
data_offset: 0,
data_length: 7,
start_coding_pass: 0,
end_coding_pass: 91,
use_arithmetic: true,
}];
assert!(validate_classic_job(7, &segments, 64 * 64, &job).is_err());
job.output_offset = 0;
job.payload_len = 8;
assert!(validate_classic_job(8, &segments, 64 * 64, &job).is_err());
}
#[cfg(target_pointer_width = "64")]
#[test]
fn classic_preflight_accepts_output_ranges_beyond_u32_words() {
let mut job = max_job();
job.width = 2;
job.height = 2;
job.output_stride = u32::MAX;
job.number_of_coding_passes = 1;
let segments = [CudaClassicSegment {
data_offset: 0,
data_length: 7,
start_coding_pass: 0,
end_coding_pass: 1,
use_arithmetic: true,
}];
validate_classic_job(
7,
&segments,
usize::try_from(u64::from(u32::MAX) + 2).expect("64-bit output words"),
&job,
)
.expect("device output addressing must support the host-validated range");
}
#[test]
fn classic_runtime_validates_empty_work_and_times_only_status_copy() {
let source = include_str!("launch.rs");
let method = source
.split("pub fn decode_classic_codeblocks_multi_with_resources_and_pool_timed")
.nth(1)
.expect("timed classic decode method");
let owner_validation = method
.find("validate_classic_launch_owners")
.expect("owner validation");
let prepare = method.find("prepare_classic_decode").expect("preparation");
let empty_return = method
.find("if prepared.jobs.is_empty()")
.expect("validated empty fast path");
assert!(owner_validation < empty_return && prepare < empty_return);
let status_copy = method.find("statuses.copy_to_host").expect("status copy");
let status_timing = method
.find("let status_d2h_us")
.expect("status timing result");
let pool_release = method
.find("let release_result = pool_reuse_guard.release()")
.expect("pool release");
assert!(status_copy < status_timing && status_timing < pool_release);
}
#[test]
fn queued_classic_launch_defers_its_only_status_copy_to_guard_completion() {
let launch = include_str!("launch.rs");
let enqueue = launch
.split("pub unsafe fn decode_classic_codeblocks_multi_enqueue_with_resources_and_pool")
.nth(1)
.expect("queued classic decode method")
.split("/// Decode classic Tier-1 code-blocks and return optional stage timings.")
.next()
.expect("queued classic decode body");
assert!(enqueue.contains("launch_kernel_async"));
assert!(enqueue.contains("CudaQueuedClassicDecode"));
assert!(!enqueue.contains("copy_to_host"));
let completion = include_str!("queued.rs")
.split("pub fn finish(")
.nth(1)
.expect("queued classic completion");
let status_copy = completion
.find("copy_to_host")
.expect("deferred status copy");
let release = completion
.find("let release_result = self.release_after_stream_completion()")
.expect("release after status completion");
assert!(status_copy < release);
}