Back to Repositories

Testing SQL Types Serialization Implementation in google/gson

This test suite validates GSON’s handling of SQL data types, focusing on serialization and deserialization of java.sql.Date, Time, and Timestamp classes. The tests ensure proper conversion between JSON and SQL types while handling different time zones and locale settings.

Test Coverage Overview

The test suite provides comprehensive coverage of SQL data type handling in GSON.

Key areas tested include:
  • Null value handling for all SQL types
  • Date format conversions with different patterns
  • Time zone and locale-specific serialization
  • Timestamp precision and formatting

Implementation Analysis

The testing approach uses JUnit framework with systematic validation of both serialization and deserialization processes.

Technical patterns include:
  • Setup/teardown for timezone and locale management
  • Consistent test structure for each SQL type
  • Custom date format pattern testing
  • Edge case handling with epoch timestamps

Technical Details

Testing infrastructure includes:
  • JUnit test framework
  • Google Truth assertion library
  • GSON builder configuration
  • TimeZone and Locale manipulation
  • Custom date format patterns

Best Practices Demonstrated

The test suite exemplifies high-quality testing practices through:
  • Proper test isolation with @Before/@After handlers
  • Comprehensive null case coverage
  • Explicit timezone handling
  • Clear test method naming
  • Modular test organization

google/gson

gson/src/test/java/com/google/gson/internal/sql/SqlTypesGsonTest.java

            
/*
 * Copyright (C) 2020 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.internal.sql;

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

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.functional.DefaultTypeAdaptersTest;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Locale;
import java.util.TimeZone;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

// Suppression for `java.sql.Date` to make it explicit that this is not `java.util.Date`
@SuppressWarnings("UnnecessarilyFullyQualified")
public class SqlTypesGsonTest {
  private Gson gson;
  private TimeZone oldTimeZone;
  private Locale oldLocale;

  @Before
  public void setUp() throws Exception {
    this.oldTimeZone = TimeZone.getDefault();
    TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles"));
    this.oldLocale = Locale.getDefault();
    Locale.setDefault(Locale.US);
    gson = new Gson();
  }

  @After
  public void tearDown() throws Exception {
    TimeZone.setDefault(oldTimeZone);
    Locale.setDefault(oldLocale);
  }

  @Test
  public void testNullSerializationAndDeserialization() {
    testNullSerializationAndDeserialization(java.sql.Date.class);
    testNullSerializationAndDeserialization(Time.class);
    testNullSerializationAndDeserialization(Timestamp.class);
  }

  private void testNullSerializationAndDeserialization(Class<?> c) {
    DefaultTypeAdaptersTest.testNullSerializationAndDeserialization(gson, c);
  }

  @Test
  public void testDefaultSqlDateSerialization() {
    java.sql.Date instant = new java.sql.Date(1259875082000L);
    String json = gson.toJson(instant);
    assertThat(json).isEqualTo("\"Dec 3, 2009\"");
  }

  @Test
  public void testDefaultSqlDateDeserialization() {
    String json = "'Dec 3, 2009'";
    java.sql.Date extracted = gson.fromJson(json, java.sql.Date.class);
    DefaultTypeAdaptersTest.assertEqualsDate(extracted, 2009, 11, 3);
  }

  // http://code.google.com/p/google-gson/issues/detail?id=230
  @Test
  public void testSqlDateSerialization() throws Exception {
    TimeZone defaultTimeZone = TimeZone.getDefault();
    TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
    Locale defaultLocale = Locale.getDefault();
    Locale.setDefault(Locale.US);
    try {
      java.sql.Date sqlDate = new java.sql.Date(0L);
      Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd").create();
      String json = gson.toJson(sqlDate, Timestamp.class);
      assertThat(json).isEqualTo("\"1970-01-01\"");
      assertThat(gson.fromJson("\"1970-01-01\"", java.sql.Date.class).getTime()).isEqualTo(0);
    } finally {
      TimeZone.setDefault(defaultTimeZone);
      Locale.setDefault(defaultLocale);
    }
  }

  @Test
  public void testDefaultSqlTimeSerialization() {
    Time now = new Time(1259875082000L);
    String json = gson.toJson(now);
    assertThat(json).isEqualTo("\"01:18:02 PM\"");
  }

  @Test
  public void testDefaultSqlTimeDeserialization() {
    String json = "'1:18:02 PM'";
    Time extracted = gson.fromJson(json, Time.class);
    DefaultTypeAdaptersTest.assertEqualsTime(extracted, 13, 18, 2);
  }

  @Test
  public void testDefaultSqlTimestampSerialization() {
    Timestamp now = new java.sql.Timestamp(1259875082000L);
    String json = gson.toJson(now);
    // The exact format of the serialized date-time string depends on the JDK version. The pattern
    // here allows for an optional comma after the date, and what might be U+202F (Narrow No-Break
    // Space) before "PM".
    assertThat(json).matches("\"Dec 3, 2009,? 1:18:02\\hPM\"");
  }

  @Test
  public void testDefaultSqlTimestampDeserialization() {
    String json = "'Dec 3, 2009 1:18:02 PM'";
    Timestamp extracted = gson.fromJson(json, Timestamp.class);
    DefaultTypeAdaptersTest.assertEqualsDate(extracted, 2009, 11, 3);
    DefaultTypeAdaptersTest.assertEqualsTime(extracted, 13, 18, 2);
  }

  // http://code.google.com/p/google-gson/issues/detail?id=230
  @Test
  public void testTimestampSerialization() throws Exception {
    TimeZone defaultTimeZone = TimeZone.getDefault();
    TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
    Locale defaultLocale = Locale.getDefault();
    Locale.setDefault(Locale.US);
    try {
      Timestamp timestamp = new Timestamp(0L);
      Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd").create();
      String json = gson.toJson(timestamp, Timestamp.class);
      assertThat(json).isEqualTo("\"1970-01-01\"");
      assertThat(gson.fromJson("\"1970-01-01\"", Timestamp.class).getTime()).isEqualTo(0);
    } finally {
      TimeZone.setDefault(defaultTimeZone);
      Locale.setDefault(defaultLocale);
    }
  }
}