Repository: moby/moby
File: daemon/list_test.go (Go)

Code before:
		containerList, err := d.Containers(context.Background(), &containertypes.ListOptions{All: true})
		assert.NilError(t, err)
		assert.Assert(t, is.Len(containerList, 1))
		assert.Assert(t, is.Equal(containerList[0].Names[0], one.Name))
	})

	// test list with random number of containers
	t.Run("random", func(t *testing.T) {
		// Use constant seed for reproducibility
		randGen := rand.New(rand.NewSource(1982731263716))

		db2, err := container.NewViewDB() // new DB to ignore prior containers
		assert.NilError(t, err)
		d = &Daemon{
			containersReplica: db2,
		}

		// start a random number of containers (between 0->64)
		num := randGen.Intn(64)
		containers := make([]*container.Container, num)
		for i := range num {
			name := fmt.Sprintf("cont-%d", i)
			containers[i] = setupContainerWithName(t, name, d)
			// wait a bit to ensure container timestamps are separated enough so the
			// sort used by d.Containers() can deterministically sort them.
			time.Sleep(50 * time.Millisecond)
		}

		// list them and verify correctness
		containerList, err := d.Containers(context.Background(), &containertypes.ListOptions{All: true})
		assert.NilError(t, err)
		assert.Assert(t, is.Len(containerList, num))

		for i := range num {
			// container list should be ordered in descending creation order
			assert.Assert(t, is.Equal(containerList[i].Names[0], containers[num-1-i].Name))
		}
	})
}

func TestContainerList_InvalidFilter(t *testing.T) {
	db, err := container.NewViewDB()
	assert.NilError(t, err)
	d := &Daemon{
		containersReplica: db,
	}

	_, err = d.Containers(context.Background(), &containertypes.ListOptions{
		Filters: filters.NewArgs(filters.Arg("invalid", "foo")),
	})
	assert.Assert(t, is.Error(err, "invalid filter 'invalid'"))

Review comment (performance):
Wouldn't it be better to just override the `containers[i].Created` instead of making the test slower?

(50ms times 20 containers is 1s, that's a lot)

Code after:
			for i := range num {
				name := fmt.Sprintf("cont-%d", i)
				containers[i] = setupContainerWithName(t, name, d)
				// ensure container timestamps are separated enough so the
				// sort used by d.Containers() can deterministically sort them.
				if i > 0 {
					containers[i].Created = containers[i-1].Created.Add(time.Millisecond)
				}
			}

			// list them and verify correctness
			containerList, err := d.Containers(context.Background(), &containertypes.ListOptions{All: true})
			assert.NilError(t, err)
			assert.Assert(t, is.Len(containerList, num))

			for i := range num {
				// container list should be ordered in descending creation order
				assert.Assert(t, is.Equal(containerList[i].Names[0], containers[num-1-i].Name))
			}
		})
	}
}

func TestContainerList_InvalidFilter(t *testing.T) {
	db, err := container.NewViewDB()
	assert.NilError(t, err)
	d := &Daemon{
		containersReplica: db,
	}

	_, err = d.Containers(context.Background(), &containertypes.ListOptions{
		Filters: filters.NewArgs(filters.Arg("invalid", "foo")),
	})
	assert.Assert(t, is.Error(err, "invalid filter 'invalid'"))
}

func TestContainerList_NameFilter(t *testing.T) {
	db, err := container.NewViewDB()
	assert.NilError(t, err)
	d := &Daemon{
		containersReplica: db,
	}

	var (
		one   = setupContainerWithName(t, "a1", d)
		two   = setupContainerWithName(t, "a2", d)
		three = setupContainerWithName(t, "b1", d)
	)

	// moby/moby #37453 - ^ regex not working due to prefix slash
	// not being stripped