Test cases for handling NULL input for all data types

This commit is contained in:
Greg Hysen
2019-02-05 18:01:38 -08:00
parent 2326dcdb12
commit 2ad6bd3945
2 changed files with 162 additions and 12 deletions

View File

@@ -1,4 +1,5 @@
import { DecodingRules, EncodingRules } from './rules';
import * as ethUtil from 'ethereumjs-util';
export const constants = {
EVM_WORD_WIDTH_IN_BYTES: 32,
@@ -15,7 +16,7 @@ export const constants = {
DEFAULT_ENCODING_RULES: { shouldOptimize: true, shouldAnnotate: false } as EncodingRules,
/* tslint:enable no-object-literal-type-assertion */
EMPTY_EVM_WORD_STRING: '0x0000000000000000000000000000000000000000000000000000000000000000',
EMPTY_EVM_WORD_BUFFER: new Buffer('0x0000000000000000000000000000000000000000000000000000000000000000'),
EMPTY_EVM_WORD_BUFFER: ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000000'),
NUMBER_OF_BYTES_IN_UINT8: 8,
NUMBER_OF_BYTES_IN_INT8: 8,
}

View File

@@ -11,6 +11,7 @@ const expect = chai.expect;
describe('ABI Encoder: EVM Data Type Encoding/Decoding', () => {
const encodingRules: AbiEncoder.EncodingRules = { shouldOptimize: false }; // optimizer is tested separately.
const nullEncodedArgs = '0x';
describe('Array', () => {
it('Fixed size; Static elements', async () => {
// Create DataType object
@@ -207,6 +208,51 @@ describe('ABI Encoder: EVM Data Type Encoding/Decoding', () => {
dataType.encode(args, encodingRules);
}).to.throw('Tried to assign NaN value');
});
it('Should decode NULL to default values (Fixed size; Static elements)', async () => {
// Create DataType object
const testDataItem = { name: 'testArray', type: 'int[2]' };
const dataType = new AbiEncoder.Array(testDataItem);
const args = [new BigNumber(0), new BigNumber(0)];
// Decode Encoded Args and validate result
const decodedArgs = dataType.decode(nullEncodedArgs);
expect(decodedArgs).to.be.deep.equal(args);
});
it('Should decode NULL to default values (Dynamic size; Static elements)', async () => {
// Create DataType object
const testDataItem = { name: 'testArray', type: 'int[]' };
const dataType = new AbiEncoder.Array(testDataItem);
const args: BigNumber[] = [];
// Decode Encoded Args and validate result
const decodedArgs = dataType.decode(nullEncodedArgs);
expect(decodedArgs).to.be.deep.equal(args);
});
it('Should decode NULL to default values (Fixed size; Dynamic elements)', async () => {
// Create DataType object
const testDataItem = { name: 'testArray', type: 'string[2]' };
const dataType = new AbiEncoder.Array(testDataItem);
const args = ['', ''];
// Decode Encoded Args and validate result
const decodedArgs = dataType.decode(nullEncodedArgs);
expect(decodedArgs).to.be.deep.equal(args);
});
it('Should decode NULL to default values (Dynamic size; Dynamic elements)', async () => {
// Create DataType object
const testDataItem = { name: 'testArray', type: 'string[]' };
const dataType = new AbiEncoder.Array(testDataItem);
const args: string[] = [];
// Decode Encoded Args and validate result
const decodedArgs = dataType.decode(nullEncodedArgs);
expect(decodedArgs).to.be.deep.equal(args);
});
it('Should decode NULL to default values (Dynamic Size; Multidimensional; Dynamic Elements)', async () => {
// Create DataType object
const testDataItem = { name: 'testArray', type: 'bytes[][]' };
const dataType = new AbiEncoder.Array(testDataItem);
const args: string[][] = [];
// Decode Encoded Args and validate result
const decodedArgs = dataType.decode(nullEncodedArgs);
expect(decodedArgs).to.be.deep.equal(args);
});
});
describe('Tuple', () => {
@@ -407,6 +453,46 @@ describe('ABI Encoder: EVM Data Type Encoding/Decoding', () => {
dataType.encode(args, encodingRules);
}).to.throw('Could not assign tuple to object: missing key \'field_2\' in object {"field_1":"-5"}');
});
it('Should decode NULL to default values (static elements only)', async () => {
// Create DataType object
const testDataItem = {
name: 'Tuple',
type: 'tuple',
components: [{ name: 'field_1', type: 'int32' }, { name: 'field_2', type: 'bool' }],
};
const dataType = new AbiEncoder.Tuple(testDataItem);
// Construct args to be encoded
const args = { field_1: new BigNumber(0), field_2: false };
// Decode Encoded Args and validate result
const decodingRules: AbiEncoder.DecodingRules = { shouldConvertStructsToObjects: true };
const decodedArgs = dataType.decode(nullEncodedArgs, decodingRules);
expect(decodedArgs).to.be.deep.equal(args);
});
it('Should decode NULL to default values (static and dynamic elements)', async () => {
// Create DataType object
const testDataItem = {
name: 'Tuple',
type: 'tuple',
components: [
{ name: 'field_1', type: 'int32' },
{ name: 'field_2', type: 'string' },
{ name: 'field_3', type: 'bool' },
{ name: 'field_4', type: 'bytes' },
],
};
const dataType = new AbiEncoder.Tuple(testDataItem);
// Construct args to be encoded
const args = {
field_1: new BigNumber(0),
field_2: '',
field_3: false,
field_4: '0x',
};
// Decode Encoded Args and validate result
const decodingRules: AbiEncoder.DecodingRules = { shouldConvertStructsToObjects: true };
const decodedArgs = dataType.decode(nullEncodedArgs, decodingRules);
expect(decodedArgs).to.be.deep.equal(args);
});
});
describe('Address', () => {
@@ -450,6 +536,15 @@ describe('ABI Encoder: EVM Data Type Encoding/Decoding', () => {
dataType.encode(args, encodingRules);
}).to.throw(`Invalid address: '${args}'`);
});
it('Should decode NULL to default value of address zero', async () => {
// Create DataType object
const testDataItem = { name: 'Address', type: 'address' };
const dataType = new AbiEncoder.Address(testDataItem);
const args = '0x0000000000000000000000000000000000000000';
// Decode Encoded Args and validate result
const decodedArgs = dataType.decode(nullEncodedArgs);
expect(decodedArgs).to.be.deep.equal(args);
});
});
describe('Bool', () => {
@@ -489,23 +584,14 @@ describe('ABI Encoder: EVM Data Type Encoding/Decoding', () => {
const argsEncodedFromSignature = dataTypeFromSignature.encode(args);
expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs);
});
it('Null should decode as False', async () => {
// Hack @hysz: there are some cases where `false` is encoded as 0x instead of 0x0.
it('Should decode NULL to default value of False', async () => {
// Create DataType object
const testDataItem = { name: 'Boolean', type: 'bool' };
const dataType = new AbiEncoder.Bool(testDataItem);
// Construct args to be encoded
const args = false;
// Encode Args and validate result
const encodedArgs = '0x';
const expectedEncodedArgs = '0x0000000000000000000000000000000000000000000000000000000000000000';
// Decode Encoded Args and validate result
const decodedArgs = dataType.decode(encodedArgs);
const decodedArgs = dataType.decode(nullEncodedArgs);
expect(decodedArgs).to.be.deep.equal(args);
// Validate signature
const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true));
const argsEncodedFromSignature = dataTypeFromSignature.encode(args);
expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs);
});
});
@@ -705,6 +791,15 @@ describe('ABI Encoder: EVM Data Type Encoding/Decoding', () => {
dataType.encode(args, encodingRules);
}).to.throw();
});
it('Should decode NULL to default value of 0', async () => {
// Create DataType object
const testDataItem = { name: 'Integer (256)', type: 'int' };
const dataType = new AbiEncoder.Int(testDataItem);
const args = new BigNumber(0);
// Decode Encoded Args and validate result
const decodedArgs = dataType.decode(nullEncodedArgs);
expect(decodedArgs).to.be.deep.equal(args);
});
});
describe('Unsigned Integer', () => {
@@ -867,6 +962,15 @@ describe('ABI Encoder: EVM Data Type Encoding/Decoding', () => {
dataType.encode(args, encodingRules);
}).to.throw();
});
it('Should decode NULL to default value of 0', async () => {
// Create DataType object
const testDataItem = { name: 'Unsigned Integer (256)', type: 'uint' };
const dataType = new AbiEncoder.UInt(testDataItem);
const args = new BigNumber(0);
// Decode Encoded Args and validate result
const decodedArgs = dataType.decode(nullEncodedArgs);
expect(decodedArgs).to.be.deep.equal(args);
});
});
describe('Static Bytes', () => {
@@ -1030,6 +1134,33 @@ describe('ABI Encoder: EVM Data Type Encoding/Decoding', () => {
dataType.encode(args, encodingRules);
}).to.throw('Tried to assign 0x010, which is contains a half-byte. Use full bytes only.');
});
it('Should decode NULL to default value - Single Byte (byte)', async () => {
// Create DataType object
const testDataItem = { name: 'Static Byte', type: 'byte' };
const dataType = new AbiEncoder.StaticBytes(testDataItem);
const args = '0x00';
// Decode Encoded Args and validate result
const decodedArgs = dataType.decode(nullEncodedArgs);
expect(decodedArgs).to.be.deep.equal(args);
});
it('Should decode NULL to default value - 4 Bytes (bytes4)', async () => {
// Create DataType object
const testDataItem = { name: 'Static Bytes4', type: 'bytes4' };
const dataType = new AbiEncoder.StaticBytes(testDataItem);
const args = '0x00000000';
// Decode Encoded Args and validate result
const decodedArgs = dataType.decode(nullEncodedArgs);
expect(decodedArgs).to.be.deep.equal(args);
});
it('Should decode NULL to default value - 32 Bytes (bytes32)', async () => {
// Create DataType object
const testDataItem = { name: 'Static Bytes32', type: 'bytes32' };
const dataType = new AbiEncoder.StaticBytes(testDataItem);
const args = '0x0000000000000000000000000000000000000000000000000000000000000000';
// Decode Encoded Args and validate result
const decodedArgs = dataType.decode(nullEncodedArgs);
expect(decodedArgs).to.be.deep.equal(args);
});
});
describe('Dynamic Bytes', () => {
@@ -1117,6 +1248,15 @@ describe('ABI Encoder: EVM Data Type Encoding/Decoding', () => {
dataType.encode(args, encodingRules);
}).to.throw('Tried to assign 0x010, which is contains a half-byte. Use full bytes only.');
});
it('Should decode NULL to empty byte array', async () => {
// Create DataType object
const testDataItem = { name: 'Dynamic Bytes', type: 'bytes' };
const dataType = new AbiEncoder.DynamicBytes(testDataItem);
const args = '0x';
// Decode Encoded Args and validate result
const decodedArgs = dataType.decode(nullEncodedArgs);
expect(decodedArgs).to.be.deep.equal(args);
});
});
describe('String', () => {
@@ -1182,5 +1322,14 @@ describe('ABI Encoder: EVM Data Type Encoding/Decoding', () => {
const argsEncodedFromSignature = dataTypeFromSignature.encode(args);
expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs);
});
it('Should decode NULL to empty string', async () => {
// Create DataType object
const testDataItem = { name: 'String', type: 'string' };
const dataType = new AbiEncoder.String(testDataItem);
// Decode Encoded Args and validate result
const args = '';
const decodedArgs = dataType.decode(nullEncodedArgs);
expect(decodedArgs).to.be.deep.equal(args);
});
});
});