diff --git a/.github/workflows/lint-rust/action.yml b/.github/workflows/lint-rust/action.yml index 3801f9b23c..154c30a7d8 100644 --- a/.github/workflows/lint-rust/action.yml +++ b/.github/workflows/lint-rust/action.yml @@ -22,17 +22,19 @@ runs: sudo apt install protobuf-compiler shell: bash - - run: cargo fmt --manifest-path ${{ inputs.cargo-toml-folder }}/Cargo.toml --all -- --check + - run: cargo fmt --all -- --check + working-directory: ${{ inputs.cargo-toml-folder }} shell: bash - - run: cargo clippy --manifest-path ${{ inputs.cargo-toml-folder }}/Cargo.toml --all-features --all-targets -- -D warnings + - run: cargo clippy --all-features --all-targets -- -D warnings + working-directory: ${{ inputs.cargo-toml-folder }} shell: bash - run: | - cd ${{ inputs.cargo-toml-folder }} cargo update cargo install cargo-deny cargo deny check licenses --config ${GITHUB_WORKSPACE}/deny.toml + working-directory: ${{ inputs.cargo-toml-folder }} shell: bash - name: doc diff --git a/babushka-core/.cargo/config.toml b/babushka-core/.cargo/config.toml new file mode 100644 index 0000000000..e61d57cec1 --- /dev/null +++ b/babushka-core/.cargo/config.toml @@ -0,0 +1,3 @@ +[env] +BABUSHKA_NAME = "Babushka" # This should be overwritten by each wrapper library. +BABUSHKA_VERSION = "0.1.0" diff --git a/babushka-core/tests/utilities/mocks.rs b/babushka-core/tests/utilities/mocks.rs index 92332dbbc3..ab4cb138dc 100644 --- a/babushka-core/tests/utilities/mocks.rs +++ b/babushka-core/tests/utilities/mocks.rs @@ -70,6 +70,15 @@ async fn receive_and_respond_to_next_message( }; let message = from_utf8(&buffer[..size]).unwrap().to_string(); + let setinfo_count = message.matches("SETINFO").count(); + if setinfo_count > 0 { + let mut buffer = Vec::new(); + for _ in 0..setinfo_count { + super::encode_value(&Value::Okay, &mut buffer).unwrap(); + } + socket.write_all(&buffer).await.unwrap(); + return true; + } if let Some(response) = constant_responses.get(&message) { let mut buffer = Vec::new(); diff --git a/benchmarks/rust/.cargo/config.toml b/benchmarks/rust/.cargo/config.toml new file mode 100644 index 0000000000..e61d57cec1 --- /dev/null +++ b/benchmarks/rust/.cargo/config.toml @@ -0,0 +1,3 @@ +[env] +BABUSHKA_NAME = "Babushka" # This should be overwritten by each wrapper library. +BABUSHKA_VERSION = "0.1.0" diff --git a/csharp/lib/.cargo/config.toml b/csharp/lib/.cargo/config.toml new file mode 100644 index 0000000000..95016f56ae --- /dev/null +++ b/csharp/lib/.cargo/config.toml @@ -0,0 +1,3 @@ +[env] +BABUSHKA_NAME = { value = "BabushkaC#", force = true } +BABUSHKA_VERSION = "0.1.0" diff --git a/node/rust-client/.cargo/config.toml b/node/rust-client/.cargo/config.toml new file mode 100644 index 0000000000..319bf407ae --- /dev/null +++ b/node/rust-client/.cargo/config.toml @@ -0,0 +1,3 @@ +[env] +BABUSHKA_NAME = { value = "BabushkaJS", force = true } +BABUSHKA_VERSION = "0.1.0" diff --git a/node/tests/SharedTests.ts b/node/tests/SharedTests.ts index 9578688b60..d3638f4bb1 100644 --- a/node/tests/SharedTests.ts +++ b/node/tests/SharedTests.ts @@ -1,4 +1,5 @@ import { expect, it } from "@jest/globals"; +import { exec } from "child_process"; import { v4 as uuidv4 } from "uuid"; import { InfoOptions, ReturnType, SetOptions, parseInfoResponse } from "../"; import { Client, GetAndSetRandomValue, getFirstResult } from "./TestUtilities"; @@ -19,6 +20,24 @@ type BaseClient = { customCommand: (commandName: string, args: string[]) => Promise; }; +async function getVersion(): Promise<[number, number, number]> { + const versioString = await new Promise((resolve, reject) => { + exec(`redis-server -v`, (error, stdout) => { + if (error) { + reject(error); + } else { + resolve(stdout); + } + }); + }); + const version = versioString.split("v=")[1].split(" ")[0]; + const numbers = version?.split("."); + if (numbers.length != 3) { + return [0, 0, 0]; + } + return [parseInt(numbers[0]), parseInt(numbers[1]), parseInt(numbers[2])]; +} + export function runBaseTests(config: { init: () => Promise<{ context: Context; client: BaseClient }>; close: (context: Context, testSucceeded: boolean) => void; @@ -37,6 +56,24 @@ export function runBaseTests(config: { } }; + it( + "should register client name and version", + async () => { + await runTest(async (client: BaseClient) => { + const version = await getVersion(); + if (version[0] < 7 || (version[0] === 7 && version[1] < 2)) { + return; + } + + const result = await client.customCommand("CLIENT", ["INFO"]); + + expect(result).toContain("lib-name=BabushkaJS"); + expect(result).toContain("lib-ver=0.1.0"); + }); + }, + config.timeout + ); + it( "set with return of old value works", async () => { @@ -172,15 +209,19 @@ export function runBaseTests(config: { async () => { await runTest(async (client: BaseClient) => { const serverInfo = await client.info([InfoOptions.Server]); - const conf_file = parseInfoResponse(getFirstResult(serverInfo))["config_file"]; + const conf_file = parseInfoResponse(getFirstResult(serverInfo))[ + "config_file" + ]; if (conf_file.length > 0) { expect(await client.configRewrite()).toEqual("OK"); } else { - try{ + try { /// We expect Redis to return an error since the test cluster doesn't use redis.conf file expect(await client.configRewrite()).toThrow(); - } catch(e){ - expect((e as Error).message).toMatch('The server is running without a config file'); + } catch (e) { + expect((e as Error).message).toMatch( + "The server is running without a config file" + ); } } }); @@ -196,10 +237,20 @@ export function runBaseTests(config: { /// after the configResetStat call we initiate an info command and the the total_commands_processed will be 1. await client.set("foo", "bar"); const OldResult = await client.info([InfoOptions.Stats]); - expect(Number(parseInfoResponse(getFirstResult(OldResult))["total_commands_processed"])).toBeGreaterThan(1); + expect( + Number( + parseInfoResponse(getFirstResult(OldResult))[ + "total_commands_processed" + ] + ) + ).toBeGreaterThan(1); expect(await client.configResetStat()).toEqual("OK"); const result = await client.info([InfoOptions.Stats]); - expect(parseInfoResponse(getFirstResult(result))["total_commands_processed"]).toEqual("1"); + expect( + parseInfoResponse(getFirstResult(result))[ + "total_commands_processed" + ] + ).toEqual("1"); }); }, config.timeout @@ -226,7 +277,7 @@ export function runBaseTests(config: { await runTest(async (client: BaseClient) => { const key1 = uuidv4(); const key2 = uuidv4(); - /// key1 and key2 does not exist, so it set to 0 before performing the operation. + /// key1 and key2 does not exist, so it set to 0 before performing the operation. expect(await client.incr(key1)).toEqual(1); expect(await client.get(key1)).toEqual("1"); expect(await client.incrBy(key2, 2)).toEqual(2); @@ -245,13 +296,17 @@ export function runBaseTests(config: { try { expect(await client.incr(key)).toThrow(); } catch (e) { - expect((e as Error).message).toMatch("value is not an integer"); + expect((e as Error).message).toMatch( + "value is not an integer" + ); } try { expect(await client.incrBy(key, 1)).toThrow(); } catch (e) { - expect((e as Error).message).toMatch("value is not an integer"); + expect((e as Error).message).toMatch( + "value is not an integer" + ); } }); }, diff --git a/python/.cargo/config.toml b/python/.cargo/config.toml new file mode 100644 index 0000000000..24a6f21533 --- /dev/null +++ b/python/.cargo/config.toml @@ -0,0 +1,3 @@ +[env] +BABUSHKA_NAME = { value = "BabushkaPy", force = true } +BABUSHKA_VERSION = "0.1.0" diff --git a/python/python/tests/test_async_client.py b/python/python/tests/test_async_client.py index d5cf5f2370..0c65d6112b 100644 --- a/python/python/tests/test_async_client.py +++ b/python/python/tests/test_async_client.py @@ -66,7 +66,7 @@ async def check_if_server_version_lt(client: BaseRedisClient, min_version: str) @pytest.mark.asyncio -class TestSocketClient: +class TestRedisClients: @pytest.mark.parametrize("cluster_mode", [True, False]) async def test_socket_set_get(self, redis_client: BaseRedisClient): key = get_random_string(10) @@ -74,6 +74,18 @@ async def test_socket_set_get(self, redis_client: BaseRedisClient): assert await redis_client.set(key, value) == OK assert await redis_client.get(key) == value + @pytest.mark.parametrize("cluster_mode", [True, False]) + async def test_register_client_name_and_version( + self, redis_client: BaseRedisClient + ): + min_version = "7.2.0" + if await check_if_server_version_lt(redis_client, min_version): + # TODO: change it to pytest fixture after we'll implement a sync client + return pytest.mark.skip(reason=f"Redis version required >= {min_version}") + info = await redis_client.custom_command(["CLIENT", "INFO"]) + assert "lib-name=BabushkaPy" in info + assert "lib-ver=0.1.0" in info + @pytest.mark.parametrize("cluster_mode", [True, False]) async def test_large_values(self, redis_client: BaseRedisClient): length = 2**16 diff --git a/submodules/redis-rs b/submodules/redis-rs index 694fb7b1ec..962b63c5fb 160000 --- a/submodules/redis-rs +++ b/submodules/redis-rs @@ -1 +1 @@ -Subproject commit 694fb7b1ec1a826cc5a8e936a6c6eb7610b3ec65 +Subproject commit 962b63c5fb996d6acb6ac42b0a97fab801f468f8