github.com/boki/go-xmp@v1.0.1/test/path_test.go (about)

     1  // Copyright (c) 2017-2018 Alexander Eichhorn
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License"): you may
     4  // not use this file except in compliance with the License. You may obtain
     5  // a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    11  // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    12  // License for the specific language governing permissions and limitations
    13  // under the License.
    14  
    15  package main
    16  
    17  import (
    18  	"testing"
    19  
    20  	_ "trimmer.io/go-xmp/models"
    21  	"trimmer.io/go-xmp/models/dc"
    22  	"trimmer.io/go-xmp/models/xmp_mm"
    23  	"trimmer.io/go-xmp/xmp"
    24  )
    25  
    26  func TestIncorrectPaths(T *testing.T) {
    27  	d := xmp.NewDocument()
    28  	dc := &dc.DublinCore{
    29  		Format: "teststring",
    30  		Type:   xmp.NewStringArray("one", "two", "three"),
    31  		Description: xmp.NewAltString(
    32  			xmp.AltItem{Value: "german", Lang: "de", IsDefault: false},
    33  			xmp.AltItem{Value: "english", Lang: "en", IsDefault: true},
    34  		),
    35  	}
    36  	d.AddModel(dc)
    37  	mm := &xmpmm.XmpMM{
    38  		Ingredients: xmpmm.ResourceRefArray{
    39  			&xmpmm.ResourceRef{AlternatePaths: xmp.UriArray{xmp.NewUri("x")}},
    40  		},
    41  	}
    42  	d.AddModel(mm)
    43  	for i, v := range []string{
    44  		"format",                  // missing namespace
    45  		"dc/format",               // wrong namespace separator
    46  		"xmpMM:Ingredients[0][0]", // double array without /
    47  	} {
    48  		if _, err := d.GetPath(xmp.Path(v)); err == nil {
    49  			T.Errorf("unexpected nil error for case %d", i)
    50  		}
    51  	}
    52  }
    53  
    54  func TestPathGet(T *testing.T) {
    55  	d := xmp.NewDocument()
    56  	c := &dc.DublinCore{
    57  		Format: "teststring",
    58  	}
    59  	d.AddModel(c)
    60  	if v, err := d.GetPath(xmp.Path("dc:format")); err != nil {
    61  		T.Error(err)
    62  	} else if v != "teststring" {
    63  		T.Errorf("invalid result: expected=teststring got=%s", v)
    64  	}
    65  }
    66  
    67  func TestPathGetSlice(T *testing.T) {
    68  	d := xmp.NewDocument()
    69  	c := &dc.DublinCore{
    70  		Type: xmp.NewStringArray("one", "two", "three"),
    71  	}
    72  	d.AddModel(c)
    73  	if v, err := d.GetPath(xmp.Path("dc:type")); err != nil {
    74  		T.Error(err)
    75  	} else if v != "one" {
    76  		T.Errorf("invalid result: expected=one got=%s", v)
    77  	}
    78  	if v, err := d.GetPath(xmp.Path("dc:type[]")); err != nil {
    79  		T.Error(err)
    80  	} else if v != "one" {
    81  		T.Errorf("invalid result: expected=one got=%s", v)
    82  	}
    83  	if v, err := d.GetPath(xmp.Path("dc:type[0]")); err != nil {
    84  		T.Error(err)
    85  	} else if v != "one" {
    86  		T.Errorf("invalid result: expected=one got=%s", v)
    87  	}
    88  	if v, err := d.GetPath(xmp.Path("dc:type[1]")); err != nil {
    89  		T.Error(err)
    90  	} else if v != "two" {
    91  		T.Errorf("invalid result: expected=two got=%s", v)
    92  	}
    93  	if v, err := d.GetPath(xmp.Path("dc:type[3]")); err != nil {
    94  		T.Error(err)
    95  	} else if v != "" {
    96  		T.Errorf("invalid result: expected=<empty> got=%s", v)
    97  	}
    98  }
    99  
   100  func TestPathGetAltString(T *testing.T) {
   101  	d := xmp.NewDocument()
   102  	c := &dc.DublinCore{
   103  		Description: xmp.NewAltString(
   104  			xmp.AltItem{Value: "german", Lang: "de", IsDefault: false},
   105  			xmp.AltItem{Value: "english", Lang: "en", IsDefault: true},
   106  		),
   107  	}
   108  	d.AddModel(c)
   109  	if v, err := d.GetPath(xmp.Path("dc:description")); err != nil {
   110  		T.Error(err)
   111  	} else if v != "english" {
   112  		T.Errorf("invalid result: expected=english got=%s", v)
   113  	}
   114  	if v, err := d.GetPath(xmp.Path("dc:description[]")); err != nil {
   115  		T.Error(err)
   116  	} else if v != "english" {
   117  		T.Errorf("invalid result: expected=english got=%s", v)
   118  	}
   119  	if v, err := d.GetPath(xmp.Path("dc:description[en]")); err != nil {
   120  		T.Error(err)
   121  	} else if v != "english" {
   122  		T.Errorf("invalid result: expected=english got=%s", v)
   123  	}
   124  	if v, err := d.GetPath(xmp.Path("dc:description[de]")); err != nil {
   125  		T.Error(err)
   126  	} else if v != "german" {
   127  		T.Errorf("invalid result: expected=german got=%s", v)
   128  	}
   129  	if v, err := d.GetPath(xmp.Path("dc:description[fr]")); err != nil {
   130  		T.Error(err)
   131  	} else if v != "" {
   132  		T.Errorf("invalid result: expected=<empty> got=%s", v)
   133  	}
   134  	// not sure if this is a nuonce of the implementation
   135  	if v, err := d.GetPath(xmp.Path("dc:description[0]")); err != nil {
   136  		T.Error(err)
   137  	} else if v != "english" {
   138  		T.Errorf("invalid result: expected=english got=%s", v)
   139  	}
   140  }
   141  
   142  func TestPathGetNestedSlice(T *testing.T) {
   143  	d := xmp.NewDocument()
   144  	mm := &xmpmm.XmpMM{
   145  		Ingredients: xmpmm.ResourceRefArray{
   146  			&xmpmm.ResourceRef{AlternatePaths: xmp.UriArray{xmp.NewUri("x")}},
   147  		},
   148  	}
   149  	d.AddModel(mm)
   150  	if v, err := d.GetPath(xmp.Path("xmpMM:Ingredients[0]/alternatePaths")); err != nil {
   151  		T.Error(err)
   152  	} else if v != "x" {
   153  		T.Errorf("invalid result: expected=x got=%s", v)
   154  	}
   155  	if v, err := d.GetPath(xmp.Path("xmpMM:Ingredients[0]/alternatePaths[]")); err != nil {
   156  		T.Error(err)
   157  	} else if v != "x" {
   158  		T.Errorf("invalid result: expected=x got=%s", v)
   159  	}
   160  	if v, err := d.GetPath(xmp.Path("xmpMM:Ingredients[0]/alternatePaths[0]")); err != nil {
   161  		T.Error(err)
   162  	} else if v != "x" {
   163  		T.Errorf("invalid result: expected=x got=%s", v)
   164  	}
   165  	if v, err := d.GetPath(xmp.Path("xmpMM:Ingredients[0]/alternatePaths[1]")); err != nil {
   166  		T.Error(err)
   167  	} else if v != "" {
   168  		T.Errorf("invalid result: expected=<empty> got=%s", v)
   169  	}
   170  }
   171  
   172  func TestPathGetExtension(T *testing.T) {
   173  	d1 := xmp.NewDocument()
   174  	c := &dc.DublinCore{
   175  		Format: "x",
   176  	}
   177  	d1.AddModel(c)
   178  	d2 := xmp.NewDocument()
   179  	mm, err := xmpmm.MakeModel(d2)
   180  	if err != nil {
   181  		T.Errorf("error creating xmpMM model: %v", err)
   182  		return
   183  	}
   184  	mm.AddPantry(d1)
   185  	if l := len(mm.Pantry); l != 1 {
   186  		T.Errorf("invalid pantry len: expected=1 got=%d", l)
   187  	}
   188  	if v, err := d2.GetPath(xmp.Path("xmpMM:Pantry[0]/dc:format")); err != nil {
   189  		T.Error(err)
   190  	} else if v != "x" {
   191  		T.Errorf("invalid result: expected=x got=%s", v)
   192  	}
   193  }
   194  
   195  func TestPathSet(T *testing.T) {
   196  	d := xmp.NewDocument()
   197  	p := xmp.Path("dc:format")
   198  	if err := d.SetPath(xmp.PathValue{
   199  		Path:  p,
   200  		Value: "y",
   201  		Flags: xmp.DEFAULT,
   202  	}); err != nil {
   203  		T.Errorf("%v: set failed: %v", p, err)
   204  	}
   205  	if v, err := d.GetPath(p); err != nil {
   206  		T.Error(err)
   207  	} else if v != "y" {
   208  		T.Errorf("invalid result: expected=x got=%s", v)
   209  	}
   210  	if v := dc.FindModel(d); v == nil {
   211  		T.Errorf("missing dc model")
   212  	} else if v.Format != "y" {
   213  		T.Errorf("invalid result: expected=x got=%s", v.Format)
   214  	}
   215  }
   216  
   217  func TestPathSetSlice(T *testing.T) {
   218  	d := xmp.NewDocument()
   219  	p := xmp.Path("dc:type")
   220  	if err := d.SetPath(xmp.PathValue{
   221  		Path:  p,
   222  		Value: "y",
   223  		Flags: xmp.DEFAULT,
   224  	}); err != nil {
   225  		T.Errorf("%v: set failed: %v", p, err)
   226  	}
   227  	if v, err := d.GetPath(p); err != nil {
   228  		T.Error(err)
   229  	} else if v != "y" {
   230  		T.Errorf("invalid result: expected=y got=%s", v)
   231  	}
   232  	v := dc.FindModel(d)
   233  	if v == nil {
   234  		T.Errorf("missing dc model")
   235  		return
   236  	}
   237  	if l := len(v.Type); l != 1 {
   238  		T.Errorf("invalid slice length: expected=1 got=%d", l)
   239  	}
   240  	if s := v.Type[0]; s != "y" {
   241  		T.Errorf("invalid result: expected=y got=%s", s)
   242  	}
   243  }
   244  
   245  func TestPathSetAltString(T *testing.T) {
   246  	d := xmp.NewDocument()
   247  	p := xmp.Path("dc:description[en]")
   248  	if err := d.SetPath(xmp.PathValue{
   249  		Path:  p,
   250  		Value: "y",
   251  		Flags: xmp.DEFAULT,
   252  	}); err != nil {
   253  		T.Errorf("%v: set failed: %v", p, err)
   254  	}
   255  	if v, err := d.GetPath(p); err != nil {
   256  		T.Error(err)
   257  	} else if v != "y" {
   258  		T.Errorf("invalid result: expected=y got=%s", v)
   259  	}
   260  	v := dc.FindModel(d)
   261  	if v == nil {
   262  		T.Errorf("missing dc model")
   263  		return
   264  	}
   265  	if l := len(v.Description); l != 1 {
   266  		T.Errorf("invalid slice length: expected=1 got=%d", l)
   267  	}
   268  	if s := v.Description.Get("en"); s != "y" {
   269  		T.Errorf("invalid result: expected=y got=%s", s)
   270  	}
   271  	if s := v.Description.Default(); s != "y" {
   272  		T.Errorf("invalid result: expected=y got=%s", s)
   273  	}
   274  }
   275  
   276  func TestPathSetNestedSlice(T *testing.T) {
   277  	d := xmp.NewDocument()
   278  	p := xmp.Path("xmpMM:Ingredients[0]/alternatePaths")
   279  	if err := d.SetPath(xmp.PathValue{
   280  		Path:  p,
   281  		Value: "y",
   282  		Flags: xmp.DEFAULT,
   283  	}); err != nil {
   284  		T.Errorf("%v: set failed: %v", p, err)
   285  	}
   286  	if v, err := d.GetPath(p); err != nil {
   287  		T.Error(err)
   288  	} else if v != "y" {
   289  		T.Errorf("invalid result: expected=y got=%s", v)
   290  	}
   291  }
   292  
   293  func TestPathSetExtension(T *testing.T) {
   294  	d1 := xmp.NewDocument()
   295  	c := &dc.DublinCore{
   296  		Format: "x",
   297  	}
   298  	d1.AddModel(c)
   299  	d2 := xmp.NewDocument()
   300  	mm, err := xmpmm.MakeModel(d2)
   301  	if err != nil {
   302  		T.Errorf("error creating xmpMM model: %v", err)
   303  		return
   304  	}
   305  	mm.AddPantry(d1)
   306  	p := xmp.Path("xmpMM:Pantry[0]/dc:format")
   307  	if err := d2.SetPath(xmp.PathValue{
   308  		Path:  p,
   309  		Value: "y",
   310  		Flags: xmp.REPLACE,
   311  	}); err != nil {
   312  		T.Errorf("%v: set failed: %v", p, err)
   313  	}
   314  	if val, err := d2.GetPath(p); err != nil {
   315  		T.Errorf("%v: get failed: %v", p, err)
   316  	} else if val != "y" {
   317  		T.Errorf("%v: invalid contents, expected=y got=%s", p, val)
   318  	}
   319  }
   320  
   321  func TestPathCreateExtension(T *testing.T) {
   322  	d := xmp.NewDocument()
   323  	p := xmp.Path("xmpMM:Pantry[0]/dc:format")
   324  	if err := d.SetPath(xmp.PathValue{
   325  		Path:  p,
   326  		Value: "y",
   327  		Flags: xmp.CREATE,
   328  	}); err != nil {
   329  		T.Errorf("%v: set failed: %v", p, err)
   330  	}
   331  	if val, err := d.GetPath(p); err != nil {
   332  		T.Errorf("%v: get failed: %v", p, err)
   333  	} else if val != "y" {
   334  		T.Errorf("%v: invalid contents, expected=y got=%s", p, val)
   335  	}
   336  }
   337  
   338  func TestPathCreate(T *testing.T) {
   339  	d1 := xmp.NewDocument()
   340  	for n, v := range SyncMergeTestcases {
   341  		if err := d1.SetPath(xmp.PathValue{
   342  			Path:      n,
   343  			Value:     v,
   344  			Namespace: "exotic:ns:42",
   345  			Flags:     xmp.CREATE,
   346  		}); err != nil {
   347  			T.Errorf("%v: %v", n, err)
   348  		}
   349  	}
   350  	d2 := xmp.NewDocument()
   351  	if err := d2.Merge(d1, xmp.MERGE); err != nil {
   352  		T.Errorf("merge failed: %v", err)
   353  	}
   354  	for n, v := range SyncMergeTestcases {
   355  		if val, err := d2.GetPath(n); err != nil {
   356  			T.Errorf("%v: get failed: %v", n, err)
   357  		} else if v != val {
   358  			T.Errorf("%v: invalid contents, expected=%s got=%s", n, v, val)
   359  		}
   360  	}
   361  }
   362  
   363  func TestPathCreateModelNamespace(T *testing.T) {
   364  	d := xmp.NewDocument()
   365  	if v := dc.FindModel(d); v != nil {
   366  		T.Errorf("expected no model to exist")
   367  	}
   368  	if err := d.SetPath(xmp.PathValue{Path: xmp.Path("dc:"),
   369  		Value: "-",
   370  		Flags: xmp.CREATE,
   371  	}); err != nil {
   372  		T.Errorf("error creating model: %v", err)
   373  	}
   374  	if v := dc.FindModel(d); v == nil {
   375  		T.Errorf("expected model to exist")
   376  	}
   377  }
   378  
   379  func TestPathCreateCustomNamespace(T *testing.T) {
   380  	d := xmp.NewDocument()
   381  	p := xmp.Path("myCustomNs:")
   382  	if _, err := d.GetPath(p); err == nil {
   383  		T.Errorf("expected no path to exist")
   384  	}
   385  	if err := d.SetPath(xmp.PathValue{
   386  		Path:      p,
   387  		Namespace: "ns.example.com/",
   388  		Value:     "-",
   389  		Flags:     xmp.CREATE,
   390  	}); err != nil {
   391  		T.Errorf("error creating non-model path: %v", err)
   392  	}
   393  	if _, err := d.GetPath(p); err != nil {
   394  		T.Errorf("expected path to exist")
   395  	}
   396  }
   397  
   398  func TestPathReplace(T *testing.T) {
   399  	d := xmp.NewDocument()
   400  	c := &dc.DublinCore{
   401  		Format: "old",
   402  	}
   403  	d.AddModel(c)
   404  	if err := d.SetPath(xmp.PathValue{
   405  		Path:  xmp.Path("dc:format"),
   406  		Value: "new",
   407  		Flags: xmp.REPLACE,
   408  	}); err != nil {
   409  		T.Errorf("path set failed: %v", err)
   410  	}
   411  	if c.Format != "new" {
   412  		T.Errorf("invalid result: expected=new got=%s", c.Format)
   413  	}
   414  }
   415  
   416  func TestPathReplaceLong(T *testing.T) {
   417  	d := xmp.NewDocument()
   418  	mm := &xmpmm.XmpMM{
   419  		Versions: xmpmm.StVersionArray{
   420  			&xmpmm.StVersion{
   421  				Event: xmpmm.ResourceEvent{
   422  					Parameters: "testA",
   423  				},
   424  			},
   425  		},
   426  	}
   427  	d.AddModel(mm)
   428  	if err := d.SetPath(xmp.PathValue{
   429  		Path:  xmp.Path("xmpMM:Versions[0]/stVer:event/parameters"),
   430  		Value: "testB",
   431  		Flags: xmp.REPLACE,
   432  	}); err != nil {
   433  		T.Errorf("path set failed: %v", err)
   434  	}
   435  	if v := mm.Versions[0].Event.Parameters; v != "testB" {
   436  		T.Errorf("invalid result: expected=new got=%s", v)
   437  	}
   438  }
   439  
   440  func TestPathNotReplace(T *testing.T) {
   441  	d := xmp.NewDocument()
   442  	c := &dc.DublinCore{
   443  		Format: "old",
   444  	}
   445  	d.AddModel(c)
   446  	if err := d.SetPath(xmp.PathValue{
   447  		Path:  xmp.Path("dc:format"),
   448  		Value: "new",
   449  		Flags: xmp.CREATE,
   450  	}); err == nil {
   451  		T.Errorf("unexpected nil error when overwriting existing path")
   452  	}
   453  	if c.Format != "old" {
   454  		T.Errorf("invalid result: expected=old got=%s", c.Format)
   455  	}
   456  }
   457  
   458  func TestPathReplaceSlice(T *testing.T) {
   459  	d := xmp.NewDocument()
   460  	c := &dc.DublinCore{
   461  		Type: xmp.NewStringArray("one", "two", "three"),
   462  	}
   463  	d.AddModel(c)
   464  	if err := d.SetPath(xmp.PathValue{
   465  		Path:  xmp.Path("dc:type"),
   466  		Value: "four",
   467  		Flags: xmp.REPLACE,
   468  	}); err != nil {
   469  		T.Errorf("unexpected error on append to existing path: %v", err)
   470  	}
   471  	if l := len(c.Type); l != 1 {
   472  		T.Errorf("invalid len: expected=1 got=%d", l)
   473  	}
   474  	if c.Type[0] != "four" {
   475  		T.Errorf("invalid result: expected=four got=%s", c.Type[0])
   476  	}
   477  }
   478  
   479  func TestPathAppendExist(T *testing.T) {
   480  	d := xmp.NewDocument()
   481  	c := &dc.DublinCore{
   482  		Type: xmp.NewStringArray("one", "two", "three"),
   483  	}
   484  	d.AddModel(c)
   485  	if err := d.SetPath(xmp.PathValue{
   486  		Path:  xmp.Path("dc:type"),
   487  		Value: "three",
   488  		Flags: xmp.APPEND,
   489  	}); err != nil {
   490  		T.Errorf("unexpected error on append to existing path: %v", err)
   491  	}
   492  	l := len(c.Type)
   493  	if l != 4 {
   494  		T.Errorf("invalid len: expected=4 got=%d", l)
   495  	}
   496  	if c.Type[l-1] != "three" {
   497  		T.Errorf("invalid result: expected=three got=%s", c.Type[l-1])
   498  	}
   499  }
   500  
   501  func TestPathAppendNotExist(T *testing.T) {
   502  	d := xmp.NewDocument()
   503  	c := &dc.DublinCore{}
   504  	d.AddModel(c)
   505  	if err := d.SetPath(xmp.PathValue{
   506  		Path:  xmp.Path("dc:type"),
   507  		Value: "three",
   508  		Flags: xmp.APPEND | xmp.CREATE,
   509  	}); err != nil {
   510  		T.Errorf("expected no error on append+create to non-existing path: %v", err)
   511  	}
   512  	l := len(c.Type)
   513  	if l != 1 {
   514  		T.Errorf("invalid len: expected=1 got=%d", l)
   515  	}
   516  	if c.Type[0] != "three" {
   517  		T.Errorf("invalid result: expected=three got=%s", c.Type[0])
   518  	}
   519  }
   520  
   521  func TestPathAppendAltExist(T *testing.T) {
   522  	d := xmp.NewDocument()
   523  	c := &dc.DublinCore{
   524  		Description: xmp.NewAltString(
   525  			xmp.AltItem{Value: "german", Lang: "de", IsDefault: false},
   526  			xmp.AltItem{Value: "english", Lang: "en", IsDefault: true},
   527  		),
   528  	}
   529  	d.AddModel(c)
   530  	if err := d.SetPath(xmp.PathValue{
   531  		Path:  xmp.Path("dc:description[fi]"),
   532  		Value: "finnish",
   533  		Flags: xmp.APPEND,
   534  	}); err != nil {
   535  		T.Errorf("unexpected error on append to existing path: %v", err)
   536  	}
   537  	l := len(c.Description)
   538  	if l != 3 {
   539  		T.Errorf("invalid len: expected=3 got=%d", l)
   540  	}
   541  	if s := c.Description.Get("fi"); s != "finnish" {
   542  		T.Errorf("invalid result: expected=finnish got=%s", s)
   543  	}
   544  	if s := c.Description.Default(); s == "" {
   545  		T.Errorf("invalid result: expected not to be default")
   546  	}
   547  }
   548  
   549  func TestPathAppendAltNotExist(T *testing.T) {
   550  	d := xmp.NewDocument()
   551  	c := &dc.DublinCore{}
   552  	d.AddModel(c)
   553  	if err := d.SetPath(xmp.PathValue{
   554  		Path:  xmp.Path("dc:description[fi]"),
   555  		Value: "finnish",
   556  		Flags: xmp.APPEND | xmp.CREATE,
   557  	}); err != nil {
   558  		T.Errorf("unexpected error on append+create to non-existing path: %v", err)
   559  	}
   560  	l := len(c.Description)
   561  	if l != 1 {
   562  		T.Errorf("invalid len: expected=1 got=%d", l)
   563  	}
   564  	if s := c.Description.Get("fi"); s != "finnish" {
   565  		T.Errorf("invalid result: expected=finnish got=%s", s)
   566  	}
   567  	if s := c.Description.Default(); s == "" {
   568  		T.Errorf("invalid result: expected default")
   569  	}
   570  }
   571  
   572  func TestPathAppendUnique(T *testing.T) {
   573  	d := xmp.NewDocument()
   574  	c := &dc.DublinCore{
   575  		Type: xmp.NewStringArray("one", "two", "three"),
   576  	}
   577  	d.AddModel(c)
   578  	if err := d.SetPath(xmp.PathValue{
   579  		Path:  xmp.Path("dc:type"),
   580  		Value: "one",
   581  		Flags: xmp.APPEND | xmp.UNIQUE,
   582  	}); err != nil {
   583  		T.Errorf("unexpected error on append unique to existing path: %v", err)
   584  	}
   585  	l := len(c.Type)
   586  	if l != 3 {
   587  		T.Errorf("invalid len: expected=3 got=%d", l)
   588  	}
   589  	if c.Type[l-1] != "three" {
   590  		T.Errorf("invalid result: expected=three got=%s", c.Type[l-1])
   591  	}
   592  }
   593  
   594  func TestPathAppendUniqueAlt(T *testing.T) {
   595  	d := xmp.NewDocument()
   596  	c := &dc.DublinCore{
   597  		Description: xmp.NewAltString(
   598  			xmp.AltItem{Value: "german", Lang: "de", IsDefault: false},
   599  			xmp.AltItem{Value: "english", Lang: "en", IsDefault: true},
   600  		),
   601  	}
   602  	d.AddModel(c)
   603  	if err := d.SetPath(xmp.PathValue{
   604  		Path:  xmp.Path("dc:description[de]"),
   605  		Value: "german",
   606  		Flags: xmp.APPEND | xmp.UNIQUE,
   607  	}); err != nil {
   608  		T.Errorf("unexpected error on append unique to existing path: %v", err)
   609  	}
   610  	l := len(c.Description)
   611  	if l != 2 {
   612  		T.Errorf("invalid len: expected=2 got=%d", l)
   613  	}
   614  }
   615  
   616  func TestPathDeleteWithoutFlag(T *testing.T) {
   617  	d := xmp.NewDocument()
   618  	c := &dc.DublinCore{
   619  		Format: "old",
   620  	}
   621  	d.AddModel(c)
   622  	if err := d.SetPath(xmp.PathValue{
   623  		Path:  xmp.Path("dc:format"),
   624  		Value: "",
   625  		Flags: xmp.CREATE,
   626  	}); err == nil {
   627  		T.Errorf("unexpected nil error when deleting without flag")
   628  	}
   629  	if c.Format == "" {
   630  		T.Errorf("invalid result: expected=old got=%s", c.Format)
   631  	}
   632  	if v := dc.FindModel(d); v == nil {
   633  		T.Errorf("unexpected empty model after delete")
   634  	}
   635  }
   636  
   637  func TestPathDeleteNonExist(T *testing.T) {
   638  	d := xmp.NewDocument()
   639  	c := &dc.DublinCore{
   640  		Description: xmp.NewAltString(
   641  			xmp.AltItem{Value: "german", Lang: "de", IsDefault: false},
   642  			xmp.AltItem{Value: "english", Lang: "en", IsDefault: true},
   643  		),
   644  	}
   645  	d.AddModel(c)
   646  	if err := d.SetPath(xmp.PathValue{
   647  		Path:  xmp.Path("dc:format"),
   648  		Value: "",
   649  		Flags: xmp.DELETE,
   650  	}); err != nil {
   651  		T.Errorf("unexpected error when deleting existing path: %v", err)
   652  	}
   653  	if len(c.Description) == 0 {
   654  		T.Errorf("unexpected empty AltString")
   655  	}
   656  	if v := dc.FindModel(d); v == nil {
   657  		T.Errorf("unexpected empty model after delete")
   658  	}
   659  }
   660  
   661  func TestPathDelete(T *testing.T) {
   662  	d := xmp.NewDocument()
   663  	c := &dc.DublinCore{
   664  		Format: "old",
   665  	}
   666  	d.AddModel(c)
   667  	if err := d.SetPath(xmp.PathValue{
   668  		Path:  xmp.Path("dc:format"),
   669  		Value: "",
   670  		Flags: xmp.DELETE,
   671  	}); err != nil {
   672  		T.Errorf("unexpected error when deleting existing path: %v", err)
   673  	}
   674  	if c.Format != "" {
   675  		T.Errorf("invalid result: expected=<empty> got=%s", c.Format)
   676  	}
   677  	if v := dc.FindModel(d); v == nil {
   678  		T.Errorf("unexpected empty model after delete")
   679  	}
   680  }
   681  
   682  func TestPathDeleteSlice(T *testing.T) {
   683  	d := xmp.NewDocument()
   684  	c := &dc.DublinCore{
   685  		Type: xmp.NewStringArray("one", "two", "three"),
   686  	}
   687  	d.AddModel(c)
   688  	if err := d.SetPath(xmp.PathValue{
   689  		Path:  xmp.Path("dc:type"),
   690  		Value: "",
   691  		Flags: xmp.DELETE,
   692  	}); err != nil {
   693  		T.Errorf("unexpected error when deleting existing path: %v", err)
   694  	}
   695  	if len(c.Type) != 0 {
   696  		T.Errorf("unexpected non-empty array after delete")
   697  	}
   698  	if v := dc.FindModel(d); v == nil {
   699  		T.Errorf("unexpected empty model after delete")
   700  	}
   701  }
   702  
   703  func TestPathDeleteAltString(T *testing.T) {
   704  	d := xmp.NewDocument()
   705  	c := &dc.DublinCore{
   706  		Description: xmp.NewAltString(
   707  			xmp.AltItem{Value: "german", Lang: "de", IsDefault: false},
   708  			xmp.AltItem{Value: "english", Lang: "en", IsDefault: true},
   709  		),
   710  	}
   711  	d.AddModel(c)
   712  	if err := d.SetPath(xmp.PathValue{
   713  		Path:  xmp.Path("dc:description"),
   714  		Value: "",
   715  		Flags: xmp.DELETE,
   716  	}); err != nil {
   717  		T.Errorf("unexpected error when deleting existing path: %v", err)
   718  	}
   719  	if len(c.Description) != 0 {
   720  		T.Errorf("unexpected non-empty array after delete")
   721  	}
   722  	if v := dc.FindModel(d); v == nil {
   723  		T.Errorf("unexpected empty model after delete")
   724  	}
   725  }
   726  
   727  func TestPathDeleteFromSlice1(T *testing.T) {
   728  	d := xmp.NewDocument()
   729  	c := &dc.DublinCore{
   730  		Type: xmp.NewStringArray("one", "two", "three"),
   731  	}
   732  	d.AddModel(c)
   733  	if err := d.SetPath(xmp.PathValue{
   734  		Path:  xmp.Path("dc:type[0]"),
   735  		Value: "",
   736  		Flags: xmp.DELETE,
   737  	}); err != nil {
   738  		T.Errorf("unexpected error when deleting existing slice element: %v", err)
   739  	}
   740  	if v := dc.FindModel(d); v == nil {
   741  		T.Errorf("unexpected empty model after delete")
   742  	}
   743  	if l := len(c.Type); l != 2 {
   744  		T.Errorf("unexpected slice length after delete: expected=2 got=%d", l)
   745  		return
   746  	}
   747  	if s := c.Type[0]; s != "two" {
   748  		T.Errorf("unexpected first slice element after delete: expected=two got=%s", s)
   749  	}
   750  	if s := c.Type[1]; s != "three" {
   751  		T.Errorf("unexpected last slice element after delete: expected=three got=%s", s)
   752  	}
   753  }
   754  
   755  func TestPathDeleteFromSlice2(T *testing.T) {
   756  	d := xmp.NewDocument()
   757  	c := &dc.DublinCore{
   758  		Type: xmp.NewStringArray("one", "two", "three"),
   759  	}
   760  	d.AddModel(c)
   761  	if err := d.SetPath(xmp.PathValue{
   762  		Path:  xmp.Path("dc:type[1]"),
   763  		Value: "",
   764  		Flags: xmp.DELETE,
   765  	}); err != nil {
   766  		T.Errorf("unexpected error when deleting existing slice element: %v", err)
   767  	}
   768  	if v := dc.FindModel(d); v == nil {
   769  		T.Errorf("unexpected empty model after delete")
   770  	}
   771  	if l := len(c.Type); l != 2 {
   772  		T.Errorf("unexpected slice length after delete: expected=2 got=%d", l)
   773  		return
   774  	}
   775  	if s := c.Type[0]; s != "one" {
   776  		T.Errorf("unexpected first slice element after delete: expected=one got=%s", s)
   777  	}
   778  	if s := c.Type[1]; s != "three" {
   779  		T.Errorf("unexpected last slice element after delete: expected=three got=%s", s)
   780  	}
   781  }
   782  
   783  func TestPathDeleteFromSlice3(T *testing.T) {
   784  	d := xmp.NewDocument()
   785  	c := &dc.DublinCore{
   786  		Type: xmp.NewStringArray("one", "two", "three"),
   787  	}
   788  	d.AddModel(c)
   789  	if err := d.SetPath(xmp.PathValue{
   790  		Path:  xmp.Path("dc:type[2]"),
   791  		Value: "",
   792  		Flags: xmp.DELETE,
   793  	}); err != nil {
   794  		T.Errorf("unexpected error when deleting existing slice element: %v", err)
   795  	}
   796  	if v := dc.FindModel(d); v == nil {
   797  		T.Errorf("unexpected empty model after delete")
   798  	}
   799  	if l := len(c.Type); l != 2 {
   800  		T.Errorf("unexpected slice length after delete: expected=2 got=%d", l)
   801  		return
   802  	}
   803  	if s := c.Type[0]; s != "one" {
   804  		T.Errorf("unexpected first slice element after delete: expected=one got=%s", s)
   805  	}
   806  	if s := c.Type[1]; s != "two" {
   807  		T.Errorf("unexpected last slice element after delete: expected=two got=%s", s)
   808  	}
   809  }
   810  
   811  func TestPathDeleteFromSliceNotExist(T *testing.T) {
   812  	d := xmp.NewDocument()
   813  	c := &dc.DublinCore{
   814  		Type: xmp.NewStringArray("one", "two", "three"),
   815  	}
   816  	d.AddModel(c)
   817  	if err := d.SetPath(xmp.PathValue{
   818  		Path:  xmp.Path("dc:type[3]"),
   819  		Value: "",
   820  		Flags: xmp.DELETE,
   821  	}); err != nil {
   822  		T.Errorf("unexpected error when deleting non-existing slice element: %v", err)
   823  	}
   824  	if v := dc.FindModel(d); v == nil {
   825  		T.Errorf("unexpected empty model after delete")
   826  	}
   827  	if l := len(c.Type); l != 3 {
   828  		T.Errorf("unexpected slice length after delete: expected=3 got=%d", l)
   829  		return
   830  	}
   831  	if s := c.Type[0]; s != "one" {
   832  		T.Errorf("unexpected first slice element after delete: expected=one got=%s", s)
   833  	}
   834  	if s := c.Type[1]; s != "two" {
   835  		T.Errorf("unexpected first slice element after delete: expected=two got=%s", s)
   836  	}
   837  	if s := c.Type[2]; s != "three" {
   838  		T.Errorf("unexpected last slice element after delete: expected=three got=%s", s)
   839  	}
   840  }
   841  
   842  func TestPathDeleteFromAltString(T *testing.T) {
   843  	d := xmp.NewDocument()
   844  	c := &dc.DublinCore{
   845  		Description: xmp.NewAltString(
   846  			xmp.AltItem{Value: "german", Lang: "de", IsDefault: false},
   847  			xmp.AltItem{Value: "english", Lang: "en", IsDefault: true},
   848  		),
   849  	}
   850  	d.AddModel(c)
   851  	if err := d.SetPath(xmp.PathValue{
   852  		Path:  xmp.Path("dc:description[de]"),
   853  		Value: "",
   854  		Flags: xmp.DELETE,
   855  	}); err != nil {
   856  		T.Errorf("unexpected error when deleting existing path: %v", err)
   857  	}
   858  	if len(c.Description) != 1 {
   859  		T.Errorf("unexpected non-empty AltString after delete")
   860  	}
   861  	if v := dc.FindModel(d); v == nil {
   862  		T.Errorf("unexpected empty model after delete")
   863  	}
   864  	if s := c.Description.Get("de"); s != "" {
   865  		T.Errorf("invalid result: expected=<empty> got=%s", s)
   866  	}
   867  	if s := c.Description.Get("en"); s != "english" {
   868  		T.Errorf("invalid result: expected=english got=%s", s)
   869  	}
   870  	if s := c.Description.Default(); s != "english" {
   871  		T.Errorf("invalid default: expected=english got=%s", s)
   872  	}
   873  }
   874  
   875  func TestPathDeleteFromAltStringDefault(T *testing.T) {
   876  	d := xmp.NewDocument()
   877  	c := &dc.DublinCore{
   878  		Description: xmp.NewAltString(
   879  			xmp.AltItem{Value: "german", Lang: "de", IsDefault: false},
   880  			xmp.AltItem{Value: "english", Lang: "en", IsDefault: true},
   881  		),
   882  	}
   883  	d.AddModel(c)
   884  	if err := d.SetPath(xmp.PathValue{
   885  		Path:  xmp.Path("dc:description[en]"),
   886  		Value: "",
   887  		Flags: xmp.DELETE,
   888  	}); err != nil {
   889  		T.Errorf("unexpected error when deleting existing path: %v", err)
   890  	}
   891  	if len(c.Description) != 1 {
   892  		T.Errorf("unexpected non-empty AltString after delete")
   893  	}
   894  	if v := dc.FindModel(d); v == nil {
   895  		T.Errorf("unexpected empty model after delete")
   896  	}
   897  	if s := c.Description.Get("en"); s != "" {
   898  		T.Errorf("invalid result: expected=<empty> got=%s", s)
   899  	}
   900  	if s := c.Description.Get("de"); s != "german" {
   901  		T.Errorf("invalid result: expected=german got=%s", s)
   902  	}
   903  	if s := c.Description.Default(); s != "german" {
   904  		T.Errorf("invalid default: expected=german got=%s", s)
   905  	}
   906  }
   907  
   908  func TestPathDeleteNamespace(T *testing.T) {
   909  	d := xmp.NewDocument()
   910  	c := &dc.DublinCore{}
   911  	d.AddModel(c)
   912  	if err := d.SetPath(xmp.PathValue{
   913  		Path:  xmp.Path("dc:"),
   914  		Value: "",
   915  		Flags: xmp.DELETE,
   916  	}); err != nil {
   917  		T.Errorf("unexpected error on delete existing namespace: %v", err)
   918  	}
   919  	if v := dc.FindModel(d); v != nil {
   920  		T.Errorf("expected no model to exist")
   921  	}
   922  }