4. “Requests are sent from the client to
the Redis server as arrays of strings
representing the arguments of the
command to execute.”
–Redis documentation
RESP
(REdis Serialization Protocol)
5. Ruby
# Get the value of a key.
#
# @param [String] key
# @return [String]
def get(key)
synchronize do |client|
client.call([:get, key])
end
end
https://github.com/redis/redis-rb/blob/master/lib/
redis.rb
26. Elixir
defmodule Comredis.Command.Generator do
defmacro __using__(_options) do
for command <- FileReader.load do
generate(command)
end
end
defp generate(command = %Command{}) do
quote do
@doc unquote doc(command)
unquote bodies(command,
Argument.split_options(command.arguments))
end
end
...
end
27. Elixir
defp bodies(command, {required_args, []}) do
args = argument_names(required_args)
quote do
def unquote(command.canonical_name)(unquote_splicing(args)) do
List.flatten [unquote(command.name), unquote_splicing(args)]
end
end
end
28. Elixir
defp bodies(%Command{canonical_name: :get, name: "GET"},
{[%Argument{canonical_name: :key}], []}) do
args = [{:key, [], Elixir}]
quote do
def unquote(command.canonical_name)(unquote_splicing(args)) do
List.flatten [unquote(command.name), unquote_splicing(args)]
end
end
end
defp bodies(%Command{canonical_name: :get, name: "GET"},
{%Argument{canonical_name: :key}, []}) do
quote do
def get(key) do
List.flatten ["GET", key]
end
end
end
29.
30. How to test it?
Don’t test code generation, but the
generated code
Write tests for each function?
No, automatically test all of them
31. Property-based testing
Generator: random arguments compliant to
command arguments
Property: commands have a valid syntax
Use a Redis server as a test oracle
github.com/parroty/excheck (triq)