github.com/cilki/sh@v2.6.4+incompatible/syntax/walk_test.go (about)

     1  // Copyright (c) 2016, Daniel Martí <mvdan@mvdan.cc>
     2  // See LICENSE for licensing information
     3  
     4  package syntax
     5  
     6  import (
     7  	"fmt"
     8  	"reflect"
     9  	"strings"
    10  	"testing"
    11  )
    12  
    13  func TestWalk(t *testing.T) {
    14  	t.Parallel()
    15  	seen := map[string]bool{
    16  		"*syntax.File":         false,
    17  		"*syntax.Comment":      false,
    18  		"*syntax.Stmt":         false,
    19  		"*syntax.Assign":       false,
    20  		"*syntax.Redirect":     false,
    21  		"*syntax.CallExpr":     false,
    22  		"*syntax.Subshell":     false,
    23  		"*syntax.Block":        false,
    24  		"*syntax.IfClause":     false,
    25  		"*syntax.WhileClause":  false,
    26  		"*syntax.ForClause":    false,
    27  		"*syntax.WordIter":     false,
    28  		"*syntax.CStyleLoop":   false,
    29  		"*syntax.BinaryCmd":    false,
    30  		"*syntax.FuncDecl":     false,
    31  		"*syntax.Word":         false,
    32  		"*syntax.Lit":          false,
    33  		"*syntax.SglQuoted":    false,
    34  		"*syntax.DblQuoted":    false,
    35  		"*syntax.CmdSubst":     false,
    36  		"*syntax.ParamExp":     false,
    37  		"*syntax.ArithmExp":    false,
    38  		"*syntax.ArithmCmd":    false,
    39  		"*syntax.BinaryArithm": false,
    40  		"*syntax.UnaryArithm":  false,
    41  		"*syntax.ParenArithm":  false,
    42  		"*syntax.CaseClause":   false,
    43  		"*syntax.CaseItem":     false,
    44  		"*syntax.TestClause":   false,
    45  		"*syntax.BinaryTest":   false,
    46  		"*syntax.UnaryTest":    false,
    47  		"*syntax.ParenTest":    false,
    48  		"*syntax.DeclClause":   false,
    49  		"*syntax.ArrayExpr":    false,
    50  		"*syntax.ArrayElem":    false,
    51  		"*syntax.ExtGlob":      false,
    52  		"*syntax.ProcSubst":    false,
    53  		"*syntax.TimeClause":   false,
    54  		"*syntax.CoprocClause": false,
    55  		"*syntax.LetClause":    false,
    56  	}
    57  	parser := NewParser(KeepComments)
    58  	var allStrs []string
    59  	for _, c := range fileTests {
    60  		allStrs = append(allStrs, c.Strs[0])
    61  	}
    62  	for _, c := range printTests {
    63  		allStrs = append(allStrs, c.in)
    64  	}
    65  	for i, in := range allStrs {
    66  		t.Run(fmt.Sprintf("%03d", i), func(t *testing.T) {
    67  			prog, err := parser.Parse(strings.NewReader(in), "")
    68  			if err != nil {
    69  				// good enough for now, as the bash
    70  				// parser ignoring errors covers what we
    71  				// need.
    72  				return
    73  			}
    74  			lastOffs := uint(0)
    75  			Walk(prog, func(node Node) bool {
    76  				if node == nil {
    77  					return false
    78  				}
    79  				tstr := reflect.TypeOf(node).String()
    80  				if _, ok := seen[tstr]; !ok {
    81  					t.Errorf("unexpected type: %s", tstr)
    82  				} else {
    83  					seen[tstr] = true
    84  				}
    85  				switch node.(type) {
    86  				case *Lit:
    87  					return false
    88  				case *Comment:
    89  				default:
    90  					return true
    91  				}
    92  				offs := node.Pos().Offset()
    93  				if offs >= lastOffs {
    94  					lastOffs = offs
    95  				} else {
    96  					t.Errorf("comment offset goes back")
    97  				}
    98  				return true
    99  			})
   100  		})
   101  	}
   102  	for tstr, tseen := range seen {
   103  		if !tseen {
   104  			t.Errorf("type not seen: %s", tstr)
   105  		}
   106  	}
   107  }
   108  
   109  type newNode struct{}
   110  
   111  func (newNode) Pos() Pos { return Pos{} }
   112  func (newNode) End() Pos { return Pos{} }
   113  
   114  func TestWalkUnexpectedType(t *testing.T) {
   115  	t.Parallel()
   116  	defer func() {
   117  		if r := recover(); r == nil {
   118  			t.Errorf("did not panic")
   119  		}
   120  	}()
   121  	Walk(newNode{}, func(node Node) bool {
   122  		return true
   123  	})
   124  }