diff --git a/tests/message.cr b/tests/message.cr new file mode 100644 index 0000000..649510a --- /dev/null +++ b/tests/message.cr @@ -0,0 +1,48 @@ + +# Context class, so the variables are available everywhere. +class Context + class_property requests = [] of IPC::CBOR.class + class_property responses = [] of IPC::CBOR.class +end + +class IPC::CBOR + def handle + raise "unimplemented" + end +end + +IPC::CBOR.message Message, 10 do + property content : String? + property some_number : Int32? + def initialize(@content = nil, @some_number = nil) + end + + def handle + info "message received: #{@content}, number: #{@some_number}" + if number = @some_number + ::MessageReceived.new number - 1 + else + ::MessageReceived.new + end + end +end +Context.requests << Message + + +IPC::CBOR.message Error, 0 do + property reason : String + def initialize(@reason) + end +end +Context.responses << Error + +IPC::CBOR.message MessageReceived, 20 do + property minus_one : Int32? + def initialize(@minus_one = nil) + end + + def handle + info "<< MessageReceived (#{@minus_one})" + end +end +Context.responses << MessageReceived diff --git a/tests/pongc-cbor.cr b/tests/pongc-cbor.cr new file mode 100644 index 0000000..e42aecc --- /dev/null +++ b/tests/pongc-cbor.cr @@ -0,0 +1,117 @@ +require "option_parser" +require "../src/ipc.cr" +require "../src/cbor.cr" +require "./prints.cr" + +require "cbor" +require "./message" + +class IPC::CBOR + def handle + raise "unimplemented" + end +end + +class CLI + class_property service_name = "pong" + class_property message : String? = nil + class_property type = 1 + class_property user_type = 42 + class_property verbosity = 1 + class_property rounds = 1 +end + +OptionParser.parse do |parser| + parser.on "-s service_name", "--service-name service_name", "URI" do |optsn| + CLI.service_name = optsn + end + + parser.on "-v verbosity", "--verbosity verbosity", "Verbosity (0 = nothing is printed, 1 = only events, 2 = events and messages). Default: 1" do |optsn| + CLI.verbosity = optsn.to_i + end + + parser.on "-t message_type", + "--type message_type", + "(internal) message type." do |opt| + CLI.type = opt.to_i + end + + parser.on "-u user_message_type", + "--user-type user_message_type", + "Message type." do |opt| + CLI.user_type = opt.to_i + end + + + parser.on "-r rounds", "--rounds count", "Number of messages sent." do |opt| + CLI.rounds = opt.to_i + end + + parser.on "-m message", "--message m", "Message to sent." do |opt| + CLI.message = opt + end + + parser.on "-h", "--help", "Show this help" do + puts parser + exit 0 + end +end + +def main + client = IPC::Client.new CLI.service_name + client.base_timer = 30_000 # 30 seconds + client.timer = 30_000 # 30 seconds + + server_fd = client.server_fd + if server_fd.nil? + puts "there is no server_fd!!" + exit 1 + end + + nb_messages_remaining = CLI.rounds + + # Listening on STDIN. + client << 0 + + client.loop do |event| + case event + when IPC::Event::ExtraSocket + info "reading on #{event.fd}" + + mstr = if CLI.message.nil? + if event.fd == 0 STDIN.gets || "STDIN failed!" else "coucou" end + else + CLI.message.not_nil! + end + + m = Message.new mstr, nb_messages_remaining + + info ">> Message" + + CLI.rounds.times do |i| + client.send server_fd.not_nil!, m + end + when IPC::Event::MessageReceived + nb_messages_remaining -= 1 + response = Context.responses.parse_ipc_cbor event.message + response.handle + case response + when MessageReceived + info "#{nb_messages_remaining} messages remaining" + if nb_messages_remaining == 0 + exit 0 + end + when Error + end + when IPC::Event::Disconnection + info "Disconnection from #{event.fd}" + if event.fd == 0 + client.remove_fd 0 + end + else + info "unhandled event: #{event.class}" + end + end +end + +main diff --git a/tests/pongd-cbor.cr b/tests/pongd-cbor.cr new file mode 100644 index 0000000..110b75a --- /dev/null +++ b/tests/pongd-cbor.cr @@ -0,0 +1,96 @@ +require "option_parser" +require "cbor" +require "../src/ipc.cr" +require "../src/cbor.cr" +require "./prints.cr" + +require "./message" + +class CLI + class_property service_name = "pong" + class_property verbosity = 1 + class_property timer = 30_000 + class_property no_response = false +end + +OptionParser.parse do |parser| + parser.on "-s service_name", "--service-name service_name", "URI" do |optsn| + CLI.service_name = optsn + end + + parser.on "-n", "--no-response", "Do not provide any response back." do + CLI.no_response = true + end + + parser.on "-t timer", "--timer ms", "Timer in ms. Default: 30 000" do |optsn| + CLI.timer = optsn.to_i + end + + + parser.on "-v verbosity", "--verbosity verbosity", "Verbosity (0 = nothing is printed, 1 = only events, 2 = events and messages). Default: 1" do |optsn| + CLI.verbosity = optsn.to_i + end + + parser.on "-h", "--help", "Show this help" do + puts parser + exit 0 + end +end + +def main + service = IPC::Server.new CLI.service_name + service.base_timer = CLI.timer # default: 30 seconds + service.timer = CLI.timer # default: 30 seconds + + service.loop do |event| + # service.pp + case event + when IPC::Event::Timer + info "IPC::Event::Timer" + when IPC::Event::Connection + info "IPC::Event::Connection, client: #{event.fd}" + when IPC::Event::Disconnection + info "IPC::Event::Disconnection, client: #{event.fd}" + when IPC::Event::MessageSent + begin + info "IPC::Event::MessageSent, client: #{event.fd}" + rescue e + important "#{e.message}" + service.remove_fd event.fd + end + + when IPC::Event::MessageReceived + begin + info "IPC::Event::MessageReceived, client: #{event.fd}" + + request = Context.requests.parse_ipc_cbor event.message + + if request.nil? + raise "unknown request type" + end + + info "<< #{request.class.name}" + + response = begin + request.handle + rescue e + important "#{request.class.name} generic error #{e}" + ::Error.new "unknown error" + end + + unless CLI.no_response + info ">> #{response.class.name}" + service.send event.fd, response.not_nil! + end + + rescue e + important "#{e.message}" + service.remove_fd event.fd + end + else + important "Exception: message #{event}" + end + end +end + +main