#include "pressure_decode.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
static void clear_check(xp_result o) { assert(!o.decoded && !o.suction_valid && !o.raw_signed && !o.pressure_millipa); }
int main(void) {
    xp_profile p={0x58,33,-5000,5000}; xp_result o;
    uint8_t b[5]={0}; uint64_t checked=0;
    for(unsigned revision_index=0;revision_index<2;revision_index++){
        p=(xp_profile){0x58,revision_index?33:31,revision_index?-5000:-500,revision_index?5000:500};
    for (uint32_t u=0;u<16777216u;u++) {
        b[0]=(uint8_t)(u>>16); b[1]=(uint8_t)(u>>8); b[2]=(uint8_t)u;
        int32_t raw=(int32_t)(u & 0x7fffff) - ((u & 0x800000)?8388608:0);
        /* Independent long-double reference, inclusive range and rounding. */
        long double pa=(long double)raw * (long double)(p.pmax_pa-p.pmin_pa) / 2097152.0L;
        xp_status s=xp_decode(&p,b,5,true,&o);
        if (pa < p.pmin_pa || pa > p.pmax_pa) { assert(s==XP_RANGE); clear_check(o); }
        else { assert(s==XP_OK && o.decoded && !o.suction_valid && o.raw_signed==raw);
            long double m=pa*1000; int64_t ref=(int64_t)(m+(m<0?-0.5L:0.5L)); assert(o.pressure_millipa==ref); }
        checked++;
    }
    }
    const xp_profile profiles[]={{0x58,33,-1000,1000},{0x58,33,0,5000},{0x58,33,-20000,0},{0x58,33,-100000,100000}};
    memset(b,0,sizeof b);
    for(size_t i=0;i<sizeof profiles/sizeof profiles[0];i++) assert(xp_decode(profiles+i,b,5,true,&o)==XP_OK && o.pressure_millipa==0 && !o.suction_valid);
    for(size_t n=0;n<8;n++) if(n!=5) {o=(xp_result){1,1,true,true};assert(xp_decode(&p,b,n,true,&o)==XP_TRANSPORT);clear_check(o);}
    assert(xp_decode(&p,b,5,false,&o)==XP_TRANSPORT);clear_check(o);
    p.address=0x6d;assert(xp_decode(&p,b,5,true,&o)==XP_PROFILE);clear_check(o);
    p.address=0x58;p.protocol_revision=31;assert(xp_decode(&p,b,5,true,&o)==XP_OK && o.decoded && !o.suction_valid);
    p.protocol_revision=32;assert(xp_decode(&p,b,5,true,&o)==XP_PROFILE);clear_check(o);
    p.protocol_revision=33;p.pmin_pa=1;assert(xp_decode(&p,b,5,true,&o)==XP_PROFILE);clear_check(o);
    assert(xp_decode(NULL,b,5,true,&o)==XP_ARGUMENT);clear_check(o);
    assert(xp_decode(&p,NULL,5,true,&o)==XP_ARGUMENT);clear_check(o);
    assert(xp_decode(&p,b,5,true,NULL)==XP_ARGUMENT);
    printf("PASS: %llu raw encodings, range/sign/rounding and stale-output guards; suction_valid always false\n",(unsigned long long)checked);
}
