Skip to content
This repository has been archived by the owner on Jul 6, 2024. It is now read-only.

Commit

Permalink
Adding testing for Redis All in One feature (#179)
Browse files Browse the repository at this point in the history
  • Loading branch information
danitseitlin authored Nov 19, 2021
1 parent 06b6b86 commit 9a46d69
Show file tree
Hide file tree
Showing 17 changed files with 266 additions and 353 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ Come and read our documentation [here](https://github.com/danitseitlin/redis-mod
* [RedisAI](https://github.com/danitseitlin/redis-modules-sdk-ts/blob/master/docs/doc.md#-redisai-module)
* [RedisIntervalSets](https://github.com/danitseitlin/redis-modules-sdk-ts/blob/master/docs/doc.md#ris-module)

# Redis "All in One"! :scream:
# (RAIO) Redis "All in One"! :scream:
A class built for integrating more than one Redis module without creating more than one class!
```
const client = new Redis(....);
Expand Down
8 changes: 6 additions & 2 deletions modules/redis-modules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { GraphCommander } from './redisgraph/redisgraph.commander';
import { RejsonCommander } from './rejson/rejson.commander';
import { RedisTimeSeriesCommander } from './rts/rts.commander';
import { RedisearchHelpers } from './redisearch/redisearch.helpers';
import { RedisIntervalSetsHelpers } from './ris/ris.helpers';

export class RedisModules extends Module {
public bloomCommander = new BloomCommander()
Expand All @@ -43,6 +44,7 @@ export class RedisModules extends Module {
public risCommander = new RedisIntervalSetsCommander()
public rtsCommander = new RedisTimeSeriesCommander()
public searchHelpers = new RedisearchHelpers();
public risHelpers = new RedisIntervalSetsHelpers();

/**
* Initializing the module object
Expand Down Expand Up @@ -219,7 +221,8 @@ export type RedisearchMixin = {
search_module_dictadd: typeof Redisearch.prototype.dictadd,
search_module_dictdel: typeof Redisearch.prototype.dictdel,
search_module_dictdump: typeof Redisearch.prototype.dictdump,
search_module_info: typeof Redisearch.prototype.info
search_module_info: typeof Redisearch.prototype.info,
search_module_config: typeof Redisearch.prototype.config
}

/**
Expand Down Expand Up @@ -304,7 +307,8 @@ export type RedisTimeSeriesMixin = {
rts_module_get: typeof RedisTimeSeries.prototype.get,
rts_module_mget: typeof RedisTimeSeries.prototype.mget,
rts_module_info: typeof RedisTimeSeries.prototype.info
rts_module_queryindex: typeof RedisTimeSeries.prototype.queryindex
rts_module_queryindex: typeof RedisTimeSeries.prototype.queryindex,
rts_module_del: typeof RedisTimeSeries.prototype.del
}

/**
Expand Down
2 changes: 1 addition & 1 deletion modules/redisearch/redisearch.commander.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {
FTIndexType, FTSchemaField, FTCreateParameters, FTSearchParameters, FTAggregateParameters, FTFieldType,
FTFieldOptions, FTSugAddParameters, FTSugGetParameters, FTSpellCheck, FTAggregateResponse
FTFieldOptions, FTSugAddParameters, FTSugGetParameters, FTSpellCheck
} from "./redisearch.types";
import { CommandData } from "../module.base";

Expand Down
20 changes: 20 additions & 0 deletions modules/ris/ris.helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { RISSet } from "./ris.types";

export class RedisIntervalSetsHelpers {
/**
* Parsing the iset.get command response
* @param sets The list of sets
*/
parseGet(sets: string[][]): RISSet[] {
const parsedSets: RISSet[] = [];
for(const set of sets) {
if(set.length > 2){
parsedSets.push({name: set[0], minimum: parseInt(set[1]), maximum: parseInt(set[2])})
}
else {
return [{minimum: parseInt(set[0]), maximum: parseInt(set[1])}]
}
}
return parsedSets;
}
}
22 changes: 3 additions & 19 deletions modules/ris/ris.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import * as Redis from 'ioredis';
import { Module, RedisModuleOptions } from '../module.base';
import { RedisIntervalSetsCommander } from './ris.commander';
import { RedisIntervalSetsHelpers } from './ris.helpers';
import { RISSet } from './ris.types';

export class RedisIntervalSets extends Module {

private risHelpers = new RedisIntervalSetsHelpers();
private risCommander = new RedisIntervalSetsCommander();
/**
* Initializing the module object
Expand Down Expand Up @@ -47,7 +48,7 @@ export class RedisIntervalSets extends Module {
async get(key: string, setName?: string): Promise<RISSet[]> {
const command = this.risCommander.get(key, setName);
const response = await this.sendCommand(command);
return this.parseGet(response);
return this.risHelpers.parseGet(response);
}

/**
Expand Down Expand Up @@ -79,21 +80,4 @@ export class RedisIntervalSets extends Module {
const command = this.risCommander.notScore(key, score);
return await this.sendCommand(command);
}

/**
* Parsing the iset.get command response
* @param sets The list of sets
*/
private parseGet(sets: string[][]): RISSet[] {
const parsedSets: RISSet[] = [];
for(const set of sets) {
if(set.length > 2){
parsedSets.push({name: set[0], minimum: parseInt(set[1]), maximum: parseInt(set[2])})
}
else {
return [{minimum: parseInt(set[0]), maximum: parseInt(set[1])}]
}
}
return parsedSets;
}
}
64 changes: 28 additions & 36 deletions tests/redis-ai.ts
Original file line number Diff line number Diff line change
@@ -1,65 +1,57 @@
import { cliArguments } from 'cli-argument-parser';
import { expect } from 'chai'
import { RedisAI } from '../modules/redis-ai/redis-ai';
import * as fs from 'fs';
import { RedisModules } from '../modules/redis-modules';
import { AIModel, AIScript, AIScriptInfo, AITensorInfo } from '../modules/redis-ai/redis-ai.types';
let client: RedisAI;
let redis: RedisModules;

describe('AI testing', async function() {
before(async () => {
client = new RedisAI({
const clientOptions = {
host: cliArguments.host,
port: parseInt(cliArguments.port)
});
redis = new RedisModules({
host: cliArguments.host,
port: parseInt(cliArguments.port),
});
await client.connect();
};
redis = new RedisModules(clientOptions);
await redis.connect();
})
after(async () => {
await client.disconnect();
await redis.disconnect();
})
it('tensorset function', async () => {
let response = await client.tensorset('values-key', 'FLOAT', [2, 2], [1, 2 ,3, 4])
let response = await redis.ai_module_tensorset('values-key', 'FLOAT', [2, 2], [1, 2 ,3, 4])
expect(response).to.eql('OK', 'The response of tensorset')
response = await client.tensorset('blob-key', 'FLOAT', [1], [Buffer.from('1.11111')])
response = await redis.ai_module_tensorset('blob-key', 'FLOAT', [1], [Buffer.from('1.11111')])
expect(response).to.eql('OK', 'The response of tensorset')
});
it('tensorget function', async () => {
let response = await client.tensorget('values-key', 'VALUES', true) as AITensorInfo;
let response = await redis.ai_module_tensorget('values-key', 'VALUES', true) as AITensorInfo;
expect(response.dtype).to.eql('FLOAT', 'The dtype of tensor')
response = await client.tensorget('blob-key', 'BLOB', true) as AITensorInfo
response = await redis.ai_module_tensorget('blob-key', 'BLOB', true) as AITensorInfo
expect(response.dtype).to.eql('FLOAT', 'The dtype of tensor')
response = await redis.ai_module_tensorget('blob-key', 'BLOB', true) as AITensorInfo
expect(response.dtype).to.eql('FLOAT', 'The dtype of tensor')
});
it('modelstore function', async () => {
const file = fs.readFileSync('./tests/data/models/model1.onnx')
const response = await client.modelstore('blob-model', 'ONNX', 'CPU', file)
const response = await redis.ai_module_modelstore('blob-model', 'ONNX', 'CPU', file)
expect(response).to.eql('OK', 'The response of modelset')
});
it('modelget function', async () => {
const modelName = 'blob-model';
const response = await client.modelget('blob-model', true, true) as AIModel;
const response = await redis.ai_module_modelget('blob-model', true, true) as AIModel;
expect(response.device).to.eql('CPU', `The device of key ${modelName}`)
});
it('modelexecute function', async () => {
let response = await client.tensorset('tensorA', 'FLOAT', [1, 2], [2, 3])
response = await client.tensorset('tensorB', 'FLOAT', [1, 2], [3, 5])
let response = await redis.ai_module_tensorset('tensorA', 'FLOAT', [1, 2], [2, 3])
response = await redis.ai_module_tensorset('tensorB', 'FLOAT', [1, 2], [3, 5])
const blob = fs.readFileSync('./tests/data/models/graph.pb');
response = await client.modelstore('mymodel', 'TF', 'CPU', blob, {
response = await redis.ai_module_modelstore('mymodel', 'TF', 'CPU', blob, {
inputs: ['a', 'b'],
inputsCount: 2,
outputs: ['c'],
outputsCount: 1
})
expect(response).to.eql('OK', 'The response of modelstore')
response = await client.modelexecute('mymodel', {
response = await redis.ai_module_modelexecute('mymodel', {
inputs: ['tensorA', 'tensorB'],
outputs: ['tensorC'],
inputsCount: 2,
Expand All @@ -68,31 +60,31 @@ describe('AI testing', async function() {
expect(response).to.eql('OK', 'The response of modelexecute')
});
it('modelscan function', async () => {
const response = await client.modelscan();
const response = await redis.ai_module_modelscan();
expect(response[0][0]).to.eql('mymodel', 'The response of mymodel')
});
it('modeldel function', async () => {
const response = await client.modeldel('blob-model');
const response = await redis.ai_module_modeldel('blob-model');
expect(response).to.eql('OK', 'The response of modeldel')
});
it('scriptset function', async () => {
const scriptFileStr = fs.readFileSync('./tests/data/scripts/script.txt').toString();
const response = await client.scriptset('myscript', {
const response = await redis.ai_module_scriptset('myscript', {
device: 'CPU',
script: scriptFileStr
});
expect(response).to.eql('OK', 'The response of scriptset')
});
it('scriptget function', async () => {
const scriptName = 'myscript'
const response = await client.scriptget(scriptName, true, true) as AIScript;
const response = await redis.ai_module_scriptget(scriptName, true, true) as AIScript;
expect(response.device).to.eql('CPU', `The device of script ${scriptName}`)
});

it('scriptexecute function', async () => {
await client.tensorset('tensorA', 'FLOAT', [1, 2], [2, 3]);
await client.tensorset('tensorB', 'FLOAT', [1, 2], [3, 5]);
const response = await client.scriptexecute('myscript', 'bar', {
await redis.ai_module_tensorset('tensorA', 'FLOAT', [1, 2], [2, 3]);
await redis.ai_module_tensorset('tensorB', 'FLOAT', [1, 2], [3, 5]);
const response = await redis.ai_module_scriptexecute('myscript', 'bar', {
numberOfKeys: 3,
keys: ['tensorA', 'tensorB', 'tensorC'],
numberOfInputs: 2,
Expand All @@ -103,24 +95,24 @@ describe('AI testing', async function() {
expect(response).to.eql('OK', 'The response of scriptexecute')
});
it('scriptscan function', async () => {
const response = await client.scriptscan();
const response = await redis.ai_module_scriptscan();
expect(response[0][0]).to.eql('myscript', 'The response of scriptscan')
});
it('info function', async () => {
const response: AIScriptInfo = await client.info('myscript') as AIScriptInfo;
const response: AIScriptInfo = await redis.ai_module_info('myscript') as AIScriptInfo;
expect(response.key).to.eql('myscript', 'The response of info')
});
it('scriptdel function', async () => {
const response = await client.scriptdel('myscript');
const response = await redis.ai_module_scriptdel('myscript');
expect(response).to.eql('OK', 'The response of scriptdel')
});
it('config function', async () => {
const response = await client.config('/usr/lib/redis/modules/backends/')
const response = await redis.ai_module_config('/usr/lib/redis/modules/backends/')
expect(response).to.eql('OK', 'The response of config')
});
it('dagexecute function', async () => {
await client.tensorset('tensorA', 'FLOAT', [1, 2], [2, 3]);
const response = await client.dagexecute({
await redis.ai_module_tensorset('tensorA', 'FLOAT', [1, 2], [2, 3]);
const response = await redis.ai_module_dagexecute({
type: 'load',
numberOfKeys: 1,
keys: ['tensorA']
Expand All @@ -135,8 +127,8 @@ describe('AI testing', async function() {
], 'The response of dagexecute')
});
it('dagexecuteRO function', async () => {
await client.tensorset('tensorA', 'FLOAT', [1, 2], [2, 3]);
const response = await client.dagexecuteRO({
await redis.ai_module_tensorset('tensorA', 'FLOAT', [1, 2], [2, 3]);
const response = await redis.ai_module_dagexecuteRO({
type: 'load',
numberOfKeys: 1,
keys: ['tensorA']
Expand Down
23 changes: 8 additions & 15 deletions tests/redisbloom-cmk.ts
Original file line number Diff line number Diff line change
@@ -1,57 +1,50 @@
import { cliArguments } from 'cli-argument-parser';
import { expect } from 'chai'
import { RedisBloomCMK } from '../modules/bloom-cmk/redisbloom-cmk';
import { RedisModules } from '../modules/redis-modules';
let client: RedisBloomCMK;
let redis: RedisModules;
const key1 = 'key1cmk'
const key2 = 'key1cmk2';

describe('RedisBloom Count-Min-Sketch filter testing', async function() {
before(async () => {
client = new RedisBloomCMK({
host: cliArguments.host,
port: parseInt(cliArguments.port),
});

redis = new RedisModules({
host: cliArguments.host,
port: parseInt(cliArguments.port),
});
await client.connect();
await redis.connect();
})
after(async () => {
await client.disconnect();
await redis.disconnect();
})

it('initbydim function', async () => {
let response = await client.initbydim('dest', 1, 2);
let response = await redis.bloom_cmk_module_initbydim('dest', 1, 2);
expect(response).to.equal('OK', 'The response of CMS.INITBYDIM command');
response = await client.initbydim(key1, 1, 2);
response = await redis.bloom_cmk_module_initbydim(key1, 1, 2);
expect(response).to.equal('OK', 'The response of CMS.INITBYDIM command');
});
it('initbyprob function', async () => {
const response = await client.initbyprob(key2, 0.001, 0.01);
const response = await redis.bloom_cmk_module_initbyprob(key2, 0.001, 0.01);
expect(response).to.equal('OK', 'The response of CMS.INITBYPROB command');
});
it('incrby function', async () => {
const response = await client.incrby(key1, [{
const response = await redis.bloom_cmk_module_incrby(key1, [{
name: 'foo',
increment: 10
}]);
expect(response[0]).to.equal(10, 'The response of CMS.INCRBY command');
});
it('query function', async () => {
const response = await client.query(key1, ['foo']);
const response = await redis.bloom_cmk_module_query(key1, ['foo']);
expect(response[0]).to.equal(10, 'The response of CMS.QUERY command');
});
it('merge function', async () => {
const response = await client.merge('dest', 1, [key1]);
const response = await redis.bloom_cmk_module_merge('dest', 1, [key1]);
expect(response).to.equal('OK', 'The response of CMS.MERGE command');
});
it('info function', async () => {
const response = await client.info(key1);
const response = await redis.bloom_cmk_module_info(key1);
expect(response[1]).to.equal(1, 'The width of the key');
expect(response[3]).to.equal(2, 'The depth of the key');
expect(response[5]).to.equal(10, 'The count of the key');
Expand Down
Loading

0 comments on commit 9a46d69

Please sign in to comment.