vitess.io/vitess@v0.16.2/go/tools/asthelpergen/integration/integration_visit_test.go (about)

     1  /*
     2  Copyright 2021 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package integration
    18  
    19  import (
    20  	"fmt"
    21  	"reflect"
    22  	"testing"
    23  
    24  	"github.com/stretchr/testify/require"
    25  )
    26  
    27  type testVisitor struct {
    28  	seen []AST
    29  }
    30  
    31  func (tv *testVisitor) visit(node AST) (bool, error) {
    32  	tv.seen = append(tv.seen, node)
    33  	return true, nil
    34  }
    35  
    36  func TestVisitRefContainer(t *testing.T) {
    37  	leaf1 := &Leaf{1}
    38  	leaf2 := &Leaf{2}
    39  	container := &RefContainer{ASTType: leaf1, ASTImplementationType: leaf2}
    40  	containerContainer := &RefContainer{ASTType: container}
    41  
    42  	tv := &testVisitor{}
    43  
    44  	require.NoError(t,
    45  		VisitAST(containerContainer, tv.visit))
    46  
    47  	tv.assertVisitOrder(t, []AST{
    48  		containerContainer,
    49  		container,
    50  		leaf1,
    51  		leaf2,
    52  	})
    53  }
    54  
    55  func TestVisitValueContainer(t *testing.T) {
    56  	leaf1 := &Leaf{1}
    57  	leaf2 := &Leaf{2}
    58  	container := ValueContainer{ASTType: leaf1, ASTImplementationType: leaf2}
    59  	containerContainer := ValueContainer{ASTType: container}
    60  
    61  	tv := &testVisitor{}
    62  
    63  	require.NoError(t,
    64  		VisitAST(containerContainer, tv.visit))
    65  
    66  	expected := []AST{
    67  		containerContainer,
    68  		container,
    69  		leaf1,
    70  		leaf2,
    71  	}
    72  	tv.assertVisitOrder(t, expected)
    73  }
    74  
    75  func TestVisitRefSliceContainer(t *testing.T) {
    76  	leaf1 := &Leaf{1}
    77  	leaf2 := &Leaf{2}
    78  	leaf3 := &Leaf{3}
    79  	leaf4 := &Leaf{4}
    80  	container := &RefSliceContainer{ASTElements: []AST{leaf1, leaf2}, ASTImplementationElements: []*Leaf{leaf3, leaf4}}
    81  	containerContainer := &RefSliceContainer{ASTElements: []AST{container}}
    82  
    83  	tv := &testVisitor{}
    84  
    85  	require.NoError(t,
    86  		VisitAST(containerContainer, tv.visit))
    87  
    88  	tv.assertVisitOrder(t, []AST{
    89  		containerContainer,
    90  		container,
    91  		leaf1,
    92  		leaf2,
    93  		leaf3,
    94  		leaf4,
    95  	})
    96  }
    97  
    98  func TestVisitValueSliceContainer(t *testing.T) {
    99  	leaf1 := &Leaf{1}
   100  	leaf2 := &Leaf{2}
   101  	leaf3 := &Leaf{3}
   102  	leaf4 := &Leaf{4}
   103  	container := ValueSliceContainer{ASTElements: []AST{leaf1, leaf2}, ASTImplementationElements: []*Leaf{leaf3, leaf4}}
   104  	containerContainer := ValueSliceContainer{ASTElements: []AST{container}}
   105  
   106  	tv := &testVisitor{}
   107  
   108  	require.NoError(t,
   109  		VisitAST(containerContainer, tv.visit))
   110  
   111  	tv.assertVisitOrder(t, []AST{
   112  		containerContainer,
   113  		container,
   114  		leaf1,
   115  		leaf2,
   116  		leaf3,
   117  		leaf4,
   118  	})
   119  }
   120  
   121  func TestVisitInterfaceSlice(t *testing.T) {
   122  	leaf1 := &Leaf{2}
   123  	astType := &RefContainer{NotASTType: 12}
   124  	implementationType := &Leaf{2}
   125  
   126  	leaf2 := &Leaf{3}
   127  	refContainer := &RefContainer{
   128  		ASTType:               astType,
   129  		ASTImplementationType: implementationType,
   130  	}
   131  	ast := InterfaceSlice{
   132  		refContainer,
   133  		leaf1,
   134  		leaf2,
   135  	}
   136  
   137  	tv := &testVisitor{}
   138  
   139  	require.NoError(t,
   140  		VisitAST(ast, tv.visit))
   141  
   142  	tv.assertVisitOrder(t, []AST{
   143  		ast,
   144  		refContainer,
   145  		astType,
   146  		implementationType,
   147  		leaf1,
   148  		leaf2,
   149  	})
   150  }
   151  
   152  func (tv *testVisitor) assertVisitOrder(t *testing.T, expected []AST) {
   153  	t.Helper()
   154  	var lines []string
   155  	failed := false
   156  	expectedSize := len(expected)
   157  	for i, step := range tv.seen {
   158  		if expectedSize <= i {
   159  			t.Errorf("❌️ - Expected less elements %v", tv.seen[i:])
   160  			break
   161  		} else {
   162  			e := expected[i]
   163  			if reflect.DeepEqual(e, step) {
   164  				a := "✔️ - " + e.String()
   165  				if failed {
   166  					fmt.Println(a)
   167  				} else {
   168  					lines = append(lines, a)
   169  				}
   170  			} else {
   171  				if !failed {
   172  					// first error we see.
   173  					failed = true
   174  					for _, line := range lines {
   175  						fmt.Println(line)
   176  					}
   177  				}
   178  				t.Errorf("❌️ - Expected: %s Got: %s\n", e.String(), step.String())
   179  			}
   180  		}
   181  	}
   182  	walkSize := len(tv.seen)
   183  	if expectedSize > walkSize {
   184  		t.Errorf("❌️ - Expected more elements %v", expected[walkSize:])
   185  	}
   186  }