How to use GoModDownload method of performance_test Package

Best Ginkgo code snippet using performance_test.GoModDownload

Run Ginkgo automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

performance_suite_test.go

Source: performance_suite_test.go Github

copy
1package performance_test
2
3import (
4	"flag"
5	"fmt"
6	"math/rand"
7	"os"
8	"os/exec"
9	"path/filepath"
10	"strings"
11	"sync"
12	"testing"
13	"time"
14
15	. "github.com/onsi/ginkgo/v2"
16	"github.com/onsi/ginkgo/v2/ginkgo/internal"
17	"github.com/onsi/ginkgo/v2/types"
18	. "github.com/onsi/gomega"
19	"github.com/onsi/gomega/format"
20	"github.com/onsi/gomega/gbytes"
21	"github.com/onsi/gomega/gexec"
22	"github.com/onsi/gomega/gmeasure"
23)
24
25var pathToGinkgo string
26var DEBUG bool
27var pfm PerformanceFixtureManager
28var gmcm GoModCacheManager
29
30func init() {
31	flag.BoolVar(&DEBUG, "debug", false, "keep assets around after test run")
32}
33
34func TestPerformance(t *testing.T) {
35	SetDefaultEventuallyTimeout(30 * time.Second)
36	format.TruncatedDiff = false
37	RegisterFailHandler(Fail)
38	RunSpecs(t, "Performance Suite", Label("performance"))
39}
40
41var _ = SynchronizedBeforeSuite(func() []byte {
42	pathToGinkgo, err := gexec.Build("../../ginkgo")
43	Ω(err).ShouldNot(HaveOccurred())
44	return []byte(pathToGinkgo)
45}, func(computedPathToGinkgo []byte) {
46	pathToGinkgo = string(computedPathToGinkgo)
47})
48
49var _ = SynchronizedAfterSuite(func() {}, func() {
50	gexec.CleanupBuildArtifacts()
51})
52
53/*
54	GoModCacheManager sets up a new GOMODCACHE and knows how to clear it
55	This allows us to bust the go mod cache.
56*/
57type GoModCacheManager struct {
58	Path         string
59	OldCachePath string
60}
61
62func NewGoModCacheManager(path string) GoModCacheManager {
63	err := os.MkdirAll(path, 0700)
64	Ω(err).ShouldNot(HaveOccurred())
65	absPath, err := filepath.Abs(path)
66	Ω(err).ShouldNot(HaveOccurred())
67	oldCachePath := os.Getenv("GOMODCACHE")
68	os.Setenv("GOMODCACHE", absPath)
69	return GoModCacheManager{
70		Path:         path,
71		OldCachePath: oldCachePath,
72	}
73
74}
75
76func (m GoModCacheManager) Clear() {
77	cmd := exec.Command("go", "clean", "-modcache")
78	session, err := gexec.Start(cmd, GinkgoWriter, GinkgoWriter)
79	Ω(err).ShouldNot(HaveOccurred())
80	Eventually(session).Should(gexec.Exit(0))
81}
82
83func (m GoModCacheManager) Cleanup() {
84	m.Clear()
85	if m.OldCachePath == "" {
86		os.Unsetenv("GOMODCACHE")
87	} else {
88		os.Setenv("GOMODCACHE", m.OldCachePath)
89	}
90}
91
92/* PerformanceFixtureManager manages fixture data */
93type PerformanceFixtureManager struct {
94	TmpDir string
95}
96
97func NewPerformanceFixtureManager(tmpDir string) PerformanceFixtureManager {
98	err := os.MkdirAll(tmpDir, 0700)
99	Ω(err).ShouldNot(HaveOccurred())
100	return PerformanceFixtureManager{
101		TmpDir: tmpDir,
102	}
103}
104
105func (f PerformanceFixtureManager) Cleanup() {
106	Ω(os.RemoveAll(f.TmpDir)).Should(Succeed())
107}
108
109func (f PerformanceFixtureManager) MountFixture(fixture string, subPackage ...string) {
110	src := filepath.Join("_fixtures", fixture+"_fixture")
111	dst := filepath.Join(f.TmpDir, fixture)
112
113	if len(subPackage) > 0 {
114		src = filepath.Join(src, subPackage[0])
115		dst = filepath.Join(dst, subPackage[0])
116	}
117
118	f.copyIn(src, dst)
119}
120
121func (f PerformanceFixtureManager) copyIn(src string, dst string) {
122	Expect(os.MkdirAll(dst, 0777)).To(Succeed())
123
124	files, err := os.ReadDir(src)
125	Expect(err).NotTo(HaveOccurred())
126
127	for _, file := range files {
128		srcPath := filepath.Join(src, file.Name())
129		dstPath := filepath.Join(dst, file.Name())
130		if file.IsDir() {
131			f.copyIn(srcPath, dstPath)
132			continue
133		}
134
135		srcContent, err := os.ReadFile(srcPath)
136		Ω(err).ShouldNot(HaveOccurred())
137		Ω(os.WriteFile(dstPath, srcContent, 0666)).Should(Succeed())
138	}
139}
140
141func (f PerformanceFixtureManager) PathTo(pkg string, target ...string) string {
142	if len(target) == 0 {
143		return filepath.Join(f.TmpDir, pkg)
144	}
145	components := append([]string{f.TmpDir, pkg}, target...)
146	return filepath.Join(components...)
147}
148
149/* GoModDownload runs go mod download for a given package */
150func GoModDownload(fixture string) {
151	cmd := exec.Command("go", "mod", "download")
152	cmd.Dir = pfm.PathTo(fixture)
153	sess, err := gexec.Start(cmd, GinkgoWriter, GinkgoWriter)
154	Ω(err).ShouldNot(HaveOccurred())
155	Eventually(sess).Should(gexec.Exit(0))
156}
157
158/* ScenarioSettings configures the test scenario */
159type ScenarioSettings struct {
160	Fixture         string
161	NumSuites       int
162	Recurse         bool
163	ClearGoModCache bool
164
165	ConcurrentCompilers       int
166	ConcurrentRunners         int
167	CompileFirstSuiteSerially bool
168	GoModDownloadFirst        bool
169
170	UseGoTestDirectly            bool
171	ConcurrentGoTests            int
172	GoTestCompileThenRunSerially bool
173	GoTestRecurse                bool
174}
175
176func (s ScenarioSettings) Name() string {
177	out := []string{s.Fixture}
178	if s.UseGoTestDirectly {
179		if s.GoTestCompileThenRunSerially {
180			out = append(out, "go test -c; then run (serially)")
181		} else if s.GoTestRecurse {
182			out = append(out, "go test ./...")
183		} else {
184			out = append(out, "go test")
185			if s.ConcurrentGoTests == 1 {
186				out = append(out, "serially")
187			} else {
188				out = append(out, fmt.Sprintf("run concurrently [%d]", s.ConcurrentGoTests))
189			}
190		}
191	} else {
192		if s.ConcurrentCompilers == 1 {
193			out = append(out, "compile serially")
194		} else {
195			out = append(out, fmt.Sprintf("compile concurrently [%d]", s.ConcurrentCompilers))
196		}
197		if s.ConcurrentRunners == 1 {
198			out = append(out, "run serially")
199		} else {
200			out = append(out, fmt.Sprintf("run concurrently [%d]", s.ConcurrentRunners))
201		}
202		if s.CompileFirstSuiteSerially {
203			out = append(out, "will compile first suite serially")
204		}
205		if s.GoModDownloadFirst {
206			out = append(out, "will go mod download first")
207		}
208	}
209	return strings.Join(out, " - ")
210}
211
212func SampleScenarios(cache gmeasure.ExperimentCache, numSamples int, cacheVersion int, runGoModDownload bool, scenarios ...ScenarioSettings) {
213	// we randomize the sample set of scenarios to try to avoid any systematic effects that emerge
214	// during the run (e.g. change in internet connection speed, change in computer performance)
215
216	experiments := map[string]*gmeasure.Experiment{}
217	runs := []ScenarioSettings{}
218	for _, scenario := range scenarios {
219		name := scenario.Name()
220		if experiment := cache.Load(name, cacheVersion); experiment != nil {
221			AddReportEntry(name, experiment, Offset(1), ReportEntryVisibilityFailureOrVerbose)
222			continue
223		}
224		experiments[name] = gmeasure.NewExperiment(name)
225		AddReportEntry(name, experiments[name], Offset(1), ReportEntryVisibilityFailureOrVerbose)
226		for i := 0; i < numSamples; i++ {
227			runs = append(runs, scenario)
228		}
229	}
230	rand.New(rand.NewSource(GinkgoRandomSeed())).Shuffle(len(runs), func(i, j int) {
231		runs[i], runs[j] = runs[j], runs[i]
232	})
233
234	if len(runs) > 0 && runGoModDownload {
235		GoModDownload("performance")
236	}
237
238	for idx, run := range runs {
239		fmt.Printf("%d - %s\n", idx, run.Name())
240		RunScenario(experiments[run.Name()].NewStopwatch(), run, gmeasure.Annotation(fmt.Sprintf("%d", idx+1)))
241	}
242
243	for name, experiment := range experiments {
244		cache.Save(name, cacheVersion, experiment)
245	}
246}
247
248func AnalyzeCache(cache gmeasure.ExperimentCache) {
249	headers, err := cache.List()
250	Ω(err).ShouldNot(HaveOccurred())
251
252	experiments := []*gmeasure.Experiment{}
253	for _, header := range headers {
254		experiments = append(experiments, cache.Load(header.Name, header.Version))
255	}
256
257	for _, measurement := range []string{"first-output", "total-runtime"} {
258		stats := []gmeasure.Stats{}
259		for _, experiment := range experiments {
260			stats = append(stats, experiment.GetStats(measurement))
261		}
262		AddReportEntry(measurement, gmeasure.RankStats(gmeasure.LowerMedianIsBetter, stats...))
263	}
264}
265
266func RunScenario(stopwatch *gmeasure.Stopwatch, settings ScenarioSettings, annotation gmeasure.Annotation) {
267	if settings.ClearGoModCache {
268		gmcm.Clear()
269	}
270
271	if settings.GoModDownloadFirst {
272		GoModDownload(settings.Fixture)
273		stopwatch.Record("mod-download", annotation)
274	}
275
276	if settings.UseGoTestDirectly {
277		RunScenarioWithGoTest(stopwatch, settings, annotation)
278	} else {
279		RunScenarioWithGinkgoInternals(stopwatch, settings, annotation)
280	}
281}
282
283/* CompileAndRun uses the Ginkgo CLIs internals to compile and run tests with different possible settings governing concurrency and ordering */
284func RunScenarioWithGinkgoInternals(stopwatch *gmeasure.Stopwatch, settings ScenarioSettings, annotation gmeasure.Annotation) {
285	cliConfig := types.NewDefaultCLIConfig()
286	cliConfig.Recurse = settings.Recurse
287	suiteConfig := types.NewDefaultSuiteConfig()
288	reporterConfig := types.NewDefaultReporterConfig()
289	reporterConfig.Succinct = true
290	goFlagsConfig := types.NewDefaultGoFlagsConfig()
291
292	suites := internal.FindSuites([]string{pfm.PathTo(settings.Fixture)}, cliConfig, true)
293	Ω(suites).Should(HaveLen(settings.NumSuites))
294
295	compile := make(chan internal.TestSuite, len(suites))
296	compiled := make(chan internal.TestSuite, len(suites))
297	completed := make(chan internal.TestSuite, len(suites))
298	firstOutputOnce := sync.Once{}
299
300	for compiler := 0; compiler < settings.ConcurrentCompilers; compiler++ {
301		go func() {
302			for suite := range compile {
303				if !suite.State.Is(internal.TestSuiteStateCompiled) {
304					subStopwatch := stopwatch.NewStopwatch()
305					suite = internal.CompileSuite(suite, goFlagsConfig)
306					subStopwatch.Record("compile-test: "+suite.PackageName, annotation)
307					Ω(suite.CompilationError).Should(BeNil())
308				}
309				compiled <- suite
310			}
311		}()
312	}
313
314	if settings.CompileFirstSuiteSerially {
315		compile <- suites[0]
316		suites[0] = <-compiled
317	}
318
319	for runner := 0; runner < settings.ConcurrentRunners; runner++ {
320		go func() {
321			for suite := range compiled {
322				firstOutputOnce.Do(func() {
323					stopwatch.Record("first-output", annotation, gmeasure.Style("{{cyan}}"))
324				})
325				subStopwatch := stopwatch.NewStopwatch()
326				suite = internal.RunCompiledSuite(suite, suiteConfig, reporterConfig, cliConfig, goFlagsConfig, []string{})
327				subStopwatch.Record("run-test: "+suite.PackageName, annotation)
328				Ω(suite.State).Should(Equal(internal.TestSuiteStatePassed))
329				completed <- suite
330			}
331		}()
332	}
333
334	for _, suite := range suites {
335		compile <- suite
336	}
337
338	completedSuites := []internal.TestSuite{}
339	for suite := range completed {
340		completedSuites = append(completedSuites, suite)
341		if len(completedSuites) == len(suites) {
342			close(completed)
343			close(compile)
344			close(compiled)
345		}
346	}
347
348	stopwatch.Record("total-runtime", annotation, gmeasure.Style("{{green}}"))
349	internal.Cleanup(goFlagsConfig, completedSuites...)
350}
351
352func RunScenarioWithGoTest(stopwatch *gmeasure.Stopwatch, settings ScenarioSettings, annotation gmeasure.Annotation) {
353	defer func() {
354		stopwatch.Record("total-runtime", annotation, gmeasure.Style("{{green}}"))
355	}()
356
357	if settings.GoTestRecurse {
358		cmd := exec.Command("go", "test", "-count=1", "./...")
359		cmd.Dir = pfm.PathTo(settings.Fixture)
360		sess, err := gexec.Start(cmd, GinkgoWriter, GinkgoWriter)
361		Ω(err).ShouldNot(HaveOccurred())
362		Eventually(sess).Should(gbytes.Say(`.`)) //should say _something_ eventually!
363		stopwatch.Record("first-output", annotation, gmeasure.Style("{{cyan}}"))
364		Eventually(sess).Should(gexec.Exit(0))
365		return
366	}
367
368	cliConfig := types.NewDefaultCLIConfig()
369	cliConfig.Recurse = settings.Recurse
370	suites := internal.FindSuites([]string{pfm.PathTo(settings.Fixture)}, cliConfig, true)
371	Ω(suites).Should(HaveLen(settings.NumSuites))
372	firstOutputOnce := sync.Once{}
373
374	if settings.GoTestCompileThenRunSerially {
375		for _, suite := range suites {
376			subStopwatch := stopwatch.NewStopwatch()
377			cmd := exec.Command("go", "test", "-c", "-o=out.test")
378			cmd.Dir = suite.AbsPath()
379			sess, err := gexec.Start(cmd, GinkgoWriter, GinkgoWriter)
380			Ω(err).ShouldNot(HaveOccurred())
381			Eventually(sess).Should(gexec.Exit(0))
382			subStopwatch.Record("compile-test: "+suite.PackageName, annotation).Reset()
383
384			firstOutputOnce.Do(func() {
385				stopwatch.Record("first-output", annotation, gmeasure.Style("{{cyan}}"))
386			})
387			cmd = exec.Command("./out.test")
388			cmd.Dir = suite.AbsPath()
389			sess, err = gexec.Start(cmd, GinkgoWriter, GinkgoWriter)
390			Ω(err).ShouldNot(HaveOccurred())
391			Eventually(sess).Should(gexec.Exit(0))
392			subStopwatch.Record("run-test: "+suite.PackageName, annotation)
393
394			Ω(os.Remove(filepath.Join(suite.AbsPath(), "out.test"))).Should(Succeed())
395		}
396	} else {
397		run := make(chan internal.TestSuite, len(suites))
398		completed := make(chan internal.TestSuite, len(suites))
399		for runner := 0; runner < settings.ConcurrentGoTests; runner++ {
400			go func() {
401				for suite := range run {
402					subStopwatch := stopwatch.NewStopwatch()
403					cmd := exec.Command("go", "test", "-count=1")
404					cmd.Dir = suite.AbsPath()
405					sess, err := gexec.Start(cmd, GinkgoWriter, GinkgoWriter)
406					Ω(err).ShouldNot(HaveOccurred())
407					Eventually(sess).Should(gbytes.Say(`.`)) //should say _something_ eventually!
408					firstOutputOnce.Do(func() {
409						stopwatch.Record("first-output", annotation, gmeasure.Style("{{cyan}}"))
410					})
411					Eventually(sess).Should(gexec.Exit(0))
412					subStopwatch.Record("run-test: "+suite.PackageName, annotation)
413					completed <- suite
414				}
415			}()
416		}
417		for _, suite := range suites {
418			run <- suite
419		}
420		numCompleted := 0
421		for _ = range completed {
422			numCompleted += 1
423			if numCompleted == len(suites) {
424				close(completed)
425				close(run)
426			}
427		}
428	}
429}
430
431func ginkgoCommand(dir string, args ...string) *exec.Cmd {
432	cmd := exec.Command(pathToGinkgo, args...)
433	cmd.Dir = dir
434
435	return cmd
436}
437
438func startGinkgo(dir string, args ...string) *gexec.Session {
439	cmd := ginkgoCommand(dir, args...)
440	session, err := gexec.Start(cmd, GinkgoWriter, GinkgoWriter)
441	Ω(err).ShouldNot(HaveOccurred())
442	return session
443}
444
445func startGinkgoWithEnv(dir string, env []string, args ...string) *gexec.Session {
446	cmd := ginkgoCommand(dir, args...)
447	cmd.Env = append(os.Environ(), env...)
448	session, err := gexec.Start(cmd, GinkgoWriter, GinkgoWriter)
449	Ω(err).ShouldNot(HaveOccurred())
450	return session
451}
452
Full Screen

Accelerate Your Automation Test Cycles With LambdaTest

Leverage LambdaTest’s cloud-based platform to execute your automation tests in parallel and trim down your test execution time significantly. Your first 100 automation testing minutes are on us.

Try LambdaTest

Trigger GoModDownload code on LambdaTest Cloud Grid

Execute automation tests with GoModDownload on a cloud-based Grid of 3000+ real browsers and operating systems for both web and mobile applications.

Test now for Free
LambdaTestX

We use cookies to give you the best experience. Cookies help to provide a more personalized experience and relevant advertising for you, and web analytics for us. Learn More in our Cookies policy, Privacy & Terms of service

Allow Cookie
Sarah

I hope you find the best code examples for your project.

If you want to accelerate automated browser testing, try LambdaTest. Your first 100 automation testing minutes are FREE.

Sarah Elson (Product & Growth Lead)