Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -97,27 +97,6 @@ def extract_supporting_solution_files
end
end

# Extracts filename and content of a data file and append it to the
# [:additionalFiles] array for the problem management API request body.
#
# @param [Pathname] pathname The pathname of the file.
# @param [String] content The content of the file.
def extract_supporting_file(filename, content)
supporting_file_object = default_codaveri_data_file_template

supporting_file_object[:type] = 'internal' # 'external' s3 upload not yet implemented by codaveri
supporting_file_object[:path] = filename.to_s
if content.force_encoding('UTF-8').valid_encoding?
supporting_file_object[:content] = content
supporting_file_object[:encoding] = 'utf8'
else
supporting_file_object[:content] = Base64.strict_encode64(content)
supporting_file_object[:encoding] = 'base64'
end

@data_files.append(supporting_file_object)
end

# Extracts test cases from the built dummy reports and append all the test cases to the
# [:IOTestcases] array for the problem management API request body.
def extract_test_cases # rubocop:disable Metrics/AbcSize
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,27 +97,6 @@ def extract_supporting_solution_files
end
end

# Extracts filename and content of a data file and append it to the
# [:additionalFiles] array for the problem management API request body.
#
# @param [Pathname] pathname The pathname of the file.
# @param [String] content The content of the file.
def extract_supporting_file(filename, content)
supporting_file_object = default_codaveri_data_file_template

supporting_file_object[:type] = 'internal' # 'external' s3 upload not yet implemented by codaveri
supporting_file_object[:path] = filename.to_s
if content.force_encoding('UTF-8').valid_encoding?
supporting_file_object[:content] = content
supporting_file_object[:encoding] = 'utf8'
else
supporting_file_object[:content] = Base64.strict_encode64(content)
supporting_file_object[:encoding] = 'base64'
end

@data_files.append(supporting_file_object)
end

# Extracts test cases from the built dummy reports and append all the test cases to the
# [:IOTestcases] array for the problem management API request body.
def extract_test_cases # rubocop:disable Metrics/AbcSize
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,23 +103,11 @@ def extract_supporting_tests_files
end
end

def extract_supporting_file(filename, content)
supporting_file_object = default_codaveri_data_file_template

supporting_file_object[:type] = 'internal' # 'external' s3 upload not yet implemented by codaveri
supporting_file_object[:path] = filename.to_s
# TODO: remove filename.to_s.downcase.end_with?('.java') check
# For now, only plaintext files that require compiling (e.g. *.java) will use 'utf8' ecoding
# Pending Codaveri 'utf8' encoding support for all plaintext files in compiled languages
if content.force_encoding('UTF-8').valid_encoding? && filename.to_s.downcase.end_with?('.java')
supporting_file_object[:content] = content
supporting_file_object[:encoding] = 'utf8'
else
supporting_file_object[:content] = Base64.strict_encode64(content)
supporting_file_object[:encoding] = 'base64'
end

@data_files.append(supporting_file_object)
# TODO: remove filename.to_s.downcase.end_with?('.java') check
# For now, only plaintext files that require compiling (e.g. *.java) will use 'utf8' ecoding
# Pending Codaveri 'utf8' encoding support for all plaintext files in compiled languages
Comment thread
adi-herwana-nus marked this conversation as resolved.
def utf8_encodable?(filename, utf8_content)
super && filename.to_s.downcase.end_with?('.java')
end

def extract_template
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,27 +97,6 @@ def extract_supporting_solution_files
end
end

# Extracts filename and content of a data file and append it to the
# [:additionalFiles] array for the problem management API request body.
#
# @param [Pathname] pathname The pathname of the file.
# @param [String] content The content of the file.
def extract_supporting_file(filename, content)
supporting_file_object = default_codaveri_data_file_template

supporting_file_object[:type] = 'internal' # 'external' s3 upload not yet implemented by codaveri
supporting_file_object[:path] = filename.to_s
if content.force_encoding('UTF-8').valid_encoding?
supporting_file_object[:content] = content
supporting_file_object[:encoding] = 'utf8'
else
supporting_file_object[:content] = Base64.strict_encode64(content)
supporting_file_object[:encoding] = 'base64'
end

@data_files.append(supporting_file_object)
end

# Extracts test cases from the built dummy reports and append all the test cases to the
# [:IOTestcases] array for the problem management API request body.
def extract_test_cases # rubocop:disable Metrics/AbcSize
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,40 @@ def process_evaluator

private

# Extracts filename and content of a data file and append it to the
# [:additionalFiles] array for the problem management API request body.
#
# @param [Pathname] filename The pathname of the file.
# @param [String] content The content of the file.
def extract_supporting_file(filename, content)
supporting_file_object = default_codaveri_data_file_template

supporting_file_object[:type] = 'internal' # 'external' s3 upload not yet implemented by codaveri
supporting_file_object[:path] = filename.to_s
# `content` is read straight out of the zip and may be frozen (rubyzip returns a frozen empty
# string literal for zero-byte entries), so tag the encoding on a copy rather than in place.
utf8_content = content.dup.force_encoding('UTF-8')
if utf8_encodable?(filename, utf8_content)
supporting_file_object[:content] = utf8_content
supporting_file_object[:encoding] = 'utf8'
else
supporting_file_object[:content] = Base64.strict_encode64(content)
supporting_file_object[:encoding] = 'base64'
end

@data_files.append(supporting_file_object)
end

# Whether a supporting file may be sent to Codaveri as plaintext 'utf8' rather than 'base64'.
# Concrete services may narrow this further; see the Java package service.
#
# @param [Pathname] filename The pathname of the file.
# @param [String] utf8_content The content of the file, tagged as UTF-8.
# @return [Boolean]
def utf8_encodable?(_filename, utf8_content)
utf8_content.valid_encoding?
end

# Defines the default solution template as indicated in the Codevari API problem management spec.
#
# @return [Hash]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,27 +97,6 @@ def extract_supporting_solution_files
end
end

# Extracts filename and content of a data file and append it to the
# [:additionalFiles] array for the problem management API request body.
#
# @param [Pathname] pathname The pathname of the file.
# @param [String] content The content of the file.
def extract_supporting_file(filename, content)
supporting_file_object = default_codaveri_data_file_template

supporting_file_object[:type] = 'internal' # 'external' s3 upload not yet implemented by codaveri
supporting_file_object[:path] = filename.to_s
if content.force_encoding('UTF-8').valid_encoding?
supporting_file_object[:content] = content
supporting_file_object[:encoding] = 'utf8'
else
supporting_file_object[:content] = Base64.strict_encode64(content)
supporting_file_object[:encoding] = 'base64'
end

@data_files.append(supporting_file_object)
end

# Extracts test cases from 'autograde.py' and append all the test cases to the
# [:resources][0][:exprTestcases] array for the problem management API request body.
def extract_test_cases
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,27 +97,6 @@ def extract_supporting_solution_files
end
end

# Extracts filename and content of a data file and append it to the
# [:additionalFiles] array for the problem management API request body.
#
# @param [Pathname] pathname The pathname of the file.
# @param [String] content The content of the file.
def extract_supporting_file(filename, content)
supporting_file_object = default_codaveri_data_file_template

supporting_file_object[:type] = 'internal' # 'external' s3 upload not yet implemented by codaveri
supporting_file_object[:path] = filename.to_s
if content.force_encoding('UTF-8').valid_encoding?
supporting_file_object[:content] = content
supporting_file_object[:encoding] = 'utf8'
else
supporting_file_object[:content] = Base64.strict_encode64(content)
supporting_file_object[:encoding] = 'base64'
end

@data_files.append(supporting_file_object)
end

# Extracts test cases from the built dummy reports and append all the test cases to the
# [:IOTestcases] array for the problem management API request body.
def extract_test_cases # rubocop:disable Metrics/AbcSize
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,27 +97,6 @@ def extract_supporting_solution_files
end
end

# Extracts filename and content of a data file and append it to the
# [:additionalFiles] array for the problem management API request body.
#
# @param [Pathname] pathname The pathname of the file.
# @param [String] content The content of the file.
def extract_supporting_file(filename, content)
supporting_file_object = default_codaveri_data_file_template

supporting_file_object[:type] = 'internal' # 'external' s3 upload not yet implemented by codaveri
supporting_file_object[:path] = filename.to_s
if content.force_encoding('UTF-8').valid_encoding?
supporting_file_object[:content] = content
supporting_file_object[:encoding] = 'utf8'
else
supporting_file_object[:content] = Base64.strict_encode64(content)
supporting_file_object[:encoding] = 'base64'
end

@data_files.append(supporting_file_object)
end

# Extracts test cases from the built dummy reports and append all the test cases to the
# [:IOTestcases] array for the problem management API request body.
def extract_test_cases # rubocop:disable Metrics/AbcSize
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,27 +97,6 @@ def extract_supporting_solution_files
end
end

# Extracts filename and content of a data file and append it to the
# [:additionalFiles] array for the problem management API request body.
#
# @param [Pathname] pathname The pathname of the file.
# @param [String] content The content of the file.
def extract_supporting_file(filename, content)
supporting_file_object = default_codaveri_data_file_template

supporting_file_object[:type] = 'internal' # 'external' s3 upload not yet implemented by codaveri
supporting_file_object[:path] = filename.to_s
if content.force_encoding('UTF-8').valid_encoding?
supporting_file_object[:content] = content
supporting_file_object[:encoding] = 'utf8'
else
supporting_file_object[:content] = Base64.strict_encode64(content)
supporting_file_object[:encoding] = 'base64'
end

@data_files.append(supporting_file_object)
end

# Extracts test cases from the built dummy reports and append all the test cases to the
# [:IOTestcases] array for the problem management API request body.
def extract_test_cases # rubocop:disable Metrics/AbcSize
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# frozen_string_literal: true
require 'rails_helper'

RSpec.describe Course::Assessment::Question::ProgrammingCodaveri::LanguagePackageService do
let(:package_path) do
File.join(Rails.root, 'spec/fixtures/course/programming_question_template_codaveri_empty_data_file.zip')
end
let(:package) { Course::Assessment::ProgrammingPackage.new(package_path) }
let(:main_files) { package.main_files }
let(:test_files) { package.test_files }
subject { described_class.new(nil, package) }

def extract(filename, content)
subject.send(:extract_supporting_file, filename, content)
subject.data_files.last
end

describe '.extract_supporting_file' do
context 'when the file is valid UTF-8 plaintext' do
it 'extracts the content as utf8' do
filename = Pathname.new('data.csv')

expect(extract(filename, main_files[filename])).to eq(
type: 'internal',
path: 'data.csv',
content: "codon,amino_acid\nAAA,Lys\nAAC,Asn\n",
encoding: 'utf8'
)
end
end

context 'when the file is not valid UTF-8' do
it 'extracts the content as base64' do
filename = Pathname.new('binary.dat')

expect(extract(filename, main_files[filename])).to eq(
type: 'internal',
path: 'binary.dat',
content: Base64.strict_encode64("\xFF\xFE\x00\x01\x02".b),
encoding: 'base64'
)
end
end

# Zero-byte zip entries are read back as a frozen empty string, which used to be mutated
# in place by `force_encoding` and raise FrozenError.
context 'when the file is empty' do
it 'extracts the file as empty utf8 content' do
filename = Pathname.new('empty.csv')
content = main_files[filename]
expect(content).to be_frozen

expect(extract(filename, content)).to eq(
type: 'internal',
path: 'empty.csv',
content: '',
encoding: 'utf8'
)
end

it 'extracts a zero-byte file in the tests folder' do
filename = Pathname.new('empty.csv')

expect { extract(filename, test_files[filename]) }.not_to raise_error
end
end

it 'does not re-tag the encoding of the content read from the package' do
filename = Pathname.new('data.csv')
content = main_files[filename]

extract(filename, content)

expect(content.encoding).to eq(Encoding::ASCII_8BIT)
end

it 'appends every extracted file to the data files' do
subject.send(:extract_supporting_file, Pathname.new('data.csv'), main_files[Pathname.new('data.csv')])
subject.send(:extract_supporting_file, Pathname.new('empty.csv'), test_files[Pathname.new('empty.csv')])

expect(subject.data_files.map { |file| file[:path] }).to eq(['data.csv', 'empty.csv'])
end
end

describe '.utf8_encodable?' do
it 'accepts any valid UTF-8 content' do
expect(subject.send(:utf8_encodable?, Pathname.new('data.csv'), 'plaintext')).to eq(true)
expect(subject.send(:utf8_encodable?, Pathname.new('empty.csv'), '')).to eq(true)
expect(subject.send(:utf8_encodable?, Pathname.new('binary.dat'), "\xFF\xFE".b.force_encoding('UTF-8'))).
to eq(false)
end

# The Java package service narrows the base implementation, pending Codaveri 'utf8' encoding
# support for all plaintext files in compiled languages.
context 'when the concrete service restricts utf8 encoding' do
subject { Course::Assessment::Question::ProgrammingCodaveri::Java::JavaPackageService.new(nil, package) }

it 'only accepts plaintext files that require compiling' do
expect(subject.send(:utf8_encodable?, Pathname.new('Helper.java'), 'class Helper {}')).to eq(true)
expect(subject.send(:utf8_encodable?, Pathname.new('data.csv'), 'plaintext')).to eq(false)
end

it 'extracts an empty supporting file as base64' do
filename = Pathname.new('empty.csv')

expect(extract(filename, main_files[filename])).to eq(
type: 'internal',
path: 'empty.csv',
content: '',
encoding: 'base64'
)
end
end
end
end