Java tutorial
/* * Copyright 2017 Google LLC * * Licensed 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 com.google.cloud.spanner; import static com.google.common.truth.Truth.assertThat; import com.google.cloud.ByteArray; import com.google.cloud.spanner.spi.v1.SpannerRpc; import com.google.common.io.Resources; import com.google.protobuf.util.JsonFormat; import com.google.spanner.v1.ExecuteSqlRequest.QueryMode; import com.google.spanner.v1.PartialResultSet; import com.google.spanner.v1.Transaction; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import javax.annotation.Nullable; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.junit.Assert; import org.junit.internal.runners.model.EachTestNotifier; import org.junit.runner.Description; import org.junit.runner.notification.RunNotifier; import org.junit.runners.ParentRunner; import org.junit.runners.model.InitializationError; /** Test runner that runs tests specified in json file */ public class ReadFormatTestRunner extends ParentRunner<JSONObject> { private static class NoOpListener implements SpannerImpl.AbstractResultSet.Listener { @Override public void onTransactionMetadata(Transaction transaction) throws SpannerException { } @Override public void onError(SpannerException e) { } @Override public void onDone() { } } public ReadFormatTestRunner(Class<?> clazz) throws InitializationError { super(clazz); } @Override protected Description describeChild(JSONObject child) { try { return Description.createTestDescription(getTestClass().getJavaClass(), child.getString("name")); } catch (JSONException e) { throw new IllegalStateException("Illegal json object: " + child.toString(), e); } } @Override protected void runChild(JSONObject child, RunNotifier notifier) { EachTestNotifier eachNotifier = new EachTestNotifier(notifier, describeChild(child)); eachNotifier.fireTestStarted(); try { new TestCaseRunner(child).run(); eachNotifier.fireTestFinished(); } catch (Exception | AssertionError e) { eachNotifier.addFailure(e); } } @Override protected List<JSONObject> getChildren() { try { List<JSONObject> children = new ArrayList<>(); String jsonStr = Resources.toString(Resources.getResource(this.getClass(), "read_tests.json"), StandardCharsets.UTF_8); JSONObject json = new JSONObject(jsonStr); JSONArray testCases = json.getJSONArray("tests"); for (int i = 0; i < testCases.length(); i++) { JSONObject testCase = testCases.getJSONObject(i); children.add(testCase); } return children; } catch (Exception e) { throw new IllegalStateException(e); } } private class TestCaseRunner { private SpannerImpl.GrpcResultSet resultSet; private SpannerRpc.ResultStreamConsumer consumer; private SpannerImpl.GrpcStreamIterator stream; private JSONObject testCase; TestCaseRunner(JSONObject testCase) { this.testCase = testCase; } private void run() throws Exception { stream = new SpannerImpl.GrpcStreamIterator(10); stream.setCall(new SpannerRpc.StreamingCall() { @Override public void cancel(@Nullable String message) { } @Override public void request(int numMessages) { } }); consumer = stream.consumer(); resultSet = new SpannerImpl.GrpcResultSet(stream, new NoOpListener(), QueryMode.NORMAL); JSONArray chunks = testCase.getJSONArray("chunks"); JSONObject expectedResult = testCase.getJSONObject("result"); for (int i = 0; i < chunks.length(); i++) { PartialResultSet.Builder builder = PartialResultSet.newBuilder(); JsonFormat.parser().merge(chunks.getString(i), builder); consumer.onPartialResultSet(builder.build()); } consumer.onCompleted(); assertResultSet(resultSet, expectedResult.getJSONArray("value")); } private void assertResultSet(SpannerImpl.GrpcResultSet actual, JSONArray expected) throws Exception { int i = 0; while (actual.next()) { Struct actualRow = actual.getCurrentRowAsStruct(); JSONArray expectedRow = expected.getJSONArray(i); assertRow(actualRow, expectedRow); i++; } assertThat(i).isEqualTo(expected.length()); } private void assertRow(Struct actualRow, JSONArray expectedRow) throws Exception { assertThat(actualRow.getColumnCount()).isEqualTo(expectedRow.length()); for (int i = 0; i < expectedRow.length(); i++) { switch (actualRow.getColumnType(i).getCode()) { case BOOL: assertThat(actualRow.getBoolean(i)).isEqualTo(expectedRow.getBoolean(i)); break; case STRING: assertThat(actualRow.getString(i)).isEqualTo(expectedRow.getString(i)); break; case INT64: assertThat(actualRow.getLong(i)).isEqualTo(expectedRow.getLong(i)); break; case FLOAT64: assertThat(actualRow.getDouble(i)).isEqualTo(expectedRow.getDouble(i)); break; case BYTES: assertThat(actualRow.getBytes(i)).isEqualTo(ByteArray.fromBase64(expectedRow.getString(i))); break; case ARRAY: Type elementType = actualRow.getColumnType(i).getArrayElementType(); assertArray(getRawList(actualRow, i, elementType), expectedRow.getJSONArray(i)); break; default: Assert.fail("Unexpected type code:" + actualRow.getColumnType(i).getCode()); } } } private List<?> getRawList(Struct actualRow, int index, Type elementType) throws Exception { List<?> rawList = null; switch (elementType.getCode()) { case BOOL: rawList = actualRow.getBooleanList(index); break; case STRING: rawList = actualRow.getStringList(index); break; case BYTES: rawList = actualRow.getBytesList(index); break; case INT64: rawList = actualRow.getLongList(index); break; case FLOAT64: rawList = actualRow.getDoubleList(index); break; case STRUCT: rawList = actualRow.getStructList(index); break; default: Assert.fail("Unexpected type code:" + elementType.getCode()); } return rawList; } private void assertArray(List<?> actualValues, JSONArray expectedList) throws Exception { assertThat(actualValues.size()).isEqualTo(expectedList.length()); for (int i = 0; i < actualValues.size(); i++) { Object actualValue = actualValues.get(i); if (actualValue == null) { assertThat(expectedList.isNull(i)).isTrue(); } else { if (actualValue instanceof Boolean) { assertThat((Boolean) actualValue).isEqualTo(expectedList.getBoolean(i)); } else if (actualValue instanceof String) { assertThat((String) actualValue).isEqualTo(expectedList.getString(i)); } else if (actualValue instanceof Long) { assertThat((Long) actualValue).isEqualTo(expectedList.getLong(i)); } else if (actualValue instanceof Double) { assertThat((Double) actualValue).isEqualTo(expectedList.getDouble(i)); } else if (actualValue instanceof ByteArray) { assertThat((ByteArray) actualValue) .isEqualTo(ByteArray.fromBase64(expectedList.getString(i))); } else if (actualValue instanceof Struct) { Struct actualStruct = (Struct) actualValue; JSONArray expectedFields = expectedList.getJSONArray(i); assertRow(actualStruct, expectedFields); } } } } } }