kamerling 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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