derelict 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.
Files changed (63) hide show
  1. checksums.yaml +5 -13
  2. data/.cane +2 -0
  3. data/.coveralls.yml +1 -0
  4. data/.travis.yml +13 -0
  5. data/README.md +55 -9
  6. data/Rakefile +21 -0
  7. data/derelict.gemspec +25 -1
  8. data/lib/derelict/connection/invalid.rb +14 -0
  9. data/lib/derelict/connection/not_found.rb +13 -0
  10. data/lib/derelict/connection.rb +84 -0
  11. data/lib/derelict/exception/optional_reason.rb +32 -0
  12. data/lib/derelict/exception.rb +3 -2
  13. data/lib/derelict/instance/command_failed.rb +28 -0
  14. data/lib/derelict/instance/invalid.rb +11 -11
  15. data/lib/derelict/instance/missing_binary.rb +13 -0
  16. data/lib/derelict/instance/non_directory.rb +10 -8
  17. data/lib/derelict/instance/not_found.rb +10 -8
  18. data/lib/derelict/instance.rb +105 -33
  19. data/lib/derelict/parser/status/invalid_format.rb +16 -0
  20. data/lib/derelict/parser/status.rb +89 -0
  21. data/lib/derelict/parser/version/invalid_format.rb +16 -0
  22. data/lib/derelict/parser/version.rb +28 -0
  23. data/lib/derelict/parser.rb +25 -0
  24. data/lib/derelict/utils/logger/array_outputter.rb +43 -0
  25. data/lib/derelict/utils/logger/invalid_type.rb +15 -0
  26. data/lib/derelict/utils/logger/raw_formatter.rb +12 -0
  27. data/lib/derelict/utils/logger.rb +51 -0
  28. data/lib/derelict/utils.rb +11 -0
  29. data/lib/derelict/version.rb +2 -2
  30. data/lib/derelict/virtual_machine/invalid.rb +14 -0
  31. data/lib/derelict/virtual_machine/not_found.rb +18 -0
  32. data/lib/derelict/virtual_machine.rb +154 -0
  33. data/lib/derelict.rb +61 -14
  34. data/spec/coverage_helper.rb +16 -0
  35. data/spec/derelict/connection/invalid_spec.rb +16 -0
  36. data/spec/derelict/connection/not_found_spec.rb +13 -0
  37. data/spec/derelict/connection_spec.rb +107 -0
  38. data/spec/derelict/exception/optional_reason_spec.rb +41 -0
  39. data/spec/derelict/exception_spec.rb +11 -0
  40. data/spec/derelict/instance/command_failed_spec.rb +40 -0
  41. data/spec/derelict/instance/invalid_spec.rb +16 -0
  42. data/spec/derelict/instance/missing_binary_spec.rb +13 -0
  43. data/spec/derelict/instance/non_directory_spec.rb +13 -0
  44. data/spec/derelict/instance/not_found_spec.rb +13 -0
  45. data/spec/derelict/instance_spec.rb +226 -0
  46. data/spec/derelict/parser/status/invalid_format_spec.rb +16 -0
  47. data/spec/derelict/parser/status_spec.rb +214 -0
  48. data/spec/derelict/parser/version/invalid_format_spec.rb +16 -0
  49. data/spec/derelict/parser/version_spec.rb +31 -0
  50. data/spec/derelict/parser_spec.rb +24 -0
  51. data/spec/derelict/utils/logger/array_outputter_spec.rb +40 -0
  52. data/spec/derelict/utils/logger/invalid_type_spec.rb +13 -0
  53. data/spec/derelict/utils/logger/raw_formatter_spec.rb +17 -0
  54. data/spec/derelict/utils/logger_spec.rb +35 -0
  55. data/spec/derelict/virtual_machine/invalid_spec.rb +16 -0
  56. data/spec/derelict/virtual_machine/not_found_spec.rb +34 -0
  57. data/spec/derelict/virtual_machine_spec.rb +295 -0
  58. data/spec/derelict_spec.rb +50 -0
  59. data/spec/spec_helper.rb +28 -3
  60. data/spec/support/log_context.rb +36 -0
  61. metadata +175 -22
  62. data/lib/derelict/instance/already_active.rb +0 -9
  63. data/spec/system_spec.spec +0 -10
@@ -0,0 +1,89 @@
1
+ module Derelict
2
+ # Parses the output of "vagrant status"
3
+ class Parser::Status < Parser
4
+ autoload :InvalidFormat, "derelict/parser/status/invalid_format"
5
+
6
+ # Include "memoize" class method to memoize methods
7
+ extend Memoist
8
+
9
+ # Regexp to extract the VM list from the "vagrant status" output
10
+ PARSE_LIST_FROM_OUTPUT = /\n\n((?:.*\n)+)\n/
11
+
12
+ # Regexp to extract the state from a line in the VM list
13
+ PARSE_STATE_FROM_LIST_ITEM = %r[
14
+ ^(.*?) # VM name starts at the start of the line,
15
+ \s{2,} # to the first instance of 2 or more spaces.
16
+ (.*?) # VM state starts after the whitespace,
17
+ \s+\( # continuing until whitespace and open bracket.
18
+ (.*) # The provider name starts after the bracket,
19
+ \)$ # and ends at a closing bracket at line end.
20
+ ]x # Ignore whitespace to allow these comments
21
+
22
+ # Retrieves the names of all virtual machines in the output
23
+ #
24
+ # The names are returned as a Set of symbols.
25
+ def vm_names
26
+ Set[*states.keys]
27
+ end
28
+
29
+ # Determines if a particular virtual machine exists in the output
30
+ #
31
+ # * vm_name: The name of the virtual machine to look for
32
+ def exists?(vm_name)
33
+ vm_names.include? vm_name.to_sym
34
+ end
35
+
36
+ # Determines the state of a particular virtual machine
37
+ #
38
+ # The state is returned as a symbol, e.g. :running.
39
+ #
40
+ # * vm_name: The name of the virtual machine to retrieve state
41
+ def state(vm_name)
42
+ unless states.include? vm_name.to_sym
43
+ raise Derelict::VirtualMachine::NotFound.new vm_name
44
+ end
45
+
46
+ states[vm_name.to_sym]
47
+ end
48
+
49
+ # Provides a description of this Parser
50
+ #
51
+ # Mainly used for log messages.
52
+ def description
53
+ "Derelict::Parser::Status instance"
54
+ end
55
+
56
+ private
57
+ # Retrieves the virtual machine list section of the output
58
+ def vm_lines
59
+ output.match(PARSE_LIST_FROM_OUTPUT).tap {|list|
60
+ logger.debug "Parsing VM list from output using #{description}"
61
+ raise InvalidFormat.new "Couldn't find VM list" if list.nil?
62
+ }.captures[0].lines
63
+ end
64
+ memoize :vm_lines
65
+
66
+ # Retrieves the state data for all virtual machines in the output
67
+ #
68
+ # The state is returned as a Hash, mapping virtual machine names
69
+ # (as symbols) to their state (also as a symbol). Both of these
70
+ # symbols have spaces converted to underscores (for convenience
71
+ # when writing literals in other code).
72
+ def states
73
+ logger.debug "Parsing states from VM list using #{description}"
74
+ vm_lines.inject Hash.new do |hash, line|
75
+ hash.merge! parse_line(line.match PARSE_STATE_FROM_LIST_ITEM)
76
+ end
77
+ end
78
+ memoize :states
79
+
80
+ def parse_line(match)
81
+ raise InvalidFormat.new "Couldn't parse VM list" if match.nil?
82
+ Hash[*match.captures[0..1].map {|value| sanitize value }]
83
+ end
84
+
85
+ def sanitize(value)
86
+ value.to_s.gsub(/\s+/, "_").downcase.to_sym
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,16 @@
1
+ module Derelict
2
+ class Parser
3
+ class Version
4
+ # The version wasn't in the expected format and couldn't be parsed
5
+ class InvalidFormat < Derelict::Exception
6
+ include Derelict::Exception::OptionalReason
7
+
8
+ private
9
+ # Retrieves the default error message
10
+ def default_message
11
+ "Output from 'vagrant --version' was in an unexpected format"
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,28 @@
1
+ module Derelict
2
+ # Parses the output of "vagrant --version"
3
+ class Parser::Version < Parser
4
+ autoload :InvalidFormat, "derelict/parser/version/invalid_format"
5
+
6
+ # Include "memoize" class method to memoize methods
7
+ extend Memoist
8
+
9
+ # Regexp to extract the version from the "vagrant --version" output
10
+ PARSE_VERSION_FROM_OUTPUT = /^Vagrant v(?:ersion )?(.*)?$/
11
+
12
+ # Determines the version of Vagrant based on the output
13
+ def version
14
+ logger.debug "Parsing version from output using #{description}"
15
+ matches = output.match PARSE_VERSION_FROM_OUTPUT
16
+ raise InvalidFormat.new output if matches.nil?
17
+ matches.captures[0]
18
+ end
19
+ memoize :version
20
+
21
+ # Provides a description of this Parser
22
+ #
23
+ # Mainly used for log messages.
24
+ def description
25
+ "Derelict::Parser::Version instance"
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,25 @@
1
+ module Derelict
2
+ # Base class for parsers, which extract data from command output
3
+ class Parser
4
+ autoload :Status, "derelict/parser/status"
5
+ autoload :Version, "derelict/parser/version"
6
+
7
+ # Include "logger" method to get a logger for this class
8
+ include Utils::Logger
9
+
10
+ attr_reader :output
11
+
12
+ # Initializes the parser with the output it will be parsing
13
+ def initialize(output)
14
+ @output = output
15
+ logger.debug "Successfully initialized #{description}"
16
+ end
17
+
18
+ # Provides a description of this Parser
19
+ #
20
+ # Mainly used for log messages.
21
+ def description
22
+ "Derelict::Parser (unknown type)"
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,43 @@
1
+ module Derelict
2
+ module Utils
3
+ module Logger
4
+ # A Log4r Outputter which stores all logs in an array
5
+ #
6
+ # Logs are stored in the internal array by #write. Logs can be
7
+ # cleared using #flush, which returns the flushed logs too.
8
+ class ArrayOutputter < Log4r::Outputter
9
+ # Include "memoize" class method to memoize methods
10
+ extend Memoist
11
+
12
+ # Force the outputter to receive and store all levels of messages
13
+ def level
14
+ Log4r::ALL
15
+ end
16
+
17
+ # The internal array of messages
18
+ def messages
19
+ []
20
+ end
21
+ memoize :messages
22
+
23
+ # Clear internal log messages array and return the erased data
24
+ def flush
25
+ messages.dup.tap { messages.clear }
26
+ end
27
+
28
+ private
29
+
30
+ # Write a message to the internal array
31
+ #
32
+ # This is an abstract method in the parent class, and handles
33
+ # persisting the log data. In this class, it saves the message
34
+ # into an internal array to be retrieved later.
35
+ #
36
+ # * message: The log message to be persisted
37
+ def write(message)
38
+ messages << message
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,15 @@
1
+ module Derelict
2
+ module Utils
3
+ module Logger
4
+ # The "type" option when requesting the logger was invalid
5
+ class InvalidType < ::Derelict::Exception
6
+ # Initializes a new instance of this exception for a type
7
+ #
8
+ # * type: The (invalid) requested type
9
+ def initialize(type)
10
+ super "Invalid logger type '#{type}'"
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,12 @@
1
+ module Derelict
2
+ module Utils
3
+ module Logger
4
+ # A Formatter that passes the log message through untouched
5
+ class RawFormatter < Log4r::Formatter
6
+ def format(event)
7
+ event.data
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,51 @@
1
+ module Derelict
2
+ module Utils
3
+ # Provides a method to retrieve a logger
4
+ module Logger
5
+ autoload :ArrayOutputter, "derelict/utils/logger/array_outputter"
6
+ autoload :InvalidType, "derelict/utils/logger/invalid_type"
7
+ autoload :RawFormatter, "derelict/utils/logger/raw_formatter"
8
+
9
+ # Retrieves the logger for this class
10
+ def logger(options = {})
11
+ options = {:type => :internal}.merge(options)
12
+
13
+ case options[:type].to_sym
14
+ when :external
15
+ external_logger
16
+ when :internal
17
+ find_or_create_logger(logger_name)
18
+ else raise InvalidType.new options[:type]
19
+ end
20
+ end
21
+
22
+ private
23
+ # Finds or creates a Logger with a particular fullname
24
+ def find_or_create_logger(fullname)
25
+ Log4r::Logger[fullname.to_s] || Log4r::Logger.new(fullname.to_s)
26
+ end
27
+
28
+ # Gets the "external" logger, used to print to stdout
29
+ def external_logger
30
+ @@external ||= find_or_create_logger("external").tap do |external|
31
+ logger.debug "Created external logger instance"
32
+ external.add(Log4r::Outputter.stdout.tap do |outputter|
33
+ outputter.formatter = RawFormatter.new
34
+ end)
35
+ end
36
+ end
37
+
38
+ # Retrieves the name of the logger for this class
39
+ #
40
+ # By default, the name of the logger is just the lowercase
41
+ # version of the class name.
42
+ def logger_name
43
+ if self.is_a? Module
44
+ self.name.downcase
45
+ else
46
+ self.class.name.downcase
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,11 @@
1
+ module Derelict
2
+ # A namespaced collection of utilities for general purpose use
3
+ #
4
+ # Derelict::Utils contains all the individual sub-modules inside it.
5
+ module Utils
6
+ autoload :Logger, "derelict/utils/logger"
7
+
8
+ # Include sub-modules here
9
+ include Derelict::Utils::Logger
10
+ end
11
+ end
@@ -1,3 +1,3 @@
1
- class Derelict
2
- VERSION = "0.0.1"
1
+ module Derelict
2
+ VERSION = "0.1.0"
3
3
  end
@@ -0,0 +1,14 @@
1
+ module Derelict
2
+ class VirtualMachine
3
+ # Represents an invalid virtual machine, which Derelict can't use
4
+ class Invalid < ::Derelict::Exception
5
+ include Derelict::Exception::OptionalReason
6
+
7
+ private
8
+ # Retrieves the default error message
9
+ def default_message
10
+ "Invalid Derelict virtual machine"
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,18 @@
1
+ module Derelict
2
+ class VirtualMachine
3
+ # The requested virtual machine isn't defined in the Vagrantfile
4
+ class NotFound < Invalid
5
+ # Initializes a new instance of this exception for a given name
6
+ #
7
+ # * name: The requested name of the virtual machine
8
+ # * connection: The Derelict connection used for this VM
9
+ def initialize(name, connection = nil)
10
+ if connection.respond_to? :path
11
+ super "Virtual machine #{name} not found in #{connection.path}"
12
+ else
13
+ super "Virtual machine #{name} not found"
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,154 @@
1
+ module Derelict
2
+ # A Vagrant virtual machine in a particular Derelict connection
3
+ class VirtualMachine
4
+ autoload :Invalid, "derelict/virtual_machine/invalid"
5
+ autoload :NotFound, "derelict/virtual_machine/not_found"
6
+
7
+ # Include "memoize" class method to memoize methods
8
+ extend Memoist
9
+
10
+ # Include "logger" method to get a logger for this class
11
+ include Utils::Logger
12
+
13
+ COMMANDS = [
14
+ :up,
15
+ :halt,
16
+ :destroy,
17
+ :reload,
18
+ :suspend,
19
+ :resume,
20
+ ]
21
+
22
+ attr_reader :connection
23
+ attr_reader :name
24
+
25
+ # Initializes a new VirtualMachine for a connection and name
26
+ #
27
+ # * connection: The +Derelict::Connection+ to use to manipulate
28
+ # the VirtualMachine instance
29
+ # * name: The name of the virtual machine, used when
30
+ # communicating with the connection)
31
+ def initialize(connection, name)
32
+ @connection = connection
33
+ @name = name
34
+ logger.debug "Successfully initialized #{description}"
35
+ end
36
+
37
+ # Validates the data used for this connection
38
+ #
39
+ # Raises exceptions on failure:
40
+ #
41
+ # * +Derelict::VirtualMachine::NotFound+ if the connection
42
+ # doesn't know about a virtual machine with the requested
43
+ # name
44
+ def validate!
45
+ logger.debug "Starting validation for #{description}"
46
+ raise NotFound.new name, connection unless exists?
47
+ logger.info "Successfully validated #{description}"
48
+ self
49
+ end
50
+
51
+ # Determines whether this Vagrant virtual machine exists
52
+ #
53
+ # Returns +true+ if the connection reports a virtual machine with
54
+ # the requested name, otherwise returns +false+.
55
+ def exists?
56
+ status.exists? name
57
+ end
58
+ memoize :exists?
59
+
60
+ # Gets the current state of this Vagrant virtual machine
61
+ #
62
+ # The state is returned as a symbol, e.g. :running.
63
+ def state
64
+ status.state name
65
+ end
66
+ memoize :state
67
+
68
+ # Determines whether this virtual machine is currently running
69
+ def running?
70
+ (state == :running)
71
+ end
72
+ memoize :running?
73
+
74
+ # Add methods for each command
75
+ #
76
+ # A method is defined for each of the symbols in COMMANDS. The
77
+ # method name will be the symbol with an added bang (!). For
78
+ # example, #up!, #halt!, etc.
79
+ #
80
+ # Each method takes an options hash as an argument. For example:
81
+ #
82
+ # vm.up! :log => true
83
+ #
84
+ # This example will run the "up" command with logging enabled. The
85
+ # option keys can optionally include any of the following symbols:
86
+ #
87
+ # * log: Should the log output be printed? (defaults to false)
88
+ COMMANDS.each do |command|
89
+ define_method :"#{command}!" do |options|
90
+ # Log message if there's one for this command
91
+ message = log_message_for command
92
+ logger.info message unless message.nil?
93
+
94
+ # Set defaults for the options hash
95
+ options = {:log => false}.merge options
96
+
97
+ # Execute the command, optionally logging output
98
+ log_block = options[:log] ? shell_log_block : nil
99
+ connection.execute! command, name, *arguments_for(command), &log_block
100
+ end
101
+ end
102
+
103
+ # Retrieves the (parsed) status from the connection
104
+ def status
105
+ logger.info "Retrieving Vagrant status for #{description}"
106
+ output = connection.execute!(:status).stdout
107
+ Derelict::Parser::Status.new(output)
108
+ end
109
+ memoize :status
110
+
111
+ # Provides a description of this Connection
112
+ #
113
+ # Mainly used for log messages.
114
+ def description
115
+ "Derelict::VirtualMachine '#{name}' from #{connection.description}"
116
+ end
117
+
118
+ private
119
+ # A block that can be passed to #execute to log the output
120
+ def shell_log_block
121
+ Proc.new do |line|
122
+ logger(:type => :external).info line
123
+ end
124
+ end
125
+ memoize :shell_log_block
126
+
127
+ # Retrieves the arguments for a particular action
128
+ #
129
+ # * action: The symbol representing the action (one of :up,
130
+ # :halt, :destroy, :reload, :suspend, :resume)
131
+ def arguments_for(action)
132
+ case action
133
+ when :destroy then ['--force']
134
+ else []
135
+ end
136
+ end
137
+
138
+ # Retrieves the correct log message for a particular action
139
+ #
140
+ # * action: The symbol representing the action (one of :up,
141
+ # :halt, :destroy, :reload, :suspend, :resume)
142
+ def log_message_for(action)
143
+ case action
144
+ when :up then "Bringing up #{description}"
145
+ when :halt then "Halting #{description}"
146
+ when :destroy then "Destroying #{description}"
147
+ when :reload then "Reloading #{description}"
148
+ when :suspend then "Suspending #{description}"
149
+ when :resume then "Resuming #{description}"
150
+ else nil
151
+ end
152
+ end
153
+ end
154
+ end
data/lib/derelict.rb CHANGED
@@ -1,22 +1,69 @@
1
- require "rubygems"
2
1
  require "derelict/version"
2
+ require "log4r"
3
+ require "memoist"
4
+ require "shell/executer"
3
5
 
4
- # Controls a Vagrant instance
5
- class Derelict
6
- autoload :Instance, "derelict/instance"
7
- autoload :Exception, "derelict/exception"
6
+ Log4r::Logger["root"] # creates the level constants (INFO, etc).
8
7
 
9
- # Connects to an instance of Vagrant installed via Installer package
8
+ # Main module/entry point for Derelict
9
+ module Derelict
10
+ autoload :Connection, "derelict/connection"
11
+ autoload :Exception, "derelict/exception"
12
+ autoload :Instance, "derelict/instance"
13
+ autoload :Parser, "derelict/parser"
14
+ autoload :Utils, "derelict/utils"
15
+ autoload :VirtualMachine, "derelict/virtual_machine"
16
+
17
+ # Make functions accessible by Derelict.foo and private when included
18
+ module_function
19
+
20
+ # Include "logger" method to get a logger for this class
21
+ extend Utils::Logger
22
+
23
+ # Creates a new Derelict instance for a Vagrant installation
10
24
  #
11
- # path: The path to the location of the Vagrant instance
12
- def self.connect(path)
13
- Instance.new path
25
+ # * path: The path to the Vagrant installation (optional, defaults
26
+ # to Instance::DEFAULT_PATH)
27
+ def instance(path = Instance::DEFAULT_PATH)
28
+ logger.info "Creating and validating new instance for '#{path}'"
29
+ Instance.new(path).validate!
14
30
  end
15
31
 
16
- # Determines if an instance is currently active
17
- def self.active?
18
- Module.const_get("::Vagrant").is_a?(Class)
19
- rescue NameError
20
- false
32
+ # Enables (or disables) Derelict's debug mode
33
+ #
34
+ # When in debug mode, Derelict will log to stderr. The debug level
35
+ # can be controlled as well (which affects the verbosity of the
36
+ # logging).
37
+ #
38
+ # Valid (symbol) keys for the options hash include:
39
+ #
40
+ # * enabled: Whether debug mode should be enabled (defaults to true)
41
+ # * level: Allows setting a custom log level (defaults to INFO)
42
+ def debug!(options = {})
43
+ options = debug_options_defaults.merge options
44
+ logger.level = options[:enabled] ? options[:level] : Log4r::OFF
45
+
46
+ if options[:enabled]
47
+ logger.add stderr unless logger.outputters.include? stderr
48
+ logger.info "enabling debug mode"
49
+ else
50
+ logger.info "disabling debug mode"
51
+ logger.remove "stderr"
52
+ end
53
+
54
+ self
21
55
  end
56
+
57
+ private
58
+ # Retrieves the default values for the options hash for #debug!
59
+ def self.debug_options_defaults
60
+ {
61
+ :enabled => true,
62
+ :level => Log4r::INFO,
63
+ }
64
+ end
65
+
66
+ def self.stderr
67
+ Log4r::Outputter.stderr
68
+ end
22
69
  end
@@ -0,0 +1,16 @@
1
+ if ENV['TRAVIS']
2
+ # Running on Travis CI: initialize Coveralls to submit coverage data
3
+ require "coveralls"
4
+ Coveralls.wear!
5
+ else
6
+ # Not running on Travis CI: Run SimpleCov locally for coverage data
7
+ # Since SimpleCov requires Ruby 1.9+, only include it if we're
8
+ # running on a compatible version.
9
+ version_major = RbConfig::CONFIG["MAJOR"].to_i
10
+ version_minor = RbConfig::CONFIG["MINOR"].to_i
11
+ if version_major >= 1 and version_minor >= 9
12
+ require "simplecov"
13
+ SimpleCov.start
14
+ end
15
+ end
16
+
@@ -0,0 +1,16 @@
1
+ require "spec_helper"
2
+
3
+ describe Derelict::Connection::Invalid do
4
+ it "is autoloaded" do
5
+ should be_a Derelict::Connection::Invalid
6
+ end
7
+
8
+ context "when using default reason" do
9
+ its(:message) { should eq "Invalid Derelict connection" }
10
+ end
11
+
12
+ context "when using custom reason" do
13
+ subject { Derelict::Connection::Invalid.new "reason" }
14
+ its(:message) { should eq "Invalid Derelict connection: reason" }
15
+ end
16
+ end
@@ -0,0 +1,13 @@
1
+ require "spec_helper"
2
+
3
+ describe Derelict::Connection::NotFound do
4
+ subject { Derelict::Connection::NotFound.new "/foo/bar" }
5
+
6
+ it "is autoloaded" do
7
+ should be_a Derelict::Connection::NotFound
8
+ end
9
+
10
+ its(:message) {
11
+ should eq "Invalid Derelict connection: Vagrantfile not found for /foo/bar"
12
+ }
13
+ end