xgo icon indicating copy to clipboard operation
xgo copied to clipboard

Support mock some stdlib functions

Open xhd2015 opened this issue 1 year ago • 9 comments

Some use case involve mocking time.Now,time.Sleep, etc.

For example: https://www.reddit.com/r/golang/s/VKGwG7SjlG

Currently IR rewritting is turned off for stdlib. Should add support for these functions and may even allow user to specify what other functions they want to mock.

xhd2015 avatar Mar 24 '24 03:03 xhd2015

So up to now, xgo cannot be patched for any standard library functions?

WAY29 avatar Mar 24 '24 12:03 WAY29

Stdlib is no difference with user written lib.It's just that currently stdlib is skipped by default.Will explore a way for user to control whether stdlib should be trapped.

xhd2015 avatar Mar 24 '24 12:03 xhd2015

Mock stdlib functions will be useful in test

WAY29 avatar Mar 26 '24 09:03 WAY29

@WAY29 I'm planning to enable mock by default for these stdlib functions, how do you think?

time.Now
time.Sleep
os.Getenv
net/http.*

Do you think we need to add more?

xhd2015 avatar Mar 26 '24 10:03 xhd2015

@WAY29 I'm planning to enable mock by default for these stdlib functions, how do you think?

time.Now
time.Sleep
os.Getenv
net/http.*

Do you think we need to add more?

Maybe add a cmd option is better?

WAY29 avatar Mar 26 '24 11:03 WAY29

@WAY29 I'm planning to enable mock by default for these stdlib functions, how do you think?

time.Now
time.Sleep
os.Getenv
net/http.*

Do you think we need to add more?

Maybe add a cmd option is better?

Ok, I will add support for it. Currently, what stdlib function do you want to mock?

xhd2015 avatar Mar 26 '24 12:03 xhd2015

@WAY29 I'm planning to enable mock by default for these stdlib functions, how do you think?

time.Now
time.Sleep
os.Getenv
net/http.*

Do you think we need to add more?

Maybe add a cmd option is better?

Ok, I will add support for it. Currently, what stdlib function do you want to mock?

net.*

However I think udp connection is unable to mock, because it's a struct pointer but not a interface... There is no good way

WAY29 avatar Mar 26 '24 12:03 WAY29

This is still working because it seems that standard lib is a little different from ordinary code. The IR rewriting is not taking effect.I'm solving it using source rewriting.

xhd2015 avatar Mar 28 '24 11:03 xhd2015

@WAY29 mocking stdlib functions has been supported, see commit https://github.com/xhd2015/xgo/commit/f911dc86a2f7dbb62b2361f3649c823e0b2ea4b8

As usual, you may need to upgrade xgo and go get github.com/xhd2015/xgo/runtime@latest to use the latest version.

Here is an example mocking time.Now:

package mock_time_now

import (
	"context"
	"testing"
	"time"

	"github.com/xhd2015/xgo/runtime/core"
	"github.com/xhd2015/xgo/runtime/mock"
)

func TestMockTimeNow(t *testing.T) {
	now1 := time.Now()
	now2 := time.Now()

	d1 := now2.Sub(now1)
	if d1 <= 0 {
		t.Fatalf("expect now2-now1 > 0 , actual: %v", d1)
	}
	cancel := mock.Mock(time.Now, func(ctx context.Context, fn *core.FuncInfo, args, results core.Object) error {
		results.GetFieldIndex(0).Set(now1)
		return nil
	})

	now3 := time.Now()
	if now3 != now1 {
		t.Fatalf("expect now3 equals to now1 exactly, actual diff: %v", now3.Sub(now1))
	}
	cancel()

	now4 := time.Now()
	d4 := now4.Sub(now1)
	if d4 <= 0 {
		t.Fatalf("expect now4-now1 > 0 after cancelling mock, actual: %v", d4)
	}
}

Another example mocking http.Client.Do:

package mock_http_do

import (
	"context"
	"net/http"
	"testing"

	"github.com/xhd2015/xgo/runtime/core"
	"github.com/xhd2015/xgo/runtime/mock"
)

func TestMockHTTP(t *testing.T) {
	var haveMocked bool
	mock.Mock(http.DefaultClient.Do, func(ctx context.Context, fn *core.FuncInfo, args, results core.Object) error {
		haveMocked = true
		return nil
	})
	http.DefaultClient.Do(nil)
	if !haveMocked {
		t.Fatalf("expect http.DefaultClient.Do to have been mocked, actually not mocked")
	}
}

However, there are limitations on mocking stdlib functions. Currently only a list of packages and functions can be mocked, you can view them at runtime/mock/stdlib.md.

Of course, if there are some functions you want to mock are missing, you can leave a comment here, I'll test then and then add them.

xhd2015 avatar Mar 28 '24 16:03 xhd2015