gopkg.in/mvdan/sh.v1@v1.3.1/cmd/shfmt/main_test.go (about)

     1  // Copyright (c) 2016, Daniel Martí <mvdan@mvdan.cc>
     2  // See LICENSE for licensing information
     3  
     4  package main
     5  
     6  import (
     7  	"bufio"
     8  	"bytes"
     9  	"io/ioutil"
    10  	"os"
    11  	"path/filepath"
    12  	"regexp"
    13  	"testing"
    14  )
    15  
    16  type action uint
    17  
    18  const (
    19  	None action = iota
    20  	Modify
    21  	Error
    22  )
    23  
    24  var walkTests = []struct {
    25  	want       action
    26  	mode       os.FileMode
    27  	path, body string
    28  }{
    29  	{Modify, 0666, "shebang-1", "#!/bin/sh\n foo"},
    30  	{Modify, 0666, "shebang-2", "#!/bin/bash\n foo"},
    31  	{Modify, 0666, "shebang-3", "#!/usr/bin/sh\n foo"},
    32  	{Modify, 0666, "shebang-4", "#!/usr/bin/env bash\n foo"},
    33  	{Modify, 0666, "shebang-5", "#!/bin/env sh\n foo"},
    34  	{Modify, 0666, "shebang-space", "#! /bin/sh\n foo"},
    35  	{Modify, 0666, "shebang-tabs", "#!\t/bin/env\tsh\n foo"},
    36  	{Modify, 0666, "shebang-args", "#!/bin/bash -e -x\nfoo"},
    37  	{Modify, 0666, "ext.sh", " foo"},
    38  	{Modify, 0666, "ext.bash", " foo"},
    39  	{Modify, 0666, "ext-shebang.sh", "#!/bin/sh\n foo"},
    40  	{Modify, 0666, filepath.Join("dir", "ext.sh"), " foo"},
    41  	{None, 0666, ".hidden", " foo long enough"},
    42  	{None, 0666, ".hidden-shebang", "#!/bin/sh\n foo"},
    43  	{None, 0666, "..hidden-shebang", "#!/bin/sh\n foo"},
    44  	{None, 0666, "noext-empty", " foo"},
    45  	{None, 0666, "noext-noshebang", " foo long enough"},
    46  	{None, 0666, "shebang-nonewline", "#!/bin/shfoo"},
    47  	{None, 0666, "ext.other", " foo"},
    48  	{None, 0666, "ext-shebang.other", "#!/bin/sh\n foo"},
    49  	{None, 0666, "shebang-nospace", "#!/bin/envsh\n foo"},
    50  	{None, 0666, filepath.Join(".git", "ext.sh"), " foo"},
    51  	{None, 0666, filepath.Join(".svn", "ext.sh"), " foo"},
    52  	{None, 0666, filepath.Join(".hg", "ext.sh"), " foo"},
    53  	{Error, 0666, "parse-error.sh", " foo("},
    54  	{Error, 0111, "open-error.sh", " foo"},
    55  }
    56  
    57  var errPathMentioned = regexp.MustCompile(`([^ :]+):`)
    58  
    59  func TestWalk(t *testing.T) {
    60  	dir, err := ioutil.TempDir("", "shfmt-walk")
    61  	if err != nil {
    62  		t.Fatal(err)
    63  	}
    64  	defer os.RemoveAll(dir)
    65  
    66  	if err := os.Chdir(dir); err != nil {
    67  		t.Fatal(err)
    68  	}
    69  	for _, wt := range walkTests {
    70  		if dir, _ := filepath.Split(wt.path); dir != "" {
    71  			dir = dir[:len(dir)-1]
    72  			os.Mkdir(dir, 0777)
    73  		}
    74  		err := ioutil.WriteFile(wt.path, []byte(wt.body), wt.mode)
    75  		if err != nil {
    76  			t.Fatal(err)
    77  		}
    78  	}
    79  	var outBuf bytes.Buffer
    80  	out = &outBuf
    81  	*list, *write = true, true
    82  	gotError := false
    83  	errored := map[string]bool{}
    84  	onError := func(err error) {
    85  		gotError = true
    86  		line := err.Error()
    87  		if sub := errPathMentioned.FindStringSubmatch(line); sub != nil {
    88  			errored[sub[1]] = true
    89  		}
    90  	}
    91  	doWalk := func(path string) {
    92  		gotError = false
    93  		outBuf.Reset()
    94  		walk(path, onError)
    95  	}
    96  	doWalk(".")
    97  	modified := map[string]bool{}
    98  	outScan := bufio.NewScanner(&outBuf)
    99  	for outScan.Scan() {
   100  		path := outScan.Text()
   101  		modified[path] = true
   102  	}
   103  	for _, wt := range walkTests {
   104  		t.Run(wt.path, func(t *testing.T) {
   105  			mod := modified[wt.path]
   106  			if mod && wt.want != Modify {
   107  				t.Fatalf("walk had to not run on %s but did", wt.path)
   108  			} else if !mod && wt.want == Modify {
   109  				t.Fatalf("walk had to run on %s but didn't", wt.path)
   110  			}
   111  			err := errored[wt.path]
   112  			if err && wt.want != Error {
   113  				t.Fatalf("walk had to not err on %s but did", wt.path)
   114  			} else if !err && wt.want == Error {
   115  				t.Fatalf("walk had to err on %s but didn't", wt.path)
   116  			}
   117  		})
   118  	}
   119  	if doWalk("."); outBuf.Len() > 0 {
   120  		t.Fatal("shfmt -l -w printed paths on a duplicate run")
   121  	}
   122  	*list, *write = false, false
   123  	if doWalk("."); outBuf.Len() == 0 {
   124  		t.Fatal("shfmt without -l nor -w did not print anything")
   125  	}
   126  	if doWalk(".hidden"); outBuf.Len() == 0 {
   127  		t.Fatal("`shfmt .hidden` did not print anything")
   128  	}
   129  	if doWalk("nonexistent"); !gotError {
   130  		t.Fatal("`shfmt nonexistent` did not error")
   131  	}
   132  	if err := ioutil.WriteFile("nowrite", []byte(" foo"), 0444); err != nil {
   133  		t.Fatal(err)
   134  	}
   135  	*write = true
   136  	if doWalk("nowrite"); !gotError {
   137  		t.Fatal("`shfmt nowrite` did not error")
   138  	}
   139  }