mips_tester 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,54 @@
1
+ # Compiled source #
2
+ ###################
3
+ *.com
4
+ *.class
5
+ *.dll
6
+ *.exe
7
+ *.o
8
+ *.so
9
+
10
+ # Packages #
11
+ ############
12
+ # it's better to unpack these files and commit the raw source
13
+ # git has its own built in compression methods
14
+ *.7z
15
+ *.dmg
16
+ *.gz
17
+ *.iso
18
+ *.jar
19
+ *.rar
20
+ *.tar
21
+ *.zip
22
+
23
+ # Logs and databases #
24
+ ######################
25
+ *.log
26
+ *.sql
27
+ *.sqlite
28
+
29
+ # OS generated files #
30
+ ######################
31
+ .DS_Store?
32
+ ehthumbs.db
33
+ Icon?
34
+ Thumbs.db
35
+
36
+ coverage
37
+ rdoc
38
+ pkg
39
+ test/tmp
40
+ test/version_tmp
41
+ tmp
42
+ pkg
43
+ *.gem
44
+ *.rbc
45
+ lib/bundler/man
46
+ spec/reports
47
+ .config
48
+ InstalledFiles
49
+ .bundle
50
+
51
+ # YARD artifacts
52
+ .yardoc
53
+ _yardoc
54
+ doc/
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mips_tester (0.0.1)
4
+ mips_tester (0.1.0)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
data/README.md CHANGED
@@ -19,14 +19,10 @@ It relies on MARS (it's ugly I know, but SPIM's cli doesn't work with automated
19
19
  $> irb
20
20
  $irb :001> require 'mips_tester'
21
21
  $irb :002> tester = MIPSTester::MIPS.new :mars_path => "/Applications/MARS_4_1.jar"
22
- $irb :003> tester.run "test.asm" do
23
- $irb :004> register :s0 => 0x01
24
- $irb :005> register :s1 => 0x45
25
- $irb :006> expected :s0 => 0x01, :s1 => 0x45
22
+ $irb :003> tester.test "test.asm" do
23
+ $irb :004> set :s0 => 0x01
24
+ $irb :005> set '0x10010004' => 45
25
+ $irb :006> expect :s0 => 0x01, :s1 => 0x45
26
26
  $irb :007> verbose! # Optional verbosity!
27
27
  $irb :008> end
28
- => true
29
-
30
- ## TO-DOs
31
- * Ability to input memory address and expect their results
32
- * Better failing messages
28
+ => true
data/lib/mips_tester.rb CHANGED
@@ -1,47 +1,88 @@
1
1
  require 'tempfile' unless defined? Tempfile
2
- require 'pp'
3
2
 
3
+ # Main MIPSTester module
4
4
  module MIPSTester
5
- VERSION = "0.0.1"
5
+ # Library version
6
+ VERSION = "0.1.0"
6
7
 
7
- class MIPS
8
- REGISTER = /^(at|v[01]|a[0-3]|s[0-7]|t\d|[2-9]|1[0-9]|2[0-5])$/
9
- ADDRESS = /^(\d{1,10}|0x[\da-f]{1,8}|0b[01]{1,32})$/
8
+ # MIPSFileError Exception, raised when test file is not valid or non-existent
9
+ class MIPSFileError < Exception; end
10
+
11
+ # MIPSInvalidBlockError Exception, raised when no block is given to test method
12
+ class MIPSInvalidBlockError < Exception; end
13
+
14
+ # MIPSMarsError Exception, raised when MARS installation path is not valid.
15
+ class MIPSMarsError < Exception; end
10
16
 
17
+ # Main MIPS tester class.
18
+ # It provides the methods to test MIPS ASMs files
19
+ class MIPS
20
+ # Register validation
21
+ REGISTER_REGEX = /^(at|v[01]|a[0-3]|s[0-7]|t\d|[2-9]|1[0-9]|2[0-5])$/
22
+
23
+ # Memory address validation
24
+ ADDRESS_REGEX = /^0x[\da-f]{8}$/
25
+
26
+ # MARS jar path
27
+ attr_reader :mars_path
28
+
29
+ # Create a new MIPSTester::MIPS object
30
+ #
31
+ # @example
32
+ # MIPSTester::MIPS.new :mars_path => 'path/to/mars.jar'
33
+ #
34
+ # @return [MIPSTester::MIPS] The MIPSTester::MIPS object
11
35
  def initialize(params = {})
12
36
  @mars_path = params.delete(:mars_path)
13
- raise Exception.new("Provide valid Mars jar!") if not @mars_path or not File.exists? @mars_path
37
+ raise MIPSMarsError.new("Provide valid Mars jar.") if not @mars_path or not File.exists? @mars_path
14
38
  end
15
39
 
16
- def run(file, &block)
17
- raise Exception.new("Provide valid file!") if not file or not File.exists? file
18
- raise Exception.new("Provide block!") if not block
40
+ # Run a given file in the emulator. *A provided block is mandatory*, with starter registers
41
+ # and expected values.
42
+ # A simple DSL is provided:
43
+ # * set [Hash] => set initial registers or memory addresses
44
+ # * expect [Hash] => expect values of registers or memory addresses
45
+ # * verbose! => optional, if given prints on STDOUT set registers and expected ones
46
+ #
47
+ # @example
48
+ # test "file.asm" do
49
+ # set :s1 => 6, '0x10010000' => 0xFF
50
+ # expect :s5 => 6
51
+ # verbose!
52
+ # end
53
+ #
54
+ # @param file [String] The path to the file to run
55
+ # @param block The block to provide info on what to test
56
+ #
57
+ # @return [Boolean] True if the test went well, False if not.
58
+ def test(file, &block)
59
+ raise MIPSFileError.new("Provide valid file.") if not file or not File.exists? file
60
+ raise MIPSInvalidBlockError.new("Provide block.") if not block
19
61
 
20
62
  reset!
21
63
 
22
64
  instance_eval(&block)
23
65
 
24
66
  asm = Tempfile.new "temp.asm"
25
- asm.write prep_registers(@regs)
26
- asm.write File.read(file)
67
+ asm.write(prep_params + File.read(file))
27
68
  asm.close
28
69
 
29
- cli = `#{["java -jar", @mars_path, @regs.keys.join(" "), "nc dec", asm.path].join(" ")}`
30
-
70
+ cli = `#{["java -jar",
71
+ @mars_path,
72
+ @regs.empty? ? "" : @regs.keys.join(" "),
73
+ @addresses.empty? ? "" : [@addresses.keys.min, @addresses.keys.max].join("-"),
74
+ "nc dec",
75
+ asm.path].join(" ")}`
76
+
31
77
  begin
32
78
  results = parse_results cli
33
79
 
34
- if @verbose
35
- puts "\nExpected:"
36
- pp @exp
37
- puts "\nResults:"
38
- pp results
39
- end
80
+ puts "Expected:\n#{@exp}\nResults:\n#{results}" if @verbose
40
81
 
41
82
  return compare_hashes(@exp, results)
42
83
  rescue Exception => ex
43
84
  puts ex.message
44
- return nil
85
+ return false
45
86
  ensure
46
87
  asm.unlink
47
88
  end
@@ -50,39 +91,50 @@ module MIPSTester
50
91
  private
51
92
 
52
93
  def verbose!; @verbose = true; end
53
- def register hash; @regs.merge! hash; end
54
- def expected hash; @exp.merge! hash; end
94
+
95
+ def set hash
96
+ hash.each_pair do |key, value|
97
+ case key
98
+ when REGISTER_REGEX then @regs.merge! key => value
99
+ when ADDRESS_REGEX then @addresses.merge! key => value
100
+ else puts "Warning: #{key} not recognized as register or memory address. Discarded."
101
+ end
102
+ end
103
+ end
104
+
105
+ def expect hash; @exp.merge! hash; end
55
106
 
56
107
  def reset!
57
- @regs = {}; @exp = {}; @verbose = false
108
+ @regs = {}; @addresses = {}; @exp = {}; @verbose = false
58
109
  end
59
110
 
60
111
  def parse_results(results)
61
- if results =~ /^Error/
62
- throw Exception.new "Error in file\nReason: #{results}\n\n"
63
- end
112
+ raise Exception.new "Error in given file!\nReason: #{results}\n\n" if results =~ /^Error/
64
113
 
65
114
  out = {}
66
115
 
67
- results.split("\n")[1..-1].map do |reg|
68
- g = reg.strip.split("\t")
69
- out.merge! g[0].gsub("$", "") => g[1].to_i
116
+ results.split("\n")[1..-1].each do |reg|
117
+ key, value = reg.strip.split("\t")
118
+
119
+ if key =~ /^Mem/
120
+ out.merge! key[4..-2] => value.to_i
121
+ else
122
+ out.merge! key[1..-1] => value.to_i
123
+ end
70
124
  end
71
125
 
72
126
  out
73
127
  end
74
128
 
75
- def prep_registers(regs)
129
+ def prep_params
76
130
  out = ""
77
- regs.each_pair do |key, value|
78
- if key =~ REGISTER
79
- out << "li\t\t$#{key}, #{value}\n"
80
- elsif key =~ ADDRESS
81
- out << "li\t\t$t0, #{key}\n"
82
- out << "li\t\t$t1, 0x#{value.to_s(16)}\n"
83
- out << "sb\t\t$t1, ($t0)\n"
84
- end
131
+ @regs.each_pair {|key, value| out << "li\t\t$#{key}, #{value}\n" }
132
+ @addresses.each_pair do |key, value|
133
+ out << "li\t\t$t0, #{key}\n"
134
+ out << "li\t\t$t1, 0x#{value.to_s(16)}\n"
135
+ out << "sb\t\t$t1, ($t0)\n"
85
136
  end
137
+
86
138
  out
87
139
  end
88
140
 
data/spec/mips_spec.rb CHANGED
@@ -1,16 +1,61 @@
1
1
  require 'spec_helper'
2
+ include MIPSTester
2
3
 
3
- describe MIPSTester::MIPS do
4
- let :mips do
5
- MIPSTester::MIPS.new :mars_path => "/Applications/MARS_4_1.jar"
4
+ describe MIPS do
5
+ context 'passing wrong parameters' do
6
+ it 'should raise exception if not valid MARS path is given' do
7
+ expect do
8
+ MIPS.new :mars_path => '/tmp/MARS.jar'
9
+ end.to raise_error(::MIPSMarsError)
10
+ end
11
+
12
+ it 'should raise exception if not valid file path is given' do
13
+ mips = MIPS.new :mars_path => "/Applications/MARS_4_1.jar"
14
+ expect do
15
+ mips.test fixture_path("non-existing.asm") {}
16
+ end.to raise_error(::MIPSFileError)
17
+ end
18
+
19
+ it 'should raise exception if no block is given on test method' do
20
+ mips = MIPS.new :mars_path => "/Applications/MARS_4_1.jar"
21
+ expect do
22
+ mips.test fixture_path("empty.asm")
23
+ end.to raise_error(::MIPSInvalidBlockError)
24
+ end
6
25
  end
7
26
 
8
- it 'should work properly with an empty file' do
9
- mips.run fixture_path("empty.asm") do
10
- register :s0 => 0x0C, :s1 => 0x3F
11
- register :s2 => 0x34
12
- expected :s0 => 0x0C, :s1 => 0x3F
13
- expected :s2 => 0x34
14
- end.should be_true
27
+
28
+ context 'work on empty file' do
29
+ let :mips do
30
+ MIPS.new :mars_path => "/Applications/MARS_4_1.jar"
31
+ end
32
+
33
+ it 'should expect given register values' do
34
+ mips.test fixture_path("empty.asm") do
35
+ set :s0 => 0x0C, :s1 => 0x3F
36
+ expect :s0 => 0x0C, :s1 => 0x3F
37
+ end.should be_true
38
+ end
39
+
40
+ it 'should fail with expected results different from set results' do
41
+ mips.test fixture_path("empty.asm") do
42
+ set :s0 => 0x0D, :s1 => 0x3E
43
+ expect :s0 => 0x0C, :s1 => 0x3F
44
+ end.should be_false
45
+ end
46
+
47
+ it 'should expect given memory address values' do
48
+ mips.test fixture_path("empty.asm") do
49
+ set '0x10010000' => 45, '0x10010010' => 32, '0x10010020' => 0xFF
50
+ expect '0x10010000' => 45, '0x10010010' => 32, '0x10010020' => 0xFF
51
+ end.should be_true
52
+ end
53
+
54
+ it 'should expect mixed parameters' do
55
+ mips.test fixture_path("empty.asm") do
56
+ set '0x10010000' => 45, :s0 => 32
57
+ expect '0x10010000' => 45, :s0 => 32
58
+ end.should be_true
59
+ end
15
60
  end
16
61
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: mips_tester
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.1
5
+ version: 0.1.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Federico Ravasio
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-04-17 00:00:00 +02:00
13
+ date: 2011-04-25 00:00:00 +02:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -34,13 +34,13 @@ extensions: []
34
34
  extra_rdoc_files: []
35
35
 
36
36
  files:
37
+ - .gitignore
37
38
  - Gemfile
38
39
  - Gemfile.lock
39
40
  - LICENSE
40
41
  - README.md
41
42
  - Rakefile
42
43
  - lib/mips_tester.rb
43
- - mips_tester-0.0.1.gem
44
44
  - mips_tester.gemspec
45
45
  - spec/fixtures/empty.asm
46
46
  - spec/mips_spec.rb