From 38ef549139849d62ffe88af54af14ab7d456ebf8 Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Tue, 31 Oct 2017 09:59:38 +0100 Subject: [PATCH] Move tunnels from workers to separate package Tunnels package provides implementation of simple data forwarding tunnels between IP addresses pairs. The implementation has been moved from workers package and adjusted to newly defined Tunneler interface. The interface defines basic operations on tunnels (creation, getting address, closing). It provides additional layer of abstraction allowing mockuping tests of parts of the code using tunnels. The mock implementation of interface is provided in matcher package. It is generated using mockgen command: mockgen -package matcher \ -destination=matcher/tunneler_mock_test.go \ -write_package_comment=false \ git.tizen.org/tools/boruta/tunnels Tunneler Change-Id: Ida42f0134f0c365c8f1ffe772b859a0218c301ed Signed-off-by: Lukasz Wojciechowski Signed-off-by: Maciej Wereski --- matcher/tunneler_mock_test.go | 69 +++++++++++++++++++++++ tunnels/tunneler.go | 35 ++++++++++++ workers/tunnel.go => tunnels/tunnels.go | 32 ++++++----- tunnels/tunnels_suite_test.go | 29 ++++++++++ workers/tunnel_test.go => tunnels/tunnels_test.go | 21 ++++--- 5 files changed, 164 insertions(+), 22 deletions(-) create mode 100644 matcher/tunneler_mock_test.go create mode 100644 tunnels/tunneler.go rename workers/tunnel.go => tunnels/tunnels.go (83%) create mode 100644 tunnels/tunnels_suite_test.go rename workers/tunnel_test.go => tunnels/tunnels_test.go (89%) diff --git a/matcher/tunneler_mock_test.go b/matcher/tunneler_mock_test.go new file mode 100644 index 0000000..27def65 --- /dev/null +++ b/matcher/tunneler_mock_test.go @@ -0,0 +1,69 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: git.tizen.org/tools/boruta/tunnels (interfaces: Tunneler) + +package matcher + +import ( + gomock "github.com/golang/mock/gomock" + net "net" + reflect "reflect" +) + +// MockTunneler is a mock of Tunneler interface +type MockTunneler struct { + ctrl *gomock.Controller + recorder *MockTunnelerMockRecorder +} + +// MockTunnelerMockRecorder is the mock recorder for MockTunneler +type MockTunnelerMockRecorder struct { + mock *MockTunneler +} + +// NewMockTunneler creates a new mock instance +func NewMockTunneler(ctrl *gomock.Controller) *MockTunneler { + mock := &MockTunneler{ctrl: ctrl} + mock.recorder = &MockTunnelerMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockTunneler) EXPECT() *MockTunnelerMockRecorder { + return m.recorder +} + +// Addr mocks base method +func (m *MockTunneler) Addr() net.Addr { + ret := m.ctrl.Call(m, "Addr") + ret0, _ := ret[0].(net.Addr) + return ret0 +} + +// Addr indicates an expected call of Addr +func (mr *MockTunnelerMockRecorder) Addr() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Addr", reflect.TypeOf((*MockTunneler)(nil).Addr)) +} + +// Close mocks base method +func (m *MockTunneler) Close() error { + ret := m.ctrl.Call(m, "Close") + ret0, _ := ret[0].(error) + return ret0 +} + +// Close indicates an expected call of Close +func (mr *MockTunnelerMockRecorder) Close() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockTunneler)(nil).Close)) +} + +// Create mocks base method +func (m *MockTunneler) Create(arg0, arg1 net.IP) error { + ret := m.ctrl.Call(m, "Create", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// Create indicates an expected call of Create +func (mr *MockTunnelerMockRecorder) Create(arg0, arg1 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockTunneler)(nil).Create), arg0, arg1) +} diff --git a/tunnels/tunneler.go b/tunnels/tunneler.go new file mode 100644 index 0000000..8f369b1 --- /dev/null +++ b/tunnels/tunneler.go @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2017-2018 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +// File tunnels/tunneler.go defines Tunneler interface with API +// for basic operations on tunnels. + +package tunnels + +import ( + "net" +) + +// Tunneler defines API for basic operations on tunnels. +type Tunneler interface { + // Create sets up a new tunnel. + Create(net.IP, net.IP) error + // Close shuts down tunnel. + Close() error + // Addr returns the address of the tunnel to be used by a user + // for a connection to Dryad. + Addr() net.Addr +} diff --git a/workers/tunnel.go b/tunnels/tunnels.go similarity index 83% rename from workers/tunnel.go rename to tunnels/tunnels.go index f4a4e17..d8409db 100644 --- a/workers/tunnel.go +++ b/tunnels/tunnels.go @@ -14,7 +14,9 @@ * limitations under the License */ -package workers +// Package tunnels allows creation of simple forwarding tunnels +// between IP addresses pairs. +package tunnels import ( "io" @@ -26,35 +28,35 @@ const defaultSSHPort = 22 // Tunnel forwards data between source and destination addresses. type Tunnel struct { + Tunneler listener *net.TCPListener dest *net.TCPAddr done chan struct{} } -// NewTunnel sets up data forwarding tunnel between src and dest IP addresses. -// It will listen on random port on src and forward data to port 22 of dest. +// Create sets up data forwarding tunnel between src and dest IP addresses. +// It will listen on random port on src and forward to SSH port (22) of dest. // // When connection to src is made a corresponding one is created to dest // and data is copied between them. // // Close should be called to clean up this function and terminate connections. -func NewTunnel(src, dest net.IP) (t *Tunnel, err error) { - return newTunnel(src, dest, defaultSSHPort) +func (t *Tunnel) Create(src, dest net.IP) (err error) { + return t.create(src, dest, defaultSSHPort) } -func newTunnel(src, dest net.IP, port int) (t *Tunnel, err error) { - listener, err := net.ListenTCP("tcp", &net.TCPAddr{IP: src}) +// create is a helper function for Create method, which allows to setup any +// port for testing purposes. +func (t *Tunnel) create(src, dest net.IP, portSSH int) (err error) { + t.dest = &net.TCPAddr{IP: dest, Port: portSSH} + t.done = make(chan struct{}) + // It will listen on a random port. + t.listener, err = net.ListenTCP("tcp", &net.TCPAddr{IP: src}) if err != nil { - return nil, err - } - t = &Tunnel{ - listener: listener, - dest: &net.TCPAddr{IP: dest, Port: port}, - done: make(chan struct{}), + return err } - // It will listen on a random port. go t.listenAndForward() - return t, nil + return nil } // Close stops listening on the port for new connections and terminates exisiting ones. diff --git a/tunnels/tunnels_suite_test.go b/tunnels/tunnels_suite_test.go new file mode 100644 index 0000000..32d4c7e --- /dev/null +++ b/tunnels/tunnels_suite_test.go @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package tunnels + +import ( + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + "testing" +) + +func TestTunnels(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Tunnels Suite") +} diff --git a/workers/tunnel_test.go b/tunnels/tunnels_test.go similarity index 89% rename from workers/tunnel_test.go rename to tunnels/tunnels_test.go index d9eca36..99af08f 100644 --- a/workers/tunnel_test.go +++ b/tunnels/tunnels_test.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2017-2018 Samsung Electronics Co., Ltd All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License */ -package workers +package tunnels import ( "io" @@ -23,7 +23,7 @@ import ( . "github.com/onsi/gomega" ) -var _ = Describe("Tunnel", func() { +var _ = Describe("Tunnels", func() { invalidIP := net.IPv4(255, 8, 8, 8) listen := func(done chan struct{}, in, out string) *net.TCPAddr { @@ -52,10 +52,17 @@ var _ = Describe("Tunnel", func() { return ln.Addr().(*net.TCPAddr) } + var t *Tunnel + + BeforeEach(func() { + t = new(Tunnel) + Expect(t).NotTo(BeNil()) + }) + It("should make a connection", func() { done := make(chan struct{}) lAddr := listen(done, "", "") - t, err := newTunnel(nil, nil, lAddr.Port) + err := t.create(nil, nil, lAddr.Port) Expect(err).ToNot(HaveOccurred()) conn, err := net.DialTCP("tcp", nil, lAddr) @@ -71,7 +78,7 @@ var _ = Describe("Tunnel", func() { testIn := "input test string" testOut := "output test string" lAddr := listen(done, testIn, testOut) - t, err := newTunnel(nil, nil, lAddr.Port) + err := t.create(nil, nil, lAddr.Port) Expect(err).ToNot(HaveOccurred()) conn, err := net.DialTCP("tcp", nil, t.Addr().(*net.TCPAddr)) Expect(err).ToNot(HaveOccurred()) @@ -89,12 +96,12 @@ var _ = Describe("Tunnel", func() { }) It("should fail to listen on invalid address", func() { - _, err := NewTunnel(invalidIP, nil) + err := t.Create(invalidIP, nil) Expect(err).To(HaveOccurred()) }) It("should fail to connect to invalid address", func() { - t, err := newTunnel(nil, nil, 0) + err := t.create(nil, nil, 0) Expect(err).ToNot(HaveOccurred()) conn, err := net.DialTCP("tcp", nil, t.Addr().(*net.TCPAddr)) -- 2.7.4