// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespaxmlparser; import com.yahoo.document.DataType; import com.yahoo.document.DocumentType; import com.yahoo.document.DocumentTypeManager; import com.yahoo.document.DocumentUpdate; import com.yahoo.document.Field; import com.yahoo.document.StructDataType; import com.yahoo.document.TensorDataType; import com.yahoo.document.serialization.DeserializationException; import com.yahoo.tensor.TensorType; import org.junit.Ignore; import org.junit.Test; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.PrintStream; import java.nio.charset.StandardCharsets; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; /** * @author Simon Thoresen Hult */ public class VespaXmlUpdateReaderTestCase { @Test @Ignore public void requireThatArithmeticDeserializationValidateValue() throws Exception { // tracked in ticket 6675085 // problem caused by VespaXMLUpdateReader#readArithmetic() parsing value as double Field field = new Field("my_field", DataType.BYTE); assertThrows(field, "", "Field 'my_field': Invalid byte \"-129\". (at line 1, column X)"); assertThrows(field, "", "Field 'my_field': Invalid byte \"-129\". (at line 1, column X)"); assertThrows(field, "", "Field 'my_field': Invalid byte \"-129\". (at line 1, column X)"); assertThrows(field, "", "Field 'my_field': Invalid byte \"-129\". (at line 1, column X)"); assertThrows(field, "", "Field 'my_field': Invalid byte \"-129\". (at line 1, column X)"); } @Test @Ignore public void requireThatAssignNumericFieldPathValidatesFieldValue() throws Exception { // tracked in ticket 6675089 // problem caused by VespaXMLUpdateReader#read(AssignFieldPathUpdate) assertThrows(new Field("my_field", DataType.BYTE), "-129", "Field 'my_field': Invalid byte \"-129\". (at line 1, column X)"); } @Test @Ignore public void requireThatFieldPathWhereClauseIsValidated() throws Exception { // tracked in ticket 6675091 // problem caused by VespaXMLUpdateReader#read(FieldPathUpdate) not validating where clause assertThrows(new Field("my_field", DataType.getArray(DataType.BYTE)), "", "Field 'my_field': Invalid byte \"-129\". (at line 1, column X)"); assertThrows(new Field("my_field", DataType.getMap(DataType.STRING, DataType.BYTE)), "", "Field 'my_field': Invalid byte \"-129\". (at line 1, column 109)"); } @Test public void requireThatDeserializeExceptionIncludesFieldName() throws Exception { assertThrows(new Field("my_field", DataType.BYTE), "-129", "Field 'my_field': Invalid byte \"-129\". (at line 1, column 82)"); } @Test public void requireThatArrayItemDeserializeExceptionIncludesFieldName() throws Exception { Field field = new Field("my_field", DataType.getArray(DataType.BYTE)); assertThrows(field, "-129", "Field 'my_field': Invalid byte \"-129\". (at line 1, column 86)"); assertThrows(field, "-129", "Field 'my_field': Invalid byte \"-129\". (at line 1, column 90)"); assertThrows(field, "-129", "Field 'my_field': Invalid byte \"-129\". (at line 1, column 83)"); assertThrows(field, "-129", "Field 'my_field': Invalid byte \"-129\". (at line 1, column 87)"); assertThrows(field, "-129", "Field 'my_field': Invalid byte \"-129\". (at line 1, column 86)"); } @Test public void requireThatMapKeyDeserializeExceptionIncludesFieldName() throws Exception { Field field = new Field("my_field", DataType.getMap(DataType.BYTE, DataType.STRING)); assertThrows(field, "-129foo", "Field 'my_field': Invalid byte \"-129\". (at line 1, column 90)"); assertThrows(field, "-129foo", "Field 'my_field': Invalid byte \"-129\". (at line 1, column 94)"); assertThrows(field, "-129foo", "Field 'my_field': Invalid byte \"-129\". (at line 1, column 87)"); assertThrows(field, "-129foo", "Field 'my_field': Invalid byte \"-129\". (at line 1, column 91)"); assertThrows(field, "-129foo", "Field 'my_field': Invalid byte \"-129\". (at line 1, column 90)"); try { readUpdate(field, ""); fail(); } catch (NumberFormatException e) { } } @Test public void requireThatMapValueDeserializeExceptionIncludesFieldName() throws Exception { Field field = new Field("my_field", DataType.getMap(DataType.STRING, DataType.BYTE)); assertThrows(field, "foo-129", "Field 'my_field': Invalid byte \"-129\". (at line 1, column 108)"); assertThrows(field, "foo-129", "Field 'my_field': Invalid byte \"-129\". (at line 1, column 112)"); assertThrows(field, "foo-129", "Field 'my_field': Invalid byte \"-129\". (at line 1, column 105)"); assertThrows(field, "foo-129", "Field 'my_field': Invalid byte \"-129\". (at line 1, column 109)"); assertThrows(field, "foo-129", "Field 'my_field': Invalid byte \"-129\". (at line 1, column 108)"); } @Test public void requireThatStructFieldDeserializeExceptionIncludesFieldName() throws Exception { StructDataType structType = new StructDataType("my_struct"); structType.addField(new Field("my_byte", DataType.BYTE)); Field field = new Field("my_field", structType); assertThrows(field, "-129", "Field 'my_byte': Invalid byte \"-129\". (at line 1, column 92)"); assertThrows(field, "-129", "Field 'my_byte': Invalid byte \"-129\". (at line 1, column 96)"); assertThrows(field, "-129", "Field 'my_byte': Invalid byte \"-129\". (at line 1, column 89)"); assertThrows(field, "-129", "Field 'my_byte': Invalid byte \"-129\". (at line 1, column 93)"); assertThrows(field, "-129", "Field 'my_byte': Invalid byte \"-129\". (at line 1, column 92)"); } @Test public void requireThatWSetItemDeserializeExceptionIncludesFieldName() throws Exception { Field field = new Field("my_field", DataType.getWeightedSet(DataType.BYTE)); assertThrows(field, "-129", "Field 'my_field': Invalid byte \"-129\". (at line 1, column 86)"); assertThrows(field, "-129", "Field 'my_field': Invalid byte \"-129\". (at line 1, column 90)"); assertThrows(field, "-129", "Field 'my_field': Invalid byte \"-129\". (at line 1, column 83)"); assertThrows(field, "-129", "Field 'my_field': Invalid byte \"-129\". (at line 1, column 87)"); assertThrows(field, "-129", "Field 'my_field': Invalid byte \"-129\". (at line 1, column 86)"); try { readUpdate(field, ""); fail(); } catch (NumberFormatException e) { } } @Test public void requireThatCreateIfNonExistentFlagCanBeSpecified() throws Exception { { assertTrue(readUpdate(true).getCreateIfNonExistent()); assertFalse(readUpdate(false).getCreateIfNonExistent()); } } @Test public void requireThatCreateIfNonExistentFlagIsValidated() throws Exception { String documentXml = ""; try { readUpdateHelper(null, documentXml); fail(); } catch (DeserializationException e) { assertEquals(printStackTrace(e), "'create-if-non-existent' must be either 'true' or 'false', was 'illegal' (at line 1, column 77)", e.getMessage()); } } @Test public void requireThatUpdatesForTensorFieldsAreNotSupported() throws Exception { assertThrows(new Field("my_tensor", new TensorDataType(TensorType.empty)), "", "Field 'my_tensor': XML input for fields of type TENSOR is not supported. Please use JSON input instead."); } private static void assertThrows(Field field, String fieldXml, String expected) throws Exception { try { readUpdate(field, fieldXml); fail(); } catch (DeserializationException e) { assertEquals(printStackTrace(e), expected, e.getMessage()); } } private static DocumentUpdate readUpdate(Field field, String fieldXml) throws Exception { String documentXml = "" + fieldXml + ""; return readUpdateHelper(field, documentXml); } private static DocumentUpdate readUpdate(boolean createIfNonExistent) throws Exception { String documentXml = ""; return readUpdateHelper(null, documentXml); } private static DocumentUpdate readUpdateHelper(Field field, String documentXml) throws Exception { DocumentTypeManager docManager = new DocumentTypeManager(); DocumentType docType = new DocumentType("my_type"); if (field != null) { docType.addField(field); } docManager.register(docType); InputStream in = new ByteArrayInputStream(documentXml.getBytes(StandardCharsets.UTF_8)); DocumentUpdate doc = new DocumentUpdate(docType, "id:ns:my_doc::"); VespaXMLUpdateReader reader = new VespaXMLUpdateReader(in, docManager); reader.reader.next(); // initialize reader reader.read(doc); return doc; } private static String printStackTrace(Throwable t) { ByteArrayOutputStream out = new ByteArrayOutputStream(); t.printStackTrace(new PrintStream(out)); return new String(out.toByteArray(), StandardCharsets.UTF_8); } }