rcomp 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,4 +3,4 @@ Feature: Version
3
3
 
4
4
  Scenario: run version
5
5
  When I run `rcomp version`
6
- Then the output should contain "0.1.0"
6
+ Then the output should contain the version number
data/lib/rcomp.rb CHANGED
@@ -7,3 +7,5 @@ require 'rcomp/runner'
7
7
  require 'rcomp/suite'
8
8
  require 'rcomp/test'
9
9
  require 'rcomp/version'
10
+ require 'rcomp/initializer'
11
+ require 'rcomp/process'
data/lib/rcomp/actions.rb CHANGED
@@ -26,6 +26,12 @@ module RComp
26
26
  end
27
27
  end
28
28
 
29
+ def mkpath(path)
30
+ unless File.exists? path
31
+ FileUtils.mkpath path
32
+ end
33
+ end
34
+
29
35
  def touch(path)
30
36
  unless File.exist? path
31
37
  FileUtils.touch path
data/lib/rcomp/cli.rb CHANGED
@@ -3,9 +3,10 @@ require 'thor'
3
3
  module RComp
4
4
  class CLI < Thor
5
5
 
6
- include RComp::Actions
6
+ include Thor::Actions
7
7
  include RComp::Runner
8
8
  include RComp::Suite
9
+ include RComp::Initializer
9
10
 
10
11
  def initialize(args=[], options={}, config={})
11
12
  super
@@ -13,69 +14,47 @@ module RComp
13
14
  @conf = Conf.instance
14
15
  end
15
16
 
16
- ##
17
- ## CLI Commands
18
- ##
17
+ ###
18
+ # CLI Commands
19
+ ###
19
20
 
20
- # init
21
21
  desc "init", "Setup rcomp test directory"
22
22
  def init
23
- if initialized?
24
- puts "RComp already initialized"
25
- exit 1
26
- end
23
+ guard_initialized
27
24
 
28
- unless Dir.exists?(File.dirname(@conf.root))
29
- puts "No directory #{File.dirname(@conf.root)}"
30
- exit 1
25
+ unless command_exists?
26
+ @conf.set_command(ask("Enter the command you want to test:"))
31
27
  end
32
28
 
33
- # Create RComp directories
34
- mkdir @conf.root
35
- mkdir @conf.test_root
36
- mkdir @conf.expected_root
37
- mkdir @conf.result_root
38
-
29
+ initialize_directories
39
30
  puts "RComp successfully initialized"
40
31
  end
41
32
 
42
- # version
33
+
43
34
  desc "version", "Prints RComp's version information"
44
35
  def version
45
36
  puts "RComp version #{RComp::VERSION}"
46
37
  end
47
- map %w(-v --version) => :version
48
38
 
49
- # set-command
50
- desc "set_command COMMAND", "Sets the command RComp will run tests with"
51
- def set_command(command)
52
- @conf.set_conf_value("command", command)
53
- end
54
- map "c" => :set_command
39
+ map %w(-v --version) => :version
55
40
 
56
- # set-directory
57
- desc "set_directory PATH", "Set the directory RComp will store files"
58
- def set_directory(path)
59
- @conf.set_conf_value("directory", path)
60
- end
61
- map "d" => :set_directory
62
41
 
63
- # test
64
42
  desc "test", "Run all tests"
65
43
  method_option :grep,
66
44
  :type => :string,
67
45
  :desc => "Only test files that match pattern"
68
46
  def test
69
- @conf.require_basic_conf
47
+ guard_uninitialized
70
48
  if @options[:grep]
71
49
  run_suite(load_suite(@options[:grep]), :test)
72
50
  else
73
51
  run_suite(load_suite, :test)
74
52
  end
75
53
  end
54
+
76
55
  map "t" => :test
77
56
 
78
- # generate
57
+
79
58
  desc "generate", "Generate expected output for all tests"
80
59
  method_option :grep,
81
60
  :type => :string,
@@ -86,11 +65,14 @@ module RComp
86
65
  :aliases => "-O",
87
66
  :desc => "Overwrite expected output file for test if present"
88
67
  def generate
89
- @conf.require_basic_conf
68
+ guard_uninitialized
90
69
 
91
70
  # Display confirmation dialouge when -O is passed without filter
92
71
  if !@options[:grep] && options.overwrite
93
- confirm_action "This will overwrite all existing expected results."
72
+ unless yes? "This will overwrite all existing expected results."
73
+ say 'Aborting...'
74
+ exit 1
75
+ end
94
76
  end
95
77
 
96
78
  if @options[:grep]
@@ -99,26 +81,7 @@ module RComp
99
81
  run_suite(load_suite, :generate, @options)
100
82
  end
101
83
  end
102
- map "g" => :generate
103
-
104
- private
105
-
106
- def confirm_action(warning)
107
- puts warning
108
- print 'Are you sure? (Y/N) '
109
- confirm = STDIN.gets.chomp
110
-
111
- unless confirm.downcase == 'y'
112
- say 'Aborting...'
113
- exit 1
114
- end
115
- end
116
84
 
117
- def initialized?
118
- File.exists?(@conf.root) &&
119
- File.exists?(@conf.test_root) &&
120
- File.exists?(@conf.result_root) &&
121
- File.exists?(@conf.expected_root)
122
- end
85
+ map "g" => :generate
123
86
  end
124
87
  end
data/lib/rcomp/conf.rb CHANGED
@@ -8,61 +8,58 @@ module RComp
8
8
  include RComp::Actions
9
9
 
10
10
  attr_reader :root, :test_root, :result_root, :expected_root,
11
- :command
11
+ :command, :ignore, :timeout
12
+
13
+ # Conf file path
14
+ CONF_PATH = '.rcomp'
15
+
16
+ # Valid configuraiton keys
17
+ VALID_KEYS = ['directory',
18
+ 'command',
19
+ 'ignore',
20
+ 'timeout']
21
+
22
+ # Default configuration options
23
+ DEFAULT = { 'directory' => 'rcomp',
24
+ 'timeout' => 5 }
12
25
 
13
26
  # Initialize a new config object
14
27
  #
15
28
  # Loads options from config file, merges with defaults
16
29
  # and stores everything in memory
17
30
  def initialize
18
- # Config file path
19
- @path = '.rcomp'
20
-
21
- # Set valid keys for config file
22
- @valid_keys = ['directory',
23
- 'command']
24
-
25
- # Set default options and overwrite with config file options
26
- @default = { 'directory' => 'rcomp' }
31
+ # Load custom configuration and merge it with defaults
27
32
  @custom = read_conf_file
28
- @conf = @default.merge(@custom)
33
+ @conf = DEFAULT.merge(@custom)
29
34
 
30
35
  # Load configuration values into attributes
31
36
  @command = @conf['command']
37
+ @ignore = @conf['ignore']
38
+ @ignore ||= []
39
+ @timeout = @conf['timeout']
32
40
  @root = @conf['directory']
33
41
  @test_root = @root + '/tests'
34
42
  @result_root = @root + '/results'
35
43
  @expected_root = @root + '/expected'
36
44
  end
37
45
 
38
- # Set a configuration value and write it to the config file
46
+ # Set a command as a custom configuration value
39
47
  #
40
48
  # Returns nothing
41
- def set_conf_value(key, value)
42
- @custom[key] = value
43
- puts "#{key} set to #{value}"
49
+ def set_command(command)
50
+ @custom['command'] = command
51
+ puts "Command set to #{command}"
44
52
  write_conf_file
45
53
  end
46
-
47
- # Emit error unless all required conf keys are present in conf file
48
- #
49
- # Returns nothing
50
- def require_basic_conf
51
- require_command
52
- require_root_exists
53
- require_root_subdirs
54
- end
55
-
56
-
54
+
57
55
  private
58
56
 
59
- # Write the current config options to the config file
57
+ # Write the current custom config options to the config file
60
58
  #
61
59
  # Returns nothing
62
60
  def write_conf_file
63
- exit 1 unless @path
64
- touch @path unless File.exists?(@path)
65
- conf_file = File.open(@path, 'w')
61
+ touch CONF_PATH unless File.exists?(CONF_PATH)
62
+ conf_file = File.open(CONF_PATH, 'w')
66
63
  conf_file.puts YAML.dump @custom
67
64
  end
68
65
 
@@ -71,58 +68,17 @@ module RComp
71
68
  # Returns a Hash of config options
72
69
  def read_conf_file
73
70
  conf = {}
74
-
75
- if File.exists?(@path) && File.size?(@path)
76
-
71
+ if File.exists?(CONF_PATH) && File.size?(CONF_PATH)
77
72
  # Store valid conf keys
78
- YAML.load_file(@path).each do |key, value|
79
-
80
- if @valid_keys.include? key
73
+ YAML.load_file(CONF_PATH).each do |key, value|
74
+ if VALID_KEYS.include? key
81
75
  conf[key] = value
82
76
  else
83
77
  say "Invalid configuration key: #{key}"
84
78
  end
85
79
  end
86
80
  end
87
-
88
81
  conf
89
82
  end
90
-
91
- # Require the command config option to be set
92
- # Print error and exit otherwise
93
- #
94
- # Returns nothing
95
- def require_command
96
- unless @command
97
- puts "No command present"
98
- puts "Run rcomp c COMMAND to add a command to test with"
99
- exit 1
100
- end
101
- end
102
-
103
- # Require the existance of the root directory
104
- # Print error and exit otherwise
105
- #
106
- # Returns nothing
107
- def require_root_exists
108
- unless File.exists? @root
109
- puts "No RComp directory. Run rcomp init to create"
110
- exit 1
111
- end
112
- end
113
-
114
- # Require all sudirectories of the root directory to exist
115
- # Print error and exit otherwise
116
- #
117
- # Returns nothing
118
- def require_root_subdirs
119
- unless File.exists?(@test_root) &&
120
- File.exists?(@result_root) &&
121
- File.exists?(@expected_root)
122
- puts "Missing RComp directories at #{@root}"
123
- puts "Run rcomp init to repair"
124
- exit 1
125
- end
126
- end
127
83
  end
128
84
  end
@@ -0,0 +1,108 @@
1
+ module RComp
2
+ module Initializer
3
+
4
+ include RComp::Actions
5
+
6
+ @@conf = Conf.instance
7
+
8
+ # Emit error unless RComp is fully initialized
9
+ #
10
+ # Returns nothing
11
+ def guard_uninitialized
12
+ guard_command_exists
13
+ guard_root_dir_exists
14
+ guard_root_subdirs_exist
15
+ end
16
+
17
+ # Emit error unless RComp is not fully initialized
18
+ #
19
+ # Returns nothing
20
+ def guard_initialized
21
+ if initialized?
22
+ puts "RComp already initialized"
23
+ exit 1
24
+ end
25
+ end
26
+
27
+ # Create RComp directories if they don't already exist
28
+ #
29
+ # Returns nothing
30
+ def initialize_directories
31
+ mkpath @@conf.root
32
+ mkdir @@conf.test_root
33
+ mkdir @@conf.expected_root
34
+ mkdir @@conf.result_root
35
+ end
36
+
37
+ private
38
+
39
+ # Checks for the existance of a command to test with
40
+ #
41
+ # Returns a boolean
42
+ def command_exists?
43
+ @@conf.command
44
+ end
45
+
46
+ # Checks for the existance of RComp's root directory
47
+ #
48
+ # Returns a boolean
49
+ def root_dir_exists?
50
+ File.exists?(@@conf.root)
51
+ end
52
+
53
+ # Checks for the existance of the required subdirectories inside
54
+ # of RComp's root directory
55
+ #
56
+ # Returns a boolean
57
+ def root_subdirs_exist?
58
+ File.exists?(@@conf.test_root) &&
59
+ File.exists?(@@conf.result_root) &&
60
+ File.exists?(@conf.expected_root)
61
+ end
62
+
63
+ # Checks to see if RComp is fully initialized
64
+ #
65
+ # Returns a boolean
66
+ def initialized?
67
+ command_exists? &&
68
+ root_dir_exists? &&
69
+ root_subdirs_exist?
70
+ end
71
+
72
+ # Require the command config option to be set
73
+ # Print error and exit otherwise
74
+ #
75
+ # Returns nothing
76
+ def guard_command_exists
77
+ unless command_exists?
78
+ puts "No command present"
79
+ puts "Run rcomp init to setup"
80
+ exit 1
81
+ end
82
+ end
83
+
84
+ # Require the existance of the root directory
85
+ # Print error and exit otherwise
86
+ #
87
+ # Returns nothing
88
+ def guard_root_dir_exists
89
+ unless root_dir_exists?
90
+ puts "No RComp directory"
91
+ puts "Run rcomp init to create"
92
+ exit 1
93
+ end
94
+ end
95
+
96
+ # Require all sudirectories of the root directory to exist
97
+ # Print error and exit otherwise
98
+ #
99
+ # Returns nothing
100
+ def guard_root_subdirs_exist
101
+ unless root_subdirs_exist?
102
+ puts "Missing RComp directories at #{@@conf.root}"
103
+ puts "Run rcomp init to repair"
104
+ exit 1
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,44 @@
1
+ require 'childprocess'
2
+
3
+ module RComp
4
+ class Process
5
+
6
+ include RComp::Actions
7
+
8
+ # Initialize a new process
9
+ #
10
+ # cmd - An array of shellwords of a command
11
+ # timeout - Time until the process is automatically killed
12
+ # out - Path to send stdout of process
13
+ # err - Path to send stderr of process
14
+ def initialize(cmd, timeout, out, err)
15
+ @timeout = timeout
16
+ @process = ChildProcess.build(*cmd)
17
+ @process.io.stdout = File.new(out, 'w')
18
+ @process.io.stderr = File.new(err, 'w')
19
+ end
20
+
21
+ # Runs a process and with a specified command and timeout
22
+ #
23
+ # Returns nothing
24
+ def run
25
+ begin @process.start
26
+ rescue ChildProcess::LaunchError => e
27
+ raise StandardError.new(e.message)
28
+ end
29
+
30
+ begin @process.poll_for_exit(@timeout)
31
+ rescue ChildProcess::TimeoutError
32
+ @timedout = true
33
+ @process.stop
34
+ end
35
+ end
36
+
37
+ # Check if the proccess timed out or not
38
+ #
39
+ # Returns a boolean
40
+ def timedout?
41
+ @timedout ||= false
42
+ end
43
+ end
44
+ end