registry_test.go 9.2 KB

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