/* * Copyright (C) 2016 Haruki Hasegawa * * 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.h6ah4i.android.widget.advrecyclerview.adapter; import android.support.v7.widget.RecyclerView; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; public class ItemIdComposerTest { @Rule public ExpectedException thrown = ExpectedException.none(); @Test public void totalBitWidth() { assertThat( ItemIdComposer.BIT_WIDTH_RESERVED_SIGN_FLAG + ItemIdComposer.BIT_WIDTH_SEGMENT + ItemIdComposer.BIT_WIDTH_GROUP_ID + ItemIdComposer.BIT_WIDTH_CHILD_ID, is(64)); } @Test public void bitOffsets() { assertThat(ItemIdComposer.BIT_OFFSET_CHILD_ID, is(0)); assertThat(ItemIdComposer.BIT_OFFSET_GROUP_ID, is(ItemIdComposer.BIT_WIDTH_CHILD_ID + ItemIdComposer.BIT_OFFSET_CHILD_ID)); assertThat(ItemIdComposer.BIT_OFFSET_SEGMENT, is(ItemIdComposer.BIT_WIDTH_GROUP_ID + ItemIdComposer.BIT_OFFSET_GROUP_ID)); assertThat(ItemIdComposer.BIT_OFFSET_RESERVED_SIGN_FLAG, is(ItemIdComposer.BIT_WIDTH_SEGMENT + ItemIdComposer.BIT_OFFSET_SEGMENT)); assertThat(ItemIdComposer.BIT_OFFSET_RESERVED_SIGN_FLAG + ItemIdComposer.BIT_WIDTH_RESERVED_SIGN_FLAG, is(64)); } @Test public void bitMasks() { assertThat( ItemIdComposer.BIT_MASK_RESERVED_SIGN_FLAG, is(genBitMask(ItemIdComposer.BIT_WIDTH_RESERVED_SIGN_FLAG, ItemIdComposer.BIT_OFFSET_RESERVED_SIGN_FLAG))); assertThat( ItemIdComposer.BIT_MASK_SEGMENT, is(genBitMask(ItemIdComposer.BIT_WIDTH_SEGMENT, ItemIdComposer.BIT_OFFSET_SEGMENT))); assertThat( ItemIdComposer.BIT_MASK_GROUP_ID, is(genBitMask(ItemIdComposer.BIT_WIDTH_GROUP_ID, ItemIdComposer.BIT_OFFSET_GROUP_ID))); assertThat( ItemIdComposer.BIT_MASK_CHILD_ID, is(genBitMask(ItemIdComposer.BIT_WIDTH_CHILD_ID, ItemIdComposer.BIT_OFFSET_CHILD_ID))); } @Test public void bitWidthSegment() { assertThat(ItemIdComposer.BIT_WIDTH_SEGMENT, is(ItemViewTypeComposer.BIT_WIDTH_SEGMENT)); } @Test public void minMaxSegment() { assertThat(ItemIdComposer.MIN_SEGMENT, is(0)); assertThat(ItemIdComposer.MAX_SEGMENT, is(unsignedIntMax(ItemIdComposer.BIT_WIDTH_SEGMENT))); } @Test public void minMaxGroupId() { assertThat(ItemIdComposer.MIN_GROUP_ID, is(signedLongMin(ItemIdComposer.BIT_WIDTH_GROUP_ID))); assertThat(ItemIdComposer.MAX_GROUP_ID, is(signedLongMax(ItemIdComposer.BIT_WIDTH_GROUP_ID))); } @Test public void minMaxChildId() { assertThat(ItemIdComposer.MIN_CHILD_ID, is(signedLongMin(ItemIdComposer.BIT_WIDTH_CHILD_ID))); assertThat(ItemIdComposer.MAX_CHILD_ID, is(signedLongMax(ItemIdComposer.BIT_WIDTH_CHILD_ID))); } @Test public void minMaxWrappedId() { assertThat(ItemIdComposer.MIN_WRAPPED_ID, is(signedLongMin(ItemIdComposer.BIT_WIDTH_GROUP_ID + ItemIdComposer.BIT_WIDTH_CHILD_ID))); assertThat(ItemIdComposer.MAX_WRAPPED_ID, is(signedLongMax(ItemIdComposer.BIT_WIDTH_GROUP_ID + ItemIdComposer.BIT_WIDTH_CHILD_ID))); } @Test public void composeExpandableChildId() throws Exception { // zero assertThat(ItemIdComposer.composeExpandableChildId(0L, 0L), is(0L)); // one assertThat(ItemIdComposer.composeExpandableChildId(1L, 0L), is(1L << ItemIdComposer.BIT_OFFSET_GROUP_ID)); assertThat(ItemIdComposer.composeExpandableChildId(0L, 1L), is(1L << ItemIdComposer.BIT_OFFSET_CHILD_ID)); // minus one assertThat(ItemIdComposer.composeExpandableChildId(-1L, 0L), is(ItemIdComposer.BIT_MASK_GROUP_ID)); assertThat(ItemIdComposer.composeExpandableChildId(0L, -1L), is(ItemIdComposer.BIT_MASK_CHILD_ID)); // min assertThat(ItemIdComposer.composeExpandableChildId(ItemIdComposer.MIN_GROUP_ID, 0L), is(genBitMask(1, (ItemIdComposer.BIT_WIDTH_GROUP_ID - 1) + ItemIdComposer.BIT_OFFSET_GROUP_ID))); assertThat(ItemIdComposer.composeExpandableChildId(0L, ItemIdComposer.MIN_CHILD_ID), is(genBitMask(1, (ItemIdComposer.BIT_WIDTH_CHILD_ID - 1) + ItemIdComposer.BIT_OFFSET_CHILD_ID))); // max assertThat(ItemIdComposer.composeExpandableChildId(ItemIdComposer.MAX_GROUP_ID, 0L), is(genBitMask(ItemIdComposer.BIT_WIDTH_GROUP_ID - 1, ItemIdComposer.BIT_OFFSET_GROUP_ID))); assertThat(ItemIdComposer.composeExpandableChildId(0L, ItemIdComposer.MAX_CHILD_ID), is(genBitMask(ItemIdComposer.BIT_WIDTH_CHILD_ID - 1, ItemIdComposer.BIT_OFFSET_CHILD_ID))); } @Test public void composeExpandableChildId_GroupIdMaxOutOfRange() throws Exception { thrown.expect(IllegalArgumentException.class); ItemIdComposer.composeExpandableChildId(ItemIdComposer.MAX_GROUP_ID + 1, 0); } @Test public void composeExpandableChildId_GroupIdMinOutOfRange() throws Exception { thrown.expect(IllegalArgumentException.class); ItemIdComposer.composeExpandableChildId(ItemIdComposer.MIN_GROUP_ID - 1, 0); } @Test public void composeExpandableChildId_ChildIdMaxOutOfRange() throws Exception { thrown.expect(IllegalArgumentException.class); ItemIdComposer.composeExpandableChildId(0, ItemIdComposer.MAX_CHILD_ID + 1); } @Test public void composeExpandableChildId_ChildIdMinOutOfRange() throws Exception { thrown.expect(IllegalArgumentException.class); ItemIdComposer.composeExpandableChildId(0, ItemIdComposer.MIN_CHILD_ID - 1); } @Test public void composeExpandableGroupId() throws Exception { // zero assertThat(ItemIdComposer.composeExpandableGroupId(0L), is((0L << ItemIdComposer.BIT_OFFSET_GROUP_ID) | ItemIdComposer.BIT_MASK_CHILD_ID)); // one assertThat(ItemIdComposer.composeExpandableGroupId(1L), is((1L << ItemIdComposer.BIT_OFFSET_GROUP_ID) | ItemIdComposer.BIT_MASK_CHILD_ID)); // minus one assertThat(ItemIdComposer.composeExpandableGroupId(-1L), is(ItemIdComposer.BIT_MASK_GROUP_ID | ItemIdComposer.BIT_MASK_CHILD_ID)); // min assertThat( ItemIdComposer.composeExpandableGroupId(ItemIdComposer.MIN_GROUP_ID), is(genBitMask(1, (ItemIdComposer.BIT_WIDTH_GROUP_ID - 1) + ItemIdComposer.BIT_OFFSET_GROUP_ID) | ItemIdComposer.BIT_MASK_CHILD_ID)); // max assertThat( ItemIdComposer.composeExpandableGroupId(ItemIdComposer.MAX_GROUP_ID), is(genBitMask(ItemIdComposer.BIT_WIDTH_GROUP_ID - 1, ItemIdComposer.BIT_OFFSET_GROUP_ID) | ItemIdComposer.BIT_MASK_CHILD_ID)); } @Test public void isExpandableGroup() throws Exception { // zero assertThat(ItemIdComposer.isExpandableGroup(0L), is(false)); // NO_ID assertThat(ItemIdComposer.isExpandableGroup(RecyclerView.NO_ID), is(false)); // not group - 1 assertThat(ItemIdComposer.isExpandableGroup(ItemIdComposer.BIT_MASK_CHILD_ID >> 1), is(false)); // not group - 2 assertThat(ItemIdComposer.isExpandableGroup(ItemIdComposer.BIT_MASK_CHILD_ID & ~1), is(false)); // is group - 1 assertThat(ItemIdComposer.isExpandableGroup(ItemIdComposer.BIT_MASK_CHILD_ID), is(true)); // is group - 2 assertThat(ItemIdComposer.isExpandableGroup(ItemIdComposer.BIT_MASK_GROUP_ID | ItemIdComposer.BIT_MASK_CHILD_ID), is(true)); } @Test public void extractSegmentPart() throws Exception { // zero assertThat(ItemIdComposer.extractSegmentPart(0L), is(0)); // one assertThat(ItemIdComposer.extractSegmentPart(1L << ItemIdComposer.BIT_OFFSET_SEGMENT), is(1)); // min assertThat(ItemIdComposer.extractSegmentPart(((long) ItemIdComposer.MIN_SEGMENT) << ItemIdComposer.BIT_OFFSET_SEGMENT), is(ItemIdComposer.MIN_SEGMENT)); // max assertThat(ItemIdComposer.extractSegmentPart(((long) ItemIdComposer.MAX_SEGMENT) << ItemIdComposer.BIT_OFFSET_SEGMENT), is(ItemIdComposer.MAX_SEGMENT)); // etc - 1 assertThat(ItemIdComposer.extractSegmentPart(ItemIdComposer.BIT_MASK_RESERVED_SIGN_FLAG | ItemIdComposer.BIT_MASK_GROUP_ID | ItemIdComposer.BIT_MASK_CHILD_ID), is(0)); // etc - 2 assertThat(ItemIdComposer.extractSegmentPart(ItemIdComposer.BIT_MASK_SEGMENT), is(ItemIdComposer.MAX_SEGMENT)); } @Test public void extractExpandableGroupIdPart() throws Exception { // invalid - 1 assertThat(ItemIdComposer.extractExpandableGroupIdPart(0L), is(RecyclerView.NO_ID)); // invalid - 2 assertThat(ItemIdComposer.extractExpandableGroupIdPart(1), is(RecyclerView.NO_ID)); // invalid - 3 assertThat(ItemIdComposer.extractExpandableGroupIdPart(RecyclerView.NO_ID), is(RecyclerView.NO_ID)); // zero assertThat(ItemIdComposer.extractExpandableGroupIdPart(ItemIdComposer.composeExpandableGroupId(0L)), is(0L)); // one assertThat(ItemIdComposer.extractExpandableGroupIdPart(ItemIdComposer.composeExpandableGroupId(1L)), is(1L)); // minus one assertThat(ItemIdComposer.extractExpandableGroupIdPart(ItemIdComposer.composeExpandableGroupId(-1L)), is(-1L)); // min assertThat(ItemIdComposer.extractExpandableGroupIdPart(ItemIdComposer.composeExpandableGroupId(ItemIdComposer.MIN_GROUP_ID)), is(ItemIdComposer.MIN_GROUP_ID)); // max assertThat(ItemIdComposer.extractExpandableGroupIdPart(ItemIdComposer.composeExpandableGroupId(ItemIdComposer.MAX_GROUP_ID)), is(ItemIdComposer.MAX_GROUP_ID)); // etc - 1 assertThat(ItemIdComposer.extractExpandableGroupIdPart(ItemIdComposer.BIT_MASK_RESERVED_SIGN_FLAG | ItemIdComposer.BIT_MASK_CHILD_ID), is(0L)); // etc - 2 assertThat(ItemIdComposer.extractExpandableGroupIdPart(ItemIdComposer.BIT_MASK_SEGMENT | ItemIdComposer.BIT_MASK_CHILD_ID), is(0L)); } @Test public void extractExpandableChildIdPart() throws Exception { // invalid - 1 assertThat(ItemIdComposer.extractExpandableChildIdPart(ItemIdComposer.composeExpandableGroupId(0L)), is(RecyclerView.NO_ID)); // invalid - 2 assertThat(ItemIdComposer.extractExpandableChildIdPart(RecyclerView.NO_ID), is(RecyclerView.NO_ID)); // zero assertThat(ItemIdComposer.extractExpandableChildIdPart(ItemIdComposer.composeExpandableChildId(0L, 0L)), is(0L)); // one assertThat(ItemIdComposer.extractExpandableChildIdPart(ItemIdComposer.composeExpandableChildId(0L, 1L)), is(1L)); // minus one assertThat(ItemIdComposer.extractExpandableChildIdPart(ItemIdComposer.composeExpandableChildId(0L, -1L)), is(-1L)); // min assertThat(ItemIdComposer.extractExpandableChildIdPart(ItemIdComposer.composeExpandableChildId(0L, ItemIdComposer.MIN_CHILD_ID)), is(ItemIdComposer.MIN_CHILD_ID)); // max assertThat(ItemIdComposer.extractExpandableChildIdPart(ItemIdComposer.composeExpandableChildId(0L, ItemIdComposer.MAX_CHILD_ID)), is(ItemIdComposer.MAX_CHILD_ID)); // etc - 1 assertThat(ItemIdComposer.extractExpandableChildIdPart(ItemIdComposer.BIT_MASK_RESERVED_SIGN_FLAG), is(0L)); // etc - 2 assertThat(ItemIdComposer.extractExpandableChildIdPart(ItemIdComposer.BIT_MASK_SEGMENT), is(0L)); } @Test public void extractWrappedIdPart() throws Exception { // invalid - 1 assertThat(ItemIdComposer.extractWrappedIdPart(RecyclerView.NO_ID), is(RecyclerView.NO_ID)); // zero assertThat(ItemIdComposer.extractWrappedIdPart(0L), is(0L)); // full bits assertThat(ItemIdComposer.extractWrappedIdPart(ItemIdComposer.BIT_MASK_GROUP_ID | ItemIdComposer.BIT_MASK_CHILD_ID), is(-1L)); // etc - 1 assertThat(ItemIdComposer.extractWrappedIdPart(ItemIdComposer.BIT_MASK_RESERVED_SIGN_FLAG), is(0L)); // etc - 2 assertThat(ItemIdComposer.extractWrappedIdPart(ItemIdComposer.BIT_MASK_SEGMENT), is(0L)); } @Test public void composeSegment() throws Exception { // zero assertThat(ItemIdComposer.composeSegment(0, 0L), is(0L)); // one assertThat(ItemIdComposer.composeSegment(1, 0L), is(1L << ItemIdComposer.BIT_OFFSET_SEGMENT)); // min assertThat(ItemIdComposer.composeSegment(ItemIdComposer.MIN_SEGMENT, 0L), is(((long) ItemIdComposer.MIN_SEGMENT) << ItemIdComposer.BIT_OFFSET_SEGMENT)); // max assertThat(ItemIdComposer.composeSegment(ItemIdComposer.MAX_SEGMENT, 0L), is(((long) ItemIdComposer.MAX_SEGMENT) << ItemIdComposer.BIT_OFFSET_SEGMENT)); } @Test public void composeSegment_MinOutOfRange() throws Exception { thrown.expect(IllegalArgumentException.class); //noinspection Range ItemIdComposer.composeSegment(ItemIdComposer.MIN_SEGMENT - 1, 0L); } @Test public void composeSegment_MaxOutOfRange() throws Exception { thrown.expect(IllegalArgumentException.class); //noinspection Range ItemIdComposer.composeSegment(ItemIdComposer.MAX_SEGMENT + 1, 0L); } private static long genBitMask(int width, int offset) { return ((1L << width) - 1) << offset; } private static int unsignedIntMax(int bitWidth) { return (1 << bitWidth) - 1; } private static long signedLongMax(int bitWidth) { return (1L << (bitWidth - 1)) - 1; } private static long signedLongMin(int bitWidth) { return (-1L & ~signedLongMax(bitWidth)); } }