From 63fcd8f8feed58af4b1e1ff0e5fdaa09791c9596 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Thu, 8 Mar 2012 15:23:43 +0000 Subject: improved integration of error reports, call stack added as errorDetails --- lib/error.rb | 147 ++++++++++++++------------------------------- lib/opentox-client.rb | 16 +++++ lib/opentox.rb | 118 ++++++++++++++++++++++++------------ lib/overwrite.rb | 55 ++++++++++++----- lib/rest-client-wrapper.rb | 122 +++++-------------------------------- lib/task.rb | 37 ++++-------- test/dataset.rb | 44 ++++++-------- test/error.rb | 2 +- test/feature.rb | 4 +- test/task.rb | 6 +- 10 files changed, 236 insertions(+), 315 deletions(-) diff --git a/lib/error.rb b/lib/error.rb index 2033c1e..0ab2c73 100644 --- a/lib/error.rb +++ b/lib/error.rb @@ -1,24 +1,27 @@ require 'open4' -# adding additional fields to Exception class to format errors according to OT-API +# add additional fields to Exception class to format errors according to OT-API class RuntimeError - attr_accessor :report, :http_code - def initialize message + attr_accessor :http_code, :uri + def initialize message, uri=nil super message - self.set_backtrace message.backtrace if message.is_a? Exception + @uri = uri @http_code ||= 500 - puts self.class - @report = OpenTox::ErrorReport.create self - $logger.error "\n"+@report.to_turtle + $logger.error "\n"+self.report.to_turtle + end + + def report + # TODO: remove kludge for old task services + OpenTox::ErrorReport.new(@http_code, self) end end module OpenTox class Error < RuntimeError - def initialize code, message + def initialize code, message, uri=nil @http_code = code - super message + super message, uri end end @@ -35,15 +38,16 @@ module OpenTox }.each do |klass,code| # create error classes c = Class.new Error do - define_method :initialize do |message| - super code, message + define_method :initialize do |message, uri=nil| + super code, message, uri end end OpenTox.const_set klass,c # define global methods for raising errors, eg. bad_request_error Object.send(:define_method, klass.underscore.to_sym) do |message| - raise c.new message + defined?(@uri) ? uri = @uri : uri=nil + raise c, message, uri end end @@ -53,61 +57,41 @@ module OpenTox def initialize request, response, message @request = request @response = response - super 502, message + super 502, message, request.url end end + # TODO: create reports directly from errors, requires modified task service class ErrorReport - - attr_accessor :rdf # RDF Graph - attr_accessor :http_code # TODO: remove when task service is fixed - - def initialize - @rdf = RDF::Graph.new - end - - # creates a error report object, from an ruby-exception object - # @param [Exception] error - def self.create error - report = ErrorReport.new - subject = RDF::Node.new - report.rdf << [subject, RDF.type, RDF::OT.ErrorReport] - message = error.message - errorDetails = "" - if error.respond_to? :request - report.rdf << [subject, RDF::OT.actor, error.request.url ] - errorDetails += "REST paramenters:\n#{error.request.args.inspect}" - end - error.respond_to?(:http_code) ? statusCode = error.http_code : statusCode = 500 - puts error.inspect - if error.respond_to? :response - statusCode = error.response.code if error.response - message = error.response.body - end - statusCode = error.http_code if error.respond_to? :http_code - report.rdf << [subject, RDF::OT.statusCode, statusCode ] - report.rdf << [subject, RDF::OT.errorCode, error.class.to_s ] - # TODO: remove kludge for old task services - report.http_code = statusCode - report.rdf << [subject, RDF::OT.message , message ] - errorDetails += "\nBacktrace:\n" + error.backtrace.short_backtrace if error.respond_to?(:backtrace) and error.backtrace - report.rdf << [subject, RDF::OT.errorDetails, errorDetails ] - # TODO Error cause - #report.rdf << [subject, OT.errorCause, error.report] if error.respond_to?(:report) and !error.report.empty? - report + def initialize http_code, error + @http_code = http_code + #@report = report#.to_yaml + @report = {} + @report[RDF::OT.actor] = error.uri + @report[RDF::OT.message] = error.message + @report[RDF::OT.statusCode] = @http_code + @report[RDF::OT.errorCode] = error.class.to_s + @report[RDF::OT.errorDetails] = caller.collect{|line| line unless line =~ /#{File.dirname(__FILE__)}/}.compact.join("\n") + @report[RDF::OT.errorDetails] += "REST paramenters:\n#{error.request.args.inspect}" if defined? error.request + @report[RDF::OT.message] += "\n" + error.response.body if defined? error.response + # TODO fix Error cause + #report[RDF::OT.errorCause] = @report if defined?(@report) end - def actor=(uri) - # TODO: test actor assignement (in opentox-server) - subject = RDF::Query.execute(@rdf) do - pattern [:subject, RDF.type, RDF::OT.ErrorReport] - end.limit(1).select(:subject) - @rdf << [subject, RDF::OT.actor, uri] - end - # define to_ and self.from_ methods for various rdf formats - [:rdfxml,:ntriples,:turtle].each do |format| + RDF_FORMATS.each do |format| + + send :define_method, "to_#{format}".to_sym do + rdf = RDF::Writer.for(format).buffer do |writer| + subject = RDF::Node.new + @report.each do |predicate,object| + writer << [subject, predicate, object] if object + end + end + rdf + end +=begin define_singleton_method "from_#{format}".to_sym do |rdf| report = ErrorReport.new RDF::Reader.for(format).new(rdf) do |reader| @@ -115,50 +99,7 @@ module OpenTox end report end - - send :define_method, "to_#{format}".to_sym do - rdfxml = RDF::Writer.for(format).buffer do |writer| - @rdf.each{|statement| writer << statement} - end - rdfxml - end - end - - end -end - -# overwrite backtick operator to catch system errors -module Kernel - - # Override raises an error if _cmd_ returns a non-zero exit status. - # Returns stdout if _cmd_ succeeds. Note that these are simply concatenated; STDERR is not inline. - def ` cmd - stdout, stderr = '' - status = Open4::popen4(cmd) do |pid, stdin_stream, stdout_stream, stderr_stream| - stdout = stdout_stream.read - stderr = stderr_stream.read - end - raise stderr.strip if !status.success? - return stdout - rescue Exception - internal_server_error $! - end - - alias_method :system!, :system - - def system cmd - `#{cmd}` - return true - end -end - -class Array - def short_backtrace - short = [] - each do |c| - break if c =~ /sinatra\/base/ - short << c +=end end - short.join("\n") end end diff --git a/lib/opentox-client.rb b/lib/opentox-client.rb index a587aa5..7d9329d 100644 --- a/lib/opentox-client.rb +++ b/lib/opentox-client.rb @@ -6,6 +6,22 @@ require "rest-client" require 'uri' require 'yaml' require 'logger' + +# define constants and global variables +#TODO: switch services to 1.2 +RDF::OT = RDF::Vocabulary.new 'http://www.opentox.org/api/1.2#' +RDF::OT1 = RDF::Vocabulary.new 'http://www.opentox.org/api/1.1#' +RDF::OTA = RDF::Vocabulary.new 'http://www.opentox.org/algorithmTypes.owl#' + +#CLASSES = ["Compound", "Feature", "Dataset", "Algorithm", "Model", "Validation", "Task", "ErrorReport", "Investigation"] +CLASSES = ["Compound", "Feature", "Dataset", "Algorithm", "Model", "Validation", "Task", "Investigation"] +RDF_FORMATS = [:rdfxml,:ntriples,:turtle] +$default_rdf = "application/rdf+xml" + +# Regular expressions for parsing classification data +TRUE_REGEXP = /^(true|active|1|1.0|tox|activating|carcinogen|mutagenic)$/i +FALSE_REGEXP = /^(false|inactive|0|0.0|low tox|deactivating|non-carcinogen|non-mutagenic)$/i + require File.join(File.dirname(__FILE__),"overwrite.rb") require File.join(File.dirname(__FILE__),"error.rb") require File.join(File.dirname(__FILE__),"rest-client-wrapper.rb") diff --git a/lib/opentox.rb b/lib/opentox.rb index 9ba64bd..342b04e 100644 --- a/lib/opentox.rb +++ b/lib/opentox.rb @@ -1,52 +1,73 @@ -#TODO: switch services to 1.2 -RDF::OT = RDF::Vocabulary.new 'http://www.opentox.org/api/1.2#' -RDF::OT1 = RDF::Vocabulary.new 'http://www.opentox.org/api/1.1#' -RDF::OTA = RDF::Vocabulary.new 'http://www.opentox.org/algorithmTypes.owl#' - -SERVICES = ["Compound", "Feature", "Dataset", "Algorithm", "Model", "Validation", "Task", "Investigation"] - -# Regular expressions for parsing classification data -TRUE_REGEXP = /^(true|active|1|1.0|tox|activating|carcinogen|mutagenic)$/i -FALSE_REGEXP = /^(false|inactive|0|0.0|low tox|deactivating|non-carcinogen|non-mutagenic)$/i - # defaults to stderr, may be changed to file output (e.g in opentox-service) $logger = OTLogger.new(STDERR) $logger.level = Logger::DEBUG module OpenTox - attr_accessor :subjectid, :uri, :response - attr_writer :metadata + attr_accessor :uri, :subjectid, :rdf, :response + # Ruby interface + + # Create a new OpenTox object (does not load data from service) + # @param [optional,String] URI + # @param [optional,String] subjectid + # @return [OpenTox] OpenTox object def initialize uri=nil, subjectid=nil - @uri = uri.chomp + @uri = uri.to_s.chomp @subjectid = subjectid + @rdf = RDF::Graph.new end - # Ruby interface + # Load metadata from service + def pull + kind_of?(OpenTox::Dataset) ? uri = File.join(@uri,"metadata") : uri = @uri + # TODO generic method for all formats + parse_rdfxml RestClientWrapper.get(uri,{},{:accept => $default_rdf, :subjectid => @subjectid}) + end - def metadata reload=true - if reload or @metadata.empty? - @metadata = {} - kind_of?(OpenTox::Dataset) ? uri = File.join(@uri,"metadata") : uri = @uri - RDF::Reader.for(:rdfxml).new( RestClientWrapper.get(uri) ) do |reader| - reader.each_statement do |statement| - @metadata[statement.predicate] = statement.object if statement.subject == @uri - end - end + # Get object metadata + # @return [Hash] Metadata + def metadata + pull if @rdf.empty? + metadata = {} + @rdf.query([RDF::URI.new(@uri),nil,nil]).collect do |statement| + metadata[statement.predicate] ||= [] + metadata[statement.predicate] << statement.object end - @metadata + metadata + end + + # Get metadata values + # @param [RDF] Key from RDF Vocabularies + # @return [Array] Values for supplied key + def [](key) + pull if @rdf.empty? + @rdf.query([RDF::URI.new(@uri),key,nil]).collect{|statement| statement.object} end + # Save object at service def save - post self.to_rdfxml, { :content_type => 'application/rdf+xml'} + #TODO: dynamic assignment + post self.to_rdfxml, { :content_type => $default_rdf} end - def to_rdfxml - rdf = RDF::Writer.for(:rdfxml).buffer do |writer| - @metadata.each { |p,o| writer << RDF::Statement.new(RDF::URI.new(@uri), p, o) } + RDF_FORMATS.each do |format| + + # rdf parse methods for all formats e.g. parse_rdfxml + send :define_method, "parse_#{format}".to_sym do |rdf| + @rdf = RDF::Graph.new + RDF::Reader.for(format).new(rdf) do |reader| + reader.each_statement{ |statement| @rdf << statement } + end + end + + # rdf serialization methods for all formats e.g. to_rdfxml + send :define_method, "to_#{format}".to_sym do + rdf = RDF::Writer.for(format).buffer do |writer| + @rdf.each{|statement| writer << statement} + end + rdf end - rdf end # REST API @@ -70,32 +91,49 @@ module OpenTox def delete headers={} headers[:subjectid] ||= @subjectid - @response = RestClientWrapper.delete(@uri.to_s,nil,nil,headers) + @response = RestClientWrapper.delete(@uri.to_s,nil,headers) end # class methods module ClassMethods + def all service_uri, subjectid=nil + uris = RestClientWrapper.get(service_uri, {}, :accept => 'text/uri-list').split("\n").compact + uris.collect{|uri| URI.task?(service_uri) ? from_uri(uri, subjectid, false) : from_uri(uri, subjectid)} + end + def create service_uri, subjectid=nil - uri = RestClientWrapper.post(service_uri, {}, :subjectid => subjectid).chomp - subjectid ? eval("#{self}.new(\"#{uri}\", #{subjectid})") : eval("#{self}.new(\"#{uri}\")") + uri = RestClientWrapper.post(service_uri, {}, {:accept => 'text/uri-list', :subjectid => subjectid}) + URI.task?(service_uri) ? from_uri(uri, subjectid, false) : from_uri(uri, subjectid) end def from_file service_uri, filename, subjectid=nil file = File.new filename - uri = RestClientWrapper.post(service_uri, {:file => file}, {:subjectid => subjectid, :content_type => file.mime_type, :accept => "text/uri-list"}) - puts uri + from_uri RestClientWrapper.post(service_uri, {:file => file}, {:subjectid => subjectid, :content_type => file.mime_type, :accept => "text/uri-list"}), subjectid end - def all service_uri, subjectid=nil - uris = RestClientWrapper.get(service_uri, {}, :accept => 'text/uri-list').split("\n").compact - uris.collect{|uri| subjectid ? eval("#{self}.new(\"#{uri}\", #{subjectid})") : eval("#{self}.new(\"#{uri}\")")} - end + private + def from_uri uri, subjectid=nil, wait=true + + uri.chomp! + # TODO add waiting task + if URI.task? uri and wait + t = OpenTox::Task.new(uri) + t.wait + uri = t.resultURI + end + # guess class from uri, this is potentially unsafe, but polling metadata from large uri lists is way too slow (and not all service provide RDF.type in their metadata) + result = CLASSES.collect{|s| s if uri =~ /#{s.downcase}/}.compact + internal_server_error "Cannot determine class from URI: '#{uri}.\nCandidate classes are #{result.inspect}" unless result.size == 1 + klass = result.first + # initialize with/without subjectid + subjectid ? eval("#{self}.new(\"#{uri}\", #{subjectid})") : eval("#{self}.new(\"#{uri}\")") + end end # create default OpenTox classes - SERVICES.each do |klass| + CLASSES.each do |klass| c = Class.new do include OpenTox extend OpenTox::ClassMethods diff --git a/lib/overwrite.rb b/lib/overwrite.rb index c7a1d43..7b6cb4f 100644 --- a/lib/overwrite.rb +++ b/lib/overwrite.rb @@ -10,6 +10,10 @@ end module URI + def self.compound? uri + uri =~ /compound/ and URI.valid? uri + end + def self.task? uri uri =~ /task/ and URI.valid? uri end @@ -23,8 +27,8 @@ module URI end def self.accessible? uri, subjectid=nil - if URI.task? uri - # just ry to get a response, valid tasks may return codes > 400 + if URI.task? uri or URI.compound? uri + # just try to get a response, valid tasks may return codes > 400 Net::HTTP.get_response(URI.parse(uri)) true else @@ -41,23 +45,46 @@ module URI false end - def self.to_object uri, wait=true +end - # TODO add waiting task - if task? uri and wait - t = OpenTox::Task.new(uri) - t.wait - uri = t.resultURI - end +class File + def mime_type + `file -ib #{self.path}`.chomp + end +end - klass = - subjectid ? eval("#{self}.new(\"#{uri}\", #{subjectid})") : eval("#{self}.new(\"#{uri}\")") +# overwrite backtick operator to catch system errors +module Kernel + + # Override raises an error if _cmd_ returns a non-zero exit status. + # Returns stdout if _cmd_ succeeds. Note that these are simply concatenated; STDERR is not inline. + def ` cmd + stdout, stderr = '' + status = Open4::popen4(cmd) do |pid, stdin_stream, stdout_stream, stderr_stream| + stdout = stdout_stream.read + stderr = stderr_stream.read + end + raise stderr.strip if !status.success? + return stdout + rescue Exception + internal_server_error $! end + alias_method :system!, :system + + def system cmd + `#{cmd}` + return true + end end -class File - def mime_type - `file -ib #{self.path}`.chomp +class Array + def short_backtrace + short = [] + each do |c| + break if c =~ /sinatra\/base/ + short << c + end + short.join("\n") end end diff --git a/lib/rest-client-wrapper.rb b/lib/rest-client-wrapper.rb index e594729..c9e6bbb 100644 --- a/lib/rest-client-wrapper.rb +++ b/lib/rest-client-wrapper.rb @@ -10,21 +10,10 @@ module OpenTox # @param [String] destination URI # @param [optional,Hash|String] Payload data posted to the service # @param [optional,Hash] Headers with params like :accept, :content_type, :subjectid - # @param [optional,OpenTox::Task] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly - # @param [wait,Boolean] Set to false to NOT wait for task if result is a task # @return [RestClient::Response] REST call response [:head,:get,:post,:put,:delete].each do |method| - define_singleton_method method do |uri,payload={},headers={},waiting_task=nil, wait=true| - - # create request - args={} - args[:method] = method - args[:url] = uri - args[:timeout] = 600 - args[:payload] = payload - headers.each{ |k,v| headers.delete(k) if v==nil } if headers #remove keys with empty values, as this can cause problems - args[:headers] = headers + define_singleton_method method do |uri,payload={},headers={}| # check input bad_request_error "Invalid URI: '#{uri}'" unless URI.valid? uri @@ -34,106 +23,25 @@ module OpenTox [:accept,:content_type,:subjectid].each do |header| bad_request_error "#{header} should be submitted in the headers" if payload and payload.is_a?(Hash) and payload[header] end - #bad_request_error "waiting_task is not 'nil', OpenTox::SubTask or OpenTox::Task: #{waiting_task.class}" unless waiting_task.nil? or waiting_task.is_a?(OpenTox::Task) or waiting_task.is_a?(OpenTox::SubTask) + + # create request + args={} + args[:method] = method + args[:url] = uri + args[:timeout] = 600 + args[:payload] = payload + headers.each{ |k,v| headers.delete(k) if v==nil } if headers #remove keys with empty values, as this can cause problems + args[:headers] = headers # perform request @request = RestClient::Request.new(args) - #begin - # do not throw RestClient exceptions in order to create a @response object (needed for error reports) in every case - @response = @request.execute { |response, request, result| return response } - # ignore error codes from Task services (may return error codes >= 400 according to API, which causes exceptions in RestClient and RDF::Reader) - raise OpenTox::RestCallError.new @request, @response, "Response code is #{@response.code}." unless @response.code < 400 or URI.task? uri - #return @response if @response.code==200 or !wait - - # wait for task - #while @response.code==201 or @response.code==202 - #@response = wait_for_task(@response, uri, waiting_task) - #end - @response - - #rescue - #rest_error $!.message - #end - end - end - -=begin - def wait_for_task( response, base_uri, waiting_task=nil ) - - task = nil - case @response.headers[:content_type] - when /application\/rdf\+xml/ - # TODO: task uri from rdf - #task = OpenTox::Task.from_rdfxml(@response) - #task = OpenTox::Task.from_rdfxml(@response) - when /text\/uri-list/ - rest_error "Uri list has more than one entry, should be a single task" if @response.split("\n").size > 1 #if uri list contains more then one uri, its not a task - task = OpenTox::Task.new(@response.to_s.chomp) if URI.available? @response.to_s - else - rest_error "Unknown content-type for task : '"+@response.headers[:content_type].to_s+"'"+" base-uri: "+base_uri.to_s+" content: "+@response[0..200].to_s + # do not throw RestClient exceptions in order to create a @response object (needed for error reports) in every case + @response = @request.execute { |response, request, result| return response } + # ignore error codes from Task services (may return error codes >= 400 according to API, which causes exceptions in RestClient and RDF::Reader) + raise OpenTox::RestCallError.new @request, @response, "Response code is #{@response.code}." unless @response.code < 400 or URI.task? uri + @response end - - task.wait waiting_task - unless task.completed? # maybe task was cancelled / error - if task.errorReport - received_error task.errorReport, task.http_code, nil, {:rest_uri => task.uri, :rest_code => task.http_code} - else - rest_error "Status of task '"+task.uri.to_s+"' is no longer running (hasStatus is '"+task.status+ - "'), but it is neither completed nor has an errorReport" - end - end - @response - end - - def self.rest_error message - puts message - raise OpenTox::RestCallError.new @request, @response, message end - def self.received_error( body, code, content_type=nil, params=nil ) - - # try to parse body TODO - body.is_a?(OpenTox::ErrorReport) ? report = body : report = OpenTox::ErrorReport.from_rdf(body) - rest_call_error "REST call returned error: '"+body.to_s+"'" unless report - # parsing sucessfull - # raise RestCallError with parsed report as error cause - err = OpenTox::RestCallError.new(@request, @response, "REST call subsequent error") - err.errorCause = report - raise err - end -=end -=begin - def self.received_error( body, code, content_type=nil, params=nil ) - - # try to parse body - report = nil - #report = OpenTox::ErrorReport.from_rdf(body) - if body.is_a?(OpenTox::ErrorReport) - report = body - else - case content_type - when /yaml/ - report = YAML.load(body) - when /rdf/ - report = OpenTox::ErrorReport.from_rdf(body) - end - end - - unless report - # parsing was not successfull - # raise 'plain' RestCallError - err = OpenTox::RestCallError.new("REST call returned error: '"+body.to_s+"'") - err.rest_params = params - raise err - else - # parsing sucessfull - # raise RestCallError with parsed report as error cause - err = OpenTox::RestCallError.new("REST call subsequent error") - err.errorCause = report - err.rest_params = params - raise err - end - end -=end end end diff --git a/lib/task.rb b/lib/task.rb index 3a52dee..0562dc7 100644 --- a/lib/task.rb +++ b/lib/task.rb @@ -15,13 +15,11 @@ module OpenTox pid = fork do begin result_uri = yield - if URI.accessible?(result_uri) - task.completed result_uri - else - not_found_error "\"#{result_uri}\" is not a valid result URI" - end + task.completed result_uri rescue - task.error $! + RestClientWrapper.put(File.join(task.uri,'Error'),{:errorReport => $!.report.to_yaml}) + task.kill + #raise $! end end Process.detach(pid) @@ -49,11 +47,13 @@ module OpenTox end def description - metadata[RDF::DC.description] + pull + self.[](RDF::DC.description).uniq.first end def creator - metadata[RDF::DC.creator] + pull + self.[](RDF::DC.creator).uniq.first end def cancel @@ -66,16 +66,6 @@ module OpenTox RestClientWrapper.put(File.join(@uri,'Completed'),{:resultURI => uri}) end - def error error - # TODO: switch task service to rdf - #RestClientWrapper.put(File.join(@uri,'Error'),{:errorReport => error.report.to_rdfxml}) - # create report for non-runtime errors - error.respond_to?(:reporti) ? report = error.report : report = OpenTox::ErrorReport.create(error) - RestClientWrapper.put(File.join(@uri,'Error'),{:errorReport => report.to_yaml}) - kill - raise error - end - # waits for a task, unless time exceeds or state is no longer running # @param [optional,Numeric] dur seconds pausing before checking again for completion def wait(dur=0.3) @@ -114,12 +104,11 @@ module OpenTox res = RestClientWrapper.put(File.join(@uri,method.sub(/=/,'')),{}) super unless res.code == 200 else - response = metadata[RDF::OT[method]].to_s - response = metadata[RDF::OT1[method]].to_s if response.empty? # API 1.1 compatibility - if response.empty? - not_found_error "No #{method} metadata for #{@uri} " - end - return response + pull + response = self.[](RDF::OT[method]) + response = self.[](RDF::OT1[method]) if response.empty? # API 1.1 compatibility + internal_server_error "No #{method} metadata for #{@uri} " if response.empty? + return response.uniq.first.to_s end rescue OpenTox::Error raise $! diff --git a/test/dataset.rb b/test/dataset.rb index 13012bd..d2c8d57 100644 --- a/test/dataset.rb +++ b/test/dataset.rb @@ -4,43 +4,39 @@ require File.join File.dirname(__FILE__),'..','lib','opentox-client.rb' class DatasetTest < Test::Unit::TestCase -=begin - def test_post_get_delete - service_uri = "http://ot-dev.in-silico.ch/dataset" - dataset = OpenTox::Dataset.create service_uri - assert_match /#{service_uri}/, dataset.uri.to_s - puts dataset.uri - puts dataset.class - puts dataset.to_yaml - metadata = dataset.metadata - puts dataset.class - assert_equal RDF::OT.Dataset, metadata[RDF.type] - assert_equal dataset.uri, metadata[RDF::XSD.anyURI] - dataset.delete - end def test_all datasets = OpenTox::Dataset.all "http://ot-dev.in-silico.ch/dataset" assert_equal OpenTox::Dataset, datasets.first.class end - def test_create - d = OpenTox::Dataset.create "http://ot-dev.in-silico.ch/dataset" + def test_create_empty + service_uri = "http://ot-dev.in-silico.ch/dataset" + d = OpenTox::Dataset.create service_uri assert_equal OpenTox::Dataset, d.class - puts d.delete - assert_raise OpenTox::NotFoundError do - puts d.get(:accept => 'application/x-yaml') - end + assert_match /#{service_uri}/, d.uri.to_s + d.delete end -=end def test_create_from_file - d = OpenTox::Dataset.from_file "http://ot-dev.in-silico.ch/dataset", "data/EPAFHM.mini.csv" + d = OpenTox::Dataset.from_file "http://ot-dev.in-silico.ch/dataset", File.join(File.dirname(__FILE__),"data","EPAFHM.mini.csv") assert_equal OpenTox::Dataset, d.class - puts d.inspect - + d.delete + assert_raise OpenTox::NotFoundError do + d.get + end end + =begin + def test_metadata + d = OpenTox::Dataset.from_file "http://ot-dev.in-silico.ch/dataset", "data/EPAFHM.mini.csv" + assert_equal OpenTox::Dataset, d.class + # TODO fix metadata retrieval + metadata = d.metadata + assert_equal RDF::OT.Dataset, metadata[RDF.type] + assert_equal dataset.uri, metadata[RDF::XSD.anyURI] + d.delete + end def test_save d = OpenTox::Dataset.create "http://ot-dev.in-silico.ch/dataset" d.metadata diff --git a/test/error.rb b/test/error.rb index af5db52..d736620 100644 --- a/test/error.rb +++ b/test/error.rb @@ -6,7 +6,7 @@ class ErrorTest < Test::Unit::TestCase def test_bad_request object = OpenTox::Feature.new "http://this-is-a/fantasy/url" - assert_raise OpenTox::BadRequestError do + assert_raise OpenTox::NotFoundError do response = object.get end end diff --git a/test/feature.rb b/test/feature.rb index 1308e77..01c2206 100644 --- a/test/feature.rb +++ b/test/feature.rb @@ -16,7 +16,9 @@ class FeatureTest < Test::Unit::TestCase def test_feature @features.each do |uri| f = OpenTox::Feature.new(uri) - assert_equal RDF::OT1.Feature, f.metadata[RDF.type] + assert_equal [RDF::OT1.TUM_CDK_nAtom], f[RDF::OWL.sameAs] + assert_equal RDF::OT1.TUM_CDK_nAtom, f.metadata[RDF::OWL.sameAs].first + assert_equal [RDF::OT1.Feature,RDF::OT1.NumericFeature].sort, f[RDF.type].sort end end diff --git a/test/task.rb b/test/task.rb index 932d5c9..adbba12 100644 --- a/test/task.rb +++ b/test/task.rb @@ -10,12 +10,14 @@ TASK_SERVICE_URI = "http://ot-dev.in-silico.ch/task" class TaskTest < Test::Unit::TestCase +=begin +=end def test_all all = OpenTox::Task.all(TASK_SERVICE_URI) assert_equal Array, all.class t = all.last assert_equal OpenTox::Task, t.class - assert_equal RDF::OT1.Task, t.metadata[RDF.type] + assert_equal RDF::OT1.Task, t[RDF.type].first end def test_create_and_complete @@ -77,5 +79,7 @@ class TaskTest < Test::Unit::TestCase assert task.error? assert_equal "Error", task.hasStatus end +=begin +=end end -- cgit v1.2.3