1717package compose
1818
1919import (
20+ "bytes"
21+ "encoding/binary"
22+ "errors"
2023 "io"
2124 "strings"
2225 "sync"
2326 "testing"
2427
2528 "github.com/compose-spec/compose-go/v2/types"
26- "github.com/docker/docker /pkg/stdcopy"
29+ "github.com/moby/moby/api /pkg/stdcopy"
2730 containerType "github.com/moby/moby/api/types/container"
2831 "github.com/moby/moby/client"
2932 "go.uber.org/mock/gomock"
@@ -33,6 +36,56 @@ import (
3336 compose "github.com/docker/compose/v5/pkg/api"
3437)
3538
39+ // newStdWriter is copied from github.com/moby/moby/daemon/internal/stdcopymux
40+ // because NewStdWriter was moved to a daemon-internal package in moby v2 and
41+ // is no longer publicly importable. We need it in tests to produce multiplexed
42+ // streams that stdcopy.StdCopy can demultiplex.
43+
44+ const (
45+ stdWriterPrefixLen = 8
46+ stdWriterFdIndex = 0
47+ stdWriterSizeIndex = 4
48+ )
49+
50+ var bufPool = & sync.Pool {New : func () any { return bytes .NewBuffer (nil ) }}
51+
52+ type stdWriter struct {
53+ io.Writer
54+ prefix byte
55+ }
56+
57+ func (w * stdWriter ) Write (p []byte ) (int , error ) {
58+ if w == nil || w .Writer == nil {
59+ return 0 , errors .New ("writer not instantiated" )
60+ }
61+ if p == nil {
62+ return 0 , nil
63+ }
64+
65+ header := [stdWriterPrefixLen ]byte {stdWriterFdIndex : w .prefix }
66+ binary .BigEndian .PutUint32 (header [stdWriterSizeIndex :], uint32 (len (p )))
67+ buf := bufPool .Get ().(* bytes.Buffer )
68+ buf .Write (header [:])
69+ buf .Write (p )
70+
71+ n , err := w .Writer .Write (buf .Bytes ())
72+ n -= stdWriterPrefixLen
73+ if n < 0 {
74+ n = 0
75+ }
76+
77+ buf .Reset ()
78+ bufPool .Put (buf )
79+ return n , err
80+ }
81+
82+ func newStdWriter (w io.Writer , streamType stdcopy.StdType ) io.Writer {
83+ return & stdWriter {
84+ Writer : w ,
85+ prefix : byte (streamType ),
86+ }
87+ }
88+
3689func TestComposeService_Logs_Demux (t * testing.T ) {
3790 mockCtrl := gomock .NewController (t )
3891 defer mockCtrl .Finish ()
@@ -68,8 +121,8 @@ func TestComposeService_Logs_Demux(t *testing.T) {
68121 _ = c1Reader .Close ()
69122 _ = c1Writer .Close ()
70123 })
71- c1Stdout := stdcopy . NewStdWriter (c1Writer , stdcopy .Stdout )
72- c1Stderr := stdcopy . NewStdWriter (c1Writer , stdcopy .Stderr )
124+ c1Stdout := newStdWriter (c1Writer , stdcopy .Stdout )
125+ c1Stderr := newStdWriter (c1Writer , stdcopy .Stderr )
73126 go func () {
74127 _ , err := c1Stdout .Write ([]byte ("hello stdout\n " ))
75128 assert .NilError (t , err , "Writing to fake stdout" )
0 commit comments