github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/scheduler/algorithm/migration_test.go (about)

     1  package algorithm_test
     2  
     3  import (
     4  	"crypto/md5"
     5  	"encoding/hex"
     6  	"encoding/json"
     7  
     8  	"github.com/pf-qiu/concourse/v6/atc"
     9  	. "github.com/onsi/ginkgo/extensions/table"
    10  )
    11  
    12  // NOTE: The purpose of these tests are to test the migration of build inputs
    13  // and outputs to the new successful build outputs table. These tests are very
    14  // dependent on the Row Limit that is set in the table helpers test file. The
    15  // value is currently set to 2 and these tests that expect the migrated rows
    16  // are all written to revolve around that number limit.
    17  
    18  var _ = DescribeTable("Migrating build inputs and outputs into successful build outputs",
    19  	(Example).Run,
    20  
    21  	Entry("migrating all build inputs/outputs and finds a candidate", Example{
    22  		DB: DB{
    23  			NeedsV6Migration: true,
    24  
    25  			BuildInputs: []DBRow{
    26  				{Job: CurrentJobName, BuildID: 100, Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
    27  				{Job: CurrentJobName, BuildID: 100, Resource: "resource-y", Version: "ryv1", CheckOrder: 1},
    28  
    29  				{Job: "simple-a", BuildID: 1, Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
    30  				{Job: "simple-a", BuildID: 2, Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
    31  				{Job: "simple-a", BuildID: 3, Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
    32  				{Job: "simple-a", BuildID: 4, Resource: "resource-x", Version: "rxv1", CheckOrder: 1, RerunOfBuildID: 2},
    33  				{Job: "simple-a", BuildID: 5, Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
    34  
    35  				{Job: "simple-b", BuildID: 6, Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
    36  				{Job: "simple-b", BuildID: 7, Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
    37  				{Job: "simple-b", BuildID: 8, Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
    38  				{Job: "simple-b", BuildID: 9, Resource: "resource-x", Version: "rxv1", CheckOrder: 1, RerunOfBuildID: 7},
    39  				{Job: "simple-b", BuildID: 10, Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
    40  
    41  				{Job: "simple-a", BuildID: 1, Resource: "resource-y", Version: "ryv1", CheckOrder: 1},
    42  				{Job: "simple-a", BuildID: 2, Resource: "resource-y", Version: "ryv2", CheckOrder: 2},
    43  				{Job: "simple-a", BuildID: 3, Resource: "resource-y", Version: "ryv3", CheckOrder: 3},
    44  				{Job: "simple-a", BuildID: 4, Resource: "resource-y", Version: "ryv2", CheckOrder: 2, RerunOfBuildID: 2},
    45  				{Job: "simple-a", BuildID: 5, Resource: "resource-y", Version: "ryv4", CheckOrder: 4},
    46  
    47  				{Job: "simple-b", BuildID: 6, Resource: "resource-y", Version: "ryv1", CheckOrder: 1},
    48  				{Job: "simple-b", BuildID: 7, Resource: "resource-y", Version: "ryv2", CheckOrder: 2},
    49  				{Job: "simple-b", BuildID: 8, Resource: "resource-y", Version: "ryv3", CheckOrder: 3},
    50  				{Job: "simple-b", BuildID: 9, Resource: "resource-y", Version: "ryv2", CheckOrder: 2, RerunOfBuildID: 7},
    51  				{Job: "simple-b", BuildID: 10, Resource: "resource-y", Version: "ryv4", CheckOrder: 4},
    52  
    53  				{Job: "simple-c", BuildID: 11, Resource: "resource-y", Version: "ryv4", CheckOrder: 4},
    54  			},
    55  
    56  			BuildPipes: []DBRow{
    57  				{FromBuildID: 1, ToBuildID: 100},
    58  				{FromBuildID: 6, ToBuildID: 100},
    59  			},
    60  
    61  			BuildOutputs: []DBRow{
    62  				{Job: "simple-a", BuildID: 1, Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
    63  				{Job: "simple-a", BuildID: 2, Resource: "resource-x", Version: "rxv2", CheckOrder: 2},
    64  				{Job: "simple-a", BuildID: 3, Resource: "resource-x", Version: "rxv3", CheckOrder: 3},
    65  				{Job: "simple-a", BuildID: 4, Resource: "resource-x", Version: "rxv2", CheckOrder: 2, RerunOfBuildID: 2},
    66  				{Job: "simple-a", BuildID: 5, Resource: "resource-x", Version: "rxv4", CheckOrder: 4},
    67  
    68  				{Job: "simple-b", BuildID: 6, Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
    69  				{Job: "simple-b", BuildID: 7, Resource: "resource-x", Version: "rxv2", CheckOrder: 2},
    70  				{Job: "simple-b", BuildID: 8, Resource: "resource-x", Version: "rxv3", CheckOrder: 3},
    71  				{Job: "simple-b", BuildID: 9, Resource: "resource-x", Version: "rxv2", CheckOrder: 2, RerunOfBuildID: 7},
    72  				{Job: "simple-b", BuildID: 10, Resource: "resource-x", Version: "rxv4", CheckOrder: 4},
    73  			},
    74  
    75  			Resources: []DBRow{
    76  				{Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
    77  				{Resource: "resource-x", Version: "rxv2", CheckOrder: 2},
    78  				{Resource: "resource-x", Version: "rxv3", CheckOrder: 3},
    79  				{Resource: "resource-x", Version: "rxv4", CheckOrder: 4},
    80  
    81  				{Resource: "resource-y", Version: "ryv1", CheckOrder: 1},
    82  				{Resource: "resource-y", Version: "ryv2", CheckOrder: 2},
    83  				{Resource: "resource-y", Version: "ryv3", CheckOrder: 3},
    84  				{Resource: "resource-y", Version: "ryv4", CheckOrder: 4},
    85  				{Resource: "resource-y", Version: "ryv5", CheckOrder: 5},
    86  			},
    87  		},
    88  
    89  		Inputs: Inputs{
    90  			{
    91  				Name:     "resource-x",
    92  				Resource: "resource-x",
    93  				Version:  Version{Every: true},
    94  				Passed:   []string{"simple-a", "simple-b"},
    95  			},
    96  			{
    97  				Name:     "resource-y",
    98  				Resource: "resource-y",
    99  				Version:  Version{Every: true},
   100  				Passed:   []string{"simple-a", "simple-b", "simple-c"},
   101  			},
   102  		},
   103  
   104  		Result: Result{
   105  			OK: true,
   106  			Values: map[string]string{
   107  				"resource-x": "rxv4",
   108  				"resource-y": "ryv4",
   109  			},
   110  			ExpectedMigrated: map[int]map[int][]string{
   111  				2: map[int][]string{
   112  					1: []string{migratorConvertToMD5("rxv2"), migratorConvertToMD5("rxv1")},
   113  					2: []string{migratorConvertToMD5("ryv2")},
   114  				},
   115  				3: map[int][]string{
   116  					1: []string{migratorConvertToMD5("rxv3"), migratorConvertToMD5("rxv1")},
   117  					2: []string{migratorConvertToMD5("ryv3")},
   118  				},
   119  				4: map[int][]string{
   120  					1: []string{migratorConvertToMD5("rxv2"), migratorConvertToMD5("rxv1")},
   121  					2: []string{migratorConvertToMD5("ryv2")},
   122  				},
   123  				5: map[int][]string{
   124  					1: []string{migratorConvertToMD5("rxv4"), migratorConvertToMD5("rxv1")},
   125  					2: []string{migratorConvertToMD5("ryv4")},
   126  				},
   127  				6: map[int][]string{
   128  					1: []string{migratorConvertToMD5("rxv1"), migratorConvertToMD5("rxv1")},
   129  					2: []string{migratorConvertToMD5("ryv1")},
   130  				},
   131  				7: map[int][]string{
   132  					1: []string{migratorConvertToMD5("rxv2"), migratorConvertToMD5("rxv1")},
   133  					2: []string{migratorConvertToMD5("ryv2")},
   134  				},
   135  				8: map[int][]string{
   136  					1: []string{migratorConvertToMD5("rxv3"), migratorConvertToMD5("rxv1")},
   137  					2: []string{migratorConvertToMD5("ryv3")},
   138  				},
   139  				9: map[int][]string{
   140  					1: []string{migratorConvertToMD5("rxv2"), migratorConvertToMD5("rxv1")},
   141  					2: []string{migratorConvertToMD5("ryv2")},
   142  				},
   143  				10: map[int][]string{
   144  					1: []string{migratorConvertToMD5("rxv4"), migratorConvertToMD5("rxv1")},
   145  					2: []string{migratorConvertToMD5("ryv4")},
   146  				},
   147  				11: map[int][]string{
   148  					2: []string{migratorConvertToMD5("ryv4")},
   149  				},
   150  			},
   151  		},
   152  	}),
   153  
   154  	Entry("migrates all build inputs/outputs and does not find a candidate", Example{
   155  		DB: DB{
   156  			NeedsV6Migration: true,
   157  
   158  			BuildInputs: []DBRow{
   159  				{Job: CurrentJobName, BuildID: 100, Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
   160  
   161  				{Job: "simple-a", BuildID: 1, Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
   162  				{Job: "simple-a", BuildID: 2, Resource: "resource-x", Version: "rxv2", CheckOrder: 2},
   163  				{Job: "simple-a", BuildID: 3, Resource: "resource-x", Version: "rxv3", CheckOrder: 3},
   164  				{Job: "simple-a", BuildID: 4, Resource: "resource-x", Version: "rxv2", CheckOrder: 2, RerunOfBuildID: 2},
   165  				{Job: "simple-a", BuildID: 5, Resource: "resource-x", Version: "rxv4", CheckOrder: 4},
   166  
   167  				{Job: "simple-b", BuildID: 6, Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
   168  				{Job: "simple-b", BuildID: 7, Resource: "resource-x", Version: "rxv2", CheckOrder: 2},
   169  				{Job: "simple-b", BuildID: 8, Resource: "resource-x", Version: "rxv3", CheckOrder: 3},
   170  				{Job: "simple-b", BuildID: 9, Resource: "resource-x", Version: "rxv2", CheckOrder: 2, RerunOfBuildID: 7},
   171  				{Job: "simple-b", BuildID: 10, Resource: "resource-x", Version: "rxv4", CheckOrder: 4},
   172  
   173  				{Job: "simple-a", BuildID: 1, Resource: "resource-y", Version: "ryv1", CheckOrder: 1},
   174  				{Job: "simple-a", BuildID: 2, Resource: "resource-y", Version: "ryv2", CheckOrder: 2},
   175  				{Job: "simple-a", BuildID: 3, Resource: "resource-y", Version: "ryv3", CheckOrder: 3},
   176  				{Job: "simple-a", BuildID: 4, Resource: "resource-y", Version: "ryv2", CheckOrder: 2, RerunOfBuildID: 2},
   177  				{Job: "simple-a", BuildID: 5, Resource: "resource-y", Version: "ryv4", CheckOrder: 4},
   178  
   179  				{Job: "simple-b", BuildID: 6, Resource: "resource-y", Version: "ryv1", CheckOrder: 1},
   180  				{Job: "simple-b", BuildID: 7, Resource: "resource-y", Version: "ryv2", CheckOrder: 2},
   181  				{Job: "simple-b", BuildID: 8, Resource: "resource-y", Version: "ryv3", CheckOrder: 3},
   182  				{Job: "simple-b", BuildID: 9, Resource: "resource-y", Version: "ryv2", CheckOrder: 2, RerunOfBuildID: 7},
   183  				{Job: "simple-b", BuildID: 10, Resource: "resource-y", Version: "ryv4", CheckOrder: 4},
   184  
   185  				{Job: "simple-c", BuildID: 11, Resource: "resource-y", Version: "ryv5", CheckOrder: 4},
   186  			},
   187  
   188  			BuildPipes: []DBRow{
   189  				{FromBuildID: 1, ToBuildID: 100},
   190  				{FromBuildID: 6, ToBuildID: 100},
   191  			},
   192  
   193  			BuildOutputs: []DBRow{
   194  				{Job: "simple-a", BuildID: 1, Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
   195  				{Job: "simple-a", BuildID: 2, Resource: "resource-x", Version: "rxv2", CheckOrder: 2},
   196  				{Job: "simple-a", BuildID: 3, Resource: "resource-x", Version: "rxv3", CheckOrder: 3},
   197  				{Job: "simple-a", BuildID: 4, Resource: "resource-x", Version: "rxv2", CheckOrder: 2, RerunOfBuildID: 2},
   198  				{Job: "simple-a", BuildID: 5, Resource: "resource-x", Version: "rxv4", CheckOrder: 4},
   199  
   200  				{Job: "simple-b", BuildID: 6, Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
   201  				{Job: "simple-b", BuildID: 7, Resource: "resource-x", Version: "rxv2", CheckOrder: 2},
   202  				{Job: "simple-b", BuildID: 8, Resource: "resource-x", Version: "rxv3", CheckOrder: 3},
   203  				{Job: "simple-b", BuildID: 9, Resource: "resource-x", Version: "rxv2", CheckOrder: 2, RerunOfBuildID: 7},
   204  				{Job: "simple-b", BuildID: 10, Resource: "resource-x", Version: "rxv4", CheckOrder: 4},
   205  			},
   206  
   207  			Resources: []DBRow{
   208  				{Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
   209  				{Resource: "resource-x", Version: "rxv2", CheckOrder: 2},
   210  				{Resource: "resource-x", Version: "rxv3", CheckOrder: 3},
   211  				{Resource: "resource-x", Version: "rxv4", CheckOrder: 4},
   212  
   213  				{Resource: "resource-y", Version: "ryv1", CheckOrder: 1},
   214  				{Resource: "resource-y", Version: "ryv2", CheckOrder: 2},
   215  				{Resource: "resource-y", Version: "ryv3", CheckOrder: 3},
   216  				{Resource: "resource-y", Version: "ryv4", CheckOrder: 4},
   217  				{Resource: "resource-y", Version: "ryv5", CheckOrder: 5},
   218  			},
   219  		},
   220  
   221  		Inputs: Inputs{
   222  			{
   223  				Name:     "resource-x",
   224  				Resource: "resource-x",
   225  				Version:  Version{Every: true},
   226  				Passed:   []string{"simple-a", "simple-b"},
   227  			},
   228  			{
   229  				Name:     "resource-y",
   230  				Resource: "resource-y",
   231  				Version:  Version{Every: true},
   232  				Passed:   []string{"simple-a", "simple-b", "simple-c"},
   233  			},
   234  		},
   235  
   236  		Result: Result{
   237  			OK: false,
   238  			Errors: map[string]string{
   239  				"resource-x": "no satisfiable builds from passed jobs found for set of inputs",
   240  				"resource-y": "no satisfiable builds from passed jobs found for set of inputs",
   241  			},
   242  			ExpectedMigrated: map[int]map[int][]string{
   243  				1: map[int][]string{
   244  					1: []string{migratorConvertToMD5("rxv1"), migratorConvertToMD5("rxv1")},
   245  					2: []string{migratorConvertToMD5("ryv1")},
   246  				},
   247  				2: map[int][]string{
   248  					1: []string{migratorConvertToMD5("rxv2"), migratorConvertToMD5("rxv2")},
   249  					2: []string{migratorConvertToMD5("ryv2")},
   250  				},
   251  				3: map[int][]string{
   252  					1: []string{migratorConvertToMD5("rxv3"), migratorConvertToMD5("rxv3")},
   253  					2: []string{migratorConvertToMD5("ryv3")},
   254  				},
   255  				4: map[int][]string{
   256  					1: []string{migratorConvertToMD5("rxv2"), migratorConvertToMD5("rxv2")},
   257  					2: []string{migratorConvertToMD5("ryv2")},
   258  				},
   259  				5: map[int][]string{
   260  					1: []string{migratorConvertToMD5("rxv4"), migratorConvertToMD5("rxv4")},
   261  					2: []string{migratorConvertToMD5("ryv4")},
   262  				},
   263  				6: map[int][]string{
   264  					1: []string{migratorConvertToMD5("rxv1"), migratorConvertToMD5("rxv1")},
   265  					2: []string{migratorConvertToMD5("ryv1")},
   266  				},
   267  				7: map[int][]string{
   268  					1: []string{migratorConvertToMD5("rxv2"), migratorConvertToMD5("rxv2")},
   269  					2: []string{migratorConvertToMD5("ryv2")},
   270  				},
   271  				8: map[int][]string{
   272  					1: []string{migratorConvertToMD5("rxv3"), migratorConvertToMD5("rxv3")},
   273  					2: []string{migratorConvertToMD5("ryv3")},
   274  				},
   275  				9: map[int][]string{
   276  					1: []string{migratorConvertToMD5("rxv2"), migratorConvertToMD5("rxv2")},
   277  					2: []string{migratorConvertToMD5("ryv2")},
   278  				},
   279  				10: map[int][]string{
   280  					1: []string{migratorConvertToMD5("rxv4"), migratorConvertToMD5("rxv4")},
   281  					2: []string{migratorConvertToMD5("ryv4")},
   282  				},
   283  				11: map[int][]string{
   284  					2: []string{migratorConvertToMD5("ryv5")},
   285  				},
   286  			},
   287  		},
   288  	}),
   289  
   290  	Entry("migrates part of the build inputs/outputs and finds a candidate with version every", Example{
   291  		DB: DB{
   292  			NeedsV6Migration: true,
   293  
   294  			BuildInputs: []DBRow{
   295  				{Job: CurrentJobName, BuildID: 100, Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
   296  			},
   297  
   298  			BuildPipes: []DBRow{
   299  				{FromBuildID: 1, ToBuildID: 100},
   300  				{FromBuildID: 6, ToBuildID: 100},
   301  			},
   302  
   303  			BuildOutputs: []DBRow{
   304  				{Job: "simple-a", BuildID: 1, Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
   305  				{Job: "simple-a", BuildID: 2, Resource: "resource-x", Version: "rxv2", CheckOrder: 2},
   306  				{Job: "simple-a", BuildID: 3, Resource: "resource-x", Version: "rxv3", CheckOrder: 3},
   307  				{Job: "simple-a", BuildID: 4, Resource: "resource-x", Version: "rxv4", CheckOrder: 4},
   308  
   309  				{Job: "simple-b", BuildID: 6, Resource: "resource-x", Version: "rxv3", CheckOrder: 4},
   310  			},
   311  
   312  			Resources: []DBRow{
   313  				{Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
   314  				{Resource: "resource-x", Version: "rxv2", CheckOrder: 2},
   315  				{Resource: "resource-x", Version: "rxv3", CheckOrder: 3},
   316  				{Resource: "resource-x", Version: "rxv4", CheckOrder: 4},
   317  			},
   318  		},
   319  
   320  		Inputs: Inputs{
   321  			{
   322  				Name:     "resource-x",
   323  				Resource: "resource-x",
   324  				Version:  Version{Every: true},
   325  				Passed:   []string{"simple-a", "simple-b"},
   326  			},
   327  		},
   328  
   329  		Result: Result{
   330  			OK: true,
   331  			Values: map[string]string{
   332  				"resource-x": "rxv3",
   333  			},
   334  			ExpectedMigrated: map[int]map[int][]string{
   335  				2: map[int][]string{
   336  					1: []string{migratorConvertToMD5("rxv2")},
   337  				},
   338  				3: map[int][]string{
   339  					1: []string{migratorConvertToMD5("rxv3")},
   340  				},
   341  				6: map[int][]string{
   342  					1: []string{migratorConvertToMD5("rxv3")},
   343  				},
   344  			},
   345  		},
   346  	}),
   347  
   348  	Entry("migrates older build inputs/outputs and finds a candidate with version every", Example{
   349  		DB: DB{
   350  			NeedsV6Migration: true,
   351  
   352  			BuildInputs: []DBRow{
   353  				{Job: CurrentJobName, BuildID: 100, Resource: "resource-x", Version: "rxv4", CheckOrder: 4},
   354  			},
   355  
   356  			BuildPipes: []DBRow{
   357  				{FromBuildID: 4, ToBuildID: 100},
   358  			},
   359  
   360  			BuildOutputs: []DBRow{
   361  				{Job: "simple-a", BuildID: 1, Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
   362  				{Job: "simple-a", BuildID: 2, Resource: "resource-x", Version: "rxv2", CheckOrder: 2},
   363  				{Job: "simple-a", BuildID: 3, Resource: "resource-x", Version: "rxv3", CheckOrder: 3},
   364  				{Job: "simple-a", BuildID: 4, Resource: "resource-x", Version: "rxv4", CheckOrder: 4},
   365  
   366  				{Job: "simple-b", BuildID: 5, Resource: "resource-x", Version: "rxv3", CheckOrder: 3},
   367  			},
   368  
   369  			Resources: []DBRow{
   370  				{Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
   371  				{Resource: "resource-x", Version: "rxv2", CheckOrder: 2},
   372  				{Resource: "resource-x", Version: "rxv3", CheckOrder: 3},
   373  				{Resource: "resource-x", Version: "rxv4", CheckOrder: 4},
   374  			},
   375  		},
   376  
   377  		Inputs: Inputs{
   378  			{
   379  				Name:     "resource-x",
   380  				Resource: "resource-x",
   381  				Version:  Version{Every: true},
   382  				Passed:   []string{"simple-a", "simple-b"},
   383  			},
   384  		},
   385  
   386  		Result: Result{
   387  			OK: true,
   388  			Values: map[string]string{
   389  				"resource-x": "rxv3",
   390  			},
   391  			ExpectedMigrated: map[int]map[int][]string{
   392  				4: map[int][]string{
   393  					1: []string{migratorConvertToMD5("rxv4")},
   394  				},
   395  				3: map[int][]string{
   396  					1: []string{migratorConvertToMD5("rxv3")},
   397  				},
   398  				5: map[int][]string{
   399  					1: []string{migratorConvertToMD5("rxv3")},
   400  				},
   401  			},
   402  		},
   403  	}),
   404  
   405  	Entry("migrates part of the build inputs/outputs and finds a candidate with version latest", Example{
   406  		DB: DB{
   407  			NeedsV6Migration: true,
   408  
   409  			BuildInputs: []DBRow{
   410  				{Job: "simple-a", BuildID: 1, Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
   411  				{Job: "simple-a", BuildID: 2, Resource: "resource-x", Version: "rxv2", CheckOrder: 2},
   412  				{Job: "simple-a", BuildID: 3, Resource: "resource-x", Version: "rxv3", CheckOrder: 3},
   413  				{Job: "simple-a", BuildID: 4, Resource: "resource-x", Version: "rxv4", CheckOrder: 4},
   414  
   415  				{Job: "simple-b", BuildID: 6, Resource: "resource-x", Version: "rxv3", CheckOrder: 3},
   416  			},
   417  
   418  			Resources: []DBRow{
   419  				{Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
   420  				{Resource: "resource-x", Version: "rxv2", CheckOrder: 2},
   421  				{Resource: "resource-x", Version: "rxv3", CheckOrder: 3},
   422  				{Resource: "resource-x", Version: "rxv4", CheckOrder: 4},
   423  			},
   424  		},
   425  
   426  		Inputs: Inputs{
   427  			{
   428  				Name:     "resource-x",
   429  				Resource: "resource-x",
   430  				Passed:   []string{"simple-a", "simple-b"},
   431  			},
   432  		},
   433  
   434  		Result: Result{
   435  			OK: true,
   436  			Values: map[string]string{
   437  				"resource-x": "rxv3",
   438  			},
   439  			ExpectedMigrated: map[int]map[int][]string{
   440  				3: map[int][]string{
   441  					1: []string{migratorConvertToMD5("rxv3")},
   442  				},
   443  				4: map[int][]string{
   444  					1: []string{migratorConvertToMD5("rxv4")},
   445  				},
   446  				6: map[int][]string{
   447  					1: []string{migratorConvertToMD5("rxv3")},
   448  				},
   449  			},
   450  		},
   451  	}),
   452  
   453  	Entry("migrating preserves outputs over inputs", Example{
   454  		DB: DB{
   455  			NeedsV6Migration: true,
   456  
   457  			BuildInputs: []DBRow{
   458  				{Job: "simple-a", BuildID: 1, Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
   459  			},
   460  
   461  			BuildOutputs: []DBRow{
   462  				{Job: "simple-a", BuildID: 1, Resource: "resource-x", Version: "rxv2", CheckOrder: 1},
   463  			},
   464  
   465  			Resources: []DBRow{
   466  				{Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
   467  				{Resource: "resource-x", Version: "rxv2", CheckOrder: 2},
   468  			},
   469  		},
   470  
   471  		Inputs: Inputs{
   472  			{
   473  				Name:     "resource-x",
   474  				Resource: "resource-x",
   475  				Passed:   []string{"simple-a"},
   476  			},
   477  		},
   478  
   479  		Result: Result{
   480  			OK: true,
   481  			Values: map[string]string{
   482  				"resource-x": "rxv2",
   483  			},
   484  			ExpectedMigrated: map[int]map[int][]string{
   485  				1: map[int][]string{
   486  					1: []string{migratorConvertToMD5("rxv2"), migratorConvertToMD5("rxv1")},
   487  				},
   488  			},
   489  		},
   490  	}),
   491  
   492  	Entry("migrates only successful build inputs/outputs", Example{
   493  		DB: DB{
   494  			NeedsV6Migration: true,
   495  
   496  			BuildInputs: []DBRow{
   497  				{Job: CurrentJobName, BuildID: 100, Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
   498  			},
   499  
   500  			BuildPipes: []DBRow{
   501  				{FromBuildID: 1, ToBuildID: 100},
   502  				{FromBuildID: 6, ToBuildID: 100},
   503  			},
   504  
   505  			BuildOutputs: []DBRow{
   506  				{Job: "simple-a", BuildID: 1, Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
   507  				{Job: "simple-a", BuildID: 2, Resource: "resource-x", Version: "rxv2", CheckOrder: 2},
   508  				{Job: "simple-a", BuildID: 3, Resource: "resource-x", Version: "rxv3", CheckOrder: 3, BuildStatus: "failed"},
   509  				{Job: "simple-a", BuildID: 4, Resource: "resource-x", Version: "rxv4", CheckOrder: 4},
   510  
   511  				{Job: "simple-b", BuildID: 6, Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
   512  				{Job: "simple-b", BuildID: 7, Resource: "resource-x", Version: "rxv2", CheckOrder: 2, BuildStatus: "pending"},
   513  				{Job: "simple-b", BuildID: 8, Resource: "resource-x", Version: "rxv3", CheckOrder: 3},
   514  				{Job: "simple-b", BuildID: 9, Resource: "resource-x", Version: "rxv4", CheckOrder: 4},
   515  			},
   516  
   517  			Resources: []DBRow{
   518  				{Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
   519  				{Resource: "resource-x", Version: "rxv2", CheckOrder: 2},
   520  				{Resource: "resource-x", Version: "rxv3", CheckOrder: 3},
   521  				{Resource: "resource-x", Version: "rxv4", CheckOrder: 4},
   522  			},
   523  		},
   524  
   525  		Inputs: Inputs{
   526  			{
   527  				Name:     "resource-x",
   528  				Resource: "resource-x",
   529  				Version:  Version{Every: true},
   530  				Passed:   []string{"simple-a", "simple-b"},
   531  			},
   532  		},
   533  
   534  		Result: Result{
   535  			OK: true,
   536  			Values: map[string]string{
   537  				"resource-x": "rxv4",
   538  			},
   539  			ExpectedMigrated: map[int]map[int][]string{
   540  				2: map[int][]string{
   541  					1: []string{migratorConvertToMD5("rxv2")},
   542  				},
   543  				4: map[int][]string{
   544  					1: []string{migratorConvertToMD5("rxv4")},
   545  				},
   546  				6: map[int][]string{
   547  					1: []string{migratorConvertToMD5("rxv1")},
   548  				},
   549  				8: map[int][]string{
   550  					1: []string{migratorConvertToMD5("rxv3")},
   551  				},
   552  				9: map[int][]string{
   553  					1: []string{migratorConvertToMD5("rxv4")},
   554  				},
   555  			},
   556  		},
   557  	}),
   558  
   559  	Entry("migrates build inputs/outputs with rerun builds in the right order", Example{
   560  		DB: DB{
   561  			NeedsV6Migration: true,
   562  
   563  			BuildInputs: []DBRow{
   564  				{Job: CurrentJobName, BuildID: 100, Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
   565  			},
   566  
   567  			BuildPipes: []DBRow{
   568  				{FromBuildID: 1, ToBuildID: 100},
   569  			},
   570  
   571  			BuildOutputs: []DBRow{
   572  				{Job: "simple-a", BuildID: 1, Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
   573  				{Job: "simple-a", BuildID: 2, Resource: "resource-x", Version: "rxv5", CheckOrder: 5},
   574  				{Job: "simple-a", BuildID: 3, Resource: "resource-x", Version: "rxv2", CheckOrder: 2},
   575  				{Job: "simple-a", BuildID: 4, Resource: "resource-x", Version: "rxv3", CheckOrder: 3},
   576  				{Job: "simple-a", BuildID: 5, Resource: "resource-x", Version: "rxv5", CheckOrder: 5, RerunOfBuildID: 2},
   577  			},
   578  
   579  			Resources: []DBRow{
   580  				{Resource: "resource-x", Version: "rxv1", CheckOrder: 1},
   581  				{Resource: "resource-x", Version: "rxv2", CheckOrder: 2},
   582  				{Resource: "resource-x", Version: "rxv3", CheckOrder: 3},
   583  				{Resource: "resource-x", Version: "rxv4", CheckOrder: 4},
   584  				{Resource: "resource-x", Version: "rxv5", CheckOrder: 5},
   585  			},
   586  		},
   587  
   588  		Inputs: Inputs{
   589  			{
   590  				Name:     "resource-x",
   591  				Resource: "resource-x",
   592  				Passed:   []string{"simple-a"},
   593  			},
   594  		},
   595  
   596  		Result: Result{
   597  			OK: true,
   598  			Values: map[string]string{
   599  				"resource-x": "rxv3",
   600  			},
   601  			ExpectedMigrated: map[int]map[int][]string{
   602  				4: map[int][]string{
   603  					1: []string{migratorConvertToMD5("rxv3")},
   604  				},
   605  			},
   606  		},
   607  	}),
   608  )
   609  
   610  func migratorConvertToMD5(version string) string {
   611  	versionJSON, _ := json.Marshal(atc.Version{"ver": version})
   612  
   613  	hasher := md5.New()
   614  	hasher.Write([]byte(versionJSON))
   615  	return hex.EncodeToString(hasher.Sum(nil))
   616  }