Rcov C0 Coverage Information - RCov

app/models/submission_file.rb

Name Total Lines Lines of Code Total Coverage Code Coverage
app/models/submission_file.rb 214 157
64.02%
56.69%

Key

Code reported as executed by Ruby looks like this...and this: this line is also marked as covered.Lines considered as run by rcov, but not reported by Ruby, look like this,and this: these lines were inferred by rcov (using simple heuristics).Finally, here's a line marked as not executed.

Coverage Details

1 class SubmissionFile < ActiveRecord::Base
2 
3   # Only allow alphanumeric characters, '.', '-', and '_' as
4   # character set for submission files.
5   FILENAME_SANITIZATION_REGEXP = Regexp.new('[^0-9a-zA-Z\.\-_]')
6   # Character to be used as a replacement for all characters
7   # matching the regular expression above
8   SUBSTITUTION_CHAR = '_'
9 
10   belongs_to  :submission
11   has_many :annotations
12   validates_associated :submission
13   validates_presence_of :submission
14   validates_presence_of :filename
15   validates_presence_of :path
16 
17   validates_inclusion_of :is_converted, :in => [true, false]
18 
19   def get_file_type
20     # This is where you can add more languages that SubmissionFile will
21     # recognize.  It will return the name of the language, which
22     # SyntaxHighlighter can work with.
23     case File.extname(filename)
24     when ".sci"
25       return "scilab"
26     when ".java"
27       return "java"
28     when ".rb"
29       return "ruby"
30     when ".py"
31       return "python"
32     when ".js"
33       return "javascript"
34     when ".c"
35       return "c"
36     when ".scm"
37       return "scheme"
38     when ".ss"
39       return "scheme"
40     else
41       return "unknown"
42     end
43   end
44 
45   def get_comment_syntax
46     # This is where you can add more languages that SubmissionFile will
47     # be able to insert comments into, for example when downloading annotations.
48     # It will return a list, with the first element being the syntax to start a
49     # comment and the second element being the syntax to end a comment.  Use
50     #the language's multiple line comment format.
51     case File.extname(filename)
52     when ".java", ".js", ".c"
53       return ["/*", "*/"]
54     when ".rb"
55       return ["=begin\n", "\n=end"]
56     when ".py"
57       return ['"""', '"""']
58     when ".scm", ".ss"
59       return ["#|","|#"]
60     else
61       return ["##","##"]
62     end
63   end
64 
65   def is_supported_image?
66     #Here you can add more image types to support
67     supported_formats = ['.jpeg', '.jpg', '.gif', '.png']
68     return supported_formats.include?(File.extname(filename))
69   end
70 
71   def is_pdf?
72     return File.extname(filename) == '.pdf'
73   end
74 
75   # Taken from http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/44936
76   def self.is_binary?(file_contents)
77     return file_contents.size == 0 ||
78           file_contents.count("^ -~", "^\r\n") / file_contents.size > 0.3 ||
79           file_contents.count("\x00") > 0
80   end
81 
82   # Return an array representing the annotated areas of the submission file
83   #
84   # ===Returns:
85   #
86   # An array containing the extracted coordinates of all the annotations
87   # associated with this file
88   #
89   # Return nil if this SubmissionFile is not a supported image.
90 
91   def get_annotation_grid
92     return unless self.is_supported_image? || self.is_pdf?
93     all_annotations = []
94     self.annotations.each do |annot|
95       if annot.is_a?(ImageAnnotation)
96         extracted_coords = annot.extract_coords
97         return nil if extracted_coords.nil?
98         all_annotations.push(extracted_coords)
99       end
100     end
101     return all_annotations
102   end
103 
104   def convert_pdf_to_jpg
105     return unless MarkusConfigurator.markus_config_pdf_support && self.is_pdf?
106     m_logger = MarkusLogger.instance
107     storage_path = File.join(MarkusConfigurator.markus_config_pdf_storage,
108       self.submission.grouping.group.repository_name,
109       self.path)
110     file_path = File.join(storage_path, self.filename.split('.')[0] + '.jpg')
111     self.export_file(storage_path)
112     # Remove any old copies of this image if they exist
113     FileUtils.remove_file(file_path, true) if File.exists?(file_path)
114     m_logger.log("Starting pdf conversion from #{File.join(storage_path, self.filename)} to #{file_path}")
115     # ImageMagick can only save images with heights not exceeding 65500 pixels.
116     # Larger images result in a conversion failure.
117     begin
118       # This is an ImageMagick command, see http://www.imagemagick.org/script/convert.php for documentation
119       # For some reason, ImageMagick seemed to fail silently when not
120       # redirecting the output to a log file. Let's redirect the output to
121       # "something"
122       `convert -limit memory #{MarkusConfigurator.markus_config_pdf_conv_memory_allowance} -limit map 0 -density 150 -resize 66% #{File.join(storage_path, self.filename)} -append #{file_path} >> #{File.join(RAILS_ROOT, "log", "export-pdf.log")}`
123       # Sometimes, ImageMagick fails silently
124       if File.exists?(file_path)
125         m_logger.log("Successfully converted pdf file to jpg")
126       else
127         m_logger.log("Problem in PDF conversion")
128       end
129     rescue Exception => e
130       m_logger.log("Pdf file couldn't be converted")
131     end
132 
133     FileUtils.remove_file(File.join(storage_path, self.filename), true)
134     self.is_converted = true
135     self.save
136   end
137 
138   # Return the contents of this SubmissionFile.  Include annotations in the
139   # file if include_annotations is true.
140   def retrieve_file(include_annotations=false)
141     student_group = submission.grouping.group
142     repo = student_group.repo
143     revision_number = submission.revision_number
144     revision = repo.get_revision(revision_number)
145     if revision.files_at_path(path)[filename].nil?
146       raise I18n.t("results.could_not_find_file",
147                    :filename => filename,
148                    :repository_name => student_group.repository_name)
149     end
150     retrieved_file = repo.download_as_string(revision.files_at_path(path)[filename])
151     repo.close
152     if include_annotations
153       retrieved_file = add_annotations(retrieved_file)
154     end
155     return retrieved_file
156   end
157 
158   # Export this file from the svn repository into storage_path
159   # If a file of the same name as the one we are trying to export exists in
160   # the given repository, it will be overwritten by the svn exports
161   def export_file(storage_path)
162     m_logger = MarkusLogger.instance
163     m_logger.log("Exporting #{self.filename} from student repository")
164     begin
165       # Create the storage directories if they dont already exist
166       FileUtils.makedirs(storage_path)
167       # but deleted the file if it already exists
168       if File.exists?(File.join(storage_path, self.filename))
169         FileUtils.rm(File.join(storage_path, self.filename))
170       end
171       repo = submission.grouping.group.repo
172       revision_number = submission.revision_number
173       repo.export(File.join(storage_path, self.filename),
174                   File.join(self.path, self.filename),
175                   revision_number)
176     end
177 
178     # Let's check the file exists befor claiming the file has been exported
179     # properly
180     if File.exists?(File.join(storage_path, self.filename))
181       m_logger.log("Successfuly exported #{self.filename} from student repository to #{File.join(storage_path, self.filename)}")
182     else
183       m_logger.log("Failed to export #{self.filename} from student
184                       repository")
185     end
186   end
187 
188   private
189 
190   def add_annotations(file_contents)
191     comment_syntax = get_comment_syntax
192     result = ""
193     file_contents.split("\n").each_with_index do |contents, index|
194       annotations.each do |annot|
195         if index == annot.line_start.to_i - 1
196            text = AnnotationText.find(annot.annotation_text_id).content
197            result = result.concat(I18n.t("graders.download.begin_annotation",
198                :id => annot.annotation_number.to_s,
199                :text => text,
200                :comment_start => comment_syntax[0],
201                :comment_end => comment_syntax[1]) + "\n")
202         elsif index == annot.line_end.to_i
203            result = result.concat(I18n.t("graders.download.end_annotation",
204                :id => annot.annotation_number.to_s,
205                :comment_start => comment_syntax[0],
206                :comment_end => comment_syntax[1]) + "\n")
207         end
208       end
209     result = result.concat(contents + "\n")
210     end
211     return result
212   end
213 end
214 

Generated on Tue Feb 07 00:07:36 -0500 2012 with rcov 0.9.10