LibraryInfoTest.java
package redis.clients.jedis.resps;
import org.junit.jupiter.api.Test;
import redis.clients.jedis.Protocol;
import redis.clients.jedis.util.RedisInputStream;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class LibraryInfoTest {
private static Object parseRespResponse(String respResponse) {
InputStream is = new ByteArrayInputStream(respResponse.getBytes());
return Protocol.read(new RedisInputStream(is));
}
@Test
public void buildLibraryInfoResp2Standard() {
// Simulate standard RESP2 response for FUNCTION LIST (without WITHCODE)
// Format: [library_name, <value>, engine, <value>, functions, <value>]
String respResponse = "*6\r\n" + "$12\r\nlibrary_name\r\n" + "$5\r\nmylib\r\n"
+ "$6\r\nengine\r\n" + "$3\r\nLUA\r\n" + "$9\r\nfunctions\r\n" + "*1\r\n" + // functions
// array with 1
// element
"*6\r\n" + // function info with 3 key-value pairs
"$4\r\nname\r\n" + "$6\r\nmyfunc\r\n" + "$11\r\ndescription\r\n" + "$-1\r\n" + // null
// description
"$5\r\nflags\r\n" + "*0\r\n"; // empty flags array
Object data = parseRespResponse(respResponse);
LibraryInfo result = LibraryInfo.LIBRARY_INFO.build(data);
assertNotNull(result);
assertEquals("mylib", result.getLibraryName());
assertEquals("LUA", result.getEngine());
assertNotNull(result.getFunctions());
assertEquals(1, result.getFunctions().size());
assertEquals("myfunc", result.getFunctions().get(0).get("name"));
assertNull(result.getLibraryCode());
}
@Test
public void buildLibraryInfoResp2WithCode() {
// Simulate RESP2 response for FUNCTION LIST WITHCODE
// Format: [library_name, <value>, engine, <value>, functions, <value>, library_code, <value>]
String respResponse = "*8\r\n" + "$12\r\nlibrary_name\r\n" + "$5\r\nmylib\r\n"
+ "$6\r\nengine\r\n" + "$3\r\nLUA\r\n" + "$9\r\nfunctions\r\n" + "*1\r\n" + // functions
// array with 1
// element
"*6\r\n" + // function info with 3 key-value pairs
"$4\r\nname\r\n" + "$6\r\nmyfunc\r\n" + "$11\r\ndescription\r\n" + "$-1\r\n" + // null
// description
"$5\r\nflags\r\n" + "*0\r\n" + // empty flags array
"$12\r\nlibrary_code\r\n"
+ "$50\r\n#!LUA name=mylib\nredis.register_function('myfunc')\r\n";
Object data = parseRespResponse(respResponse);
LibraryInfo result = LibraryInfo.LIBRARY_INFO.build(data);
assertNotNull(result);
assertEquals("mylib", result.getLibraryName());
assertEquals("LUA", result.getEngine());
assertNotNull(result.getFunctions());
assertEquals(1, result.getFunctions().size());
assertEquals("myfunc", result.getFunctions().get(0).get("name"));
assertNotNull(result.getLibraryCode());
assertTrue(result.getLibraryCode().contains("#!LUA name=mylib"));
}
@Test
public void buildLibraryInfoResp2WithExtraConsistentField() {
// Simulate Redis Enterprise RESP2 response with extra "consistent" field
// This is the bug scenario from CAE-2120
// Format: [library_name, <value>, engine, <value>, consistent, <value>, functions, <value>]
String respResponse = "*8\r\n" + "$12\r\nlibrary_name\r\n" + "$5\r\nmylib\r\n"
+ "$6\r\nengine\r\n" + "$3\r\nLUA\r\n" + "$10\r\nconsistent\r\n" + ":1\r\n" + // consistent
// value
// (integer)
"$9\r\nfunctions\r\n" + "*1\r\n" + // functions array with 1 element
"*6\r\n" + // function info with 3 key-value pairs
"$4\r\nname\r\n" + "$6\r\nmyfunc\r\n" + "$11\r\ndescription\r\n" + "$-1\r\n" + // null
// description
"$5\r\nflags\r\n" + "*0\r\n"; // empty flags array
Object data = parseRespResponse(respResponse);
LibraryInfo result = LibraryInfo.LIBRARY_INFO.build(data);
assertNotNull(result);
assertEquals("mylib", result.getLibraryName());
assertEquals("LUA", result.getEngine());
assertNotNull(result.getFunctions());
assertEquals(1, result.getFunctions().size());
assertEquals("myfunc", result.getFunctions().get(0).get("name"));
assertNull(result.getLibraryCode());
}
@Test
public void buildLibraryInfoResp2WithExtraConsistentFieldAndCode() {
// Simulate Redis Enterprise RESP2 response with extra "consistent" field and WITHCODE
// Format: [library_name, <value>, engine, <value>, consistent, <value>, functions, <value>,
// library_code, <value>]
String respResponse = "*10\r\n" + "$12\r\nlibrary_name\r\n" + "$5\r\nmylib\r\n"
+ "$6\r\nengine\r\n" + "$3\r\nLUA\r\n" + "$10\r\nconsistent\r\n" + ":1\r\n" + // consistent
// value
// (integer)
"$9\r\nfunctions\r\n" + "*1\r\n" + // functions array with 1 element
"*6\r\n" + // function info with 3 key-value pairs
"$4\r\nname\r\n" + "$6\r\nmyfunc\r\n" + "$11\r\ndescription\r\n" + "$-1\r\n" + // null
// description
"$5\r\nflags\r\n" + "*0\r\n" + // empty flags array
"$12\r\nlibrary_code\r\n"
+ "$50\r\n#!LUA name=mylib\nredis.register_function('myfunc')\r\n";
Object data = parseRespResponse(respResponse);
LibraryInfo result = LibraryInfo.LIBRARY_INFO.build(data);
assertNotNull(result);
assertEquals("mylib", result.getLibraryName());
assertEquals("LUA", result.getEngine());
assertNotNull(result.getFunctions());
assertEquals(1, result.getFunctions().size());
assertEquals("myfunc", result.getFunctions().get(0).get("name"));
assertNotNull(result.getLibraryCode());
assertTrue(result.getLibraryCode().contains("#!LUA name=mylib"));
}
}