/* * 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 hivemall.mix.server; import hivemall.mix.store.PartialResult; import org.junit.Assert; import org.junit.Test; public class PartialResultTest { @Test public void testOverflowUnderflowClock() { // The clock implementation inside PartialResult depends // on the overflow/underflow behavior of short-typed values // in the JVM specification. // Related discussion can be found in a link below; // // How does Java handle integer underflows and overflows and how would you check for it? // - http://stackoverflow.com/questions/3001836/how-does-java-handle-integer-underflows-and-overflows-and-how-would-you-check-fo // short testValue = Short.MAX_VALUE; Assert.assertEquals(Short.MIN_VALUE, ++testValue); Assert.assertEquals(Short.MAX_VALUE, --testValue); // Initially, clock == 0 PartialResult value = new PartialResult() { @Override public void add(float localWeight, float covar, int deltaUpdates, float scale) { incrClock(deltaUpdates); } @Override public void subtract(float localWeight, float covar, int deltaUpdates, float scale) {} @Override public float getWeight(float scale) { return 0.f; } @Override public float getCovariance(float scale) { return 0.f; } }; Assert.assertEquals(0, value.diffClock((short) 0)); Assert.assertEquals(3, value.diffClock((short) -3)); Assert.assertEquals(2, value.diffClock((short) 2)); Assert.assertEquals(32767, value.diffClock(Short.MAX_VALUE)); // Max value of PartialResult#diffClock is 32768 Assert.assertEquals(32768, value.diffClock(Short.MIN_VALUE)); Assert.assertEquals(32767, value.diffClock((short) (Short.MIN_VALUE - 1))); // Proceed the clock by 12 value.add(0.f, 0.f, 12, 1.f); Assert.assertEquals(0, value.diffClock((short) 12)); Assert.assertEquals(7, value.diffClock((short) 5)); Assert.assertEquals(6, value.diffClock((short) 18)); Assert.assertEquals(32767, value.diffClock(addWithUnderOverflow(Short.MAX_VALUE, (short) 12))); // -32757 Assert.assertEquals(32768, value.diffClock(addWithUnderOverflow(Short.MAX_VALUE, (short) 13))); // -32756 Assert.assertEquals(32767, value.diffClock(addWithUnderOverflow(Short.MAX_VALUE, (short) 14))); // -32755 // Overflow test value.add(0.f, 0.f, Short.MAX_VALUE, 1.f); Assert.assertEquals(0, value.diffClock(addWithUnderOverflow(Short.MAX_VALUE, (short) 12))); // -32757 Assert.assertEquals(2, value.diffClock(addWithUnderOverflow(Short.MAX_VALUE, (short) 10))); // -32755 Assert.assertEquals(4, value.diffClock(addWithUnderOverflow(Short.MAX_VALUE, (short) 16))); // -32761 Assert.assertEquals(32767, value.diffClock((short) 10)); Assert.assertEquals(32768, value.diffClock((short) 11)); Assert.assertEquals(32767, value.diffClock((short) 12)); } @Test public void testBoundaries() { Partial partial = new Partial(); partial.setGlobalClock(Short.MAX_VALUE); Assert.assertEquals(0, partial.diffClock(Short.MAX_VALUE)); Assert.assertEquals(1, partial.diffClock(Short.MIN_VALUE)); partial.setGlobalClock((short) (Short.MAX_VALUE + 1)); Assert.assertEquals(Short.MIN_VALUE, partial.getClock()); partial.setGlobalClock((short) (Short.MAX_VALUE - 10)); Assert.assertEquals(21, partial.diffClock((short) (Short.MIN_VALUE + 10))); } public void testDiff() { Partial partial = new Partial(); partial.setGlobalClock((short) 2); Assert.assertEquals(2, partial.diffClock((short) 0)); Assert.assertEquals(4, partial.diffClock((short) -2)); partial.setGlobalClock((short) -2); Assert.assertEquals(2, partial.diffClock((short) 0)); Assert.assertEquals(0, partial.diffClock((short) -2)); Assert.assertEquals(4, partial.diffClock((short) 2)); } private static short addWithUnderOverflow(short value1, short value2) { value1 += value2; return value1; } private static class Partial extends PartialResult { public void setGlobalClock(short global) { this.globalClock = global; } @Override public void add(float localWeight, float covar, int deltaUpdates, float scale) { throw new UnsupportedOperationException(); } @Override public void subtract(float localWeight, float covar, int deltaUpdates, float scale) { throw new UnsupportedOperationException(); } @Override public float getWeight(float scale) { throw new UnsupportedOperationException(); } @Override public float getCovariance(float scale) { throw new UnsupportedOperationException(); } } }