Test for Pruner

This commit is contained in:
Senad Uka
2018-08-13 18:54:12 +02:00
parent 5684e58826
commit 973f1e1093
15 changed files with 2888 additions and 53 deletions

View File

@@ -6,27 +6,26 @@ require_relative '../exceptions'
module Pruning
module API
# Handles general concers regarding API calls
class App < Sinatra::Base
before { content_type :json }
after { serialise_response }
set :show_exceptions, true
error Pruning::Exceptions::UnexpectedError do
error Pruning::Exceptions::UnexpectedError do
status 500
end
error Pruning::Exceptions::OriginCannotFindTheResource do
status 404
status 404
end
get '/' do
"Try /tree/:name"
'Try /tree/:name?indicator_ids[]=32&indicator_ids[]=31'
end
private
def serialise_response
return unless content_type == 'application/json'
response.body = [JSON(response.body)]

View File

@@ -7,17 +7,15 @@ require_relative '../exceptions'
module Pruning
module API
# Handles all tree related API requests
class Tree < App
get '/tree/:name' do
tree_repo = Pruning::Repos::Tree.new(RestClient, ENV['TREE_SOURCE_API_HOSTNAME'])
complete_tree = tree_repo.get(query.name)
pruner = Pruning::Processing::Pruner.new(complete_tree)
pruner.prune_tree(query.indicator_ids)
tree_repo = Pruning::Repos::Tree.new(RestClient,
ENV['TREE_SOURCE_API_HOSTNAME'])
complete_tree = tree_repo.get(query.name)
pruner = Pruning::Processing::Pruner.new(complete_tree)
pruner.prune_tree(query.indicator_ids.to_a)
end
end
end
end
end

View File

@@ -4,10 +4,9 @@ module Pruning
end
class OriginCannotFindTheResource < StandardError
end
end
class UnexpectedError < StandardError
end
end
end

View File

@@ -1,5 +1,6 @@
module Pruning
module HTTP
# Whitelists the URL query parameters
class Query < Struct.new(:name, :indicator_ids)
def initialize(params = {})
symbolised = params.map { |k, v| { k.to_sym => v } }.reduce({}, :merge)
@@ -7,9 +8,9 @@ module Pruning
value = symbolised.fetch(member, nil)
next if value.nil?
case member
when :indicator_ids then value.map(&->(indicator_id) { indicator_id.to_i } ) # break on purpose if indicator_ids is not an array
when :name then value.to_s.gsub(/[^A-Za-z]/,'')
else value
when :indicator_ids then value.map(&->(indicator_id) { indicator_id.to_i }) # break on purpose if indicator_ids is not an array
when :name then value.to_s.gsub(/[^A-Za-z]/, '')
else value
end
end
super(*values)

View File

@@ -1,27 +1,29 @@
module Pruning
module Processing
# Contains methods that store the tree and prune everything
# except the branches with requested indicator
class Pruner
def initialize(tree)
@tree = tree
end
def prune_tree(indicator_ids)
pruned_tree = @tree.dup
pruned_tree = @tree
prune_subtree(pruned_tree, indicator_ids)
pruned_tree
end
private
def prune_subtree(nodes, indicator_ids)
nodes_to_examine = nodes.dup
nodes_to_examine.each do |node|
if indicator_node?(node)
unwanted_indicator = !indicator_ids.include?(node['id'])
nodes.delete(node) if unwanted_indicator
else
has_no_wanted_indicators_in_children = prune_subtree(children(node), indicator_ids)
nodes.delete(node) if has_no_wanted_indicators_in_children
if indicator_node?(node)
indicator_not_wanted = !indicator_ids.include?(node['id'])
nodes.delete(node) if indicator_not_wanted
else
no_wanted_children = prune_subtree(children(node), indicator_ids)
nodes.delete(node) if no_wanted_children
end
end
nodes.empty?
@@ -29,11 +31,11 @@ module Pruning
def children(node)
node.fetch('sub_themes', false) ||
node.fetch('categories', false) ||
node.fetch('indicators', false) ||
[]
node.fetch('categories', false) ||
node.fetch('indicators', false) ||
[]
end
def indicator_node?(node)
children(node).empty?
end

View File

@@ -3,31 +3,36 @@ require 'retries'
require 'json'
require_relative '../exceptions'
NUMBER_OF_RETRIES = 3
module Pruning
module Repos
# Handles communication with origin server
# and all its problems
class Tree
def initialize(client=RestClient, base_url)
def initialize(client, base_url)
@client = client
@base_url = base_url
end
def get(name)
with_retries(max_tries: 3, rescue: [Pruning::Exceptions::ServerErrorOnOrigin]) do
with_retries(max_tries: NUMBER_OF_RETRIES, rescue: [Pruning::Exceptions::ServerErrorOnOrigin]) do
begin
resp = @client.get(url(name))
rescue RestClient::ExceptionWithResponse => e
if e.response.code != 404
raise Pruning::Exceptions::ServerErrorOnOrigin
else
raise Pruning::Exceptions::OriginCannotFindTheResource
end
rescue RestClient::ExceptionWithResponse => e
raise Pruning::Exceptions::ServerErrorOnOrigin if e.response.code != 404
raise Pruning::Exceptions::OriginCannotFindTheResource
end
return JSON(resp.body)
end
return JSON(resp.body)
end
raise Pruning::Exceptions::UnexpectedError
raise Pruning::Exceptions::UnexpectedError
end
private
private
def url(name)
"#{@base_url}/tree/#{name}"
end