From 258b877f5f7eb94cf1c1eb349d6e35c089afabde Mon Sep 17 00:00:00 2001 From: George Dietrich Date: Wed, 30 Jun 2021 17:24:16 -0400 Subject: [PATCH 1/3] Handle EOF input from jq Ensure process is successful unless otherwise specified --- spec/converters/simple_yaml_spec.cr | 8 ++++++++ spec/converters/xml_spec.cr | 3 +-- spec/converters/yaml_spec.cr | 8 ++++++++ spec/oq_spec.cr | 9 +++------ spec/spec_helper.cr | 9 ++++++++- src/converters/yaml.cr | 3 +++ 6 files changed, 31 insertions(+), 9 deletions(-) diff --git a/spec/converters/simple_yaml_spec.cr b/spec/converters/simple_yaml_spec.cr index f7a9f43..4dffc1f 100644 --- a/spec/converters/simple_yaml_spec.cr +++ b/spec/converters/simple_yaml_spec.cr @@ -333,6 +333,14 @@ describe OQ::Converters::SimpleYAML do end end end + + describe "when the jq filter doesn't return data" do + it "should return an empty string" do + run_binary(%([{"name":"foo"}]), args: ["-i", "simpleyaml", "-o", "simpleyaml", %<.[] | select(.name != "foo")>]) do |output| + output.should eq("") + end + end + end end describe Object do diff --git a/spec/converters/xml_spec.cr b/spec/converters/xml_spec.cr index 462bf1c..a1be32b 100644 --- a/spec/converters/xml_spec.cr +++ b/spec/converters/xml_spec.cr @@ -203,9 +203,8 @@ describe OQ::Converters::XML do describe "should raise if invalid" do it "should output correctly" do - run_binary(%(]) do |output| + output.should eq("") + end + end + end end describe Object do diff --git a/spec/oq_spec.cr b/spec/oq_spec.cr index 428515d..b45da56 100644 --- a/spec/oq_spec.cr +++ b/spec/oq_spec.cr @@ -260,27 +260,24 @@ describe OQ do describe "when there is a jq error" do it "should return the error and correct exit code" do - run_binary(input: ARRAY_JSON_OBJECT, args: [".names | .[] | .name"]) do |_, status, error| + run_binary(input: ARRAY_JSON_OBJECT, args: [".names | .[] | .name"], success: false) do |_, _, error| error.should eq %(jq: error (at :0): Cannot index number with string "name"\n) - status.exit_code.should eq 1 end end end describe "with an invalid input format" do it "should return the error and correct exit code" do - run_binary(input: SIMPLE_JSON_OBJECT, args: ["-i", "foo"]) do |_, status, error| + run_binary(input: SIMPLE_JSON_OBJECT, args: ["-i", "foo"], success: false) do |_, _, error| error.should eq %(Invalid input format: 'foo'\n) - status.exit_code.should eq 1 end end end describe "with an invalid output format" do it "should return the error and correct exit code" do - run_binary(input: SIMPLE_JSON_OBJECT, args: ["-o", "foo"]) do |_, status, error| + run_binary(input: SIMPLE_JSON_OBJECT, args: ["-o", "foo"], success: false) do |_, _, error| error.should eq %(Invalid output format: 'foo'\n) - status.exit_code.should eq 1 end end end diff --git a/spec/spec_helper.cr b/spec/spec_helper.cr index c40ff24..7c24a29 100644 --- a/spec/spec_helper.cr +++ b/spec/spec_helper.cr @@ -2,11 +2,18 @@ require "spec" require "../src/oq" # Runs the the binary with the given *name* and *args*. -def run_binary(input : String? = nil, name : String = "bin/oq", args : Array(String) = [] of String, &block : String, Process::Status, String -> Nil) +def run_binary(input : String? = nil, name : String = "bin/oq", args : Array(String) = [] of String, *, success : Bool = true, file = __FILE__, line = __LINE__, & : String, Process::Status, String -> Nil) buffer_io = IO::Memory.new error_io = IO::Memory.new input_io = IO::Memory.new input_io << input if input status = Process.run(name, args, output: buffer_io, input: input_io.rewind, error: error_io) + + if success + status.success?.should be_true, file: file, line: line + else + status.success?.should_not be_true, file: file, line: line + end + yield buffer_io.to_s, status, error_io.to_s end diff --git a/src/converters/yaml.cr b/src/converters/yaml.cr index 0a94e60..3e75e73 100644 --- a/src/converters/yaml.cr +++ b/src/converters/yaml.cr @@ -11,6 +11,9 @@ module OQ::Converters::YAML json = ::JSON::PullParser.new input yaml = ::YAML::Builder.new output + # Return early is there is no JSON to be read. + return if json.kind.eof? + yaml.stream do yaml.document do loop do From 4f6372a77ed645149c2b58730a91582ff2124ae5 Mon Sep 17 00:00:00 2001 From: George Dietrich Date: Wed, 30 Jun 2021 20:53:15 -0400 Subject: [PATCH 2/3] Use the expectation --- spec/converters/simple_yaml_spec.cr | 2 +- spec/converters/yaml_spec.cr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/converters/simple_yaml_spec.cr b/spec/converters/simple_yaml_spec.cr index 4dffc1f..fc7b952 100644 --- a/spec/converters/simple_yaml_spec.cr +++ b/spec/converters/simple_yaml_spec.cr @@ -337,7 +337,7 @@ describe OQ::Converters::SimpleYAML do describe "when the jq filter doesn't return data" do it "should return an empty string" do run_binary(%([{"name":"foo"}]), args: ["-i", "simpleyaml", "-o", "simpleyaml", %<.[] | select(.name != "foo")>]) do |output| - output.should eq("") + output.should be_empty end end end diff --git a/spec/converters/yaml_spec.cr b/spec/converters/yaml_spec.cr index b288ce6..9a2e676 100644 --- a/spec/converters/yaml_spec.cr +++ b/spec/converters/yaml_spec.cr @@ -413,7 +413,7 @@ describe OQ::Converters::YAML do describe "when the jq filter doesn't return data" do it "should return an empty string" do run_binary(%([{"name":"foo"}]), args: ["-i", "yaml", "-o", "yaml", %<.[] | select(.name != "foo")>]) do |output| - output.should eq("") + output.should be_empty end end end From 69d2450b79b3bef199f0fff3216b865995da6e32 Mon Sep 17 00:00:00 2001 From: George Dietrich Date: Sun, 1 Aug 2021 16:04:45 -0400 Subject: [PATCH 3/3] Manually handle the EOF exception Can be removed after next Crystal release --- src/converters/yaml.cr | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/converters/yaml.cr b/src/converters/yaml.cr index 3e75e73..109b4ba 100644 --- a/src/converters/yaml.cr +++ b/src/converters/yaml.cr @@ -8,7 +8,18 @@ module OQ::Converters::YAML # ameba:disable Metrics/CyclomaticComplexity def serialize(input : IO, output : IO, **args) : Nil - json = ::JSON::PullParser.new input + # TODO: Remove this in favor of the .eof? check after + # https://github.com/crystal-lang/crystal/pull/10864 is released. + begin + json = ::JSON::PullParser.new input + rescue ex : ::JSON::ParseException + if (message = ex.message) && (message.includes? "Unexpected token: ") + return + end + + raise ex + end + yaml = ::YAML::Builder.new output # Return early is there is no JSON to be read.