Skip to content

Commit 90e7a4b

Browse files
avifeneshcyip10
authored andcommitted
HOT-FIX: CRITICAL - fixed set command optional arguments and added tests to set command (valkey-io#1508)
fixed set command optional arguments and added tests to set command
1 parent 242b4f1 commit 90e7a4b

File tree

3 files changed

+220
-64
lines changed

3 files changed

+220
-64
lines changed

node/src/Commands.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,13 +145,13 @@ export function createSet(
145145
if (options.expiry === "keepExisting") {
146146
args.push("KEEPTTL");
147147
} else if (options.expiry?.type === "seconds") {
148-
args.push("EX " + options.expiry.count);
148+
args.push("EX", options.expiry.count.toString());
149149
} else if (options.expiry?.type === "milliseconds") {
150-
args.push("PX " + options.expiry.count);
150+
args.push("PX", options.expiry.count.toString());
151151
} else if (options.expiry?.type === "unixSeconds") {
152-
args.push("EXAT " + options.expiry.count);
152+
args.push("EXAT", options.expiry.count.toString());
153153
} else if (options.expiry?.type === "unixMilliseconds") {
154-
args.push("PXAT " + options.expiry.count);
154+
args.push("PXAT", options.expiry.count.toString());
155155
}
156156
}
157157

node/tests/RedisClientInternals.test.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -524,12 +524,13 @@ describe("SocketConnectionInternals", () => {
524524
throw new Error("no args");
525525
}
526526

527-
expect(args.length).toEqual(5);
527+
expect(args.length).toEqual(6);
528528
expect(args[0]).toEqual("foo");
529529
expect(args[1]).toEqual("bar");
530530
expect(args[2]).toEqual("XX");
531531
expect(args[3]).toEqual("GET");
532-
expect(args[4]).toEqual("EX 10");
532+
expect(args[4]).toEqual("EX");
533+
expect(args[5]).toEqual("10");
533534
sendResponse(socket, ResponseType.OK, request.callbackIdx);
534535
});
535536
const request1 = connection.set("foo", "bar", {
@@ -538,7 +539,7 @@ describe("SocketConnectionInternals", () => {
538539
expiry: { type: "seconds", count: 10 },
539540
});
540541

541-
await expect(await request1).toMatch("OK");
542+
expect(await request1).toMatch("OK");
542543
});
543544
});
544545

node/tests/SharedTests.ts

Lines changed: 212 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -165,63 +165,6 @@ export function runBaseTests<Context>(config: {
165165
config.timeout,
166166
);
167167

168-
it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])(
169-
`set with return of old value works_%p`,
170-
async (protocol) => {
171-
await runTest(async (client: BaseClient) => {
172-
const key = uuidv4();
173-
// Adding random repetition, to prevent the inputs from always having the same alignment.
174-
const value = uuidv4() + "0".repeat(Math.random() * 7);
175-
176-
let result = await client.set(key, value);
177-
expect(result).toEqual("OK");
178-
179-
result = await client.set(key, "", {
180-
returnOldValue: true,
181-
});
182-
expect(result).toEqual(value);
183-
184-
result = await client.get(key);
185-
expect(result).toEqual("");
186-
}, protocol);
187-
},
188-
config.timeout,
189-
);
190-
191-
it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])(
192-
`conditional set works_%p`,
193-
async (protocol) => {
194-
await runTest(async (client: BaseClient) => {
195-
const key = uuidv4();
196-
// Adding random repetition, to prevent the inputs from always having the same alignment.
197-
const value = uuidv4() + "0".repeat(Math.random() * 7);
198-
let result = await client.set(key, value, {
199-
conditionalSet: "onlyIfExists",
200-
});
201-
expect(result).toEqual(null);
202-
203-
result = await client.set(key, value, {
204-
conditionalSet: "onlyIfDoesNotExist",
205-
});
206-
expect(result).toEqual("OK");
207-
expect(await client.get(key)).toEqual(value);
208-
209-
result = await client.set(key, "foobar", {
210-
conditionalSet: "onlyIfDoesNotExist",
211-
});
212-
expect(result).toEqual(null);
213-
214-
result = await client.set(key, "foobar", {
215-
conditionalSet: "onlyIfExists",
216-
});
217-
expect(result).toEqual("OK");
218-
219-
expect(await client.get(key)).toEqual("foobar");
220-
}, protocol);
221-
},
222-
config.timeout,
223-
);
224-
225168
it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])(
226169
`custom command works_%p`,
227170
async (protocol) => {
@@ -2527,6 +2470,218 @@ export function runBaseTests<Context>(config: {
25272470
},
25282471
config.timeout,
25292472
);
2473+
2474+
// Set command tests
2475+
2476+
async function setWithExpiryOptions(client: BaseClient) {
2477+
const key = uuidv4();
2478+
const value = uuidv4();
2479+
const setResWithExpirySetMilli = await client.set(key, value, {
2480+
expiry: {
2481+
type: "milliseconds",
2482+
count: 500,
2483+
},
2484+
});
2485+
expect(setResWithExpirySetMilli).toEqual("OK");
2486+
const getWithExpirySetMilli = await client.get(key);
2487+
expect(getWithExpirySetMilli).toEqual(value);
2488+
2489+
const setResWithExpirySec = await client.set(key, value, {
2490+
expiry: {
2491+
type: "seconds",
2492+
count: 1,
2493+
},
2494+
});
2495+
expect(setResWithExpirySec).toEqual("OK");
2496+
const getResWithExpirySec = await client.get(key);
2497+
expect(getResWithExpirySec).toEqual(value);
2498+
2499+
const setWithUnixSec = await client.set(key, value, {
2500+
expiry: {
2501+
type: "unixSeconds",
2502+
count: 1,
2503+
},
2504+
});
2505+
expect(setWithUnixSec).toEqual("OK");
2506+
const getWithUnixSec = await client.get(key);
2507+
expect(getWithUnixSec).toEqual(value);
2508+
2509+
const setResWithExpiryKeep = await client.set(key, value, {
2510+
expiry: "keepExisting",
2511+
});
2512+
expect(setResWithExpiryKeep).toEqual("OK");
2513+
const getResWithExpiryKeep = await client.get(key);
2514+
expect(getResWithExpiryKeep).toEqual(value);
2515+
// wait for the key to expire base on the previous set
2516+
setTimeout(() => {}, 1000);
2517+
const getResExpire = await client.get(key);
2518+
// key should have expired
2519+
expect(getResExpire).toEqual(null);
2520+
2521+
const setResWithExpiryWithUmilli = await client.set(key, value, {
2522+
expiry: {
2523+
type: "unixMilliseconds",
2524+
count: 2,
2525+
},
2526+
});
2527+
expect(setResWithExpiryWithUmilli).toEqual("OK");
2528+
// wait for the key to expire
2529+
setTimeout(() => {}, 3);
2530+
const getResWithExpiryWithUmilli = await client.get(key);
2531+
// key should have expired
2532+
expect(getResWithExpiryWithUmilli).toEqual(null);
2533+
}
2534+
2535+
async function setWithOnlyIfExistOptions(client: BaseClient) {
2536+
const key = uuidv4();
2537+
const value = uuidv4();
2538+
const setExistingKeyRes = await client.set(key, value, {
2539+
conditionalSet: "onlyIfExists",
2540+
});
2541+
expect(setExistingKeyRes).toEqual("OK");
2542+
const getExistingKeyRes = await client.get(key);
2543+
expect(getExistingKeyRes).toEqual(value);
2544+
2545+
const notExistingKeyRes = await client.set(key, value + "1", {
2546+
conditionalSet: "onlyIfExists",
2547+
});
2548+
// key does not exist, so it should not be set
2549+
expect(notExistingKeyRes).toEqual(null);
2550+
const getNotExistingKey = await client.get(key);
2551+
// key should not have been set
2552+
expect(getNotExistingKey).toEqual(null);
2553+
}
2554+
2555+
async function setWithOnlyIfNotExistOptions(client: BaseClient) {
2556+
const key = uuidv4();
2557+
const value = uuidv4();
2558+
const notExistingKeyRes = await client.set(key, value, {
2559+
conditionalSet: "onlyIfDoesNotExist",
2560+
});
2561+
// key does not exist, so it should be set
2562+
expect(notExistingKeyRes).toEqual("OK");
2563+
const getNotExistingKey = await client.get(key);
2564+
// key should have been set
2565+
expect(getNotExistingKey).toEqual(value);
2566+
2567+
const existingKeyRes = await client.set(key, value, {
2568+
conditionalSet: "onlyIfDoesNotExist",
2569+
});
2570+
// key exists, so it should not be set
2571+
expect(existingKeyRes).toEqual(null);
2572+
const getExistingKey = await client.get(key);
2573+
// key should not have been set
2574+
expect(getExistingKey).toEqual(value);
2575+
}
2576+
2577+
async function setWithGetOldOptions(client: BaseClient) {
2578+
const key = uuidv4();
2579+
const value = uuidv4();
2580+
2581+
const setResGetNotExistOld = await client.set(key, value, {
2582+
returnOldValue: true,
2583+
});
2584+
// key does not exist, so old value should be null
2585+
expect(setResGetNotExistOld).toEqual(null);
2586+
// key should have been set
2587+
const getResGetNotExistOld = await client.get(key);
2588+
expect(getResGetNotExistOld).toEqual(value);
2589+
2590+
const setResGetExistOld = await client.set(key, value, {
2591+
returnOldValue: true,
2592+
});
2593+
// key exists, so old value should be returned
2594+
expect(setResGetExistOld).toEqual(value);
2595+
// key should have been set
2596+
const getResGetExistOld = await client.get(key);
2597+
expect(getResGetExistOld).toEqual(value);
2598+
}
2599+
2600+
async function setWithAllOptions(client: BaseClient) {
2601+
const key = uuidv4();
2602+
const value = uuidv4();
2603+
2604+
const setResWithAllOptions = await client.set(key, value, {
2605+
expiry: {
2606+
type: "unixSeconds",
2607+
count: 1,
2608+
},
2609+
conditionalSet: "onlyIfExists",
2610+
returnOldValue: true,
2611+
});
2612+
// key does not exist, so old value should be null
2613+
expect(setResWithAllOptions).toEqual(null);
2614+
// key should have been set
2615+
const getResWithAllOptions = await client.get(key);
2616+
expect(getResWithAllOptions).toEqual(value);
2617+
2618+
// wait for the key to expire
2619+
setTimeout(() => {}, 1000);
2620+
// key should have expired
2621+
const gettResWithAllOptions = await client.get(key);
2622+
expect(gettResWithAllOptions).toEqual(null);
2623+
}
2624+
2625+
async function testSetWithAllCombination(client: BaseClient) {
2626+
const key = uuidv4();
2627+
const value = uuidv4();
2628+
const count = 1;
2629+
const expiryCombination = [
2630+
"keepExisting",
2631+
{ type: "seconds", count },
2632+
{ type: "milliseconds", count },
2633+
{ type: "unixSeconds", count },
2634+
{ type: "unixMilliseconds", count },
2635+
undefined,
2636+
];
2637+
const conditionalSetCombination = [
2638+
"onlyIfExists",
2639+
"onlyIfDoesNotExist",
2640+
undefined,
2641+
];
2642+
const returnOldValueCombination = [true, false, undefined];
2643+
2644+
for (const expiryVal of expiryCombination) {
2645+
for (const conditionalSetVal of conditionalSetCombination) {
2646+
for (const returnOldValueVal of returnOldValueCombination) {
2647+
const setRes = await client.set(key, value, {
2648+
expiry: expiryVal as
2649+
| "keepExisting"
2650+
| {
2651+
type:
2652+
| "seconds"
2653+
| "milliseconds"
2654+
| "unixSeconds"
2655+
| "unixMilliseconds";
2656+
count: number;
2657+
}
2658+
| undefined,
2659+
conditionalSet: conditionalSetVal as
2660+
| "onlyIfExists"
2661+
| "onlyIfDoesNotExist"
2662+
| undefined,
2663+
returnOldValue: returnOldValueVal,
2664+
});
2665+
expect(setRes).not.toBeNull();
2666+
}
2667+
}
2668+
}
2669+
}
2670+
2671+
it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])(
2672+
"Set commands with options test_%p",
2673+
async (protocol) => {
2674+
await runTest(async (client: BaseClient) => {
2675+
await setWithExpiryOptions(client);
2676+
await setWithOnlyIfExistOptions(client);
2677+
await setWithOnlyIfNotExistOptions(client);
2678+
await setWithGetOldOptions(client);
2679+
await setWithAllOptions(client);
2680+
await testSetWithAllCombination(client);
2681+
}, protocol);
2682+
},
2683+
config.timeout,
2684+
);
25302685
}
25312686

25322687
export function runCommonTests<Context>(config: {

0 commit comments

Comments
 (0)