@@ -1578,3 +1578,105 @@ func TestShimSockLength(t *testing.T) {
15781578
15791579 <- statusC
15801580}
1581+
1582+ func TestContainerExecLargeOutputWithTTY (t * testing.T ) {
1583+ t .Parallel ()
1584+
1585+ client , err := newClient (t , address )
1586+ if err != nil {
1587+ t .Fatal (err )
1588+ }
1589+ defer client .Close ()
1590+
1591+ var (
1592+ image Image
1593+ ctx , cancel = testContext (t )
1594+ id = t .Name ()
1595+ )
1596+ defer cancel ()
1597+
1598+ image , err = client .GetImage (ctx , testImage )
1599+ if err != nil {
1600+ t .Fatal (err )
1601+ }
1602+
1603+ container , err := client .NewContainer (ctx , id , WithNewSnapshot (id , image ), WithNewSpec (oci .WithImageConfig (image ), withProcessArgs ("sleep" , "999" )))
1604+ if err != nil {
1605+ t .Fatal (err )
1606+ }
1607+ defer container .Delete (ctx , WithSnapshotCleanup )
1608+
1609+ task , err := container .NewTask (ctx , empty ())
1610+ if err != nil {
1611+ t .Fatal (err )
1612+ }
1613+ defer task .Delete (ctx )
1614+
1615+ finishedC , err := task .Wait (ctx )
1616+ if err != nil {
1617+ t .Fatal (err )
1618+ }
1619+
1620+ if err := task .Start (ctx ); err != nil {
1621+ t .Fatal (err )
1622+ }
1623+
1624+ for i := 0 ; i < 100 ; i ++ {
1625+ spec , err := container .Spec (ctx )
1626+ if err != nil {
1627+ t .Fatal (err )
1628+ }
1629+
1630+ // start an exec process without running the original container process info
1631+ processSpec := spec .Process
1632+ withExecArgs (processSpec , "sh" , "-c" , `seq -s " " 1000000` )
1633+
1634+ stdout := bytes .NewBuffer (nil )
1635+
1636+ execID := t .Name () + "_exec"
1637+ process , err := task .Exec (ctx , execID , processSpec , cio .NewCreator (withByteBuffers (stdout ), withProcessTTY ()))
1638+ if err != nil {
1639+ t .Fatal (err )
1640+ }
1641+ processStatusC , err := process .Wait (ctx )
1642+ if err != nil {
1643+ t .Fatal (err )
1644+ }
1645+
1646+ if err := process .Start (ctx ); err != nil {
1647+ t .Fatal (err )
1648+ }
1649+
1650+ // wait for the exec to return
1651+ status := <- processStatusC
1652+ code , _ , err := status .Result ()
1653+ if err != nil {
1654+ t .Fatal (err )
1655+ }
1656+
1657+ if code != 0 {
1658+ t .Errorf ("expected exec exit code 0 but received %d" , code )
1659+ }
1660+ if _ , err := process .Delete (ctx ); err != nil {
1661+ t .Fatal (err )
1662+ }
1663+
1664+ const expectedSuffix = "999999 1000000"
1665+ stdoutString := stdout .String ()
1666+ if ! strings .Contains (stdoutString , expectedSuffix ) {
1667+ t .Fatalf ("process output does not end with %q at iteration %d, here are the last 20 characters of the output:\n \n %q" , expectedSuffix , i , stdoutString [len (stdoutString )- 20 :])
1668+ }
1669+
1670+ }
1671+
1672+ if err := task .Kill (ctx , syscall .SIGKILL ); err != nil {
1673+ t .Error (err )
1674+ }
1675+ <- finishedC
1676+ }
1677+
1678+ func withProcessTTY () cio.Opt {
1679+ return func (opt * cio.Streams ) {
1680+ cio .WithTerminal (opt )
1681+ }
1682+ }
0 commit comments