github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/libraries/doltcore/sqle/setalgebra/union_test.go (about)

     1  // Copyright 2020 Dolthub, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain 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,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package setalgebra
    16  
    17  import (
    18  	"testing"
    19  
    20  	"github.com/stretchr/testify/assert"
    21  	"github.com/stretchr/testify/require"
    22  
    23  	"github.com/dolthub/dolt/go/store/hash"
    24  	"github.com/dolthub/dolt/go/store/types"
    25  )
    26  
    27  func assertErr(t *testing.T, expectErr bool, err error) {
    28  	if expectErr {
    29  		assert.Error(t, err)
    30  	} else {
    31  		assert.NoError(t, err)
    32  	}
    33  }
    34  
    35  func mustFiniteSet(fs FiniteSet, err error) FiniteSet {
    36  	if err != nil {
    37  		panic(err)
    38  	}
    39  
    40  	return fs
    41  }
    42  
    43  func TestFiniteSetUnion(t *testing.T) {
    44  	tests := []struct {
    45  		name         string
    46  		setVals1     []types.Value
    47  		setVals2     []types.Value
    48  		expectedVals []types.Value
    49  		expectErr    bool
    50  	}{
    51  		{
    52  			"empty finite set",
    53  			[]types.Value{},
    54  			[]types.Value{},
    55  			[]types.Value{},
    56  			false,
    57  		},
    58  		{
    59  			"non overlapping",
    60  			[]types.Value{types.Int(1), types.Int(2)},
    61  			[]types.Value{types.Int(3), types.Int(4)},
    62  			[]types.Value{types.Int(1), types.Int(2), types.Int(3), types.Int(4)},
    63  			false,
    64  		},
    65  	}
    66  
    67  	for _, test := range tests {
    68  		t.Run(test.name, func(t *testing.T) {
    69  			fs1, err := NewFiniteSet(types.Format_Default, test.setVals1...)
    70  			require.NoError(t, err)
    71  
    72  			fs2, err := NewFiniteSet(types.Format_Default, test.setVals2...)
    73  			require.NoError(t, err)
    74  
    75  			res, err := finiteSetUnion(fs1, fs2)
    76  			assertErr(t, test.expectErr, err)
    77  
    78  			expected, err := NewFiniteSet(types.Format_Default, test.expectedVals...)
    79  			require.NoError(t, err)
    80  
    81  			assert.Equal(t, expected, res)
    82  		})
    83  	}
    84  }
    85  
    86  func TestFiniteSetIntervalUnion(t *testing.T) {
    87  	tests := []struct {
    88  		name      string
    89  		setVals   []types.Value
    90  		in        Interval
    91  		expected  Set
    92  		expectErr bool
    93  	}{
    94  		{
    95  			"interval contains set",
    96  			[]types.Value{types.Int(0), types.Int(5), types.Int(10)},
    97  			Interval{
    98  				types.Format_Default,
    99  				&IntervalEndpoint{types.Int(0), true},
   100  				&IntervalEndpoint{types.Int(10), true},
   101  			},
   102  			Interval{
   103  				types.Format_Default,
   104  				&IntervalEndpoint{types.Int(0), true},
   105  				&IntervalEndpoint{types.Int(10), true},
   106  			},
   107  			false,
   108  		},
   109  		{
   110  			"some of set outside interval",
   111  			[]types.Value{types.Int(0), types.Int(5), types.Int(20)},
   112  			Interval{
   113  				types.Format_Default,
   114  				&IntervalEndpoint{types.Int(0), true},
   115  				&IntervalEndpoint{types.Int(10), true},
   116  			},
   117  			CompositeSet{
   118  				mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(20))),
   119  				[]Interval{
   120  					{
   121  						types.Format_Default,
   122  						&IntervalEndpoint{types.Int(0), true},
   123  						&IntervalEndpoint{types.Int(10), true},
   124  					},
   125  				},
   126  			},
   127  			false,
   128  		},
   129  		{
   130  			"open intervals",
   131  			[]types.Value{types.Int(0), types.Int(5), types.Int(10)},
   132  			Interval{
   133  				types.Format_Default,
   134  				&IntervalEndpoint{types.Int(0), false},
   135  				&IntervalEndpoint{types.Int(10), false},
   136  			},
   137  			Interval{
   138  				types.Format_Default,
   139  				&IntervalEndpoint{types.Int(0), true},
   140  				&IntervalEndpoint{types.Int(10), true},
   141  			},
   142  			false,
   143  		},
   144  		{
   145  			"negative infinity",
   146  			[]types.Value{types.Int(0), types.Int(5), types.Int(10)},
   147  			Interval{
   148  				types.Format_Default,
   149  				nil,
   150  				&IntervalEndpoint{types.Int(10), true},
   151  			},
   152  			Interval{
   153  				types.Format_Default,
   154  				nil,
   155  				&IntervalEndpoint{types.Int(10), true},
   156  			},
   157  			false,
   158  		},
   159  		{
   160  			"positive infinity",
   161  			[]types.Value{types.Int(0), types.Int(5), types.Int(10)},
   162  			Interval{
   163  				types.Format_Default,
   164  				&IntervalEndpoint{types.Int(0), true},
   165  				nil,
   166  			},
   167  			Interval{
   168  				types.Format_Default,
   169  				&IntervalEndpoint{types.Int(0), true},
   170  				nil,
   171  			},
   172  			false,
   173  		},
   174  		{
   175  			"negative to positive infinity",
   176  			[]types.Value{types.Int(0), types.Int(5), types.Int(10)},
   177  			Interval{
   178  				types.Format_Default,
   179  				nil,
   180  				nil,
   181  			},
   182  			Interval{
   183  				types.Format_Default,
   184  				nil,
   185  				nil,
   186  			},
   187  			false,
   188  		},
   189  	}
   190  
   191  	for _, test := range tests {
   192  		t.Run(test.name, func(t *testing.T) {
   193  			fs, err := NewFiniteSet(types.Format_Default, test.setVals...)
   194  			require.NoError(t, err)
   195  
   196  			res, err := finiteSetIntervalUnion(fs, test.in)
   197  			assert.NoError(t, err)
   198  
   199  			assert.Equal(t, test.expected, res)
   200  		})
   201  	}
   202  }
   203  
   204  func TestFiniteSetCompositeSetUnion(t *testing.T) {
   205  	tests := []struct {
   206  		name      string
   207  		setVals   []types.Value
   208  		cs        CompositeSet
   209  		expected  Set
   210  		expectErr bool
   211  	}{
   212  		{
   213  			"empty set",
   214  			[]types.Value{},
   215  			CompositeSet{
   216  				mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(20))),
   217  				[]Interval{
   218  					{
   219  						types.Format_Default,
   220  						&IntervalEndpoint{types.Int(0), true},
   221  						&IntervalEndpoint{types.Int(10), true},
   222  					},
   223  				},
   224  			},
   225  			CompositeSet{
   226  				mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(20))),
   227  				[]Interval{
   228  					{
   229  						types.Format_Default,
   230  						&IntervalEndpoint{types.Int(0), true},
   231  						&IntervalEndpoint{types.Int(10), true},
   232  					},
   233  				},
   234  			},
   235  			false,
   236  		},
   237  		{
   238  			"set with contained and uncontained vals",
   239  			[]types.Value{types.Int(-10), types.Int(0), types.Int(10), types.Int(20), types.Int(30)},
   240  			CompositeSet{
   241  				mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(20))),
   242  				[]Interval{
   243  					{
   244  						types.Format_Default,
   245  						&IntervalEndpoint{types.Int(0), true},
   246  						&IntervalEndpoint{types.Int(10), true},
   247  					},
   248  				},
   249  			},
   250  			CompositeSet{
   251  				mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(-10), types.Int(20), types.Int(30))),
   252  				[]Interval{
   253  					{
   254  						types.Format_Default,
   255  						&IntervalEndpoint{types.Int(0), true},
   256  						&IntervalEndpoint{types.Int(10), true},
   257  					},
   258  				},
   259  			},
   260  			false,
   261  		},
   262  		{
   263  			"composite set with multiple intervals",
   264  			[]types.Value{types.Int(-10), types.Int(0), types.Int(10), types.Int(20), types.Int(30), types.Int(99), types.Int(100), types.Int(0x7FFFFFFFFFFFFFFF)},
   265  			CompositeSet{
   266  				mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(20))),
   267  				[]Interval{
   268  					{
   269  						types.Format_Default,
   270  						&IntervalEndpoint{types.Int(0), true},
   271  						&IntervalEndpoint{types.Int(10), true},
   272  					},
   273  					{
   274  						types.Format_Default,
   275  						&IntervalEndpoint{types.Int(100), true},
   276  						nil,
   277  					},
   278  				},
   279  			},
   280  			CompositeSet{
   281  				mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(-10), types.Int(20), types.Int(30), types.Int(99))),
   282  				[]Interval{
   283  					{
   284  						types.Format_Default,
   285  						&IntervalEndpoint{types.Int(0), true},
   286  						&IntervalEndpoint{types.Int(10), true},
   287  					},
   288  					{
   289  						types.Format_Default,
   290  						&IntervalEndpoint{types.Int(100), true},
   291  						nil,
   292  					},
   293  				},
   294  			},
   295  			false,
   296  		},
   297  	}
   298  
   299  	for _, test := range tests {
   300  		t.Run(test.name, func(t *testing.T) {
   301  			fs, err := NewFiniteSet(types.Format_Default, test.setVals...)
   302  			require.NoError(t, err)
   303  
   304  			res, err := finiteSetCompositeSetUnion(fs, test.cs)
   305  			assert.NoError(t, err)
   306  
   307  			assert.Equal(t, test.expected, res)
   308  		})
   309  	}
   310  }
   311  
   312  func TestIntervalUnion(t *testing.T) {
   313  	tests := []struct {
   314  		name      string
   315  		in1       Interval
   316  		in2       Interval
   317  		expected  Set
   318  		expectErr bool
   319  	}{
   320  		{
   321  			"No overlap",
   322  			Interval{
   323  				types.Format_Default,
   324  				&IntervalEndpoint{types.Int(0), true},
   325  				&IntervalEndpoint{types.Int(10), false},
   326  			},
   327  			Interval{
   328  				types.Format_Default,
   329  				&IntervalEndpoint{types.Int(10), false},
   330  				&IntervalEndpoint{types.Int(20), true},
   331  			},
   332  			CompositeSet{
   333  				FiniteSet{make(map[hash.Hash]types.Value)},
   334  				[]Interval{
   335  					{
   336  						types.Format_Default,
   337  						&IntervalEndpoint{types.Int(0), true},
   338  						&IntervalEndpoint{types.Int(10), false},
   339  					},
   340  					{
   341  						types.Format_Default,
   342  						&IntervalEndpoint{types.Int(10), false},
   343  						&IntervalEndpoint{types.Int(20), true},
   344  					},
   345  				},
   346  			},
   347  			false,
   348  		},
   349  		{
   350  			"overlap at endpoints",
   351  			Interval{
   352  				types.Format_Default,
   353  				&IntervalEndpoint{types.Int(0), true},
   354  				&IntervalEndpoint{types.Int(10), true},
   355  			},
   356  			Interval{
   357  				types.Format_Default,
   358  				&IntervalEndpoint{types.Int(10), true},
   359  				&IntervalEndpoint{types.Int(20), true},
   360  			},
   361  			Interval{
   362  				types.Format_Default,
   363  				&IntervalEndpoint{types.Int(0), true},
   364  				&IntervalEndpoint{types.Int(20), true},
   365  			},
   366  			false,
   367  		},
   368  		{
   369  			"fully enclose interval",
   370  			Interval{
   371  				types.Format_Default,
   372  				&IntervalEndpoint{types.Int(0), true},
   373  				&IntervalEndpoint{types.Int(20), true},
   374  			},
   375  			Interval{
   376  				types.Format_Default,
   377  				&IntervalEndpoint{types.Int(5), true},
   378  				&IntervalEndpoint{types.Int(15), true},
   379  			},
   380  			Interval{
   381  				types.Format_Default,
   382  				&IntervalEndpoint{types.Int(0), true},
   383  				&IntervalEndpoint{types.Int(20), true},
   384  			},
   385  			false,
   386  		},
   387  		{
   388  			"overlap with infinite interval",
   389  			Interval{
   390  				types.Format_Default,
   391  				&IntervalEndpoint{types.Int(10), true},
   392  				nil,
   393  			},
   394  			Interval{
   395  				types.Format_Default,
   396  				&IntervalEndpoint{types.Int(0), true},
   397  				&IntervalEndpoint{types.Int(20), true},
   398  			},
   399  			Interval{
   400  				types.Format_Default,
   401  				&IntervalEndpoint{types.Int(0), true},
   402  				nil,
   403  			},
   404  			false,
   405  		},
   406  		{
   407  			"No overlap",
   408  			Interval{
   409  				types.Format_Default,
   410  				&IntervalEndpoint{types.Int(10), true},
   411  				nil,
   412  			},
   413  			Interval{
   414  				types.Format_Default,
   415  				nil,
   416  				&IntervalEndpoint{types.Int(0), true},
   417  			},
   418  			CompositeSet{
   419  				FiniteSet{make(map[hash.Hash]types.Value)},
   420  				[]Interval{
   421  					{
   422  						types.Format_Default,
   423  						nil,
   424  						&IntervalEndpoint{types.Int(0), true},
   425  					},
   426  					{
   427  						types.Format_Default,
   428  						&IntervalEndpoint{types.Int(10), true},
   429  						nil,
   430  					},
   431  				},
   432  			},
   433  			false,
   434  		},
   435  		{
   436  			"Overlap at closed endpoint",
   437  			Interval{
   438  				types.Format_Default,
   439  				&IntervalEndpoint{types.Int(10), true},
   440  				nil,
   441  			},
   442  			Interval{
   443  				types.Format_Default,
   444  				nil,
   445  				&IntervalEndpoint{types.Int(10), true},
   446  			},
   447  			UniversalSet{},
   448  			false,
   449  		},
   450  		{
   451  			"overlapping at open endpoint",
   452  			Interval{
   453  				types.Format_Default,
   454  				&IntervalEndpoint{types.Int(10), false},
   455  				nil,
   456  			},
   457  			Interval{
   458  				types.Format_Default,
   459  				nil,
   460  				&IntervalEndpoint{types.Int(10), false},
   461  			},
   462  			CompositeSet{
   463  				FiniteSet{make(map[hash.Hash]types.Value)},
   464  				[]Interval{
   465  					{
   466  						types.Format_Default,
   467  						nil,
   468  						&IntervalEndpoint{types.Int(10), false},
   469  					},
   470  					{
   471  						types.Format_Default,
   472  						&IntervalEndpoint{types.Int(10), false},
   473  						nil,
   474  					},
   475  				},
   476  			},
   477  			false,
   478  		},
   479  		{
   480  			"finite interval start equal to infinite interval end",
   481  			Interval{
   482  				types.Format_Default,
   483  				nil,
   484  				&IntervalEndpoint{types.Int(10), false},
   485  			},
   486  			Interval{
   487  				types.Format_Default,
   488  				&IntervalEndpoint{types.Int(10), true},
   489  				&IntervalEndpoint{types.Int(20), false},
   490  			},
   491  			Interval{
   492  				types.Format_Default,
   493  				nil,
   494  				&IntervalEndpoint{types.Int(20), false},
   495  			},
   496  			false,
   497  		},
   498  		{
   499  			"finite interval start equal to infinite interval end 2",
   500  			Interval{
   501  				types.Format_Default,
   502  				&IntervalEndpoint{types.Int(10), true},
   503  				&IntervalEndpoint{types.Int(20), false},
   504  			},
   505  			Interval{
   506  				types.Format_Default,
   507  				nil,
   508  				&IntervalEndpoint{types.Int(10), false},
   509  			},
   510  			Interval{
   511  				types.Format_Default,
   512  				nil,
   513  				&IntervalEndpoint{types.Int(20), false},
   514  			},
   515  			false,
   516  		},
   517  		{
   518  			"finite interval start and end less than infinite end",
   519  			Interval{
   520  				types.Format_Default,
   521  				&IntervalEndpoint{types.Int(10), true},
   522  				&IntervalEndpoint{types.Int(15), false},
   523  			},
   524  			Interval{
   525  				types.Format_Default,
   526  				nil,
   527  				&IntervalEndpoint{types.Int(20), false},
   528  			},
   529  			Interval{
   530  				types.Format_Default,
   531  				nil,
   532  				&IntervalEndpoint{types.Int(20), false},
   533  			},
   534  			false,
   535  		},
   536  
   537  		{
   538  			"infinite interval end between finite interval start and end",
   539  			Interval{
   540  				types.Format_Default,
   541  				&IntervalEndpoint{types.Int(10), true},
   542  				&IntervalEndpoint{types.Int(25), false},
   543  			},
   544  			Interval{
   545  				types.Format_Default,
   546  				nil,
   547  				&IntervalEndpoint{types.Int(20), false},
   548  			},
   549  			Interval{
   550  				types.Format_Default,
   551  				nil,
   552  				&IntervalEndpoint{types.Int(25), false},
   553  			},
   554  			false,
   555  		},
   556  		{
   557  			"no overlap between finite interval and infinite interval",
   558  			Interval{
   559  				types.Format_Default,
   560  				&IntervalEndpoint{types.Int(20), false},
   561  				&IntervalEndpoint{types.Int(30), false},
   562  			},
   563  			Interval{
   564  				types.Format_Default,
   565  				nil,
   566  				&IntervalEndpoint{types.Int(10), false},
   567  			},
   568  			CompositeSet{
   569  				FiniteSet{make(map[hash.Hash]types.Value)},
   570  				[]Interval{
   571  					{
   572  						types.Format_Default,
   573  						nil,
   574  						&IntervalEndpoint{types.Int(10), false},
   575  					},
   576  					{
   577  						types.Format_Default,
   578  						&IntervalEndpoint{types.Int(20), false},
   579  						&IntervalEndpoint{types.Int(30), false},
   580  					},
   581  				},
   582  			},
   583  			false,
   584  		},
   585  		{
   586  			"in1 < in2",
   587  			Interval{
   588  				types.Format_Default,
   589  				nil,
   590  				&IntervalEndpoint{types.Int(5), false},
   591  			},
   592  			Interval{
   593  				types.Format_Default,
   594  				nil,
   595  				&IntervalEndpoint{types.Int(10), false},
   596  			},
   597  			Interval{
   598  				types.Format_Default,
   599  				nil,
   600  				&IntervalEndpoint{types.Int(10), false},
   601  			},
   602  			false,
   603  		},
   604  		{
   605  			"in1 > in2",
   606  			Interval{
   607  				types.Format_Default,
   608  				nil,
   609  				&IntervalEndpoint{types.Int(10), false},
   610  			},
   611  			Interval{
   612  				types.Format_Default,
   613  				nil,
   614  				&IntervalEndpoint{types.Int(5), false},
   615  			},
   616  			Interval{
   617  				types.Format_Default,
   618  				nil,
   619  				&IntervalEndpoint{types.Int(10), false},
   620  			},
   621  			false,
   622  		},
   623  
   624  		{
   625  			"in1 == in2, in1 inclusive",
   626  			Interval{
   627  				types.Format_Default,
   628  				nil,
   629  				&IntervalEndpoint{types.Int(10), true},
   630  			},
   631  			Interval{
   632  				types.Format_Default,
   633  				nil,
   634  				&IntervalEndpoint{types.Int(10), false},
   635  			},
   636  			Interval{
   637  				types.Format_Default,
   638  				nil,
   639  				&IntervalEndpoint{types.Int(10), true},
   640  			},
   641  			false,
   642  		},
   643  
   644  		{
   645  			"in1 == in2, in2 inclusive",
   646  			Interval{
   647  				types.Format_Default,
   648  				nil,
   649  				&IntervalEndpoint{types.Int(10), false},
   650  			},
   651  			Interval{
   652  				types.Format_Default,
   653  				nil,
   654  				&IntervalEndpoint{types.Int(10), true},
   655  			},
   656  			Interval{
   657  				types.Format_Default,
   658  				nil,
   659  				&IntervalEndpoint{types.Int(10), true},
   660  			},
   661  			false,
   662  		},
   663  	}
   664  
   665  	for _, test := range tests {
   666  		t.Run(test.name, func(t *testing.T) {
   667  			res, err := intervalUnion(test.in1, test.in2)
   668  			assertErr(t, test.expectErr, err)
   669  
   670  			assert.Equal(t, test.expected, res)
   671  		})
   672  	}
   673  }
   674  
   675  func TestIntervalCompositeSetUnion(t *testing.T) {
   676  	tests := []struct {
   677  		name      string
   678  		in        Interval
   679  		cs        CompositeSet
   680  		expected  Set
   681  		expectErr bool
   682  	}{
   683  		{
   684  			"make universal set",
   685  			testInterv(&IntervalEndpoint{types.Int(0), true}, nil),
   686  			CompositeSet{
   687  				mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(10), types.Int(20))),
   688  				[]Interval{
   689  					testInterv(nil, &IntervalEndpoint{types.Int(0), true}),
   690  				},
   691  			},
   692  			UniversalSet{},
   693  			false,
   694  		},
   695  		{
   696  			"multiple intervals one overlapping",
   697  			testInterv(&IntervalEndpoint{types.Int(20), true}, &IntervalEndpoint{types.Int(30), true}),
   698  			CompositeSet{
   699  				mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(10), types.Int(30))),
   700  				[]Interval{
   701  					testInterv(nil, &IntervalEndpoint{types.Int(0), true}),
   702  					testInterv(&IntervalEndpoint{types.Int(15), true}, &IntervalEndpoint{types.Int(25), true}),
   703  					testInterv(&IntervalEndpoint{types.Int(50), true}, &IntervalEndpoint{types.Int(100), true}),
   704  				},
   705  			},
   706  			CompositeSet{
   707  				mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(10))),
   708  				[]Interval{
   709  					testInterv(nil, &IntervalEndpoint{types.Int(0), true}),
   710  					testInterv(&IntervalEndpoint{types.Int(15), true}, &IntervalEndpoint{types.Int(30), true}),
   711  					testInterv(&IntervalEndpoint{types.Int(50), true}, &IntervalEndpoint{types.Int(100), true}),
   712  				},
   713  			},
   714  			false,
   715  		},
   716  
   717  		{
   718  			"Join two intervals",
   719  			testInterv(&IntervalEndpoint{types.Int(20), true}, &IntervalEndpoint{types.Int(30), true}),
   720  			CompositeSet{
   721  				mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(25))),
   722  				[]Interval{
   723  					testInterv(&IntervalEndpoint{types.Int(0), true}, &IntervalEndpoint{types.Int(20), false}),
   724  					testInterv(&IntervalEndpoint{types.Int(30), false}, &IntervalEndpoint{types.Int(100), true}),
   725  				},
   726  			},
   727  			testInterv(&IntervalEndpoint{types.Int(0), true}, &IntervalEndpoint{types.Int(100), true}),
   728  			false,
   729  		},
   730  	}
   731  
   732  	for _, test := range tests {
   733  		t.Run(test.name, func(t *testing.T) {
   734  			res, err := intervalCompositeSetUnion(test.in, test.cs)
   735  			assertErr(t, test.expectErr, err)
   736  
   737  			assert.Equal(t, test.expected, res)
   738  		})
   739  	}
   740  }
   741  
   742  func TestCompositeSetUnion(t *testing.T) {
   743  	tests := []struct {
   744  		name      string
   745  		cs1       CompositeSet
   746  		cs2       CompositeSet
   747  		expected  Set
   748  		expectErr bool
   749  	}{
   750  		{
   751  			"make universal set",
   752  			CompositeSet{
   753  				FiniteSet{make(map[hash.Hash]types.Value)},
   754  				[]Interval{testInterv(&IntervalEndpoint{types.Int(0), true}, nil)},
   755  			},
   756  			CompositeSet{
   757  				mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(10), types.Int(20))),
   758  				[]Interval{
   759  					testInterv(nil, &IntervalEndpoint{types.Int(0), true}),
   760  				},
   761  			},
   762  			UniversalSet{},
   763  			false,
   764  		},
   765  		{
   766  			"multiple intervals one overlapping",
   767  			CompositeSet{
   768  				FiniteSet{make(map[hash.Hash]types.Value)},
   769  				[]Interval{
   770  					testInterv(&IntervalEndpoint{types.Int(20), true}, &IntervalEndpoint{types.Int(30), true}),
   771  				},
   772  			},
   773  			CompositeSet{
   774  				mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(10), types.Int(30))),
   775  				[]Interval{
   776  					testInterv(nil, &IntervalEndpoint{types.Int(0), true}),
   777  					testInterv(&IntervalEndpoint{types.Int(15), true}, &IntervalEndpoint{types.Int(25), true}),
   778  					testInterv(&IntervalEndpoint{types.Int(50), true}, &IntervalEndpoint{types.Int(100), true}),
   779  				},
   780  			},
   781  			CompositeSet{
   782  				mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(10))),
   783  				[]Interval{
   784  					testInterv(nil, &IntervalEndpoint{types.Int(0), true}),
   785  					testInterv(&IntervalEndpoint{types.Int(15), true}, &IntervalEndpoint{types.Int(30), true}),
   786  					testInterv(&IntervalEndpoint{types.Int(50), true}, &IntervalEndpoint{types.Int(100), true}),
   787  				},
   788  			},
   789  			false,
   790  		},
   791  
   792  		{
   793  			"Join two intervals",
   794  			CompositeSet{
   795  				FiniteSet{make(map[hash.Hash]types.Value)},
   796  				[]Interval{
   797  					testInterv(&IntervalEndpoint{types.Int(20), true}, &IntervalEndpoint{types.Int(30), true}),
   798  				},
   799  			},
   800  			CompositeSet{
   801  				mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(25))),
   802  				[]Interval{
   803  					testInterv(&IntervalEndpoint{types.Int(0), true}, &IntervalEndpoint{types.Int(20), false}),
   804  					testInterv(&IntervalEndpoint{types.Int(30), false}, &IntervalEndpoint{types.Int(100), true}),
   805  				},
   806  			},
   807  			testInterv(&IntervalEndpoint{types.Int(0), true}, &IntervalEndpoint{types.Int(100), true}),
   808  			false,
   809  		},
   810  
   811  		{
   812  			"multiple intervals in multiple composite sets",
   813  			CompositeSet{
   814  				mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(10), types.Int(15), types.Int(400))),
   815  				[]Interval{
   816  					testInterv(&IntervalEndpoint{types.Int(20), true}, &IntervalEndpoint{types.Int(30), true}),
   817  					testInterv(&IntervalEndpoint{types.Int(50), true}, &IntervalEndpoint{types.Int(100), true}),
   818  					testInterv(&IntervalEndpoint{types.Int(200), true}, &IntervalEndpoint{types.Int(300), true}),
   819  				},
   820  			},
   821  			CompositeSet{
   822  				mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(1), types.Int(10), types.Int(30))),
   823  				[]Interval{
   824  					testInterv(nil, &IntervalEndpoint{types.Int(0), true}),
   825  					testInterv(&IntervalEndpoint{types.Int(15), true}, &IntervalEndpoint{types.Int(25), true}),
   826  					testInterv(&IntervalEndpoint{types.Int(50), true}, &IntervalEndpoint{types.Int(100), true}),
   827  				},
   828  			},
   829  			CompositeSet{
   830  				mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(1), types.Int(10), types.Int(400))),
   831  				[]Interval{
   832  					testInterv(nil, &IntervalEndpoint{types.Int(0), true}),
   833  					testInterv(&IntervalEndpoint{types.Int(15), true}, &IntervalEndpoint{types.Int(30), true}),
   834  					testInterv(&IntervalEndpoint{types.Int(50), true}, &IntervalEndpoint{types.Int(100), true}),
   835  					testInterv(&IntervalEndpoint{types.Int(200), true}, &IntervalEndpoint{types.Int(300), true}),
   836  				},
   837  			},
   838  			false,
   839  		},
   840  	}
   841  
   842  	for _, test := range tests {
   843  		t.Run(test.name, func(t *testing.T) {
   844  			res, err := compositeUnion(test.cs1, test.cs2)
   845  			assertErr(t, test.expectErr, err)
   846  
   847  			assert.Equal(t, test.expected, res)
   848  		})
   849  	}
   850  
   851  }