Add BigIntegerCoder and tests

Project: http://git-wip-us.apache.org/repos/asf/incubator-beam/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-beam/commit/8268f1d7
Tree: http://git-wip-us.apache.org/repos/asf/incubator-beam/tree/8268f1d7
Diff: http://git-wip-us.apache.org/repos/asf/incubator-beam/diff/8268f1d7

Branch: refs/heads/python-sdk
Commit: 8268f1d7ffdd1205a1904037f7dd1e1887a52f8d
Parents: 6460df1
Author: Kenneth Knowles <[email protected]>
Authored: Thu Jun 9 13:24:49 2016 -0700
Committer: Davor Bonaci <[email protected]>
Committed: Mon Jun 20 15:14:30 2016 -0700

----------------------------------------------------------------------
 .../apache/beam/sdk/coders/BigIntegerCoder.java |  91 ++++++++++++++
 .../beam/sdk/coders/BigIntegerCoderTest.java    | 119 +++++++++++++++++++
 2 files changed, 210 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-beam/blob/8268f1d7/sdks/java/core/src/main/java/org/apache/beam/sdk/coders/BigIntegerCoder.java
----------------------------------------------------------------------
diff --git 
a/sdks/java/core/src/main/java/org/apache/beam/sdk/coders/BigIntegerCoder.java 
b/sdks/java/core/src/main/java/org/apache/beam/sdk/coders/BigIntegerCoder.java
new file mode 100644
index 0000000..a41defe
--- /dev/null
+++ 
b/sdks/java/core/src/main/java/org/apache/beam/sdk/coders/BigIntegerCoder.java
@@ -0,0 +1,91 @@
+/*
+ * 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.beam.sdk.coders;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.math.BigInteger;
+
+/**
+ * A {@link BigIntegerCoder} encodes a {@link BigInteger} as a byte array 
containing the big endian
+ * two's-complement representation, encoded via {@link ByteArrayCoder}.
+ */
+public class BigIntegerCoder extends AtomicCoder<BigInteger> {
+
+  @JsonCreator
+  public static BigIntegerCoder of() {
+    return INSTANCE;
+  }
+
+  /////////////////////////////////////////////////////////////////////////////
+
+  private static final BigIntegerCoder INSTANCE = new BigIntegerCoder();
+
+  private BigIntegerCoder() {}
+
+  private final ByteArrayCoder byteArrayCoder = ByteArrayCoder.of();
+
+  @Override
+  public void encode(BigInteger value, OutputStream outStream, Context context)
+      throws IOException, CoderException {
+    checkNotNull(value, String.format("cannot encode a null %s", 
BigInteger.class.getSimpleName()));
+    byteArrayCoder.encode(value.toByteArray(), outStream, context);
+  }
+
+  @Override
+  public BigInteger decode(InputStream inStream, Context context)
+      throws IOException, CoderException {
+    return new BigInteger(byteArrayCoder.decode(inStream, context));
+  }
+
+  /**
+   * {@inheritDoc}
+   *
+   * @return {@code true}. This coder is injective.
+   */
+  @Override
+  public boolean consistentWithEquals() {
+    return true;
+  }
+
+  /**
+   * {@inheritDoc}
+   *
+   * @return {@code true}, because {@link #getEncodedElementByteSize} runs in 
constant time.
+   */
+  @Override
+  public boolean isRegisterByteSizeObserverCheap(BigInteger value, Context 
context) {
+    return true;
+  }
+
+  /**
+   * {@inheritDoc}
+   *
+   * @return the size of the encoding as a byte array according to {@link 
ByteArrayCoder}
+   */
+  @Override
+  protected long getEncodedElementByteSize(BigInteger value, Context context) 
throws Exception {
+    checkNotNull(value, String.format("cannot encode a null %s", 
BigInteger.class.getSimpleName()));
+    return byteArrayCoder.getEncodedElementByteSize(value.toByteArray(), 
context);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-beam/blob/8268f1d7/sdks/java/core/src/test/java/org/apache/beam/sdk/coders/BigIntegerCoderTest.java
----------------------------------------------------------------------
diff --git 
a/sdks/java/core/src/test/java/org/apache/beam/sdk/coders/BigIntegerCoderTest.java
 
b/sdks/java/core/src/test/java/org/apache/beam/sdk/coders/BigIntegerCoderTest.java
new file mode 100644
index 0000000..3934b03
--- /dev/null
+++ 
b/sdks/java/core/src/test/java/org/apache/beam/sdk/coders/BigIntegerCoderTest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.beam.sdk.coders;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+import org.apache.beam.sdk.testing.CoderProperties;
+import org.apache.beam.sdk.util.CoderUtils;
+import org.apache.beam.sdk.util.common.Counter;
+import org.apache.beam.sdk.util.common.Counter.AggregationKind;
+import org.apache.beam.sdk.util.common.CounterName;
+import org.apache.beam.sdk.util.common.ElementByteSizeObserver;
+
+import com.google.common.collect.ImmutableList;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.math.BigInteger;
+import java.util.List;
+
+/**
+ * Test case for {@link BigIntegerCoder}.
+ */
+@RunWith(JUnit4.class)
+public class BigIntegerCoderTest {
+
+  @Rule public ExpectedException thrown = ExpectedException.none();
+
+  private static final Coder<BigInteger> TEST_CODER = BigIntegerCoder.of();
+
+  private static final List<BigInteger> TEST_VALUES =
+      ImmutableList.of(
+          
BigInteger.valueOf(Integer.MIN_VALUE).subtract(BigInteger.valueOf(Integer.MAX_VALUE)),
+          BigInteger.valueOf(Integer.MIN_VALUE).subtract(BigInteger.ONE),
+          BigInteger.valueOf(-1),
+          BigInteger.ZERO,
+          BigInteger.valueOf(1),
+          BigInteger.valueOf(Integer.MAX_VALUE).add(BigInteger.ONE),
+          BigInteger.valueOf(Integer.MAX_VALUE).multiply(BigInteger.TEN));
+
+  @Test
+  public void testDecodeEncodeEqual() throws Exception {
+    for (BigInteger value : TEST_VALUES) {
+      CoderProperties.coderDecodeEncodeEqual(TEST_CODER, value);
+    }
+  }
+
+  // This should never change. The definition of big endian encoding is fixed.
+  private static final String EXPECTED_ENCODING_ID = "";
+
+  @Test
+  public void testEncodingId() throws Exception {
+    CoderProperties.coderHasEncodingId(TEST_CODER, EXPECTED_ENCODING_ID);
+  }
+
+  /**
+   * Generated data to check that the wire format has not changed. To 
regenerate, see
+   * {@link org.apache.beam.sdk.coders.PrintBase64Encodings}.
+   */
+  private static final List<String> TEST_ENCODINGS =
+      ImmutableList.of("_wAAAAE", "_3____8", "_w", "AA", "AQ", "AIAAAAA", 
"BP____Y");
+
+  @Test
+  public void testWireFormatEncode() throws Exception {
+    CoderProperties.coderEncodesBase64(TEST_CODER, TEST_VALUES, 
TEST_ENCODINGS);
+  }
+
+  @Test
+  public void testGetEncodedElementByteSize() throws Exception {
+    Counter<Long> counter = Counter.longs(CounterName.named("dummy"), 
AggregationKind.SUM);
+    ElementByteSizeObserver observer = new ElementByteSizeObserver(counter);
+    for (BigInteger value : TEST_VALUES) {
+      TEST_CODER.registerByteSizeObserver(value, observer, 
Coder.Context.OUTER);
+      observer.advance();
+      assertThat(
+          counter.getAggregate(),
+          equalTo((long) CoderUtils.encodeToByteArray(TEST_CODER, 
value).length));
+      counter.resetToValue(0L);
+    }
+  }
+
+  @Test
+  public void encodeNullThrowsCoderException() throws Exception {
+    thrown.expect(NullPointerException.class);
+    thrown.expectMessage("cannot encode a null BigInteger");
+
+    CoderUtils.encodeToBase64(TEST_CODER, null);
+  }
+
+  /**
+   * This is a change-detector test. If this test fails, then the encoding id 
of
+   * {@link BigIntegerCoder} must change.
+   */
+  @Test
+  public void testCoderIdDependencies() {
+    assertThat(VarIntCoder.of().getEncodingId(), equalTo(""));
+    assertThat(ByteArrayCoder.of().getEncodingId(), equalTo(""));
+  }
+}

Reply via email to