Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Fix integration tests #1853

Merged
merged 81 commits into from May 17, 2022
Merged
Show file tree
Hide file tree
Changes from 80 commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
87f7316
Run integration tests with unstable commands turned on
Naatan May 6, 2022
ad95e96
Fix branch switching test
Naatan May 6, 2022
3a0ec85
Fix package search test
Naatan May 6, 2022
77cdbd0
Fix bundle search test
Naatan May 6, 2022
63069a8
Fix config test
Naatan May 6, 2022
f0da54e
Disable impossible test
Naatan May 6, 2022
77633b4
Don't test values that are bound to change
Naatan May 6, 2022
2e6a34b
Attempt to supply FULL snapshot
Naatan May 6, 2022
76d976f
Fix single tag having trailing colon
Naatan May 6, 2022
1a4dfa5
Fix editor v0 error not printing
Naatan May 9, 2022
f59bc2b
Fix expectation
Naatan May 9, 2022
b63a83b
Update expectation
Naatan May 9, 2022
94bce77
Make assertion less specific
Naatan May 9, 2022
97bdb4d
Remove redundant assertion
Naatan May 9, 2022
6abfd52
Address prompt
Naatan May 9, 2022
ecf8d11
Update assertion
Naatan May 9, 2022
f3ad8b1
Remove overly specific assertions
Naatan May 9, 2022
261a744
Fix false negative
Naatan May 9, 2022
9c56b48
Fix unstable warnings in json output
Naatan May 9, 2022
d74d3fc
Remove overly specific assertion
Naatan May 9, 2022
8cf8ac6
Update assertion
Naatan May 9, 2022
7f13afc
Attempt to fix s3 error
Naatan May 9, 2022
716bf15
Update assertion
Naatan May 9, 2022
8d84ea4
Update assertion
Naatan May 9, 2022
d73a189
Update assertion
Naatan May 9, 2022
2223ec7
Use package that won't fail
Naatan May 9, 2022
83daf46
Don't fetch project ID if no namespace was given
Naatan May 9, 2022
e9ff249
Give plenty of time
Naatan May 9, 2022
ba38eae
Attempt to fix path missmatch
Naatan May 9, 2022
ce9a27f
Drop MSI tests
Naatan May 9, 2022
c7ed63e
Remove overly specific test that's testing the wrong thing (it's a ca…
Naatan May 10, 2022
6d3d768
Update assertions
Naatan May 10, 2022
79b65e4
Debug performance
Naatan May 10, 2022
4ed6892
Only assert unique path component rather than whole path
Naatan May 10, 2022
00c318c
Fix package name
Naatan May 10, 2022
5562e47
Give plenty of time
Naatan May 10, 2022
ba03e3a
Assert path component instead
Naatan May 10, 2022
7b45f28
Don't run bash test on windows
Naatan May 10, 2022
f7f9e48
Update assertion
Naatan May 10, 2022
7e7ed87
Ensure we install to right dir
Naatan May 10, 2022
ec99156
Debug performance
Naatan May 10, 2022
902acd8
Performance test improvements
Naatan May 10, 2022
fa5e809
Update assertion
Naatan May 10, 2022
90c8423
Improve performance by not checking for deprecation on startup or upd…
Naatan May 10, 2022
a98046c
Test without overhead
Naatan May 10, 2022
1203a90
Increase performance max time
Naatan May 11, 2022
4a964be
Fix upgen test
Naatan May 11, 2022
d9120e4
Make poller test more robust
Naatan May 11, 2022
1109995
Cleanup
Naatan May 11, 2022
9b7990f
Debug failure
Naatan May 11, 2022
607cf41
Only shut down svc at end of suite
Naatan May 11, 2022
2302a9e
Attempt to fix job running forever
Naatan May 11, 2022
d9c34d1
Fix path assertion
Naatan May 11, 2022
65691f9
Fix nil pointer panic
Naatan May 11, 2022
b1b8869
Fix logging of test failure
Naatan May 11, 2022
5cb4ffa
Use different pkg
Naatan May 11, 2022
306cd9d
Make poller test less opinionated while still asserting success
Naatan May 11, 2022
d0a3ade
Update assertion
Naatan May 11, 2022
38e6714
Reduce timeout for integration tests
Naatan May 11, 2022
97cc10c
Debug update performance test
Naatan May 12, 2022
1c8555e
Fix CI authentication for user cleanup
Naatan May 12, 2022
5dd1458
Let the solver sort it out
Naatan May 12, 2022
24293b6
Disable test for now
Naatan May 12, 2022
d3c9a0c
Don't run with verbose
Naatan May 12, 2022
c4b1afa
Avoid mixing exit codes
Naatan May 12, 2022
5bc6cfc
Disable debug logging
Naatan May 12, 2022
591f66e
Ensure config is closed
Naatan May 12, 2022
e6d0bd2
Ensure svc has time to collect update info
Naatan May 12, 2022
14c712e
Retry on EOF
Naatan May 12, 2022
db8b5fb
Debug
Naatan May 12, 2022
507e7e6
Add debugging info to testfmt
Naatan May 13, 2022
8a70e8d
Ensure expectation times out
Naatan May 13, 2022
d9f541b
Debug hanging threads
Naatan May 13, 2022
ae161d3
Merge branch 'master' into DX-925
Naatan May 13, 2022
5498ba7
Enable debug logging again
Naatan May 13, 2022
39402d8
Revert "Debug hanging threads"
Naatan May 13, 2022
d33ebb3
Add space
Naatan May 13, 2022
b9354ad
Account for race condition
Naatan May 13, 2022
c7e8682
Debug log performance test for future failures
Naatan May 16, 2022
cf40c58
Fix test
Naatan May 16, 2022
d61147c
Merge branch 'master' into DX-925
Naatan May 16, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 6 additions & 2 deletions .github/workflows/build.yml
Expand Up @@ -242,7 +242,11 @@ jobs:
if [ "$START" == "Test" ]; then
TAG=${i##*:}
TAG=$(echo $TAG | xargs)
TEST_SUITE_TAGS="$TAG:$TEST_SUITE_TAGS"
if [[ "$TEST_SUITE_TAGS" == "" ]]; then
TEST_SUITE_TAGS=$TAG
else
TEST_SUITE_TAGS="$TAG:$TEST_SUITE_TAGS"
fi
fi
done

Expand All @@ -262,7 +266,7 @@ jobs:
export TEST_SUITE_TAGS="$TEST_SUITE_TAGS"
TIMEOUT=10m
if [[ "$TEST_SUITE_TAGS" == "all" ]]; then
TIMEOUT=90m
TIMEOUT=30m
fi
set +e
SHELL='' go test -timeout $TIMEOUT -v `go list ./... | grep integration` &> build/integration-tests.out
Expand Down
2 changes: 1 addition & 1 deletion .gotestfmt/package.gotpl
Expand Up @@ -23,7 +23,7 @@ we are creating a stylized header for each package.
{{- else -}}
{{ "\033" }}[0;31m❌
{{- end -}}
{{ " " }}{{- .Name -}}
{{ " " }}{{- .Name -}}{{ " " }}[{{ .Result -}}]
{{- "\033" -}}[0;37m ({{ .Duration -}}
{{- with .Coverage -}}
, coverage: {{ . }}%
Expand Down
7 changes: 4 additions & 3 deletions cmd/state-installer/cmd.go
Expand Up @@ -62,8 +62,8 @@ func main() {
exitCode = 1
}

if err := cfg.Close(); err != nil {
multilog.Error("Failed to close config: %v", err)
if cfg != nil {
events.Close("config", cfg.Close)
}

if err := events.WaitForEvents(5*time.Second, rollbar.Wait, an.Wait, logging.Close); err != nil {
Expand All @@ -78,7 +78,8 @@ func main() {
rollbar.SetupRollbar(constants.StateInstallerRollbarToken)

// Set up configuration handler
cfg, err := config.New()
var err error
cfg, err = config.New()
if err != nil {
multilog.Error("Could not set up configuration handler: " + errs.JoinMessage(err))
fmt.Fprintln(os.Stderr, err.Error())
Expand Down
2 changes: 1 addition & 1 deletion cmd/state-installer/installer.go
Expand Up @@ -126,7 +126,7 @@ func (i *Installer) Install() (rerr error) {

// Run state _prepare after updates to facilitate anything the new version of the state tool might need to set up
// Yes this is awkward, followup story here: https://www.pivotaltracker.com/story/show/176507898
if stdout, stderr, err := exeutils.ExecSimple(stateExec, "_prepare"); err != nil {
if stdout, stderr, err := exeutils.ExecSimple(stateExec, []string{"_prepare"}, []string{}); err != nil {
multilog.Error("_prepare failed after update: %v\n\nstdout: %s\n\nstderr: %s", err, stdout, stderr)
}

Expand Down
55 changes: 3 additions & 52 deletions cmd/state-svc/internal/deprecation/deprecation.go
Expand Up @@ -13,10 +13,8 @@ import (
"github.com/ActiveState/cli/internal/graph"
"github.com/ActiveState/cli/internal/locale"
"github.com/ActiveState/cli/internal/logging"
"github.com/ActiveState/cli/internal/multilog"
"github.com/ActiveState/cli/internal/retryhttp"
"github.com/hashicorp/go-version"
"github.com/patrickmn/go-cache"
)

const (
Expand All @@ -39,8 +37,6 @@ type info struct {
// Checker is the struct that we use to do checks with
type Checker struct {
config configurable
cache *cache.Cache
done chan struct{}
}

// configurable defines the configuration function used by the functions in this package
Expand All @@ -55,61 +51,20 @@ type configurable interface {
func NewChecker(configuration configurable) *Checker {
checker := &Checker{
configuration,
cache.New(15*time.Minute, 5*time.Minute),
make(chan struct{}),
}

go checker.pollDeprecationInfo()

return checker
}

// Check will Check if the current version of the tool is deprecated and returns deprecation info if it is.
// This uses a fairly short timeout to Check against our deprecation url, so this should not be considered conclusive.
func (checker *Checker) Check() (*graph.DeprecationInfo, error) {
data, exists := checker.cache.Get(cacheKey)
if !exists {
logging.Debug("No deprecation information cached")
return nil, nil
}

deprecationInfo, ok := data.(*graph.DeprecationInfo)
if !ok {
return nil, errs.New("Unexpected cache entry for deprecation info")
}
return deprecationInfo, nil
}

func (checker *Checker) pollDeprecationInfo() {
timer := time.NewTicker(1 * time.Hour)
defer timer.Stop()

for {
select {
case <-timer.C:
err := checker.Refresh()
if err != nil {
multilog.Error("Could not update deprecation information %s", errs.JoinMessage(err))
return
}
case <-checker.done:
return
}
}
}

func (checker *Checker) Refresh() error {
info, err := checker.fetchDeprecationInfo()
deprecationInfo, err := checker.fetchDeprecationInfo()
if err != nil {
return errs.Wrap(err, "Could not fetch deprecation information")
}
if info == nil {
return nil
return nil, errs.Wrap(err, "Could not fetch deprecation information")
}

checker.cache.Set(cacheKey, info, cache.DefaultExpiration)

return nil
return deprecationInfo, nil
}

func (checker *Checker) fetchDeprecationInfo() (*graph.DeprecationInfo, error) {
Expand Down Expand Up @@ -197,7 +152,3 @@ func initializeInfo(data []byte) ([]info, error) {
return info, nil
}

func (checker *Checker) Close() {
logging.Debug("Closing deprecation checker")
checker.done <- struct{}{}
}
55 changes: 25 additions & 30 deletions cmd/state-svc/internal/resolver/resolver.go
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/ActiveState/cli/internal/analytics/client/sync"
"github.com/ActiveState/cli/internal/analytics/dimensions"
"github.com/ActiveState/cli/internal/cache/projectcache"
"github.com/ActiveState/cli/internal/poller"
"github.com/ActiveState/cli/pkg/platform/authentication"
"golang.org/x/net/context"

Expand All @@ -23,13 +24,12 @@ import (
configMediator "github.com/ActiveState/cli/internal/mediators/config"
"github.com/ActiveState/cli/internal/updater"
"github.com/ActiveState/cli/pkg/projectfile"
"github.com/patrickmn/go-cache"
)

type Resolver struct {
cfg *config.Instance
cache *cache.Cache
deprecation *deprecation.Checker
depPoller *poller.Poller
updatePoller *poller.Poller
projectIDCache *projectcache.ID
an *sync.Client
anForClient *sync.Client // Use separate client for events sent through service so we don't contaminate one with the other
Expand All @@ -39,16 +39,21 @@ type Resolver struct {
// var _ genserver.ResolverRoot = &Resolver{} // Must implement ResolverRoot

func New(cfg *config.Instance, an *sync.Client, auth *authentication.Auth) (*Resolver, error) {
checker := deprecation.NewChecker(cfg)
err := checker.Refresh()
if err != nil {
return nil, errs.Wrap(err, "Could not refresh deprecation info")
}
depchecker := deprecation.NewChecker(cfg)
pollDep := poller.New(1*time.Hour, func() (interface{}, error) {
return depchecker.Check()
})

upchecker := updater.NewDefaultChecker(cfg)
pollUpdate := poller.New(1*time.Hour, func() (interface{}, error) {
return upchecker.Check()
})

anForClient := sync.New(cfg, auth)
return &Resolver{
cfg,
cache.New(12*time.Hour, time.Hour),
checker,
pollDep,
pollUpdate,
projectcache.NewID(),
an,
anForClient,
Expand All @@ -57,7 +62,8 @@ func New(cfg *config.Instance, an *sync.Client, auth *authentication.Auth) (*Res
}

func (r *Resolver) Close() error {
r.deprecation.Close()
r.depPoller.Close()
r.updatePoller.Close()
r.anForClient.Close()
return r.rtwatch.Close()
}
Expand Down Expand Up @@ -85,24 +91,13 @@ func (r *Resolver) AvailableUpdate(ctx context.Context) (*graph.AvailableUpdate,
logging.Debug("AvailableUpdate resolver")
defer logging.Debug("AvailableUpdate done")

const cacheKey = "AvailableUpdate"
if up, exists := r.cache.Get(cacheKey); exists {
logging.Debug("Using cache")
return up.(*graph.AvailableUpdate), nil
}

var availableUpdate *graph.AvailableUpdate
defer func() { r.cache.Set(cacheKey, availableUpdate, cache.DefaultExpiration) }()

update, err := updater.NewDefaultChecker(r.cfg).Check()
if err != nil {
return nil, errs.Wrap(err, "Failed to check for available update")
}
if update == nil {
update, ok := r.updatePoller.ValueFromCache().(*updater.AvailableUpdate)
if !ok {
logging.Debug("No update info in cache")
return nil, nil
}

availableUpdate = &graph.AvailableUpdate{
availableUpdate := &graph.AvailableUpdate{
Version: update.Version,
Channel: update.Channel,
Path: update.Path,
Expand Down Expand Up @@ -147,7 +142,7 @@ func (r *Resolver) AnalyticsEvent(_ context.Context, category, action string, _l
// Resolve the project ID - this is a little awkward since I had to work around an import cycle
dims.RegisterPreProcessor(func(values *dimensions.Values) error {
values.ProjectID = nil
if values.ProjectNameSpace == nil {
if values.ProjectNameSpace == nil || *values.ProjectNameSpace == "" {
return nil
}
id, err := r.projectIDCache.FromNamespace(*values.ProjectNameSpace)
Expand Down Expand Up @@ -178,9 +173,9 @@ func (r *Resolver) RuntimeUsage(ctx context.Context, pid int, exec string, dimen
func (r *Resolver) CheckDeprecation(ctx context.Context) (*graph.DeprecationInfo, error) {
logging.Debug("Check deprecation resolver")

deprecated, err := r.deprecation.Check()
if err != nil {
return nil, errs.Wrap(err, "Could not fetch deprecation information")
deprecated, ok := r.depPoller.ValueFromCache().(*graph.DeprecationInfo)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won't panic if the value from ValueFromCache() is nil right? I'm pretty sure it won't. Might be something nice to confirm in the unit test for the poller

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't confirm it in the poller, because the value type is an interface and we can't reliably assert nil unless we know the type.

We're not doing anything with the returned value here, other than also return it. And as per the contract of the function it CAN return a nil, which isn't a new change.

if !ok {
logging.Debug("No deprecation info in cache")
}

return deprecated, nil
Expand Down
7 changes: 4 additions & 3 deletions cmd/state-svc/main.go
Expand Up @@ -45,8 +45,8 @@ func main() {
exitCode = 1
}

if err := cfg.Close(); err != nil {
multilog.Error("Failed to close config: %v", err)
if cfg != nil {
events.Close("config", cfg.Close)
}

if err := events.WaitForEvents(5*time.Second, rollbar.Wait, authentication.LegacyClose, logging.Close); err != nil {
Expand All @@ -55,7 +55,8 @@ func main() {
os.Exit(exitCode)
}()

cfg, err := config.New()
var err error
cfg, err = config.New()
if err != nil {
multilog.Critical("Could not initialize config: %v", errs.JoinMessage(err))
fmt.Fprintf(os.Stderr, "Could not load config, if this problem persists please reinstall the State Tool. Error: %s\n", errs.JoinMessage(err))
Expand Down
13 changes: 5 additions & 8 deletions cmd/state-tray/main.go
Expand Up @@ -59,8 +59,8 @@ func onReady() {
}
logging.Debug("onReady is done with exit code %d", exitCode)

if err := cfg.Close(); err != nil {
multilog.Error("Failed to close config after exiting systray: %v", err)
if cfg != nil {
events.Close("config", cfg.Close)
}

if err := events.WaitForEvents(1*time.Second, rollbar.Wait, authentication.LegacyClose, logging.Close); err != nil {
Expand All @@ -69,7 +69,8 @@ func onReady() {
os.Exit(exitCode)
}()

cfg, err := config.New()
var err error
cfg, err = config.New()
if err != nil {
multilog.Critical("Could not initialize config: %v", errs.JoinMessage(err))
fmt.Fprintf(os.Stderr, "Could not load config, if this problem persists please reinstall the State Tool. Error: %s\n", errs.JoinMessage(err))
Expand Down Expand Up @@ -275,11 +276,7 @@ func onExit() {
multilog.Error("Could not get configuration object on Systray exit")
return
}
defer func() {
if err := cfg.Close(); err != nil {
multilog.Error("Failed to close config after exiting systray: %v", err)
}
}()
defer events.Close("config", cfg.Close)
err = cfg.GetThenSet(installmgr.ConfigKeyTrayPid, func(currentValue interface{}) (interface{}, error) {
setPid := cast.ToInt(currentValue)
if setPid != os.Getpid() {
Expand Down
9 changes: 6 additions & 3 deletions cmd/state-update-dialog/main.go
Expand Up @@ -28,8 +28,10 @@ func main() {
exitCode = 1
}

if err := cfg.Close(); err != nil {
multilog.Error("Failed to close config after exiting systray: %v", err)
if cfg != nil {
if err := cfg.Close(); err != nil {
multilog.Error("Failed to close config after exiting systray: %v", err)
}
}

if err := events.WaitForEvents(1*time.Second, rollbar.Wait, authentication.LegacyClose, logging.Close); err != nil {
Expand All @@ -38,7 +40,8 @@ func main() {
os.Exit(exitCode)
}()

cfg, err := config.New()
var err error
cfg, err = config.New()
if err != nil {
multilog.Critical("Could not initialize config: %v", errs.JoinMessage(err))
fmt.Fprintf(os.Stderr, "Could not load config, if this problem persists please reinstall the State Tool. Error: %s\n", errs.JoinMessage(err))
Expand Down
4 changes: 4 additions & 0 deletions cmd/state/errors.go
Expand Up @@ -132,5 +132,9 @@ func unwrapError(err error) (int, error) {
}
}

if hasMarshaller {
return code, err
}

return code, &OutputError{err}
}
11 changes: 9 additions & 2 deletions cmd/state/main.go
Expand Up @@ -44,6 +44,8 @@ import (
)

func main() {
startTime := time.Now()

var exitCode int
// Set up logging
rollbar.SetupRollbar(constants.StateToolRollbarToken)
Expand All @@ -60,13 +62,18 @@ func main() {
logging.Warning("Failed waiting for events: %v", err)
}

events.Close("config", cfg.Close)
if cfg != nil {
events.Close("config", cfg.Close)
}

profile.Measure("main", startTime)

// exit with exitCode
os.Exit(exitCode)
}()

cfg, err := config.New()
var err error
cfg, err = config.New()
if err != nil {
multilog.Critical("Could not initialize config: %v", errs.JoinMessage(err))
fmt.Fprintf(os.Stderr, "Could not load config, if this problem persists please reinstall the State Tool. Error: %s\n", errs.JoinMessage(err))
Expand Down