content: /*
   * 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 accord.maelstrom;
  
  import org.junit.jupiter.api.Test;
  
  import accord.api.Key;
  import accord.primitives.Deps;
  import accord.primitives.Range;
  import accord.primitives.RangeDeps;
  import accord.primitives.RoutableKey;
  import accord.utils.AccordGens;
  import accord.utils.Gen;
  import accord.utils.Gens;
  import org.assertj.core.api.Assertions;
  
  import static accord.utils.Property.qt;
  
  class JsonTest
  {
      @Test
      void serdeDeps()
      {
          qt().forAll(depsGen()).check(JsonTest::serde);
      }
  
      private static <T> void serde(T expected)
      {
          String json = Json.GSON.toJson(expected);
          T parsed;
          try
          {
              parsed = Json.GSON.<T>fromJson(json, expected.getClass());
          }
          catch (Throwable t)
          {
              throw new AssertionError("Unable to parse json: " + json, t);
          }
          Assertions.assertThat(parsed)
                    .isEqualTo(expected);
      }
  
      static Gen<Key> keyGen()
      {
          Gen<Datum.Kind> kindGen = Gens.enums().all(Datum.Kind.class);
          Gen<String> strings = Gens.strings().all().ofLengthBetween(0, 10);
          return rs -> {
              Datum.Kind next = kindGen.next(rs);
              switch (next)
              {
                  case STRING: return new MaelstromKey.Key(Datum.Kind.STRING, strings.next(rs));
                  case LONG: return new MaelstromKey.Key(Datum.Kind.LONG, rs.nextLong());
                  case HASH: return new MaelstromKey.Key(Datum.Kind.HASH, new Datum.Hash(rs.nextInt()));
                  case DOUBLE: return new MaelstromKey.Key(Datum.Kind.DOUBLE, rs.nextDouble());
                  default: throw new AssertionError("Unknown kind: " + next);
              }
          };
      }
  
      static Gen<Range> rangeGen()
      {
          return AccordGens.ranges(keyGen().map(Key::toUnseekable), MaelstromKey.Range::new);
      }
  
      static Gen<RangeDeps> rangeDepsGen()
      {
          return AccordGens.rangeDeps(rangeGen());
      }
  
      static Gen<Deps> depsGen()
      {
          return AccordGens.deps(AccordGens.keyDeps(keyGen().map(RoutableKey::toUnseekable)),
                                 rangeDepsGen());
      }
  
  }