Skip to content
Merged
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
31 changes: 22 additions & 9 deletions core/src/main/java/google/registry/model/eppcommon/Address.java
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ public Builder<? extends Address> asBuilder() {

@Override
public void postProcess() {
validateState();
if (street == null || street.isEmpty()) {
return;
}
Expand All @@ -163,6 +164,21 @@ public void postProcess() {
streetLine3 = street.size() >= 3 ? street.get(2) : null;
}

public void validateState() {
checkArgument(
street == null || (!street.isEmpty() && street.size() <= 3),
"Street address must have [1-3] lines: %s",
street);
//noinspection ConstantConditions
checkArgument(
street == null || street.stream().noneMatch(String::isEmpty),
"Street address cannot contain empty string: %s",
street);
checkArgument(
countryCode == null || countryCode.length() == 2,
"Country code should be a 2 character string");
}

/** A builder for constructing {@link Address}. */
public static class Builder<T extends Address> extends Buildable.Builder<T> {

Expand All @@ -172,16 +188,13 @@ protected Builder(T instance) {
super(instance);
}

@Override
public T build() {
getInstance().validateState();
return super.build();
}

public Builder<T> setStreet(ImmutableList<String> street) {
checkArgument(
street == null || (!street.isEmpty() && street.size() <= 3),
"Street address must have [1-3] lines: %s",
street);
//noinspection ConstantConditions
checkArgument(
street.stream().noneMatch(String::isEmpty),
"Street address cannot contain empty string: %s",
street);
getInstance().street = street;
getInstance().streetLine1 = street.get(0);
getInstance().streetLine2 = street.size() >= 2 ? street.get(1) : null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,21 +37,20 @@ public Builder asBuilder() {
return new Builder(clone(this));
}

@Override
public void validateState() {
super.validateState();
checkNotNull(forceEmptyToNull(getStreet()), "Missing street");
checkNotNull(getCity(), "Missing city");
checkNotNull(getCountryCode(), "Missing country code");
}

/** Builder for {@link RegistrarAddress}. */
public static class Builder extends Address.Builder<RegistrarAddress> {
public Builder() {}

private Builder(RegistrarAddress instance) {
super(instance);
}

@Override
public RegistrarAddress build() {
RegistrarAddress instance = getInstance();
checkNotNull(forceEmptyToNull(instance.getStreet()), "Missing street");
checkNotNull(instance.getCity(), "Missing city");
checkNotNull(instance.getCountryCode(), "Missing country code");
return super.build();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import google.registry.model.eppcommon.AddressTest.TestEntity.TestAddress;
import google.registry.persistence.transaction.JpaTestExtensions;
import google.registry.persistence.transaction.JpaTestExtensions.JpaUnitTestExtension;
import google.registry.tools.GsonUtils;
import jakarta.persistence.Embeddable;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
Expand Down Expand Up @@ -124,6 +125,38 @@ void testSuccess_pojoToAndFromXml() throws Exception {
assertAddress(unmarshalledEntity.address, "123 W 14th St", "8th Fl", "Rm 8");
}

@Test
void testSuccess_gsonInstantiation() {
String json = "{\"street\":[\"123 W 14th St\",\"8th Fl\"],\"countryCode\":\"US\"}";
TestAddress address = GsonUtils.provideGson().fromJson(json, TestAddress.class);
assertThat(address.getStreet()).containsExactly("123 W 14th St", "8th Fl");
assertThat(address.getCountryCode()).isEqualTo("US");
}

@Test
void testFailure_gsonInstantiation_tooManyStreetLines() {
String json = "{\"street\":[\"123 W 14th St\",\"8th Fl\",\"Rm 8\",\"4th Line\"]}";
assertThrows(
IllegalArgumentException.class,
() -> GsonUtils.provideGson().fromJson(json, TestAddress.class));
}

@Test
void testFailure_gsonInstantiation_emptyStreetLine() {
String json = "{\"street\":[\"123 W 14th St\",\"\"]}";
assertThrows(
IllegalArgumentException.class,
() -> GsonUtils.provideGson().fromJson(json, TestAddress.class));
}

@Test
void testFailure_gsonInstantiation_invalidCountryCode() {
String json = "{\"countryCode\":\"USA\"}";
assertThrows(
IllegalArgumentException.class,
() -> GsonUtils.provideGson().fromJson(json, TestAddress.class));
}

private static TestAddress createAddress(String... streetList) {
return new TestAddress.Builder()
.setStreet(ImmutableList.copyOf(streetList))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// Copyright 2026 The Nomulus Authors. All Rights Reserved.
//
// 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 google.registry.model.registrar;

import static com.google.common.truth.Truth.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;

import com.google.common.collect.ImmutableList;
import google.registry.tools.GsonUtils;
import org.junit.jupiter.api.Test;

/** Unit tests for {@link RegistrarAddress}. */
class RegistrarAddressTest {

@Test
void testSuccess_gsonInstantiation() {
String json = "{\"street\":[\"123 W 14th St\"],\"city\":\"New York\",\"countryCode\":\"US\"}";
RegistrarAddress address = GsonUtils.provideGson().fromJson(json, RegistrarAddress.class);
assertThat(address.getStreet()).containsExactly("123 W 14th St");
assertThat(address.getCity()).isEqualTo("New York");
assertThat(address.getCountryCode()).isEqualTo("US");
}

@Test
void testFailure_gsonInstantiation_missingStreet() {
String json = "{\"city\":\"New York\",\"countryCode\":\"US\"}";
assertThrows(
NullPointerException.class,
() -> GsonUtils.provideGson().fromJson(json, RegistrarAddress.class));
}

@Test
void testFailure_gsonInstantiation_missingCity() {
String json = "{\"street\":[\"123 W 14th St\"],\"countryCode\":\"US\"}";
assertThrows(
NullPointerException.class,
() -> GsonUtils.provideGson().fromJson(json, RegistrarAddress.class));
}

@Test
void testFailure_gsonInstantiation_missingCountryCode() {
String json = "{\"street\":[\"123 W 14th St\"],\"city\":\"New York\"}";
assertThrows(
NullPointerException.class,
() -> GsonUtils.provideGson().fromJson(json, RegistrarAddress.class));
}

@Test
void testFailure_gsonInstantiation_invalidCountryCode() {
String json = "{\"street\":[\"123 W 14th St\"],\"city\":\"New York\",\"countryCode\":\"USA\"}";
assertThrows(
IllegalArgumentException.class,
() -> GsonUtils.provideGson().fromJson(json, RegistrarAddress.class));
}

@Test
void testFailure_gsonInstantiation_tooManyStreetLines() {
String json =
"{\"street\":[\"1\",\"2\",\"3\",\"4\"],\"city\":\"New York\",\"countryCode\":\"US\"}";
assertThrows(
IllegalArgumentException.class,
() -> GsonUtils.provideGson().fromJson(json, RegistrarAddress.class));
}

@Test
void testSuccess_builder() {
RegistrarAddress address =
new RegistrarAddress.Builder()
.setStreet(ImmutableList.of("123 W 14th St"))
.setCity("New York")
.setCountryCode("US")
.build();
assertThat(address.getStreet()).containsExactly("123 W 14th St");
}

@Test
void testFailure_builder_missingStreet() {
assertThrows(
NullPointerException.class,
() -> new RegistrarAddress.Builder().setCity("New York").setCountryCode("US").build());
}
}
Loading