@@ -21,14 +21,17 @@ import (
2121 "path/filepath"
2222 "sync"
2323 "testing"
24+ "time"
2425
2526 "github.com/containerd/containerd"
27+ "github.com/containerd/containerd/content"
2628 "github.com/containerd/containerd/log/logtest"
2729 "github.com/containerd/containerd/pkg/cri/constants"
2830 "github.com/containerd/containerd/platforms"
2931 "github.com/containerd/containerd/plugin"
3032 ctrdsrv "github.com/containerd/containerd/services/server"
3133 srvconfig "github.com/containerd/containerd/services/server/config"
34+ "github.com/opencontainers/go-digest"
3235
3336 _ "github.com/containerd/containerd/diff/walking/plugin"
3437 "github.com/containerd/containerd/events/exchange"
5962 loadedPluginsErr error
6063)
6164
65+ type tweakPluginInitFunc func (t * testing.T , p * plugin.Registration ) * plugin.Registration
66+
6267// buildLocalContainerdClient is to return containerd client with initialized
6368// core plugins in local.
64- func buildLocalContainerdClient (t * testing.T , tmpDir string ) * containerd.Client {
69+ func buildLocalContainerdClient (t * testing.T , tmpDir string , tweakInitFn tweakPluginInitFunc ) * containerd.Client {
6570 ctx := logtest .WithT (context .Background (), t )
6671
6772 // load plugins
@@ -107,6 +112,10 @@ func buildLocalContainerdClient(t *testing.T, tmpDir string) *containerd.Client
107112 initContext .Config = pc
108113 }
109114
115+ if tweakInitFn != nil {
116+ p = tweakInitFn (t , p )
117+ }
118+
110119 result := p .Init (initContext )
111120 assert .NoError (t , initialized .Add (result ))
112121
@@ -126,3 +135,61 @@ func buildLocalContainerdClient(t *testing.T, tmpDir string) *containerd.Client
126135
127136 return client
128137}
138+
139+ func tweakContentInitFnWithDelayer (commitDelayDuration time.Duration ) tweakPluginInitFunc {
140+ return func (t * testing.T , p * plugin.Registration ) * plugin.Registration {
141+ if p .URI () != "io.containerd.content.v1.content" {
142+ return p
143+ }
144+
145+ oldInitFn := p .InitFn
146+ p .InitFn = func (ic * plugin.InitContext ) (interface {}, error ) {
147+ instance , err := oldInitFn (ic )
148+ if err != nil {
149+ return nil , err
150+ }
151+
152+ return & contentStoreDelayer {
153+ t : t ,
154+
155+ Store : instance .(content.Store ),
156+ commitDelayDuration : commitDelayDuration ,
157+ }, nil
158+ }
159+ return p
160+ }
161+ }
162+
163+ type contentStoreDelayer struct {
164+ t * testing.T
165+
166+ content.Store
167+ commitDelayDuration time.Duration
168+ }
169+
170+ func (cs * contentStoreDelayer ) Writer (ctx context.Context , opts ... content.WriterOpt ) (content.Writer , error ) {
171+ w , err := cs .Store .Writer (ctx , opts ... )
172+ if err != nil {
173+ return nil , err
174+ }
175+
176+ return & contentWriterDelayer {
177+ t : cs .t ,
178+
179+ Writer : w ,
180+ commitDelayDuration : cs .commitDelayDuration ,
181+ }, nil
182+ }
183+
184+ type contentWriterDelayer struct {
185+ t * testing.T
186+
187+ content.Writer
188+ commitDelayDuration time.Duration
189+ }
190+
191+ func (w * contentWriterDelayer ) Commit (ctx context.Context , size int64 , expected digest.Digest , opts ... content.Opt ) error {
192+ w .t .Logf ("[testcase: %s] Commit %v blob after %v" , w .t .Name (), expected , w .commitDelayDuration )
193+ time .Sleep (w .commitDelayDuration )
194+ return w .Writer .Commit (ctx , size , expected , opts ... )
195+ }
0 commit comments