/**
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.hadoop.hive.ql.hooks;
import com.google.common.collect.Lists;
import org.apache.hadoop.hive.conf.HiveConf;
import org.apache.hadoop.hive.ql.CommandNeedRetryException;
import org.apache.hadoop.hive.ql.Driver;
import org.apache.hadoop.hive.ql.session.SessionState;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.ArgumentMatcher;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.argThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class TestQueryHooks {
private static HiveConf conf;
@BeforeClass
public static void setUpBeforeClass() {
conf = new HiveConf(TestQueryHooks.class);
conf.setBoolVar(HiveConf.ConfVars.HIVE_SUPPORT_CONCURRENCY, false);
conf.setVar(HiveConf.ConfVars.HIVE_AUTHORIZATION_MANAGER,
"org.apache.hadoop.hive.ql.security.authorization.plugin.sqlstd.SQLStdHiveAuthorizerFactory");
}
@Test
public void testAllQueryLifeTimeWithParseHooks() throws IllegalAccessException, ClassNotFoundException, InstantiationException, CommandNeedRetryException {
String query = "select 1";
ArgumentMatcher<QueryLifeTimeHookContext> argMatcher = new QueryLifeTimeHookContextMatcher(query);
QueryLifeTimeHookWithParseHooks mockHook = mock(QueryLifeTimeHookWithParseHooks.class);
int ret = createDriver(mockHook).run(query).getResponseCode();
assertEquals("Expected query to succeed", 0, ret);
verify(mockHook).beforeParse(argThat(argMatcher));
verify(mockHook).afterParse(argThat(argMatcher), eq(false));
verify(mockHook).beforeCompile(argThat(argMatcher));
verify(mockHook).afterCompile(argThat(argMatcher), eq(false));
verify(mockHook).beforeExecution(argThat(argMatcher));
verify(mockHook).afterExecution(argThat(argMatcher), eq(false));
}
@Test
public void testQueryLifeTimeWithParseHooksWithParseError() throws IllegalAccessException, ClassNotFoundException, InstantiationException, CommandNeedRetryException {
String query = "invalidquery";
ArgumentMatcher<QueryLifeTimeHookContext> argMatcher = new QueryLifeTimeHookContextMatcher(query);
QueryLifeTimeHookWithParseHooks mockHook = mock(QueryLifeTimeHookWithParseHooks.class);
int ret = createDriver(mockHook).run(query).getResponseCode();
assertNotEquals("Expected parsing to fail", 0, ret);
verify(mockHook).beforeParse(argThat(argMatcher));
verify(mockHook).afterParse(argThat(argMatcher), eq(true));
verify(mockHook, never()).beforeCompile(any());
verify(mockHook, never()).afterCompile(any(), anyBoolean());
verify(mockHook, never()).beforeExecution(any());
verify(mockHook, never()).afterExecution(any(), anyBoolean());
}
@Test
public void testQueryLifeTimeWithParseHooksWithCompileError() throws IllegalAccessException, ClassNotFoundException, InstantiationException, CommandNeedRetryException {
String query = "select * from foo";
ArgumentMatcher<QueryLifeTimeHookContext> argMatcher = new QueryLifeTimeHookContextMatcher(query);
QueryLifeTimeHookWithParseHooks mockHook = mock(QueryLifeTimeHookWithParseHooks.class);
int ret = createDriver(mockHook).run(query).getResponseCode();
assertNotEquals("Expected compilation to fail", 0, ret);
verify(mockHook).beforeParse(argThat(argMatcher));
verify(mockHook).afterParse(argThat(argMatcher), eq(false));
verify(mockHook).beforeCompile(argThat(argMatcher));
verify(mockHook).afterCompile(argThat(argMatcher), eq(true));
verify(mockHook, never()).beforeExecution(any());
verify(mockHook, never()).afterExecution(any(), anyBoolean());
}
@Test
public void testAllQueryLifeTimeHooks() throws IllegalAccessException, ClassNotFoundException, InstantiationException, CommandNeedRetryException {
String query = "select 1";
ArgumentMatcher<QueryLifeTimeHookContext> argMatcher = new QueryLifeTimeHookContextMatcher(query);
QueryLifeTimeHook mockHook = mock(QueryLifeTimeHook.class);
int ret = createDriver(mockHook).run(query).getResponseCode();
assertEquals("Expected query to succeed", 0, ret);
verify(mockHook).beforeCompile(argThat(argMatcher));
verify(mockHook).afterCompile(argThat(argMatcher), eq(false));
verify(mockHook).beforeExecution(argThat(argMatcher));
verify(mockHook).afterExecution(argThat(argMatcher), eq(false));
}
@Test
public void testQueryLifeTimeWithCompileError() throws IllegalAccessException, ClassNotFoundException, InstantiationException, CommandNeedRetryException {
String query = "select * from foo";
ArgumentMatcher<QueryLifeTimeHookContext> argMatcher = new QueryLifeTimeHookContextMatcher(query);
QueryLifeTimeHook mockHook = mock(QueryLifeTimeHook.class);
int ret = createDriver(mockHook).run(query).getResponseCode();
assertNotEquals("Expected compilation to fail", 0, ret);
verify(mockHook).beforeCompile(argThat(argMatcher));
verify(mockHook).afterCompile(argThat(argMatcher), eq(true));
verify(mockHook, never()).beforeExecution(any());
verify(mockHook, never()).afterExecution(any(), anyBoolean());
}
private Driver createDriver(QueryLifeTimeHook mockHook) throws IllegalAccessException, ClassNotFoundException, InstantiationException {
HooksLoader mockLoader = mock(HooksLoader.class);
when(mockLoader.getHooks(eq(HiveConf.ConfVars.HIVE_QUERY_LIFETIME_HOOKS), any())).thenReturn(
Lists.newArrayList(mockHook));
SessionState.start(conf);
Driver driver = new Driver(conf, mockLoader);
driver.init();
return driver;
}
private static final class QueryLifeTimeHookContextMatcher extends ArgumentMatcher<QueryLifeTimeHookContext> {
private final String command;
private QueryLifeTimeHookContextMatcher(String command) {
this.command = command;
}
@Override
public boolean matches(Object o) {
return ((QueryLifeTimeHookContext) o).getCommand().equals(this.command);
}
}
}