rmonitor 1.0.1 → 2.0.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 (72) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +1 -1
  3. data/README.md +49 -40
  4. data/bin/rmonitor +38 -100
  5. data/lib/rmonitor.rb +17 -20
  6. data/lib/rmonitor/actions.rb +30 -0
  7. data/lib/rmonitor/actions/builder.rb +15 -0
  8. data/lib/rmonitor/actions/dsl.rb +23 -0
  9. data/lib/rmonitor/cache.rb +12 -0
  10. data/lib/rmonitor/capabilities.rb +38 -0
  11. data/lib/rmonitor/capabilities/builder.rb +15 -0
  12. data/lib/rmonitor/capabilities/dsl.rb +15 -0
  13. data/lib/rmonitor/commands/cl/base.rb +13 -0
  14. data/lib/rmonitor/commands/cl/invoke.rb +22 -0
  15. data/lib/rmonitor/commands/cl/list.rb +43 -0
  16. data/lib/rmonitor/commands/cl/update.rb +20 -0
  17. data/lib/rmonitor/commands/invoke.rb +23 -0
  18. data/lib/rmonitor/commands/list.rb +13 -0
  19. data/lib/rmonitor/commands/update.rb +18 -0
  20. data/lib/rmonitor/config.rb +27 -0
  21. data/lib/rmonitor/config/builder.rb +21 -0
  22. data/lib/rmonitor/config/dsl.rb +25 -0
  23. data/lib/rmonitor/invoker.rb +9 -0
  24. data/lib/rmonitor/matcher.rb +32 -0
  25. data/lib/rmonitor/profile/builder.rb +15 -0
  26. data/lib/rmonitor/profile/dsl.rb +15 -0
  27. data/lib/rmonitor/selector.rb +14 -0
  28. data/lib/rmonitor/strategies/base.rb +10 -0
  29. data/lib/rmonitor/strategies/optimistic.rb +15 -0
  30. data/lib/rmonitor/strategies/pessimistic.rb +17 -0
  31. data/lib/rmonitor/transformer.rb +38 -0
  32. data/lib/rmonitor/version.rb +1 -1
  33. data/lib/rmonitor/xrandr.rb +16 -0
  34. data/test/actions/builder_test.rb +27 -0
  35. data/test/actions_test.rb +60 -0
  36. data/test/cache_test.rb +30 -0
  37. data/test/capabilities/builder_test.rb +23 -0
  38. data/test/capabilities_test.rb +114 -0
  39. data/test/commands/cl/invoke_test.rb +38 -0
  40. data/test/commands/cl/list_test.rb +36 -0
  41. data/test/commands/cl/update_test.rb +24 -0
  42. data/test/commands/invoke_test.rb +86 -0
  43. data/test/commands/list_test.rb +50 -0
  44. data/test/commands/update_test.rb +67 -0
  45. data/test/config/builder_test.rb +51 -0
  46. data/test/config_test.rb +68 -0
  47. data/test/matcher_test.rb +90 -0
  48. data/test/profile/builder_test.rb +26 -0
  49. data/test/selector_test.rb +30 -0
  50. data/test/strategies/optimistic_test.rb +24 -0
  51. data/test/strategies/pessimistic_test.rb +26 -0
  52. data/test/test_helper.rb +19 -0
  53. data/test/transformer_test.rb +159 -0
  54. data/test/xrandr_test.rb +76 -0
  55. metadata +178 -28
  56. data/.rspec +0 -1
  57. data/Gemfile +0 -3
  58. data/Gemfile.lock +0 -24
  59. data/lib/rmonitor/devices.rb +0 -29
  60. data/lib/rmonitor/helpers/dsl_helpers.rb +0 -38
  61. data/lib/rmonitor/helpers/profile_helpers.rb +0 -48
  62. data/lib/rmonitor/helpers/xrandr_read_helpers.rb +0 -75
  63. data/lib/rmonitor/helpers/xrandr_write_helpers.rb +0 -55
  64. data/lib/rmonitor/profiles.rb +0 -51
  65. data/rmonitor.gemspec +0 -44
  66. data/spec/lib/helpers/dsl_helper_spec.rb +0 -29
  67. data/spec/lib/helpers/profile_helpers_spec.rb +0 -138
  68. data/spec/lib/helpers/xrandr_read_helpers_spec.rb +0 -259
  69. data/spec/lib/helpers/xrandr_write_helpers_spec.rb +0 -158
  70. data/spec/support/device_helper.rb +0 -3
  71. data/spec/support/profile_helper.rb +0 -3
  72. data/spec/support/string_helpers.rb +0 -25
@@ -1,3 +1,3 @@
1
1
  class RMonitor
2
- VERSION = '1.0.1'
2
+ VERSION = "2.0.0"
3
3
  end
@@ -0,0 +1,16 @@
1
+ class RMonitor
2
+ class XRandR
3
+ def initialize(options = {})
4
+ @invoker = options[:invoker] || Invoker.new(options)
5
+ @out = options[:out] || $stdout
6
+ @verbose = options[:verbose]
7
+ @dry_run = options[:dry_run]
8
+ end
9
+
10
+ def invoke(*args)
11
+ command = ("xrandr " + args.join(" ")).strip
12
+ @out.puts command if @verbose
13
+ @invoker.invoke(command) if args.empty? || !@dry_run
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,27 @@
1
+ require "test_helper"
2
+
3
+ describe RMonitor::Actions::Builder do
4
+
5
+ describe "::define" do
6
+
7
+ it "should return an array consisting of actions" do
8
+ actual = RMonitor::Actions::Builder.define do
9
+ off "LVDS1"
10
+ dpi 96
11
+ on "HDMI1", :mode => "1920x1080", :rate => "60.0"
12
+ on "HDMI2", :mode => "1920x1080", :rate => "60.0"
13
+ end
14
+
15
+ expected = [
16
+ {:name => "LVDS1", :action => :off},
17
+ {:name => :dpi, :value => 96, :action => :option},
18
+ {:name => "HDMI1", :action => :on, :mode => "1920x1080", :rate => "60.0"},
19
+ {:name => "HDMI2", :action => :on, :mode => "1920x1080", :rate => "60.0"}
20
+ ]
21
+
22
+ assert_equal expected, actual
23
+ end
24
+
25
+ end
26
+
27
+ end
@@ -0,0 +1,60 @@
1
+ require "test_helper"
2
+
3
+ describe RMonitor::Actions do
4
+
5
+ describe "#create" do
6
+
7
+ it "should create on actions for used monitors" do
8
+ capabilities = RMonitor::Capabilities::Builder.define do
9
+ device "HDMI1", :mode => "1920x1080", :rate => "60.0"
10
+ device "HDMI2", :mode => "1920x1080", :rate => "60.0"
11
+ end
12
+
13
+ profile = RMonitor::Profile::Builder.define "docked" do
14
+ device "HDMI1", :mode => "1920x1080", :rate => "60.0"
15
+ end
16
+
17
+ on_actions = RMonitor::Actions::Builder.define do
18
+ on "HDMI1", :mode => "1920x1080", :rate => "60.0"
19
+ end
20
+
21
+ assert_subset_of RMonitor::Actions.new(:capabilities => capabilities).create(profile), on_actions
22
+ end
23
+
24
+ it "should create off actions for unused monitors" do
25
+ capabilities = RMonitor::Capabilities::Builder.define do
26
+ device "HDMI1", :mode => "1920x1080", :rate => "60.0"
27
+ device "HDMI2", :mode => "1920x1080", :rate => "60.0"
28
+ end
29
+
30
+ profile = RMonitor::Profile::Builder.define "docked" do
31
+ device "HDMI1", :mode => "1920x1080", :rate => "60.0"
32
+ end
33
+
34
+ off_actions = RMonitor::Actions::Builder.define do
35
+ off "HDMI2"
36
+ end
37
+
38
+ assert_subset_of RMonitor::Actions.new(:capabilities => capabilities).create(profile), off_actions
39
+ end
40
+
41
+ it "should create option actions for profile options (eg. dpi)" do
42
+ capabilities = RMonitor::Capabilities::Builder.define do
43
+ device "HDMI1", :mode => "1920x1080", :rate => "60.0"
44
+ device "HDMI2", :mode => "1920x1080", :rate => "60.0"
45
+ end
46
+
47
+ profile = RMonitor::Profile::Builder.define "docked", :dpi => 96 do
48
+ device "HDMI1", :mode => "1920x1080", :rate => "60.0"
49
+ end
50
+
51
+ option_actions = RMonitor::Actions::Builder.define do
52
+ dpi 96
53
+ end
54
+
55
+ assert_subset_of RMonitor::Actions.new(:capabilities => capabilities).create(profile), option_actions
56
+ end
57
+
58
+ end
59
+
60
+ end
@@ -0,0 +1,30 @@
1
+ require "test_helper"
2
+
3
+ describe RMonitor::Cache do
4
+
5
+ describe "#invoke" do
6
+
7
+ it "should call Invoker#invoke the first time" do
8
+ invoker = MiniTest::Mock.new
9
+ invoker.expect :invoke, "foo", ["bar"]
10
+
11
+ assert_equal "foo", RMonitor::Cache.new(:invoker => invoker).invoke("bar")
12
+
13
+ invoker.verify
14
+ end
15
+
16
+ it "should return the cached reuslt the second time" do
17
+ invoker = MiniTest::Mock.new
18
+ invoker.expect :invoke, "foo", ["bar"]
19
+
20
+ cache = RMonitor::Cache.new(:invoker => invoker)
21
+
22
+ assert_equal "foo", cache.invoke("bar")
23
+ assert_equal "foo", cache.invoke("bar")
24
+
25
+ invoker.verify
26
+ end
27
+
28
+ end
29
+
30
+ end
@@ -0,0 +1,23 @@
1
+ require "test_helper"
2
+
3
+ describe RMonitor::Capabilities::Builder do
4
+
5
+ describe "::define" do
6
+
7
+ it "should return an array consisting of device name and options" do
8
+ actual = RMonitor::Capabilities::Builder.define do
9
+ device "HDMI1", :mode => "1920x1080", :rate => "60.0"
10
+ device "HDMI2", :mode => "1920x1080", :rate => "60.0"
11
+ end
12
+
13
+ expected = [
14
+ {:name => "HDMI1", :mode => "1920x1080", :rate => "60.0"},
15
+ {:name => "HDMI2", :mode => "1920x1080", :rate => "60.0"}
16
+ ]
17
+
18
+ assert_equal expected, actual
19
+ end
20
+
21
+ end
22
+
23
+ end
@@ -0,0 +1,114 @@
1
+ require "test_helper"
2
+
3
+ describe RMonitor::Capabilities do
4
+
5
+ describe "#parse" do
6
+
7
+ it "should correctly parse the most trivial case" do
8
+ actual = RMonitor::Capabilities.new.parse <<-OUTPUT
9
+ Screen 0: minimum 8 x 8, current 1920 x 1080, maximum 1920 x 1080
10
+ HDMI1 connected (normal left inverted right x axis y axis)
11
+ 1920x1080 60.0
12
+ OUTPUT
13
+
14
+ expected = RMonitor::Capabilities::Builder.define do
15
+ device "HDMI1", :mode => "1920x1080", :rate => "60.0"
16
+ end
17
+
18
+ assert_equal expected, actual
19
+ end
20
+
21
+ it "should correctly parse secondary rates for a mode" do
22
+ actual = RMonitor::Capabilities.new.parse <<-OUTPUT
23
+ Screen 0: minimum 8 x 8, current 1920 x 1080, maximum 1920 x 1080
24
+ HDMI1 connected (normal left inverted right x axis y axis)
25
+ 1920x1080 60.0 30.0
26
+ OUTPUT
27
+
28
+ expected = RMonitor::Capabilities::Builder.define do
29
+ device "HDMI1", :mode => "1920x1080", :rate => "60.0"
30
+ device "HDMI1", :mode => "1920x1080", :rate => "30.0"
31
+ end
32
+
33
+ assert_equal expected, actual
34
+ end
35
+
36
+ it "should correctly parse the current mode / rate" do
37
+ actual = RMonitor::Capabilities.new.parse <<-OUTPUT
38
+ Screen 0: minimum 8 x 8, current 1920 x 1080, maximum 1920 x 1080
39
+ HDMI1 connected (normal left inverted right x axis y axis)
40
+ 1920x1080 60.0 +
41
+ OUTPUT
42
+
43
+ expected = RMonitor::Capabilities::Builder.define do
44
+ device "HDMI1", :mode => "1920x1080", :rate => "60.0", :current => true
45
+ end
46
+
47
+ assert_equal expected, actual
48
+ end
49
+
50
+ it "should correctly parse the native mode / rate" do
51
+ actual = RMonitor::Capabilities.new.parse <<-OUTPUT
52
+ Screen 0: minimum 8 x 8, current 1920 x 1080, maximum 1920 x 1080
53
+ HDMI1 connected (normal left inverted right x axis y axis)
54
+ 1920x1080 60.0*
55
+ OUTPUT
56
+
57
+ expected = RMonitor::Capabilities::Builder.define do
58
+ device "HDMI1", :mode => "1920x1080", :rate => "60.0", :native => true
59
+ end
60
+
61
+ assert_equal expected, actual
62
+ end
63
+
64
+ it "should correctly parse multiple rates" do
65
+ actual = RMonitor::Capabilities.new.parse <<-OUTPUT
66
+ Screen 0: minimum 8 x 8, current 1920 x 1080, maximum 1920 x 1080
67
+ HDMI1 connected (normal left inverted right x axis y axis)
68
+ 1920x1080 60.0
69
+ 1400x1050 60.0
70
+ OUTPUT
71
+
72
+ expected = RMonitor::Capabilities::Builder.define do
73
+ device "HDMI1", :mode => "1920x1080", :rate => "60.0"
74
+ device "HDMI1", :mode => "1400x1050", :rate => "60.0"
75
+ end
76
+
77
+ assert_equal expected, actual
78
+ end
79
+
80
+ it "should correctly parse multiple devices" do
81
+ actual = RMonitor::Capabilities.new.parse <<-OUTPUT
82
+ Screen 0: minimum 8 x 8, current 1920 x 1080, maximum 1920 x 1080
83
+ HDMI1 connected (normal left inverted right x axis y axis)
84
+ 1920x1080 60.0
85
+ HDMI2 connected (normal left inverted right x axis y axis)
86
+ 1920x1080 60.0
87
+ OUTPUT
88
+
89
+ expected = RMonitor::Capabilities::Builder.define do
90
+ device "HDMI1", :mode => "1920x1080", :rate => "60.0"
91
+ device "HDMI2", :mode => "1920x1080", :rate => "60.0"
92
+ end
93
+
94
+ assert_equal expected, actual
95
+ end
96
+
97
+ it "should not parse disconnected devices" do
98
+ actual = RMonitor::Capabilities.new.parse <<-OUTPUT
99
+ Screen 0: minimum 8 x 8, current 1920 x 1080, maximum 1920 x 1080
100
+ HDMI1 connected (normal left inverted right x axis y axis)
101
+ 1920x1080 60.0
102
+ HDMI2 disconnected (normal left inverted right x axis y axis)
103
+ OUTPUT
104
+
105
+ expected = RMonitor::Capabilities::Builder.define do
106
+ device "HDMI1", :mode => "1920x1080", :rate => "60.0"
107
+ end
108
+
109
+ assert_equal expected, actual
110
+ end
111
+
112
+ end
113
+
114
+ end
@@ -0,0 +1,38 @@
1
+ require "test_helper"
2
+ require "stringio"
3
+
4
+ describe RMonitor::Commands::CL::Invoke do
5
+
6
+ describe "#execute" do
7
+
8
+ it "should write to :err when RMonitor::Commands::Invoke raises UnknownProfileError" do
9
+ err = StringIO.new
10
+
11
+ non_cl_invoke = Object.new
12
+
13
+ def non_cl_invoke.execute(*)
14
+ raise RMonitor::UnknownProfileError
15
+ end
16
+
17
+ RMonitor::Commands::CL::Invoke.new(:invoke => non_cl_invoke, :err => err).execute("foo")
18
+
19
+ assert_equal "unknown profile\n", err.string
20
+ end
21
+
22
+ it "should write to :err when RMonitor::Commands::Invoke raises UninvokableProfileError" do
23
+ err = StringIO.new
24
+
25
+ non_cl_invoke = Object.new
26
+
27
+ def non_cl_invoke.execute(*)
28
+ raise RMonitor::UninvokableProfileError
29
+ end
30
+
31
+ RMonitor::Commands::CL::Invoke.new(:invoke => non_cl_invoke, :err => err).execute("foo")
32
+
33
+ assert_equal "profile is not invokable\n", err.string
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,36 @@
1
+ require "test_helper"
2
+ require "stringio"
3
+
4
+ describe RMonitor::Commands::CL::List do
5
+
6
+ describe "#execute" do
7
+
8
+ it "should output profiles in a human readable manner" do
9
+ profiles = RMonitor::Config::Builder.define do
10
+ profile "docked" do
11
+ device "HDMI1", :mode => "1920x1080", :rate => "60.0"
12
+ device "HDMI2", :mode => "1920x1080", :rate => "60.0"
13
+ end
14
+
15
+ profile "default" do
16
+ device "eDP1", :mode => "1920x1080"
17
+ end
18
+ end
19
+
20
+ matcher = MiniTest::Mock.new
21
+ matcher.expect :invokable?, true, [profiles.first]
22
+ matcher.expect :invokable?, false, [profiles.last]
23
+
24
+ out = StringIO.new
25
+
26
+ RMonitor::Commands::CL::List.new(:profiles => profiles, :matcher => matcher, :out => out).execute
27
+
28
+ assert_equal <<-LIST, out.string
29
+ docked\tinvokable\tHDMI1 (1920x1080 60.0)\tHDMI2 (1920x1080 60.0)
30
+ default\tuninvokable\teDP1 (1920x1080)
31
+ LIST
32
+ end
33
+
34
+ end
35
+
36
+ end
@@ -0,0 +1,24 @@
1
+ require "test_helper"
2
+ require "stringio"
3
+
4
+ describe RMonitor::Commands::CL::Update do
5
+
6
+ describe "#execute" do
7
+
8
+ it "should write to :err when RMonitor::Commands::Update raises NoInvokableProfileError" do
9
+ err = StringIO.new
10
+
11
+ non_cl_update = Object.new
12
+
13
+ def non_cl_update.execute
14
+ raise RMonitor::NoInvokableProfileError
15
+ end
16
+
17
+ RMonitor::Commands::CL::Update.new(:update => non_cl_update, :err => err).execute
18
+
19
+ assert_equal "no invokable profile\n", err.string
20
+ end
21
+
22
+ end
23
+
24
+ end
@@ -0,0 +1,86 @@
1
+ require "test_helper"
2
+ require "fakefs/safe"
3
+
4
+ describe RMonitor::Commands::Invoke do
5
+
6
+ before :each do
7
+ FakeFS.activate!
8
+
9
+ RMonitor::Config.config_path = nil
10
+
11
+ FileUtils.mkdir_p File.dirname DEFAULT_CONFIG_PATH
12
+
13
+ File.write DEFAULT_CONFIG_PATH, <<-CONFIG
14
+ profile "docked" do
15
+ device "HDMI1", :mode => "1920x1080", :rate => "60.0"
16
+ device "HDMI2", :mode => "1920x1080", :rate => "60.0"
17
+ end
18
+
19
+ profile "default" do
20
+ device "eDP1", :mode => "1920x1080"
21
+ end
22
+ CONFIG
23
+ end
24
+
25
+ after :each do
26
+ FakeFS.deactivate!
27
+ end
28
+
29
+ describe "#execute" do
30
+
31
+ it "should throw an exception when given an unknown profile name" do
32
+ invoker = MiniTest::Mock.new
33
+
34
+ invoker.expect :invoke, <<-XRANDR, ["xrandr"]
35
+ Screen 0: minimum 8 x 8, current 1920 x 1080, maximum 1920 x 1080
36
+ HDMI1 connected (normal left inverted right x axis y axis)
37
+ 1920x1080 60.0
38
+ XRANDR
39
+
40
+ cache = RMonitor::Cache.new(:invoker => invoker)
41
+
42
+ assert_raises RMonitor::UnknownProfileError do
43
+ RMonitor::Commands::Invoke.new(:invoker => cache).execute("foo")
44
+ end
45
+ end
46
+
47
+ it "should throw an exception if a profile is not invokable" do
48
+ invoker = MiniTest::Mock.new
49
+
50
+ invoker.expect :invoke, <<-XRANDR, ["xrandr"]
51
+ Screen 0: minimum 8 x 8, current 1920 x 1080, maximum 1920 x 1080
52
+ HDMI1 connected (normal left inverted right x axis y axis)
53
+ 1920x1080 60.0
54
+ XRANDR
55
+
56
+ cache = RMonitor::Cache.new(:invoker => invoker)
57
+
58
+ assert_raises RMonitor::UninvokableProfileError do
59
+ RMonitor::Commands::Invoke.new(:invoker => cache).execute("docked")
60
+ end
61
+ end
62
+
63
+ it "should call xrandr on the system when given an existing profile name" do
64
+ invoker = MiniTest::Mock.new
65
+
66
+ invoker.expect :invoke, <<-XRANDR, ["xrandr"]
67
+ Screen 0: minimum 8 x 8, current 1920 x 1080, maximum 1920 x 1080
68
+ HDMI1 connected (normal left inverted right x axis y axis)
69
+ 1920x1080 60.0
70
+ HDMI2 connected (normal left inverted right x axis y axis)
71
+ 1920x1080 60.0
72
+ XRANDR
73
+
74
+ invoker.expect :invoke, nil, ["xrandr --output HDMI1 --mode 1920x1080 --rate 60.0"]
75
+ invoker.expect :invoke, nil, ["xrandr --output HDMI2 --mode 1920x1080 --rate 60.0"]
76
+
77
+ cache = RMonitor::Cache.new(:invoker => invoker)
78
+
79
+ RMonitor::Commands::Invoke.new(:invoker => cache).execute("docked")
80
+
81
+ invoker.verify
82
+ end
83
+
84
+ end
85
+
86
+ end