/* * Copyright 2021 Juan Cruz Viotti * * 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. */ import tap from 'tap' import * as fc from 'fast-check' import { BOUNDED_MULTIPLE_8BITS_ENUM_FIXED as ENCODE_BOUNDED_MULTIPLE_8BITS_ENUM_FIXED, FLOOR_MULTIPLE_ENUM_VARINT as ENCODE_FLOOR_MULTIPLE_ENUM_VARINT, ROOF_MULTIPLE_MIRROR_ENUM_VARINT as ENCODE_ROOF_MULTIPLE_MIRROR_ENUM_VARINT, ARBITRARY_MULTIPLE_ZIGZAG_VARINT as ENCODE_ARBITRARY_MULTIPLE_ZIGZAG_VARINT } from '../../lib/encoder/integer/encode' import { IntegerResult, BOUNDED_MULTIPLE_8BITS_ENUM_FIXED as DECODE_BOUNDED_MULTIPLE_8BITS_ENUM_FIXED, FLOOR_MULTIPLE_ENUM_VARINT as DECODE_FLOOR_MULTIPLE_ENUM_VARINT, ROOF_MULTIPLE_MIRROR_ENUM_VARINT as DECODE_ROOF_MULTIPLE_MIRROR_ENUM_VARINT, ARBITRARY_MULTIPLE_ZIGZAG_VARINT as DECODE_ARBITRARY_MULTIPLE_ZIGZAG_VARINT } from '../../lib/encoder/integer/decode' import { UINT8_MAX } from '../../lib/utils/limits' import { ResizableBuffer, EncodingContext, getDefaultEncodingContext } from '../../lib/encoder' tap.test('BOUNDED_MULTIPLE_8BITS_ENUM_FIXED', (test) => { const arbitrary = fc.integer().chain((minimum: number) => { return fc.tuple( fc.nat(10), fc.constant(minimum), fc.integer(minimum, minimum + UINT8_MAX), fc.integer(minimum, minimum + UINT8_MAX)) }) fc.assert(fc.property(arbitrary, ([ offset, minimum, maximum, value ]): boolean => { fc.pre(value <= maximum) const context: EncodingContext = getDefaultEncodingContext() const buffer: ResizableBuffer = new ResizableBuffer(Buffer.allocUnsafe(offset + 1)) const bytesWritten: number = ENCODE_BOUNDED_MULTIPLE_8BITS_ENUM_FIXED(buffer, offset, value, { minimum, maximum, multiplier: 1 }, context) const result: IntegerResult = DECODE_BOUNDED_MULTIPLE_8BITS_ENUM_FIXED(buffer, offset, { minimum, maximum, multiplier: 1 }) return bytesWritten === 1 && result.bytes === bytesWritten && result.value === value }), { verbose: false }) test.end() }) tap.test('BOUNDED_MULTIPLE_8BITS_ENUM_FIXED', (test) => { const arbitrary = fc.integer().chain((minimum: number) => { return fc.integer(minimum, minimum + UINT8_MAX).chain((maximum: number) => { return fc.tuple( fc.nat(10), fc.constant(minimum), fc.constant(maximum), fc.integer(minimum, maximum), fc.integer(minimum, maximum) ) }) }) fc.assert(fc.property(arbitrary, ([ offset, minimum, maximum, value, multiplier ]): boolean => { fc.pre(value % multiplier === 0) const context: EncodingContext = getDefaultEncodingContext() const buffer: ResizableBuffer = new ResizableBuffer(Buffer.allocUnsafe(offset + 1)) const bytesWritten: number = ENCODE_BOUNDED_MULTIPLE_8BITS_ENUM_FIXED( buffer, offset, value, { minimum, maximum, multiplier }, context) const result: IntegerResult = DECODE_BOUNDED_MULTIPLE_8BITS_ENUM_FIXED( buffer, offset, { minimum, maximum, multiplier }) return bytesWritten > 0 && result.bytes === bytesWritten && result.value === value }), { verbose: false }) test.end() }) tap.test('FLOOR_MULTIPLE_ENUM_VARINT: should encode 696667952522107300000', (test) => { const context: EncodingContext = getDefaultEncodingContext() const buffer: ResizableBuffer = new ResizableBuffer(Buffer.allocUnsafe(60)) const value: number = 696667952522107300000 const bytesWritten: number = ENCODE_FLOOR_MULTIPLE_ENUM_VARINT(buffer, 0, value, { minimum: 0, multiplier: 1 }, context) const result: IntegerResult = DECODE_FLOOR_MULTIPLE_ENUM_VARINT(buffer, 0, { minimum: 0, multiplier: 1 }) test.is(bytesWritten, result.bytes) test.is(result.value, value) test.end() }) tap.test('FLOOR_MULTIPLE_ENUM_VARINT', (test) => { fc.assert(fc.property(fc.nat(10), fc.integer(), fc.integer(), ( offset: number, value: number, minimum: number ): boolean => { fc.pre(value >= minimum) const context: EncodingContext = getDefaultEncodingContext() const buffer: ResizableBuffer = new ResizableBuffer(Buffer.allocUnsafe(offset + 8)) const bytesWritten: number = ENCODE_FLOOR_MULTIPLE_ENUM_VARINT(buffer, offset, value, { minimum, multiplier: 1 }, context) const result: IntegerResult = DECODE_FLOOR_MULTIPLE_ENUM_VARINT(buffer, offset, { minimum, multiplier: 1 }) return bytesWritten > 0 && result.bytes === bytesWritten && result.value === value }), { verbose: false }) test.end() }) tap.test('FLOOR_MULTIPLE_ENUM_VARINT', (test) => { const arbitrary = fc.integer().chain((minimum: number) => { return fc.tuple( fc.nat(10), fc.constant(minimum), fc.integer({ min: minimum }), fc.integer({ min: minimum }) ) }) fc.assert(fc.property(arbitrary, ([ offset, minimum, value, multiplier ]): boolean => { fc.pre(value % multiplier === 0) const context: EncodingContext = getDefaultEncodingContext() const buffer: ResizableBuffer = new ResizableBuffer(Buffer.allocUnsafe(offset + 8)) const bytesWritten: number = ENCODE_FLOOR_MULTIPLE_ENUM_VARINT(buffer, offset, value, { minimum, multiplier }, context) const result: IntegerResult = DECODE_FLOOR_MULTIPLE_ENUM_VARINT(buffer, offset, { minimum, multiplier }) return bytesWritten > 0 && result.bytes === bytesWritten && result.value === value }), { verbose: false }) test.end() }) tap.test('ROOF_MULTIPLE_MIRROR_ENUM_VARINT', (test) => { fc.assert(fc.property(fc.nat(10), fc.integer(), fc.integer(), ( offset: number, value: number, maximum: number ): boolean => { fc.pre(value <= maximum) const context: EncodingContext = getDefaultEncodingContext() const buffer: ResizableBuffer = new ResizableBuffer(Buffer.allocUnsafe(offset + 8)) const bytesWritten: number = ENCODE_ROOF_MULTIPLE_MIRROR_ENUM_VARINT(buffer, offset, value, { maximum, multiplier: 1 }, context) const result: IntegerResult = DECODE_ROOF_MULTIPLE_MIRROR_ENUM_VARINT(buffer, offset, { maximum, multiplier: 1 }) return bytesWritten > 0 && result.bytes === bytesWritten && result.value === value }), { verbose: false }) test.end() }) tap.test('ROOF_MULTIPLE_MIRROR_ENUM_VARINT', (test) => { const arbitrary = fc.integer().chain((maximum: number) => { return fc.tuple( fc.nat(10), fc.constant(maximum), fc.integer({ max: maximum }), fc.integer({ max: maximum }) ) }) fc.assert(fc.property(arbitrary, ([ offset, maximum, value, multiplier ]): boolean => { fc.pre(value % multiplier === 0) const context: EncodingContext = getDefaultEncodingContext() const buffer: ResizableBuffer = new ResizableBuffer(Buffer.allocUnsafe(offset + 8)) const bytesWritten: number = ENCODE_ROOF_MULTIPLE_MIRROR_ENUM_VARINT(buffer, offset, value, { maximum, multiplier }, context) const result: IntegerResult = DECODE_ROOF_MULTIPLE_MIRROR_ENUM_VARINT(buffer, offset, { maximum, multiplier }) return bytesWritten > 0 && result.bytes === bytesWritten && result.value === value }), { verbose: false }) test.end() }) tap.test('ARBITRARY_MULTIPLE_ZIGZAG_VARINT with multiplier 1', (test) => { fc.assert(fc.property(fc.nat(10), fc.integer(), (offset: number, value: number): boolean => { const context: EncodingContext = getDefaultEncodingContext() const buffer: ResizableBuffer = new ResizableBuffer(Buffer.allocUnsafe(offset + 8)) const bytesWritten: number = ENCODE_ARBITRARY_MULTIPLE_ZIGZAG_VARINT(buffer, offset, value, { multiplier: 1 }, context) const result: IntegerResult = DECODE_ARBITRARY_MULTIPLE_ZIGZAG_VARINT(buffer, offset, { multiplier: 1 }) return bytesWritten > 0 && result.bytes === bytesWritten && result.value === value }), { verbose: false }) test.end() }) tap.test('ARBITRARY_MULTIPLE_ZIGZAG_VARINT', (test) => { fc.assert(fc.property(fc.nat(10), fc.integer(), fc.integer(), ( offset: number, value: number, multiplier: number ): boolean => { fc.pre(value % multiplier === 0) const context: EncodingContext = getDefaultEncodingContext() const buffer: ResizableBuffer = new ResizableBuffer(Buffer.allocUnsafe(offset + 8)) const bytesWritten: number = ENCODE_ARBITRARY_MULTIPLE_ZIGZAG_VARINT(buffer, offset, value, { multiplier }, context) const result: IntegerResult = DECODE_ARBITRARY_MULTIPLE_ZIGZAG_VARINT(buffer, offset, { multiplier }) return bytesWritten > 0 && result.bytes === bytesWritten && result.value === value }), { verbose: false }) test.end() })