CodeSampleX

サンプル

cloud.google.com/go/longrunning v0.9.0

検証済みサンプル — golang cloud.google.com/go/longrunning v0.9.0. go 1.26 · linux debian/x64 · docker で contract を実行し、成功しました: longrunning.InternalNewOperation wraps…

sha256:2eaef92cc432e13f54e90ac8a4c59f0bf8acc656b2d86445108fef4a6636c57b

このネットワークが提供するのは一つだけです。ビルドされるサンプル。サンドボックスで実行し、署名済みの受領証を保管します。等級はつけず、何も保証しません — 同じコードがあなたの環境でビルドされるかは測定していません。 合格した契約受領証を提出した異なる署名鍵の数です。1 なら作者だけ、2 以上なら他の誰かもビルドしています。鍵は自己生成で背後に登録された身元がないため、数えているのは人ではなく鍵です。 MIT-0

実行証拠

宣言された環境と署名済みの実行を分けてあります。このサンプルが何をどこで実行したかをそのまま確認できます。

証拠の基準
署名済みコントラクト合格
検証レシート
1
ビルドした署名鍵
1
宣言された環境 linux 24 · ubuntu · glibc 2.39 x64 go

検証実行環境

環境 コントラクト ステージ 実行日
go 1.26 · linux debian/x64 · docker ed25519:c1973797be207ac4 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · golang@1golang:1.26@sha256:e30143be198a…
2026-10-14

ケース

HOW
ゴール
verify pkg:golang/cloud.google.com/go/longrunning@v0.9.0
パッケージ
作成日
2026-10-14T01:10:55Z

コントラクト

  1. longrunning.InternalNewOperation wraps a longrunningpb.Operation and exposes its Name() and initial Done() state
  2. Operation.Metadata returns longrunning.ErrNoMetadata when Metadata is nil and unmarshals anypb.Any metadata into a target protobuf message when present
  3. Operation.Poll calls GetOperation via autogen.OperationsClient, keeping Done() false while running and setting Done() true while unmarshaling the response payload upon completion
  4. Operation.Poll sets Done() true and returns the corresponding gRPC status error when an operation completes with Operation_Error
  5. Operation.Cancel and Operation.Delete dispatch CancelOperationRequest and DeleteOperationRequest for the operation name, and autogen.OperationsClient.ListOperations iterates over operations until iterator.Done

ファイル

  • PROMPT.md
  • csx.json
  • go.mod
  • go.sum
  • spec.json
  • test/contract.go

ソースアーティファクトをダウンロード (tar.gz)

ソース

PROMPT.md
Clean-room public code sample — generation instructions

Write a brand-new, minimal, self-contained code sample in this clean-room directory.
Do not copy, paraphrase, or reference any existing project source. Work only from this spec.

A csx.json manifest scaffold already exists. Do not recreate it from memory. Preserve its case.goal, packages and symbols; fill its empty case.contract with exact assertions and correct its environment, commands and verifierAdapter for the files you generate.

Goal: verify pkg:golang/cloud.google.com/go/longrunning@v0.9.0
Kind: HOW

Use EXACTLY these public packages and versions:
  - pkg:golang/cloud.google.com/go/longrunning@v0.9.0

Rules:
  - One focused purpose; the smallest project that proves the goal.
  - Include a contract test (test/contract.*) that runs OFFLINE and exits 0 exactly when the goal behavior works.
  - Pin every dependency with a lockfile so resolution is reproducible.
  - No secrets, credentials, or tokens. No real URLs (only example.com or localhost). No absolute paths.
  - No personal names, emails, company names, or project identifiers of any kind.
  - No binaries and no generated output (node_modules, dist, target, venv, .git, .env).
  - Keep it under 200 files and 256KB packed.
csx.json
{"case":{"caseId":"case:sha256:f85cb0d08c2e1b3710b91cc31f8aa548df118bf6175206254d505249a1a405bf","contract":["longrunning.InternalNewOperation wraps a longrunningpb.Operation and exposes its Name() and initial Done() state","Operation.Metadata returns longrunning.ErrNoMetadata when Metadata is nil and unmarshals anypb.Any metadata into a target protobuf message when present","Operation.Poll calls GetOperation via autogen.OperationsClient, keeping Done() false while running and setting Done() true while unmarshaling the response payload upon completion","Operation.Poll sets Done() true and returns the corresponding gRPC status error when an operation completes with Operation_Error","Operation.Cancel and Operation.Delete dispatch CancelOperationRequest and DeleteOperationRequest for the operation name, and autogen.OperationsClient.ListOperations iterates over operations until iterator.Done"],"goal":"verify pkg:golang/cloud.google.com/go/longrunning@v0.9.0","kind":"HOW","packages":["pkg:golang/cloud.google.com/go/longrunning@v0.9.0"],"schemaVersion":1},"contractCommand":["go","run","./test"],"environment":{"arch":"x64","distro":"ubuntu","ecosystem":"golang","libc":"glibc","libcVersion":"2.39","os":"linux","osVersionBucket":"24","packageManager":"go","schemaVersion":1},"license":"MIT-0","packages":["pkg:golang/cloud.google.com/go/longrunning@v0.9.0"],"schemaVersion":1,"subject":"pkg:golang/cloud.google.com/go/longrunning@v0.9.0","verifierAdapter":"golang@1"}
go.mod
module example.com/sample

go 1.25.0

require (
	cloud.google.com/go/longrunning v0.9.0
	google.golang.org/api v0.273.1
	google.golang.org/genproto/googleapis/rpc v0.0.0-20260401001100-f93e5f3e9f0f
	google.golang.org/grpc v1.79.3
	google.golang.org/protobuf v1.36.11
)

require (
	cloud.google.com/go v0.123.0 // indirect
	cloud.google.com/go/auth v0.18.2 // indirect
	cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
	cloud.google.com/go/compute/metadata v0.9.0 // indirect
	github.com/cespare/xxhash/v2 v2.3.0 // indirect
	github.com/felixge/httpsnoop v1.0.4 // indirect
	github.com/go-logr/logr v1.4.3 // indirect
	github.com/go-logr/stdr v1.2.2 // indirect
	github.com/google/s2a-go v0.1.9 // indirect
	github.com/googleapis/enterprise-certificate-proxy v0.3.14 // indirect
	github.com/googleapis/gax-go/v2 v2.20.0 // indirect
	go.opentelemetry.io/auto/sdk v1.2.1 // indirect
	go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect
	go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
	go.opentelemetry.io/otel v1.42.0 // indirect
	go.opentelemetry.io/otel/metric v1.42.0 // indirect
	go.opentelemetry.io/otel/trace v1.42.0 // indirect
	golang.org/x/crypto v0.49.0 // indirect
	golang.org/x/net v0.52.0 // indirect
	golang.org/x/oauth2 v0.36.0 // indirect
	golang.org/x/sync v0.20.0 // indirect
	golang.org/x/sys v0.42.0 // indirect
	golang.org/x/text v0.35.0 // indirect
	golang.org/x/time v0.15.0 // indirect
	google.golang.org/genproto/googleapis/api v0.0.0-20260401001100-f93e5f3e9f0f // indirect
)
go.sum
cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE=
cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU=
cloud.google.com/go/auth v0.18.2 h1:+Nbt5Ev0xEqxlNjd6c+yYUeosQ5TtEUaNcN/3FozlaM=
cloud.google.com/go/auth v0.18.2/go.mod h1:xD+oY7gcahcu7G2SG2DsBerfFxgPAJz17zz2joOFF3M=
cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs=
cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10=
cloud.google.com/go/longrunning v0.9.0 h1:0EzbDEGsAvOZNbqXopgniY0w0a1phvu5IdUFq8grmqY=
cloud.google.com/go/longrunning v0.9.0/go.mod h1:pkTz846W7bF4o2SzdWJ40Hu0Re+UoNT6Q5t+igIcb8E=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 h1:6xNmx7iTtyBRev0+D/Tv1FZd4SCg8axKApyNyRsAt/w=
github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/envoyproxy/go-control-plane v0.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA=
github.com/envoyproxy/go-control-plane/envoy v1.36.0 h1:yg/JjO5E7ubRyKX3m07GF3reDNEnfOboJ0QySbH736g=
github.com/envoyproxy/go-control-plane/envoy v1.36.0/go.mod h1:ty89S1YCCVruQAm9OtKeEkQLTb+Lkz0k8v9W0Oxsv98=
github.com/envoyproxy/protoc-gen-validate v1.3.0 h1:TvGH1wof4H33rezVKWSpqKz5NXWg5VPuZ0uONDT6eb4=
github.com/envoyproxy/protoc-gen-validate v1.3.0/go.mod h1:HvYl7zwPa5mffgyeTUHA9zHIH36nmrm7oCbo4YKoSWA=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.3.14 h1:yh8ncqsbUY4shRD5dA6RlzjJaT4hi3kII+zYw8wmLb8=
github.com/googleapis/enterprise-certificate-proxy v0.3.14/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg=
github.com/googleapis/gax-go/v2 v2.20.0 h1:NIKVuLhDlIV74muWlsMM4CcQZqN6JJ20Qcxd9YMuYcs=
github.com/googleapis/gax-go/v2 v2.20.0/go.mod h1:But/NJU6TnZsrLai/xBAQLLz+Hc7fHZJt/hsCz3Fih4=
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo=
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 h1:q4XOmH/0opmeuJtPsbFNivyl7bCt7yRBbeEm2sC/XtQ=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0/go.mod h1:snMWehoOh2wsEwnvvwtDyFCxVeDAODenXHtn5vzrKjo=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q=
go.opentelemetry.io/otel v1.42.0 h1:lSQGzTgVR3+sgJDAU/7/ZMjN9Z+vUip7leaqBKy4sho=
go.opentelemetry.io/otel v1.42.0/go.mod h1:lJNsdRMxCUIWuMlVJWzecSMuNjE7dOYyWlqOXWkdqCc=
go.opentelemetry.io/otel/metric v1.42.0 h1:2jXG+3oZLNXEPfNmnpxKDeZsFI5o4J+nz6xUlaFdF/4=
go.opentelemetry.io/otel/metric v1.42.0/go.mod h1:RlUN/7vTU7Ao/diDkEpQpnz3/92J9ko05BIwxYa2SSI=
go.opentelemetry.io/otel/sdk v1.42.0 h1:LyC8+jqk6UJwdrI/8VydAq/hvkFKNHZVIWuslJXYsDo=
go.opentelemetry.io/otel/sdk v1.42.0/go.mod h1:rGHCAxd9DAph0joO4W6OPwxjNTYWghRWmkHuGbayMts=
go.opentelemetry.io/otel/sdk/metric v1.42.0 h1:D/1QR46Clz6ajyZ3G8SgNlTJKBdGp84q9RKCAZ3YGuA=
go.opentelemetry.io/otel/sdk/metric v1.42.0/go.mod h1:Ua6AAlDKdZ7tdvaQKfSmnFTdHx37+J4ba8MwVCYM5hc=
go.opentelemetry.io/otel/trace v1.42.0 h1:OUCgIPt+mzOnaUTpOQcBiM/PLQ/Op7oq6g4LenLmOYY=
go.opentelemetry.io/otel/trace v1.42.0/go.mod h1:f3K9S+IFqnumBkKhRJMeaZeNk9epyhnCmQh/EysQCdc=
golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno=
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
google.golang.org/api v0.273.1 h1:L7G/TmpAMz0nKx/ciAVssVmWQiOF6+pOuXeKrWVsquY=
google.golang.org/api v0.273.1/go.mod h1:JbAt7mF+XVmWu6xNP8/+CTiGH30ofmCmk9nM8d8fHew=
google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7 h1:XzmzkmB14QhVhgnawEVsOn6OFsnpyxNPRY9QV01dNB0=
google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7/go.mod h1:L43LFes82YgSonw6iTXTxXUX1OlULt4AQtkik4ULL/I=
google.golang.org/genproto/googleapis/api v0.0.0-20260401001100-f93e5f3e9f0f h1:K3zPU40OFjwD5YKADLMLoiL0L7JJpBgEdLqGuCNPfp0=
google.golang.org/genproto/googleapis/api v0.0.0-20260401001100-f93e5f3e9f0f/go.mod h1:EIQZ5bFCfRQDV4MhRle7+OgjNtZ6P1PiZBgAKuxXu/Y=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401001100-f93e5f3e9f0f h1:Rka45QInERYknkHYfJEPBQaoobXl+YpxTMjAKgWUq2A=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401001100-f93e5f3e9f0f/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE=
google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
spec.json
{
  "schemaVersion": 1,
  "goal": "verify pkg:golang/cloud.google.com/go/longrunning@v0.9.0",
  "kind": "HOW",
  "packages": [
    "pkg:golang/cloud.google.com/go/longrunning@v0.9.0"
  ]
}
test/contract.go
package main

import (
	"context"
	"errors"
	"fmt"
	"net"
	"os"
	"sync"

	"cloud.google.com/go/longrunning"
	autogen "cloud.google.com/go/longrunning/autogen"
	"cloud.google.com/go/longrunning/autogen/longrunningpb"
	"google.golang.org/api/iterator"
	"google.golang.org/api/option"
	statuspb "google.golang.org/genproto/googleapis/rpc/status"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/credentials/insecure"
	"google.golang.org/grpc/status"
	"google.golang.org/protobuf/types/known/anypb"
	"google.golang.org/protobuf/types/known/emptypb"
)

type fakeOperationsServer struct {
	longrunningpb.UnimplementedOperationsServer
	mu        sync.Mutex
	pollCount int
	canceled  map[string]bool
	deleted   map[string]bool
}

func (s *fakeOperationsServer) GetOperation(_ context.Context, req *longrunningpb.GetOperationRequest) (*longrunningpb.Operation, error) {
	s.mu.Lock()
	defer s.mu.Unlock()

	switch req.GetName() {
	case "operations/success-op":
		s.pollCount++
		if s.pollCount == 1 {
			return &longrunningpb.Operation{
				Name: req.GetName(),
				Done: false,
			}, nil
		}
		respAny, err := anypb.New(&longrunningpb.OperationInfo{
			ResponseType: "CompletedResult",
			MetadataType: "CompletedMeta",
		})
		if err != nil {
			return nil, err
		}
		return &longrunningpb.Operation{
			Name:   req.GetName(),
			Done:   true,
			Result: &longrunningpb.Operation_Response{Response: respAny},
		}, nil

	case "operations/failed-op":
		return &longrunningpb.Operation{
			Name: req.GetName(),
			Done: true,
			Result: &longrunningpb.Operation_Error{
				Error: &statuspb.Status{
					Code:    int32(codes.InvalidArgument),
					Message: "invalid operation input",
				},
			},
		}, nil

	default:
		return nil, status.Errorf(codes.NotFound, "unknown operation %s", req.GetName())
	}
}

func (s *fakeOperationsServer) CancelOperation(_ context.Context, req *longrunningpb.CancelOperationRequest) (*emptypb.Empty, error) {
	s.mu.Lock()
	defer s.mu.Unlock()
	s.canceled[req.GetName()] = true
	return &emptypb.Empty{}, nil
}

func (s *fakeOperationsServer) DeleteOperation(_ context.Context, req *longrunningpb.DeleteOperationRequest) (*emptypb.Empty, error) {
	s.mu.Lock()
	defer s.mu.Unlock()
	s.deleted[req.GetName()] = true
	return &emptypb.Empty{}, nil
}

func (s *fakeOperationsServer) ListOperations(_ context.Context, req *longrunningpb.ListOperationsRequest) (*longrunningpb.ListOperationsResponse, error) {
	return &longrunningpb.ListOperationsResponse{
		Operations: []*longrunningpb.Operation{
			{Name: req.GetName() + "/op-1", Done: false},
			{Name: req.GetName() + "/op-2", Done: true},
		},
	}, nil
}

func fail(msg string, args ...any) {
	fmt.Fprintf(os.Stderr, "FAIL: "+msg+"\n", args...)
	os.Exit(1)
}

func main() {
	ctx := context.Background()

	lis, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		fail("listen: %v", err)
	}
	defer lis.Close()

	srvImpl := &fakeOperationsServer{
		canceled: make(map[string]bool),
		deleted:  make(map[string]bool),
	}
	grpcSrv := grpc.NewServer()
	longrunningpb.RegisterOperationsServer(grpcSrv, srvImpl)
	go func() {
		_ = grpcSrv.Serve(lis)
	}()
	defer grpcSrv.Stop()

	conn, err := grpc.NewClient(lis.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil {
		fail("grpc client: %v", err)
	}
	defer conn.Close()

	client, err := autogen.NewOperationsClient(ctx, option.WithGRPCConn(conn))
	if err != nil {
		fail("NewOperationsClient: %v", err)
	}
	defer client.Close()

	// 1. Metadata handling: ErrNoMetadata when absent, and unmarshaling when present.
	opNoMeta := longrunning.InternalNewOperation(client, &longrunningpb.Operation{
		Name: "operations/no-meta",
		Done: false,
	})
	if opNoMeta.Name() != "operations/no-meta" || opNoMeta.Done() {
		fail("unexpected initial Name/Done state: %q, %v", opNoMeta.Name(), opNoMeta.Done())
	}
	var metaOut longrunningpb.OperationInfo
	if err := opNoMeta.Metadata(&metaOut); !errors.Is(err, longrunning.ErrNoMetadata) {
		fail("expected ErrNoMetadata, got %v", err)
	}

	metaAny, err := anypb.New(&longrunningpb.OperationInfo{
		ResponseType: "BatchResponse",
		MetadataType: "BatchMetadata",
	})
	if err != nil {
		fail("anypb.New: %v", err)
	}
	opWithMeta := longrunning.InternalNewOperation(client, &longrunningpb.Operation{
		Name:     "operations/success-op",
		Metadata: metaAny,
		Done:     false,
	})
	if err := opWithMeta.Metadata(&metaOut); err != nil {
		fail("Metadata unmarshal failed: %v", err)
	}
	if metaOut.GetResponseType() != "BatchResponse" || metaOut.GetMetadataType() != "BatchMetadata" {
		fail("unexpected unmarshaled metadata: %+v", &metaOut)
	}

	// 2. Poll lifecycle: in-progress first, then completed with response payload.
	var respOut longrunningpb.OperationInfo
	if err := opWithMeta.Poll(ctx, &respOut); err != nil {
		fail("first Poll failed: %v", err)
	}
	if opWithMeta.Done() {
		fail("expected operation to still be in progress after first Poll")
	}

	if err := opWithMeta.Poll(ctx, &respOut); err != nil {
		fail("second Poll failed: %v", err)
	}
	if !opWithMeta.Done() {
		fail("expected operation to be Done after second Poll")
	}
	if respOut.GetResponseType() != "CompletedResult" || respOut.GetMetadataType() != "CompletedMeta" {
		fail("unexpected response payload: %+v", &respOut)
	}

	// 3. Poll on an operation that finishes with Operation_Error returns a gRPC status error.
	opFailed := longrunning.InternalNewOperation(client, &longrunningpb.Operation{
		Name: "operations/failed-op",
		Done: false,
	})
	err = opFailed.Poll(ctx, &respOut)
	if err == nil || status.Code(err) != codes.InvalidArgument {
		fail("expected InvalidArgument error from failed operation Poll, got %v", err)
	}
	if !opFailed.Done() {
		fail("expected failed operation to report Done() == true")
	}

	// 4. Cancel and Delete forward requests to the Operations service.
	if err := opWithMeta.Cancel(ctx); err != nil {
		fail("Cancel failed: %v", err)
	}
	if err := opWithMeta.Delete(ctx); err != nil {
		fail("Delete failed: %v", err)
	}
	srvImpl.mu.Lock()
	wasCanceled := srvImpl.canceled["operations/success-op"]
	wasDeleted := srvImpl.deleted["operations/success-op"]
	srvImpl.mu.Unlock()
	if !wasCanceled || !wasDeleted {
		fail("expected Cancel and Delete to be recorded on server: canceled=%v deleted=%v", wasCanceled, wasDeleted)
	}

	// 5. ListOperations iterator traverses server-returned operations until iterator.Done.
	it := client.ListOperations(ctx, &longrunningpb.ListOperationsRequest{Name: "operations"})
	var listed []string
	for {
		item, err := it.Next()
		if errors.Is(err, iterator.Done) {
			break
		}
		if err != nil {
			fail("ListOperations Next failed: %v", err)
		}
		listed = append(listed, item.GetName())
	}
	if len(listed) != 2 || listed[0] != "operations/op-1" || listed[1] != "operations/op-2" {
		fail("unexpected ListOperations result: %v", listed)
	}
}

オリジンシーダー

匿名