1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.adservices.service.js; 18 19 20 import static com.android.adservices.service.js.JSScriptArgument.arrayArg; 21 import static com.android.adservices.service.js.JSScriptArgument.jsonArg; 22 import static com.android.adservices.service.js.JSScriptArgument.jsonArrayArg; 23 import static com.android.adservices.service.js.JSScriptArgument.jsonArrayArgNoValidation; 24 import static com.android.adservices.service.js.JSScriptArgument.numericArg; 25 import static com.android.adservices.service.js.JSScriptArgument.recordArg; 26 import static com.android.adservices.service.js.JSScriptArgument.stringArg; 27 import static com.android.adservices.service.js.JSScriptArgument.stringMapToRecordArg; 28 29 import static com.google.common.truth.Truth.assertThat; 30 31 import static org.junit.Assert.assertThrows; 32 33 import com.google.common.collect.ImmutableMap; 34 import com.google.common.collect.ImmutableSet; 35 36 import org.json.JSONException; 37 import org.junit.Test; 38 39 import java.util.Map; 40 41 public class JSScriptArgumentTest { 42 private static final String VALID_TEST_OBJECT_JSON_ARRAY = 43 "[" 44 + "{" 45 + "\"name\":\"John\"," 46 + "\"age\":30," 47 + "\"city\":\"New York\"" 48 + "}," 49 + "{" 50 + "\"name\":\"Alice\"," 51 + "\"age\":25," 52 + "\"city\":\"Los Angeles\"" 53 + "}," 54 + "{" 55 + "\"name\":\"Bob\"," 56 + "\"age\":35," 57 + "\"city\":\"Chicago\"" 58 + "}]"; 59 60 private static final ImmutableSet<TestObject> VALID_TEST_OBJECT_ARRAY = 61 ImmutableSet.of( 62 new TestObject("John", 30, "New York"), 63 new TestObject("Alice", 25, "Los Angeles"), 64 new TestObject("Bob", 35, "Chicago")); 65 66 @Test test_stringArg_validString_returnsSuccess()67 public void test_stringArg_validString_returnsSuccess() { 68 JSScriptArgument arg = stringArg("stringArg", "value"); 69 assertThat(arg.variableDeclaration()).isEqualTo("const stringArg = \"value\";"); 70 } 71 72 @Test test_numericArg_validInteger_returnsSuccess()73 public void test_numericArg_validInteger_returnsSuccess() { 74 JSScriptArgument arg = numericArg("numericArg", 1); 75 assertThat(arg.variableDeclaration()).isEqualTo("const numericArg = 1;"); 76 } 77 78 @Test test_numericArg_validFloat_returnsSuccess()79 public void test_numericArg_validFloat_returnsSuccess() { 80 JSScriptArgument arg = numericArg("numericArg", 1.001); 81 assertThat(arg.variableDeclaration()).isEqualTo("const numericArg = 1.001;"); 82 } 83 84 @Test test_jsonArg_validJson_returnsSuccess()85 public void test_jsonArg_validJson_returnsSuccess() throws JSONException { 86 final String jsonValue = "{\"intField\": 123, \"stringField\": \"value\"}"; 87 JSScriptArgument arg = jsonArg("jsonArg", jsonValue); 88 assertThat(arg.variableDeclaration()) 89 .isEqualTo(String.format("const jsonArg = %s;", jsonValue)); 90 } 91 92 @Test test_jsonArrayArg_validJsonArray_returnsSuccess()93 public void test_jsonArrayArg_validJsonArray_returnsSuccess() throws JSONException { 94 JSScriptArgument arg = jsonArrayArg("jsonArrayArg", VALID_TEST_OBJECT_JSON_ARRAY); 95 assertThat(arg.variableDeclaration()) 96 .isEqualTo(String.format("const jsonArrayArg = %s;", VALID_TEST_OBJECT_JSON_ARRAY)); 97 } 98 99 @Test test_jsonArrayArg_invalidJsonArray_throwsException()100 public void test_jsonArrayArg_invalidJsonArray_throwsException() { 101 final String jsonArrayValue = "this is an invalid json array"; 102 assertThrows(JSONException.class, () -> jsonArrayArg("jsonArrayArg", jsonArrayValue)); 103 } 104 105 @Test test_jsonArrayArgNoValidation_emptyCollection_returnsEmptyJson()106 public void test_jsonArrayArgNoValidation_emptyCollection_returnsEmptyJson() { 107 JSScriptArgument arg = 108 jsonArrayArgNoValidation( 109 "jsonArrayArg", ImmutableSet.of(), TestObject::serializeEntryToJson); 110 assertThat(arg.variableDeclaration()).isEqualTo("const jsonArrayArg = [];"); 111 } 112 113 @Test test_jsonArrayArgNoValidation_testObjectMarshaling_returnsMarshalledJson()114 public void test_jsonArrayArgNoValidation_testObjectMarshaling_returnsMarshalledJson() { 115 JSScriptArgument arg = 116 jsonArrayArgNoValidation( 117 "jsonArrayArg", VALID_TEST_OBJECT_ARRAY, TestObject::serializeEntryToJson); 118 assertThat(arg.variableDeclaration()) 119 .isEqualTo(String.format("const jsonArrayArg = %s;", VALID_TEST_OBJECT_JSON_ARRAY)); 120 } 121 122 @Test test_jsonArg_invalidJson_throwsException()123 public void test_jsonArg_invalidJson_throwsException() throws JSONException { 124 // Missing closing } 125 final String jsonValue = "{\"intField\": 123, \"stringField\": \"value\""; 126 assertThrows(JSONException.class, () -> jsonArg("jsonArg", jsonValue)); 127 } 128 129 @Test test_arrayArg_validArray_returnsSuccess()130 public void test_arrayArg_validArray_returnsSuccess() throws JSONException { 131 JSScriptArgument arg = 132 JSScriptArgument.arrayArg( 133 "arrayArg", stringArg("ignored", "value1"), stringArg("ignored", "value2")); 134 135 assertThat(arg.variableDeclaration()) 136 .isEqualTo("const arrayArg = [\n\"value1\"," + "\n\"value2\"\n];"); 137 } 138 139 @Test test_recordArg_validInput_returnsSuccess()140 public void test_recordArg_validInput_returnsSuccess() throws JSONException { 141 JSScriptArgument arg = 142 recordArg( 143 "recordArg", 144 numericArg("intField", 123), 145 arrayArg( 146 "arrayField", 147 stringArg("ignored", "value1"), 148 stringArg("ignored", "value2"))); 149 assertThat(arg.variableDeclaration()) 150 .isEqualTo( 151 "const recordArg = {\n\"intField\": 123,\n\"arrayField\": [\n\"value1\"," 152 + "\n\"value2\"\n]\n};"); 153 } 154 155 @Test test_stringMapToRecordArg_validStringMap_returnsSuccess()156 public void test_stringMapToRecordArg_validStringMap_returnsSuccess() throws JSONException { 157 Map<String, String> signals = 158 ImmutableMap.of( 159 "key1", 160 "{\"signals\":1}", 161 "key2", 162 "{\"signals\":2}", 163 "key3", 164 "{\"signals\":3}"); 165 JSScriptArgument arg = stringMapToRecordArg("stringMapToRecordArg", signals); 166 assertThat(arg.variableDeclaration()) 167 .isEqualTo( 168 "const stringMapToRecordArg = {\n" 169 + "\"key1\": {\"signals\":1},\n" 170 + "\"key2\": {\"signals\":2},\n" 171 + "\"key3\": {\"signals\":3}\n" 172 + "};"); 173 } 174 175 private static class TestObject { 176 public String name; 177 public int age; 178 public String city; 179 TestObject(String name, int age, String city)180 TestObject(String name, int age, String city) { 181 this.name = name; 182 this.age = age; 183 this.city = city; 184 } 185 serializeEntryToJson(TestObject value, StringBuilder accumulator)186 static void serializeEntryToJson(TestObject value, StringBuilder accumulator) { 187 accumulator.append("{"); 188 accumulator.append("\"name\":\"").append(value.name).append("\","); 189 accumulator.append("\"age\":").append(value.age).append(","); 190 accumulator.append("\"city\":\"").append(value.city).append("\""); 191 accumulator.append("}"); 192 } 193 } 194 } 195