/**
* 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.postgresql;
import static com.google.common.collect.Sets.newHashSet;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import jline.console.completer.Completer;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Joiner;
import com.google.common.collect.Sets;
import com.mockrunner.jdbc.BasicJDBCTestCaseAdapter;
public class SqlCompleterTest extends BasicJDBCTestCaseAdapter {
private Logger logger = LoggerFactory.getLogger(SqlCompleterTest.class);
private final static Set<String> EMPTY = new HashSet<String>();
private CompleterTester tester;
private SqlCompleter sqlCompleter;
@Before
public void beforeTest() throws IOException, SQLException {
Set<String> keywordsCompletions =
SqlCompleter.getSqlKeywordsCompletions(getJDBCMockObjectFactory().getMockConnection());
Set<String> dataModelCompletions =
SqlCompleter
.getDataModelMetadataCompletions(getJDBCMockObjectFactory().getMockConnection());
sqlCompleter =
new SqlCompleter(Sets.union(keywordsCompletions, dataModelCompletions),
dataModelCompletions);
tester = new CompleterTester(sqlCompleter);
}
@Test
public void testAfterBufferEnd() {
String buffer = "ORDER";
// Up to 2 white spaces after the buffer end, the completer still uses the last argument
tester.buffer(buffer).from(0).to(buffer.length() + 1).expect(newHashSet("ORDER ")).test();
// 2 white spaces or more behind the buffer end the completer returns empty result
tester.buffer(buffer).from(buffer.length() + 2).to(buffer.length() + 5).expect(EMPTY).test();
}
@Test
public void testEdges() {
String buffer = " ORDER ";
tester.buffer(buffer).from(0).to(8).expect(newHashSet("ORDER ")).test();
tester.buffer(buffer).from(9).to(15).expect(EMPTY).test();
}
@Test
public void testMultipleWords() {
String buffer = " SELE fro LIM";
tester.buffer(buffer).from(0).to(6).expect(newHashSet("SELECT ")).test();
tester.buffer(buffer).from(7).to(11).expect(newHashSet("from ")).test();
tester.buffer(buffer).from(12).to(19).expect(newHashSet("LIMIT ")).test();
tester.buffer(buffer).from(20).to(24).expect(EMPTY).test();
}
@Test
public void testMultiLineBuffer() {
String buffer = " \n SELE \n fro";
tester.buffer(buffer).from(0).to(7).expect(newHashSet("SELECT ")).test();
tester.buffer(buffer).from(8).to(14).expect(newHashSet("from ")).test();
tester.buffer(buffer).from(15).to(17).expect(EMPTY).test();
}
@Test
public void testMultipleCompletionSuggestions() {
String buffer = " SU";
tester.buffer(buffer).from(0).to(5).expect(newHashSet("SUBCLASS_ORIGIN", "SUM", "SUBSTRING"))
.test();
tester.buffer(buffer).from(6).to(7).expect(EMPTY).test();
}
@Test
public void testDotDelimiter() {
String buffer = " order.select ";
tester.buffer(buffer).from(4).to(7).expect(newHashSet("order ")).test();
tester.buffer(buffer).from(8).to(15).expect(newHashSet("select ")).test();
tester.buffer(buffer).from(16).to(17).expect(EMPTY).test();
}
@Test
public void testSqlDelimiterCharacters() {
assertTrue(sqlCompleter.getSqlDelimiter().isDelimiterChar("r.", 1));
assertTrue(sqlCompleter.getSqlDelimiter().isDelimiterChar("SS;", 2));
assertTrue(sqlCompleter.getSqlDelimiter().isDelimiterChar(":", 0));
assertTrue(sqlCompleter.getSqlDelimiter().isDelimiterChar("ttt,", 3));
}
public class CompleterTester {
private Completer completer;
private String buffer;
private int fromCursor;
private int toCursor;
private Set<String> expectedCompletions;
public CompleterTester(Completer completer) {
this.completer = completer;
}
public CompleterTester buffer(String buffer) {
this.buffer = buffer;
return this;
}
public CompleterTester from(int fromCursor) {
this.fromCursor = fromCursor;
return this;
}
public CompleterTester to(int toCursor) {
this.toCursor = toCursor;
return this;
}
public CompleterTester expect(Set<String> expectedCompletions) {
this.expectedCompletions = expectedCompletions;
return this;
}
public void test() {
for (int c = fromCursor; c <= toCursor; c++) {
expectedCompletions(buffer, c, expectedCompletions);
}
}
private void expectedCompletions(String buffer, int cursor, Set<String> expected) {
ArrayList<CharSequence> candidates = new ArrayList<CharSequence>();
completer.complete(buffer, cursor, candidates);
String explain = explain(buffer, cursor, candidates);
logger.info(explain);
assertEquals("Buffer [" + buffer.replace(" ", ".") + "] and Cursor[" + cursor + "] "
+ explain, expected, newHashSet(candidates));
}
private String explain(String buffer, int cursor, ArrayList<CharSequence> candidates) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i <= Math.max(cursor, buffer.length()); i++) {
if (i == cursor) {
sb.append("(");
}
if (i >= buffer.length()) {
sb.append("_");
} else {
if (Character.isWhitespace(buffer.charAt(i))) {
sb.append(".");
} else {
sb.append(buffer.charAt(i));
}
}
if (i == cursor) {
sb.append(")");
}
}
sb.append(" >> [").append(Joiner.on(",").join(candidates)).append("]");
return sb.toString();
}
}
}