Cleanups & expand tests (#1330)

* Vote cleanups & tests

* VecFixed with tests & bugfixes
This commit is contained in:
Jaco Greeff
2019-08-21 14:14:46 +02:00
committed by GitHub
parent 501b8f8ba1
commit 6d2c2bb8a1
6 changed files with 111 additions and 30 deletions
+6
View File
@@ -109,6 +109,12 @@ describe('Vec', (): void => {
vector.reduce((r, e): string => `${r}${e}`, '')
).toEqual('123345456756789');
});
it('exposes a working indexOf', (): void => {
expect(vector.indexOf('1')).toEqual(0);
expect(vector.indexOf(new Text('23'))).toEqual(1);
expect(vector.indexOf('0')).toEqual(-1);
});
});
describe('encode', (): void => {
+36
View File
@@ -0,0 +1,36 @@
// Copyright 2017-2019 @polkadot/types authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import Text from '../primitive/Text';
import VecFixed from './VecFixed';
describe('VecFixed', (): void => {
describe('construction', (): void => {
it('constructs via empty', (): void => {
expect(new VecFixed(Text, 2).toHex()).toEqual('0x0000');
});
it('constructs via Uint8Array', (): void => {
expect(new VecFixed(Text, 2, new Uint8Array([0x00, 0x04, 0x31])).toHex()).toEqual('0x000431');
});
});
describe('utils', (): void => {
let test: VecFixed<Text>;
beforeEach((): void => {
test = new (VecFixed.with(Text, 5))(['1', '2', '3', undefined, '5']);
});
it('has a sane string types', (): void => {
expect(test.toRawType()).toEqual('[Text;5]');
expect(test.Type).toEqual('Text');
});
it('has a correct toHex', (): void => {
// each entry length 1 << 2, char as hex (0x31 === `1`), one empty
expect(test.toHex()).toEqual('0x043104320433000435');
});
});
});
+7 -3
View File
@@ -54,17 +54,21 @@ export default class VecFixed<T extends Codec> extends AbstractArray<T> {
* @description The type for the items
*/
public get Type (): string {
return this._Type.name;
return new this._Type().toRawType();
}
public toU8a (): Uint8Array {
return super.toU8a(true);
// we override, we don't add the length prefix for outselves, and at the same time we
// ignore isBare on entries, since they should be properly encoded at all times
const encoded = this.map((entry): Uint8Array => entry.toU8a());
return u8aConcat(...encoded);
}
/**
* @description Returns the base runtime type name for this instance
*/
public toRawType (): string {
return `[${new this._Type().toRawType()};${this.length}`;
return `[${this.Type};${this.length}]`;
}
}
@@ -16,11 +16,4 @@ export default class Origin extends Null {
throw new Error('Origin should not be constructed, it is only a placeholder for compatibility');
}
/**
* @description Returns the base runtime type name for this instance
*/
public toRawType (): string {
return 'Origin'; // yes, we cannot instantiate, but for consistency
}
}
@@ -41,6 +41,25 @@ describe('Vote', (): void => {
it('is Nay for 0', (): void => {
expect(new Vote(0).isNay).toBe(true);
});
it('constructs via empty', (): void => {
expect(new Vote().isNay).toBe(true);
});
it('constructs via Uint8Array (empty)', (): void => {
expect(new Vote(new Uint8Array()).isNay).toBe(true);
});
it('constructs via Uint8Array (nay)', (): void => {
expect(new Vote(new Uint8Array([1])).isNay).toBe(true);
});
it('constructs via Uint8Array (aye)', (): void => {
const test = new Vote(new Uint8Array([0b10000010]));
expect(test.isNay).toBe(false);
expect(test.conviction.toString()).toEqual('Locked2x');
});
});
describe('Vote with conviction', (): void => {
@@ -100,6 +119,13 @@ describe('Vote', (): void => {
).toEqual('Locked2x');
});
it('Conviction getter works with raw boolean and no conviction', (): void => {
const test = new Vote({ aye: true });
expect(test.isAye).toEqual(true);
expect(test.conviction.toString()).toEqual('None');
});
it('isAye getter works', (): void => {
expect(
new Vote({
@@ -118,4 +144,10 @@ describe('Vote', (): void => {
.toEqual(false);
});
});
describe('utils', (): void => {
it('has a sane toRawType', (): void => {
expect(new Vote().toRawType()).toEqual('Vote');
});
});
});
+30 -20
View File
@@ -4,12 +4,18 @@
import { Conviction } from '../../interfaces/democracy';
import { isBoolean, isNumber, isObject, isU8a, isUndefined } from '@polkadot/util';
import { isBoolean, isNumber, isU8a, isUndefined } from '@polkadot/util';
import { createType } from '../../codec/create';
import U8aFixed from '../../codec/U8aFixed';
import Bool from '../Bool';
// eslint-disable-next-line @typescript-eslint/ban-types
type InputTypes = boolean | number | Boolean | Uint8Array | {
aye: boolean;
conviction?: number | ('None' | 'Locked1x' | 'Locked2x' | 'Locked3x' | 'Locked4x' | 'Locked5x');
};
// For votes, the topmost bit indicated aye/nay, the lower bits indicate the conviction
const AYE_BITS = 0b10000000;
const NAY_BITS = 0b00000000;
@@ -26,7 +32,7 @@ export default class Vote extends U8aFixed {
private _conviction: Conviction;
public constructor (value?: any) {
public constructor (value?: InputTypes) {
// decoded is just 1 byte
// Aye: Most Significant Bit
// Conviction: 0000 - 0101
@@ -38,29 +44,33 @@ export default class Vote extends U8aFixed {
this._conviction = createType('Conviction', decoded[0] & CON_MASK);
}
private static decodeVote (value?: any): Uint8Array {
private static decodeVote (value?: InputTypes): Uint8Array {
if (isUndefined(value)) {
return new Uint8Array([NAY_BITS]);
} else if (isBoolean(value)) {
return value
? new Uint8Array([AYE_BITS | DEF_CONV])
: new Uint8Array([NAY_BITS]);
} else if (value instanceof Boolean) {
return Vote.decodeVote(value.valueOf());
return Vote.decodeVoteBool(false);
} else if (value instanceof Boolean || isBoolean(value)) {
return Vote.decodeVoteBool(new Bool(value).isTrue);
} else if (isNumber(value)) {
return Vote.decodeVote(value < 0);
return Vote.decodeVoteBool(value < 0);
} else if (isU8a(value)) {
return value.length
? value.subarray(0, 1)
: new Uint8Array([NAY_BITS]);
} else if (isObject(value)) {
const vote = new Bool(value.aye).eq(true) ? AYE_BITS : NAY_BITS;
const conviction = createType('Conviction', isUndefined(value.conviction) ? DEF_CONV : value.conviction);
return new Uint8Array([vote | conviction.index]);
return Vote.decodeVoteU8a(value);
}
throw new Error(`Unable to convert input ${value} to Vote`);
const vote = new Bool(value.aye).isTrue ? AYE_BITS : NAY_BITS;
const conviction = createType('Conviction', isUndefined(value.conviction) ? DEF_CONV : value.conviction);
return new Uint8Array([vote | conviction.index]);
}
private static decodeVoteBool (value: boolean): Uint8Array {
return value
? new Uint8Array([AYE_BITS | DEF_CONV])
: new Uint8Array([NAY_BITS]);
}
private static decodeVoteU8a (value: Uint8Array): Uint8Array {
return value.length
? value.subarray(0, 1)
: new Uint8Array([NAY_BITS]);
}
/**