github.com/grailbio/bigslice@v0.0.0-20230519005545-30c4c12152ad/typecheck/func_test.go (about)

     1  // Copyright 2018 GRAIL, Inc. All rights reserved.
     2  // Use of this source code is governed by the Apache 2.0
     3  // license that can be found in the LICENSE file.
     4  
     5  package typecheck
     6  
     7  import (
     8  	"fmt"
     9  	"reflect"
    10  	"testing"
    11  
    12  	"github.com/grailbio/bigslice/slicefunc"
    13  	"github.com/grailbio/bigslice/slicetype"
    14  )
    15  
    16  type testStringer struct{}
    17  
    18  func (testStringer) String() string {
    19  	return "testStringer"
    20  }
    21  
    22  var typeOfTestStringer = reflect.TypeOf(testStringer{})
    23  
    24  // TestCanApply verifies basic handling of function and argument types.
    25  func TestCanApply(t *testing.T) {
    26  	fn, ok := slicefunc.Of(func(int, string) string { return "" })
    27  	if !ok {
    28  		t.Fatal("not a func")
    29  	}
    30  	for _, c := range []struct {
    31  		args     []reflect.Type
    32  		canApply bool
    33  	}{
    34  		{[]reflect.Type{}, false},
    35  		{[]reflect.Type{typeOfInt}, false},
    36  		{[]reflect.Type{typeOfString}, false},
    37  		{[]reflect.Type{typeOfInt, typeOfString}, true},
    38  		{[]reflect.Type{typeOfInt, typeOfString, typeOfString}, false},
    39  		{[]reflect.Type{typeOfInt, typeOfString, typeOfBool}, false},
    40  	} {
    41  		argTyp := slicetype.New(c.args...)
    42  		if got, want := CanApply(fn, argTyp), c.canApply; got != want {
    43  			t.Errorf("got %v, want %v", got, want)
    44  		}
    45  	}
    46  }
    47  
    48  // TestCanApplyVariadic verifies the ability to apply a variadic function is
    49  // properly evaluated.
    50  func TestCanApplyVariadic(t *testing.T) {
    51  	fn, ok := slicefunc.Of(func(int, ...string) string { return "" })
    52  	if !ok {
    53  		t.Fatal("not a func")
    54  	}
    55  	for _, c := range []struct {
    56  		args     []reflect.Type
    57  		canApply bool
    58  	}{
    59  		{[]reflect.Type{}, false},
    60  		{[]reflect.Type{typeOfInt}, true},
    61  		{[]reflect.Type{typeOfString}, false},
    62  		{[]reflect.Type{typeOfInt, typeOfString}, true},
    63  		{[]reflect.Type{typeOfInt, typeOfString, typeOfString}, true},
    64  		{[]reflect.Type{typeOfInt, typeOfString, typeOfBool}, false},
    65  	} {
    66  		argTyp := slicetype.New(c.args...)
    67  		if got, want := CanApply(fn, argTyp), c.canApply; got != want {
    68  			t.Errorf("got %v, want %v", got, want)
    69  		}
    70  	}
    71  }
    72  
    73  // TestCanApplyInterface verifies that types that implement interfaces can be
    74  // passed as their interface types.
    75  func TestCanApplyInterface(t *testing.T) {
    76  	fn, ok := slicefunc.Of(func(int, fmt.Stringer) string { return "" })
    77  	if !ok {
    78  		t.Fatal("not a func")
    79  	}
    80  	for _, c := range []struct {
    81  		args     []reflect.Type
    82  		canApply bool
    83  	}{
    84  		{[]reflect.Type{}, false},
    85  		{[]reflect.Type{typeOfInt}, false},
    86  		{[]reflect.Type{typeOfString}, false},
    87  		{[]reflect.Type{typeOfInt, typeOfString}, false},
    88  		{[]reflect.Type{typeOfInt, typeOfTestStringer}, true},
    89  	} {
    90  		argTyp := slicetype.New(c.args...)
    91  		if got, want := CanApply(fn, argTyp), c.canApply; got != want {
    92  			t.Logf("fn.In: %v, arg: %v", fn.In, argTyp)
    93  			t.Errorf("got %v, want %v", got, want)
    94  		}
    95  	}
    96  }