| // Copyright (c) The OpenTofu Authors | |
| // SPDX-License-Identifier: MPL-2.0 | |
| // Copyright (c) 2023 HashiCorp, Inc. | |
| // SPDX-License-Identifier: MPL-2.0 | |
| package planning | |
| import ( | |
| "bufio" | |
| "fmt" | |
| "math" | |
| "strings" | |
| "github.com/opentofu/opentofu/internal/addrs" | |
| "github.com/opentofu/opentofu/internal/engine/internal/execgraph" | |
| ) | |
| func newExecGraphBuilderForTesting() *execGraphBuilder { | |
| var placeholderDeposedKey uint32 | |
| return &execGraphBuilder{ | |
| lower: execgraph.NewBuilder(), | |
| makeDeposedKey: func(_ addrs.AbsResourceInstance) addrs.DeposedKey { | |
| // For testing purposes we just allocate sequential integers | |
| // so that we have predictable keys to include in the expected | |
| // output of each test. | |
| placeholderDeposedKey++ | |
| return addrs.DeposedKey(fmt.Sprintf("%08x", placeholderDeposedKey)) | |
| }, | |
| } | |
| } | |
| // stripCommonLeadingTabs is a helper for tests that include constant strings | |
| // for comparison with the result of a [Graph.DebugRepr] call, so that we can | |
| // write the constant strings indentation to fit well with the surrounding | |
| // context while ignoring the extra leading tabs that causes. | |
| // | |
| // This only considers tabs -- ignoring any other kind of whitespace -- because | |
| // this is narrowly focused only on test code indentation and we always indent | |
| // code using tabs. | |
| func stripCommonLeadingTabs(s string) string { | |
| // We work in two passes here: first we scan over and find the smallest | |
| // number of leading tabs that all of the lines of the string have in | |
| // common, and then we do a second pass to build a new string with that | |
| // many leading tabs removed from each line. | |
| sc := bufio.NewScanner(strings.NewReader(s)) | |
| sc.Split(bufio.ScanLines) | |
| minTabCount := math.MaxInt | |
| for sc.Scan() { | |
| line := sc.Text() | |
| trimmed := strings.TrimLeft(line, "\t") | |
| if len(strings.TrimSpace(trimmed)) == 0 { | |
| continue // empty lines and lines containing only whitespace are ignored | |
| } | |
| tabCount := len(line) - len(trimmed) | |
| if tabCount < minTabCount { | |
| minTabCount = tabCount | |
| } | |
| } | |
| // (No error check because strings.Reader reads cannot fail) | |
| if minTabCount == math.MaxInt { | |
| // If minTabCount is still the max then that suggests we didn't have | |
| // any non-empty lines at all, and so there's nothing useful we can do | |
| // here. | |
| return "" | |
| } | |
| trimmedPrefix := strings.Repeat("\t", minTabCount) | |
| var buf strings.Builder | |
| sc = bufio.NewScanner(strings.NewReader(s)) | |
| sc.Split(bufio.ScanLines) | |
| for sc.Scan() { | |
| // No error check because strings.Builder writes cannot fail. | |
| buf.WriteString(strings.TrimPrefix(sc.Text(), trimmedPrefix)) | |
| buf.WriteByte('\n') | |
| } | |
| // (No error check because strings.Reader reads cannot fail) | |
| return buf.String() | |
| } |