From 8b559f0a6edb161720a640e93d8b47d8e216145b Mon Sep 17 00:00:00 2001 From: Keenan Brock Date: Wed, 22 May 2024 10:08:55 -0400 Subject: [PATCH 01/10] add tests for runner --- spec/runner_spec.rb | 78 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 spec/runner_spec.rb diff --git a/spec/runner_spec.rb b/spec/runner_spec.rb new file mode 100644 index 00000000..8b80e306 --- /dev/null +++ b/spec/runner_spec.rb @@ -0,0 +1,78 @@ +RSpec.describe Floe::Runner do + let(:runner) { described_class.new } + + describe ".register_scheme", ".for_resource" do + it "registers a scheme" do + x = Class.new + y = Class.new + + described_class.register_scheme("x", x) + described_class.register_scheme("y", y) + + expect(described_class.for_resource("x://abc")).to eq(x) + expect(described_class.for_resource("y://abc")).to eq(y) + end + + it "overrides a scheme" do + x = Class.new + x2 = Class.new + + described_class.register_scheme("x", x) + described_class.register_scheme("x", x2) + + expect(described_class.for_resource("x://abc")).to eq(x2) + end + + it "resolves a scheme lambda" do + x = Class.new + + described_class.register_scheme("x", -> { x }) + + expect(described_class.for_resource("x://abc")).to eq(x) + end + end + + # interface methods (not implemented) + + describe "#run_async!" do + it "is not implemented" do + expect { runner.run_async!("local://resource") }.to raise_error(NotImplementedError) + end + end + + describe "#status!" do + it "is not implemented" do + expect { runner.status!({}) }.to raise_error(NotImplementedError) + end + end + + describe "#running?" do + it "is not implemented" do + expect { runner.running?({}) }.to raise_error(NotImplementedError) + end + end + + describe "#success?" do + it "is not implemented" do + expect { runner.success?({}) }.to raise_error(NotImplementedError) + end + end + + describe "#output" do + it "is not implemented" do + expect { runner.output({}) }.to raise_error(NotImplementedError) + end + end + + describe "#cleanup" do + it "is not implemented" do + expect { runner.cleanup({}) }.to raise_error(NotImplementedError) + end + end + + describe "#wait" do + it "is not implemented" do + expect { runner.wait }.to raise_error(NotImplementedError) + end + end +end From 6d13bf88cf1dd13355f66b8abf776270ce744724 Mon Sep 17 00:00:00 2001 From: Keenan Brock Date: Wed, 22 May 2024 10:11:42 -0400 Subject: [PATCH 02/10] drop unused Task#next_state last usage: f019789800e55b8a390d --- lib/floe/workflow/states/task.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/floe/workflow/states/task.rb b/lib/floe/workflow/states/task.rb index 47c3e522..c0a7e626 100644 --- a/lib/floe/workflow/states/task.rb +++ b/lib/floe/workflow/states/task.rb @@ -142,10 +142,6 @@ def parse_output(output) rescue JSON::ParserError nil end - - def next_state - end? ? nil : @next - end end end end From f84a8259ca2dd6821baee2c528e3ff5d24a1ef93 Mon Sep 17 00:00:00 2001 From: Keenan Brock Date: Wed, 22 May 2024 10:47:23 -0400 Subject: [PATCH 03/10] test for ChoiceRule abstract implementation --- spec/workflow/choice_rule_spec.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/spec/workflow/choice_rule_spec.rb b/spec/workflow/choice_rule_spec.rb index b08209ad..92e287f5 100644 --- a/spec/workflow/choice_rule_spec.rb +++ b/spec/workflow/choice_rule_spec.rb @@ -3,6 +3,14 @@ let(:subject) { described_class.build(payload).true?(context, input) } let(:context) { {} } + context "Abstract Interface" do + let(:input) { {} } + let(:subject) { described_class.new({}).true?(context, input) } + it "is not implemented" do + expect { subject }.to raise_exception(NotImplementedError) + end + end + context "Boolean Expression" do context "Not" do let(:payload) { {"Not" => {"Variable" => "$.foo", "StringEquals" => "bar"}, "Next" => "FirstMatchState"} } From 66690a5c4ee3426e49fc0dc3188ecbf350ec7c0b Mon Sep 17 00:00:00 2001 From: Keenan Brock Date: Wed, 22 May 2024 10:57:44 -0400 Subject: [PATCH 04/10] specs for payload_template --- spec/workflow/payload_template_spec.rb | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/spec/workflow/payload_template_spec.rb b/spec/workflow/payload_template_spec.rb index 49197829..7b540509 100644 --- a/spec/workflow/payload_template_spec.rb +++ b/spec/workflow/payload_template_spec.rb @@ -2,12 +2,21 @@ let(:subject) { described_class.new(payload) } describe "#value" do + context "with static array" do + let(:payload) { ["a", 2] } + let(:context) { {} } + + it "returns the original value" do + expect(subject.value(context)).to eq(["a", 2]) + end + end + context "with static values" do - let(:payload) { {"foo" => "bar", "bar" => "$.baz"} } + let(:payload) { {"foo" => "bar", "bar" => "$.baz", "baz" => 3} } let(:context) { {} } it "returns the original value" do - expect(subject.value(context)).to eq({"foo" => "bar", "bar" => "$.baz"}) + expect(subject.value(context)).to eq({"foo" => "bar", "bar" => "$.baz", "baz" => 3}) end end From 44976ac8b6b8f1e61b5b962ea4fb91361e1cc1d4 Mon Sep 17 00:00:00 2001 From: Keenan Brock Date: Wed, 22 May 2024 22:40:32 -0400 Subject: [PATCH 05/10] test floe log setters --- spec/floe_spec.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 spec/floe_spec.rb diff --git a/spec/floe_spec.rb b/spec/floe_spec.rb new file mode 100644 index 00000000..5af6ea7c --- /dev/null +++ b/spec/floe_spec.rb @@ -0,0 +1,13 @@ +RSpec.describe Floe do + describe "logger=", "logger" do + it "sets the logger" do + old_logger = Floe.logger + new_logger = "abc" + + Floe.logger = new_logger + expect(Floe.logger).to eq(new_logger) + + Floe.logger = old_logger + end + end +end From 4825d01d3e9b405091d0228b4d6497ad05009645 Mon Sep 17 00:00:00 2001 From: Keenan Brock Date: Wed, 22 May 2024 22:43:14 -0400 Subject: [PATCH 06/10] Drop ReferencePath.get and set --- lib/floe/workflow/reference_path.rb | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/lib/floe/workflow/reference_path.rb b/lib/floe/workflow/reference_path.rb index 5650145a..2633c0fa 100644 --- a/lib/floe/workflow/reference_path.rb +++ b/lib/floe/workflow/reference_path.rb @@ -3,16 +3,6 @@ module Floe class Workflow class ReferencePath < Path - class << self - def get(payload, context) - new(payload).get(context) - end - - def set(payload, context, value) - new(payload).set(context, value) - end - end - attr_reader :path def initialize(*) From ef7d04e50167abd54f7a6be0f437bf4367751325 Mon Sep 17 00:00:00 2001 From: Keenan Brock Date: Wed, 22 May 2024 22:50:02 -0400 Subject: [PATCH 07/10] test Context#success? This is only used by bin/floe --- spec/workflow/context_spec.rb | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/spec/workflow/context_spec.rb b/spec/workflow/context_spec.rb index 74753929..1111d6c1 100644 --- a/spec/workflow/context_spec.rb +++ b/spec/workflow/context_spec.rb @@ -78,6 +78,8 @@ it "ended" do ctx.state["Output"] = input.dup + ctx.execution["StartTime"] ||= Time.now.utc + ctx.execution["EndTime"] ||= Time.now.utc expect(ctx.failed?).to eq(false) end @@ -91,6 +93,34 @@ end end + describe "#success?" do + it "new context" do + expect(ctx.success?).to eq(false) + end + + it "started" do + ctx.state["Output"] = {} + + expect(ctx.success?).to eq(false) + end + + it "ended" do + ctx.state["Output"] = input.dup + ctx.execution["StartTime"] ||= Time.now.utc + ctx.execution["EndTime"] ||= Time.now.utc + + expect(ctx.success?).to eq(true) + end + + it "ended with error" do + ctx.execution["StartTime"] ||= Time.now.utc + ctx.execution["EndTime"] ||= Time.now.utc + ctx.output = {"Cause" => "issue", "Error" => "error"} + + expect(ctx.success?).to eq(false) + end + end + describe "#input" do it "started" do ctx.state["Input"] = input From 6cc0282b0502e68b736a25768344538188db16ff Mon Sep 17 00:00:00 2001 From: Keenan Brock Date: Wed, 22 May 2024 22:54:22 -0400 Subject: [PATCH 08/10] test invalid state type --- spec/workflow_spec.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spec/workflow_spec.rb b/spec/workflow_spec.rb index d69bc6cb..52dc1085 100644 --- a/spec/workflow_spec.rb +++ b/spec/workflow_spec.rb @@ -34,6 +34,10 @@ expect { described_class.new(payload) }.to raise_error(Floe::InvalidWorkflowError, "Missing field \"States\"") end + it "raises an exception for invalid States" do + expect { make_workflow(ctx, {"FirstState" => {"Type" => "Invalid"}}) }.to raise_error(Floe::InvalidWorkflowError, "Invalid state type: [Invalid]") + end + it "raises an exception for missing StartAt" do payload = {"Comment" => "Test", "States" => {}} From 69a0a9638d19ef0df6548b4d34eefd661d649f2a Mon Sep 17 00:00:00 2001 From: Keenan Brock Date: Thu, 23 May 2024 14:03:37 -0400 Subject: [PATCH 09/10] test State#finished? --- spec/workflow/state_spec.rb | 45 +++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 spec/workflow/state_spec.rb diff --git a/spec/workflow/state_spec.rb b/spec/workflow/state_spec.rb new file mode 100644 index 00000000..d340d896 --- /dev/null +++ b/spec/workflow/state_spec.rb @@ -0,0 +1,45 @@ +RSpec.describe Floe::Workflow::State do + let(:input) { {} } + let(:ctx) { Floe::Workflow::Context.new(:input => input) } + let(:state) { workflow.current_state } + # picked a state that doesn't instantly finish + let(:workflow) { make_workflow(ctx, {"WaitState" => {"Type" => "Wait", "Seconds" => 1, "Next" => "SuccessState"}, "SuccessState" => {"Type" => "Succeed"}}) } + + describe "#started?" do + it "is not started yet" do + expect(state.started?).to eq(false) + end + + it "is started" do + state.start(ctx.input) + expect(state.started?).to eq(true) + end + + it "is finished" do + state.start(ctx.input) + state.finish + + state.start(ctx.input) + expect(state.started?).to eq(true) + end + end + + describe "#finished?" do + it "is not started yet" do + expect(state.finished?).to eq(false) + end + + it "is started" do + state.start(ctx.input) + expect(state.finished?).to eq(false) + end + + it "is finished" do + state.start(ctx.input) + state.finish + + state.start(ctx.input) + expect(state.finished?).to eq(true) + end + end +end From 2f504f1727cd9f27c53c212ea1cea912464f79af Mon Sep 17 00:00:00 2001 From: Keenan Brock Date: Wed, 22 May 2024 23:00:54 -0400 Subject: [PATCH 10/10] test workflow invalid payload --- spec/workflow_spec.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spec/workflow_spec.rb b/spec/workflow_spec.rb index 52dc1085..8c10bf06 100644 --- a/spec/workflow_spec.rb +++ b/spec/workflow_spec.rb @@ -62,6 +62,10 @@ expect { described_class.new(payload) }.to raise_error(Floe::InvalidWorkflowError, /must be less than or equal to 80 characters/) end + + it "raises an exception for invalid context" do + expect { described_class.new(make_payload({"Start" => {"Type" => "Success"}}), "abc") }.to raise_error(Floe::InvalidWorkflowError, /unexpected token/) + end end describe "#run_nonblock" do