/* * 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.kylin; import static org.junit.Assert.assertEquals; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Locale; import java.util.Properties; import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.ProtocolVersion; import org.apache.http.StatusLine; import org.apache.http.client.methods.HttpPost; import org.apache.http.message.AbstractHttpMessage; import org.apache.zeppelin.interpreter.InterpreterResult; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; public class KylinInterpreterTest { static final Properties kylinProperties = new Properties(); @BeforeClass public static void setUpClass() { kylinProperties.put("kylin.api.url", "http://localhost:7070/kylin/api/query"); kylinProperties.put("kylin.api.user", "ADMIN"); kylinProperties.put("kylin.api.password", "KYLIN"); kylinProperties.put("kylin.query.project", "default"); kylinProperties.put("kylin.query.offset", "0"); kylinProperties.put("kylin.query.limit", "5000"); kylinProperties.put("kylin.query.ispartial", "true"); } @Test public void testWithDefault() { KylinInterpreter t = new MockKylinInterpreter(getDefaultProperties()); InterpreterResult result = t.interpret( "select a.date,sum(b.measure) as measure from kylin_fact_table a " + "inner join kylin_lookup_table b on a.date=b.date group by a.date", null); assertEquals("default", t.getProject("select a.date,sum(b.measure) as measure " + "from kylin_fact_table a inner join kylin_lookup_table b on a.date=b.date group by a.date")); assertEquals(InterpreterResult.Type.TABLE,result.message().get(0).getType()); } @Test public void testWithProject() { KylinInterpreter t = new MockKylinInterpreter(getDefaultProperties()); assertEquals("project2", t.getProject("(project2)\n select a.date,sum(b.measure) as measure " + "from kylin_fact_table a inner join kylin_lookup_table b on a.date=b.date group by a.date")); assertEquals("", t.getProject("()\n select a.date,sum(b.measure) as measure " + "from kylin_fact_table a inner join kylin_lookup_table b on a.date=b.date group by a.date")); assertEquals("\n select a.date,sum(b.measure) as measure from kylin_fact_table a inner join " + "kylin_lookup_table b on a.date=b.date group by a.date", t.getSQL("(project2)\n select a.date," + "sum(b.measure) as measure from kylin_fact_table a inner join kylin_lookup_table b on a.date=b.date " + "group by a.date")); assertEquals("\n select a.date,sum(b.measure) as measure from kylin_fact_table a inner join kylin_lookup_table b " + "on a.date=b.date group by a.date", t.getSQL("()\n select a.date,sum(b.measure) as measure " + "from kylin_fact_table a inner join kylin_lookup_table b on a.date=b.date group by a.date")); } @Test public void testParseResult() { String msg = "{\"columnMetas\":[{\"isNullable\":1,\"displaySize\":256,\"label\":\"COUNTRY\",\"name\":\"COUNTRY\"," + "\"schemaName\":\"DEFAULT\",\"catelogName\":null,\"tableName\":\"SALES_TABLE\",\"precision\":256," + "\"scale\":0,\"columnType\":12,\"columnTypeName\":\"VARCHAR\",\"writable\":false,\"readOnly\":true," + "\"definitelyWritable\":false,\"autoIncrement\":false,\"caseSensitive\":true,\"searchable\":false," + "\"currency\":false,\"signed\":true},{\"isNullable\":1,\"displaySize\":256,\"label\":\"CURRENCY\"," + "\"name\":\"CURRENCY\",\"schemaName\":\"DEFAULT\",\"catelogName\":null,\"tableName\":\"SALES_TABLE\"," + "\"precision\":256,\"scale\":0,\"columnType\":12,\"columnTypeName\":\"VARCHAR\",\"writable\":false," + "\"readOnly\":true,\"definitelyWritable\":false,\"autoIncrement\":false,\"caseSensitive\":true," + "\"searchable\":false,\"currency\":false,\"signed\":true},{\"isNullable\":0,\"displaySize\":19," + "\"label\":\"COUNT__\",\"name\":\"COUNT__\",\"schemaName\":\"DEFAULT\",\"catelogName\":null," + "\"tableName\":\"SALES_TABLE\",\"precision\":19,\"scale\":0,\"columnType\":-5,\"columnTypeName\":" + "\"BIGINT\",\"writable\":false,\"readOnly\":true,\"definitelyWritable\":false,\"autoIncrement\":false," + "\"caseSensitive\":true,\"searchable\":false,\"currency\":false,\"signed\":true}],\"results\":" + "[[\"AMERICA\",\"USD\",null],[null,\"RMB\",0],[\"KOR\",null,100],[\"\\\"abc\\\"\",\"a,b,c\",-1]]," + "\"cube\":\"Sample_Cube\",\"affectedRowCount\":0,\"isException\":false,\"exceptionMessage\":null," + "\"duration\":134,\"totalScanCount\":1,\"hitExceptionCache\":false,\"storageCacheUsed\":false," + "\"partial\":false}"; String expected="%table COUNTRY \tCURRENCY \tCOUNT__ \t \n" + "AMERICA \tUSD \tnull \t \n" + "null \tRMB \t0 \t \n" + "KOR \tnull \t100 \t \n" + "\\\"abc\\\" \ta,b,c \t-1 \t \n"; KylinInterpreter t = new MockKylinInterpreter(getDefaultProperties()); String actual = t.formatResult(msg); Assert.assertEquals(expected, actual); } private Properties getDefaultProperties() { Properties prop = new Properties(); prop.put("kylin.api.username", "ADMIN"); prop.put("kylin.api.password", "KYLIN"); prop.put("kylin.api.url", "http://<host>:<port>/kylin/api/query"); prop.put("kylin.query.project", "default"); prop.put("kylin.query.offset", "0"); prop.put("kylin.query.limit", "5000"); prop.put("kylin.query.ispartial", "true"); return prop; } } class MockKylinInterpreter extends KylinInterpreter { public MockKylinInterpreter(Properties property) { super(property); } @Override public HttpResponse prepareRequest(String sql) throws IOException { MockHttpClient client = new MockHttpClient(); return client.execute(new HttpPost()); } } class MockHttpClient{ public MockHttpResponse execute(HttpPost post){ return new MockHttpResponse(); } } class MockHttpResponse extends AbstractHttpMessage implements HttpResponse{ @Override public StatusLine getStatusLine() { return new MockStatusLine(); } @Override public void setStatusLine(StatusLine statusLine) { } @Override public void setStatusLine(ProtocolVersion protocolVersion, int i) { } @Override public void setStatusLine(ProtocolVersion protocolVersion, int i, String s) { } @Override public void setStatusCode(int i) throws IllegalStateException { } @Override public void setReasonPhrase(String s) throws IllegalStateException { } @Override public HttpEntity getEntity() { return new MockEntity(); } @Override public void setEntity(HttpEntity httpEntity) { } @Override public Locale getLocale() { return null; } @Override public void setLocale(Locale locale) { } @Override public ProtocolVersion getProtocolVersion() { return null; } } class MockStatusLine implements StatusLine{ @Override public ProtocolVersion getProtocolVersion() { return null; } @Override public int getStatusCode() { return 200; } @Override public String getReasonPhrase() { return null; } } class MockEntity implements HttpEntity{ @Override public boolean isRepeatable() { return false; } @Override public boolean isChunked() { return false; } @Override public long getContentLength() { return 0; } @Override public Header getContentType() { return null; } @Override public Header getContentEncoding() { return null; } @Override public InputStream getContent() throws IOException, IllegalStateException { return new ByteArrayInputStream(("{\"columnMetas\":" + "[{\"label\":\"PART_DT\"},{\"label\":\"measure\"}]," + "\"results\":[[\"2012-01-03\",\"917.4138\"]," + "[\"2012-05-06\",\"592.4823\"]]}").getBytes()); } @Override public void writeTo(OutputStream outputStream) throws IOException { } @Override public boolean isStreaming() { return false; } @Override public void consumeContent() throws IOException { } }