mirror of
https://github.com/postgresml/pgcat.git
synced 2026-03-23 01:16:30 +00:00
156 lines
4.0 KiB
Ruby
156 lines
4.0 KiB
Ruby
|
|
# frozen_string_literal: true
|
||
|
|
require_relative 'spec_helper'
|
||
|
|
|
||
|
|
|
||
|
|
describe "Portocol handling" do
|
||
|
|
let(:processes) { Helpers::Pgcat.single_instance_setup("sharded_db", 1, "session") }
|
||
|
|
let(:sequence) { [] }
|
||
|
|
let(:pgcat_socket) { PostgresSocket.new('localhost', processes.pgcat.port) }
|
||
|
|
let(:pgdb_socket) { PostgresSocket.new('localhost', processes.all_databases.first.port) }
|
||
|
|
|
||
|
|
after do
|
||
|
|
pgdb_socket.close
|
||
|
|
pgcat_socket.close
|
||
|
|
processes.all_databases.map(&:reset)
|
||
|
|
processes.pgcat.shutdown
|
||
|
|
end
|
||
|
|
|
||
|
|
def run_comparison(sequence, socket_a, socket_b)
|
||
|
|
sequence.each do |msg, *args|
|
||
|
|
socket_a.send(msg, *args)
|
||
|
|
socket_b.send(msg, *args)
|
||
|
|
|
||
|
|
compare_messages(
|
||
|
|
socket_a.read_from_server,
|
||
|
|
socket_b.read_from_server
|
||
|
|
)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
def compare_messages(msg_arr0, msg_arr1)
|
||
|
|
if msg_arr0.count != msg_arr1.count
|
||
|
|
error_output = []
|
||
|
|
|
||
|
|
error_output << "#{msg_arr0.count} : #{msg_arr1.count}"
|
||
|
|
error_output << "PgCat Messages"
|
||
|
|
error_output += msg_arr0.map { |message| "\t#{message[:code]} - #{message[:bytes].map(&:chr).join(" ")}" }
|
||
|
|
error_output << "PgServer Messages"
|
||
|
|
error_output += msg_arr1.map { |message| "\t#{message[:code]} - #{message[:bytes].map(&:chr).join(" ")}" }
|
||
|
|
error_desc = error_output.join("\n")
|
||
|
|
raise StandardError, "Message count mismatch #{error_desc}"
|
||
|
|
end
|
||
|
|
|
||
|
|
(0..msg_arr0.count - 1).all? do |i|
|
||
|
|
msg0 = msg_arr0[i]
|
||
|
|
msg1 = msg_arr1[i]
|
||
|
|
|
||
|
|
result = [
|
||
|
|
msg0[:code] == msg1[:code],
|
||
|
|
msg0[:len] == msg1[:len],
|
||
|
|
msg0[:bytes] == msg1[:bytes],
|
||
|
|
].all?
|
||
|
|
|
||
|
|
next result if result
|
||
|
|
|
||
|
|
if result == false
|
||
|
|
error_string = []
|
||
|
|
if msg0[:code] != msg1[:code]
|
||
|
|
error_string << "code #{msg0[:code]} != #{msg1[:code]}"
|
||
|
|
end
|
||
|
|
if msg0[:len] != msg1[:len]
|
||
|
|
error_string << "len #{msg0[:len]} != #{msg1[:len]}"
|
||
|
|
end
|
||
|
|
if msg0[:bytes] != msg1[:bytes]
|
||
|
|
error_string << "bytes #{msg0[:bytes]} != #{msg1[:bytes]}"
|
||
|
|
end
|
||
|
|
err = error_string.join("\n")
|
||
|
|
|
||
|
|
raise StandardError, "Message mismatch #{err}"
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
RSpec.shared_examples "at parity with database" do
|
||
|
|
before do
|
||
|
|
pgcat_socket.send_startup_message("sharding_user", "sharded_db", "sharding_user")
|
||
|
|
pgdb_socket.send_startup_message("sharding_user", "shard0", "sharding_user")
|
||
|
|
end
|
||
|
|
|
||
|
|
it "works" do
|
||
|
|
run_comparison(sequence, pgcat_socket, pgdb_socket)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
context "Cancel Query" do
|
||
|
|
let(:sequence) {
|
||
|
|
[
|
||
|
|
[:send_query_message, "SELECT pg_sleep(5)"],
|
||
|
|
[:cancel_query]
|
||
|
|
]
|
||
|
|
}
|
||
|
|
|
||
|
|
it_behaves_like "at parity with database"
|
||
|
|
end
|
||
|
|
|
||
|
|
xcontext "Simple query after parse" do
|
||
|
|
let(:sequence) {
|
||
|
|
[
|
||
|
|
[:send_parse_message, "SELECT 5"],
|
||
|
|
[:send_query_message, "SELECT 1"],
|
||
|
|
[:send_bind_message],
|
||
|
|
[:send_describe_message, "P"],
|
||
|
|
[:send_execute_message],
|
||
|
|
[:send_sync_message],
|
||
|
|
]
|
||
|
|
}
|
||
|
|
|
||
|
|
# Known to fail due to PgCat not supporting flush
|
||
|
|
it_behaves_like "at parity with database"
|
||
|
|
end
|
||
|
|
|
||
|
|
xcontext "Flush message" do
|
||
|
|
let(:sequence) {
|
||
|
|
[
|
||
|
|
[:send_parse_message, "SELECT 1"],
|
||
|
|
[:send_flush_message]
|
||
|
|
]
|
||
|
|
}
|
||
|
|
|
||
|
|
# Known to fail due to PgCat not supporting flush
|
||
|
|
it_behaves_like "at parity with database"
|
||
|
|
end
|
||
|
|
|
||
|
|
xcontext "Bind without parse" do
|
||
|
|
let(:sequence) {
|
||
|
|
[
|
||
|
|
[:send_bind_message]
|
||
|
|
]
|
||
|
|
}
|
||
|
|
# This is known to fail.
|
||
|
|
# Server responds immediately, Proxy buffers the message
|
||
|
|
it_behaves_like "at parity with database"
|
||
|
|
end
|
||
|
|
|
||
|
|
context "Simple message" do
|
||
|
|
let(:sequence) {
|
||
|
|
[[:send_query_message, "SELECT 1"]]
|
||
|
|
}
|
||
|
|
|
||
|
|
it_behaves_like "at parity with database"
|
||
|
|
end
|
||
|
|
|
||
|
|
context "Extended protocol" do
|
||
|
|
let(:sequence) {
|
||
|
|
[
|
||
|
|
[:send_parse_message, "SELECT 1"],
|
||
|
|
[:send_bind_message],
|
||
|
|
[:send_describe_message, "P"],
|
||
|
|
[:send_execute_message],
|
||
|
|
[:send_sync_message],
|
||
|
|
]
|
||
|
|
}
|
||
|
|
|
||
|
|
it_behaves_like "at parity with database"
|
||
|
|
end
|
||
|
|
end
|