/* * 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.zeppelin.cassandra; import static com.datastax.driver.core.BatchStatement.Type.UNLOGGED; import static com.datastax.driver.core.ConsistencyLevel.ALL; import static com.datastax.driver.core.ConsistencyLevel.LOCAL_SERIAL; import static com.datastax.driver.core.ConsistencyLevel.ONE; import static com.datastax.driver.core.ConsistencyLevel.QUORUM; import static com.datastax.driver.core.ConsistencyLevel.SERIAL; import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; import com.datastax.driver.core.BatchStatement; import com.datastax.driver.core.ConsistencyLevel; import com.datastax.driver.core.Session; import com.datastax.driver.core.SimpleStatement; import com.datastax.driver.core.Statement; import org.apache.zeppelin.display.GUI; import org.apache.zeppelin.display.Input.ParamOption; import org.apache.zeppelin.interpreter.InterpreterContext; import org.apache.zeppelin.interpreter.InterpreterException; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.mockito.Answers; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import scala.Option; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.List; import org.apache.zeppelin.cassandra.TextBlockHierarchy.*; @RunWith(MockitoJUnitRunner.class) public class InterpreterLogicTest { @Rule public ExpectedException expectedException = ExpectedException.none(); @Mock(answer = Answers.RETURNS_DEEP_STUBS) private InterpreterContext intrContext; @Mock private Session session; final InterpreterLogic helper = new InterpreterLogic(session); @Captor ArgumentCaptor<ParamOption[]> optionsCaptor; @Test public void should_parse_input_string_block() throws Exception { //Given String input = "SELECT * FROM users LIMIT 10;"; //When final List<AnyBlock> anyBlocks = this.<AnyBlock>toJavaList(helper.parseInput(input)); //Then assertThat(anyBlocks).hasSize(1); assertThat(anyBlocks.get(0)).isInstanceOf(SimpleStm.class); } @Test public void should_exception_while_parsing_input() throws Exception { //Given String input = "SELECT * FROM users LIMIT 10"; //When expectedException.expect(InterpreterException.class); expectedException.expectMessage("Error parsing input:\n" + "\t'SELECT * FROM users LIMIT 10'\n" + "Did you forget to add ; (semi-colon) at the end of each CQL statement ?"); helper.parseInput(input); } @Test public void should_extract_variable_and_default_value() throws Exception { //Given when(intrContext.getGui().input("table", "zeppelin.demo")).thenReturn("zeppelin.demo"); when(intrContext.getGui().input("id", "'John'")).thenReturn("'John'"); //When final String actual = helper.maybeExtractVariables("SELECT * FROM {{table=zeppelin.demo}} WHERE id={{id='John'}}", intrContext); //Then assertThat(actual).isEqualTo("SELECT * FROM zeppelin.demo WHERE id='John'"); } @Test public void should_extract_variable_and_choices() throws Exception { //Given when(intrContext.getGui().select(eq("name"), eq("'Paul'"), optionsCaptor.capture())).thenReturn("'Jack'"); //When final String actual = helper.maybeExtractVariables("SELECT * FROM zeppelin.artists WHERE name={{name='Paul'|'Jack'|'Smith'}}", intrContext); //Then assertThat(actual).isEqualTo("SELECT * FROM zeppelin.artists WHERE name='Jack'"); final List<ParamOption> paramOptions = asList(optionsCaptor.getValue()); assertThat(paramOptions.get(0).getValue()).isEqualTo("'Paul'"); assertThat(paramOptions.get(1).getValue()).isEqualTo("'Jack'"); assertThat(paramOptions.get(2).getValue()).isEqualTo("'Smith'"); } @Test public void should_extract_no_variable() throws Exception { //Given GUI gui = mock(GUI.class); when(intrContext.getGui()).thenReturn(gui); //When final String actual = helper.maybeExtractVariables("SELECT * FROM zeppelin.demo", intrContext); //Then verifyZeroInteractions(gui); assertThat(actual).isEqualTo("SELECT * FROM zeppelin.demo"); } @Test public void should_error_if_incorrect_variable_definition() throws Exception { //Given //When expectedException.expect(ParsingException.class); expectedException.expectMessage("Invalid bound variable definition for '{{table?zeppelin.demo}}' in 'SELECT * FROM {{table?zeppelin.demo}} WHERE id={{id='John'}}'. It should be of form 'variable=defaultValue'"); //Then helper.maybeExtractVariables("SELECT * FROM {{table?zeppelin.demo}} WHERE id={{id='John'}}", intrContext); } @Test public void should_extract_consistency_option() throws Exception { //Given List<QueryParameters> options = Arrays.<QueryParameters>asList(new Consistency(ALL), new Consistency(ONE)); //When final CassandraQueryOptions actual = helper.extractQueryOptions(toScalaList(options)); //Then assertThat(actual.consistency().get()).isEqualTo(ALL); } @Test public void should_extract_serial_consistency_option() throws Exception { //Given List<QueryParameters> options = Arrays.<QueryParameters>asList(new SerialConsistency(SERIAL), new SerialConsistency(LOCAL_SERIAL)); //When final CassandraQueryOptions actual = helper.extractQueryOptions(toScalaList(options)); //Then assertThat(actual.serialConsistency().get()).isEqualTo(SERIAL); } @Test public void should_extract_timestamp_option() throws Exception { //Given List<QueryParameters> options = Arrays.<QueryParameters>asList(new Timestamp(123L), new Timestamp(456L)); //When final CassandraQueryOptions actual = helper.extractQueryOptions(toScalaList(options)); //Then assertThat(actual.timestamp().get()).isEqualTo(123L); } @Test public void should_extract_retry_policy_option() throws Exception { //Given List<QueryParameters> options = Arrays.<QueryParameters>asList(DowngradingRetryPolicy$.MODULE$, LoggingDefaultRetryPolicy$.MODULE$); //When final CassandraQueryOptions actual = helper.extractQueryOptions(toScalaList(options)); //Then assertThat(actual.retryPolicy().get()).isSameAs(DowngradingRetryPolicy$.MODULE$); } @Test public void should_generate_simple_statement() throws Exception { //Given String input = "SELECT * FROM users LIMIT 10;"; CassandraQueryOptions options = new CassandraQueryOptions(Option.apply(QUORUM), Option.<ConsistencyLevel>empty(), Option.empty(), Option.<RetryPolicy>empty(), Option.empty()); //When final SimpleStatement actual = helper.generateSimpleStatement(new SimpleStm(input), options, intrContext); //Then assertThat(actual).isNotNull(); assertThat(actual.getQueryString()).isEqualTo("SELECT * FROM users LIMIT 10;"); assertThat(actual.getConsistencyLevel()).isSameAs(QUORUM); } @Test public void should_generate_batch_statement() throws Exception { //Given Statement st1 = new SimpleStatement("SELECT * FROM users LIMIT 10;"); Statement st2 = new SimpleStatement("INSERT INTO users(id) VALUES(10);"); Statement st3 = new SimpleStatement("UPDATE users SET name = 'John DOE' WHERE id=10;"); CassandraQueryOptions options = new CassandraQueryOptions(Option.apply(QUORUM), Option.<ConsistencyLevel>empty(), Option.empty(), Option.<RetryPolicy>empty(), Option.empty()); //When BatchStatement actual = helper.generateBatchStatement(UNLOGGED, options, toScalaList(asList(st1, st2, st3))); //Then assertThat(actual).isNotNull(); final List<Statement> statements = new ArrayList<>(actual.getStatements()); assertThat(statements).hasSize(3); assertThat(statements.get(0)).isSameAs(st1); assertThat(statements.get(1)).isSameAs(st2); assertThat(statements.get(2)).isSameAs(st3); assertThat(actual.getConsistencyLevel()).isSameAs(QUORUM); } @Test public void should_parse_bound_values() throws Exception { //Given String bs="'jdoe',32,'John DOE',null, true, '2014-06-12 34:00:34'"; //When final List<String> actual = this.<String>toJavaList(helper.parseBoundValues("ps", bs)); //Then assertThat(actual).containsExactly("'jdoe'", "32", "'John DOE'", "null", "true", "2014-06-12 34:00:34"); } @Test public void should_parse_simple_date() throws Exception { //Given String dateString = "2015-07-30 12:00:01"; //When final Date actual = helper.parseDate(dateString); //Then Calendar calendar = Calendar.getInstance(); calendar.setTime(actual); assertThat(calendar.get(Calendar.YEAR)).isEqualTo(2015); assertThat(calendar.get(Calendar.MONTH)).isEqualTo(Calendar.JULY); assertThat(calendar.get(Calendar.DAY_OF_MONTH)).isEqualTo(30); assertThat(calendar.get(Calendar.HOUR_OF_DAY)).isEqualTo(12); assertThat(calendar.get(Calendar.MINUTE)).isEqualTo(0); assertThat(calendar.get(Calendar.SECOND)).isEqualTo(1); } @Test public void should_parse_accurate_date() throws Exception { //Given String dateString = "2015-07-30 12:00:01.123"; //When final Date actual = helper.parseDate(dateString); //Then Calendar calendar = Calendar.getInstance(); calendar.setTime(actual); assertThat(calendar.get(Calendar.YEAR)).isEqualTo(2015); assertThat(calendar.get(Calendar.MONTH)).isEqualTo(Calendar.JULY); assertThat(calendar.get(Calendar.DAY_OF_MONTH)).isEqualTo(30); assertThat(calendar.get(Calendar.HOUR_OF_DAY)).isEqualTo(12); assertThat(calendar.get(Calendar.MINUTE)).isEqualTo(0); assertThat(calendar.get(Calendar.SECOND)).isEqualTo(1); assertThat(calendar.get(Calendar.MILLISECOND)).isEqualTo(123); } private <A> scala.collection.immutable.List<A> toScalaList(java.util.List<A> list) { return scala.collection.JavaConverters.asScalaBufferConverter(list).asScala().toList(); } private <A> java.util.List<A> toJavaList(scala.collection.immutable.List<A> list){ return scala.collection.JavaConverters.seqAsJavaListConverter(list).asJava(); } }