Repository: microsoft/garnet
File: test/Garnet.test/RespVectorSetTests.cs (C#)

Code before:
            ClassicAssert.AreEqual("num-links", (string)res2[8]);
            ClassicAssert.AreEqual(32, (int)res2[9]);
            ClassicAssert.AreEqual("size", (string)res2[10]);
            ClassicAssert.AreEqual(0, (long)res2[11]);

            // Add another element and try again
            var res3 = db.Execute("VADD", ["foo", "REDUCE", "5", "VALUES", "10", "11.0", "12.0", "13.0", "14.0", "15.0", "16.0", "17.0", "18.0", "19.0", "20.0", new byte[] { 0, 0, 0, 1 }, "M", "32"]);
            ClassicAssert.AreEqual(1, (int)res3);

            var res4 = (RedisValue[])db.Execute("VINFO", ["foo"]);
            ClassicAssert.AreEqual(12, res4.Length);
            ClassicAssert.AreEqual("quant-type", (string)res2[0]);
            ClassicAssert.AreEqual("q8", (string)res2[1]);
            ClassicAssert.AreEqual("input-vector-dimensions", (string)res2[2]);
            ClassicAssert.AreEqual(10, (int)res2[3]);
            ClassicAssert.AreEqual("reduced-dimensions", (string)res2[4]);
            ClassicAssert.AreEqual(5, (int)res2[5]);
            ClassicAssert.AreEqual("build-exploration-factor", (string)res2[6]);
            ClassicAssert.AreEqual(16, (int)res2[7]);
            ClassicAssert.AreEqual("num-links", (string)res2[8]);
            ClassicAssert.AreEqual(32, (int)res2[9]);
            ClassicAssert.AreEqual("size", (string)res2[10]);
            ClassicAssert.AreEqual(0, (long)res2[11]);

            // VINFO on non-existent key returns null
            var res5 = db.Execute("VINFO", ["nonexistent"]);
            ClassicAssert.IsTrue(res5.IsNull);

            // VINFO on wrong type returns error
            // TODO: add WRONGTYPE test once implemented
            //_ = db.StringSet("stringkey", "value");
            //var exc1 = ClassicAssert.Throws<RedisServerException>(() => db.Execute("VINFO", ["stringkey"]));
            //ClassicAssert.IsTrue(exc1.Message.StartsWith("WRONGTYPE"));
        }

        [Test]
        public void VREM()
        {
            using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig());
            var db = redis.GetDatabase(0);

            // Populate
            var res1 = db.Execute("VADD", ["foo", "REDUCE", "50", "VALUES", "75", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", new byte[] { 0, 0, 0, 0 }, "CAS", "Q8", "EF", "16", "M", "32"]);
            ClassicAssert.AreEqual(1, (int)res1);

            var res2 = db.Execute("VADD", ["foo", "REDUCE", "50", "VALUES", "75", "100.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", "4.0", "1.0", "2.0", "3.0", new byte[] { 1, 0, 0, 0 }, "CAS", "Q8", "EF", "16", "M", "32"]);
            ClassicAssert.AreEqual(1, (int)res2);

            // Remove on non-vector set fails
            // TODO: test against Redis, how do they respond (I expect WRONGTYPE, but needs verification)
            //_ = db.StringSet("fizz", "buzz");

Review comment (suggestion):
Per prior comment, give this a test with both RESP2 and RESP3 (you'll need to be explicit with connections to test that).  SE.Redis does expose types on RedisResult, though I'm not 100% sure if you can distinguish the null array.  Regardless, exercise the code path.

Code after:
#pragma warning restore CS0618

                    var commit = server.Store.WaitForCommit();
                    ClassicAssert.IsTrue(commit);
                    server.Dispose(deleteDir: false);

                    server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true);
                    server.Start();
                }

                using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true)))
                {
                    var db = redis.GetDatabase(0);

                    var res2 = (string[])db.Execute("VEMB", ["foo", new byte[] { 0, 0, 0, 0 }]);
                    ClassicAssert.AreEqual(res2.Length, addData1.Length);

                    for (var i = 0; i < res2.Length; i++)
                    {
                        ClassicAssert.AreEqual((float)addData1[i], float.Parse(res2[i]));
                    }
                }
            }

            // VREM
            {
                using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true)))
                {
                    var s = redis.GetServers()[0];
                    var db = redis.GetDatabase(0);

                    _ = db.KeyDelete("foo");

                    var res1 = db.Execute("VADD", ["foo", "XB8", addData1, new byte[] { 0, 0, 0, 0 }, "CAS", "Q8", "EF", "16", "M", "32", "SETATTR", "hello world"]);
                    ClassicAssert.AreEqual(1, (int)res1);

                    var res2 = db.Execute("VADD", ["foo", "XB8", addData2, new byte[] { 0, 0, 0, 1 }, "CAS", "Q8", "EF", "16", "M", "32", "SETATTR", "hello world"]);
                    ClassicAssert.AreEqual(1, (int)res1);

#pragma warning disable CS0618 // Intentionally doing bad things
                    s.Save(SaveType.ForegroundSave);
#pragma warning restore CS0618

                    var commit = server.Store.WaitForCommit();
                    ClassicAssert.IsTrue(commit);
                    server.Dispose(deleteDir: false);

                    server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true);
                    server.Start();
                }