diff --git a/neo4j/logging_test.go b/neo4j/logging_test.go index 07e23e95..4f513a4d 100644 --- a/neo4j/logging_test.go +++ b/neo4j/logging_test.go @@ -8,21 +8,22 @@ * 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 + * 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. + * 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 neo4j import ( "github.com/golang/mock/gomock" - "github.com/neo4j/neo4j-go-driver/neo4j/utils/mocks" + "github.com/neo4j/neo4j-go-driver/neo4j/utils/test" . "github.com/onsi/ginkgo" + "github.com/onsi/gomega" ) var _ = Describe("Logging", func() { @@ -41,7 +42,7 @@ var _ = Describe("Logging", func() { Context("errorf", func() { When("Error level is not enabled", func() { It("should not invoke Errorf on logger", func() { - logging := mocks.NewMockLogging(mockCtrl) + logging := NewMockLogging(mockCtrl) logging.EXPECT().ErrorEnabled().Times(1).Return(false) logging.EXPECT().Errorf(gomock.Any(), gomock.Any()).Times(0) @@ -52,11 +53,10 @@ var _ = Describe("Logging", func() { When("Error level is enabled", func() { It("should invoke Errorf on logger", func() { - logging := mocks.NewMockLogging(mockCtrl) + logging := NewMockLogging(mockCtrl) logging.EXPECT().ErrorEnabled().Times(1).Return(true) - // TODO: Add some custom matcher to match message itself? - logging.EXPECT().Errorf(gomock.Any(), "str1", 1).Times(1) + logging.EXPECT().Errorf(test.WrapMatcher(gomega.ContainSubstring("some error")), "str1", 1).Times(1) errorf(logging, "some error", "str1", 1) }) @@ -66,7 +66,7 @@ var _ = Describe("Logging", func() { Context("warningf", func() { When("Warning level is not enabled", func() { It("should not invoke Warningf on logger", func() { - logging := mocks.NewMockLogging(mockCtrl) + logging := NewMockLogging(mockCtrl) logging.EXPECT().WarningEnabled().Times(1).Return(false) logging.EXPECT().Warningf(gomock.Any(), gomock.Any()).Times(0) @@ -77,10 +77,10 @@ var _ = Describe("Logging", func() { When("Warning level is enabled", func() { It("should invoke Warningf on logger", func() { - logging := mocks.NewMockLogging(mockCtrl) + logging := NewMockLogging(mockCtrl) logging.EXPECT().WarningEnabled().Times(1).Return(true) - logging.EXPECT().Warningf(gomock.Any(), "str1", 1).Times(1) + logging.EXPECT().Warningf(test.WrapMatcher(gomega.ContainSubstring("some warning")), "str1", 1).Times(1) warningf(logging, "some warning", "str1", 1) }) @@ -90,7 +90,7 @@ var _ = Describe("Logging", func() { Context("infof", func() { When("Info level is not enabled", func() { It("should not invoke Infof on logger", func() { - logging := mocks.NewMockLogging(mockCtrl) + logging := NewMockLogging(mockCtrl) logging.EXPECT().InfoEnabled().Times(1).Return(false) logging.EXPECT().Infof(gomock.Any(), gomock.Any()).Times(0) @@ -101,10 +101,10 @@ var _ = Describe("Logging", func() { When("Info level is enabled", func() { It("should invoke Infof on logger", func() { - logging := mocks.NewMockLogging(mockCtrl) + logging := NewMockLogging(mockCtrl) logging.EXPECT().InfoEnabled().Times(1).Return(true) - logging.EXPECT().Infof(gomock.Any(), "str1", 1).Times(1) + logging.EXPECT().Infof(test.WrapMatcher(gomega.ContainSubstring("some info")), "str1", 1).Times(1) infof(logging, "some info", "str1", 1) }) @@ -114,7 +114,7 @@ var _ = Describe("Logging", func() { Context("debugf", func() { When("Debug level is not enabled", func() { It("should not invoke Debugf on logger", func() { - logging := mocks.NewMockLogging(mockCtrl) + logging := NewMockLogging(mockCtrl) logging.EXPECT().DebugEnabled().Times(1).Return(false) logging.EXPECT().Debugf(gomock.Any(), gomock.Any()).Times(0) @@ -125,10 +125,10 @@ var _ = Describe("Logging", func() { When("Debug level is enabled", func() { It("should invoke Debugf on logger", func() { - logging := mocks.NewMockLogging(mockCtrl) + logging := NewMockLogging(mockCtrl) logging.EXPECT().DebugEnabled().Times(1).Return(true) - logging.EXPECT().Debugf(gomock.Any(), "str1", 1).Times(1) + logging.EXPECT().Debugf(test.WrapMatcher(gomega.ContainSubstring("some debug")), "str1", 1).Times(1) debugf(logging, "some debug", "str1", 1) }) diff --git a/neo4j/utils/mocks/mock_connection.go b/neo4j/mock_connection_test.go similarity index 91% rename from neo4j/utils/mocks/mock_connection.go rename to neo4j/mock_connection_test.go index 89c59e8a..c8504685 100644 --- a/neo4j/utils/mocks/mock_connection.go +++ b/neo4j/mock_connection_test.go @@ -1,27 +1,27 @@ /* * Copyright (c) 2002-2018 "Neo4j," - * Neo4j Sweden AB [http://seabolt.com] + * Neo4j Sweden AB [http://neo4j.com] * - * This file is part of seabolt. + * This file is part of Neo4j. * * 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 + * 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. + * 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. */ // Code generated by MockGen. DO NOT EDIT. // Source: neo4j-go-connector/neo4j (interfaces: Connection) // Package connector-mocks is a generated GoMock package. -package mocks +package neo4j import ( "reflect" @@ -55,6 +55,18 @@ func (m *MockConnection) EXPECT() *MockConnectionMockRecorder { return m.recorder } +// Id connector-mocks base method +func (m *MockConnection) Id() string { + ret := m.ctrl.Call(m, "Id") + ret0, _ := ret[0].(string) + return ret0 +} + +// Id indicates an expected call of Id +func (mr *MockConnectionMockRecorder) Id() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Id", reflect.TypeOf((*MockConnection)(nil).Id)) +} + // RemoteAddress connector-mocks base method func (m *MockConnection) RemoteAddress() string { ret := m.ctrl.Call(m, "RemoteAddress") diff --git a/neo4j/utils/mocks/mock_connector.go b/neo4j/mock_connector_test.go similarity index 81% rename from neo4j/utils/mocks/mock_connector.go rename to neo4j/mock_connector_test.go index 199f4d31..f7a80334 100644 --- a/neo4j/utils/mocks/mock_connector.go +++ b/neo4j/mock_connector_test.go @@ -1,27 +1,27 @@ /* * Copyright (c) 2002-2018 "Neo4j," - * Neo4j Sweden AB [http://seabolt.com] + * Neo4j Sweden AB [http://neo4j.com] * - * This file is part of seabolt. + * This file is part of Neo4j. * * 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 + * 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. + * 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. */ // Code generated by MockGen. DO NOT EDIT. // Source: neo4j-go-connector/neo4j (interfaces: Connector) // Package connector-mocks is a generated GoMock package. -package mocks +package neo4j import ( reflect "reflect" diff --git a/neo4j/utils/mocks/factory.go b/neo4j/mock_factory_test.go similarity index 67% rename from neo4j/utils/mocks/factory.go rename to neo4j/mock_factory_test.go index 30daeb9b..5cac5e64 100644 --- a/neo4j/utils/mocks/factory.go +++ b/neo4j/mock_factory_test.go @@ -8,16 +8,16 @@ * 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 + * 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. + * 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 mocks +package neo4j import "github.com/neo4j-drivers/gobolt" diff --git a/neo4j/utils/mocks/mock_logging.go b/neo4j/mock_logging_test.go similarity index 91% rename from neo4j/utils/mocks/mock_logging.go rename to neo4j/mock_logging_test.go index 8f82e3b7..6cad4916 100644 --- a/neo4j/utils/mocks/mock_logging.go +++ b/neo4j/mock_logging_test.go @@ -1,27 +1,27 @@ /* * Copyright (c) 2002-2018 "Neo4j," - * Neo4j Sweden AB [http://seabolt.com] + * Neo4j Sweden AB [http://neo4j.com] * - * This file is part of seabolt. + * This file is part of Neo4j. * * 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 + * 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. + * 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. */ // Code generated by MockGen. DO NOT EDIT. // Source: github.com/neo4j/neo4j-go-driver (interfaces: Logging) // Package mocks is a generated GoMock package. -package mocks +package neo4j import ( reflect "reflect" diff --git a/neo4j/utils/mocks/mock_pool.go b/neo4j/mock_pool_test.go similarity index 80% rename from neo4j/utils/mocks/mock_pool.go rename to neo4j/mock_pool_test.go index aba74d71..1c443c59 100644 --- a/neo4j/utils/mocks/mock_pool.go +++ b/neo4j/mock_pool_test.go @@ -1,27 +1,27 @@ /* * Copyright (c) 2002-2018 "Neo4j," - * Neo4j Sweden AB [http://seabolt.com] + * Neo4j Sweden AB [http://neo4j.com] * - * This file is part of seabolt. + * This file is part of Neo4j. * * 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 + * 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. + * 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. */ // Code generated by MockGen. DO NOT EDIT. // Source: neo4j-go-connector/neo4j (interfaces: Pool) // Package connector-mocks is a generated GoMock package. -package mocks +package neo4j import ( reflect "reflect" diff --git a/neo4j/mock_record_test.go b/neo4j/mock_record_test.go new file mode 100644 index 00000000..f896b84d --- /dev/null +++ b/neo4j/mock_record_test.go @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2002-2018 "Neo4j," + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * 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. + */ + +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/neo4j/neo4j-go-driver/neo4j (interfaces: Record) + +// Package mocks is a generated GoMock package. +package neo4j + +import ( + gomock "github.com/golang/mock/gomock" + reflect "reflect" +) + +// MockRecord is a mock of Record interface +type MockRecord struct { + ctrl *gomock.Controller + recorder *MockRecordMockRecorder +} + +// MockRecordMockRecorder is the mock recorder for MockRecord +type MockRecordMockRecorder struct { + mock *MockRecord +} + +// NewMockRecord creates a new mock instance +func NewMockRecord(ctrl *gomock.Controller) *MockRecord { + mock := &MockRecord{ctrl: ctrl} + mock.recorder = &MockRecordMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockRecord) EXPECT() *MockRecordMockRecorder { + return m.recorder +} + +// Get mocks base method +func (m *MockRecord) Get(arg0 string) (interface{}, bool) { + ret := m.ctrl.Call(m, "Get", arg0) + ret0, _ := ret[0].(interface{}) + ret1, _ := ret[1].(bool) + return ret0, ret1 +} + +// Get indicates an expected call of Get +func (mr *MockRecordMockRecorder) Get(arg0 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockRecord)(nil).Get), arg0) +} + +// GetByIndex mocks base method +func (m *MockRecord) GetByIndex(arg0 int) interface{} { + ret := m.ctrl.Call(m, "GetByIndex", arg0) + ret0, _ := ret[0].(interface{}) + return ret0 +} + +// GetByIndex indicates an expected call of GetByIndex +func (mr *MockRecordMockRecorder) GetByIndex(arg0 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByIndex", reflect.TypeOf((*MockRecord)(nil).GetByIndex), arg0) +} + +// Keys mocks base method +func (m *MockRecord) Keys() []string { + ret := m.ctrl.Call(m, "Keys") + ret0, _ := ret[0].([]string) + return ret0 +} + +// Keys indicates an expected call of Keys +func (mr *MockRecordMockRecorder) Keys() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Keys", reflect.TypeOf((*MockRecord)(nil).Keys)) +} + +// Values mocks base method +func (m *MockRecord) Values() []interface{} { + ret := m.ctrl.Call(m, "Values") + ret0, _ := ret[0].([]interface{}) + return ret0 +} + +// Values indicates an expected call of Values +func (mr *MockRecordMockRecorder) Values() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Values", reflect.TypeOf((*MockRecord)(nil).Values)) +} diff --git a/neo4j/mock_result_test.go b/neo4j/mock_result_test.go new file mode 100644 index 00000000..288b2b5f --- /dev/null +++ b/neo4j/mock_result_test.go @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2002-2018 "Neo4j," + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * 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. + */ + +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/neo4j/neo4j-go-driver/neo4j (interfaces: Result) + +// Package mock_neo4j is a generated GoMock package. +package neo4j + +import ( + gomock "github.com/golang/mock/gomock" + reflect "reflect" +) + +// MockResult is a mock of Result interface +type MockResult struct { + ctrl *gomock.Controller + recorder *MockResultMockRecorder +} + +// MockResultMockRecorder is the mock recorder for MockResult +type MockResultMockRecorder struct { + mock *MockResult +} + +// NewMockResult creates a new mock instance +func NewMockResult(ctrl *gomock.Controller) *MockResult { + mock := &MockResult{ctrl: ctrl} + mock.recorder = &MockResultMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockResult) EXPECT() *MockResultMockRecorder { + return m.recorder +} + +// Consume mocks base method +func (m *MockResult) Consume() (ResultSummary, error) { + ret := m.ctrl.Call(m, "Consume") + ret0, _ := ret[0].(ResultSummary) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Consume indicates an expected call of Consume +func (mr *MockResultMockRecorder) Consume() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Consume", reflect.TypeOf((*MockResult)(nil).Consume)) +} + +// Err mocks base method +func (m *MockResult) Err() error { + ret := m.ctrl.Call(m, "Err") + ret0, _ := ret[0].(error) + return ret0 +} + +// Err indicates an expected call of Err +func (mr *MockResultMockRecorder) Err() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Err", reflect.TypeOf((*MockResult)(nil).Err)) +} + +// Keys mocks base method +func (m *MockResult) Keys() ([]string, error) { + ret := m.ctrl.Call(m, "Keys") + ret0, _ := ret[0].([]string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Keys indicates an expected call of Keys +func (mr *MockResultMockRecorder) Keys() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Keys", reflect.TypeOf((*MockResult)(nil).Keys)) +} + +// Next mocks base method +func (m *MockResult) Next() bool { + ret := m.ctrl.Call(m, "Next") + ret0, _ := ret[0].(bool) + return ret0 +} + +// Next indicates an expected call of Next +func (mr *MockResultMockRecorder) Next() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Next", reflect.TypeOf((*MockResult)(nil).Next)) +} + +// Record mocks base method +func (m *MockResult) Record() Record { + ret := m.ctrl.Call(m, "Record") + ret0, _ := ret[0].(Record) + return ret0 +} + +// Record indicates an expected call of Record +func (mr *MockResultMockRecorder) Record() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Record", reflect.TypeOf((*MockResult)(nil).Record)) +} + +// Summary mocks base method +func (m *MockResult) Summary() (ResultSummary, error) { + ret := m.ctrl.Call(m, "Summary") + ret0, _ := ret[0].(ResultSummary) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Summary indicates an expected call of Summary +func (mr *MockResultMockRecorder) Summary() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Summary", reflect.TypeOf((*MockResult)(nil).Summary)) +} diff --git a/neo4j/mock_resultsummary_test.go b/neo4j/mock_resultsummary_test.go new file mode 100644 index 00000000..e32bea05 --- /dev/null +++ b/neo4j/mock_resultsummary_test.go @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2002-2018 "Neo4j," + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * 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. + */ + +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/neo4j/neo4j-go-driver/neo4j (interfaces: ResultSummary) + +// Package mocks is a generated GoMock package. +package neo4j + +import ( + gomock "github.com/golang/mock/gomock" + reflect "reflect" + time "time" +) + +// MockResultSummary is a mock of ResultSummary interface +type MockResultSummary struct { + ctrl *gomock.Controller + recorder *MockResultSummaryMockRecorder +} + +// MockResultSummaryMockRecorder is the mock recorder for MockResultSummary +type MockResultSummaryMockRecorder struct { + mock *MockResultSummary +} + +// NewMockResultSummary creates a new mock instance +func NewMockResultSummary(ctrl *gomock.Controller) *MockResultSummary { + mock := &MockResultSummary{ctrl: ctrl} + mock.recorder = &MockResultSummaryMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockResultSummary) EXPECT() *MockResultSummaryMockRecorder { + return m.recorder +} + +// Counters mocks base method +func (m *MockResultSummary) Counters() Counters { + ret := m.ctrl.Call(m, "Counters") + ret0, _ := ret[0].(Counters) + return ret0 +} + +// Counters indicates an expected call of Counters +func (mr *MockResultSummaryMockRecorder) Counters() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Counters", reflect.TypeOf((*MockResultSummary)(nil).Counters)) +} + +// Notifications mocks base method +func (m *MockResultSummary) Notifications() []Notification { + ret := m.ctrl.Call(m, "Notifications") + ret0, _ := ret[0].([]Notification) + return ret0 +} + +// Notifications indicates an expected call of Notifications +func (mr *MockResultSummaryMockRecorder) Notifications() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Notifications", reflect.TypeOf((*MockResultSummary)(nil).Notifications)) +} + +// Plan mocks base method +func (m *MockResultSummary) Plan() Plan { + ret := m.ctrl.Call(m, "Plan") + ret0, _ := ret[0].(Plan) + return ret0 +} + +// Plan indicates an expected call of Plan +func (mr *MockResultSummaryMockRecorder) Plan() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Plan", reflect.TypeOf((*MockResultSummary)(nil).Plan)) +} + +// Profile mocks base method +func (m *MockResultSummary) Profile() ProfiledPlan { + ret := m.ctrl.Call(m, "Profile") + ret0, _ := ret[0].(ProfiledPlan) + return ret0 +} + +// Profile indicates an expected call of Profile +func (mr *MockResultSummaryMockRecorder) Profile() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Profile", reflect.TypeOf((*MockResultSummary)(nil).Profile)) +} + +// ResultAvailableAfter mocks base method +func (m *MockResultSummary) ResultAvailableAfter() time.Duration { + ret := m.ctrl.Call(m, "ResultAvailableAfter") + ret0, _ := ret[0].(time.Duration) + return ret0 +} + +// ResultAvailableAfter indicates an expected call of ResultAvailableAfter +func (mr *MockResultSummaryMockRecorder) ResultAvailableAfter() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResultAvailableAfter", reflect.TypeOf((*MockResultSummary)(nil).ResultAvailableAfter)) +} + +// ResultConsumedAfter mocks base method +func (m *MockResultSummary) ResultConsumedAfter() time.Duration { + ret := m.ctrl.Call(m, "ResultConsumedAfter") + ret0, _ := ret[0].(time.Duration) + return ret0 +} + +// ResultConsumedAfter indicates an expected call of ResultConsumedAfter +func (mr *MockResultSummaryMockRecorder) ResultConsumedAfter() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResultConsumedAfter", reflect.TypeOf((*MockResultSummary)(nil).ResultConsumedAfter)) +} + +// Server mocks base method +func (m *MockResultSummary) Server() ServerInfo { + ret := m.ctrl.Call(m, "Server") + ret0, _ := ret[0].(ServerInfo) + return ret0 +} + +// Server indicates an expected call of Server +func (mr *MockResultSummaryMockRecorder) Server() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Server", reflect.TypeOf((*MockResultSummary)(nil).Server)) +} + +// Statement mocks base method +func (m *MockResultSummary) Statement() Statement { + ret := m.ctrl.Call(m, "Statement") + ret0, _ := ret[0].(Statement) + return ret0 +} + +// Statement indicates an expected call of Statement +func (mr *MockResultSummaryMockRecorder) Statement() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Statement", reflect.TypeOf((*MockResultSummary)(nil).Statement)) +} + +// StatementType mocks base method +func (m *MockResultSummary) StatementType() StatementType { + ret := m.ctrl.Call(m, "StatementType") + ret0, _ := ret[0].(StatementType) + return ret0 +} + +// StatementType indicates an expected call of StatementType +func (mr *MockResultSummaryMockRecorder) StatementType() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StatementType", reflect.TypeOf((*MockResultSummary)(nil).StatementType)) +} diff --git a/neo4j/result_helpers.go b/neo4j/result_helpers.go new file mode 100644 index 00000000..a174c1a4 --- /dev/null +++ b/neo4j/result_helpers.go @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2002-2018 "Neo4j," + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * 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 neo4j + +// Single returns one and only one record from the result stream. Any error passed in +// or reported while navigating the result stream is returned without any conversion. +// If the result stream contains zero or more than one records error is returned. +func Single(from interface{}, err error) (Record, error) { + var result Result + var record Record + var ok bool + + if err != nil { + return nil, err + } + + if result, ok = from.(Result); !ok { + return nil, newDriverError("expected from to be a result but it was '%v'", from) + } + + if result.Next() { + record = result.Record() + } + + if err := result.Err(); err != nil { + return nil, err + } + + if record == nil { + return nil, newDriverError("result contains no records") + } + + if result.Next() { + return nil, newDriverError("result contains more than one record") + } + + return record, nil +} + +// Collect loops through the result stream, collects records into a slice and returns the +// resulting slice. Any error passed in or reported while navigating the result stream is +// returned without any conversion. +func Collect(from interface{}, err error) ([]Record, error) { + var result Result + var list []Record + var ok bool + + if err != nil { + return nil, err + } + + if result, ok = from.(Result); !ok { + return nil, newDriverError("expected from to be a result but it was '%v'", from) + } + + for result.Next() { + list = append(list, result.Record()) + } + if err := result.Err(); err != nil { + return nil, err + } + + return list, nil +} diff --git a/neo4j/result_helpers_test.go b/neo4j/result_helpers_test.go new file mode 100644 index 00000000..da10de82 --- /dev/null +++ b/neo4j/result_helpers_test.go @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2002-2018 "Neo4j," + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * 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 neo4j + +import ( + "github.com/golang/mock/gomock" + . "github.com/neo4j/neo4j-go-driver/neo4j/utils/test" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "github.com/pkg/errors" +) + +var _ = Describe("Result Helpers", func() { + var ( + mockCtrl *gomock.Controller + mockResult *MockResult + mockRecord *MockRecord + ) + + BeforeEach(func() { + mockCtrl = gomock.NewController(GinkgoT()) + }) + + AfterEach(func() { + mockCtrl.Finish() + }) + + Context("Single", func() { + var fixedError = errors.New("some error") + + It("should return error when error is passed", func() { + record, err := Single(nil, fixedError) + + Expect(record).To(BeNil()) + Expect(err).To(Equal(fixedError)) + }) + + It("should return error when from is not record", func() { + record, err := Single("i'm not a record", nil) + + Expect(record).To(BeNil()) + Expect(err).To(BeGenericError(ContainSubstring("expected from to be a result but it was 'i'm not a record'"))) + }) + + It("should return error if result returns error", func() { + mockResult = NewMockResult(mockCtrl) + gomock.InOrder( + mockResult.EXPECT().Next().Return(false), + mockResult.EXPECT().Err().Return(fixedError), + ) + + record, err := Single(mockResult, nil) + + Expect(record).To(BeNil()) + Expect(err).To(Equal(fixedError)) + }) + + It("should return error if result returns error after first Next", func() { + mockRecord = NewMockRecord(mockCtrl) + mockResult = NewMockResult(mockCtrl) + + gomock.InOrder( + mockResult.EXPECT().Next().Return(true), + mockResult.EXPECT().Record().Return(mockRecord), + mockResult.EXPECT().Err().Return(fixedError), + ) + + record, err := Single(mockResult, nil) + + Expect(record).To(BeNil()) + Expect(err).To(Equal(fixedError)) + }) + + It("should return nil when there's no elements", func() { + mockResult = NewMockResult(mockCtrl) + + gomock.InOrder( + mockResult.EXPECT().Next().Return(false), + mockResult.EXPECT().Err().Return(nil), + ) + + record, err := Single(mockResult, nil) + + Expect(record).To(BeNil()) + Expect(err).Should(BeGenericError(ContainSubstring("result contains no records"))) + }) + + It("should return record when there's only one element", func() { + mockRecord = NewMockRecord(mockCtrl) + mockResult = NewMockResult(mockCtrl) + + gomock.InOrder( + mockResult.EXPECT().Next().Return(true), + mockResult.EXPECT().Record().Return(mockRecord), + mockResult.EXPECT().Err().Return(nil), + mockResult.EXPECT().Next().Return(false), + ) + + record, err := Single(mockResult, nil) + + Expect(record).To(Equal(mockRecord)) + Expect(err).To(BeNil()) + }) + + It("should return error when there's more than one element", func() { + mockRecord = NewMockRecord(mockCtrl) + mockResult = NewMockResult(mockCtrl) + + gomock.InOrder( + mockResult.EXPECT().Next().Return(true), + mockResult.EXPECT().Record().Return(mockRecord), + mockResult.EXPECT().Err().Return(nil), + mockResult.EXPECT().Next().Return(true), + ) + + record, err := Single(mockResult, nil) + + Expect(record).To(BeNil()) + Expect(err).Should(BeGenericError(ContainSubstring("result contains more than one record"))) + }) + }) + + Context("Collect", func() { + var fixedError = errors.New("some error") + + It("should return error when error is passed", func() { + records, err := Collect(nil, fixedError) + + Expect(records).To(BeNil()) + Expect(err).To(Equal(fixedError)) + }) + + It("should return error when from is not record", func() { + record, err := Collect("i'm not a record", nil) + + Expect(record).To(BeNil()) + Expect(err).To(BeGenericError(ContainSubstring("expected from to be a result but it was 'i'm not a record'"))) + }) + + It("should return error if result returns error", func() { + mockResult = NewMockResult(mockCtrl) + gomock.InOrder( + mockResult.EXPECT().Next().Return(false), + mockResult.EXPECT().Err().Return(fixedError), + ) + + records, err := Collect(mockResult, nil) + + Expect(records).To(BeNil()) + Expect(err).To(Equal(fixedError)) + }) + + It("should return error if result returns error after first Next", func() { + mockRecord = NewMockRecord(mockCtrl) + mockResult = NewMockResult(mockCtrl) + + gomock.InOrder( + mockResult.EXPECT().Next().Return(true), + mockResult.EXPECT().Record().Return(mockRecord), + mockResult.EXPECT().Next().Return(false), + mockResult.EXPECT().Err().Return(fixedError), + ) + + records, err := Collect(mockResult, nil) + + Expect(records).To(BeNil()) + Expect(err).To(Equal(fixedError)) + }) + + It("should return one record", func() { + mockRecord = NewMockRecord(mockCtrl) + mockResult = NewMockResult(mockCtrl) + + gomock.InOrder( + mockResult.EXPECT().Next().Return(true), + mockResult.EXPECT().Record().Return(mockRecord), + mockResult.EXPECT().Next().Return(false), + mockResult.EXPECT().Err().Return(nil), + ) + + records, err := Collect(mockResult, nil) + + Expect(records).To(HaveLen(1)) + Expect(records[0]).To(Equal(mockRecord)) + Expect(err).To(BeNil()) + }) + + It("should return five records", func() { + mockRecord1 := NewMockRecord(mockCtrl) + mockRecord2 := NewMockRecord(mockCtrl) + mockRecord3 := NewMockRecord(mockCtrl) + mockRecord4 := NewMockRecord(mockCtrl) + mockRecord5 := NewMockRecord(mockCtrl) + + mockResult = NewMockResult(mockCtrl) + + gomock.InOrder( + mockResult.EXPECT().Next().Return(true), + mockResult.EXPECT().Record().Return(mockRecord1), + mockResult.EXPECT().Next().Return(true), + mockResult.EXPECT().Record().Return(mockRecord2), + mockResult.EXPECT().Next().Return(true), + mockResult.EXPECT().Record().Return(mockRecord3), + mockResult.EXPECT().Next().Return(true), + mockResult.EXPECT().Record().Return(mockRecord4), + mockResult.EXPECT().Next().Return(true), + mockResult.EXPECT().Record().Return(mockRecord5), + mockResult.EXPECT().Next().Return(false), + mockResult.EXPECT().Err().Return(nil), + ) + + records, err := Collect(mockResult, nil) + + Expect(records).To(HaveLen(5)) + Expect(records[0]).To(Equal(mockRecord1)) + Expect(records[1]).To(Equal(mockRecord2)) + Expect(records[2]).To(Equal(mockRecord3)) + Expect(records[3]).To(Equal(mockRecord4)) + Expect(records[4]).To(Equal(mockRecord5)) + Expect(err).To(BeNil()) + }) + }) +}) diff --git a/neo4j/result_impl.go b/neo4j/result_impl.go index 6d920d87..79f1ef4b 100644 --- a/neo4j/result_impl.go +++ b/neo4j/result_impl.go @@ -44,10 +44,18 @@ func (result *neoResult) collectMetadata(metadata map[string]interface{}) { result.summary.resultAvailableAfter = time.Duration(resultAvailabilityTimer.(int64)) / time.Millisecond } + if resultAvailabilityTimer, ok := metadata["t_first"]; ok { + result.summary.resultAvailableAfter = time.Duration(resultAvailabilityTimer.(int64)) / time.Millisecond + } + if resultConsumptionTimer, ok := metadata["result_consumed_after"]; ok { result.summary.resultConsumedAfter = time.Duration(resultConsumptionTimer.(int64)) / time.Millisecond } + if resultConsumptionTimer, ok := metadata["t_last"]; ok { + result.summary.resultConsumedAfter = time.Duration(resultConsumptionTimer.(int64)) / time.Millisecond + } + if typeString, ok := metadata["type"]; ok { switch typeString.(string) { case "r": diff --git a/neo4j/retry.go b/neo4j/retry.go index 5156dacb..7cf84940 100644 --- a/neo4j/retry.go +++ b/neo4j/retry.go @@ -69,7 +69,6 @@ func (logic *retryLogic) retry(work func() (interface{}, error)) (interface{}, e warningf(logic.logging, "retriable operation failed to complete [error: %s] and will be retried in %dms", err.Error(), delayWithJitter.Nanoseconds()/int64(time.Millisecond)) time.Sleep(delayWithJitter) nextDelay = delayWithJitter - // TODO: record error continue } } diff --git a/neo4j/runner.go b/neo4j/runner.go index fd76a011..4cea0be3 100644 --- a/neo4j/runner.go +++ b/neo4j/runner.go @@ -44,6 +44,22 @@ func (runner *statementRunner) lastSeenBookmark() string { return runner.lastBookmark } +func (runner *statementRunner) assertConnection() error { + if runner.connection == nil { + return newDriverError("unexpected state: expected an active connection bound to this runner") + } + + return nil +} + +func (runner *statementRunner) assertNoConnection() error { + if runner.connection != nil { + return newDriverError("unexpected state: expected no connection bound to this runner") + } + + return nil +} + // This ensures that we've a connection to run statements against func (runner *statementRunner) ensureConnection() error { if runner.connection == nil { @@ -237,7 +253,9 @@ func (runner *statementRunner) runStatement(statement *neoStatement, bookmarks [ } func (runner *statementRunner) beginTransaction(bookmarks []string, txConfig TransactionConfig) (Result, error) { - // TODO: assert no connection + if err := runner.assertNoConnection(); err != nil { + return nil, err + } if err := runner.ensureConnection(); err != nil { defer runner.closeConnection() @@ -267,7 +285,9 @@ func (runner *statementRunner) beginTransaction(bookmarks []string, txConfig Tra } func (runner *statementRunner) commitTransaction() (Result, error) { - // TODO: assert connection + if err := runner.assertConnection(); err != nil { + return nil, err + } commitHandle, err := runner.connection.Commit() if err != nil { @@ -289,7 +309,9 @@ func (runner *statementRunner) commitTransaction() (Result, error) { } func (runner *statementRunner) rollbackTransaction() (Result, error) { - // TODO: assert connection + if err := runner.assertConnection(); err != nil { + return nil, err + } rollbackHandle, err := runner.connection.Rollback() if err != nil { diff --git a/neo4j/runner_test.go b/neo4j/runner_test.go index 9b32e420..74e5a19a 100644 --- a/neo4j/runner_test.go +++ b/neo4j/runner_test.go @@ -21,7 +21,6 @@ package neo4j import ( "github.com/golang/mock/gomock" - "github.com/neo4j/neo4j-go-driver/neo4j/utils/mocks" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "time" @@ -42,8 +41,8 @@ var _ = Describe("Runner", func() { Context("runStatement", func() { It("should invoke run on connection", func() { - mockConnection := mocks.NewMockConnection(mockCtrl) - mockConnector := mocks.MockedConnector(mockConnection) + mockConnection := NewMockConnection(mockCtrl) + mockConnector := MockedConnector(mockConnection) mockDriver := newGoboltWithConnector("bolt://localhost", mockConnector) runner := newRunner(mockDriver, AccessModeWrite, true) diff --git a/neo4j/test-integration/examples_test.go b/neo4j/test-integration/examples_test.go index c0461c34..77456304 100644 --- a/neo4j/test-integration/examples_test.go +++ b/neo4j/test-integration/examples_test.go @@ -105,6 +105,24 @@ var _ = Describe("Examples", func() { Expect(err).To(BeNil()) }) + Specify("Config - With Customized Connection Pool", func() { + driver, err := createDriverWithCustomizedConnectionPool(uri, username, password) + Expect(err).To(BeNil()) + Expect(driver).NotTo(BeNil()) + + err = driver.Close() + Expect(err).To(BeNil()) + }) + + Specify("Config - With Connection Timeout", func() { + driver, err := createDriverWithConnectionTimeout(uri, username, password) + Expect(err).To(BeNil()) + Expect(driver).NotTo(BeNil()) + + err = driver.Close() + Expect(err).To(BeNil()) + }) + Specify("Service Unavailable", func() { driver, err := createDriverWithMaxRetryTime("bolt://localhost:8080", username, password) Expect(err).To(BeNil()) @@ -198,6 +216,25 @@ var _ = Describe("Examples", func() { Expect(people).To(ContainElement("Annie")) Expect(people).To(ContainElement("Joe")) }) + + Specify("Result Retain", func() { + driver, err := createDriverWithMaxRetryTime(uri, username, password) + Expect(err).To(BeNil()) + Expect(driver).NotTo(BeNil()) + defer driver.Close() + + id, err := addPersonNode(driver, "Carl") + Expect(err).To(BeNil()) + Expect(id).To(BeNumerically(">=", 0)) + + id, err = addPersonNode(driver, "Thomas") + Expect(err).To(BeNil()) + Expect(id).To(BeNumerically(">=", 0)) + + count, err := addPersonsAsEmployees(driver, "Acme") + Expect(err).To(BeNil()) + Expect(count).To(BeNumerically(">=", 2)) + }) }) Context("Causal Cluster", func() { @@ -385,10 +422,22 @@ func addPerson(name string) error { // end::config-custom-resolver[] // tag::config-connection-pool[] +func createDriverWithCustomizedConnectionPool(uri, username, password string) (neo4j.Driver, error) { + return neo4j.NewDriver(uri, neo4j.BasicAuth(username, password, ""), func(config *neo4j.Config) { + config.MaxConnectionLifetime = 30 * time.Minute + config.MaxConnectionPoolSize = 50 + config.ConnectionAcquisitionTimeout = 2 * time.Minute + }) +} // end::config-connection-pool[] // tag::config-connection-timeout[] +func createDriverWithConnectionTimeout(uri, username, password string) (neo4j.Driver, error) { + return neo4j.NewDriver(uri, neo4j.BasicAuth(username, password, ""), func(config *neo4j.Config) { + config.SocketConnectTimeout = 15 * time.Second + }) +} // end::config-connection-timeout[] @@ -396,6 +445,7 @@ func addPerson(name string) error { func createDriverWithMaxRetryTime(uri, username, password string) (neo4j.Driver, error) { return neo4j.NewDriver(uri, neo4j.BasicAuth(username, password, ""), func(config *neo4j.Config) { config.MaxTransactionRetryTime = 15 * time.Second + config.Log = neo4j.ConsoleLogger(neo4j.DEBUG) }) } @@ -745,5 +795,38 @@ func getPeople(driver neo4j.Driver) ([]string, error) { // end::result-consume[] // tag::result-retain[] +func addPersonsAsEmployees(driver neo4j.Driver, companyName string) (int, error) { + var session neo4j.Session + var err error + var persons []neo4j.Record + var employees int + + if session, err = driver.Session(neo4j.AccessModeWrite); err != nil { + return 0, err + } + defer session.Close() + + persons, err = neo4j.Collect(session.ReadTransaction(func(tx neo4j.Transaction) (interface{}, error) { + return tx.Run("MATCH (a:Person) RETURN a.name AS name", nil) + })) + if err != nil { + return 0, err + } + + for _, person := range persons { + _, err = session.WriteTransaction(func(tx neo4j.Transaction) (interface{}, error) { + return tx.Run("MATCH (emp:Person {name: $person_name}) "+ + "MERGE (com:Company {name: $company_name}) "+ + "MERGE (emp)-[:WORKS_FOR]->(com)", map[string]interface{}{"person_name": person.GetByIndex(0), "company_name": companyName}) + }) + if err != nil { + return 0, err + } + + employees++ + } + + return employees, nil +} // end::result-retain[] diff --git a/neo4j/utils/test/gomock_matchers.go b/neo4j/utils/test/gomock_matchers.go new file mode 100644 index 00000000..db4eebd8 --- /dev/null +++ b/neo4j/utils/test/gomock_matchers.go @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2002-2018 "Neo4j," + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * 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 test + +import ( + "github.com/golang/mock/gomock" + "github.com/onsi/gomega" +) + +type omegaMatcherWrapper struct { + matcher gomega.OmegaMatcher +} + +func WrapMatcher(matcher gomega.OmegaMatcher) gomock.Matcher { + return &omegaMatcherWrapper{matcher: matcher} +} + +func (wrapper *omegaMatcherWrapper) Matches(actual interface{}) bool { + result, err := wrapper.matcher.Match(actual) + if err != nil { + panic(err) + } + return result +} + +func (wrapper *omegaMatcherWrapper) String() string { + return wrapper.matcher.FailureMessage(nil) +}