github.com/cayleygraph/cayley@v0.7.7/graph/iterator/or_test.go (about)

     1  // Copyright 2014 The Cayley Authors. All rights reserved.
     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 iterator_test
    16  
    17  import (
    18  	"context"
    19  	"errors"
    20  	"reflect"
    21  	"testing"
    22  
    23  	"github.com/cayleygraph/cayley/graph"
    24  	. "github.com/cayleygraph/cayley/graph/iterator"
    25  )
    26  
    27  func iterated(it graph.Iterator) []int {
    28  	ctx := context.TODO()
    29  	var res []int
    30  	for it.Next(ctx) {
    31  		res = append(res, int(it.Result().(Int64Node)))
    32  	}
    33  	return res
    34  }
    35  
    36  func TestOrIteratorBasics(t *testing.T) {
    37  	ctx := context.TODO()
    38  	or := NewOr()
    39  	f1 := NewFixed(
    40  		Int64Node(1),
    41  		Int64Node(2),
    42  		Int64Node(3),
    43  	)
    44  	f2 := NewFixed(
    45  		Int64Node(3),
    46  		Int64Node(9),
    47  		Int64Node(20),
    48  		Int64Node(21),
    49  	)
    50  	or.AddSubIterator(f1)
    51  	or.AddSubIterator(f2)
    52  
    53  	if v, _ := or.Size(); v != 7 {
    54  		t.Errorf("Unexpected iterator size, got:%d expected %d", v, 7)
    55  	}
    56  
    57  	expect := []int{1, 2, 3, 3, 9, 20, 21}
    58  	for i := 0; i < 2; i++ {
    59  		if got := iterated(or); !reflect.DeepEqual(got, expect) {
    60  			t.Errorf("Failed to iterate Or correctly on repeat %d, got:%v expect:%v", i, got, expect)
    61  		}
    62  		or.Reset()
    63  	}
    64  
    65  	// Check that optimization works.
    66  	optOr, _ := or.Optimize()
    67  	if got := iterated(optOr); !reflect.DeepEqual(got, expect) {
    68  		t.Errorf("Failed to iterate optimized Or correctly, got:%v expect:%v", got, expect)
    69  	}
    70  
    71  	for _, v := range []int{2, 3, 21} {
    72  		if !or.Contains(ctx, Int64Node(v)) {
    73  			t.Errorf("Failed to correctly check %d as true", v)
    74  		}
    75  	}
    76  
    77  	for _, v := range []int{22, 5, 0} {
    78  		if or.Contains(ctx, Int64Node(v)) {
    79  			t.Errorf("Failed to correctly check %d as false", v)
    80  		}
    81  	}
    82  }
    83  
    84  func TestShortCircuitingOrBasics(t *testing.T) {
    85  	ctx := context.TODO()
    86  	var or *Or
    87  
    88  	f1 := NewFixed(
    89  		Int64Node(1),
    90  		Int64Node(2),
    91  		Int64Node(3),
    92  	)
    93  	f2 := NewFixed(
    94  		Int64Node(3),
    95  		Int64Node(9),
    96  		Int64Node(20),
    97  		Int64Node(21),
    98  	)
    99  
   100  	or = NewShortCircuitOr()
   101  	or.AddSubIterator(f1)
   102  	or.AddSubIterator(f2)
   103  	f2.Reset()
   104  	size, exact := or.Size()
   105  	if size != 4 {
   106  		t.Errorf("Unexpected iterator size, got:%d expected %d", size, 4)
   107  	}
   108  	if !exact {
   109  		t.Error("Size not exact.")
   110  	}
   111  
   112  	// It should extract the first iterators' numbers.
   113  	or = NewShortCircuitOr()
   114  	or.AddSubIterator(f1)
   115  	or.AddSubIterator(f2)
   116  	f2.Reset()
   117  	expect := []int{1, 2, 3}
   118  	for i := 0; i < 2; i++ {
   119  		if got := iterated(or); !reflect.DeepEqual(got, expect) {
   120  			t.Errorf("Failed to iterate Or correctly on repeat %d, got:%v expect:%v", i, got, expect)
   121  		}
   122  		or.Reset()
   123  	}
   124  
   125  	// Check optimization works.
   126  	optOr, _ := or.Optimize()
   127  	if got := iterated(optOr); !reflect.DeepEqual(got, expect) {
   128  		t.Errorf("Failed to iterate optimized Or correctly, got:%v expect:%v", got, expect)
   129  	}
   130  
   131  	// Check that numbers in either iterator exist.
   132  	or = NewShortCircuitOr()
   133  	or.AddSubIterator(f1)
   134  	or.AddSubIterator(f2)
   135  	f2.Reset()
   136  	for _, v := range []int{2, 3, 21} {
   137  		if !or.Contains(ctx, Int64Node(v)) {
   138  			t.Errorf("Failed to correctly check %d as true", v)
   139  		}
   140  	}
   141  	for _, v := range []int{22, 5, 0} {
   142  		if or.Contains(ctx, Int64Node(v)) {
   143  			t.Errorf("Failed to correctly check %d as false", v)
   144  		}
   145  	}
   146  
   147  	// Check that it pulls the second iterator's numbers if the first is empty.
   148  	or = NewShortCircuitOr()
   149  	or.AddSubIterator(NewFixed())
   150  	or.AddSubIterator(f2)
   151  	f2.Reset()
   152  	expect = []int{3, 9, 20, 21}
   153  	for i := 0; i < 2; i++ {
   154  		if got := iterated(or); !reflect.DeepEqual(got, expect) {
   155  			t.Errorf("Failed to iterate Or correctly on repeat %d, got:%v expect:%v", i, got, expect)
   156  		}
   157  		or.Reset()
   158  	}
   159  	// Check optimization works.
   160  	optOr, _ = or.Optimize()
   161  	if got := iterated(optOr); !reflect.DeepEqual(got, expect) {
   162  		t.Errorf("Failed to iterate optimized Or correctly, got:%v expect:%v", got, expect)
   163  	}
   164  }
   165  
   166  func TestOrIteratorErr(t *testing.T) {
   167  	ctx := context.TODO()
   168  	wantErr := errors.New("unique")
   169  	orErr := newTestIterator(false, wantErr)
   170  
   171  	fix1 := NewFixed(Int64Node(1))
   172  
   173  	or := NewOr(
   174  		fix1,
   175  		orErr,
   176  		newInt64(1, 5, true),
   177  	)
   178  
   179  	if !or.Next(ctx) {
   180  		t.Errorf("Failed to iterate Or correctly")
   181  	}
   182  	if got := or.Result(); got.(Int64Node) != 1 {
   183  		t.Errorf("Failed to iterate Or correctly, got:%v expect:1", got)
   184  	}
   185  
   186  	if or.Next(ctx) != false {
   187  		t.Errorf("Or iterator did not pass through underlying 'false'")
   188  	}
   189  	if or.Err() != wantErr {
   190  		t.Errorf("Or iterator did not pass through underlying Err")
   191  	}
   192  }
   193  
   194  func TestShortCircuitOrIteratorErr(t *testing.T) {
   195  	ctx := context.TODO()
   196  	wantErr := errors.New("unique")
   197  	orErr := newTestIterator(false, wantErr)
   198  
   199  	or := NewOr(
   200  		orErr,
   201  		newInt64(1, 5, true),
   202  	)
   203  
   204  	if or.Next(ctx) != false {
   205  		t.Errorf("Or iterator did not pass through underlying 'false'")
   206  	}
   207  	if or.Err() != wantErr {
   208  		t.Errorf("Or iterator did not pass through underlying Err")
   209  	}
   210  }