rcomp 0.1.1 → 0.2.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.
@@ -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