Skip to content
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
name: CI
on:
pull_request:
branches:
- main
push:
paths:
- 'run-specs-in-docker.sh'
Expand Down
3 changes: 3 additions & 0 deletions spec/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ RUN shards install
COPY src/ src/
COPY spec/ spec/

COPY spec/config.ini /tmp/config.ini
COPY spec/config_empty.ini /tmp/config_empty.ini
Comment on lines +14 to +15
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All files in spec/ is already copied on the line above?


COPY spec/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
189 changes: 189 additions & 0 deletions spec/amqproxy/config_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
require "spec"
require "../../src/amqproxy/config"

describe AMQProxy::Config do
it "loads defaults when no ini file, env vars or options are available" do
options = AMQProxy::Options.new
options = options.with(ini_file: "/tmp/non_existing_file.ini")

config = AMQProxy::Config.load_with_cli(options)

config.listen_address.should eq "localhost"
config.listen_port.should eq 5673
config.http_port.should eq 15673
config.log_level.should eq ::Log::Severity::Info
config.idle_connection_timeout.should eq 5
config.term_timeout.should eq -1
config.term_client_close_timeout.should eq 0
config.upstream.should eq nil
end

it "reads from empty config file returning default configuration" do
options = AMQProxy::Options.new
options = options.with(ini_file: "/tmp/config_empty.ini")

config = AMQProxy::Config.load_with_cli(options)

config.listen_address.should eq "localhost"
config.listen_port.should eq 5673
config.http_port.should eq 15673
config.log_level.should eq ::Log::Severity::Info
config.idle_connection_timeout.should eq 5
config.term_timeout.should eq -1
config.term_client_close_timeout.should eq 0
config.upstream.should eq nil
end

it "reads from environment variables and use AMPQ_URL over UPSTREAM variable" do
options = AMQProxy::Options.new

ENV["AMQP_URL"] = "amqp://localhost:5673"
ENV["UPSTREAM"] = "amqp://localhost:5674"

config = AMQProxy::Config.load_with_cli(options)

config.upstream.should eq "amqp://localhost:5673"

# Clean up
ENV.delete("AMQP_URL")
ENV.delete("UPSTREAM")
end

it "reads from environment variables and overrules ini file values" do
options = AMQProxy::Options.new

ENV["LISTEN_ADDRESS"] = "example.com"
ENV["LISTEN_PORT"] = "5674"
ENV["HTTP_PORT"] = "15674"
ENV["LOG_LEVEL"] = "Error"
ENV["IDLE_CONNECTION_TIMEOUT"] = "12"
ENV["TERM_TIMEOUT"] = "13"
ENV["TERM_CLIENT_CLOSE_TIMEOUT"] = "14"
ENV["UPSTREAM"] = "amqp://localhost:5674"

config = AMQProxy::Config.load_with_cli(options)

config.listen_address.should eq "example.com"
config.listen_port.should eq 5674
config.http_port.should eq 15674
config.log_level.should eq ::Log::Severity::Error
config.idle_connection_timeout.should eq 12
config.term_timeout.should eq 13
config.term_client_close_timeout.should eq 14
config.upstream.should eq "amqp://localhost:5674"

# Clean up
ENV.delete("LISTEN_ADDRESS")
ENV.delete("LISTEN_PORT")
ENV.delete("HTTP_PORT")
ENV.delete("LOG_LEVEL")
ENV.delete("IDLE_CONNECTION_TIMEOUT")
ENV.delete("TERM_TIMEOUT")
ENV.delete("TERM_CLIENT_CLOSE_TIMEOUT")
ENV.delete("UPSTREAM")
end

it "reads from command line arguments and overrules env vars" do
ENV["LISTEN_ADDRESS"] = "example.com"
ENV["LISTEN_PORT"] = "5674"
ENV["HTTP_PORT"] = "15674"
ENV["LOG_LEVEL"] = "Error"
ENV["IDLE_CONNECTION_TIMEOUT"] = "12"
ENV["TERM_TIMEOUT"] = "13"
ENV["TERM_CLIENT_CLOSE_TIMEOUT"] = "14"
ENV["UPSTREAM"] = "amqp://localhost:5674"

options = AMQProxy::Options.new
options = options.with(
listen_address: "example_arg.com",
listen_port: 5675,
http_port: 15675,
log_level: ::Log::Severity::Warn,
idle_connection_timeout: 15,
term_timeout: 16,
term_client_close_timeout: 17,
upstream: "amqp://localhost:5679"
)

config = AMQProxy::Config.load_with_cli(options)

config.listen_address.should eq "example_arg.com"
config.log_level.should eq ::Log::Severity::Warn
config.listen_port.should eq 5675
config.http_port.should eq 15675
config.idle_connection_timeout.should eq 15
config.term_timeout.should eq 16
config.term_client_close_timeout.should eq 17
config.upstream.should eq "amqp://localhost:5679"

# Clean Up
ENV.delete("LISTEN_ADDRESS")
ENV.delete("LISTEN_PORT")
ENV.delete("HTTP_PORT")
ENV.delete("LOG_LEVEL")
ENV.delete("IDLE_CONNECTION_TIMEOUT")
ENV.delete("TERM_TIMEOUT")
ENV.delete("TERM_CLIENT_CLOSE_TIMEOUT")
ENV.delete("UPSTREAM")
end

it "sets log level to debug when debug flag is present" do
options = AMQProxy::Options.new
options = options.with(
listen_address: "example_arg.com",
listen_port: 5675,
http_port: 15675,
log_level: ::Log::Severity::Warn,
idle_connection_timeout: 15,
term_timeout: 16,
term_client_close_timeout: 17,
is_debug: true,
upstream: "amqp://localhost:5679"
)

config = AMQProxy::Config.load_with_cli(options)

config.listen_address.should eq "example_arg.com"
config.log_level.should eq ::Log::Severity::Debug
config.listen_port.should eq 5675
config.http_port.should eq 15675
config.idle_connection_timeout.should eq 15
config.term_timeout.should eq 16
config.term_client_close_timeout.should eq 17
config.upstream.should eq "amqp://localhost:5679"
end

it "keeps the log level to trace when debug flag is present" do
options = AMQProxy::Options.new
options = options.with(
listen_address: "example_arg.com",
listen_port: 5675,
http_port: 15675,
log_level: ::Log::Severity::Trace,
idle_connection_timeout: 15,
term_timeout: 16,
term_client_close_timeout: 17,
is_debug: true,
upstream: "amqp://localhost:5679"
)

config = AMQProxy::Config.load_with_cli(options)

config.log_level.should eq ::Log::Severity::Trace
end

it "reads default ini file when ini file path is null" do
options = AMQProxy::Options.new

config = AMQProxy::Config.load_with_cli(options)

config.listen_address.should eq "127.0.0.2"
config.listen_port.should eq 5678
config.http_port.should eq 15678
config.log_level.should eq ::Log::Severity::Debug
config.idle_connection_timeout.should eq 55
config.term_timeout.should eq 56
config.term_client_close_timeout.should eq 57
config.upstream.should eq "amqp://localhost:5678"
end
end
32 changes: 32 additions & 0 deletions spec/amqproxy/options_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
require "spec"
require "../../src/amqproxy/options"

describe AMQProxy::Options do
it "can be changed by with yielding a new options record with correct property values" do
options = AMQProxy::Options.new

options = options.with(
listen_port: 34,
http_port: 35,
idle_connection_timeout: 36,
term_timeout: 37,
term_client_close_timeout: 38,
log_level: ::Log::Severity::Trace,
is_debug: true,
ini_file: "the_init_file.config",
listen_address: "listen.example.com",
upstream: "upstream.example.com:39"
)

options.listen_address.should eq "listen.example.com"
options.listen_port.should eq 34
options.upstream.should eq "upstream.example.com:39"
options.http_port.should eq 35
options.idle_connection_timeout.should eq 36
options.term_timeout.should eq 37
options.term_client_close_timeout.should eq 38
options.log_level.should eq ::Log::Severity::Trace
options.is_debug.should eq true
options.ini_file.should eq "the_init_file.config"
end
end
13 changes: 13 additions & 0 deletions spec/config.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[main]
log_level = debug
idle_connection_timeout = 55
term_timeout = 56
term_client_close_timeout = 57
upstream = amqp://localhost:5678

[listen]
bind = 127.0.0.1
address = 127.0.0.2
port = 5678
http_port = 15678
log_level = debug
Empty file added spec/config_empty.ini
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good to avoid having empty files in the repository, maybe this file can be created when needed in config_spec.cr and then cleaned up at the end of the spec.

Copy link
Member

@dentarg dentarg Jun 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it good to avoid empty files in the repo? If the file serves a purpose (used in specs? I haven't actually checked this 🙈), we should not be afraid to have it around. Creating it with code sounds both more complex and slower to me.

Copy link
Member

@kickster97 kickster97 Jun 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My reasoning is mostly about cleanliness so the repository remains free of files that are solely for transient test purposes.
Sure complexion grows slightly, thats a good point. I don't know the performance impact of creating an empty file, but is it really notably expensive to create once?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we have files like this in the repo I think it should be clear in some way what they are used for so its less confusing.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree it should be more made more clear. Could be made by having a "fixtures" or "config fixtures" directory.

Empty file.
Loading
Loading