Flesh out the rest of the CRUD tests, update types to string responses

This commit is contained in:
Connor Peet 2017-04-12 10:03:56 -07:00
Родитель e814557902
Коммит 756d2ac3cd
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: CF8FD2EA0DBC61BD
4 изменённых файлов: 172 добавлений и 102 удалений

Просмотреть файл

@ -26,27 +26,29 @@ const indentation = ' ';
const enums = [];
const services = {};
const pbTypes = {
// Built-in types:
double: 'number',
float: 'number',
int32: 'number',
int64: 'number',
uint32: 'number',
uint64: 'number',
sint32: 'number',
sint64: 'number',
fixed32: 'number',
fixed64: 'number',
sfixed32: 'number',
sfixed64: 'number',
const pbTypeAliases = {
bool: 'boolean',
string: 'string',
bytes: 'Buffer',
// Aliases:
Type: 'PermissionType',
};
const numericTypes = [
'double',
'float',
'int32',
'int64',
'uint32',
'uint64',
'sint32',
'sint64',
'fixed32',
'fixed64',
'sfixed32',
'sfixed64',
];
class MessageCollection {
constructor() {
this._messages = {};
@ -83,13 +85,17 @@ function stripPackageNameFrom(name) {
return name;
}
function formatType(type) {
if (type in pbTypes) {
return pbTypes[type];
function formatType(type, isInResponse = false) {
if (type in pbTypeAliases) {
return pbTypeAliases[type];
}
// grpc unmarshals number as strings, but we want to let people provide them as Numbers.
if (numericTypes.includes(type)) {
return isInResponse ? 'string' : 'string | number';
}
type = stripPackageNameFrom(type);
if (enums.includes(type)) {
return type;
}
@ -170,14 +176,14 @@ function generateInterface(node, name) {
fname = formatFieldName(fname);
emit(getCommentPrefixing(fname, getLineContaining(`message ${name}`)));
emit(`${indent(1)}${fname}${message.response ? '' : '?'}: `
+ `${formatType(field.type)}${field.rule === 'repeated' ? '[]' : '' };`);
+ `${formatType(field.type, message.response)}${field.rule === 'repeated' ? '[]' : '' };`);
});
emit('}\n');
}
function generateEnum(node, name) {
enums.push(name);
emit(`export enum ${name in pbTypes ? pbTypes[name] : name} {`);
emit(`export enum ${name in pbTypeAliases ? pbTypeAliases[name] : name} {`);
_.forOwn(node.values, (count, fname) => {
emit(getCommentPrefixing(fname, getLineContaining(`enum ${fname}`)));
emit(`${indent(1)}${fname} = ${count},`);

Просмотреть файл

@ -65,7 +65,7 @@ export abstract class RangeBuilder extends PromiseWrap<RPC.IRangeResponse> {
/**
* revision is the point-in-time of the key-value store to use for the range.
*/
public revision(rev: number): this {
public revision(rev: number | string): this {
this.request.revision = rev;
return this;
}
@ -81,7 +81,7 @@ export abstract class RangeBuilder extends PromiseWrap<RPC.IRangeResponse> {
/**
* minModRevision sets the minimum modified revision of keys to return.
*/
public minModRevision(minModRevision: number): this {
public minModRevision(minModRevision: number | string): this {
this.request.min_mod_revision = minModRevision;
return this;
}
@ -89,7 +89,7 @@ export abstract class RangeBuilder extends PromiseWrap<RPC.IRangeResponse> {
/**
* maxModRevision sets the maximum modified revision of keys to return.
*/
public maxModRevision(maxModRevision: number): this {
public maxModRevision(maxModRevision: number | string): this {
this.request.max_mod_revision = maxModRevision;
return this;
}
@ -97,7 +97,7 @@ export abstract class RangeBuilder extends PromiseWrap<RPC.IRangeResponse> {
/**
* minCreateRevision sets the minimum create revision of keys to return.
*/
public minCreateRevision(minCreateRevision: number): this {
public minCreateRevision(minCreateRevision: number | string): this {
this.request.min_create_revision = minCreateRevision;
return this;
}
@ -105,7 +105,7 @@ export abstract class RangeBuilder extends PromiseWrap<RPC.IRangeResponse> {
/**
* maxCreateRevision sets the maximum create revision of keys to return.
*/
public maxCreateRevision(maxCreateRevision: number): this {
public maxCreateRevision(maxCreateRevision: number | string): this {
this.request.max_create_revision = maxCreateRevision;
return this;
}
@ -209,7 +209,7 @@ export class MultiRangeBuilder extends RangeBuilder {
*/
public count(): Promise<number> {
this.request.count_only = true;
return this.exec().then(res => res.count);
return this.exec().then(res => Number(res.count));
}
/**
@ -300,9 +300,9 @@ export class DeleteBuilder extends PromiseWrap<RPC.IDeleteRangeResponse> {
* key before setting it. One may not always be available if a compaction
* takes place.
*/
public getPrevious(): this {
public getPrevious(): Promise<RPC.IKeyValue[]> {
this.request.prev_kv = true;
return this;
return this.exec().then(res => res.prev_kvs);
}
/**
* exec runs the delete put request.
@ -335,21 +335,11 @@ export class PutBuilder extends PromiseWrap<RPC.IPutResponse> {
* Sets the lease value to use for storing the key. You usually don't
* need to use this directly, use `client.lease()` instead!
*/
public lease(lease: number): this {
public lease(lease: number | string): this {
this.request.lease = lease;
return this;
}
/**
* getPrevious instructs etcd to *try* to get the previous value of the
* key before setting it. One may not always be available if a compaction
* takes place.
*/
public getPrevious(): this {
this.request.prev_kv = true;
return this;
}
/**
* Updates the key on its current lease, regardless of what that lease is.
*/
@ -358,6 +348,16 @@ export class PutBuilder extends PromiseWrap<RPC.IPutResponse> {
return this;
}
/**
* getPrevious instructs etcd to *try* to get the previous value of the
* key before setting it. One may not always be available if a compaction
* takes place.
*/
public getPrevious(): Promise<RPC.IKeyValue & { header: RPC.IResponseHeader }> {
this.request.prev_kv = true;
return this.exec().then(res => ({ ...res.prev_kv, header: res.header }));
}
/**
* Touch updates the key's revision without changing its value. This is
* equivalent to the etcd 'ignore value' flag.

Просмотреть файл

@ -307,19 +307,19 @@ export interface IResponseHeader {
/**
* cluster_id is the ID of the cluster which sent the response.
*/
cluster_id: number;
cluster_id: string;
/**
* member_id is the ID of the member which sent the response.
*/
member_id: number;
member_id: string;
/**
* revision is the key-value store revision when the request was applied.
*/
revision: number;
revision: string;
/**
* raft_term is the raft term when the request was applied.
*/
raft_term: number;
raft_term: string;
}
export enum SortOrder {
@ -357,11 +357,11 @@ export interface IRangeRequest {
/**
* limit is a limit on the number of keys returned for the request. When limit is set to 0,
*/
limit?: number;
limit?: string | number;
/**
* revision is the point-in-time of the key-value store to use for the range.
*/
revision?: number;
revision?: string | number;
/**
* sort_order is the order for returned sorted results.
*/
@ -385,19 +385,19 @@ export interface IRangeRequest {
/**
* min_mod_revision is the lower bound for returned key mod revisions; all keys with
*/
min_mod_revision?: number;
min_mod_revision?: string | number;
/**
* max_mod_revision is the upper bound for returned key mod revisions; all keys with
*/
max_mod_revision?: number;
max_mod_revision?: string | number;
/**
* min_create_revision is the lower bound for returned key create revisions; all keys with
*/
min_create_revision?: number;
min_create_revision?: string | number;
/**
* max_create_revision is the upper bound for returned key create revisions; all keys with
*/
max_create_revision?: number;
max_create_revision?: string | number;
}
export interface IRangeResponse {
@ -413,7 +413,7 @@ export interface IRangeResponse {
/**
* kvs is empty when count is requested.
*/
count: number;
count: string;
}
export interface IPutRequest {
@ -428,7 +428,7 @@ export interface IPutRequest {
/**
* lease is the lease ID to associate with the key in the key-value store. A lease
*/
lease?: number;
lease?: string | number;
/**
* If prev_kv is set, etcd gets the previous key-value pair before changing it.
*/
@ -471,7 +471,7 @@ export interface IDeleteRangeResponse {
/**
* deleted is the number of keys deleted by the delete range request.
*/
deleted: number;
deleted: string;
/**
* if prev_kv is set in the request, the previous key-value pairs will be returned.
*/
@ -520,15 +520,15 @@ export interface ICompare {
/**
* version is the version of the given key
*/
version?: number;
version?: string | number;
/**
* create_revision is the creation revision of the given key
*/
create_revision?: number;
create_revision?: string | number;
/**
* mod_revision is the last modified revision of the given key.
*/
mod_revision?: number;
mod_revision?: string | number;
/**
* target is the key-value field to inspect for the comparison.
*/
@ -566,7 +566,7 @@ export interface ICompactionRequest {
/**
* revision is the key-value store revision for the compaction operation.
*/
revision?: number;
revision?: string | number;
/**
* physical is set so the RPC will wait until the compaction is physically
*/
@ -582,7 +582,7 @@ export interface IHashResponse {
/**
* hash is the hash value computed from the responding member's key-value store.
*/
hash: number;
hash: string;
}
export interface ISnapshotResponse {
@ -593,7 +593,7 @@ export interface ISnapshotResponse {
/**
* remaining_bytes is the number of blob bytes to be sent after this message
*/
remaining_bytes: number;
remaining_bytes: string;
/**
* remaining_bytes is the number of blob bytes to be sent after this message
*/
@ -628,7 +628,7 @@ export interface IWatchCreateRequest {
/**
* start_revision is an optional revision to watch from (inclusive). No start_revision is "now".
*/
start_revision?: number;
start_revision?: string | number;
/**
* progress_notify is set so that the etcd server will periodically send a WatchResponse with
*/
@ -647,7 +647,7 @@ export interface IWatchCancelRequest {
/**
* watch_id is the watcher id to cancel so that no more events are transmitted.
*/
watch_id?: number;
watch_id?: string | number;
}
export interface IWatchResponse {
@ -655,7 +655,7 @@ export interface IWatchResponse {
/**
* watch_id is the ID of the watcher that corresponds to the response.
*/
watch_id: number;
watch_id: string;
/**
* created is set to true if the response is for a create watch request.
*/
@ -667,7 +667,7 @@ export interface IWatchResponse {
/**
* compact_revision is set to the minimum index if a watcher tries to watch
*/
compact_revision: number;
compact_revision: string;
/**
* The client should record the watch_id and expect to receive events for
*/
@ -675,11 +675,11 @@ export interface IWatchResponse {
}
export interface ILeaseGrantRequest {
ttl?: number;
ttl?: string | number;
/**
* alarm is the type of alarm to consider for this request.
*/
id?: number;
id?: string | number;
}
export interface ILeaseGrantResponse {
@ -687,8 +687,8 @@ export interface ILeaseGrantResponse {
/**
* alarm is the type of alarm to consider for this request.
*/
id: number;
ttl: number;
id: string;
ttl: string;
error: string;
}
@ -696,7 +696,7 @@ export interface ILeaseRevokeRequest {
/**
* alarm is the type of alarm to consider for this request.
*/
id?: number;
id?: string | number;
}
export interface ILeaseRevokeResponse {
@ -707,7 +707,7 @@ export interface ILeaseKeepAliveRequest {
/**
* alarm is the type of alarm to consider for this request.
*/
id?: number;
id?: string | number;
}
export interface ILeaseKeepAliveResponse {
@ -715,15 +715,15 @@ export interface ILeaseKeepAliveResponse {
/**
* alarm is the type of alarm to consider for this request.
*/
id: number;
ttl: number;
id: string;
ttl: string;
}
export interface ILeaseTimeToLiveRequest {
/**
* alarm is the type of alarm to consider for this request.
*/
id?: number;
id?: string | number;
/**
* keys is true to query all the keys attached to this lease.
*/
@ -735,9 +735,9 @@ export interface ILeaseTimeToLiveResponse {
/**
* alarm is the type of alarm to consider for this request.
*/
id: number;
ttl: number;
granted_ttl: number;
id: string;
ttl: string;
granted_ttl: string;
/**
* Keys is the list of keys attached to this lease.
*/
@ -748,7 +748,7 @@ export interface IMember {
/**
* alarm is the type of alarm to consider for this request.
*/
id: number;
id: string;
/**
* name is the human-readable name of the member. If the member is not started, the name will be an empty string.
*/
@ -773,7 +773,7 @@ export interface IMemberRemoveRequest {
/**
* alarm is the type of alarm to consider for this request.
*/
id?: number;
id?: string | number;
}
export interface IMemberRemoveResponse {
@ -784,7 +784,7 @@ export interface IMemberUpdateRequest {
/**
* alarm is the type of alarm to consider for this request.
*/
id?: number;
id?: string | number;
peer_ur_ls?: string[];
}
@ -826,7 +826,7 @@ export interface IAlarmRequest {
* action is the kind of alarm request to issue. The action
*/
action?: AlarmAction;
member_id?: number;
member_id?: string | number;
/**
* action is the kind of alarm request to issue. The action
*/
@ -834,7 +834,7 @@ export interface IAlarmRequest {
}
export interface IAlarmMember {
member_id: number;
member_id: string;
/**
* memberID is the ID of the member associated with the raised alarm.
*/
@ -855,13 +855,13 @@ export interface IStatusResponse {
* version is the cluster protocol version used by the responding member.
*/
version: string;
db_size: number;
db_size: string;
/**
* leader is the member ID which the responding member believes is the current leader.
*/
leader: number;
raft_index: number;
raft_term: number;
leader: string;
raft_index: string;
raft_term: string;
}
export interface IAuthenticateRequest {
@ -1065,15 +1065,15 @@ export interface IKeyValue {
/**
* min_create_revision is the lower bound for returned key create revisions; all keys with
*/
create_revision: number;
create_revision: string;
/**
* min_mod_revision is the lower bound for returned key mod revisions; all keys with
*/
mod_revision: number;
mod_revision: string;
/**
* version is the version of the given key
*/
version: number;
version: string;
/**
* Range gets the keys in the range from the key-value store.
*/
@ -1081,7 +1081,7 @@ export interface IKeyValue {
/**
* LeaseGrant creates a lease which expires if the server does not receive a keepAlive
*/
lease: number;
lease: string;
}
export enum EventType {

Просмотреть файл

@ -18,23 +18,87 @@ describe('connection pool', () => {
afterEach(() => client.delete().all());
it('lists all values', async () => {
expect(await client.getAll().strings()).to.containSubset(['bar1', 'bar2', 'bar5']);
describe('get() / getAll()', () => {
it('lists all values', async () => {
expect(await client.getAll().strings()).to.containSubset(['bar1', 'bar2', 'bar5']);
});
it('gets single keys with various encoding', async () => {
expect(await client.get('foo1').string()).to.equal('bar1');
expect(await client.get('foo2').buffer()).to.deep.equal(Buffer.from('bar2'));
expect(await client.get('foo3').json()).to.deep.equal({ value: 'bar3' });
expect(await client.get('wut').string()).to.be.null;
});
it('queries prefixes', async () => {
expect(await client.getAll().prefix('foo').strings())
.to.have.members(['bar1', 'bar2', '{"value":"bar3"}']);
});
it('gets keys', async () => {
expect(await client.getAll().keys()).to.have.members(['foo1', 'foo2', 'foo3', 'baz']);
});
it('counts', async () => {
expect(await client.getAll().count()).to.equal(4);
});
it('sorts', async () => {
expect(await client.getAll()
.prefix('foo')
.sort('key', 'asc')
.limit(2)
.keys(),
).to.deep.equal(['foo1', 'foo2']);
expect(await client.getAll()
.prefix('foo')
.sort('key', 'desc')
.limit(2)
.keys(),
).to.deep.equal(['foo3', 'foo2']);
});
});
it('gets single keys with various encoding', async () => {
expect(await client.get('foo1').string()).to.equal('bar1');
expect(await client.get('foo2').buffer()).to.deep.equal(Buffer.from('bar2'));
expect(await client.get('foo3').json()).to.deep.equal({ value: 'bar3' });
expect(await client.get('wut').string()).to.be.null;
});
describe('delete()', () => {
it('deletes all', async () => {
await client.delete().all();
expect(await client.getAll().count()).to.equal(0);
});
it('queries prefixes', async () => {
expect(await client.getAll().prefix('foo').strings())
.to.have.members(['bar1', 'bar2', '{"value":"bar3"}']);
});
it('deletes prefix', async () => {
await client.delete().prefix('foo');
expect(await client.getAll().keys()).to.deep.equal(['baz']);
});
it('gets keys', async () => {
expect(await client.getAll().keys()).to.have.members(['foo1', 'foo2', 'foo3', 'baz']);
it('gets previous', async () => {
expect(await client.delete().key('foo1').getPrevious()).to.containSubset([
{
key: new Buffer('foo1'),
value: new Buffer('bar1'),
},
]);
});
describe('put()', () => {
it('allows touching key revisions', async () => {
const original = (await client.get('foo1').exec()).kvs[0].mod_revision;
await client.put('foo1').touch();
const updated = (await client.get('foo1').exec()).kvs[0].mod_revision;
expect(Number(updated)).to.be.greaterThan(Number(original));
});
it('updates key values', async () => {
await client.put('foo1').value('updated');
expect(await client.get('foo1').string()).to.equal('updated');
});
it('includes previous values', async () => {
expect(await client.put('foo1').value('updated').getPrevious()).to.containSubset({
key: new Buffer('foo1'),
value: new Buffer('bar1'),
});
});
});
});
});