### Question:
HexFunnel implements Funnel<CharSequence> { @Override public void funnel(@Nonnull final CharSequence from, @Nonnull final PrimitiveSink into) { final byte[] decoded = convertHex(from); if (decoded != null) { into.putBytes(decoded, 0, size); } else { fallbackFunnel.funnel(from, into); } } HexFunnel(@Nonnull final Funnel<CharSequence> fallbackFunnel);  HexFunnel(); @Override void funnel(@Nonnull final CharSequence from, @Nonnull final PrimitiveSink into);  }### Answer:
@Test public void shouldConvertHexString() { funnel.funnel("01AbcD", sink); final ArgumentCaptor<byte[]> argumentCaptor = ArgumentCaptor.forClass(byte[].class); verify(sink).putBytes(argumentCaptor.capture(), eq(0), eq(3)); assertThat(argumentCaptor.getValue()).startsWith(1, 0xab, 0xcd); verifyNoMoreInteractions(sink); }
@Test public void shouldConvertEmptyString() { funnel.funnel("", sink); final ArgumentCaptor<byte[]> argumentCaptor = ArgumentCaptor.forClass(byte[].class); verify(sink).putBytes(argumentCaptor.capture(), eq(0), eq(0)); verifyNoMoreInteractions(sink); }
@Test public void shouldConvertHexStringMultipleTimes() { funnel.funnel("FEDCBA01020304", sink); final ArgumentCaptor<byte[]> argumentCaptor = ArgumentCaptor.forClass(byte[].class); verify(sink).putBytes(argumentCaptor.capture(), eq(0), eq(7)); final byte[] valueOne = Arrays.copyOf(argumentCaptor.getValue(), 7); assertThat(valueOne).startsWith(0xfe, 0xdc, 0xba, 1, 2, 3, 4); funnel.funnel("01AbcD", sink); verify(sink).putBytes(argumentCaptor.capture(), eq(0), eq(3)); final byte[] valueTwo = Arrays.copyOf(argumentCaptor.getValue(), 3); assertThat(valueTwo).startsWith(1, 0xab, 0xcd); verifyNoMoreInteractions(sink); }
@Test public void shouldFallbackOnNonEvenLengthString() { funnel.funnel("01AbcD0", sink); verify(fallback).funnel("01AbcD0", sink); verifyNoMoreInteractions(fallback); }
@Test @Parameters({"foo", "123G", "-1 ", "11 22"}) public void shouldFallbackOnNonHexString(final String example) { funnel.funnel(example, sink); verify(fallback).funnel(example, sink); verifyNoMoreInteractions(fallback); }
@Test @Parameters({"*12*", "11*12", "**"}) public void shouldFallbackOnStringWithSpaces(final String exampleTemplate) { final String example = exampleTemplate.replace('*', ' '); funnel.funnel(example, sink); verify(fallback).funnel(example, sink); verifyNoMoreInteractions(fallback); }
@Test public void should_not_allow_processing_non_hex_values_when_no_fallback_provided() { funnel = new HexFunnel(); final Throwable throwable = catchThrowable(() -> funnel.funnel("not-a-hex-value", sink)); assertThat(throwable).isInstanceOf(NotHexStringException.class); }