Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,15 @@ public interface ValueState<T> extends ReadableState<@Nullable T>, State {
@Nullable
T read();

/**
* Returns the current value of the state, or {@code defaultValue} if the value has never been
* written.
*/
Comment on lines +40 to +43
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The Javadoc states that defaultValue is returned 'if the value has never been written'. However, the implementation returns defaultValue whenever read() returns null. This can occur not only when the state is uninitialized, but also when null has been explicitly written or the state has been cleared. To avoid confusion, the Javadoc should be updated to accurately reflect this behavior.

Suggested change
/**
* Returns the current value of the state, or {@code defaultValue} if the value has never been
* written.
*/
/**
* Returns the current value of the state, or {@code defaultValue} if the current value is {@code
* null}. This can happen if the value has never been written or if {@code null} was written.
*/

default T read(T defaultValue) {
T value = read();
return value == null ? defaultValue : value;
}

@Override
ValueState<T> readLater();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* 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.state;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;

import org.checkerframework.checker.nullness.qual.Nullable;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests for {@link ValueState}. */
@RunWith(JUnit4.class)
public class ValueStateTest {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The tests for the new functionality are a good start. To make them more comprehensive, consider adding test cases for edge scenarios. Specifically, testing the behavior after state.clear() is called, and after null is explicitly written to the state, would strengthen the test suite and clarify the contract of the new method.

For example:

@Test
public void testReadReturnsDefaultValueAfterClear() {
  TestValueState<Integer> state = new TestValueState<>();
  state.write(10);
  state.clear();
  assertEquals(Integer.valueOf(5), state.read(5));
}

@Test
public void testReadReturnsDefaultValueWhenNullIsWritten() {
  TestValueState<Integer> state = new TestValueState<>();
  state.write(null);
  assertEquals(Integer.valueOf(5), state.read(5));
}


@Test
public void testReadReturnsDefaultValueWhenStateIsEmpty() {
ValueState<Integer> state = new TestValueState<>();
assertEquals(Integer.valueOf(5), state.read(5));
}

@Test
public void testReadReturnsStoredValueWhenStateIsPresent() {
TestValueState<Integer> state = new TestValueState<>();
state.write(10);
assertEquals(Integer.valueOf(10), state.read(5));
}

@Test
public void testReadLaterReturnsSameState() {
ValueState<Integer> state = new TestValueState<>();
assertSame(state, state.readLater());
}

private static class TestValueState<T> implements ValueState<T> {

private @Nullable T value;

@Override
public void write(T input) {
value = input;
}

@Override
public @Nullable T read() {
return value;
}

@Override
public ValueState<T> readLater() {
return this;
}

@Override
public void clear() {
value = null;
}
}
}
Loading