mirror of
https://github.com/dolthub/dolt.git
synced 2026-02-12 02:58:53 -06:00
Add more detailed error information when writing the wrong type (#1202)
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@attic/noms",
|
||||
"version": "7.6.1",
|
||||
"version": "7.6.2",
|
||||
"main": "dist/commonjs/noms.js",
|
||||
"jsnext:main": "dist/es6/noms.js",
|
||||
"dependencies": {
|
||||
|
||||
16
js/src/describe-type.js
Normal file
16
js/src/describe-type.js
Normal file
@@ -0,0 +1,16 @@
|
||||
// @flow
|
||||
|
||||
import {ValueBase} from './value.js';
|
||||
|
||||
export default function describeType(v: any): string {
|
||||
const t = typeof v;
|
||||
if (t === 'object') {
|
||||
if (v === null) {
|
||||
return 'null';
|
||||
}
|
||||
if (v instanceof ValueBase) {
|
||||
return v.type.describe();
|
||||
}
|
||||
}
|
||||
return t;
|
||||
}
|
||||
@@ -9,13 +9,28 @@ import RefValue from './ref-value.js';
|
||||
import {newStruct} from './struct.js';
|
||||
import type {NomsKind} from './noms-kind.js';
|
||||
import {encodeNomsValue, JsonArrayWriter} from './encode.js';
|
||||
import {Field, makeCompoundType, makeEnumType, makePrimitiveType, makeStructType, makeType, Type,}
|
||||
from './type.js';
|
||||
import {
|
||||
blobType,
|
||||
boolType,
|
||||
Field,
|
||||
float64Type,
|
||||
int8Type,
|
||||
makeCompoundType,
|
||||
makeEnumType,
|
||||
makeListType,
|
||||
makeMapType,
|
||||
makePrimitiveType,
|
||||
makeSetType,
|
||||
makeStructType,
|
||||
makeType,
|
||||
stringType,
|
||||
Type,
|
||||
} from './type.js';
|
||||
import {IndexedMetaSequence, MetaTuple} from './meta-sequence.js';
|
||||
import {Kind} from './noms-kind.js';
|
||||
import {ListLeafSequence, NomsList} from './list.js';
|
||||
import {MapLeafSequence, NomsMap} from './map.js';
|
||||
import {NomsSet, SetLeafSequence} from './set.js';
|
||||
import {newList, ListLeafSequence, NomsList} from './list.js';
|
||||
import {newMap, MapLeafSequence, NomsMap} from './map.js';
|
||||
import {newSet, NomsSet, SetLeafSequence} from './set.js';
|
||||
import {Package, registerPackage} from './package.js';
|
||||
import {newBlob} from './blob.js';
|
||||
import DataStore from './data-store.js';
|
||||
@@ -434,4 +449,60 @@ suite('Encode', () => {
|
||||
|
||||
assert.deepEqual([Kind.Ref, Kind.Blob, ref.toString()], w.array);
|
||||
});
|
||||
|
||||
test('type errors', async () => {
|
||||
const ds = new DataStore(new MemoryStore());
|
||||
const w = new JsonArrayWriter(ds);
|
||||
|
||||
const test = (et, at, t, v) => {
|
||||
try {
|
||||
w.writeTopLevel(t, v);
|
||||
} catch (ex) {
|
||||
assert.equal(ex.message, `Failed to write ${et}. Invalid type: ${at}`);
|
||||
return;
|
||||
}
|
||||
assert.ok(false, `Expected error, 'Failed to write ${et}. Invalid type: ${at}' but Got none`);
|
||||
};
|
||||
|
||||
test('Int8', 'string', int8Type, 'hi');
|
||||
test('Float64', 'string', float64Type, 'hi');
|
||||
test('Bool', 'string', boolType, 'hi');
|
||||
test('Blob', 'string', blobType, 'hi');
|
||||
|
||||
test('String', 'number', stringType, 42);
|
||||
test('Bool', 'number', boolType, 42);
|
||||
test('Blob', 'number', blobType, 42);
|
||||
|
||||
test('Int8', 'boolean', int8Type, true);
|
||||
test('Float64', 'boolean', float64Type, true);
|
||||
test('String', 'boolean', stringType, true);
|
||||
test('Blob', 'boolean', blobType, true);
|
||||
|
||||
const blob = await newBlob(new Uint8Array([0, 1]));
|
||||
test('Int8', 'Blob', int8Type, blob);
|
||||
test('Float64', 'Blob', float64Type, blob);
|
||||
test('String', 'Blob', stringType, blob);
|
||||
test('Bool', 'Blob', boolType, blob);
|
||||
|
||||
const list = await newList([0, 1], makeListType(int8Type));
|
||||
test('Int8', 'List<Int8>', int8Type, list);
|
||||
test('Float64', 'List<Int8>', float64Type, list);
|
||||
test('String', 'List<Int8>', stringType, list);
|
||||
test('Bool', 'List<Int8>', boolType, list);
|
||||
test('Blob', 'List<Int8>', blobType, list);
|
||||
|
||||
const map = await newMap(['zero', 1], makeMapType(stringType, int8Type));
|
||||
test('Int8', 'Map<String, Int8>', int8Type, map);
|
||||
test('Float64', 'Map<String, Int8>', float64Type, map);
|
||||
test('String', 'Map<String, Int8>', stringType, map);
|
||||
test('Bool', 'Map<String, Int8>', boolType, map);
|
||||
test('Blob', 'Map<String, Int8>', blobType, map);
|
||||
|
||||
const set = await newSet([0, 1], makeSetType(int8Type));
|
||||
test('Int8', 'Set<Int8>', int8Type, set);
|
||||
test('Float64', 'Set<Int8>', float64Type, set);
|
||||
test('String', 'Set<Int8>', stringType, set);
|
||||
test('Bool', 'Set<Int8>', boolType, set);
|
||||
test('Blob', 'Set<Int8>', blobType, set);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -18,6 +18,7 @@ import {NomsSet, SetLeafSequence} from './set.js';
|
||||
import {Sequence} from './sequence.js';
|
||||
import {setEncodeNomsValue} from './get-ref.js';
|
||||
import {NomsBlob, BlobLeafSequence} from './blob.js';
|
||||
import describeType from './describe-type.js';
|
||||
|
||||
const typedTag = 't ';
|
||||
|
||||
@@ -118,7 +119,8 @@ export class JsonArrayWriter {
|
||||
writeValue(v: any, t: Type, pkg: ?Package) {
|
||||
switch (t.kind) {
|
||||
case Kind.Blob:
|
||||
invariant(v instanceof NomsBlob || v instanceof Sequence);
|
||||
invariant(v instanceof NomsBlob || v instanceof Sequence,
|
||||
`Failed to write Blob. Invalid type: ${describeType(v)}`);
|
||||
const sequence: Sequence = v instanceof NomsBlob ? v.sequence : v;
|
||||
|
||||
if (this.maybeWriteMetaSequence(sequence, t, pkg)) {
|
||||
@@ -129,11 +131,18 @@ export class JsonArrayWriter {
|
||||
this.writeBlob(sequence);
|
||||
break;
|
||||
case Kind.Bool:
|
||||
invariant(typeof v === 'boolean', `Failed to write Bool. Invalid type: ${describeType(v)}`);
|
||||
this.write(v);
|
||||
break;
|
||||
case Kind.String:
|
||||
invariant(typeof v === 'string',
|
||||
`Failed to write String. Invalid type: ${describeType(v)}`);
|
||||
this.write(v);
|
||||
break;
|
||||
case Kind.Float32:
|
||||
case Kind.Float64:
|
||||
invariant(typeof v === 'number',
|
||||
`Failed to write ${t.describe()}. Invalid type: ${describeType(v)}`);
|
||||
this.writeFloat(v); // TODO: Verify value fits in type
|
||||
break;
|
||||
case Kind.Uint8:
|
||||
@@ -144,10 +153,13 @@ export class JsonArrayWriter {
|
||||
case Kind.Int16:
|
||||
case Kind.Int32:
|
||||
case Kind.Int64:
|
||||
invariant(typeof v === 'number',
|
||||
`Failed to write ${t.describe()}. Invalid type: ${describeType(v)}`);
|
||||
this.writeInt(v); // TODO: Verify value fits in type
|
||||
break;
|
||||
case Kind.List: {
|
||||
invariant(v instanceof NomsList || v instanceof Sequence);
|
||||
invariant(v instanceof NomsList || v instanceof Sequence,
|
||||
`Failed to write List. Invalid type: ${describeType(v)}`);
|
||||
const sequence: Sequence = v instanceof NomsList ? v.sequence : v;
|
||||
|
||||
if (this.maybeWriteMetaSequence(sequence, t, pkg)) {
|
||||
@@ -162,7 +174,8 @@ export class JsonArrayWriter {
|
||||
break;
|
||||
}
|
||||
case Kind.Map: {
|
||||
invariant(v instanceof NomsMap || v instanceof Sequence);
|
||||
invariant(v instanceof NomsMap || v instanceof Sequence,
|
||||
`Failed to write Map. Invalid type: ${describeType(v)}`);
|
||||
const sequence: Sequence = v instanceof NomsMap ? v.sequence : v;
|
||||
|
||||
if (this.maybeWriteMetaSequence(sequence, t, pkg)) {
|
||||
@@ -181,7 +194,8 @@ export class JsonArrayWriter {
|
||||
break;
|
||||
}
|
||||
case Kind.Package: {
|
||||
invariant(v instanceof Package);
|
||||
invariant(v instanceof Package,
|
||||
`Failed to write Package. Invalid type: ${describeType(v)}`);
|
||||
const ptr = makePrimitiveType(Kind.Type);
|
||||
const w2 = new JsonArrayWriter(this._ds);
|
||||
v.types.forEach(type => w2.writeValue(type, ptr, pkg));
|
||||
@@ -192,12 +206,14 @@ export class JsonArrayWriter {
|
||||
break;
|
||||
}
|
||||
case Kind.Ref: {
|
||||
invariant(v instanceof RefValue);
|
||||
invariant(v instanceof RefValue,
|
||||
`Failed to write Ref. Invalid type: ${describeType(v)}`);
|
||||
this.writeRef(v.targetRef);
|
||||
break;
|
||||
}
|
||||
case Kind.Set: {
|
||||
invariant(v instanceof NomsSet || v instanceof Sequence);
|
||||
invariant(v instanceof NomsSet || v instanceof Sequence,
|
||||
`Failed to write Set. Invalid type: ${describeType(v)}`);
|
||||
const sequence: Sequence = v instanceof NomsSet ? v.sequence : v;
|
||||
|
||||
if (this.maybeWriteMetaSequence(sequence, t, pkg)) {
|
||||
@@ -216,7 +232,8 @@ export class JsonArrayWriter {
|
||||
break;
|
||||
}
|
||||
case Kind.Type: {
|
||||
invariant(v instanceof Type);
|
||||
invariant(v instanceof Type,
|
||||
`Failed to write Type. Invalid type: ${describeType(v)}`);
|
||||
this.writeTypeAsValue(v);
|
||||
break;
|
||||
}
|
||||
@@ -310,11 +327,13 @@ export class JsonArrayWriter {
|
||||
const typeDef = pkg.types[t.ordinal];
|
||||
switch (typeDef.kind) {
|
||||
case Kind.Enum:
|
||||
invariant(typeof v === 'number');
|
||||
invariant(typeof v === 'number',
|
||||
`Failed to write ${typeDef.describe()}. Invalid type: ${describeType(v)}`);
|
||||
this.writeEnum(v);
|
||||
break;
|
||||
case Kind.Struct: {
|
||||
invariant(v instanceof Struct);
|
||||
invariant(v instanceof Struct,
|
||||
`Failed to write ${typeDef.describe()}. Invalid type: ${describeType(v)}`);
|
||||
this.writeStruct(v, t, typeDef, pkg);
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user