# frozen_string_literal: true # See ./README.md for standalone usage # TODO: remember to set up and test the --host option after all require "cheetah" require "webrick" # @param filename relative to git repo root # @return usable for this suite def fixture(filename) # the tests specify the paths relative to repo root # but we run in service/ "../" + filename end # @param filename relative to git repo root # @return usable for this suite, absolute def abs_fixture(filename) File.absolute_path(fixture(filename)) end def cheetah_kwargs { stdout: :capture, stderr: :capture, allowed_exitstatus: 0..255 } end WEB_SERVER_PORT = 8000 # @return [HTTPServer] def web_server_start root = abs_fixture(".") server = WEBrick::HTTPServer.new(Port: WEB_SERVER_PORT, DocumentRoot: root) Thread.new { server.start } server end def web_server_shutdown(server) server.shutdown end # needs declarations: # command [Array] like ["agama", "profile", "validate"] shared_examples "accepts input in 3 ways" do |filename, stdout_match, stderr_match| context "with #{filename} as path" do it "output matches" do cmd = [*command, fixture(filename)] stdout, stderr = Cheetah.run(*cmd, **cheetah_kwargs) expect(stdout).to include(stdout_match) expect(stderr).to include(stderr_match) end end context "with #{filename} as http URL" do it "output matches" do url = "http://localhost:#{WEB_SERVER_PORT}/#{filename}" cmd = [*command, url] stdout, stderr = Cheetah.run(*cmd, **cheetah_kwargs) expect(stdout).to include(stdout_match) expect(stderr).to include(stderr_match) end end context "with #{filename} as stdin" do it "output matches" do input = File.read(fixture(filename)) cmd = [*command, "-"] stdout, stderr = Cheetah.run(*cmd, stdin: input, **cheetah_kwargs) expect(stdout).to include(stdout_match) expect(stderr).to include(stderr_match) end end end describe "agama config" do before(:all) do @web_server = web_server_start end after(:all) do web_server_shutdown(@web_server) end describe "validate:" do let(:command) { ["agama", "config", "validate"] } context "valid profile" do include_examples \ "accepts input in 3 ways", \ "rust/agama-lib/share/examples/profile_tw_minimal.json", \ "", \ "is valid" end context "valid profile with space in path" do include_examples \ "accepts input in 3 ways", \ "rust/agama-lib/share/examples space/profile_tw_minimal.json", \ "", \ "is valid" end # Rust Url library will see the percent # and wrongly think that the path does not need escaping. # This is a bug but its impact is low. xcontext "valid profile with percent in path" do include_examples \ "accepts input in 3 ways", \ "rust/agama-lib/share/examples%20percent/profile_tw_minimal.json", \ "", \ "is valid" end context "invalid profile" do include_examples \ "accepts input in 3 ways", \ "rust/agama-lib/share/examples/profile_tw_invalid.json", \ "", \ "* Additional properties are not allowed ('ID' was unexpected). /product" end end describe "generate:" do context "config via stdin contains relative URL references:" do let(:profile_body) do json = <<~JSON { "scripts": { "postPartitioning": [ { "name": "foo", "url": "my-script.sh" } ] } } JSON json end it "they are resolved" do output = Cheetah.run("agama", "config", "generate", "-", stdout: :capture, stdin: profile_body) expect(output).to include("file:///") expect(output).to include("/service/my-script.sh") end end context "config via file contains relative URL references:" do let(:filename) { "rust/agama-lib/share/examples/post-script-ref.jsonnet" } it "they are resolved" do output = Cheetah.run("agama", "config", "generate", fixture(filename), stdout: :capture) expect(output).to include("file:///") expect(output).to include("/rust/agama-lib/share/examples/enable-sshd.sh") expect(output).to_not include("..") end end context "jsonnet valid (by stdin)" do let(:profile_body) { '{product: {id: "Tumbleweed"}}' } it "is evaluated and validity reported" do stdout, stderr = Cheetah.run("agama", "config", "generate", "-", stdout: :capture, stderr: :capture, stdin: profile_body) expected = <<~JSON { "product": { "id": "Tumbleweed" } } JSON expect(stdout).to eq(expected) expect(stderr).to include("profile is valid") end end context "jsonnet invalid (by stdin)" do let(:profile_body) { '{product: {uh: "oh"}}' } it "is evaluated and invalidity reported" do stdout, stderr = Cheetah.run("agama", "config", "generate", "-", stdout: :capture, stderr: :capture, stdin: profile_body) # NOTE: 3 space indent here expected = <<~JSON { "product": { "uh": "oh" } } JSON expect(stdout).to eq(expected) expect(stderr).to include("profile is not valid") expect(stderr).to include("'uh' was unexpected") expect(stderr).to include("\"id\" is a required property") end end end describe "generate (autoyast):" do let(:command) { ["agama", "config", "generate"] } let(:output_match) do json = <<~JSON { "software": { "patterns": [ "base" ], "packages": [] }, "product": { "id": "Tumbleweed" } } JSON json end # I want to test that YaST special schemes like label: # are handled, but unable to make them work in my testing environment xcontext "XML, with a YaST special URL" do let(:filename) { "service/test/fixtures/profiles/trivial_tw.xml" } let(:label_url) { "label://mylabel#{abs_fixture(filename)}" } end context "XML, with path" do let(:filename) { "service/test/fixtures/profiles/trivial_tw.xml" } it "output matches" do path = fixture(filename) output = Cheetah.run(*command, path, stdout: :capture) expect(output).to include(output_match) end end context "XML, with file:/// URL" do let(:filename) { "service/test/fixtures/profiles/trivial_tw.xml" } it "output matches" do url = "file://" + abs_fixture(filename) output = Cheetah.run(*command, url, stdout: :capture) expect(output).to include(output_match) end end context "ERB, with file:/// URL" do let(:filename) { "service/test/fixtures/profiles/trivial_tw.xml.erb" } it "output matches" do url = "file://" + abs_fixture(filename) output = Cheetah.run(*command, url, stdout: :capture) expect(output).to include(output_match) end end # I get a deadlock because two processes want the libstorage lock. why? xcontext ".../, with file:/// URL" do let(:filename) { "service/test/fixtures/profiles/profile/" } it "output matches" do url = "file://" + abs_fixture(filename) output = Cheetah.run(*command, url, stdout: :capture) # this claim is too weak but the test needs to be fixed first expect(output).to include("Tumbleweed") end end end end