registry_test.go 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. package core
  2. import (
  3. "os"
  4. "reflect"
  5. "testing"
  6. "github.com/spf13/cobra"
  7. "github.com/spf13/pflag"
  8. "github.com/stretchr/testify/assert"
  9. "gopkg.in/src-d/go-git.v4"
  10. "gopkg.in/src-d/hercules.v10/internal/test"
  11. )
  12. func getRegistry() *PipelineItemRegistry {
  13. return &PipelineItemRegistry{
  14. provided: map[string][]reflect.Type{},
  15. registered: map[string]reflect.Type{},
  16. flags: map[string]reflect.Type{},
  17. featureFlags: arrayFeatureFlags{Flags: []string{}, Choices: map[string]bool{}},
  18. }
  19. }
  20. type dummyPipelineItem struct{}
  21. func (item *dummyPipelineItem) Name() string {
  22. return "dummy"
  23. }
  24. func (item *dummyPipelineItem) Provides() []string {
  25. arr := [...]string{"dummy"}
  26. return arr[:]
  27. }
  28. func (item *dummyPipelineItem) Requires() []string {
  29. return []string{}
  30. }
  31. func (item *dummyPipelineItem) Features() []string {
  32. arr := [...]string{"power"}
  33. return arr[:]
  34. }
  35. func (item *dummyPipelineItem) Configure(facts map[string]interface{}) error {
  36. return nil
  37. }
  38. func (item *dummyPipelineItem) ListConfigurationOptions() []ConfigurationOption {
  39. options := [...]ConfigurationOption{{
  40. Name: "DummyOption",
  41. Description: "The option description.",
  42. Flag: "dummy-option",
  43. Type: BoolConfigurationOption,
  44. Default: false,
  45. }}
  46. return options[:]
  47. }
  48. func (item *dummyPipelineItem) Initialize(repository *git.Repository) error {
  49. return nil
  50. }
  51. func (item *dummyPipelineItem) Consume(deps map[string]interface{}) (map[string]interface{}, error) {
  52. return map[string]interface{}{"dummy": nil}, nil
  53. }
  54. func (item *dummyPipelineItem) Fork(n int) []PipelineItem {
  55. return nil
  56. }
  57. func (item *dummyPipelineItem) Merge(branches []PipelineItem) {
  58. }
  59. type dummyPipelineItem2 struct{}
  60. func (item *dummyPipelineItem2) Name() string {
  61. return "dummy2"
  62. }
  63. func (item *dummyPipelineItem2) Provides() []string {
  64. arr := [...]string{"dummy2"}
  65. return arr[:]
  66. }
  67. func (item *dummyPipelineItem2) Requires() []string {
  68. return []string{}
  69. }
  70. func (item *dummyPipelineItem2) Features() []string {
  71. arr := [...]string{"other"}
  72. return arr[:]
  73. }
  74. func (item *dummyPipelineItem2) Configure(facts map[string]interface{}) error {
  75. return nil
  76. }
  77. func (item *dummyPipelineItem2) ListConfigurationOptions() []ConfigurationOption {
  78. return []ConfigurationOption{}
  79. }
  80. func (item *dummyPipelineItem2) Initialize(repository *git.Repository) error {
  81. return nil
  82. }
  83. func (item *dummyPipelineItem2) Consume(deps map[string]interface{}) (map[string]interface{}, error) {
  84. return map[string]interface{}{"dummy2": nil}, nil
  85. }
  86. func (item *dummyPipelineItem2) Fork(n int) []PipelineItem {
  87. return nil
  88. }
  89. func (item *dummyPipelineItem2) Merge(branches []PipelineItem) {
  90. }
  91. type dummyPipelineItem3 struct{}
  92. func (item *dummyPipelineItem3) Name() string {
  93. return "dummy3"
  94. }
  95. func (item *dummyPipelineItem3) Provides() []string {
  96. arr := [...]string{"dummy3"}
  97. return arr[:]
  98. }
  99. func (item *dummyPipelineItem3) Requires() []string {
  100. return []string{"dummy"}
  101. }
  102. func (item *dummyPipelineItem3) Configure(facts map[string]interface{}) error {
  103. return nil
  104. }
  105. func (item *dummyPipelineItem3) ListConfigurationOptions() []ConfigurationOption {
  106. return nil
  107. }
  108. func (item *dummyPipelineItem3) Initialize(repository *git.Repository) error {
  109. return nil
  110. }
  111. func (item *dummyPipelineItem3) Consume(deps map[string]interface{}) (map[string]interface{}, error) {
  112. return map[string]interface{}{"dummy": nil}, nil
  113. }
  114. func (item *dummyPipelineItem3) Fork(n int) []PipelineItem {
  115. return nil
  116. }
  117. func (item *dummyPipelineItem3) Merge(branches []PipelineItem) {
  118. }
  119. type dummyPipelineItem4 struct{}
  120. func (item *dummyPipelineItem4) Name() string {
  121. return "dummy4"
  122. }
  123. func (item *dummyPipelineItem4) Provides() []string {
  124. arr := [...]string{"dummy4"}
  125. return arr[:]
  126. }
  127. func (item *dummyPipelineItem4) Requires() []string {
  128. return []string{"dummy3"}
  129. }
  130. func (item *dummyPipelineItem4) Configure(facts map[string]interface{}) error {
  131. return nil
  132. }
  133. func (item *dummyPipelineItem4) ListConfigurationOptions() []ConfigurationOption {
  134. return nil
  135. }
  136. func (item *dummyPipelineItem4) Initialize(repository *git.Repository) error {
  137. return nil
  138. }
  139. func (item *dummyPipelineItem4) Consume(deps map[string]interface{}) (map[string]interface{}, error) {
  140. return map[string]interface{}{"dummy": nil}, nil
  141. }
  142. func (item *dummyPipelineItem4) Fork(n int) []PipelineItem {
  143. return nil
  144. }
  145. func (item *dummyPipelineItem4) Merge(branches []PipelineItem) {
  146. }
  147. func TestRegistrySummon(t *testing.T) {
  148. reg := getRegistry()
  149. assert.Len(t, reg.Summon("whatever"), 0)
  150. reg.Register(&testPipelineItem{})
  151. summoned := reg.Summon((&testPipelineItem{}).Provides()[0])
  152. assert.Len(t, summoned, 1)
  153. assert.Equal(t, summoned[0].Name(), (&testPipelineItem{}).Name())
  154. summoned = reg.Summon((&testPipelineItem{}).Name())
  155. assert.Len(t, summoned, 1)
  156. assert.Equal(t, summoned[0].Name(), (&testPipelineItem{}).Name())
  157. }
  158. func TestRegistryAddFlags(t *testing.T) {
  159. reg := getRegistry()
  160. reg.Register(&testPipelineItem{})
  161. reg.Register(&dummyPipelineItem{})
  162. testCmd := &cobra.Command{
  163. Use: "test",
  164. Short: "Temporary command to test the stuff.",
  165. Long: ``,
  166. Args: cobra.MaximumNArgs(0),
  167. Run: func(cmd *cobra.Command, args []string) {},
  168. }
  169. facts, deployed := reg.AddFlags(testCmd.Flags())
  170. assert.Len(t, facts, 7)
  171. assert.IsType(t, 0, facts[(&testPipelineItem{}).ListConfigurationOptions()[0].Name])
  172. assert.IsType(t, true, facts[(&dummyPipelineItem{}).ListConfigurationOptions()[0].Name])
  173. assert.Contains(t, facts, ConfigPipelineDryRun)
  174. assert.Contains(t, facts, ConfigPipelineDAGPath)
  175. assert.Contains(t, facts, ConfigPipelineDumpPlan)
  176. assert.Contains(t, facts, ConfigPipelineHibernationDistance)
  177. assert.Len(t, deployed, 1)
  178. assert.Contains(t, deployed, (&testPipelineItem{}).Name())
  179. assert.NotNil(t, testCmd.Flags().Lookup((&testPipelineItem{}).Flag()))
  180. assert.NotNil(t, testCmd.Flags().Lookup("feature"))
  181. assert.NotNil(t, testCmd.Flags().Lookup("dump-dag"))
  182. assert.NotNil(t, testCmd.Flags().Lookup("dump-plan"))
  183. assert.NotNil(t, testCmd.Flags().Lookup("dry-run"))
  184. assert.NotNil(t, testCmd.Flags().Lookup("hibernation-distance"))
  185. assert.NotNil(t, testCmd.Flags().Lookup("print-actions"))
  186. assert.NotNil(t, testCmd.Flags().Lookup(
  187. (&testPipelineItem{}).ListConfigurationOptions()[0].Flag))
  188. assert.NotNil(t, testCmd.Flags().Lookup(
  189. (&dummyPipelineItem{}).ListConfigurationOptions()[0].Flag))
  190. testCmd.UsageString() // to test that nothing is broken
  191. }
  192. func TestRegistryFeatures(t *testing.T) {
  193. reg := getRegistry()
  194. reg.Register(&dummyPipelineItem{})
  195. reg.Register(&dummyPipelineItem2{})
  196. testCmd := &cobra.Command{
  197. Use: "test",
  198. Short: "Temporary command to test the stuff.",
  199. Long: ``,
  200. Args: cobra.MaximumNArgs(0),
  201. Run: func(cmd *cobra.Command, args []string) {},
  202. }
  203. reg.AddFlags(testCmd.Flags())
  204. args := [...]string{"--feature", "other", "--feature", "power"}
  205. testCmd.ParseFlags(args[:])
  206. pipeline := NewPipeline(test.Repository)
  207. val, _ := pipeline.GetFeature("power")
  208. assert.False(t, val)
  209. val, _ = pipeline.GetFeature("other")
  210. assert.False(t, val)
  211. pipeline.SetFeaturesFromFlags(reg)
  212. val, _ = pipeline.GetFeature("power")
  213. assert.True(t, val)
  214. val, _ = pipeline.GetFeature("other")
  215. assert.True(t, val)
  216. }
  217. func TestRegistryCollectAllDependencies(t *testing.T) {
  218. reg := getRegistry()
  219. reg.Register(&dummyPipelineItem{})
  220. reg.Register(&dummyPipelineItem3{})
  221. reg.Register(&dummyPipelineItem4{})
  222. assert.Len(t, reg.CollectAllDependencies(&dummyPipelineItem{}), 0)
  223. deps := reg.CollectAllDependencies(&dummyPipelineItem4{})
  224. assert.Len(t, deps, 2)
  225. assert.Equal(t, deps[0].Name(), (&dummyPipelineItem{}).Name())
  226. assert.Equal(t, deps[1].Name(), (&dummyPipelineItem3{}).Name())
  227. }
  228. func TestRegistryLeaves(t *testing.T) {
  229. reg := getRegistry()
  230. reg.Register(&testPipelineItem{})
  231. reg.Register(&dependingTestPipelineItem{})
  232. reg.Register(&dummyPipelineItem{})
  233. leaves := reg.GetLeaves()
  234. assert.Len(t, leaves, 2)
  235. assert.Equal(t, leaves[0].Name(), (&dependingTestPipelineItem{}).Name())
  236. assert.Equal(t, leaves[1].Name(), (&testPipelineItem{}).Name())
  237. }
  238. func TestRegistryPlumbingItems(t *testing.T) {
  239. reg := getRegistry()
  240. reg.Register(&testPipelineItem{})
  241. reg.Register(&dependingTestPipelineItem{})
  242. reg.Register(&dummyPipelineItem{})
  243. plumbing := reg.GetPlumbingItems()
  244. assert.Len(t, plumbing, 1)
  245. assert.Equal(t, plumbing[0].Name(), (&dummyPipelineItem{}).Name())
  246. }
  247. func TestRegistryFeaturedItems(t *testing.T) {
  248. reg := getRegistry()
  249. reg.Register(&testPipelineItem{})
  250. reg.Register(&dependingTestPipelineItem{})
  251. reg.Register(&dummyPipelineItem{})
  252. reg.Register(&dummyPipelineItem3{})
  253. reg.Register(&dummyPipelineItem4{})
  254. featured := reg.GetFeaturedItems()
  255. assert.Len(t, featured, 1)
  256. power := featured["power"]
  257. assert.Len(t, power, 5)
  258. assert.Equal(t, power[0].Name(), (&testPipelineItem{}).Name())
  259. assert.Equal(t, power[1].Name(), (&dependingTestPipelineItem{}).Name())
  260. assert.Equal(t, power[2].Name(), (&dummyPipelineItem{}).Name())
  261. assert.Equal(t, power[3].Name(), (&dummyPipelineItem3{}).Name())
  262. assert.Equal(t, power[4].Name(), (&dummyPipelineItem4{}).Name())
  263. }
  264. func TestRegistryPathMasquerade(t *testing.T) {
  265. fs := pflag.NewFlagSet(os.Args[0], pflag.ContinueOnError)
  266. var value string
  267. fs.StringVar(&value, "test", "", "usage")
  268. flag := fs.Lookup("test")
  269. PathifyFlagValue(flag)
  270. assert.Equal(t, flag.Value.Type(), "string")
  271. assert.Nil(t, flag.Value.Set("xxx"))
  272. assert.Equal(t, flag.Value.String(), "xxx")
  273. EnablePathFlagTypeMasquerade()
  274. assert.Equal(t, flag.Value.Type(), "path")
  275. assert.Equal(t, flag.Value.String(), "xxx")
  276. }