plug

package module
v0.0.0-...-6302abc Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 31, 2024 License: BSD-3-Clause Imports: 1 Imported by: 0

README

plug

Package plug replaces functions, defined in the other packages, on testing. The idea underlying this library was heavy inspired from tenntenn/testtime.

GoDev

Usage

See examples.

go test -overlay <(go run github.com/lufia/plug/cmd/plug@latest)

Then add below to .gitignore

plug

Limitations

  • cyclic import: runtime, reflect, etc.
  • go:linkname functions: time.Sleep, etc.

Documentation

Overview

Package plug replaces functions, defined in the other packages, on testing.

Scope

TBD.

Generics

TBD.

Example (MathRandV2N)
scope := plug.CurrentScope()
defer scope.Delete()

key := plug.Func("math/rand/v2.N", rand.N[int])
plug.Set(scope, key, func(n int) int {
	return 3
})
fmt.Println(rand.N[int](10))
Output:

3
Example (NetHttpClientDo)
package main

import (
	"fmt"
	"net/http"

	"github.com/lufia/plug"
)

func main() {
	scope := plug.CurrentScope()
	defer scope.Delete()

	key := plug.Func("net/http.Client.Do", (*http.Client)(nil).Do)
	plug.Set(scope, key, func(req *http.Request) (*http.Response, error) {
		return &http.Response{StatusCode: 200}, nil
	})
	resp, _ := http.Get("https://example.com")
	fmt.Println(resp.StatusCode)
}
Output:

200
Example (OsGetpid)
package main

import (
	"fmt"
	"os"

	"github.com/lufia/plug"
)

func main() {
	scope := plug.CurrentScope()
	defer scope.Delete()

	key := plug.Func("os.Getpid", os.Getpid)
	plug.Set(scope, key, func() int {
		return 1
	})
	fmt.Println(os.Getpid())
}
Output:

1
Example (OsUserCurrent)
package main

import (
	"fmt"
	"os/user"

	"github.com/lufia/plug"
)

func main() {
	scope := plug.CurrentScope()
	defer scope.Delete()

	key := plug.Func("os/user.Current", user.Current)
	plug.Set(scope, key, func() (*user.User, error) {
		return &user.User{Uid: "100", Username: "user"}, nil
	})
	u, _ := user.Current()
	fmt.Println(u.Username, u.Uid)
}
Output:

user 100
Example (RecordGetenv)
package main

import (
	"fmt"
	"os"

	"github.com/lufia/plug"
)

func main() {
	scope := plug.CurrentScope()
	defer scope.Delete()

	key := plug.Func("os.Getenv", os.Getenv)
	var r plug.FuncRecorder[struct {
		Key string
	}]
	plug.Set(scope, key, func(_ string) string {
		return "dummy"
	}).SetRecorder(&r)

	_ = os.Getenv("PATH")
	fmt.Println(r.Count())
	fmt.Println(r.At(0).Key)
}
Output:

1
PATH
Example (TimeNow)
package main

import (
	"fmt"
	"time"

	"github.com/lufia/plug"
)

func main() {
	scope := plug.CurrentScope()
	defer scope.Delete()

	now := time.Date(2024, time.April, 1, 10, 12, 50, 0, time.UTC)
	key := plug.Func("time.Now", time.Now)
	plug.Set(scope, key, func() time.Time {
		return now
	})
	fmt.Println(time.Now().Format(time.RFC3339))
}
Output:

2024-04-01T10:12:50Z

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Get

func Get[T any](scope *Scope, s *Symbol[T], dflt T, opts ...Option) T

Get returns an object that is bound to s, or dflt if s is bound nothing.

Types

type FuncRecorder

type FuncRecorder[T any] plugcore.FuncRecorder[T]

FuncRecorder records its function callings for later inspection in tests.

func (*FuncRecorder[T]) At

func (r *FuncRecorder[T]) At(i int) T

func (*FuncRecorder[T]) Count

func (r *FuncRecorder[T]) Count() int

func (*FuncRecorder[T]) Record

func (r *FuncRecorder[T]) Record(params map[string]any)

type Object

type Object plugcore.Object

func Set

func Set[T any](scope *Scope, s *Symbol[T], v T, opts ...Option) *Object

Set binds s to v. If s does already bound to another object, it will unbound.

func (*Object) SetRecorder

func (obj *Object) SetRecorder(r Recorder)

type Option

type Option func(*constraints)

Option represents the constraints for Get or Set.

func WithParams

func WithParams(params map[string]any) Option

type Recorder

type Recorder interface {
	Record(params map[string]any)
}

Recorder is the interface that wraps the Record method.

type Scope

type Scope plugcore.Scope

func CurrentScope

func CurrentScope() *Scope

CurrentScope returns the scope object that is strongly related to current calling stacks on the goroutine.

When the scope becomes unnecessary the scope should be released through Scope.Delete method. Otherwise the scope and its objects will not be garbage collection because the package continues to kept them in the internal state.

func CurrentScopeFor

func CurrentScopeFor(t testingTB) *Scope

CurrentScopeFor is similar to CurrentScope except the scope will be automatically deleted on cleanup of t.

func CurrentScopeOn

func CurrentScopeOn(scope *Scope) *Scope

CurrentScopeOn likes CurrentScope except it returns Scope that continues from scope even if the current function stack is separated.

func (*Scope) Delete

func (s *Scope) Delete()

Delete deletes all objects that were bound by Set from s then deletes s itself from the internal state.

type Symbol

type Symbol[T any] plugcore.Symbol[T]

Symbol represents an object that will be replaced.

func Func

func Func[F any](name string, f F) *Symbol[F]

Func returns a symbol constructed with both the name and the function is referenced to. The name syntax must be either $package.$function or $package.$type.$method.

For example:

  • math/rand/v2.N
  • net/http.Client.Do

Directories

Path Synopsis
cmd
Package plugcore is designed to be imported only from the plug package.
Package plugcore is designed to be imported only from the plug package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL