Repository: ambari Updated Branches: refs/heads/AMBARI-2.4.2.16 [created] d8c707bc2
http://git-wip-us.apache.org/repos/asf/ambari/blob/85e3e332/contrib/views/hawq/src/main/resources/ui/tests/unit/adapters/query-test.js ---------------------------------------------------------------------- diff --git a/contrib/views/hawq/src/main/resources/ui/tests/unit/adapters/query-test.js b/contrib/views/hawq/src/main/resources/ui/tests/unit/adapters/query-test.js index bab0260..4eacd26 100644 --- a/contrib/views/hawq/src/main/resources/ui/tests/unit/adapters/query-test.js +++ b/contrib/views/hawq/src/main/resources/ui/tests/unit/adapters/query-test.js @@ -19,20 +19,17 @@ /*jshint node:true*/ /* global sinon */ -import { moduleFor, test } from 'ember-qunit'; +import {moduleFor, test} from 'ember-qunit'; import Utils from 'hawq-view/utils/utils'; -moduleFor('adapter:query', 'Unit | Adapter | query', { - // Specify the other units that are required for this test. - // needs: ['serializer:foo'] -}); +moduleFor('adapter:query', 'Unit | Adapter | query', {}); -test('has the right namespace for testing', function(assert) { +test('has the right namespace for testing', function (assert) { assert.expect(0); let spy = sinon.spy(Utils, 'getNamespace'); let adapter = this.subject(); - adapter.get('namespace'); + adapter.buildURL(); sinon.assert.calledOnce(spy); Utils.getNamespace.restore(); -}); +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/85e3e332/contrib/views/hawq/src/main/resources/ui/tests/unit/models/query-test.js ---------------------------------------------------------------------- diff --git a/contrib/views/hawq/src/main/resources/ui/tests/unit/models/query-test.js b/contrib/views/hawq/src/main/resources/ui/tests/unit/models/query-test.js index b83130e..227325d 100644 --- a/contrib/views/hawq/src/main/resources/ui/tests/unit/models/query-test.js +++ b/contrib/views/hawq/src/main/resources/ui/tests/unit/models/query-test.js @@ -19,15 +19,12 @@ /*jshint node:true*/ /* global sinon */ -import { moduleForModel, test } from 'ember-qunit'; +import {moduleForModel, test} from 'ember-qunit'; import Utils from 'hawq-view/utils/utils'; -moduleForModel('query', 'Unit | Model | query', { - // Specify the other units that are required for this test. - needs: [] -}); +moduleForModel('query', 'Unit | Model | query', {}); -test('#computeClientAddress called ', function(assert) { +test('#computeClientAddress called ', function (assert) { assert.expect(0); let options = { clientHost: 'host', @@ -42,7 +39,7 @@ test('#computeClientAddress called ', function(assert) { Utils.computeClientAddress.restore(); }); -test('#generateStatusString called', function(assert) { +test('#generateStatusString called', function (assert) { assert.expect(0); let options = { waiting: false, @@ -55,4 +52,4 @@ test('#generateStatusString called', function(assert) { sinon.assert.calledOnce(spy); sinon.assert.calledWith(spy, options.waiting, options.waitingResource); Utils.generateStatusString.restore(); -}); +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/85e3e332/contrib/views/hawq/src/main/resources/ui/tests/unit/routes/main-test.js ---------------------------------------------------------------------- diff --git a/contrib/views/hawq/src/main/resources/ui/tests/unit/routes/main-test.js b/contrib/views/hawq/src/main/resources/ui/tests/unit/routes/main-test.js index 7ad0b79..e3367d1 100644 --- a/contrib/views/hawq/src/main/resources/ui/tests/unit/routes/main-test.js +++ b/contrib/views/hawq/src/main/resources/ui/tests/unit/routes/main-test.js @@ -16,14 +16,11 @@ * limitations under the License. */ -import { moduleFor, test } from 'ember-qunit'; +import {moduleFor, test} from 'ember-qunit'; -moduleFor('route:main', 'Unit | Route | main', { - // Specify the other units that are required for this test. - // needs: ['controller:foo'] -}); +moduleFor('route:main', 'Unit | Route | main', {}); -test('it exists', function(assert) { +test('it exists', function (assert) { let route = this.subject(); assert.ok(route); -}); +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/85e3e332/contrib/views/hawq/src/main/resources/ui/tests/unit/serializers/query-test.js ---------------------------------------------------------------------- diff --git a/contrib/views/hawq/src/main/resources/ui/tests/unit/serializers/query-test.js b/contrib/views/hawq/src/main/resources/ui/tests/unit/serializers/query-test.js index 6cd5f88..e5c9ce9 100644 --- a/contrib/views/hawq/src/main/resources/ui/tests/unit/serializers/query-test.js +++ b/contrib/views/hawq/src/main/resources/ui/tests/unit/serializers/query-test.js @@ -16,19 +16,19 @@ * limitations under the License. */ -import { moduleForModel, test } from 'ember-qunit'; +import {moduleForModel, test} from 'ember-qunit'; import Pretender from 'pretender'; -import { getMockPayload } from 'hawq-view/tests/helpers/test-helper'; +import {getMockPayload} from 'hawq-view/tests/helpers/test-helper'; var mockPayload = getMockPayload(); let server; moduleForModel('query', 'Unit | Serializer | query', { - // Specify the other units that are required for this test. needs: ['serializer:query'], + beforeEach() { - server = new Pretender(function() { - this.get('/queries', function() { + server = new Pretender(function () { + this.get('/queries', function () { return [200, {'Content-Type': 'application/json'}, JSON.stringify(mockPayload)]; }); }); @@ -39,10 +39,61 @@ moduleForModel('query', 'Unit | Serializer | query', { } }); -// Replace this with your real tests. -test('it serializes records', function(assert) { - let record = this.subject(); - let serializedRecord = record.serialize(); - assert.ok(serializedRecord); +test('it serializes all records', function (assert) { + return this.store().query('query', {fields: '*'}).then(function (queries) { + assert.equal(queries.get('length'), 2); + }); }); +test('transforms payload correctly', function (assert) { + return this.store().query('query', {fields: '*'}).then(function (queries) { + let expectedRecords = [ + { + "applicationName": "", + "clientHost": "192.168.64.101", + "clientPort": 34941, + "queryText": "SELECT * FROM pg_stat_activity", + "databaseName": "template1", + "pid": 116662, + "duration": 0.0, + "queryStartTime": "2016-10-25 19:31:04", + "userName": "gpadmin", + "waiting": false, + "waitingResource": false + }, + { + "applicationName": "", + "clientHost": "192.168.64.104", + "clientPort": 42811, + "queryText": "SELECT * FROM customers", + "databaseName": "gpadmin", + "pid": 12345, + "duration": 0.0, + "queryStartTime": "2016-10-25 19:31:24", + "userName": "gpadmin", + "waiting": true, + "waitingResource": true + } + ]; + + const keyList = [ + "applicationName", + "clientHost", + "clientPort", + "queryText", + "databaseName", + "pid", + "duration", + "queryStartTime", + "userName", + "waiting", + "waitingResource" + ]; + + for (var i = 0, ii = expectedRecords.length; i < ii; i++) { + for (var j = 0; j < keyList.length; j++) { + assert.equal(queries.objectAtContent(i).get(keyList[j]), expectedRecords[i][keyList[j]]); + } + } + }, this); +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/85e3e332/contrib/views/hawq/src/main/resources/ui/tests/unit/utils/utils-test.js ---------------------------------------------------------------------- diff --git a/contrib/views/hawq/src/main/resources/ui/tests/unit/utils/utils-test.js b/contrib/views/hawq/src/main/resources/ui/tests/unit/utils/utils-test.js index 969ee6d..9d1f73f 100644 --- a/contrib/views/hawq/src/main/resources/ui/tests/unit/utils/utils-test.js +++ b/contrib/views/hawq/src/main/resources/ui/tests/unit/utils/utils-test.js @@ -20,86 +20,74 @@ /* global sinon */ import Utils from 'hawq-view/utils/utils'; -import { module, test } from 'qunit'; +import {module, test} from 'qunit'; import ENV from 'hawq-view/config/environment'; module('Unit | Utility | utils'); -test('#formatTimeOfDay: extracts time of day from a string', function(assert) { - assert.equal(Utils.formatTimeOfDay('2016-02-16T16:41:13'), '16:41:13'); +test('#computeClientAddress: compute clientAddress', function (assert) { + assert.equal(Utils.computeClientAddress('host', '9999'), 'host:9999'); }); -// TODO: make this TZ-independent for testing purposes -//test('#formatTimeOfDay: extracts time of day from a string, in the local time zone', function(assert) { -// assert.equal(Utils.formatTimeOfDay('2016-02-17T00:41:13+00:00'), '16:41:13'); -//}); - -test('#formatTimeDelta: extracts time difference between two date strings', function(assert) { - var spy = sinon.spy(Utils, 'calculateTimeDelta'); - let backendStartTime = '2016-02-17T00:41:13-08:00'; - let queryStartTime = '2016-02-17T01:43:43-08:00'; - assert.equal(Utils.formatTimeDelta(backendStartTime, queryStartTime).text, '1h 2m 30s'); - sinon.assert.calledOnce(spy); - sinon.assert.calledWith(spy, backendStartTime, queryStartTime); - Utils.calculateTimeDelta.restore(); +test('#computeClientAddress: computed host address', function (assert) { + assert.equal(Utils.computeClientAddress('host', 7777), 'host:7777', 'invalid computed client address'); }); -test('#formatTimeDelta: shows "0m 0s" for two identical times', function(assert) { - var response = Utils.formatTimeDelta('2016-02-17T00:41:13-08:00', '2016-02-17T00:41:13-08:00'); - assert.equal(response.text, '0s'); - assert.equal(response.value, 0); +test('#computeClientAddress: computed host address, -1 port', function (assert) { + assert.equal(Utils.computeClientAddress('host', -1), 'local', 'invalid computed client address'); }); -test('#formatTimeDelta: shows "0m 0s" for the second time being earlier than the first', function(assert) { - var response = Utils.formatTimeDelta('2016-02-17T00:45:13-08:00', '2016-02-17T00:41:13-08:00'); - assert.equal(response.text, '0s'); - assert.equal(response.value, 0); +test('#computeClientAddress: computed host address, Undefined/Null/Empty Host', function (assert) { + assert.equal(Utils.computeClientAddress(undefined, 7777), 'local', 'Invalid hostname: Undefined clientHost'); + assert.equal(Utils.computeClientAddress(null, 7777), 'local', 'Invalid hostname: Null clientHost'); + assert.equal(Utils.computeClientAddress('', 7777), 'local', 'Invalid hostname: Empty clientHost'); }); -test('#computeClientAddress: compute clientAddress', function(assert) { - assert.equal(Utils.computeClientAddress('host', '9999'), 'host:9999'); +test('#formatDuration returns 00:00:00 for null or undefined duration', function (assert) { + assert.equal(Utils.formatDuration(null), "00:00:00"); + assert.equal(Utils.formatDuration(), "00:00:00"); }); -test('#computeClientAddress: computed host address', function(assert) { - assert.equal(Utils.computeClientAddress('host', 7777), 'host:7777', 'invalid computed client address'); +test('#formatDuration returns correct string for query running for seconds', function (assert) { + assert.equal(Utils.formatDuration(0), "00:00:00"); + assert.equal(Utils.formatDuration(32), "00:00:32"); + assert.equal(Utils.formatDuration(59), "00:00:59"); }); -test('#computeClientAddress: computed host address, -1 port', function(assert) { - assert.equal(Utils.computeClientAddress('host', -1), 'local', 'invalid computed client address'); +test('#formatDuration returns correct string for query running for minutes', function (assert) { + assert.equal(Utils.formatDuration(60), "00:01:00"); + assert.equal(Utils.formatDuration(72), "00:01:12"); + assert.equal(Utils.formatDuration(3599), "00:59:59"); }); -test('#computeClientAddress: computed host address, Undefined/Null/Empty Host', function(assert) { - assert.equal(Utils.computeClientAddress(undefined, 7777), 'local', 'Invalid hostname: Undefined clientHost'); - assert.equal(Utils.computeClientAddress( null, 7777), 'local', 'Invalid hostname: Null clientHost'); - assert.equal(Utils.computeClientAddress('', 7777), 'local', 'Invalid hostname: Empty clientHost'); +test('#formatDuration returns correct string for query running for hours', function (assert) { + assert.equal(Utils.formatDuration(3600), "01:00:00"); + assert.equal(Utils.formatDuration(7272), "02:01:12"); + assert.equal(Utils.formatDuration(363599), "100:59:59"); }); -test('#getNamespace returns namespace for testing', function(assert) { +test('#getNamespace returns namespace for testing', function (assert) { assert.equal(Utils.getNamespace(), ENV.apiURL); }); -test('#getNamespace returns namespace for production', function(assert) { - var baseNamespace = 'foo/'; +test('#getNamespace returns namespace for production', function (assert) { + var baseNamespace = '/views/HAWQ/1.0.0/HAWQView/'; var oldEnvironment = ENV.environment; ENV.environment = 'production'; sinon.stub(Utils, 'getWindowPathname').returns(baseNamespace); - assert.equal(Utils.getNamespace(), baseNamespace + ENV.apiURL); + assert.equal(Utils.getNamespace(), '/api/v1/views/HAWQ/versions/1.0.0/instances/HAWQView'); Utils.getWindowPathname.restore(); ENV.environment = oldEnvironment; }); -test('#generateStatusString returns "Running" when waiting and waitingResource are both false', function(assert) { +test('#generateStatusString returns "Running" when waiting and waitingResource are both false', function (assert) { assert.equal(Utils.generateStatusString(false, false), 'Running'); }); -test('#generateStatusString returns "Waiting on Lock" when waiting is true', function(assert) { +test('#generateStatusString returns "Waiting on Lock" when waiting is true', function (assert) { assert.equal(Utils.generateStatusString(true, false), 'Waiting on Lock'); }); -test('#generateStatusString returns "Queued" when waitingResource is true', function(assert) { +test('#generateStatusString returns "Queued" when waitingResource is true', function (assert) { assert.equal(Utils.generateStatusString(true, true), 'Queued'); -}); - -test('#calculateTimeDelta returns difference between two time objects', function(assert) { - assert.equal(Utils.calculateTimeDelta('2016-02-17T00:41:13-08:00', '2016-02-17T11:52:24-08:00'), 40271000); -}); +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/85e3e332/contrib/views/hawq/src/main/resources/view.log4j.properties ---------------------------------------------------------------------- diff --git a/contrib/views/hawq/src/main/resources/view.log4j.properties b/contrib/views/hawq/src/main/resources/view.log4j.properties new file mode 100644 index 0000000..0bd9102 --- /dev/null +++ b/contrib/views/hawq/src/main/resources/view.log4j.properties @@ -0,0 +1,27 @@ +# Copyright 2011 The Apache Software Foundation +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +log4j.appender.hawqView=org.apache.log4j.RollingFileAppender +log4j.appender.hawqView.File=${ambari.log.dir}/hawq-view/hawq-view.log +log4j.appender.hawqView.MaxFileSize=80MB +log4j.appender.hawqView.MaxBackupIndex=60 +log4j.appender.hawqView.layout=org.apache.log4j.PatternLayout +log4j.appender.hawqView.layout.ConversionPattern=%d{DATE} %5p [%t] [%X{viewName} %X{viewVersion} %X{viewInstanceName}] %c{1}:%L - %m%n + +log4j.logger.org.apache.ambari.view.hawq=INFO,hawqView +log4j.additivity.org.apache.ambari.view.hawq=false \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/85e3e332/contrib/views/hawq/src/main/resources/view.xml ---------------------------------------------------------------------- diff --git a/contrib/views/hawq/src/main/resources/view.xml b/contrib/views/hawq/src/main/resources/view.xml index 1421c27..f07e3be 100644 --- a/contrib/views/hawq/src/main/resources/view.xml +++ b/contrib/views/hawq/src/main/resources/view.xml @@ -20,6 +20,51 @@ <version>1.0.0</version> <build>${env.BUILD_NUMBER}</build> + <parameter> + <name>hawq.user.name</name> + <description>Name of the user to connect to HAWQ.</description> + <label>HAWQ User Name</label> + <place-holder>gpadmin</place-holder> + <default-value>gpadmin</default-value> + <required>true</required> + </parameter> + + <parameter> + <name>hawq.user.password</name> + <description>Password of the user to connect to HAWQ.</description> + <label>HAWQ User Password</label> + <place-holder>gpadmin</place-holder> + <default-value>gpadmin</default-value> + <required>true</required> + <masked>true</masked> + </parameter> + + <parameter> + <name>hawq.master.host</name> + <description>HAWQ Master Host.</description> + <label>HAWQ Master Host</label> + <cluster-config>hawq-site/hawq_master_address_host</cluster-config> + <required>true</required> + </parameter> + + <parameter> + <name>hawq.master.port</name> + <description>HAWQ Master Port.</description> + <label>HAWQ Master Port</label> + <place-holder>5432</place-holder> + <cluster-config>hawq-site/hawq_master_address_port</cluster-config> + <required>true</required> + </parameter> + <min-ambari-version>2.2.*</min-ambari-version> + <resource> + <name>query</name> + <plural-name>queries</plural-name> + <id-property>id</id-property> + <resource-class>org.apache.ambari.view.hawq.QueryResource</resource-class> + <provider-class>org.apache.ambari.view.hawq.QueryResourceProvider</provider-class> + <service-class>org.apache.ambari.view.hawq.QueryService</service-class> + </resource> + </view> http://git-wip-us.apache.org/repos/asf/ambari/blob/85e3e332/contrib/views/hawq/src/test/java/org/apache/ambari/view/hawq/HAWQDataSourceTest.java ---------------------------------------------------------------------- diff --git a/contrib/views/hawq/src/test/java/org/apache/ambari/view/hawq/HAWQDataSourceTest.java b/contrib/views/hawq/src/test/java/org/apache/ambari/view/hawq/HAWQDataSourceTest.java new file mode 100644 index 0000000..973d485 --- /dev/null +++ b/contrib/views/hawq/src/test/java/org/apache/ambari/view/hawq/HAWQDataSourceTest.java @@ -0,0 +1,170 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you 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 org.apache.ambari.view.hawq; + +import com.mchange.v2.c3p0.ComboPooledDataSource; +import org.apache.ambari.view.SystemException; +import org.easymock.EasyMockSupport; +import org.easymock.TestSubject; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; + +import java.sql.Connection; +import java.sql.SQLException; + +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.expectLastCall; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.core.classloader.annotations.PrepareForTest; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.powermock.api.easymock.PowerMock.*; +import static org.powermock.api.easymock.PowerMock.expectNew; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({HAWQDataSource.class, ComboPooledDataSource.class}) +public class HAWQDataSourceTest extends EasyMockSupport { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @TestSubject + private HAWQDataSource datasource = new HAWQDataSource(); + + @Test + public void testGetConnection() throws Exception { + + // first invocation, creates new CPDS + ComboPooledDataSource cpds1 = createMock(ComboPooledDataSource.class); + expectNew(ComboPooledDataSource.class).andReturn(cpds1); + cpds1.setDriverClass("org.postgresql.Driver"); + expectLastCall().once(); + cpds1.setJdbcUrl("jdbc:postgresql://host:port/template1"); + expectLastCall().once(); + cpds1.setUser("user"); + expectLastCall().once(); + cpds1.setPassword("password"); + expectLastCall().once(); + cpds1.setInitialPoolSize(0); + expectLastCall().once(); + cpds1.setMinPoolSize(0); + expectLastCall().once(); + cpds1.setMaxPoolSize(1); + expectLastCall().once(); + cpds1.setMaxIdleTime(600); + expectLastCall().once(); + cpds1.setAcquireRetryAttempts(5); + expectLastCall().once(); + cpds1.setAcquireRetryDelay(1000); + expectLastCall().once(); + + Connection conn1 = createMock(Connection.class); + expect(cpds1.getConnection()).andReturn(conn1); + + // second invocation, closes old CPDS, creates a new one + + cpds1.close(); + expectLastCall().once(); + + ComboPooledDataSource cpds2 = createStrictMock(ComboPooledDataSource.class); + expectNew(ComboPooledDataSource.class).andReturn(cpds2); + cpds2.setDriverClass("org.postgresql.Driver"); + expectLastCall().once(); + cpds2.setJdbcUrl("jdbc:postgresql://host:port/template1"); + expectLastCall().once(); + cpds2.setUser("user2"); + expectLastCall().once(); + cpds2.setPassword("password"); + expectLastCall().once(); + cpds2.setInitialPoolSize(0); + expectLastCall().once(); + cpds2.setMinPoolSize(0); + expectLastCall().once(); + cpds2.setMaxPoolSize(1); + expectLastCall().once(); + cpds2.setMaxIdleTime(600); + expectLastCall().once(); + cpds2.setAcquireRetryAttempts(5); + expectLastCall().once(); + cpds2.setAcquireRetryDelay(1000); + expectLastCall().once(); + + Connection conn2 = createMock(Connection.class); + expect(cpds2.getConnection()).andReturn(conn2); + + // third invocation, only return the same connection + expect(cpds2.getConnection()).andReturn(conn2); + + replay(cpds1, ComboPooledDataSource.class); + replay(cpds2, ComboPooledDataSource.class); + replay(conn1); + replay(conn2); + + Connection connection1 = datasource.getConnection("host", "port", "user", "password"); + Connection connection2 = datasource.getConnection("host", "port", "user2", "password"); + Connection connection3 = datasource.getConnection("host", "port", "user2", "password"); + assertNotEquals(connection1, connection2); + assertEquals(connection2, connection3); + } + + @Test(expected = SystemException.class) + public void testGetConnection_FailToLoadDriver() throws Exception { + ComboPooledDataSource cpds = createMock(ComboPooledDataSource.class); + expectNew(ComboPooledDataSource.class).andReturn(cpds); + cpds.setDriverClass("org.postgresql.Driver"); + expectLastCall().andThrow(new RuntimeException("driver not found")); + replay(cpds, ComboPooledDataSource.class); + datasource.getConnection("host", "port", "user", "password"); + } + + @Test(expected = SQLException.class) + public void testGetConnection_FailToGetConnection() throws Exception { + ComboPooledDataSource cpds1 = createMock(ComboPooledDataSource.class); + expectNew(ComboPooledDataSource.class).andReturn(cpds1); + cpds1.setDriverClass("org.postgresql.Driver"); + expectLastCall().once(); + cpds1.setJdbcUrl("jdbc:postgresql://host:port/template1"); + expectLastCall().once(); + cpds1.setUser("user"); + expectLastCall().once(); + cpds1.setPassword("password"); + expectLastCall().once(); + cpds1.setInitialPoolSize(0); + expectLastCall().once(); + cpds1.setMinPoolSize(0); + expectLastCall().once(); + cpds1.setMaxPoolSize(1); + expectLastCall().once(); + cpds1.setMaxIdleTime(600); + expectLastCall().once(); + cpds1.setAcquireRetryAttempts(5); + expectLastCall().once(); + cpds1.setAcquireRetryDelay(1000); + expectLastCall().once(); + + Connection conn1 = createMock(Connection.class); + expect(cpds1.getConnection()).andThrow(new SQLException("fail")); + replay(cpds1, ComboPooledDataSource.class); + replay(conn1); + datasource.getConnection("host", "port", "user", "password"); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/85e3e332/contrib/views/hawq/src/test/java/org/apache/ambari/view/hawq/QueryResourceProviderTest.java ---------------------------------------------------------------------- diff --git a/contrib/views/hawq/src/test/java/org/apache/ambari/view/hawq/QueryResourceProviderTest.java b/contrib/views/hawq/src/test/java/org/apache/ambari/view/hawq/QueryResourceProviderTest.java new file mode 100644 index 0000000..819c3be --- /dev/null +++ b/contrib/views/hawq/src/test/java/org/apache/ambari/view/hawq/QueryResourceProviderTest.java @@ -0,0 +1,200 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you 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 org.apache.ambari.view.hawq; + +import static org.easymock.EasyMock.anyString; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.expectLastCall; +import static org.junit.Assert.*; + +import org.apache.ambari.view.SystemException; +import org.apache.ambari.view.ViewContext; +import org.easymock.EasyMockRunner; +import org.easymock.EasyMockSupport; +import org.easymock.Mock; +import org.easymock.TestSubject; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; + +import java.sql.*; +import java.util.*; + +@RunWith(EasyMockRunner.class) +public class QueryResourceProviderTest extends EasyMockSupport { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @TestSubject + private QueryResourceProvider provider = new QueryResourceProvider(); + + @Mock + private ViewContext viewContext; + + @Mock + private HAWQDataSource dataSource; + + @Mock + private Connection connection; + + @Mock + private Statement statement; + + @Mock + private ResultSet rs; + + @Mock + private ResultSetMetaData rsMetaData; + + @Test + public void testGetResources() throws Exception { + + expect(viewContext.getProperties()).andReturn(prepareViewContextProperties()).anyTimes(); + + expect(dataSource.getConnection("host1", "1234", "gpadmin-user", "gpadmin-password")).andReturn(connection); + expect(connection.createStatement()).andReturn(statement); + expect(statement.executeQuery(anyString())).andReturn(rs); + expect(rs.getMetaData()).andReturn(rsMetaData); + expect(rsMetaData.getColumnCount()).andReturn(2); + + // row 1 + expect(rs.next()).andReturn(true); + // mock only 2 columns + expect(rsMetaData.getColumnName(1)).andReturn("procpid"); + expect(rs.getObject(1)).andReturn(10); + expect(rsMetaData.getColumnName(2)).andReturn("text"); + expect(rs.getObject(2)).andReturn("text-10"); + + // row 2 + expect(rs.next()).andReturn(true); + // mock only 2 columns + expect(rsMetaData.getColumnName(1)).andReturn("procpid"); + expect(rs.getObject(1)).andReturn(20); + expect(rsMetaData.getColumnName(2)).andReturn("text"); + expect(rs.getObject(2)).andReturn("text-20"); + + expect(rs.next()).andReturn(false); + rs.close(); + expectLastCall().once(); + statement.close(); + expectLastCall().once(); + connection.close(); + expectLastCall().once(); + + replayAll(); + Set<QueryResource> results = provider.getResources(null); + + assertEquals(2, results.size()); + Set<String> ids = new HashSet<>(); + ids.add("10"); + ids.add("20"); + for (QueryResource query : results) { + String id = query.getId(); + ids.remove(id); + assertEquals(id, query.getAttributes().get("procpid").toString()); + assertEquals("text-" + id, query.getAttributes().get("text")); + } + assertTrue(ids.isEmpty()); + + verifyAll(); + } + + + @Test + public void testGetResources_MissingUserName() throws Exception { + thrown.expect(SystemException.class); + thrown.expectMessage("HAWQ User Name property is not specified for the view instance."); + + Map<String, String> props = prepareViewContextProperties(); + props.remove("hawq.user.name"); + expect(viewContext.getProperties()).andReturn(props).anyTimes(); + replayAll(); + + provider.getResources(null); + } + + @Test + public void testGetResources_MissingUserPassword() throws Exception { + thrown.expect(SystemException.class); + thrown.expectMessage("HAWQ User Password property is not specified for the view instance."); + + Map<String, String> props = prepareViewContextProperties(); + props.remove("hawq.user.password"); + expect(viewContext.getProperties()).andReturn(props).anyTimes(); + replayAll(); + + provider.getResources(null); + } + + @Test + public void testGetResources_MissingHostName() throws Exception { + thrown.expect(SystemException.class); + thrown.expectMessage("HAWQ Master Host property is not specified for the view instance."); + + Map<String, String> props = prepareViewContextProperties(); + props.remove("hawq.master.host"); + expect(viewContext.getProperties()).andReturn(props).anyTimes(); + replayAll(); + + provider.getResources(null); + } + + @Test + public void testGetResources_MissingHostPort() throws Exception { + thrown.expect(SystemException.class); + thrown.expectMessage("HAWQ Master Port property is not specified for the view instance."); + + Map<String, String> props = prepareViewContextProperties(); + props.remove("hawq.master.port"); + expect(viewContext.getProperties()).andReturn(props).anyTimes(); + replayAll(); + + provider.getResources(null); + } + + @Test + public void testGetResources_ExceptionOnExecute() throws Exception { + thrown.expect(SystemException.class); + thrown.expectMessage("Can't get current queries."); + + expect(viewContext.getProperties()).andReturn(prepareViewContextProperties()).anyTimes(); + + expect(dataSource.getConnection("host1", "1234", "gpadmin-user", "gpadmin-password")).andReturn(connection); + expect(connection.createStatement()).andReturn(statement); + expect(statement.executeQuery(anyString())).andStubThrow(new SQLException("test message")); + statement.close(); + expectLastCall().once(); + connection.close(); + expectLastCall().once(); + replayAll(); + + provider.getResources(null); + } + + private Map<String, String> prepareViewContextProperties() { + Map<String, String> props = new HashMap<>(); + props.put("hawq.user.name", "gpadmin-user"); + props.put("hawq.user.password", "gpadmin-password"); + props.put("hawq.master.host", "host1"); + props.put("hawq.master.port", "1234"); + return props; + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/85e3e332/contrib/views/pom.xml ---------------------------------------------------------------------- diff --git a/contrib/views/pom.xml b/contrib/views/pom.xml index 901c31e..b14300e 100644 --- a/contrib/views/pom.xml +++ b/contrib/views/pom.xml @@ -74,6 +74,7 @@ <exclude>pass.txt</exclude> <exclude>.DS_Store</exclude> <exclude>.iml/</exclude> + <exclude>**/*.iml</exclude> <exclude>.classpath</exclude> <exclude>.project</exclude> <exclude>.settings</exclude>