github.com/onsi/ginkgo@v1.16.6-0.20211118180735-4e1925ba4c95/core_dsl.go (about)

     1  /*
     2  Ginkgo is a testing framework for Go designed to help you write expressive tests.
     3  https://github.com/onsi/ginkgo
     4  MIT-Licensed
     5  
     6  The godoc documentation outlines Ginkgo's API.  Since Ginkgo is a Domain-Specific Language it is important to
     7  build a mental model for Ginkgo - the narrative documentation at https://onsi.github.io/ginkgo/ is designed to help you do that.
     8  You should start there - even a brief skim will be helpful.  At minimum you should skim through the https://onsi.github.io/ginkgo/#getting-started chapter.
     9  
    10  Ginkgo's is best paired with the Gomega matcher library: https://github.com/onsi/gomega
    11  
    12  You can run Ginkgo specs with go test - however we recommend using the ginkgo cli.  It enables functionality
    13  that go test does not (especially running suites in parallel).  You can learn more at https://onsi.github.io/ginkgo/#ginkgo-cli-overview
    14  or by running 'ginkgo help'.
    15  */
    16  package ginkgo
    17  
    18  import (
    19  	"fmt"
    20  	"io"
    21  	"os"
    22  	"path/filepath"
    23  	"strings"
    24  	"time"
    25  
    26  	"github.com/onsi/ginkgo/formatter"
    27  	"github.com/onsi/ginkgo/internal"
    28  	"github.com/onsi/ginkgo/internal/global"
    29  	"github.com/onsi/ginkgo/internal/interrupt_handler"
    30  	"github.com/onsi/ginkgo/internal/parallel_support"
    31  	"github.com/onsi/ginkgo/reporters"
    32  	"github.com/onsi/ginkgo/types"
    33  )
    34  
    35  const GINKGO_VERSION = types.VERSION
    36  
    37  var flagSet types.GinkgoFlagSet
    38  var deprecationTracker = types.NewDeprecationTracker()
    39  var suiteConfig = types.NewDefaultSuiteConfig()
    40  var reporterConfig = types.NewDefaultReporterConfig()
    41  var suiteDidRun = false
    42  var outputInterceptor internal.OutputInterceptor
    43  var client parallel_support.Client
    44  
    45  func init() {
    46  	var err error
    47  	flagSet, err = types.BuildTestSuiteFlagSet(&suiteConfig, &reporterConfig)
    48  	exitIfErr(err)
    49  	GinkgoWriter = internal.NewWriter(os.Stdout)
    50  }
    51  
    52  func exitIfErr(err error) {
    53  	if err != nil {
    54  		if outputInterceptor != nil {
    55  			outputInterceptor.Shutdown()
    56  		}
    57  		if client != nil {
    58  			client.Close()
    59  		}
    60  		fmt.Fprintln(formatter.ColorableStdErr, err.Error())
    61  		os.Exit(1)
    62  	}
    63  }
    64  
    65  func exitIfErrors(errors []error) {
    66  	if len(errors) > 0 {
    67  		if outputInterceptor != nil {
    68  			outputInterceptor.Shutdown()
    69  		}
    70  		if client != nil {
    71  			client.Close()
    72  		}
    73  		for _, err := range errors {
    74  			fmt.Fprintln(formatter.ColorableStdErr, err.Error())
    75  		}
    76  		os.Exit(1)
    77  	}
    78  }
    79  
    80  //The interface implemented by GinkgoWriter
    81  type GinkgoWriterInterface interface {
    82  	io.Writer
    83  
    84  	Print(a ...interface{})
    85  	Printf(format string, a ...interface{})
    86  	Println(a ...interface{})
    87  
    88  	TeeTo(writer io.Writer)
    89  	ClearTeeWriters()
    90  }
    91  
    92  /*
    93  GinkgoWriter implements a GinkgoWriterInterface and io.Writer
    94  
    95  When running in verbose mode (ginkgo -v) any writes to GinkgoWriter will be immediately printed
    96  to stdout.  Otherwise, GinkgoWriter will buffer any writes produced during the current test and flush them to screen
    97  only if the current test fails.
    98  
    99  GinkgoWriter also provides convenience Print, Printf and Println methods and allows you to tee to a custom writer via GinkgoWriter.TeeTo(writer).
   100  Writes to GinkgoWriter are immediately sent to any registered TeeTo() writers.  You can unregister all TeeTo() Writers with GinkgoWriter.ClearTeeWriters()
   101  
   102  You can learn more at https://onsi.github.io/ginkgo/#logging-output
   103  */
   104  var GinkgoWriter GinkgoWriterInterface
   105  
   106  //The interface by which Ginkgo receives *testing.T
   107  type GinkgoTestingT interface {
   108  	Fail()
   109  }
   110  
   111  /*
   112  GinkgoConfiguration returns the configuration of the current suite.
   113  
   114  The first return value is the SuiteConfig which controls aspects of how the suite runs,
   115  the second return value is the ReporterConfig which controls aspects of how Ginkgo's default
   116  reporter emits output.
   117  
   118  Mutating the returned configurations has no effect.  To reconfigure Ginkgo programatically you need
   119  to pass in your mutated copies into RunSpecs().
   120  
   121  You can learn more at https://onsi.github.io/ginkgo/#overriding-ginkgos-command-line-configuration-in-the-suite
   122  */
   123  func GinkgoConfiguration() (types.SuiteConfig, types.ReporterConfig) {
   124  	return suiteConfig, reporterConfig
   125  }
   126  
   127  /*
   128  GinkgoRandomSeed returns the seed used to randomize spec execution order.  It is
   129  useful for seeding your own pseudorandom number generators to ensure
   130  consistent executions from run to run, where your tests contain variability (for
   131  example, when selecting random spec data).
   132  
   133  You can learn more at https://onsi.github.io/ginkgo/#spec-randomization
   134  */
   135  func GinkgoRandomSeed() int64 {
   136  	return suiteConfig.RandomSeed
   137  }
   138  
   139  /*
   140  GinkgoParallelProcess returns the parallel process number for the current ginkgo process
   141  The process number is 1-indexed.  You can use GinkgoParallelProcess() to shard access to shared
   142  resources across your suites.  You can learn more about patterns for sharding at https://onsi.github.io/ginkgo/#patterns-for-parallel-integration-specs
   143  
   144  For more on how specs are parallelized in Ginkgo, see http://onsi.github.io/ginkgo/#spec-parallelization
   145  */
   146  func GinkgoParallelProcess() int {
   147  	return suiteConfig.ParallelProcess
   148  }
   149  
   150  /*
   151  PauseOutputInterception() pauses Ginkgo's output interception.  This is only relevant
   152  when running in parallel and output to stdout/stderr is being intercepted.  You generally
   153  don't need to call this function - however there are cases when Ginkgo's output interception
   154  mechanisms can interfere with external processes launched by the test process.
   155  
   156  In particular, if an external process is launched that has cmd.Stdout/cmd.Stderr set to os.Stdout/os.Stderr
   157  then Ginkgo's output interceptor will hang.  To circumvent this, set cmd.Stdout/cmd.Stderr to GinkgoWriter.
   158  If, for some reason, you aren't able to do that, you can PauseOutputInterception() before starting the process
   159  then ResumeOutputInterception() after starting it.
   160  
   161  Note that PauseOutputInterception() does not cause stdout writes to print to the console -
   162  this simply stops intercepting and storing stdout writes to an internal buffer.
   163  */
   164  func PauseOutputInterception() {
   165  	if outputInterceptor == nil {
   166  		return
   167  	}
   168  	outputInterceptor.PauseIntercepting()
   169  }
   170  
   171  //ResumeOutputInterception() - see docs for PauseOutputInterception()
   172  func ResumeOutputInterception() {
   173  	if outputInterceptor == nil {
   174  		return
   175  	}
   176  	outputInterceptor.ResumeIntercepting()
   177  }
   178  
   179  /*
   180  RunSpecs is the entry point for the Ginkgo spec runner.
   181  
   182  You must call this within a Golang testing TestX(t *testing.T) function.
   183  If you bootstrapped your suite with "ginkgo bootstrap" this is already
   184  done for you.
   185  
   186  Ginkgo is typically configured via command-line flags.  This configuration
   187  can be overriden, however, and passed into RunSpecs as optional arguments:
   188  
   189  	func TestMySuite(t *testing.T)  {
   190  		RegisterFailHandler(gomega.Fail)
   191  		// fetch the current config
   192  		suiteConfig, reporterConfig := GinkgoConfiguration()
   193  		// adjust it
   194  		suiteConfig.SkipStrings = []string{"NEVER-RUN"}
   195  		reporterConfig.FullTrace = true
   196  		// pass it in to RunSpecs
   197  		RunSpecs(t, "My Suite", suiteConfig, reporterConfig)
   198  	}
   199  
   200  Note that some configuration changes can lead to undefined behavior.  For example,
   201  you should not change ParallelProcess or ParallelTotal as the Ginkgo CLI is responsible
   202  for setting these and orchestrating parallel specs across the parallel processes.  See http://onsi.github.io/ginkgo/#spec-parallelization
   203  for more on how specs are parallelized in Ginkgo.
   204  
   205  You can also pass suite-level Label() decorators to RunSpecs.  The passed-in labels will apply to all specs in the suite.
   206  */
   207  func RunSpecs(t GinkgoTestingT, description string, args ...interface{}) bool {
   208  	if suiteDidRun {
   209  		exitIfErr(types.GinkgoErrors.RerunningSuite())
   210  	}
   211  	suiteDidRun = true
   212  
   213  	suiteLabels := Labels{}
   214  	configErrors := []error{}
   215  	for _, arg := range args {
   216  		switch arg := arg.(type) {
   217  		case types.SuiteConfig:
   218  			suiteConfig = arg
   219  		case types.ReporterConfig:
   220  			reporterConfig = arg
   221  		case Labels:
   222  			suiteLabels = append(suiteLabels, arg...)
   223  		default:
   224  			configErrors = append(configErrors, types.GinkgoErrors.UnkownTypePassedToRunSpecs(arg))
   225  		}
   226  	}
   227  	exitIfErrors(configErrors)
   228  
   229  	configErrors = types.VetConfig(flagSet, suiteConfig, reporterConfig)
   230  	if len(configErrors) > 0 {
   231  		fmt.Fprintf(formatter.ColorableStdErr, formatter.F("{{red}}Ginkgo detected configuration issues:{{/}}\n"))
   232  		for _, err := range configErrors {
   233  			fmt.Fprintf(formatter.ColorableStdErr, err.Error())
   234  		}
   235  		os.Exit(1)
   236  	}
   237  
   238  	var reporter reporters.Reporter
   239  	if suiteConfig.ParallelTotal == 1 {
   240  		reporter = reporters.NewDefaultReporter(reporterConfig, formatter.ColorableStdOut)
   241  		outputInterceptor = internal.NoopOutputInterceptor{}
   242  		client = nil
   243  	} else {
   244  		reporter = reporters.NoopReporter{}
   245  		switch strings.ToLower(suiteConfig.OutputInterceptorMode) {
   246  		case "swap":
   247  			outputInterceptor = internal.NewOSGlobalReassigningOutputInterceptor()
   248  		case "none":
   249  			outputInterceptor = internal.NoopOutputInterceptor{}
   250  		default:
   251  			outputInterceptor = internal.NewOutputInterceptor()
   252  		}
   253  		client = parallel_support.NewClient(suiteConfig.ParallelHost)
   254  		if !client.Connect() {
   255  			client = nil
   256  			exitIfErr(types.GinkgoErrors.UnreachableParallelHost(suiteConfig.ParallelHost))
   257  		}
   258  		defer client.Close()
   259  	}
   260  
   261  	writer := GinkgoWriter.(*internal.Writer)
   262  	if reporterConfig.Verbose && suiteConfig.ParallelTotal == 1 {
   263  		writer.SetMode(internal.WriterModeStreamAndBuffer)
   264  	} else {
   265  		writer.SetMode(internal.WriterModeBufferOnly)
   266  	}
   267  
   268  	if reporterConfig.WillGenerateReport() {
   269  		registerReportAfterSuiteNodeForAutogeneratedReports(reporterConfig)
   270  	}
   271  
   272  	err := global.Suite.BuildTree()
   273  	exitIfErr(err)
   274  
   275  	suitePath, err := os.Getwd()
   276  	exitIfErr(err)
   277  	suitePath, err = filepath.Abs(suitePath)
   278  	exitIfErr(err)
   279  
   280  	passed, hasFocusedTests := global.Suite.Run(description, suiteLabels, suitePath, global.Failer, reporter, writer, outputInterceptor, interrupt_handler.NewInterruptHandler(suiteConfig.Timeout, client), client, suiteConfig)
   281  	outputInterceptor.Shutdown()
   282  
   283  	flagSet.ValidateDeprecations(deprecationTracker)
   284  	if deprecationTracker.DidTrackDeprecations() {
   285  		fmt.Fprintln(formatter.ColorableStdErr, deprecationTracker.DeprecationsReport())
   286  	}
   287  
   288  	if !passed {
   289  		t.Fail()
   290  	}
   291  
   292  	if passed && hasFocusedTests && strings.TrimSpace(os.Getenv("GINKGO_EDITOR_INTEGRATION")) == "" {
   293  		fmt.Println("PASS | FOCUSED")
   294  		os.Exit(types.GINKGO_FOCUS_EXIT_CODE)
   295  	}
   296  	return passed
   297  }
   298  
   299  /*
   300  Skip instructs Ginkgo to skip the current spec
   301  
   302  You can call Skip in any Setup or Subject node closure.
   303  
   304  For more on how to filter specs in Ginkgo see https://onsi.github.io/ginkgo/#filtering-specs
   305  */
   306  func Skip(message string, callerSkip ...int) {
   307  	skip := 0
   308  	if len(callerSkip) > 0 {
   309  		skip = callerSkip[0]
   310  	}
   311  	cl := types.NewCodeLocationWithStackTrace(skip + 1)
   312  	global.Failer.Skip(message, cl)
   313  	panic(types.GinkgoErrors.UncaughtGinkgoPanic(cl))
   314  }
   315  
   316  /*
   317  Fail notifies Ginkgo that the current spec has failed. (Gomega will call Fail for you automatically when an assertion fails.)
   318  
   319  Under the hood, Fail panics to end execution of the current spec.  Ginkgo will catch this panic and proceed with
   320  the subsequent spec.  If you call Fail, or make an assertion, within a goroutine launched by your spec you must
   321  add defer GinkgoRecover() to the goroutine to catch the panic emitted by Fail.
   322  
   323  You can call Fail in any Setup or Subject node closure.
   324  
   325  You can learn more about how Ginkgo manages failures here: https://onsi.github.io/ginkgo/#mental-model-how-ginkgo-handles-failure
   326  */
   327  func Fail(message string, callerSkip ...int) {
   328  	skip := 0
   329  	if len(callerSkip) > 0 {
   330  		skip = callerSkip[0]
   331  	}
   332  
   333  	cl := types.NewCodeLocationWithStackTrace(skip + 1)
   334  	global.Failer.Fail(message, cl)
   335  	panic(types.GinkgoErrors.UncaughtGinkgoPanic(cl))
   336  }
   337  
   338  /*
   339  AbortSuite instructs Ginkgo to fail the current spec and skip all subsequent specs, thereby aborting the suite.
   340  
   341  You can call AbortSuite in any Setup or Subject node closure.
   342  
   343  You can learn more about how Ginkgo handles suite interruptions here: https://onsi.github.io/ginkgo/#interrupting-aborting-and-timing-out-suites
   344  */
   345  func AbortSuite(message string, callerSkip ...int) {
   346  	skip := 0
   347  	if len(callerSkip) > 0 {
   348  		skip = callerSkip[0]
   349  	}
   350  
   351  	cl := types.NewCodeLocationWithStackTrace(skip + 1)
   352  	global.Failer.AbortSuite(message, cl)
   353  	panic(types.GinkgoErrors.UncaughtGinkgoPanic(cl))
   354  }
   355  
   356  /*
   357  GinkgoRecover should be deferred at the top of any spawned goroutine that (may) call `Fail`
   358  Since Gomega assertions call fail, you should throw a `defer GinkgoRecover()` at the top of any goroutine that
   359  calls out to Gomega
   360  
   361  Here's why: Ginkgo's `Fail` method records the failure and then panics to prevent
   362  further assertions from running.  This panic must be recovered.  Normally, Ginkgo recovers the panic for you,
   363  however if a panic originates on a goroutine *launched* from one of your specs there's no
   364  way for Ginkgo to rescue the panic.  To do this, you must remember to `defer GinkgoRecover()` at the top of such a goroutine.
   365  
   366  You can learn more about how Ginkgo manages failures here: https://onsi.github.io/ginkgo/#mental-model-how-ginkgo-handles-failure
   367  */
   368  func GinkgoRecover() {
   369  	e := recover()
   370  	if e != nil {
   371  		global.Failer.Panic(types.NewCodeLocationWithStackTrace(1), e)
   372  	}
   373  }
   374  
   375  // pushNode is used by the various test construction DSL methods to push nodes onto the suite
   376  // it handles returned errors, emits a detailed error message to help the user learn what they may have done wrong, then exits
   377  func pushNode(node internal.Node, errors []error) bool {
   378  	exitIfErrors(errors)
   379  	exitIfErr(global.Suite.PushNode(node))
   380  	return true
   381  }
   382  
   383  /*
   384  Describe nodes are Container nodes that allow you to organize your specs.  A Describe node's closure can contain any number of
   385  Setup nodes (e.g. BeforeEach, AfterEach, JustBeforeEach), and Subject nodes (i.e. It).
   386  
   387  Context and When nodes are aliases for Describe - use whichever gives your suite a better narrative flow.  It is idomatic
   388  to Describe the behavior of an object or function and, within that Describe, outline a number of Contexts and Whens.
   389  
   390  You can learn more at https://onsi.github.io/ginkgo/#organizing-specs-with-container-nodes
   391  In addition, container nodes can be decorated with a variety of decorators.  You can learn more here: https://onsi.github.io/ginkgo/#decorator-reference
   392  */
   393  func Describe(text string, args ...interface{}) bool {
   394  	return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeContainer, text, args...))
   395  }
   396  
   397  /*
   398  FDescribe focuses specs within the Describe block.
   399  */
   400  func FDescribe(text string, args ...interface{}) bool {
   401  	args = append(args, internal.Focus)
   402  	return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeContainer, text, args...))
   403  }
   404  
   405  /*
   406  PDescribe marks specs within the Describe block as pending.
   407  */
   408  func PDescribe(text string, args ...interface{}) bool {
   409  	args = append(args, internal.Pending)
   410  	return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeContainer, text, args...))
   411  }
   412  
   413  /*
   414  XDescribe marks specs within the Describe block as pending.
   415  
   416  XDescribe is an alias for PDescribe
   417  */
   418  var XDescribe = PDescribe
   419  
   420  /* Context is an alias for Describe - it generates the exact same kind of Container node */
   421  var Context, FContext, PContext, XContext = Describe, FDescribe, PDescribe, XDescribe
   422  
   423  /* When is an alias for Describe - it generates the exact same kind of Container node */
   424  var When, FWhen, PWhen, XWhen = Describe, FDescribe, PDescribe, XDescribe
   425  
   426  /*
   427  It nodes are Subject nodes that contain your spec code and assertions.
   428  
   429  Each It node corresponds to an individual Ginkgo spec.  You cannot nest any other Ginkgo nodes within an It node's closure.
   430  
   431  You can learn more at https://onsi.github.io/ginkgo/#spec-subjects-it
   432  In addition, subject nodes can be decorated with a variety of decorators.  You can learn more here: https://onsi.github.io/ginkgo/#decorator-reference
   433  */
   434  func It(text string, args ...interface{}) bool {
   435  	return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeIt, text, args...))
   436  }
   437  
   438  /*
   439  FIt allows you to focus an individual It.
   440  */
   441  func FIt(text string, args ...interface{}) bool {
   442  	args = append(args, internal.Focus)
   443  	return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeIt, text, args...))
   444  }
   445  
   446  /*
   447  PIt allows you to mark an individual It as pending.
   448  */
   449  func PIt(text string, args ...interface{}) bool {
   450  	args = append(args, internal.Pending)
   451  	return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeIt, text, args...))
   452  }
   453  
   454  /*
   455  XIt allows you to mark an individual It as pending.
   456  
   457  XIt is an alias for PIt
   458  */
   459  var XIt = PIt
   460  
   461  /*
   462  Specify is an alias for It - it can allow for more natural wording in some context.
   463  */
   464  var Specify, FSpecify, PSpecify, XSpecify = It, FIt, PIt, XIt
   465  
   466  /*
   467  By allows you to better document complex Specs.
   468  
   469  Generally you should try to keep your Its short and to the point.  This is not always possible, however,
   470  especially in the context of integration tests that capture complex or lengthy workflows.
   471  
   472  By allows you to document such flows.  By may be called within a Setup or Subject node (It, BeforeEach, etc...)
   473  and will simply log the passed in text to the GinkgoWriter.  If By is handed a function it will immediately run the function.
   474  
   475  By will also generate and attach a ReportEntry to the spec.  This will ensure that By annotations appear in Ginkgo's machine-readable reports.
   476  
   477  Note that By does not generate a new Ginkgo node - rather it is simply synctactic sugar around GinkgoWriter and AddReportEntry
   478  You can learn more about By here: https://onsi.github.io/ginkgo/#documenting-complex-specs-by
   479  */
   480  func By(text string, callback ...func()) {
   481  	value := struct {
   482  		Text     string
   483  		Duration time.Duration
   484  	}{
   485  		Text: text,
   486  	}
   487  	t := time.Now()
   488  	AddReportEntry("By Step", ReportEntryVisibilityNever, Offset(1), &value, t)
   489  	formatter := formatter.NewWithNoColorBool(reporterConfig.NoColor)
   490  	GinkgoWriter.Println(formatter.F("{{bold}}STEP:{{/}} %s {{gray}}%s{{/}}", text, t.Format(types.GINKGO_TIME_FORMAT)))
   491  	if len(callback) == 1 {
   492  		callback[0]()
   493  		value.Duration = time.Since(t)
   494  	}
   495  	if len(callback) > 1 {
   496  		panic("just one callback per By, please")
   497  	}
   498  }
   499  
   500  /*
   501  BeforeSuite nodes are suite-level Setup nodes that run just once before any specs are run.
   502  When running in parallel, each parallel process will call BeforeSuite.
   503  
   504  You may only register *one* BeforeSuite handler per test suite.  You typically do so in your bootstrap file at the top level.
   505  
   506  You cannot nest any other Ginkgo nodes within a BeforeSuite node's closure.
   507  You can learn more here: https://onsi.github.io/ginkgo/#suite-setup-and-cleanup-beforesuite-and-aftersuite
   508  */
   509  func BeforeSuite(body func()) bool {
   510  	return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeBeforeSuite, "", body))
   511  }
   512  
   513  /*
   514  AfterSuite nodes are suite-level Setup nodes run after all specs have finished - regardless of whether specs have passed or failed.
   515  AfterSuite node closures always run, even if Ginkgo receives an interrupt signal (^C), in order to ensure cleanup occurs.
   516  
   517  When running in parallel, each parallel process will call AfterSuite.
   518  
   519  You may only register *one* AfterSuite handler per test suite.  You typically do so in your bootstrap file at the top level.
   520  
   521  You cannot nest any other Ginkgo nodes within an AfterSuite node's closure.
   522  You can learn more here: https://onsi.github.io/ginkgo/#suite-setup-and-cleanup-beforesuite-and-aftersuite
   523  */
   524  func AfterSuite(body func()) bool {
   525  	return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeAfterSuite, "", body))
   526  }
   527  
   528  /*
   529  SynchronizedBeforeSuite nodes allow you to perform some of the suite setup just once - on parallel process #1 - and then pass information
   530  from that setup to the rest of the suite setup on all processes.  This is useful for performing expensive or singleton setup once, then passing
   531  information from that setup to all parallel processes.
   532  
   533  SynchronizedBeforeSuite accomplishes this by taking *two* function arguments and passing data between them.
   534  The first function is only run on parallel process #1.  The second is run on all processes, but *only* after the first function completes successfully.  The functions have the following signatures:
   535  
   536  The first function (which only runs on process #1) has the signature:
   537  
   538  	func() []byte
   539  
   540  The byte array returned by the first function is then passed to the second function, which has the signature:
   541  
   542  	func(data []byte)
   543  
   544  You cannot nest any other Ginkgo nodes within an SynchronizedBeforeSuite node's closure.
   545  You can learn more, and see some examples, here: https://onsi.github.io/ginkgo/#parallel-suite-setup-and-cleanup-synchronizedbeforesuite-and-synchronizedaftersuite
   546  */
   547  func SynchronizedBeforeSuite(process1Body func() []byte, allProcessBody func([]byte)) bool {
   548  	return pushNode(internal.NewSynchronizedBeforeSuiteNode(process1Body, allProcessBody, types.NewCodeLocation(1)))
   549  }
   550  
   551  /*
   552  SynchronizedAfterSuite nodes complement the SynchronizedBeforeSuite nodes in solving the problem of splitting clean up into a piece that runs on all processes
   553  and a piece that must only run once - on process #1.
   554  
   555  SynchronizedAfterSuite accomplishes this by taking *two* function arguments.  The first runs on all processes.  The second runs only on parallel process #1
   556  and *only* after all other processes have finished and exited.  This ensures that process #1, and any resources it is managing, remain alive until
   557  all other processes are finished.
   558  
   559  Note that you can also use DeferCleanup() in SynchronizedBeforeSuite to accomplish similar results.
   560  
   561  You cannot nest any other Ginkgo nodes within an SynchronizedAfterSuite node's closure.
   562  You can learn more, and see some examples, here: https://onsi.github.io/ginkgo/#parallel-suite-setup-and-cleanup-synchronizedbeforesuite-and-synchronizedaftersuite
   563  */
   564  func SynchronizedAfterSuite(allProcessBody func(), process1Body func()) bool {
   565  	return pushNode(internal.NewSynchronizedAfterSuiteNode(allProcessBody, process1Body, types.NewCodeLocation(1)))
   566  }
   567  
   568  /*
   569  BeforeEach nodes are Setup nodes whose closures run before It node closures.  When multiple BeforeEach nodes
   570  are defined in nested Container nodes the outermost BeforeEach node closures are run first.
   571  
   572  You cannot nest any other Ginkgo nodes within a BeforeEach node's closure.
   573  You can learn more here: https://onsi.github.io/ginkgo/#extracting-common-setup-beforeeach
   574  */
   575  func BeforeEach(args ...interface{}) bool {
   576  	return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeBeforeEach, "", args...))
   577  }
   578  
   579  /*
   580  JustBeforeEach nodes are similar to BeforeEach nodes, however they are guaranteed to run *after* all BeforeEach node closures - just before the It node closure.
   581  This can allow you to separate configuration from creation of resources for a spec.
   582  
   583  You cannot nest any other Ginkgo nodes within a JustBeforeEach node's closure.
   584  You can learn more and see some examples here: https://onsi.github.io/ginkgo/#separating-creation-and-configuration-justbeforeeach
   585  */
   586  func JustBeforeEach(args ...interface{}) bool {
   587  	return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeJustBeforeEach, "", args...))
   588  }
   589  
   590  /*
   591  AfterEach nodes are Setup nodes whose closures run after It node closures.  When multiple AfterEach nodes
   592  are defined in nested Container nodes the innermost AfterEach node closures are run first.
   593  
   594  Note that you can also use DeferCleanup() in other Setup or Subject nodes to accomplish similar results.
   595  
   596  You cannot nest any other Ginkgo nodes within an AfterEach node's closure.
   597  You can learn more here: https://onsi.github.io/ginkgo/#spec-cleanup-aftereach-and-defercleanup
   598  */
   599  func AfterEach(args ...interface{}) bool {
   600  	return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeAfterEach, "", args...))
   601  }
   602  
   603  /*
   604  JustAfterEach nodes are similar to AfterEach nodes, however they are guaranteed to run *before* all AfterEach node closures - just after the It node closure. This can allow you to separate diagnostics collection from teardown for a spec.
   605  
   606  You cannot nest any other Ginkgo nodes within a JustAfterEach node's closure.
   607  You can learn more and see some examples here: https://onsi.github.io/ginkgo/#separating-diagnostics-collection-and-teardown-justaftereach
   608  */
   609  func JustAfterEach(args ...interface{}) bool {
   610  	return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeJustAfterEach, "", args...))
   611  }
   612  
   613  /*
   614  BeforeAll nodes are Setup nodes that can occur inside Ordered contaienrs.  They run just once before any specs in the Ordered container run.
   615  
   616  Multiple BeforeAll nodes can be defined in a given Ordered container however they cannot be nested inside any other container.
   617  
   618  You cannot nest any other Ginkgo nodes within a BeforeAll node's closure.
   619  You can learn more about Ordered Containers at: https://onsi.github.io/ginkgo/#ordered-containers
   620  And you can learn more about BeforeAll at: https://onsi.github.io/ginkgo/#setup-in-ordered-containers-beforeall-and-afterall
   621  */
   622  func BeforeAll(args ...interface{}) bool {
   623  	return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeBeforeAll, "", args...))
   624  }
   625  
   626  /*
   627  AfterAll nodes are Setup nodes that can occur inside Ordered contaienrs.  They run just once after all specs in the Ordered container have run.
   628  
   629  Multiple AfterAll nodes can be defined in a given Ordered container however they cannot be nested inside any other container.
   630  
   631  Note that you can also use DeferCleanup() in a BeforeAll node to accomplish similar behavior.
   632  
   633  You cannot nest any other Ginkgo nodes within an AfterAll node's closure.
   634  You can learn more about Ordered Containers at: https://onsi.github.io/ginkgo/#ordered-containers
   635  And you can learn more about AfterAll at: https://onsi.github.io/ginkgo/#setup-in-ordered-containers-beforeall-and-afterall
   636  */
   637  func AfterAll(args ...interface{}) bool {
   638  	return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeAfterAll, "", args...))
   639  }
   640  
   641  /*
   642  DeferCleanup can be called within any Setup or Subject node to register a cleanup callback that Ginkgo will call at the appropriate time to cleanup after the spec.
   643  
   644  DeferCleanup can be passed:
   645  1. A function that takes no arguments and returns no values.
   646  2. A function that returns an error (in which case it will assert that the returned error was nil, or it will fail the spec).
   647  3. A function that takes arguments (and optionally returns an error) followed by a list of arguments to passe to the function. For example:
   648  
   649      BeforeEach(func() {
   650          DeferCleanup(os.SetEnv, "FOO", os.GetEnv("FOO"))
   651          os.SetEnv("FOO", "BAR")
   652      })
   653  
   654  will register a cleanup handler that will set the environment variable "FOO" to it's current value (obtained by os.GetEnv("FOO")) after the spec runs and then sets the environment variable "FOO" to "BAR" for the current spec.
   655  
   656  When DeferCleanup is called in BeforeEach, JustBeforeEach, It, AfterEach, or JustAfterEach the registered callback will be invoked when the spec completes (i.e. it will behave like an AfterEach node)
   657  When DeferCleanup is called in BeforeAll or AfterAll the registered callback will be invoked when the ordered container completes (i.e. it will behave like an AfterAll node)
   658  When DeferCleanup is called in BeforeSuite, SynchronizedBeforeSuite, AfterSuite, or SynchronizedAfterSuite the registered callback will be invoked when the suite completes (i.e. it will behave like an AfterSuite node)
   659  
   660  Note that DeferCleanup does not represent a node but rather dynamically generates the appropriate type of cleanup node based on the context in which it is called.  As such you must call DeferCleanup within a Setup or Subject node, and not within a Container node.
   661  You can learn more about DeferCleanup here: https://onsi.github.io/ginkgo/#cleaning-up-our-cleanup-code-defercleanup
   662  */
   663  func DeferCleanup(args ...interface{}) {
   664  	fail := func(message string, cl types.CodeLocation) {
   665  		global.Failer.Fail(message, cl)
   666  	}
   667  	pushNode(internal.NewCleanupNode(fail, args...))
   668  }