|
| 1 | +/* |
| 2 | + * Copyright 2018 Google LLC |
| 3 | + * |
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | + * you may not use this file except in compliance with the License. |
| 6 | + * You may obtain a copy of the License at |
| 7 | + * |
| 8 | + * https://www.apache.org/licenses/LICENSE-2.0 |
| 9 | + * |
| 10 | + * Unless required by applicable law or agreed to in writing, software |
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | + * See the License for the specific language governing permissions and |
| 14 | + * limitations under the License. |
| 15 | + */ |
| 16 | +package com.google.cloud.bigtable.data.v2.stub.readrows; |
| 17 | + |
| 18 | +import static com.google.common.truth.Truth.assertThat; |
| 19 | +import static com.google.common.truth.Truth.assertWithMessage; |
| 20 | + |
| 21 | +import com.google.api.gax.rpc.ServerStream; |
| 22 | +import com.google.api.gax.rpc.ServerStreamingCallable; |
| 23 | +import com.google.bigtable.v2.ReadRowsRequest; |
| 24 | +import com.google.bigtable.v2.ReadRowsResponse; |
| 25 | +import com.google.bigtable.v2.ReadRowsResponse.CellChunk; |
| 26 | +import com.google.cloud.bigtable.data.v2.models.DefaultRowAdapter; |
| 27 | +import com.google.cloud.bigtable.data.v2.models.Row; |
| 28 | +import com.google.cloud.bigtable.data.v2.models.RowCell; |
| 29 | +import com.google.cloud.bigtable.gaxx.testing.FakeStreamingApi.ServerStreamingStashCallable; |
| 30 | +import com.google.cloud.conformance.bigtable.v2.TestDefinition.ReadRowsTest; |
| 31 | +import com.google.cloud.conformance.bigtable.v2.TestDefinition.TestFile; |
| 32 | +import com.google.common.base.CaseFormat; |
| 33 | +import com.google.common.collect.Lists; |
| 34 | +import com.google.protobuf.util.JsonFormat; |
| 35 | +import java.io.IOException; |
| 36 | +import java.io.InputStream; |
| 37 | +import java.io.InputStreamReader; |
| 38 | +import java.util.ArrayList; |
| 39 | +import java.util.Collection; |
| 40 | +import java.util.List; |
| 41 | +import org.junit.Test; |
| 42 | +import org.junit.runner.RunWith; |
| 43 | +import org.junit.runners.Parameterized; |
| 44 | +import org.junit.runners.Parameterized.Parameters; |
| 45 | + |
| 46 | +/** Parses and runs the acceptance tests for read rows */ |
| 47 | +@RunWith(Parameterized.class) |
| 48 | +public class ReadRowsMergingAcceptanceTest { |
| 49 | + private static final String TEST_DATA_JSON_RESOURCE = |
| 50 | + "com/google/cloud/conformance/bigtable/v2/readrows.json"; |
| 51 | + |
| 52 | + private final ReadRowsTest testCase; |
| 53 | + |
| 54 | + /** |
| 55 | + * @param testData The serialized test data representing the test case. |
| 56 | + * @param junitName Not used by the test, but used by the parameterized test runner as the name of |
| 57 | + * the test. |
| 58 | + */ |
| 59 | + public ReadRowsMergingAcceptanceTest( |
| 60 | + ReadRowsTest testData, @SuppressWarnings("unused") String junitName) { |
| 61 | + this.testCase = testData; |
| 62 | + } |
| 63 | + |
| 64 | + // Each tuple consists of [testData: ReadRowsTest, junitName: String] |
| 65 | + @Parameters(name = "{1}") |
| 66 | + public static Collection<Object[]> data() throws IOException { |
| 67 | + ClassLoader cl = Thread.currentThread().getContextClassLoader(); |
| 68 | + InputStream dataJson = cl.getResourceAsStream(TEST_DATA_JSON_RESOURCE); |
| 69 | + assertWithMessage("Unable to load test definition: %s", TEST_DATA_JSON_RESOURCE) |
| 70 | + .that(dataJson) |
| 71 | + .isNotNull(); |
| 72 | + |
| 73 | + InputStreamReader reader = new InputStreamReader(dataJson); |
| 74 | + TestFile.Builder testBuilder = TestFile.newBuilder(); |
| 75 | + JsonFormat.parser().merge(reader, testBuilder); |
| 76 | + TestFile testDefinition = testBuilder.build(); |
| 77 | + |
| 78 | + List<ReadRowsTest> tests = testDefinition.getReadRowsTestsList(); |
| 79 | + ArrayList<Object[]> data = new ArrayList<>(tests.size()); |
| 80 | + for (ReadRowsTest test : tests) { |
| 81 | + String junitName = |
| 82 | + CaseFormat.LOWER_HYPHEN.to( |
| 83 | + CaseFormat.LOWER_CAMEL, test.getDescription().replace(" ", "-")); |
| 84 | + data.add(new Object[] {test, junitName}); |
| 85 | + } |
| 86 | + return data; |
| 87 | + } |
| 88 | + |
| 89 | + @Test |
| 90 | + public void test() throws Exception { |
| 91 | + List<ReadRowsResponse> responses = Lists.newArrayList(); |
| 92 | + |
| 93 | + // Convert the chunks into a single ReadRowsResponse |
| 94 | + for (CellChunk chunk : testCase.getChunksList()) { |
| 95 | + ReadRowsResponse.Builder responseBuilder = ReadRowsResponse.newBuilder(); |
| 96 | + responseBuilder.addChunks(chunk); |
| 97 | + responses.add(responseBuilder.build()); |
| 98 | + } |
| 99 | + |
| 100 | + // Wrap the responses in a callable |
| 101 | + ServerStreamingCallable<ReadRowsRequest, ReadRowsResponse> source = |
| 102 | + new ServerStreamingStashCallable<>(responses); |
| 103 | + RowMergingCallable<Row> mergingCallable = |
| 104 | + new RowMergingCallable<>(source, new DefaultRowAdapter()); |
| 105 | + |
| 106 | + // Invoke the callable to get the merged rows |
| 107 | + ServerStream<Row> stream = mergingCallable.call(ReadRowsRequest.getDefaultInstance()); |
| 108 | + |
| 109 | + // Read all of the rows and transform them into logical cells |
| 110 | + List<ReadRowsTest.Result> actualResults = Lists.newArrayList(); |
| 111 | + Exception error = null; |
| 112 | + |
| 113 | + try { |
| 114 | + for (Row row : stream) { |
| 115 | + for (RowCell cell : row.getCells()) { |
| 116 | + actualResults.add( |
| 117 | + ReadRowsTest.Result.newBuilder() |
| 118 | + .setRowKeyBytes(row.getKey()) |
| 119 | + .setFamilyName(cell.getFamily()) |
| 120 | + .setQualifierBytes(cell.getQualifier()) |
| 121 | + .setTimestampMicros(cell.getTimestamp()) |
| 122 | + .setValueBytes(cell.getValue()) |
| 123 | + .setLabel(cell.getLabels().isEmpty() ? "" : cell.getLabels().get(0)) |
| 124 | + .build()); |
| 125 | + } |
| 126 | + } |
| 127 | + } catch (Exception e) { |
| 128 | + error = e; |
| 129 | + } |
| 130 | + |
| 131 | + // Verify the results |
| 132 | + if (expectsError(testCase)) { |
| 133 | + assertThat(error).isNotNull(); |
| 134 | + } else { |
| 135 | + if (error != null) { |
| 136 | + throw error; |
| 137 | + } |
| 138 | + } |
| 139 | + |
| 140 | + assertThat(getNonExceptionResults(testCase)).isEqualTo(actualResults); |
| 141 | + } |
| 142 | + |
| 143 | + private static boolean expectsError(ReadRowsTest rrt) { |
| 144 | + List<ReadRowsTest.Result> results = rrt.getResultsList(); |
| 145 | + return results != null && !results.isEmpty() && results.get(results.size() - 1).getError(); |
| 146 | + } |
| 147 | + |
| 148 | + private static List<ReadRowsTest.Result> getNonExceptionResults(ReadRowsTest rrt) { |
| 149 | + List<ReadRowsTest.Result> results = rrt.getResultsList(); |
| 150 | + |
| 151 | + List<ReadRowsTest.Result> response = new ArrayList<>(); |
| 152 | + if (results != null) { |
| 153 | + for (ReadRowsTest.Result result : results) { |
| 154 | + if (!result.getError()) { |
| 155 | + response.add(result); |
| 156 | + } |
| 157 | + } |
| 158 | + } |
| 159 | + return response; |
| 160 | + } |
| 161 | +} |
0 commit comments