Back to Repositories

Validating Generic Type Variable Resolution in google/gson

This test suite validates Gson’s handling of reused type variables in generic type definitions, specifically focusing on proper type resolution during JSON deserialization. The tests ensure that when a type variable is referenced multiple times in a type hierarchy, all references resolve correctly to the same concrete type.

Test Coverage Overview

The test suite provides comprehensive coverage of generic type variable resolution in Gson.

Key areas tested include:
  • Enum deserialization within nested generic collections
  • Type variable preservation across inheritance hierarchies
  • Proper resolution of reused type parameters
  • Edge cases in generic type mapping

Implementation Analysis

The testing approach employs a hierarchical structure with nested generic types to validate type resolution. The implementation uses a three-level inheritance chain (BaseCollection -> SetCollection -> TestEnumSetCollection) with reused type variables to verify proper type preservation during JSON deserialization.

Technical patterns include:
  • Generic type parameter propagation
  • Collection type constraints
  • Enum type preservation

Technical Details

Testing infrastructure includes:
  • JUnit 4 framework for test execution
  • Gson builder configuration for JSON processing
  • Truth assertion library for enhanced verification
  • Custom generic class hierarchy for type testing
  • Enum-based test data structures

Best Practices Demonstrated

The test suite exemplifies several testing best practices:
  • Proper test setup isolation using @Before
  • Clear test case documentation
  • Specific assertion messages
  • Comprehensive type checking
  • Proper handling of generic type safety
  • Clean separation of test concerns

google/gson

gson/src/test/java/com/google/gson/functional/ReusedTypeVariablesFullyResolveTest.java

            
/*
 * Copyright (C) 2018 Google Inc.
 *
 * 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.google.gson.functional;

import static com.google.common.truth.Truth.assertThat;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;

/**
 * This test covers the scenario described in #1390 where a type variable needs to be used by a type
 * definition multiple times. Both type variable references should resolve to the same underlying
 * concrete type.
 */
public class ReusedTypeVariablesFullyResolveTest {

  private Gson gson;

  @Before
  public void setUp() {
    gson = new GsonBuilder().create();
  }

  // The instances were being unmarshaled as Strings instead of TestEnums
  @SuppressWarnings("ConstantConditions")
  @Test
  public void testGenericsPreservation() {
    TestEnumSetCollection withSet =
        gson.fromJson("{\"collection\":[\"ONE\",\"THREE\"]}", TestEnumSetCollection.class);
    Iterator<TestEnum> iterator = withSet.collection.iterator();
    assertThat(withSet).isNotNull();
    assertThat(withSet.collection).isNotNull();
    assertThat(withSet.collection).hasSize(2);
    TestEnum first = iterator.next();
    TestEnum second = iterator.next();

    assertThat(first).isInstanceOf(TestEnum.class);
    assertThat(second).isInstanceOf(TestEnum.class);
  }

  enum TestEnum {
    ONE,
    TWO,
    THREE
  }

  private static class TestEnumSetCollection extends SetCollection<TestEnum> {}

  private static class SetCollection<T> extends BaseCollection<T, Set<T>> {}

  private static class BaseCollection<U, C extends Collection<U>> {
    public C collection;
  }
}