framework.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  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/mock/server"
  11. "github.com/fatedier/frp/test/e2e/pkg/port"
  12. "github.com/fatedier/frp/test/e2e/pkg/process"
  13. "github.com/onsi/ginkgo"
  14. "github.com/onsi/ginkgo/config"
  15. )
  16. type Options struct {
  17. TotalParallelNode int
  18. CurrentNodeIndex int
  19. FromPortIndex int
  20. ToPortIndex int
  21. }
  22. type Framework struct {
  23. TempDirectory string
  24. // ports used in this framework indexed by port name.
  25. usedPorts map[string]int
  26. // portAllocator to alloc port for this test case.
  27. portAllocator *port.Allocator
  28. // Multiple default mock servers used for e2e testing.
  29. mockServers *MockServers
  30. // To make sure that this framework cleans up after itself, no matter what,
  31. // we install a Cleanup action before each test and clear it after. If we
  32. // should abort, the AfterSuite hook should run all Cleanup actions.
  33. cleanupHandle CleanupActionHandle
  34. // beforeEachStarted indicates that BeforeEach has started
  35. beforeEachStarted bool
  36. serverConfPaths []string
  37. serverProcesses []*process.Process
  38. clientConfPaths []string
  39. clientProcesses []*process.Process
  40. // Manual registered mock servers.
  41. servers []*server.Server
  42. }
  43. func NewDefaultFramework() *Framework {
  44. options := Options{
  45. TotalParallelNode: config.GinkgoConfig.ParallelTotal,
  46. CurrentNodeIndex: config.GinkgoConfig.ParallelNode,
  47. FromPortIndex: 20000,
  48. ToPortIndex: 50000,
  49. }
  50. return NewFramework(options)
  51. }
  52. func NewFramework(opt Options) *Framework {
  53. f := &Framework{
  54. portAllocator: port.NewAllocator(opt.FromPortIndex, opt.ToPortIndex, opt.TotalParallelNode, opt.CurrentNodeIndex-1),
  55. usedPorts: make(map[string]int),
  56. }
  57. ginkgo.BeforeEach(f.BeforeEach)
  58. ginkgo.AfterEach(f.AfterEach)
  59. return f
  60. }
  61. // BeforeEach create a temp directory.
  62. func (f *Framework) BeforeEach() {
  63. f.beforeEachStarted = true
  64. f.cleanupHandle = AddCleanupAction(f.AfterEach)
  65. dir, err := ioutil.TempDir(os.TempDir(), "frpe2e-test-*")
  66. ExpectNoError(err)
  67. f.TempDirectory = dir
  68. f.mockServers = NewMockServers(f.portAllocator)
  69. if err := f.mockServers.Run(); err != nil {
  70. Failf("%v", err)
  71. }
  72. }
  73. func (f *Framework) AfterEach() {
  74. if !f.beforeEachStarted {
  75. return
  76. }
  77. RemoveCleanupAction(f.cleanupHandle)
  78. // stop processor
  79. for _, p := range f.serverProcesses {
  80. p.Stop()
  81. if TestContext.Debug {
  82. fmt.Println(p.ErrorOutput())
  83. fmt.Println(p.StdOutput())
  84. }
  85. }
  86. for _, p := range f.clientProcesses {
  87. p.Stop()
  88. if TestContext.Debug {
  89. fmt.Println(p.ErrorOutput())
  90. fmt.Println(p.StdOutput())
  91. }
  92. }
  93. f.serverProcesses = nil
  94. f.clientProcesses = nil
  95. // close default mock servers
  96. f.mockServers.Close()
  97. // close manual registered mock servers
  98. for _, s := range f.servers {
  99. s.Close()
  100. }
  101. // clean directory
  102. os.RemoveAll(f.TempDirectory)
  103. f.TempDirectory = ""
  104. f.serverConfPaths = nil
  105. f.clientConfPaths = nil
  106. // release used ports
  107. for _, port := range f.usedPorts {
  108. f.portAllocator.Release(port)
  109. }
  110. f.usedPorts = make(map[string]int)
  111. }
  112. var portRegex = regexp.MustCompile(`{{ \.Port.*? }}`)
  113. // RenderPortsTemplate render templates with ports.
  114. //
  115. // Local: {{ .Port1 }}
  116. // Target: {{ .Port2 }}
  117. //
  118. // return rendered content and all allocated ports.
  119. func (f *Framework) genPortsFromTemplates(templates []string) (ports map[string]int, err error) {
  120. ports = make(map[string]int)
  121. for _, t := range templates {
  122. arrs := portRegex.FindAllString(t, -1)
  123. for _, str := range arrs {
  124. str = strings.TrimPrefix(str, "{{ .")
  125. str = strings.TrimSuffix(str, " }}")
  126. str = strings.TrimSpace(str)
  127. ports[str] = 0
  128. }
  129. }
  130. defer func() {
  131. if err != nil {
  132. for _, port := range ports {
  133. f.portAllocator.Release(port)
  134. }
  135. }
  136. }()
  137. for name := range ports {
  138. port := f.portAllocator.GetByName(name)
  139. if port <= 0 {
  140. return nil, fmt.Errorf("can't allocate port")
  141. }
  142. ports[name] = port
  143. }
  144. return
  145. }
  146. // RenderTemplates alloc all ports for port names placeholder.
  147. func (f *Framework) RenderTemplates(templates []string) (outs []string, ports map[string]int, err error) {
  148. ports, err = f.genPortsFromTemplates(templates)
  149. if err != nil {
  150. return
  151. }
  152. params := f.mockServers.GetTemplateParams()
  153. for name, port := range ports {
  154. params[name] = port
  155. }
  156. for name, port := range f.usedPorts {
  157. params[name] = port
  158. }
  159. for _, t := range templates {
  160. tmpl, err := template.New("").Parse(t)
  161. if err != nil {
  162. return nil, nil, err
  163. }
  164. buffer := bytes.NewBuffer(nil)
  165. if err = tmpl.Execute(buffer, params); err != nil {
  166. return nil, nil, err
  167. }
  168. outs = append(outs, buffer.String())
  169. }
  170. return
  171. }
  172. func (f *Framework) PortByName(name string) int {
  173. return f.usedPorts[name]
  174. }
  175. func (f *Framework) AllocPort() int {
  176. port := f.portAllocator.Get()
  177. ExpectTrue(port > 0, "alloc port failed")
  178. return port
  179. }
  180. func (f *Framework) ReleasePort(port int) {
  181. f.portAllocator.Release(port)
  182. }
  183. func (f *Framework) RunServer(portName string, s *server.Server) {
  184. f.servers = append(f.servers, s)
  185. if s.BindPort() > 0 {
  186. f.usedPorts[portName] = s.BindPort()
  187. }
  188. err := s.Run()
  189. ExpectNoError(err, portName)
  190. }