spec/controllers/rpc_controller_spec.rb in marty-1.0.35 vs spec/controllers/rpc_controller_spec.rb in marty-1.0.36
- old
+ new
@@ -45,11 +45,11 @@
e =?
f =?
g = e * 5 + f
h = f + 1
ptest = p * 10
- result = [{"a": 123, "b": 456}, {"a": 789, "b": 101112}]
+ result = [{"a": p, "b": 456}, {"a": 789, "b": p}]
eof
sample_script5 = <<eof
A:
f =?
@@ -58,10 +58,12 @@
else if f == "Banana"
then 1
else if f == "Orange"
then 2
else 9
+ result = [{"a": "str", "b": 456}, {"a": 789, "b": "str"}]
+ result2 = [{"a": "str", "b": 456}, {"a": 789, "b": "str"}]
eof
sample_script6 = <<eof
A:
b =?
@@ -78,10 +80,17 @@
A:
b =?
res = 123
eof
+sample_script9 = <<eof
+A:
+ b =?
+ res = b + 1
+ result = [{"a": 1, "b": res}, {"a": 789, "b": res}]
+eof
+
script3_schema = <<eof
A:
pc = { "properties : {
"p" : { "type" : "integer" },
}
@@ -92,29 +101,82 @@
A:
d = { "properties" : {
"p" : { "type" : "integer" },
}
}
+ d_ = { "type" : "integer" }
g = { "properties" : {
"e" : { "type" : "integer" },
"f" : { "type" : "integer" },
}
}
+ g_ = { "type" : "integer" }
+
lc = { "properties" : {
"p" : { "type" : "integer" },
}
}
+
+ result = { "properties" : {
+ "p" : { "type" : "integer" },
+ }
+ }
+
+ result_ = {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object",
+ "properties": {
+ "a": { "type" : "integer" },
+ "b": { "type" : "integer" }
+ }
+ }
+ }
eof
script5_schema = <<eof
A:
res = { "properties" : {
"f" : { "pg_enum" : "FruitsEnum" },
}
}
+
+ result = { "properties" : {
+ "f" : { "pg_enum" : "FruitsEnum" },
+ }
+ }
+
+ result_ = { "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object",
+ "properties": {
+ "a": { "type" : "integer" },
+ "b": { "type" : "string" }
+ }
+ }
+ }
+
+ result2 = { "properties" : {
+ "f" : { "pg_enum" : "FruitsEnum" },
+ }
+ }
+
+ result2_ = { "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object",
+ "properties": {
+ "a": { "type" : "integer" },
+ "b": { "type" : "string" }
+ }
+ }
+ }
+
eof
script6_schema = <<eof
A:
res = { "properties" : {
@@ -137,11 +199,36 @@
"b" : { "pg_enum" : "Gemini::MiDurationType" },
}
}
eof
+script9_schema = <<eof
+A:
+ res = { "properties" : {
+ "b" : { "type" : "number" },
+ }
+ }
+ result = { "properties" : {
+ "b" : { "type" : "number" },
+ }
+ }
+
+ result_ = { "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object",
+ "properties": {
+ "a": { "type" : "integer" },
+ "b": { "type" : "integer" },
+ "c": { "type" : "string" }
+ },
+ "required" : ["a", "b", "c"]
+ }
+ }
+eof
+
describe Marty::RpcController do
before(:each) {
@routes = Marty::Engine.routes
# HACKY: 'params' param is special to the Rails controller test helper (at
@@ -160,16 +247,18 @@
"M4" => sample_script4,
"M5" => sample_script5,
"M6" => sample_script6,
"M7" => sample_script7,
"M8" => sample_script8,
+ "M9" => sample_script9,
"M3Schemas" => script3_schema,
"M4Schemas" => script4_schema,
"M5Schemas" => script5_schema,
"M6Schemas" => script6_schema,
"M7Schemas" => script7_schema,
"M8Schemas" => script8_schema,
+ "M9Schemas" => script9_schema,
}, Date.today + 1.minute)
@p1 = Marty::Posting.do_create("BASE", Date.today + 2.minute, 'a comment')
@t2 = Marty::Script.load_script_bodies({
@@ -413,19 +502,19 @@
script: "M4",
node: "A",
attrs: ["result"].to_json,
}
# puts 'Z'*40, request.inspect
- expect(response.body).to eq("a,b\r\n123,456\r\n789,101112\r\n")
+ expect(response.body).to eq("a,b\r\n10,456\r\n789,10\r\n")
end
it "returns an error message on missing schema script (csv)" do
Marty::ApiConfig.create!(script: "M1",
node: "A",
attr: nil,
logged: false,
- validated: true)
+ input_validated: true)
attrs = ["b"].to_json
params = {"a" => 5}.to_json
get 'evaluate', {
format: :csv,
script: "M1",
@@ -440,11 +529,11 @@
it "returns an error message on missing schema script (json)" do
Marty::ApiConfig.create!(script: "M1",
node: "A",
attr: nil,
logged: false,
- validated: true)
+ input_validated: true)
attrs = ["b"].to_json
params = {"a" => 5}.to_json
get 'evaluate', {
format: :json,
script: "M1",
@@ -462,49 +551,50 @@
it "returns an error message on missing attributes in schema script" do
Marty::ApiConfig.create!(script: "M4",
node: "A",
attr: nil,
logged: false,
- validated: true)
+ input_validated: true)
attrs = ["h"].to_json
params = {"f" => 5}.to_json
get 'evaluate', {
format: :csv,
script: "M4",
node: "A",
attrs: attrs,
params: params
}
- expect = "Schema error for M4/A attrs=h: Problem with schema\r\n"
- expect(response.body).to eq("error,#{expect}")
+ expect = "Schema error for M4/A attrs=h: Problem with schema"
+ expect(response.body).to include("error,#{expect}")
end
it "returns an error message on invalid schema" do
Marty::ApiConfig.create!(script: "M3",
node: "A",
attr: nil,
logged: false,
- validated: true)
+ input_validated: true)
attrs = ["pc"].to_json
params = {"p" => 5}.to_json
get 'evaluate', {
format: :csv,
script: "M3",
node: "A",
attrs: attrs,
params: params
}
- expect = "Schema error for M3/A attrs=pc: Problem with schema\r\n"
+ expect = "Schema error for M3/A attrs=pc: Problem with schema: "\
+ "syntax error M3Schemas:2\r\n"
expect(response.body).to eq("error,#{expect}")
end
it "returns a validation error when validating a single attribute" do
Marty::ApiConfig.create!(script: "M4",
node: "A",
attr: nil,
logged: false,
- validated: true)
+ input_validated: true)
attrs = ["d"].to_json
params = {"p" => "132"}.to_json
get 'evaluate', {
format: :csv,
script: "M4",
@@ -520,20 +610,21 @@
it "returns a validation error when validating multiple attributes" do
Marty::ApiConfig.create!(script: "M4",
node: "A",
attr: nil,
logged: false,
- validated: true)
+ input_validated: true,
+ output_validated: true)
attrs = ["d", "g"].to_json
params = {"p" => "132", "e" => "55", "f"=>"16"}.to_json
get 'evaluate', {
format: :csv,
script: "M4",
node: "A",
attrs: attrs,
params: params
- }
+ }
expect = '""d""=>[""The property \'#/p\' of type string did not '\
'match the following type: integer'
expect(response.body).to include(expect)
expect = '""g""=>[""The property \'#/e\' of type string did not '\
'match the following type: integer'
@@ -541,16 +632,129 @@
expect = 'The property \'#/f\' of type string did not '\
'match the following type: integer'
expect(response.body).to include(expect)
end
+ context "output_validation" do
+ before(:all) do
+ @db = SQLite3::Database.new(Marty::Log.logfile)
+ end
+ before(:each) do
+ @logid = @db.execute('select max(id) from log').first.first || 0 rescue 0
+ end
+ after(:all) do
+ @db.close
+ end
+ it "validates output" do
+ Marty::ApiConfig.create!(script: "M4",
+ node: "A",
+ attr: nil,
+ logged: false,
+ input_validated: true,
+ output_validated: true)
+ attrs = ["d", "g", "result"].to_json
+ params = {"p" => 132, "e" => 55, "f"=>16}.to_json
+ get 'evaluate', {
+ format: :json,
+ script: "M4",
+ node: "A",
+ attrs: attrs,
+ params: params
+ }
+ res_hash = JSON.parse(response.body)
+ expect(res_hash).to eq([135,291,[{"a"=>132,"b"=>456},
+ {"a"=>789,"b"=>132}]])
+ logs = Marty::Log.where("id > #{@logid}").to_a
+ expect(logs.count).to eq(0)
+ end
+
+ it "validates output (bad type, with strict/non strict errors)" do
+ Marty::ApiConfig.create!(script: "M5",
+ node: "A",
+ attr: nil,
+ logged: false,
+ input_validated: true,
+ output_validated: true,
+ strict_validate: true)
+ Marty::ApiConfig.create!(script: "M5",
+ node: "A",
+ attr: "result2",
+ logged: false,
+ input_validated: true,
+ output_validated: true,
+ strict_validate: false)
+ attrs = ["result", "result2"].to_json
+ params = {"f" => "Banana"}.to_json
+ get 'evaluate', {
+ format: :json,
+ script: "M5",
+ node: "A",
+ attrs: attrs,
+ params: params
+ }
+ res_hash = JSON.parse(response.body)
+ expect(res_hash[0]).to include("error")
+ expect1 = "The property '#/0/b' of type integer did not match the "\
+ "following type: string"
+ expect2 = "The property '#/0/a' of type string did not match the "\
+ "following type: integer"
+ expect(res_hash[0]["error"]).to include(expect1)
+ expect(res_hash[0]["error"]).to include(expect2)
+
+ logs = Marty::Log.where("id > #{@logid}").to_a
+ expect(logs.count).to eq(2)
+ expect(logs[0].message).to eq("API M5:A.result")
+ expect(logs[1].message).to eq("API M5:A.result2")
+ logs.each do |ml|
+ expect(ml.details).to include(expect1)
+ expect(ml.details).to include(expect2)
+ expect(ml.details).to include(
+ ":data=>[{\"a\"=>\"str\", \"b\"=>456}, {\"a\"=>789, \"b\"=>\"str\"}]}")
+ end
+ end
+
+ it "validates output (missing item)" do
+ logid = @db.execute('select max(id) from log').first.first rescue 0
+ Marty::ApiConfig.create!(script: "M9",
+ node: "A",
+ attr: nil,
+ logged: false,
+ input_validated: true,
+ output_validated: true,
+ strict_validate: true)
+ attrs = ["result"].to_json
+ params = {"b" => 122}.to_json
+ get 'evaluate', {
+ format: :json,
+ script: "M9",
+ node: "A",
+ attrs: attrs,
+ params: params
+ }
+ res_hash = JSON.parse(response.body)
+ expect(res_hash[0]).to include("error")
+ expect1 = "The property '#/0' did not contain a required property of 'c'"
+ expect2 = "The property '#/1' did not contain a required property of 'c'"
+ expect(res_hash[0]["error"]).to include(expect1)
+ expect(res_hash[0]["error"]).to include(expect2)
+
+ logs = Marty::Log.where("id > #{@logid}").to_a
+ expect(logs.count).to eq(1)
+ expect(logs[0].message).to eq("API M9:A.result")
+ expect(logs[0].details).to include(expect1)
+ expect(logs[0].details).to include(expect2)
+ expect(logs[0].details).to include(
+ ":data=>[{\"a\"=>1, \"b\"=>123}, {\"a\"=>789, \"b\"=>123}]")
+ end
+ end
+
it "validates schema" do
Marty::ApiConfig.create!(script: "M4",
node: "A",
attr: nil,
logged: false,
- validated: true)
+ input_validated: true)
attrs = ["lc"].to_json
params = {"p" => 5}.to_json
get 'evaluate', {
format: :csv,
script: "M4",
@@ -564,21 +768,21 @@
it "catches JSON::Validator exceptions" do
Marty::ApiConfig.create!(script: "M6",
node: "A",
attr: nil,
logged: false,
- validated: true)
+ input_validated: true)
attrs = ["res"].to_json
params = {"b" => 5.22}.to_json
get 'evaluate', {
format: :json,
script: "M6",
node: "A",
attrs: attrs,
params: params
}
- expect = 'The property \'#/properties/b/type\' of type string '\
+ expect = 'res: The property \'#/properties/b/type\' of type string '\
'did not match one or more of the required schemas'
res_hsh = JSON.parse(response.body)
expect(res_hsh.keys.size).to eq(1)
expect(res_hsh.keys[0]).to eq("error")
expect(res_hsh.values[0]).to eq(expect)
@@ -592,11 +796,11 @@
it "validates schema with a pg_enum (Positive)" do
Marty::ApiConfig.create!(script: "M5",
node: "A",
attr: nil,
logged: false,
- validated: true)
+ input_validated: true)
attrs = ["res"].to_json
params = {"f" => "Banana"}.to_json
get 'evaluate', {
format: :csv,
script: "M5",
@@ -610,11 +814,11 @@
it "validates schema with a pg_enum (Negative)" do
Marty::ApiConfig.create!(script: "M5",
node: "A",
attr: nil,
logged: false,
- validated: true)
+ input_validated: true)
attrs = ["res"].to_json
params = {"f" => "Beans"}.to_json
get 'evaluate', {
format: :csv,
script: "M5",
@@ -629,11 +833,11 @@
it "validates schema with a non-existant enum" do
Marty::ApiConfig.create!(script: "M7",
node: "A",
attr: nil,
logged: false,
- validated: true)
+ input_validated: true)
attrs = ["res"].to_json
params = {"b" => "MemberOfANonExistantEnum"}.to_json
get 'evaluate', {
format: :json,
script: "M7",
@@ -651,10 +855,10 @@
it "validates pgenum with capitalization issues" do
Marty::ApiConfig.create!(script: "M8",
node: "A",
attr: nil,
logged: false,
- validated: true)
+ input_validated: true)
skip "pending until a solution is found that handles "\
"autoload issues involving constantize"
attrs = ["res"].to_json
params = {"b" => "Annual"}.to_json
get 'evaluate', {