func()

in e2e_tests/compute/instance.go [108:170]


func (i *Instance) WaitForSerialOutput(positiveRegexes []*regexp.Regexp, negativeRegexes []*regexp.Regexp, port int64, interval, timeout time.Duration) error {
	var start int64
	var errs int
	matches := make([]bool, len(positiveRegexes))
	tick := time.Tick(interval)
	timedout := time.After(timeout)
	for {
		select {
		case <-timedout:
			var patterns []string
			for _, regex := range positiveRegexes {
				patterns = append(patterns, regex.String())
			}
			return fmt.Errorf("timed out waiting for regexes [%s]", strings.Join(patterns, ","))
		case <-tick:
			resp, err := i.client.GetSerialPortOutput(i.Project, i.Zone, i.Name, port, start)
			if err != nil {
				status, sErr := i.client.InstanceStatus(i.Project, i.Zone, i.Name)
				if sErr != nil {
					err = fmt.Errorf("%v, error getting InstanceStatus: %v", err, sErr)
				} else {
					err = fmt.Errorf("%v, InstanceStatus: %q", err, status)
				}

				// Wait until machine restarts to evaluate SerialOutput.
				if isTerminal(status) {
					continue
				}

				// Retry up to 3 times in a row on any error if we successfully got InstanceStatus.
				if errs < 3 {
					errs++
					continue
				}

				return err
			}
			start = resp.Next
			for _, ln := range strings.Split(resp.Contents, "\n") {
				for _, regex := range negativeRegexes {
					if regex.MatchString(ln) {
						return fmt.Errorf("matched negative regexes [%s]", regex)
					}
				}
				for i, regex := range positiveRegexes {
					if regex.MatchString(ln) {
						matches[i] = true
					}
				}
				matched := 0
				for _, match := range matches {
					if match {
						matched++
					}
				}
				if matched == len(positiveRegexes) {
					return nil
				}
			}
			errs = 0
		}
	}
}