How to use HasStarted method of lib Package

Best K6 code snippet using lib.HasStarted

externally_controlled.go

Source:externally_controlled.go Github

copy

Full Screen

1/*2 *3 * k6 - a next-generation load testing tool4 * Copyright (C) 2019 Load Impact5 *6 * This program is free software: you can redistribute it and/or modify7 * it under the terms of the GNU Affero General Public License as8 * published by the Free Software Foundation, either version 3 of the9 * License, or (at your option) any later version.10 *11 * This program is distributed in the hope that it will be useful,12 * but WITHOUT ANY WARRANTY; without even the implied warranty of13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the14 * GNU Affero General Public License for more details.15 *16 * You should have received a copy of the GNU Affero General Public License17 * along with this program. If not, see <http://www.gnu.org/licenses/>.18 *19 */20package executor21import (22 "context"23 "errors"24 "fmt"25 "math"26 "sync"27 "sync/atomic"28 "time"29 "github.com/sirupsen/logrus"30 "gopkg.in/guregu/null.v3"31 "go.k6.io/k6/lib"32 "go.k6.io/k6/lib/types"33 "go.k6.io/k6/metrics"34 "go.k6.io/k6/ui/pb"35)36const externallyControlledType = "externally-controlled"37func init() {38 lib.RegisterExecutorConfigType(39 externallyControlledType,40 func(name string, rawJSON []byte) (lib.ExecutorConfig, error) {41 config := ExternallyControlledConfig{BaseConfig: NewBaseConfig(name, externallyControlledType)}42 err := lib.StrictJSONUnmarshal(rawJSON, &config)43 if err != nil {44 return config, err45 }46 if !config.MaxVUs.Valid {47 config.MaxVUs = config.VUs48 }49 return config, nil50 },51 )52}53// ExternallyControlledConfigParams contains all of the options that actually54// determine the scheduling of VUs in the externally controlled executor.55type ExternallyControlledConfigParams struct {56 VUs null.Int `json:"vus"`57 Duration types.NullDuration `json:"duration"` // 0 is a valid value, meaning infinite duration58 MaxVUs null.Int `json:"maxVUs"`59}60// Validate just checks the control options in isolation.61func (mecc ExternallyControlledConfigParams) Validate() (errors []error) {62 if mecc.VUs.Int64 < 0 {63 errors = append(errors, fmt.Errorf("the number of VUs can't be negative"))64 }65 if mecc.MaxVUs.Int64 < mecc.VUs.Int64 {66 errors = append(errors, fmt.Errorf(67 "the number of active VUs (%d) must be less than or equal to the number of maxVUs (%d)",68 mecc.VUs.Int64, mecc.MaxVUs.Int64,69 ))70 }71 if !mecc.Duration.Valid {72 errors = append(errors, fmt.Errorf("the duration must be specified, for infinite duration use 0"))73 } else if mecc.Duration.TimeDuration() < 0 {74 errors = append(errors, fmt.Errorf(75 "the duration can't be negative, for infinite duration use 0",76 ))77 }78 return errors79}80// ExternallyControlledConfig stores the number of currently active VUs, the max81// number of VUs and the executor duration. The duration can be 0, which means82// "infinite duration", i.e. the user has to manually abort the script.83type ExternallyControlledConfig struct {84 BaseConfig85 ExternallyControlledConfigParams86}87// Make sure we implement the lib.ExecutorConfig interface88var _ lib.ExecutorConfig = &ExternallyControlledConfig{}89// GetDescription returns a human-readable description of the executor options90func (mec ExternallyControlledConfig) GetDescription(_ *lib.ExecutionTuple) string {91 duration := "infinite"92 if mec.Duration.Duration != 0 {93 duration = mec.Duration.String()94 }95 return fmt.Sprintf(96 "Externally controlled execution with %d VUs, %d max VUs, %s duration",97 mec.VUs.Int64, mec.MaxVUs.Int64, duration,98 )99}100// Validate makes sure all options are configured and valid101func (mec ExternallyControlledConfig) Validate() []error {102 errors := append(mec.BaseConfig.Validate(), mec.ExternallyControlledConfigParams.Validate()...)103 if mec.GracefulStop.Valid {104 errors = append(errors, fmt.Errorf(105 "gracefulStop is not supported by the externally controlled executor",106 ))107 }108 return errors109}110// GetExecutionRequirements reserves the configured number of max VUs for the111// whole duration of the executor, so these VUs can be externally initialized in112// the beginning of the test.113//114// Importantly, if 0 (i.e. infinite) duration is configured, this executor115// doesn't emit the last step to relinquish these VUs.116//117// Also, the externally controlled executor doesn't set MaxUnplannedVUs in the118// returned steps, since their initialization and usage is directly controlled119// by the user, can be changed during the test runtime, and is effectively120// bounded only by the resources of the machine k6 is running on.121//122// This is not a problem, because the MaxUnplannedVUs are mostly meant to be123// used for calculating the maximum possible number of initialized VUs at any124// point during a test run. That's used for sizing purposes and for user qouta125// checking in the cloud execution, where the externally controlled executor126// isn't supported.127func (mec ExternallyControlledConfig) GetExecutionRequirements(et *lib.ExecutionTuple) []lib.ExecutionStep {128 startVUs := lib.ExecutionStep{129 TimeOffset: 0,130 PlannedVUs: uint64(et.ScaleInt64(mec.MaxVUs.Int64)), // user-configured, VUs to be pre-initialized131 MaxUnplannedVUs: 0, // intentional, see function comment132 }133 maxDuration := mec.Duration.TimeDuration()134 if maxDuration == 0 {135 // Infinite duration, don't emit 0 VUs at the end since there's no planned end136 return []lib.ExecutionStep{startVUs}137 }138 return []lib.ExecutionStep{startVUs, {139 TimeOffset: maxDuration,140 PlannedVUs: 0,141 MaxUnplannedVUs: 0, // intentional, see function comment142 }}143}144// IsDistributable simply returns false because there's no way to reliably145// distribute the externally controlled executor.146func (ExternallyControlledConfig) IsDistributable() bool {147 return false148}149// NewExecutor creates a new ExternallyControlled executor150func (mec ExternallyControlledConfig) NewExecutor(es *lib.ExecutionState, logger *logrus.Entry) (lib.Executor, error) {151 return &ExternallyControlled{152 BaseExecutor: NewBaseExecutor(mec, es, logger),153 config: mec,154 currentControlConfig: mec.ExternallyControlledConfigParams,155 configLock: &sync.RWMutex{},156 newControlConfigs: make(chan updateConfigEvent),157 pauseEvents: make(chan pauseEvent),158 hasStarted: make(chan struct{}),159 }, nil160}161// HasWork reports whether there is any work to be done for the given execution segment.162func (mec ExternallyControlledConfig) HasWork(_ *lib.ExecutionTuple) bool {163 // We can always initialize new VUs via the REST API, so return true.164 return true165}166type pauseEvent struct {167 isPaused bool168 err chan error169}170type updateConfigEvent struct {171 newConfig ExternallyControlledConfigParams172 err chan error173}174// ExternallyControlled is an implementation of the old k6 executor that could be175// controlled externally, via the k6 REST API. It implements both the176// lib.PausableExecutor and the lib.LiveUpdatableExecutor interfaces.177type ExternallyControlled struct {178 *BaseExecutor179 config ExternallyControlledConfig180 currentControlConfig ExternallyControlledConfigParams181 configLock *sync.RWMutex182 newControlConfigs chan updateConfigEvent183 pauseEvents chan pauseEvent184 hasStarted chan struct{}185}186// Make sure we implement all the interfaces187var (188 _ lib.Executor = &ExternallyControlled{}189 _ lib.PausableExecutor = &ExternallyControlled{}190 _ lib.LiveUpdatableExecutor = &ExternallyControlled{}191)192// GetCurrentConfig just returns the executor's current configuration.193func (mex *ExternallyControlled) GetCurrentConfig() ExternallyControlledConfig {194 mex.configLock.RLock()195 defer mex.configLock.RUnlock()196 return ExternallyControlledConfig{197 BaseConfig: mex.config.BaseConfig,198 ExternallyControlledConfigParams: mex.currentControlConfig,199 }200}201// GetConfig just returns the executor's current configuration, it's basically202// an alias of GetCurrentConfig that implements the more generic interface.203func (mex *ExternallyControlled) GetConfig() lib.ExecutorConfig {204 return mex.GetCurrentConfig()205}206// GetProgress just returns the executor's progress bar instance.207func (mex ExternallyControlled) GetProgress() *pb.ProgressBar {208 mex.configLock.RLock()209 defer mex.configLock.RUnlock()210 return mex.progress211}212// GetLogger just returns the executor's logger instance.213func (mex ExternallyControlled) GetLogger() *logrus.Entry {214 mex.configLock.RLock()215 defer mex.configLock.RUnlock()216 return mex.logger217}218// Init doesn't do anything...219func (mex ExternallyControlled) Init(ctx context.Context) error {220 return nil221}222// SetPaused pauses or resumes the executor.223func (mex *ExternallyControlled) SetPaused(paused bool) error {224 select {225 case <-mex.hasStarted:226 event := pauseEvent{isPaused: paused, err: make(chan error)}227 mex.pauseEvents <- event228 return <-event.err229 default:230 return fmt.Errorf("cannot pause the externally controlled executor before it has started")231 }232}233// UpdateConfig validates the supplied config and updates it in real time. It is234// possible to update the configuration even when k6 is paused, either in the235// beginning (i.e. when running k6 with --paused) or in the middle of the script236// execution.237func (mex *ExternallyControlled) UpdateConfig(ctx context.Context, newConf interface{}) error {238 newConfigParams, ok := newConf.(ExternallyControlledConfigParams)239 if !ok {240 return errors.New("invalid config type")241 }242 if errs := newConfigParams.Validate(); len(errs) != 0 {243 return fmt.Errorf("invalid configuration supplied: %s", lib.ConcatErrors(errs, ", "))244 }245 if newConfigParams.Duration.Valid && newConfigParams.Duration != mex.config.Duration {246 return fmt.Errorf("the externally controlled executor duration cannot be changed")247 }248 if newConfigParams.MaxVUs.Valid && newConfigParams.MaxVUs.Int64 < mex.config.MaxVUs.Int64 {249 // This limitation is because the externally controlled executor is250 // still an executor that participates in the overall k6 scheduling.251 // Thus, any VUs that were explicitly specified by the user in the252 // config may be reused from or by other executors.253 return fmt.Errorf(254 "the new number of max VUs cannot be lower than the starting number of max VUs (%d)",255 mex.config.MaxVUs.Int64,256 )257 }258 mex.configLock.Lock() // guard against a simultaneous start of the test (which will close hasStarted)259 select {260 case <-mex.hasStarted:261 mex.configLock.Unlock()262 event := updateConfigEvent{newConfig: newConfigParams, err: make(chan error)}263 mex.newControlConfigs <- event264 return <-event.err265 case <-ctx.Done():266 mex.configLock.Unlock()267 return ctx.Err()268 default:269 mex.currentControlConfig = newConfigParams270 mex.configLock.Unlock()271 return nil272 }273}274// This is a helper function that is used in run for non-infinite durations.275func (mex *ExternallyControlled) stopWhenDurationIsReached(ctx context.Context, duration time.Duration, cancel func()) {276 ctxDone := ctx.Done()277 checkInterval := time.NewTicker(100 * time.Millisecond)278 for {279 select {280 case <-ctxDone:281 checkInterval.Stop()282 return283 // TODO: something saner and more optimized that sleeps for pauses and284 // doesn't depend on the global execution state?285 case <-checkInterval.C:286 elapsed := mex.executionState.GetCurrentTestRunDuration() - mex.config.StartTime.TimeDuration()287 if elapsed >= duration {288 cancel()289 return290 }291 }292 }293}294// manualVUHandle is a wrapper around the vuHandle helper, used in the295// ramping-vus executor. Here, instead of using its getVU and returnVU296// methods to retrieve and return a VU from the global buffer, we use them to297// accurately update the local and global active VU counters and to ensure that298// the pausing and reducing VUs operations wait for VUs to fully finish299// executing their current iterations before returning.300type manualVUHandle struct {301 *vuHandle302 initVU lib.InitializedVU303 wg *sync.WaitGroup304 // This is the cancel of the local context, used to kill its goroutine when305 // we reduce the number of MaxVUs, so that the Go GC can clean up the VU.306 cancelVU func()307}308func (rs *externallyControlledRunState) newManualVUHandle(309 initVU lib.InitializedVU, logger *logrus.Entry,310) *manualVUHandle {311 wg := sync.WaitGroup{}312 state := rs.executor.executionState313 getVU := func() (lib.InitializedVU, error) {314 wg.Add(1)315 state.ModCurrentlyActiveVUsCount(+1)316 atomic.AddInt64(rs.activeVUsCount, +1)317 return initVU, nil318 }319 returnVU := func(_ lib.InitializedVU) {320 state.ModCurrentlyActiveVUsCount(-1)321 atomic.AddInt64(rs.activeVUsCount, -1)322 wg.Done()323 }324 ctx, cancel := context.WithCancel(rs.ctx)325 return &manualVUHandle{326 vuHandle: newStoppedVUHandle(ctx, getVU, returnVU,327 rs.executor.nextIterationCounters,328 &rs.executor.config.BaseConfig, logger),329 initVU: initVU,330 wg: &wg,331 cancelVU: cancel,332 }333}334// externallyControlledRunState is created and initialized by the Run() method335// of the externally controlled executor. It is used to track and modify various336// details of the execution, including handling of live config changes.337type externallyControlledRunState struct {338 ctx context.Context339 executor *ExternallyControlled340 startMaxVUs int64 // the scaled number of initially configured MaxVUs341 duration time.Duration // the total duration of the executor, could be 0 for infinite342 activeVUsCount *int64 // the current number of active VUs, used only for the progress display343 maxVUs *int64 // the current number of initialized VUs344 vuHandles []*manualVUHandle // handles for manipulating and tracking all of the VUs345 currentlyPaused bool // whether the executor is currently paused346 runIteration func(context.Context, lib.ActiveVU) bool // a helper closure function that runs a single iteration347}348// retrieveStartMaxVUs gets and initializes the (scaled) number of MaxVUs349// from the global VU buffer. These are the VUs that the user originally350// specified in the JS config, and that the ExecutionScheduler pre-initialized351// for us.352func (rs *externallyControlledRunState) retrieveStartMaxVUs() error {353 for i := int64(0); i < rs.startMaxVUs; i++ { // get the initial planned VUs from the common buffer354 initVU, vuGetErr := rs.executor.executionState.GetPlannedVU(rs.executor.logger, false)355 if vuGetErr != nil {356 return vuGetErr357 }358 vuHandle := rs.newManualVUHandle(initVU, rs.executor.logger.WithField("vuNum", i))359 go vuHandle.runLoopsIfPossible(rs.runIteration)360 rs.vuHandles[i] = vuHandle361 }362 return nil363}364func (rs *externallyControlledRunState) progressFn() (float64, []string) {365 // TODO: simulate spinner for the other case or cycle 0-100?366 currentActiveVUs := atomic.LoadInt64(rs.activeVUsCount)367 currentMaxVUs := atomic.LoadInt64(rs.maxVUs)368 vusFmt := pb.GetFixedLengthIntFormat(currentMaxVUs)369 progVUs := fmt.Sprintf(vusFmt+"/"+vusFmt+" VUs", currentActiveVUs, currentMaxVUs)370 right := []string{progVUs, rs.duration.String(), ""}371 // TODO: use a saner way to calculate the elapsed time, without relying on372 // the global execution state...373 elapsed := rs.executor.executionState.GetCurrentTestRunDuration() - rs.executor.config.StartTime.TimeDuration()374 if elapsed > rs.duration {375 return 1, right376 }377 progress := 0.0378 if rs.duration > 0 {379 progress = math.Min(1, float64(elapsed)/float64(rs.duration))380 }381 spentDuration := pb.GetFixedLengthDuration(elapsed, rs.duration)382 progDur := fmt.Sprintf("%s/%s", spentDuration, rs.duration)383 right[1] = progDur384 return progress, right385}386func (rs *externallyControlledRunState) handleConfigChange(oldCfg, newCfg ExternallyControlledConfigParams) error {387 executionState := rs.executor.executionState388 et := executionState.ExecutionTuple389 oldActiveVUs := et.ScaleInt64(oldCfg.VUs.Int64)390 oldMaxVUs := et.ScaleInt64(oldCfg.MaxVUs.Int64)391 newActiveVUs := et.ScaleInt64(newCfg.VUs.Int64)392 newMaxVUs := et.ScaleInt64(newCfg.MaxVUs.Int64)393 rs.executor.logger.WithFields(logrus.Fields{394 "oldActiveVUs": oldActiveVUs, "oldMaxVUs": oldMaxVUs,395 "newActiveVUs": newActiveVUs, "newMaxVUs": newMaxVUs,396 }).Debug("Updating execution configuration...")397 for i := oldMaxVUs; i < newMaxVUs; i++ {398 select { // check if the user didn't try to abort k6 while we're scaling up the VUs399 case <-rs.ctx.Done():400 return rs.ctx.Err()401 default: // do nothing402 }403 initVU, vuInitErr := executionState.InitializeNewVU(rs.ctx, rs.executor.logger)404 if vuInitErr != nil {405 return vuInitErr406 }407 vuHandle := rs.newManualVUHandle(initVU, rs.executor.logger.WithField("vuNum", i))408 go vuHandle.runLoopsIfPossible(rs.runIteration)409 rs.vuHandles = append(rs.vuHandles, vuHandle)410 }411 if oldActiveVUs < newActiveVUs {412 for i := oldActiveVUs; i < newActiveVUs; i++ {413 if !rs.currentlyPaused {414 if err := rs.vuHandles[i].start(); err != nil {415 // TODO: maybe just log it ?416 return err417 }418 }419 }420 } else {421 for i := newActiveVUs; i < oldActiveVUs; i++ {422 rs.vuHandles[i].hardStop()423 }424 for i := newActiveVUs; i < oldActiveVUs; i++ {425 rs.vuHandles[i].wg.Wait()426 }427 }428 if oldMaxVUs > newMaxVUs {429 for i := newMaxVUs; i < oldMaxVUs; i++ {430 rs.vuHandles[i].cancelVU()431 if i < rs.startMaxVUs {432 // return the initial planned VUs to the common buffer433 executionState.ReturnVU(rs.vuHandles[i].initVU, false)434 } else {435 executionState.ModInitializedVUsCount(-1)436 }437 rs.vuHandles[i] = nil438 }439 rs.vuHandles = rs.vuHandles[:newMaxVUs]440 }441 atomic.StoreInt64(rs.maxVUs, newMaxVUs)442 return nil443}444// Run constantly loops through as many iterations as possible on a variable445// dynamically controlled number of VUs either for the specified duration, or446// until the test is manually stopped.447// nolint:funlen,gocognit,cyclop448func (mex *ExternallyControlled) Run(parentCtx context.Context, out chan<- metrics.SampleContainer) (err error) {449 mex.configLock.RLock()450 // Safely get the current config - it's important that the close of the451 // hasStarted channel is inside of the lock, so that there are no data races452 // between it and the UpdateConfig() method.453 currentControlConfig := mex.currentControlConfig454 close(mex.hasStarted)455 mex.configLock.RUnlock()456 ctx, cancel := context.WithCancel(parentCtx)457 waitOnProgressChannel := make(chan struct{})458 defer func() {459 cancel()460 <-waitOnProgressChannel461 }()462 duration := currentControlConfig.Duration.TimeDuration()463 if duration > 0 { // Only keep track of duration if it's not infinite464 go mex.stopWhenDurationIsReached(ctx, duration, cancel)465 }466 mex.logger.WithFields(467 logrus.Fields{"type": externallyControlledType, "duration": duration},468 ).Debug("Starting executor run...")469 startMaxVUs := mex.executionState.ExecutionTuple.ScaleInt64(mex.config.MaxVUs.Int64)470 ss := &lib.ScenarioState{471 Name: mex.config.Name,472 Executor: mex.config.Type,473 StartTime: time.Now(),474 }475 ctx = lib.WithScenarioState(ctx, ss)476 runState := &externallyControlledRunState{477 ctx: ctx,478 executor: mex,479 startMaxVUs: startMaxVUs,480 duration: duration,481 vuHandles: make([]*manualVUHandle, startMaxVUs),482 currentlyPaused: false,483 activeVUsCount: new(int64),484 maxVUs: new(int64),485 runIteration: getIterationRunner(mex.executionState, mex.logger),486 }487 ss.ProgressFn = runState.progressFn488 *runState.maxVUs = startMaxVUs489 if err = runState.retrieveStartMaxVUs(); err != nil {490 return err491 }492 mex.progress.Modify(pb.WithProgress(runState.progressFn)) // Keep track of the progress493 go func() {494 trackProgress(parentCtx, ctx, ctx, mex, runState.progressFn)495 close(waitOnProgressChannel)496 }()497 err = runState.handleConfigChange( // Start by setting MaxVUs to the starting MaxVUs498 ExternallyControlledConfigParams{MaxVUs: mex.config.MaxVUs}, currentControlConfig,499 )500 if err != nil {501 return err502 }503 defer func() { // Make sure we release the VUs at the end504 err = runState.handleConfigChange(currentControlConfig, ExternallyControlledConfigParams{})505 }()506 for {507 select {508 case <-ctx.Done():509 return nil510 case updateConfigEvent := <-mex.newControlConfigs:511 err := runState.handleConfigChange(currentControlConfig, updateConfigEvent.newConfig)512 if err != nil {513 updateConfigEvent.err <- err514 if ctx.Err() == err {515 return nil // we've already returned an error to the API client, but k6 should stop normally516 }517 return err518 }519 currentControlConfig = updateConfigEvent.newConfig520 mex.configLock.Lock()521 mex.currentControlConfig = updateConfigEvent.newConfig522 mex.configLock.Unlock()523 updateConfigEvent.err <- nil524 case pauseEvent := <-mex.pauseEvents:525 if pauseEvent.isPaused == runState.currentlyPaused {526 pauseEvent.err <- nil527 continue528 }529 activeVUs := currentControlConfig.VUs.Int64530 if pauseEvent.isPaused {531 for i := int64(0); i < activeVUs; i++ {532 runState.vuHandles[i].gracefulStop()533 }534 for i := int64(0); i < activeVUs; i++ {535 runState.vuHandles[i].wg.Wait()536 }537 } else {538 for i := int64(0); i < activeVUs; i++ {539 if err := runState.vuHandles[i].start(); err != nil {540 // TODO again ... just log it?541 pauseEvent.err <- err542 return err543 }544 }545 }546 runState.currentlyPaused = pauseEvent.isPaused547 pauseEvent.err <- nil548 }549 }550}...

Full Screen

Full Screen

cgogperf.go

Source:cgogperf.go Github

copy

Full Screen

1// +build gperf2package cgogperf3/*4#cgo CXXFLAGS: -I ../include5#cgo CFLAGS: -I ../include6#cgo LDFLAGS: -L ../lib -ltcmalloc -lprofiler -lstdc++7#include <stdlib.h>8#include <gperftools/profiler.h>9#include <gperftools/heap-profiler.h>10#include "heap_checker.h"11*/12import "C"13import (14 "log"15 "unsafe"16 gogperf "github.com/amazingchow/go-gperftools"17)18func init() {19 gogperf.CGOHeapProfiler = &cgoHeapProfiler{}20 gogperf.CGOHeapLeakChecker = &cgoHeapLeakChecker{}21}22//********** HeapProfiler **********//23type cgoHeapProfiler struct {24 hasStarted bool25}26func (c *cgoHeapProfiler) Start(name string) {27 if c.Started() {28 log.Fatal("CGOHeapProfiler has started already!!!")29 }30 startHeapProfiler(name)31 c.hasStarted = true32}33func (c *cgoHeapProfiler) Started() bool {34 return c.hasStarted35}36func (c *cgoHeapProfiler) Stop(name string) {37 if !c.Started() {38 log.Fatal("CGOHeapProfiler has not started yet!!!")39 }40 dumpHeapProfiler(name)41 stopHeapProfiler()42 c.hasStarted = false43}44func startHeapProfiler(name string) {45 cName := C.CString(name)46 defer C.free(unsafe.Pointer(cName))47 C.HeapProfilerStart(cName)48}49func dumpHeapProfiler(name string) {50 cName := C.CString(name)51 defer C.free(unsafe.Pointer(cName))52 C.HeapProfilerDump(cName)53}54func stopHeapProfiler() {55 C.HeapProfilerStop()56}57//********** HeapLeakChecker **********//58type cgoHeapLeakChecker struct {59 handler C.HeapLeakCheckerCGO60}61func (c *cgoHeapLeakChecker) Start(name string) {62 if c.Started() {63 log.Fatal("cgoHeapLeakChecker has started already!!!")64 }65 cName := C.CString(name)66 defer C.free(unsafe.Pointer(cName))67 c.handler = C.start(cName)68}69func (c *cgoHeapLeakChecker) Started() bool {70 return c.handler != nil71}72func (c *cgoHeapLeakChecker) Stop(_ string) {73 if !c.Started() {74 log.Fatal("cgoHeapLeakChecker has not started yet!!!")75 }76 C.stop(c.handler)77 c.handler = nil78}...

Full Screen

Full Screen

HasStarted

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 fmt.Println(lib.HasStarted())4}5import (6func HasStarted() bool {7 return time.Now().Unix() > 08}9import (

Full Screen

Full Screen

HasStarted

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 fmt.Println(lib.HasStarted())4}5import (6func HasStarted() bool {7 fmt.Println("Hello world")8 return time.Now().Unix() > 09}

Full Screen

Full Screen

HasStarted

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 fmt.Println(lib.HasStarted())4}5import (6func HasStarted() bool {7 return time.Now().Unix() > 08}9import "github.com/user/lib/v1.2.3"

Full Screen

Full Screen

HasStarted

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 fmt.Println("HasStarted:", lib.HasStarted())4}5import (6var startTime = time.Now()7func HasStarted() bool {8 return time.Now().After(startTime)9}10This error is because the lib package is not imported in the main package. The lib package will be imported in the main package as:11import (12This error is because the lib package is not imported in the main package. The lib package will be imported in the main package as:13import (14This error is because the lib package is not imported in the main package. The lib package will be imported in the main package as:15import (16This error is because the lib package is not imported in the main package. The lib package will be imported in the main package as:17import (18This error is because the lib package is not imported in the main package. The lib package will be imported in the main package as:19import (20This error is because the lib package is not imported in the main package. The lib package will be imported in the main package as:21import (

Full Screen

Full Screen

HasStarted

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 fmt.Println(lib.HasStarted())4}5func HasStarted() bool {6}7import (8func TestHasStarted(t *testing.T) {9 if !HasStarted() {10 t.Error("HasStarted() returned false, want true")11 }12}13import (14func BenchmarkHasStarted(b *testing.B) {15 for n := 0; n < b.N; n++ {16 HasStarted()17 }18}19import (20func main() {21 fmt.Println(lib.HasStarted())22}23func HasStarted() bool {24}25import (26func TestHasStarted(t *testing.T) {27 if !HasStarted() {28 t.Error("HasStarted() returned false, want true")29 }30}31import (32func BenchmarkHasStarted(b *testing.B) {33 for n := 0; n < b.N; n++ {34 HasStarted()35 }36}37import (

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run K6 automation tests on LambdaTest cloud grid

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

Most used method in

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful