github.com/redhat-appstudio/e2e-tests@v0.0.0-20230619105049-9a422b2094d7/magefiles/utils_test.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"math/rand"
     6  	"strings"
     7  	"sync"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/redhat-appstudio/image-controller/pkg/quay"
    12  )
    13  
    14  type QuayClientMock struct {
    15  	AllRepositories         []quay.Repository
    16  	AllRobotAccounts        []quay.RobotAccount
    17  	AllTags                 []quay.Tag
    18  	DeleteRepositoryCalls   map[string]bool
    19  	DeleteRobotAccountCalls map[string]bool
    20  	DeleteTagCalls          map[string]bool
    21  	TagsOnPage              int
    22  	TagPages                int
    23  	Benchmark               bool
    24  }
    25  
    26  var _ quay.QuayService = (*QuayClientMock)(nil)
    27  
    28  func (m *QuayClientMock) GetAllRepositories(organization string) ([]quay.Repository, error) {
    29  	return m.AllRepositories, nil
    30  }
    31  
    32  func (m *QuayClientMock) GetAllRobotAccounts(organization string) ([]quay.RobotAccount, error) {
    33  	return m.AllRobotAccounts, nil
    34  }
    35  
    36  func (m *QuayClientMock) DeleteRepository(organization, repoName string) (bool, error) {
    37  	m.DeleteRepositoryCalls[repoName] = true
    38  	return true, nil
    39  }
    40  
    41  func (m *QuayClientMock) DeleteRobotAccount(organization, robotName string) (bool, error) {
    42  	m.DeleteRobotAccountCalls[robotName] = true
    43  	return true, nil
    44  }
    45  
    46  func (m *QuayClientMock) GetTagsFromPage(organization, repository string, page int) ([]quay.Tag, bool, error) {
    47  	if m.Benchmark {
    48  		time.Sleep(100 * time.Millisecond) // Mock delay for request
    49  	}
    50  	if page == m.TagPages {
    51  		return m.AllTags[(page-1)*m.TagsOnPage : (page * m.TagsOnPage)], false, nil
    52  	}
    53  	return m.AllTags[(page-1)*m.TagsOnPage : (page * m.TagsOnPage)], true, nil
    54  }
    55  
    56  var deleteTagCallsMutex = sync.RWMutex{}
    57  
    58  func (m *QuayClientMock) DeleteTag(organization, repository, tag string) (bool, error) {
    59  	if m.Benchmark {
    60  		time.Sleep(100 * time.Millisecond) // Mock delay for request
    61  	}
    62  	deleteTagCallsMutex.Lock()
    63  	m.DeleteTagCalls[tag] = true
    64  	deleteTagCallsMutex.Unlock()
    65  	return true, nil
    66  }
    67  
    68  // Dummy functions
    69  func (m *QuayClientMock) AddWritePermissionsToRobotAccount(organization, imageRepository, robotAccountName string) error {
    70  	return nil
    71  }
    72  
    73  func (m *QuayClientMock) CreateRepository(r quay.RepositoryRequest) (*quay.Repository, error) {
    74  	return nil, nil
    75  }
    76  
    77  func (m *QuayClientMock) CreateRobotAccount(organization string, robotName string) (*quay.RobotAccount, error) {
    78  	return nil, nil
    79  }
    80  
    81  func (m *QuayClientMock) GetRobotAccount(organization string, robotName string) (*quay.RobotAccount, error) {
    82  	return nil, nil
    83  }
    84  
    85  func TestCleanupQuayReposAndRobots(t *testing.T) {
    86  	timeFormat := "Mon, 02 Jan 2006 15:04:05 -0700"
    87  
    88  	deletedRepos := []quay.Repository{
    89  		{Name: "e2e-demos/test-old"},
    90  		{Name: "has-e2e/test-old"},
    91  	}
    92  	preservedRepos := []quay.Repository{
    93  		{Name: "e2e-demos/test-new"},
    94  		{Name: "has-e2e/test-new"},
    95  		{Name: "other/test-new"},
    96  		{Name: "other/test-old"},
    97  	}
    98  	deletedRobots := []quay.RobotAccount{
    99  		{Name: "test-org+e2e-demostest-old", Created: time.Now().Add(-25 * time.Hour).Format(timeFormat)},
   100  		{Name: "test-org+has-e2etest-old", Created: time.Now().Add(-25 * time.Hour).Format(timeFormat)},
   101  	}
   102  	preservedRobots := []quay.RobotAccount{
   103  		{Name: "test-org+e2e-demostest-new", Created: time.Now().Format(timeFormat)},
   104  		{Name: "test-org+has-e2etest-new", Created: time.Now().Format(timeFormat)},
   105  		{Name: "test-org+othertest-old", Created: time.Now().Add(-25 * time.Hour).Format(timeFormat)},
   106  		{Name: "test-org+othertest-new", Created: time.Now().Format(timeFormat)},
   107  	}
   108  	quayClientMock := QuayClientMock{
   109  		AllRepositories:         append(deletedRepos, preservedRepos...),
   110  		AllRobotAccounts:        append(deletedRobots, preservedRobots...),
   111  		DeleteRepositoryCalls:   make(map[string]bool),
   112  		DeleteRobotAccountCalls: make(map[string]bool),
   113  	}
   114  	err := cleanupQuayReposAndRobots(&quayClientMock, "test-org")
   115  	if err != nil {
   116  		t.Errorf("error during quay cleanup, error: %s", err)
   117  	}
   118  
   119  	for _, repo := range deletedRepos {
   120  		if !quayClientMock.DeleteRepositoryCalls[repo.Name] {
   121  			t.Errorf("DeleteRepository() should have been called for '%s'", repo.Name)
   122  		}
   123  	}
   124  	for _, repo := range preservedRepos {
   125  		if quayClientMock.DeleteRepositoryCalls[repo.Name] {
   126  			t.Errorf("DeleteRepository() should not have been called for '%s'", repo.Name)
   127  		}
   128  	}
   129  	for _, robot := range deletedRobots {
   130  		shortName := strings.Split(robot.Name, "+")[1]
   131  		if !quayClientMock.DeleteRobotAccountCalls[shortName] {
   132  			t.Errorf("DeleteRobotAccount() should have been called for '%s'", shortName)
   133  		}
   134  	}
   135  	for _, robot := range preservedRobots {
   136  		shortName := strings.Split(robot.Name, "+")[1]
   137  		if quayClientMock.DeleteRepositoryCalls[shortName] {
   138  			t.Errorf("DeleteRobotAccount() should not have been called for '%s'", shortName)
   139  		}
   140  	}
   141  }
   142  
   143  func TestCleanupQuayTags(t *testing.T) {
   144  	testOrg := "test-org"
   145  	testRepo := "test-repo"
   146  
   147  	tagsOnPage := 20
   148  	tagPages := 20
   149  
   150  	var deletedTags []quay.Tag
   151  	var preservedTags []quay.Tag
   152  	var allTags []quay.Tag
   153  
   154  	// Randomly generate slices of deleted and preserved tags
   155  	for i := 0; i < tagsOnPage*tagPages; i++ {
   156  		tagName := fmt.Sprintf("tag%d", i)
   157  		var tag quay.Tag
   158  		if rand.Intn(2) == 0 {
   159  			tag = quay.Tag{Name: tagName, StartTS: time.Now().AddDate(0, 0, -8).Unix()}
   160  			deletedTags = append(deletedTags, tag)
   161  		} else {
   162  			tag = quay.Tag{Name: tagName, StartTS: time.Now().Unix()}
   163  			preservedTags = append(preservedTags, tag)
   164  		}
   165  		allTags = append(allTags, tag)
   166  	}
   167  
   168  	quayClientMock := QuayClientMock{
   169  		AllTags:        allTags,
   170  		DeleteTagCalls: make(map[string]bool),
   171  		TagsOnPage:     tagsOnPage,
   172  		TagPages:       tagPages,
   173  	}
   174  
   175  	err := cleanupQuayTags(&quayClientMock, testOrg, testRepo)
   176  	if err != nil {
   177  		t.Errorf("error during quay tag cleanup, error: %s", err)
   178  	}
   179  
   180  	for _, tag := range deletedTags {
   181  		if !quayClientMock.DeleteTagCalls[tag.Name] {
   182  			t.Errorf("DeleteTag() should have been called for '%s'", tag.Name)
   183  		}
   184  	}
   185  	for _, tag := range preservedTags {
   186  		if quayClientMock.DeleteTagCalls[tag.Name] {
   187  			t.Errorf("DeleteTag() should not have been called for '%s'", tag.Name)
   188  		}
   189  	}
   190  }
   191  
   192  func BenchmarkCleanupQuayTags(b *testing.B) {
   193  	testOrg := "test-org"
   194  	testRepo := "test-repo"
   195  	var allTags []quay.Tag
   196  
   197  	tagsOnPage := 20
   198  	tagPages := 20
   199  
   200  	// Randomly generate slices of deleted and preserved tags
   201  	for i := 0; i < tagsOnPage*tagPages; i++ {
   202  		tagName := fmt.Sprintf("tag%d", i)
   203  		var tag quay.Tag
   204  		if rand.Intn(2) == 0 {
   205  			tag = quay.Tag{Name: tagName, StartTS: time.Now().AddDate(0, 0, -8).Unix()}
   206  		} else {
   207  			tag = quay.Tag{Name: tagName, StartTS: time.Now().Unix()}
   208  		}
   209  		allTags = append(allTags, tag)
   210  	}
   211  
   212  	quayClientMock := QuayClientMock{
   213  		AllTags:        allTags,
   214  		DeleteTagCalls: make(map[string]bool),
   215  		TagsOnPage:     tagsOnPage,
   216  		TagPages:       tagPages,
   217  		Benchmark:      true,
   218  	}
   219  	err := cleanupQuayTags(&quayClientMock, testOrg, testRepo)
   220  	if err != nil {
   221  		b.Errorf("error during quay tag cleanup, error: %s", err)
   222  	}
   223  }