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.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -13
- data/Gemfile +0 -1
- data/Gemfile.lock +64 -64
- data/README.md +18 -1
- data/Rakefile +5 -3
- data/bin/kamerling +1 -1
- data/config/reek.yml +20 -3
- data/kamerling.gemspec +16 -13
- data/lib/kamerling.rb +2 -28
- data/lib/kamerling/addr.rb +17 -3
- data/lib/kamerling/client.rb +10 -11
- data/lib/kamerling/core_extensions/main.rb +14 -14
- data/lib/kamerling/dispatch.rb +13 -0
- data/lib/kamerling/handler.rb +16 -25
- data/lib/kamerling/http_api.rb +50 -34
- data/lib/kamerling/logging.rb +36 -16
- data/lib/kamerling/mapper.rb +33 -0
- data/lib/kamerling/message.rb +50 -37
- data/lib/kamerling/migrations/2_results_received_at.rb +7 -0
- data/lib/kamerling/migrations/3_dispatches.rb +17 -0
- data/lib/kamerling/migrations/4_registrations_registered_at.rb +7 -0
- data/lib/kamerling/migrations/5_clients_type.rb +7 -0
- data/lib/kamerling/net_dispatcher.rb +12 -7
- data/lib/kamerling/project.rb +7 -3
- data/lib/kamerling/receiver.rb +38 -10
- data/lib/kamerling/registrar.rb +45 -8
- data/lib/kamerling/registration.rb +9 -10
- data/lib/kamerling/repo.rb +33 -26
- data/lib/kamerling/repos.rb +52 -45
- data/lib/kamerling/result.rb +10 -11
- data/lib/kamerling/server/http.rb +28 -21
- data/lib/kamerling/server/sock.rb +32 -24
- data/lib/kamerling/server/tcp.rb +23 -15
- data/lib/kamerling/server/udp.rb +24 -16
- data/lib/kamerling/server_runner.rb +30 -41
- data/lib/kamerling/settings.rb +28 -0
- data/lib/kamerling/task.rb +7 -7
- data/lib/kamerling/task_dispatcher.rb +31 -22
- data/lib/kamerling/uuid.rb +13 -11
- data/lib/kamerling/uuid_entity.rb +23 -9
- data/lib/kamerling/value.rb +13 -0
- data/lib/kamerling/views/clients.slim +3 -1
- data/lib/kamerling/views/project.slim +8 -4
- data/lib/kamerling/views/projects.slim +7 -1
- data/spec/kamerling/addr_spec.rb +32 -22
- data/spec/kamerling/client_spec.rb +9 -5
- data/spec/kamerling/core_extensions/main_spec.rb +18 -13
- data/spec/kamerling/dispatch_spec.rb +16 -0
- data/spec/kamerling/handler_spec.rb +24 -34
- data/spec/kamerling/http_api_spec.rb +94 -73
- data/spec/kamerling/logging_spec.rb +93 -62
- data/spec/kamerling/mapper_spec.rb +151 -0
- data/spec/kamerling/message_spec.rb +73 -49
- data/spec/kamerling/net_dispatcher_spec.rb +22 -16
- data/spec/kamerling/receiver_spec.rb +29 -19
- data/spec/kamerling/registrar_spec.rb +43 -15
- data/spec/kamerling/registration_spec.rb +17 -0
- data/spec/kamerling/repo_spec.rb +63 -47
- data/spec/kamerling/repos_spec.rb +121 -109
- data/spec/kamerling/result_spec.rb +16 -0
- data/spec/kamerling/server/http_spec.rb +19 -14
- data/spec/kamerling/server/tcp_spec.rb +41 -35
- data/spec/kamerling/server/udp_spec.rb +40 -34
- data/spec/kamerling/server_runner_spec.rb +62 -53
- data/spec/kamerling/settings_spec.rb +36 -0
- data/spec/kamerling/task_dispatcher_spec.rb +38 -15
- data/spec/kamerling/task_spec.rb +9 -5
- data/spec/kamerling/uuid_entity_spec.rb +53 -25
- data/spec/kamerling/uuid_spec.rb +19 -16
- data/spec/kamerling/value_spec.rb +21 -0
- data/spec/spec_helper.rb +3 -6
- metadata +54 -8
- 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
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
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
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
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
|
-
|
25
|
-
|
26
|
-
|
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
|
-
|
30
|
-
|
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
|
-
|
35
|
-
|
36
|
-
|
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
|
-
|
41
|
-
|
42
|
-
|
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
|
-
|
47
|
-
|
48
|
-
|
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
|
-
|
53
|
-
|
54
|
-
|
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
|
-
|
59
|
-
|
60
|
-
|
61
|
-
'
|
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
|
-
|
66
|
-
|
67
|
-
|
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
|
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
|
4
|
-
describe
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
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
|
4
|
-
describe
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
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
|
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
|
4
|
-
describe
|
5
|
-
|
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
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
}
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
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
|
48
|
+
end
|