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 org.apache.beam.runners.dataflow.util;
  
  import static org.apache.beam.runners.dataflow.util.Structs.addBoolean;
  import static org.apache.beam.runners.dataflow.util.Structs.addDouble;
  import static org.apache.beam.runners.dataflow.util.Structs.addList;
  import static org.apache.beam.runners.dataflow.util.Structs.addLong;
  import static org.apache.beam.runners.dataflow.util.Structs.addLongs;
  import static org.apache.beam.runners.dataflow.util.Structs.addNull;
  import static org.apache.beam.runners.dataflow.util.Structs.addString;
  import static org.apache.beam.runners.dataflow.util.Structs.addStringList;
  import static org.apache.beam.runners.dataflow.util.Structs.getBoolean;
  import static org.apache.beam.runners.dataflow.util.Structs.getDictionary;
  import static org.apache.beam.runners.dataflow.util.Structs.getInt;
  import static org.apache.beam.runners.dataflow.util.Structs.getListOfMaps;
  import static org.apache.beam.runners.dataflow.util.Structs.getLong;
  import static org.apache.beam.runners.dataflow.util.Structs.getObject;
  import static org.apache.beam.runners.dataflow.util.Structs.getString;
  import static org.apache.beam.runners.dataflow.util.Structs.getStrings;
  import static org.hamcrest.MatcherAssert.assertThat;
  
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.Collections;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  import org.hamcrest.Matchers;
  import org.junit.Assert;
  import org.junit.Test;
  import org.junit.runner.RunWith;
  import org.junit.runners.JUnit4;
  
  /** Tests for Structs. */
  @RunWith(JUnit4.class)
  public class StructsTest {
    private List<Map<String, Object>> makeCloudObjects() {
      List<Map<String, Object>> objects = new ArrayList<>();
      {
        CloudObject o = CloudObject.forClassName("string");
        addString(o, "singletonStringKey", "stringValue");
        objects.add(o);
      }
      {
        CloudObject o = CloudObject.forClassName("long");
        addLong(o, "singletonLongKey", 42L);
        objects.add(o);
      }
      return objects;
    }
  
    private Map<String, Object> makeCloudDictionary() {
      Map<String, Object> o = new HashMap<>();
      addList(o, "emptyKey", Collections.emptyList());
      addNull(o, "noStringsKey");
      addString(o, "singletonStringKey", "stringValue");
      addStringList(o, "multipleStringsKey", Arrays.asList("hi", "there", "bob"));
      addLongs(o, "multipleLongsKey", 47L, 1L << 42, -5L);
      addLong(o, "singletonLongKey", 42L);
      addDouble(o, "singletonDoubleKey", Math.PI);
      addBoolean(o, "singletonBooleanKey", true);
      addNull(o, "noObjectsKey");
      addList(o, "multipleObjectsKey", makeCloudObjects());
      return o;
    }
  
    @Test
    public void testGetStringParameter() throws Exception {
      Map<String, Object> o = makeCloudDictionary();
  
      Assert.assertEquals("stringValue", getString(o, "singletonStringKey"));
      Assert.assertEquals("stringValue", getString(o, "singletonStringKey", "defaultValue"));
      Assert.assertEquals("defaultValue", getString(o, "missingKey", "defaultValue"));
  
      try {
        getString(o, "missingKey");
        Assert.fail("should have thrown an exception");
      } catch (Exception exn) {
        assertThat(
            exn.toString(), Matchers.containsString("didn't find required parameter missingKey"));
      }
  
      try {
        getString(o, "noStringsKey");
        Assert.fail("should have thrown an exception");
      } catch (Exception exn) {
        assertThat(exn.toString(), Matchers.containsString("not a string"));
      }
  
      assertThat(getStrings(o, "noStringsKey", null), Matchers.emptyIterable());
      assertThat(getObject(o, "noStringsKey").keySet(), Matchers.emptyIterable());
      assertThat(getDictionary(o, "noStringsKey").keySet(), Matchers.emptyIterable());
      assertThat(getDictionary(o, "noStringsKey", null).keySet(), Matchers.emptyIterable());
  
      try {
        getString(o, "multipleStringsKey");
        Assert.fail("should have thrown an exception");
      } catch (Exception exn) {
        assertThat(exn.toString(), Matchers.containsString("not a string"));
      }
  
      try {
        getString(o, "emptyKey");
        Assert.fail("should have thrown an exception");
      } catch (Exception exn) {
        assertThat(exn.toString(), Matchers.containsString("not a string"));
      }
    }
  
    @Test
    public void testGetBooleanParameter() throws Exception {
      Map<String, Object> o = makeCloudDictionary();
  
      Assert.assertTrue(getBoolean(o, "singletonBooleanKey", false));
      Assert.assertFalse(getBoolean(o, "missingKey", false));
  
      try {
        getBoolean(o, "emptyKey", false);
        Assert.fail("should have thrown an exception");
      } catch (Exception exn) {
        assertThat(exn.toString(), Matchers.containsString("not a boolean"));
      }
    }
  
    @Test
    public void testGetLongParameter() throws Exception {
      Map<String, Object> o = makeCloudDictionary();
  
      Assert.assertEquals((Long) 42L, getLong(o, "singletonLongKey", 666L));
      Assert.assertEquals((Integer) 42, getInt(o, "singletonLongKey", 666));
      Assert.assertEquals((Long) 666L, getLong(o, "missingKey", 666L));
  
      try {
        getLong(o, "emptyKey", 666L);
        Assert.fail("should have thrown an exception");
      } catch (Exception exn) {
        assertThat(exn.toString(), Matchers.containsString("not a long"));
      }
      try {
        getInt(o, "emptyKey", 666);
        Assert.fail("should have thrown an exception");
      } catch (Exception exn) {
        assertThat(exn.toString(), Matchers.containsString("not an int"));
      }
    }
  
    @Test
    public void testGetListOfMaps() throws Exception {
      Map<String, Object> o = makeCloudDictionary();
  
      Assert.assertEquals(makeCloudObjects(), getListOfMaps(o, "multipleObjectsKey", null));
  
      try {
        getListOfMaps(o, "singletonLongKey", null);
        Assert.fail("should have thrown an exception");
      } catch (Exception exn) {
        assertThat(exn.toString(), Matchers.containsString("not a list"));
      }
    }
  
    // TODO: Test builder operations.
  }
  