duck_test 0.1.4

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 (45) hide show
  1. data/bin/ducktest +29 -0
  2. data/lib/duck_test/autoload_config.rb +103 -0
  3. data/lib/duck_test/base.rb +41 -0
  4. data/lib/duck_test/commands.rb +208 -0
  5. data/lib/duck_test/config.rb +675 -0
  6. data/lib/duck_test/config_helper.rb +99 -0
  7. data/lib/duck_test/console.rb +18 -0
  8. data/lib/duck_test/default_config.rb +48 -0
  9. data/lib/duck_test/frame_work/base.rb +587 -0
  10. data/lib/duck_test/frame_work/file_manager.rb +511 -0
  11. data/lib/duck_test/frame_work/filter_set.rb +233 -0
  12. data/lib/duck_test/frame_work/map.rb +331 -0
  13. data/lib/duck_test/frame_work/queue.rb +221 -0
  14. data/lib/duck_test/frame_work/queue_event.rb +29 -0
  15. data/lib/duck_test/frame_work/rspec/base.rb +17 -0
  16. data/lib/duck_test/frame_work/rspec/frame_work.rb +30 -0
  17. data/lib/duck_test/frame_work/test_unit/base.rb +14 -0
  18. data/lib/duck_test/frame_work/test_unit/frame_work.rb +33 -0
  19. data/lib/duck_test/frame_work/watch_config.rb +69 -0
  20. data/lib/duck_test/gem/helper.rb +107 -0
  21. data/lib/duck_test/logger.rb +127 -0
  22. data/lib/duck_test/option_parser.rb +30 -0
  23. data/lib/duck_test/platforms/base.rb +18 -0
  24. data/lib/duck_test/platforms/dependencies.rb +18 -0
  25. data/lib/duck_test/platforms/generic/base.rb +15 -0
  26. data/lib/duck_test/platforms/generic/listener.rb +104 -0
  27. data/lib/duck_test/platforms/linux/base.rb +15 -0
  28. data/lib/duck_test/platforms/linux/listener.rb +76 -0
  29. data/lib/duck_test/platforms/listener.rb +303 -0
  30. data/lib/duck_test/platforms/mac/base.rb +15 -0
  31. data/lib/duck_test/platforms/mac/listener.rb +79 -0
  32. data/lib/duck_test/platforms/mac/listener.rb.orig +147 -0
  33. data/lib/duck_test/platforms/os_helper.rb +102 -0
  34. data/lib/duck_test/platforms/watch_event.rb +47 -0
  35. data/lib/duck_test/platforms/windows/base.rb +15 -0
  36. data/lib/duck_test/platforms/windows/listener.rb +123 -0
  37. data/lib/duck_test/railtie.rb +29 -0
  38. data/lib/duck_test/usage.rb +34 -0
  39. data/lib/duck_test/usage.yml +112 -0
  40. data/lib/duck_test/version.rb +3 -0
  41. data/lib/duck_test.rb +6 -0
  42. data/lib/notes.txt +215 -0
  43. data/lib/tasks/duck_tests.rake +35 -0
  44. data/lib/tasks/gem_tasks.rake +18 -0
  45. metadata +92 -0
@@ -0,0 +1,147 @@
1
+ require 'digest/sha1'
2
+
3
+ module DuckTest
4
+ module Platforms
5
+ module Mac
6
+ class Listener
7
+ include DuckTest::LoggerHelper
8
+ include DuckTest::Platforms::Listener
9
+
10
+ attr_accessor :thread
11
+ attr_accessor :mechanism
12
+
13
+ ##################################################################################
14
+ def initialize
15
+ super()
16
+ @mechanism = FSEvent.new
17
+ ducklog.console "Platform listener: Mac"
18
+ end
19
+
20
+ ##################################################################################
21
+ def self.available?
22
+ return defined?(FSEvent)
23
+ end
24
+
25
+ ##################################################################################
26
+ def file_list
27
+ @file_list ||= {}
28
+ return @file_list
29
+ end
30
+
31
+ ##################################################################################
32
+ def watched?(file_spec)
33
+ return self.file_list[file_spec] ? true : false
34
+ end
35
+
36
+ ##################################################################################
37
+ def changed?(file_spec)
38
+ value = false
39
+ file_object = self.file_list[file_spec]
40
+ if file_object && !file_object[:is_dir]
41
+ value = File.mtime(file_spec).to_f > file_object[:mtime] || !Digest::SHA1.file(file_spec).to_s.eql?(file_object[:sha])
42
+ end
43
+ return value
44
+ end
45
+
46
+ ##################################################################################
47
+ def watch_file_spec(file_spec)
48
+ buffer = {}
49
+ buffer[:is_dir] = File.directory?(file_spec)
50
+ buffer[:mtime] = File.mtime(file_spec).to_f
51
+ buffer[:sha] = Digest::SHA1.file(file_spec).to_s unless buffer[:is_dir]
52
+ self.file_list[file_spec] = buffer
53
+ end
54
+
55
+ ##################################################################################
56
+ def start
57
+
58
+ self.file_list.each do |file_object|
59
+
60
+ if file_object.last[:is_dir]
61
+
62
+ @mechanism.watch file_object.first do |dir|
63
+ if dir.kind_of?(Array) && dir.length > 0
64
+ dir_spec = dir.first.to_s
65
+ # couldn't make this work using File::SEPARATOR
66
+ # look at it again later
67
+ if dir_spec =~ /\/$/
68
+ dir_spec = dir_spec.slice(0, dir_spec.length - 1)
69
+ end
70
+ if self.watched?(dir_spec)
71
+ changed_files = []
72
+ list = Dir.glob "#{dir_spec}/*"
73
+ list.each do |item|
74
+ if self.watched?(item)
75
+ if self.changed?(item)
76
+ self.watch_file_spec(item)
77
+ changed_files.push(item)
78
+ end
79
+ else
80
+ self.watch_file_spec(item)
81
+ changed_files.push(item)
82
+ end
83
+ end
84
+ changed_files.each do |item|
85
+ self.call_listener_event(WatchEvent.new(self, item, :update, nil))
86
+ end
87
+ end
88
+ end
89
+ end
90
+
91
+ end
92
+
93
+ end
94
+
95
+ @thread = Thread.new do
96
+ until self.stop do
97
+ ducklog.console "starting thread"
98
+ # @mechanism.process
99
+ @mechanism.run
100
+ ducklog.console "sleeping..."
101
+ sleep(1)
102
+ end
103
+ ducklog.console "out of the loop now: #{self.stop}"
104
+ end
105
+ ducklog.console "out of the thread..."
106
+
107
+
108
+ # @thread = Thread.new do
109
+ # until self.stop do
110
+ # ducklog.console "starting thread"
111
+ # @dude = "/alldata/rails/gems/duck_test/mac.com/test/unit"
112
+ # puts "going to watch #{@dude}"
113
+ # worker = FSEvent.new
114
+ # worker.watch @dude do |dir|
115
+ # puts "\r\ndude #{dir}"
116
+ # end
117
+ # worker.run
118
+ # ducklog.console "sleeping..."
119
+ # sleep(1)
120
+ # end
121
+ # ducklog.console "out of the loop now: #{self.stop}"
122
+ # end
123
+ # ducklog.console "out of the thread..."
124
+ end
125
+
126
+ ##################################################################################
127
+ def watch(file_spec)
128
+ watch_file_spec(file_spec)
129
+ end
130
+
131
+ end
132
+ end
133
+ end
134
+ end
135
+
136
+
137
+
138
+
139
+
140
+
141
+
142
+
143
+
144
+
145
+
146
+
147
+
@@ -0,0 +1,102 @@
1
+ module DuckTest
2
+ module Platforms
3
+
4
+ # Conveinence methods to include in classes that need to determine current platform.
5
+ # Method calls are relative to {OSHelper OSHelper}
6
+ module OSHelpers
7
+
8
+ ##################################################################################
9
+ # Conveinence method that calls {OSHelper.is_linux?}
10
+ def is_linux?
11
+ OSHelper.is_linux?
12
+ end
13
+
14
+ ##################################################################################
15
+ # Conveinence method that calls {OSHelper.is_mac?}
16
+ def is_mac?
17
+ OSHelper.is_mac?
18
+ end
19
+
20
+ ##################################################################################
21
+ # Conveinence method that calls {OSHelper.is_windows?}
22
+ def is_windows?
23
+ OSHelper.is_windows?
24
+ end
25
+
26
+ ##################################################################################
27
+ # Conveinence method that calls {OSHelper.available?}
28
+ def available?
29
+ OSHelper.available?
30
+ end
31
+
32
+ ##################################################################################
33
+ # Conveinence method that calls {OSHelper.current_os}
34
+ def current_os
35
+ OSHelper.current_os
36
+ end
37
+
38
+ end
39
+
40
+ # Methods used to determine the current operating system platform.
41
+ class OSHelper
42
+
43
+ ##################################################################################
44
+ # Determines if the current operating system is: Linux
45
+ # @return [Boolean] Returns true if the current operating system is: Linux
46
+ def self.is_linux?
47
+ RUBY_PLATFORM =~ /linux/i
48
+ end
49
+
50
+ ##################################################################################
51
+ # Determines if the current operating system is: Macintosh
52
+ # @return [Boolean] Returns true if the current operating system is: Macintosh
53
+ def self.is_mac?
54
+ RUBY_PLATFORM =~ /darwin/i
55
+ end
56
+
57
+ ##################################################################################
58
+ # Determines if the current operating system is: Windoze
59
+ # @return [Boolean] Returns true if the current operating system is: Windoze
60
+ def self.is_windows?
61
+ RUBY_PLATFORM =~ /mswin|mingw/i
62
+ end
63
+
64
+ ##################################################################################
65
+ # Determines if a native listener is available for the current platform.
66
+ # @return [Boolean] Returns true if the listener is available.
67
+ def self.available?
68
+ if self.is_linux?
69
+ return Platforms::Linux::Listener.available?
70
+
71
+ elsif self.is_mac?
72
+ return Platforms::Mac::Listener.available?
73
+
74
+ elsif self.is_windows?
75
+ return Platforms::Windows::Listener.available?
76
+
77
+ end
78
+
79
+ return false
80
+ end
81
+
82
+ ##################################################################################
83
+ # Returns a Symbol indicating the current operating system.
84
+ #
85
+ # Currently returns one of four possible values:
86
+ # :linux
87
+ # :mac
88
+ # :windows
89
+ # :unknown
90
+ #
91
+ # @return [Symbol]
92
+ def self.current_os
93
+ return :linux if self.is_linux?
94
+ return :mac if self.is_mac?
95
+ return :windows if self.is_windows?
96
+ return :unknown
97
+ end
98
+
99
+ end
100
+
101
+ end
102
+ end
@@ -0,0 +1,47 @@
1
+ module DuckTest
2
+ module Platforms
3
+
4
+ # A watch event represents some type of change to the file system. A directory / file is changed, created, or deleted.
5
+ class WatchEvent
6
+
7
+ # See {#initialize}
8
+ attr_accessor :source
9
+
10
+ # See {#initialize}
11
+ attr_accessor :file_spec
12
+
13
+ # See {#initialize}
14
+ attr_accessor :flag
15
+
16
+ # See {#initialize}
17
+ attr_accessor :cargo
18
+
19
+ # See {#initialize}
20
+ attr_accessor :event
21
+
22
+ ##################################################################################
23
+ # Initialize a new WatchEvent
24
+ # @param [Object] source A reference to the calling object that triggered the watch event.
25
+ # @param [String] file_spec A file name that adheres to {http://ruby-doc.org/core-1.9.3/File.html#method-c-basename File.basename}.
26
+ # The full file specification of the file or directory on which the event occured.
27
+ # @param [Symbol] flag The type of event
28
+ # Supported events
29
+ # - :create A new object under the watched object was created.
30
+ # - :destroy The object being watched was destroyed.
31
+ # - :moved The object being watched was moved into or out of the watched directory.
32
+ # - :update The object being watched was updated.
33
+ # @param [Object] event Event generated by a native file watching class.
34
+ # @return [WatchEvent]
35
+ def initialize(source, file_spec, flag, event = nil)
36
+ super()
37
+ self.source = source
38
+ self.file_spec = file_spec
39
+ self.flag = flag
40
+ self.event = event
41
+ return self
42
+ end
43
+
44
+ end
45
+
46
+ end
47
+ end
@@ -0,0 +1,15 @@
1
+ module DuckTest
2
+ # ...
3
+ module Platforms
4
+ # ...
5
+ module Windows
6
+
7
+ autoload :Listener, 'duck_test/platforms/windows/listener'
8
+
9
+ # ...
10
+ module Base
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,123 @@
1
+ # TODO needs to be refactored like the mac listener
2
+ require 'digest/sha1'
3
+
4
+ module DuckTest
5
+ module Platforms
6
+ module Windows
7
+
8
+ ##################################################################################
9
+ # Listener that wraps the native file system notifier for Windows.
10
+ class Listener
11
+ include DuckTest::LoggerHelper
12
+ include DuckTest::Platforms::Listener
13
+
14
+ attr_accessor :thread
15
+ attr_accessor :mechanism
16
+
17
+ ##################################################################################
18
+ def initialize
19
+ super()
20
+ self.mechanism = FChange::Notifier.new
21
+ ducklog.console "Platform listener: Windows"
22
+ end
23
+
24
+ ##################################################################################
25
+ def self.available?
26
+ return defined?(FChange::Notifier)
27
+ end
28
+
29
+ ##################################################################################
30
+ def file_list
31
+ @file_list ||= {}
32
+ return @file_list
33
+ end
34
+
35
+ ##################################################################################
36
+ def watched?(file_spec)
37
+ return self.file_list[file_spec] ? true : false
38
+ end
39
+
40
+ ##################################################################################
41
+ def changed?(file_spec)
42
+ value = false
43
+ file_object = self.file_list[file_spec]
44
+ if file_object && !file_object[:is_dir]
45
+ value = File.mtime(file_spec).to_f > file_object[:mtime] || !Digest::SHA1.file(file_spec).to_s.eql?(file_object[:sha])
46
+ end
47
+ return value
48
+ end
49
+
50
+ ##################################################################################
51
+ def watch_file_spec(file_spec)
52
+ buffer = {}
53
+ buffer[:is_dir] = File.directory?(file_spec)
54
+ buffer[:mtime] = File.mtime(file_spec).to_f
55
+ buffer[:sha] = Digest::SHA1.file(file_spec).to_s unless buffer[:is_dir]
56
+ self.file_list[file_spec] = buffer
57
+ end
58
+
59
+ ##################################################################################
60
+ def start
61
+
62
+ self.file_list.each do |file_object|
63
+
64
+ if file_object.last[:is_dir]
65
+
66
+ @mechanism.watch file_object.first, :all_events, :recursive do |dir|
67
+
68
+ dir_spec = dir.watcher.path
69
+ if self.watched?(dir_spec)
70
+ changed_files = []
71
+ list = Dir.glob "#{dir_spec}/*"
72
+ list.each do |item|
73
+ if self.watched?(item)
74
+ if self.changed?(item)
75
+ self.watch_file_spec(item)
76
+ changed_files.push(item)
77
+ end
78
+ else
79
+ self.watch_file_spec(item)
80
+ changed_files.push(item)
81
+ end
82
+ end
83
+ changed_files.each do |item|
84
+ self.call_listener_event(WatchEvent.new(self, item, :update, nil))
85
+ end
86
+ end
87
+ end
88
+
89
+ end
90
+
91
+ end
92
+
93
+ self.thread = Thread.new do
94
+ until self.stop do
95
+ @mechanism.run
96
+ sleep(self.speed)
97
+ end
98
+ end
99
+
100
+ end
101
+
102
+ ##################################################################################
103
+ def watch(file_spec)
104
+ watch_file_spec(file_spec)
105
+ end
106
+
107
+ end
108
+ end
109
+ end
110
+ end
111
+
112
+
113
+
114
+
115
+
116
+
117
+
118
+
119
+
120
+
121
+
122
+
123
+
@@ -0,0 +1,29 @@
1
+ # TODO figure out a good strategy for setting autoload_paths or getting the test/specs into the load path to run tests in the console.
2
+ require 'active_support'
3
+ require 'irb' unless defined?(IRB)
4
+ #require 'rspec'
5
+
6
+ module DuckTest
7
+ extend ActiveSupport::Autoload
8
+
9
+ # ...
10
+ class Railtie < Rails::Railtie
11
+
12
+ puts "DuckTest #{VERSION}"
13
+
14
+ config.before_configuration do |app|
15
+ app.config.autoload_paths += AutoloadConfig.new.paths
16
+ end
17
+
18
+ config.after_initialize do |app|
19
+ DuckTest::Config.reload!
20
+ end
21
+
22
+ #initializer 'duck_test' do
23
+ #end
24
+
25
+ IRB::ExtendCommandBundle.send :include, DuckTest::Console
26
+
27
+ end
28
+
29
+ end
@@ -0,0 +1,34 @@
1
+ module DuckTest
2
+
3
+ # Provides usage details for all of the console commands.
4
+ module Usage
5
+
6
+ ##################################################################################
7
+ # @note future version will pull usage info using i18n
8
+ # @param [Symbol] key The usage details to display.
9
+ # @param [Boolean] show Flag indicating if the details should be displayed.
10
+ # This value is often used by the calling code as part of an unless statement.
11
+ # @return [Boolean] Returns the value of show
12
+ def usage(key, show = false)
13
+
14
+ if show
15
+ content = YAML.load_file(File.expand_path(__FILE__).gsub(".rb", ".yml"))
16
+ case key
17
+ when :usage
18
+ puts "DuckTest #{VERSION}"
19
+ puts content[:usage]
20
+
21
+ else
22
+ if content[key]
23
+ puts content[key]
24
+ else
25
+ puts "help not found for command: #{key}"
26
+ end
27
+ end
28
+ end
29
+
30
+ return show
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,112 @@
1
+ ---
2
+ :usage: ! '
3
+
4
+ Commands:
5
+
6
+ The following commands do not require arguments.
7
+
8
+ duck.autorun - Toggles autorun on/off
9
+
10
+ duck.blacklist - Lists all of the files that have been blacklisted
11
+
12
+ duck.history - Lists all of the non-runnable and runnable files that have been loaded into memory during the current session
13
+
14
+ duck.info - Displays information about the current loaded testing framework
15
+
16
+ duck.maps - Lists mappings of non-runnable to runnable files
17
+
18
+ duck.runall - Loads all runnable test files from disk and executes the run_tests method
19
+
20
+ duck.whitelist - Lists all of the files that have been whitelisted
21
+
22
+
23
+ The following commands accept optional arguments. Type the command followed by :help Example: duck.run :help
24
+
25
+ duck.run
26
+
27
+
28
+ Type any command without arguments to display help
29
+
30
+ duck.ar
31
+
32
+ duck.latency
33
+
34
+ duck.listen_speed
35
+
36
+ duck.ll
37
+
38
+ duck.speed
39
+
40
+ '
41
+
42
+ :ar: ! '
43
+
44
+ Sets the ActiveRecord::Base logging level. Valid values are: :debug, :error, :fatal, :info, :unknown, :warn
45
+
46
+ Usage:
47
+
48
+ duck.ar_loglevel [value]
49
+
50
+ value - :debug, :error, :fatal, :info
51
+
52
+ '
53
+
54
+ :latency: ! '
55
+
56
+ Sets the queue latency. The queue latency is the amount of time that MUST PASS since the last queue event. A queue event would be adding a file to the queue.
57
+
58
+ Usage:
59
+
60
+ duck.latency [value]
61
+
62
+ value - any number including decimal point: 0.5, 0.75, 1, 1.5
63
+
64
+ '
65
+
66
+ :listen_speed: ! '
67
+
68
+ Sets the listener speed. The listener speed is the amount of time the listener loop will sleep inbetween polling for changes.
69
+
70
+ Usage:
71
+
72
+ duck.listen_speed [value]
73
+
74
+ value - any number including decimal point: 0.5, 0.75, 1, 1.5
75
+
76
+ '
77
+
78
+ :ll: ! '
79
+
80
+ Sets the logging level. Valid values are: :debug, :error, :fatal, :info, :unknown, :warn
81
+
82
+ Usage:
83
+
84
+ duck.loglevel [value]
85
+
86
+ value - :debug, :error, :fatal, :info
87
+
88
+ '
89
+
90
+ :run: ! '
91
+
92
+ Manually runs test file(s).
93
+
94
+ Usage:
95
+
96
+ duck.run [value]
97
+
98
+ value - a single file name or multiple file names separated by commas or spaces.
99
+
100
+ '
101
+
102
+ :speed: ! '
103
+
104
+ Sets the queue speed. The queue speed is the amount of time the queue loop will sleep inbetween polling for files being on the queue.
105
+
106
+ Usage:
107
+
108
+ duck.speed [value]
109
+
110
+ value - any number including decimal point: 0.5, 0.75, 1, 1.5
111
+
112
+ '
@@ -0,0 +1,3 @@
1
+ module DuckTest
2
+ VERSION = "0.1.4"
3
+ end
data/lib/duck_test.rb ADDED
@@ -0,0 +1,6 @@
1
+ # loads all of the source code files used by the gem.
2
+ module DuckTest
3
+ require "duck_test/base"
4
+ require "duck_test/platforms/dependencies"
5
+ require "duck_test/railtie" if defined?(Rails)
6
+ end