framework.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. package framework
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io/ioutil"
  6. "os"
  7. "regexp"
  8. "strings"
  9. "text/template"
  10. "github.com/fatedier/frp/test/e2e/pkg/port"
  11. "github.com/fatedier/frp/test/e2e/pkg/process"
  12. "github.com/onsi/ginkgo"
  13. "github.com/onsi/ginkgo/config"
  14. )
  15. type Options struct {
  16. TotalParallelNode int
  17. CurrentNodeIndex int
  18. FromPortIndex int
  19. ToPortIndex int
  20. }
  21. type Framework struct {
  22. TempDirectory string
  23. UsedPorts map[string]int
  24. portAllocator *port.Allocator
  25. // Multiple mock servers used for e2e testing.
  26. mockServers *MockServers
  27. // To make sure that this framework cleans up after itself, no matter what,
  28. // we install a Cleanup action before each test and clear it after. If we
  29. // should abort, the AfterSuite hook should run all Cleanup actions.
  30. cleanupHandle CleanupActionHandle
  31. // beforeEachStarted indicates that BeforeEach has started
  32. beforeEachStarted bool
  33. serverConfPaths []string
  34. serverProcesses []*process.Process
  35. clientConfPaths []string
  36. clientProcesses []*process.Process
  37. }
  38. func NewDefaultFramework() *Framework {
  39. options := Options{
  40. TotalParallelNode: config.GinkgoConfig.ParallelTotal,
  41. CurrentNodeIndex: config.GinkgoConfig.ParallelNode,
  42. FromPortIndex: 20000,
  43. ToPortIndex: 50000,
  44. }
  45. return NewFramework(options)
  46. }
  47. func NewFramework(opt Options) *Framework {
  48. f := &Framework{
  49. portAllocator: port.NewAllocator(opt.FromPortIndex, opt.ToPortIndex, opt.TotalParallelNode, opt.CurrentNodeIndex-1),
  50. }
  51. f.mockServers = NewMockServers(f.portAllocator)
  52. if err := f.mockServers.Run(); err != nil {
  53. Failf("%v", err)
  54. }
  55. ginkgo.BeforeEach(f.BeforeEach)
  56. ginkgo.AfterEach(f.AfterEach)
  57. return f
  58. }
  59. // BeforeEach create a temp directory.
  60. func (f *Framework) BeforeEach() {
  61. f.beforeEachStarted = true
  62. f.cleanupHandle = AddCleanupAction(f.AfterEach)
  63. dir, err := ioutil.TempDir(os.TempDir(), "frpe2e-test-*")
  64. ExpectNoError(err)
  65. f.TempDirectory = dir
  66. }
  67. func (f *Framework) AfterEach() {
  68. if !f.beforeEachStarted {
  69. return
  70. }
  71. RemoveCleanupAction(f.cleanupHandle)
  72. os.RemoveAll(f.TempDirectory)
  73. f.TempDirectory = ""
  74. f.UsedPorts = nil
  75. f.serverConfPaths = nil
  76. f.clientConfPaths = nil
  77. for _, p := range f.serverProcesses {
  78. p.Stop()
  79. }
  80. for _, p := range f.clientProcesses {
  81. p.Stop()
  82. }
  83. f.serverProcesses = nil
  84. f.clientProcesses = nil
  85. }
  86. var portRegex = regexp.MustCompile(`{{ \.Port.*? }}`)
  87. // RenderPortsTemplate render templates with ports.
  88. //
  89. // Local: {{ .Port1 }}
  90. // Target: {{ .Port2 }}
  91. //
  92. // return rendered content and all allocated ports.
  93. func (f *Framework) genPortsFromTemplates(templates []string) (ports map[string]int, err error) {
  94. ports = make(map[string]int)
  95. for _, t := range templates {
  96. arrs := portRegex.FindAllString(t, -1)
  97. for _, str := range arrs {
  98. str = strings.TrimPrefix(str, "{{ .")
  99. str = strings.TrimSuffix(str, " }}")
  100. str = strings.TrimSpace(str)
  101. ports[str] = 0
  102. }
  103. }
  104. defer func() {
  105. if err != nil {
  106. for _, port := range ports {
  107. f.portAllocator.Release(port)
  108. }
  109. }
  110. }()
  111. for name := range ports {
  112. port := f.portAllocator.Get()
  113. if port <= 0 {
  114. return nil, fmt.Errorf("can't allocate port")
  115. }
  116. ports[name] = port
  117. }
  118. return
  119. }
  120. func (f *Framework) RenderTemplates(templates []string) (outs []string, ports map[string]int, err error) {
  121. ports, err = f.genPortsFromTemplates(templates)
  122. if err != nil {
  123. return
  124. }
  125. params := f.mockServers.GetTemplateParams()
  126. for name, port := range ports {
  127. params[name] = port
  128. }
  129. for _, t := range templates {
  130. tmpl, err := template.New("").Parse(t)
  131. if err != nil {
  132. return nil, nil, err
  133. }
  134. buffer := bytes.NewBuffer(nil)
  135. if err = tmpl.Execute(buffer, params); err != nil {
  136. return nil, nil, err
  137. }
  138. outs = append(outs, buffer.String())
  139. }
  140. return
  141. }