// Copyright 2017 The Bazel 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 com.google.devtools.build.lib.skyframe.serialization.testutils;

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

import com.google.common.base.Preconditions;
import com.google.common.base.Stopwatch;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.skyframe.serialization.AutoRegistry;
import com.google.devtools.build.lib.skyframe.serialization.ObjectCodec;
import com.google.devtools.build.lib.skyframe.serialization.ObjectCodecRegistry;
import com.google.devtools.build.lib.skyframe.serialization.ObjectCodecs;
import com.google.devtools.build.lib.skyframe.serialization.SerializationException;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Map;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Utility for testing serialization of given subjects.
 *
 * <p>Differs from {@link ObjectCodecTester} in that this uses the context to perform serialization
 * deserialization instead of a specific codec.
 */
public class SerializationTester {
  public static final int DEFAULT_JUNK_INPUTS = 20;
  public static final int JUNK_LENGTH_UPPER_BOUND = 20;

  private static final Logger logger = Logger.getLogger(SerializationTester.class.getName());

  /** Interface for testing successful deserialization of an object. */
  @FunctionalInterface
  public interface VerificationFunction<T> {
    /**
     * Verifies that the original object was sufficiently serialized/deserialized.
     *
     * <p><i>Must</i> throw an exception on failure.
     */
    void verifyDeserialized(T original, T deserialized) throws Exception;
  }

  private final ImmutableList<Object> subjects;
  private final ImmutableMap.Builder<Class<?>, Object> dependenciesBuilder;
  private final ArrayList<ObjectCodec<?>> additionalCodecs = new ArrayList<>();
  private boolean memoize;
  private boolean allowFutureBlocking;
  private ObjectCodecs objectCodecs;

  @SuppressWarnings("rawtypes")
  private VerificationFunction verificationFunction =
      (original, deserialized) -> assertThat(deserialized).isEqualTo(original);

  private int repetitions = 1;

  public SerializationTester(Object... subjects) {
    this(ImmutableList.copyOf(subjects));
  }

  public SerializationTester(ImmutableList<Object> subjects) {
    Preconditions.checkArgument(!subjects.isEmpty());
    this.subjects = subjects;
    this.dependenciesBuilder = ImmutableMap.builder();
  }

  public <D> SerializationTester addDependency(Class<? super D> type, D dependency) {
    dependenciesBuilder.put(type, dependency);
    return this;
  }

  public SerializationTester addDependencies(Map<Class<?>, Object> dependencies) {
    dependenciesBuilder.putAll(dependencies);
    return this;
  }

  public SerializationTester addCodec(ObjectCodec<?> codec) {
    additionalCodecs.add(codec);
    return this;
  }

  public SerializationTester makeMemoizing() {
    this.memoize = true;
    return this;
  }

  public SerializationTester makeMemoizingAndAllowFutureBlocking(boolean allowFutureBlocking) {
    makeMemoizing();
    this.allowFutureBlocking = allowFutureBlocking;
    return this;
  }

  public SerializationTester setObjectCodecs(ObjectCodecs objectCodecs) {
    this.objectCodecs = objectCodecs;
    return this;
  }

  @SuppressWarnings("rawtypes")
  public <T> SerializationTester setVerificationFunction(
      VerificationFunction<T> verificationFunction) {
    this.verificationFunction = verificationFunction;
    return this;
  }

  /** Sets the number of times to repeat serialization and deserialization. */
  public SerializationTester setRepetitions(int repetitions) {
    this.repetitions = repetitions;
    return this;
  }

  public void runTests() throws Exception {
    ObjectCodecs codecs = this.objectCodecs == null ? createObjectCodecs() : this.objectCodecs;
    testSerializeDeserialize(codecs);
    testStableSerialization(codecs);
    testDeserializeJunkData(codecs);
  }

  private ObjectCodecs createObjectCodecs() {
    ObjectCodecRegistry registry = AutoRegistry.get();
    ImmutableMap<Class<?>, Object> dependencies = dependenciesBuilder.build();
    ObjectCodecRegistry.Builder registryBuilder = registry.getBuilder();
    for (Object val : dependencies.values()) {
      registryBuilder.addReferenceConstant(val);
    }
    for (ObjectCodec<?> codec : additionalCodecs) {
      registryBuilder.add(codec);
    }
    return new ObjectCodecs(registryBuilder.build(), dependencies);
  }

  private ByteString serialize(Object subject, ObjectCodecs codecs) throws SerializationException {
    if (memoize) {
      if (allowFutureBlocking) {
        return codecs.serializeMemoizedAndBlocking(subject).getObject();
      } else {
        return codecs.serializeMemoized(subject);
      }
    } else {
      return codecs.serialize(subject);
    }
  }

  private Object deserialize(ByteString serialized, ObjectCodecs codecs)
      throws SerializationException, IOException {
    if (memoize) {
      return codecs.deserializeMemoized(serialized);
    } else {
      return codecs.deserialize(serialized);
    }
  }

  /** Runs serialization/deserialization tests. */
  @SuppressWarnings("unchecked")
  private void testSerializeDeserialize(ObjectCodecs codecs) throws Exception {
    Stopwatch timer = Stopwatch.createStarted();
    int totalBytes = 0;
    for (int i = 0; i < repetitions; ++i) {
      for (Object subject : subjects) {
        ByteString serialized = serialize(subject, codecs);
        totalBytes += serialized.size();
        Object deserialized = deserialize(serialized, codecs);
        verificationFunction.verifyDeserialized(subject, deserialized);
      }
    }
    logger.log(
        Level.INFO,
        subjects.get(0).getClass().getSimpleName()
            + " total serialized bytes = "
            + totalBytes
            + ", "
            + timer);
  }

  /** Runs serialized bytes stability tests. */
  private void testStableSerialization(ObjectCodecs codecs)
      throws SerializationException, IOException {
    for (Object subject : subjects) {
      ByteString serialized = serialize(subject, codecs);
      Object deserialized = deserialize(serialized, codecs);
      ByteString reserialized = serialize(deserialized, codecs);
      assertThat(reserialized).isEqualTo(serialized);
    }
  }

  /** Runs junk-data recognition tests. */
  private void testDeserializeJunkData(ObjectCodecs codecs) throws IOException {
    Random rng = new Random(0);
    for (int i = 0; i < DEFAULT_JUNK_INPUTS; ++i) {
      byte[] junkData = new byte[rng.nextInt(JUNK_LENGTH_UPPER_BOUND)];
      rng.nextBytes(junkData);
      try {
        deserialize(ByteString.copyFrom(junkData), codecs);
        // OK. Junk string was coincidentally parsed.
      } catch (SerializationException | InvalidProtocolBufferException e) {
        // OK. Deserialization of junk failed.
        return;
      }
    }
    assert_().fail("all junk was parsed successfully");
  }
}
