kamerling 0.0.2 → 0.0.3

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 (74) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -13
  3. data/Gemfile +0 -1
  4. data/Gemfile.lock +64 -64
  5. data/README.md +18 -1
  6. data/Rakefile +5 -3
  7. data/bin/kamerling +1 -1
  8. data/config/reek.yml +20 -3
  9. data/kamerling.gemspec +16 -13
  10. data/lib/kamerling.rb +2 -28
  11. data/lib/kamerling/addr.rb +17 -3
  12. data/lib/kamerling/client.rb +10 -11
  13. data/lib/kamerling/core_extensions/main.rb +14 -14
  14. data/lib/kamerling/dispatch.rb +13 -0
  15. data/lib/kamerling/handler.rb +16 -25
  16. data/lib/kamerling/http_api.rb +50 -34
  17. data/lib/kamerling/logging.rb +36 -16
  18. data/lib/kamerling/mapper.rb +33 -0
  19. data/lib/kamerling/message.rb +50 -37
  20. data/lib/kamerling/migrations/2_results_received_at.rb +7 -0
  21. data/lib/kamerling/migrations/3_dispatches.rb +17 -0
  22. data/lib/kamerling/migrations/4_registrations_registered_at.rb +7 -0
  23. data/lib/kamerling/migrations/5_clients_type.rb +7 -0
  24. data/lib/kamerling/net_dispatcher.rb +12 -7
  25. data/lib/kamerling/project.rb +7 -3
  26. data/lib/kamerling/receiver.rb +38 -10
  27. data/lib/kamerling/registrar.rb +45 -8
  28. data/lib/kamerling/registration.rb +9 -10
  29. data/lib/kamerling/repo.rb +33 -26
  30. data/lib/kamerling/repos.rb +52 -45
  31. data/lib/kamerling/result.rb +10 -11
  32. data/lib/kamerling/server/http.rb +28 -21
  33. data/lib/kamerling/server/sock.rb +32 -24
  34. data/lib/kamerling/server/tcp.rb +23 -15
  35. data/lib/kamerling/server/udp.rb +24 -16
  36. data/lib/kamerling/server_runner.rb +30 -41
  37. data/lib/kamerling/settings.rb +28 -0
  38. data/lib/kamerling/task.rb +7 -7
  39. data/lib/kamerling/task_dispatcher.rb +31 -22
  40. data/lib/kamerling/uuid.rb +13 -11
  41. data/lib/kamerling/uuid_entity.rb +23 -9
  42. data/lib/kamerling/value.rb +13 -0
  43. data/lib/kamerling/views/clients.slim +3 -1
  44. data/lib/kamerling/views/project.slim +8 -4
  45. data/lib/kamerling/views/projects.slim +7 -1
  46. data/spec/kamerling/addr_spec.rb +32 -22
  47. data/spec/kamerling/client_spec.rb +9 -5
  48. data/spec/kamerling/core_extensions/main_spec.rb +18 -13
  49. data/spec/kamerling/dispatch_spec.rb +16 -0
  50. data/spec/kamerling/handler_spec.rb +24 -34
  51. data/spec/kamerling/http_api_spec.rb +94 -73
  52. data/spec/kamerling/logging_spec.rb +93 -62
  53. data/spec/kamerling/mapper_spec.rb +151 -0
  54. data/spec/kamerling/message_spec.rb +73 -49
  55. data/spec/kamerling/net_dispatcher_spec.rb +22 -16
  56. data/spec/kamerling/receiver_spec.rb +29 -19
  57. data/spec/kamerling/registrar_spec.rb +43 -15
  58. data/spec/kamerling/registration_spec.rb +17 -0
  59. data/spec/kamerling/repo_spec.rb +63 -47
  60. data/spec/kamerling/repos_spec.rb +121 -109
  61. data/spec/kamerling/result_spec.rb +16 -0
  62. data/spec/kamerling/server/http_spec.rb +19 -14
  63. data/spec/kamerling/server/tcp_spec.rb +41 -35
  64. data/spec/kamerling/server/udp_spec.rb +40 -34
  65. data/spec/kamerling/server_runner_spec.rb +62 -53
  66. data/spec/kamerling/settings_spec.rb +36 -0
  67. data/spec/kamerling/task_dispatcher_spec.rb +38 -15
  68. data/spec/kamerling/task_spec.rb +9 -5
  69. data/spec/kamerling/uuid_entity_spec.rb +53 -25
  70. data/spec/kamerling/uuid_spec.rb +19 -16
  71. data/spec/kamerling/value_spec.rb +21 -0
  72. data/spec/spec_helper.rb +3 -6
  73. metadata +54 -8
  74. data/lib/kamerling/core_extensions.rb +0 -1
@@ -0,0 +1,151 @@
1
+ require_relative '../spec_helper'
2
+ require_relative '../../lib/kamerling/addr'
3
+ require_relative '../../lib/kamerling/client'
4
+ require_relative '../../lib/kamerling/dispatch'
5
+ require_relative '../../lib/kamerling/mapper'
6
+ require_relative '../../lib/kamerling/project'
7
+ require_relative '../../lib/kamerling/registration'
8
+ require_relative '../../lib/kamerling/result'
9
+ require_relative '../../lib/kamerling/task'
10
+
11
+ module Kamerling
12
+ describe Mapper do
13
+ let(:addr) { Addr['127.0.0.1', 1979, :TCP] }
14
+ let(:client) { Client.new(addr: addr, busy: true, type: :FPGA) }
15
+ let(:project) { Project.new(name: 'project') }
16
+ let(:task) { Task.new(data: 'data', done: true, project: project) }
17
+
18
+ describe '.from_h' do
19
+ let(:repos) do
20
+ {
21
+ Client => { client.uuid => client },
22
+ Project => { project.uuid => project },
23
+ Task => { task.uuid => task },
24
+ }
25
+ end
26
+
27
+ it 'builds the proper Client from the Hash representation' do
28
+ hash = {
29
+ busy: true,
30
+ host: '127.0.0.1',
31
+ port: 1979,
32
+ prot: 'TCP',
33
+ type: 'FPGA',
34
+ uuid: client.uuid,
35
+ }
36
+ Mapper.from_h(Client, hash).to_h.must_equal client.to_h
37
+ end
38
+
39
+ it 'builds the proper Dispatch from the Hash representation' do
40
+ dispatch = Dispatch.new(addr: addr, client: client, project: project,
41
+ task: task)
42
+ hash = {
43
+ client_uuid: client.uuid,
44
+ data: 'data',
45
+ dispatched_at: any(Time),
46
+ host: '127.0.0.1',
47
+ port: 1979,
48
+ project_uuid: project.uuid,
49
+ prot: 'TCP',
50
+ task_uuid: task.uuid,
51
+ uuid: dispatch.uuid,
52
+ }
53
+ mapped = Mapper.from_h(Dispatch, hash, repos: repos)
54
+ mapped.to_h.must_equal dispatch.to_h
55
+ end
56
+
57
+ it 'builds the proper Project from the Hash representation' do
58
+ hash = { name: 'project', uuid: project.uuid }
59
+ Mapper.from_h(Project, hash).to_h.must_equal project.to_h
60
+ end
61
+
62
+ it 'builds the proper Registration from the Hash representation' do
63
+ reg = Registration.new(addr: addr, client: client, project: project)
64
+ hash = {
65
+ client_uuid: client.uuid,
66
+ host: '127.0.0.1',
67
+ port: 1979,
68
+ project_uuid: project.uuid,
69
+ prot: 'TCP',
70
+ registered_at: any(Time),
71
+ uuid: reg.uuid,
72
+ }
73
+ Mapper.from_h(Registration, hash, repos: repos).to_h.must_equal reg.to_h
74
+ end
75
+
76
+ it 'builds the proper Result from the Hash representation' do
77
+ result = Result.new(addr: addr, client: client, data: 'data',
78
+ task: task)
79
+ hash = {
80
+ client_uuid: client.uuid,
81
+ data: 'data',
82
+ host: '127.0.0.1',
83
+ port: 1979,
84
+ prot: 'TCP',
85
+ received_at: any(Time),
86
+ task_uuid: task.uuid,
87
+ uuid: result.uuid,
88
+ }
89
+ Mapper.from_h(Result, hash, repos: repos).to_h.must_equal result.to_h
90
+ end
91
+
92
+ it 'builds the proper Task from the Hash representation' do
93
+ hash = {
94
+ data: 'data',
95
+ done: true,
96
+ project_uuid: project.uuid,
97
+ uuid: task.uuid,
98
+ }
99
+ Mapper.from_h(Task, hash, repos: repos).to_h.must_equal task.to_h
100
+ end
101
+ end
102
+
103
+ describe '.to_h' do
104
+ it 'returns the proper Hash representation of a Client' do
105
+ Mapper.to_h(client).must_equal busy: true, host: '127.0.0.1',
106
+ port: 1979, prot: 'TCP',
107
+ type: 'FPGA', uuid: client.uuid
108
+ end
109
+
110
+ it 'returns the proper Hash representation of a Dispatch' do
111
+ dispatched_at = Time.new(2014, 7, 6, 5, 4, 3)
112
+ dispatch = Dispatch.new(addr: addr, client: client,
113
+ dispatched_at: dispatched_at, project: project,
114
+ task: task)
115
+ Mapper.to_h(dispatch).must_equal client_uuid: client.uuid,
116
+ dispatched_at: dispatched_at,
117
+ host: '127.0.0.1',
118
+ port: 1979,
119
+ prot: 'TCP',
120
+ project_uuid: project.uuid,
121
+ task_uuid: task.uuid,
122
+ uuid: dispatch.uuid
123
+ end
124
+
125
+ it 'returns the proper Hash representation of a Registration' do
126
+ registered_at = Time.new(2014, 7, 6, 5, 4, 3)
127
+ reg = Registration.new(addr: addr, client: client, project: project,
128
+ registered_at: registered_at)
129
+ Mapper.to_h(reg).must_equal client_uuid: client.uuid, host: '127.0.0.1',
130
+ port: 1979, prot: 'TCP',
131
+ project_uuid: project.uuid,
132
+ registered_at: registered_at, uuid: reg.uuid
133
+ end
134
+
135
+ it 'returns the proper Hash representation of a Result' do
136
+ received_at = Time.new(2014, 7, 6, 5, 4, 3)
137
+ result = Result.new(addr: addr, client: client, data: 'res',
138
+ received_at: received_at, task: task)
139
+ Mapper.to_h(result).must_equal client_uuid: client.uuid, data: 'res',
140
+ host: '127.0.0.1', port: 1979,
141
+ prot: 'TCP', received_at: received_at,
142
+ task_uuid: task.uuid, uuid: result.uuid
143
+ end
144
+
145
+ it 'returns the proper Hash representation of a Tag' do
146
+ Mapper.to_h(task).must_equal data: 'data', done: true,
147
+ project_uuid: project.uuid, uuid: task.uuid
148
+ end
149
+ end
150
+ end
151
+ end
@@ -1,70 +1,94 @@
1
1
  require_relative '../spec_helper'
2
+ require_relative '../../lib/kamerling/client'
3
+ require_relative '../../lib/kamerling/message'
4
+ require_relative '../../lib/kamerling/project'
5
+ require_relative '../../lib/kamerling/task'
6
+ require_relative '../../lib/kamerling/uuid'
2
7
 
3
- module Kamerling describe Message do
4
- let(:mess) do
5
- Message.new "DATA\0\0\0\0\0\0\0\0\0\0\0\0" \
6
- '16B client UUID16B project UUID16B task UUIDsome payload'
7
- end
8
+ module Kamerling
9
+ describe Message do
10
+ let(:mess) do
11
+ Message.parse("DATA\0\0\0\0\0\0\0\0\0\0\0\0" \
12
+ '16B client UUID16B project UUID16B task UUIDsome payload')
13
+ end
8
14
 
9
- describe '.[]' do
10
- it 'constructs a new message' do
11
- client = fake :client, uuid: UUID.new
12
- project = fake :project, uuid: UUID.new
13
- task = fake :task, uuid: UUID.new
14
- message = Message[client: client, payload: 'pay', project: project,
15
- task: task, type: :DATA]
16
- message.client_uuid.must_equal client.uuid
17
- message.project_uuid.must_equal project.uuid
18
- message.task_uuid.must_equal task.uuid
19
- message.payload.must_equal 'pay'
20
- message.type.must_equal :DATA
15
+ describe '.build' do
16
+ it 'constructs a new message' do
17
+ client = Client.new
18
+ project = Project.new
19
+ task = Task.new
20
+ message = Message.build(client: client, payload: 'pay',
21
+ project: project, task: task, type: :DATA)
22
+ message.client_uuid.must_equal client.uuid
23
+ message.project_uuid.must_equal project.uuid
24
+ message.task_uuid.must_equal task.uuid
25
+ message.payload.must_equal 'pay'
26
+ message.type.must_equal :DATA
27
+ end
21
28
  end
22
- end
23
29
 
24
- describe '.new' do
25
- it 'raises on unknown message types' do
26
- -> { Message.new 'MESS age' }.must_raise Message::UnknownType
30
+ describe '.parse' do
31
+ it 'raises on unknown message types' do
32
+ -> { Message.parse('MESS age') }.must_raise Message::UnknownType
33
+ end
34
+
35
+ it 'doesn’t raise on empty messages' do
36
+ Message.parse('')
37
+ end
27
38
  end
28
39
 
29
- it 'doesn’t raise on empty messages' do
30
- Message.new ''
40
+ describe '#client_type' do
41
+ it 'returns the client’s type' do
42
+ mess.client_type.must_equal :"\0\0\0\0"
43
+ fpga_mess = Message.parse("RGSTFPGA\0\0\0\0\0\0\0\0" \
44
+ '16B client UUID16B project UUID' \
45
+ '16B task UUID')
46
+ fpga_mess.client_type.must_equal :FPGA
47
+ end
31
48
  end
32
- end
33
49
 
34
- describe '#client_uuid' do
35
- it 'returns the client UUID' do
36
- mess.client_uuid.must_equal '31364220-636c-6965-6e74-202055554944'
50
+ describe '#client_uuid' do
51
+ it 'returns the client UUID' do
52
+ mess.client_uuid.must_equal '31364220-636c-6965-6e74-202055554944'
53
+ end
37
54
  end
38
- end
39
55
 
40
- describe '#payload' do
41
- it 'returns the result payload' do
42
- mess.payload.must_equal 'some payload'
56
+ describe '#payload' do
57
+ it 'returns the result payload' do
58
+ mess.payload.must_equal 'some payload'
59
+ end
43
60
  end
44
- end
45
61
 
46
- describe '#project_uuid' do
47
- it 'returns the project UUID' do
48
- mess.project_uuid.must_equal '31364220-7072-6f6a-6563-742055554944'
62
+ describe '#project_uuid' do
63
+ it 'returns the project UUID' do
64
+ mess.project_uuid.must_equal '31364220-7072-6f6a-6563-742055554944'
65
+ end
49
66
  end
50
- end
51
67
 
52
- describe '#task_uuid' do
53
- it 'returns the task UUID' do
54
- mess.task_uuid.must_equal '31364220-7461-736b-2020-202055554944'
68
+ describe '#task_uuid' do
69
+ it 'returns the task UUID' do
70
+ mess.task_uuid.must_equal '31364220-7461-736b-2020-202055554944'
71
+ end
55
72
  end
56
- end
57
73
 
58
- describe '#to_s' do
59
- it 'returns the raw bytes' do
60
- mess.to_s.must_equal "#{mess.type}\0\0\0\0\0\0\0\0\0\0\0\0" \
61
- '16B client UUID16B project UUID16B task UUIDsome payload'
74
+ describe '#to_hex' do
75
+ it 'returns a hex representation of the message' do
76
+ assert mess.to_hex.start_with?('44 41 54 41')
77
+ assert mess.to_hex.end_with?('70 61 79 6c 6f 61 64')
78
+ end
79
+ end
80
+
81
+ describe '#to_s' do
82
+ it 'returns the raw bytes' do
83
+ mess.to_s.must_equal "#{mess.type}\0\0\0\0\0\0\0\0\0\0\0\0" \
84
+ '16B client UUID16B project UUID16B task UUIDsome payload'
85
+ end
62
86
  end
63
- end
64
87
 
65
- describe '#type' do
66
- it 'returns the message type' do
67
- mess.type.must_match(/\A[A-Z]{4}\z/)
88
+ describe '#type' do
89
+ it 'returns the message type' do
90
+ mess.type.must_match(/\A[A-Z]{4}\z/)
91
+ end
68
92
  end
69
93
  end
70
- end end
94
+ end
@@ -1,21 +1,27 @@
1
+ require 'socket'
1
2
  require_relative '../spec_helper'
3
+ require_relative '../../lib/kamerling/addr'
4
+ require_relative '../../lib/kamerling/message'
5
+ require_relative '../../lib/kamerling/net_dispatcher'
2
6
 
3
- module Kamerling describe NetDispatcher do
4
- describe '#dispatch' do
5
- it 'dispatches messages to TCP clients' do
6
- server = TCPServer.open 0
7
- thread = Thread.new { server.accept.read }
8
- addr = Addr[server.addr[3], server.addr[1], :TCP]
9
- NetDispatcher.dispatch addr, 'foo'
10
- thread.value.must_equal 'foo'
11
- end
7
+ module Kamerling
8
+ describe NetDispatcher do
9
+ describe '#dispatch' do
10
+ it 'dispatches messages to TCP clients' do
11
+ server = TCPServer.open(0)
12
+ thread = Thread.new { server.accept.read }
13
+ addr = Addr[server.addr[3], server.addr[1], :TCP]
14
+ NetDispatcher.dispatch addr, Message.parse('PING')
15
+ thread.value.must_equal 'PING'
16
+ end
12
17
 
13
- it 'dispatches messages to UDP clients' do
14
- server = UDPSocket.new.tap { |s| s.bind '127.0.0.1', 0 }
15
- thread = Thread.new { server.recvfrom(2**16).first }
16
- addr = Addr[server.addr[3], server.addr[1], :UDP]
17
- NetDispatcher.dispatch addr, 'foo'
18
- thread.value.must_equal 'foo'
18
+ it 'dispatches messages to UDP clients' do
19
+ server = UDPSocket.new.tap { |s| s.bind '127.0.0.1', 0 }
20
+ thread = Thread.new { server.recvfrom(2**16).first }
21
+ addr = Addr[server.addr[3], server.addr[1], :UDP]
22
+ NetDispatcher.dispatch addr, Message.parse('PING')
23
+ thread.value.must_equal 'PING'
24
+ end
19
25
  end
20
26
  end
21
- end end
27
+ end
@@ -1,23 +1,33 @@
1
1
  require_relative '../spec_helper'
2
+ require_relative '../../lib/kamerling/addr'
3
+ require_relative '../../lib/kamerling/client'
4
+ require_relative '../../lib/kamerling/message'
5
+ require_relative '../../lib/kamerling/receiver'
6
+ require_relative '../../lib/kamerling/repo'
7
+ require_relative '../../lib/kamerling/repos'
8
+ require_relative '../../lib/kamerling/result'
9
+ require_relative '../../lib/kamerling/task'
2
10
 
3
- module Kamerling describe Receiver do
4
- describe '#receive' do
5
- fakes :addr, :client, :task
6
-
7
- it 'saves the result and updates client and task' do
8
- repos = fake :repos, as: :class
9
- stub(repos).<<(any_args) { repos }
10
- stub(repos).[](Client) { fake :repo, :[] => client }
11
- stub(repos).[](Task) { fake :repo, :[] => task }
12
- Receiver.new.receive addr: addr, client_uuid: client.uuid, data: 'data',
13
- repos: repos, task_uuid: task.uuid
14
- result = Result.new addr: addr, client: client, data: 'data', task: task,
15
- uuid: anything
16
- client.must_have_received :busy=, [false]
17
- task.must_have_received :done=, [true]
18
- repos.must_have_received :<<, [client]
19
- repos.must_have_received :<<, [task]
20
- repos.must_have_received :<<, [result]
11
+ module Kamerling
12
+ describe Receiver do
13
+ describe '.receive' do
14
+ it 'saves the result and updates client and task' do
15
+ addr = Addr.new
16
+ client = Client.new(busy: true)
17
+ task = Task.new(done: false)
18
+ repos = fake(:repos, as: :class)
19
+ stub(repos).<<(any_args) { repos }
20
+ stub(repos).[](Client) { fake(:repo, :[] => client) }
21
+ stub(repos).[](Task) { fake(:repo, :[] => task) }
22
+ message = Message.build(client: client, payload: 'data',
23
+ project: Project.new, task: task, type: :RSLT)
24
+ Receiver.receive addr: addr, message: message, repos: repos
25
+ refute client.busy
26
+ assert task.done
27
+ repos.must_have_received :<<, [client]
28
+ repos.must_have_received :<<, [any(Result)]
29
+ repos.must_have_received :<<, [task]
30
+ end
21
31
  end
22
32
  end
23
- end end
33
+ end
@@ -1,20 +1,48 @@
1
1
  require_relative '../spec_helper'
2
+ require_relative '../../lib/kamerling/addr'
3
+ require_relative '../../lib/kamerling/client'
4
+ require_relative '../../lib/kamerling/message'
5
+ require_relative '../../lib/kamerling/project'
6
+ require_relative '../../lib/kamerling/registration'
7
+ require_relative '../../lib/kamerling/registrar'
8
+ require_relative '../../lib/kamerling/repo'
2
9
 
3
- module Kamerling describe Registrar do
4
- describe '#register' do
5
- fakes :addr, :client, :project, :repo
10
+ module Kamerling
11
+ describe Registrar do
12
+ describe '.register' do
13
+ let(:addr) { Addr.new }
14
+ let(:client) { Client.new }
15
+ let(:project) { Project.new }
6
16
 
7
- it 'registers that the given client can do the given project' do
8
- repos = {
9
- Client => { client.uuid => client },
10
- Project => { project.uuid => project },
11
- Registration => repo,
12
- }
13
- Registrar.new.register addr: addr, client_uuid: client.uuid,
14
- project_uuid: project.uuid, repos: repos
15
- registration = Registration.new addr: addr, client: client,
16
- project: project, uuid: anything
17
- repo.must_have_received :<<, [registration]
17
+ let(:mess) do
18
+ Message.build(client: client, payload: 'data', project: project,
19
+ task: Task.new, type: :RGST)
20
+ end
21
+
22
+ let(:repos) { fake(:repos, as: :class) }
23
+
24
+ before do
25
+ stub(repos).[](Client) { fake(:repo, :[] => client) }
26
+ stub(repos).[](Project) { fake(:repo, :[] => project) }
27
+ stub(repos).[](Registration) { fake(:repo) }
28
+ end
29
+
30
+ it 'registers that the given client can do the given project' do
31
+ Registrar.register addr: addr, message: mess, repos: repos
32
+ repos.must_have_received :<<, [any(Registration)]
33
+ end
34
+
35
+ it 'updates the clien’t addr' do
36
+ Registrar.register addr: addr, message: mess, repos: repos
37
+ repos.must_have_received :<<, [client]
38
+ end
39
+
40
+ it 'doesn’t blow up when a new client tries to register' do
41
+ empty_repo = fake(:repo, :[] => -> { fail Repo::NotFound })
42
+ stub(repos).[](Client) { empty_repo }
43
+ Registrar.register addr: addr, message: mess, repos: repos
44
+ repos.must_have_received :<<, [client]
45
+ end
18
46
  end
19
47
  end
20
- end end
48
+ end