tenv detects environment variable not using t.Setenv

tenv

tenv Gopher

test_and_lint

tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17

Instruction

go install github.com/sivchari/tenv/cmd/tenv

Usage

package main

import (
	"fmt"
	"os"
	"testing"
)

func TestMain(t *testing.T) {
	fmt.Println(os.Getenv("GO"))
	os.Setenv("GO", "HACKING GOPHER")
}

func TestMain2(t *testing.T) {
	fmt.Println(os.Getenv("GO"))
}

func helper() {
	os.Setenv("GO", "HACKING GOPHER")
}
go vet -vettool=(which tenv) ./...

# a
./main_test.go:11:2: os.Setenv() can be replaced by `t.Setenv()` in TestMain

option

The option all will run against whole test files (_test.go) regardless of method/function signatures.

By default, only methods that take *testing.T, *testing.B, and testing.TB as arguments are checked.

package main

import (
	"fmt"
	"os"
	"testing"
)

func TestMain(t *testing.T) {
	fmt.Println(os.Getenv("GO"))
	os.Setenv("GO", "HACKING GOPHER")
}

func TestMain2(t *testing.T) {
	fmt.Println(os.Getenv("GO"))
}

func helper() {
	os.Setenv("GO", "HACKING GOPHER")
}
go vet -vettool=(which tenv) -tenv.all ./...

# a
./main_test.go:11:2: os.Setenv() can be replaced by `t.Setenv()` in TestMain
./main_test.go:19:2: os.Setenv() can be replaced by `testing.Setenv()` in helper

CI

CircleCI

- run:
    name: install tenv
    command: go install github.com/sivchari/tenv

- run:
    name: run tenv
    command: go vet -vettool=`which tenv` ./...

GitHub Actions

- name: install tenv
  run: go install github.com/sivchari/tenv

- name: run tenv
  run: go vet -vettool=`which tenv` ./...
Owner
Comments
  • fix: index out of range

    fix: index out of range

    Found this panic while running tenv in golangci-lint. See https://github.com/coder/coder/pull/4687 for code that can reproduce.

    WARN [runner] The linter 'deadcode' is deprecated (since v1.49.0) due to: The owner seems to have abandoned the linter.  Replaced by unused.
    WARN [runner] The linter 'varcheck' is deprecated (since v1.49.0) due to: The owner seems to have abandoned the linter.  Replaced by unused.
    ERRO [runner] Panic: tenv: package "tailnet_test" (isInitialPkg: true, needAnalyzeSource: true): runtime error: index out of range [0] with length 0: goroutine 79536 [running]:
    runtime/debug.Stack()
    	/usr/lib/go/src/runtime/debug/stack.go:24 +0x65
    github.com/golangci/golangci-lint/pkg/golinters/goanalysis.(*action).analyzeSafe.func1()
    	/home/colin/go/pkg/mod/github.com/golangci/[email protected]/pkg/golinters/goanalysis/runner_action.go:102 +0x155
    panic({0x165cc80, 0xc02d4ca708})
    	/usr/lib/go/src/runtime/panic.go:884 +0x212
    github.com/sivchari/tenv.targetRunner({0xc0289ac7d8, 0x1, 0x2?}, {0xc00123c730, 0x47})
    	/home/colin/go/pkg/mod/github.com/sivchari/[email protected]/tenv.go:174 +0x405
    github.com/sivchari/tenv.checkFuncLit(0xc00094e340?, 0xc0093ac140, {0xc00123c730?, 0x0?})
    	/home/colin/go/pkg/mod/github.com/sivchari/[email protected]/tenv.go:62 +0x4e
    github.com/sivchari/tenv.run.func1({0x194d078?, 0xc0093ac140?})
    	/home/colin/go/pkg/mod/github.com/sivchari/[email protected]/tenv.go:46 +0xa5
    golang.org/x/tools/go/ast/inspector.(*Inspector).Preorder(0xc02a270408, {0xc0034b8d18?, 0x2?, 0x914a27?}, 0xc02c69fd08)
    	/home/colin/go/pkg/mod/golang.org/x/[email protected]/go/ast/inspector/inspector.go:77 +0x9a
    github.com/sivchari/tenv.run(0xc02d4ed520)
    	/home/colin/go/pkg/mod/github.com/sivchari/[email protected]/tenv.go:41 +0xa5
    github.com/golangci/golangci-lint/pkg/golinters/goanalysis.(*action).analyze(0xc005efc410)
    	/home/colin/go/pkg/mod/github.com/golangci/[email protected]/pkg/golinters/goanalysis/runner_action.go:188 +0x9d6
    github.com/golangci/golangci-lint/pkg/golinters/goanalysis.(*action).analyzeSafe.func2()
    	/home/colin/go/pkg/mod/github.com/golangci/[email protected]/pkg/golinters/goanalysis/runner_action.go:106 +0x1d
    github.com/golangci/golangci-lint/pkg/timeutils.(*Stopwatch).TrackStage(0xc0011d66e0, {0x16c12ce, 0x4}, 0xc0034b8f48)
    	/home/colin/go/pkg/mod/github.com/golangci/[email protected]/pkg/timeutils/stopwatch.go:111 +0x4a
    github.com/golangci/golangci-lint/pkg/golinters/goanalysis.(*action).analyzeSafe(0xc02ec88800?)
    	/home/colin/go/pkg/mod/github.com/golangci/[email protected]/pkg/golinters/goanalysis/runner_action.go:105 +0x85
    github.com/golangci/golangci-lint/pkg/golinters/goanalysis.(*loadingPackage).analyze.func2(0xc005efc410)
    	/home/colin/go/pkg/mod/github.com/golangci/[email protected]/pkg/golinters/goanalysis/runner_loadingpackage.go:80 +0xb4
    created by github.com/golangci/golangci-lint/pkg/golinters/goanalysis.(*loadingPackage).analyze
    	/home/colin/go/pkg/mod/github.com/golangci/[email protected]/pkg/golinters/goanalysis/runner_loadingpackage.go:75 +0x1eb
    WARN [runner] Can't run linter goanalysis_metalinter: goanalysis_metalinter: tenv: package "tailnet_test" (isInitialPkg: true, needAnalyzeSource: true): runtime error: index out of range [0] with length 0
    ERRO Running error: 1 error occurred:
    	* can't run linter goanalysis_metalinter: goanalysis_metalinter: tenv: package "tailnet_test" (isInitialPkg: true, needAnalyzeSource: true): runtime error: index out of range [0] with length 0
    
  • Panic in golangci-lint when tenv is enabled

    Panic in golangci-lint when tenv is enabled

    Not sure if this should be reported here, or in golangci-lint, but I'm sure you can advise me on that :) When I run tenv "standalone" on the Open Policy Agent codebase it works as expected, but when included in golangci-lint I get a panic:

    level=error msg="[runner] Panic: tenv: package \"test\" (isInitialPkg: true, needAnalyzeSource: true): runtime error: index out of range [0] with length 0: goroutine 14707 [running]:\nruntime/debug.Stack()\n\truntime/debug/stack.go:24 +0x68\ngithub.com/golangci/golangci-lint/pkg/golinters/goanalysis.(*action).analyzeSafe.func1()\n\tgithub.com/golangci/golangci-lint/pkg/golinters/goanalysis/runner_action.go:101 +0x108\npanic({0xafebc0, 0x400130a588})\n\truntime/panic.go:838 +0x20c\ngithub.com/sivchari/tenv.targetRunner(0xa00?, {0x4000f36ce0, 0x19})\n\tgithub.com/sivchari/[email protected]/tenv.go:158 +0x3f0\ngithub.com/sivchari/tenv.checkFunc(0x40016905c0?, 0x400bd6bec0, {0x4000f36ce0?, 0x1?})\n\tgithub.com/sivchari/[email protected]/tenv.go:58 +0x38\ngithub.com/sivchari/tenv.run.func1({0xda80a0?, 0x40067e0e80})\n\tgithub.com/sivchari/[email protected]/tenv.go:49 +0xf4\ngolang.org/x/tools/go/ast/inspector.(*Inspector).Preorder(0x400ca92a68, {0x4003cc6ce8?, 0x1?, 0xcf5d0?}, 0x400222fcf8)\n\tgolang.org/x/[email protected]/go/ast/inspector/inspector.go:77 +0xac\ngithub.com/sivchari/tenv.run(0x40111528f0)\n\tgithub.com/sivchari/[email protected]/tenv.go:40 +0x94\ngithub.com/golangci/golangci-lint/pkg/golinters/goanalysis.(*action).analyze(0x4003296d90)\n\tgithub.com/golangci/golangci-lint/pkg/golinters/goanalysis/runner_action.go:187 +0x98c\ngithub.com/golangci/golangci-lint/pkg/golinters/goanalysis.(*action).analyzeSafe.func2()\n\tgithub.com/golangci/golangci-lint/pkg/golinters/goanalysis/runner_action.go:105 +0x24\ngithub.com/golangci/golangci-lint/pkg/timeutils.(*Stopwatch).TrackStage(0x4001a9b810, {0xb594fb, 0x4}, 0x4003d69730)\n\tgithub.com/golangci/golangci-lint/pkg/timeutils/stopwatch.go:111 +0x48\ngithub.com/golangci/golangci-lint/pkg/golinters/goanalysis.(*action).analyzeSafe(0x5593a0?)\n\tgithub.com/golangci/golangci-lint/pkg/golinters/goanalysis/runner_action.go:104 +0x78\ngithub.com/golangci/golangci-lint/pkg/golinters/goanalysis.(*loadingPackage).analyze.func2(0x4003296d90)\n\tgithub.com/golangci/golangci-lint/pkg/golinters/goanalysis/runner_loadingpackage.go:80 +0xb4\ncreated by github.com/golangci/golangci-lint/pkg/golinters/goanalysis.(*loadingPackage).analyze\n\tgithub.com/golangci/golangci-lint/pkg/golinters/goanalysis/runner_loadingpackage.go:75 +0x16c\n"
    level=warning msg="[runner] Can't run linter goanalysis_metalinter: goanalysis_metalinter: tenv: package \"test\" (isInitialPkg: true, needAnalyzeSource: true): runtime error: index out of range [0] with length 0"
    
    > go version 
    go1.19.1 darwin/arm64
    
  • panic in table-driven tests

    panic in table-driven tests

    package tenv_test
    
    import (
    	"testing"
    )
    
    func TestTenv(t *testing.T) {
    	t.Run("test", func(*testing.T) { })
    }
    

    running version 1.47.0 of golangci-lint

    $ golangci-lint run --disable-all --enable tenv tenv_test.go
    
    ERRO [runner] Panic: tenv: package "tenv_test" (isInitialPkg: true, needAnalyzeSource: true): runtime error: index out of range [0] with length 0: goroutine 268 [running]:
    runtime/debug.Stack()
            runtime/debug/stack.go:24 +0x65
    github.com/golangci/golangci-lint/pkg/golinters/goanalysis.(*action).analyzeSafe.func1()
            github.com/golangci/golangci-lint/pkg/golinters/goanalysis/runner_action.go:101 +0x155
    panic({0x1bd22a0, 0xc0005a4000})
            runtime/panic.go:838 +0x207
    github.com/sivchari/tenv.targetRunner({0xc00021a060, 0x1, 0x1?}, {0xc001495e60, 0x25})
            github.com/sivchari/[email protected]/tenv.go:166 +0x3e5
    github.com/sivchari/tenv.checkFuncLit(0xc00020ccc0?, 0xc0002060b0, {0xc001495e60?, 0x0?})
            github.com/sivchari/[email protected]/tenv.go:62 +0x4e
    github.com/sivchari/tenv.run.func1({0x1e86290?, 0xc0002060b0?})
            github.com/sivchari/[email protected]/tenv.go:46 +0x105
    golang.org/x/tools/go/ast/inspector.(*Inspector).Preorder(0xc000eee258, {0xc00094ad18?, 0x2?, 0xc00094ad28?}, 0xc0017c9d08)
            golang.org/x/[email protected]/go/ast/inspector/inspector.go:77 +0x9a
    github.com/sivchari/tenv.run(0xc0007fc680)
            github.com/sivchari/[email protected]/tenv.go:41 +0xa5
    github.com/golangci/golangci-lint/pkg/golinters/goanalysis.(*action).analyze(0xc000120000)
            github.com/golangci/golangci-lint/pkg/golinters/goanalysis/runner_action.go:187 +0x9c4
    github.com/golangci/golangci-lint/pkg/golinters/goanalysis.(*action).analyzeSafe.func2()
            github.com/golangci/golangci-lint/pkg/golinters/goanalysis/runner_action.go:105 +0x1d
    github.com/golangci/golangci-lint/pkg/timeutils.(*Stopwatch).TrackStage(0xc00011e190, {0x1c2e909, 0x4}, 0xc00094af48)
            github.com/golangci/golangci-lint/pkg/timeutils/stopwatch.go:111 +0x4a
    github.com/golangci/golangci-lint/pkg/golinters/goanalysis.(*action).analyzeSafe(0xc001c5f860?)
            github.com/golangci/golangci-lint/pkg/golinters/goanalysis/runner_action.go:104 +0x85
    github.com/golangci/golangci-lint/pkg/golinters/goanalysis.(*loadingPackage).analyze.func2(0xc000120000)
            github.com/golangci/golangci-lint/pkg/golinters/goanalysis/runner_loadingpackage.go:80 +0xb4
    created by github.com/golangci/golangci-lint/pkg/golinters/goanalysis.(*loadingPackage).analyze
            github.com/golangci/golangci-lint/pkg/golinters/goanalysis/runner_loadingpackage.go:75 +0x1eb 
    WARN [runner] Can't run linter tenv: tenv: tenv: package "tenv_test" (isInitialPkg: true, needAnalyzeSource: true): runtime error: index out of range [0] with length 0 
    ERRO Running error: 1 error occurred:
            * can't run linter tenv: tenv: tenv: package "tenv_test" (isInitialPkg: true, needAnalyzeSource: true): runtime error: index out of range [0] with length 0
    
  • Does not work in table-driven tests

    Does not work in table-driven tests

    One standard pattern in go is to used table driven tests, see https://dave.cheney.net/2019/05/07/prefer-table-driven-tests

    This linter does not work if os.Setenv is used in these tests.

    Example:

    func TestLintShouldFailButDoesnt(t *testing.T) {
    	tests := map[string]struct {
    		fooValue string
    	}{
    		"does something": {fooValue: "bar"},
    	}
    
    	for name, tc := range tests {
    		t.Run(name, func(t *testing.T) {
    			os.Setenv("foo", tc.fooValue)
    		})
    	}
    }
    

    I created this on my repo with the github-action version of the golang-ci linter: https://github.com/vankleefjim/tenv-bug/commit/10f12e411fc285d5abe19fcb9ad63d9ef0f139be with successful CI run https://github.com/vankleefjim/tenv-bug/commit/f01c6891a6020c613e9cbccf5df46dc5dd71e188 with failing CI run, but only in the test that directly runs os.Setenv without a table-driven test.

  • Support Test Suites

    Support Test Suites

    I believe the linter fails on detecting os.Setenv calls in more advanced scenarios. Here's one:

    func TestModelSuite(t *testing.T) {
    	suite.Run(t, &MySuite{})
    }
    
    func (s *MySuite) SetupTest() {
    	// ... some setup code
    
    	s.NoError(os.Setenv("AWS_XRAY_SDK_DISABLED", "true")) // want "some linting error to detect this"
    
    	// ... more setup code
    }
    

    FIY: The test suite here is from stretchr/testify should that help you pinpoint the issue.

    The solution should look like this:

    	s.T().Setenv("AWS_XRAY_SDK_DISABLED", "true")
    

    As you can see, T() will return the *testing.T instance. So your linter should be sensible to this case as well :)

    And just for clarity: I have the configuration parameter all set to true

A funny utility to manage your PS1 variable.
A funny utility to manage your PS1 variable.

PSOne Introduction Are you a Veteran Unix Admin? If so, you probably know the charm of the PS1 environment variable. For a deep focus I suggest you to

Oct 23, 2022
流媒体NetFlix解锁检测脚本 / A script used to determine whether your network can watch native Netflix movies or not
流媒体NetFlix解锁检测脚本 / A script used to determine whether your network can watch native Netflix movies or not

netflix-verify 流媒体NetFlix解锁检测脚本,使用Go语言编写 在VPS网络正常的情况下,哪怕是双栈网络也可在几秒内快速完成IPv4/IPv6的解锁判断 鸣谢 感谢 @CoiaPrant 指出对于地域检测更简便的方法 感谢 @XmJwit 解决了IPV6 Only VPS无法下载脚

Dec 29, 2022
Fast, lightweight and NOT reliable tool for downloading tons of images.

image-download-tool Fast, lightweight and NOT reliable tool for downloading tons of images. How to use Run .exe with --help flag Create json file with

May 12, 2022
DO NOT use `named return values` in Go

namedreturn DO NOT use named return values in Go namedreturn finds a named return value, you must remove it.

Dec 17, 2021
Payload is a simple tool for working with production data in your local environment.

Payload Payload is a simple tool for working with production data in your local environment. What problem does it solve? You're working with Cloud SQL

Oct 13, 2021
Perforator is a tool for recording performance metrics over subregions of a program using the Linux "perf" interface.

Perforator Perforator is a tool for recording performance metrics over subregions of a program (e.g., functions) using the Linux "perf" interface.

Dec 15, 2022
rxscan provides functionality to scan text to variables using regular expression capture group.

rxscan rxscan provides functionality to scan text to variables using regular expression capture group. This library is still experimental, use at your

Dec 21, 2020
A tool and library for using structural regular expressions.

Structural Regular Expressions sregx is a package and tool for using structural regular expressions as described by Rob Pike (link).

Dec 7, 2022
This project provides some working examples using Go and Hotwire Turbo.

hotwire-golang-website This project provides some working examples using Go the hotwire/turbo library published by basecamp.

Dec 29, 2022
Visualize your Go data structures using graphviz

memviz How would you rather debug a data structure? "Pretty" printed Visual graph (*test.fib)(0xc04204a5a0)({ index: (int) 5, prev: (*test.fib)(0xc0

Dec 22, 2022
Bitwise AND on two byte-slices using SIMD instructions

This package provides a vectorised function which performs bitwise AND operation on all pairs of elements in two byte-slices. It detects CPU instruction set and chooses the available best one (AVX512, AVX2, SSE2).

Oct 17, 2022
A go library to manipulate keyboards using libevdev

gokbd About This is an elementary library using libevdev to talk to a keyboard on Linux. It allows snooping the keys pressed as well as typing out key

Jan 19, 2022
An Api for Task by Appointy made using go.

AppointyTask API How to Compile Export All the required environment variables. MONGO_URI = Database URI PORT = Port to run the server on DATABA

Oct 10, 2021
Scalable golang ratelimiter using the sliding window algorithm. Currently supports only Redis.
Scalable golang ratelimiter using the sliding window algorithm. Currently supports only Redis.

go-ratelimiter Scalable golang ratelimiter using the sliding window algorithm. Currently supports only Redis. Example usage client := redis.NewClient

Oct 19, 2021
Instagram Backend API Using GO
Instagram Backend API Using GO

InstaCloneGo ⚡ Instagram Backend API Using GO Setup ❄️ go run server.go API END POINTS CREATE USERS :http://localhost:8001/users GET A USER USING ID

Oct 10, 2021
Validates Terraform Plans using TFSEC and OPA

Terraform Plan Validator Validates Terraform Plans using TFSEC and OPA Commands go run main.go check "delete-rg-test.json" "azure" Docker docker build

Jun 3, 2022
Instrumentations of third-party libraries using opentelemetry-go library

OpenTelemetry Go Contributions About This reopsitory hosts instrumentations of the following OpenTelemetry libraries: confluentinc/confluent-kafka-go

Nov 14, 2022
Encriptator using random generated numbers

public-private-key-encrypter Encriptator using random generated numbers The input file must be in one file called 'data.txt' The execution will genera

Oct 15, 2021
Extended library functions using generics in Go.

Just few extended standard library functions for Golang using generics.

Dec 16, 2021