einhorn 0.4.7 → 0.4.8

Sign up to get free protection for your applications and to get access to all the features.
data/bin/einhorn CHANGED
@@ -187,6 +187,7 @@ if true # $0 == __FILE__
187
187
  Einhorn::TransientState.script_name = $0
188
188
  Einhorn::TransientState.argv = ARGV.dup
189
189
  Einhorn::TransientState.environ = ENV.to_hash
190
+ Einhorn.initialize_plugins
190
191
 
191
192
  optparse = OptionParser.new do |opts|
192
193
  opts.on('-b ADDR', '--bind ADDR', 'Bind an address and add the corresponding FD via the environment') do |addr|
@@ -274,6 +275,8 @@ if true # $0 == __FILE__
274
275
  Einhorn::Command.louder(false)
275
276
  end
276
277
 
278
+ Einhorn.plugins_send(:optparse, opts)
279
+
277
280
  opts.on('--nice MASTER[:WORKER=0][:RENICE_CMD=/usr/bin/renice]', 'Unix nice level at which to run the einhorn processes. If not running as root, make sure to ulimit -e as appopriate.') do |nice|
278
281
  master, worker, renice_cmd = nice.split(':')
279
282
  master = Integer(master) if master
@@ -306,6 +309,8 @@ if true # $0 == __FILE__
306
309
  exit(1)
307
310
  end
308
311
 
312
+ Einhorn.plugins_send(:post_optparse)
313
+
309
314
  ret = Einhorn.run
310
315
  begin
311
316
  exit(ret)
data/einhorn.gemspec CHANGED
@@ -15,7 +15,7 @@ Gem::Specification.new do |gem|
15
15
  gem.require_paths = ["lib"]
16
16
 
17
17
  gem.add_development_dependency('rake')
18
- gem.add_development_dependency('shoulda', '~> 3.4.0')
19
- gem.add_development_dependency('mocha')
18
+ gem.add_development_dependency('minitest', '< 5.0')
19
+ gem.add_development_dependency('mocha', '~> 0.13')
20
20
  gem.version = Einhorn::VERSION
21
21
  end
data/example/plugin.rb ADDED
@@ -0,0 +1,40 @@
1
+ #
2
+ # plugin.rb - An example Einhorn plugin.
3
+ #
4
+ # Including this file in [yourgemhere]/lib/einhorn/plugins/ will cause Einhorn
5
+ # to load it. This example plugin defines all the methods that Einhorn
6
+ # recognizes and will invoke, although none of these methods is required.
7
+ #
8
+
9
+ module Einhorn::Plugins
10
+ module ExamplePlugin
11
+ def self.initialize_example_plugin
12
+ # The initializer method must be named `initialize_##[plugin_name]',
13
+ # where [plugin_name] is the name of the plugin module or class in
14
+ # lower_case_with_underscores.
15
+ puts 'I will be called before einhorn does any work.'
16
+ end
17
+
18
+ def self.optparse(opts)
19
+ @options = {}
20
+ opts.on("--my-option X", "Patch einhorn with additional options!") do |x|
21
+ @options[:yay] = x
22
+ end
23
+ end
24
+
25
+ def self.post_optparse
26
+ # Called after all options native to einhorn or patched by any plugins
27
+ # are parsed.
28
+ @required_x = @options.fetch(:yay)
29
+ end
30
+
31
+ def self.event_loop
32
+ # Called each time einhorn enters its event loop, in which it cleans up
33
+ # any terminated children and respawns them.
34
+ end
35
+
36
+ def self.exit
37
+ # Called after the event loop terminates, just before einhorn exits.
38
+ end
39
+ end
40
+ end
data/lib/einhorn.rb CHANGED
@@ -6,7 +6,18 @@ require 'socket'
6
6
  require 'tmpdir'
7
7
  require 'yaml'
8
8
 
9
+ require 'einhorn/third/little-plugger'
10
+
9
11
  module Einhorn
12
+ extend Third::LittlePlugger
13
+ module Plugins; end
14
+
15
+ def self.plugins_send(sym, *args)
16
+ plugins.values.each do |plugin|
17
+ plugin.send(sym, *args) if plugin.respond_to? sym
18
+ end
19
+ end
20
+
10
21
  module AbstractState
11
22
  def default_state; raise NotImplementedError.new('Override in extended modules'); end
12
23
  def state; @state ||= default_state; end
@@ -321,6 +332,8 @@ module Einhorn
321
332
 
322
333
  while Einhorn::State.respawn || Einhorn::State.children.size > 0
323
334
  log_debug("Entering event loop")
335
+ Einhorn.plugins_send(:event_loop)
336
+
324
337
  # All of these are non-blocking
325
338
  Einhorn::Command.reap
326
339
  Einhorn::Command.replenish
@@ -329,6 +342,8 @@ module Einhorn
329
342
  # Make sure to do this last, as it's blocking.
330
343
  Einhorn::Event.loop_once
331
344
  end
345
+
346
+ Einhorn.plugins_send(:exit)
332
347
  end
333
348
  end
334
349
 
@@ -0,0 +1 @@
1
+ module Einhorn; module Third; end; end
@@ -0,0 +1,2 @@
1
+ require 'einhorn/third'
2
+ require 'einhorn/third/little-plugger/lib/little-plugger'
@@ -0,0 +1,17 @@
1
+ # The list of files that should be ignored by Mr Bones.
2
+ # Lines that start with '#' are comments.
3
+ #
4
+ # A .gitignore file can be used instead by setting it as the ignore
5
+ # file in your Rakefile:
6
+ #
7
+ # PROJ.ignore_file = '.gitignore'
8
+ #
9
+ # For a project with a C extension, the following would be a good set of
10
+ # exclude patterns (uncomment them if you want to use them):
11
+ # *.[oa]
12
+ # *~
13
+ announcement.txt
14
+ coverage
15
+ doc
16
+ pkg
17
+ .rvmrc
@@ -0,0 +1,30 @@
1
+ == 1.1.3 / 2011-11-17
2
+
3
+ * 1 bug fix
4
+ * Ensuring gem files are in a sorted order
5
+
6
+ == 1.1.2 / 2010-02-01
7
+
8
+ * 1 bug fix
9
+ * Resovling some circular dependencies
10
+
11
+ == 1.1.1 / 2009-11-08
12
+
13
+ * 1 bug fix
14
+ * Catching script errors and standard errors when loading plugins
15
+
16
+ == 1.1.0 / 2009-11-04
17
+
18
+ * 2 minor enhancements
19
+ * Loading the first plugin found by name (instead of the last)
20
+ * Plugins can be disregarded so they will not be loaded
21
+
22
+ == 1.0.1 / 2009-08-14
23
+
24
+ * 1 bug fix
25
+ * Using the wrong file extension for the File#basename call
26
+
27
+ == 1.0.0 / 2009-07-16
28
+
29
+ * 1 major enhancement
30
+ * Birthday!
@@ -0,0 +1,53 @@
1
+ = Little Plugger
2
+ * by Tim Pease
3
+ * http://github.com/TwP/little-plugger/tree/master
4
+
5
+ === DESCRIPTION:
6
+
7
+ LittlePlugger is a module that provides Gem based plugin management.
8
+ By extending your own class or module with LittlePlugger you can easily
9
+ manage the loading and initializing of plugins provided by other gems.
10
+
11
+ === FEATURES:
12
+
13
+ * List of plugins so that some plugins can be excluded while others are
14
+ loaded by default.
15
+ * Loading and initializing of plugins.
16
+ * Access to the plugin classes and modules.
17
+
18
+ LittlePlugger is a distallation of the plugin system from Hoe. It has been
19
+ "genericized" and encapsulated into its own easy to use module.
20
+
21
+ === REQUIREMENTS:
22
+
23
+ Since Little Plugger is a Gem based plugin system, Ruby Gems must be
24
+ installed on your system.
25
+
26
+ === INSTALL:
27
+
28
+ gem install little-plugger
29
+
30
+ === LICENSE:
31
+
32
+ (The MIT License)
33
+
34
+ Copyright (c) 2009-2011
35
+
36
+ Permission is hereby granted, free of charge, to any person obtaining
37
+ a copy of this software and associated documentation files (the
38
+ 'Software'), to deal in the Software without restriction, including
39
+ without limitation the rights to use, copy, modify, merge, publish,
40
+ distribute, sublicense, and/or sell copies of the Software, and to
41
+ permit persons to whom the Software is furnished to do so, subject to
42
+ the following conditions:
43
+
44
+ The above copyright notice and this permission notice shall be
45
+ included in all copies or substantial portions of the Software.
46
+
47
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
48
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
49
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
50
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
51
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
52
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
53
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,31 @@
1
+
2
+ begin
3
+ require 'bones'
4
+ rescue LoadError
5
+ abort '### please install the "bones" gem ###'
6
+ end
7
+
8
+ ensure_in_path 'lib'
9
+ require 'little-plugger'
10
+
11
+ task :default => 'spec:run'
12
+ task 'gem:release' => 'spec:run'
13
+
14
+ Bones {
15
+ name 'little-plugger'
16
+ authors 'Tim Pease'
17
+ email 'tim.pease@gmail.com'
18
+ url 'http://gemcutter.org/gems/little-plugger'
19
+ version LittlePlugger::VERSION
20
+ readme_file 'README.rdoc'
21
+
22
+ spec.opts.concat %w[--color --format documentation]
23
+ use_gmail
24
+
25
+ depend_on 'rspec', :development => true
26
+ }
27
+
28
+ # depending on bones (even as a development dependency) creates a circular
29
+ # reference that prevents the auto install of little-plugger when instsalling
30
+ # bones
31
+ ::Bones.config.gem._spec.dependencies.delete_if {|d| d.name == 'bones'}
@@ -0,0 +1,325 @@
1
+
2
+ # == Synopsis
3
+ # LittlePlugger is a module that provides Gem based plugin management.
4
+ # By extending your own class or module with LittlePlugger you can easily
5
+ # manage the loading and initializing of plugins provided by other gems.
6
+ #
7
+ # == Details
8
+ # Plugins are great! They allow other developers to add functionality to
9
+ # an application but relieve the application developer of the responsibility
10
+ # for mainting some other developer's plugin code. LittlePlugger aims to
11
+ # make it dead simple to manage external plugins as gems.
12
+ #
13
+ # === Naming
14
+ # Every plugin managed by LittlePlugger will have a name represented as a
15
+ # Symbol. This name is used to register the plugin, load the plugin file,
16
+ # and manage the plugin class/module. Here are the three rules for plugin
17
+ # names:
18
+ #
19
+ # 1) all lowercase with underscores
20
+ # 2) maps to a file of the same name with an '.rb' extension
21
+ # 3) converting the name to camel case yields the plugin class / module
22
+ #
23
+ # These rules are essentially the standard ruby practice of naming files
24
+ # after the class / module the file defines.
25
+ #
26
+ # === Finding & Loading
27
+ # Plugins are found by searching through the lib folders of all installed
28
+ # gems; these gems are not necessarily loaded - just searched. If the lib
29
+ # folder has a subdirectory that matches the +plugin_path+, then all ruby
30
+ # files in the gem's +plugin_path+ are noted for later loading.
31
+ #
32
+ # A file is only loaded if the basename of the file matches one of the
33
+ # registered plugin names. If no plugins are registered, then every file in
34
+ # the +plugin_path+ is loaded.
35
+ #
36
+ # The plugin classes / modules are all expected to live in the same
37
+ # namespace for a particular application. For example, all plugins for the
38
+ # "Foo" application should reside in a "Foo::Plugins" namespace. This allows
39
+ # the plugins to be automatically initialized by LittlePlugger.
40
+ #
41
+ # === Initializing
42
+ # Optionally, plugins can provide an initialization method for running any
43
+ # setup code needed by the plugin. This initialize method should be named as
44
+ # follows: "initializer_#{plugin_name}" where the name of the plugin is
45
+ # appended to the end of the initializer method name.
46
+ #
47
+ # If this method exists, it will be called automatically when plugins are
48
+ # loaded. The order of loading of initialization is not strictly defined, so
49
+ # do not rely on another plugin being initialized for your own plugin
50
+ # successfully initialize.
51
+ #
52
+ # == Usage
53
+ # LittlePlugger is used by extending your own class or module with the
54
+ # LittlePlugger module.
55
+ #
56
+ # module Logging
57
+ # extend LittlePlugger
58
+ # end
59
+ #
60
+ # This defines a +plugin_path+ and a +plugin_module+ for our Logging module.
61
+ # The +plugin_path+ is set to "logging/plugins", and therefore, the
62
+ # +plugin_modlue+ is defined as Logging::Plugins. All plugins for the
63
+ # Logging module should be found underneath this plugin module.
64
+ #
65
+ # The plugins for the Logging module are loaded and initialized by calling
66
+ # the +initialize_plugins+ method.
67
+ #
68
+ # Logging.initialize_plugins
69
+ #
70
+ # If you only want to load the plugin files but not initialize the plugin
71
+ # classes / modules then you can call the +load_plugins+ method.
72
+ #
73
+ # Logging.load_plugins
74
+ #
75
+ # Finally, you can get a hash of all the loaded plugins.
76
+ #
77
+ # Logging.plugins
78
+ #
79
+ # This returns a hash keyed by the plugin names with the plugin class /
80
+ # module as the value.
81
+ #
82
+ # If you only want a certain set of plugins to be loaded, then pass the
83
+ # names to the +plugin+ method.
84
+ #
85
+ # Logging.plugin :foo, :bar, :baz
86
+ #
87
+ # Now only three plugins for the Logging module will be loaded.
88
+ #
89
+ # === Customizing
90
+ # LittlePlugger allows the use of a custom plugin path and module. These are
91
+ # specified when extending with LilttlePlugger by passing the specific path
92
+ # and module to LittlePlugger.
93
+ #
94
+ # class Hoe
95
+ # extend LittlePlugger( :path => 'hoe', :module => Hoe )
96
+ #
97
+ # plugin(
98
+ # :clean, :debug, :deps, :flay, :flog, :package,
99
+ # :publish, :rcov, :signing, :test
100
+ # )
101
+ # end
102
+ #
103
+ # All ruby files found under the "hoe" directory will be treated as
104
+ # plugins, and the plugin classes / modules should reside directly under the
105
+ # Hoe namespace.
106
+ #
107
+ # We also specify a list of plugins to be loaded. Only these plugins will be
108
+ # loaded and initialized by the LittlePlugger module. The +plugin+ method
109
+ # can be called multiple times to add more plugins.
110
+ #
111
+ module Einhorn::Third::LittlePlugger
112
+
113
+ VERSION = '1.1.3' # :nodoc:
114
+
115
+ # Returns the version string for the library.
116
+ #
117
+ def self.version
118
+ VERSION
119
+ end
120
+
121
+ module ClassMethods
122
+
123
+ # Add the _names_ to the list of plugins that will be loaded.
124
+ #
125
+ def plugin( *names )
126
+ plugin_names.concat(names.map! {|n| n.to_sym})
127
+ end
128
+
129
+ # Add the _names_ to the list of plugins that will *not* be loaded. This
130
+ # list prevents the plugin system from loading unwanted or unneeded
131
+ # plugins.
132
+ #
133
+ # If a plugin name appears in both the 'disregard_plugin' list and the
134
+ # 'plugin' list, the disregard list takes precedence; that is, the plugin
135
+ # will not be loaded.
136
+ #
137
+ def disregard_plugin( *names )
138
+ @disregard_plugin ||= []
139
+ @disregard_plugin.concat(names.map! {|n| n.to_sym})
140
+ @disregard_plugin
141
+ end
142
+ alias :disregard_plugins :disregard_plugin
143
+
144
+ # Returns the array of plugin names that will be loaded. If the array is
145
+ # empty, then any plugin found in the +plugin_path+ will be loaded.
146
+ #
147
+ def plugin_names
148
+ @plugin_names ||= []
149
+ end
150
+
151
+ # Loads the desired plugins and returns a hash. The hash contains all
152
+ # the plugin classes and modules keyed by the plugin name.
153
+ #
154
+ def plugins
155
+ load_plugins
156
+ pm = plugin_module
157
+ names = pm.constants.map { |s| s.to_s }
158
+ names.reject! { |n| n =~ %r/^[A-Z_]+$/ }
159
+
160
+ h = {}
161
+ names.each do |name|
162
+ sym = ::Einhorn::Third::LittlePlugger.underscore(name).to_sym
163
+ next unless plugin_names.empty? or plugin_names.include? sym
164
+ next if disregard_plugins.include? sym
165
+ h[sym] = pm.const_get name
166
+ end
167
+ h
168
+ end
169
+
170
+ # Iterate over the loaded plugin classes and modules and call the
171
+ # initialize method for each plugin. The plugin's initialize method is
172
+ # defeind as +initialize_plugin_name+, where the plugin name is unique
173
+ # to each plugin.
174
+ #
175
+ def initialize_plugins
176
+ plugins.each do |name, klass|
177
+ msg = "initialize_#{name}"
178
+ klass.send msg if klass.respond_to? msg
179
+ end
180
+ end
181
+
182
+ # Iterate through all installed gems looking for those that have the
183
+ # +plugin_path+ in their "lib" folder, and load all .rb files found in
184
+ # the gem's plugin path. Each .rb file should define one class or module
185
+ # that will be used as a plugin.
186
+ #
187
+ def load_plugins
188
+ @loaded ||= {}
189
+ found = {}
190
+
191
+ Gem.find_files(File.join(plugin_path, '*.rb')).sort!.reverse_each do |path|
192
+ name = File.basename(path, '.rb').to_sym
193
+ found[name] = path unless found.key? name
194
+ end
195
+
196
+ :keep_on_truckin while found.map { |name, path|
197
+ next unless plugin_names.empty? or plugin_names.include? name
198
+ next if disregard_plugins.include? name
199
+ next if @loaded[name]
200
+ begin
201
+ @loaded[name] = load path
202
+ rescue ScriptError, StandardError => err
203
+ warn "Error loading #{path.inspect}: #{err.message}. skipping..."
204
+ end
205
+ }.any?
206
+ end
207
+
208
+ # The path to search in a gem's 'lib' folder for plugins.
209
+ #
210
+ def plugin_path
211
+ ::Einhorn::Third::LittlePlugger.default_plugin_path(self)
212
+ end
213
+
214
+ # This module or class where plugins are located.
215
+ #
216
+ def plugin_module
217
+ ::Einhorn::Third::LittlePlugger.default_plugin_module(plugin_path)
218
+ end
219
+
220
+ end # module ClassMethods
221
+
222
+ # :stopdoc:
223
+
224
+ # Called when another object extends itself with LittlePlugger.
225
+ #
226
+ def self.extended( other )
227
+ other.extend ClassMethods
228
+ end
229
+
230
+ # Convert the given string from camel case to snake case. Method liberally
231
+ # stolen from ActiveSupport.
232
+ #
233
+ # underscore( "FooBar" ) #=> "foo_bar"
234
+ #
235
+ def self.underscore( string )
236
+ string.to_s.
237
+ gsub(%r/::/, '/').
238
+ gsub(%r/([A-Z]+)([A-Z][a-z])/,'\1_\2').
239
+ gsub(%r/([a-z\d])([A-Z])/,'\1_\2').
240
+ tr('-', '_').
241
+ downcase
242
+ end
243
+
244
+ # For a given object returns a default plugin path. The path is
245
+ # created by splitting the object's class name on the namespace separator
246
+ # "::" and converting each part of the namespace into an underscored
247
+ # string (see the +underscore+ method). The strings are then joined using
248
+ # the File#join method to give a filesystem path. Appended to this path is
249
+ # the 'plugins' directory.
250
+ #
251
+ # default_plugin_path( FooBar::Baz ) #=> "foo_bar/baz/plugins"
252
+ #
253
+ def self.default_plugin_path( obj )
254
+ obj = obj.class unless obj.is_a? Module
255
+ File.join(underscore(obj.name), 'plugins')
256
+ end
257
+
258
+ # For a given path returns the class or module corresponding to the
259
+ # path. This method assumes a correspondence between directory names and
260
+ # Ruby namespaces.
261
+ #
262
+ # default_plugin_module( "foo_bar/baz/plugins" ) #=> FooBar::Baz::Plugins
263
+ #
264
+ # This method will fail if any of the namespaces have not yet been
265
+ # defined.
266
+ #
267
+ def self.default_plugin_module( path )
268
+ path.split(File::SEPARATOR).inject(Object) do |mod, const|
269
+ const = const.split('_').map { |s| s.capitalize }.join
270
+ mod.const_get const
271
+ end
272
+ end
273
+ # :startdoc:
274
+
275
+ end # module Einhorn::Third::LittlePlugger
276
+
277
+
278
+ module Kernel
279
+ module Einhorn::Third
280
+
281
+ # call-seq:
282
+ # LittlePlugger( opts = {} )
283
+ #
284
+ # This method allows the user to override some of LittlePlugger's default
285
+ # settings when mixed into a module or class.
286
+ #
287
+ # See the "Customizing" section of the LittlePlugger documentation for an
288
+ # example of how this method is used.
289
+ #
290
+ # ==== Options
291
+ #
292
+ # * :path <String>
293
+ # The default plugin path. Defaults to "module_name/plugins".
294
+ #
295
+ # * :module <Module>
296
+ # The module where plugins will be loaded. Defaults to
297
+ # ModuleName::Plugins.
298
+ #
299
+ # * :plugins <Array>
300
+ # The array of default plugins to load. Only the plugins listed in this
301
+ # array will be loaded by LittlePlugger.
302
+ #
303
+ def LittlePlugger( opts = {} )
304
+ return ::Einhorn::LittlePlugger::ClassMethods if opts.empty?
305
+ Module.new {
306
+ include ::Einhorn::LittlePlugger::ClassMethods
307
+
308
+ if opts.key?(:path)
309
+ eval %Q{def plugin_path() #{opts[:path].to_s.inspect} end}
310
+ end
311
+
312
+ if opts.key?(:module)
313
+ eval %Q{def plugin_module() #{opts[:module].name} end}
314
+ end
315
+
316
+ if opts.key?(:plugins)
317
+ plugins = Array(opts[:plugins]).map {|val| val.to_sym.inspect}.join(',')
318
+ eval %Q{def plugin_names() @plugin_names ||= [#{plugins}] end}
319
+ end
320
+ }
321
+ end
322
+ end # module Einhorn::Third
323
+ end # module Kernel
324
+
325
+ # EOF
@@ -0,0 +1,26 @@
1
+
2
+ require File.join(File.dirname(__FILE__), %w[spec_helper])
3
+
4
+ describe LittlePlugger do
5
+
6
+ it "converts a string from camel-case to underscore" do
7
+ LittlePlugger.underscore('FooBarBaz').should be == 'foo_bar_baz'
8
+ LittlePlugger.underscore('CouchDB').should be == 'couch_db'
9
+ LittlePlugger.underscore('FOOBar').should be == 'foo_bar'
10
+ LittlePlugger.underscore('Foo::Bar::BazBuz').should be == 'foo/bar/baz_buz'
11
+ end
12
+
13
+ it "generates a default plugin path" do
14
+ LittlePlugger.default_plugin_path(LittlePlugger).should be == 'little_plugger/plugins'
15
+ LittlePlugger.default_plugin_path(Process::Status).should be == 'process/status/plugins'
16
+ end
17
+
18
+ it "generates a default plugin module" do
19
+ LittlePlugger.default_plugin_module('little_plugger').should be == LittlePlugger
20
+ lambda {LittlePlugger.default_plugin_module('little_plugger/plugins')}.
21
+ should raise_error(NameError, 'uninitialized constant LittlePlugger::Plugins')
22
+ LittlePlugger.default_plugin_module('process/status').should be == Process::Status
23
+ end
24
+ end
25
+
26
+ # EOF
@@ -0,0 +1,4 @@
1
+
2
+ require File.expand_path(
3
+ File.join(File.dirname(__FILE__), %w[.. lib little-plugger]))
4
+
@@ -1,3 +1,3 @@
1
1
  module Einhorn
2
- VERSION = '0.4.7'
2
+ VERSION = '0.4.8'
3
3
  end
data/test/_lib.rb ADDED
@@ -0,0 +1,12 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ require 'minitest/autorun'
5
+ require 'minitest/spec'
6
+ require 'mocha/setup'
7
+
8
+ class EinhornTestCase < ::MiniTest::Spec
9
+ def setup
10
+ # Put global stubs here
11
+ end
12
+ end
data/test/unit/einhorn.rb CHANGED
@@ -1,14 +1,14 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '../test_helper'))
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '../_lib'))
2
2
 
3
3
  require 'einhorn'
4
4
 
5
- class EinhornTest < Test::Unit::TestCase
6
- context "when sockifying" do
7
- teardown do
5
+ class EinhornTest < EinhornTestCase
6
+ describe "when sockifying" do
7
+ after do
8
8
  Einhorn::State.sockets = {}
9
9
  end
10
10
 
11
- should "correctly parse srv: arguments" do
11
+ it "correctly parses srv: arguments" do
12
12
  cmd = ['foo', 'srv:1.2.3.4:123,llama,test', 'bar']
13
13
  Einhorn.expects(:bind).once.with('1.2.3.4', '123', ['llama', 'test']).returns(4)
14
14
 
@@ -17,7 +17,7 @@ class EinhornTest < Test::Unit::TestCase
17
17
  assert_equal(['foo', '4', 'bar'], cmd)
18
18
  end
19
19
 
20
- should "correctly parse --opt=srv: arguments" do
20
+ it "correctly parses --opt=srv: arguments" do
21
21
  cmd = ['foo', '--opt=srv:1.2.3.4:456', 'baz']
22
22
  Einhorn.expects(:bind).once.with('1.2.3.4', '456', []).returns(5)
23
23
 
@@ -26,7 +26,7 @@ class EinhornTest < Test::Unit::TestCase
26
26
  assert_equal(['foo', '--opt=5', 'baz'], cmd)
27
27
  end
28
28
 
29
- should "use the same fd number for the same server spec" do
29
+ it "uses the same fd number for the same server spec" do
30
30
  cmd = ['foo', '--opt=srv:1.2.3.4:8910', 'srv:1.2.3.4:8910']
31
31
  Einhorn.expects(:bind).once.with('1.2.3.4', '8910', []).returns(10)
32
32
 
@@ -36,8 +36,8 @@ class EinhornTest < Test::Unit::TestCase
36
36
  end
37
37
  end
38
38
 
39
- context '.update_state' do
40
- should 'correctly update keys to match new default state hash' do
39
+ describe '.update_state' do
40
+ it 'correctly updates keys to match new default state hash' do
41
41
  Einhorn::State.stubs(:default_state).returns(:baz => 23, :foo => 1)
42
42
  old_state = {:foo => 2, :bar => 2}
43
43
 
@@ -46,7 +46,7 @@ class EinhornTest < Test::Unit::TestCase
46
46
  assert_match(/State format has changed/, message)
47
47
  end
48
48
 
49
- should 'not change the state if the format has not changed' do
49
+ it 'does not change the state if the format has not changed' do
50
50
  Einhorn::State.stubs(:default_state).returns(:baz => 23, :foo => 1)
51
51
  old_state = {:baz => 14, :foo => 1234}
52
52
 
@@ -1,8 +1,8 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '../../test_helper'))
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '../../_lib'))
2
2
 
3
3
  require 'einhorn'
4
4
 
5
- class ClientTest < Test::Unit::TestCase
5
+ class ClientTest < EinhornTestCase
6
6
  def unserialized_message
7
7
  {:foo => ['%bar', '%baz']}
8
8
  end
@@ -15,8 +15,8 @@ class ClientTest < Test::Unit::TestCase
15
15
  "---%0A:foo:%0A- ! '%25bar'%0A- ! '%25baz'%0A\n"
16
16
  end
17
17
 
18
- context "when sending a message" do
19
- should "write a serialized line" do
18
+ describe "when sending a message" do
19
+ it "writes a serialized line" do
20
20
  socket = mock
21
21
  socket.expects(:write).with do |write|
22
22
  write == serialized_1_8 || write == serialized_1_9
@@ -25,15 +25,15 @@ class ClientTest < Test::Unit::TestCase
25
25
  end
26
26
  end
27
27
 
28
- context "when receiving a message" do
29
- should "deserialize a single 1.8-style line" do
28
+ describe "when receiving a message" do
29
+ it "deserializes a single 1.8-style line" do
30
30
  socket = mock
31
31
  socket.expects(:readline).returns(serialized_1_8)
32
32
  result = Einhorn::Client::Transport.receive_message(socket)
33
33
  assert_equal(result, unserialized_message)
34
34
  end
35
35
 
36
- should "deserialize a single 1.9-style line" do
36
+ it "deserializes a single 1.9-style line" do
37
37
  socket = mock
38
38
  socket.expects(:readline).returns(serialized_1_9)
39
39
  result = Einhorn::Client::Transport.receive_message(socket)
@@ -41,23 +41,23 @@ class ClientTest < Test::Unit::TestCase
41
41
  end
42
42
  end
43
43
 
44
- context "when {de,}serializing a message" do
45
- should "serialize and escape a message as expected" do
44
+ describe "when {de,}serializing a message" do
45
+ it "serializes and escape a message as expected" do
46
46
  actual = Einhorn::Client::Transport.serialize_message(unserialized_message)
47
47
  assert(actual == serialized_1_8 || actual == serialized_1_9, "Actual message is #{actual.inspect}")
48
48
  end
49
49
 
50
- should "deserialize and unescape a 1.8-style message as expected" do
50
+ it "deserializes and unescape a 1.8-style message as expected" do
51
51
  actual = Einhorn::Client::Transport.deserialize_message(serialized_1_8)
52
52
  assert_equal(unserialized_message, actual)
53
53
  end
54
54
 
55
- should "deserialize and unescape a 1.9-style message as expected" do
55
+ it "deserializes and unescape a 1.9-style message as expected" do
56
56
  actual = Einhorn::Client::Transport.deserialize_message(serialized_1_9)
57
57
  assert_equal(unserialized_message, actual)
58
58
  end
59
59
 
60
- should "raise an error when deserializing invalid YAML" do
60
+ it "raises an error when deserializing invalid YAML" do
61
61
  invalid_serialized = "-%0A\t-"
62
62
  expected = [ArgumentError]
63
63
  expected << Psych::SyntaxError if defined?(Psych::SyntaxError) # 1.9
@@ -1,18 +1,18 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '../../test_helper'))
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '../../_lib'))
2
2
 
3
3
  require 'einhorn'
4
4
 
5
- class CommandTest < Test::Unit::TestCase
5
+ class CommandTest < EinhornTestCase
6
6
  include Einhorn
7
7
 
8
- context "when running quieter" do
9
- should "increase the verbosity threshold" do
8
+ describe "when running quieter" do
9
+ it "increases the verbosity threshold" do
10
10
  Einhorn::State.stubs(:verbosity => 1)
11
11
  Einhorn::State.expects(:verbosity=).once.with(2).returns(2)
12
12
  Command.quieter
13
13
  end
14
14
 
15
- should "max out at 2" do
15
+ it "maxes out at 2" do
16
16
  Einhorn::State.stubs(:verbosity => 2)
17
17
  Einhorn::State.expects(:verbosity=).never
18
18
  Command.quieter
@@ -1,12 +1,12 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '../../../test_helper'))
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '../../../_lib'))
2
2
 
3
3
  require 'einhorn'
4
4
 
5
- class InterfaceTest < Test::Unit::TestCase
5
+ class InterfaceTest < EinhornTestCase
6
6
  include Einhorn::Command
7
7
 
8
- context "when a command is received" do
9
- should "call that command" do
8
+ describe "when a command is received" do
9
+ it "calls that command" do
10
10
  conn = stub(:log_debug => nil)
11
11
  conn.expects(:write).once.with do |message|
12
12
  # Remove trailing newline
@@ -22,8 +22,8 @@ class InterfaceTest < Test::Unit::TestCase
22
22
  end
23
23
  end
24
24
 
25
- context "when an unrecognized command is received" do
26
- should "call the unrecognized_command method" do
25
+ describe "when an unrecognized command is received" do
26
+ it "calls the unrecognized_command method" do
27
27
  conn = stub(:log_debug => nil)
28
28
  Interface.expects(:unrecognized_command).once
29
29
  request = {
@@ -33,8 +33,8 @@ class InterfaceTest < Test::Unit::TestCase
33
33
  end
34
34
  end
35
35
 
36
- context "when a worker ack is received" do
37
- should "register ack and close the connection" do
36
+ describe "when a worker ack is received" do
37
+ it "registers ack and close the connection" do
38
38
  conn = stub(:log_debug => nil)
39
39
  conn.expects(:close).once
40
40
  conn.expects(:write).never
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '../../test_helper'))
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '../../_lib'))
2
2
 
3
3
  require 'set'
4
4
  require 'einhorn'
@@ -13,17 +13,17 @@ module Einhorn::Event
13
13
  end
14
14
  end
15
15
 
16
- class EventTest < Test::Unit::TestCase
17
- context "when running the event loop" do
18
- setup do
16
+ class EventTest < EinhornTestCase
17
+ describe "when running the event loop" do
18
+ before do
19
19
  Einhorn::Event.reset
20
20
  end
21
21
 
22
- teardown do
22
+ after do
23
23
  Einhorn::Event.reset
24
24
  end
25
25
 
26
- should "select on readable descriptors" do
26
+ it "selects on readable descriptors" do
27
27
  sock1 = mock(:fileno => 4)
28
28
  sock2 = mock(:fileno => 5)
29
29
 
@@ -40,7 +40,7 @@ class EventTest < Test::Unit::TestCase
40
40
  Einhorn::Event.loop_once
41
41
  end
42
42
 
43
- should "select on writeable descriptors" do
43
+ it "selects on writeable descriptors" do
44
44
  sock1 = mock(:fileno => 4)
45
45
  sock2 = mock(:fileno => 5)
46
46
 
@@ -60,7 +60,7 @@ class EventTest < Test::Unit::TestCase
60
60
  Einhorn::Event.loop_once
61
61
  end
62
62
 
63
- should "run callbacks for ready selectables" do
63
+ it "runs callbacks for ready selectables" do
64
64
  sock1 = mock(:fileno => 4)
65
65
  sock2 = mock(:fileno => 5)
66
66
 
@@ -1,8 +1,8 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '../../test_helper'))
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '../../_lib'))
2
2
 
3
3
  require 'einhorn'
4
4
 
5
- class WorkerPoolTest < Test::Unit::TestCase
5
+ class WorkerPoolTest < EinhornTestCase
6
6
  def stub_children
7
7
  Einhorn::State.stubs(:children).returns(
8
8
  1234 => {:type => :worker, :signaled => Set.new(['INT'])},
@@ -11,12 +11,12 @@ class WorkerPoolTest < Test::Unit::TestCase
11
11
  )
12
12
  end
13
13
 
14
- context "#workers_with_state" do
15
- setup do
14
+ describe "#workers_with_state" do
15
+ before do
16
16
  stub_children
17
17
  end
18
18
 
19
- should "select only the workers" do
19
+ it "selects only the workers" do
20
20
  workers_with_state = Einhorn::WorkerPool.workers_with_state
21
21
  # Sort only needed for Ruby 1.8
22
22
  assert_equal([
@@ -26,12 +26,12 @@ class WorkerPoolTest < Test::Unit::TestCase
26
26
  end
27
27
  end
28
28
 
29
- context "#unsignaled_workers" do
30
- setup do
29
+ describe "#unsignaled_workers" do
30
+ before do
31
31
  stub_children
32
32
  end
33
33
 
34
- should "selects unsignaled workers" do
34
+ it "selects unsignaled workers" do
35
35
  unsignaled_workers = Einhorn::WorkerPool.unsignaled_workers
36
36
  assert_equal([1236], unsignaled_workers)
37
37
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: einhorn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.7
4
+ version: 0.4.8
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-20 00:00:00.000000000 Z
12
+ date: 2013-07-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -28,37 +28,37 @@ dependencies:
28
28
  - !ruby/object:Gem::Version
29
29
  version: '0'
30
30
  - !ruby/object:Gem::Dependency
31
- name: shoulda
31
+ name: minitest
32
32
  requirement: !ruby/object:Gem::Requirement
33
33
  none: false
34
34
  requirements:
35
- - - ~>
35
+ - - <
36
36
  - !ruby/object:Gem::Version
37
- version: 3.4.0
37
+ version: '5.0'
38
38
  type: :development
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
41
41
  none: false
42
42
  requirements:
43
- - - ~>
43
+ - - <
44
44
  - !ruby/object:Gem::Version
45
- version: 3.4.0
45
+ version: '5.0'
46
46
  - !ruby/object:Gem::Dependency
47
47
  name: mocha
48
48
  requirement: !ruby/object:Gem::Requirement
49
49
  none: false
50
50
  requirements:
51
- - - ! '>='
51
+ - - ~>
52
52
  - !ruby/object:Gem::Version
53
- version: '0'
53
+ version: '0.13'
54
54
  type: :development
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  none: false
58
58
  requirements:
59
- - - ! '>='
59
+ - - ~>
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: '0.13'
62
62
  description: Einhorn makes it easy to run multiple instances of an application server,
63
63
  all listening on the same port. You can also seamlessly restart your workers without
64
64
  dropping any requests. Einhorn requires minimal application-level support, making
@@ -81,6 +81,7 @@ files:
81
81
  - bin/einhorn
82
82
  - bin/einhornsh
83
83
  - einhorn.gemspec
84
+ - example/plugin.rb
84
85
  - example/pool_worker.rb
85
86
  - example/thin_example
86
87
  - example/time_server
@@ -96,10 +97,19 @@ files:
96
97
  - lib/einhorn/event/loop_breaker.rb
97
98
  - lib/einhorn/event/persistent.rb
98
99
  - lib/einhorn/event/timer.rb
100
+ - lib/einhorn/third.rb
101
+ - lib/einhorn/third/little-plugger.rb
102
+ - lib/einhorn/third/little-plugger/.gitignore
103
+ - lib/einhorn/third/little-plugger/History.txt
104
+ - lib/einhorn/third/little-plugger/README.rdoc
105
+ - lib/einhorn/third/little-plugger/Rakefile
106
+ - lib/einhorn/third/little-plugger/lib/little-plugger.rb
107
+ - lib/einhorn/third/little-plugger/spec/little-plugger_spec.rb
108
+ - lib/einhorn/third/little-plugger/spec/spec_helper.rb
99
109
  - lib/einhorn/version.rb
100
110
  - lib/einhorn/worker.rb
101
111
  - lib/einhorn/worker_pool.rb
102
- - test/test_helper.rb
112
+ - test/_lib.rb
103
113
  - test/unit/einhorn.rb
104
114
  - test/unit/einhorn/client.rb
105
115
  - test/unit/einhorn/command.rb
@@ -131,11 +141,10 @@ signing_key:
131
141
  specification_version: 3
132
142
  summary: ! 'Einhorn: the language-independent shared socket manager'
133
143
  test_files:
134
- - test/test_helper.rb
144
+ - test/_lib.rb
135
145
  - test/unit/einhorn.rb
136
146
  - test/unit/einhorn/client.rb
137
147
  - test/unit/einhorn/command.rb
138
148
  - test/unit/einhorn/command/interface.rb
139
149
  - test/unit/einhorn/event.rb
140
150
  - test/unit/einhorn/worker_pool.rb
141
- has_rdoc:
data/test/test_helper.rb DELETED
@@ -1,8 +0,0 @@
1
- require 'rubygems'
2
- require 'bundler/setup'
3
-
4
- require 'test/unit'
5
- require 'mocha'
6
- require 'shoulda'
7
-
8
- $:.unshift(File.join(File.dirname(__FILE__), '../lib'))