Skip to content

Commit c73186d

Browse files
committed
churn(test) WIP update various commands to work with 8
1 parent b7f4ea6 commit c73186d

10 files changed

+286
-190
lines changed

packages/client/lib/commands/GEOPOS.spec.ts

+133-5
Original file line numberDiff line numberDiff line change
@@ -32,21 +32,149 @@ describe('GEOPOS', () => {
3232

3333
testUtils.testAll('geoPos with member', async client => {
3434
const coordinates = {
35-
longitude: '-122.06429868936538696',
36-
latitude: '37.37749628831998194'
35+
longitude: '-122.06429868936539',
36+
latitude: '37.37749628831998'
3737
};
3838

3939
await client.geoAdd('key', {
4040
member: 'member',
4141
...coordinates
4242
});
4343

44-
assert.deepEqual(
45-
await client.geoPos('key', 'member'),
46-
[coordinates]
44+
const result = await client.geoPos('key', 'member');
45+
46+
/**
47+
* - Redis < 8: Returns coordinates with 14 decimal places (e.g., "-122.06429868936539")
48+
* - Redis 8+: Returns coordinates with 17 decimal places (e.g., "-122.06429868936538696")
49+
*
50+
*/
51+
const PRECISION = 13; // Number of decimal places to compare
52+
53+
assert.ok(result.length === 1, 'Expected one result');
54+
55+
assert.ok(
56+
compareWithPrecision(result[0].longitude, coordinates.longitude, PRECISION),
57+
`Longitude mismatch: ${result[0].longitude} vs ${coordinates.longitude}`
58+
);
59+
assert.ok(
60+
compareWithPrecision(result[0].latitude, coordinates.latitude, PRECISION),
61+
`Latitude mismatch: ${result[0].latitude} vs ${coordinates.latitude}`
4762
);
4863
}, {
4964
client: GLOBAL.SERVERS.OPEN,
5065
cluster: GLOBAL.CLUSTERS.OPEN
5166
});
5267
});
68+
69+
describe('compareWithPrecision', () => {
70+
it('should match exact same numbers', () => {
71+
assert.strictEqual(
72+
compareWithPrecision('123.456789', '123.456789', 6),
73+
true
74+
);
75+
});
76+
77+
it('should match when actual has more precision than needed', () => {
78+
assert.strictEqual(
79+
compareWithPrecision('123.456789123456', '123.456789', 6),
80+
true
81+
);
82+
});
83+
84+
it('should match when expected has more precision than needed', () => {
85+
assert.strictEqual(
86+
compareWithPrecision('123.456789', '123.456789123456', 6),
87+
true
88+
);
89+
});
90+
91+
it('should fail when decimals differ within precision', () => {
92+
assert.strictEqual(
93+
compareWithPrecision('123.456689', '123.456789', 6),
94+
false
95+
);
96+
});
97+
98+
it('should handle negative numbers', () => {
99+
assert.strictEqual(
100+
compareWithPrecision('-122.06429868936538', '-122.06429868936539', 13),
101+
true
102+
);
103+
});
104+
105+
it('should fail when integer parts differ', () => {
106+
assert.strictEqual(
107+
compareWithPrecision('124.456789', '123.456789', 6),
108+
false
109+
);
110+
});
111+
112+
it('should handle zero decimal places', () => {
113+
assert.strictEqual(
114+
compareWithPrecision('123.456789', '123.456789', 0),
115+
true
116+
);
117+
});
118+
119+
it('should handle numbers without decimal points', () => {
120+
assert.strictEqual(
121+
compareWithPrecision('123', '123', 6),
122+
true
123+
);
124+
});
125+
126+
it('should handle one number without decimal point', () => {
127+
assert.strictEqual(
128+
compareWithPrecision('123', '123.000', 3),
129+
false
130+
);
131+
});
132+
133+
it('should match Redis coordinates with different precision', () => {
134+
assert.strictEqual(
135+
compareWithPrecision(
136+
'-122.06429868936538696',
137+
'-122.06429868936539',
138+
13
139+
),
140+
true
141+
);
142+
});
143+
144+
it('should match Redis latitude with different precision', () => {
145+
assert.strictEqual(
146+
compareWithPrecision(
147+
'37.37749628831998194',
148+
'37.37749628831998',
149+
14
150+
),
151+
true
152+
);
153+
});
154+
});
155+
156+
// Helper function to compare with fixed decimal places
157+
const compareWithPrecision = (actual, expected, decimals) => {
158+
const actualDotIndex = actual.indexOf('.');
159+
const expectedDotIndex = expected.indexOf('.');
160+
161+
// If either number doesn't have a decimal point
162+
if (actualDotIndex === -1 || expectedDotIndex === -1) {
163+
// If both don't have decimal points, compare directly
164+
if (actualDotIndex === -1 && expectedDotIndex === -1) {
165+
return actual === expected;
166+
}
167+
// If only one has a decimal point, add .000... to the other
168+
const withoutDecimal = actualDotIndex === -1 ? actual : expected;
169+
const withDecimal = actualDotIndex === -1 ? expected : actual;
170+
return compareWithPrecision(withoutDecimal + '.0', withDecimal, decimals);
171+
}
172+
173+
const integerPart = actual.slice(0, actualDotIndex);
174+
const decimalPart = actual.slice(actualDotIndex + 1, actualDotIndex + 1 + decimals);
175+
176+
const expectedIntegerPart = expected.slice(0, expectedDotIndex);
177+
const expectedDecimalPart = expected.slice(expectedDotIndex + 1, expectedDotIndex + 1 + decimals);
178+
179+
return integerPart === expectedIntegerPart && decimalPart === expectedDecimalPart;
180+
};

packages/search/lib/commands/INFO.spec.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,14 @@ describe('INFO', () => {
2424
index_name: 'index',
2525
index_options: [],
2626
index_definition: Object.create(null, {
27-
default_score: {
27+
28+
indexes_all: {
29+
value: 'false',
30+
configurable: true,
31+
enumerable: true
32+
},
33+
34+
default_score: {
2835
value: '1',
2936
configurable: true,
3037
enumerable: true

packages/search/lib/commands/PROFILE_AGGREGATE.spec.ts

+39-15
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,43 @@ describe('PROFILE AGGREGATE', () => {
3131
});
3232
});
3333

34-
testUtils.testWithClient('client.ft.search', async client => {
35-
await Promise.all([
36-
client.ft.create('index', {
37-
field: SCHEMA_FIELD_TYPE.NUMERIC
38-
}),
39-
client.hSet('1', 'field', '1'),
40-
client.hSet('2', 'field', '2')
41-
]);
42-
43-
const res = await client.ft.profileAggregate('index', '*');
44-
assert.deepEqual('None', res.profile.warning);
45-
assert.ok(typeof res.profile.iteratorsProfile.counter === 'number');
46-
assert.ok(typeof res.profile.parsingTime === 'string');
47-
assert.ok(res.results.total == 1);
48-
}, GLOBAL.SERVERS.OPEN);
34+
testUtils.testWithClient('client.ft.search', async client => {
35+
await Promise.all([
36+
client.ft.create('index', {
37+
field: SCHEMA_FIELD_TYPE.NUMERIC
38+
}),
39+
client.hSet('1', 'field', '1'),
40+
client.hSet('2', 'field', '2')
41+
]);
42+
43+
44+
const normalizeObject = obj => JSON.parse(JSON.stringify(obj));
45+
const res = await client.ft.profileAggregate('index', '*');
46+
47+
assert.deepEqual(
48+
normalizeObject({
49+
results: {
50+
total: 1,
51+
results: [{}, {}]
52+
},
53+
profile: [
54+
'Shards',
55+
[[
56+
'Total profile time', '0',
57+
'Parsing time', '0',
58+
'Pipeline creation time', '0',
59+
'Warning', 'None',
60+
'Iterators profile',
61+
['Type', 'WILDCARD', 'Time', '0', 'Counter', 2],
62+
'Result processors profile',
63+
[['Type', 'Index', 'Time', '0', 'Counter', 2]]
64+
]],
65+
'Coordinator',
66+
[]
67+
]
68+
}),
69+
normalizeObject(res)
70+
);
71+
72+
}, GLOBAL.SERVERS.OPEN);
4973
});
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,38 @@
11
import { CommandParser } from '@redis/client/dist/lib/client/parser';
2-
import { Command, ReplyUnion } from "@redis/client/dist/lib/RESP/types";
3-
import AGGREGATE, { AggregateRawReply, FtAggregateOptions, parseAggregateOptions } from "./AGGREGATE";
4-
import { ProfileOptions, ProfileRawReply, ProfileReply, transformProfile } from "./PROFILE_SEARCH";
5-
2+
import { Command, ReplyUnion, Resp2Reply, UnwrapReply } from '@redis/client/dist/lib/RESP/types';
3+
import AGGREGATE, { AggregateRawReply, FtAggregateOptions, parseAggregateOptions } from './AGGREGATE';
4+
import { ProfileOptions, ProfileRawReply, ProfileReply, } from './PROFILE_SEARCH';
5+
export interface TransformReplyType {
6+
2: (reply: UnwrapReply<Resp2Reply<ProfileRawReply<AggregateRawReply>>>) => ProfileReply;
7+
3: () => ReplyUnion;
8+
}
69
export default {
710
NOT_KEYED_COMMAND: true,
8-
IS_READ_ONLY: true,
9-
parseCommand(
10-
parser: CommandParser,
11-
index: string,
12-
query: string,
13-
options?: ProfileOptions & FtAggregateOptions
14-
) {
15-
parser.push('FT.PROFILE', index, 'AGGREGATE');
16-
17-
if (options?.LIMITED) {
18-
parser.push('LIMITED');
19-
}
20-
21-
parser.push('QUERY', query);
11+
IS_READ_ONLY: true,
12+
parseCommand(
13+
parser: CommandParser,
14+
index: string,
15+
query: string,
16+
options?: ProfileOptions & FtAggregateOptions
17+
) {
18+
parser.push('FT.PROFILE', index, 'AGGREGATE');
2219

23-
parseAggregateOptions(parser, options)
24-
},
25-
transformReply: {
26-
2: (reply: ProfileAggeregateRawReply): ProfileReply => {
27-
return {
28-
results: AGGREGATE.transformReply[2](reply[0]),
29-
profile: transformProfile(reply[1])
30-
}
31-
},
32-
3: undefined as unknown as () => ReplyUnion
33-
},
34-
unstableResp3: true
35-
} as const satisfies Command;
20+
if (options?.LIMITED) {
21+
parser.push('LIMITED');
22+
}
3623

37-
type ProfileAggeregateRawReply = ProfileRawReply<AggregateRawReply>;
24+
parser.push('QUERY', query);
25+
26+
parseAggregateOptions(parser, options)
27+
},
28+
transformReply: {
29+
2: (reply: UnwrapReply<Resp2Reply<ProfileRawReply<AggregateRawReply>>>): ProfileReply => {
30+
return {
31+
results: AGGREGATE.transformReply[2](reply[0]),
32+
profile: reply[1]
33+
}
34+
},
35+
3: undefined as unknown as () => ReplyUnion
36+
} as TransformReplyType,
37+
unstableResp3: true
38+
} as const satisfies Command;

packages/search/lib/commands/PROFILE_SEARCH.spec.ts

+45-14
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,49 @@ describe('PROFILE SEARCH', () => {
2727
});
2828
});
2929

30-
testUtils.testWithClient('client.ft.search', async client => {
31-
await Promise.all([
32-
client.ft.create('index', {
33-
field: SCHEMA_FIELD_TYPE.NUMERIC
34-
}),
35-
client.hSet('1', 'field', '1')
36-
]);
37-
38-
const res = await client.ft.profileSearch('index', '*');
39-
assert.strictEqual('None', res.profile.warning);
40-
assert.ok(typeof res.profile.iteratorsProfile.counter === 'number');
41-
assert.ok(typeof res.profile.parsingTime === 'string');
42-
assert.ok(res.results.total == 1);
43-
}, GLOBAL.SERVERS.OPEN);
30+
testUtils.testWithClient('client.ft.search', async client => {
31+
await Promise.all([
32+
client.ft.create('index', {
33+
field: SCHEMA_FIELD_TYPE.NUMERIC
34+
}),
35+
client.hSet('1', 'field', '1')
36+
]);
37+
38+
const normalizeObject = obj => JSON.parse(JSON.stringify(obj));
39+
40+
const res = await client.ft.profileSearch('index', '*');
41+
assert.deepEqual(
42+
normalizeObject({
43+
results: {
44+
total: 1,
45+
documents: [{
46+
id: "1",
47+
value: {
48+
field: "1"
49+
}
50+
}]
51+
},
52+
profile: [
53+
"Shards",
54+
[[
55+
"Total profile time", "0",
56+
"Parsing time", "0",
57+
"Pipeline creation time", "0",
58+
"Warning", "None",
59+
"Iterators profile", ["Type", "WILDCARD", "Time", "0", "Counter", 1],
60+
"Result processors profile", [
61+
["Type", "Index", "Time", "0", "Counter", 1],
62+
["Type", "Scorer", "Time", "0", "Counter", 1],
63+
["Type", "Sorter", "Time", "0", "Counter", 1],
64+
["Type", "Loader", "Time", "0", "Counter", 1]
65+
]
66+
]],
67+
"Coordinator",
68+
[]
69+
]
70+
}),
71+
normalizeObject(res)
72+
);
73+
74+
}, GLOBAL.SERVERS.OPEN);
4475
});

0 commit comments

Comments
 (0)