uh-wm 0.0.2.pre → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +15 -0
  5. data/Gemfile +5 -0
  6. data/Guardfile +12 -0
  7. data/LICENSE +30 -0
  8. data/README.md +68 -0
  9. data/Rakefile +40 -0
  10. data/bin/uhwm +5 -0
  11. data/config/cucumber.yaml +1 -0
  12. data/features/actions/execute.feature +9 -0
  13. data/features/actions/layout_delegation.feature +31 -0
  14. data/features/actions/quit.feature +9 -0
  15. data/features/cli/debug.feature +5 -0
  16. data/features/cli/layout.feature +15 -0
  17. data/features/cli/require.feature +5 -0
  18. data/features/cli/run_control.feature +9 -0
  19. data/features/cli/usage.feature +11 -0
  20. data/features/cli/verbose.feature +5 -0
  21. data/features/cli/version.feature +6 -0
  22. data/features/cli/worker.feature +9 -0
  23. data/features/layout/manage.feature +12 -0
  24. data/features/layout/protocol.feature +24 -0
  25. data/features/layout/unmanage.feature +10 -0
  26. data/features/manager/check_other_wm.feature +8 -0
  27. data/features/manager/input_events.feature +8 -0
  28. data/features/manager/manage.feature +14 -0
  29. data/features/manager/unmanage.feature +13 -0
  30. data/features/manager/x_errors.feature +17 -0
  31. data/features/run_control/evaluation.feature +18 -0
  32. data/features/run_control/key.feature +33 -0
  33. data/features/run_control/modifier.feature +10 -0
  34. data/features/run_control/worker.feature +9 -0
  35. data/features/session/connection.feature +5 -0
  36. data/features/session/termination.feature +13 -0
  37. data/features/steps/filesystem_steps.rb +3 -0
  38. data/features/steps/output_steps.rb +44 -0
  39. data/features/steps/run_control_steps.rb +3 -0
  40. data/features/steps/run_steps.rb +41 -0
  41. data/features/steps/x_steps.rb +53 -0
  42. data/features/support/env.rb +33 -0
  43. data/lib/uh/wm.rb +8 -0
  44. data/lib/uh/wm/actions_handler.rb +46 -0
  45. data/lib/uh/wm/cli.rb +20 -13
  46. data/lib/uh/wm/client.rb +64 -0
  47. data/lib/uh/wm/dispatcher.rb +3 -1
  48. data/lib/uh/wm/env.rb +15 -9
  49. data/lib/uh/wm/env_logging.rb +8 -0
  50. data/lib/uh/wm/logger_formatter.rb +16 -0
  51. data/lib/uh/wm/manager.rb +96 -14
  52. data/lib/uh/wm/run_control.rb +8 -3
  53. data/lib/uh/wm/runner.rb +82 -14
  54. data/lib/uh/wm/testing/acceptance_helpers.rb +140 -18
  55. data/lib/uh/wm/version.rb +1 -1
  56. data/lib/uh/wm/workers.rb +21 -0
  57. data/lib/uh/wm/workers/base.rb +27 -0
  58. data/lib/uh/wm/workers/blocking.rb +11 -0
  59. data/lib/uh/wm/workers/mux.rb +18 -0
  60. data/spec/spec_helper.rb +26 -0
  61. data/spec/support/exit_helpers.rb +6 -0
  62. data/spec/support/filesystem_helpers.rb +11 -0
  63. data/spec/uh/wm/actions_handler_spec.rb +30 -0
  64. data/spec/uh/wm/cli_spec.rb +214 -0
  65. data/spec/uh/wm/client_spec.rb +133 -0
  66. data/spec/uh/wm/dispatcher_spec.rb +76 -0
  67. data/spec/uh/wm/env_spec.rb +145 -0
  68. data/spec/uh/wm/manager_spec.rb +355 -0
  69. data/spec/uh/wm/run_control_spec.rb +102 -0
  70. data/spec/uh/wm/runner_spec.rb +186 -0
  71. data/uh-wm.gemspec +25 -0
  72. metadata +112 -9
@@ -0,0 +1,17 @@
1
+ Feature: X errors logging
2
+
3
+ Scenario: logs error details
4
+ Given a file named layout.rb with:
5
+ """
6
+ class Layout
7
+ def register _; end
8
+
9
+ # Focusing a client before mapping will force an error
10
+ def << client
11
+ client.focus
12
+ end
13
+ end
14
+ """
15
+ And uhwm is running with options -v -r./layout -l Layout
16
+ When a window requests to be mapped
17
+ Then the output must match /x.*error.+x_setinputfocus.+/i
@@ -0,0 +1,18 @@
1
+ Feature: run control file evaluation
2
+
3
+ Scenario: evaluates the default run control file when present
4
+ Given a run control file with:
5
+ """
6
+ puts 'run control evaluation'
7
+ """
8
+ When I start uhwm
9
+ Then the output must contain "run control evaluation"
10
+
11
+ Scenario: reports run control code in backtrace on errors
12
+ Given a run control file with:
13
+ """
14
+ 'no error on first line'
15
+ fail 'fails on second line'
16
+ """
17
+ When I start uhwm
18
+ Then the output must match /\.uhwmrc\.rb:2:.+fails on second line/
@@ -0,0 +1,33 @@
1
+ Feature: `key' run control keyword
2
+
3
+ Scenario: defines code to run when given key is pressed
4
+ Given uhwm is running with this run control file:
5
+ """
6
+ key(:f) { puts 'trigger f key code' }
7
+ """
8
+ When I press the alt+f keys
9
+ Then the output must contain "trigger f key code"
10
+
11
+ Scenario: defines code to run when given keys are pressed
12
+ Given uhwm is running with this run control file:
13
+ """
14
+ key(:f, :shift) { puts 'trigger f key code' }
15
+ """
16
+ When I press the alt+shift+f keys
17
+ Then the output must contain "trigger f key code"
18
+
19
+ Scenario: translates common key names to their X equivalent
20
+ Given uhwm is running with this run control file:
21
+ """
22
+ key(:enter) { puts 'trigger return key code' }
23
+ """
24
+ When I press the alt+Return keys
25
+ Then the output must contain "trigger return key code"
26
+
27
+ Scenario: translates upcased key names to combination with shift key
28
+ Given uhwm is running with this run control file:
29
+ """
30
+ key(:F) { puts 'trigger shift+f key code' }
31
+ """
32
+ When I press the alt+shift+f keys
33
+ Then the output must contain "trigger shift+f key code"
@@ -0,0 +1,10 @@
1
+ Feature: `modifier' run control keyword
2
+
3
+ Scenario: configures the modifier key
4
+ Given a run control file with:
5
+ """
6
+ modifier :ctrl
7
+ """
8
+ And uhwm is running
9
+ When I press the ctrl+shift+q keys
10
+ Then uhwm must terminate successfully
@@ -0,0 +1,9 @@
1
+ Feature: `worker' run control keyword
2
+
3
+ Scenario: configures the modifier key
4
+ Given a run control file with:
5
+ """
6
+ worker :mux
7
+ """
8
+ And I start uhwm
9
+ Then the output must match /work.+event.+mux/i
@@ -0,0 +1,5 @@
1
+ Feature: connection to X server
2
+
3
+ Scenario: connects to X server
4
+ When I start uhwm
5
+ Then it must connect to X display
@@ -0,0 +1,13 @@
1
+ Feature: program termination
2
+
3
+ Background:
4
+ Given uhwm is running
5
+
6
+ Scenario: terminates on quit request
7
+ When I tell uhwm to quit
8
+ Then uhwm must terminate successfully
9
+
10
+ Scenario: logs about termination
11
+ When I tell uhwm to quit
12
+ Then uhwm must terminate successfully
13
+ And the output must match /terminat/i
@@ -0,0 +1,3 @@
1
+ Given /^a file named ([^ ]+) with:$/ do |path, content|
2
+ write_file path, content
3
+ end
@@ -0,0 +1,44 @@
1
+ Then /^the output must contain exactly the usage$/ do
2
+ assert_exact_output <<-eoh, all_output
3
+ Usage: uhwm [options]
4
+
5
+ options:
6
+ -v, --verbose enable verbose mode
7
+ -d, --debug enable debug mode
8
+ -f, --run-control PATH specify alternate run control file
9
+ -r, --require PATH require ruby feature
10
+ -l, --layout LAYOUT specify layout
11
+ -w, --worker WORKER specify worker
12
+
13
+ -h, --help print this message
14
+ -V, --version print version
15
+ eoh
16
+ end
17
+
18
+ Then /^the output must contain exactly the version$/ do
19
+ assert_exact_output "%s\n" % Uh::WM::VERSION, all_output
20
+ end
21
+
22
+ Then /^the output must match \/([^\/]+)\/([a-z]*)$/ do |pattern, options|
23
+ uhwm_wait_output Regexp.new(pattern, options)
24
+ end
25
+
26
+ Then /^the output must not match \/([^\/]+)\/([a-z]*)$/ do |pattern, options|
27
+ expect(all_output).not_to match Regexp.new(pattern, options)
28
+ end
29
+
30
+ Then /^the output must contain:$/ do |content|
31
+ uhwm_wait_output content.to_s
32
+ end
33
+
34
+ Then /^the output must contain "([^"]+)"$/ do |content|
35
+ uhwm_wait_output content.to_s
36
+ end
37
+
38
+ Then /^the output must contain current display$/ do
39
+ uhwm_wait_output ENV['DISPLAY']
40
+ end
41
+
42
+ Then /^the output must contain the window name$/ do
43
+ uhwm_wait_output x_window_name
44
+ end
@@ -0,0 +1,3 @@
1
+ Given /^a run control file with:$/ do |content|
2
+ write_file '.uhwmrc.rb', content
3
+ end
@@ -0,0 +1,41 @@
1
+ Given /^another window manager is running$/ do
2
+ expect(other_wm).to be_alive
3
+ end
4
+
5
+ Given /^uhwm is running$/ do
6
+ uhwm_run_wait_ready
7
+ end
8
+
9
+ Given /^uhwm is running with options? (-.+)$/ do |options|
10
+ uhwm_run_wait_ready options
11
+ end
12
+
13
+ Given /^uhwm is running with this run control file:$/ do |rc|
14
+ write_file '.uhwmrc.rb', rc
15
+ uhwm_run_wait_ready
16
+ end
17
+
18
+ When /^I start uhwm$/ do
19
+ uhwm_run
20
+ end
21
+
22
+ When /^I run uhwm with options? (-.+)$/ do |options|
23
+ uhwm_run options
24
+ end
25
+
26
+ When /^I tell uhwm to quit$/ do
27
+ x_key 'alt+shift+q'
28
+ end
29
+
30
+ When /^I quit uhwm$/ do
31
+ x_key 'alt+shift+q'
32
+ assert_exit_status 0
33
+ end
34
+
35
+ Then /^the exit status must be (\d+)$/ do |exit_status|
36
+ assert_exit_status exit_status.to_i
37
+ end
38
+
39
+ Then /^uhwm must terminate successfully$/ do
40
+ assert_exit_status 0
41
+ end
@@ -0,0 +1,53 @@
1
+ Given /^a (\w+) window is mapped$/ do |ident|
2
+ x_window_map ident: ident
3
+ end
4
+
5
+ Given /^a window is managed$/ do
6
+ x_window_map
7
+ uhwm_wait_output /manag.+#{x_window_name}/i
8
+ end
9
+
10
+ When /^I press the ([^ ]+) keys?$/ do |keys|
11
+ x_key keys
12
+ end
13
+
14
+ When /^a window requests to be mapped$/ do
15
+ x_window_map
16
+ end
17
+
18
+ When /^the window requests to be unmapped$/ do
19
+ x_window_unmap
20
+ end
21
+
22
+ When /^the (\w+) window requests to be unmapped$/ do |ident|
23
+ x_window_unmap ident: ident
24
+ end
25
+
26
+ When /^a window requests to be mapped (\d+) times$/ do |times|
27
+ x_window_map times: times.to_i
28
+ end
29
+
30
+ When /^the window is destroyed$/ do
31
+ x_window_destroy
32
+ end
33
+
34
+ Then /^it must connect to X display$/ do
35
+ uhwm_wait_output 'Connected to'
36
+ expect(x_socket_check uhwm_pid).to be true
37
+ end
38
+
39
+ Then /^the window must be mapped$/ do
40
+ expect(x_window_map_state).to eq 'IsViewable'
41
+ end
42
+
43
+ Then /^the (\w+) window must be mapped$/ do |ident|
44
+ expect(x_window_map_state ident: ident).to eq 'IsViewable'
45
+ end
46
+
47
+ Then /^the window must be focused$/ do
48
+ expect(x_focused_window_id).to eq x_window_id
49
+ end
50
+
51
+ Then /^the input event mask must include (.+)$/ do |mask|
52
+ expect(x_input_event_masks).to include mask
53
+ end
@@ -0,0 +1,33 @@
1
+ require 'aruba/cucumber'
2
+ require 'headless'
3
+
4
+ require 'uh/wm/testing/acceptance_helpers'
5
+
6
+ module Aruba
7
+ class SpawnProcess
8
+ def pid
9
+ @process.pid
10
+ end
11
+ end
12
+ end
13
+
14
+ World(Uh::WM::Testing::AcceptanceHelpers)
15
+
16
+ Headless.new.start
17
+
18
+ Before do
19
+ set_env 'HOME', File.expand_path(current_dir)
20
+ end
21
+
22
+ After do
23
+ uhwm_ensure_stop
24
+ x_clients_ensure_stop
25
+ end
26
+
27
+ Around '@other_wm_running' do |_, block|
28
+ with_other_wm { block.call }
29
+ end
30
+
31
+ if ENV.key? 'TRAVIS'
32
+ ENV['UHWMTEST_TIMEOUT'] = 8.to_s
33
+ end
data/lib/uh/wm.rb CHANGED
@@ -3,13 +3,21 @@ require 'logger'
3
3
  require 'optparse'
4
4
  require 'uh'
5
5
 
6
+ require 'uh/wm/env_logging'
7
+
6
8
  require 'uh/wm/actions_handler'
7
9
  require 'uh/wm/cli'
10
+ require 'uh/wm/client'
8
11
  require 'uh/wm/dispatcher'
9
12
  require 'uh/wm/env'
13
+ require 'uh/wm/logger_formatter'
10
14
  require 'uh/wm/manager'
11
15
  require 'uh/wm/run_control'
12
16
  require 'uh/wm/runner'
17
+ require 'uh/wm/workers'
18
+ require 'uh/wm/workers/base'
19
+ require 'uh/wm/workers/blocking'
20
+ require 'uh/wm/workers/mux'
13
21
 
14
22
  module Uh
15
23
  module WM
@@ -1,6 +1,11 @@
1
1
  module Uh
2
2
  module WM
3
3
  class ActionsHandler
4
+ include EnvLogging
5
+
6
+ extend Forwardable
7
+ def_delegator :@env, :layout
8
+
4
9
  def initialize env, events
5
10
  @env, @events = env, events
6
11
  end
@@ -10,8 +15,49 @@ module Uh
10
15
  end
11
16
 
12
17
  def quit
18
+ log 'Quit requested'
13
19
  @events.emit :quit
14
20
  end
21
+
22
+ def execute command
23
+ log "Execute: #{command}"
24
+ pid = fork do
25
+ fork do
26
+ Process.setsid
27
+ begin
28
+ exec command
29
+ rescue Errno::ENOENT => e
30
+ log_error "ExecuteError: #{e}"
31
+ end
32
+ end
33
+ end
34
+ Process.waitpid pid
35
+ end
36
+
37
+ def method_missing(m, *args, &block)
38
+ if respond_to? m
39
+ meth = layout_method m
40
+ log "#{layout.class.name}##{meth} #{args.inspect}"
41
+ begin
42
+ layout.send(meth, *args)
43
+ rescue NoMethodError
44
+ log_error "Layout does not implement `#{meth}'"
45
+ end
46
+ else
47
+ super
48
+ end
49
+ end
50
+
51
+ def respond_to_missing?(m, *)
52
+ m.to_s =~ /\Alayout_/ || super
53
+ end
54
+
55
+
56
+ private
57
+
58
+ def layout_method(m)
59
+ m.to_s.gsub(/\Alayout_/, 'handle_').to_sym
60
+ end
15
61
  end
16
62
  end
17
63
  end
data/lib/uh/wm/cli.rb CHANGED
@@ -3,6 +3,8 @@ module Uh
3
3
  class CLI
4
4
  ArgumentError = Class.new(ArgumentError)
5
5
 
6
+ include EnvLogging
7
+
6
8
  USAGE = "Usage: #{File.basename $0} [options]".freeze
7
9
 
8
10
  EX_USAGE = 64
@@ -49,33 +51,38 @@ module Uh
49
51
  opts.separator ''
50
52
  opts.separator 'options:'
51
53
 
52
- opts.on '-h', '--help', 'print this message' do
53
- @env.print opts
54
- exit
55
- end
56
-
57
- opts.on '-v', '--version', 'enable verbose mode' do
54
+ opts.on '-v', '--verbose', 'enable verbose mode' do
58
55
  @env.verbose = true
59
56
  @env.log_logger_level
60
57
  end
61
-
62
58
  opts.on '-d', '--debug', 'enable debug mode' do
63
59
  @env.debug = true
64
60
  @env.log_logger_level
65
61
  end
66
-
67
62
  opts.on '-f', '--run-control PATH',
68
- 'specify alternate run control file' do |e|
63
+ 'specify alternate run control file' do |e|
69
64
  @env.rc_path = e
70
65
  end
71
-
72
66
  opts.on '-r', '--require PATH', 'require ruby feature' do |feature|
73
67
  require feature
74
- @env.log "Loaded `#{feature}' ruby feature"
68
+ log "Loaded `#{feature}' ruby feature"
75
69
  end
76
-
77
70
  opts.on '-l', '--layout LAYOUT', 'specify layout' do |layout|
78
- @env.layout_class = self.class.const_get layout.to_sym
71
+ @env.layout_class = Object.const_get layout.to_sym
72
+ end
73
+ opts.on '-w', Workers.types, '--worker WORKER',
74
+ 'specify worker' do |worker|
75
+ @env.worker = worker.to_sym
76
+ end
77
+
78
+ opts.separator ''
79
+ opts.on_tail '-h', '--help', 'print this message' do
80
+ @env.print opts
81
+ exit
82
+ end
83
+ opts.on_tail '-V', '--version', 'print version' do
84
+ @env.puts VERSION
85
+ exit
79
86
  end
80
87
  end
81
88
  end