diff options
author | Lev Walkin <vlm@lionet.info> | 2012-01-07 17:00:29 -0800 |
---|---|---|
committer | Lev Walkin <vlm@lionet.info> | 2012-01-07 17:00:29 -0800 |
commit | 5fe72e9d6ce7c0a9512046b30ae244a772b56fa8 (patch) | |
tree | ff03af9639146786bfeb4e898e8f803aa8686362 | |
parent | 833d27521dfa4425d9adbae4f6472d68c1f68f72 (diff) |
test encoding of special values
-rw-r--r-- | skeletons/REAL.c | 10 | ||||
-rw-r--r-- | skeletons/tests/check-REAL.c | 223 |
2 files changed, 166 insertions, 67 deletions
diff --git a/skeletons/REAL.c b/skeletons/REAL.c index e5cced8e..b8585e02 100644 --- a/skeletons/REAL.c +++ b/skeletons/REAL.c @@ -577,14 +577,14 @@ asn_double2REAL(REAL_t *st, double dbl_value) { st->buf[1] = 0; st->size = 1; } else { - if(copysign(1.0, dbl_value) < 0.0) { - st->buf[0] = 0x80 | 0x40; - st->buf[1] = 0; - st->size = 2; - } else { + if(copysign(1.0, dbl_value) >= 0.0) { /* no content octets: positive zero */ st->buf[0] = 0; /* JIC */ st->size = 0; + } else { + /* Negative zero. #8.5.3, 8.5.9 */ + st->buf[0] = 0x43; + st->size = 1; } } return 0; diff --git a/skeletons/tests/check-REAL.c b/skeletons/tests/check-REAL.c index 46b1a95b..07918ef2 100644 --- a/skeletons/tests/check-REAL.c +++ b/skeletons/tests/check-REAL.c @@ -39,26 +39,29 @@ d2s(double d, int canonical, const char *str) { * is as given in the (sample) and (canonical_sample) arguments. */ static void -check_str_repr(double d, const char *sample, const char *canonical_sample) { +check_str_representation(double d, const char *sample, const char *canonical_sample) { char *s0, *s1; s0 = d2s(d, 0, sample); s1 = d2s(d, 1, canonical_sample); if(sample) { - printf("Checking %f->[%s] against [%s]%s\n", + printf("Checking %f->[\"%s\"] against [\"%s\"]%s\n", d, s0, sample, canonical_sample ? " (canonical follows...)" : "" ); assert(!strcmp(s0, sample)); } if(canonical_sample) { - printf("Checking %f->[%s] against [%s] (canonical)\n", + printf("Checking %f->[\"%s\"] against [\"%s\"] (canonical)\n", d, s1, canonical_sample); assert(!strcmp(s1, canonical_sample)); } } +#define check(rn, d, str1, str2) \ + check_impl(rn, d, str1, str2, __LINE__) + static void check_impl(REAL_t *rn, double orig_dbl, const char *sample, const char *canonical_sample, int line) { double val; @@ -96,57 +99,8 @@ check_impl(REAL_t *rn, double orig_dbl, const char *sample, const char *canonica assert((isnan(orig_dbl) && isnan(val)) || val == orig_dbl); printf("OK\n"); - check_str_repr(val, sample, canonical_sample); + check_str_representation(val, sample, canonical_sample); } - -uint8_t buf_1_0[] = { 0x80, 0xcc, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -uint8_t buf_1_1[] = { 0x80, 0xcc, 0x11, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a }; -uint8_t buf_3_14[] = { 0x80, 0xcd, 0x19, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f }; -/* These ones are very interesting! They check mantissa overflow! */ -uint8_t buf_mo1[] = { 0xC0, 0xc5, 0x19, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f,3}; -uint8_t buf_mo2[] = { 0x80, 0xbd, 0x19, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f,3,2}; - -static void -check_buf(uint8_t *buf, size_t bufsize, double verify, const char *sample, const char *canonical_sample) { - REAL_t rn; - double val; - uint8_t *p, *end; - int ret; - - printf("verify double value %.12f [", verify); - for(p = (uint8_t *)&verify, end = p + sizeof(double); p < end ; p++) - printf("%02x", *p); - printf("] (ilogb %d)\n", ilogb(verify)); - - rn.buf = 0; - rn.size = 0; - - ret = asn_double2REAL(&rn, verify); - assert(ret == 0); - - printf("canonical DER: ["); - for(p = rn.buf, end = p + rn.size; p < end; p++) - printf("%02x", *p); - printf("]\n"); - - rn.buf = buf; - rn.size = bufsize; - - printf("received as: ["); - for(p = rn.buf, end = p + rn.size; p < end; p++) - printf("%02x", *p); - printf("]\n"); - - ret = asn_REAL2double(&rn, &val); - assert(ret == 0); - - printf("%.12f vs %.12f\n", verify, val); - - assert(val == verify); - - check_str_repr(val, sample, canonical_sample); -} - static void check_xer(int fuzzy, double orig_value) { asn_enc_rval_t er; @@ -207,16 +161,167 @@ check_xer(int fuzzy, double orig_value) { assert(memcmp(newst1->buf, st.buf, st.size) == 0); } -#define check(rn, d, str1, str2) \ - check_impl(rn, d, str1, str2, __LINE__) +static void +check_ber_buffer_twoway(double d, const char *sample, const char *canonical_sample, uint8_t *inbuf, size_t insize, uint8_t *outbuf, size_t outsize) { + REAL_t rn; + double val; + int ret; + + /* + * Decode our expected buffer and check that it matches the given (d). + */ + rn.buf = inbuf; + rn.size = insize; + asn_REAL2double(&rn, &val); + if(isnan(val)) assert(isnan(d)); + if(isnan(d)) assert(isnan(val)); + if(!isnan(val) && !isnan(d)) { + assert(copysign(1.0, d) == copysign(1.0, val)); + assert(d == val); + } + + /* + * Encode value and check that it matches our expected buffer. + */ + memset(&rn, 0, sizeof(rn)); + ret = asn_double2REAL(&rn, d); + assert(ret == 0); + uint8_t *p, *end; + printf("received as: ["); + for(p = rn.buf, end = p + rn.size; p < end; p++) + printf("%02x", *p); + printf("]\n"); + printf("received as: ["); + for(p = outbuf, end = p + outsize; p < end; p++) + printf("%02x", *p); + printf("]\n"); + if(rn.size != outsize) { + printf("Encoded %f into %d expected %ld\n", + d, (int)rn.size, outsize); + assert(rn.size == outsize); + } + assert(memcmp(rn.buf, outbuf, rn.size) == 0); + + check_str_representation(d, sample, canonical_sample); +} + +static void +check_ber_buffer_oneway(double d, const char *sample, const char *canonical_sample, uint8_t *buf, size_t bufsize) { + REAL_t rn; + double val; + uint8_t *p, *end; + int ret; + + memset(&rn, 0, sizeof(rn)); + + printf("verify double value %.12f [", d); + for(p = (uint8_t *)&d, end = p + sizeof(double); p < end ; p++) + printf("%02x", *p); + printf("] (ilogb %d)\n", ilogb(d)); + + + ret = asn_double2REAL(&rn, d); + assert(ret == 0); + + printf("canonical DER: ["); + for(p = rn.buf, end = p + rn.size; p < end; p++) + printf("%02x", *p); + printf("]\n"); + + rn.buf = buf; + rn.size = bufsize; + + printf("received as: ["); + for(p = rn.buf, end = p + rn.size; p < end; p++) + printf("%02x", *p); + printf("]\n"); + + ret = asn_REAL2double(&rn, &val); + assert(ret == 0); + + printf("%.12f vs %.12f\n", d, val); + + assert(val == d); + + check_str_representation(val, sample, canonical_sample); +} + + +static void +check_ber_encoding() { + static const double zero = 0.0; + +#define CHECK_BER_STRICT(v, nocan, can, inbuf, outbuf) \ + check_ber_buffer_twoway(v, nocan, can, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf)) + +#define CHECK_BER_NONSTRICT(v, nocan, can, buf) \ + check_ber_buffer_oneway(v, nocan, can, buf, sizeof(buf)) + + /* + * X.690 8.4 Encoding of an enumerated value. + */ + + /* 8.5.2 If the real value is the value plus zero, + * there shall be no contents octet in the encoding */ + { uint8_t b_0[] = {}; + CHECK_BER_STRICT(0, "0", "0", b_0, b_0); + } + + /* 8.5.3 When -0 is to be encoded, there shall be only one contents octet */ + { uint8_t b_m0[] = { 0x43 }; + CHECK_BER_STRICT(-0.0, "-0", "-0", b_m0, b_m0); + } + + /* Old way of encoding -0.0: 8.5.6 a) */ + { uint8_t b_m0[] = { 0x43 }; + uint8_t b_m0_856a[] = { 0xC0, 0x00 }; /* #8.5.6 a) */ + uint8_t b_m0_856a_1[] = { 0xC0, 0x00, 0x00 }; + uint8_t b_m0_856a_2[] = { 0xC0, 0x00, 0x00, 0x00 }; + uint8_t b_m0_856a_3[] = { 0xC0, 0x00, 0x00, 0x00, 0x00 }; + CHECK_BER_STRICT(-0.0, "-0", "-0", b_m0_856a, b_m0); + CHECK_BER_STRICT(-0.0, "-0", "-0", b_m0_856a_1, b_m0); + CHECK_BER_STRICT(-0.0, "-0", "-0", b_m0_856a_2, b_m0); + CHECK_BER_STRICT(-0.0, "-0", "-0", b_m0_856a_3, b_m0); + } + + /* 8.5.6 c) => 8.5.9 SpecialRealValue */ + { uint8_t b_pinf[] = { 0x40 }; + uint8_t b_minf[] = { 0x41 }; + uint8_t b_nan[] = { 0x42 }; + CHECK_BER_STRICT(1.0/zero, "<PLUS-INFINITY/>", "<PLUS-INFINITY/>", b_pinf, b_pinf); + CHECK_BER_STRICT(-1.0/zero, "<MINUS-INFINITY/>", "<MINUS-INFINITY/>", b_minf, b_minf); + CHECK_BER_STRICT(zero/zero, "<NOT-A-NUMBER/>", "<NOT-A-NUMBER/>", b_nan, b_nan); + } + + { + uint8_t b_1_0[] = + { 0x80, 0xcc, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + uint8_t b_1_1[] = + { 0x80, 0xcc, 0x11, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a }; + uint8_t b_3_14[] = + { 0x80, 0xcd, 0x19, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f }; + uint8_t b_3_14_mo1[] = + { 0xC0, 0xc5, 0x19, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f,3}; + uint8_t b_3_14_mo2[] = + { 0x80, 0xbd, 0x19, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f,3,2}; + + CHECK_BER_NONSTRICT(1.0, "1.0", "1.0E0", b_1_0); + CHECK_BER_NONSTRICT(1.1, "1.1", "1.1E0", b_1_1); + CHECK_BER_NONSTRICT(3.14, "3.14", "3.14E0", b_3_14); + /* These two are very interesting! They check mantissa overflow! */ + CHECK_BER_NONSTRICT(-3.14, "-3.14", "-3.14E0", b_3_14_mo1); + CHECK_BER_NONSTRICT(3.14, "3.14", "3.14E0", b_3_14_mo2); + } +} int main() { REAL_t rn; static const double zero = 0.0; - memset(&rn, 0, sizeof(rn)); + check_ber_encoding(); + check(&rn, 0.0, "0", "0"); check(&rn, -0.0, "-0", "-0"); /* minus-zero */ check(&rn, zero/zero, "<NOT-A-NUMBER/>", "<NOT-A-NUMBER/>"); @@ -260,12 +365,6 @@ main() { check(&rn, 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000033333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333, 0, 0); check(&rn, -0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001, 0, 0); - check_buf(buf_1_0, sizeof(buf_1_0), 1.0, "1.0", "1.0E0"); - check_buf(buf_1_1, sizeof(buf_1_1), 1.1, "1.1", "1.1E0"); - check_buf(buf_3_14, sizeof(buf_3_14), 3.14, "3.14", "3.14E0"); - check_buf(buf_mo1, sizeof(buf_mo1), -3.14, "-3.14", "-3.14E0"); - check_buf(buf_mo2, sizeof(buf_mo2), 3.14, "3.14", "3.14E0"); - #ifdef NAN check_xer(0, NAN); /* "<NOT-A-NUMBER/>" */ |