/* * 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.flink.runtime.memory; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.nio.ByteBuffer; import java.util.Random; import org.apache.flink.core.memory.MemorySegmentFactory; import org.apache.flink.core.memory.MemoryType; import org.apache.flink.runtime.operators.testutils.DummyInvokable; import org.apache.flink.core.memory.MemorySegment; import org.junit.Assert; import org.junit.After; import org.junit.Before; import org.junit.Test; public class MemorySegmentSimpleTest { public static final long RANDOM_SEED = 643196033469871L; public static final int MANAGED_MEMORY_SIZE = 1024 * 1024 * 16; public static final int PAGE_SIZE = 1024 * 512; private MemoryManager manager; private MemorySegment segment; private Random random; @Before public void setUp() throws Exception{ try { this.manager = new MemoryManager(MANAGED_MEMORY_SIZE, 1, PAGE_SIZE, MemoryType.HEAP, true); this.segment = manager.allocatePages(new DummyInvokable(), 1).get(0); this.random = new Random(RANDOM_SEED); } catch (Exception e) { e.printStackTrace(); fail("Test setup failed."); } } @After public void tearDown() { this.manager.release(this.segment); this.random = null; this.segment = null; if (!this.manager.verifyEmpty()) { Assert.fail("Not all memory has been properly released."); } this.manager = null; } @Test public void bulkByteAccess() { // test exceptions { byte[] bytes = new byte[PAGE_SIZE / 4]; try { segment.put(3 * (PAGE_SIZE / 4) + 1, bytes); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } try { segment.put(7 * (PAGE_SIZE / 8) + 1, bytes, 0, bytes.length / 2); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } } // test expected correct behavior with default offset / length { long seed = random.nextLong(); random.setSeed(seed); byte[] src = new byte[PAGE_SIZE / 8]; for (int i = 0; i < 8; i++) { random.nextBytes(src); segment.put(i * (PAGE_SIZE / 8), src); } random.setSeed(seed); byte[] expected = new byte[PAGE_SIZE / 8]; byte[] actual = new byte[PAGE_SIZE / 8]; for (int i = 0; i < 8; i++) { random.nextBytes(expected); segment.get(i * (PAGE_SIZE / 8), actual); assertArrayEquals(expected, actual); } } // test expected correct behavior with specific offset / length { byte[] expected = new byte[PAGE_SIZE]; random.nextBytes(expected); for (int i = 0; i < 16; i++) { segment.put(i * (PAGE_SIZE / 16), expected, i * (PAGE_SIZE / 16), PAGE_SIZE / 16); } byte[] actual = new byte[PAGE_SIZE]; for (int i = 0; i < 16; i++) { segment.get(i * (PAGE_SIZE / 16), actual, i * (PAGE_SIZE / 16), PAGE_SIZE / 16); } assertArrayEquals(expected, actual); } } @Test public void byteAccess() { // test exceptions { try { segment.put(-1, (byte) 0); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } try { segment.put(PAGE_SIZE, (byte) 0); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } try { segment.get(-1); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } try { segment.get(PAGE_SIZE); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } } // test expected correct behavior { long seed = random.nextLong(); random.setSeed(seed); for (int i = 0; i < PAGE_SIZE; i++) { segment.put(i, (byte) random.nextInt()); } random.setSeed(seed); for (int i = 0; i < PAGE_SIZE; i++) { assertEquals((byte) random.nextInt(), segment.get(i)); } } } @Test public void booleanAccess() { // test exceptions { try { segment.putBoolean(-1, false); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } try { segment.putBoolean(PAGE_SIZE, false); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } try { segment.getBoolean(-1); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } try { segment.getBoolean(PAGE_SIZE); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } } // test expected correct behavior { long seed = random.nextLong(); random.setSeed(seed); for (int i = 0; i < PAGE_SIZE; i++) { segment.putBoolean(i, random.nextBoolean()); } random.setSeed(seed); for (int i = 0; i < PAGE_SIZE; i++) { assertEquals(random.nextBoolean(), segment.getBoolean(i)); } } } @Test public void charAccess() { // test exceptions { try { segment.putChar(-1, 'a'); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } try { segment.putChar(PAGE_SIZE, 'a'); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } try { segment.getChar(-1); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } try { segment.getChar(PAGE_SIZE); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } } // test expected correct behavior { long seed = random.nextLong(); random.setSeed(seed); for (int i = 0; i <= PAGE_SIZE - 2; i += 2) { segment.putChar(i, (char) ('a' + random.nextInt(26))); } random.setSeed(seed); for (int i = 0; i <= PAGE_SIZE - 2; i += 2) { assertEquals((char) ('a' + random.nextInt(26)), segment.getChar(i)); } } } @Test public void doubleAccess() { // test exceptions { try { segment.putDouble(-1, 0.0); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } try { segment.putDouble(PAGE_SIZE, 0.0); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } try { segment.getDouble(-1); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } try { segment.getDouble(PAGE_SIZE); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } } // test expected correct behavior { long seed = random.nextLong(); random.setSeed(seed); for (int i = 0; i <= PAGE_SIZE - 8; i += 8) { segment.putDouble(i, random.nextDouble()); } random.setSeed(seed); for (int i = 0; i <= PAGE_SIZE - 8; i += 8) { assertEquals(random.nextDouble(), segment.getDouble(i), 0.0); } } } // @Test public void floatAccess() { // test exceptions { try { segment.putFloat(-1, 0.0f); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } try { segment.putFloat(PAGE_SIZE, 0.0f); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } try { segment.getFloat(-1); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } try { segment.getFloat(PAGE_SIZE); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } } // test expected correct behavior { long seed = random.nextLong(); random.setSeed(seed); for (int i = 0; i <= PAGE_SIZE - 4; i += 4) { segment.putFloat(i, random.nextFloat()); } random.setSeed(seed); for (int i = 0; i <= PAGE_SIZE - 4; i += 4) { assertEquals(random.nextFloat(), segment.getFloat(i), 0.0); } } } @Test public void longAccess() { // test exceptions { try { segment.putLong(-1, 0L); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } try { segment.putLong(PAGE_SIZE, 0L); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } try { segment.getLong(-1); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } try { segment.getLong(PAGE_SIZE); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } } // test expected correct behavior { long seed = random.nextLong(); random.setSeed(seed); for (int i = 0; i <= PAGE_SIZE - 8; i += 8) { segment.putLong(i, random.nextLong()); } random.setSeed(seed); for (int i = 0; i <= PAGE_SIZE - 8; i += 8) { assertEquals(random.nextLong(), segment.getLong(i)); } } // test unaligned offsets { final long seed = random.nextLong(); random.setSeed(seed); for (int offset = 0; offset < PAGE_SIZE - 8; offset += random.nextInt(24) + 8) { long value = random.nextLong(); segment.putLong(offset, value); } random.setSeed(seed); for (int offset = 0; offset < PAGE_SIZE - 8; offset += random.nextInt(24) + 8) { long shouldValue = random.nextLong(); long isValue = segment.getLong(offset); assertEquals(shouldValue, isValue); } } } @Test public void intAccess() { // test exceptions { try { segment.putInt(-1, 0); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } try { segment.putInt(PAGE_SIZE, 0); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } try { segment.getInt(-1); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } try { segment.getInt(PAGE_SIZE); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } } // test expected correct behavior { long seed = random.nextLong(); random.setSeed(seed); for (int i = 0; i <= PAGE_SIZE - 4; i += 4) { segment.putInt(i, random.nextInt()); } random.setSeed(seed); for (int i = 0; i <= PAGE_SIZE - 4; i += 4) { assertEquals(random.nextInt(), segment.getInt(i)); } } } @Test public void shortAccess() { // test exceptions { try { segment.putShort(-1, (short) 0); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } try { segment.putShort(PAGE_SIZE, (short) 0); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } try { segment.getShort(-1); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } try { segment.getShort(PAGE_SIZE); fail("IndexOutOfBoundsException expected"); } catch (Exception e) { assertTrue(e instanceof IndexOutOfBoundsException); } } // test expected correct behavior { long seed = random.nextLong(); random.setSeed(seed); for (int i = 0; i <= PAGE_SIZE - 2; i += 2) { segment.putShort(i, (short) random.nextInt()); } random.setSeed(seed); for (int i = 0; i <= PAGE_SIZE - 2; i += 2) { assertEquals((short) random.nextInt(), segment.getShort(i)); } } } @Test public void testByteBufferWrapping() { try { MemorySegment seg = MemorySegmentFactory.allocateUnpooledSegment(1024); ByteBuffer buf1 = seg.wrap(13, 47); assertEquals(13, buf1.position()); assertEquals(60, buf1.limit()); assertEquals(47, buf1.remaining()); ByteBuffer buf2 = seg.wrap(500, 267); assertEquals(500, buf2.position()); assertEquals(767, buf2.limit()); assertEquals(267, buf2.remaining()); ByteBuffer buf3 = seg.wrap(0, 1024); assertEquals(0, buf3.position()); assertEquals(1024, buf3.limit()); assertEquals(1024, buf3.remaining()); } catch (Exception e) { e.printStackTrace(); Assert.fail(e.getMessage()); } } }