Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Support mock some stdlib functions #6

Closed
xhd2015 opened this issue Mar 24, 2024 · 9 comments
Closed

Support mock some stdlib functions #6

xhd2015 opened this issue Mar 24, 2024 · 9 comments
Labels
done feature proposal Proposal new ideas

Comments

@xhd2015
Copy link
Owner

xhd2015 commented Mar 24, 2024

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 xhd2015 added enhancement New feature or request feature and removed enhancement New feature or request labels Mar 24, 2024
@WAY29
Copy link

WAY29 commented Mar 24, 2024

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

@xhd2015
Copy link
Owner Author

xhd2015 commented Mar 24, 2024

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.

@WAY29
Copy link

WAY29 commented Mar 26, 2024

Mock stdlib functions will be useful in test

@xhd2015
Copy link
Owner Author

xhd2015 commented Mar 26, 2024

@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?

@WAY29
Copy link

WAY29 commented Mar 26, 2024

@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?

@xhd2015
Copy link
Owner Author

xhd2015 commented Mar 26, 2024

@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?

@WAY29
Copy link

WAY29 commented Mar 26, 2024

@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

@xhd2015
Copy link
Owner Author

xhd2015 commented Mar 28, 2024

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
Copy link
Owner Author

xhd2015 commented Mar 28, 2024

@WAY29 mocking stdlib functions has been supported, see commit f911dc8

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.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
done feature proposal Proposal new ideas
Projects
None yet
Development

No branches or pull requests

2 participants