Skip to content

Commit c04c107

Browse files
SarahFrenchradeksimko
authored andcommitted
[WIP] - Testing ReadStateBytes and WriteStateBytes (#37464)
* Fix nil pointer error * Add WIP test for ReadStateBytes * Move test mock to separate testing file * Update mock to send unexpected EOF when there's a problem returning data and it's not a true EOF * Add test case for when length != expected length * Add test for when trying to read state from a store type that doesn't exist * Change symbol names to lowercase * Add ability to force a diagnostic to be returned from `mockReadStateBytesClient`'s `Recv` method * Add test showing error diagnostics raised by the ReadStateBytes client are returned * Add missing header * Simplify mock by using an embedded type * Rename `mockOpts` to `mockReadStateBytesOpts` * Update existing tests to assert what arguments are passed to the RPC method call * Add mock WriteStateBytesClient which uses `go.uber.org/mock/gomock` to enable assertions about calls to Send * Add a test for WriteStateBytes that makes assertions about calls to the Send method * Update test case to explicitly test writing data smaller than the chunk size * Implement chunking in WriteStateBytes, add test case to assert expected chunking behaviour * Add generated mock for Provider_WriteStateBytesClient in protocol v6 * Update tests to use new `MockProvider_WriteStateBytesClient`, remove handwritten mock * Update code comments in test * Add tests for diagnostics and errors returned during WriteStateBytes * Add generated mock for Provider_ReadStateBytesClient in protocol v6, replace old mock * Add test case for grpc errors in ReadStateBytes, fix how error is returned * Typo in comment * Add missing warning test, rename some test cases
1 parent 40da592 commit c04c107

File tree

4 files changed

+899
-26
lines changed

4 files changed

+899
-26
lines changed

internal/plugin6/grpc_provider.go

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1550,7 +1550,7 @@ func (p *GRPCProvider) ReadStateBytes(r providers.ReadStateBytesRequest) (resp p
15501550
return resp
15511551
}
15521552

1553-
var buf *bytes.Buffer
1553+
buf := &bytes.Buffer{}
15541554
var expectedTotalLength int
15551555
for {
15561556
chunk, err := client.Recv()
@@ -1559,7 +1559,7 @@ func (p *GRPCProvider) ReadStateBytes(r providers.ReadStateBytesRequest) (resp p
15591559
break
15601560
}
15611561
if err != nil {
1562-
resp.Diagnostics = resp.Diagnostics.Append(err)
1562+
resp.Diagnostics = resp.Diagnostics.Append(grpcErr(err))
15631563
break
15641564
}
15651565
resp.Diagnostics = resp.Diagnostics.Append(convert.ProtoToDiagnostics(chunk.Diagnostics))
@@ -1616,39 +1616,52 @@ func (p *GRPCProvider) WriteStateBytes(r providers.WriteStateBytesRequest) (resp
16161616
// TODO: Configurable chunk size
16171617
chunkSize := 4 * 1_000_000 // 4MB
16181618

1619-
if len(r.Bytes) < chunkSize {
1619+
client, err := p.client.WriteStateBytes(ctx)
1620+
if err != nil {
1621+
resp.Diagnostics = resp.Diagnostics.Append(grpcErr(err))
1622+
return resp
1623+
}
1624+
1625+
buf := bytes.NewBuffer(r.Bytes)
1626+
var totalLength int64 = int64(len(r.Bytes))
1627+
var totalBytesProcessed int
1628+
for {
1629+
chunk := buf.Next(chunkSize)
1630+
1631+
if len(chunk) == 0 {
1632+
// The previous iteration read the last of the data. Now we finish up.
1633+
protoResp, err := client.CloseAndRecv()
1634+
if err != nil {
1635+
resp.Diagnostics = resp.Diagnostics.Append(grpcErr(err))
1636+
return resp
1637+
}
1638+
resp.Diagnostics = resp.Diagnostics.Append(convert.ProtoToDiagnostics(protoResp.Diagnostics))
1639+
if resp.Diagnostics.HasErrors() {
1640+
return resp
1641+
}
1642+
break
1643+
}
1644+
1645+
// There is more data to write
16201646
protoReq := &proto6.WriteStateBytes_RequestChunk{
16211647
TypeName: r.TypeName,
16221648
StateId: r.StateId,
1623-
Bytes: r.Bytes,
1624-
TotalLength: int64(len(r.Bytes)),
1649+
Bytes: chunk,
1650+
TotalLength: totalLength,
16251651
Range: &proto6.StateRange{
1626-
Start: 0,
1627-
End: int64(len(r.Bytes)),
1652+
Start: int64(totalBytesProcessed),
1653+
End: int64(totalBytesProcessed + len(chunk)),
16281654
},
16291655
}
1630-
client, err := p.client.WriteStateBytes(ctx)
1631-
if err != nil {
1632-
resp.Diagnostics = resp.Diagnostics.Append(grpcErr(err))
1633-
return resp
1634-
}
16351656
err = client.Send(protoReq)
16361657
if err != nil {
16371658
resp.Diagnostics = resp.Diagnostics.Append(grpcErr(err))
16381659
return resp
16391660
}
1640-
protoResp, err := client.CloseAndRecv()
1641-
if err != nil {
1642-
resp.Diagnostics = resp.Diagnostics.Append(grpcErr(err))
1643-
return resp
1644-
}
1645-
resp.Diagnostics = resp.Diagnostics.Append(convert.ProtoToDiagnostics(protoResp.Diagnostics))
1646-
if resp.Diagnostics.HasErrors() {
1647-
return resp
1648-
}
1649-
}
16501661

1651-
// TODO: implement chunking for state files larger than chunkSize
1662+
// Track progress before next iteration
1663+
totalBytesProcessed += len(chunk)
1664+
}
16521665

16531666
return resp
16541667
}

0 commit comments

Comments
 (0)