Skip to content

Commit

Permalink
Fixes for latest redis-doc (#328)
Browse files Browse the repository at this point in the history
Fixes #324 

Supersedes #327

Fixes/patches required:

- update SET command (redis/redis-doc#1232 still getting no love. I will take that PR to my grave I guess)
- disable redis v7 commands/options tests
- disable non-deterministic command tests (hrandfield etc.)
  • Loading branch information
mmkal committed Sep 17, 2021
1 parent f3f38d3 commit 49744d9
Show file tree
Hide file tree
Showing 45 changed files with 23,081 additions and 2,916 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
services:
redis:
image: redis:6.0.9
image: redis:6.2.4
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
Expand Down
136 changes: 71 additions & 65 deletions codegen/__tests__/generate-client.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { overloads, formatOverloads } from "../generate-client";
import { overloads, formatOverloads as _formatOverloads } from "../generate-client";
import { schema } from "..";
import { format } from "../util";
import { flow } from "lodash";

const formatOverloads = flow(_formatOverloads, overloads =>
format({ content: `interface Overloads { ${overloads.join("\n")} }` })
);

test("overloads", () => {
expect(
Expand All @@ -22,71 +28,71 @@ test("overloads", () => {

test("formatOverloads", () => {
expect(formatOverloads("LATENCY RESET", schema["LATENCY RESET"])).toMatchInlineSnapshot(`
Array [
"
/**
* Reset latency data for one or more events.
* - _group_: server
* - _complexity_: undefined
* - _since_: 2.8.13
*
* [Full docs](https://redis.io/commands/latency-reset)
*/
latency(latency_subcommand: \\"RESET\\", ...event: Array<string>):
Result<unknown, Context>
",
]
"interface Overloads {
/**
* Reset latency data for one or more events.
* - _group_: server
* - _since_: 2.8.13
*
* [Full docs](https://redis.io/commands/latency-reset)
*/
latency(latency_subcommand: \\"RESET\\", ...event: Array<string>): Result<unknown, Context>;
}
"
`);
expect(formatOverloads("SET", schema.SET)).toMatchInlineSnapshot(`
Array [
"
/**
* Set the string value of a key
* - _group_: string
* - _complexity_: O(1)
* - _since_: 1.0.0
*
* [Full docs](https://redis.io/commands/set)
*/
set(key: string, value: string, get?: \\"GET\\"):
Result<(\\"OK\\") | (string) | (null), Context>
",
"
/**
* Set the string value of a key
* - _group_: string
* - _complexity_: O(1)
* - _since_: 1.0.0
*
* [Full docs](https://redis.io/commands/set)
*/
set(key: string, value: string, condition?: \\"NX\\"|\\"XX\\", get?: \\"GET\\"):
Result<(\\"OK\\") | (string) | (null), Context>
",
"
/**
* Set the string value of a key
* - _group_: string
* - _complexity_: O(1)
* - _since_: 1.0.0
*
* [Full docs](https://redis.io/commands/set)
*/
set(key: string, value: string, expiration?: ([ex_px: (\\"EX\\"|\\"PX\\"), number: (number)]) | (\\"KEEPTTL\\"), get?: \\"GET\\"):
Result<(\\"OK\\") | (string) | (null), Context>
",
"
/**
* Set the string value of a key
* - _group_: string
* - _complexity_: O(1)
* - _since_: 1.0.0
*
* [Full docs](https://redis.io/commands/set)
*/
set(key: string, value: string, expiration?: ([ex_px: (\\"EX\\"|\\"PX\\"), number: (number)]) | (\\"KEEPTTL\\"), condition?: \\"NX\\"|\\"XX\\", get?: \\"GET\\"):
Result<(\\"OK\\") | (string) | (null), Context>
",
]
"interface Overloads {
/**
* Set the string value of a key
* - _group_: string
* - _complexity_: O(1)
* - _since_: 1.0.0
*
* [Full docs](https://redis.io/commands/set)
*/
set(key: string, value: string, get?: \\"GET\\"): Result<\\"OK\\" | string | null, Context>;
/**
* Set the string value of a key
* - _group_: string
* - _complexity_: O(1)
* - _since_: 1.0.0
*
* [Full docs](https://redis.io/commands/set)
*/
set(key: string, value: string, condition?: \\"NX\\" | \\"XX\\", get?: \\"GET\\"): Result<\\"OK\\" | string | null, Context>;
/**
* Set the string value of a key
* - _group_: string
* - _complexity_: O(1)
* - _since_: 1.0.0
*
* [Full docs](https://redis.io/commands/set)
*/
set(
key: string,
value: string,
expiration?: [ex_px_exat_pxat: \\"EX\\" | \\"PX\\" | \\"EXAT\\" | \\"PXAT\\", number: number] | \\"KEEPTTL\\",
get?: \\"GET\\"
): Result<\\"OK\\" | string | null, Context>;
/**
* Set the string value of a key
* - _group_: string
* - _complexity_: O(1)
* - _since_: 1.0.0
*
* [Full docs](https://redis.io/commands/set)
*/
set(
key: string,
value: string,
expiration?: [ex_px_exat_pxat: \\"EX\\" | \\"PX\\" | \\"EXAT\\" | \\"PXAT\\", number: number] | \\"KEEPTTL\\",
condition?: \\"NX\\" | \\"XX\\",
get?: \\"GET\\"
): Result<\\"OK\\" | string | null, Context>;
}
"
`);
});
14 changes: 7 additions & 7 deletions codegen/__tests__/generate-tests.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ describe("toArgs", () => {
Object {
"command": "set",
"context": Array [
"decoding set overload 0 (key,value): { name: 'key', schema: { title: 'key', type: 'string' } },{ name: 'value', schema: { title: 'value', type: 'string' } }",
"decoding set overload 0 (key,value): {name:'key',schema:{title:'key',type:'string'}},{name:'value',schema:{title:'value',type:'string'}}",
"foo successfully decoded as key (string). Decoded value foo. Tokens remaining [bar,WRONG,123], target args remainin count: 1",
"bar successfully decoded as value (string). Decoded value bar. Tokens remaining [WRONG,123], target args remainin count: 0",
"Tokens remain but no target args left! Tokens: WRONG,123",
Expand Down Expand Up @@ -78,7 +78,7 @@ describe("toArgs", () => {
Object {
"command": "setbit",
"context": Array [
"decoding setbit overload 0 (key,offset,value): { name: 'key', schema: { title: 'key', type: 'string' } },{ name: 'offset', schema: { title: 'offset', type: 'integer' } },{ name: 'value', schema: { title: 'value', type: 'integer' } }",
"decoding setbit overload 0 (key,offset,value): {name:'key',schema:{title:'key',type:'string'}},{name:'offset',schema:{title:'offset',type:'integer'}},{name:'value',schema:{title:'value',type:'integer'}}",
"foo successfully decoded as key (string). Decoded value foo. Tokens remaining [1.2,34], target args remainin count: 2",
"1.2 isn't an integer. Decoded as something different: 1",
],
Expand All @@ -91,7 +91,7 @@ describe("toArgs", () => {
Object {
"command": "setbit",
"context": Array [
"decoding setbit overload 0 (key,offset,value): { name: 'key', schema: { title: 'key', type: 'string' } },{ name: 'offset', schema: { title: 'offset', type: 'integer' } },{ name: 'value', schema: { title: 'value', type: 'integer' } }",
"decoding setbit overload 0 (key,offset,value): {name:'key',schema:{title:'key',type:'string'}},{name:'offset',schema:{title:'offset',type:'integer'}},{name:'value',schema:{title:'value',type:'integer'}}",
"foo successfully decoded as key (string). Decoded value foo. Tokens remaining [not_an_integer,34], target args remainin count: 2",
"not_an_integer isn't an integer. Decoded as something different: NaN",
],
Expand Down Expand Up @@ -207,7 +207,7 @@ describe("potential future edge cases", () => {
expect(decoded).toMatchInlineSnapshot(`
Object {
"context": Array [
"Not smart enough to deal with { name: 'testarg', schema: { type: 'thistypedoesnotreallyexist' } } yet",
"Not smart enough to deal with {name:'testarg',schema:{type:'thistypedoesnotreallyexist'}} yet",
],
"error": true,
"tokens": Array [
Expand All @@ -223,7 +223,7 @@ describe("potential future edge cases", () => {
expect(decoded).toMatchInlineSnapshot(`
Object {
"context": Array [
"Not smart enough to deal with { name: 'testarg', schema: { type: 'object' } } yet",
"Not smart enough to deal with {name:'testarg',schema:{type:'object'}} yet",
],
"error": true,
"tokens": Array [
Expand Down Expand Up @@ -254,7 +254,7 @@ describe("potential future edge cases", () => {
Object {
"context": Array [
"Decoding array item",
"Not smart enough to deal with { name: 'testarg', schema: { type: 'thistypedoesnotreallyexist' } } yet",
"Not smart enough to deal with {name:'testarg',schema:{type:'thistypedoesnotreallyexist'}} yet",
],
"error": true,
"tokens": Array [
Expand Down Expand Up @@ -284,7 +284,7 @@ describe("potential future edge cases", () => {
expect(decoded).toMatchInlineSnapshot(`
Object {
"context": Array [
"Target args remain but no tokens left! Target args [ { name: 'testarg', schema: { type: 'array', items: { type: 'string' } } } ]",
"Target args remain but no tokens left! Target args [{name:'testarg',schema:{type:'array',items:{type:'string'}}}]",
],
"error": true,
}
Expand Down
21 changes: 18 additions & 3 deletions codegen/__tests__/util.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,27 @@ test("writeFile still writes when prettier failes", () => {
expect(mockWarn.mock.calls).toEqual([[expect.stringMatching(/.*this.*is a syntax error/)]]);
});

test("maybe do", () => {
test("maybe do", async () => {
const mock = jest.fn();
const error = jest.spyOn(console, "error").mockImplementation(() => {});
const exit = jest.spyOn(process, "exit").mockImplementation((() => {}) as any);

maybeDo(false, mock);
await maybeDo(false, mock);
expect(mock).toHaveBeenCalledTimes(0);
expect(exit).not.toHaveBeenCalled();

maybeDo(true, mock);
jest.clearAllMocks();

await maybeDo(true, mock);
expect(mock).toHaveBeenCalledTimes(1);
expect(exit).toHaveBeenCalledWith(0);

jest.clearAllMocks();

mock.mockRejectedValue(Error("foo"));

await maybeDo(true, mock);
expect(mock).toHaveBeenCalledTimes(1);
expect(error).toHaveBeenCalledTimes(1);
expect(exit).toHaveBeenCalledWith(1);
});
12 changes: 9 additions & 3 deletions codegen/generate-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,18 @@ export const formatOverloads = (fullCommand: string, { arguments: originalArgs,
return !betterAlternativeExists;
})
.map(val => {
const bullets = [
["group", spec.group],
["complexity", spec.complexity],
["since", spec.since],
];
return `
/**
* ${spec.summary}
* - _group_: ${spec.group}
* - _complexity_: ${spec.complexity}
* - _since_: ${spec.since}
${bullets
.filter(e => e[1])
.map(e => `* - _${e[0]}_: ${e[1]}`)
.join("\n")}
*
* [Full docs](https://redis.io/commands/${lo.kebabCase(fullCommand)})
*/
Expand Down
7 changes: 2 additions & 5 deletions codegen/generate-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import * as glob from "glob";
import * as path from "path";
import * as fs from "fs";
import { overloads as getOverloads } from "./generate-client";
import { inspect } from "util";
import { maybeDo, writeFile } from "./util";
import { parseArgsStringToArgv } from "string-argv";
import { fixupGeneratedTests } from "./patches/tests";
import { fixMarkdownExampleLine } from "./patches/markdown";
import * as lo from "lodash";
import * as jsonSchema from "json-schema";
import * as ESON from "eson-parser";

const extractCliExamples = (markdown: string) => {
const eolMarker = " END_OF_LINE_MARKER ";
Expand Down Expand Up @@ -51,10 +51,7 @@ const tokenizeCliExample = (ex: ExtractedCliExample) => ({
.map(original => ({ original, argv: parseArgsStringToArgv(original) })),
});

const print = (val: unknown) =>
inspect(val, { breakLength: 1000, depth: 1000 })
.replace(/, toString: \[Function\]/g, "")
.replace(/\r?\n[ \t]*/g, " ");
const print = (val: unknown) => ESON.stringify(val);

export const toArgs = (tokens: string[]) => {
const [command, ...args] = tokens;
Expand Down
7 changes: 6 additions & 1 deletion codegen/patches/__tests__/schema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,25 @@ test("detected generic arrays", () => {
fixArrayRepliesManually(schema);

expect(warn.mock.calls.map(([c]) => c).join("\n")).toMatchInlineSnapshot(`
"COMMAND has a generic array return type
"BITFIELD_RO has a generic array return type
COMMAND has a generic array return type
GEORADIUS has a generic array return type
GEOSEARCH has a generic array return type
HELLO has a generic array return type
HGETALL has a generic array return type
PUBSUB has a generic array return type
ROLE has a generic array return type
SMISMEMBER has a generic array return type
SORT_RO has a generic array return type
ZDIFF has a generic array return type
ZINTER has a generic array return type
ZUNION has a generic array return type
XRANGE has a generic array return type
XREVRANGE has a generic array return type
XREAD has a generic array return type
XREADGROUP has a generic array return type
XCLAIM has a generic array return type
XAUTOCLAIM has a generic array return type
XPENDING has a generic array return type"
`);
});
Expand Down
36 changes: 33 additions & 3 deletions codegen/patches/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,38 @@ export const fixupSchema = (schema: Record<string, JsonSchemaCommand>) => {

/** https://github.com/redis/redis-doc/pull/1232 */
function fixSetEnum(schema: Record<string, JsonSchemaCommand>) {
/**
* was:
* {
"name": "expiration",
"type": "enum",
"enum": [
"EX seconds",
"PX milliseconds",
"KEEPTTL"
],
"optional": true
},
now:
{
"name": "expiration",
"type": "enum",
"enum": [
"EX seconds",
"PX milliseconds",
"EXAT timestamp",
"PXAT milliseconds-timestamp",
"KEEPTTL"
],
"optional": true
},
*/
const badSetArg = schema.SET.arguments.find(
a => a.name === "expiration" && a.schema.enum!.join(",") === "EX seconds,PX milliseconds,KEEPTTL"
a =>
a.name === "expiration" &&
a.schema.enum!.join(",") === "EX seconds,PX milliseconds,EXAT timestamp,PXAT milliseconds-timestamp,KEEPTTL"
)!;
// this will throw if the SET schema has changed (see `!` on line above). If that's the case, maybe the
// issue was fixed and this can be deleted?
Expand All @@ -25,8 +55,8 @@ function fixSetEnum(schema: Record<string, JsonSchemaCommand>) {
{
type: "array",
items: [
// format: `["EX", 123]` or `["PX", 123]`
{ type: "string", enum: ["EX", "PX"] },
// format: `["EX", 123]` or `["PX", 123]` or `["EXAT", 1631875021]` or `["PXAT", 1631875021160]`
{ type: "string", enum: ["EX", "PX", "EXAT", "PXAT"] },
{ type: "number" },
],
},
Expand Down

0 comments on commit 49744d9

Please sign in to comment.