Compare commits

..

1 Commits

Author SHA1 Message Date
André Roth d5f1929dd1 tests: add api repo edit test 2026-05-26 00:32:47 +02:00
4 changed files with 52 additions and 42 deletions
-7
View File
@@ -182,13 +182,6 @@ func apiSnapshotsCreate(c *gin.Context) {
resources = append(resources, string(sources[i].ResourceKey()))
}
// Pre-task check for destination snapshot name
_, err = snapshotCollection.ByName(b.Name)
if err == nil {
AbortWithJSONError(c, 409, fmt.Errorf("unable to create: snapshot %s already exists", b.Name))
return
}
maybeRunTaskInBackground(c, "Create snapshot "+b.Name, resources, func(_ aptly.Progress, _ *task.Detail) (*task.ProcessReturnValue, error) {
// Phase 2: Inside task lock - create fresh factory
taskCollectionFactory := context.NewCollectionFactory()
+31
View File
@@ -461,3 +461,34 @@ class ReposAPITestCopyPackage(APITest):
self.check_equal(self.get(f"/api/repos/{repo2_name}/packages").json(),
['Pi386 libboost-program-options-dev 1.49.0.1 918d2f433384e378'])
class ReposAPITestCreateEdit(APITest):
"""
POST /api/repos,
"""
def check(self):
repo_name = self.random_name() + ' with space'
repo_desc = {'Comment': 'fun repo',
'DefaultComponent': 'contrib',
'DefaultDistribution': 'bookworm',
'Name': repo_name}
resp = self.post("/api/repos", json=repo_desc)
self.check_equal(resp.json(), repo_desc)
self.check_equal(resp.status_code, 201)
repo_desc = {'Comment': 'modified repo',
'DefaultComponent': 'main',
'DefaultDistribution': 'trixie',
'Name': repo_name + '@renamed'}
resp = self.put(f"/api/repos/{repo_name}", json=repo_desc)
self.check_equal(resp.json(), repo_desc)
self.check_equal(resp.status_code, 200)
resp = self.get("/api/repos/" + repo_name + '@renamed')
self.check_equal(resp.json(), repo_desc)
self.check_equal(resp.status_code, 200)
resp = self.delete("/api/repos/" + repo_name + '@renamed')
self.check_equal(resp.status_code, 200)
+21 -34
View File
@@ -44,27 +44,25 @@ func (list *List) consumer() {
for {
select {
case task := <-list.queue:
// Set task state to RUNNING before processing
list.Lock()
task.State = RUNNING
{
task.State = RUNNING
}
list.Unlock()
go func() {
retValue, err := task.process(aptly.Progress(task.output), task.detail)
// Update task completion state and cleanup with list lock held
list.Lock()
{
task.processReturnValue = retValue
task.err = err
if err != nil {
task.output.Printf("Task failed with error: %v", err)
task.State = FAILED
task.err = err
task.processReturnValue = retValue
} else {
task.output.Print("Task succeeded")
task.State = SUCCEEDED
task.err = nil
task.processReturnValue = retValue
}
list.usedResources.Free(task.resources)
@@ -107,15 +105,13 @@ func (list *List) Stop() {
// GetTasks gets complete list of tasks
func (list *List) GetTasks() []Task {
list.Lock()
defer list.Unlock()
tasks := []Task{}
list.Lock()
for _, task := range list.tasks {
// Copy task while holding list lock
tasks = append(tasks, *task)
}
list.Unlock()
return tasks
}
@@ -143,11 +139,11 @@ func (list *List) DeleteTaskByID(ID int) (Task, error) {
// GetTaskByID returns task with given id
func (list *List) GetTaskByID(ID int) (Task, error) {
list.Lock()
defer list.Unlock()
tasks := list.tasks
list.Unlock()
for _, task := range list.tasks {
for _, task := range tasks {
if task.ID == ID {
// Copy task while holding list lock
return *task, nil
}
}
@@ -184,16 +180,13 @@ func (list *List) GetTaskDetailByID(ID int) (interface{}, error) {
// GetTaskReturnValueByID returns process return value of task with given id
func (list *List) GetTaskReturnValueByID(ID int) (*ProcessReturnValue, error) {
list.Lock()
defer list.Unlock()
task, err := list.GetTaskByID(ID)
for _, task := range list.tasks {
if task.ID == ID {
return task.processReturnValue, nil
}
if err != nil {
return nil, err
}
return nil, fmt.Errorf("could not find task with id %v", ID)
return task.processReturnValue, nil
}
// RunTaskInBackground creates task and runs it in background. This will block until the necessary resources
@@ -211,10 +204,6 @@ func (list *List) RunTaskInBackground(name string, resources []string, process P
list.wg.Add(1)
task.wgTask.Add(1)
// Copy task while still holding the lock to avoid racing with consumer
// setting State=RUNNING after receiving from queue
taskCopy := *task
// add task to queue for processing if resources are available
// if not, task will be queued by the consumer once resources are available
tasks := list.usedResources.UsedBy(resources)
@@ -227,13 +216,12 @@ func (list *List) RunTaskInBackground(name string, resources []string, process P
list.Unlock()
}
return taskCopy, nil
return *task, nil
}
// Clear removes finished tasks from list
func (list *List) Clear() {
list.Lock()
defer list.Unlock()
var tasks []*Task
for _, task := range list.tasks {
@@ -242,6 +230,8 @@ func (list *List) Clear() {
}
}
list.tasks = tasks
list.Unlock()
}
// Wait waits till all tasks are processed
@@ -264,14 +254,11 @@ func (list *List) WaitForTaskByID(ID int) (Task, error) {
// GetTaskErrorByID returns the Task error for a given id
func (list *List) GetTaskErrorByID(ID int) (error, error) {
list.Lock()
defer list.Unlock()
task, err := list.GetTaskByID(ID)
for _, task := range list.tasks {
if task.ID == ID {
return task.err, nil
}
if err != nil {
return nil, err
}
return nil, fmt.Errorf("could not find task with id %v", ID)
return task.err, nil
}
-1
View File
@@ -42,7 +42,6 @@ const (
)
// Task represents as task in a queue encapsulates process code
// All fields are protected by List.Mutex - access task fields only while holding list.Lock()
type Task struct {
output *Output
detail *Detail