From 8fbbc0d7c1ae81e9314a83673a9996c52ec1f5da Mon Sep 17 00:00:00 2001 From: Boshi Lian Date: Wed, 16 Jan 2019 21:47:37 +0000 Subject: [PATCH] dep 0.5 prune --- Gopkg.lock | 219 +- Gopkg.toml | 5 + vendor/cloud.google.com/go/CHANGES.md | 1024 --- vendor/cloud.google.com/go/CODE_OF_CONDUCT.md | 44 - vendor/cloud.google.com/go/CONTRIBUTING.md | 234 - vendor/cloud.google.com/go/README.md | 505 -- vendor/cloud.google.com/go/RELEASING.md | 47 - .../cloud.google.com/go/authexample_test.go | 73 - .../cloud.google.com/go/civil/civil_test.go | 442 - vendor/cloud.google.com/go/cloud.go | 79 - vendor/cloud.google.com/go/examples_test.go | 60 - vendor/cloud.google.com/go/issue_template.md | 17 - vendor/cloud.google.com/go/keys.tar.enc | Bin 10256 -> 0 bytes vendor/cloud.google.com/go/license_test.go | 74 - vendor/cloud.google.com/go/old-news.md | 698 -- vendor/cloud.google.com/go/regen-gapic.sh | 86 - vendor/cloud.google.com/go/run-tests.sh | 88 - .../exporter/ocagent/CONTRIBUTING.md | 24 - .../exporter/ocagent/README.md | 61 - .../exporter/ocagent/example_test.go | 46 - .../exporter/ocagent/go.mod | 9 - .../exporter/ocagent/go.sum | 44 - .../exporter/ocagent/mock_agent_test.go | 218 - .../exporter/ocagent/ocagent_test.go | 329 - .../exporter/ocagent/transform_spans_test.go | 166 - .../Azure/azure-sdk-for-go/CHANGELOG.md | 1337 --- .../Azure/azure-sdk-for-go/CODEOWNERS | 12 - .../Azure/azure-sdk-for-go/CONTRIBUTING.md | 17 - .../Azure/azure-sdk-for-go/Gopkg.lock | 384 - .../Azure/azure-sdk-for-go/Gopkg.toml | 61 - .../Azure/azure-sdk-for-go/README.md | 505 -- .../github.com/Azure/azure-sdk-for-go/doc.go | 26 - .../azure-sdk-for-go/findTestedPackages.sh | 1 - .../Azure/azure-sdk-for-go/rungas.sh | 15 - .../swagger_to_sdk_config.json | 27 - .../github.com/Azure/go-autorest/CHANGELOG.md | 728 -- .../github.com/Azure/go-autorest/GNUmakefile | 23 - .../github.com/Azure/go-autorest/Gopkg.lock | 247 - .../github.com/Azure/go-autorest/Gopkg.toml | 45 - vendor/github.com/Azure/go-autorest/README.md | 149 - .../Azure/go-autorest/autorest/adal/README.md | 292 - .../go-autorest/autorest/adal/config_test.go | 95 - .../autorest/adal/devicetoken_test.go | 330 - .../go-autorest/autorest/adal/persist_test.go | 171 - .../go-autorest/autorest/adal/token_test.go | 929 --- .../autorest/authorization_test.go | 230 - .../go-autorest/autorest/autorest_test.go | 140 - .../go-autorest/autorest/azure/async_test.go | 1156 --- .../go-autorest/autorest/azure/azure_test.go | 668 -- .../autorest/azure/environments_test.go | 348 - .../go-autorest/autorest/azure/rp_test.go | 169 - .../Azure/go-autorest/autorest/client_test.go | 415 - .../go-autorest/autorest/date/date_test.go | 237 - .../go-autorest/autorest/date/time_test.go | 277 - .../autorest/date/timerfc1123_test.go | 226 - .../autorest/date/unixtime_test.go | 283 - .../Azure/go-autorest/autorest/error_test.go | 202 - .../go-autorest/autorest/preparer_test.go | 802 -- .../go-autorest/autorest/responder_test.go | 665 -- .../Azure/go-autorest/autorest/sender_test.go | 954 --- .../go-autorest/autorest/to/convert_test.go | 234 - .../go-autorest/autorest/utility_test.go | 462 - .../autorest/validation/validation_test.go | 2450 ------ .../Azure/go-autorest/logger/logger_test.go | 185 - .../Azure/go-autorest/tracing/tracing_test.go | 155 - .../opencensus-proto/CONTRIBUTING.md | 26 - .../opencensus-proto/README.md | 80 - .../opencensus-proto/RELEASING.md | 190 - .../opencensus-proto/build.gradle | 170 - .../opencensus-proto/gradlew | 172 - .../opencensus-proto/gradlew.bat | 84 - .../opencensus-proto/settings.gradle | 1 - .../denisenkom/go-mssqldb/README.md | 215 - .../denisenkom/go-mssqldb/appveyor.yml | 48 - .../denisenkom/go-mssqldb/buf_test.go | 284 - .../denisenkom/go-mssqldb/bulkcopy_test.go | 237 - .../denisenkom/go-mssqldb/decimal_test.go | 107 - .../go-mssqldb/error_example_test.go | 38 - .../denisenkom/go-mssqldb/mssql_test.go | 39 - .../denisenkom/go-mssqldb/ntlm_test.go | 76 - .../denisenkom/go-mssqldb/parser_test.go | 60 - .../go-mssqldb/queries_go110_test.go | 189 - .../go-mssqldb/queries_go19_test.go | 856 -- .../denisenkom/go-mssqldb/queries_test.go | 2186 ----- .../denisenkom/go-mssqldb/tds_test.go | 522 -- .../denisenkom/go-mssqldb/types_test.go | 123 - .../go-mssqldb/uniqueidentifier_test.go | 70 - .../dgrijalva/jwt-go/MIGRATION_GUIDE.md | 97 - vendor/github.com/dgrijalva/jwt-go/README.md | 100 - .../dgrijalva/jwt-go/VERSION_HISTORY.md | 118 - .../github.com/dgrijalva/jwt-go/ecdsa_test.go | 100 - .../dgrijalva/jwt-go/example_test.go | 114 - .../dgrijalva/jwt-go/hmac_example_test.go | 66 - .../github.com/dgrijalva/jwt-go/hmac_test.go | 91 - .../dgrijalva/jwt-go/http_example_test.go | 216 - .../github.com/dgrijalva/jwt-go/none_test.go | 72 - .../dgrijalva/jwt-go/parser_test.go | 301 - .../dgrijalva/jwt-go/rsa_pss_test.go | 96 - .../github.com/dgrijalva/jwt-go/rsa_test.go | 185 - .../go-sql-driver/mysql/CHANGELOG.md | 178 - .../go-sql-driver/mysql/CONTRIBUTING.md | 23 - .../github.com/go-sql-driver/mysql/README.md | 490 -- .../go-sql-driver/mysql/auth_test.go | 1330 --- .../mysql/benchmark_go18_test.go | 93 - .../go-sql-driver/mysql/benchmark_test.go | 242 - .../mysql/connection_go18_test.go | 59 - .../go-sql-driver/mysql/connection_test.go | 67 - .../go-sql-driver/mysql/driver_go18_test.go | 806 -- .../go-sql-driver/mysql/driver_test.go | 2075 ----- .../go-sql-driver/mysql/dsn_test.go | 331 - .../go-sql-driver/mysql/errors_test.go | 42 - .../go-sql-driver/mysql/packets_test.go | 336 - .../go-sql-driver/mysql/statement_test.go | 126 - .../go-sql-driver/mysql/utils_go18_test.go | 57 - .../go-sql-driver/mysql/utils_test.go | 292 - vendor/github.com/gokyle/sshkey/README | 22 - vendor/github.com/gokyle/sshkey/TODO | 2 - .../github.com/gokyle/sshkey/sshkey_test.go | 108 - vendor/github.com/golang/protobuf/Makefile | 50 - vendor/github.com/golang/protobuf/README.md | 281 - .../golang/protobuf/proto/all_test.go | 2492 ------ .../golang/protobuf/proto/any_test.go | 300 - .../golang/protobuf/proto/clone_test.go | 390 - .../golang/protobuf/proto/decode_test.go | 255 - .../golang/protobuf/proto/discard_test.go | 170 - .../golang/protobuf/proto/encode_test.go | 85 - .../golang/protobuf/proto/equal_test.go | 244 - .../golang/protobuf/proto/extensions_test.go | 688 -- .../golang/protobuf/proto/map_test.go | 70 - .../golang/protobuf/proto/message_set_test.go | 77 - .../golang/protobuf/proto/proto3_test.go | 151 - .../golang/protobuf/proto/size2_test.go | 63 - .../golang/protobuf/proto/size_test.go | 191 - .../golang/protobuf/proto/text_parser_test.go | 706 -- .../golang/protobuf/proto/text_test.go | 518 -- .../golang/protobuf/ptypes/any/any.proto | 149 - .../golang/protobuf/ptypes/any_test.go | 154 - .../protobuf/ptypes/duration/duration.proto | 117 - .../golang/protobuf/ptypes/duration_test.go | 121 - .../protobuf/ptypes/timestamp/timestamp.proto | 133 - .../golang/protobuf/ptypes/timestamp_test.go | 153 - .../protobuf/ptypes/wrappers/wrappers.proto | 118 - .../github.com/golang/protobuf/regenerate.sh | 53 - vendor/github.com/jessevdk/go-flags/README.md | 134 - .../github.com/jessevdk/go-flags/arg_test.go | 163 - .../jessevdk/go-flags/assert_test.go | 177 - .../jessevdk/go-flags/check_crosscompile.sh | 16 - .../jessevdk/go-flags/command_test.go | 582 -- .../jessevdk/go-flags/completion_test.go | 315 - .../jessevdk/go-flags/convert_test.go | 159 - .../jessevdk/go-flags/example_test.go | 110 - .../jessevdk/go-flags/group_test.go | 255 - .../github.com/jessevdk/go-flags/help_test.go | 538 -- .../github.com/jessevdk/go-flags/ini_test.go | 1053 --- .../github.com/jessevdk/go-flags/long_test.go | 85 - .../jessevdk/go-flags/marshal_test.go | 119 - .../jessevdk/go-flags/options_test.go | 45 - .../jessevdk/go-flags/parser_test.go | 612 -- .../jessevdk/go-flags/pointer_test.go | 164 - .../jessevdk/go-flags/short_test.go | 234 - .../github.com/jessevdk/go-flags/tag_test.go | 38 - .../jessevdk/go-flags/unknown_test.go | 66 - vendor/github.com/jinzhu/gorm/README.md | 40 - .../jinzhu/gorm/association_test.go | 1050 --- .../jinzhu/gorm/callback_system_test.go | 112 - .../github.com/jinzhu/gorm/callbacks_test.go | 177 - vendor/github.com/jinzhu/gorm/create_test.go | 231 - .../jinzhu/gorm/customize_column_test.go | 346 - vendor/github.com/jinzhu/gorm/delete_test.go | 91 - .../github.com/jinzhu/gorm/docker-compose.yml | 30 - .../jinzhu/gorm/embedded_struct_test.go | 91 - vendor/github.com/jinzhu/gorm/errors_test.go | 20 - vendor/github.com/jinzhu/gorm/field_test.go | 67 - .../github.com/jinzhu/gorm/join_table_test.go | 117 - vendor/github.com/jinzhu/gorm/main_test.go | 1108 --- .../github.com/jinzhu/gorm/migration_test.go | 540 -- .../jinzhu/gorm/multi_primary_keys_test.go | 381 - vendor/github.com/jinzhu/gorm/naming_test.go | 69 - vendor/github.com/jinzhu/gorm/pointer_test.go | 84 - .../jinzhu/gorm/polymorphic_test.go | 366 - vendor/github.com/jinzhu/gorm/preload_test.go | 1700 ---- vendor/github.com/jinzhu/gorm/query_test.go | 773 -- vendor/github.com/jinzhu/gorm/scaner_test.go | 139 - vendor/github.com/jinzhu/gorm/scope_test.go | 80 - vendor/github.com/jinzhu/gorm/search_test.go | 30 - vendor/github.com/jinzhu/gorm/test_all.sh | 5 - vendor/github.com/jinzhu/gorm/update_test.go | 465 -- vendor/github.com/jinzhu/gorm/wercker.yml | 148 - vendor/github.com/jinzhu/inflection/README.md | 55 - .../jinzhu/inflection/inflections_test.go | 213 - .../github.com/jinzhu/inflection/wercker.yml | 23 - vendor/github.com/lib/pq/CONTRIBUTING.md | 29 - vendor/github.com/lib/pq/README.md | 95 - vendor/github.com/lib/pq/TESTS.md | 33 - vendor/github.com/lib/pq/array_test.go | 1311 --- vendor/github.com/lib/pq/bench_test.go | 436 - vendor/github.com/lib/pq/conn_test.go | 1659 ---- .../lib/pq/connector_example_test.go | 33 - vendor/github.com/lib/pq/connector_test.go | 67 - vendor/github.com/lib/pq/copy_test.go | 468 -- vendor/github.com/lib/pq/encode_test.go | 766 -- vendor/github.com/lib/pq/go.mod | 1 - vendor/github.com/lib/pq/go18_test.go | 321 - .../github.com/lib/pq/hstore/hstore_test.go | 148 - vendor/github.com/lib/pq/issues_test.go | 26 - vendor/github.com/lib/pq/notify_test.go | 570 -- vendor/github.com/lib/pq/rows_test.go | 220 - vendor/github.com/lib/pq/ssl_test.go | 279 - vendor/github.com/lib/pq/url_test.go | 66 - vendor/github.com/lib/pq/uuid_test.go | 46 - vendor/github.com/mattn/go-sqlite3/README.md | 519 -- .../mattn/go-sqlite3/backup_test.go | 290 - .../mattn/go-sqlite3/callback_test.go | 97 - .../github.com/mattn/go-sqlite3/error_test.go | 242 - .../go-sqlite3/sqlite3_func_crypt_test.go | 57 - .../mattn/go-sqlite3/sqlite3_go18_test.go | 156 - .../mattn/go-sqlite3/sqlite3_opt_fts3_test.go | 130 - .../sqlite3_opt_unlock_notify_test.go | 222 - .../go-sqlite3/sqlite3_opt_userauth_test.go | 619 -- .../go-sqlite3/sqlite3_opt_vtable_test.go | 486 -- .../mattn/go-sqlite3/sqlite3_test.go | 2195 ----- vendor/github.com/msteinert/pam/README.md | 30 - .../github.com/msteinert/pam/callback_test.go | 33 - .../github.com/msteinert/pam/example_test.go | 53 - .../msteinert/pam/transaction_test.go | 349 - vendor/go.opencensus.io/CONTRIBUTING.md | 56 - vendor/go.opencensus.io/Gopkg.lock | 231 - vendor/go.opencensus.io/Gopkg.toml | 36 - vendor/go.opencensus.io/README.md | 263 - vendor/go.opencensus.io/appveyor.yml | 24 - vendor/go.opencensus.io/go.mod | 25 - vendor/go.opencensus.io/go.sum | 48 - .../internal/sanitize_test.go | 67 - .../plugin/ochttp/client_test.go | 316 - .../plugin/ochttp/example_test.go | 77 - .../plugin/ochttp/propagation/b3/b3_test.go | 210 - .../tracecontext/propagation_test.go | 267 - .../plugin/ochttp/propagation_test.go | 74 - .../plugin/ochttp/route_test.go | 80 - .../plugin/ochttp/server_test.go | 597 -- .../span_annotating_client_trace_test.go | 109 - .../plugin/ochttp/stats_test.go | 88 - .../plugin/ochttp/trace_test.go | 543 -- .../go.opencensus.io/stats/benchmark_test.go | 96 - vendor/go.opencensus.io/stats/example_test.go | 33 - .../stats/view/aggregation_data_test.go | 145 - .../stats/view/benchmark_test.go | 92 - .../stats/view/collector_test.go | 118 - .../stats/view/example_test.go | 39 - .../stats/view/view_measure_test.go | 50 - .../go.opencensus.io/stats/view/view_test.go | 446 - .../stats/view/worker_test.go | 435 - vendor/go.opencensus.io/tag/context_test.go | 44 - vendor/go.opencensus.io/tag/example_test.go | 97 - vendor/go.opencensus.io/tag/map_codec_test.go | 154 - vendor/go.opencensus.io/tag/map_test.go | 222 - vendor/go.opencensus.io/tag/validate_test.go | 110 - .../go.opencensus.io/trace/benchmark_test.go | 105 - vendor/go.opencensus.io/trace/config_test.go | 33 - .../go.opencensus.io/trace/examples_test.go | 41 - .../go.opencensus.io/trace/exemplar_test.go | 100 - .../trace/propagation/propagation_test.go | 150 - vendor/go.opencensus.io/trace/trace_test.go | 714 -- .../trace/tracestate/tracestate_test.go | 313 - vendor/golang.org/x/crypto/CONTRIBUTING.md | 26 - vendor/golang.org/x/crypto/README.md | 21 - vendor/golang.org/x/crypto/codereview.cfg | 1 - .../x/crypto/curve25519/curve25519_test.go | 39 - .../x/crypto/ed25519/ed25519_test.go | 220 - .../x/crypto/internal/chacha20/chacha_test.go | 225 - .../crypto/internal/chacha20/vectors_test.go | 578 -- .../x/crypto/internal/subtle/aliasing_test.go | 50 - .../golang.org/x/crypto/md4/example_test.go | 20 - vendor/golang.org/x/crypto/md4/md4_test.go | 71 - .../x/crypto/poly1305/poly1305_test.go | 132 - .../x/crypto/poly1305/vectors_test.go | 2943 ------- .../golang.org/x/crypto/ssh/benchmark_test.go | 123 - vendor/golang.org/x/crypto/ssh/buffer_test.go | 87 - vendor/golang.org/x/crypto/ssh/certs_test.go | 335 - vendor/golang.org/x/crypto/ssh/cipher_test.go | 131 - .../x/crypto/ssh/client_auth_test.go | 678 -- vendor/golang.org/x/crypto/ssh/client_test.go | 166 - .../golang.org/x/crypto/ssh/example_test.go | 320 - .../golang.org/x/crypto/ssh/handshake_test.go | 559 -- vendor/golang.org/x/crypto/ssh/kex_test.go | 50 - vendor/golang.org/x/crypto/ssh/keys_test.go | 574 -- .../crypto/ssh/knownhosts/knownhosts_test.go | 356 - .../golang.org/x/crypto/ssh/mempipe_test.go | 110 - .../golang.org/x/crypto/ssh/messages_test.go | 288 - vendor/golang.org/x/crypto/ssh/mux_test.go | 501 -- .../golang.org/x/crypto/ssh/session_test.go | 774 -- .../golang.org/x/crypto/ssh/sshpiper_test.go | 800 -- vendor/golang.org/x/crypto/ssh/tcpip_test.go | 20 - .../x/crypto/ssh/test/agent_unix_test.go | 59 - .../x/crypto/ssh/test/banner_test.go | 32 - .../golang.org/x/crypto/ssh/test/cert_test.go | 77 - .../x/crypto/ssh/test/dial_unix_test.go | 128 - vendor/golang.org/x/crypto/ssh/test/doc.go | 7 - .../x/crypto/ssh/test/forward_unix_test.go | 194 - .../x/crypto/ssh/test/multi_auth_test.go | 144 - .../x/crypto/ssh/test/session_test.go | 443 - .../x/crypto/ssh/test/sshd_test_pw.c | 173 - .../x/crypto/ssh/test/test_unix_test.go | 368 - .../x/crypto/ssh/test/testdata_test.go | 64 - .../golang.org/x/crypto/ssh/testdata_test.go | 63 - .../golang.org/x/crypto/ssh/transport_test.go | 113 - vendor/golang.org/x/net/CONTRIBUTING.md | 26 - vendor/golang.org/x/net/README.md | 16 - vendor/golang.org/x/net/codereview.cfg | 1 - .../golang.org/x/net/context/context_test.go | 583 -- .../x/net/context/withtimeout_test.go | 31 - .../x/net/http/httpguts/httplex_test.go | 119 - vendor/golang.org/x/net/http2/Dockerfile | 51 - vendor/golang.org/x/net/http2/Makefile | 3 - vendor/golang.org/x/net/http2/README | 20 - vendor/golang.org/x/net/http2/ciphers_test.go | 309 - .../golang.org/x/net/http2/databuffer_test.go | 155 - vendor/golang.org/x/net/http2/errors_test.go | 24 - vendor/golang.org/x/net/http2/flow_test.go | 87 - vendor/golang.org/x/net/http2/frame_test.go | 1235 --- vendor/golang.org/x/net/http2/gotrack_test.go | 33 - .../x/net/http2/hpack/encode_test.go | 386 - .../x/net/http2/hpack/hpack_test.go | 770 -- .../x/net/http2/hpack/tables_test.go | 214 - vendor/golang.org/x/net/http2/http2_test.go | 280 - vendor/golang.org/x/net/http2/pipe_test.go | 130 - .../x/net/http2/server_push_test.go | 519 -- vendor/golang.org/x/net/http2/server_test.go | 3899 --------- .../golang.org/x/net/http2/transport_test.go | 4281 ---------- .../x/net/http2/writesched_priority_test.go | 541 -- .../x/net/http2/writesched_random_test.go | 44 - .../golang.org/x/net/http2/writesched_test.go | 125 - vendor/golang.org/x/net/http2/z_spec_test.go | 356 - vendor/golang.org/x/net/idna/example_test.go | 70 - vendor/golang.org/x/net/idna/idna_test.go | 108 - vendor/golang.org/x/net/idna/punycode_test.go | 198 - .../internal/timeseries/timeseries_test.go | 170 - .../golang.org/x/net/trace/histogram_test.go | 325 - vendor/golang.org/x/net/trace/trace_test.go | 178 - vendor/golang.org/x/sync/CONTRIBUTING.md | 26 - vendor/golang.org/x/sync/README.md | 18 - vendor/golang.org/x/sync/codereview.cfg | 1 - .../x/sync/semaphore/semaphore_bench_test.go | 131 - .../sync/semaphore/semaphore_example_test.go | 84 - .../x/sync/semaphore/semaphore_test.go | 171 - vendor/golang.org/x/sys/CONTRIBUTING.md | 26 - vendor/golang.org/x/sys/README.md | 18 - vendor/golang.org/x/sys/codereview.cfg | 1 - vendor/golang.org/x/sys/unix/README.md | 173 - vendor/golang.org/x/sys/unix/creds_test.go | 134 - vendor/golang.org/x/sys/unix/darwin_test.go | 210 - .../golang.org/x/sys/unix/dev_linux_test.go | 56 - .../x/sys/unix/example_exec_test.go | 19 - .../x/sys/unix/example_flock_test.go | 25 - vendor/golang.org/x/sys/unix/export_test.go | 9 - vendor/golang.org/x/sys/unix/mkall.sh | 214 - vendor/golang.org/x/sys/unix/mkerrors.sh | 664 -- .../x/sys/unix/mksyscall_aix_ppc64.pl | 579 -- .../x/sys/unix/mksyscall_solaris.pl | 294 - .../golang.org/x/sys/unix/mksysctl_openbsd.pl | 265 - .../golang.org/x/sys/unix/mmap_unix_test.go | 41 - vendor/golang.org/x/sys/unix/openbsd_test.go | 113 - vendor/golang.org/x/sys/unix/sendfile_test.go | 98 - .../golang.org/x/sys/unix/syscall_aix_test.go | 162 - .../golang.org/x/sys/unix/syscall_bsd_test.go | 89 - .../x/sys/unix/syscall_darwin_test.go | 63 - .../x/sys/unix/syscall_freebsd_test.go | 312 - .../x/sys/unix/syscall_linux_test.go | 484 -- .../x/sys/unix/syscall_netbsd_test.go | 51 - .../x/sys/unix/syscall_openbsd_test.go | 49 - .../x/sys/unix/syscall_solaris_test.go | 55 - vendor/golang.org/x/sys/unix/syscall_test.go | 60 - .../x/sys/unix/syscall_unix_test.go | 677 -- .../golang.org/x/sys/unix/timestruct_test.go | 54 - vendor/golang.org/x/sys/unix/xattr_test.go | 207 - vendor/golang.org/x/text/CONTRIBUTING.md | 31 - vendor/golang.org/x/text/README.md | 93 - vendor/golang.org/x/text/codereview.cfg | 1 - .../x/text/collate/build/builder_test.go | 290 - .../x/text/collate/build/colelem_test.go | 215 - .../x/text/collate/build/contract_test.go | 266 - .../x/text/collate/build/order_test.go | 229 - .../x/text/collate/build/trie_test.go | 107 - .../golang.org/x/text/collate/collate_test.go | 482 -- .../golang.org/x/text/collate/export_test.go | 51 - .../golang.org/x/text/collate/option_test.go | 209 - vendor/golang.org/x/text/collate/reg_test.go | 230 - vendor/golang.org/x/text/collate/sort_test.go | 55 - .../golang.org/x/text/collate/table_test.go | 291 - vendor/golang.org/x/text/doc.go | 13 - vendor/golang.org/x/text/gen.go | 319 - .../x/text/internal/colltab/collate_test.go | 121 - .../x/text/internal/colltab/collelem_test.go | 183 - .../x/text/internal/colltab/colltab_test.go | 64 - .../x/text/internal/colltab/contract_test.go | 131 - .../x/text/internal/colltab/iter_test.go | 63 - .../x/text/internal/colltab/numeric_test.go | 159 - .../x/text/internal/colltab/trie_test.go | 106 - .../x/text/internal/colltab/weighter_test.go | 42 - vendor/golang.org/x/text/internal/gen.go | 52 - vendor/golang.org/x/text/internal/gen_test.go | 38 - vendor/golang.org/x/text/internal/internal.go | 51 - .../x/text/internal/internal_test.go | 38 - vendor/golang.org/x/text/internal/match.go | 67 - .../golang.org/x/text/internal/match_test.go | 56 - vendor/golang.org/x/text/internal/tables.go | 118 - .../x/text/internal/tag/tag_test.go | 67 - .../x/text/internal/triegen/data_test.go | 875 -- .../internal/triegen/example_compact_test.go | 71 - .../x/text/internal/triegen/example_test.go | 148 - .../x/text/internal/triegen/gen_test.go | 68 - .../x/text/internal/ucd/example_test.go | 81 - .../x/text/internal/ucd/ucd_test.go | 105 - vendor/golang.org/x/text/language/Makefile | 16 - .../x/text/language/coverage_test.go | 154 - .../x/text/language/examples_test.go | 413 - .../x/text/language/httpexample_test.go | 48 - .../x/text/language/language_test.go | 911 -- .../golang.org/x/text/language/lookup_test.go | 457 - .../golang.org/x/text/language/match_test.go | 505 -- .../golang.org/x/text/language/parse_test.go | 517 -- .../x/text/secure/bidirule/bench_test.go | 54 - .../secure/bidirule/bidirule10.0.0_test.go | 694 -- .../secure/bidirule/bidirule9.0.0_test.go | 668 -- .../x/text/secure/bidirule/bidirule_test.go | 168 - vendor/golang.org/x/text/secure/doc.go | 6 - .../x/text/transform/examples_test.go | 37 - .../x/text/transform/transform_test.go | 1317 --- .../x/text/unicode/bidi/core_test.go | 224 - .../x/text/unicode/bidi/ranges_test.go | 53 - .../x/text/unicode/bidi/tables_test.go | 82 - .../x/text/unicode/cldr/cldr_test.go | 27 - .../x/text/unicode/cldr/collate_test.go | 275 - .../x/text/unicode/cldr/data_test.go | 186 - .../x/text/unicode/cldr/examples_test.go | 21 - .../x/text/unicode/cldr/resolve_test.go | 368 - .../x/text/unicode/cldr/slice_test.go | 175 - vendor/golang.org/x/text/unicode/doc.go | 8 - .../x/text/unicode/norm/composition_test.go | 130 - .../x/text/unicode/norm/data10.0.0_test.go | 7424 ----------------- .../x/text/unicode/norm/data9.0.0_test.go | 7409 ---------------- .../x/text/unicode/norm/example_iter_test.go | 82 - .../x/text/unicode/norm/example_test.go | 27 - .../x/text/unicode/norm/forminfo_test.go | 54 - .../x/text/unicode/norm/iter_test.go | 98 - .../x/text/unicode/norm/normalize_test.go | 1287 --- .../x/text/unicode/norm/readwriter_test.go | 56 - .../x/text/unicode/norm/transform_test.go | 101 - .../x/text/unicode/norm/ucd_test.go | 275 - .../x/text/unicode/rangetable/merge_test.go | 184 - .../unicode/rangetable/rangetable_test.go | 55 - vendor/google.golang.org/api/CONTRIBUTING.md | 484 -- .../google.golang.org/api/GettingStarted.md | 146 - vendor/google.golang.org/api/NOTES | 13 - vendor/google.golang.org/api/README.md | 104 - vendor/google.golang.org/api/TODO | 2 - vendor/google.golang.org/api/api-list.json | 3419 -------- vendor/google.golang.org/api/go.mod | 11 - vendor/google.golang.org/api/go.sum | 58 - .../googleapi/internal/uritemplates/LICENSE | 18 + vendor/google.golang.org/api/key.json.enc | Bin 2432 -> 0 bytes .../api/support/bundler/bundler_test.go | 366 - .../appengine/CONTRIBUTING.md | 90 - vendor/google.golang.org/appengine/README.md | 73 - .../google.golang.org/appengine/appengine.go | 131 - .../appengine/appengine_test.go | 49 - .../appengine/appengine_vm.go | 20 - vendor/google.golang.org/appengine/errors.go | 46 - vendor/google.golang.org/appengine/go.mod | 7 - vendor/google.golang.org/appengine/go.sum | 6 - .../google.golang.org/appengine/identity.go | 142 - .../google.golang.org/appengine/namespace.go | 25 - .../appengine/namespace_test.go | 39 - vendor/google.golang.org/appengine/timeout.go | 20 - .../appengine/travis_install.sh | 18 - .../appengine/travis_test.sh | 12 - .../genproto/CONTRIBUTING.md | 27 - vendor/google.golang.org/genproto/README.md | 31 - vendor/google.golang.org/genproto/go.mod | 7 - vendor/google.golang.org/genproto/go.sum | 26 - vendor/google.golang.org/genproto/regen.go | 137 - vendor/google.golang.org/genproto/regen.sh | 86 - vendor/google.golang.org/grpc/CONTRIBUTING.md | 36 - vendor/google.golang.org/grpc/Makefile | 60 - vendor/google.golang.org/grpc/README.md | 67 - .../balancer/roundrobin/roundrobin_test.go | 477 -- .../grpc/balancer_switching_test.go | 469 -- .../google.golang.org/grpc/balancer_test.go | 808 -- vendor/google.golang.org/grpc/call_test.go | 293 - .../grpc/clientconn_state_transition_test.go | 515 -- .../google.golang.org/grpc/clientconn_test.go | 1022 --- vendor/google.golang.org/grpc/codec_test.go | 32 - vendor/google.golang.org/grpc/codegen.sh | 17 - .../grpc/codes/codes_test.go | 84 - .../grpc/credentials/credentials_test.go | 206 - .../credentials/internal/syscallconn_test.go | 64 - .../encoding/proto/proto_benchmark_test.go | 98 - .../grpc/encoding/proto/proto_test.go | 129 - vendor/google.golang.org/grpc/go.mod | 20 - vendor/google.golang.org/grpc/go.sum | 32 - .../grpc/grpclog/loggerv2_test.go | 62 - vendor/google.golang.org/grpc/install_gae.sh | 6 - .../binarylog/binarylog_end2end_test.go | 1044 --- .../grpc/internal/binarylog/binarylog_test.go | 147 - .../internal/binarylog/env_config_test.go | 478 -- .../internal/binarylog/method_logger_test.go | 542 -- .../grpc/internal/binarylog/regenerate.sh | 33 - .../grpc/internal/binarylog/regexp_test.go | 179 - .../grpc/internal/binarylog/util_test.go | 59 - .../grpc/internal/channelz/util_test.go | 90 - .../grpc/internal/grpcsync/event_test.go | 69 - .../internal/transport/handler_server_test.go | 481 -- .../grpc/internal/transport/http_util_test.go | 237 - .../grpc/internal/transport/transport_test.go | 2375 ------ .../grpc/metadata/metadata_test.go | 250 - .../grpc/naming/dns_resolver_test.go | 331 - .../grpc/picker_wrapper_test.go | 160 - .../google.golang.org/grpc/pickfirst_test.go | 360 - vendor/google.golang.org/grpc/proxy_test.go | 235 - .../grpc/resolver/dns/dns_resolver_test.go | 1124 --- .../grpc/resolver_conn_wrapper_test.go | 116 - .../google.golang.org/grpc/rpc_util_test.go | 288 - vendor/google.golang.org/grpc/server_test.go | 136 - .../grpc/service_config_test.go | 386 - .../grpc/stats/stats_test.go | 1255 --- .../grpc/status/status_test.go | 348 - vendor/google.golang.org/grpc/vet.sh | 136 - 527 files changed, 228 insertions(+), 157973 deletions(-) delete mode 100644 vendor/cloud.google.com/go/CHANGES.md delete mode 100644 vendor/cloud.google.com/go/CODE_OF_CONDUCT.md delete mode 100644 vendor/cloud.google.com/go/CONTRIBUTING.md delete mode 100644 vendor/cloud.google.com/go/README.md delete mode 100644 vendor/cloud.google.com/go/RELEASING.md delete mode 100644 vendor/cloud.google.com/go/authexample_test.go delete mode 100644 vendor/cloud.google.com/go/civil/civil_test.go delete mode 100644 vendor/cloud.google.com/go/cloud.go delete mode 100644 vendor/cloud.google.com/go/examples_test.go delete mode 100644 vendor/cloud.google.com/go/issue_template.md delete mode 100644 vendor/cloud.google.com/go/keys.tar.enc delete mode 100644 vendor/cloud.google.com/go/license_test.go delete mode 100644 vendor/cloud.google.com/go/old-news.md delete mode 100755 vendor/cloud.google.com/go/regen-gapic.sh delete mode 100755 vendor/cloud.google.com/go/run-tests.sh delete mode 100644 vendor/contrib.go.opencensus.io/exporter/ocagent/CONTRIBUTING.md delete mode 100644 vendor/contrib.go.opencensus.io/exporter/ocagent/README.md delete mode 100644 vendor/contrib.go.opencensus.io/exporter/ocagent/example_test.go delete mode 100644 vendor/contrib.go.opencensus.io/exporter/ocagent/go.mod delete mode 100644 vendor/contrib.go.opencensus.io/exporter/ocagent/go.sum delete mode 100644 vendor/contrib.go.opencensus.io/exporter/ocagent/mock_agent_test.go delete mode 100644 vendor/contrib.go.opencensus.io/exporter/ocagent/ocagent_test.go delete mode 100644 vendor/contrib.go.opencensus.io/exporter/ocagent/transform_spans_test.go delete mode 100644 vendor/github.com/Azure/azure-sdk-for-go/CHANGELOG.md delete mode 100644 vendor/github.com/Azure/azure-sdk-for-go/CODEOWNERS delete mode 100644 vendor/github.com/Azure/azure-sdk-for-go/CONTRIBUTING.md delete mode 100644 vendor/github.com/Azure/azure-sdk-for-go/Gopkg.lock delete mode 100644 vendor/github.com/Azure/azure-sdk-for-go/Gopkg.toml delete mode 100644 vendor/github.com/Azure/azure-sdk-for-go/README.md delete mode 100644 vendor/github.com/Azure/azure-sdk-for-go/doc.go delete mode 100644 vendor/github.com/Azure/azure-sdk-for-go/findTestedPackages.sh delete mode 100644 vendor/github.com/Azure/azure-sdk-for-go/rungas.sh delete mode 100644 vendor/github.com/Azure/azure-sdk-for-go/swagger_to_sdk_config.json delete mode 100644 vendor/github.com/Azure/go-autorest/CHANGELOG.md delete mode 100644 vendor/github.com/Azure/go-autorest/GNUmakefile delete mode 100644 vendor/github.com/Azure/go-autorest/Gopkg.lock delete mode 100644 vendor/github.com/Azure/go-autorest/Gopkg.toml delete mode 100644 vendor/github.com/Azure/go-autorest/README.md delete mode 100644 vendor/github.com/Azure/go-autorest/autorest/adal/README.md delete mode 100644 vendor/github.com/Azure/go-autorest/autorest/adal/config_test.go delete mode 100644 vendor/github.com/Azure/go-autorest/autorest/adal/devicetoken_test.go delete mode 100644 vendor/github.com/Azure/go-autorest/autorest/adal/persist_test.go delete mode 100644 vendor/github.com/Azure/go-autorest/autorest/adal/token_test.go delete mode 100644 vendor/github.com/Azure/go-autorest/autorest/authorization_test.go delete mode 100644 vendor/github.com/Azure/go-autorest/autorest/autorest_test.go delete mode 100644 vendor/github.com/Azure/go-autorest/autorest/azure/async_test.go delete mode 100644 vendor/github.com/Azure/go-autorest/autorest/azure/azure_test.go delete mode 100644 vendor/github.com/Azure/go-autorest/autorest/azure/environments_test.go delete mode 100644 vendor/github.com/Azure/go-autorest/autorest/azure/rp_test.go delete mode 100644 vendor/github.com/Azure/go-autorest/autorest/client_test.go delete mode 100644 vendor/github.com/Azure/go-autorest/autorest/date/date_test.go delete mode 100644 vendor/github.com/Azure/go-autorest/autorest/date/time_test.go delete mode 100644 vendor/github.com/Azure/go-autorest/autorest/date/timerfc1123_test.go delete mode 100644 vendor/github.com/Azure/go-autorest/autorest/date/unixtime_test.go delete mode 100644 vendor/github.com/Azure/go-autorest/autorest/error_test.go delete mode 100644 vendor/github.com/Azure/go-autorest/autorest/preparer_test.go delete mode 100644 vendor/github.com/Azure/go-autorest/autorest/responder_test.go delete mode 100644 vendor/github.com/Azure/go-autorest/autorest/sender_test.go delete mode 100644 vendor/github.com/Azure/go-autorest/autorest/to/convert_test.go delete mode 100644 vendor/github.com/Azure/go-autorest/autorest/utility_test.go delete mode 100644 vendor/github.com/Azure/go-autorest/autorest/validation/validation_test.go delete mode 100644 vendor/github.com/Azure/go-autorest/logger/logger_test.go delete mode 100644 vendor/github.com/Azure/go-autorest/tracing/tracing_test.go delete mode 100644 vendor/github.com/census-instrumentation/opencensus-proto/CONTRIBUTING.md delete mode 100644 vendor/github.com/census-instrumentation/opencensus-proto/README.md delete mode 100644 vendor/github.com/census-instrumentation/opencensus-proto/RELEASING.md delete mode 100644 vendor/github.com/census-instrumentation/opencensus-proto/build.gradle delete mode 100755 vendor/github.com/census-instrumentation/opencensus-proto/gradlew delete mode 100644 vendor/github.com/census-instrumentation/opencensus-proto/gradlew.bat delete mode 100644 vendor/github.com/census-instrumentation/opencensus-proto/settings.gradle delete mode 100644 vendor/github.com/denisenkom/go-mssqldb/README.md delete mode 100644 vendor/github.com/denisenkom/go-mssqldb/appveyor.yml delete mode 100644 vendor/github.com/denisenkom/go-mssqldb/buf_test.go delete mode 100644 vendor/github.com/denisenkom/go-mssqldb/bulkcopy_test.go delete mode 100644 vendor/github.com/denisenkom/go-mssqldb/decimal_test.go delete mode 100644 vendor/github.com/denisenkom/go-mssqldb/error_example_test.go delete mode 100644 vendor/github.com/denisenkom/go-mssqldb/mssql_test.go delete mode 100644 vendor/github.com/denisenkom/go-mssqldb/ntlm_test.go delete mode 100644 vendor/github.com/denisenkom/go-mssqldb/parser_test.go delete mode 100644 vendor/github.com/denisenkom/go-mssqldb/queries_go110_test.go delete mode 100644 vendor/github.com/denisenkom/go-mssqldb/queries_go19_test.go delete mode 100644 vendor/github.com/denisenkom/go-mssqldb/queries_test.go delete mode 100644 vendor/github.com/denisenkom/go-mssqldb/tds_test.go delete mode 100644 vendor/github.com/denisenkom/go-mssqldb/types_test.go delete mode 100644 vendor/github.com/denisenkom/go-mssqldb/uniqueidentifier_test.go delete mode 100644 vendor/github.com/dgrijalva/jwt-go/MIGRATION_GUIDE.md delete mode 100644 vendor/github.com/dgrijalva/jwt-go/README.md delete mode 100644 vendor/github.com/dgrijalva/jwt-go/VERSION_HISTORY.md delete mode 100644 vendor/github.com/dgrijalva/jwt-go/ecdsa_test.go delete mode 100644 vendor/github.com/dgrijalva/jwt-go/example_test.go delete mode 100644 vendor/github.com/dgrijalva/jwt-go/hmac_example_test.go delete mode 100644 vendor/github.com/dgrijalva/jwt-go/hmac_test.go delete mode 100644 vendor/github.com/dgrijalva/jwt-go/http_example_test.go delete mode 100644 vendor/github.com/dgrijalva/jwt-go/none_test.go delete mode 100644 vendor/github.com/dgrijalva/jwt-go/parser_test.go delete mode 100644 vendor/github.com/dgrijalva/jwt-go/rsa_pss_test.go delete mode 100644 vendor/github.com/dgrijalva/jwt-go/rsa_test.go delete mode 100644 vendor/github.com/go-sql-driver/mysql/CHANGELOG.md delete mode 100644 vendor/github.com/go-sql-driver/mysql/CONTRIBUTING.md delete mode 100644 vendor/github.com/go-sql-driver/mysql/README.md delete mode 100644 vendor/github.com/go-sql-driver/mysql/auth_test.go delete mode 100644 vendor/github.com/go-sql-driver/mysql/benchmark_go18_test.go delete mode 100644 vendor/github.com/go-sql-driver/mysql/benchmark_test.go delete mode 100644 vendor/github.com/go-sql-driver/mysql/connection_go18_test.go delete mode 100644 vendor/github.com/go-sql-driver/mysql/connection_test.go delete mode 100644 vendor/github.com/go-sql-driver/mysql/driver_go18_test.go delete mode 100644 vendor/github.com/go-sql-driver/mysql/driver_test.go delete mode 100644 vendor/github.com/go-sql-driver/mysql/dsn_test.go delete mode 100644 vendor/github.com/go-sql-driver/mysql/errors_test.go delete mode 100644 vendor/github.com/go-sql-driver/mysql/packets_test.go delete mode 100644 vendor/github.com/go-sql-driver/mysql/statement_test.go delete mode 100644 vendor/github.com/go-sql-driver/mysql/utils_go18_test.go delete mode 100644 vendor/github.com/go-sql-driver/mysql/utils_test.go delete mode 100644 vendor/github.com/gokyle/sshkey/README delete mode 100644 vendor/github.com/gokyle/sshkey/TODO delete mode 100644 vendor/github.com/gokyle/sshkey/sshkey_test.go delete mode 100644 vendor/github.com/golang/protobuf/Makefile delete mode 100644 vendor/github.com/golang/protobuf/README.md delete mode 100644 vendor/github.com/golang/protobuf/proto/all_test.go delete mode 100644 vendor/github.com/golang/protobuf/proto/any_test.go delete mode 100644 vendor/github.com/golang/protobuf/proto/clone_test.go delete mode 100644 vendor/github.com/golang/protobuf/proto/decode_test.go delete mode 100644 vendor/github.com/golang/protobuf/proto/discard_test.go delete mode 100644 vendor/github.com/golang/protobuf/proto/encode_test.go delete mode 100644 vendor/github.com/golang/protobuf/proto/equal_test.go delete mode 100644 vendor/github.com/golang/protobuf/proto/extensions_test.go delete mode 100644 vendor/github.com/golang/protobuf/proto/map_test.go delete mode 100644 vendor/github.com/golang/protobuf/proto/message_set_test.go delete mode 100644 vendor/github.com/golang/protobuf/proto/proto3_test.go delete mode 100644 vendor/github.com/golang/protobuf/proto/size2_test.go delete mode 100644 vendor/github.com/golang/protobuf/proto/size_test.go delete mode 100644 vendor/github.com/golang/protobuf/proto/text_parser_test.go delete mode 100644 vendor/github.com/golang/protobuf/proto/text_test.go delete mode 100644 vendor/github.com/golang/protobuf/ptypes/any/any.proto delete mode 100644 vendor/github.com/golang/protobuf/ptypes/any_test.go delete mode 100644 vendor/github.com/golang/protobuf/ptypes/duration/duration.proto delete mode 100644 vendor/github.com/golang/protobuf/ptypes/duration_test.go delete mode 100644 vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto delete mode 100644 vendor/github.com/golang/protobuf/ptypes/timestamp_test.go delete mode 100644 vendor/github.com/golang/protobuf/ptypes/wrappers/wrappers.proto delete mode 100755 vendor/github.com/golang/protobuf/regenerate.sh delete mode 100644 vendor/github.com/jessevdk/go-flags/README.md delete mode 100644 vendor/github.com/jessevdk/go-flags/arg_test.go delete mode 100644 vendor/github.com/jessevdk/go-flags/assert_test.go delete mode 100755 vendor/github.com/jessevdk/go-flags/check_crosscompile.sh delete mode 100644 vendor/github.com/jessevdk/go-flags/command_test.go delete mode 100644 vendor/github.com/jessevdk/go-flags/completion_test.go delete mode 100644 vendor/github.com/jessevdk/go-flags/convert_test.go delete mode 100644 vendor/github.com/jessevdk/go-flags/example_test.go delete mode 100644 vendor/github.com/jessevdk/go-flags/group_test.go delete mode 100644 vendor/github.com/jessevdk/go-flags/help_test.go delete mode 100644 vendor/github.com/jessevdk/go-flags/ini_test.go delete mode 100644 vendor/github.com/jessevdk/go-flags/long_test.go delete mode 100644 vendor/github.com/jessevdk/go-flags/marshal_test.go delete mode 100644 vendor/github.com/jessevdk/go-flags/options_test.go delete mode 100644 vendor/github.com/jessevdk/go-flags/parser_test.go delete mode 100644 vendor/github.com/jessevdk/go-flags/pointer_test.go delete mode 100644 vendor/github.com/jessevdk/go-flags/short_test.go delete mode 100644 vendor/github.com/jessevdk/go-flags/tag_test.go delete mode 100644 vendor/github.com/jessevdk/go-flags/unknown_test.go delete mode 100644 vendor/github.com/jinzhu/gorm/README.md delete mode 100644 vendor/github.com/jinzhu/gorm/association_test.go delete mode 100644 vendor/github.com/jinzhu/gorm/callback_system_test.go delete mode 100644 vendor/github.com/jinzhu/gorm/callbacks_test.go delete mode 100644 vendor/github.com/jinzhu/gorm/create_test.go delete mode 100644 vendor/github.com/jinzhu/gorm/customize_column_test.go delete mode 100644 vendor/github.com/jinzhu/gorm/delete_test.go delete mode 100644 vendor/github.com/jinzhu/gorm/docker-compose.yml delete mode 100644 vendor/github.com/jinzhu/gorm/embedded_struct_test.go delete mode 100644 vendor/github.com/jinzhu/gorm/errors_test.go delete mode 100644 vendor/github.com/jinzhu/gorm/field_test.go delete mode 100644 vendor/github.com/jinzhu/gorm/join_table_test.go delete mode 100644 vendor/github.com/jinzhu/gorm/main_test.go delete mode 100644 vendor/github.com/jinzhu/gorm/migration_test.go delete mode 100644 vendor/github.com/jinzhu/gorm/multi_primary_keys_test.go delete mode 100644 vendor/github.com/jinzhu/gorm/naming_test.go delete mode 100644 vendor/github.com/jinzhu/gorm/pointer_test.go delete mode 100644 vendor/github.com/jinzhu/gorm/polymorphic_test.go delete mode 100644 vendor/github.com/jinzhu/gorm/preload_test.go delete mode 100644 vendor/github.com/jinzhu/gorm/query_test.go delete mode 100644 vendor/github.com/jinzhu/gorm/scaner_test.go delete mode 100644 vendor/github.com/jinzhu/gorm/scope_test.go delete mode 100644 vendor/github.com/jinzhu/gorm/search_test.go delete mode 100755 vendor/github.com/jinzhu/gorm/test_all.sh delete mode 100644 vendor/github.com/jinzhu/gorm/update_test.go delete mode 100644 vendor/github.com/jinzhu/gorm/wercker.yml delete mode 100644 vendor/github.com/jinzhu/inflection/README.md delete mode 100644 vendor/github.com/jinzhu/inflection/inflections_test.go delete mode 100644 vendor/github.com/jinzhu/inflection/wercker.yml delete mode 100644 vendor/github.com/lib/pq/CONTRIBUTING.md delete mode 100644 vendor/github.com/lib/pq/README.md delete mode 100644 vendor/github.com/lib/pq/TESTS.md delete mode 100644 vendor/github.com/lib/pq/array_test.go delete mode 100644 vendor/github.com/lib/pq/bench_test.go delete mode 100644 vendor/github.com/lib/pq/conn_test.go delete mode 100644 vendor/github.com/lib/pq/connector_example_test.go delete mode 100644 vendor/github.com/lib/pq/connector_test.go delete mode 100644 vendor/github.com/lib/pq/copy_test.go delete mode 100644 vendor/github.com/lib/pq/encode_test.go delete mode 100644 vendor/github.com/lib/pq/go.mod delete mode 100644 vendor/github.com/lib/pq/go18_test.go delete mode 100644 vendor/github.com/lib/pq/hstore/hstore_test.go delete mode 100644 vendor/github.com/lib/pq/issues_test.go delete mode 100644 vendor/github.com/lib/pq/notify_test.go delete mode 100644 vendor/github.com/lib/pq/rows_test.go delete mode 100644 vendor/github.com/lib/pq/ssl_test.go delete mode 100644 vendor/github.com/lib/pq/url_test.go delete mode 100644 vendor/github.com/lib/pq/uuid_test.go delete mode 100644 vendor/github.com/mattn/go-sqlite3/README.md delete mode 100644 vendor/github.com/mattn/go-sqlite3/backup_test.go delete mode 100644 vendor/github.com/mattn/go-sqlite3/callback_test.go delete mode 100644 vendor/github.com/mattn/go-sqlite3/error_test.go delete mode 100644 vendor/github.com/mattn/go-sqlite3/sqlite3_func_crypt_test.go delete mode 100644 vendor/github.com/mattn/go-sqlite3/sqlite3_go18_test.go delete mode 100644 vendor/github.com/mattn/go-sqlite3/sqlite3_opt_fts3_test.go delete mode 100644 vendor/github.com/mattn/go-sqlite3/sqlite3_opt_unlock_notify_test.go delete mode 100644 vendor/github.com/mattn/go-sqlite3/sqlite3_opt_userauth_test.go delete mode 100644 vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vtable_test.go delete mode 100644 vendor/github.com/mattn/go-sqlite3/sqlite3_test.go delete mode 100644 vendor/github.com/msteinert/pam/README.md delete mode 100644 vendor/github.com/msteinert/pam/callback_test.go delete mode 100644 vendor/github.com/msteinert/pam/example_test.go delete mode 100644 vendor/github.com/msteinert/pam/transaction_test.go delete mode 100644 vendor/go.opencensus.io/CONTRIBUTING.md delete mode 100644 vendor/go.opencensus.io/Gopkg.lock delete mode 100644 vendor/go.opencensus.io/Gopkg.toml delete mode 100644 vendor/go.opencensus.io/README.md delete mode 100644 vendor/go.opencensus.io/appveyor.yml delete mode 100644 vendor/go.opencensus.io/go.mod delete mode 100644 vendor/go.opencensus.io/go.sum delete mode 100644 vendor/go.opencensus.io/internal/sanitize_test.go delete mode 100644 vendor/go.opencensus.io/plugin/ochttp/client_test.go delete mode 100644 vendor/go.opencensus.io/plugin/ochttp/example_test.go delete mode 100644 vendor/go.opencensus.io/plugin/ochttp/propagation/b3/b3_test.go delete mode 100644 vendor/go.opencensus.io/plugin/ochttp/propagation/tracecontext/propagation_test.go delete mode 100644 vendor/go.opencensus.io/plugin/ochttp/propagation_test.go delete mode 100644 vendor/go.opencensus.io/plugin/ochttp/route_test.go delete mode 100644 vendor/go.opencensus.io/plugin/ochttp/server_test.go delete mode 100644 vendor/go.opencensus.io/plugin/ochttp/span_annotating_client_trace_test.go delete mode 100644 vendor/go.opencensus.io/plugin/ochttp/stats_test.go delete mode 100644 vendor/go.opencensus.io/plugin/ochttp/trace_test.go delete mode 100644 vendor/go.opencensus.io/stats/benchmark_test.go delete mode 100644 vendor/go.opencensus.io/stats/example_test.go delete mode 100644 vendor/go.opencensus.io/stats/view/aggregation_data_test.go delete mode 100644 vendor/go.opencensus.io/stats/view/benchmark_test.go delete mode 100644 vendor/go.opencensus.io/stats/view/collector_test.go delete mode 100644 vendor/go.opencensus.io/stats/view/example_test.go delete mode 100644 vendor/go.opencensus.io/stats/view/view_measure_test.go delete mode 100644 vendor/go.opencensus.io/stats/view/view_test.go delete mode 100644 vendor/go.opencensus.io/stats/view/worker_test.go delete mode 100644 vendor/go.opencensus.io/tag/context_test.go delete mode 100644 vendor/go.opencensus.io/tag/example_test.go delete mode 100644 vendor/go.opencensus.io/tag/map_codec_test.go delete mode 100644 vendor/go.opencensus.io/tag/map_test.go delete mode 100644 vendor/go.opencensus.io/tag/validate_test.go delete mode 100644 vendor/go.opencensus.io/trace/benchmark_test.go delete mode 100644 vendor/go.opencensus.io/trace/config_test.go delete mode 100644 vendor/go.opencensus.io/trace/examples_test.go delete mode 100644 vendor/go.opencensus.io/trace/exemplar_test.go delete mode 100644 vendor/go.opencensus.io/trace/propagation/propagation_test.go delete mode 100644 vendor/go.opencensus.io/trace/trace_test.go delete mode 100644 vendor/go.opencensus.io/trace/tracestate/tracestate_test.go delete mode 100644 vendor/golang.org/x/crypto/CONTRIBUTING.md delete mode 100644 vendor/golang.org/x/crypto/README.md delete mode 100644 vendor/golang.org/x/crypto/codereview.cfg delete mode 100644 vendor/golang.org/x/crypto/curve25519/curve25519_test.go delete mode 100644 vendor/golang.org/x/crypto/ed25519/ed25519_test.go delete mode 100644 vendor/golang.org/x/crypto/internal/chacha20/chacha_test.go delete mode 100644 vendor/golang.org/x/crypto/internal/chacha20/vectors_test.go delete mode 100644 vendor/golang.org/x/crypto/internal/subtle/aliasing_test.go delete mode 100644 vendor/golang.org/x/crypto/md4/example_test.go delete mode 100644 vendor/golang.org/x/crypto/md4/md4_test.go delete mode 100644 vendor/golang.org/x/crypto/poly1305/poly1305_test.go delete mode 100644 vendor/golang.org/x/crypto/poly1305/vectors_test.go delete mode 100644 vendor/golang.org/x/crypto/ssh/benchmark_test.go delete mode 100644 vendor/golang.org/x/crypto/ssh/buffer_test.go delete mode 100644 vendor/golang.org/x/crypto/ssh/certs_test.go delete mode 100644 vendor/golang.org/x/crypto/ssh/cipher_test.go delete mode 100644 vendor/golang.org/x/crypto/ssh/client_auth_test.go delete mode 100644 vendor/golang.org/x/crypto/ssh/client_test.go delete mode 100644 vendor/golang.org/x/crypto/ssh/example_test.go delete mode 100644 vendor/golang.org/x/crypto/ssh/handshake_test.go delete mode 100644 vendor/golang.org/x/crypto/ssh/kex_test.go delete mode 100644 vendor/golang.org/x/crypto/ssh/keys_test.go delete mode 100644 vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts_test.go delete mode 100644 vendor/golang.org/x/crypto/ssh/mempipe_test.go delete mode 100644 vendor/golang.org/x/crypto/ssh/messages_test.go delete mode 100644 vendor/golang.org/x/crypto/ssh/mux_test.go delete mode 100644 vendor/golang.org/x/crypto/ssh/session_test.go delete mode 100644 vendor/golang.org/x/crypto/ssh/sshpiper_test.go delete mode 100644 vendor/golang.org/x/crypto/ssh/tcpip_test.go delete mode 100644 vendor/golang.org/x/crypto/ssh/test/agent_unix_test.go delete mode 100644 vendor/golang.org/x/crypto/ssh/test/banner_test.go delete mode 100644 vendor/golang.org/x/crypto/ssh/test/cert_test.go delete mode 100644 vendor/golang.org/x/crypto/ssh/test/dial_unix_test.go delete mode 100644 vendor/golang.org/x/crypto/ssh/test/doc.go delete mode 100644 vendor/golang.org/x/crypto/ssh/test/forward_unix_test.go delete mode 100644 vendor/golang.org/x/crypto/ssh/test/multi_auth_test.go delete mode 100644 vendor/golang.org/x/crypto/ssh/test/session_test.go delete mode 100644 vendor/golang.org/x/crypto/ssh/test/sshd_test_pw.c delete mode 100644 vendor/golang.org/x/crypto/ssh/test/test_unix_test.go delete mode 100644 vendor/golang.org/x/crypto/ssh/test/testdata_test.go delete mode 100644 vendor/golang.org/x/crypto/ssh/testdata_test.go delete mode 100644 vendor/golang.org/x/crypto/ssh/transport_test.go delete mode 100644 vendor/golang.org/x/net/CONTRIBUTING.md delete mode 100644 vendor/golang.org/x/net/README.md delete mode 100644 vendor/golang.org/x/net/codereview.cfg delete mode 100644 vendor/golang.org/x/net/context/context_test.go delete mode 100644 vendor/golang.org/x/net/context/withtimeout_test.go delete mode 100644 vendor/golang.org/x/net/http/httpguts/httplex_test.go delete mode 100644 vendor/golang.org/x/net/http2/Dockerfile delete mode 100644 vendor/golang.org/x/net/http2/Makefile delete mode 100644 vendor/golang.org/x/net/http2/README delete mode 100644 vendor/golang.org/x/net/http2/ciphers_test.go delete mode 100644 vendor/golang.org/x/net/http2/databuffer_test.go delete mode 100644 vendor/golang.org/x/net/http2/errors_test.go delete mode 100644 vendor/golang.org/x/net/http2/flow_test.go delete mode 100644 vendor/golang.org/x/net/http2/frame_test.go delete mode 100644 vendor/golang.org/x/net/http2/gotrack_test.go delete mode 100644 vendor/golang.org/x/net/http2/hpack/encode_test.go delete mode 100644 vendor/golang.org/x/net/http2/hpack/hpack_test.go delete mode 100644 vendor/golang.org/x/net/http2/hpack/tables_test.go delete mode 100644 vendor/golang.org/x/net/http2/http2_test.go delete mode 100644 vendor/golang.org/x/net/http2/pipe_test.go delete mode 100644 vendor/golang.org/x/net/http2/server_push_test.go delete mode 100644 vendor/golang.org/x/net/http2/server_test.go delete mode 100644 vendor/golang.org/x/net/http2/transport_test.go delete mode 100644 vendor/golang.org/x/net/http2/writesched_priority_test.go delete mode 100644 vendor/golang.org/x/net/http2/writesched_random_test.go delete mode 100644 vendor/golang.org/x/net/http2/writesched_test.go delete mode 100644 vendor/golang.org/x/net/http2/z_spec_test.go delete mode 100644 vendor/golang.org/x/net/idna/example_test.go delete mode 100644 vendor/golang.org/x/net/idna/idna_test.go delete mode 100644 vendor/golang.org/x/net/idna/punycode_test.go delete mode 100644 vendor/golang.org/x/net/internal/timeseries/timeseries_test.go delete mode 100644 vendor/golang.org/x/net/trace/histogram_test.go delete mode 100644 vendor/golang.org/x/net/trace/trace_test.go delete mode 100644 vendor/golang.org/x/sync/CONTRIBUTING.md delete mode 100644 vendor/golang.org/x/sync/README.md delete mode 100644 vendor/golang.org/x/sync/codereview.cfg delete mode 100644 vendor/golang.org/x/sync/semaphore/semaphore_bench_test.go delete mode 100644 vendor/golang.org/x/sync/semaphore/semaphore_example_test.go delete mode 100644 vendor/golang.org/x/sync/semaphore/semaphore_test.go delete mode 100644 vendor/golang.org/x/sys/CONTRIBUTING.md delete mode 100644 vendor/golang.org/x/sys/README.md delete mode 100644 vendor/golang.org/x/sys/codereview.cfg delete mode 100644 vendor/golang.org/x/sys/unix/README.md delete mode 100644 vendor/golang.org/x/sys/unix/creds_test.go delete mode 100644 vendor/golang.org/x/sys/unix/darwin_test.go delete mode 100644 vendor/golang.org/x/sys/unix/dev_linux_test.go delete mode 100644 vendor/golang.org/x/sys/unix/example_exec_test.go delete mode 100644 vendor/golang.org/x/sys/unix/example_flock_test.go delete mode 100644 vendor/golang.org/x/sys/unix/export_test.go delete mode 100755 vendor/golang.org/x/sys/unix/mkall.sh delete mode 100755 vendor/golang.org/x/sys/unix/mkerrors.sh delete mode 100755 vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.pl delete mode 100755 vendor/golang.org/x/sys/unix/mksyscall_solaris.pl delete mode 100755 vendor/golang.org/x/sys/unix/mksysctl_openbsd.pl delete mode 100644 vendor/golang.org/x/sys/unix/mmap_unix_test.go delete mode 100644 vendor/golang.org/x/sys/unix/openbsd_test.go delete mode 100644 vendor/golang.org/x/sys/unix/sendfile_test.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_aix_test.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_bsd_test.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_test.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_freebsd_test.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_test.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_netbsd_test.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_openbsd_test.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_solaris_test.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_test.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_unix_test.go delete mode 100644 vendor/golang.org/x/sys/unix/timestruct_test.go delete mode 100644 vendor/golang.org/x/sys/unix/xattr_test.go delete mode 100644 vendor/golang.org/x/text/CONTRIBUTING.md delete mode 100644 vendor/golang.org/x/text/README.md delete mode 100644 vendor/golang.org/x/text/codereview.cfg delete mode 100644 vendor/golang.org/x/text/collate/build/builder_test.go delete mode 100644 vendor/golang.org/x/text/collate/build/colelem_test.go delete mode 100644 vendor/golang.org/x/text/collate/build/contract_test.go delete mode 100644 vendor/golang.org/x/text/collate/build/order_test.go delete mode 100644 vendor/golang.org/x/text/collate/build/trie_test.go delete mode 100644 vendor/golang.org/x/text/collate/collate_test.go delete mode 100644 vendor/golang.org/x/text/collate/export_test.go delete mode 100644 vendor/golang.org/x/text/collate/option_test.go delete mode 100644 vendor/golang.org/x/text/collate/reg_test.go delete mode 100644 vendor/golang.org/x/text/collate/sort_test.go delete mode 100644 vendor/golang.org/x/text/collate/table_test.go delete mode 100644 vendor/golang.org/x/text/doc.go delete mode 100644 vendor/golang.org/x/text/gen.go delete mode 100644 vendor/golang.org/x/text/internal/colltab/collate_test.go delete mode 100644 vendor/golang.org/x/text/internal/colltab/collelem_test.go delete mode 100644 vendor/golang.org/x/text/internal/colltab/colltab_test.go delete mode 100644 vendor/golang.org/x/text/internal/colltab/contract_test.go delete mode 100644 vendor/golang.org/x/text/internal/colltab/iter_test.go delete mode 100644 vendor/golang.org/x/text/internal/colltab/numeric_test.go delete mode 100644 vendor/golang.org/x/text/internal/colltab/trie_test.go delete mode 100644 vendor/golang.org/x/text/internal/colltab/weighter_test.go delete mode 100644 vendor/golang.org/x/text/internal/gen.go delete mode 100644 vendor/golang.org/x/text/internal/gen_test.go delete mode 100644 vendor/golang.org/x/text/internal/internal.go delete mode 100644 vendor/golang.org/x/text/internal/internal_test.go delete mode 100644 vendor/golang.org/x/text/internal/match.go delete mode 100644 vendor/golang.org/x/text/internal/match_test.go delete mode 100644 vendor/golang.org/x/text/internal/tables.go delete mode 100644 vendor/golang.org/x/text/internal/tag/tag_test.go delete mode 100644 vendor/golang.org/x/text/internal/triegen/data_test.go delete mode 100644 vendor/golang.org/x/text/internal/triegen/example_compact_test.go delete mode 100644 vendor/golang.org/x/text/internal/triegen/example_test.go delete mode 100644 vendor/golang.org/x/text/internal/triegen/gen_test.go delete mode 100644 vendor/golang.org/x/text/internal/ucd/example_test.go delete mode 100644 vendor/golang.org/x/text/internal/ucd/ucd_test.go delete mode 100644 vendor/golang.org/x/text/language/Makefile delete mode 100644 vendor/golang.org/x/text/language/coverage_test.go delete mode 100644 vendor/golang.org/x/text/language/examples_test.go delete mode 100644 vendor/golang.org/x/text/language/httpexample_test.go delete mode 100644 vendor/golang.org/x/text/language/language_test.go delete mode 100644 vendor/golang.org/x/text/language/lookup_test.go delete mode 100644 vendor/golang.org/x/text/language/match_test.go delete mode 100644 vendor/golang.org/x/text/language/parse_test.go delete mode 100644 vendor/golang.org/x/text/secure/bidirule/bench_test.go delete mode 100644 vendor/golang.org/x/text/secure/bidirule/bidirule10.0.0_test.go delete mode 100644 vendor/golang.org/x/text/secure/bidirule/bidirule9.0.0_test.go delete mode 100644 vendor/golang.org/x/text/secure/bidirule/bidirule_test.go delete mode 100644 vendor/golang.org/x/text/secure/doc.go delete mode 100644 vendor/golang.org/x/text/transform/examples_test.go delete mode 100644 vendor/golang.org/x/text/transform/transform_test.go delete mode 100644 vendor/golang.org/x/text/unicode/bidi/core_test.go delete mode 100644 vendor/golang.org/x/text/unicode/bidi/ranges_test.go delete mode 100644 vendor/golang.org/x/text/unicode/bidi/tables_test.go delete mode 100644 vendor/golang.org/x/text/unicode/cldr/cldr_test.go delete mode 100644 vendor/golang.org/x/text/unicode/cldr/collate_test.go delete mode 100644 vendor/golang.org/x/text/unicode/cldr/data_test.go delete mode 100644 vendor/golang.org/x/text/unicode/cldr/examples_test.go delete mode 100644 vendor/golang.org/x/text/unicode/cldr/resolve_test.go delete mode 100644 vendor/golang.org/x/text/unicode/cldr/slice_test.go delete mode 100644 vendor/golang.org/x/text/unicode/doc.go delete mode 100644 vendor/golang.org/x/text/unicode/norm/composition_test.go delete mode 100644 vendor/golang.org/x/text/unicode/norm/data10.0.0_test.go delete mode 100644 vendor/golang.org/x/text/unicode/norm/data9.0.0_test.go delete mode 100644 vendor/golang.org/x/text/unicode/norm/example_iter_test.go delete mode 100644 vendor/golang.org/x/text/unicode/norm/example_test.go delete mode 100644 vendor/golang.org/x/text/unicode/norm/forminfo_test.go delete mode 100644 vendor/golang.org/x/text/unicode/norm/iter_test.go delete mode 100644 vendor/golang.org/x/text/unicode/norm/normalize_test.go delete mode 100644 vendor/golang.org/x/text/unicode/norm/readwriter_test.go delete mode 100644 vendor/golang.org/x/text/unicode/norm/transform_test.go delete mode 100644 vendor/golang.org/x/text/unicode/norm/ucd_test.go delete mode 100644 vendor/golang.org/x/text/unicode/rangetable/merge_test.go delete mode 100644 vendor/golang.org/x/text/unicode/rangetable/rangetable_test.go delete mode 100644 vendor/google.golang.org/api/CONTRIBUTING.md delete mode 100644 vendor/google.golang.org/api/GettingStarted.md delete mode 100644 vendor/google.golang.org/api/NOTES delete mode 100644 vendor/google.golang.org/api/README.md delete mode 100644 vendor/google.golang.org/api/TODO delete mode 100644 vendor/google.golang.org/api/api-list.json delete mode 100644 vendor/google.golang.org/api/go.mod delete mode 100644 vendor/google.golang.org/api/go.sum create mode 100644 vendor/google.golang.org/api/googleapi/internal/uritemplates/LICENSE delete mode 100644 vendor/google.golang.org/api/key.json.enc delete mode 100644 vendor/google.golang.org/api/support/bundler/bundler_test.go delete mode 100644 vendor/google.golang.org/appengine/CONTRIBUTING.md delete mode 100644 vendor/google.golang.org/appengine/README.md delete mode 100644 vendor/google.golang.org/appengine/appengine.go delete mode 100644 vendor/google.golang.org/appengine/appengine_test.go delete mode 100644 vendor/google.golang.org/appengine/appengine_vm.go delete mode 100644 vendor/google.golang.org/appengine/errors.go delete mode 100644 vendor/google.golang.org/appengine/go.mod delete mode 100644 vendor/google.golang.org/appengine/go.sum delete mode 100644 vendor/google.golang.org/appengine/identity.go delete mode 100644 vendor/google.golang.org/appengine/namespace.go delete mode 100644 vendor/google.golang.org/appengine/namespace_test.go delete mode 100644 vendor/google.golang.org/appengine/timeout.go delete mode 100755 vendor/google.golang.org/appengine/travis_install.sh delete mode 100755 vendor/google.golang.org/appengine/travis_test.sh delete mode 100644 vendor/google.golang.org/genproto/CONTRIBUTING.md delete mode 100644 vendor/google.golang.org/genproto/README.md delete mode 100644 vendor/google.golang.org/genproto/go.mod delete mode 100644 vendor/google.golang.org/genproto/go.sum delete mode 100644 vendor/google.golang.org/genproto/regen.go delete mode 100755 vendor/google.golang.org/genproto/regen.sh delete mode 100644 vendor/google.golang.org/grpc/CONTRIBUTING.md delete mode 100644 vendor/google.golang.org/grpc/Makefile delete mode 100644 vendor/google.golang.org/grpc/README.md delete mode 100644 vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin_test.go delete mode 100644 vendor/google.golang.org/grpc/balancer_switching_test.go delete mode 100644 vendor/google.golang.org/grpc/balancer_test.go delete mode 100644 vendor/google.golang.org/grpc/call_test.go delete mode 100644 vendor/google.golang.org/grpc/clientconn_state_transition_test.go delete mode 100644 vendor/google.golang.org/grpc/clientconn_test.go delete mode 100644 vendor/google.golang.org/grpc/codec_test.go delete mode 100755 vendor/google.golang.org/grpc/codegen.sh delete mode 100644 vendor/google.golang.org/grpc/codes/codes_test.go delete mode 100644 vendor/google.golang.org/grpc/credentials/credentials_test.go delete mode 100644 vendor/google.golang.org/grpc/credentials/internal/syscallconn_test.go delete mode 100644 vendor/google.golang.org/grpc/encoding/proto/proto_benchmark_test.go delete mode 100644 vendor/google.golang.org/grpc/encoding/proto/proto_test.go delete mode 100644 vendor/google.golang.org/grpc/go.mod delete mode 100644 vendor/google.golang.org/grpc/go.sum delete mode 100644 vendor/google.golang.org/grpc/grpclog/loggerv2_test.go delete mode 100755 vendor/google.golang.org/grpc/install_gae.sh delete mode 100644 vendor/google.golang.org/grpc/internal/binarylog/binarylog_end2end_test.go delete mode 100644 vendor/google.golang.org/grpc/internal/binarylog/binarylog_test.go delete mode 100644 vendor/google.golang.org/grpc/internal/binarylog/env_config_test.go delete mode 100644 vendor/google.golang.org/grpc/internal/binarylog/method_logger_test.go delete mode 100755 vendor/google.golang.org/grpc/internal/binarylog/regenerate.sh delete mode 100644 vendor/google.golang.org/grpc/internal/binarylog/regexp_test.go delete mode 100644 vendor/google.golang.org/grpc/internal/binarylog/util_test.go delete mode 100644 vendor/google.golang.org/grpc/internal/channelz/util_test.go delete mode 100644 vendor/google.golang.org/grpc/internal/grpcsync/event_test.go delete mode 100644 vendor/google.golang.org/grpc/internal/transport/handler_server_test.go delete mode 100644 vendor/google.golang.org/grpc/internal/transport/http_util_test.go delete mode 100644 vendor/google.golang.org/grpc/internal/transport/transport_test.go delete mode 100644 vendor/google.golang.org/grpc/metadata/metadata_test.go delete mode 100644 vendor/google.golang.org/grpc/naming/dns_resolver_test.go delete mode 100644 vendor/google.golang.org/grpc/picker_wrapper_test.go delete mode 100644 vendor/google.golang.org/grpc/pickfirst_test.go delete mode 100644 vendor/google.golang.org/grpc/proxy_test.go delete mode 100644 vendor/google.golang.org/grpc/resolver/dns/dns_resolver_test.go delete mode 100644 vendor/google.golang.org/grpc/resolver_conn_wrapper_test.go delete mode 100644 vendor/google.golang.org/grpc/rpc_util_test.go delete mode 100644 vendor/google.golang.org/grpc/server_test.go delete mode 100644 vendor/google.golang.org/grpc/service_config_test.go delete mode 100644 vendor/google.golang.org/grpc/stats/stats_test.go delete mode 100644 vendor/google.golang.org/grpc/status/status_test.go delete mode 100755 vendor/google.golang.org/grpc/vet.sh diff --git a/Gopkg.lock b/Gopkg.lock index 1a00a5d1..b437e9a3 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -2,166 +2,357 @@ [[projects]] + digest = "1:b62a3c5b37db602bf1158e921da1a762315a4c37855fd418a14498aa87a342d5" name = "cloud.google.com/go" packages = ["civil"] + pruneopts = "NUT" revision = "0ebda48a7f143b1cce9eb37a8c1106ac762a3430" version = "v0.34.0" [[projects]] + digest = "1:f323f98930459f65f4699b5bfba563743680e2633d96e72d61a9732648e2d07c" name = "contrib.go.opencensus.io/exporter/ocagent" packages = ["."] + pruneopts = "NUT" revision = "00af367e65149ff1f2f4b93bbfbb84fd9297170d" version = "v0.2.0" [[projects]] + digest = "1:551eb5689acc063e875cd17d8c667cce5eb298f5c1562273cb886f2f8f81121e" name = "github.com/Azure/azure-sdk-for-go" - packages = ["services/graphrbac/1.6/graphrbac","version"] + packages = [ + "services/graphrbac/1.6/graphrbac", + "version", + ] + pruneopts = "NUT" revision = "1951233eb944a49aa5f7278cba8e3e32a8c958af" version = "v24.0.0" [[projects]] + digest = "1:9b74a0138f67968c3b48282efd29ad08bed3e380cac7589f85418638ed51e8d9" name = "github.com/Azure/go-autorest" - packages = ["autorest","autorest/adal","autorest/azure","autorest/date","autorest/to","autorest/validation","logger","tracing"] + packages = [ + "autorest", + "autorest/adal", + "autorest/azure", + "autorest/date", + "autorest/to", + "autorest/validation", + "logger", + "tracing", + ] + pruneopts = "NUT" revision = "be17756531f50014397912b7aa557ec335e39b98" version = "v11.3.0" [[projects]] + digest = "1:65b0d980b428a6ad4425f2df4cd5410edd81f044cf527bd1c345368444649e58" name = "github.com/census-instrumentation/opencensus-proto" - packages = ["gen-go/agent/common/v1","gen-go/agent/trace/v1","gen-go/resource/v1","gen-go/trace/v1"] + packages = [ + "gen-go/agent/common/v1", + "gen-go/agent/trace/v1", + "gen-go/resource/v1", + "gen-go/trace/v1", + ] + pruneopts = "NUT" revision = "7f2434bc10da710debe5c4315ed6d4df454b4024" version = "v0.1.0" [[projects]] branch = "master" + digest = "1:3a0e8b1ac13f6daa8e6e18b0129a8f1498ade5530fb55cba67c7312ddbb1c78c" name = "github.com/denisenkom/go-mssqldb" - packages = [".","internal/cp"] + packages = [ + ".", + "internal/cp", + ] + pruneopts = "NUT" revision = "2fea367d496dade570d9c1959be58a98a9061522" [[projects]] + digest = "1:7a6852b35eb5bbc184561443762d225116ae630c26a7c4d90546619f1e7d2ad2" name = "github.com/dgrijalva/jwt-go" packages = ["."] + pruneopts = "NUT" revision = "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e" version = "v3.2.0" [[projects]] + digest = "1:13e9a236e56e18fecb73f5b2f2eb7f60060a1a9bc27e5a7328ab22e275ecb63e" name = "github.com/go-sql-driver/mysql" packages = ["."] + pruneopts = "NUT" revision = "72cd26f257d44c1114970e19afddcd812016007e" version = "v1.4.1" [[projects]] branch = "master" + digest = "1:745fa6a19eb7613f207a17b42db0c4425d553fd38ee9387bc686a4b87beb178b" name = "github.com/gokyle/sshkey" - packages = [".","readpass"] + packages = [ + ".", + "readpass", + ] + pruneopts = "NUT" revision = "d32a9ef172a1ec91efdf3ce26b240c946285bfe7" [[projects]] + digest = "1:479e958ad7ae540d7a3c565d1839cc7c8ab9b627640144443f1e88d11d4023d0" name = "github.com/golang/protobuf" - packages = ["proto","ptypes","ptypes/any","ptypes/duration","ptypes/timestamp","ptypes/wrappers"] + packages = [ + "proto", + "ptypes", + "ptypes/any", + "ptypes/duration", + "ptypes/timestamp", + "ptypes/wrappers", + ] + pruneopts = "NUT" revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5" version = "v1.2.0" [[projects]] branch = "hack_global_ref" + digest = "1:a45cc1a5e646cce0742dd386ed88240e0152f7b7fee7ed1cdf9a2356a739c580" name = "github.com/jessevdk/go-flags" packages = ["."] + pruneopts = "NUT" revision = "3e2b0d3b82050426db6ebde363a66b2c7711d8fc" source = "https://github.com/tg123/go-flags" [[projects]] + digest = "1:7f6c7654b72f950f1774b593357ce70314dd0116e3a1ed0e9a02513a73506208" name = "github.com/jinzhu/gorm" - packages = [".","dialects/mssql","dialects/mysql","dialects/postgres","dialects/sqlite"] + packages = [ + ".", + "dialects/mssql", + "dialects/mysql", + "dialects/postgres", + "dialects/sqlite", + ] + pruneopts = "NUT" revision = "472c70caa40267cb89fd8facb07fe6454b578626" version = "v1.9.2" [[projects]] branch = "master" + digest = "1:802f75230c29108e787d40679f9bf5da1a5673eaf5c10eb89afd993e18972909" name = "github.com/jinzhu/inflection" packages = ["."] + pruneopts = "NUT" revision = "04140366298a54a039076d798123ffa108fff46c" [[projects]] + digest = "1:981b5a5a9c05b9f5645e68e2c13dd498a048e8ab0aec07397f33edb3301f2569" name = "github.com/lib/pq" - packages = [".","hstore","oid"] + packages = [ + ".", + "hstore", + "oid", + ] + pruneopts = "NUT" revision = "4ded0e9383f75c197b3a2aaa6d590ac52df6fd79" version = "v1.0.0" [[projects]] + digest = "1:c9724c929d27a14475a45b17a267dbc60671c0bc2c5c05ed21f011f7b5bc9fb5" name = "github.com/mattn/go-sqlite3" packages = ["."] + pruneopts = "NUT" revision = "c7c4067b79cc51e6dfdcef5c702e74b1e0fa7c75" version = "v1.10.0" [[projects]] branch = "master" + digest = "1:15bc31ae39f989dda613930c1de860aced7b922502f8d9d861998fc195b7937c" name = "github.com/msteinert/pam" packages = ["."] + pruneopts = "NUT" revision = "f4cd9f5e29232537a12db1678f48c702ad6896b7" [[projects]] + digest = "1:f2805adeca595d7dbd25173b57f83daaa79f44d43475263c4e34b05020eac9a7" name = "go.opencensus.io" - packages = [".","exemplar","internal","internal/tagencoding","plugin/ochttp","plugin/ochttp/propagation/b3","plugin/ochttp/propagation/tracecontext","stats","stats/internal","stats/view","tag","trace","trace/internal","trace/propagation","trace/tracestate"] + packages = [ + ".", + "exemplar", + "internal", + "internal/tagencoding", + "plugin/ochttp", + "plugin/ochttp/propagation/b3", + "plugin/ochttp/propagation/tracecontext", + "stats", + "stats/internal", + "stats/view", + "tag", + "trace", + "trace/internal", + "trace/propagation", + "trace/tracestate", + ] + pruneopts = "NUT" revision = "b7bf3cdb64150a8c8c53b769fdeb2ba581bd4d4b" version = "v0.18.0" [[projects]] branch = "master" + digest = "1:2d30be27dd2b729c66b70701d20cbae931800b707a5efb8e85546b0314a413a2" name = "golang.org/x/crypto" - packages = ["curve25519","ed25519","ed25519/internal/edwards25519","internal/chacha20","internal/subtle","md4","poly1305","ssh","ssh/knownhosts","ssh/testdata"] + packages = [ + "curve25519", + "ed25519", + "ed25519/internal/edwards25519", + "internal/chacha20", + "internal/subtle", + "md4", + "poly1305", + "ssh", + "ssh/knownhosts", + "ssh/testdata", + ] + pruneopts = "NUT" revision = "0a9e5a7b288dccb74e2efd0fe62005aaf2a6ddbb" source = "https://github.com/tg123/sshpiper.crypto" [[projects]] branch = "master" + digest = "1:e947d55d941f561ff2ecd75221e9befa27dffbdaa4507925e57c1e452ff9f096" name = "golang.org/x/net" - packages = ["context","http/httpguts","http2","http2/hpack","idna","internal/timeseries","trace"] + packages = [ + "context", + "http/httpguts", + "http2", + "http2/hpack", + "idna", + "internal/timeseries", + "trace", + ] + pruneopts = "NUT" revision = "1e06a53dbb7e2ed46e91183f219db23c6943c532" [[projects]] branch = "master" + digest = "1:75515eedc0dc2cb0b40372008b616fa2841d831c63eedd403285ff286c593295" name = "golang.org/x/sync" packages = ["semaphore"] + pruneopts = "NUT" revision = "37e7f081c4d4c64e13b10787722085407fe5d15f" [[projects]] branch = "master" + digest = "1:d3d29753d439e2dd58bab6ed54426db663ffa4673e522971ec14f430d08c6e85" name = "golang.org/x/sys" packages = ["unix"] + pruneopts = "NUT" revision = "7fbe1cd0fcc20051e1fcb87fbabec4a1bacaaeba" [[projects]] + digest = "1:e7071ed636b5422cc51c0e3a6cebc229d6c9fffc528814b519a980641422d619" name = "golang.org/x/text" - packages = ["collate","collate/build","internal/colltab","internal/gen","internal/tag","internal/triegen","internal/ucd","language","secure/bidirule","transform","unicode/bidi","unicode/cldr","unicode/norm","unicode/rangetable"] + packages = [ + "collate", + "collate/build", + "internal/colltab", + "internal/gen", + "internal/tag", + "internal/triegen", + "internal/ucd", + "language", + "secure/bidirule", + "transform", + "unicode/bidi", + "unicode/cldr", + "unicode/norm", + "unicode/rangetable", + ] + pruneopts = "NUT" revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" version = "v0.3.0" [[projects]] + digest = "1:5f003878aabe31d7f6b842d4de32b41c46c214bb629bb485387dbcce1edf5643" name = "google.golang.org/api" packages = ["support/bundler"] + pruneopts = "NUT" revision = "19e022d8cf43ce81f046bae8cc18c5397cc7732f" version = "v0.1.0" [[projects]] + digest = "1:c25289f43ac4a68d88b02245742347c94f1e108c534dda442188015ff80669b3" name = "google.golang.org/appengine" packages = ["cloudsql"] + pruneopts = "NUT" revision = "4a4468ece617fc8205e99368fa2200e9d1fad421" version = "v1.3.0" [[projects]] branch = "master" + digest = "1:077c1c599507b3b3e9156d17d36e1e61928ee9b53a5b420f10f28ebd4a0b275c" name = "google.golang.org/genproto" packages = ["googleapis/rpc/status"] + pruneopts = "NUT" revision = "ae2f86662275e140f395167f1dab7081a5bd5fa8" [[projects]] + digest = "1:638e6e596d67d0a0c8aeb76ebdcf73561b701ea43f21963b1db231d96ed7db68" name = "google.golang.org/grpc" - packages = [".","balancer","balancer/base","balancer/roundrobin","binarylog/grpc_binarylog_v1","codes","connectivity","credentials","credentials/internal","encoding","encoding/proto","grpclog","internal","internal/backoff","internal/binarylog","internal/channelz","internal/envconfig","internal/grpcrand","internal/grpcsync","internal/syscall","internal/transport","keepalive","metadata","naming","peer","resolver","resolver/dns","resolver/passthrough","stats","status","tap"] + packages = [ + ".", + "balancer", + "balancer/base", + "balancer/roundrobin", + "binarylog/grpc_binarylog_v1", + "codes", + "connectivity", + "credentials", + "credentials/internal", + "encoding", + "encoding/proto", + "grpclog", + "internal", + "internal/backoff", + "internal/binarylog", + "internal/channelz", + "internal/envconfig", + "internal/grpcrand", + "internal/grpcsync", + "internal/syscall", + "internal/transport", + "keepalive", + "metadata", + "naming", + "peer", + "resolver", + "resolver/dns", + "resolver/passthrough", + "stats", + "status", + "tap", + ] + pruneopts = "NUT" revision = "df014850f6dee74ba2fc94874043a9f3f75fbfd8" version = "v1.17.0" [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "462e8a5c0f53ae4a78ab2d005630854f64df61142ef3409475ff2b3f1c5640fb" + input-imports = [ + "github.com/Azure/azure-sdk-for-go/services/graphrbac/1.6/graphrbac", + "github.com/Azure/go-autorest/autorest", + "github.com/Azure/go-autorest/autorest/adal", + "github.com/Azure/go-autorest/autorest/azure", + "github.com/go-sql-driver/mysql", + "github.com/gokyle/sshkey", + "github.com/jessevdk/go-flags", + "github.com/jinzhu/gorm", + "github.com/jinzhu/gorm/dialects/mssql", + "github.com/jinzhu/gorm/dialects/mysql", + "github.com/jinzhu/gorm/dialects/postgres", + "github.com/jinzhu/gorm/dialects/sqlite", + "github.com/msteinert/pam", + "golang.org/x/crypto/ssh", + "golang.org/x/crypto/ssh/knownhosts", + "golang.org/x/crypto/ssh/testdata", + ] solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 1add90e3..971d358c 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -20,6 +20,11 @@ # name = "github.com/x/y" # version = "2.4.0" +[prune] + go-tests = true + unused-packages = true + non-go = true + [[constraint]] branch = "master" name = "golang.org/x/crypto" diff --git a/vendor/cloud.google.com/go/CHANGES.md b/vendor/cloud.google.com/go/CHANGES.md deleted file mode 100644 index bec57e0a..00000000 --- a/vendor/cloud.google.com/go/CHANGES.md +++ /dev/null @@ -1,1024 +0,0 @@ -# Changes - -## v0.34.0 - -- functions/metadata: - - Switch to using JSON in context. - - Make Resource a value. -- vision: Fix ProductSearch return type. -- datastore: Add an example for how to handle MultiError. - -## v0.33.1 - -- compute: Removes an erroneously added go.mod. -- logging: Populate source location in fromLogEntry. - -## v0.33.0 - -- bttest: - - Add support for apply_label_transformer. -- expr: - - Add expr library. -- firestore: - - Support retrieval of missing documents. -- kms: - - Add IAM methods. -- pubsub: - - Clarify extension documentation. -- scheduler: - - Add v1beta1 client. -- vision: - - Add product search helper. - - Add new product search client. - -## v0.32.0 - -Note: This release is the last to support Go 1.6 and 1.8. - -- bigquery: - - Add support for removing an expiration. - - Ignore NeverExpire in Table.Create. - - Validate table expiration time. -- cbt: - - Add note about not supporting arbitrary bytes. -- datastore: - - Align key checks. -- firestore: - - Return an error when using Start/End without providing values. -- pubsub: - - Add pstest Close method. - - Clarify MaxExtension documentation. -- securitycenter: - - Add v1beta1 client. -- spanner: - - Allow nil in mutations. - - Improve doc of SessionPoolConfig.MaxOpened. - - Increase session deletion timeout from 5s to 15s. - -## v0.31.0 - -- bigtable: - - Group mutations across multiple requests. -- bigquery: - - Link to bigquery troubleshooting errors page in bigquery.Error comment. -- cbt: - - Fix go generate command. - - Document usage of both maxage + maxversions. -- datastore: - - Passing nil keys results in ErrInvalidKey. -- firestore: - - Clarify what Document.DataTo does with untouched struct fields. -- profile: - - Validate service name in agent. -- pubsub: - - Fix deadlock with pstest and ctx.Cancel. - - Fix a possible deadlock in pstest. -- trace: - - Update doc URL with new fragment. - -Special thanks to @fastest963 for going above and beyond helping us to debug -hard-to-reproduce Pub/Sub issues. - -## v0.30.0 - -- spanner: DML support added. See https://godoc.org/cloud.google.com/go/spanner#hdr-DML_and_Partitioned_DML for more information. -- bigtable: bttest supports row sample filter. -- functions: metadata package added for accessing Cloud Functions resource metadata. - -## v0.29.0 - -- bigtable: - - Add retry to all idempotent RPCs. - - cbt supports complex GC policies. - - Emulator supports arbitrary bytes in regex filters. -- firestore: Add ArrayUnion and ArrayRemove. -- logging: Add the ContextFunc option to supply the context used for - asynchronous RPCs. -- profiler: Ignore NotDefinedError when fetching the instance name -- pubsub: - - BEHAVIOR CHANGE: Receive doesn't retry if an RPC returns codes.Cancelled. - - BEHAVIOR CHANGE: Receive retries on Unavailable intead of returning. - - Fix deadlock. - - Restore Ack/Nack/Modacks metrics. - - Improve context handling in iterator. - - Implement synchronous mode for Receive. - - pstest: add Pull. -- spanner: Add a metric for the number of sessions currently opened. -- storage: - - Canceling the context releases all resources. - - Add additional RetentionPolicy attributes. -- vision/apiv1: Add LocalizeObjects method. - -## v0.28.0 - -- bigtable: - - Emulator returns Unimplemented for snapshot RPCs. -- bigquery: - - Support zero-length repeated, nested fields. -- cloud assets: - - Add v1beta client. -- datastore: - - Don't nil out transaction ID on retry. -- firestore: - - BREAKING CHANGE: When watching a query with Query.Snapshots, QuerySnapshotIterator.Next - returns a QuerySnapshot which contains read time, result size, change list and the DocumentIterator - (previously, QuerySnapshotIterator.Next returned just the DocumentIterator). See: https://godoc.org/cloud.google.com/go/firestore#Query.Snapshots. - - Add array-contains operator. -- IAM: - - Add iam/credentials/apiv1 client. -- pubsub: - - Canceling the context passed to Subscription.Receive causes Receive to return when - processing finishes on all messages currently in progress, even if new messages are arriving. -- redis: - - Add redis/apiv1 client. -- storage: - - Add Reader.Attrs. - - Deprecate several Reader getter methods: please use Reader.Attrs for these instead. - - Add ObjectHandle.Bucket and ObjectHandle.Object methods. - -## v0.27.0 - -- bigquery: - - Allow modification of encryption configuration and partitioning options to a table via the Update call. - - Add a SchemaFromJSON function that converts a JSON table schema. -- bigtable: - - Restore cbt count functionality. -- containeranalysis: - - Add v1beta client. -- spanner: - - Fix a case where an iterator might not be closed correctly. -- storage: - - Add ServiceAccount method https://godoc.org/cloud.google.com/go/storage#Client.ServiceAccount. - - Add a method to Reader that returns the parsed value of the Last-Modified header. - -## v0.26.0 - -- bigquery: - - Support filtering listed jobs by min/max creation time. - - Support data clustering (https://godoc.org/cloud.google.com/go/bigquery#Clustering). - - Include job creator email in Job struct. -- bigtable: - - Add `RowSampleFilter`. - - emulator: BREAKING BEHAVIOR CHANGE: Regexps in row, family, column and value filters - must match the entire target string to succeed. Previously, the emulator was - succeeding on partial matches. - NOTE: As of this release, this change only affects the emulator when run - from this repo (bigtable/cmd/emulator/cbtemulator.go). The version launched - from `gcloud` will be updated in a subsequent `gcloud` release. -- dataproc: Add apiv1beta2 client. -- datastore: Save non-nil pointer fields on omitempty. -- logging: populate Entry.Trace from the HTTP X-Cloud-Trace-Context header. -- logging/logadmin: Support writer_identity and include_children. -- pubsub: - - Support labels on topics and subscriptions. - - Support message storage policy for topics. - - Use the distribution of ack times to determine when to extend ack deadlines. - The only user-visible effect of this change should be that programs that - call only `Subscription.Receive` need no IAM permissions other than `Pub/Sub - Subscriber`. -- storage: - - Support predefined ACLs. - - Support additional ACL fields other than Entity and Role. - - Support bucket websites. - - Support bucket logging. - - -## v0.25.0 - -- Added [Code of Conduct](https://github.com/GoogleCloudPlatform/google-cloud-go/blob/master/CODE_OF_CONDUCT.md) -- bigtable: - - cbt: Support a GC policy of "never". -- errorreporting: - - Support User. - - Close now calls Flush. - - Use OnError (previously ignored). - - Pass through the RPC error as-is to OnError. -- httpreplay: A tool for recording and replaying HTTP requests - (for the bigquery and storage clients in this repo). -- kms: v1 client added -- logging: add SourceLocation to Entry. -- storage: improve CRC checking on read. - -## v0.24.0 - -- bigquery: Support for the NUMERIC type. -- bigtable: - - cbt: Optionally specify columns for read/lookup - - Support instance-level administration. -- oslogin: New client for the OS Login API. -- pubsub: - - The package is now stable. There will be no further breaking changes. - - Internal changes to improve Subscription.Receive behavior. -- storage: Support updating bucket lifecycle config. -- spanner: Support struct-typed parameter bindings. -- texttospeech: New client for the Text-to-Speech API. - -## v0.23.0 - -- bigquery: Add DDL stats to query statistics. -- bigtable: - - cbt: Add cells-per-column limit for row lookup. - - cbt: Make it possible to combine read filters. -- dlp: v2beta2 client removed. Use the v2 client instead. -- firestore, spanner: Fix compilation errors due to protobuf changes. - -## v0.22.0 - -- bigtable: - - cbt: Support cells per column limit for row read. - - bttest: Correctly handle empty RowSet. - - Fix ReadModifyWrite operation in emulator. - - Fix API path in GetCluster. - -- bigquery: - - BEHAVIOR CHANGE: Retry on 503 status code. - - Add dataset.DeleteWithContents. - - Add SchemaUpdateOptions for query jobs. - - Add Timeline to QueryStatistics. - - Add more stats to ExplainQueryStage. - - Support Parquet data format. - -- datastore: - - Support omitempty for times. - -- dlp: - - **BREAKING CHANGE:** Remove v1beta1 client. Please migrate to the v2 client, - which is now out of beta. - - Add v2 client. - -- firestore: - - BEHAVIOR CHANGE: Treat set({}, MergeAll) as valid. - -- iam: - - Support JWT signing via SignJwt callopt. - -- profiler: - - BEHAVIOR CHANGE: PollForSerialOutput returns an error when context.Done. - - BEHAVIOR CHANGE: Increase the initial backoff to 1 minute. - - Avoid returning empty serial port output. - -- pubsub: - - BEHAVIOR CHANGE: Don't backoff during next retryable error once stream is healthy. - - BEHAVIOR CHANGE: Don't backoff on EOF. - - pstest: Support Acknowledge and ModifyAckDeadline RPCs. - -- redis: - - Add v1 beta Redis client. - -- spanner: - - Support SessionLabels. - -- speech: - - Add api v1 beta1 client. - -- storage: - - BEHAVIOR CHANGE: Retry reads when retryable error occurs. - - Fix delete of object in requester-pays bucket. - - Support KMS integration. - -## v0.21.0 - -- bigquery: - - Add OpenCensus tracing. - -- firestore: - - **BREAKING CHANGE:** If a document does not exist, return a DocumentSnapshot - whose Exists method returns false. DocumentRef.Get and Transaction.Get - return the non-nil DocumentSnapshot in addition to a NotFound error. - **DocumentRef.GetAll and Transaction.GetAll return a non-nil - DocumentSnapshot instead of nil.** - - Add DocumentIterator.Stop. **Call Stop whenever you are done with a - DocumentIterator.** - - Added Query.Snapshots and DocumentRef.Snapshots, which provide realtime - notification of updates. See https://cloud.google.com/firestore/docs/query-data/listen. - - Canceling an RPC now always returns a grpc.Status with codes.Canceled. - -- spanner: - - Add `CommitTimestamp`, which supports inserting the commit timestamp of a - transaction into a column. - -## v0.20.0 - -- bigquery: Support SchemaUpdateOptions for load jobs. - -- bigtable: - - Add SampleRowKeys. - - cbt: Support union, intersection GCPolicy. - - Retry admin RPCS. - - Add trace spans to retries. - -- datastore: Add OpenCensus tracing. - -- firestore: - - Fix queries involving Null and NaN. - - Allow Timestamp protobuffers for time values. - -- logging: Add a WriteTimeout option. - -- spanner: Support Batch API. - -- storage: Add OpenCensus tracing. - -## v0.19.0 - -- bigquery: - - Support customer-managed encryption keys. - -- bigtable: - - Improved emulator support. - - Support GetCluster. - -- datastore: - - Add general mutations. - - Support pointer struct fields. - - Support transaction options. - -- firestore: - - Add Transaction.GetAll. - - Support document cursors. - -- logging: - - Support concurrent RPCs to the service. - - Support per-entry resources. - -- profiler: - - Add config options to disable heap and thread profiling. - - Read the project ID from $GOOGLE_CLOUD_PROJECT when it's set. - -- pubsub: - - BEHAVIOR CHANGE: Release flow control after ack/nack (instead of after the - callback returns). - - Add SubscriptionInProject. - - Add OpenCensus instrumentation for streaming pull. - -- storage: - - Support CORS. - -## v0.18.0 - -- bigquery: - - Marked stable. - - Schema inference of nullable fields supported. - - Added TimePartitioning to QueryConfig. - -- firestore: Data provided to DocumentRef.Set with a Merge option can contain - Delete sentinels. - -- logging: Clients can accept parent resources other than projects. - -- pubsub: - - pubsub/pstest: A lighweight fake for pubsub. Experimental; feedback welcome. - - Support updating more subscription metadata: AckDeadline, - RetainAckedMessages and RetentionDuration. - -- oslogin/apiv1beta: New client for the Cloud OS Login API. - -- rpcreplay: A package for recording and replaying gRPC traffic. - -- spanner: - - Add a ReadWithOptions that supports a row limit, as well as an index. - - Support query plan and execution statistics. - - Added [OpenCensus](http://opencensus.io) support. - -- storage: Clarify checksum validation for gzipped files (it is not validated - when the file is served uncompressed). - - -## v0.17.0 - -- firestore BREAKING CHANGES: - - Remove UpdateMap and UpdateStruct; rename UpdatePaths to Update. - Change - `docref.UpdateMap(ctx, map[string]interface{}{"a.b", 1})` - to - `docref.Update(ctx, []firestore.Update{{Path: "a.b", Value: 1}})` - - Change - `docref.UpdateStruct(ctx, []string{"Field"}, aStruct)` - to - `docref.Update(ctx, []firestore.Update{{Path: "Field", Value: aStruct.Field}})` - - Rename MergePaths to Merge; require args to be FieldPaths - - A value stored as an integer can be read into a floating-point field, and vice versa. -- bigtable/cmd/cbt: - - Support deleting a column. - - Add regex option for row read. -- spanner: Mark stable. -- storage: - - Add Reader.ContentEncoding method. - - Fix handling of SignedURL headers. -- bigquery: - - If Uploader.Put is called with no rows, it returns nil without making a - call. - - Schema inference supports the "nullable" option in struct tags for - non-required fields. - - TimePartitioning supports "Field". - - -## v0.16.0 - -- Other bigquery changes: - - `JobIterator.Next` returns `*Job`; removed `JobInfo` (BREAKING CHANGE). - - UseStandardSQL is deprecated; set UseLegacySQL to true if you need - Legacy SQL. - - Uploader.Put will generate a random insert ID if you do not provide one. - - Support time partitioning for load jobs. - - Support dry-run queries. - - A `Job` remembers its last retrieved status. - - Support retrieving job configuration. - - Support labels for jobs and tables. - - Support dataset access lists. - - Improve support for external data sources, including data from Bigtable and - Google Sheets, and tables with external data. - - Support updating a table's view configuration. - - Fix uploading civil times with nanoseconds. - -- storage: - - Support PubSub notifications. - - Support Requester Pays buckets. - -- profiler: Support goroutine and mutex profile types. - -## v0.15.0 - -- firestore: beta release. See the - [announcement](https://firebase.googleblog.com/2017/10/introducing-cloud-firestore.html). - -- errorreporting: The existing package has been redesigned. - -- errors: This package has been removed. Use errorreporting. - - -## v0.14.0 - -- bigquery BREAKING CHANGES: - - Standard SQL is the default for queries and views. - - `Table.Create` takes `TableMetadata` as a second argument, instead of - options. - - `Dataset.Create` takes `DatasetMetadata` as a second argument. - - `DatasetMetadata` field `ID` renamed to `FullID` - - `TableMetadata` field `ID` renamed to `FullID` - -- Other bigquery changes: - - The client will append a random suffix to a provided job ID if you set - `AddJobIDSuffix` to true in a job config. - - Listing jobs is supported. - - Better retry logic. - -- vision, language, speech: clients are now stable - -- monitoring: client is now beta - -- profiler: - - Rename InstanceName to Instance, ZoneName to Zone - - Auto-detect service name and version on AppEngine. - -## v0.13.0 - -- bigquery: UseLegacySQL options for CreateTable and QueryConfig. Use these - options to continue using Legacy SQL after the client switches its default - to Standard SQL. - -- bigquery: Support for updating dataset labels. - -- bigquery: Set DatasetIterator.ProjectID to list datasets in a project other - than the client's. DatasetsInProject is no longer needed and is deprecated. - -- bigtable: Fail ListInstances when any zones fail. - -- spanner: support decoding of slices of basic types (e.g. []string, []int64, - etc.) - -- logging/logadmin: UpdateSink no longer creates a sink if it is missing - (actually a change to the underlying service, not the client) - -- profiler: Service and ServiceVersion replace Target in Config. - -## v0.12.0 - -- pubsub: Subscription.Receive now uses streaming pull. - -- pubsub: add Client.TopicInProject to access topics in a different project - than the client. - -- errors: renamed errorreporting. The errors package will be removed shortly. - -- datastore: improved retry behavior. - -- bigquery: support updates to dataset metadata, with etags. - -- bigquery: add etag support to Table.Update (BREAKING: etag argument added). - -- bigquery: generate all job IDs on the client. - -- storage: support bucket lifecycle configurations. - - -## v0.11.0 - -- Clients for spanner, pubsub and video are now in beta. - -- New client for DLP. - -- spanner: performance and testing improvements. - -- storage: requester-pays buckets are supported. - -- storage, profiler, bigtable, bigquery: bug fixes and other minor improvements. - -- pubsub: bug fixes and other minor improvements - -## v0.10.0 - -- pubsub: Subscription.ModifyPushConfig replaced with Subscription.Update. - -- pubsub: Subscription.Receive now runs concurrently for higher throughput. - -- vision: cloud.google.com/go/vision is deprecated. Use -cloud.google.com/go/vision/apiv1 instead. - -- translation: now stable. - -- trace: several changes to the surface. See the link below. - -### Code changes required from v0.9.0 - -- pubsub: Replace - - ``` - sub.ModifyPushConfig(ctx, pubsub.PushConfig{Endpoint: "https://example.com/push"}) - ``` - - with - - ``` - sub.Update(ctx, pubsub.SubscriptionConfigToUpdate{ - PushConfig: &pubsub.PushConfig{Endpoint: "https://example.com/push"}, - }) - ``` - -- trace: traceGRPCServerInterceptor will be provided from *trace.Client. -Given an initialized `*trace.Client` named `tc`, instead of - - ``` - s := grpc.NewServer(grpc.UnaryInterceptor(trace.GRPCServerInterceptor(tc))) - ``` - - write - - ``` - s := grpc.NewServer(grpc.UnaryInterceptor(tc.GRPCServerInterceptor())) - ``` - -- trace trace.GRPCClientInterceptor will also provided from *trace.Client. -Instead of - - ``` - conn, err := grpc.Dial(srv.Addr, grpc.WithUnaryInterceptor(trace.GRPCClientInterceptor())) - ``` - - write - - ``` - conn, err := grpc.Dial(srv.Addr, grpc.WithUnaryInterceptor(tc.GRPCClientInterceptor())) - ``` - -- trace: We removed the deprecated `trace.EnableGRPCTracing`. Use the gRPC -interceptor as a dial option as shown below when initializing Cloud package -clients: - - ``` - c, err := pubsub.NewClient(ctx, "project-id", option.WithGRPCDialOption(grpc.WithUnaryInterceptor(tc.GRPCClientInterceptor()))) - if err != nil { - ... - } - ``` - - -## v0.9.0 - -- Breaking changes to some autogenerated clients. -- rpcreplay package added. - -## v0.8.0 - -- profiler package added. -- storage: - - Retry Objects.Insert call. - - Add ProgressFunc to WRiter. -- pubsub: breaking changes: - - Publish is now asynchronous ([announcement](https://groups.google.com/d/topic/google-api-go-announce/aaqRDIQ3rvU/discussion)). - - Subscription.Pull replaced by Subscription.Receive, which takes a callback ([announcement](https://groups.google.com/d/topic/google-api-go-announce/8pt6oetAdKc/discussion)). - - Message.Done replaced with Message.Ack and Message.Nack. - -## v0.7.0 - -- Release of a client library for Spanner. See -the -[blog -post](https://cloudplatform.googleblog.com/2017/02/introducing-Cloud-Spanner-a-global-database-service-for-mission-critical-applications.html). -Note that although the Spanner service is beta, the Go client library is alpha. - -## v0.6.0 - -- Beta release of BigQuery, DataStore, Logging and Storage. See the -[blog post](https://cloudplatform.googleblog.com/2016/12/announcing-new-google-cloud-client.html). - -- bigquery: - - struct support. Read a row directly into a struct with -`RowIterator.Next`, and upload a row directly from a struct with `Uploader.Put`. -You can also use field tags. See the [package documentation][cloud-bigquery-ref] -for details. - - - The `ValueList` type was removed. It is no longer necessary. Instead of - ```go - var v ValueList - ... it.Next(&v) .. - ``` - use - - ```go - var v []Value - ... it.Next(&v) ... - ``` - - - Previously, repeatedly calling `RowIterator.Next` on the same `[]Value` or - `ValueList` would append to the slice. Now each call resets the size to zero first. - - - Schema inference will infer the SQL type BYTES for a struct field of - type []byte. Previously it inferred STRING. - - - The types `uint`, `uint64` and `uintptr` are no longer supported in schema - inference. BigQuery's integer type is INT64, and those types may hold values - that are not correctly represented in a 64-bit signed integer. - -## v0.5.0 - -- bigquery: - - The SQL types DATE, TIME and DATETIME are now supported. They correspond to - the `Date`, `Time` and `DateTime` types in the new `cloud.google.com/go/civil` - package. - - Support for query parameters. - - Support deleting a dataset. - - Values from INTEGER columns will now be returned as int64, not int. This - will avoid errors arising from large values on 32-bit systems. -- datastore: - - Nested Go structs encoded as Entity values, instead of a -flattened list of the embedded struct's fields. This means that you may now have twice-nested slices, eg. - ```go - type State struct { - Cities []struct{ - Populations []int - } - } - ``` - See [the announcement](https://groups.google.com/forum/#!topic/google-api-go-announce/79jtrdeuJAg) for -more details. - - Contexts no longer hold namespaces; instead you must set a key's namespace - explicitly. Also, key functions have been changed and renamed. - - The WithNamespace function has been removed. To specify a namespace in a Query, use the Query.Namespace method: - ```go - q := datastore.NewQuery("Kind").Namespace("ns") - ``` - - All the fields of Key are exported. That means you can construct any Key with a struct literal: - ```go - k := &Key{Kind: "Kind", ID: 37, Namespace: "ns"} - ``` - - As a result of the above, the Key methods Kind, ID, d.Name, Parent, SetParent and Namespace have been removed. - - `NewIncompleteKey` has been removed, replaced by `IncompleteKey`. Replace - ```go - NewIncompleteKey(ctx, kind, parent) - ``` - with - ```go - IncompleteKey(kind, parent) - ``` - and if you do use namespaces, make sure you set the namespace on the returned key. - - `NewKey` has been removed, replaced by `NameKey` and `IDKey`. Replace - ```go - NewKey(ctx, kind, name, 0, parent) - NewKey(ctx, kind, "", id, parent) - ``` - with - ```go - NameKey(kind, name, parent) - IDKey(kind, id, parent) - ``` - and if you do use namespaces, make sure you set the namespace on the returned key. - - The `Done` variable has been removed. Replace `datastore.Done` with `iterator.Done`, from the package `google.golang.org/api/iterator`. - - The `Client.Close` method will have a return type of error. It will return the result of closing the underlying gRPC connection. - - See [the announcement](https://groups.google.com/forum/#!topic/google-api-go-announce/hqXtM_4Ix-0) for -more details. - -## v0.4.0 - -- bigquery: - -`NewGCSReference` is now a function, not a method on `Client`. - - `Table.LoaderFrom` now accepts a `ReaderSource`, enabling - loading data into a table from a file or any `io.Reader`. - * Client.Table and Client.OpenTable have been removed. - Replace - ```go - client.OpenTable("project", "dataset", "table") - ``` - with - ```go - client.DatasetInProject("project", "dataset").Table("table") - ``` - - * Client.CreateTable has been removed. - Replace - ```go - client.CreateTable(ctx, "project", "dataset", "table") - ``` - with - ```go - client.DatasetInProject("project", "dataset").Table("table").Create(ctx) - ``` - - * Dataset.ListTables have been replaced with Dataset.Tables. - Replace - ```go - tables, err := ds.ListTables(ctx) - ``` - with - ```go - it := ds.Tables(ctx) - for { - table, err := it.Next() - if err == iterator.Done { - break - } - if err != nil { - // TODO: Handle error. - } - // TODO: use table. - } - ``` - - * Client.Read has been replaced with Job.Read, Table.Read and Query.Read. - Replace - ```go - it, err := client.Read(ctx, job) - ``` - with - ```go - it, err := job.Read(ctx) - ``` - and similarly for reading from tables or queries. - - * The iterator returned from the Read methods is now named RowIterator. Its - behavior is closer to the other iterators in these libraries. It no longer - supports the Schema method; see the next item. - Replace - ```go - for it.Next(ctx) { - var vals ValueList - if err := it.Get(&vals); err != nil { - // TODO: Handle error. - } - // TODO: use vals. - } - if err := it.Err(); err != nil { - // TODO: Handle error. - } - ``` - with - ``` - for { - var vals ValueList - err := it.Next(&vals) - if err == iterator.Done { - break - } - if err != nil { - // TODO: Handle error. - } - // TODO: use vals. - } - ``` - Instead of the `RecordsPerRequest(n)` option, write - ```go - it.PageInfo().MaxSize = n - ``` - Instead of the `StartIndex(i)` option, write - ```go - it.StartIndex = i - ``` - - * ValueLoader.Load now takes a Schema in addition to a slice of Values. - Replace - ```go - func (vl *myValueLoader) Load(v []bigquery.Value) - ``` - with - ```go - func (vl *myValueLoader) Load(v []bigquery.Value, s bigquery.Schema) - ``` - - - * Table.Patch is replace by Table.Update. - Replace - ```go - p := table.Patch() - p.Description("new description") - metadata, err := p.Apply(ctx) - ``` - with - ```go - metadata, err := table.Update(ctx, bigquery.TableMetadataToUpdate{ - Description: "new description", - }) - ``` - - * Client.Copy is replaced by separate methods for each of its four functions. - All options have been replaced by struct fields. - - * To load data from Google Cloud Storage into a table, use Table.LoaderFrom. - - Replace - ```go - client.Copy(ctx, table, gcsRef) - ``` - with - ```go - table.LoaderFrom(gcsRef).Run(ctx) - ``` - Instead of passing options to Copy, set fields on the Loader: - ```go - loader := table.LoaderFrom(gcsRef) - loader.WriteDisposition = bigquery.WriteTruncate - ``` - - * To extract data from a table into Google Cloud Storage, use - Table.ExtractorTo. Set fields on the returned Extractor instead of - passing options. - - Replace - ```go - client.Copy(ctx, gcsRef, table) - ``` - with - ```go - table.ExtractorTo(gcsRef).Run(ctx) - ``` - - * To copy data into a table from one or more other tables, use - Table.CopierFrom. Set fields on the returned Copier instead of passing options. - - Replace - ```go - client.Copy(ctx, dstTable, srcTable) - ``` - with - ```go - dst.Table.CopierFrom(srcTable).Run(ctx) - ``` - - * To start a query job, create a Query and call its Run method. Set fields - on the query instead of passing options. - - Replace - ```go - client.Copy(ctx, table, query) - ``` - with - ```go - query.Run(ctx) - ``` - - * Table.NewUploader has been renamed to Table.Uploader. Instead of options, - configure an Uploader by setting its fields. - Replace - ```go - u := table.NewUploader(bigquery.UploadIgnoreUnknownValues()) - ``` - with - ```go - u := table.NewUploader(bigquery.UploadIgnoreUnknownValues()) - u.IgnoreUnknownValues = true - ``` - -- pubsub: remove `pubsub.Done`. Use `iterator.Done` instead, where `iterator` is the package -`google.golang.org/api/iterator`. - -## v0.3.0 - -- storage: - * AdminClient replaced by methods on Client. - Replace - ```go - adminClient.CreateBucket(ctx, bucketName, attrs) - ``` - with - ```go - client.Bucket(bucketName).Create(ctx, projectID, attrs) - ``` - - * BucketHandle.List replaced by BucketHandle.Objects. - Replace - ```go - for query != nil { - objs, err := bucket.List(d.ctx, query) - if err != nil { ... } - query = objs.Next - for _, obj := range objs.Results { - fmt.Println(obj) - } - } - ``` - with - ```go - iter := bucket.Objects(d.ctx, query) - for { - obj, err := iter.Next() - if err == iterator.Done { - break - } - if err != nil { ... } - fmt.Println(obj) - } - ``` - (The `iterator` package is at `google.golang.org/api/iterator`.) - - Replace `Query.Cursor` with `ObjectIterator.PageInfo().Token`. - - Replace `Query.MaxResults` with `ObjectIterator.PageInfo().MaxSize`. - - - * ObjectHandle.CopyTo replaced by ObjectHandle.CopierFrom. - Replace - ```go - attrs, err := src.CopyTo(ctx, dst, nil) - ``` - with - ```go - attrs, err := dst.CopierFrom(src).Run(ctx) - ``` - - Replace - ```go - attrs, err := src.CopyTo(ctx, dst, &storage.ObjectAttrs{ContextType: "text/html"}) - ``` - with - ```go - c := dst.CopierFrom(src) - c.ContextType = "text/html" - attrs, err := c.Run(ctx) - ``` - - * ObjectHandle.ComposeFrom replaced by ObjectHandle.ComposerFrom. - Replace - ```go - attrs, err := dst.ComposeFrom(ctx, []*storage.ObjectHandle{src1, src2}, nil) - ``` - with - ```go - attrs, err := dst.ComposerFrom(src1, src2).Run(ctx) - ``` - - * ObjectHandle.Update's ObjectAttrs argument replaced by ObjectAttrsToUpdate. - Replace - ```go - attrs, err := obj.Update(ctx, &storage.ObjectAttrs{ContextType: "text/html"}) - ``` - with - ```go - attrs, err := obj.Update(ctx, storage.ObjectAttrsToUpdate{ContextType: "text/html"}) - ``` - - * ObjectHandle.WithConditions replaced by ObjectHandle.If. - Replace - ```go - obj.WithConditions(storage.Generation(gen), storage.IfMetaGenerationMatch(mgen)) - ``` - with - ```go - obj.Generation(gen).If(storage.Conditions{MetagenerationMatch: mgen}) - ``` - - Replace - ```go - obj.WithConditions(storage.IfGenerationMatch(0)) - ``` - with - ```go - obj.If(storage.Conditions{DoesNotExist: true}) - ``` - - * `storage.Done` replaced by `iterator.Done` (from package `google.golang.org/api/iterator`). - -- Package preview/logging deleted. Use logging instead. - -## v0.2.0 - -- Logging client replaced with preview version (see below). - -- New clients for some of Google's Machine Learning APIs: Vision, Speech, and -Natural Language. - -- Preview version of a new [Stackdriver Logging][cloud-logging] client in -[`cloud.google.com/go/preview/logging`](https://godoc.org/cloud.google.com/go/preview/logging). -This client uses gRPC as its transport layer, and supports log reading, sinks -and metrics. It will replace the current client at `cloud.google.com/go/logging` shortly. - - diff --git a/vendor/cloud.google.com/go/CODE_OF_CONDUCT.md b/vendor/cloud.google.com/go/CODE_OF_CONDUCT.md deleted file mode 100644 index 8fd1bc9c..00000000 --- a/vendor/cloud.google.com/go/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,44 +0,0 @@ -# Contributor Code of Conduct - -As contributors and maintainers of this project, -and in the interest of fostering an open and welcoming community, -we pledge to respect all people who contribute through reporting issues, -posting feature requests, updating documentation, -submitting pull requests or patches, and other activities. - -We are committed to making participation in this project -a harassment-free experience for everyone, -regardless of level of experience, gender, gender identity and expression, -sexual orientation, disability, personal appearance, -body size, race, ethnicity, age, religion, or nationality. - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery -* Personal attacks -* Trolling or insulting/derogatory comments -* Public or private harassment -* Publishing other's private information, -such as physical or electronic -addresses, without explicit permission -* Other unethical or unprofessional conduct. - -Project maintainers have the right and responsibility to remove, edit, or reject -comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct. -By adopting this Code of Conduct, -project maintainers commit themselves to fairly and consistently -applying these principles to every aspect of managing this project. -Project maintainers who do not follow or enforce the Code of Conduct -may be permanently removed from the project team. - -This code of conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. - -Instances of abusive, harassing, or otherwise unacceptable behavior -may be reported by opening an issue -or contacting one or more of the project maintainers. - -This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, -available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/) - diff --git a/vendor/cloud.google.com/go/CONTRIBUTING.md b/vendor/cloud.google.com/go/CONTRIBUTING.md deleted file mode 100644 index eef41ed0..00000000 --- a/vendor/cloud.google.com/go/CONTRIBUTING.md +++ /dev/null @@ -1,234 +0,0 @@ -# Contributing - -1. Sign one of the contributor license agreements below. -1. `go get golang.org/x/review/git-codereview` to install the code reviewing -tool. - 1. You will need to ensure that your `GOBIN` directory (by default - `$GOPATH/bin`) is in your `PATH` so that git can find the command. - 1. If you would like, you may want to set up aliases for git-codereview, - such that `git codereview change` becomes `git change`. See the - [godoc](https://godoc.org/golang.org/x/review/git-codereview) for details. - 1. Should you run into issues with the git-codereview tool, please note - that all error messages will assume that you have set up these aliases. -1. Get the cloud package by running `go get -d cloud.google.com/go`. - 1. If you have already checked out the source, make sure that the remote - git origin is https://code.googlesource.com/gocloud: - - ``` - git remote set-url origin https://code.googlesource.com/gocloud - ``` - -1. Make sure your auth is configured correctly by visiting -https://code.googlesource.com, clicking "Generate Password", and following the -directions. -1. Make changes and create a change by running `git codereview change `, -provide a commit message, and use `git codereview mail` to create a Gerrit CL. -1. Keep amending to the change with `git codereview change` and mail as your -receive feedback. Each new mailed amendment will create a new patch set for -your change in Gerrit. - -## Integration Tests - -In addition to the unit tests, you may run the integration test suite. These -directions describe setting up your environment to run integration tests for -_all_ packages: note that many of these instructions may be redundant if you -intend only to run integration tests on a single package. - -#### GCP Setup - -To run the integrations tests, creation and configuration of two projects in -the Google Developers Console is required: one specifically for Firestore -integration tests, and another for all other integration tests. We'll refer to -these projects as "general project" and "Firestore project". - -After creating each project, you must [create a service account](https://developers.google.com/identity/protocols/OAuth2ServiceAccount#creatinganaccount) -for each project. Ensure the project-level **Owner** -[IAM role](console.cloud.google.com/iam-admin/iam/project) role is added to -each service account. During the creation of the service account, you should -download the JSON credential file for use later. - -Next, ensure the following APIs are enabled in the general project: - -- BigQuery API -- BigQuery Data Transfer API -- Cloud Dataproc API -- Cloud Dataproc Control API Private -- Cloud Datastore API -- Cloud Firestore API -- Cloud Key Management Service (KMS) API -- Cloud Natural Language API -- Cloud OS Login API -- Cloud Pub/Sub API -- Cloud Resource Manager API -- Cloud Spanner API -- Cloud Speech API -- Cloud Translation API -- Cloud Video Intelligence API -- Cloud Vision API -- Compute Engine API -- Compute Engine Instance Group Manager API -- Container Registry API -- Firebase Rules API -- Google Cloud APIs -- Google Cloud Deployment Manager V2 API -- Google Cloud SQL -- Google Cloud Storage -- Google Cloud Storage JSON API -- Google Compute Engine Instance Group Updater API -- Google Compute Engine Instance Groups API -- Kubernetes Engine API -- Stackdriver Error Reporting API - -Next, create a Datastore database in the general project, and a Firestore -database in the Firestore project. - -Finally, in the general project, create an API key for the translate API: - -- Go to GCP Developer Console. -- Navigate to APIs & Services > Credentials. -- Click Create Credentials > API Key. -- Save this key for use in `GCLOUD_TESTS_API_KEY` as described below. - -#### Local Setup - -Once the two projects are created and configured, set the following environment -variables: - -- `GCLOUD_TESTS_GOLANG_PROJECT_ID`: Developers Console project's ID (e.g. -bamboo-shift-455) for the general project. -- `GCLOUD_TESTS_GOLANG_KEY`: The path to the JSON key file of the general -project's service account. -- `GCLOUD_TESTS_GOLANG_FIRESTORE_PROJECT_ID`: Developers Console project's ID -(e.g. doorway-cliff-677) for the Firestore project. -- `GCLOUD_TESTS_GOLANG_FIRESTORE_KEY`: The path to the JSON key file of the -Firestore project's service account. -- `GCLOUD_TESTS_GOLANG_KEYRING`: The full name of the keyring for the tests, -in the form -"projects/P/locations/L/keyRings/R". The creation of this is described below. -- `GCLOUD_TESTS_API_KEY`: API key for using the Translate API. -- `GCLOUD_TESTS_GOLANG_ZONE`: Compute Engine zone. - -Install the [gcloud command-line tool][gcloudcli] to your machine and use it to -create some resources used in integration tests. - -From the project's root directory: - -``` sh -# Sets the default project in your env. -$ gcloud config set project $GCLOUD_TESTS_GOLANG_PROJECT_ID - -# Authenticates the gcloud tool with your account. -$ gcloud auth login - -# Create the indexes used in the datastore integration tests. -$ gcloud datastore create-indexes datastore/testdata/index.yaml - -# Creates a Google Cloud storage bucket with the same name as your test project, -# and with the Stackdriver Logging service account as owner, for the sink -# integration tests in logging. -$ gsutil mb gs://$GCLOUD_TESTS_GOLANG_PROJECT_ID -$ gsutil acl ch -g cloud-logs@google.com:O gs://$GCLOUD_TESTS_GOLANG_PROJECT_ID - -# Creates a PubSub topic for integration tests of storage notifications. -$ gcloud beta pubsub topics create go-storage-notification-test -# Next, go to the Pub/Sub dashboard in GCP console. Authorize the user -# "service-@gs-project-accounts.iam.gserviceaccount.com" -# as a publisher to that topic. - -# Creates a Spanner instance for the spanner integration tests. -$ gcloud beta spanner instances create go-integration-test --config regional-us-central1 --nodes 10 --description 'Instance for go client test' -# NOTE: Spanner instances are priced by the node-hour, so you may want to -# delete the instance after testing with 'gcloud beta spanner instances delete'. - -$ export MY_KEYRING=some-keyring-name -$ export MY_LOCATION=global -# Creates a KMS keyring, in the same location as the default location for your -# project's buckets. -$ gcloud kms keyrings create $MY_KEYRING --location $MY_LOCATION -# Creates two keys in the keyring, named key1 and key2. -$ gcloud kms keys create key1 --keyring $MY_KEYRING --location $MY_LOCATION --purpose encryption -$ gcloud kms keys create key2 --keyring $MY_KEYRING --location $MY_LOCATION --purpose encryption -# Sets the GCLOUD_TESTS_GOLANG_KEYRING environment variable. -$ export GCLOUD_TESTS_GOLANG_KEYRING=projects/$GCLOUD_TESTS_GOLANG_PROJECT_ID/locations/$MY_LOCATION/keyRings/$MY_KEYRING -# Authorizes Google Cloud Storage to encrypt and decrypt using key1. -gsutil kms authorize -p $GCLOUD_TESTS_GOLANG_PROJECT_ID -k $GCLOUD_TESTS_GOLANG_KEYRING/cryptoKeys/key1 -``` - -#### Running - -Once you've done the necessary setup, you can run the integration tests by -running: - -``` sh -$ go test -v cloud.google.com/go/... -``` - -#### Replay - -Some packages can record the RPCs during integration tests to a file for -subsequent replay. To record, pass the `-record` flag to `go test`. The -recording will be saved to the _package_`.replay` file. To replay integration -tests from a saved recording, the replay file must be present, the `-short` -flag must be passed to `go test`, and the `GCLOUD_TESTS_GOLANG_ENABLE_REPLAY` -environment variable must have a non-empty value. - -## Contributor License Agreements - -Before we can accept your pull requests you'll need to sign a Contributor -License Agreement (CLA): - -- **If you are an individual writing original source code** and **you own the -intellectual property**, then you'll need to sign an [individual CLA][indvcla]. -- **If you work for a company that wants to allow you to contribute your -work**, then you'll need to sign a [corporate CLA][corpcla]. - -You can sign these electronically (just scroll to the bottom). After that, -we'll be able to accept your pull requests. - -## Contributor Code of Conduct - -As contributors and maintainers of this project, -and in the interest of fostering an open and welcoming community, -we pledge to respect all people who contribute through reporting issues, -posting feature requests, updating documentation, -submitting pull requests or patches, and other activities. - -We are committed to making participation in this project -a harassment-free experience for everyone, -regardless of level of experience, gender, gender identity and expression, -sexual orientation, disability, personal appearance, -body size, race, ethnicity, age, religion, or nationality. - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery -* Personal attacks -* Trolling or insulting/derogatory comments -* Public or private harassment -* Publishing other's private information, -such as physical or electronic -addresses, without explicit permission -* Other unethical or unprofessional conduct. - -Project maintainers have the right and responsibility to remove, edit, or reject -comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct. -By adopting this Code of Conduct, -project maintainers commit themselves to fairly and consistently -applying these principles to every aspect of managing this project. -Project maintainers who do not follow or enforce the Code of Conduct -may be permanently removed from the project team. - -This code of conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. - -Instances of abusive, harassing, or otherwise unacceptable behavior -may be reported by opening an issue -or contacting one or more of the project maintainers. - -This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, -available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/) - -[gcloudcli]: https://developers.google.com/cloud/sdk/gcloud/ -[indvcla]: https://developers.google.com/open-source/cla/individual -[corpcla]: https://developers.google.com/open-source/cla/corporate diff --git a/vendor/cloud.google.com/go/README.md b/vendor/cloud.google.com/go/README.md deleted file mode 100644 index 1c8c1604..00000000 --- a/vendor/cloud.google.com/go/README.md +++ /dev/null @@ -1,505 +0,0 @@ -# Google Cloud Client Libraries for Go - -[![GoDoc](https://godoc.org/cloud.google.com/go?status.svg)](https://godoc.org/cloud.google.com/go) - -Go packages for [Google Cloud Platform](https://cloud.google.com) services. - -``` go -import "cloud.google.com/go" -``` - -To install the packages on your system, *do not clone the repo*. Instead use - -``` -$ go get -u cloud.google.com/go/... -``` - -**NOTE:** Some of these packages are under development, and may occasionally -make backwards-incompatible changes. - -**NOTE:** Github repo is a mirror of [https://code.googlesource.com/gocloud](https://code.googlesource.com/gocloud). - - * [News](#news) - * [Supported APIs](#supported-apis) - * [Go Versions Supported](#go-versions-supported) - * [Authorization](#authorization) - * [Cloud Datastore](#cloud-datastore-) - * [Cloud Storage](#cloud-storage-) - * [Cloud Pub/Sub](#cloud-pub-sub-) - * [BigQuery](#cloud-bigquery-) - * [Stackdriver Logging](#stackdriver-logging-) - * [Cloud Spanner](#cloud-spanner-) - - -## News - -_7 August 2018_ - -As of November 1, the code in the repo will no longer support Go versions 1.8 -and earlier. No one other than AppEngine users should be on those old versions, -and AppEngine -[Standard](https://groups.google.com/forum/#!topic/google-appengine-go/e7oPNomd7ak) -and -[Flex](https://groups.google.com/forum/#!topic/google-appengine-go/wHsYtxvEbXI) -will stop supporting new deployments with those versions on that date. - - -Changes have been moved to [CHANGES](https://github.com/GoogleCloudPlatform/google-cloud-go/blob/master/CHANGES.md). - - -## Supported APIs - -Google API | Status | Package ----------------------------------------------|--------------|----------------------------------------------------------- -[Asset][cloud-asset] | alpha | [`godoc.org/cloud.google.com/go/asset/v1beta`][cloud-asset-ref] -[BigQuery][cloud-bigquery] | stable | [`godoc.org/cloud.google.com/go/bigquery`][cloud-bigquery-ref] -[Bigtable][cloud-bigtable] | stable | [`godoc.org/cloud.google.com/go/bigtable`][cloud-bigtable-ref] -[Cloudtasks][cloud-tasks] | beta | [`godoc.org/cloud.google.com/go/cloudtasks/apiv2beta3`][cloud-tasks-ref] -[Container][cloud-container] | stable | [`godoc.org/cloud.google.com/go/container/apiv1`][cloud-container-ref] -[ContainerAnalysis][cloud-containeranalysis] | beta | [`godoc.org/cloud.google.com/go/containeranalysis/apiv1beta1`][cloud-containeranalysis-ref] -[Dataproc][cloud-dataproc] | stable | [`godoc.org/cloud.google.com/go/dataproc/apiv1`][cloud-dataproc-ref] -[Datastore][cloud-datastore] | stable | [`godoc.org/cloud.google.com/go/datastore`][cloud-datastore-ref] -[Debugger][cloud-debugger] | alpha | [`godoc.org/cloud.google.com/go/debugger/apiv2`][cloud-debugger-ref] -[Dialogflow][cloud-dialogflow] | alpha | [`godoc.org/cloud.google.com/go/dialogflow/apiv2`][cloud-dialogflow-ref] -[Data Loss Prevention][cloud-dlp] | alpha | [`godoc.org/cloud.google.com/go/dlp/apiv2`][cloud-dlp-ref] -[ErrorReporting][cloud-errors] | alpha | [`godoc.org/cloud.google.com/go/errorreporting`][cloud-errors-ref] -[Firestore][cloud-firestore] | beta | [`godoc.org/cloud.google.com/go/firestore`][cloud-firestore-ref] -[IAM][cloud-iam] | stable | [`godoc.org/cloud.google.com/go/iam`][cloud-iam-ref] -[KMS][cloud-kms] | stable | [`godoc.org/cloud.google.com/go/kms`][cloud-kms-ref] -[Natural Language][cloud-natural-language] | stable | [`godoc.org/cloud.google.com/go/language/apiv1`][cloud-natural-language-ref] -[Logging][cloud-logging] | stable | [`godoc.org/cloud.google.com/go/logging`][cloud-logging-ref] -[Monitoring][cloud-monitoring] | alpha | [`godoc.org/cloud.google.com/go/monitoring/apiv3`][cloud-monitoring-ref] -[OS Login][cloud-oslogin] | alpha | [`cloud.google.com/compute/docs/oslogin/rest`][cloud-oslogin-ref] -[Pub/Sub][cloud-pubsub] | stable | [`godoc.org/cloud.google.com/go/pubsub`][cloud-pubsub-ref] -[Memorystore][cloud-memorystore] | stable | [`godoc.org/cloud.google.com/go/redis/apiv1beta1`][cloud-memorystore-ref] -[Spanner][cloud-spanner] | stable | [`godoc.org/cloud.google.com/go/spanner`][cloud-spanner-ref] -[Speech][cloud-speech] | stable | [`godoc.org/cloud.google.com/go/speech/apiv1`][cloud-speech-ref] -[Storage][cloud-storage] | stable | [`godoc.org/cloud.google.com/go/storage`][cloud-storage-ref] -[Text To Speech][cloud-texttospeech] | alpha | [`godoc.org/cloud.google.com/go/texttospeech/apiv1`][cloud-storage-ref] -[Trace][cloud-trace] | alpha | [`godoc.org/cloud.google.com/go/trace/apiv2`][cloud-translation-ref] -[Translation][cloud-translation] | stable | [`godoc.org/cloud.google.com/go/translate`][cloud-translation-ref] -[Video Intelligence][cloud-video] | alpha | [`godoc.org/cloud.google.com/go/videointelligence/apiv1beta1`][cloud-video-ref] -[Vision][cloud-vision] | stable | [`godoc.org/cloud.google.com/go/vision/apiv1`][cloud-vision-ref] - -> **Alpha status**: the API is still being actively developed. As a -> result, it might change in backward-incompatible ways and is not recommended -> for production use. -> -> **Beta status**: the API is largely complete, but still has outstanding -> features and bugs to be addressed. There may be minor backwards-incompatible -> changes where necessary. -> -> **Stable status**: the API is mature and ready for production use. We will -> continue addressing bugs and feature requests. - -Documentation and examples are available at -https://godoc.org/cloud.google.com/go - -Visit or join the -[google-api-go-announce group](https://groups.google.com/forum/#!forum/google-api-go-announce) -for updates on these packages. - -## Go Versions Supported - -We support the two most recent major versions of Go. If Google App Engine uses -an older version, we support that as well. - -## Authorization - -By default, each API will use [Google Application Default Credentials][default-creds] -for authorization credentials used in calling the API endpoints. This will allow your -application to run in many environments without requiring explicit configuration. - -[snip]:# (auth) -```go -client, err := storage.NewClient(ctx) -``` - -To authorize using a -[JSON key file](https://cloud.google.com/iam/docs/managing-service-account-keys), -pass -[`option.WithCredentialsFile`](https://godoc.org/google.golang.org/api/option#WithCredentialsFile) -to the `NewClient` function of the desired package. For example: - -[snip]:# (auth-JSON) -```go -client, err := storage.NewClient(ctx, option.WithCredentialsFile("path/to/keyfile.json")) -``` - -You can exert more control over authorization by using the -[`golang.org/x/oauth2`](https://godoc.org/golang.org/x/oauth2) package to -create an `oauth2.TokenSource`. Then pass -[`option.WithTokenSource`](https://godoc.org/google.golang.org/api/option#WithTokenSource) -to the `NewClient` function: -[snip]:# (auth-ts) -```go -tokenSource := ... -client, err := storage.NewClient(ctx, option.WithTokenSource(tokenSource)) -``` - -## Cloud Datastore [![GoDoc](https://godoc.org/cloud.google.com/go/datastore?status.svg)](https://godoc.org/cloud.google.com/go/datastore) - -- [About Cloud Datastore][cloud-datastore] -- [Activating the API for your project][cloud-datastore-activation] -- [API documentation][cloud-datastore-docs] -- [Go client documentation](https://godoc.org/cloud.google.com/go/datastore) -- [Complete sample program](https://github.com/GoogleCloudPlatform/golang-samples/tree/master/datastore/tasks) - -### Example Usage - -First create a `datastore.Client` to use throughout your application: - -[snip]:# (datastore-1) -```go -client, err := datastore.NewClient(ctx, "my-project-id") -if err != nil { - log.Fatal(err) -} -``` - -Then use that client to interact with the API: - -[snip]:# (datastore-2) -```go -type Post struct { - Title string - Body string `datastore:",noindex"` - PublishedAt time.Time -} -keys := []*datastore.Key{ - datastore.NameKey("Post", "post1", nil), - datastore.NameKey("Post", "post2", nil), -} -posts := []*Post{ - {Title: "Post 1", Body: "...", PublishedAt: time.Now()}, - {Title: "Post 2", Body: "...", PublishedAt: time.Now()}, -} -if _, err := client.PutMulti(ctx, keys, posts); err != nil { - log.Fatal(err) -} -``` - -## Cloud Storage [![GoDoc](https://godoc.org/cloud.google.com/go/storage?status.svg)](https://godoc.org/cloud.google.com/go/storage) - -- [About Cloud Storage][cloud-storage] -- [API documentation][cloud-storage-docs] -- [Go client documentation](https://godoc.org/cloud.google.com/go/storage) -- [Complete sample programs](https://github.com/GoogleCloudPlatform/golang-samples/tree/master/storage) - -### Example Usage - -First create a `storage.Client` to use throughout your application: - -[snip]:# (storage-1) -```go -client, err := storage.NewClient(ctx) -if err != nil { - log.Fatal(err) -} -``` - -[snip]:# (storage-2) -```go -// Read the object1 from bucket. -rc, err := client.Bucket("bucket").Object("object1").NewReader(ctx) -if err != nil { - log.Fatal(err) -} -defer rc.Close() -body, err := ioutil.ReadAll(rc) -if err != nil { - log.Fatal(err) -} -``` - -## Cloud Pub/Sub [![GoDoc](https://godoc.org/cloud.google.com/go/pubsub?status.svg)](https://godoc.org/cloud.google.com/go/pubsub) - -- [About Cloud Pubsub][cloud-pubsub] -- [API documentation][cloud-pubsub-docs] -- [Go client documentation](https://godoc.org/cloud.google.com/go/pubsub) -- [Complete sample programs](https://github.com/GoogleCloudPlatform/golang-samples/tree/master/pubsub) - -### Example Usage - -First create a `pubsub.Client` to use throughout your application: - -[snip]:# (pubsub-1) -```go -client, err := pubsub.NewClient(ctx, "project-id") -if err != nil { - log.Fatal(err) -} -``` - -Then use the client to publish and subscribe: - -[snip]:# (pubsub-2) -```go -// Publish "hello world" on topic1. -topic := client.Topic("topic1") -res := topic.Publish(ctx, &pubsub.Message{ - Data: []byte("hello world"), -}) -// The publish happens asynchronously. -// Later, you can get the result from res: -... -msgID, err := res.Get(ctx) -if err != nil { - log.Fatal(err) -} - -// Use a callback to receive messages via subscription1. -sub := client.Subscription("subscription1") -err = sub.Receive(ctx, func(ctx context.Context, m *pubsub.Message) { - fmt.Println(m.Data) - m.Ack() // Acknowledge that we've consumed the message. -}) -if err != nil { - log.Println(err) -} -``` - -## BigQuery [![GoDoc](https://godoc.org/cloud.google.com/go/bigquery?status.svg)](https://godoc.org/cloud.google.com/go/bigquery) - -- [About BigQuery][cloud-bigquery] -- [API documentation][cloud-bigquery-docs] -- [Go client documentation][cloud-bigquery-ref] -- [Complete sample programs](https://github.com/GoogleCloudPlatform/golang-samples/tree/master/bigquery) - -### Example Usage - -First create a `bigquery.Client` to use throughout your application: -[snip]:# (bq-1) -```go -c, err := bigquery.NewClient(ctx, "my-project-ID") -if err != nil { - // TODO: Handle error. -} -``` - -Then use that client to interact with the API: -[snip]:# (bq-2) -```go -// Construct a query. -q := c.Query(` - SELECT year, SUM(number) - FROM [bigquery-public-data:usa_names.usa_1910_2013] - WHERE name = "William" - GROUP BY year - ORDER BY year -`) -// Execute the query. -it, err := q.Read(ctx) -if err != nil { - // TODO: Handle error. -} -// Iterate through the results. -for { - var values []bigquery.Value - err := it.Next(&values) - if err == iterator.Done { - break - } - if err != nil { - // TODO: Handle error. - } - fmt.Println(values) -} -``` - - -## Stackdriver Logging [![GoDoc](https://godoc.org/cloud.google.com/go/logging?status.svg)](https://godoc.org/cloud.google.com/go/logging) - -- [About Stackdriver Logging][cloud-logging] -- [API documentation][cloud-logging-docs] -- [Go client documentation][cloud-logging-ref] -- [Complete sample programs](https://github.com/GoogleCloudPlatform/golang-samples/tree/master/logging) - -### Example Usage - -First create a `logging.Client` to use throughout your application: -[snip]:# (logging-1) -```go -ctx := context.Background() -client, err := logging.NewClient(ctx, "my-project") -if err != nil { - // TODO: Handle error. -} -``` - -Usually, you'll want to add log entries to a buffer to be periodically flushed -(automatically and asynchronously) to the Stackdriver Logging service. -[snip]:# (logging-2) -```go -logger := client.Logger("my-log") -logger.Log(logging.Entry{Payload: "something happened!"}) -``` - -Close your client before your program exits, to flush any buffered log entries. -[snip]:# (logging-3) -```go -err = client.Close() -if err != nil { - // TODO: Handle error. -} -``` - -## Cloud Spanner [![GoDoc](https://godoc.org/cloud.google.com/go/spanner?status.svg)](https://godoc.org/cloud.google.com/go/spanner) - -- [About Cloud Spanner][cloud-spanner] -- [API documentation][cloud-spanner-docs] -- [Go client documentation](https://godoc.org/cloud.google.com/go/spanner) - -### Example Usage - -First create a `spanner.Client` to use throughout your application: - -[snip]:# (spanner-1) -```go -client, err := spanner.NewClient(ctx, "projects/P/instances/I/databases/D") -if err != nil { - log.Fatal(err) -} -``` - -[snip]:# (spanner-2) -```go -// Simple Reads And Writes -_, err = client.Apply(ctx, []*spanner.Mutation{ - spanner.Insert("Users", - []string{"name", "email"}, - []interface{}{"alice", "a@example.com"})}) -if err != nil { - log.Fatal(err) -} -row, err := client.Single().ReadRow(ctx, "Users", - spanner.Key{"alice"}, []string{"email"}) -if err != nil { - log.Fatal(err) -} -``` - - -## Contributing - -Contributions are welcome. Please, see the -[CONTRIBUTING](https://github.com/GoogleCloudPlatform/google-cloud-go/blob/master/CONTRIBUTING.md) -document for details. We're using Gerrit for our code reviews. Please don't open pull -requests against this repo, new pull requests will be automatically closed. - -Please note that this project is released with a Contributor Code of Conduct. -By participating in this project you agree to abide by its terms. -See [Contributor Code of Conduct](https://github.com/GoogleCloudPlatform/google-cloud-go/blob/master/CONTRIBUTING.md#contributor-code-of-conduct) -for more information. - -[cloud-datastore]: https://cloud.google.com/datastore/ -[cloud-datastore-ref]: https://godoc.org/cloud.google.com/go/datastore -[cloud-datastore-docs]: https://cloud.google.com/datastore/docs -[cloud-datastore-activation]: https://cloud.google.com/datastore/docs/activate - -[cloud-firestore]: https://cloud.google.com/firestore/ -[cloud-firestore-ref]: https://godoc.org/cloud.google.com/go/firestore -[cloud-firestore-docs]: https://cloud.google.com/firestore/docs -[cloud-firestore-activation]: https://cloud.google.com/firestore/docs/activate - -[cloud-pubsub]: https://cloud.google.com/pubsub/ -[cloud-pubsub-ref]: https://godoc.org/cloud.google.com/go/pubsub -[cloud-pubsub-docs]: https://cloud.google.com/pubsub/docs - -[cloud-storage]: https://cloud.google.com/storage/ -[cloud-storage-ref]: https://godoc.org/cloud.google.com/go/storage -[cloud-storage-docs]: https://cloud.google.com/storage/docs -[cloud-storage-create-bucket]: https://cloud.google.com/storage/docs/cloud-console#_creatingbuckets - -[cloud-bigtable]: https://cloud.google.com/bigtable/ -[cloud-bigtable-ref]: https://godoc.org/cloud.google.com/go/bigtable - -[cloud-bigquery]: https://cloud.google.com/bigquery/ -[cloud-bigquery-docs]: https://cloud.google.com/bigquery/docs -[cloud-bigquery-ref]: https://godoc.org/cloud.google.com/go/bigquery - -[cloud-logging]: https://cloud.google.com/logging/ -[cloud-logging-docs]: https://cloud.google.com/logging/docs -[cloud-logging-ref]: https://godoc.org/cloud.google.com/go/logging - -[cloud-monitoring]: https://cloud.google.com/monitoring/ -[cloud-monitoring-ref]: https://godoc.org/cloud.google.com/go/monitoring/apiv3 - -[cloud-vision]: https://cloud.google.com/vision -[cloud-vision-ref]: https://godoc.org/cloud.google.com/go/vision/apiv1 - -[cloud-language]: https://cloud.google.com/natural-language -[cloud-language-ref]: https://godoc.org/cloud.google.com/go/language/apiv1 - -[cloud-oslogin]: https://cloud.google.com/compute/docs/oslogin/rest -[cloud-oslogin-ref]: https://cloud.google.com/compute/docs/oslogin/rest - -[cloud-speech]: https://cloud.google.com/speech -[cloud-speech-ref]: https://godoc.org/cloud.google.com/go/speech/apiv1 - -[cloud-spanner]: https://cloud.google.com/spanner/ -[cloud-spanner-ref]: https://godoc.org/cloud.google.com/go/spanner -[cloud-spanner-docs]: https://cloud.google.com/spanner/docs - -[cloud-translation]: https://cloud.google.com/translation -[cloud-translation-ref]: https://godoc.org/cloud.google.com/go/translation - -[cloud-video]: https://cloud.google.com/video-intelligence/ -[cloud-video-ref]: https://godoc.org/cloud.google.com/go/videointelligence/apiv1beta1 - -[cloud-errors]: https://cloud.google.com/error-reporting/ -[cloud-errors-ref]: https://godoc.org/cloud.google.com/go/errorreporting - -[cloud-container]: https://cloud.google.com/containers/ -[cloud-container-ref]: https://godoc.org/cloud.google.com/go/container/apiv1 - -[cloud-debugger]: https://cloud.google.com/debugger/ -[cloud-debugger-ref]: https://godoc.org/cloud.google.com/go/debugger/apiv2 - -[cloud-dlp]: https://cloud.google.com/dlp/ -[cloud-dlp-ref]: https://godoc.org/cloud.google.com/go/dlp/apiv2beta1 - -[default-creds]: https://developers.google.com/identity/protocols/application-default-credentials - -[cloud-dataproc]: https://cloud.google.com/dataproc/ -[cloud-dataproc-docs]: https://cloud.google.com/dataproc/docs -[cloud-dataproc-ref]: https://godoc.org/cloud.google.com/go/dataproc/apiv1 - -[cloud-iam]: https://cloud.google.com/iam/ -[cloud-iam-docs]: https://cloud.google.com/iam/docs -[cloud-iam-ref]: https://godoc.org/cloud.google.com/go/iam - -[cloud-kms]: https://cloud.google.com/kms/ -[cloud-kms-docs]: https://cloud.google.com/kms/docs -[cloud-kms-ref]: https://godoc.org/cloud.google.com/go/kms/apiv1 - -[cloud-natural-language]: https://cloud.google.com/natural-language/ -[cloud-natural-language-docs]: https://cloud.google.com/natural-language/docs -[cloud-natural-language-ref]: https://godoc.org/cloud.google.com/go/language/apiv1 - -[cloud-memorystore]: https://cloud.google.com/memorystore/ -[cloud-memorystore-docs]: https://cloud.google.com/memorystore/docs -[cloud-memorystore-ref]: https://godoc.org/cloud.google.com/go/redis/apiv1beta1 - -[cloud-texttospeech]: https://cloud.google.com/texttospeech/ -[cloud-texttospeech-docs]: https://cloud.google.com/texttospeech/docs -[cloud-texttospeech-ref]: https://godoc.org/cloud.google.com/go/texttospeech/apiv1 - -[cloud-trace]: https://cloud.google.com/trace/ -[cloud-trace-docs]: https://cloud.google.com/trace/docs -[cloud-trace-ref]: https://godoc.org/cloud.google.com/go/trace/apiv1 - -[cloud-dialogflow]: https://cloud.google.com/dialogflow-enterprise/ -[cloud-dialogflow-docs]: https://cloud.google.com/dialogflow-enterprise/docs/ -[cloud-dialogflow-ref]: https://godoc.org/cloud.google.com/go/dialogflow/apiv2 - -[cloud-containeranalysis]: https://cloud.google.com/container-registry/docs/container-analysis -[cloud-containeranalysis-docs]: https://cloud.google.com/container-analysis/api/reference/rest/ -[cloud-containeranalysis-ref]: https://godoc.org/cloud.google.com/go/devtools/containeranalysis/apiv1beta1 - -[cloud-asset]: https://cloud.google.com/security-command-center/docs/how-to-asset-inventory -[cloud-asset-docs]: https://cloud.google.com/security-command-center/docs/how-to-asset-inventory -[cloud-asset-ref]: https://godoc.org/cloud.google.com/go/asset/apiv1 - -[cloud-tasks]: https://cloud.google.com/tasks/ -[cloud-tasks-ref]: https://godoc.org/cloud.google.com/go/cloudtasks/apiv2beta3 diff --git a/vendor/cloud.google.com/go/RELEASING.md b/vendor/cloud.google.com/go/RELEASING.md deleted file mode 100644 index 1028a261..00000000 --- a/vendor/cloud.google.com/go/RELEASING.md +++ /dev/null @@ -1,47 +0,0 @@ -# How to Create a New Release - -## Prerequisites - -Install [releasetool](https://github.com/googleapis/releasetool). - -## Create a release - -1. `cd` into the root directory, e.g., `~/go/src/cloud.google.com/go` -1. Checkout the master branch and ensure a clean and up-to-date state. - ``` - git checkout master - git pull --tags origin master - ``` -1. Run releasetool to generate a changelog from the last version. Note, - releasetool will prompt if the new version is a major, minor, or patch - version. - ``` - releasetool start --language go - ``` -1. Format the output to match CHANGES.md. -1. Submit a CL with the changes in CHANGES.md. The commit message should look - like this (where `v0.31.0` is instead the correct version number): - ``` - all: Release v0.31.0 - ``` -1. Wait for approval from all reviewers and then submit the CL. -1. Return to the master branch and pull the release commit. - ``` - git checkout master - git pull origin master - ``` -1. Tag the current commit with the new version (e.g., `v0.31.0`) - ``` - releasetool tag --language go - ``` -1. Publish the tag to GoogleSource (i.e., origin): - ``` - git push origin $NEW_VERSION - ``` -1. Visit the [releases page][releases] on GitHub and click the "Draft a new - release" button. For tag version, enter the tag published in the previous - step. For the release title, use the version (e.g., `v0.31.0`). For the - description, copy the changes added to CHANGES.md. - - -[releases]: https://github.com/GoogleCloudPlatform/google-cloud-go/releases diff --git a/vendor/cloud.google.com/go/authexample_test.go b/vendor/cloud.google.com/go/authexample_test.go deleted file mode 100644 index aafbe226..00000000 --- a/vendor/cloud.google.com/go/authexample_test.go +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2016 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package cloud_test - -import ( - "context" - - "cloud.google.com/go/datastore" - "cloud.google.com/go/pubsub" - "golang.org/x/oauth2/google" - "google.golang.org/api/option" -) - -// Google Application Default Credentials is the recommended way to authorize -// and authenticate clients. -// -// For information on how to create and obtain Application Default Credentials, see -// https://developers.google.com/identity/protocols/application-default-credentials. -func Example_applicationDefaultCredentials() { - client, err := datastore.NewClient(context.Background(), "project-id") - if err != nil { - // TODO: handle error. - } - _ = client // Use the client. -} - -// You can use a file with credentials to authenticate and authorize, such as a JSON -// key file associated with a Google service account. Service Account keys can be -// created and downloaded from -// https://console.developers.google.com/permissions/serviceaccounts. -// -// This example uses the Datastore client, but the same steps apply to -// the other client libraries underneath this package. -func Example_credentialsFile() { - client, err := datastore.NewClient(context.Background(), - "project-id", option.WithCredentialsFile("/path/to/service-account-key.json")) - if err != nil { - // TODO: handle error. - } - _ = client // Use the client. -} - -// In some cases (for instance, you don't want to store secrets on disk), you can -// create credentials from in-memory JSON and use the WithCredentials option. -// -// The google package in this example is at golang.org/x/oauth2/google. -// -// This example uses the PubSub client, but the same steps apply to -// the other client libraries underneath this package. -func Example_credentialsFromJSON() { - ctx := context.Background() - creds, err := google.CredentialsFromJSON(ctx, []byte("JSON creds"), pubsub.ScopePubSub) - if err != nil { - // TODO: handle error. - } - client, err := pubsub.NewClient(ctx, "project-id", option.WithCredentials(creds)) - if err != nil { - // TODO: handle error. - } - _ = client // Use the client. -} diff --git a/vendor/cloud.google.com/go/civil/civil_test.go b/vendor/cloud.google.com/go/civil/civil_test.go deleted file mode 100644 index 0720092e..00000000 --- a/vendor/cloud.google.com/go/civil/civil_test.go +++ /dev/null @@ -1,442 +0,0 @@ -// Copyright 2016 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package civil - -import ( - "encoding/json" - "testing" - "time" - - "github.com/google/go-cmp/cmp" -) - -func TestDates(t *testing.T) { - for _, test := range []struct { - date Date - loc *time.Location - wantStr string - wantTime time.Time - }{ - { - date: Date{2014, 7, 29}, - loc: time.Local, - wantStr: "2014-07-29", - wantTime: time.Date(2014, time.July, 29, 0, 0, 0, 0, time.Local), - }, - { - date: DateOf(time.Date(2014, 8, 20, 15, 8, 43, 1, time.Local)), - loc: time.UTC, - wantStr: "2014-08-20", - wantTime: time.Date(2014, 8, 20, 0, 0, 0, 0, time.UTC), - }, - { - date: DateOf(time.Date(999, time.January, 26, 0, 0, 0, 0, time.Local)), - loc: time.UTC, - wantStr: "0999-01-26", - wantTime: time.Date(999, 1, 26, 0, 0, 0, 0, time.UTC), - }, - } { - if got := test.date.String(); got != test.wantStr { - t.Errorf("%#v.String() = %q, want %q", test.date, got, test.wantStr) - } - if got := test.date.In(test.loc); !got.Equal(test.wantTime) { - t.Errorf("%#v.In(%v) = %v, want %v", test.date, test.loc, got, test.wantTime) - } - } -} - -func TestDateIsValid(t *testing.T) { - for _, test := range []struct { - date Date - want bool - }{ - {Date{2014, 7, 29}, true}, - {Date{2000, 2, 29}, true}, - {Date{10000, 12, 31}, true}, - {Date{1, 1, 1}, true}, - {Date{0, 1, 1}, true}, // year zero is OK - {Date{-1, 1, 1}, true}, // negative year is OK - {Date{1, 0, 1}, false}, - {Date{1, 1, 0}, false}, - {Date{2016, 1, 32}, false}, - {Date{2016, 13, 1}, false}, - {Date{1, -1, 1}, false}, - {Date{1, 1, -1}, false}, - } { - got := test.date.IsValid() - if got != test.want { - t.Errorf("%#v: got %t, want %t", test.date, got, test.want) - } - } -} - -func TestParseDate(t *testing.T) { - for _, test := range []struct { - str string - want Date // if empty, expect an error - }{ - {"2016-01-02", Date{2016, 1, 2}}, - {"2016-12-31", Date{2016, 12, 31}}, - {"0003-02-04", Date{3, 2, 4}}, - {"999-01-26", Date{}}, - {"", Date{}}, - {"2016-01-02x", Date{}}, - } { - got, err := ParseDate(test.str) - if got != test.want { - t.Errorf("ParseDate(%q) = %+v, want %+v", test.str, got, test.want) - } - if err != nil && test.want != (Date{}) { - t.Errorf("Unexpected error %v from ParseDate(%q)", err, test.str) - } - } -} - -func TestDateArithmetic(t *testing.T) { - for _, test := range []struct { - desc string - start Date - end Date - days int - }{ - { - desc: "zero days noop", - start: Date{2014, 5, 9}, - end: Date{2014, 5, 9}, - days: 0, - }, - { - desc: "crossing a year boundary", - start: Date{2014, 12, 31}, - end: Date{2015, 1, 1}, - days: 1, - }, - { - desc: "negative number of days", - start: Date{2015, 1, 1}, - end: Date{2014, 12, 31}, - days: -1, - }, - { - desc: "full leap year", - start: Date{2004, 1, 1}, - end: Date{2005, 1, 1}, - days: 366, - }, - { - desc: "full non-leap year", - start: Date{2001, 1, 1}, - end: Date{2002, 1, 1}, - days: 365, - }, - { - desc: "crossing a leap second", - start: Date{1972, 6, 30}, - end: Date{1972, 7, 1}, - days: 1, - }, - { - desc: "dates before the unix epoch", - start: Date{101, 1, 1}, - end: Date{102, 1, 1}, - days: 365, - }, - } { - if got := test.start.AddDays(test.days); got != test.end { - t.Errorf("[%s] %#v.AddDays(%v) = %#v, want %#v", test.desc, test.start, test.days, got, test.end) - } - if got := test.end.DaysSince(test.start); got != test.days { - t.Errorf("[%s] %#v.Sub(%#v) = %v, want %v", test.desc, test.end, test.start, got, test.days) - } - } -} - -func TestDateBefore(t *testing.T) { - for _, test := range []struct { - d1, d2 Date - want bool - }{ - {Date{2016, 12, 31}, Date{2017, 1, 1}, true}, - {Date{2016, 1, 1}, Date{2016, 1, 1}, false}, - {Date{2016, 12, 30}, Date{2016, 12, 31}, true}, - } { - if got := test.d1.Before(test.d2); got != test.want { - t.Errorf("%v.Before(%v): got %t, want %t", test.d1, test.d2, got, test.want) - } - } -} - -func TestDateAfter(t *testing.T) { - for _, test := range []struct { - d1, d2 Date - want bool - }{ - {Date{2016, 12, 31}, Date{2017, 1, 1}, false}, - {Date{2016, 1, 1}, Date{2016, 1, 1}, false}, - {Date{2016, 12, 30}, Date{2016, 12, 31}, false}, - } { - if got := test.d1.After(test.d2); got != test.want { - t.Errorf("%v.After(%v): got %t, want %t", test.d1, test.d2, got, test.want) - } - } -} - -func TestTimeToString(t *testing.T) { - for _, test := range []struct { - str string - time Time - roundTrip bool // ParseTime(str).String() == str? - }{ - {"13:26:33", Time{13, 26, 33, 0}, true}, - {"01:02:03.000023456", Time{1, 2, 3, 23456}, true}, - {"00:00:00.000000001", Time{0, 0, 0, 1}, true}, - {"13:26:03.1", Time{13, 26, 3, 100000000}, false}, - {"13:26:33.0000003", Time{13, 26, 33, 300}, false}, - } { - gotTime, err := ParseTime(test.str) - if err != nil { - t.Errorf("ParseTime(%q): got error: %v", test.str, err) - continue - } - if gotTime != test.time { - t.Errorf("ParseTime(%q) = %+v, want %+v", test.str, gotTime, test.time) - } - if test.roundTrip { - gotStr := test.time.String() - if gotStr != test.str { - t.Errorf("%#v.String() = %q, want %q", test.time, gotStr, test.str) - } - } - } -} - -func TestTimeOf(t *testing.T) { - for _, test := range []struct { - time time.Time - want Time - }{ - {time.Date(2014, 8, 20, 15, 8, 43, 1, time.Local), Time{15, 8, 43, 1}}, - {time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC), Time{0, 0, 0, 0}}, - } { - if got := TimeOf(test.time); got != test.want { - t.Errorf("TimeOf(%v) = %+v, want %+v", test.time, got, test.want) - } - } -} - -func TestTimeIsValid(t *testing.T) { - for _, test := range []struct { - time Time - want bool - }{ - {Time{0, 0, 0, 0}, true}, - {Time{23, 0, 0, 0}, true}, - {Time{23, 59, 59, 999999999}, true}, - {Time{24, 59, 59, 999999999}, false}, - {Time{23, 60, 59, 999999999}, false}, - {Time{23, 59, 60, 999999999}, false}, - {Time{23, 59, 59, 1000000000}, false}, - {Time{-1, 0, 0, 0}, false}, - {Time{0, -1, 0, 0}, false}, - {Time{0, 0, -1, 0}, false}, - {Time{0, 0, 0, -1}, false}, - } { - got := test.time.IsValid() - if got != test.want { - t.Errorf("%#v: got %t, want %t", test.time, got, test.want) - } - } -} - -func TestDateTimeToString(t *testing.T) { - for _, test := range []struct { - str string - dateTime DateTime - roundTrip bool // ParseDateTime(str).String() == str? - }{ - {"2016-03-22T13:26:33", DateTime{Date{2016, 03, 22}, Time{13, 26, 33, 0}}, true}, - {"2016-03-22T13:26:33.000000600", DateTime{Date{2016, 03, 22}, Time{13, 26, 33, 600}}, true}, - {"2016-03-22t13:26:33", DateTime{Date{2016, 03, 22}, Time{13, 26, 33, 0}}, false}, - } { - gotDateTime, err := ParseDateTime(test.str) - if err != nil { - t.Errorf("ParseDateTime(%q): got error: %v", test.str, err) - continue - } - if gotDateTime != test.dateTime { - t.Errorf("ParseDateTime(%q) = %+v, want %+v", test.str, gotDateTime, test.dateTime) - } - if test.roundTrip { - gotStr := test.dateTime.String() - if gotStr != test.str { - t.Errorf("%#v.String() = %q, want %q", test.dateTime, gotStr, test.str) - } - } - } -} - -func TestParseDateTimeErrors(t *testing.T) { - for _, str := range []string{ - "", - "2016-03-22", // just a date - "13:26:33", // just a time - "2016-03-22 13:26:33", // wrong separating character - "2016-03-22T13:26:33x", // extra at end - } { - if _, err := ParseDateTime(str); err == nil { - t.Errorf("ParseDateTime(%q) succeeded, want error", str) - } - } -} - -func TestDateTimeOf(t *testing.T) { - for _, test := range []struct { - time time.Time - want DateTime - }{ - {time.Date(2014, 8, 20, 15, 8, 43, 1, time.Local), - DateTime{Date{2014, 8, 20}, Time{15, 8, 43, 1}}}, - {time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC), - DateTime{Date{1, 1, 1}, Time{0, 0, 0, 0}}}, - } { - if got := DateTimeOf(test.time); got != test.want { - t.Errorf("DateTimeOf(%v) = %+v, want %+v", test.time, got, test.want) - } - } -} - -func TestDateTimeIsValid(t *testing.T) { - // No need to be exhaustive here; it's just Date.IsValid && Time.IsValid. - for _, test := range []struct { - dt DateTime - want bool - }{ - {DateTime{Date{2016, 3, 20}, Time{0, 0, 0, 0}}, true}, - {DateTime{Date{2016, -3, 20}, Time{0, 0, 0, 0}}, false}, - {DateTime{Date{2016, 3, 20}, Time{24, 0, 0, 0}}, false}, - } { - got := test.dt.IsValid() - if got != test.want { - t.Errorf("%#v: got %t, want %t", test.dt, got, test.want) - } - } -} - -func TestDateTimeIn(t *testing.T) { - dt := DateTime{Date{2016, 1, 2}, Time{3, 4, 5, 6}} - got := dt.In(time.UTC) - want := time.Date(2016, 1, 2, 3, 4, 5, 6, time.UTC) - if !got.Equal(want) { - t.Errorf("got %v, want %v", got, want) - } -} - -func TestDateTimeBefore(t *testing.T) { - d1 := Date{2016, 12, 31} - d2 := Date{2017, 1, 1} - t1 := Time{5, 6, 7, 8} - t2 := Time{5, 6, 7, 9} - for _, test := range []struct { - dt1, dt2 DateTime - want bool - }{ - {DateTime{d1, t1}, DateTime{d2, t1}, true}, - {DateTime{d1, t1}, DateTime{d1, t2}, true}, - {DateTime{d2, t1}, DateTime{d1, t1}, false}, - {DateTime{d2, t1}, DateTime{d2, t1}, false}, - } { - if got := test.dt1.Before(test.dt2); got != test.want { - t.Errorf("%v.Before(%v): got %t, want %t", test.dt1, test.dt2, got, test.want) - } - } -} - -func TestDateTimeAfter(t *testing.T) { - d1 := Date{2016, 12, 31} - d2 := Date{2017, 1, 1} - t1 := Time{5, 6, 7, 8} - t2 := Time{5, 6, 7, 9} - for _, test := range []struct { - dt1, dt2 DateTime - want bool - }{ - {DateTime{d1, t1}, DateTime{d2, t1}, false}, - {DateTime{d1, t1}, DateTime{d1, t2}, false}, - {DateTime{d2, t1}, DateTime{d1, t1}, true}, - {DateTime{d2, t1}, DateTime{d2, t1}, false}, - } { - if got := test.dt1.After(test.dt2); got != test.want { - t.Errorf("%v.After(%v): got %t, want %t", test.dt1, test.dt2, got, test.want) - } - } -} - -func TestMarshalJSON(t *testing.T) { - for _, test := range []struct { - value interface{} - want string - }{ - {Date{1987, 4, 15}, `"1987-04-15"`}, - {Time{18, 54, 2, 0}, `"18:54:02"`}, - {DateTime{Date{1987, 4, 15}, Time{18, 54, 2, 0}}, `"1987-04-15T18:54:02"`}, - } { - bgot, err := json.Marshal(test.value) - if err != nil { - t.Fatal(err) - } - if got := string(bgot); got != test.want { - t.Errorf("%#v: got %s, want %s", test.value, got, test.want) - } - } -} - -func TestUnmarshalJSON(t *testing.T) { - var d Date - var tm Time - var dt DateTime - for _, test := range []struct { - data string - ptr interface{} - want interface{} - }{ - {`"1987-04-15"`, &d, &Date{1987, 4, 15}}, - {`"1987-04-\u0031\u0035"`, &d, &Date{1987, 4, 15}}, - {`"18:54:02"`, &tm, &Time{18, 54, 2, 0}}, - {`"1987-04-15T18:54:02"`, &dt, &DateTime{Date{1987, 4, 15}, Time{18, 54, 2, 0}}}, - } { - if err := json.Unmarshal([]byte(test.data), test.ptr); err != nil { - t.Fatalf("%s: %v", test.data, err) - } - if !cmp.Equal(test.ptr, test.want) { - t.Errorf("%s: got %#v, want %#v", test.data, test.ptr, test.want) - } - } - - for _, bad := range []string{"", `""`, `"bad"`, `"1987-04-15x"`, - `19870415`, // a JSON number - `11987-04-15x`, // not a JSON string - - } { - if json.Unmarshal([]byte(bad), &d) == nil { - t.Errorf("%q, Date: got nil, want error", bad) - } - if json.Unmarshal([]byte(bad), &tm) == nil { - t.Errorf("%q, Time: got nil, want error", bad) - } - if json.Unmarshal([]byte(bad), &dt) == nil { - t.Errorf("%q, DateTime: got nil, want error", bad) - } - } -} diff --git a/vendor/cloud.google.com/go/cloud.go b/vendor/cloud.google.com/go/cloud.go deleted file mode 100644 index 9cf75c5e..00000000 --- a/vendor/cloud.google.com/go/cloud.go +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2014 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/* -Package cloud is the root of the packages used to access Google Cloud -Services. See https://godoc.org/cloud.google.com/go for a full list -of sub-packages. - - -Client Options - -All clients in sub-packages are configurable via client options. These options are -described here: https://godoc.org/google.golang.org/api/option. - - -Authentication and Authorization - -All the clients in sub-packages support authentication via Google Application Default -Credentials (see https://cloud.google.com/docs/authentication/production), or -by providing a JSON key file for a Service Account. See the authentication examples -in this package for details. - - -Timeouts and Cancellation - -By default, all requests in sub-packages will run indefinitely, retrying on transient -errors when correctness allows. To set timeouts or arrange for cancellation, use -contexts. See the examples for details. - -Do not attempt to control the initial connection (dialing) of a service by setting a -timeout on the context passed to NewClient. Dialing is non-blocking, so timeouts -would be ineffective and would only interfere with credential refreshing, which uses -the same context. - - -Connection Pooling - -Connection pooling differs in clients based on their transport. Cloud -clients either rely on HTTP or gRPC transports to communicate -with Google Cloud. - -Cloud clients that use HTTP (bigquery, compute, storage, and translate) rely on the -underlying HTTP transport to cache connections for later re-use. These are cached to -the default http.MaxIdleConns and http.MaxIdleConnsPerHost settings in -http.DefaultTransport. - -For gRPC clients (all others in this repo), connection pooling is configurable. Users -of cloud client libraries may specify option.WithGRPCConnectionPool(n) as a client -option to NewClient calls. This configures the underlying gRPC connections to be -pooled and addressed in a round robin fashion. - - -Using the Libraries with Docker - -Minimal docker images like Alpine lack CA certificates. This causes RPCs to appear to -hang, because gRPC retries indefinitely. See https://github.com/GoogleCloudPlatform/google-cloud-go/issues/928 -for more information. - - -Debugging - -To see gRPC logs, set the environment variable GRPC_GO_LOG_SEVERITY_LEVEL. See -https://godoc.org/google.golang.org/grpc/grpclog for more information. - -For HTTP logging, set the GODEBUG environment variable to "http2debug=1" or "http2debug=2". - -*/ -package cloud // import "cloud.google.com/go" diff --git a/vendor/cloud.google.com/go/examples_test.go b/vendor/cloud.google.com/go/examples_test.go deleted file mode 100644 index c623ba9d..00000000 --- a/vendor/cloud.google.com/go/examples_test.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2018 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package cloud_test - -import ( - "context" - "time" - - "cloud.google.com/go/bigquery" -) - -// To set a timeout for an RPC, use context.WithTimeout. -func Example_timeout() { - ctx := context.Background() - // Do not set a timeout on the context passed to NewClient: dialing happens - // asynchronously, and the context is used to refresh credentials in the - // background. - client, err := bigquery.NewClient(ctx, "project-id") - if err != nil { - // TODO: handle error. - } - // Time out if it takes more than 10 seconds to create a dataset. - tctx, cancel := context.WithTimeout(ctx, 10*time.Second) - defer cancel() // Always call cancel. - - if err := client.Dataset("new-dataset").Create(tctx, nil); err != nil { - // TODO: handle error. - } -} - -// To arrange for an RPC to be canceled, use context.WithCancel. -func Example_cancellation() { - ctx := context.Background() - // Do not cancel the context passed to NewClient: dialing happens asynchronously, - // and the context is used to refresh credentials in the background. - client, err := bigquery.NewClient(ctx, "project-id") - if err != nil { - // TODO: handle error. - } - cctx, cancel := context.WithCancel(ctx) - defer cancel() // Always call cancel. - - // TODO: Make the cancel function available to whatever might want to cancel the - // call--perhaps a GUI button. - if err := client.Dataset("new-dataset").Create(cctx, nil); err != nil { - // TODO: handle error. - } -} diff --git a/vendor/cloud.google.com/go/issue_template.md b/vendor/cloud.google.com/go/issue_template.md deleted file mode 100644 index e2ccef3e..00000000 --- a/vendor/cloud.google.com/go/issue_template.md +++ /dev/null @@ -1,17 +0,0 @@ -(delete this for feature requests) - -## Client - -e.g. PubSub - -## Describe Your Environment - -e.g. Alpine Docker on GKE - -## Expected Behavior - -e.g. Messages arrive really fast. - -## Actual Behavior - -e.g. Messages arrive really slowly. \ No newline at end of file diff --git a/vendor/cloud.google.com/go/keys.tar.enc b/vendor/cloud.google.com/go/keys.tar.enc deleted file mode 100644 index c54408c93a2b7d36467ceced9e697a7e6be66db5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10256 zcmV+rDDT%d%4FE-XGE3p;$)uBB?9V+ouudaKhoM}hbuNiA~pZ{E8E-hBY`-Dn_Q%D z)1eTB-6xjC`t3rjAH(j)i+}xJ0#_k#k2Ei-53?7pb(EE)s?ceMM>7zAAv>$SzP9-h zHi8>*N=*@`J_+b(a1jXZ(+M=#xZ;N&knOE6gw@5_dZB+sYusIMbmvbdeU>he9Zmq3 z7IfMkHTjLY+Jn_1Zy14{?#2fgMv-vh_Qa|bOItot{b4e5?QEPEqMPX*xdx>5w zTt*8it3>fa)awDKDNh0HtzYlzJ@1<@O1)#R#Fzw2S5FB;2IhW)5i#@B)p-qFz;$z?e{Z-huragATmXz zSTOC<2gDF{%_s}F^%zNV6N~igmTwHb1mBT*^CA^@soq^ z+<#m8D%(S_$p5}UYl@NJoJBV!g zc?^JRPT@FROn^^CBj~Dy0VyPXaTviGoF$seUez{s&nn4wmvaTbrTv`zaFmIEs8-bT z-Sbw%Fj}r!&$18`7|;b`!$zoOD1QAtz>~%g{DVJRm(|bbb**QdepSwaVs#bKhm-+ zc_CBe!I}>4=DyBd6Omd71Ktp`6nhA^$3@GdbA=U3t)2S?nqpLS!Wxla?bWRJ2YHAH z@Df|>tCsw(=GxQXg1;oz`r77C(uGgsGGUaPCM^9K1nhz~>Uim_t%z;Ud3W?cZ#~g9 z)+_0w$>bCua;W+Rnj}EDfXBFn8{yz7uyDfL&2IZ9t+2Xb{@iana-TFz?ic-2KCR=a zpX;Nq#W~!?bXJdp;LRQo>I<}bs5WSJhGZ5$!zEtr;lcaph1p;f1gj{AODENdep|_6 z?#}50L@7Gw(Kg;u3%0iQ<^XAGtbDi~s8_ROq~9(eVl^5eC>F>|;Z{U`0%K$c=7n!~ zaVy7Y8gbPa)sO!@(+qeqrTAHlZntqJMFfE-_icOnY3Zt+?Ll%L3y@I#1sTi{*zdb< zFJA28ZwTxgzNZ=tK7W=1*z1XZo$mhW>u`OuFDMHpLK76y=jo}^vXUE_T_YDo)-j*v z>nHKlA2k14n}!u%<DpyyKCHc>9Dm!D3O~<^1!z&M zx^bZ|4LkR5o~AJB@y=+bpTT#q`eZP5Pzi#wNq1&F`{%j-_o+IJ39Qa7;ttdY#ekn9 zRDymxZq)uPZW2oMD`d!%9Vwy%;xB7y8Ou!=N?8Z+KjoYk%5pT)pzXGC~rMB#16J&}C&~&Li+e>{P>ZDThyl`m|SJix~w$9%GCpFkcO{PR0TBpXNdn_^2mcdJ;;^5lPA;< zdW{p!%(!4YGN1I7e5|b{k42|owjY<`?10CCRL-h;-2_JslMUN1UXpN(JgX%-d1nM%y*W=r72P~k4o z?9AmJtr7{J#GyEe=X68u__?HvbD}zd#6=N=So*5a<7yNCgtFvoZ6X@_Os9ESREtxx zY_vzNJgca!y*$ZCuJ{zSB3P^W8uQ!GdKU-0TB`|4MjOG`Qd!8O30Wf}c(B;p{P6Wp zD!7UDS(PCf3piqXn2p^t&vKK)JNVIn%R4LuHXk#6g2Va*AKLv7gW1@|EGq2(vIqzv zC3M+ilY&N-u_bdhcB_{khbo2oB1ou`wF-H_33M__b<;;4Z9o_meKvKfA+U^JZlxq1F)5c73St7fs>0@K5J?EHJP=N@ zI!-=!^J5riIY#r7kBBJ%9@svn*J;(BH~$?6Ne$SL^AJ& z|E9^+ZAD_lGJb@z{?6KK9+qrXYev>%Lwc- z#SyG5FHLKzvyzveqMmSl1``^qr@-X$6n}tn4?x5))?&@~Rx;r3<2D4;MW7T=meKuj zR5J`_zckAHW+b@5`mN(70i3DVYhty}{kaW=r&EqIj;kV=(gz6ShmX8Jb?L4pwZ~)g zg2Yp+%J-#Qd_*cF7~M_h9w}A@mZv!CI5O}kIWG*dO@QHZXUQ^_b2*~0ivGMGOnbL7 zSePL`G{Czy5&5)B@~|`FV9)=Iw6+J2#+=^Rr`8AuHK}dX{?}R>UHUR7c3b1U@{437 z&nzV=x*+N)uMH#o0J?b(K2Y@5uLoF(K8hCU18x|z)sIt3d%TineP)`_cQud;z5+rFMmr_H+e1Ze zaL;M0h-v|A)N4a0CjUC?43r88z^-JOG`oUHh82hGIM>I}cqrFFt?_Xap=lJW(=m41 zjxh>qf&p8!w_1$~TK$|VM7b&N5>a%@EM%D~wGkYdbBRb2bvQn z65?`Uh5+1cBV$Bh+)lxH$fi}m`~gNU@&rWjbbYJH z``*)UGVsbc&K9A>$xO>5QFV+btPpB&f)!;eWjhcyg&$=1OuNYGbl=1wBb&09Wz4Nu zk;3IcUq~CcS2^)LN!Q3v(h1yUhrgmY5$H)AX1wl4xB ziC12Tr9IZuDZe!$k=)}G8iBMo;URV0uI7^G5nwVf|3+6yMTDZg7ygmq0{^u{bbv64 z`$$@mZLb>_QnOZKgcYgTpy6Yz&f@B4^F1@*bBS578`^3 z{)00y3}rzArlWG)=njUp>mN^U0qj-~>c&__-}tYf??|ntj~9}LLh9>)rw7P<3{6D4fpnnf0B!5WpdcnDc?c4Mo427}3y=lT^*z19nRYh0^bu;hikJLh)un zA2)Q0A1aR5M@4cpi(*sscB)7RarN*=ppr!JH^D)S~d`99;&g-j4h;pj-I_2s?~T0^0*U7}&j7YS znQ6ebPqs6C?GELt+(0d~djDz*)kU7F|_OK0WvjBczgOJAVl*VY~ zew1ENHvN6L*$Rq&EIWxYRG^qwTvXEUraD03#YQdE1a9;v%CrqpB?6(YuJ@v)abLRN z4RaZAd+c4T82CN9)5dsmGsDJ^?!r(X2~EqFeWUEDEz+7TOe1$Y&>O0Mtc_ZW1bTf5 z_GwJ(S?o*6%`|U4E^}%XsKe#qy?NND3{NE4Cj~1YNfJ%$*0<35lxsaTHtKJa`)aih z{gk%2w#chF_vMbi=kh;bROmspkG7cCLeKZL-p?xo0T^&!J1zJk37IC15%zfhKr*?O zB{(g?z$}&=u>w0jZ!nF<{H08V%Ljc7K0RA@fvLrf$_K)mzY-)JoIUQQmt8$}`&#Gw zS`=d~Zm^W~+pK>%1u(pdoPWT*UjmD=g}?T`x7=w#^%C5h=I?~n67kd6{UmAcMeGsD z-2t(#2b=83S^Gguxg~*xt^5m$^7ap%YJRbDbj)jzz9kc_=wyG%`B~_YUk2Rt&m+YZ zQp4Sns)1a_Pr^F|syj^4meXW_ce)LW0969-dm}|#-zDwtOBZM#WgHFB*Mmugft&m% zkM6A0f{{+xbP5900`p(?q+nC7L^L|D<{S@ar#$~LX~Qez{!>CYKJtBY zdZV6=ah-z$oH3+F66iZMDlMg9U+azmU%c}65tPVuh{eh^RW<7C>8-8LK^`4trY)=| z&dZYzpQwT9K3nk+D~mW2S2<|M3vc%+UIyOf4&|b63<=SJ4!sxQ0)QOdP}Xbkh(#A5 zp!bI3*&z^p`U(2@^^Re)OzW&0hchNFAhQ?>7rqDE7VE{n(>Ke%F1v7z)DK}j>hyT* zSCDi*CxWm(d^J^`_8G+m<~Q(!b!Ir+UGxD-nEp?Qbj9M`sHnnnSF|C|>0FIp!m(|$A^4xe3?E;E_ZJB8eXvVCny>l%B1hfPNK`dMV3Sf{i>vy^MMGzr@pRY$G!aYTxW5ytW^CjMkw`}7jgQ&K#?Dz;3 z@uoo4!Y1eMUun$2vxdbY-Ku z(e?Y73Xc7$9>WBz1lZIjPmSuq_q;-Klcp2kV3V7EqU)Mn=9lDK~XgBUQ&amv52 zx;0w8mYJV={o!&f4rc}5Do5@fM}Nmew>9m}K+ zkmuez$a%1$?&?jQ~|rD-iejJaHYQd|HcOmo3IJ) zaE+2%n}N5Ec*Tq|+XimH{d4;WuNH$|8PIKlG;99&z6ZLzZ`3nE+&j0}U0D{bs_L-W z0wd0O4*h&!@WOG{jRbx+o==YMlQ}V#kp%m|!LQ%(P!`V{>NxsOVBtjEb%%=_y_9$v za7(VfVGVPPV{1al(HnPLz18*HU~SgoQmc}=xUM2fv0j86u>4&vD$qMc+;R-^QDy{@ za)E=gaZ;6Mh6p!N>5!^mI85}_^cEJ>m{6g?%A4bzKkcXTz?yyNB1|b#cPL%u&2I?b z`JfD*B_RqRiKxJphax@mQ(+XhnQgUzo90RZ_T^;VXng`Wrp+w_b<`kwQYAJ%3@*pT z)9J@h_ocUk+-r&p3vHe##RdP4O>NIv8wO?10Y?bGt}OInrZ8`HrE23maFr!~>nMVm z+5p!YWsS8K7%Q_%*TSkKW zZ|u4$D{zG52B8i6$2}gN*WhL=!oL6kP$b|dpujKGoVWYY51>g(yFz=oXQ`dqhbs(` zLLcl>+Rw<>-zo=K&ip{9-bTAyY9+T7&9j%KH1U54jyhvJ*ZS(0 zGXF?vTsAye2K^6DSU?(Rc%Z%T6%JPuHE~BJZE2k?m=3h60%{jyaij|6*YKJEf2fi84{XKF57(aA{pX0&URv2kKdekL<@ zsdD@wA?0~6_q^mRN zJ-ON!F>A&yBATCVNY&R@!Qd=?DD}qORWp}x`-5K95}8sxa^P03?hqM9x9PTcnFD|U zF)Q5VWa{}#Y81o79t7!dY4iekBNS5k3}{#NGJ@ZRFaXcf@5dY5*C92&SXSfqH{Klp z#15kl21f`$$t;6T%ac5c^D8j&)gPQ$Np8*0p28@xs;oVkq9P6Z0mIQ|H2=Oz8)b9L zFnP{$Wv9>zG(pll*G_vcu@9F1&lCL!_Y#!0Zgx84_)cSY9;=>Sy&Wdflx=Qg^6I%z z+K`Pyyo6pXYaMQmqM{Y)k(<*7`}3!`6_1^wl+i4!KX`}5qVyW#k~ZWnlGUH`rl{z|#og&2ZZrhd z@>nz$D@K;f{+@`ecgbJDk8n7+@XeqW%93HBGD-p4>K~EflaXSDIcjCte&{29?fZS> zjQDB%f@A24i_Pkh{M)|niy})S@umuj)fYDq(2g}fTqSw4Fv%yLoj%KNkabdQ3I@RQ z#`glL(>t%eAS2vwZeuEnA!r7~Q4t62PY75RFA%>_6l5lHD6g2>4ztj$?mG2fr;#kJ9ltNHAEHf1Hc_&I+4?Jf*2!m<4`WRmdVO{c6Lci8nfhIurItki0q z2uqvlHY^UhEx)A5;uFOK1zVbHIRORe2s(fJi@(0`A!6a@n-69oBTVCdVAcl_DJV1| z%q)}O~01yRqlo60#D?r>c; zw+LDyQ`G(7F=QFmH*!4LTt-j1WopoQU(x8L0A)S=#>c--+k z^udb{OAvnC$hP?qA?|;DVuM-?>5Z76yH^H5F(Ct5>GQx@gt=sNm`AXW{vPHo1iV5; z#ok__P;nbv@k`UtUKpFwzxEV2S7j#S`hq5#$nphU#7%U`^q=TCCy|BsQ-4FWtBt;5 z5lg1xr(5kyc?cHPh}yK|%6IGmt7b}`hwegg#Asf33g1ie(%{k+weflY)$~f^?alCW z3Gb~c@R~cF7(=6Nq48~_B$G3cse9(DMDYpE@GkPlg0VFI1kWqJ^g=cJ62&PRLhIb+ zm9>n?^rv2cmb9T?m(9)KPY}> zV4amq=dG7byHc&iu^pn6qT-Y;VH`K2!>?EByg}S+q;)QTExZ73a8CFdAZ= zJDXGG@@Iw=tw1dIp%(1h;qUcMoBBk!GcA2$Bi+X9Ktf1@liH=D_2+3}^B!;oU;3y` z=}ws9(;*@fhX$ad859=^%+iyXGPg5&*T@I3f1_5{`XqxL5b=#lJSd2pHV;2^H_PuN-b1#X@v zOalvs?7N1WkriZlHBCXYF1Tr?a#o(`b_lv+E1(*n->RG95fP&2W4f`bY91$coOo`HUymltOKZ<&U~l7h5Gx^l_0;EuM9dv$dUd zK~xZLFR84Cacx*Ek8$Zksq8$;4IL=KR16!op&U&=gpqup${L3ys$GY-Qs=uZ>W2=t z_1kvZfrUYeCl2OfN8n2>-7Bik8cHh4#_VnJ=f;IA#K;_m*y8k9;>O`-@~)iox5GQv zNkrMGH67FuX&IV%?@cb^|E~vZ4$kfv+OgvYsm_jtZq3UE6D?dE>H+1gpI1IDK@esM zl1r3dIVRALnR0w5Nm5O9F0u(gf6%>j{B#&9-GPPm;fY7TM_HCB22GSXj$m zIkO=TG>?IKTN% z?c5tk4D78k46*mQlO2wC@{)hJm;bQv9VT@=z z52g=a90@rXmXpz#?Z{25(jQB~|EVZ3Y~n*&;6Oq+ROAg2xx;SrIVN^-OBviXSHSB| zv5#ug&T8x1ywY0FW4q<8!nIy%<#?C;3CiLMT*#49ASeKxP1_N{=!O0A%p_lzh6l$y ze!EwGvsK#qM%MKRul!?BrY99K<{Tm4{}q+Df<>4fBszF0YKoMst2ro|#k5W^8UWbG zIWVC1jj{Babn;2P1?sQt6=H8A=rqY=xAmqZ8~HkNm<4ASTvX?aL zJp+Dt`u&BjUQY|nz5v4gv-89i4`OfK1;7>0X8%qVH0{0@lN@26Y{PIlLt- zylUx##ov|6-<=}cEN)?w^JNZD9MogG!z=3De$lR(1Pwr7?+&*83cSRU`=5xfH@4gJS2!c?+l*BK97R?^pnANZD!J_tNc>Xs8?G6}~NF?V)3)^~O~!P}S1jwV$iV&PrqN z19JV{h(0sF+8B&j1suhG7Hr9xgr3T}0*K%m6YBXuB_s-czIp?o##_7*xDREqzN%Kl zNV~KYHb;%_QaBn$#MmE-5ydy0RzFp<&N2z7W6l};d&jcLWiu3{2FzI$wUN$=Pmbn1 zt@UR-n9lI58SNOkyiiEwk3A`wK%0Bq(Qj{&;i7n$g3QS&xkqs1-Os=tsfxs_fDZ3k z%OF3R$~XVaGpc<|xP@|S9^rlClUXgbtoDimos*dZCa#%~)hmQyw`AhQel4D89Ttd8 zWE(M3K_JLO`6yN@E!l4tbOw*w3)Bo-KelG7!Qf8A1e&^1o^Vh7Kg#hI4hJ~T+lZ5$ z>>{^w9IE&>1MSK*rT526L2}x+VSX#FpP2s?KaVjN;%*R;Uh&zxhJzk^Wdjo~<@glj zsPoY!vVF`RU-!9}go-G%Hg-D-GlDs4CK0^q*bw-Eg0l=BYB<6}F0fd1Iw zB1tF27B$%!k8B!w06En(S&jG9p)tgw^RK^{{?KY#GDt-e-r2iG^QusFbA|gAmpFj( zz1?ajcKCvf?=rs=(L75&ubCZyluky9Zq%~J3IOmA#BV>2anKf%kD0_dxA~g`YMC}H zzWFYK31-LFX}uTf2NzcsLzOjQq3}F$->x8uzYq{cpxex}8k&AjBKbD0*LHoC;d=Kt zeLV?otF=HCNYQWjph}pR+-9S>{MD)-MpvZiri%9AoKj8Ewd3wq`k^qcpgS816j{9S zAFmtRD;^$JwD`Sy4fgJ2-SP%g*LrgNgtXAT_xyf!J%L`ZD}?#jI3+5y0*qW3nBDfG zuid}anyzn$dw#Fkr{lbSPK(oAPYXj>faM7o&?0fP;2?Labw>2HtSqW%u^6pX+n&o( zskce>)_;SWUHi@*mKtvv@ z;LaGT)#$z^4A-ETCcp$7{>fjh#+y(`YsB+xs7@yR1Pp$h7gSXP_%~OWw`d>*+|H5R z+ahN;BqWl??#FnMwAS&rPA(6%_Cr zf#xf>)S62xWGvUC+1#iXJwap&WlQ{vx93Q%$FrTIRfEv>QNVa(RhNhH=_%|w-2Z;j zg>-WT2OWJ(n#q_B%?4{}cyaHHAYejfy1>75=6G918Z?uIS3P%&b*V^IPcq2RX14O6 z6%67B^|GtUeCt$4`MgLsR&L;yUZh92+o#!Z`>-V4fa(J4ejdWqL6Uh3R!x~|1qA~k zC?{j@0aPoHP#el+L>b~bL;NTCuo>6#(jM$^qx+GxuIiq;Z}vR2kF9Ap$mWQ;L~ueZjbYUtRN z_Mn)W%w^WIvCQ#eCN82;?SS`r!_hrZb7dgFvb`@Aa!8T(l-r zMey26L9@dxr@EgpBfm$4aL)pn<>}zMo-JH#8g3J4%C_cRSlX`Z2J~PgiLwi5oXXrH zZ@rm{UUp$+{}3@m7j&dAV0eYbIf;A)Y6wpyDMnB6HSY}G^TS)%Bxi+y*4VYuJ*6Zuv{ zzCpNgC%HyRX!s@|DpK}y+gN9#%HwmG!eodpS4t|$x0P7{iA3*%Q18Ussq-}u0bghs zLY(c)DTR5a9`%|+;IIHK>?S23MMzX;-BWU%IBomnM12~=oS!!&rEv;Uj8D86G9XK diff --git a/vendor/cloud.google.com/go/license_test.go b/vendor/cloud.google.com/go/license_test.go deleted file mode 100644 index a30cad19..00000000 --- a/vendor/cloud.google.com/go/license_test.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2016 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package cloud - -import ( - "bytes" - "io/ioutil" - "os" - "path/filepath" - "strings" - "testing" -) - -var sentinels = []string{ - "Copyright", - "Google", - `Licensed under the Apache License, Version 2.0 (the "License");`, -} - -func TestLicense(t *testing.T) { - t.Parallel() - err := filepath.Walk(".", func(path string, fi os.FileInfo, err error) error { - if err != nil { - return err - } - - if ext := filepath.Ext(path); ext != ".go" && ext != ".proto" { - return nil - } - if strings.HasSuffix(path, ".pb.go") { - // .pb.go files are generated from the proto files. - // .proto files must have license headers. - return nil - } - if path == "bigtable/cmd/cbt/cbtdoc.go" { - // Automatically generated. - return nil - } - if path == "cmd/go-cloud-debug-agent/internal/debug/elf/elf.go" { - // BSD license, which is compatible, is embedded in the file. - return nil - } - src, err := ioutil.ReadFile(path) - if err != nil { - return nil - } - src = src[:300] // Ensure all of the sentinel values are at the top of the file. - - // Find license - for _, sentinel := range sentinels { - if !bytes.Contains(src, []byte(sentinel)) { - t.Errorf("%v: license header not present. want %q", path, sentinel) - return nil - } - } - - return nil - }) - if err != nil { - t.Fatal(err) - } -} diff --git a/vendor/cloud.google.com/go/old-news.md b/vendor/cloud.google.com/go/old-news.md deleted file mode 100644 index 6a8b84d7..00000000 --- a/vendor/cloud.google.com/go/old-news.md +++ /dev/null @@ -1,698 +0,0 @@ -_February 26, 2018_ - -*v0.19.0* - -- bigquery: - - Support customer-managed encryption keys. - -- bigtable: - - Improved emulator support. - - Support GetCluster. - -- datastore: - - Add general mutations. - - Support pointer struct fields. - - Support transaction options. - -- firestore: - - Add Transaction.GetAll. - - Support document cursors. - -- logging: - - Support concurrent RPCs to the service. - - Support per-entry resources. - -- profiler: - - Add config options to disable heap and thread profiling. - - Read the project ID from $GOOGLE_CLOUD_PROJECT when it's set. - -- pubsub: - - BEHAVIOR CHANGE: Release flow control after ack/nack (instead of after the - callback returns). - - Add SubscriptionInProject. - - Add OpenCensus instrumentation for streaming pull. - -- storage: - - Support CORS. - - -_January 18, 2018_ - -*v0.18.0* - -- bigquery: - - Marked stable. - - Schema inference of nullable fields supported. - - Added TimePartitioning to QueryConfig. - -- firestore: Data provided to DocumentRef.Set with a Merge option can contain - Delete sentinels. - -- logging: Clients can accept parent resources other than projects. - -- pubsub: - - pubsub/pstest: A lighweight fake for pubsub. Experimental; feedback welcome. - - Support updating more subscription metadata: AckDeadline, - RetainAckedMessages and RetentionDuration. - -- oslogin/apiv1beta: New client for the Cloud OS Login API. - -- rpcreplay: A package for recording and replaying gRPC traffic. - -- spanner: - - Add a ReadWithOptions that supports a row limit, as well as an index. - - Support query plan and execution statistics. - - Added [OpenCensus](http://opencensus.io) support. - -- storage: Clarify checksum validation for gzipped files (it is not validated - when the file is served uncompressed). - - -_December 11, 2017_ - -*v0.17.0* - -- firestore BREAKING CHANGES: - - Remove UpdateMap and UpdateStruct; rename UpdatePaths to Update. - Change - `docref.UpdateMap(ctx, map[string]interface{}{"a.b", 1})` - to - `docref.Update(ctx, []firestore.Update{{Path: "a.b", Value: 1}})` - - Change - `docref.UpdateStruct(ctx, []string{"Field"}, aStruct)` - to - `docref.Update(ctx, []firestore.Update{{Path: "Field", Value: aStruct.Field}})` - - Rename MergePaths to Merge; require args to be FieldPaths - - A value stored as an integer can be read into a floating-point field, and vice versa. -- bigtable/cmd/cbt: - - Support deleting a column. - - Add regex option for row read. -- spanner: Mark stable. -- storage: - - Add Reader.ContentEncoding method. - - Fix handling of SignedURL headers. -- bigquery: - - If Uploader.Put is called with no rows, it returns nil without making a - call. - - Schema inference supports the "nullable" option in struct tags for - non-required fields. - - TimePartitioning supports "Field". - - -_October 30, 2017_ - -*v0.16.0* - -- Other bigquery changes: - - `JobIterator.Next` returns `*Job`; removed `JobInfo` (BREAKING CHANGE). - - UseStandardSQL is deprecated; set UseLegacySQL to true if you need - Legacy SQL. - - Uploader.Put will generate a random insert ID if you do not provide one. - - Support time partitioning for load jobs. - - Support dry-run queries. - - A `Job` remembers its last retrieved status. - - Support retrieving job configuration. - - Support labels for jobs and tables. - - Support dataset access lists. - - Improve support for external data sources, including data from Bigtable and - Google Sheets, and tables with external data. - - Support updating a table's view configuration. - - Fix uploading civil times with nanoseconds. - -- storage: - - Support PubSub notifications. - - Support Requester Pays buckets. - -- profiler: Support goroutine and mutex profile types. - - -_October 3, 2017_ - -*v0.15.0* - -- firestore: beta release. See the - [announcement](https://firebase.googleblog.com/2017/10/introducing-cloud-firestore.html). - -- errorreporting: The existing package has been redesigned. - -- errors: This package has been removed. Use errorreporting. - - -_September 28, 2017_ - -*v0.14.0* - -- bigquery BREAKING CHANGES: - - Standard SQL is the default for queries and views. - - `Table.Create` takes `TableMetadata` as a second argument, instead of - options. - - `Dataset.Create` takes `DatasetMetadata` as a second argument. - - `DatasetMetadata` field `ID` renamed to `FullID` - - `TableMetadata` field `ID` renamed to `FullID` - -- Other bigquery changes: - - The client will append a random suffix to a provided job ID if you set - `AddJobIDSuffix` to true in a job config. - - Listing jobs is supported. - - Better retry logic. - -- vision, language, speech: clients are now stable - -- monitoring: client is now beta - -- profiler: - - Rename InstanceName to Instance, ZoneName to Zone - - Auto-detect service name and version on AppEngine. - -_September 8, 2017_ - -*v0.13.0* - -- bigquery: UseLegacySQL options for CreateTable and QueryConfig. Use these - options to continue using Legacy SQL after the client switches its default - to Standard SQL. - -- bigquery: Support for updating dataset labels. - -- bigquery: Set DatasetIterator.ProjectID to list datasets in a project other - than the client's. DatasetsInProject is no longer needed and is deprecated. - -- bigtable: Fail ListInstances when any zones fail. - -- spanner: support decoding of slices of basic types (e.g. []string, []int64, - etc.) - -- logging/logadmin: UpdateSink no longer creates a sink if it is missing - (actually a change to the underlying service, not the client) - -- profiler: Service and ServiceVersion replace Target in Config. - -_August 22, 2017_ - -*v0.12.0* - -- pubsub: Subscription.Receive now uses streaming pull. - -- pubsub: add Client.TopicInProject to access topics in a different project - than the client. - -- errors: renamed errorreporting. The errors package will be removed shortly. - -- datastore: improved retry behavior. - -- bigquery: support updates to dataset metadata, with etags. - -- bigquery: add etag support to Table.Update (BREAKING: etag argument added). - -- bigquery: generate all job IDs on the client. - -- storage: support bucket lifecycle configurations. - - -_July 31, 2017_ - -*v0.11.0* - -- Clients for spanner, pubsub and video are now in beta. - -- New client for DLP. - -- spanner: performance and testing improvements. - -- storage: requester-pays buckets are supported. - -- storage, profiler, bigtable, bigquery: bug fixes and other minor improvements. - -- pubsub: bug fixes and other minor improvements - -_June 17, 2017_ - - -*v0.10.0* - -- pubsub: Subscription.ModifyPushConfig replaced with Subscription.Update. - -- pubsub: Subscription.Receive now runs concurrently for higher throughput. - -- vision: cloud.google.com/go/vision is deprecated. Use -cloud.google.com/go/vision/apiv1 instead. - -- translation: now stable. - -- trace: several changes to the surface. See the link below. - -[Code changes required from v0.9.0.](https://github.com/GoogleCloudPlatform/google-cloud-go/blob/master/MIGRATION.md) - - -_March 17, 2017_ - -Breaking Pubsub changes. -* Publish is now asynchronous -([announcement](https://groups.google.com/d/topic/google-api-go-announce/aaqRDIQ3rvU/discussion)). -* Subscription.Pull replaced by Subscription.Receive, which takes a callback ([announcement](https://groups.google.com/d/topic/google-api-go-announce/8pt6oetAdKc/discussion)). -* Message.Done replaced with Message.Ack and Message.Nack. - -_February 14, 2017_ - -Release of a client library for Spanner. See -the -[blog post](https://cloudplatform.googleblog.com/2017/02/introducing-Cloud-Spanner-a-global-database-service-for-mission-critical-applications.html). - -Note that although the Spanner service is beta, the Go client library is alpha. - -_December 12, 2016_ - -Beta release of BigQuery, DataStore, Logging and Storage. See the -[blog post](https://cloudplatform.googleblog.com/2016/12/announcing-new-google-cloud-client.html). - -Also, BigQuery now supports structs. Read a row directly into a struct with -`RowIterator.Next`, and upload a row directly from a struct with `Uploader.Put`. -You can also use field tags. See the [package documentation][cloud-bigquery-ref] -for details. - -_December 5, 2016_ - -More changes to BigQuery: - -* The `ValueList` type was removed. It is no longer necessary. Instead of - ```go - var v ValueList - ... it.Next(&v) .. - ``` - use - - ```go - var v []Value - ... it.Next(&v) ... - ``` - -* Previously, repeatedly calling `RowIterator.Next` on the same `[]Value` or - `ValueList` would append to the slice. Now each call resets the size to zero first. - -* Schema inference will infer the SQL type BYTES for a struct field of - type []byte. Previously it inferred STRING. - -* The types `uint`, `uint64` and `uintptr` are no longer supported in schema - inference. BigQuery's integer type is INT64, and those types may hold values - that are not correctly represented in a 64-bit signed integer. - -* The SQL types DATE, TIME and DATETIME are now supported. They correspond to - the `Date`, `Time` and `DateTime` types in the new `cloud.google.com/go/civil` - package. - -_November 17, 2016_ - -Change to BigQuery: values from INTEGER columns will now be returned as int64, -not int. This will avoid errors arising from large values on 32-bit systems. - -_November 8, 2016_ - -New datastore feature: datastore now encodes your nested Go structs as Entity values, -instead of a flattened list of the embedded struct's fields. -This means that you may now have twice-nested slices, eg. -```go -type State struct { - Cities []struct{ - Populations []int - } -} -``` - -See [the announcement](https://groups.google.com/forum/#!topic/google-api-go-announce/79jtrdeuJAg) for -more details. - -_November 8, 2016_ - -Breaking changes to datastore: contexts no longer hold namespaces; instead you -must set a key's namespace explicitly. Also, key functions have been changed -and renamed. - -* The WithNamespace function has been removed. To specify a namespace in a Query, use the Query.Namespace method: - ```go - q := datastore.NewQuery("Kind").Namespace("ns") - ``` - -* All the fields of Key are exported. That means you can construct any Key with a struct literal: - ```go - k := &Key{Kind: "Kind", ID: 37, Namespace: "ns"} - ``` - -* As a result of the above, the Key methods Kind, ID, d.Name, Parent, SetParent and Namespace have been removed. - -* `NewIncompleteKey` has been removed, replaced by `IncompleteKey`. Replace - ```go - NewIncompleteKey(ctx, kind, parent) - ``` - with - ```go - IncompleteKey(kind, parent) - ``` - and if you do use namespaces, make sure you set the namespace on the returned key. - -* `NewKey` has been removed, replaced by `NameKey` and `IDKey`. Replace - ```go - NewKey(ctx, kind, name, 0, parent) - NewKey(ctx, kind, "", id, parent) - ``` - with - ```go - NameKey(kind, name, parent) - IDKey(kind, id, parent) - ``` - and if you do use namespaces, make sure you set the namespace on the returned key. - -* The `Done` variable has been removed. Replace `datastore.Done` with `iterator.Done`, from the package `google.golang.org/api/iterator`. - -* The `Client.Close` method will have a return type of error. It will return the result of closing the underlying gRPC connection. - -See [the announcement](https://groups.google.com/forum/#!topic/google-api-go-announce/hqXtM_4Ix-0) for -more details. - -_October 27, 2016_ - -Breaking change to bigquery: `NewGCSReference` is now a function, -not a method on `Client`. - -New bigquery feature: `Table.LoaderFrom` now accepts a `ReaderSource`, enabling -loading data into a table from a file or any `io.Reader`. - -_October 21, 2016_ - -Breaking change to pubsub: removed `pubsub.Done`. - -Use `iterator.Done` instead, where `iterator` is the package -`google.golang.org/api/iterator`. - -_October 19, 2016_ - -Breaking changes to cloud.google.com/go/bigquery: - -* Client.Table and Client.OpenTable have been removed. - Replace - ```go - client.OpenTable("project", "dataset", "table") - ``` - with - ```go - client.DatasetInProject("project", "dataset").Table("table") - ``` - -* Client.CreateTable has been removed. - Replace - ```go - client.CreateTable(ctx, "project", "dataset", "table") - ``` - with - ```go - client.DatasetInProject("project", "dataset").Table("table").Create(ctx) - ``` - -* Dataset.ListTables have been replaced with Dataset.Tables. - Replace - ```go - tables, err := ds.ListTables(ctx) - ``` - with - ```go - it := ds.Tables(ctx) - for { - table, err := it.Next() - if err == iterator.Done { - break - } - if err != nil { - // TODO: Handle error. - } - // TODO: use table. - } - ``` - -* Client.Read has been replaced with Job.Read, Table.Read and Query.Read. - Replace - ```go - it, err := client.Read(ctx, job) - ``` - with - ```go - it, err := job.Read(ctx) - ``` - and similarly for reading from tables or queries. - -* The iterator returned from the Read methods is now named RowIterator. Its - behavior is closer to the other iterators in these libraries. It no longer - supports the Schema method; see the next item. - Replace - ```go - for it.Next(ctx) { - var vals ValueList - if err := it.Get(&vals); err != nil { - // TODO: Handle error. - } - // TODO: use vals. - } - if err := it.Err(); err != nil { - // TODO: Handle error. - } - ``` - with - ``` - for { - var vals ValueList - err := it.Next(&vals) - if err == iterator.Done { - break - } - if err != nil { - // TODO: Handle error. - } - // TODO: use vals. - } - ``` - Instead of the `RecordsPerRequest(n)` option, write - ```go - it.PageInfo().MaxSize = n - ``` - Instead of the `StartIndex(i)` option, write - ```go - it.StartIndex = i - ``` - -* ValueLoader.Load now takes a Schema in addition to a slice of Values. - Replace - ```go - func (vl *myValueLoader) Load(v []bigquery.Value) - ``` - with - ```go - func (vl *myValueLoader) Load(v []bigquery.Value, s bigquery.Schema) - ``` - - -* Table.Patch is replace by Table.Update. - Replace - ```go - p := table.Patch() - p.Description("new description") - metadata, err := p.Apply(ctx) - ``` - with - ```go - metadata, err := table.Update(ctx, bigquery.TableMetadataToUpdate{ - Description: "new description", - }) - ``` - -* Client.Copy is replaced by separate methods for each of its four functions. - All options have been replaced by struct fields. - - * To load data from Google Cloud Storage into a table, use Table.LoaderFrom. - - Replace - ```go - client.Copy(ctx, table, gcsRef) - ``` - with - ```go - table.LoaderFrom(gcsRef).Run(ctx) - ``` - Instead of passing options to Copy, set fields on the Loader: - ```go - loader := table.LoaderFrom(gcsRef) - loader.WriteDisposition = bigquery.WriteTruncate - ``` - - * To extract data from a table into Google Cloud Storage, use - Table.ExtractorTo. Set fields on the returned Extractor instead of - passing options. - - Replace - ```go - client.Copy(ctx, gcsRef, table) - ``` - with - ```go - table.ExtractorTo(gcsRef).Run(ctx) - ``` - - * To copy data into a table from one or more other tables, use - Table.CopierFrom. Set fields on the returned Copier instead of passing options. - - Replace - ```go - client.Copy(ctx, dstTable, srcTable) - ``` - with - ```go - dst.Table.CopierFrom(srcTable).Run(ctx) - ``` - - * To start a query job, create a Query and call its Run method. Set fields - on the query instead of passing options. - - Replace - ```go - client.Copy(ctx, table, query) - ``` - with - ```go - query.Run(ctx) - ``` - -* Table.NewUploader has been renamed to Table.Uploader. Instead of options, - configure an Uploader by setting its fields. - Replace - ```go - u := table.NewUploader(bigquery.UploadIgnoreUnknownValues()) - ``` - with - ```go - u := table.NewUploader(bigquery.UploadIgnoreUnknownValues()) - u.IgnoreUnknownValues = true - ``` - -_October 10, 2016_ - -Breaking changes to cloud.google.com/go/storage: - -* AdminClient replaced by methods on Client. - Replace - ```go - adminClient.CreateBucket(ctx, bucketName, attrs) - ``` - with - ```go - client.Bucket(bucketName).Create(ctx, projectID, attrs) - ``` - -* BucketHandle.List replaced by BucketHandle.Objects. - Replace - ```go - for query != nil { - objs, err := bucket.List(d.ctx, query) - if err != nil { ... } - query = objs.Next - for _, obj := range objs.Results { - fmt.Println(obj) - } - } - ``` - with - ```go - iter := bucket.Objects(d.ctx, query) - for { - obj, err := iter.Next() - if err == iterator.Done { - break - } - if err != nil { ... } - fmt.Println(obj) - } - ``` - (The `iterator` package is at `google.golang.org/api/iterator`.) - - Replace `Query.Cursor` with `ObjectIterator.PageInfo().Token`. - - Replace `Query.MaxResults` with `ObjectIterator.PageInfo().MaxSize`. - - -* ObjectHandle.CopyTo replaced by ObjectHandle.CopierFrom. - Replace - ```go - attrs, err := src.CopyTo(ctx, dst, nil) - ``` - with - ```go - attrs, err := dst.CopierFrom(src).Run(ctx) - ``` - - Replace - ```go - attrs, err := src.CopyTo(ctx, dst, &storage.ObjectAttrs{ContextType: "text/html"}) - ``` - with - ```go - c := dst.CopierFrom(src) - c.ContextType = "text/html" - attrs, err := c.Run(ctx) - ``` - -* ObjectHandle.ComposeFrom replaced by ObjectHandle.ComposerFrom. - Replace - ```go - attrs, err := dst.ComposeFrom(ctx, []*storage.ObjectHandle{src1, src2}, nil) - ``` - with - ```go - attrs, err := dst.ComposerFrom(src1, src2).Run(ctx) - ``` - -* ObjectHandle.Update's ObjectAttrs argument replaced by ObjectAttrsToUpdate. - Replace - ```go - attrs, err := obj.Update(ctx, &storage.ObjectAttrs{ContextType: "text/html"}) - ``` - with - ```go - attrs, err := obj.Update(ctx, storage.ObjectAttrsToUpdate{ContextType: "text/html"}) - ``` - -* ObjectHandle.WithConditions replaced by ObjectHandle.If. - Replace - ```go - obj.WithConditions(storage.Generation(gen), storage.IfMetaGenerationMatch(mgen)) - ``` - with - ```go - obj.Generation(gen).If(storage.Conditions{MetagenerationMatch: mgen}) - ``` - - Replace - ```go - obj.WithConditions(storage.IfGenerationMatch(0)) - ``` - with - ```go - obj.If(storage.Conditions{DoesNotExist: true}) - ``` - -* `storage.Done` replaced by `iterator.Done` (from package `google.golang.org/api/iterator`). - -_October 6, 2016_ - -Package preview/logging deleted. Use logging instead. - -_September 27, 2016_ - -Logging client replaced with preview version (see below). - -_September 8, 2016_ - -* New clients for some of Google's Machine Learning APIs: Vision, Speech, and -Natural Language. - -* Preview version of a new [Stackdriver Logging][cloud-logging] client in -[`cloud.google.com/go/preview/logging`](https://godoc.org/cloud.google.com/go/preview/logging). -This client uses gRPC as its transport layer, and supports log reading, sinks -and metrics. It will replace the current client at `cloud.google.com/go/logging` shortly. - diff --git a/vendor/cloud.google.com/go/regen-gapic.sh b/vendor/cloud.google.com/go/regen-gapic.sh deleted file mode 100755 index 252c9be0..00000000 --- a/vendor/cloud.google.com/go/regen-gapic.sh +++ /dev/null @@ -1,86 +0,0 @@ -#!/bin/bash - -# This script generates all GAPIC clients in this repo. -# One-time setup: -# cd path/to/googleapis # https://github.com/googleapis/googleapis -# virtualenv env -# . env/bin/activate -# pip install googleapis-artman -# deactivate -# -# Regenerate: -# cd path/to/googleapis -# . env/bin/activate -# $GOPATH/src/cloud.google.com/go/regen-gapic.sh -# deactivate -# -# Being in googleapis directory is important; -# that's where we find YAML files and where artman puts the "artman-genfiles" directory. -# -# NOTE: This script does not generate the "raw" gRPC client found in google.golang.org/genproto. -# To do that, use the regen.sh script in the genproto repo instead. - -set -ex - -APIS=( -google/api/expr/artman_cel.yaml -google/iam/artman_iam_admin.yaml -google/cloud/asset/artman_cloudasset_v1beta1.yaml -google/iam/credentials/artman_iamcredentials_v1.yaml -google/cloud/bigquery/datatransfer/artman_bigquerydatatransfer.yaml -google/cloud/dataproc/artman_dataproc_v1.yaml -google/cloud/dataproc/artman_dataproc_v1beta2.yaml -google/cloud/dialogflow/artman_dialogflow_v2.yaml -google/cloud/kms/artman_cloudkms.yaml -google/cloud/language/artman_language_v1.yaml -google/cloud/language/artman_language_v1beta2.yaml -google/cloud/oslogin/artman_oslogin_v1.yaml -google/cloud/oslogin/artman_oslogin_v1beta.yaml -google/cloud/redis/artman_redis_v1beta1.yaml -google/cloud/redis/artman_redis_v1.yaml -google/cloud/scheduler/artman_cloudscheduler_v1beta1.yaml -google/cloud/securitycenter/artman_securitycenter_v1beta1.yaml -google/cloud/speech/artman_speech_v1.yaml -google/cloud/speech/artman_speech_v1p1beta1.yaml -google/cloud/tasks/artman_cloudtasks_v2beta2.yaml -google/cloud/tasks/artman_cloudtasks_v2beta3.yaml -google/cloud/texttospeech/artman_texttospeech_v1.yaml -google/cloud/videointelligence/artman_videointelligence_v1.yaml -google/cloud/videointelligence/artman_videointelligence_v1beta1.yaml -google/cloud/videointelligence/artman_videointelligence_v1beta2.yaml -google/cloud/vision/artman_vision_v1.yaml -google/cloud/vision/artman_vision_v1p1beta1.yaml -google/devtools/artman_clouddebugger.yaml -google/devtools/clouderrorreporting/artman_errorreporting.yaml -google/devtools/cloudtrace/artman_cloudtrace_v1.yaml -google/devtools/cloudtrace/artman_cloudtrace_v2.yaml -google/devtools/containeranalysis/artman_containeranalysis_v1beta1.yaml -google/firestore/artman_firestore.yaml -google/logging/artman_logging.yaml -google/longrunning/artman_longrunning.yaml -google/monitoring/artman_monitoring.yaml -google/privacy/dlp/artman_dlp_v2.yaml -google/pubsub/artman_pubsub.yaml -google/spanner/admin/database/artman_spanner_admin_database.yaml -google/spanner/admin/instance/artman_spanner_admin_instance.yaml -google/spanner/artman_spanner.yaml -) - -for api in "${APIS[@]}"; do - rm -rf artman-genfiles/* - artman --config "$api" generate go_gapic - cp -r artman-genfiles/gapi-*/cloud.google.com/go/* $GOPATH/src/cloud.google.com/go/ -done - -# NOTE(pongad): `sed -i` doesn't work on Macs, because -i option needs an argument. -# `-i ''` doesn't work on GNU, since the empty string is treated as a file name. -# So we just create the backup and delete it after. -ver=$(date +%Y%m%d) -find $GOPATH/src/cloud.google.com/go/ -name '*.go' -exec sed -i.backup -e "s/^const versionClient.*/const versionClient = \"$ver\"/" '{}' + -find $GOPATH/src/cloud.google.com/go/ -name '*.backup' -delete - -#go list cloud.google.com/go/... | grep apiv | xargs go test - -#go test -short cloud.google.com/go/... - -#echo "googleapis version: $(git rev-parse HEAD)" diff --git a/vendor/cloud.google.com/go/run-tests.sh b/vendor/cloud.google.com/go/run-tests.sh deleted file mode 100755 index a643e61c..00000000 --- a/vendor/cloud.google.com/go/run-tests.sh +++ /dev/null @@ -1,88 +0,0 @@ -#!/bin/bash - -# Selectively run tests for this repo, based on what has changed -# in a commit. Runs short tests for the whole repo, and full tests -# for changed directories. - -set -e - -prefix=cloud.google.com/go - -dryrun=false -if [[ $1 == "-n" ]]; then - dryrun=true - shift -fi - -if [[ $1 == "" ]]; then - echo >&2 "usage: $0 [-n] COMMIT" - exit 1 -fi - -# Files or directories that cause all tests to run if modified. -declare -A run_all -run_all=([.travis.yml]=1 [run-tests.sh]=1) - -function run { - if $dryrun; then - echo $* - else - (set -x; $*) - fi -} - - -# Find all the packages that have changed in this commit. -declare -A changed_packages - -for f in $(git diff-tree --no-commit-id --name-only -r $1); do - if [[ ${run_all[$f]} == 1 ]]; then - # This change requires a full test. Do it and exit. - run go test -race -v $prefix/... - exit - fi - # Map, e.g., "spanner/client.go" to "$prefix/spanner". - d=$(dirname $f) - if [[ $d == "." ]]; then - pkg=$prefix - else - pkg=$prefix/$d - fi - changed_packages[$pkg]=1 -done - -echo "changed packages: ${!changed_packages[*]}" - - -# Reports whether its argument, a package name, depends (recursively) -# on a changed package. -function depends_on_changed_package { - # According to go list, a package does not depend on itself, so - # we test that separately. - if [[ ${changed_packages[$1]} == 1 ]]; then - return 0 - fi - for dep in $(go list -f '{{range .Deps}}{{.}} {{end}}' $1); do - if [[ ${changed_packages[$dep]} == 1 ]]; then - return 0 - fi - done - return 1 -} - -# Collect the packages into two separate lists. (It is faster to call "go test" on a -# list of packages than to individually "go test" each one.) - -shorts= -fulls= -for pkg in $(go list $prefix/...); do # for each package in the repo - if depends_on_changed_package $pkg; then # if it depends on a changed package - fulls="$fulls $pkg" # run the full test - else # otherwise - shorts="$shorts $pkg" # run the short test - fi -done -run go test -race -v -short $shorts -if [[ $fulls != "" ]]; then - run go test -race -v $fulls -fi diff --git a/vendor/contrib.go.opencensus.io/exporter/ocagent/CONTRIBUTING.md b/vendor/contrib.go.opencensus.io/exporter/ocagent/CONTRIBUTING.md deleted file mode 100644 index 0786fdf4..00000000 --- a/vendor/contrib.go.opencensus.io/exporter/ocagent/CONTRIBUTING.md +++ /dev/null @@ -1,24 +0,0 @@ -# How to contribute - -We'd love to accept your patches and contributions to this project. There are -just a few small guidelines you need to follow. - -## Contributor License Agreement - -Contributions to this project must be accompanied by a Contributor License -Agreement. You (or your employer) retain the copyright to your contribution, -this simply gives us permission to use and redistribute your contributions as -part of the project. Head over to to see -your current agreements on file or to sign a new one. - -You generally only need to submit a CLA once, so if you've already submitted one -(even if it was for a different project), you probably don't need to do it -again. - -## Code reviews - -All submissions, including submissions by project members, require review. We -use GitHub pull requests for this purpose. Consult [GitHub Help] for more -information on using pull requests. - -[GitHub Help]: https://help.github.com/articles/about-pull-requests/ diff --git a/vendor/contrib.go.opencensus.io/exporter/ocagent/README.md b/vendor/contrib.go.opencensus.io/exporter/ocagent/README.md deleted file mode 100644 index 64550ee6..00000000 --- a/vendor/contrib.go.opencensus.io/exporter/ocagent/README.md +++ /dev/null @@ -1,61 +0,0 @@ -# OpenCensus Agent Go Exporter - -[![Build Status][travis-image]][travis-url] [![GoDoc][godoc-image]][godoc-url] - - -This repository contains the Go implementation of the OpenCensus Agent (OC-Agent) Exporter. -OC-Agent is a deamon process running in a VM that can retrieve spans/stats/metrics from -OpenCensus Library, export them to other backends and possibly push configurations back to -Library. See more details on [OC-Agent Readme][OCAgentReadme]. - -Note: This is an experimental repository and is likely to get backwards-incompatible changes. -Ultimately we may want to move the OC-Agent Go Exporter to [OpenCensus Go core library][OpenCensusGo]. - -## Installation - -```bash -$ go get -u contrib.go.opencensus.io/exporter/ocagent/v1 -``` - -## Usage - -```go -import ( - "context" - "fmt" - "log" - "time" - - "contrib.go.opencensus.io/exporter/ocagent/v1" - "go.opencensus.io/trace" -) - -func Example() { - exp, err := ocagent.NewExporter(ocagent.WithInsecure(), ocagent.WithServiceName("your-service-name")) - if err != nil { - log.Fatalf("Failed to create the agent exporter: %v", err) - } - defer exp.Stop() - - // Now register it as a trace exporter. - trace.RegisterExporter(exp) - - // Then use the OpenCensus tracing library, like we normally would. - ctx, span := trace.StartSpan(context.Background(), "AgentExporter-Example") - defer span.End() - - for i := 0; i < 10; i++ { - _, iSpan := trace.StartSpan(ctx, fmt.Sprintf("Sample-%d", i)) - <-time.After(6 * time.Millisecond) - iSpan.End() - } -} -``` - -[OCAgentReadme]: https://github.com/census-instrumentation/opencensus-proto/tree/master/opencensus/proto/agent#opencensus-agent-proto -[OpenCensusGo]: https://github.com/census-instrumentation/opencensus-go -[godoc-image]: https://godoc.org/contrib.go.opencensus.io/exporter/ocagent?status.svg -[godoc-url]: https://godoc.org/contrib.go.opencensus.io/exporter/ocagent -[travis-image]: https://travis-ci.org/census-ecosystem/opencensus-go-exporter-ocagent.svg?branch=master -[travis-url]: https://travis-ci.org/census-ecosystem/opencensus-go-exporter-ocagent - diff --git a/vendor/contrib.go.opencensus.io/exporter/ocagent/example_test.go b/vendor/contrib.go.opencensus.io/exporter/ocagent/example_test.go deleted file mode 100644 index e913a652..00000000 --- a/vendor/contrib.go.opencensus.io/exporter/ocagent/example_test.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2018, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package ocagent_test - -import ( - "context" - "fmt" - "log" - "time" - - "contrib.go.opencensus.io/exporter/ocagent" - "go.opencensus.io/trace" -) - -func Example() { - exp, err := ocagent.NewExporter(ocagent.WithInsecure(), ocagent.WithServiceName("engine")) - if err != nil { - log.Fatalf("Failed to create the agent exporter: %v", err) - } - defer exp.Stop() - - // Now register it as a trace exporter. - trace.RegisterExporter(exp) - - // Then use the OpenCensus tracing library, like we normally would. - ctx, span := trace.StartSpan(context.Background(), "AgentExporter-Example") - defer span.End() - - for i := 0; i < 10; i++ { - _, iSpan := trace.StartSpan(ctx, fmt.Sprintf("Sample-%d", i)) - <-time.After(6 * time.Millisecond) - iSpan.End() - } -} diff --git a/vendor/contrib.go.opencensus.io/exporter/ocagent/go.mod b/vendor/contrib.go.opencensus.io/exporter/ocagent/go.mod deleted file mode 100644 index 410687e9..00000000 --- a/vendor/contrib.go.opencensus.io/exporter/ocagent/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module contrib.go.opencensus.io/exporter/ocagent - -require ( - github.com/census-instrumentation/opencensus-proto v0.0.2-0.20180913191712-f303ae3f8d6a - github.com/golang/protobuf v1.2.0 - go.opencensus.io v0.17.0 - google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf - google.golang.org/grpc v1.15.0 -) diff --git a/vendor/contrib.go.opencensus.io/exporter/ocagent/go.sum b/vendor/contrib.go.opencensus.io/exporter/ocagent/go.sum deleted file mode 100644 index 8bf9888c..00000000 --- a/vendor/contrib.go.opencensus.io/exporter/ocagent/go.sum +++ /dev/null @@ -1,44 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/census-instrumentation/opencensus-proto v0.0.1 h1:4v5I+ax5jCmwTYVaWQacX8ZSxvUZemBX4UwBGSkDeoA= -github.com/census-instrumentation/opencensus-proto v0.0.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/census-instrumentation/opencensus-proto v0.0.2-0.20180913191712-f303ae3f8d6a h1:t88pXOTS5K+pjfuhTOcul6sdC4khgqB8ukyfbe62Zxo= -github.com/census-instrumentation/opencensus-proto v0.0.2-0.20180913191712-f303ae3f8d6a/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= -github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -go.opencensus.io v0.17.0 h1:2Cu88MYg+1LU+WVD+NWwYhyP0kKgRlN9QjWGaX0jKTE= -go.opencensus.io v0.17.0/go.mod h1:mp1VrMQxhlqqDpKvH4UcQUa4YwlzNmymAjPrDdfxNpI= -golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf h1:rjxqQmxjyqerRKEj+tZW+MCm4LgpFXu18bsEoCMgDsk= -google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20180831171423-11092d34479b h1:lohp5blsw53GBXtLyLNaTXPXS9pJ1tiTw61ZHUoE9Qw= -google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -google.golang.org/grpc v1.15.0 h1:Az/KuahOM4NAidTEuJCv/RonAA7rYsTPkqXVjr+8OOw= -google.golang.org/grpc v1.15.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/vendor/contrib.go.opencensus.io/exporter/ocagent/mock_agent_test.go b/vendor/contrib.go.opencensus.io/exporter/ocagent/mock_agent_test.go deleted file mode 100644 index df8c6669..00000000 --- a/vendor/contrib.go.opencensus.io/exporter/ocagent/mock_agent_test.go +++ /dev/null @@ -1,218 +0,0 @@ -// Copyright 2018, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package ocagent_test - -import ( - "fmt" - "net" - "strconv" - "sync" - "testing" - "time" - - "google.golang.org/grpc" - - commonpb "github.com/census-instrumentation/opencensus-proto/gen-go/agent/common/v1" - agenttracepb "github.com/census-instrumentation/opencensus-proto/gen-go/agent/trace/v1" - tracepb "github.com/census-instrumentation/opencensus-proto/gen-go/trace/v1" -) - -func makeMockAgent(t *testing.T) *mockAgent { - return &mockAgent{configsToSend: make(chan *agenttracepb.UpdatedLibraryConfig), t: t, wg: new(sync.WaitGroup)} -} - -type mockAgent struct { - t *testing.T - - spans []*tracepb.Span - mu sync.Mutex - wg *sync.WaitGroup - - traceNodes []*commonpb.Node - receivedConfigs []*agenttracepb.CurrentLibraryConfig - - configsToSend chan *agenttracepb.UpdatedLibraryConfig - closeConfigsToSendOnce sync.Once - - port uint16 - stopFunc func() error - stopOnce sync.Once -} - -var _ agenttracepb.TraceServiceServer = (*mockAgent)(nil) - -func (ma *mockAgent) Config(tscs agenttracepb.TraceService_ConfigServer) error { - ma.mu.Lock() - ma.wg.Add(1) - ma.mu.Unlock() - defer func() { - ma.mu.Lock() - ma.wg.Done() - ma.mu.Unlock() - }() - - in, err := tscs.Recv() - if err != nil { - return err - } - if in == nil || in.Node == nil { - return fmt.Errorf("the first message must contain the node identifier") - } - ma.receivedConfigs = append(ma.receivedConfigs, in) - - // Push down all the configs - for cfg := range ma.configsToSend { - // Push down configs - if err := tscs.Send(cfg); err != nil { - return err - } - - // And then get back the config sent back by the client library - back, err := tscs.Recv() - if err != nil { - return err - } - ma.receivedConfigs = append(ma.receivedConfigs, back) - } - - // Just for the sake of draining any configs - // that the client-side exporter is still sending. - for { - back, err := tscs.Recv() - if err != nil { - return err - } - ma.receivedConfigs = append(ma.receivedConfigs, back) - } -} - -func (ma *mockAgent) Export(tses agenttracepb.TraceService_ExportServer) error { - in, err := tses.Recv() - if err != nil { - return err - } - - ma.mu.Lock() - ma.wg.Add(1) - ma.mu.Unlock() - defer func() { - ma.mu.Lock() - ma.wg.Done() - ma.mu.Unlock() - }() - - // The first trace message should contain the node identifier. - if in == nil || in.Node == nil { - return fmt.Errorf("the first message must contain the node identifier") - } - ma.traceNodes = append(ma.traceNodes, in.Node) - - // Now that we have the node identifier, let's start receiving spans. - for { - req, err := tses.Recv() - if err != nil { - return err - } - ma.mu.Lock() - ma.spans = append(ma.spans, req.Spans...) - ma.traceNodes = append(ma.traceNodes, req.Node) - ma.mu.Unlock() - } -} - -func (ma *mockAgent) transitionToReceivingClientConfigs() { - // Since we are done sending all the configs, close the configsChannel - // so that the state can transition to receiving all the client configs. - ma.closeConfigsToSendOnce.Do(func() { - close(ma.configsToSend) - }) -} - -var errAlreadyStopped = fmt.Errorf("already stopped") - -func (ma *mockAgent) stop() error { - var err = errAlreadyStopped - ma.stopOnce.Do(func() { - ma.transitionToReceivingClientConfigs() - - if ma.stopFunc != nil { - err = ma.stopFunc() - } - }) - // Give it sometime to shutdown. - <-time.After(160 * time.Millisecond) - ma.mu.Lock() - ma.wg.Wait() - ma.mu.Unlock() - return err -} - -// runMockAgent is a helper function to create a mockAgent -func runMockAgent(t *testing.T) *mockAgent { - return runMockAgentAtAddr(t, ":0") -} - -func runMockAgentAtAddr(t *testing.T, addr string) *mockAgent { - var deferFuncs []func() error - ln, err := net.Listen("tcp", addr) - if err != nil { - t.Fatalf("Failed to get an address: %v", err) - } - deferFuncs = append(deferFuncs, ln.Close) - - srv := grpc.NewServer() - ma := makeMockAgent(t) - agenttracepb.RegisterTraceServiceServer(srv, ma) - go func() { - _ = srv.Serve(ln) - }() - - deferFunc := func() error { - srv.Stop() - return ln.Close() - } - - _, agentPortStr, _ := net.SplitHostPort(ln.Addr().String()) - agentPort, _ := strconv.Atoi(agentPortStr) - - ma.port = uint16(agentPort) - ma.stopFunc = deferFunc - - return ma -} - -func (ma *mockAgent) getSpans() []*tracepb.Span { - ma.mu.Lock() - spans := append([]*tracepb.Span{}, ma.spans...) - ma.mu.Unlock() - - return spans -} - -func (ma *mockAgent) getReceivedConfigs() []*agenttracepb.CurrentLibraryConfig { - ma.mu.Lock() - receivedConfigs := append([]*agenttracepb.CurrentLibraryConfig{}, ma.receivedConfigs...) - ma.mu.Unlock() - - return receivedConfigs -} - -func (ma *mockAgent) getTraceNodes() []*commonpb.Node { - ma.mu.Lock() - traceNodes := append([]*commonpb.Node{}, ma.traceNodes...) - ma.mu.Unlock() - - return traceNodes -} diff --git a/vendor/contrib.go.opencensus.io/exporter/ocagent/ocagent_test.go b/vendor/contrib.go.opencensus.io/exporter/ocagent/ocagent_test.go deleted file mode 100644 index 62ed5114..00000000 --- a/vendor/contrib.go.opencensus.io/exporter/ocagent/ocagent_test.go +++ /dev/null @@ -1,329 +0,0 @@ -// Copyright 2018, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package ocagent_test - -import ( - "context" - "fmt" - "net" - "os" - "strconv" - "strings" - "testing" - "time" - - "contrib.go.opencensus.io/exporter/ocagent" - commonpb "github.com/census-instrumentation/opencensus-proto/gen-go/agent/common/v1" - agenttracepb "github.com/census-instrumentation/opencensus-proto/gen-go/agent/trace/v1" - tracepb "github.com/census-instrumentation/opencensus-proto/gen-go/trace/v1" - "go.opencensus.io" - "go.opencensus.io/trace" -) - -func TestNewExporter_endToEnd(t *testing.T) { - ma := runMockAgent(t) - defer ma.stop() - - serviceName := "endToEnd_test" - exp, err := ocagent.NewExporter(ocagent.WithInsecure(), ocagent.WithPort(ma.port), ocagent.WithServiceName(serviceName)) - if err != nil { - t.Fatalf("Failed to create a new agent exporter: %v", err) - } - defer exp.Stop() - - // Once we've register the exporter, we can then send over a bunch of spans. - trace.RegisterExporter(exp) - defer trace.UnregisterExporter(exp) - - // Let the agent push down a couple of configurations. - // 1. Always sample - ma.configsToSend <- &agenttracepb.UpdatedLibraryConfig{ - Config: &tracepb.TraceConfig{ - Sampler: &tracepb.TraceConfig_ConstantSampler{ - ConstantSampler: &tracepb.ConstantSampler{Decision: true}, // Always sample - }, - }, - } - <-time.After(5 * time.Millisecond) - - // Now create a couple of spans - for i := 0; i < 4; i++ { - _, span := trace.StartSpan(context.Background(), "AlwaysSample") - span.Annotatef([]trace.Attribute{trace.Int64Attribute("i", int64(i))}, "Annotation") - span.End() - } - <-time.After(10 * time.Millisecond) - exp.Flush() - - // 2. Never sample - ma.configsToSend <- &agenttracepb.UpdatedLibraryConfig{ - Config: &tracepb.TraceConfig{ - Sampler: &tracepb.TraceConfig_ConstantSampler{ - ConstantSampler: &tracepb.ConstantSampler{Decision: false}, // Never sample - }, - }, - } - <-time.After(5 * time.Millisecond) - exp.Flush() - - // Now create a couple of spans - for i, n := 0, 2; i < n; i++ { - _, span := trace.StartSpan(context.Background(), "NeverSample") - span.Annotatef([]trace.Attribute{trace.Int64Attribute("i", int64(n-i))}, "Annotation") - span.End() - } - <-time.After(10 * time.Millisecond) - exp.Flush() - - // 3. Probability sampler (100%) - ma.configsToSend <- &agenttracepb.UpdatedLibraryConfig{ - Config: &tracepb.TraceConfig{ - Sampler: &tracepb.TraceConfig_ProbabilitySampler{ - ProbabilitySampler: &tracepb.ProbabilitySampler{SamplingProbability: 1.0}, // 100% probability - }, - }, - } - <-time.After(5 * time.Millisecond) - exp.Flush() - - // Now create a couple of spans - for i := 0; i < 3; i++ { - _, span := trace.StartSpan(context.Background(), "ProbabilitySampler-100%") - span.Annotatef([]trace.Attribute{trace.BoolAttribute("odd", i&1 == 1)}, "Annotation") - span.End() - } - <-time.After(10 * time.Millisecond) - exp.Flush() - - // 4. Probability sampler (0%) - ma.configsToSend <- &agenttracepb.UpdatedLibraryConfig{ - Config: &tracepb.TraceConfig{ - Sampler: &tracepb.TraceConfig_ProbabilitySampler{ - ProbabilitySampler: &tracepb.ProbabilitySampler{SamplingProbability: 0.0}, // 0% probability - }, - }, - } - <-time.After(5 * time.Millisecond) - exp.Flush() - - for i := 0; i < 3; i++ { - _, span := trace.StartSpan(context.Background(), "ProbabilitySampler-0%") - span.Annotatef([]trace.Attribute{trace.BoolAttribute("even", i&1 == 0)}, "Annotation") - span.End() - } - // Give the traces some time to be exported or dropped by the core library - <-time.After(5 * time.Millisecond) - - ma.transitionToReceivingClientConfigs() - <-time.After(5 * time.Millisecond) - - // Now invoke Flush on the exporter. - exp.Flush() - <-time.After(5 * time.Millisecond) - - // Now shutdown the exporter - if err := exp.Stop(); err != nil { - t.Errorf("Failed to stop the exporter: %v", err) - } - - // Shutdown the agent too so that we can begin - // verification checks of expected data back. - ma.stop() - - // Expecting 5 receivedConfigs: the first one with the nodeInfo - // and the rest with {AlwaysSample, NeverSample, 100%, 0%} - spans := ma.getSpans() - traceNodes := ma.getTraceNodes() - receivedConfigs := ma.getReceivedConfigs() - - if g, w := len(receivedConfigs), 5; g != w { - t.Errorf("ReceivedConfigs: got %d want %d", g, w) - } - - // Expecting 7 spanData that were sampled, given that - // two of the trace configs pushed down to the client - // were {NeverSample, ProbabilitySampler(0.0)} - if g, w := len(spans), 7; g != w { - t.Errorf("Spans: got %d want %d", g, w) - } - - // Now check that the responses received by the agent properly - // contain the node identifier that we expect the exporter to have. - wantIdentifier := &commonpb.ProcessIdentifier{ - HostName: os.Getenv("HOSTNAME"), - Pid: uint32(os.Getpid()), - } - wantLibraryInfo := &commonpb.LibraryInfo{ - Language: commonpb.LibraryInfo_GO_LANG, - ExporterVersion: ocagent.Version, - CoreLibraryVersion: opencensus.Version(), - } - wantServiceInfo := &commonpb.ServiceInfo{ - Name: serviceName, - } - - var firstNodeInConfig, firstNodeInTraceExport *commonpb.Node - if len(receivedConfigs) > 0 { - firstNodeInConfig = receivedConfigs[0].Node - } - if len(traceNodes) > 0 { - firstNodeInTraceExport = traceNodes[0] - } - nodeComparisons := []struct { - name string - node *commonpb.Node - }{ - // Expecting the first config message that the agent got to contain the nodeInfo - {name: "Config", node: firstNodeInConfig}, - // Expecting the first span message that the agent got to contain the nodeInfo - {name: "Trace", node: firstNodeInTraceExport}, - } - - for _, tt := range nodeComparisons { - node := tt.node - if node == nil { - t.Errorf("%q: first message should contain a non-nil Node", tt.name) - } else if g, w := node.Identifier, wantIdentifier; !sameProcessIdentifier(g, w) { - t.Errorf("%q: ProcessIdentifier mismatch\nGot %#v\nWant %#v", tt.name, g, w) - } else if g, w := node.LibraryInfo, wantLibraryInfo; !sameLibraryInfo(g, w) { - t.Errorf("%q: LibraryInfo mismatch\nGot %#v\nWant %#v", tt.name, g, w) - } else if g, w := node.ServiceInfo, wantServiceInfo; !sameServiceInfo(g, w) { - t.Errorf("%q: ServiceInfo mismatch\nGot %#v\nWant %#v", tt.name, g, w) - } - } -} - -func TestNewExporter_invokeStartThenStopManyTimes(t *testing.T) { - ma := runMockAgent(t) - defer ma.stop() - - exp, err := ocagent.NewUnstartedExporter(ocagent.WithInsecure(), ocagent.WithPort(ma.port)) - if err != nil { - t.Fatal("Surprisingly connected with a bad port") - } - defer exp.Stop() - - // Invoke Start numerous times - for i := 0; i < 10; i++ { - if err := exp.Start(); err != nil { - t.Errorf("#%d unexpected Start error: %v", i, err) - } - } - - exp.Stop() - // Invoke Stop numerous times - for i := 0; i < 10; i++ { - if err := exp.Stop(); err == nil || !strings.Contains(err.Error(), "not started") { - t.Errorf(`#%d got error (%v) expected a "not started error"`, i, err) - } - } -} - -func TestNewExporter_agentConnectionDiesInMidst(t *testing.T) { - ma := runMockAgent(t) - exp, err := ocagent.NewUnstartedExporter(ocagent.WithInsecure(), ocagent.WithPort(ma.port)) - if err != nil { - t.Fatal("Surprisingly connected with a bad port") - } - defer exp.Stop() - - if err := exp.Start(); err != nil { - t.Fatalf("Unexpected Start error: %v", err) - } - - // Stop the agent right away to simulate killing - // the connection in the midst of communication. - ma.stop() - - exp.ExportSpan(&trace.SpanData{Name: "in the midst"}) -} - -// This test takes a long time to run: to skip it, run tests using: -short -func TestNewExporter_agentOnBadConnection(t *testing.T) { - if testing.Short() { - t.Skipf("Skipping this long running test") - } - - ln, err := net.Listen("tcp", ":0") - if err != nil { - t.Fatalf("Failed to grab an available port: %v", err) - } - // Firstly close the "agent's" channel: optimistically this address won't get reused ASAP - // However, our goal of closing it is to simulate an unavailable connection - ln.Close() - - startTime := time.Now() - // If this returns in less than 6.5s report an error - // since that's a sign that exponential backoff didn't happen. - wantMinDuration := (6 * time.Second) + (500 * time.Millisecond) - defer func() { - timeSpent := time.Now().Sub(startTime) - if timeSpent < wantMinDuration { - t.Errorf("Took %s, yet with a non-existent connection it should take at least %s", - timeSpent, wantMinDuration) - } - }() - - _, agentPortStr, _ := net.SplitHostPort(ln.Addr().String()) - agentPort, _ := strconv.Atoi(agentPortStr) - - exp, err := ocagent.NewExporter(ocagent.WithInsecure(), ocagent.WithPort(uint16(agentPort))) - if err == nil { - t.Fatal("Surprisingly connected to an unavailable non-gRPC connection") - } - if exp != nil { - t.Fatalf("Surprisingly created an exporter: %#v", exp) - } -} - -func TestNewExporter_withAddress(t *testing.T) { - ma := runMockAgent(t) - defer ma.stop() - - addr := fmt.Sprintf("localhost:%d", ma.port) - exp, err := ocagent.NewUnstartedExporter(ocagent.WithInsecure(), ocagent.WithAddress(addr)) - if err != nil { - t.Fatal("Surprisingly connected with a bad port") - } - defer exp.Stop() - - if err := exp.Start(); err != nil { - t.Fatalf("Unexpected Start error: %v", err) - } -} - -// Best case comparison for information that we can externally introspect -func sameProcessIdentifier(n1, n2 *commonpb.ProcessIdentifier) bool { - if n1 == nil || n2 == nil { - return n1 == n2 - } - return n1.HostName == n2.HostName && n1.Pid == n2.Pid -} - -func sameLibraryInfo(li1, li2 *commonpb.LibraryInfo) bool { - if li1 == nil || li2 == nil { - return li1 == li2 - } - return li1.Language == li2.Language && - li1.ExporterVersion == li2.ExporterVersion && - li1.CoreLibraryVersion == li2.CoreLibraryVersion -} - -func sameServiceInfo(si1, si2 *commonpb.ServiceInfo) bool { - if si1 == nil || si2 == nil { - return si1 == si2 - } - return si1.Name == si2.Name -} diff --git a/vendor/contrib.go.opencensus.io/exporter/ocagent/transform_spans_test.go b/vendor/contrib.go.opencensus.io/exporter/ocagent/transform_spans_test.go deleted file mode 100644 index e64b09fc..00000000 --- a/vendor/contrib.go.opencensus.io/exporter/ocagent/transform_spans_test.go +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright 2018, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package ocagent_test - -import ( - "reflect" - "testing" - "time" - - "contrib.go.opencensus.io/exporter/ocagent" - "go.opencensus.io/trace" - "go.opencensus.io/trace/tracestate" - - tracepb "github.com/census-instrumentation/opencensus-proto/gen-go/trace/v1" - "github.com/golang/protobuf/ptypes/timestamp" -) - -func TestOCSpanToProtoSpan_endToEnd(t *testing.T) { - // The goal of this test is to ensure that each - // spanData is transformed and exported correctly! - - agent := runMockAgent(t) - defer agent.stop() - - serviceName := "spanTranslation" - exp, err := ocagent.NewExporter(ocagent.WithInsecure(), ocagent.WithPort(agent.port), ocagent.WithServiceName(serviceName)) - if err != nil { - t.Fatalf("Failed to create a new agent exporter: %v", err) - } - defer exp.Stop() - - startTime := time.Now() - endTime := startTime.Add(10 * time.Second) - ocTracestate, err := tracestate.New(new(tracestate.Tracestate), tracestate.Entry{Key: "foo", Value: "bar"}, - tracestate.Entry{Key: "a", Value: "b"}) - if err != nil || ocTracestate == nil { - t.Fatalf("Failed to create ocTracestate: %v", err) - } - - ocSpanData := &trace.SpanData{ - SpanContext: trace.SpanContext{ - TraceID: trace.TraceID{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}, - SpanID: trace.SpanID{0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8}, - Tracestate: ocTracestate, - }, - SpanKind: trace.SpanKindServer, - ParentSpanID: trace.SpanID{0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9, 0xE8}, - Name: "End-To-End Here", - StartTime: startTime, - EndTime: endTime, - MessageEvents: []trace.MessageEvent{ - {Time: startTime, EventType: trace.MessageEventTypeSent, UncompressedByteSize: 1024, CompressedByteSize: 512}, - {Time: endTime, EventType: trace.MessageEventTypeRecv, UncompressedByteSize: 1024, CompressedByteSize: 1000}, - }, - Links: []trace.Link{ - { - TraceID: trace.TraceID{0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF}, - SpanID: trace.SpanID{0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7}, - Type: trace.LinkTypeParent, - }, - { - TraceID: trace.TraceID{0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF}, - SpanID: trace.SpanID{0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7}, - Type: trace.LinkTypeChild, - }, - }, - Status: trace.Status{ - Code: trace.StatusCodeInternal, - Message: "This is not a drill!", - }, - HasRemoteParent: true, - Attributes: map[string]interface{}{ - "timeout_ns": int64(12e9), - "agent": "ocagent", - "cache_hit": true, - "ping_count": int(25), // Should be transformed into int64 - }, - } - - // TODO: file a bug with opencensus-go because trace.Annotation.Attributes' type is map[string]interface{} - // yet Attribute value and key cannot be easily introspected, so we can't easily test the values. - - exp.ExportSpan(ocSpanData) - // Also try to export a nil span and it should never make it - exp.ExportSpan(nil) - exp.Flush() - <-time.After(100 * time.Millisecond) - exp.Stop() - agent.stop() - - spans := agent.getSpans() - if len(spans) == 0 || spans[0] == nil { - t.Fatal("Expected the exported span") - } - - wantProtoSpan := &tracepb.Span{ - TraceId: []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}, - SpanId: []byte{0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8}, - ParentSpanId: []byte{0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9, 0xE8}, - Name: &tracepb.TruncatableString{Value: "End-To-End Here"}, - Kind: tracepb.Span_SERVER, - StartTime: timeToTimestamp(startTime), - EndTime: timeToTimestamp(endTime), - Status: &tracepb.Status{ - Code: 13, - Message: "This is not a drill!", - }, - Links: &tracepb.Span_Links{ - Link: []*tracepb.Span_Link{ - { - TraceId: []byte{0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF}, - SpanId: []byte{0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7}, - Type: tracepb.Span_Link_PARENT_LINKED_SPAN, - }, - { - TraceId: []byte{0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF}, - SpanId: []byte{0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7}, - Type: tracepb.Span_Link_CHILD_LINKED_SPAN, - }, - }, - }, - Tracestate: &tracepb.Span_Tracestate{ - Entries: []*tracepb.Span_Tracestate_Entry{ - {Key: "foo", Value: "bar"}, - {Key: "a", Value: "b"}, - }, - }, - Attributes: &tracepb.Span_Attributes{ - AttributeMap: map[string]*tracepb.AttributeValue{ - "cache_hit": {Value: &tracepb.AttributeValue_BoolValue{BoolValue: true}}, - "timeout_ns": {Value: &tracepb.AttributeValue_IntValue{IntValue: 12e9}}, - "ping_count": {Value: &tracepb.AttributeValue_IntValue{IntValue: 25}}, - "agent": {Value: &tracepb.AttributeValue_StringValue{ - StringValue: &tracepb.TruncatableString{Value: "ocagent"}, - }}, - }, - }, - } - - if g, w := spans[0], wantProtoSpan; !reflect.DeepEqual(g, w) { - for i := 0; i < len(w.Links.Link); i++ { - t.Logf("#%d:: \nGot: %#v\nWant: %#v\n\n", i, g.Links.Link[i], w.Links.Link[i]) - } - t.Fatalf("End-to-end transformed span\n\tGot %+v\n\tWant %+v", g, w) - } -} - -func timeToTimestamp(t time.Time) *timestamp.Timestamp { - nanoTime := t.UnixNano() - return ×tamp.Timestamp{ - Seconds: nanoTime / 1e9, - Nanos: int32(nanoTime % 1e9), - } -} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/CHANGELOG.md b/vendor/github.com/Azure/azure-sdk-for-go/CHANGELOG.md deleted file mode 100644 index 4eed0971..00000000 --- a/vendor/github.com/Azure/azure-sdk-for-go/CHANGELOG.md +++ /dev/null @@ -1,1337 +0,0 @@ -# CHANGELOG - -## `v24.0.0` - -### New Packages - -| Package Name | API Version | -| -----------: | :---------: | -| batch | 2018-12-01
2018-12-01.8.0 | -| devices | 2018-12-01-preview | -| eventgrid | 2019-01-01 | -| storagedatalake | 2018-06-17
2018-11-09 | - -### Updated Packages - -| Package Name | API Version | -| -----------: | :---------: | -| apimanagement | 2018-01-01
2018-06-01-preview | -| containerinstance | 2018-10-01 | -| containerregistry | 2017-10-01
2018-02-01
2018-09-01 | -| containerservice | 2018-08-01-preview
2018-09-30-preview | -| costmanagement | 2018-08-01-preview | -| datafactory | 2018-06-01 | -| eventhub | 2018-01-01-preview | -| hanaonazure | 2017-11-03-preview | -| hdinsight | 2018-11-01-preview | -| network | 2018-10-01 | -| resourcehealth | 2015-01-01
2017-07-01 | -| sql | 2017-03-01-preview | -| storagesync | 2018-10-01 | - -### BreakingChanges - -| Package Name | API Version | -| -----------: | :---------: | -| authoring | luis | -| cognitiveservices | 2017-04-18 | -| computervision | v2.0 | -| datamigration | 2018-04-19
2018-07-15-preview | -| labservices | 2018-10-15 | -| logic | 2018-07-01-preview | -| media | 2018-07-01 | -| siterecovery | 2018-01-10 | -| sqlvirtualmachine | 2017-03-01-preview | -| workloadmonitor | 2018-08-31-preview | - -## `v23.2.0` - -### New Packages - -| Package Name | API Version | -| -----------: | :---------: | -| hdinsight | 2018-11-01-preview | -| localsearch | 1.0 | - -## `v23.1.0` - -### New Packages - -| Package Name | API Version | -| -----------: | :---------: | -| dtl | 2018-09-15 | -| labservices | 2018-10-15 | -| msi | 2018-11-30 | -| servicefabric | 6.3
6.4 | -| timeseriesinsights | 2018-08-15-preview | - -## `v23.0.0` - -### New Packages - -Each package now has a sub-package with the suffix `api` which contains interface definitions per operation group. - -| Package Name | API Version | -| -----------: | :---------: | -| engagementfabric | 2018-09-01 | -| kusto | 2018-09-07-preview | -| network | 2018-10-01 | -| qnamaker | v4.0 | -| sqlvirtualmachine | 2017-03-01-preview | - -### Updated Packages - -| Package Name | API Version | -| -----------: | :---------: | -| account | 2015-10-01-preview
2015-10-01-preview
2016-11-01
2016-11-01 | -| advisor | 2016-07-12-preview
2017-03-31
2017-04-19 | -| alertsmanagement | 2018-05-05 | -| analysisservices | 2017-08-01 | -| apimanagement | 2016-07-07
2016-10-10
2017-03-01
2017-03-01
2018-01-01
2018-06-01-preview | -| authorization | 2015-07-01
2017-10-01-preview
2018-01-01-preview
2018-09-01-preview | -| automation | 2015-10-31
2017-05-15-preview
2018-01-15-preview
2018-06-30-preview | -| azurestack | 2017-06-01 | -| backup | 2016-06-01
2016-12-01
2017-07-01 | -| batch | 2015-12-01
2017-01-01
2017-05-01
2017-05-01.5.0
2017-09-01
2018-03-01.6.1
2018-08-01.7.0 | -| batchai | 2017-09-01-preview
2018-03-01
2018-05-01 | -| billing | 2017-02-27-preview
2017-04-24-preview
2018-03-01-preview | -| blueprint | 2017-11-11-preview | -| botservice | 2017-12-01
2018-07-12 | -| catalog | 2015-10-01-preview
2016-11-01-preview | -| cdn | 2016-10-02
2017-04-02
2017-10-12 | -| cognitiveservices | 2017-04-18 | -| commerce | 2015-06-01-preview | -| commitmentplans | 2016-05-01-preview | -| compute | 2015-06-15
2016-03-30
2016-04-30-preview
2017-03-30
2017-08-01-preview
2017-12-01
2018-04-01
2018-06-01
2018-10-01 | -| consumption | 2017-04-24-preview
2017-11-30
2017-12-30-preview
2018-01-31
2018-03-31
2018-05-31
2018-06-30
2018-08-31
2018-10-01 | -| containerinstance | 2017-08-01-preview
2017-10-01-preview
2017-12-01-preview
2018-02-01-preview
2018-04-01
2018-06-01
2018-09-01
2018-10-01 | -| containerregistry | 2016-06-27-preview
2017-03-01
2017-06-01-preview
2017-10-01
2018-02-01
2018-09-01 | -| containerservice | 2016-09-30
2017-01-31
2017-07-01
2017-08-31
2017-09-30
2018-03-31
2018-08-01-preview
2018-09-30-preview | -| costmanagement | 2018-05-31
2018-08-01-preview | -| customerinsights | 2017-01-01
2017-04-26 | -| databricks | 2018-04-01 | -| datafactory | 2017-09-01-preview | -| datamigration | 2017-11-15-preview
2018-03-31-preview
2018-04-19
2018-07-15-preview | -| devices | 2016-02-03
2017-01-19
2017-07-01
2018-01-22
2018-04-01 | -| devspaces | 2018-06-01-preview | -| dns | 2015-05-04-preview
2016-04-01
2017-09-01
2017-10-01
2018-03-01-preview | -| documentdb | 2015-04-08 | -| dtl | 2015-05-21-preview
2016-05-15 | -| eventhub | 2015-08-01
2017-04-01
2018-01-01-preview | -| experimentation | 2017-05-01-preview | -| features | 2015-12-01 | -| frontdoor | 2018-08-01-preview | -| hanaonazure | 2017-11-03-preview | -| hdinsight | 2015-03-01-preview
2018-06-01-preview | -| insights | 2015-05-01
2017-05-01-preview
2018-03-01
2018-09-01 | -| iotcentral | 2018-09-01 | -| iothub | 2017-08-21-preview
2017-11-15
2018-01-22 | -| iotspaces | 2017-10-01-preview | -| job | 2015-11-01-preview
2016-03-20-preview
2016-11-01
2017-09-01-preview | -| keyvault | 2015-06-01
2015-06-01
2016-10-01
2016-10-01
2018-02-14
v7.0 | -| links | 2016-09-01 | -| locks | 2015-01-01
2016-09-01 | -| logic | 2015-02-01-preview
2015-08-01-preview
2016-06-01
2018-07-01-preview | -| managedapplications | 2016-09-01-preview
2017-09-01
2018-06-01 | -| managementgroups | 2017-08-31-preview
2017-11-01-preview
2018-01-01-preview
2018-03-01-preview | -| managementpartner | 2018-02-01 | -| mariadb | 2018-06-01-preview | -| marketplaceordering | 2015-06-01 | -| media | 2018-03-30-preview
2018-06-01-preview
2018-07-01 | -| msi | 2015-08-31-preview | -| mysql | 2017-12-01 | -| network | 2015-05-01-preview
2015-06-15
2016-03-30
2016-06-01
2016-09-01
2016-12-01
2017-03-01
2017-06-01
2017-08-01
2017-09-01
2017-10-01
2017-11-01
2018-01-01
2018-02-01
2018-04-01
2018-06-01
2018-07-01
2018-08-01 | -| notificationhubs | 2014-09-01
2016-03-01
2017-04-01 | -| operationalinsights | 2015-03-20
2015-11-01-preview | -| policy | 2015-10-01-preview
2016-04-01
2016-12-01
2017-06-01-preview
2018-03-01
2018-05-01 | -| policyinsights | 2018-07-01-preview | -| postgresql | 2017-12-01 | -| powerbidedicated | 2017-10-01 | -| recoveryservices | 2016-06-01 | -| redis | 2015-08-01
2016-04-01
2017-02-01
2017-10-01
2018-03-01 | -| relay | 2016-07-01
2017-04-01 | -| reservations | 2017-11-01
2018-06-01 | -| resourcehealth | 2015-01-01
2017-07-01 | -| resources | 2015-11-01
2016-02-01
2016-07-01
2016-09-01
2017-05-10
2018-02-01
2018-05-01 | -| scheduler | 2014-08-01-preview
2016-01-01
2016-03-01 | -| security | 2017-08-01-preview | -| servicebus | 2015-08-01
2017-04-01 | -| services | 2018-03-01-preview | -| signalr | 2018-03-01-preview
2018-10-01 | -| siterecovery | 2016-08-10
2018-01-10 | -| skus | 2017-09-01 | -| sql | 2015-05-01-preview
2017-03-01-preview
2017-10-01-preview | -| storage | 2015-05-01-preview | -| storageimportexport | 2016-11-01 | -| storagesync | 2018-04-02
2018-07-01 | -| storsimple | 2016-10-01
2017-06-01 | -| streamanalytics | 2016-03-01 | -| subscription | 2017-11-01-preview
2018-03-01-preview | -| subscriptions | 2015-11-01
2016-06-01 | -| timeseriesinsights | 2017-02-28-preview
2017-11-15 | -| web | 2015-08-01-preview
2016-09-01 | -| webservices | 2016-05-01-preview
2017-01-01 | -| workloadmonitor | 2018-08-31-preview | -| workspaces | 2016-04-01 | - -### BreakingChanges - -| Package Name | API Version | -| -----------: | :---------: | -| aad | 2017-01-01
2017-06-01 | -| adhybridhealthservice | 2014-01-01 | -| autosuggest | v1.0 | -| customimagesearch | v1.0 | -| customsearch | v1.0 | -| databox | 2018-01-01 | -| datafactory | 2018-06-01 | -| entitysearch | v1.0 | -| graphrbac | 1.6 | -| imagesearch | v1.0 | -| newssearch | v1.0 | -| spellcheck | v1.0 | -| storage | 2018-07-01 | -| storagesync | 2018-10-01 | -| videosearch | v1.0 | -| visualsearch | v1.0 | -| web | 2018-02-01 | -| websearch | v1.0 | - -## `v22.2.2` - -Corrected typo in the env variable for enabling tracing for the SDK. The correct name is `AZURE_SDK_TRACING_ENABLED`. - -## `v22.2.1` - -Marshalling a nil object no longer includes a `null` in the JSON body for the object's field. - -## `v22.2.0` - -### New Packages - -| Package Name | API Version | -| ------------: | :-------------------------------: | -| datamigration | 2018-04-19
2018-07-15-preview | -| reservations | 2018-06-01 | - -### Updated Packages - -| Package Name | API Version | -| ----------------: | :----------------: | -| containerregistry | 2018-09-01 | -| visualstudio | 2014-04-01-preview | - -## `v22.1.0` - -Fixed a regression in the regex used for verifying resource group names. - -### New Packages - -| Package Name | API Version | -| ------------: | :---------: | -| apimanagement | 2018-01-01 | - -### Updated Packages - -| Package Name | API Version | -| ----------------: | :---------: | -| containerinstance | 2018-10-01 | -| documentdb | 2015-04-08 | -| storage | 2018-07-01 | - -## `v22.0.0` - -All packages now support tracing, see the [README](./README.md) section `Tracing and Metrics` for more details. - -Future types and pageable operations now have `*WithContext(...)` methods to support cancellation and tracing. - -### New Packages - -| Package Name | API Version | -| ----------------: | :-------------------------------------------------------------------------------------: | -| alertsmanagement | 2018-05-05 | -| automation | 2018-01-15-preview
2018-06-30-preview | -| batchai | 2017-09-01-preview | -| botservice | 2017-12-01
2018-07-12 | -| cognitiveservices | 2016-02-01-preview | -| containerservice | 2018-08-01-preview | -| insights | v1 | -| iothub | 2017-08-21-preview | -| managementgroups | 2017-08-31-preview
2017-11-01-preview
2018-01-01-preview
2018-03-01-preview | -| servicefabricmesh | 2018-09-01-preview | -| signalr | 2018-10-01 | -| storagesync | 2018-07-01
2018-10-01 | -| training | customvision | -| web | 2015-08-01-preview | -| workloadmonitor | 2018-08-31-preview | - -### Updated Packages - -| Package Name | API Version | -| --------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -| account | 2015-10-01-preview
2015-10-01-preview
2016-11-01
2016-11-01 | -| adhybridhealthservice | 2014-01-01 | -| advisor | 2016-07-12-preview
2017-03-31
2017-04-19 | -| alertsmanagement | 2018-05-05-preview | -| analysisservices | 2017-08-01 | -| apimanagement | 2016-07-07
2016-10-10
2017-03-01
2017-03-01
2018-01-01 | -| authorization | 2015-07-01
2017-10-01-preview
2018-01-01-preview
2018-09-01-preview | -| automation | 2015-10-31
2017-05-15-preview | -| azurestack | 2017-06-01 | -| backup | 2016-06-01 | -| batch | 2015-12-01
2017-01-01
2017-05-01
2017-05-01.5.0
2017-09-01
2018-03-01.6.1
2018-08-01.7.0 | -| batchai | 2018-03-01
2018-05-01 | -| billing | 2017-02-27-preview
2017-04-24-preview
2018-03-01-preview | -| blueprint | 2017-11-11-preview | -| catalog | 2015-10-01-preview
2016-11-01-preview | -| cdn | 2016-10-02
2017-04-02
2017-10-12 | -| cognitiveservices | 2017-04-18 | -| commerce | 2015-06-01-preview | -| commitmentplans | 2016-05-01-preview | -| compute | 2015-06-15
2016-03-30
2016-04-30-preview
2017-03-30
2017-08-01-preview
2017-12-01
2018-04-01 | -| consumption | 2017-04-24-preview
2017-11-30
2017-12-30-preview
2018-01-31
2018-03-31
2018-05-31
2018-06-30
2018-08-31
2018-10-01 | -| containerinstance | 2017-08-01-preview
2017-10-01-preview
2017-12-01-preview
2018-02-01-preview
2018-04-01
2018-06-01
2018-09-01
2018-10-01 | -| containerregistry | 2016-06-27-preview
2017-03-01
2017-06-01-preview
2017-10-01
2018-02-01
2018-09-01 | -| containerservice | 2016-09-30
2017-01-31
2017-07-01
2017-08-31
2017-09-30
2018-03-31
2018-09-30-preview | -| costmanagement | 2018-05-31 | -| customerinsights | 2017-01-01
2017-04-26 | -| databox | 2018-01-01 | -| databricks | 2018-04-01 | -| datafactory | 2017-09-01-preview
2018-06-01 | -| datamigration | 2017-11-15-preview
2018-03-31-preview | -| devices | 2016-02-03
2017-01-19
2017-07-01
2018-01-22
2018-04-01 | -| devspaces | 2018-06-01-preview | -| dns | 2015-05-04-preview
2016-04-01
2017-09-01
2017-10-01
2018-03-01-preview | -| documentdb | 2015-04-08 | -| dtl | 2015-05-21-preview
2016-05-15 | -| eventhub | 2015-08-01
2017-04-01
2018-01-01-preview | -| experimentation | 2017-05-01-preview | -| features | 2015-12-01 | -| frontdoor | 2018-08-01-preview | -| hanaonazure | 2017-11-03-preview | -| insights | 2015-05-01
2017-05-01-preview
2018-03-01
2018-09-01 | -| iothub | 2017-11-15
2018-01-22 | -| iotspaces | 2017-10-01-preview | -| job | 2015-11-01-preview
2016-03-20-preview
2016-11-01
2017-09-01-preview | -| keyvault | 2015-06-01
2015-06-01
2016-10-01
2016-10-01
2018-02-14
v7.0 | -| links | 2016-09-01 | -| locks | 2015-01-01 | -| logic | 2015-02-01-preview
2015-08-01-preview
2016-06-01
2018-07-01-preview | -| managedapplications | 2016-09-01-preview
2017-09-01
2018-06-01 | -| managementpartner | 2018-02-01 | -| mariadb | 2018-06-01-preview | -| marketplaceordering | 2015-06-01 | -| media | 2018-03-30-preview
2018-06-01-preview
2018-07-01 | -| msi | 2015-08-31-preview | -| mysql | 2017-12-01 | -| network | 2015-05-01-preview
2015-06-15
2016-03-30
2016-06-01
2016-09-01
2016-12-01
2017-03-01
2017-06-01
2017-08-01
2017-09-01
2017-10-01
2017-11-01
2018-01-01
2018-02-01
2018-04-01
2018-06-01
2018-07-01 | -| notificationhubs | 2014-09-01
2016-03-01
2017-04-01 | -| operationalinsights | 2015-03-20
2015-11-01-preview | -| policy | 2015-10-01-preview
2016-04-01
2016-12-01
2017-06-01-preview
2018-03-01
2018-05-01 | -| policyinsights | 2018-07-01-preview | -| postgresql | 2017-12-01 | -| powerbidedicated | 2017-10-01 | -| recoveryservices | 2016-06-01 | -| redis | 2015-08-01
2016-04-01
2017-02-01
2017-10-01
2018-03-01 | -| relay | 2016-07-01
2017-04-01 | -| reservations | 2017-11-01
2018-06-01 | -| resourcehealth | 2015-01-01
2017-07-01 | -| resources | 2015-11-01
2016-02-01
2016-07-01
2016-09-01
2017-05-10
2018-02-01
2018-05-01 | -| scheduler | 2014-08-01-preview
2016-01-01
2016-03-01 | -| security | 2017-08-01-preview | -| servicebus | 2015-08-01 | -| servicefabric | 2016-09-01
2017-07-01-preview | -| servicefabricmesh | 2018-07-01-preview | -| servicemap | 2015-11-01-preview | -| services | 2018-03-01-preview | -| signalr | 2018-03-01-preview | -| siterecovery | 2016-08-10
2018-01-10 | -| skus | 2017-09-01 | -| sql | 2015-05-01-preview
2017-03-01-preview
2017-10-01-preview | -| storage | 2015-05-01-preview | -| storageimportexport | 2016-11-01 | -| storsimple | 2016-10-01
2017-06-01 | -| streamanalytics | 2016-03-01 | -| subscription | 2017-11-01-preview
2018-03-01-preview | -| subscriptions | 2015-11-01
2016-06-01 | -| timeseriesinsights | 2017-02-28-preview
2017-11-15 | -| web | 2016-09-01 | -| webservices | 2016-05-01-preview
2017-01-01 | -| workspaces | 2016-04-01 | - -### BreakingChanges - -| Package Name | API Version | -| ------------------: | :---------------------------------------: | -| aad | 2017-01-01
2017-06-01 | -| apimanagement | 2018-06-01-preview | -| backup | 2016-12-01
2017-07-01 | -| compute | 2018-06-01
2018-10-01 | -| costmanagement | 2018-08-01-preview | -| deploymentmanager | 2018-09-01-preview | -| eventgrid | 2018-01-01 | -| graphrbac | 1.6 | -| hdinsight | 2015-03-01-preview
2018-06-01-preview | -| insights | v1 | -| iotcentral | 2018-09-01 | -| locks | 2016-09-01 | -| network | 2018-08-01 | -| operationalinsights | v1 | -| prediction | customvision | -| servicebus | 2017-04-01 | -| storagesync | 2018-04-02 | -| web | 2018-02-01 | - -### Removed Packages - -**NOTE** The majority of these packages are found under ./services/preview (they were incorrectly placed in the repository). - -| Package Name | API Version | -| -------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------: | -| account | 2015-10-01-preview
2015-10-01-preview | -| addons | 2017-05-15
2018-03-01 | -| advisor | 2016-07-12-preview | -| analysisservices | 2017-08-01-beta
2017-08-01-beta | -| appinsights | v1 | -| authorization | 2017-10-01-preview
2018-01-01-preview | -| automation | 2018-01-preview
2018-06-preview | -| batchai | 2017-09-preview
2017-09-preview | -| billing | 2017-02-27-preview
2017-04-24-preview
2018-03-01-preview | -| botservices | 2017-12-01
2018-07-12 | -| catalog | 2015-10-01-preview | -| cognitiveservices | 2016-02-01-preview
2016-02-01-preview | -| commerce | 2015-06-01-preview | -| commitmentplans | 2016-05-01-preview | -| compute | 2016-04-30-preview
2017-08-01-preview | -| consumption | 2017-04-24-preview
2017-12-30-preview | -| containerinstance | 2017-08-01-preview
2017-10-01-preview
2017-12-01-preview
2018-02-01-preview | -| containerregistry | 2016-06-27-preview
2017-06-01-preview | -| containerservice | 2015-11-01-preview | -| datamigration | 2017-11-15-preview | -| dns | 2015-05-04-preview | -| dtl | 2015-05-21-preview | -| eventgrid | 2017-06-15-preview
2017-09-15-preview | -| experimentation | 2017-05-01-preview | -| filesystem | 2015-10-01-preview | -| hanaonazure | 2017-06-15-preview
2017-11-03-preview | -| hdinsight | 2015-03-01-preview | -| insights | 2017-05-01-preview
2018-03-01 | -| iotcentral | 2018-09-01 | -| iothub | 2017-08-21-preview | -| job | 2015-11-01-preview
2016-03-20-preview
2017-09-01-preview | -| keyvault | v7.0 | -| location | 2017-01-01-preview
2017-01-01-preview | -| logic | 2015-02-01-preview
2015-08-01-preview | -| management | 2017-08-31-preview
2017-08-31-preview
2017-11-01-preview
2017-11-01-preview
2018-01-01-preview
2018-01-01-preview
2018-03-01-preview | -| msi | 2015-08-31-preview | -| mysql | 2017-04-30-preview
2017-12-01-preview | -| network | 2015-05-01-preview | -| operationalinsights | 2015-11-01-preview | -| operationsmanagement | 2015-11-01-preview | -| policyinsights | 2017-08-09-preview
2017-10-17-preview
2017-12-12-preview | -| scheduler | 2014-08-01-preview | -| servicefabric | 2017-07-01-preview | -| servicemap | 2015-11-01-preview | -| sql | 2015-05-01-preview
2017-03-01-preview
2017-10-01-preview | -| storage | 2015-05-01-preview | -| storagesync | 2018-07-01 | -| timeseriesinsights | 2017-02-28-preview | -| trafficmanager | 2017-09-01-preview | -| visualstudio | 2014-04-01-preview | -| web | 2015-08-preview
2015-08-preview | -| webservices | 2016-05-01-preview | - -## `v21.3.0` - -### New Packages - -| Package Name | API Version | -| ---------------: | :----------------: | -| consumption | 2018-10-01 | -| containerservice | 2018-09-30-preview | -| textanalytics | v2.1 | - -### Updated Packages - -| Package Name | API Version | -| -----------: | :---------: | -| servicebus | 2017-04-01 | - -## `v21.2.0` - -### New Packages - -| Package Name | API Version | -| ----------------: | :----------------: | -| blueprint | 2017-11-11-preview | -| containerinstance | 2018-10-01 | -| policyinsights | 2018-07-01-preview | - -### Updated Packages - -| Package Name | API Version | -| ------------------: | :---------------------------------------: | -| auth | keyvault | -| automation | 2018-06-preview | -| containerregistry | 2017-10-01
2018-02-01
2018-09-01 | -| costmanagement | 2018-05-31 | -| datafactory | 2018-06-01 | -| documentdb | 2015-04-08 | -| hdinsight | 2015-03-01-preview
2018-06-01-preview | -| insights | 2015-05-01
2018-03-01
2018-09-01 | -| job | 2017-09-01-preview | -| mysql | 2017-12-01 | -| operationalinsights | 2015-03-20 | -| security | 2017-08-01-preview | -| sql | 2017-10-01-preview | - -## `v21.1.0` - -### New Packages - -| Package Name | API Version | -| -----------: | :---------: | -| media | 2018-07-01 | -| storage | 2018-07-01 | - -### Updated Packages - -| Package Name | API Version | -| ------------: | :----------------: | -| authorization | 2018-09-01-preview | -| links | 2016-09-01 | -| resources | 2018-05-01 | -| servicebus | 2017-04-01 | -| subscriptions | 2016-06-01 | -| web | 2018-02-01 | - -## `v21.0.0` - -### New Packages - -| Package Name | API Version | -| ----------------: | :----------------: | -| compute | 2018-10-01 | -| deploymentmanager | 2018-09-01-preview | -| frontdoor | 2018-08-01-preview | - -### Updated Packages - -| Package Name | API Version | -| ------------------: | :-----------------------------------------------------------------------------: | -| advisor | 2017-04-19 | -| compute | 2017-08-01-preview | -| datafactory | 2017-09-01-preview | -| features | 2015-12-01 | -| graphrbac | 1.6 | -| hdinsight | 2015-03-01-preview
2018-06-01-preview | -| insights | 2017-05-01-preview
2018-03-01
2018-09-01
v1 | -| job | 2015-11-01-preview
2016-03-20-preview
2016-11-01
2017-09-01-preview | -| locks | 2016-09-01 | -| managedapplications | 2016-09-01-preview | -| policyinsights | 2017-08-09-preview
2017-10-17-preview
2017-12-12-preview
2018-04-04 | -| runtime | luis | -| security | 2017-08-01-preview | -| sql | 2015-05-01-preview
2017-10-01-preview | - -### BreakingChanges - -| Package Name | API Version | -| ------------------: | :-----------------------: | -| authoring | luis | -| automation | 2018-06-preview | -| backup | 2016-06-01
2017-07-01 | -| compute | 2018-06-01 | -| costmanagement | 2018-08-01-preview | -| customimagesearch | v1.0 | -| customsearch | v1.0 | -| databox | 2018-01-01 | -| datafactory | 2018-06-01 | -| eventhub | 2018-01-01-preview | -| logic | 2018-07-01-preview | -| monitor | 2018-09-01-preview | -| operationalinsights | v1 | -| services | 2018-03-01-preview | -| sql | 2017-03-01-preview | -| web | 2018-02-01 | - -## `v20.2.0` - -### New Services - -| Package Name | API Version | -| ----------------: | :-----------------------: | -| authorization | 2018-09-01-preview | -| automation | 2018-06-preview | -| consumption | 2018-08-31 | -| containerinstance | 2018-09-01 | -| eventgrid | 2018-09-15-preview | -| insights | 2018-09-01 | -| mariadb | 2018-06-01-preview | -| monitor | 2018-09-01-preview | -| network | 2018-08-01 | -| storagesync | 2018-04-02
2018-07-01 | -| storsimple | 2016-10-01 | - -### Updated Services - -| Package Name | API Version | -| -----------: | :-----------------------------------------------------------------------------: | -| botservices | 2018-07-12 | -| hanaonazure | 2017-11-03-preview | -| job | 2015-11-01-preview
2016-03-20-preview
2016-11-01
2017-09-01-preview | -| locks | 2016-09-01 | -| network | 2018-06-01 | -| security | 2017-08-01-preview | -| services | 2018-03-01-preview | - -## `v20.1.0` - -### New Services - -| Package Name | API Version | -| -----------: | :---------: | -| network | 2018-07-01 | - -## `v20.0.0` - -### New Services - -| Package Name | API Version | -| ----------------: | :----------------: | -| batch | 2018-08-01.7.0 | -| botservices | 2018-07-12 | -| containerregistry | 2018-09-01 | -| costmanagement | 2018-08-01-preview | -| iotcentral | 2018-09-01 | -| logic | 2018-07-01-preview | -| policy | 2018-05-01 | - -### Updated Services - -| Package Name | API Version | -| ----------------: | :-------------------------------: | -| advisor | 2017-04-19 | -| cdn | 2017-10-12 | -| consumption | 2018-06-30 | -| containerregistry | 2017-10-01
2018-02-01 | -| devices | 2018-04-01 | -| graphrbac | 1.6 | -| hanaonazure | 2017-11-03-preview | -| migrate | 2018-02-02 | -| mysql | 2017-12-01 | -| network | 2018-06-01 | -| powerbidedicated | 2017-10-01 | -| reservations | 2018-06-01 | -| signalr | 2018-03-01-preview | -| siterecovery | 2018-01-10 | -| sql | 2017-03-01-preview | -| storage | 2018-02-01
2018-03-01-preview | - -### Removed Packages - -| Package Name | API Version | -| -----------: | :-----------------------: | -| iotcentral | 2017-07-01-privatepreview | -| network | 2018-05-01 | - -### Breaking Changes - -| Package Name | API Version | -| ----------------: | :------------------------------------------------------------------------------------: | -| automation | 2015-10-31
2017-05-15-preview
2018-01-preview | -| azurestack | 2017-06-01 | -| compute | 2017-12-01
2018-04-01
2018-06-01 | -| computervision | v2.0 | -| containerinstance | 2018-06-01 | -| containerservice | 2018-03-31 | -| contentmoderator | v1.0 | -| datafactory | 2018-06-01 | -| dns | 2015-05-04-preview
2016-04-01
2017-09-01
2017-10-01
2018-03-01-preview | -| face | v1.0 | -| hdinsight | 2015-03-01-preview
2018-06-01-preview | -| insights | 2017-05-01-preview
2018-03-01 | -| luis/authoring | v2.0 | -| luis/runtime | v2.0 | -| network | 2018-04-01 | -| security | 2017-08-01-preview | -| sql | 2017-10-01-preview | -| textanalytics | v2.0 | -| visualsearch | v1.0 | -| web | 2018-02-01 | - -## `v19.1.0` - -### New Services - -| Package Name | API Version | -| -----------: | :----------------: | -| iotcentral | 2018-09-01 | -| network | 2018-06-01 | -| security | 2017-08-01-preview | - -### Updated Services - -| Package Name | API Version | -| -----------: | :---------: | -| eventgrid | 2018-01-01 | - -## `v19.0.0` - -### Removed Packages - -| Package Name | API Version | -| ---------------: | :---------------------------------------: | -| servermanagement | 2015-07-01-preview
2016-07-01-preview | - -### Breaking Changes - -| Package Name | API Version | -| ----------------: | :-------------------------------------------------------------------------------------------: | -| authoring | v2.0 | -| automation | 2015-10-31
2017-05-15-preview
2018-01-preview | -| backup | 2016-12-01
2017-07-01 | -| botservices | 2017-12-01 | -| compute | 2015-06-15
2016-03-30
2017-03-30
2017-12-01
2018-04-01
2016-04-30-preview | -| computervision | v2.0 | -| containerregistry | 2017-10-01 | -| eventgrid | 2018-01-01 | -| hdinsight | 2018-06-01-preview | -| insights | 2017-05-01-preview
2018-03-01 | -| migrate | 2018-02-02 | -| runtime | v2.0 | -| sql | 2017-03-01-preview | -| web | 2018-02-01 | - -### New Services - -| Package Name | API Version | -| ----------------: | :----------------: | -| alertsmanagement | 2018-05-05-preview | -| compute | 2018-06-01 | -| costmanagement | 2018-05-31 | -| servicefabricmesh | 2018-07-01-preview | -| compute/skus | 2017-09-01 | - -### Updated Services - -| Package Name | API Version | -| ----------------: | :-------------------------------: | -| apimanagement | 2018-01-01
2018-06-01-preview | -| containerregistry | 2018-02-01 | -| containerservice | 2018-03-31 | -| management | 2018-03-01-preview | - -## `v18.1.0` - -### New Services - -| Package Name | API Version | -| --------------------------: | :---------: | -| cognitive services training | v2.1 | -| consumption | 2018-06-30 | - -### Updated Services - -| Package Name | API Version | -| -----------: | :---------------------------------------: | -| hdinsight | 2015-03-01-preview
2018-06-01-preview | -| postgresql | 2017-12-01 | -| resources | 2018-05-01 | -| search | 2015-08-19 | - -## `v18.0.0` - -### New Services - -| Package Name | API Version | -| ----------------------: | :-------------------: | -| apimanagement | 2018-06-01-preview | -| hdinsight | 2018-06-01-preview | -| computervision | v2.0 | -| recoveryservices/backup | 2016-12-01 | -| storagedatalake | 2018-06-17 | -| devspaces | 2018-06-01-preview | -| automation | 2017-05-15-preview | -| keyvault | v7.0
2018-02-14 | -| automation | 2018-01-preview | -| media | 2018-06-01-preview | -| datafactory | 2018-06-01 | - -### Updates Services - -| Package Name | API Version | -| -------------: | :--------------------------------: | -| face | v1.0 | -| luis/authoring | v2.0 | -| luis/runtime | v2.0 | -| textanalytics | v2.0 | -| eventhub | 2017-04-01
2018-01-01-preview | -| monitor | 2017-05-01-preview | -| signalr | 2018-03-01-preview | -| sql | 2017-10-01-preview | -| storage | 2018-03-01-preview
2018-02-01 | -| servicebus | 2017-04-01 | - -### Breaking Changes - -| Package Name | API Version | -| ----------------------: | :-------------------: | -| adhybridhealthservice | 2014-01-01 | -| advisor | 2017-04-19 | -| appinsights | 2015-05-01
v1 | -| automation | 2015-10-31/automation | -| batchai | 2018-05-01/batchai | -| computervision | v1.0 | -| consumption | 2018-05-31 | -| network | 2018-04-01 | -| operationalinsights | 2015-03-20
v1 | -| recoveryservices/backup | 2017-07-01 | -| reservations | 2018-06-01 | - -## `v17.4.0` - -### New Services - -| Package Name | API Version | -| ---------------: | :---------: | -| autosuggest | v1.0 | -| containerservice | 2018-03-31 | - -### Updated Services - -| Package Name | API Version | -| ---------------: | :---------------------------------------: | -| consumption | 2018-05-31 | -| documentdb | 2015-04-08 | -| network | 2018-02-01
2018-04-01
2018-05-01 | -| notificationhubs | 2017-04-01 | -| sql | 2017-03-01-preview
2017-10-01-preview | - -## `v17.3.1` - -### Updated Services - -| Package Name | API Version | -| ------------: | :-----------------------------------------------------------------------------------: | -| network | 2017-10-01
2017-11-01
2018-01-01
2018-02-01
2018-04-01
2018-05-01 | -| servicefabric | 5.6
6.0
6.1
6.2 | - -## `v17.3.0` - -### New Services - -| Package Name | API Version | -| ----------------: | :---------: | -| containerinstance | 2018-06-01 | -| reservations | 2018-06-01 | - -### Updated Services - -| Package Name | API Version | -| -----------: | :---------: | -| datafactory | 2017-09-01 | -| network | 2015-06-15 | - -## `v17.2.0` - -### New Services - -| Package Name | API Version | -| ------------------: | :---------: | -| managedapplications | 2018-06-01 | -| resources | 2018-05-01 | - -### Updated Services - -| Package Name | API Version | -| -------------------: | :---------: | -| networksecuritygroup | classic | - -## `v17.1.0` - -### New Services - -| Package Name | API Version | -| -----------: | :-----------------------: | -| iotcentral | 2017-07-01-privatepreview | - -## `v17.0.0` - -### New Services - -| Package Name | API Version | -| --------------------: | :-----------------: | -| batchai | 2018-05-01 | -| adhybridhealthservice | 2014-01-01 | -| consumption | 2018-05-31 | -| customimagesearch | v1.0 | -| luis/authoring | v2.0 | -| management | 2018-03-01-preview | -| maps | 2017-01-01-preview | -| maps | 2018-05-01 | -| network | 2018-05-01 | -| policy | "2018-03-01 | -| servicefabric | "2018-02-01 | -| services | "2018-03-01-preview | -| storage | 2018-03-01-preview | -| trafficmanager | 2018-02-01 | -| workspaces | 2016-04-01 | - -### Updated Services - -| Package Name | API Version | -| ------------------: | :----------------: | -| aad | 2017-01-01 | -| aad | 2017-06-01 | -| account | 2016-11-01 | -| advisor | 2017-04-19 | -| analysisservices | 2016-05-16 | -| analysisservices | 2017-07-14 | -| analysisservices | 2017-08-01 | -| apimanagement | 2016-07-07 | -| apimanagement | 2016-10-10 | -| apimanagement | 2017-03-01 | -| apimanagement | 2018-01-01 | -| batch | 2015-12-01 | -| batch | 2017-01-01 | -| batch | 2017-05-01 | -| batch | 2017-09-01 | -| batchai | 2018-03-01 | -| batchai | 2018-05-01 | -| botservices | 2017-12-01 | -| catalog | 2016-11-01-preview | -| cdn | 2015-06-01 | -| cdn | 2016-04-02 | -| cdn | 2016-10-02 | -| cdn | 2017-04-02 | -| cdn | 2017-10-12 | -| compute | 2015-06-15 | -| compute | 2016-03-30 | -| compute | 2017-03-30 | -| compute | 2018-04-01 | -| computervision | v1.0 | -| consumption | 2018-03-31 | -| containerinstance | 2018-04-01 | -| containerregistry | 2017-03-01 | -| containerregistry | 2017-10-01 | -| containerregistry | 2018-02-01 | -| containerservice | 2016-03-30 | -| containerservice | 2016-09-30 | -| containerservice | 2017-01-31 | -| containerservice | 2017-07-01 | -| containerservice | 2017-08-31 | -| containerservice | 2017-09-30 | -| customerinsights | 2017-01-01 | -| customerinsights | 2017-04-26 | -| databox | 2018-01-01 | -| databricks | 2018-04-01 | -| datacatalog | 2016-03-30 | -| datafactory | 2017-09-01-preview | -| datamigration | 2018-03-31-preview | -| devices | 2016-02-03 | -| devices | 2017-01-19 | -| devices | 2017-07-01 | -| devices | 2018-01-22 | -| devices | 2018-04-01 | -| dns | 2016-04-01 | -| dns | 2017-09-01 | -| dns | 2017-10-01 | -| documentdb | 2015-04-08 | -| dtl | 2016-05-15 | -| eventgrid | 2018-01-01 | -| eventgrid | 2018-05-01-preview | -| eventhub | 2015-08-01 | -| eventhub | 2017-04-01 | -| eventhub | 2018-01-01-preview | -| insights | 2015-05-01 | -| iothub | 2017-08-21-preview | -| iothub | 2017-11-15 | -| iothub | 2018-01-22 | -| iotspaces | 2017-10-01-preview | -| logic | 2016-06-01 | -| managedapplications | 2016-09-01-preview | -| managedapplications | 2017-09-01 | -| management | 2018-01-01-preview | -| media | 2018-03-30-preview | -| mysql | 2017-12-01 | -| network | 2015-06-15 | -| network | 2016-03-30 | -| network | 2016-06-01 | -| network | 2016-09-01 | -| network | 2016-12-01 | -| network | 2017-03-01 | -| network | 2017-06-01 | -| network | 2017-08-01 | -| network | 2017-09-01 | -| network | 2017-10-01 | -| network | 2017-11-01 | -| network | 2018-01-01 | -| network | 2018-02-01 | -| network | 2018-04-01 | -| notificationhubs | 2014-09-01 | -| notificationhubs | 2016-03-01 | -| notificationhubs | 2017-04-01 | -| operationalinsights | 2015-03-20 | -| operationalinsights | v1 | -| postgresql | 2017-12-01 | -| powerbidedicated | 2017-10-01 | -| powerbiembedded | 2016-01-29 | -| prediction | customvision | -| luis/programmatic | v2.0 | -| redis | 2016-04-01 | -| redis | 2017-02-01 | -| redis | 2017-10-01 | -| redis | 2018-03-01 | -| relay | 2016-07-01 | -| relay | 2017-04-01 | -| reservations | 2017-11-01 | -| resources | 2015-11-01 | -| resources | 2016-02-01 | -| resources | 2016-07-01 | -| resources | 2016-09-01 | -| resources | 2017-05-10 | -| resources | 2018-02-01 | -| luis/runtime | v2.0 | -| scheduler | 2016-03-01 | -| search | 2015-08-19 | -| servermanagement | 2015-07-01-preview | -| servermanagement | 2016-07-01-preview | -| servicebus | 2015-08-01 | -| servicebus | 2017-04-01 | -| servicefabric | 2016-09-01 | -| servicefabric | 2017-07-01-preview | -| signalr | 2018-03-01-preview | -| siterecovery | 2016-08-10 | -| siterecovery | 2018-01-10 | -| sql | 2014-04-01 | -| sql | 2015-05-01-preview | -| sql | 2017-03-01-preview | -| sql | 2017-10-01-preview | -| storage | 2015-05-01-preview | -| storage | 2015-06-15 | -| storage | 2016-01-01 | -| storage | 2016-05-01 | -| storage | 2016-12-01 | -| storage | 2017-06-01 | -| storage | 2017-10-01 | -| storage | 2018-02-01 | -| storsimple | 2017-06-01 | -| streamanalytics | 2016-03-01 | -| subscription | 2017-11-01-preview | -| subscription | 2018-03-01-preview | -| timeseriesinsights | 2017-02-28-preview | -| timeseriesinsights | 2017-11-15 | -| trafficmanager | 2018-03-01 | -| training | customvision | -| visualstudio | 2014-04-01-preview | -| web | 2015-08-preview | -| web | 2016-09-01 | -| web | 2018-02-01 | -| webservices | 2017-01-01 | - -## `v16.2.2` - -### Updated Services - -| Package Name | API Version | -| -----------: | :----------------: | -| signalr | 2018-03-01-preview | - -## `v16.2.1` - -### Updated Services - -| Package Name | API Version | -| -----------: | :-----------------------: | -| web | 2016-09-01
2018-02-01 | - -## `v16.2.0` - -### New Services - -| Package Name | API Version | -| -------------: | :----------------: | -| eventgrid | 2018-05-01-preview | -| trafficmanager | 2018-03-01 | - -### Updated Services - -| Package Name | API Version | -| ------------: | :-----------------------: | -| redis | 2017-10-01
2018-03-01 | -| textanalytics | v2.0 | -| web | 2016-09-01
2018-02-01 | - -## `v16.1.0` - -- Added a `NewAuthorizerFromEnvironment()` function for the keyvault service. - -## `v16.0.0` - -### New Services - -| Package Name | API Version | -| ------------------: | :----------------: | -| batchai | 2018-05-01 | -| botservices | 2017-12-01 | -| containerinstance | 2018-04-01 | -| containerregistry | 2018-02-01 | -| keyvault | v7.0 | -| managedapplications | 2017-09-01 | -| network | 2018-04-01 | -| policyinsights | 2018-04-04 | -| signalr | 2018-03-01-preview | -| storage | 2018-02-0 | -| visualsearch | v1.0 | -| web | 2018-02-01 | - -### Updated Services - -| Package Name | API Version | -| ------------------: | :--------------------------------------------------------------: | -| apimanagement | 2018-01-01 | -| automation | 2015-10-31
2017-05-15-preview | -| billing | 2018-03-01-preview | -| botservices | 2017-12-01 | -| catalog | 2016-11-01-preview | -| cognitiveservices | 2017-04-18 | -| commerce | 2015-06-01-preview | -| compute | 2018-04-01 | -| consumption | 2018-03-31 | -| contentmoderator | v1.0 | -| datafactory | 2017-09-01-preview | -| datamigration | 2017-11-15-preview | -| eventhub | 2017-04-01 | -| insights | 2015-05-0 | -| iothub | 2017-11-15 | -| network | 2018-02-01 | -| operationalinsights | 2015-03-20
2015-11-01-preview | -| servicebus | 2017-04-01 | -| siterecovery | 2018-01-10 | -| sql | 2017-03-01-preview
2017-10-01-preview
2015-05-01-preview | -| timeseriesinsights | 2017-11-15 | -| luis/runtime | v2.0 | -| web | 2016-09-01 | - -## `v15.3.0` - -### New Services - -| Package Name | API Version | -| ------------: | :----------------: | -| databox | 2018-01-01 | -| devices | 2018-04-01 | -| media | 2018-03-30-preview | -| servicefabric | 6.2 | - -### Updated Services - -| Package Name | API Version | -| ----------------: | :------------: | -| apimanagement | 2018-01-01 | -| batch | 2018-03-01.6.1 | -| containerregistry | 2017-10-01 | -| documentdb | 2015-04-08 | -| servicebus | 2017-04-01 | - -## `v15.2.0` - -### New Services - -| Package Name | API Version | -| -----------: | :---------: | -| addons | 2017-05-15 | -| addons | 2018-03-01 | - -### Updated Services - -| Package Name | API Version | -| ------------: | :---------: | -| apimanagement | 2017-03-01 | -| apimanagement | 2018-01-01 | -| insights | 2015-05-01 | - -## `v15.1.1` - -### Bug Fixes - -- Drain the response body when retrying a request. -- Avoid allocating when draining a response body. - -## `v15.1.0` - -### New Services - -| Package Name | API Version | -| ----------------: | :----------------: | -| datamigration | 2018-03-31-preview | -| devices | 2018-01-22 | -| network | 2018-02-01 | -| cognitiveservices | customvision | - -## Updated Services - -| Package Name | API Version | -| -----------: | :----------------------------------------------------------------------------: | -| compute | 2015-06-15
2016-03-30
2016-04-30-preview
2017-03-30
2018-04-01 | -| datafactory | 2017-09-01-preview | -| insights | 2018-03-01 | -| mysql | 2017-12-01 | -| postgresql | 2017-12-01 | -| web | 2016-09-01 | - -## `v15.0.1` - -Fixing some build issues, and temporarily reverting CI. - -## `v15.0.0` - -NOTE: There is a new subdirectory, ./services/preview, which going forward will be used for segregating pre-GA packages. - -### New Features - -- Added helper func per enum type that returns a slice of all possible values for that type. - -### Bug Fixes - -- Removed the "arm-" prefix from user-agent strings as not all services are for ARM. -- Fixed missing marshaller for structs with flattened fields. -- Fixed an issue where the incorrect content MIME type was being specified. -- Marshalling of empty values for enum types now works as expected. - -### New Services - -| Package Name | API Version | -| -------------: | :--------------------------------------------------------------: | -| apimanagement | 2017-03-01 | -| azurestack | 2017-06-01 | -| billing | 2018-03-01-preview | -| compute | 2018-04-01 | -| consumption | 2018-03-31 | -| databricks | 2018-04-01 | -| dns | 2017-10-01 | -| insights | 2018-03-01 | -| iothub | 2018-01-22 | -| iotspaces | 2017-10-01-preview | -| management | 2018-01-01-preview | -| migrate | 2018-02-02 | -| policyinsights | 2017-08-09-preview
2017-10-17-preview
2017-12-12-preview | -| resources | 2018-02-01 | -| siterecovery | 2018-01-10 | -| sql | 2017-10-01-preview | - -### Breaking Changes - -| Package Name | API Version | -| ------------------: | :----------------------------------------: | -| automation | 2017-05-15-preview | -| advisor | 2017-04-19 | -| cognitiveservices | 2017-04-18 | -| compute | 2017-03-30
2017-12-01 | -| consumption | 2018-01-31 | -| containerinstance | 2018-02-01-preview | -| containerservice | 2017-08-31
2017-09-30 | -| customsearch | v1.0 | -| datafactory | 2017-09-01-preview | -| datamigration | 2017-11-15-preview | -| dns | 2018-03-01-preview | -| entitysearch | v1.0 | -| imagesearch | v1.0 | -| insights | 2017-05-01-preview | -| iothub | 2017-11-15 | -| management | 2017-08-31-preview
2017-11-01-preview | -| mysql | 2017-12-01-preview | -| newssearch | v1.0 | -| operationalinsights | 2015-03-20 | -| postgresql | 2017-12-01-preview | -| servicebus | 2015-08-01 | -| servicefabric | 2017-07-01-preview
5.6
6.0
6.1 | -| servicemap | 2015-11-01-preview | -| spellcheck | v1.0 | -| timeseriesinsights | 2017-02-28-preview
2017-11-15 | -| videosearch | v1.0 | -| web | 2016-09-01 | -| websearch | v1.0 | - -## `v14.6.0` - -### New Services - -- Batch 2018-03-01.6.1 -- BatchAI 2018-03-01 -- Cognitive services custom vision prediction v1.1 -- Eventhub 2018-01-01-preview -- MySQL 2017-12-01 -- PostgreSQL 2017-12-01 -- Redis 2018-03-01 -- Subscription 2018-03-01-preview - -## `v14.5.0` - -### Changes - -- Added new preview packages for apimanagement and dns. - -## `v14.4.0` - -### Changes - -- Added new preview API versions for mysql and postgresql. - -## `v14.3.0` - -### Changes - -- Add exports for max file range and sizes for files in storage. -- Updated README regarding blob storage support. -- Add godoc indexer tool. -- Add apidiff tool. - -## `v14.2.0` - -### Changes - -- For blob storage, added GetProperties() method to Container. -- Added PublicAccess field to ContainerProperties struct. - -## `v14.1.1` - -- Fixing timestamp marshalling bug in the `storage` package. -- Updating `profileBuilder` to clear-output folders when it is run by `go generate`. -- Tweaking Swagger -> SDK config to use "latest" instead of "nightly" and be tied to a particular version of autorest.go. - -## `v14.1.0` - -### Changes - -- Update README with details on new authentication helpers. -- Update `latest` profile to point to latest stable API versions. -- Add new API version for Azure Monitoring service and for Batch Data plane service. - -## `v14.0.2` - -### Changes - -- Updating `profileBuilder list` to accept an `input` flag instead of reading from `stdin`. -- Simplifying CI to have less chatter, be faster, and have no special cases. - -## `v14.0.1` - -### Changes - -- Removed the ./services/search/2016-09-01/search package, it was never intended to be included and doesn't work. - -## `v14.0.0` - -### Breaking Changes - -- Removed the ./arm, ./datalake-store and ./dataplane directories. You can find the same packages under ./services -- The management package was moved to ./services/classic/management -- Renamed package ./services/redis/mgmt/2017-10-01/cache to ./services/redis/mgmt/2017-10-01/redis - -### Changes - -- Removed the "-beta" suffix. -- Added various new services. -- Added ./version package for centralized SDK versioning. diff --git a/vendor/github.com/Azure/azure-sdk-for-go/CODEOWNERS b/vendor/github.com/Azure/azure-sdk-for-go/CODEOWNERS deleted file mode 100644 index 8254c090..00000000 --- a/vendor/github.com/Azure/azure-sdk-for-go/CODEOWNERS +++ /dev/null @@ -1,12 +0,0 @@ -/documentation/ @joshgav -/profiles/ @jhendrixMSFT @vladbarosan -/services/ @jhendrixMSFT @vladbarosan -/storage/ @jhendrixMSFT @vladbarosan -/tools/apidiff/ @jhendrixMSFT @vladbarosan -/tools/generator/ @jhendrixMSFT @vladbarosan -/tools/indexer/ @jhendrixMSFT @vladbarosan -/tools/profileBuilder/ @jhendrixMSFT @vladbarosan -/version/ @jhendrixMSFT @vladbarosan -.travis.yml @jhendrixMSFT @vladbarosan -doc.go @joshgav -findTestedPackages.sh @jhendrixMSFT @vladbarosan diff --git a/vendor/github.com/Azure/azure-sdk-for-go/CONTRIBUTING.md b/vendor/github.com/Azure/azure-sdk-for-go/CONTRIBUTING.md deleted file mode 100644 index 1b405a2d..00000000 --- a/vendor/github.com/Azure/azure-sdk-for-go/CONTRIBUTING.md +++ /dev/null @@ -1,17 +0,0 @@ -# Contributing - -As of version 14, the Azure SDK for Go is GA. We maintain only a `master` branch for releases and a `latest` branch for the latest changes. - -For bugs or feature requests you can submit them using the [Github issues page][issues] and filling the appropriate template. - -For Pull Requests, please submit them _ONLY_ to `latest` branch. - -Also please see these [guidelines][] about contributing to Azure projects. - -This project follows the [Microsoft Open Source Code of Conduct][coc]. For more information see the [Code of Conduct FAQ][cocfaq]. Contact [opencode@microsoft.com][cocmail] with questions and comments. - -[guidelines]: http://azure.github.io/guidelines/ -[coc]: https://opensource.microsoft.com/codeofconduct/ -[cocfaq]: https://opensource.microsoft.com/codeofconduct/faq/ -[cocmail]: mailto:opencode@microsoft.com -[issues]: https://github.com/Azure/Azure-sdk-for-go/issues diff --git a/vendor/github.com/Azure/azure-sdk-for-go/Gopkg.lock b/vendor/github.com/Azure/azure-sdk-for-go/Gopkg.lock deleted file mode 100644 index 7d41967e..00000000 --- a/vendor/github.com/Azure/azure-sdk-for-go/Gopkg.lock +++ /dev/null @@ -1,384 +0,0 @@ -# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. - - -[[projects]] - digest = "1:e1b859e3d9e90007d5fbf25edf57733b224f1857f6592636130afab3af8cfae7" - name = "contrib.go.opencensus.io/exporter/ocagent" - packages = ["."] - pruneopts = "" - revision = "00af367e65149ff1f2f4b93bbfbb84fd9297170d" - version = "v0.2.0" - -[[projects]] - digest = "1:597d79297997cdf9f13427b0644558c6b845451607a6893c9b00b3625ab1f4f3" - name = "github.com/Azure/go-autorest" - packages = [ - "autorest", - "autorest/adal", - "autorest/azure", - "autorest/azure/auth", - "autorest/azure/cli", - "autorest/date", - "autorest/to", - "autorest/validation", - "logger", - "tracing", - "version", - ] - pruneopts = "" - revision = "528b76fd0ebec0682f3e3da7c808cd472b999615" - version = "v11.2.7" - -[[projects]] - digest = "1:e0a4505d5cf7ac6b5d92e3aee79d838b5f1ae8e9641ec7fa5d1e9b01d7a7ea95" - name = "github.com/census-instrumentation/opencensus-proto" - packages = [ - "gen-go/agent/common/v1", - "gen-go/agent/trace/v1", - "gen-go/trace/v1", - ] - pruneopts = "" - revision = "24333298e36590ea0716598caacc8959fc393c48" - version = "v0.0.2" - -[[projects]] - digest = "1:6098222470fe0172157ce9bbef5d2200df4edde17ee649c5d6e48330e4afa4c6" - name = "github.com/dgrijalva/jwt-go" - packages = ["."] - pruneopts = "" - revision = "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e" - version = "v3.2.0" - -[[projects]] - digest = "1:7f175a633086a933d1940a7e7dc2154a0070a7c25fb4a2f671f3eef1a34d1fd7" - name = "github.com/dimchansky/utfbom" - packages = ["."] - pruneopts = "" - revision = "5448fe645cb1964ba70ac8f9f2ffe975e61a536c" - version = "v1.0.0" - -[[projects]] - branch = "master" - digest = "1:5ee2023eac9f57de6bdb055625e8ac014b2c2b39e22bb88721d62a033de76bd1" - name = "github.com/dnaeon/go-vcr" - packages = [ - "cassette", - "recorder", - ] - pruneopts = "" - revision = "5637cf3d8a31b20882d79bd0e53a186d3821b155" - -[[projects]] - branch = "master" - digest = "1:e9ffb9315dce0051beb757d0f0fc25db57c4da654efc4eada4ea109c2d9da815" - name = "github.com/globalsign/mgo" - packages = [ - ".", - "bson", - "internal/json", - "internal/sasl", - "internal/scram", - ] - pruneopts = "" - revision = "eeefdecb41b842af6dc652aaea4026e8403e62df" - -[[projects]] - digest = "1:3dd078fda7500c341bc26cfbc6c6a34614f295a2457149fc1045cab767cbcf18" - name = "github.com/golang/protobuf" - packages = [ - "proto", - "ptypes", - "ptypes/any", - "ptypes/duration", - "ptypes/timestamp", - "ptypes/wrappers", - ] - pruneopts = "" - revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5" - version = "v1.2.0" - -[[projects]] - digest = "1:870d441fe217b8e689d7949fef6e43efbc787e50f200cb1e70dbca9204a1d6be" - name = "github.com/inconshreveable/mousetrap" - packages = ["."] - pruneopts = "" - revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75" - version = "v1.0" - -[[projects]] - digest = "1:3108ec0946181c60040ff51b811908f89d03e521e2b4ade5ef5c65b3c0e911ae" - name = "github.com/kr/pretty" - packages = ["."] - pruneopts = "" - revision = "73f6ac0b30a98e433b289500d779f50c1a6f0712" - version = "v0.1.0" - -[[projects]] - digest = "1:11b056b4421396ab14e384ab8ab8c2079b03f1e51aa5eb4d9b81f9e0d1aa8fbf" - name = "github.com/kr/text" - packages = ["."] - pruneopts = "" - revision = "e2ffdb16a802fe2bb95e2e35ff34f0e53aeef34f" - version = "v0.1.0" - -[[projects]] - digest = "1:a69ca302e0e9bab6743b40cb720ef02a8abcc2072eb55c0fd8869b3b285be425" - name = "github.com/marstr/collection" - packages = ["."] - pruneopts = "" - revision = "43f1d00df9bf332cbf8d26c3eecd6c348e92f7b3" - version = "v1.0.1" - -[[projects]] - digest = "1:f95025d583786875a71183888acc9d0987fc96f12d4f5afab3d7558797ea1c5a" - name = "github.com/marstr/guid" - packages = ["."] - pruneopts = "" - revision = "8bd9a64bf37eb297b492a4101fb28e80ac0b290f" - version = "v1.1.0" - -[[projects]] - digest = "1:096a8a9182648da3d00ff243b88407838902b6703fc12657f76890e08d1899bf" - name = "github.com/mitchellh/go-homedir" - packages = ["."] - pruneopts = "" - revision = "ae18d6b8b3205b561c79e8e5f69bff09736185f4" - version = "v1.0.0" - -[[projects]] - digest = "1:7365acd48986e205ccb8652cc746f09c8b7876030d53710ea6ef7d0bd0dcd7ca" - name = "github.com/pkg/errors" - packages = ["."] - pruneopts = "" - revision = "645ef00459ed84a119197bfb8d8205042c6df63d" - version = "v0.8.0" - -[[projects]] - digest = "1:7f569d906bdd20d906b606415b7d794f798f91a62fcfb6a4daa6d50690fb7a3f" - name = "github.com/satori/go.uuid" - packages = ["."] - pruneopts = "" - revision = "f58768cc1a7a7e77a3bd49e98cdd21419399b6a3" - version = "v1.2.0" - -[[projects]] - digest = "1:615c827f6a892973a587c754ae5fad7acfc4352657aff23d0238fe0ba2a154df" - name = "github.com/shopspring/decimal" - packages = ["."] - pruneopts = "" - revision = "cd690d0c9e2447b1ef2a129a6b7b49077da89b8e" - version = "1.1.0" - -[[projects]] - digest = "1:a1403cc8a94b8d7956ee5e9694badef0e7b051af289caad1cf668331e3ffa4f6" - name = "github.com/spf13/cobra" - packages = ["."] - pruneopts = "" - revision = "ef82de70bb3f60c65fb8eebacbb2d122ef517385" - version = "v0.0.3" - -[[projects]] - digest = "1:cbaf13cdbfef0e4734ed8a7504f57fe893d471d62a35b982bf6fb3f036449a66" - name = "github.com/spf13/pflag" - packages = ["."] - pruneopts = "" - revision = "298182f68c66c05229eb03ac171abe6e309ee79a" - version = "v1.0.3" - -[[projects]] - digest = "1:ad67dfd3799a2c58f6c65871dd141d8b53f61f600aec48ce8d7fa16a4d5476f8" - name = "go.opencensus.io" - packages = [ - ".", - "exemplar", - "internal", - "internal/tagencoding", - "plugin/ochttp", - "plugin/ochttp/propagation/b3", - "plugin/ochttp/propagation/tracecontext", - "stats", - "stats/internal", - "stats/view", - "tag", - "trace", - "trace/internal", - "trace/propagation", - "trace/tracestate", - ] - pruneopts = "" - revision = "b7bf3cdb64150a8c8c53b769fdeb2ba581bd4d4b" - version = "v0.18.0" - -[[projects]] - branch = "master" - digest = "1:0049ee593cea6375d6bbabe5e0a30aa05576846025811df879e9fcf1223d29a2" - name = "golang.org/x/crypto" - packages = [ - "pkcs12", - "pkcs12/internal/rc2", - ] - pruneopts = "" - revision = "b078efbc8099b041569edb8c6ab625cd430e3fce" - -[[projects]] - branch = "master" - digest = "1:41055845ee2a3f0b0fbf94f12b7a6c5322ae66c166d192e38156e0d63a6e2993" - name = "golang.org/x/net" - packages = [ - "context", - "http/httpguts", - "http2", - "http2/hpack", - "idna", - "internal/timeseries", - "trace", - ] - pruneopts = "" - revision = "c44066c5c816ec500d459a2a324a753f78531ae0" - -[[projects]] - branch = "master" - digest = "1:b2ea75de0ccb2db2ac79356407f8a4cd8f798fe15d41b381c00abf3ae8e55ed1" - name = "golang.org/x/sync" - packages = ["semaphore"] - pruneopts = "" - revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca" - -[[projects]] - branch = "master" - digest = "1:2667800887f4161b5b1f49d3065204a82f974d1b857c00d7e450a5167477071f" - name = "golang.org/x/sys" - packages = ["unix"] - pruneopts = "" - revision = "d69651ed3497faee15a5363a89578e9991f6d5e2" - -[[projects]] - digest = "1:5acd3512b047305d49e8763eef7ba423901e85d5dd2fd1e71778a0ea8de10bd4" - name = "golang.org/x/text" - packages = [ - "collate", - "collate/build", - "internal/colltab", - "internal/gen", - "internal/tag", - "internal/triegen", - "internal/ucd", - "language", - "secure/bidirule", - "transform", - "unicode/bidi", - "unicode/cldr", - "unicode/norm", - "unicode/rangetable", - ] - pruneopts = "" - revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" - version = "v0.3.0" - -[[projects]] - branch = "master" - digest = "1:a5c40d520f13a38fe3dbe1691f82b124dd2cdfccdbde32cfc8ea4547ae55cbc1" - name = "golang.org/x/tools" - packages = [ - "go/ast/astutil", - "imports", - "internal/fastwalk", - "internal/gopathwalk", - ] - pruneopts = "" - revision = "2d2de6298155751e44170d1c9a9baacb688d2606" - -[[projects]] - branch = "master" - digest = "1:ba7c9eafe35679d6be0b1d064ab6b841fe968496c8a8381ddb55cb192b70c996" - name = "google.golang.org/api" - packages = ["support/bundler"] - pruneopts = "" - revision = "aff2d7231e3cd0219626182c997296a559b5a27b" - -[[projects]] - branch = "master" - digest = "1:5bc459e4630e2f2adcd04005a06d6f9cdf614c6ffa751309497096efcab79150" - name = "google.golang.org/genproto" - packages = ["googleapis/rpc/status"] - pruneopts = "" - revision = "b69ba1387ce2108ac9bc8e8e5e5a46e7d5c72313" - -[[projects]] - digest = "1:1293087271e314cfa2b3decededba2ecba0ff327e7b7809e00f73f616449191c" - name = "google.golang.org/grpc" - packages = [ - ".", - "balancer", - "balancer/base", - "balancer/roundrobin", - "codes", - "connectivity", - "credentials", - "encoding", - "encoding/proto", - "grpclog", - "internal", - "internal/backoff", - "internal/channelz", - "internal/envconfig", - "internal/grpcrand", - "internal/transport", - "keepalive", - "metadata", - "naming", - "peer", - "resolver", - "resolver/dns", - "resolver/passthrough", - "stats", - "status", - "tap", - ] - pruneopts = "" - revision = "2e463a05d100327ca47ac218281906921038fd95" - version = "v1.16.0" - -[[projects]] - branch = "v1" - digest = "1:1d01f96bc2293b56c3dec797b8f976d7613fb30ce92bfbc994130404f7f7f031" - name = "gopkg.in/check.v1" - packages = ["."] - pruneopts = "" - revision = "788fd78401277ebd861206a03c884797c6ec5541" - -[[projects]] - digest = "1:f0620375dd1f6251d9973b5f2596228cc8042e887cd7f827e4220bc1ce8c30e2" - name = "gopkg.in/yaml.v2" - packages = ["."] - pruneopts = "" - revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183" - version = "v2.2.1" - -[solve-meta] - analyzer-name = "dep" - analyzer-version = 1 - input-imports = [ - "github.com/Azure/go-autorest/autorest", - "github.com/Azure/go-autorest/autorest/adal", - "github.com/Azure/go-autorest/autorest/azure", - "github.com/Azure/go-autorest/autorest/azure/auth", - "github.com/Azure/go-autorest/autorest/date", - "github.com/Azure/go-autorest/autorest/to", - "github.com/Azure/go-autorest/autorest/validation", - "github.com/Azure/go-autorest/tracing", - "github.com/dnaeon/go-vcr/cassette", - "github.com/dnaeon/go-vcr/recorder", - "github.com/globalsign/mgo", - "github.com/marstr/collection", - "github.com/marstr/guid", - "github.com/pkg/errors", - "github.com/satori/go.uuid", - "github.com/shopspring/decimal", - "github.com/spf13/cobra", - "golang.org/x/crypto/pkcs12", - "golang.org/x/tools/imports", - "gopkg.in/check.v1", - ] - solver-name = "gps-cdcl" - solver-version = 1 diff --git a/vendor/github.com/Azure/azure-sdk-for-go/Gopkg.toml b/vendor/github.com/Azure/azure-sdk-for-go/Gopkg.toml deleted file mode 100644 index 84c5af8b..00000000 --- a/vendor/github.com/Azure/azure-sdk-for-go/Gopkg.toml +++ /dev/null @@ -1,61 +0,0 @@ -# Gopkg.toml example -# -# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md -# for detailed Gopkg.toml documentation. -# -# required = ["github.com/user/thing/cmd/thing"] -# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] -# -# [[constraint]] -# name = "github.com/user/project" -# version = "1.0.0" -# -# [[constraint]] -# name = "github.com/user/project2" -# branch = "dev" -# source = "github.com/myfork/project2" -# -# [[override]] -# name = "github.com/x/y" -# version = "2.4.0" - - -[[constraint]] - name = "github.com/Azure/go-autorest" - version = "11.2.7" - -[[constraint]] - branch = "master" - name = "github.com/dnaeon/go-vcr" - -[[constraint]] - branch = "master" - name = "github.com/globalsign/mgo" - -[[constraint]] - name = "github.com/marstr/collection" - version = "1.0.1" - -[[constraint]] - name = "github.com/marstr/guid" - version = "1.1.0" - -[[constraint]] - name = "github.com/satori/go.uuid" - version = "1.2.0" - -[[constraint]] - name = "github.com/shopspring/decimal" - version = "1.0.0" - -[[constraint]] - branch = "master" - name = "golang.org/x/crypto" - -[[constraint]] - branch = "master" - name = "golang.org/x/tools" - -[[constraint]] - branch = "v1" - name = "gopkg.in/check.v1" diff --git a/vendor/github.com/Azure/azure-sdk-for-go/README.md b/vendor/github.com/Azure/azure-sdk-for-go/README.md deleted file mode 100644 index c4885d52..00000000 --- a/vendor/github.com/Azure/azure-sdk-for-go/README.md +++ /dev/null @@ -1,505 +0,0 @@ -# Azure SDK for Go - -[![godoc](https://godoc.org/github.com/Azure/azure-sdk-for-go?status.svg)](https://godoc.org/github.com/Azure/azure-sdk-for-go) - -[![Build Status](https://travis-ci.org/Azure/azure-sdk-for-go.svg?branch=master)](https://travis-ci.org/Azure/azure-sdk-for-go) - -[![Go Report Card](https://goreportcard.com/badge/github.com/Azure/azure-sdk-for-go)](https://goreportcard.com/report/github.com/Azure/azure-sdk-for-go) - -azure-sdk-for-go provides Go packages for managing and using Azure services. -It is continuously tested with Go 1.8, 1.9, 1.10, 1.11 and master. - -To be notified about updates and changes, subscribe to the [Azure update -feed](https://azure.microsoft.com/updates/). - -Users may prefer to jump right in to our samples repo at -[github.com/Azure-Samples/azure-sdk-for-go-samples][samples_repo]. - -Questions and feedback? Chat with us in the **[#Azure SDK -channel](https://gophers.slack.com/messages/CA7HK8EEP)** on the [Gophers -Slack](https://gophers.slack.com/). Sign up -[here](https://invite.slack.golangbridge.org) first if necessary. - - -## Package Updates - -Most packages in the SDK are generated from [Azure API specs][azure_rest_specs] -using [Azure/autorest.go][] and [Azure/autorest][]. These generated packages -depend on the HTTP client implemented at [Azure/go-autorest][]. - -[azure_rest_specs]: https://github.com/Azure/azure-rest-api-specs -[azure/autorest]: https://github.com/Azure/autorest -[azure/autorest.go]: https://github.com/Azure/autorest.go -[azure/go-autorest]: https://github.com/Azure/go-autorest - -The SDK codebase adheres to [semantic versioning](https://semver.org) and thus -avoids breaking changes other than at major (x.0.0) releases. Because Azure's -APIs are updated frequently, we release a **new major version at the end of -each month** with a full changelog. For more details and background see [SDK Update -Practices](https://github.com/Azure/azure-sdk-for-go/wiki/SDK-Update-Practices). - -To more reliably manage dependencies like the Azure SDK in your applications we -recommend [golang/dep](https://github.com/golang/dep). - -Packages that are still in public preview can be found under the ./services/preview -directory. Please be aware that since these packages are in preview they are subject -to change, including breaking changes outside of a major semver bump. - -## Other Azure Go Packages - -Azure provides several other packages for using services from Go, listed below. -If a package you need isn't available please open an issue and let us know. - -| Service | Import Path/Repo | -| -------------------- | -------------------------------------------------------------------------------------------------- | -| Storage - Blobs | [github.com/Azure/azure-storage-blob-go](https://github.com/Azure/azure-storage-blob-go) | -| Storage - Files | [github.com/Azure/azure-storage-file-go](https://github.com/Azure/azure-storage-file-go) | -| Storage - Queues | [github.com/Azure/azure-storage-queue-go](https://github.com/Azure/azure-storage-queue-go) | -| Service Bus | [github.com/Azure/azure-service-bus-go](https://github.com/Azure/azure-service-bus-go) | -| Event Hubs | [github.com/Azure/azure-event-hubs-go](https://github.com/Azure/azure-event-hubs-go) | -| Application Insights | [github.com/Microsoft/ApplicationInsights-go](https://github.com/Microsoft/ApplicationInsights-go) | - -# Install and Use: - -## Install - -```sh -$ go get -u github.com/Azure/azure-sdk-for-go/... -``` - -or if you use dep, within your repo run: - -```sh -$ dep ensure -add github.com/Azure/azure-sdk-for-go -``` - -If you need to install Go, follow [the official instructions](https://golang.org/dl/). - -## Use - -For many more scenarios and examples see -[Azure-Samples/azure-sdk-for-go-samples][samples_repo]. - -Apply the following general steps to use packages in this repo. For more on -authentication and the `Authorizer` interface see [the next -section](#authentication). - -1. Import a package from the [services][services_dir] directory. -2. Create and authenticate a client with a `New*Client` func, e.g. - `c := compute.NewVirtualMachinesClient(...)`. -3. Invoke API methods using the client, e.g. - `res, err := c.CreateOrUpdate(...)`. -4. Handle responses and errors. - -[services_dir]: https://github.com/Azure/azure-sdk-for-go/tree/master/services - -For example, to create a new virtual network (substitute your own values for -strings in angle brackets): - -```go -package main - -import ( - "context" - "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2017-09-01/network" - - "github.com/Azure/go-autorest/autorest/azure/auth" - "github.com/Azure/go-autorest/autorest/to" -) - -func main() { - // create a VirtualNetworks client - vnetClient := network.NewVirtualNetworksClient("") - - // create an authorizer from env vars or Azure Managed Service Idenity - authorizer, err := auth.NewAuthorizerFromEnvironment() - if err == nil { - vnetClient.Authorizer = authorizer - } - - // call the VirtualNetworks CreateOrUpdate API - vnetClient.CreateOrUpdate(context.Background(), - "", - "", - network.VirtualNetwork{ - Location: to.StringPtr(""), - VirtualNetworkPropertiesFormat: &network.VirtualNetworkPropertiesFormat{ - AddressSpace: &network.AddressSpace{ - AddressPrefixes: &[]string{"10.0.0.0/8"}, - }, - Subnets: &[]network.Subnet{ - { - Name: to.StringPtr(""), - SubnetPropertiesFormat: &network.SubnetPropertiesFormat{ - AddressPrefix: to.StringPtr("10.0.0.0/16"), - }, - }, - { - Name: to.StringPtr(""), - SubnetPropertiesFormat: &network.SubnetPropertiesFormat{ - AddressPrefix: to.StringPtr("10.1.0.0/16"), - }, - }, - }, - }, - }) -} -``` - -## Authentication - -Typical SDK operations must be authenticated and authorized. The _Authorizer_ -interface allows use of any auth style in requests, such as inserting an OAuth2 -Authorization header and bearer token received from Azure AD. - -The SDK itself provides a simple way to get an authorizer which first checks -for OAuth client credentials in environment variables and then falls back to -Azure's [Managed Service Identity]() when available, e.g. when on an Azure -VM. The following snippet from [the previous section](#use) demonstrates -this helper. - -```go -import github.com/Azure/go-autorest/autorest/azure/auth - -// create a VirtualNetworks client -vnetClient := network.NewVirtualNetworksClient("") - -// create an authorizer from env vars or Azure Managed Service Idenity -authorizer, err := auth.NewAuthorizerFromEnvironment() -if err == nil { - vnetClient.Authorizer = authorizer -} - -// call the VirtualNetworks CreateOrUpdate API -vnetClient.CreateOrUpdate(context.Background(), -// ... -``` - -The following environment variables help determine authentication configuration: - -- `AZURE_ENVIRONMENT`: Specifies the Azure Environment to use. If not set, it - defaults to `AzurePublicCloud`. Not applicable to authentication with Managed - Service Identity (MSI). -- `AZURE_AD_RESOURCE`: Specifies the AAD resource ID to use. If not set, it - defaults to `ResourceManagerEndpoint` for operations with Azure Resource - Manager. You can also choose an alternate resource programatically with - `auth.NewAuthorizerFromEnvironmentWithResource(resource string)`. - -### More Authentication Details - -The previous is the first and most recommended of several authentication -options offered by the SDK because it allows seamless use of both service -principals and [Azure Managed Service Identity][]. Other options are listed -below. - -> Note: If you need to create a new service principal, run `az ad sp create-for-rbac -n ""` in the -> [azure-cli](https://github.com/Azure/azure-cli). See [these -> docs](https://docs.microsoft.com/cli/azure/create-an-azure-service-principal-azure-cli?view=azure-cli-latest) -> for more info. Copy the new principal's ID, secret, and tenant ID for use in -> your app, or consider the `--sdk-auth` parameter for serialized output. - -[azure managed service identity]: https://docs.microsoft.com/en-us/azure/active-directory/msi-overview - -- The `auth.NewAuthorizerFromEnvironment()` described above creates an authorizer - from the first available of the following configuration: - - 1. **Client Credentials**: Azure AD Application ID and Secret. - - - `AZURE_TENANT_ID`: Specifies the Tenant to which to authenticate. - - `AZURE_CLIENT_ID`: Specifies the app client ID to use. - - `AZURE_CLIENT_SECRET`: Specifies the app secret to use. - - 2. **Client Certificate**: Azure AD Application ID and X.509 Certificate. - - - `AZURE_TENANT_ID`: Specifies the Tenant to which to authenticate. - - `AZURE_CLIENT_ID`: Specifies the app client ID to use. - - `AZURE_CERTIFICATE_PATH`: Specifies the certificate Path to use. - - `AZURE_CERTIFICATE_PASSWORD`: Specifies the certificate password to use. - - 3. **Resource Owner Password**: Azure AD User and Password. This grant type is *not - recommended*, use device login instead if you need interactive login. - - - `AZURE_TENANT_ID`: Specifies the Tenant to which to authenticate. - - `AZURE_CLIENT_ID`: Specifies the app client ID to use. - - `AZURE_USERNAME`: Specifies the username to use. - - `AZURE_PASSWORD`: Specifies the password to use. - - 4. **Azure Managed Service Identity**: Delegate credential management to the - platform. Requires that code is running in Azure, e.g. on a VM. All - configuration is handled by Azure. See [Azure Managed Service - Identity](https://docs.microsoft.com/en-us/azure/active-directory/msi-overview) - for more details. - -- The `auth.NewAuthorizerFromFile()` method creates an authorizer using - credentials from an auth file created by the [Azure CLI][]. Follow these - steps to utilize: - - 1. Create a service principal and output an auth file using `az ad sp create-for-rbac --sdk-auth > client_credentials.json`. - 2. Set environment variable `AZURE_AUTH_LOCATION` to the path of the saved - output file. - 3. Use the authorizer returned by `auth.NewAuthorizerFromFile()` in your - client as described above. - -- The `auth.NewAuthorizerFromCLI()` method creates an authorizer which - uses [Azure CLI][] to obtain its credentials. To use this method follow - these steps: - - 1. Install [Azure CLI v2.0.12](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) or later. Upgrade earlier versions. - 2. Use `az login` to sign in to Azure. - - If you receive an error, use `az account get-access-token` to verify access. - - If Azure CLI is not installed to the default directory, you may receive an error - reporting that `az` cannot be found. - Use the `AzureCLIPath` environment variable to define the Azure CLI installation folder. - - If you are signed in to Azure CLI using multiple accounts or your account has - access to multiple subscriptions, you need to specify the specific subscription - to be used. To do so, use: - - ``` - az account set --subscription - ``` - - To verify the current account settings, use: - - ``` - az account list - ``` - -[azure cli]: https://github.com/Azure/azure-cli - -- Finally, you can use OAuth's [Device Flow][] by calling - `auth.NewDeviceFlowConfig()` and extracting the Authorizer as follows: - - ```go - config := auth.NewDeviceFlowConfig(clientID, tenantID) - a, err = config.Authorizer() - ``` - -[device flow]: https://oauth.net/2/device-flow/ - -# Versioning - -azure-sdk-for-go provides at least a basic Go binding for every Azure API. To -provide maximum flexibility to users, the SDK even includes previous versions of -Azure APIs which are still in use. This enables us to support users of the -most updated Azure datacenters, regional datacenters with earlier APIs, and -even on-premises installations of Azure Stack. - -**SDK versions** apply globally and are tracked by git -[tags](https://github.com/Azure/azure-sdk-for-go/tags). These are in x.y.z form -and generally adhere to [semantic versioning](https://semver.org) specifications. - -**Service API versions** are generally represented by a date string and are -tracked by offering separate packages for each version. For example, to choose the -latest API versions for Compute and Network, use the following imports: - -```go -import ( - "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute" - "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2017-09-01/network" -) -``` - -Occasionally service-side changes require major changes to existing versions. -These cases are noted in the changelog, and for this reason `Service API versions` -cannot be used alone to ensure backwards compatibility. - -All available services and versions are listed under the `services/` path in -this repo and in [GoDoc][services_godoc]. Run `find ./services -type d -mindepth 3` to list all available service packages. - -[services_godoc]: https://godoc.org/github.com/Azure/azure-sdk-for-go/services - -### Profiles - -Azure **API profiles** specify subsets of Azure APIs and versions. Profiles can provide: - -- **stability** for your application by locking to specific API versions; and/or -- **compatibility** for your application with Azure Stack and regional Azure datacenters. - -In the Go SDK, profiles are available under the `profiles/` path and their -component API versions are aliases to the true service package under -`services/`. You can use them as follows: - -```go -import "github.com/Azure/azure-sdk-for-go/profiles/2017-03-09/compute/mgmt/compute" -import "github.com/Azure/azure-sdk-for-go/profiles/2017-03-09/network/mgmt/network" -import "github.com/Azure/azure-sdk-for-go/profiles/2017-03-09/storage/mgmt/storage" -``` - -The following profiles are available for hybrid Azure and Azure Stack environments. -- 2017-03-09 -- 2018-03-01 - -In addition to versioned profiles, we also provide two special profiles -`latest` and `preview`. The `latest` profile contains the latest API version -of each service, excluding any preview versions and/or content. The `preview` -profile is similar to the `latest` profile but includes preview API versions. - -The `latest` and `preview` profiles can help you stay up to date with API -updates as you build applications. Since they are by definition not stable, -however, they **should not** be used in production apps. Instead, choose the -latest specific API version (or an older one if necessary) from the `services/` -path. - -As an example, to automatically use the most recent Compute APIs, use one of -the following imports: - -```go -import "github.com/Azure/azure-sdk-for-go/profiles/latest/compute/mgmt/compute" -import "github.com/Azure/azure-sdk-for-go/profiles/preview/compute/mgmt/compute" -``` - -### Avoiding Breaking Changes - -To avoid breaking changes, when specifying imports you should specify a `Service API Version` or `Profile`, as well as lock (using [dep](https://github.com/golang/dep) and soon with [Go Modules](https://github.com/golang/go/wiki/Modules)) to a specific SDK version. - -For example, in your source code imports, use a `Service API Version` (`2017-12-01`): - -```go -import "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute" -``` - -or `Profile` version (`2017-03-09`): - -```go -import "github.com/Azure/azure-sdk-for-go/profiles/2017-03-09/compute/mgmt/compute" -``` - -As well as, for dep, a `Gopkg.toml` file with: - -```toml -[[constraint]] - name = "github.com/Azure/azure-sdk-for-go" - version = "21.0.0" -``` - -Combined, these techniques will ensure that breaking changes should not occur. If you are extra sensitive to changes, adding an additional [version pin](https://golang.github.io/dep/docs/Gopkg.toml.html#version-rules) in your SDK Version should satisfy your needs: - -```toml -[[constraint]] - name = "github.com/Azure/azure-sdk-for-go" - version = "=21.3.0" -``` - -## Inspecting and Debugging - -### Built-in Basic Request/Response Logging - -Starting with `go-autorest v10.15.0` you can enable basic logging of requests and responses through setting environment variables. -Setting `AZURE_GO_SDK_LOG_LEVEL` to `LogInfo` will log request/response without their bodies. To include the bodies set the log level to `LogDebug`. - -By default the logger writes to strerr, however it can also write to stdout or a file -if specified in `AZURE_GO_SDK_LOG_FILE`. Note that if the specified file already exists it will be truncated. - -**IMPORTANT:** by default the logger will redact the Authorization and Ocp-Apim-Subscription-Key -headers. Any other secrets will _not_ be redacted. - -### Writing Custom Request/Response Inspectors - -All clients implement some handy hooks to help inspect the underlying requests being made to Azure. - -- `RequestInspector`: View and manipulate the go `http.Request` before it's sent -- `ResponseInspector`: View the `http.Response` received - -Here is an example of how these can be used with `net/http/httputil` to see requests and responses. - -```go -vnetClient := network.NewVirtualNetworksClient("") -vnetClient.RequestInspector = LogRequest() -vnetClient.ResponseInspector = LogResponse() - -... - -func LogRequest() autorest.PrepareDecorator { - return func(p autorest.Preparer) autorest.Preparer { - return autorest.PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err != nil { - log.Println(err) - } - dump, _ := httputil.DumpRequestOut(r, true) - log.Println(string(dump)) - return r, err - }) - } -} - -func LogResponse() autorest.RespondDecorator { - return func(p autorest.Responder) autorest.Responder { - return autorest.ResponderFunc(func(r *http.Response) error { - err := p.Respond(r) - if err != nil { - log.Println(err) - } - dump, _ := httputil.DumpResponse(r, true) - log.Println(string(dump)) - return err - }) - } -} -``` - -## Tracing and Metrics - -All packages and the runtime are instrumented using [OpenCensus](https://opencensus.io/). - -### Enable - -As of now, tracing is disabled by default. There are 2 ways to enable tracing: - -- set the environment variable `AZURE_SDK_TRACING_ENABLED` (_Recommended_) -- alternatively, import the `github.com/Azure/go-autorest/tracing` package and call the `tracing.Enable()` function or `tracing.EnableWithAIForwarding()` if using the [App Insights Forwarder](https://docs.microsoft.com/en-us/azure/application-insights/opencensus-local-forwarder). - -**Note**: In future major releases of the SDK, tracing may become enabled by default. - -### Usage - -Once enabled, all SDK calls will emit traces and metrics and the traces will correlate the SDK calls with the raw http calls made to Azure API's. To consume those traces, if are not doing it yet, you need to register an exporter of your choice such as [Azure App Insights](https://docs.microsoft.com/en-us/azure/application-insights/opencensus-local-forwarder) or [Zipkin](https://opencensus.io/quickstart/go/tracing/#exporting-traces). - -To correlate the SDK calls between them and with the rest of your code, pass in a context that has a span initiated using the [opencensus-go library](https://github.com/census-instrumentation/opencensus-go) using the `trace.Startspan(ctx context.Context, name string, o ...StartOption)` function. Here is an example: - -```go -func doAzureCalls() { - // The resulting context will be initialized with a root span as the context passed to - // trace.StartSpan() has no existing span. - ctx, span := trace.StartSpan(context.Background(),"doAzureCalls", trace.WithSampler(trace.AlwaysSample())) - defer span.End() - - // The traces from the SDK calls will be correlated under the span inside the context that is passed in. - zone, _ := zonesClient.CreateOrUpdate(ctx, rg, zoneName, dns.Zone{Location: to.StringPtr("global")}, "", "") - zone, _ = zonesClient.Get(ctx, rg, *zone.Name) - for i := 0; i < rrCount; i++ { - rr, _ := recordsClient.CreateOrUpdate(ctx, rg, zoneName, fmt.Sprintf("rr%d", i), dns.CNAME, rdSet{ - RecordSetProperties: &dns.RecordSetProperties{ - TTL: to.Int64Ptr(3600), - CnameRecord: &dns.CnameRecord{ - Cname: to.StringPtr("vladdbCname"), - }, - }, - }, - "", - "", - ) - } -} -``` - -# Resources - -- SDK docs are at [godoc.org](https://godoc.org/github.com/Azure/azure-sdk-for-go/). -- SDK samples are at [Azure-Samples/azure-sdk-for-go-samples](https://github.com/Azure-Samples/azure-sdk-for-go-samples). -- SDK notifications are published via the [Azure update feed](https://azure.microsoft.com/updates/). -- Azure API docs are at [docs.microsoft.com/rest/api](https://docs.microsoft.com/rest/api/). -- General Azure docs are at [docs.microsoft.com/azure](https://docs.microsoft.com/azure). - -## License - -Apache 2.0, see [LICENSE](./LICENSE). - -## Contribute - -See [CONTRIBUTING.md](./CONTRIBUTING.md). - -[samples_repo]: https://github.com/Azure-Samples/azure-sdk-for-go-samples diff --git a/vendor/github.com/Azure/azure-sdk-for-go/doc.go b/vendor/github.com/Azure/azure-sdk-for-go/doc.go deleted file mode 100644 index 19cde56d..00000000 --- a/vendor/github.com/Azure/azure-sdk-for-go/doc.go +++ /dev/null @@ -1,26 +0,0 @@ -/* -Package sdk provides Go packages for managing and using Azure services. - -GitHub repo: https://github.com/Azure/azure-sdk-for-go - -Official documentation: https://docs.microsoft.com/go/azure - -API reference: https://godoc.org/github.com/Azure/azure-sdk-for-go - -Samples: https://github.com/Azure-Samples/azure-sdk-for-go-samples -*/ -package sdk - -// Copyright (c) Microsoft and contributors. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// -// See the License for the specific language governing permissions and -// limitations under the License. diff --git a/vendor/github.com/Azure/azure-sdk-for-go/findTestedPackages.sh b/vendor/github.com/Azure/azure-sdk-for-go/findTestedPackages.sh deleted file mode 100644 index 2319ed12..00000000 --- a/vendor/github.com/Azure/azure-sdk-for-go/findTestedPackages.sh +++ /dev/null @@ -1 +0,0 @@ -dirname $(find | grep _test.go | grep -v vendor) | sort -u \ No newline at end of file diff --git a/vendor/github.com/Azure/azure-sdk-for-go/rungas.sh b/vendor/github.com/Azure/azure-sdk-for-go/rungas.sh deleted file mode 100644 index 92e3d4df..00000000 --- a/vendor/github.com/Azure/azure-sdk-for-go/rungas.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash -GITBRANCH=`git rev-parse --abbrev-ref HEAD` -#We intend to only run gas on release branches. -if [ "master" != $GITBRANCH ]; then - exit 0 -fi -REALEXITSTATUS=0 -go get -u github.com/HewlettPackard/gas -gas -skip=*/arm/*/models.go -skip=*/management/examples/*.go -skip=*vendor* -skip=*/Gododir/* ./... | tee /dev/stderr -REALEXITSTATUS=$(($REALEXITSTATUS+$?)) -gas -exclude=G101 ./arm/... ./management/examples/... | tee /dev/stderr -REALEXITSTATUS=$(($REALEXITSTATUS+$?)) -gas -exclude=G204 ./Gododir/... | tee /dev/stderr -REALEXITSTATUS=$(($REALEXITSTATUS+$?)) -exit $REALEXITSTATUS \ No newline at end of file diff --git a/vendor/github.com/Azure/azure-sdk-for-go/swagger_to_sdk_config.json b/vendor/github.com/Azure/azure-sdk-for-go/swagger_to_sdk_config.json deleted file mode 100644 index 4852df4a..00000000 --- a/vendor/github.com/Azure/azure-sdk-for-go/swagger_to_sdk_config.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "meta": { - "after_scripts": [ - "dep ensure", - "go generate ./profiles/generate.go", - "gofmt -w ./profiles/", - "gofmt -w ./services/" - ], - "autorest_options": { - "use": "@microsoft.azure/autorest.go@~2.1.127", - "go": "", - "verbose": "", - "sdkrel:go-sdk-folder": ".", - "multiapi": "", - "use-onever": "", - "preview-chk": "" - }, - "repotag": "azure-sdk-for-go", - "envs": { - "sdkrel:GOPATH": "../../../.." - }, - "advanced_options": { - "clone_dir": "./src/github.com/Azure/azure-sdk-for-go" - }, - "version": "0.2.0" - } -} diff --git a/vendor/github.com/Azure/go-autorest/CHANGELOG.md b/vendor/github.com/Azure/go-autorest/CHANGELOG.md deleted file mode 100644 index 68dc6f39..00000000 --- a/vendor/github.com/Azure/go-autorest/CHANGELOG.md +++ /dev/null @@ -1,728 +0,0 @@ -# CHANGELOG - -## v11.3.0 - -### New Features - -- Added method `ServicePrincipalToken()` to `DeviceFlowConfig` type. - -## v11.2.8 - -### Bug Fixes - -- Deprecate content in the `version` package. The functionality has been superseded by content in the `autorest` package. - -## v11.2.7 - -### Bug Fixes - -- Fix environment variable name for enabling tracing from `AZURE_SDK_TRACING_ENABELD` to `AZURE_SDK_TRACING_ENABLED`. - Note that for backward compatibility reasons, both will work until the next major version release of the package. - -## v11.2.6 - -### Bug Fixes - -- If zero bytes are read from a polling response body don't attempt to unmarshal them. - -## v11.2.5 - -### Bug Fixes - -- Removed race condition in `autorest.DoRetryForStatusCodes`. - -## v11.2.4 - -### Bug Fixes - -- Function `cli.ProfilePath` now respects environment `AZURE_CONFIG_DIR` if available. - -## v11.2.1 - -NOTE: Versions of Go prior to 1.10 have been removed from CI as they no -longer work with golint. - -### Bug Fixes - -- Method `MSIConfig.Authorizer` now supports user-assigned identities. -- The adal package now reports its own user-agent string. - -## v11.2.0 - -### New Features - -- Added `tracing` package that enables instrumentation of HTTP and API calls. - Setting the env variable `AZURE_SDK_TRACING_ENABLED` or calling `tracing.Enable` - will start instrumenting the code for metrics and traces. - Additionally, setting the env variable `OCAGENT_TRACE_EXPORTER_ENDPOINT` or - calling `tracing.EnableWithAIForwarding` will start the instrumentation and connect to an - App Insights Local Forwarder that is needs to be running. Note that if the - AI Local Forwarder is not running tracking will still be enabled. - By default, instrumentation is disabled. Once enabled, instrumentation can also - be programatically disabled by calling `Disable`. -- Added `DoneWithContext` call for checking LRO status. `Done` has been deprecated. - -### Bug Fixes - -- Don't use the initial request's context for LRO polling. -- Don't override the `refreshLock` and the `http.Client` when unmarshalling `ServicePrincipalToken` if - it is already set. - -## v11.1.1 - -### Bug Fixes - -- When creating a future always include the polling tracker even if there's a failure; this allows the underlying response to be obtained by the caller. - -## v11.1.0 - -### New Features - -- Added `auth.NewAuthorizerFromCLI` to create an authorizer configured from the Azure 2.0 CLI. -- Added `adal.NewOAuthConfigWithAPIVersion` to create an OAuthConfig with the specified API version. - -## v11.0.1 - -### New Features - -- Added `x5c` header to client assertion for certificate Issuer+Subject Name authentication. - -## v11.0.0 - -### Breaking Changes - -- To handle differences between ADFS and AAD the following fields have had their types changed from `string` to `json.Number` - - ExpiresIn - - ExpiresOn - - NotBefore - -### New Features - -- Added `auth.NewAuthorizerFromFileWithResource` to create an authorizer from the config file with the specified resource. -- Setting a client's `PollingDuration` to zero will use the provided context to control a LRO's polling duration. - -## v10.15.5 - -### Bug Fixes - -- In `DoRetryForStatusCodes`, if a request's context is cancelled return the last response. - -## v10.15.4 - -### Bug Fixes - -- If a polling operation returns a failure status code return the associated error. - -## v10.15.3 - -### Bug Fixes - -- Initialize the polling URL and method for an LRO tracker on each iteration, favoring the Azure-AsyncOperation header. - -## v10.15.2 - -### Bug Fixes - -- Use fmt.Fprint when printing request/response so that any escape sequences aren't treated as format specifiers. - -## v10.15.1 - -### Bug Fixes - -- If an LRO API returns a `Failed` provisioning state in the initial response return an error at that point so the caller doesn't have to poll. -- For failed LROs without an OData v4 error include the response body in the error's `AdditionalInfo` field to aid in diagnosing the failure. - -## v10.15.0 - -### New Features - -- Add initial support for request/response logging via setting environment variables. - Setting `AZURE_GO_SDK_LOG_LEVEL` to `LogInfo` will log request/response - without their bodies. To include the bodies set the log level to `LogDebug`. - By default the logger writes to strerr, however it can also write to stdout or a file - if specified in `AZURE_GO_SDK_LOG_FILE`. Note that if the specified file - already exists it will be truncated. - IMPORTANT: by default the logger will redact the Authorization and Ocp-Apim-Subscription-Key - headers. Any other secrets will _not_ be redacted. - -## v10.14.0 - -### New Features - -- Added package version that contains version constants and user-agent data. - -### Bug Fixes - -- Add the user-agent to token requests. - -## v10.13.0 - -- Added support for additionalInfo in ServiceError type. - -## v10.12.0 - -### New Features - -- Added field ServicePrincipalToken.MaxMSIRefreshAttempts to configure the maximun number of attempts to refresh an MSI token. - -## v10.11.4 - -### Bug Fixes - -- If an LRO returns http.StatusOK on the initial response with no async headers return the response body from Future.GetResult(). -- If there is no "final GET URL" return an error from Future.GetResult(). - -## v10.11.3 - -### Bug Fixes - -- In IMDS retry logic, if we don't receive a response don't retry. - - Renamed the retry function so it's clear it's meant for IMDS only. -- For error response bodies that aren't OData-v4 compliant stick the raw JSON in the ServiceError.Details field so the information isn't lost. - - Also add the raw HTTP response to the DetailedResponse. -- Removed superfluous wrapping of response error in azure.DoRetryWithRegistration(). - -## v10.11.2 - -### Bug Fixes - -- Validation for integers handles int and int64 types. - -## v10.11.1 - -### Bug Fixes - -- Adding User information to authorization config as parsed from CLI cache. - -## v10.11.0 - -### New Features - -- Added NewServicePrincipalTokenFromManualTokenSecret for creating a new SPT using a manual token and secret -- Added method ServicePrincipalToken.MarshalTokenJSON() to marshall the inner Token - -## v10.10.0 - -### New Features - -- Most ServicePrincipalTokens can now be marshalled/unmarshall to/from JSON (ServicePrincipalCertificateSecret and ServicePrincipalMSISecret are not supported). -- Added method ServicePrincipalToken.SetRefreshCallbacks(). - -## v10.9.2 - -### Bug Fixes - -- Refreshing a refresh token obtained from a web app authorization code now works. - -## v10.9.1 - -### Bug Fixes - -- The retry logic for MSI token requests now uses exponential backoff per the guidelines. -- IsTemporaryNetworkError() will return true for errors that don't implement the net.Error interface. - -## v10.9.0 - -### Deprecated Methods - -| Old Method | New Method | -| -------------------------: | :---------------------------: | -| azure.NewFuture() | azure.NewFutureFromResponse() | -| Future.WaitForCompletion() | Future.WaitForCompletionRef() | - -### New Features - -- Added azure.NewFutureFromResponse() for creating a Future from the initial response from an async operation. -- Added Future.GetResult() for making the final GET call to retrieve the result from an async operation. - -### Bug Fixes - -- Some futures failed to return their results, this should now be fixed. - -## v10.8.2 - -### Bug Fixes - -- Add nil-gaurd to token retry logic. - -## v10.8.1 - -### Bug Fixes - -- Return a TokenRefreshError if the sender fails on the initial request. -- Don't retry on non-temporary network errors. - -## v10.8.0 - -- Added NewAuthorizerFromEnvironmentWithResource() helper function. - -## v10.7.0 - -### New Features - -- Added \*WithContext() methods to ADAL token refresh operations. - -## v10.6.2 - -- Fixed a bug on device authentication. - -## v10.6.1 - -- Added retries to MSI token get request. - -## v10.6.0 - -- Changed MSI token implementation. Now, the token endpoint is the IMDS endpoint. - -## v10.5.1 - -### Bug Fixes - -- `DeviceFlowConfig.Authorizer()` now prints the device code message when running `go test`. `-v` flag is required. - -## v10.5.0 - -### New Features - -- Added NewPollingRequestWithContext() for use with polling asynchronous operations. - -### Bug Fixes - -- Make retry logic use the request's context instead of the deprecated Cancel object. - -## v10.4.0 - -### New Features - -- Added helper for parsing Azure Resource ID's. -- Added deprecation message to utils.GetEnvVarOrExit() - -## v10.3.0 - -### New Features - -- Added EnvironmentFromURL method to load an Environment from a given URL. This function is particularly useful in the private and hybrid Cloud model, where one may define their own endpoints -- Added TokenAudience endpoint to Environment structure. This is useful in private and hybrid cloud models where TokenAudience endpoint can be different from ResourceManagerEndpoint - -## v10.2.0 - -### New Features - -- Added endpoints for batch management. - -## v10.1.3 - -### Bug Fixes - -- In Client.Do() invoke WithInspection() last so that it will inspect WithAuthorization(). -- Fixed authorization methods to invoke p.Prepare() first, aligning them with the other preparers. - -## v10.1.2 - -- Corrected comment for auth.NewAuthorizerFromFile() function. - -## v10.1.1 - -- Updated version number to match current release. - -## v10.1.0 - -### New Features - -- Expose the polling URL for futures. - -### Bug Fixes - -- Add validation.NewErrorWithValidationError back to prevent breaking changes (it is deprecated). - -## v10.0.0 - -### New Features - -- Added target and innererror fields to ServiceError to comply with OData v4 spec. -- The Done() method on futures will now return a ServiceError object when available (it used to return a partial value of such errors). -- Added helper methods for obtaining authorizers. -- Expose the polling URL for futures. - -### Bug Fixes - -- Switched from glide to dep for dependency management. -- Fixed unmarshaling of ServiceError for JSON bodies that don't conform to the OData spec. -- Fixed a race condition in token refresh. - -### Breaking Changes - -- The ServiceError.Details field type has been changed to match the OData v4 spec. -- Go v1.7 has been dropped from CI. -- API parameter validation failures will now return a unique error type validation.Error. -- The adal.Token type has been decomposed from adal.ServicePrincipalToken (this was necessary in order to fix the token refresh race). - -## v9.10.0 - -- Fix the Service Bus suffix in Azure public env -- Add Service Bus Endpoint (AAD ResourceURI) for use in [Azure Service Bus RBAC Preview](https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-role-based-access-control) - -## v9.9.0 - -### New Features - -- Added EventGridKeyAuthorizer for key authorization with event grid topics. - -### Bug Fixes - -- Fixed race condition when auto-refreshing service principal tokens. - -## v9.8.1 - -### Bug Fixes - -- Added http.StatusNoContent (204) to the list of expected status codes for long-running operations. -- Updated runtime version info so it's current. - -## v9.8.0 - -### New Features - -- Added type azure.AsyncOpIncompleteError to be returned from a future's Result() method when the operation has not completed. - -## v9.7.1 - -### Bug Fixes - -- Use correct AAD and Graph endpoints for US Gov environment. - -## v9.7.0 - -### New Features - -- Added support for application/octet-stream MIME types. - -## v9.6.1 - -### Bug Fixes - -- Ensure Authorization header is added to request when polling for registration status. - -## v9.6.0 - -### New Features - -- Added support for acquiring tokens via MSI with a user assigned identity. - -## v9.5.3 - -### Bug Fixes - -- Don't remove encoding of existing URL Query parameters when calling autorest.WithQueryParameters. -- Set correct Content Type when using autorest.WithFormData. - -## v9.5.2 - -### Bug Fixes - -- Check for nil \*http.Response before dereferencing it. - -## v9.5.1 - -### Bug Fixes - -- Don't count http.StatusTooManyRequests (429) against the retry cap. -- Use retry logic when SkipResourceProviderRegistration is set to true. - -## v9.5.0 - -### New Features - -- Added support for username + password, API key, authoriazation code and cognitive services authentication. -- Added field SkipResourceProviderRegistration to clients to provide a way to skip auto-registration of RPs. -- Added utility function AsStringSlice() to convert its parameters to a string slice. - -### Bug Fixes - -- When checking for authentication failures look at the error type not the status code as it could vary. - -## v9.4.2 - -### Bug Fixes - -- Validate parameters when creating credentials. -- Don't retry requests if the returned status is a 401 (http.StatusUnauthorized) as it will never succeed. - -## v9.4.1 - -### Bug Fixes - -- Update the AccessTokensPath() to read access tokens path through AZURE_ACCESS_TOKEN_FILE. If this - environment variable is not set, it will fall back to use default path set by Azure CLI. -- Use case-insensitive string comparison for polling states. - -## v9.4.0 - -### New Features - -- Added WaitForCompletion() to Future as a default polling implementation. - -### Bug Fixes - -- Method Future.Done() shouldn't update polling status for unexpected HTTP status codes. - -## v9.3.1 - -### Bug Fixes - -- DoRetryForStatusCodes will retry if sender.Do returns a non-nil error. - -## v9.3.0 - -### New Features - -- Added PollingMethod() to Future so callers know what kind of polling mechanism is used. -- Added azure.ChangeToGet() which transforms an http.Request into a GET (to be used with LROs). - -## v9.2.0 - -### New Features - -- Added support for custom Azure Stack endpoints. -- Added type azure.Future used to track the status of long-running operations. - -### Bug Fixes - -- Preserve the original error in DoRetryWithRegistration when registration fails. - -## v9.1.1 - -- Fixes a bug regarding the cookie jar on `autorest.Client.Sender`. - -## v9.1.0 - -### New Features - -- In cases where there is a non-empty error from the service, attempt to unmarshal it instead of uniformly calling it an "Unknown" error. -- Support for loading Azure CLI Authentication files. -- Automatically register your subscription with the Azure Resource Provider if it hadn't been previously. - -### Bug Fixes - -- RetriableRequest can now tolerate a ReadSeekable body being read but not reset. -- Adding missing Apache Headers - -## v9.0.0 - -> **IMPORTANT:** This release was intially labeled incorrectly as `v8.4.0`. From the time it was released, it should have been marked `v9.0.0` because it contains breaking changes to the MSI packages. We appologize for any inconvenience this causes. - -Adding MSI Endpoint Support and CLI token rehydration. - -## v8.3.1 - -Pick up bug fix in adal for MSI support. - -## v8.3.0 - -Updates to Error string formats for clarity. Also, adding a copy of the http.Response to errors for an improved debugging experience. - -## v8.2.0 - -### New Features - -- Add support for bearer authentication callbacks -- Support 429 response codes that include "Retry-After" header -- Support validation constraint "Pattern" for map keys - -### Bug Fixes - -- Make RetriableRequest work with multiple versions of Go - -## v8.1.1 - -Updates the RetriableRequest to take advantage of GetBody() added in Go 1.8. - -## v8.1.0 - -Adds RetriableRequest type for more efficient handling of retrying HTTP requests. - -## v8.0.0 - -ADAL refactored into its own package. -Support for UNIX time. - -## v7.3.1 - -- Version Testing now removed from production bits that are shipped with the library. - -## v7.3.0 - -- Exposing new `RespondDecorator`, `ByDiscardingBody`. This allows operations - to acknowledge that they do not need either the entire or a trailing portion - of accepts response body. In doing so, Go's http library can reuse HTTP - connections more readily. -- Adding `PrepareDecorator` to target custom BaseURLs. -- Adding ACR suffix to public cloud environment. -- Updating Glide dependencies. - -## v7.2.5 - -- Fixed the Active Directory endpoint for the China cloud. -- Removes UTF-8 BOM if present in response payload. -- Added telemetry. - -## v7.2.3 - -- Fixing bug in calls to `DelayForBackoff` that caused doubling of delay - duration. - -## v7.2.2 - -- autorest/azure: added ASM and ARM VM DNS suffixes. - -## v7.2.1 - -- fixed parsing of UTC times that are not RFC3339 conformant. - -## v7.2.0 - -- autorest/validation: Reformat validation error for better error message. - -## v7.1.0 - -- preparer: Added support for multipart formdata - WithMultiPartFormdata() -- preparer: Added support for sending file in request body - WithFile -- client: Added RetryDuration parameter. -- autorest/validation: new package for validation code for Azure Go SDK. - -## v7.0.7 - -- Add trailing / to endpoint -- azure: add EnvironmentFromName - -## v7.0.6 - -- Add retry logic for 408, 500, 502, 503 and 504 status codes. -- Change url path and query encoding logic. -- Fix DelayForBackoff for proper exponential delay. -- Add CookieJar in Client. - -## v7.0.5 - -- Add check to start polling only when status is in [200,201,202]. -- Refactoring for unchecked errors. -- azure/persist changes. -- Fix 'file in use' issue in renewing token in deviceflow. -- Store header RetryAfter for subsequent requests in polling. -- Add attribute details in service error. - -## v7.0.4 - -- Better error messages for long running operation failures - -## v7.0.3 - -- Corrected DoPollForAsynchronous to properly handle the initial response - -## v7.0.2 - -- Corrected DoPollForAsynchronous to continue using the polling method first discovered - -## v7.0.1 - -- Fixed empty JSON input error in ByUnmarshallingJSON -- Fixed polling support for GET calls -- Changed format name from TimeRfc1123 to TimeRFC1123 - -## v7.0.0 - -- Added ByCopying responder with supporting TeeReadCloser -- Rewrote Azure asynchronous handling -- Reverted to only unmarshalling JSON -- Corrected handling of RFC3339 time strings and added support for Rfc1123 time format - -The `json.Decoder` does not catch bad data as thoroughly as `json.Unmarshal`. Since -`encoding/json` successfully deserializes all core types, and extended types normally provide -their custom JSON serialization handlers, the code has been reverted back to using -`json.Unmarshal`. The original change to use `json.Decode` was made to reduce duplicate -code; there is no loss of function, and there is a gain in accuracy, by reverting. - -Additionally, Azure services indicate requests to be polled by multiple means. The existing code -only checked for one of those (that is, the presence of the `Azure-AsyncOperation` header). -The new code correctly covers all cases and aligns with the other Azure SDKs. - -## v6.1.0 - -- Introduced `date.ByUnmarshallingJSONDate` and `date.ByUnmarshallingJSONTime` to enable JSON encoded values. - -## v6.0.0 - -- Completely reworked the handling of polled and asynchronous requests -- Removed unnecessary routines -- Reworked `mocks.Sender` to replay a series of `http.Response` objects -- Added `PrepareDecorators` for primitive types (e.g., bool, int32) - -Handling polled and asynchronous requests is no longer part of `Client#Send`. Instead new -`SendDecorators` implement different styles of polled behavior. See`autorest.DoPollForStatusCodes` -and `azure.DoPollForAsynchronous` for examples. - -## v5.0.0 - -- Added new RespondDecorators unmarshalling primitive types -- Corrected application of inspection and authorization PrependDecorators - -## v4.0.0 - -- Added support for Azure long-running operations. -- Added cancelation support to all decorators and functions that may delay. -- Breaking: `DelayForBackoff` now accepts a channel, which may be nil. - -## v3.1.0 - -- Add support for OAuth Device Flow authorization. -- Add support for ServicePrincipalTokens that are backed by an existing token, rather than other secret material. -- Add helpers for persisting and restoring Tokens. -- Increased code coverage in the github.com/Azure/autorest/azure package - -## v3.0.0 - -- Breaking: `NewErrorWithError` no longer takes `statusCode int`. -- Breaking: `NewErrorWithStatusCode` is replaced with `NewErrorWithResponse`. -- Breaking: `Client#Send()` no longer takes `codes ...int` argument. -- Add: XML unmarshaling support with `ByUnmarshallingXML()` -- Stopped vending dependencies locally and switched to [Glide](https://github.com/Masterminds/glide). - Applications using this library should either use Glide or vendor dependencies locally some other way. -- Add: `azure.WithErrorUnlessStatusCode()` decorator to handle Azure errors. -- Fix: use `net/http.DefaultClient` as base client. -- Fix: Missing inspection for polling responses added. -- Add: CopyAndDecode helpers. -- Improved `./autorest/to` with `[]string` helpers. -- Removed golint suppressions in .travis.yml. - -## v2.1.0 - -- Added `StatusCode` to `Error` for more easily obtaining the HTTP Reponse StatusCode (if any) - -## v2.0.0 - -- Changed `to.StringMapPtr` method signature to return a pointer -- Changed `ServicePrincipalCertificateSecret` and `NewServicePrincipalTokenFromCertificate` to support generic certificate and private keys - -## v1.0.0 - -- Added Logging inspectors to trace http.Request / Response -- Added support for User-Agent header -- Changed WithHeader PrepareDecorator to use set vs. add -- Added JSON to error when unmarshalling fails -- Added Client#Send method -- Corrected case of "Azure" in package paths -- Added "to" helpers, Azure helpers, and improved ease-of-use -- Corrected golint issues - -## v1.0.1 - -- Added CHANGELOG.md - -## v1.1.0 - -- Added mechanism to retrieve a ServicePrincipalToken using a certificate-signed JWT -- Added an example of creating a certificate-based ServicePrincipal and retrieving an OAuth token using the certificate - -## v1.1.1 - -- Introduce godeps and vendor dependencies introduced in v1.1.1 diff --git a/vendor/github.com/Azure/go-autorest/GNUmakefile b/vendor/github.com/Azure/go-autorest/GNUmakefile deleted file mode 100644 index a434e73a..00000000 --- a/vendor/github.com/Azure/go-autorest/GNUmakefile +++ /dev/null @@ -1,23 +0,0 @@ -DIR?=./autorest/ - -default: build - -build: fmt - go install $(DIR) - -test: - go test $(DIR) || exit 1 - -vet: - @echo "go vet ." - @go vet $(DIR)... ; if [ $$? -eq 1 ]; then \ - echo ""; \ - echo "Vet found suspicious constructs. Please check the reported constructs"; \ - echo "and fix them if necessary before submitting the code for review."; \ - exit 1; \ - fi - -fmt: - gofmt -w $(DIR) - -.PHONY: build test vet fmt diff --git a/vendor/github.com/Azure/go-autorest/Gopkg.lock b/vendor/github.com/Azure/go-autorest/Gopkg.lock deleted file mode 100644 index 8513320a..00000000 --- a/vendor/github.com/Azure/go-autorest/Gopkg.lock +++ /dev/null @@ -1,247 +0,0 @@ -# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. - - -[[projects]] - digest = "1:e1b859e3d9e90007d5fbf25edf57733b224f1857f6592636130afab3af8cfae7" - name = "contrib.go.opencensus.io/exporter/ocagent" - packages = ["."] - pruneopts = "" - revision = "00af367e65149ff1f2f4b93bbfbb84fd9297170d" - version = "v0.2.0" - -[[projects]] - digest = "1:e0a4505d5cf7ac6b5d92e3aee79d838b5f1ae8e9641ec7fa5d1e9b01d7a7ea95" - name = "github.com/census-instrumentation/opencensus-proto" - packages = [ - "gen-go/agent/common/v1", - "gen-go/agent/trace/v1", - "gen-go/trace/v1", - ] - pruneopts = "" - revision = "24333298e36590ea0716598caacc8959fc393c48" - version = "v0.0.2" - -[[projects]] - digest = "1:0deddd908b6b4b768cfc272c16ee61e7088a60f7fe2f06c547bd3d8e1f8b8e77" - name = "github.com/davecgh/go-spew" - packages = ["spew"] - pruneopts = "" - revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73" - version = "v1.1.1" - -[[projects]] - digest = "1:6098222470fe0172157ce9bbef5d2200df4edde17ee649c5d6e48330e4afa4c6" - name = "github.com/dgrijalva/jwt-go" - packages = ["."] - pruneopts = "" - revision = "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e" - version = "v3.2.0" - -[[projects]] - digest = "1:7f175a633086a933d1940a7e7dc2154a0070a7c25fb4a2f671f3eef1a34d1fd7" - name = "github.com/dimchansky/utfbom" - packages = ["."] - pruneopts = "" - revision = "5448fe645cb1964ba70ac8f9f2ffe975e61a536c" - version = "v1.0.0" - -[[projects]] - digest = "1:3dd078fda7500c341bc26cfbc6c6a34614f295a2457149fc1045cab767cbcf18" - name = "github.com/golang/protobuf" - packages = [ - "proto", - "ptypes", - "ptypes/any", - "ptypes/duration", - "ptypes/timestamp", - "ptypes/wrappers", - ] - pruneopts = "" - revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5" - version = "v1.2.0" - -[[projects]] - digest = "1:096a8a9182648da3d00ff243b88407838902b6703fc12657f76890e08d1899bf" - name = "github.com/mitchellh/go-homedir" - packages = ["."] - pruneopts = "" - revision = "ae18d6b8b3205b561c79e8e5f69bff09736185f4" - version = "v1.0.0" - -[[projects]] - digest = "1:256484dbbcd271f9ecebc6795b2df8cad4c458dd0f5fd82a8c2fa0c29f233411" - name = "github.com/pmezard/go-difflib" - packages = ["difflib"] - pruneopts = "" - revision = "792786c7400a136282c1664665ae0a8db921c6c2" - version = "v1.0.0" - -[[projects]] - digest = "1:c587772fb8ad29ad4db67575dad25ba17a51f072ff18a22b4f0257a4d9c24f75" - name = "github.com/stretchr/testify" - packages = [ - "assert", - "require", - ] - pruneopts = "" - revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686" - version = "v1.2.2" - -[[projects]] - digest = "1:ad67dfd3799a2c58f6c65871dd141d8b53f61f600aec48ce8d7fa16a4d5476f8" - name = "go.opencensus.io" - packages = [ - ".", - "exemplar", - "internal", - "internal/tagencoding", - "plugin/ochttp", - "plugin/ochttp/propagation/b3", - "plugin/ochttp/propagation/tracecontext", - "stats", - "stats/internal", - "stats/view", - "tag", - "trace", - "trace/internal", - "trace/propagation", - "trace/tracestate", - ] - pruneopts = "" - revision = "b7bf3cdb64150a8c8c53b769fdeb2ba581bd4d4b" - version = "v0.18.0" - -[[projects]] - branch = "master" - digest = "1:78f41d38365ccef743e54ed854a2faf73313ba0750c621116a8eeb0395590bd0" - name = "golang.org/x/crypto" - packages = [ - "pkcs12", - "pkcs12/internal/rc2", - ] - pruneopts = "" - revision = "0c41d7ab0a0ee717d4590a44bcb987dfd9e183eb" - -[[projects]] - branch = "master" - digest = "1:547dcb6aebfb7fb17947660ebb034470c13f4d63d893def190a2f7ba3d09bc38" - name = "golang.org/x/net" - packages = [ - "context", - "http/httpguts", - "http2", - "http2/hpack", - "idna", - "internal/timeseries", - "trace", - ] - pruneopts = "" - revision = "49bb7cea24b1df9410e1712aa6433dae904ff66a" - -[[projects]] - branch = "master" - digest = "1:b2ea75de0ccb2db2ac79356407f8a4cd8f798fe15d41b381c00abf3ae8e55ed1" - name = "golang.org/x/sync" - packages = ["semaphore"] - pruneopts = "" - revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca" - -[[projects]] - branch = "master" - digest = "1:2ed0bf267e44950120acd95570227e28184573ffb099bd85b529ee148e004ddb" - name = "golang.org/x/sys" - packages = ["unix"] - pruneopts = "" - revision = "fa43e7bc11baaae89f3f902b2b4d832b68234844" - -[[projects]] - digest = "1:5acd3512b047305d49e8763eef7ba423901e85d5dd2fd1e71778a0ea8de10bd4" - name = "golang.org/x/text" - packages = [ - "collate", - "collate/build", - "internal/colltab", - "internal/gen", - "internal/tag", - "internal/triegen", - "internal/ucd", - "language", - "secure/bidirule", - "transform", - "unicode/bidi", - "unicode/cldr", - "unicode/norm", - "unicode/rangetable", - ] - pruneopts = "" - revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" - version = "v0.3.0" - -[[projects]] - branch = "master" - digest = "1:ca2e72555afbcebdead7c961b135650b5111dbbaf37a874de63976fdda57f129" - name = "google.golang.org/api" - packages = ["support/bundler"] - pruneopts = "" - revision = "c51f30376ab7ec4f22b65de846a41593c8b70f07" - -[[projects]] - branch = "master" - digest = "1:1b3b4ec811695907c4a3cb92e4f32834a4a42459bff7e02068b6b2b5344803cd" - name = "google.golang.org/genproto" - packages = ["googleapis/rpc/status"] - pruneopts = "" - revision = "af9cb2a35e7f169ec875002c1829c9b315cddc04" - -[[projects]] - digest = "1:15656947b87a6a240e61dcfae9e71a55a8d5677f240d12ab48f02cdbabf1e309" - name = "google.golang.org/grpc" - packages = [ - ".", - "balancer", - "balancer/base", - "balancer/roundrobin", - "codes", - "connectivity", - "credentials", - "encoding", - "encoding/proto", - "grpclog", - "internal", - "internal/backoff", - "internal/channelz", - "internal/envconfig", - "internal/grpcrand", - "internal/transport", - "keepalive", - "metadata", - "naming", - "peer", - "resolver", - "resolver/dns", - "resolver/passthrough", - "stats", - "status", - "tap", - ] - pruneopts = "" - revision = "8dea3dc473e90c8179e519d91302d0597c0ca1d1" - version = "v1.15.0" - -[solve-meta] - analyzer-name = "dep" - analyzer-version = 1 - input-imports = [ - "contrib.go.opencensus.io/exporter/ocagent", - "github.com/dgrijalva/jwt-go", - "github.com/dimchansky/utfbom", - "github.com/mitchellh/go-homedir", - "github.com/stretchr/testify/require", - "go.opencensus.io/plugin/ochttp", - "go.opencensus.io/plugin/ochttp/propagation/tracecontext", - "go.opencensus.io/stats/view", - "go.opencensus.io/trace", - "golang.org/x/crypto/pkcs12", - ] - solver-name = "gps-cdcl" - solver-version = 1 diff --git a/vendor/github.com/Azure/go-autorest/Gopkg.toml b/vendor/github.com/Azure/go-autorest/Gopkg.toml deleted file mode 100644 index e4040c89..00000000 --- a/vendor/github.com/Azure/go-autorest/Gopkg.toml +++ /dev/null @@ -1,45 +0,0 @@ -# Gopkg.toml example -# -# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md -# for detailed Gopkg.toml documentation. -# -# required = ["github.com/user/thing/cmd/thing"] -# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] -# -# [[constraint]] -# name = "github.com/user/project" -# version = "1.0.0" -# -# [[constraint]] -# name = "github.com/user/project2" -# branch = "dev" -# source = "github.com/myfork/project2" -# -# [[override]] -# name = "github.com/x/y" -# version = "2.4.0" - - -[[constraint]] - name = "github.com/dgrijalva/jwt-go" - version = "3.1.0" - -[[constraint]] - name = "github.com/dimchansky/utfbom" - version = "1.0.0" - -[[constraint]] - name = "github.com/mitchellh/go-homedir" - version = "1.0.0" - -[[constraint]] - name = "github.com/stretchr/testify" - version = "1.2.0" - -[[constraint]] - name = "go.opencensus.io" - version = "0.18.0" - -[[constraint]] - name = "contrib.go.opencensus.io/exporter/ocagent" - version = "0.2.0" diff --git a/vendor/github.com/Azure/go-autorest/README.md b/vendor/github.com/Azure/go-autorest/README.md deleted file mode 100644 index 9a7b13a3..00000000 --- a/vendor/github.com/Azure/go-autorest/README.md +++ /dev/null @@ -1,149 +0,0 @@ -# go-autorest - -[![GoDoc](https://godoc.org/github.com/Azure/go-autorest/autorest?status.png)](https://godoc.org/github.com/Azure/go-autorest/autorest) -[![Build Status](https://travis-ci.org/Azure/go-autorest.svg?branch=master)](https://travis-ci.org/Azure/go-autorest) -[![Go Report Card](https://goreportcard.com/badge/Azure/go-autorest)](https://goreportcard.com/report/Azure/go-autorest) - -Package go-autorest provides an HTTP request client for use with [Autorest](https://github.com/Azure/autorest.go)-generated API client packages. - -An authentication client tested with Azure Active Directory (AAD) is also -provided in this repo in the package -`github.com/Azure/go-autorest/autorest/adal`. Despite its name, this package -is maintained only as part of the Azure Go SDK and is not related to other -"ADAL" libraries in [github.com/AzureAD](https://github.com/AzureAD). - -## Overview - -Package go-autorest implements an HTTP request pipeline suitable for use across -multiple goroutines and provides the shared routines used by packages generated -by [Autorest](https://github.com/Azure/autorest.go). - -The package breaks sending and responding to HTTP requests into three phases: Preparing, Sending, -and Responding. A typical pattern is: - -```go - req, err := Prepare(&http.Request{}, - token.WithAuthorization()) - - resp, err := Send(req, - WithLogging(logger), - DoErrorIfStatusCode(http.StatusInternalServerError), - DoCloseIfError(), - DoRetryForAttempts(5, time.Second)) - - err = Respond(resp, - ByDiscardingBody(), - ByClosing()) -``` - -Each phase relies on decorators to modify and / or manage processing. Decorators may first modify -and then pass the data along, pass the data first and then modify the result, or wrap themselves -around passing the data (such as a logger might do). Decorators run in the order provided. For -example, the following: - -```go - req, err := Prepare(&http.Request{}, - WithBaseURL("https://microsoft.com/"), - WithPath("a"), - WithPath("b"), - WithPath("c")) -``` - -will set the URL to: - -``` - https://microsoft.com/a/b/c -``` - -Preparers and Responders may be shared and re-used (assuming the underlying decorators support -sharing and re-use). Performant use is obtained by creating one or more Preparers and Responders -shared among multiple go-routines, and a single Sender shared among multiple sending go-routines, -all bound together by means of input / output channels. - -Decorators hold their passed state within a closure (such as the path components in the example -above). Be careful to share Preparers and Responders only in a context where such held state -applies. For example, it may not make sense to share a Preparer that applies a query string from a -fixed set of values. Similarly, sharing a Responder that reads the response body into a passed -struct (e.g., `ByUnmarshallingJson`) is likely incorrect. - -Errors raised by autorest objects and methods will conform to the `autorest.Error` interface. - -See the included examples for more detail. For details on the suggested use of this package by -generated clients, see the Client described below. - -## Helpers - -### Handling Swagger Dates - -The Swagger specification (https://swagger.io) that drives AutoRest -(https://github.com/Azure/autorest/) precisely defines two date forms: date and date-time. The -github.com/Azure/go-autorest/autorest/date package provides time.Time derivations to ensure correct -parsing and formatting. - -### Handling Empty Values - -In JSON, missing values have different semantics than empty values. This is especially true for -services using the HTTP PATCH verb. The JSON submitted with a PATCH request generally contains -only those values to modify. Missing values are to be left unchanged. Developers, then, require a -means to both specify an empty value and to leave the value out of the submitted JSON. - -The Go JSON package (`encoding/json`) supports the `omitempty` tag. When specified, it omits -empty values from the rendered JSON. Since Go defines default values for all base types (such as "" -for string and 0 for int) and provides no means to mark a value as actually empty, the JSON package -treats default values as meaning empty, omitting them from the rendered JSON. This means that, using -the Go base types encoded through the default JSON package, it is not possible to create JSON to -clear a value at the server. - -The workaround within the Go community is to use pointers to base types in lieu of base types within -structures that map to JSON. For example, instead of a value of type `string`, the workaround uses -`*string`. While this enables distinguishing empty values from those to be unchanged, creating -pointers to a base type (notably constant, in-line values) requires additional variables. This, for -example, - -```go - s := struct { - S *string - }{ S: &"foo" } -``` -fails, while, this - -```go - v := "foo" - s := struct { - S *string - }{ S: &v } -``` -succeeds. - -To ease using pointers, the subpackage `to` contains helpers that convert to and from pointers for -Go base types which have Swagger analogs. It also provides a helper that converts between -`map[string]string` and `map[string]*string`, enabling the JSON to specify that the value -associated with a key should be cleared. With the helpers, the previous example becomes - -```go - s := struct { - S *string - }{ S: to.StringPtr("foo") } -``` - -## Install - -```bash -go get github.com/Azure/go-autorest/autorest -go get github.com/Azure/go-autorest/autorest/azure -go get github.com/Azure/go-autorest/autorest/date -go get github.com/Azure/go-autorest/autorest/to -``` - -## License - -See LICENSE file. - ------ - -This project has adopted the [Microsoft Open Source Code of -Conduct](https://opensource.microsoft.com/codeofconduct/). For more information -see the [Code of Conduct -FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact -[opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional -questions or comments. diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/README.md b/vendor/github.com/Azure/go-autorest/autorest/adal/README.md deleted file mode 100644 index 7b0c4bc4..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/adal/README.md +++ /dev/null @@ -1,292 +0,0 @@ -# Azure Active Directory authentication for Go - -This is a standalone package for authenticating with Azure Active -Directory from other Go libraries and applications, in particular the [Azure SDK -for Go](https://github.com/Azure/azure-sdk-for-go). - -Note: Despite the package's name it is not related to other "ADAL" libraries -maintained in the [github.com/AzureAD](https://github.com/AzureAD) org. Issues -should be opened in [this repo's](https://github.com/Azure/go-autorest/issues) -or [the SDK's](https://github.com/Azure/azure-sdk-for-go/issues) issue -trackers. - -## Install - -```bash -go get -u github.com/Azure/go-autorest/autorest/adal -``` - -## Usage - -An Active Directory application is required in order to use this library. An application can be registered in the [Azure Portal](https://portal.azure.com/) by following these [guidelines](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-integrating-applications) or using the [Azure CLI](https://github.com/Azure/azure-cli). - -### Register an Azure AD Application with secret - - -1. Register a new application with a `secret` credential - - ``` - az ad app create \ - --display-name example-app \ - --homepage https://example-app/home \ - --identifier-uris https://example-app/app \ - --password secret - ``` - -2. Create a service principal using the `Application ID` from previous step - - ``` - az ad sp create --id "Application ID" - ``` - - * Replace `Application ID` with `appId` from step 1. - -### Register an Azure AD Application with certificate - -1. Create a private key - - ``` - openssl genrsa -out "example-app.key" 2048 - ``` - -2. Create the certificate - - ``` - openssl req -new -key "example-app.key" -subj "/CN=example-app" -out "example-app.csr" - openssl x509 -req -in "example-app.csr" -signkey "example-app.key" -out "example-app.crt" -days 10000 - ``` - -3. Create the PKCS12 version of the certificate containing also the private key - - ``` - openssl pkcs12 -export -out "example-app.pfx" -inkey "example-app.key" -in "example-app.crt" -passout pass: - - ``` - -4. Register a new application with the certificate content form `example-app.crt` - - ``` - certificateContents="$(tail -n+2 "example-app.crt" | head -n-1)" - - az ad app create \ - --display-name example-app \ - --homepage https://example-app/home \ - --identifier-uris https://example-app/app \ - --key-usage Verify --end-date 2018-01-01 \ - --key-value "${certificateContents}" - ``` - -5. Create a service principal using the `Application ID` from previous step - - ``` - az ad sp create --id "APPLICATION_ID" - ``` - - * Replace `APPLICATION_ID` with `appId` from step 4. - - -### Grant the necessary permissions - -Azure relies on a Role-Based Access Control (RBAC) model to manage the access to resources at a fine-grained -level. There is a set of [pre-defined roles](https://docs.microsoft.com/en-us/azure/active-directory/role-based-access-built-in-roles) -which can be assigned to a service principal of an Azure AD application depending of your needs. - -``` -az role assignment create --assigner "SERVICE_PRINCIPAL_ID" --role "ROLE_NAME" -``` - -* Replace the `SERVICE_PRINCIPAL_ID` with the `appId` from previous step. -* Replace the `ROLE_NAME` with a role name of your choice. - -It is also possible to define custom role definitions. - -``` -az role definition create --role-definition role-definition.json -``` - -* Check [custom roles](https://docs.microsoft.com/en-us/azure/active-directory/role-based-access-control-custom-roles) for more details regarding the content of `role-definition.json` file. - - -### Acquire Access Token - -The common configuration used by all flows: - -```Go -const activeDirectoryEndpoint = "https://login.microsoftonline.com/" -tenantID := "TENANT_ID" -oauthConfig, err := adal.NewOAuthConfig(activeDirectoryEndpoint, tenantID) - -applicationID := "APPLICATION_ID" - -callback := func(token adal.Token) error { - // This is called after the token is acquired -} - -// The resource for which the token is acquired -resource := "https://management.core.windows.net/" -``` - -* Replace the `TENANT_ID` with your tenant ID. -* Replace the `APPLICATION_ID` with the value from previous section. - -#### Client Credentials - -```Go -applicationSecret := "APPLICATION_SECRET" - -spt, err := adal.NewServicePrincipalToken( - oauthConfig, - appliationID, - applicationSecret, - resource, - callbacks...) -if err != nil { - return nil, err -} - -// Acquire a new access token -err = spt.Refresh() -if (err == nil) { - token := spt.Token -} -``` - -* Replace the `APPLICATION_SECRET` with the `password` value from previous section. - -#### Client Certificate - -```Go -certificatePath := "./example-app.pfx" - -certData, err := ioutil.ReadFile(certificatePath) -if err != nil { - return nil, fmt.Errorf("failed to read the certificate file (%s): %v", certificatePath, err) -} - -// Get the certificate and private key from pfx file -certificate, rsaPrivateKey, err := decodePkcs12(certData, "") -if err != nil { - return nil, fmt.Errorf("failed to decode pkcs12 certificate while creating spt: %v", err) -} - -spt, err := adal.NewServicePrincipalTokenFromCertificate( - oauthConfig, - applicationID, - certificate, - rsaPrivateKey, - resource, - callbacks...) - -// Acquire a new access token -err = spt.Refresh() -if (err == nil) { - token := spt.Token -} -``` - -* Update the certificate path to point to the example-app.pfx file which was created in previous section. - - -#### Device Code - -```Go -oauthClient := &http.Client{} - -// Acquire the device code -deviceCode, err := adal.InitiateDeviceAuth( - oauthClient, - oauthConfig, - applicationID, - resource) -if err != nil { - return nil, fmt.Errorf("Failed to start device auth flow: %s", err) -} - -// Display the authentication message -fmt.Println(*deviceCode.Message) - -// Wait here until the user is authenticated -token, err := adal.WaitForUserCompletion(oauthClient, deviceCode) -if err != nil { - return nil, fmt.Errorf("Failed to finish device auth flow: %s", err) -} - -spt, err := adal.NewServicePrincipalTokenFromManualToken( - oauthConfig, - applicationID, - resource, - *token, - callbacks...) - -if (err == nil) { - token := spt.Token -} -``` - -#### Username password authenticate - -```Go -spt, err := adal.NewServicePrincipalTokenFromUsernamePassword( - oauthConfig, - applicationID, - username, - password, - resource, - callbacks...) - -if (err == nil) { - token := spt.Token -} -``` - -#### Authorization code authenticate - -``` Go -spt, err := adal.NewServicePrincipalTokenFromAuthorizationCode( - oauthConfig, - applicationID, - clientSecret, - authorizationCode, - redirectURI, - resource, - callbacks...) - -err = spt.Refresh() -if (err == nil) { - token := spt.Token -} -``` - -### Command Line Tool - -A command line tool is available in `cmd/adal.go` that can acquire a token for a given resource. It supports all flows mentioned above. - -``` -adal -h - -Usage of ./adal: - -applicationId string - application id - -certificatePath string - path to pk12/PFC application certificate - -mode string - authentication mode (device, secret, cert, refresh) (default "device") - -resource string - resource for which the token is requested - -secret string - application secret - -tenantId string - tenant id - -tokenCachePath string - location of oath token cache (default "/home/cgc/.adal/accessToken.json") -``` - -Example acquire a token for `https://management.core.windows.net/` using device code flow: - -``` -adal -mode device \ - -applicationId "APPLICATION_ID" \ - -tenantId "TENANT_ID" \ - -resource https://management.core.windows.net/ - -``` diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/config_test.go b/vendor/github.com/Azure/go-autorest/autorest/adal/config_test.go deleted file mode 100644 index aad0b5a1..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/adal/config_test.go +++ /dev/null @@ -1,95 +0,0 @@ -package adal - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "testing" -) - -func TestNewOAuthConfig(t *testing.T) { - const testActiveDirectoryEndpoint = "https://login.test.com" - const testTenantID = "tenant-id-test" - - config, err := NewOAuthConfig(testActiveDirectoryEndpoint, testTenantID) - if err != nil { - t.Fatalf("autorest/adal: Unexpected error while creating oauth configuration for tenant: %v.", err) - } - - expected := "https://login.test.com/tenant-id-test/oauth2/authorize?api-version=1.0" - if config.AuthorizeEndpoint.String() != expected { - t.Fatalf("autorest/adal: Incorrect authorize url for Tenant from Environment. expected(%s). actual(%v).", expected, config.AuthorizeEndpoint) - } - - expected = "https://login.test.com/tenant-id-test/oauth2/token?api-version=1.0" - if config.TokenEndpoint.String() != expected { - t.Fatalf("autorest/adal: Incorrect authorize url for Tenant from Environment. expected(%s). actual(%v).", expected, config.TokenEndpoint) - } - - expected = "https://login.test.com/tenant-id-test/oauth2/devicecode?api-version=1.0" - if config.DeviceCodeEndpoint.String() != expected { - t.Fatalf("autorest/adal Incorrect devicecode url for Tenant from Environment. expected(%s). actual(%v).", expected, config.DeviceCodeEndpoint) - } -} - -func TestNewOAuthConfigWithAPIVersionNil(t *testing.T) { - const testActiveDirectoryEndpoint = "https://login.test.com" - const testTenantID = "tenant-id-test" - - config, err := NewOAuthConfigWithAPIVersion(testActiveDirectoryEndpoint, testTenantID, nil) - if err != nil { - t.Fatalf("autorest/adal: Unexpected error while creating oauth configuration for tenant: %v.", err) - } - - expected := "https://login.test.com/tenant-id-test/oauth2/authorize" - if config.AuthorizeEndpoint.String() != expected { - t.Fatalf("autorest/adal: Incorrect authorize url for Tenant from Environment. expected(%s). actual(%v).", expected, config.AuthorizeEndpoint) - } - - expected = "https://login.test.com/tenant-id-test/oauth2/token" - if config.TokenEndpoint.String() != expected { - t.Fatalf("autorest/adal: Incorrect authorize url for Tenant from Environment. expected(%s). actual(%v).", expected, config.TokenEndpoint) - } - - expected = "https://login.test.com/tenant-id-test/oauth2/devicecode" - if config.DeviceCodeEndpoint.String() != expected { - t.Fatalf("autorest/adal Incorrect devicecode url for Tenant from Environment. expected(%s). actual(%v).", expected, config.DeviceCodeEndpoint) - } -} - -func TestNewOAuthConfigWithAPIVersionNotNil(t *testing.T) { - const testActiveDirectoryEndpoint = "https://login.test.com" - const testTenantID = "tenant-id-test" - apiVersion := "2.0" - - config, err := NewOAuthConfigWithAPIVersion(testActiveDirectoryEndpoint, testTenantID, &apiVersion) - if err != nil { - t.Fatalf("autorest/adal: Unexpected error while creating oauth configuration for tenant: %v.", err) - } - - expected := "https://login.test.com/tenant-id-test/oauth2/authorize?api-version=2.0" - if config.AuthorizeEndpoint.String() != expected { - t.Fatalf("autorest/adal: Incorrect authorize url for Tenant from Environment. expected(%s). actual(%v).", expected, config.AuthorizeEndpoint) - } - - expected = "https://login.test.com/tenant-id-test/oauth2/token?api-version=2.0" - if config.TokenEndpoint.String() != expected { - t.Fatalf("autorest/adal: Incorrect authorize url for Tenant from Environment. expected(%s). actual(%v).", expected, config.TokenEndpoint) - } - - expected = "https://login.test.com/tenant-id-test/oauth2/devicecode?api-version=2.0" - if config.DeviceCodeEndpoint.String() != expected { - t.Fatalf("autorest/adal Incorrect devicecode url for Tenant from Environment. expected(%s). actual(%v).", expected, config.DeviceCodeEndpoint) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/devicetoken_test.go b/vendor/github.com/Azure/go-autorest/autorest/adal/devicetoken_test.go deleted file mode 100644 index 6beee161..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/adal/devicetoken_test.go +++ /dev/null @@ -1,330 +0,0 @@ -package adal - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "encoding/json" - "fmt" - "net/http" - "strings" - "testing" - - "github.com/Azure/go-autorest/autorest/mocks" -) - -const ( - TestResource = "SomeResource" - TestClientID = "SomeClientID" - TestTenantID = "SomeTenantID" - TestActiveDirectoryEndpoint = "https://login.test.com/" -) - -var ( - testOAuthConfig, _ = NewOAuthConfig(TestActiveDirectoryEndpoint, TestTenantID) - TestOAuthConfig = *testOAuthConfig -) - -const MockDeviceCodeResponse = ` -{ - "device_code": "10000-40-1234567890", - "user_code": "ABCDEF", - "verification_url": "http://aka.ms/deviceauth", - "expires_in": "900", - "interval": "0" -} -` - -const MockDeviceTokenResponse = `{ - "access_token": "accessToken", - "refresh_token": "refreshToken", - "expires_in": "1000", - "expires_on": "2000", - "not_before": "3000", - "resource": "resource", - "token_type": "type" -} -` - -func TestDeviceCodeIncludesResource(t *testing.T) { - sender := mocks.NewSender() - sender.AppendResponse(mocks.NewResponseWithContent(MockDeviceCodeResponse)) - - code, err := InitiateDeviceAuth(sender, TestOAuthConfig, TestClientID, TestResource) - if err != nil { - t.Fatalf("adal: unexpected error initiating device auth") - } - - if code.Resource != TestResource { - t.Fatalf("adal: InitiateDeviceAuth failed to stash the resource in the DeviceCode struct") - } -} - -func TestDeviceCodeReturnsErrorIfSendingFails(t *testing.T) { - sender := mocks.NewSender() - sender.SetError(fmt.Errorf("this is an error")) - - _, err := InitiateDeviceAuth(sender, TestOAuthConfig, TestClientID, TestResource) - if err == nil || !strings.Contains(err.Error(), errCodeSendingFails) { - t.Fatalf("adal: failed to get correct error expected(%s) actual(%s)", errCodeSendingFails, err.Error()) - } -} - -func TestDeviceCodeReturnsErrorIfBadRequest(t *testing.T) { - sender := mocks.NewSender() - body := mocks.NewBody("doesn't matter") - sender.AppendResponse(mocks.NewResponseWithBodyAndStatus(body, http.StatusBadRequest, "Bad Request")) - - _, err := InitiateDeviceAuth(sender, TestOAuthConfig, TestClientID, TestResource) - if err == nil || !strings.Contains(err.Error(), errCodeHandlingFails) { - t.Fatalf("adal: failed to get correct error expected(%s) actual(%s)", errCodeHandlingFails, err.Error()) - } - - if body.IsOpen() { - t.Fatalf("response body was left open!") - } -} - -func TestDeviceCodeReturnsErrorIfCannotDeserializeDeviceCode(t *testing.T) { - gibberishJSON := strings.Replace(MockDeviceCodeResponse, "expires_in", "\":, :gibberish", -1) - sender := mocks.NewSender() - body := mocks.NewBody(gibberishJSON) - sender.AppendResponse(mocks.NewResponseWithBodyAndStatus(body, http.StatusOK, "OK")) - - _, err := InitiateDeviceAuth(sender, TestOAuthConfig, TestClientID, TestResource) - if err == nil || !strings.Contains(err.Error(), errCodeHandlingFails) { - t.Fatalf("adal: failed to get correct error expected(%s) actual(%s)", errCodeHandlingFails, err.Error()) - } - - if body.IsOpen() { - t.Fatalf("response body was left open!") - } -} - -func TestDeviceCodeReturnsErrorIfEmptyDeviceCode(t *testing.T) { - sender := mocks.NewSender() - body := mocks.NewBody("") - sender.AppendResponse(mocks.NewResponseWithBodyAndStatus(body, http.StatusOK, "OK")) - - _, err := InitiateDeviceAuth(sender, TestOAuthConfig, TestClientID, TestResource) - if err != ErrDeviceCodeEmpty { - t.Fatalf("adal: failed to get correct error expected(%s) actual(%s)", ErrDeviceCodeEmpty, err.Error()) - } - - if body.IsOpen() { - t.Fatalf("response body was left open!") - } -} - -func deviceCode() *DeviceCode { - var deviceCode DeviceCode - _ = json.Unmarshal([]byte(MockDeviceCodeResponse), &deviceCode) - deviceCode.Resource = TestResource - deviceCode.ClientID = TestClientID - return &deviceCode -} - -func TestDeviceTokenReturns(t *testing.T) { - sender := mocks.NewSender() - body := mocks.NewBody(MockDeviceTokenResponse) - sender.AppendResponse(mocks.NewResponseWithBodyAndStatus(body, http.StatusOK, "OK")) - - _, err := WaitForUserCompletion(sender, deviceCode()) - if err != nil { - t.Fatalf("adal: got error unexpectedly") - } - - if body.IsOpen() { - t.Fatalf("response body was left open!") - } -} - -func TestDeviceTokenReturnsErrorIfSendingFails(t *testing.T) { - sender := mocks.NewSender() - sender.SetError(fmt.Errorf("this is an error")) - - _, err := WaitForUserCompletion(sender, deviceCode()) - if err == nil || !strings.Contains(err.Error(), errTokenSendingFails) { - t.Fatalf("adal: failed to get correct error expected(%s) actual(%s)", errTokenSendingFails, err.Error()) - } -} - -func TestDeviceTokenReturnsErrorIfServerError(t *testing.T) { - sender := mocks.NewSender() - body := mocks.NewBody("") - sender.AppendResponse(mocks.NewResponseWithBodyAndStatus(body, http.StatusInternalServerError, "Internal Server Error")) - - _, err := WaitForUserCompletion(sender, deviceCode()) - if err == nil || !strings.Contains(err.Error(), errTokenHandlingFails) { - t.Fatalf("adal: failed to get correct error expected(%s) actual(%s)", errTokenHandlingFails, err.Error()) - } - - if body.IsOpen() { - t.Fatalf("response body was left open!") - } -} - -func TestDeviceTokenReturnsErrorIfCannotDeserializeDeviceToken(t *testing.T) { - gibberishJSON := strings.Replace(MockDeviceTokenResponse, "expires_in", ";:\"gibberish", -1) - sender := mocks.NewSender() - body := mocks.NewBody(gibberishJSON) - sender.AppendResponse(mocks.NewResponseWithBodyAndStatus(body, http.StatusOK, "OK")) - - _, err := WaitForUserCompletion(sender, deviceCode()) - if err == nil || !strings.Contains(err.Error(), errTokenHandlingFails) { - t.Fatalf("adal: failed to get correct error expected(%s) actual(%s)", errTokenHandlingFails, err.Error()) - } - - if body.IsOpen() { - t.Fatalf("response body was left open!") - } -} - -func errorDeviceTokenResponse(message string) string { - return `{ "error": "` + message + `" }` -} - -func TestDeviceTokenReturnsErrorIfAuthorizationPending(t *testing.T) { - sender := mocks.NewSender() - body := mocks.NewBody(errorDeviceTokenResponse("authorization_pending")) - sender.AppendResponse(mocks.NewResponseWithBodyAndStatus(body, http.StatusBadRequest, "Bad Request")) - - _, err := CheckForUserCompletion(sender, deviceCode()) - if err != ErrDeviceAuthorizationPending { - t.Fatalf("!!!") - } - - if body.IsOpen() { - t.Fatalf("response body was left open!") - } -} - -func TestDeviceTokenReturnsErrorIfSlowDown(t *testing.T) { - sender := mocks.NewSender() - body := mocks.NewBody(errorDeviceTokenResponse("slow_down")) - sender.AppendResponse(mocks.NewResponseWithBodyAndStatus(body, http.StatusBadRequest, "Bad Request")) - - _, err := CheckForUserCompletion(sender, deviceCode()) - if err != ErrDeviceSlowDown { - t.Fatalf("!!!") - } - - if body.IsOpen() { - t.Fatalf("response body was left open!") - } -} - -type deviceTokenSender struct { - errorString string - attempts int -} - -func newDeviceTokenSender(deviceErrorString string) *deviceTokenSender { - return &deviceTokenSender{errorString: deviceErrorString, attempts: 0} -} - -func (s *deviceTokenSender) Do(req *http.Request) (*http.Response, error) { - var resp *http.Response - if s.attempts < 1 { - s.attempts++ - resp = mocks.NewResponseWithContent(errorDeviceTokenResponse(s.errorString)) - } else { - resp = mocks.NewResponseWithContent(MockDeviceTokenResponse) - } - return resp, nil -} - -// since the above only exercise CheckForUserCompletion, we repeat the test here, -// but with the intent of showing that WaitForUserCompletion loops properly. -func TestDeviceTokenSucceedsWithIntermediateAuthPending(t *testing.T) { - sender := newDeviceTokenSender("authorization_pending") - - _, err := WaitForUserCompletion(sender, deviceCode()) - if err != nil { - t.Fatalf("unexpected error occurred") - } -} - -// same as above but with SlowDown now -func TestDeviceTokenSucceedsWithIntermediateSlowDown(t *testing.T) { - sender := newDeviceTokenSender("slow_down") - - _, err := WaitForUserCompletion(sender, deviceCode()) - if err != nil { - t.Fatalf("unexpected error occurred") - } -} - -func TestDeviceTokenReturnsErrorIfAccessDenied(t *testing.T) { - sender := mocks.NewSender() - body := mocks.NewBody(errorDeviceTokenResponse("access_denied")) - sender.AppendResponse(mocks.NewResponseWithBodyAndStatus(body, http.StatusBadRequest, "Bad Request")) - - _, err := WaitForUserCompletion(sender, deviceCode()) - if err != ErrDeviceAccessDenied { - t.Fatalf("adal: got wrong error expected(%s) actual(%s)", ErrDeviceAccessDenied.Error(), err.Error()) - } - - if body.IsOpen() { - t.Fatalf("response body was left open!") - } -} - -func TestDeviceTokenReturnsErrorIfCodeExpired(t *testing.T) { - sender := mocks.NewSender() - body := mocks.NewBody(errorDeviceTokenResponse("code_expired")) - sender.AppendResponse(mocks.NewResponseWithBodyAndStatus(body, http.StatusBadRequest, "Bad Request")) - - _, err := WaitForUserCompletion(sender, deviceCode()) - if err != ErrDeviceCodeExpired { - t.Fatalf("adal: got wrong error expected(%s) actual(%s)", ErrDeviceCodeExpired.Error(), err.Error()) - } - - if body.IsOpen() { - t.Fatalf("response body was left open!") - } -} - -func TestDeviceTokenReturnsErrorForUnknownError(t *testing.T) { - sender := mocks.NewSender() - body := mocks.NewBody(errorDeviceTokenResponse("unknown_error")) - sender.AppendResponse(mocks.NewResponseWithBodyAndStatus(body, http.StatusBadRequest, "Bad Request")) - - _, err := WaitForUserCompletion(sender, deviceCode()) - if err == nil { - t.Fatalf("failed to get error") - } - if err != ErrDeviceGeneric { - t.Fatalf("adal: got wrong error expected(%s) actual(%s)", ErrDeviceGeneric.Error(), err.Error()) - } - - if body.IsOpen() { - t.Fatalf("response body was left open!") - } -} - -func TestDeviceTokenReturnsErrorIfTokenEmptyAndStatusOK(t *testing.T) { - sender := mocks.NewSender() - body := mocks.NewBody("") - sender.AppendResponse(mocks.NewResponseWithBodyAndStatus(body, http.StatusOK, "OK")) - - _, err := WaitForUserCompletion(sender, deviceCode()) - if err != ErrOAuthTokenEmpty { - t.Fatalf("adal: got wrong error expected(%s) actual(%s)", ErrOAuthTokenEmpty.Error(), err.Error()) - } - - if body.IsOpen() { - t.Fatalf("response body was left open!") - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/persist_test.go b/vendor/github.com/Azure/go-autorest/autorest/adal/persist_test.go deleted file mode 100644 index a9c287c6..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/adal/persist_test.go +++ /dev/null @@ -1,171 +0,0 @@ -package adal - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "encoding/json" - "io/ioutil" - "os" - "path" - "reflect" - "runtime" - "strings" - "testing" -) - -const MockTokenJSON string = `{ - "access_token": "accessToken", - "refresh_token": "refreshToken", - "expires_in": "1000", - "expires_on": "2000", - "not_before": "3000", - "resource": "resource", - "token_type": "type" -}` - -var TestToken = Token{ - AccessToken: "accessToken", - RefreshToken: "refreshToken", - ExpiresIn: "1000", - ExpiresOn: "2000", - NotBefore: "3000", - Resource: "resource", - Type: "type", -} - -func writeTestTokenFile(t *testing.T, suffix string, contents string) *os.File { - f, err := ioutil.TempFile(os.TempDir(), suffix) - if err != nil { - t.Fatalf("azure: unexpected error when creating temp file: %v", err) - } - defer f.Close() - - _, err = f.Write([]byte(contents)) - if err != nil { - t.Fatalf("azure: unexpected error when writing temp test file: %v", err) - } - - return f -} - -func TestLoadToken(t *testing.T) { - f := writeTestTokenFile(t, "testloadtoken", MockTokenJSON) - defer os.Remove(f.Name()) - - expectedToken := TestToken - actualToken, err := LoadToken(f.Name()) - if err != nil { - t.Fatalf("azure: unexpected error loading token from file: %v", err) - } - - if *actualToken != expectedToken { - t.Fatalf("azure: failed to decode properly expected(%v) actual(%v)", expectedToken, *actualToken) - } - - // test that LoadToken closes the file properly - err = SaveToken(f.Name(), 0600, *actualToken) - if err != nil { - t.Fatalf("azure: could not save token after LoadToken: %v", err) - } -} - -func TestLoadTokenFailsBadPath(t *testing.T) { - _, err := LoadToken("/tmp/this_file_should_never_exist_really") - expectedSubstring := "failed to open file" - if err == nil || !strings.Contains(err.Error(), expectedSubstring) { - t.Fatalf("azure: failed to get correct error expected(%s) actual(%s)", expectedSubstring, err.Error()) - } -} - -func TestLoadTokenFailsBadJson(t *testing.T) { - gibberishJSON := strings.Replace(MockTokenJSON, "expires_on", ";:\"gibberish", -1) - f := writeTestTokenFile(t, "testloadtokenfailsbadjson", gibberishJSON) - defer os.Remove(f.Name()) - - _, err := LoadToken(f.Name()) - expectedSubstring := "failed to decode contents of file" - if err == nil || !strings.Contains(err.Error(), expectedSubstring) { - t.Fatalf("azure: failed to get correct error expected(%s) actual(%s)", expectedSubstring, err.Error()) - } -} - -func token() *Token { - var token Token - json.Unmarshal([]byte(MockTokenJSON), &token) - return &token -} - -func TestSaveToken(t *testing.T) { - f, err := ioutil.TempFile("", "testloadtoken") - if err != nil { - t.Fatalf("azure: unexpected error when creating temp file: %v", err) - } - defer os.Remove(f.Name()) - f.Close() - - mode := os.ModePerm & 0642 - err = SaveToken(f.Name(), mode, *token()) - if err != nil { - t.Fatalf("azure: unexpected error saving token to file: %v", err) - } - fi, err := os.Stat(f.Name()) // open a new stat as held ones are not fresh - if err != nil { - t.Fatalf("azure: stat failed: %v", err) - } - if runtime.GOOS != "windows" { // permissions don't work on Windows - if perm := fi.Mode().Perm(); perm != mode { - t.Fatalf("azure: wrong file perm. got:%s; expected:%s file :%s", perm, mode, f.Name()) - } - } - - var actualToken Token - var expectedToken Token - - json.Unmarshal([]byte(MockTokenJSON), expectedToken) - - contents, err := ioutil.ReadFile(f.Name()) - if err != nil { - t.Fatal("!!") - } - json.Unmarshal(contents, actualToken) - - if !reflect.DeepEqual(actualToken, expectedToken) { - t.Fatal("azure: token was not serialized correctly") - } -} - -func TestSaveTokenFailsNoPermission(t *testing.T) { - pathWhereWeShouldntHavePermission := "/usr/thiswontwork/atall" - if runtime.GOOS == "windows" { - pathWhereWeShouldntHavePermission = path.Join(os.Getenv("windir"), "system32\\mytokendir\\mytoken") - } - err := SaveToken(pathWhereWeShouldntHavePermission, 0644, *token()) - expectedSubstring := "failed to create directory" - if err == nil || !strings.Contains(err.Error(), expectedSubstring) { - t.Fatalf("azure: failed to get correct error expected(%s) actual(%v)", expectedSubstring, err) - } -} - -func TestSaveTokenFailsCantCreate(t *testing.T) { - tokenPath := "/thiswontwork" - if runtime.GOOS == "windows" { - tokenPath = path.Join(os.Getenv("windir"), "system32") - } - err := SaveToken(tokenPath, 0644, *token()) - expectedSubstring := "failed to create the temp file to write the token" - if err == nil || !strings.Contains(err.Error(), expectedSubstring) { - t.Fatalf("azure: failed to get correct error expected(%s) actual(%v)", expectedSubstring, err) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/token_test.go b/vendor/github.com/Azure/go-autorest/autorest/adal/token_test.go deleted file mode 100644 index 9f4f1fa4..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/adal/token_test.go +++ /dev/null @@ -1,929 +0,0 @@ -package adal - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "context" - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "crypto/x509/pkix" - "encoding/json" - "fmt" - "io/ioutil" - "math/big" - "net/http" - "net/url" - "reflect" - "strconv" - "strings" - "sync" - "testing" - "time" - - "github.com/Azure/go-autorest/autorest/date" - "github.com/Azure/go-autorest/autorest/mocks" - jwt "github.com/dgrijalva/jwt-go" -) - -const ( - defaultFormData = "client_id=id&client_secret=secret&grant_type=client_credentials&resource=resource" - defaultManualFormData = "client_id=id&grant_type=refresh_token&refresh_token=refreshtoken&resource=resource" -) - -func TestTokenExpires(t *testing.T) { - tt := time.Now().Add(5 * time.Second) - tk := newTokenExpiresAt(tt) - - if tk.Expires().Equal(tt) { - t.Fatalf("adal: Token#Expires miscalculated expiration time -- received %v, expected %v", tk.Expires(), tt) - } -} - -func TestTokenIsExpired(t *testing.T) { - tk := newTokenExpiresAt(time.Now().Add(-5 * time.Second)) - - if !tk.IsExpired() { - t.Fatalf("adal: Token#IsExpired failed to mark a stale token as expired -- now %v, token expires at %v", - time.Now().UTC(), tk.Expires()) - } -} - -func TestTokenIsExpiredUninitialized(t *testing.T) { - tk := &Token{} - - if !tk.IsExpired() { - t.Fatalf("adal: An uninitialized Token failed to mark itself as expired (expiration time %v)", tk.Expires()) - } -} - -func TestTokenIsNoExpired(t *testing.T) { - tk := newTokenExpiresAt(time.Now().Add(1000 * time.Second)) - - if tk.IsExpired() { - t.Fatalf("adal: Token marked a fresh token as expired -- now %v, token expires at %v", time.Now().UTC(), tk.Expires()) - } -} - -func TestTokenWillExpireIn(t *testing.T) { - d := 5 * time.Second - tk := newTokenExpiresIn(d) - - if !tk.WillExpireIn(d) { - t.Fatal("adal: Token#WillExpireIn mismeasured expiration time") - } -} - -func TestServicePrincipalTokenSetAutoRefresh(t *testing.T) { - spt := newServicePrincipalToken() - - if !spt.inner.AutoRefresh { - t.Fatal("adal: ServicePrincipalToken did not default to automatic token refreshing") - } - - spt.SetAutoRefresh(false) - if spt.inner.AutoRefresh { - t.Fatal("adal: ServicePrincipalToken#SetAutoRefresh did not disable automatic token refreshing") - } -} - -func TestServicePrincipalTokenSetRefreshWithin(t *testing.T) { - spt := newServicePrincipalToken() - - if spt.inner.RefreshWithin != defaultRefresh { - t.Fatal("adal: ServicePrincipalToken did not correctly set the default refresh interval") - } - - spt.SetRefreshWithin(2 * defaultRefresh) - if spt.inner.RefreshWithin != 2*defaultRefresh { - t.Fatal("adal: ServicePrincipalToken#SetRefreshWithin did not set the refresh interval") - } -} - -func TestServicePrincipalTokenSetSender(t *testing.T) { - spt := newServicePrincipalToken() - - c := &http.Client{} - spt.SetSender(c) - if !reflect.DeepEqual(c, spt.sender) { - t.Fatal("adal: ServicePrincipalToken#SetSender did not set the sender") - } -} - -func TestServicePrincipalTokenRefreshUsesPOST(t *testing.T) { - spt := newServicePrincipalToken() - - body := mocks.NewBody(newTokenJSON("test", "test")) - resp := mocks.NewResponseWithBodyAndStatus(body, http.StatusOK, "OK") - - c := mocks.NewSender() - s := DecorateSender(c, - (func() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - if r.Method != "POST" { - t.Fatalf("adal: ServicePrincipalToken#Refresh did not correctly set HTTP method -- expected %v, received %v", "POST", r.Method) - } - return resp, nil - }) - } - })()) - spt.SetSender(s) - err := spt.Refresh() - if err != nil { - t.Fatalf("adal: ServicePrincipalToken#Refresh returned an unexpected error (%v)", err) - } - - if body.IsOpen() { - t.Fatalf("the response was not closed!") - } -} - -func TestServicePrincipalTokenFromMSIRefreshUsesGET(t *testing.T) { - resource := "https://resource" - cb := func(token Token) error { return nil } - - spt, err := NewServicePrincipalTokenFromMSI("http://msiendpoint/", resource, cb) - if err != nil { - t.Fatalf("Failed to get MSI SPT: %v", err) - } - - body := mocks.NewBody(newTokenJSON("test", "test")) - resp := mocks.NewResponseWithBodyAndStatus(body, http.StatusOK, "OK") - - c := mocks.NewSender() - s := DecorateSender(c, - (func() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - if r.Method != "GET" { - t.Fatalf("adal: ServicePrincipalToken#Refresh did not correctly set HTTP method -- expected %v, received %v", "GET", r.Method) - } - if h := r.Header.Get("Metadata"); h != "true" { - t.Fatalf("adal: ServicePrincipalToken#Refresh did not correctly set Metadata header for MSI") - } - return resp, nil - }) - } - })()) - spt.SetSender(s) - err = spt.Refresh() - if err != nil { - t.Fatalf("adal: ServicePrincipalToken#Refresh returned an unexpected error (%v)", err) - } - - if body.IsOpen() { - t.Fatalf("the response was not closed!") - } -} - -func TestServicePrincipalTokenFromMSIRefreshCancel(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - endpoint, _ := GetMSIVMEndpoint() - - spt, err := NewServicePrincipalTokenFromMSI(endpoint, "https://resource") - if err != nil { - t.Fatalf("Failed to get MSI SPT: %v", err) - } - - c := mocks.NewSender() - c.AppendAndRepeatResponse(mocks.NewResponseWithStatus("Internal server error", http.StatusInternalServerError), 5) - - var wg sync.WaitGroup - wg.Add(1) - start := time.Now() - end := time.Now() - - go func() { - spt.SetSender(c) - err = spt.RefreshWithContext(ctx) - end = time.Now() - wg.Done() - }() - - cancel() - wg.Wait() - time.Sleep(5 * time.Millisecond) - - if end.Sub(start) >= time.Second { - t.Fatalf("TestServicePrincipalTokenFromMSIRefreshCancel failed to cancel") - } -} - -func TestServicePrincipalTokenRefreshSetsMimeType(t *testing.T) { - spt := newServicePrincipalToken() - - body := mocks.NewBody(newTokenJSON("test", "test")) - resp := mocks.NewResponseWithBodyAndStatus(body, http.StatusOK, "OK") - - c := mocks.NewSender() - s := DecorateSender(c, - (func() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - if r.Header.Get(http.CanonicalHeaderKey("Content-Type")) != "application/x-www-form-urlencoded" { - t.Fatalf("adal: ServicePrincipalToken#Refresh did not correctly set Content-Type -- expected %v, received %v", - "application/x-form-urlencoded", - r.Header.Get(http.CanonicalHeaderKey("Content-Type"))) - } - return resp, nil - }) - } - })()) - spt.SetSender(s) - err := spt.Refresh() - if err != nil { - t.Fatalf("adal: ServicePrincipalToken#Refresh returned an unexpected error (%v)", err) - } -} - -func TestServicePrincipalTokenRefreshSetsURL(t *testing.T) { - spt := newServicePrincipalToken() - - body := mocks.NewBody(newTokenJSON("test", "test")) - resp := mocks.NewResponseWithBodyAndStatus(body, http.StatusOK, "OK") - - c := mocks.NewSender() - s := DecorateSender(c, - (func() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - if r.URL.String() != TestOAuthConfig.TokenEndpoint.String() { - t.Fatalf("adal: ServicePrincipalToken#Refresh did not correctly set the URL -- expected %v, received %v", - TestOAuthConfig.TokenEndpoint, r.URL) - } - return resp, nil - }) - } - })()) - spt.SetSender(s) - err := spt.Refresh() - if err != nil { - t.Fatalf("adal: ServicePrincipalToken#Refresh returned an unexpected error (%v)", err) - } -} - -func testServicePrincipalTokenRefreshSetsBody(t *testing.T, spt *ServicePrincipalToken, f func(*testing.T, []byte)) { - body := mocks.NewBody(newTokenJSON("test", "test")) - resp := mocks.NewResponseWithBodyAndStatus(body, http.StatusOK, "OK") - - c := mocks.NewSender() - s := DecorateSender(c, - (func() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - b, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatalf("adal: Failed to read body of Service Principal token request (%v)", err) - } - f(t, b) - return resp, nil - }) - } - })()) - spt.SetSender(s) - err := spt.Refresh() - if err != nil { - t.Fatalf("adal: ServicePrincipalToken#Refresh returned an unexpected error (%v)", err) - } -} - -func TestServicePrincipalTokenManualRefreshSetsBody(t *testing.T) { - sptManual := newServicePrincipalTokenManual() - testServicePrincipalTokenRefreshSetsBody(t, sptManual, func(t *testing.T, b []byte) { - if string(b) != defaultManualFormData { - t.Fatalf("adal: ServicePrincipalToken#Refresh did not correctly set the HTTP Request Body -- expected %v, received %v", - defaultManualFormData, string(b)) - } - }) -} - -func TestServicePrincipalTokenCertficateRefreshSetsBody(t *testing.T) { - sptCert := newServicePrincipalTokenCertificate(t) - testServicePrincipalTokenRefreshSetsBody(t, sptCert, func(t *testing.T, b []byte) { - body := string(b) - - values, _ := url.ParseQuery(body) - if values["client_assertion_type"][0] != "urn:ietf:params:oauth:client-assertion-type:jwt-bearer" || - values["client_id"][0] != "id" || - values["grant_type"][0] != "client_credentials" || - values["resource"][0] != "resource" { - t.Fatalf("adal: ServicePrincipalTokenCertificate#Refresh did not correctly set the HTTP Request Body.") - } - - tok, _ := jwt.Parse(values["client_assertion"][0], nil) - if tok == nil { - t.Fatalf("adal: ServicePrincipalTokenCertificate#Expected client_assertion to be a JWT") - } - if _, ok := tok.Header["x5t"]; !ok { - t.Fatalf("adal: ServicePrincipalTokenCertificate#Expected client_assertion to have an x5t header") - } - if _, ok := tok.Header["x5c"]; !ok { - t.Fatalf("adal: ServicePrincipalTokenCertificate#Expected client_assertion to have an x5c header") - } - }) -} - -func TestServicePrincipalTokenUsernamePasswordRefreshSetsBody(t *testing.T) { - spt := newServicePrincipalTokenUsernamePassword(t) - testServicePrincipalTokenRefreshSetsBody(t, spt, func(t *testing.T, b []byte) { - body := string(b) - - values, _ := url.ParseQuery(body) - if values["client_id"][0] != "id" || - values["grant_type"][0] != "password" || - values["username"][0] != "username" || - values["password"][0] != "password" || - values["resource"][0] != "resource" { - t.Fatalf("adal: ServicePrincipalTokenUsernamePassword#Refresh did not correctly set the HTTP Request Body.") - } - }) -} - -func TestServicePrincipalTokenAuthorizationCodeRefreshSetsBody(t *testing.T) { - spt := newServicePrincipalTokenAuthorizationCode(t) - testServicePrincipalTokenRefreshSetsBody(t, spt, func(t *testing.T, b []byte) { - body := string(b) - - values, _ := url.ParseQuery(body) - if values["client_id"][0] != "id" || - values["grant_type"][0] != OAuthGrantTypeAuthorizationCode || - values["code"][0] != "code" || - values["client_secret"][0] != "clientSecret" || - values["redirect_uri"][0] != "http://redirectUri/getToken" || - values["resource"][0] != "resource" { - t.Fatalf("adal: ServicePrincipalTokenAuthorizationCode#Refresh did not correctly set the HTTP Request Body.") - } - }) - testServicePrincipalTokenRefreshSetsBody(t, spt, func(t *testing.T, b []byte) { - body := string(b) - - values, _ := url.ParseQuery(body) - if values["client_id"][0] != "id" || - values["grant_type"][0] != OAuthGrantTypeRefreshToken || - values["code"][0] != "code" || - values["client_secret"][0] != "clientSecret" || - values["redirect_uri"][0] != "http://redirectUri/getToken" || - values["resource"][0] != "resource" { - t.Fatalf("adal: ServicePrincipalTokenAuthorizationCode#Refresh did not correctly set the HTTP Request Body.") - } - }) -} - -func TestServicePrincipalTokenSecretRefreshSetsBody(t *testing.T) { - spt := newServicePrincipalToken() - testServicePrincipalTokenRefreshSetsBody(t, spt, func(t *testing.T, b []byte) { - if string(b) != defaultFormData { - t.Fatalf("adal: ServicePrincipalToken#Refresh did not correctly set the HTTP Request Body -- expected %v, received %v", - defaultFormData, string(b)) - } - - }) -} - -func TestServicePrincipalTokenRefreshClosesRequestBody(t *testing.T) { - spt := newServicePrincipalToken() - - body := mocks.NewBody(newTokenJSON("test", "test")) - resp := mocks.NewResponseWithBodyAndStatus(body, http.StatusOK, "OK") - - c := mocks.NewSender() - s := DecorateSender(c, - (func() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - return resp, nil - }) - } - })()) - spt.SetSender(s) - err := spt.Refresh() - if err != nil { - t.Fatalf("adal: ServicePrincipalToken#Refresh returned an unexpected error (%v)", err) - } - if resp.Body.(*mocks.Body).IsOpen() { - t.Fatal("adal: ServicePrincipalToken#Refresh failed to close the HTTP Response Body") - } -} - -func TestServicePrincipalTokenRefreshRejectsResponsesWithStatusNotOK(t *testing.T) { - spt := newServicePrincipalToken() - - body := mocks.NewBody(newTokenJSON("test", "test")) - resp := mocks.NewResponseWithBodyAndStatus(body, http.StatusUnauthorized, "Unauthorized") - - c := mocks.NewSender() - s := DecorateSender(c, - (func() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - return resp, nil - }) - } - })()) - spt.SetSender(s) - err := spt.Refresh() - if err == nil { - t.Fatalf("adal: ServicePrincipalToken#Refresh should reject a response with status != %d", http.StatusOK) - } -} - -func TestServicePrincipalTokenRefreshRejectsEmptyBody(t *testing.T) { - spt := newServicePrincipalToken() - - c := mocks.NewSender() - s := DecorateSender(c, - (func() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - return mocks.NewResponse(), nil - }) - } - })()) - spt.SetSender(s) - err := spt.Refresh() - if err == nil { - t.Fatal("adal: ServicePrincipalToken#Refresh should reject an empty token") - } -} - -func TestServicePrincipalTokenRefreshPropagatesErrors(t *testing.T) { - spt := newServicePrincipalToken() - - c := mocks.NewSender() - c.SetError(fmt.Errorf("Faux Error")) - spt.SetSender(c) - - err := spt.Refresh() - if err == nil { - t.Fatal("adal: Failed to propagate the request error") - } -} - -func TestServicePrincipalTokenRefreshReturnsErrorIfNotOk(t *testing.T) { - spt := newServicePrincipalToken() - - c := mocks.NewSender() - c.AppendResponse(mocks.NewResponseWithStatus("401 NotAuthorized", http.StatusUnauthorized)) - spt.SetSender(c) - - err := spt.Refresh() - if err == nil { - t.Fatalf("adal: Failed to return an when receiving a status code other than HTTP %d", http.StatusOK) - } -} - -func TestServicePrincipalTokenRefreshUnmarshals(t *testing.T) { - spt := newServicePrincipalToken() - - expiresOn := strconv.Itoa(int(time.Now().Add(3600 * time.Second).Sub(date.UnixEpoch()).Seconds())) - j := newTokenJSON(expiresOn, "resource") - resp := mocks.NewResponseWithContent(j) - c := mocks.NewSender() - s := DecorateSender(c, - (func() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - return resp, nil - }) - } - })()) - spt.SetSender(s) - - err := spt.Refresh() - if err != nil { - t.Fatalf("adal: ServicePrincipalToken#Refresh returned an unexpected error (%v)", err) - } else if spt.inner.Token.AccessToken != "accessToken" || - spt.inner.Token.ExpiresIn != "3600" || - spt.inner.Token.ExpiresOn != json.Number(expiresOn) || - spt.inner.Token.NotBefore != json.Number(expiresOn) || - spt.inner.Token.Resource != "resource" || - spt.inner.Token.Type != "Bearer" { - t.Fatalf("adal: ServicePrincipalToken#Refresh failed correctly unmarshal the JSON -- expected %v, received %v", - j, *spt) - } -} - -func TestServicePrincipalTokenEnsureFreshRefreshes(t *testing.T) { - spt := newServicePrincipalToken() - expireToken(&spt.inner.Token) - - body := mocks.NewBody(newTokenJSON("test", "test")) - resp := mocks.NewResponseWithBodyAndStatus(body, http.StatusOK, "OK") - - f := false - c := mocks.NewSender() - s := DecorateSender(c, - (func() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - f = true - return resp, nil - }) - } - })()) - spt.SetSender(s) - err := spt.EnsureFresh() - if err != nil { - t.Fatalf("adal: ServicePrincipalToken#EnsureFresh returned an unexpected error (%v)", err) - } - if !f { - t.Fatal("adal: ServicePrincipalToken#EnsureFresh failed to call Refresh for stale token") - } -} - -func TestServicePrincipalTokenEnsureFreshFails(t *testing.T) { - spt := newServicePrincipalToken() - expireToken(&spt.inner.Token) - - c := mocks.NewSender() - c.SetError(fmt.Errorf("some failure")) - - spt.SetSender(c) - err := spt.EnsureFresh() - if err == nil { - t.Fatal("adal: ServicePrincipalToken#EnsureFresh didn't return an error") - } - if _, ok := err.(TokenRefreshError); !ok { - t.Fatal("adal: ServicePrincipalToken#EnsureFresh didn't return a TokenRefreshError") - } -} - -func TestServicePrincipalTokenEnsureFreshSkipsIfFresh(t *testing.T) { - spt := newServicePrincipalToken() - setTokenToExpireIn(&spt.inner.Token, 1000*time.Second) - - f := false - c := mocks.NewSender() - s := DecorateSender(c, - (func() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - f = true - return mocks.NewResponse(), nil - }) - } - })()) - spt.SetSender(s) - err := spt.EnsureFresh() - if err != nil { - t.Fatalf("adal: ServicePrincipalToken#EnsureFresh returned an unexpected error (%v)", err) - } - if f { - t.Fatal("adal: ServicePrincipalToken#EnsureFresh invoked Refresh for fresh token") - } -} - -func TestRefreshCallback(t *testing.T) { - callbackTriggered := false - spt := newServicePrincipalToken(func(Token) error { - callbackTriggered = true - return nil - }) - - expiresOn := strconv.Itoa(int(time.Now().Add(3600 * time.Second).Sub(date.UnixEpoch()).Seconds())) - - sender := mocks.NewSender() - j := newTokenJSON(expiresOn, "resource") - sender.AppendResponse(mocks.NewResponseWithContent(j)) - spt.SetSender(sender) - err := spt.Refresh() - if err != nil { - t.Fatalf("adal: ServicePrincipalToken#Refresh returned an unexpected error (%v)", err) - } - if !callbackTriggered { - t.Fatalf("adal: RefreshCallback failed to trigger call callback") - } -} - -func TestRefreshCallbackErrorPropagates(t *testing.T) { - errorText := "this is an error text" - spt := newServicePrincipalToken(func(Token) error { - return fmt.Errorf(errorText) - }) - - expiresOn := strconv.Itoa(int(time.Now().Add(3600 * time.Second).Sub(date.UnixEpoch()).Seconds())) - - sender := mocks.NewSender() - j := newTokenJSON(expiresOn, "resource") - sender.AppendResponse(mocks.NewResponseWithContent(j)) - spt.SetSender(sender) - err := spt.Refresh() - - if err == nil || !strings.Contains(err.Error(), errorText) { - t.Fatalf("adal: RefreshCallback failed to propagate error") - } -} - -// This demonstrates the danger of manual token without a refresh token -func TestServicePrincipalTokenManualRefreshFailsWithoutRefresh(t *testing.T) { - spt := newServicePrincipalTokenManual() - spt.inner.Token.RefreshToken = "" - err := spt.Refresh() - if err == nil { - t.Fatalf("adal: ServicePrincipalToken#Refresh should have failed with a ManualTokenSecret without a refresh token") - } -} - -func TestNewServicePrincipalTokenFromMSI(t *testing.T) { - resource := "https://resource" - cb := func(token Token) error { return nil } - - spt, err := NewServicePrincipalTokenFromMSI("http://msiendpoint/", resource, cb) - if err != nil { - t.Fatalf("Failed to get MSI SPT: %v", err) - } - - // check some of the SPT fields - if _, ok := spt.inner.Secret.(*ServicePrincipalMSISecret); !ok { - t.Fatal("SPT secret was not of MSI type") - } - - if spt.inner.Resource != resource { - t.Fatal("SPT came back with incorrect resource") - } - - if len(spt.refreshCallbacks) != 1 { - t.Fatal("SPT had incorrect refresh callbacks.") - } -} - -func TestNewServicePrincipalTokenFromMSIWithUserAssignedID(t *testing.T) { - resource := "https://resource" - userID := "abc123" - cb := func(token Token) error { return nil } - - spt, err := NewServicePrincipalTokenFromMSIWithUserAssignedID("http://msiendpoint/", resource, userID, cb) - if err != nil { - t.Fatalf("Failed to get MSI SPT: %v", err) - } - - // check some of the SPT fields - if _, ok := spt.inner.Secret.(*ServicePrincipalMSISecret); !ok { - t.Fatal("SPT secret was not of MSI type") - } - - if spt.inner.Resource != resource { - t.Fatal("SPT came back with incorrect resource") - } - - if len(spt.refreshCallbacks) != 1 { - t.Fatal("SPT had incorrect refresh callbacks.") - } - - if spt.inner.ClientID != userID { - t.Fatal("SPT had incorrect client ID") - } -} - -func TestNewServicePrincipalTokenFromManualTokenSecret(t *testing.T) { - token := newToken() - secret := &ServicePrincipalAuthorizationCodeSecret{ - ClientSecret: "clientSecret", - AuthorizationCode: "code123", - RedirectURI: "redirect", - } - - spt, err := NewServicePrincipalTokenFromManualTokenSecret(TestOAuthConfig, "id", "resource", token, secret, nil) - if err != nil { - t.Fatalf("Failed creating new SPT: %s", err) - } - - if !reflect.DeepEqual(token, spt.inner.Token) { - t.Fatalf("Tokens do not match: %s, %s", token, spt.inner.Token) - } - - if !reflect.DeepEqual(secret, spt.inner.Secret) { - t.Fatalf("Secrets do not match: %s, %s", secret, spt.inner.Secret) - } - -} - -func TestGetVMEndpoint(t *testing.T) { - endpoint, err := GetMSIVMEndpoint() - if err != nil { - t.Fatal("Coudn't get VM endpoint") - } - - if endpoint != msiEndpoint { - t.Fatal("Didn't get correct endpoint") - } -} - -func TestMarshalServicePrincipalNoSecret(t *testing.T) { - spt := newServicePrincipalTokenManual() - b, err := json.Marshal(spt) - if err != nil { - t.Fatalf("failed to marshal token: %+v", err) - } - var spt2 *ServicePrincipalToken - err = json.Unmarshal(b, &spt2) - if err != nil { - t.Fatalf("failed to unmarshal token: %+v", err) - } - if !reflect.DeepEqual(spt, spt2) { - t.Fatal("tokens don't match") - } -} - -func TestMarshalServicePrincipalTokenSecret(t *testing.T) { - spt := newServicePrincipalToken() - b, err := json.Marshal(spt) - if err != nil { - t.Fatalf("failed to marshal token: %+v", err) - } - var spt2 *ServicePrincipalToken - err = json.Unmarshal(b, &spt2) - if err != nil { - t.Fatalf("failed to unmarshal token: %+v", err) - } - if !reflect.DeepEqual(spt, spt2) { - t.Fatal("tokens don't match") - } -} - -func TestMarshalServicePrincipalCertificateSecret(t *testing.T) { - spt := newServicePrincipalTokenCertificate(t) - b, err := json.Marshal(spt) - if err == nil { - t.Fatal("expected error when marshalling certificate token") - } - var spt2 *ServicePrincipalToken - err = json.Unmarshal(b, &spt2) - if err == nil { - t.Fatal("expected error when unmarshalling certificate token") - } -} - -func TestMarshalServicePrincipalMSISecret(t *testing.T) { - spt, err := newServicePrincipalTokenFromMSI("http://msiendpoint/", "https://resource", nil) - if err != nil { - t.Fatalf("failed to get MSI SPT: %+v", err) - } - b, err := json.Marshal(spt) - if err == nil { - t.Fatal("expected error when marshalling MSI token") - } - var spt2 *ServicePrincipalToken - err = json.Unmarshal(b, &spt2) - if err == nil { - t.Fatal("expected error when unmarshalling MSI token") - } -} - -func TestMarshalServicePrincipalUsernamePasswordSecret(t *testing.T) { - spt := newServicePrincipalTokenUsernamePassword(t) - b, err := json.Marshal(spt) - if err != nil { - t.Fatalf("failed to marshal token: %+v", err) - } - var spt2 *ServicePrincipalToken - err = json.Unmarshal(b, &spt2) - if err != nil { - t.Fatalf("failed to unmarshal token: %+v", err) - } - if !reflect.DeepEqual(spt, spt2) { - t.Fatal("tokens don't match") - } -} - -func TestMarshalServicePrincipalAuthorizationCodeSecret(t *testing.T) { - spt := newServicePrincipalTokenAuthorizationCode(t) - b, err := json.Marshal(spt) - if err != nil { - t.Fatalf("failed to marshal token: %+v", err) - } - var spt2 *ServicePrincipalToken - err = json.Unmarshal(b, &spt2) - if err != nil { - t.Fatalf("failed to unmarshal token: %+v", err) - } - if !reflect.DeepEqual(spt, spt2) { - t.Fatal("tokens don't match") - } -} - -func TestMarshalInnerToken(t *testing.T) { - spt := newServicePrincipalTokenManual() - tokenJSON, err := spt.MarshalTokenJSON() - if err != nil { - t.Fatalf("failed to marshal token: %+v", err) - } - - testToken := newToken() - testToken.RefreshToken = "refreshtoken" - - testTokenJSON, err := json.Marshal(testToken) - if err != nil { - t.Fatalf("failed to marshal test token: %+v", err) - } - - if !reflect.DeepEqual(tokenJSON, testTokenJSON) { - t.Fatalf("tokens don't match: %s, %s", tokenJSON, testTokenJSON) - } - - var t1 Token - err = json.Unmarshal(tokenJSON, &t1) - if err != nil { - t.Fatalf("failed to unmarshal token: %+v", err) - } - - if !reflect.DeepEqual(t1, testToken) { - t.Fatalf("tokens don't match: %s, %s", t1, testToken) - } -} - -func newTokenJSON(expiresOn string, resource string) string { - return fmt.Sprintf(`{ - "access_token" : "accessToken", - "expires_in" : "3600", - "expires_on" : "%s", - "not_before" : "%s", - "resource" : "%s", - "token_type" : "Bearer", - "refresh_token": "ABC123" - }`, - expiresOn, expiresOn, resource) -} - -func newTokenExpiresIn(expireIn time.Duration) *Token { - t := newToken() - return setTokenToExpireIn(&t, expireIn) -} - -func newTokenExpiresAt(expireAt time.Time) *Token { - t := newToken() - return setTokenToExpireAt(&t, expireAt) -} - -func expireToken(t *Token) *Token { - return setTokenToExpireIn(t, 0) -} - -func setTokenToExpireAt(t *Token, expireAt time.Time) *Token { - t.ExpiresIn = "3600" - t.ExpiresOn = json.Number(strconv.FormatInt(int64(expireAt.Sub(date.UnixEpoch())/time.Second), 10)) - t.NotBefore = t.ExpiresOn - return t -} - -func setTokenToExpireIn(t *Token, expireIn time.Duration) *Token { - return setTokenToExpireAt(t, time.Now().Add(expireIn)) -} - -func newServicePrincipalToken(callbacks ...TokenRefreshCallback) *ServicePrincipalToken { - spt, _ := NewServicePrincipalToken(TestOAuthConfig, "id", "secret", "resource", callbacks...) - return spt -} - -func newServicePrincipalTokenManual() *ServicePrincipalToken { - token := newToken() - token.RefreshToken = "refreshtoken" - spt, _ := NewServicePrincipalTokenFromManualToken(TestOAuthConfig, "id", "resource", token) - return spt -} - -func newServicePrincipalTokenCertificate(t *testing.T) *ServicePrincipalToken { - template := x509.Certificate{ - SerialNumber: big.NewInt(0), - Subject: pkix.Name{CommonName: "test"}, - BasicConstraintsValid: true, - } - privateKey, err := rsa.GenerateKey(rand.Reader, 2048) - if err != nil { - t.Fatal(err) - } - certificateBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &privateKey.PublicKey, privateKey) - if err != nil { - t.Fatal(err) - } - certificate, err := x509.ParseCertificate(certificateBytes) - if err != nil { - t.Fatal(err) - } - - spt, _ := NewServicePrincipalTokenFromCertificate(TestOAuthConfig, "id", certificate, privateKey, "resource") - return spt -} - -func newServicePrincipalTokenUsernamePassword(t *testing.T) *ServicePrincipalToken { - spt, _ := NewServicePrincipalTokenFromUsernamePassword(TestOAuthConfig, "id", "username", "password", "resource") - return spt -} - -func newServicePrincipalTokenAuthorizationCode(t *testing.T) *ServicePrincipalToken { - spt, _ := NewServicePrincipalTokenFromAuthorizationCode(TestOAuthConfig, "id", "clientSecret", "code", "http://redirectUri/getToken", "resource") - return spt -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/authorization_test.go b/vendor/github.com/Azure/go-autorest/autorest/authorization_test.go deleted file mode 100644 index 331d4234..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/authorization_test.go +++ /dev/null @@ -1,230 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "fmt" - "net/http" - "reflect" - "testing" - - "github.com/Azure/go-autorest/autorest/adal" - "github.com/Azure/go-autorest/autorest/mocks" -) - -const ( - TestTenantID = "TestTenantID" - TestActiveDirectoryEndpoint = "https://login/test.com/" -) - -func TestWithAuthorizer(t *testing.T) { - r1 := mocks.NewRequest() - - na := &NullAuthorizer{} - r2, err := Prepare(r1, - na.WithAuthorization()) - if err != nil { - t.Fatalf("autorest: NullAuthorizer#WithAuthorization returned an unexpected error (%v)", err) - } else if !reflect.DeepEqual(r1, r2) { - t.Fatalf("autorest: NullAuthorizer#WithAuthorization modified the request -- received %v, expected %v", r2, r1) - } -} - -func TestTokenWithAuthorization(t *testing.T) { - token := &adal.Token{ - AccessToken: "TestToken", - Resource: "https://azure.microsoft.com/", - Type: "Bearer", - } - - ba := NewBearerAuthorizer(token) - req, err := Prepare(&http.Request{}, ba.WithAuthorization()) - if err != nil { - t.Fatalf("azure: BearerAuthorizer#WithAuthorization returned an error (%v)", err) - } else if req.Header.Get(http.CanonicalHeaderKey("Authorization")) != fmt.Sprintf("Bearer %s", token.AccessToken) { - t.Fatal("azure: BearerAuthorizer#WithAuthorization failed to set Authorization header") - } -} - -func TestServicePrincipalTokenWithAuthorizationNoRefresh(t *testing.T) { - oauthConfig, err := adal.NewOAuthConfig(TestActiveDirectoryEndpoint, TestTenantID) - if err != nil { - t.Fatalf("azure: BearerAuthorizer#WithAuthorization returned an error (%v)", err) - } - spt, err := adal.NewServicePrincipalToken(*oauthConfig, "id", "secret", "resource", nil) - if err != nil { - t.Fatalf("azure: BearerAuthorizer#WithAuthorization returned an error (%v)", err) - } - spt.SetAutoRefresh(false) - s := mocks.NewSender() - spt.SetSender(s) - - ba := NewBearerAuthorizer(spt) - req, err := Prepare(mocks.NewRequest(), ba.WithAuthorization()) - if err != nil { - t.Fatalf("azure: BearerAuthorizer#WithAuthorization returned an error (%v)", err) - } else if req.Header.Get(http.CanonicalHeaderKey("Authorization")) != fmt.Sprintf("Bearer %s", spt.OAuthToken()) { - t.Fatal("azure: BearerAuthorizer#WithAuthorization failed to set Authorization header") - } -} - -func TestServicePrincipalTokenWithAuthorizationRefresh(t *testing.T) { - - oauthConfig, err := adal.NewOAuthConfig(TestActiveDirectoryEndpoint, TestTenantID) - if err != nil { - t.Fatalf("azure: BearerAuthorizer#WithAuthorization returned an error (%v)", err) - } - refreshed := false - spt, err := adal.NewServicePrincipalToken(*oauthConfig, "id", "secret", "resource", func(t adal.Token) error { - refreshed = true - return nil - }) - if err != nil { - t.Fatalf("azure: BearerAuthorizer#WithAuthorization returned an error (%v)", err) - } - - jwt := `{ - "access_token" : "accessToken", - "expires_in" : "3600", - "expires_on" : "test", - "not_before" : "test", - "resource" : "test", - "token_type" : "Bearer" - }` - body := mocks.NewBody(jwt) - resp := mocks.NewResponseWithBodyAndStatus(body, http.StatusOK, "OK") - c := mocks.NewSender() - s := DecorateSender(c, - (func() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - return resp, nil - }) - } - })()) - spt.SetSender(s) - - ba := NewBearerAuthorizer(spt) - req, err := Prepare(mocks.NewRequest(), ba.WithAuthorization()) - if err != nil { - t.Fatalf("azure: BearerAuthorizer#WithAuthorization returned an error (%v)", err) - } else if req.Header.Get(http.CanonicalHeaderKey("Authorization")) != fmt.Sprintf("Bearer %s", spt.OAuthToken()) { - t.Fatal("azure: BearerAuthorizer#WithAuthorization failed to set Authorization header") - } - - if !refreshed { - t.Fatal("azure: BearerAuthorizer#WithAuthorization must refresh the token") - } -} - -func TestServicePrincipalTokenWithAuthorizationReturnsErrorIfConnotRefresh(t *testing.T) { - oauthConfig, err := adal.NewOAuthConfig(TestActiveDirectoryEndpoint, TestTenantID) - if err != nil { - t.Fatalf("azure: BearerAuthorizer#WithAuthorization returned an error (%v)", err) - } - spt, err := adal.NewServicePrincipalToken(*oauthConfig, "id", "secret", "resource", nil) - if err != nil { - t.Fatalf("azure: BearerAuthorizer#WithAuthorization returned an error (%v)", err) - } - - s := mocks.NewSender() - s.AppendResponse(mocks.NewResponseWithStatus("400 Bad Request", http.StatusBadRequest)) - spt.SetSender(s) - - ba := NewBearerAuthorizer(spt) - _, err = Prepare(mocks.NewRequest(), ba.WithAuthorization()) - if err == nil { - t.Fatal("azure: BearerAuthorizer#WithAuthorization failed to return an error when refresh fails") - } -} - -func TestBearerAuthorizerCallback(t *testing.T) { - tenantString := "123-tenantID-456" - resourceString := "https://fake.resource.net" - - s := mocks.NewSender() - resp := mocks.NewResponseWithStatus("401 Unauthorized", http.StatusUnauthorized) - mocks.SetResponseHeader(resp, bearerChallengeHeader, bearer+" \"authorization\"=\"https://fake.net/"+tenantString+"\",\"resource\"=\""+resourceString+"\"") - s.AppendResponse(resp) - - auth := NewBearerAuthorizerCallback(s, func(tenantID, resource string) (*BearerAuthorizer, error) { - if tenantID != tenantString { - t.Fatal("BearerAuthorizerCallback: bad tenant ID") - } - if resource != resourceString { - t.Fatal("BearerAuthorizerCallback: bad resource") - } - - oauthConfig, err := adal.NewOAuthConfig(TestActiveDirectoryEndpoint, tenantID) - if err != nil { - t.Fatalf("azure: NewOAuthConfig returned an error (%v)", err) - } - - spt, err := adal.NewServicePrincipalToken(*oauthConfig, "id", "secret", resource) - if err != nil { - t.Fatalf("azure: NewServicePrincipalToken returned an error (%v)", err) - } - - spt.SetSender(s) - return NewBearerAuthorizer(spt), nil - }) - - _, err := Prepare(mocks.NewRequest(), auth.WithAuthorization()) - if err == nil { - t.Fatal("azure: BearerAuthorizerCallback#WithAuthorization failed to return an error when refresh fails") - } -} - -func TestApiKeyAuthorization(t *testing.T) { - - headers := make(map[string]interface{}) - queryParameters := make(map[string]interface{}) - - dummyAuthHeader := "dummyAuthHeader" - dummyAuthHeaderValue := "dummyAuthHeaderValue" - - dummyAuthQueryParameter := "dummyAuthQueryParameter" - dummyAuthQueryParameterValue := "dummyAuthQueryParameterValue" - - headers[dummyAuthHeader] = dummyAuthHeaderValue - queryParameters[dummyAuthQueryParameter] = dummyAuthQueryParameterValue - - aka := NewAPIKeyAuthorizer(headers, queryParameters) - - req, err := Prepare(mocks.NewRequest(), aka.WithAuthorization()) - - if err != nil { - t.Fatalf("azure: APIKeyAuthorizer#WithAuthorization returned an error (%v)", err) - } else if req.Header.Get(http.CanonicalHeaderKey(dummyAuthHeader)) != dummyAuthHeaderValue { - t.Fatalf("azure: APIKeyAuthorizer#WithAuthorization failed to set %s header", dummyAuthHeader) - - } else if req.URL.Query().Get(dummyAuthQueryParameter) != dummyAuthQueryParameterValue { - t.Fatalf("azure: APIKeyAuthorizer#WithAuthorization failed to set %s query parameter", dummyAuthQueryParameterValue) - } -} - -func TestCognitivesServicesAuthorization(t *testing.T) { - subscriptionKey := "dummyKey" - csa := NewCognitiveServicesAuthorizer(subscriptionKey) - req, err := Prepare(mocks.NewRequest(), csa.WithAuthorization()) - - if err != nil { - t.Fatalf("azure: CognitiveServicesAuthorizer#WithAuthorization returned an error (%v)", err) - } else if req.Header.Get(http.CanonicalHeaderKey(bingAPISdkHeader)) != golangBingAPISdkHeaderValue { - t.Fatalf("azure: CognitiveServicesAuthorizer#WithAuthorization failed to set %s header", bingAPISdkHeader) - } else if req.Header.Get(http.CanonicalHeaderKey(apiKeyAuthorizerHeader)) != subscriptionKey { - t.Fatalf("azure: CognitiveServicesAuthorizer#WithAuthorization failed to set %s header", apiKeyAuthorizerHeader) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/autorest_test.go b/vendor/github.com/Azure/go-autorest/autorest/autorest_test.go deleted file mode 100644 index 467ea438..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/autorest_test.go +++ /dev/null @@ -1,140 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "net/http" - "testing" - - "github.com/Azure/go-autorest/autorest/mocks" -) - -func TestResponseHasStatusCode(t *testing.T) { - codes := []int{http.StatusOK, http.StatusAccepted} - resp := &http.Response{StatusCode: http.StatusAccepted} - if !ResponseHasStatusCode(resp, codes...) { - t.Fatalf("autorest: ResponseHasStatusCode failed to find %v in %v", resp.StatusCode, codes) - } -} - -func TestResponseHasStatusCodeNotPresent(t *testing.T) { - codes := []int{http.StatusOK, http.StatusAccepted} - resp := &http.Response{StatusCode: http.StatusInternalServerError} - if ResponseHasStatusCode(resp, codes...) { - t.Fatalf("autorest: ResponseHasStatusCode unexpectedly found %v in %v", resp.StatusCode, codes) - } -} - -func TestNewPollingRequestDoesNotReturnARequestWhenLocationHeaderIsMissing(t *testing.T) { - resp := mocks.NewResponseWithStatus("500 InternalServerError", http.StatusInternalServerError) - - req, _ := NewPollingRequest(resp, nil) - if req != nil { - t.Fatal("autorest: NewPollingRequest returned an http.Request when the Location header was missing") - } -} - -func TestNewPollingRequestReturnsAnErrorWhenPrepareFails(t *testing.T) { - resp := mocks.NewResponseWithStatus("202 Accepted", http.StatusAccepted) - mocks.SetAcceptedHeaders(resp) - resp.Header.Set(http.CanonicalHeaderKey(HeaderLocation), mocks.TestBadURL) - - _, err := NewPollingRequest(resp, nil) - if err == nil { - t.Fatal("autorest: NewPollingRequest failed to return an error when Prepare fails") - } -} - -func TestNewPollingRequestDoesNotReturnARequestWhenPrepareFails(t *testing.T) { - resp := mocks.NewResponseWithStatus("202 Accepted", http.StatusAccepted) - mocks.SetAcceptedHeaders(resp) - resp.Header.Set(http.CanonicalHeaderKey(HeaderLocation), mocks.TestBadURL) - - req, _ := NewPollingRequest(resp, nil) - if req != nil { - t.Fatal("autorest: NewPollingRequest returned an http.Request when Prepare failed") - } -} - -func TestNewPollingRequestReturnsAGetRequest(t *testing.T) { - resp := mocks.NewResponseWithStatus("202 Accepted", http.StatusAccepted) - mocks.SetAcceptedHeaders(resp) - - req, _ := NewPollingRequest(resp, nil) - if req.Method != "GET" { - t.Fatalf("autorest: NewPollingRequest did not create an HTTP GET request -- actual method %v", req.Method) - } -} - -func TestNewPollingRequestProvidesTheURL(t *testing.T) { - resp := mocks.NewResponseWithStatus("202 Accepted", http.StatusAccepted) - mocks.SetAcceptedHeaders(resp) - - req, _ := NewPollingRequest(resp, nil) - if req.URL.String() != mocks.TestURL { - t.Fatalf("autorest: NewPollingRequest did not create an HTTP with the expected URL -- received %v, expected %v", req.URL, mocks.TestURL) - } -} - -func TestGetLocation(t *testing.T) { - resp := mocks.NewResponseWithStatus("202 Accepted", http.StatusAccepted) - mocks.SetAcceptedHeaders(resp) - - l := GetLocation(resp) - if len(l) == 0 { - t.Fatalf("autorest: GetLocation failed to return Location header -- expected %v, received %v", mocks.TestURL, l) - } -} - -func TestGetLocationReturnsEmptyStringForMissingLocation(t *testing.T) { - resp := mocks.NewResponseWithStatus("202 Accepted", http.StatusAccepted) - - l := GetLocation(resp) - if len(l) != 0 { - t.Fatalf("autorest: GetLocation return a value without a Location header -- received %v", l) - } -} - -func TestGetRetryAfter(t *testing.T) { - resp := mocks.NewResponseWithStatus("202 Accepted", http.StatusAccepted) - mocks.SetAcceptedHeaders(resp) - - d := GetRetryAfter(resp, DefaultPollingDelay) - if d != mocks.TestDelay { - t.Fatalf("autorest: GetRetryAfter failed to returned the expected delay -- expected %v, received %v", mocks.TestDelay, d) - } -} - -func TestGetRetryAfterReturnsDefaultDelayIfRetryHeaderIsMissing(t *testing.T) { - resp := mocks.NewResponseWithStatus("202 Accepted", http.StatusAccepted) - - d := GetRetryAfter(resp, DefaultPollingDelay) - if d != DefaultPollingDelay { - t.Fatalf("autorest: GetRetryAfter failed to returned the default delay for a missing Retry-After header -- expected %v, received %v", - DefaultPollingDelay, d) - } -} - -func TestGetRetryAfterReturnsDefaultDelayIfRetryHeaderIsMalformed(t *testing.T) { - resp := mocks.NewResponseWithStatus("202 Accepted", http.StatusAccepted) - mocks.SetAcceptedHeaders(resp) - resp.Header.Set(http.CanonicalHeaderKey(HeaderRetryAfter), "a very bad non-integer value") - - d := GetRetryAfter(resp, DefaultPollingDelay) - if d != DefaultPollingDelay { - t.Fatalf("autorest: GetRetryAfter failed to returned the default delay for a malformed Retry-After header -- expected %v, received %v", - DefaultPollingDelay, d) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/async_test.go b/vendor/github.com/Azure/go-autorest/autorest/azure/async_test.go deleted file mode 100644 index 61cb821e..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/azure/async_test.go +++ /dev/null @@ -1,1156 +0,0 @@ -package azure - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "net/http" - "reflect" - "sync" - "testing" - "time" - - "github.com/Azure/go-autorest/autorest" - "github.com/Azure/go-autorest/autorest/mocks" -) - -func TestCreateFromInvalidRequestVerb(t *testing.T) { - resp := mocks.NewResponseWithBodyAndStatus(nil, http.StatusOK, "some status") - resp.Request = mocks.NewRequestWithParams(http.MethodGet, mocks.TestURL, nil) - _, err := createPollingTracker(resp) - if err == nil { - t.Fatal("unexpected nil error") - } -} - -// DELETE -func TestCreateDeleteTracker201Success(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodDelete, nil), http.StatusCreated, nil) - mocks.SetLocationHeader(resp, mocks.TestLocationURL) - pt, err := createPollingTracker(resp) - if err != nil { - t.Fatalf("failed to create tracker: %v", err) - } - if pt.pollingMethod() != PollingLocation { - t.Fatalf("wrong polling method: %s", pt.pollingMethod()) - } - if pt.finalGetURL() != mocks.TestLocationURL { - t.Fatalf("wrong final GET URL: %s", pt.finalGetURL()) - } -} - -func TestCreateDeleteTracker201FailNoLocation(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodDelete, nil), http.StatusCreated, nil) - _, err := createPollingTracker(resp) - if err == nil { - t.Fatal("unexpected nil error") - } -} - -func TestCreateDeleteTracker201FailBadLocation(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodDelete, nil), http.StatusCreated, nil) - mocks.SetLocationHeader(resp, mocks.TestBadURL) - _, err := createPollingTracker(resp) - if err == nil { - t.Fatal("unexpected nil error") - } -} - -func TestCreateDeleteTracker202SuccessAsyncOp(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodDelete, nil), http.StatusAccepted, nil) - setAsyncOpHeader(resp, mocks.TestAzureAsyncURL) - pt, err := createPollingTracker(resp) - if err != nil { - t.Fatalf("failed to create tracker: %v", err) - } - if pt.pollingMethod() != PollingAsyncOperation { - t.Fatalf("wrong polling method: %s", pt.pollingMethod()) - } - if pt.finalGetURL() != "" { - t.Fatal("expected empty GET URL") - } -} - -func TestCreateDeleteTracker202SuccessLocation(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodDelete, nil), http.StatusAccepted, nil) - mocks.SetLocationHeader(resp, mocks.TestLocationURL) - pt, err := createPollingTracker(resp) - if err != nil { - t.Fatalf("failed to create tracker: %v", err) - } - if pt.pollingMethod() != PollingLocation { - t.Fatalf("wrong polling method: %s", pt.pollingMethod()) - } - if pt.finalGetURL() != mocks.TestLocationURL { - t.Fatalf("wrong final GET URL: %s", pt.finalGetURL()) - } -} - -func TestCreateDeleteTracker202SuccessBoth(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodDelete, nil), http.StatusAccepted, nil) - setAsyncOpHeader(resp, mocks.TestAzureAsyncURL) - mocks.SetLocationHeader(resp, mocks.TestLocationURL) - pt, err := createPollingTracker(resp) - if err != nil { - t.Fatalf("failed to create tracker: %v", err) - } - if pt.pollingMethod() != PollingAsyncOperation { - t.Fatalf("wrong polling method: %s", pt.pollingMethod()) - } - if pt.finalGetURL() != mocks.TestLocationURL { - t.Fatalf("wrong final GET URL: %s", pt.finalGetURL()) - } -} - -func TestCreateDeleteTracker202SuccessBadLocation(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodDelete, nil), http.StatusAccepted, nil) - setAsyncOpHeader(resp, mocks.TestAzureAsyncURL) - mocks.SetLocationHeader(resp, mocks.TestBadURL) - pt, err := createPollingTracker(resp) - if err != nil { - t.Fatalf("failed to create tracker: %v", err) - } - if pt.pollingMethod() != PollingAsyncOperation { - t.Fatalf("wrong polling method: %s", pt.pollingMethod()) - } - if pt.finalGetURL() != "" { - t.Fatal("expected empty GET URL") - } -} - -func TestCreateDeleteTracker202FailBadAsyncOp(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodDelete, nil), http.StatusAccepted, nil) - setAsyncOpHeader(resp, mocks.TestBadURL) - _, err := createPollingTracker(resp) - if err == nil { - t.Fatal("unexpected nil error") - } -} - -func TestCreateDeleteTracker202FailBadLocation(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodDelete, nil), http.StatusAccepted, nil) - mocks.SetLocationHeader(resp, mocks.TestBadURL) - _, err := createPollingTracker(resp) - if err == nil { - t.Fatal("unexpected nil error") - } -} - -// PATCH - -func TestCreatePatchTracker201Success(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodPatch, nil), http.StatusCreated, nil) - setAsyncOpHeader(resp, mocks.TestAzureAsyncURL) - pt, err := createPollingTracker(resp) - if err != nil { - t.Fatalf("failed to create tracker: %v", err) - } - if pt.pollingMethod() != PollingAsyncOperation { - t.Fatalf("wrong polling method: %s", pt.pollingMethod()) - } - if pt.finalGetURL() != mocks.TestURL { - t.Fatalf("wrong final GET URL: %s", pt.finalGetURL()) - } -} - -func TestCreatePatchTracker201SuccessNoHeaders(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodPatch, nil), http.StatusCreated, nil) - pt, err := createPollingTracker(resp) - if err != nil { - t.Fatalf("failed to create tracker: %v", err) - } - if pt.pollingMethod() != PollingRequestURI { - t.Fatalf("wrong polling method: %s", pt.pollingMethod()) - } - if pt.finalGetURL() != mocks.TestURL { - t.Fatalf("wrong final GET URL: %s", pt.finalGetURL()) - } -} - -func TestCreatePatchTracker201FailBadAsyncOp(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodPatch, nil), http.StatusCreated, nil) - setAsyncOpHeader(resp, mocks.TestBadURL) - _, err := createPollingTracker(resp) - if err == nil { - t.Fatal("unexpected nil error") - } -} - -func TestCreatePatchTracker202SuccessAsyncOp(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodPatch, nil), http.StatusAccepted, nil) - setAsyncOpHeader(resp, mocks.TestAzureAsyncURL) - pt, err := createPollingTracker(resp) - if err != nil { - t.Fatalf("failed to create tracker: %v", err) - } - if pt.pollingMethod() != PollingAsyncOperation { - t.Fatalf("wrong polling method: %s", pt.pollingMethod()) - } - if pt.finalGetURL() != mocks.TestURL { - t.Fatalf("wrong final GET URL: %s", pt.finalGetURL()) - } -} - -func TestCreatePatchTracker202SuccessLocation(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodPatch, nil), http.StatusAccepted, nil) - mocks.SetLocationHeader(resp, mocks.TestLocationURL) - pt, err := createPollingTracker(resp) - if err != nil { - t.Fatalf("failed to create tracker: %v", err) - } - if pt.pollingMethod() != PollingLocation { - t.Fatalf("wrong polling method: %s", pt.pollingMethod()) - } - if pt.finalGetURL() != mocks.TestURL { - t.Fatalf("wrong final GET URL: %s", pt.finalGetURL()) - } -} - -func TestCreatePatchTracker202SuccessBoth(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodPatch, nil), http.StatusAccepted, nil) - setAsyncOpHeader(resp, mocks.TestAzureAsyncURL) - mocks.SetLocationHeader(resp, mocks.TestLocationURL) - pt, err := createPollingTracker(resp) - if err != nil { - t.Fatalf("failed to create tracker: %v", err) - } - if pt.pollingMethod() != PollingAsyncOperation { - t.Fatalf("wrong polling method: %s", pt.pollingMethod()) - } - if pt.finalGetURL() != mocks.TestURL { - t.Fatalf("wrong final GET URL: %s", pt.finalGetURL()) - } -} - -func TestCreatePatchTracker202FailBadAsyncOp(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodPatch, nil), http.StatusAccepted, nil) - setAsyncOpHeader(resp, mocks.TestBadURL) - _, err := createPollingTracker(resp) - if err == nil { - t.Fatal("unexpected nil error") - } -} - -func TestCreatePatchTracker202FailBadLocation(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodPatch, nil), http.StatusAccepted, nil) - mocks.SetLocationHeader(resp, mocks.TestBadURL) - _, err := createPollingTracker(resp) - if err == nil { - t.Fatal("unexpected nil error") - } -} - -// POST - -func TestCreatePostTracker201Success(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodPost, nil), http.StatusCreated, nil) - mocks.SetLocationHeader(resp, mocks.TestLocationURL) - pt, err := createPollingTracker(resp) - if err != nil { - t.Fatalf("failed to create tracker: %v", err) - } - if pt.pollingMethod() != PollingLocation { - t.Fatalf("wrong polling method: %s", pt.pollingMethod()) - } - if pt.finalGetURL() != mocks.TestLocationURL { - t.Fatalf("wrong final GET URL: %s", pt.finalGetURL()) - } -} - -func TestCreatePostTracker201FailNoHeader(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodPost, nil), http.StatusCreated, nil) - _, err := createPollingTracker(resp) - if err == nil { - t.Fatal("unexpected nil err") - } -} - -func TestCreatePostTracker201FailBadHeader(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodPost, nil), http.StatusCreated, nil) - mocks.SetLocationHeader(resp, mocks.TestBadURL) - _, err := createPollingTracker(resp) - if err == nil { - t.Fatal("unexpected nil err") - } -} - -func TestCreatePostTracker202SuccessAsyncOp(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodPost, nil), http.StatusAccepted, nil) - setAsyncOpHeader(resp, mocks.TestAzureAsyncURL) - pt, err := createPollingTracker(resp) - if err != nil { - t.Fatalf("failed to create tracker: %v", err) - } - if pt.pollingMethod() != PollingAsyncOperation { - t.Fatalf("wrong polling method: %s", pt.pollingMethod()) - } - if pt.finalGetURL() != "" { - t.Fatal("expected empty final GET URL") - } -} - -func TestCreatePostTracker202SuccessLocation(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodPost, nil), http.StatusAccepted, nil) - mocks.SetLocationHeader(resp, mocks.TestLocationURL) - pt, err := createPollingTracker(resp) - if err != nil { - t.Fatalf("failed to create tracker: %v", err) - } - if pt.pollingMethod() != PollingLocation { - t.Fatalf("wrong polling method: %s", pt.pollingMethod()) - } - if pt.finalGetURL() != mocks.TestLocationURL { - t.Fatalf("wrong final GET URI: %s", pt.finalGetURL()) - } -} - -func TestCreatePostTracker202SuccessBoth(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodPost, nil), http.StatusAccepted, nil) - setAsyncOpHeader(resp, mocks.TestAzureAsyncURL) - mocks.SetLocationHeader(resp, mocks.TestLocationURL) - pt, err := createPollingTracker(resp) - if err != nil { - t.Fatalf("failed to create tracker: %v", err) - } - if pt.pollingMethod() != PollingAsyncOperation { - t.Fatalf("wrong polling method: %s", pt.pollingMethod()) - } - if pt.finalGetURL() != mocks.TestLocationURL { - t.Fatalf("wrong final GET URL: %s", pt.finalGetURL()) - } -} - -func TestCreatePostTracker202SuccessBadLocation(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodPost, nil), http.StatusAccepted, nil) - setAsyncOpHeader(resp, mocks.TestAzureAsyncURL) - mocks.SetLocationHeader(resp, mocks.TestBadURL) - pt, err := createPollingTracker(resp) - if err != nil { - t.Fatalf("failed to create tracker: %v", err) - } - if pt.pollingMethod() != PollingAsyncOperation { - t.Fatalf("wrong polling method: %s", pt.pollingMethod()) - } - if pt.finalGetURL() != "" { - t.Fatal("expected empty final GET URL") - } -} - -func TestCreatePostTracker202FailBadAsyncOp(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodPost, nil), http.StatusAccepted, nil) - setAsyncOpHeader(resp, mocks.TestBadURL) - _, err := createPollingTracker(resp) - if err == nil { - t.Fatal("unexpected nil error") - } -} - -func TestCreatePostTracker202FailBadLocation(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodPost, nil), http.StatusAccepted, nil) - _, err := createPollingTracker(resp) - mocks.SetLocationHeader(resp, mocks.TestBadURL) - if err == nil { - t.Fatal("unexpected nil error") - } -} - -// PUT - -func TestCreatePutTracker201SuccessAsyncOp(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodPut, nil), http.StatusCreated, nil) - setAsyncOpHeader(resp, mocks.TestAzureAsyncURL) - pt, err := createPollingTracker(resp) - if err != nil { - t.Fatalf("failed to create tracker: %v", err) - } - if pt.pollingMethod() != PollingAsyncOperation { - t.Fatalf("wrong polling method: %s", pt.pollingMethod()) - } - if pt.finalGetURL() != mocks.TestURL { - t.Fatalf("wrong final GET URL: %s", pt.finalGetURL()) - } -} - -func TestCreatePutTracker201SuccessNoHeaders(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodPut, nil), http.StatusCreated, nil) - pt, err := createPollingTracker(resp) - if err != nil { - t.Fatalf("failed to create tracker: %v", err) - } - if pt.pollingMethod() != PollingRequestURI { - t.Fatalf("wrong polling method: %s", pt.pollingMethod()) - } - if pt.finalGetURL() != mocks.TestURL { - t.Fatalf("wrong final GET URL: %s", pt.finalGetURL()) - } -} - -func TestCreatePutTracker201FailBadAsyncOp(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodPut, nil), http.StatusCreated, nil) - setAsyncOpHeader(resp, mocks.TestBadURL) - _, err := createPollingTracker(resp) - if err == nil { - t.Fatal("unexpected nil error") - } -} - -func TestCreatePutTracker202SuccessAsyncOp(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodPut, nil), http.StatusAccepted, nil) - setAsyncOpHeader(resp, mocks.TestAzureAsyncURL) - pt, err := createPollingTracker(resp) - if err != nil { - t.Fatalf("failed to create tracker: %v", err) - } - if pt.pollingMethod() != PollingAsyncOperation { - t.Fatalf("wrong polling method: %s", pt.pollingMethod()) - } - if pt.finalGetURL() != mocks.TestURL { - t.Fatalf("wrong final GET URL: %s", pt.finalGetURL()) - } -} - -func TestCreatePutTracker202SuccessLocation(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodPut, nil), http.StatusAccepted, nil) - mocks.SetLocationHeader(resp, mocks.TestLocationURL) - pt, err := createPollingTracker(resp) - if err != nil { - t.Fatalf("failed to create tracker: %v", err) - } - if pt.pollingMethod() != PollingLocation { - t.Fatalf("wrong polling method: %s", pt.pollingMethod()) - } - if pt.finalGetURL() != mocks.TestLocationURL { - t.Fatalf("wrong final GET URL: %s", pt.finalGetURL()) - } -} - -func TestCreatePutTracker202SuccessBoth(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodPut, nil), http.StatusAccepted, nil) - setAsyncOpHeader(resp, mocks.TestAzureAsyncURL) - mocks.SetLocationHeader(resp, mocks.TestLocationURL) - pt, err := createPollingTracker(resp) - if err != nil { - t.Fatalf("failed to create tracker: %v", err) - } - if pt.pollingMethod() != PollingAsyncOperation { - t.Fatalf("wrong polling method: %s", pt.pollingMethod()) - } - if pt.finalGetURL() != mocks.TestLocationURL { - t.Fatalf("wrong final GET URL: %s", pt.finalGetURL()) - } -} - -func TestCreatePutTracker202SuccessBadLocation(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodPut, nil), http.StatusAccepted, nil) - setAsyncOpHeader(resp, mocks.TestAzureAsyncURL) - mocks.SetLocationHeader(resp, mocks.TestBadURL) - pt, err := createPollingTracker(resp) - if err != nil { - t.Fatalf("failed to create tracker: %v", err) - } - if pt.pollingMethod() != PollingAsyncOperation { - t.Fatalf("wrong polling method: %s", pt.pollingMethod()) - } - if pt.finalGetURL() != mocks.TestURL { - t.Fatalf("wrong final GET URL: %s", pt.finalGetURL()) - } -} - -func TestCreatePutTracker202FailBadAsyncOp(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodPut, nil), http.StatusAccepted, nil) - setAsyncOpHeader(resp, mocks.TestBadURL) - _, err := createPollingTracker(resp) - if err == nil { - t.Fatal("unexpected nil error") - } -} - -func TestPollPutTrackerSuccessNoHeaders(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodPut, nil), http.StatusAccepted, nil) - pt, err := createPollingTracker(resp) - if err != nil { - t.Fatalf("failed to create tracker: %v", err) - } - sender := mocks.NewSender() - sender.AppendResponse(newProvisioningStatusResponse("InProgress")) - err = pt.pollForStatus(context.Background(), sender) - if err != nil { - t.Fatalf("failed to poll for status: %v", err) - } - err = pt.checkForErrors() - if err != nil { - t.Fatalf("unexpected error: %v", err) - } -} - -func TestPollPutTrackerFailNoHeadersEmptyBody(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodPut, nil), http.StatusAccepted, nil) - pt, err := createPollingTracker(resp) - if err != nil { - t.Fatalf("failed to create tracker: %v", err) - } - sender := mocks.NewSender() - sender.AppendResponse(mocks.NewResponseWithBodyAndStatus(&mocks.Body{}, http.StatusOK, "status ok")) - err = pt.pollForStatus(context.Background(), sender) - if err != nil { - t.Fatalf("failed to poll for status: %v", err) - } - err = pt.checkForErrors() - if err == nil { - t.Fatalf("unexpected nil error") - } -} - -// errors - -func TestAsyncPollingReturnsWrappedError(t *testing.T) { - resp := newSimpleAsyncResp() - pt, err := createPollingTracker(resp) - if err != nil { - t.Fatalf("failed to create tracker: %v", err) - } - sender := mocks.NewSender() - sender.AppendResponse(newOperationResourceErrorResponse("Failed")) - err = pt.pollForStatus(context.Background(), sender) - if err == nil { - t.Fatal("unexpected nil polling error") - } - err = pt.pollingError() - if err == nil { - t.Fatal("unexpected nil polling error") - } - if se, ok := err.(*ServiceError); !ok { - t.Fatal("incorrect error type") - } else if se.Code == "" { - t.Fatal("empty service error code") - } else if se.Message == "" { - t.Fatal("empty service error message") - } -} - -func TestLocationPollingReturnsWrappedError(t *testing.T) { - resp := newSimpleLocationResp() - pt, err := createPollingTracker(resp) - if err != nil { - t.Fatalf("failed to create tracker: %v", err) - } - sender := mocks.NewSender() - sender.AppendResponse(newProvisioningStatusErrorResponse("Failed")) - err = pt.pollForStatus(context.Background(), sender) - if err == nil { - t.Fatal("unexpected nil polling error") - } - err = pt.pollingError() - if err == nil { - t.Fatal("unexpected nil polling error") - } - if se, ok := err.(*ServiceError); !ok { - t.Fatal("incorrect error type") - } else if se.Code == "" { - t.Fatal("empty service error code") - } else if se.Message == "" { - t.Fatal("empty service error message") - } -} - -func TestLocationPollingReturnsUnwrappedError(t *testing.T) { - resp := newSimpleLocationResp() - pt, err := createPollingTracker(resp) - if err != nil { - t.Fatalf("failed to create tracker: %v", err) - } - sender := mocks.NewSender() - sender.AppendResponse(newProvisioningStatusUnwrappedErrorResponse("Failed")) - err = pt.pollForStatus(context.Background(), sender) - if err == nil { - t.Fatal("unexpected nil polling error") - } - err = pt.pollingError() - if err == nil { - t.Fatal("unexpected nil polling error") - } - if se, ok := err.(*ServiceError); !ok { - t.Fatal("incorrect error type") - } else if se.Code == "" { - t.Fatal("empty service error code") - } else if se.Message == "" { - t.Fatal("empty service error message") - } -} - -// DoPollForAsynchronous (legacy so not many tests plus it builds on Future which has more tests) - -func TestDoPollForAsynchronous_Success(t *testing.T) { - r1 := newSimpleAsyncResp() - r2 := newOperationResourceResponse("busy") - r3 := newOperationResourceResponse(operationSucceeded) - - sender := mocks.NewSender() - sender.AppendResponse(r1) - sender.AppendAndRepeatResponse(r2, 2) - sender.AppendAndRepeatResponse(r3, 1) - - r, err := autorest.SendWithSender(sender, newAsyncReq(http.MethodPut, nil), DoPollForAsynchronous(time.Millisecond)) - if err != nil { - t.Fatalf("failed to poll for status: %v", err) - } - - if sender.Attempts() < sender.NumResponses() { - t.Fatal("DoPollForAsynchronous stopped polling before receiving a terminated OperationResource") - } - autorest.Respond(r, autorest.ByClosing()) -} - -func TestDoPollForAsynchronous_Failed(t *testing.T) { - r1 := newSimpleAsyncResp() - r2 := newOperationResourceResponse("busy") - r3 := newOperationResourceErrorResponse(operationFailed) - - sender := mocks.NewSender() - sender.AppendResponse(r1) - sender.AppendAndRepeatResponse(r2, 2) - sender.AppendAndRepeatResponse(r3, 1) - - r, err := autorest.SendWithSender(sender, newAsyncReq(http.MethodPut, nil), DoPollForAsynchronous(time.Millisecond)) - if err == nil { - t.Fatal("unexpected nil error when polling") - } - if se, ok := err.(*ServiceError); !ok { - t.Fatal("incorrect error type") - } else if se.Code == "" { - t.Fatal("empty service error code") - } else if se.Message == "" { - t.Fatal("empty service error message") - } - - if sender.Attempts() < sender.NumResponses() { - t.Fatalf("DoPollForAsynchronous stopped polling before receiving a terminated OperationResource") - } - autorest.Respond(r, autorest.ByClosing()) -} - -func TestDoPollForAsynchronous_CanBeCanceled(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - delay := 5 * time.Second - - r1 := newSimpleAsyncResp() - - sender := mocks.NewSender() - sender.AppendResponse(r1) - sender.AppendAndRepeatResponse(newOperationResourceResponse("Busy"), -1) - - var wg sync.WaitGroup - wg.Add(1) - start := time.Now() - end := time.Now() - var err error - go func() { - req := newAsyncReq(http.MethodPut, nil) - req = req.WithContext(ctx) - var r *http.Response - r, err = autorest.SendWithSender(sender, req, DoPollForAsynchronous(delay)) - autorest.Respond(r, autorest.ByClosing()) - end = time.Now() - wg.Done() - }() - cancel() - wg.Wait() - time.Sleep(5 * time.Millisecond) - if err == nil { - t.Fatalf("DoPollForAsynchronous didn't cancel") - } - if end.Sub(start) >= delay { - t.Fatalf("DoPollForAsynchronous failed to cancel") - } -} - -func TestFuture_PollsUntilProvisioningStatusSucceeds(t *testing.T) { - r2 := newOperationResourceResponse("busy") - r3 := newOperationResourceResponse(operationSucceeded) - - sender := mocks.NewSender() - ctx := context.Background() - sender.AppendAndRepeatResponse(r2, 2) - sender.AppendResponse(r3) - - future, err := NewFutureFromResponse(newSimpleAsyncResp()) - if err != nil { - t.Fatalf("failed to create future: %v", err) - } - - for done, err := future.DoneWithContext(ctx, sender); !done; done, err = future.DoneWithContext(ctx, sender) { - if future.PollingMethod() != PollingAsyncOperation { - t.Fatalf("wrong future polling method: %s", future.PollingMethod()) - } - if err != nil { - t.Fatalf("polling Done failed: %v", err) - } - delay, ok := future.GetPollingDelay() - if !ok { - t.Fatalf("expected Retry-After value") - } - time.Sleep(delay) - } - - if sender.Attempts() < sender.NumResponses() { - t.Fatalf("stopped polling before receiving a terminated OperationResource") - } - - autorest.Respond(future.Response(), - autorest.ByClosing()) -} - -func TestFuture_MarshallingSuccess(t *testing.T) { - future, err := NewFutureFromResponse(newSimpleAsyncResp()) - if err != nil { - t.Fatalf("failed to create future: %v", err) - } - - data, err := json.Marshal(future) - if err != nil { - t.Fatalf("failed to marshal: %v", err) - } - - var future2 Future - err = json.Unmarshal(data, &future2) - if err != nil { - t.Fatalf("failed to unmarshal: %v", err) - } - - if reflect.DeepEqual(future.pt, future2.pt) { - t.Fatalf("marshalling unexpected match") - } - - // these fields don't get marshalled so nil them before deep comparison - future.pt.(*pollingTrackerPut).resp = nil - future.pt.(*pollingTrackerPut).rawBody = nil - if !reflect.DeepEqual(future.pt, future2.pt) { - t.Fatalf("marshalling futures don't match") - } -} - -func TestFuture_MarshallingWithError(t *testing.T) { - r2 := newOperationResourceResponse("busy") - r3 := newOperationResourceErrorResponse(operationFailed) - - sender := mocks.NewSender() - sender.AppendAndRepeatResponse(r2, 2) - sender.AppendResponse(r3) - client := autorest.Client{ - PollingDelay: 1 * time.Second, - PollingDuration: autorest.DefaultPollingDuration, - RetryAttempts: autorest.DefaultRetryAttempts, - RetryDuration: 1 * time.Second, - Sender: sender, - } - - future, err := NewFutureFromResponse(newSimpleAsyncResp()) - if err != nil { - t.Fatalf("failed to create future: %v", err) - } - - err = future.WaitForCompletion(context.Background(), client) - if err == nil { - t.Fatal("expected non-nil error") - } - - data, err := json.Marshal(future) - if err != nil { - t.Fatalf("failed to marshal: %v", err) - } - - var future2 Future - err = json.Unmarshal(data, &future2) - if err != nil { - t.Fatalf("failed to unmarshal: %v", err) - } - - if reflect.DeepEqual(future.pt, future2.pt) { - t.Fatalf("marshalling unexpected match") - } - - // these fields don't get marshalled so nil them before deep comparison - future.pt.(*pollingTrackerPut).resp = nil - future.pt.(*pollingTrackerPut).rawBody = nil - if !reflect.DeepEqual(future.pt, future2.pt) { - t.Fatalf("marshalling futures don't match") - } -} - -func TestFuture_CreateFromFailedOperation(t *testing.T) { - _, err := NewFutureFromResponse(newAsyncResponseWithError(http.MethodPut)) - if err == nil { - t.Fatal("expected non-nil error") - } -} - -func TestFuture_WaitForCompletion(t *testing.T) { - r2 := newOperationResourceResponse("busy") - r3 := newOperationResourceResponse(operationSucceeded) - - sender := mocks.NewSender() - sender.AppendAndRepeatResponse(r2, 2) - sender.AppendResponse(r3) - client := autorest.Client{ - PollingDelay: 1 * time.Second, - PollingDuration: autorest.DefaultPollingDuration, - RetryAttempts: autorest.DefaultRetryAttempts, - RetryDuration: 1 * time.Second, - Sender: sender, - } - - future, err := NewFutureFromResponse(newSimpleAsyncResp()) - if err != nil { - t.Fatalf("failed to create future: %v", err) - } - - err = future.WaitForCompletion(context.Background(), client) - if err != nil { - t.Fatalf("WaitForCompletion returned non-nil error") - } - - if sender.Attempts() < sender.NumResponses() { - t.Fatalf("stopped polling before receiving a terminated OperationResource") - } - - autorest.Respond(future.Response(), - autorest.ByClosing()) -} - -func TestFuture_WaitForCompletionRef(t *testing.T) { - r2 := newOperationResourceResponse("busy") - r3 := newOperationResourceResponse(operationSucceeded) - - sender := mocks.NewSender() - sender.AppendAndRepeatResponse(r2, 2) - sender.AppendResponse(r3) - client := autorest.Client{ - PollingDelay: 1 * time.Second, - PollingDuration: autorest.DefaultPollingDuration, - RetryAttempts: autorest.DefaultRetryAttempts, - RetryDuration: 1 * time.Second, - Sender: sender, - } - - future, err := NewFutureFromResponse(newSimpleAsyncResp()) - if err != nil { - t.Fatalf("failed to create future: %v", err) - } - - err = future.WaitForCompletionRef(context.Background(), client) - if err != nil { - t.Fatalf("WaitForCompletion returned non-nil error") - } - - if sender.Attempts() < sender.NumResponses() { - t.Fatalf("stopped polling before receiving a terminated OperationResource") - } - - autorest.Respond(future.Response(), - autorest.ByClosing()) -} - -func TestFuture_WaitForCompletionTimedOut(t *testing.T) { - r2 := newProvisioningStatusResponse("busy") - - sender := mocks.NewSender() - sender.AppendAndRepeatResponseWithDelay(r2, 1*time.Second, 5) - - future, err := NewFutureFromResponse(newSimpleAsyncResp()) - if err != nil { - t.Fatalf("failed to create future: %v", err) - } - - client := autorest.Client{ - PollingDelay: autorest.DefaultPollingDelay, - PollingDuration: 2 * time.Second, - RetryAttempts: autorest.DefaultRetryAttempts, - RetryDuration: 1 * time.Second, - Sender: sender, - } - - err = future.WaitForCompletionRef(context.Background(), client) - if err == nil { - t.Fatalf("WaitForCompletion returned nil error, should have timed out") - } -} - -func TestFuture_WaitForCompletionRetriesExceeded(t *testing.T) { - r1 := newProvisioningStatusResponse("InProgress") - - sender := mocks.NewSender() - sender.AppendResponse(r1) - sender.AppendAndRepeatError(errors.New("transient network failure"), autorest.DefaultRetryAttempts+1) - - future, err := NewFutureFromResponse(newSimpleAsyncResp()) - if err != nil { - t.Fatalf("failed to create future: %v", err) - } - - client := autorest.Client{ - PollingDelay: autorest.DefaultPollingDelay, - PollingDuration: autorest.DefaultPollingDuration, - RetryAttempts: autorest.DefaultRetryAttempts, - RetryDuration: 100 * time.Millisecond, - Sender: sender, - } - - err = future.WaitForCompletionRef(context.Background(), client) - if err == nil { - t.Fatalf("WaitForCompletion returned nil error, should have errored out") - } -} - -func TestFuture_WaitForCompletionCancelled(t *testing.T) { - r1 := newProvisioningStatusResponse("InProgress") - - sender := mocks.NewSender() - sender.AppendAndRepeatResponseWithDelay(r1, 1*time.Second, 5) - - future, err := NewFutureFromResponse(newSimpleAsyncResp()) - if err != nil { - t.Fatalf("failed to create future: %v", err) - } - - client := autorest.Client{ - PollingDelay: autorest.DefaultPollingDelay, - PollingDuration: autorest.DefaultPollingDuration, - RetryAttempts: autorest.DefaultRetryAttempts, - RetryDuration: autorest.DefaultRetryDuration, - Sender: sender, - } - - ctx, cancel := context.WithCancel(context.Background()) - go func() { - time.Sleep(2 * time.Second) - cancel() - }() - - err = future.WaitForCompletionRef(ctx, client) - if err == nil { - t.Fatalf("WaitForCompletion returned nil error, should have been cancelled") - } -} - -func TestFuture_GetResultFromNonAsyncOperation(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodPost, nil), http.StatusOK, mocks.NewBody(someResource)) - future, err := NewFutureFromResponse(resp) - if err != nil { - t.Fatalf("failed to create tracker: %v", err) - } - if pm := future.PollingMethod(); pm != PollingUnknown { - t.Fatalf("wrong polling method: %s", pm) - } - done, err := future.DoneWithContext(context.Background(), nil) - if err != nil { - t.Fatalf("failed to check status: %v", err) - } - if !done { - t.Fatal("operation should be done") - } - res, err := future.GetResult(nil) - if err != nil { - t.Fatalf("failed to get result: %v", err) - } - if res != resp { - t.Fatal("result and response don't match") - } -} - -func TestFuture_GetResultNonTerminal(t *testing.T) { - resp := newAsyncResp(newAsyncReq(http.MethodDelete, nil), http.StatusAccepted, mocks.NewBody(fmt.Sprintf(operationResourceFormat, operationInProgress))) - mocks.SetResponseHeader(resp, headerAsyncOperation, mocks.TestAzureAsyncURL) - future, err := NewFutureFromResponse(resp) - if err != nil { - t.Fatalf("failed to create future: %v", err) - } - res, err := future.GetResult(nil) - if err == nil { - t.Fatal("expected non-nil error") - } - if res != nil { - t.Fatal("expected nil result") - } -} - -const ( - operationResourceIllegal = ` - This is not JSON and should fail...badly. - ` - - // returned from LROs that use Location header - pollingStateFormat = ` - { - "unused" : { - "somefield" : 42 - }, - "properties" : { - "provisioningState": "%s" - } - } - ` - - // returned from LROs that use Location header - errorResponse = ` - { - "error" : { - "code" : "InvalidParameter", - "message" : "tom-service-DISCOVERY-server-base-v1.core.local' is not a valid captured VHD blob name prefix." - } - } - ` - - // returned from LROs that use Location header - unwrappedErrorResponse = ` - { - "code" : "InvalidParameter", - "message" : "tom-service-DISCOVERY-server-base-v1.core.local' is not a valid captured VHD blob name prefix." - } - ` - - // returned from LROs that use Location header - pollingStateEmpty = ` - { - "unused" : { - "somefield" : 42 - }, - "properties" : { - } - } - ` - - // returned from LROs that use Azure-AsyncOperation header - operationResourceFormat = ` - { - "id": "/subscriptions/id/locations/westus/operationsStatus/sameguid", - "name": "sameguid", - "status" : "%s", - "startTime" : "2006-01-02T15:04:05Z", - "endTime" : "2006-01-02T16:04:05Z", - "percentComplete" : 50.00, - "properties" : { - "foo": "bar" - } - } - ` - - // returned from LROs that use Azure-AsyncOperation header - operationResourceErrorFormat = ` - { - "id": "/subscriptions/id/locations/westus/operationsStatus/sameguid", - "name": "sameguid", - "status" : "%s", - "startTime" : "2006-01-02T15:04:05Z", - "endTime" : "2006-01-02T16:04:05Z", - "percentComplete" : 50.00, - "properties" : {}, - "error" : { - "code" : "BadArgument", - "message" : "The provided database 'foo' has an invalid username." - } - } - ` - - // returned from an operation marked as LRO but really isn't - someResource = ` - { - "id": "/subscriptions/guid/resourceGroups/rg/providers/something/else/thing", - "name": "thing", - "type": "Imaginary.type", - "location": "Central US", - "properties": {} - } - ` -) - -// creates an async request with the specified body. -func newAsyncReq(reqMethod string, body *mocks.Body) *http.Request { - return mocks.NewRequestWithParams(reqMethod, mocks.TestURL, body) -} - -// creates an async response with the specified body. -// the req param is the originating LRO request. -func newAsyncResp(req *http.Request, statusCode int, body *mocks.Body) *http.Response { - status := "Unknown" - switch statusCode { - case http.StatusOK, http.StatusNoContent: - status = "Completed" - case http.StatusCreated: - status = "Creating" - case http.StatusAccepted: - status = "In progress" - case http.StatusBadRequest: - status = "Bad request" - } - r := mocks.NewResponseWithBodyAndStatus(body, statusCode, status) - r.Request = req - return r -} - -// creates a simple LRO response, PUT/201 with Azure-AsyncOperation header -func newSimpleAsyncResp() *http.Response { - r := newAsyncResp(newAsyncReq(http.MethodPut, nil), http.StatusCreated, mocks.NewBody(fmt.Sprintf(operationResourceFormat, operationInProgress))) - mocks.SetResponseHeader(r, headerAsyncOperation, mocks.TestAzureAsyncURL) - return r -} - -// creates a simple LRO response, POST/201 with Location header -func newSimpleLocationResp() *http.Response { - r := newAsyncResp(newAsyncReq(http.MethodPost, nil), http.StatusCreated, mocks.NewBody(fmt.Sprintf(pollingStateFormat, operationInProgress))) - mocks.SetResponseHeader(r, autorest.HeaderLocation, mocks.TestLocationURL) - return r -} - -// creates an async response that contains an error (HTTP 400 + error response body) -func newAsyncResponseWithError(reqMethod string) *http.Response { - return newAsyncResp(newAsyncReq(reqMethod, nil), http.StatusBadRequest, mocks.NewBody(errorResponse)) -} - -// creates a LRO polling response using the operation resource format (Azure-AsyncOperation LROs) -func newOperationResourceResponse(status string) *http.Response { - r := mocks.NewResponseWithBodyAndStatus(mocks.NewBody(fmt.Sprintf(operationResourceFormat, status)), http.StatusOK, status) - mocks.SetRetryHeader(r, retryDelay) - return r -} - -// creates a LRO polling error response using the operation resource format (Azure-AsyncOperation LROs) -func newOperationResourceErrorResponse(status string) *http.Response { - return mocks.NewResponseWithBodyAndStatus(mocks.NewBody(fmt.Sprintf(operationResourceErrorFormat, status)), http.StatusBadRequest, status) -} - -// creates a LRO polling response using the provisioning state format (Location LROs) -func newProvisioningStatusResponse(status string) *http.Response { - r := mocks.NewResponseWithBodyAndStatus(mocks.NewBody(fmt.Sprintf(pollingStateFormat, status)), http.StatusOK, status) - mocks.SetRetryHeader(r, retryDelay) - return r -} - -// creates a LRO polling error response using the provisioning state format (Location LROs) -func newProvisioningStatusErrorResponse(status string) *http.Response { - return mocks.NewResponseWithBodyAndStatus(mocks.NewBody(errorResponse), http.StatusBadRequest, status) -} - -// creates a LRO polling unwrapped error response using the provisioning state format (Location LROs) -func newProvisioningStatusUnwrappedErrorResponse(status string) *http.Response { - return mocks.NewResponseWithBodyAndStatus(mocks.NewBody(unwrappedErrorResponse), http.StatusBadRequest, status) -} - -// adds the Azure-AsyncOperation header with the specified location to the response -func setAsyncOpHeader(resp *http.Response, location string) { - mocks.SetResponseHeader(resp, http.CanonicalHeaderKey(headerAsyncOperation), location) -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/azure_test.go b/vendor/github.com/Azure/go-autorest/autorest/azure/azure_test.go deleted file mode 100644 index a99ccae7..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/azure/azure_test.go +++ /dev/null @@ -1,668 +0,0 @@ -package azure - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "reflect" - "strconv" - "testing" - "time" - - "github.com/Azure/go-autorest/autorest" - "github.com/Azure/go-autorest/autorest/mocks" -) - -const ( - headerAuthorization = "Authorization" - longDelay = 5 * time.Second - retryDelay = 10 * time.Millisecond - testLogPrefix = "azure:" -) - -// Use a Client Inspector to set the request identifier. -func ExampleWithClientID() { - uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" - req, _ := autorest.Prepare(&http.Request{}, - autorest.AsGet(), - autorest.WithBaseURL("https://microsoft.com/a/b/c/")) - - c := autorest.Client{Sender: mocks.NewSender()} - c.RequestInspector = WithReturningClientID(uuid) - - autorest.SendWithSender(c, req) - fmt.Printf("Inspector added the %s header with the value %s\n", - HeaderClientID, req.Header.Get(HeaderClientID)) - fmt.Printf("Inspector added the %s header with the value %s\n", - HeaderReturnClientID, req.Header.Get(HeaderReturnClientID)) - // Output: - // Inspector added the x-ms-client-request-id header with the value 71FDB9F4-5E49-4C12-B266-DE7B4FD999A6 - // Inspector added the x-ms-return-client-request-id header with the value true -} - -func TestWithReturningClientIDReturnsError(t *testing.T) { - var errIn error - uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" - _, errOut := autorest.Prepare(&http.Request{}, - withErrorPrepareDecorator(&errIn), - WithReturningClientID(uuid)) - - if errOut == nil || errIn != errOut { - t.Fatalf("azure: WithReturningClientID failed to exit early when receiving an error -- expected (%v), received (%v)", - errIn, errOut) - } -} - -func TestWithClientID(t *testing.T) { - uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" - req, _ := autorest.Prepare(&http.Request{}, - WithClientID(uuid)) - - if req.Header.Get(HeaderClientID) != uuid { - t.Fatalf("azure: WithClientID failed to set %s -- expected %s, received %s", - HeaderClientID, uuid, req.Header.Get(HeaderClientID)) - } -} - -func TestWithReturnClientID(t *testing.T) { - b := false - req, _ := autorest.Prepare(&http.Request{}, - WithReturnClientID(b)) - - if req.Header.Get(HeaderReturnClientID) != strconv.FormatBool(b) { - t.Fatalf("azure: WithReturnClientID failed to set %s -- expected %s, received %s", - HeaderClientID, strconv.FormatBool(b), req.Header.Get(HeaderClientID)) - } -} - -func TestExtractClientID(t *testing.T) { - uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" - resp := mocks.NewResponse() - mocks.SetResponseHeader(resp, HeaderClientID, uuid) - - if ExtractClientID(resp) != uuid { - t.Fatalf("azure: ExtractClientID failed to extract the %s -- expected %s, received %s", - HeaderClientID, uuid, ExtractClientID(resp)) - } -} - -func TestExtractRequestID(t *testing.T) { - uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" - resp := mocks.NewResponse() - mocks.SetResponseHeader(resp, HeaderRequestID, uuid) - - if ExtractRequestID(resp) != uuid { - t.Fatalf("azure: ExtractRequestID failed to extract the %s -- expected %s, received %s", - HeaderRequestID, uuid, ExtractRequestID(resp)) - } -} - -func TestIsAzureError_ReturnsTrueForAzureError(t *testing.T) { - if !IsAzureError(&RequestError{}) { - t.Fatalf("azure: IsAzureError failed to return true for an Azure Service error") - } -} - -func TestIsAzureError_ReturnsFalseForNonAzureError(t *testing.T) { - if IsAzureError(fmt.Errorf("An Error")) { - t.Fatalf("azure: IsAzureError return true for an non-Azure Service error") - } -} - -func TestNewErrorWithError_UsesReponseStatusCode(t *testing.T) { - e := NewErrorWithError(fmt.Errorf("Error"), "packageType", "method", mocks.NewResponseWithStatus("Forbidden", http.StatusForbidden), "message") - if e.StatusCode != http.StatusForbidden { - t.Fatalf("azure: NewErrorWithError failed to use the Status Code of the passed Response -- expected %v, received %v", http.StatusForbidden, e.StatusCode) - } -} - -func TestNewErrorWithError_ReturnsUnwrappedError(t *testing.T) { - e1 := RequestError{} - e1.ServiceError = &ServiceError{Code: "42", Message: "A Message"} - e1.StatusCode = 200 - e1.RequestID = "A RequestID" - e2 := NewErrorWithError(&e1, "packageType", "method", nil, "message") - - if !reflect.DeepEqual(e1, e2) { - t.Fatalf("azure: NewErrorWithError wrapped an RequestError -- expected %T, received %T", e1, e2) - } -} - -func TestNewErrorWithError_WrapsAnError(t *testing.T) { - e1 := fmt.Errorf("Inner Error") - var e2 interface{} = NewErrorWithError(e1, "packageType", "method", nil, "message") - - if _, ok := e2.(RequestError); !ok { - t.Fatalf("azure: NewErrorWithError failed to wrap a standard error -- received %T", e2) - } -} - -func TestWithErrorUnlessStatusCode_NotAnAzureError(t *testing.T) { - body := ` - - IIS Error page - - Some non-JSON error page - ` - r := mocks.NewResponseWithContent(body) - r.Request = mocks.NewRequest() - r.StatusCode = http.StatusBadRequest - r.Status = http.StatusText(r.StatusCode) - - err := autorest.Respond(r, - WithErrorUnlessStatusCode(http.StatusOK), - autorest.ByClosing()) - ok, _ := err.(*RequestError) - if ok != nil { - t.Fatalf("azure: azure.RequestError returned from malformed response: %v", err) - } - - // the error body should still be there - defer r.Body.Close() - b, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatal(err) - } - if string(b) != body { - t.Fatalf("response body is wrong. got=%q exptected=%q", string(b), body) - } -} - -func TestWithErrorUnlessStatusCode_FoundAzureErrorWithoutDetails(t *testing.T) { - j := `{ - "error": { - "code": "InternalError", - "message": "Azure is having trouble right now." - } - }` - uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" - r := mocks.NewResponseWithContent(j) - mocks.SetResponseHeader(r, HeaderRequestID, uuid) - r.Request = mocks.NewRequest() - r.StatusCode = http.StatusInternalServerError - r.Status = http.StatusText(r.StatusCode) - - err := autorest.Respond(r, - WithErrorUnlessStatusCode(http.StatusOK), - autorest.ByClosing()) - - if err == nil { - t.Fatalf("azure: returned nil error for proper error response") - } - azErr, ok := err.(*RequestError) - if !ok { - t.Fatalf("azure: returned error is not azure.RequestError: %T", err) - } - - expected := "autorest/azure: Service returned an error. Status=500 Code=\"InternalError\" Message=\"Azure is having trouble right now.\"" - if !reflect.DeepEqual(expected, azErr.Error()) { - t.Fatalf("azure: service error is not unmarshaled properly.\nexpected=%v\ngot=%v", expected, azErr.Error()) - } - - if expected := http.StatusInternalServerError; azErr.StatusCode != expected { - t.Fatalf("azure: got wrong StatusCode=%d Expected=%d", azErr.StatusCode, expected) - } - if expected := uuid; azErr.RequestID != expected { - t.Fatalf("azure: wrong request ID in error. expected=%q; got=%q", expected, azErr.RequestID) - } - - _ = azErr.Error() - - // the error body should still be there - defer r.Body.Close() - b, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatal(err) - } - if string(b) != j { - t.Fatalf("response body is wrong. got=%q expected=%q", string(b), j) - } - -} - -func TestWithErrorUnlessStatusCode_FoundAzureFullError(t *testing.T) { - j := `{ - "error": { - "code": "InternalError", - "message": "Azure is having trouble right now.", - "target": "target1", - "details": [{"code": "conflict1", "message":"error message1"}, - {"code": "conflict2", "message":"error message2"}], - "innererror": { "customKey": "customValue" }, - "additionalInfo": [{"type": "someErrorType", "info": {"someProperty": "someValue"}}] - } - }` - uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" - r := mocks.NewResponseWithContent(j) - mocks.SetResponseHeader(r, HeaderRequestID, uuid) - r.Request = mocks.NewRequest() - r.StatusCode = http.StatusInternalServerError - r.Status = http.StatusText(r.StatusCode) - - err := autorest.Respond(r, - WithErrorUnlessStatusCode(http.StatusOK), - autorest.ByClosing()) - - if err == nil { - t.Fatalf("azure: returned nil error for proper error response") - } - azErr, ok := err.(*RequestError) - if !ok { - t.Fatalf("azure: returned error is not azure.RequestError: %T", err) - } - - if expected := "InternalError"; azErr.ServiceError.Code != expected { - t.Fatalf("azure: wrong error code. expected=%q; got=%q", expected, azErr.ServiceError.Code) - } - - if azErr.ServiceError.Message == "" { - t.Fatalf("azure: error message is not unmarshaled properly") - } - - if *azErr.ServiceError.Target == "" { - t.Fatalf("azure: error target is not unmarshaled properly") - } - - d, _ := json.Marshal(azErr.ServiceError.Details) - if string(d) != `[{"code":"conflict1","message":"error message1"},{"code":"conflict2","message":"error message2"}]` { - t.Fatalf("azure: error details is not unmarshaled properly") - } - - i, _ := json.Marshal(azErr.ServiceError.InnerError) - if string(i) != `{"customKey":"customValue"}` { - t.Fatalf("azure: inner error is not unmarshaled properly") - } - - a, _ := json.Marshal(azErr.ServiceError.AdditionalInfo) - if string(a) != `[{"info":{"someProperty":"someValue"},"type":"someErrorType"}]` { - t.Fatalf("azure: error additional info is not unmarshaled properly") - } - - if expected := http.StatusInternalServerError; azErr.StatusCode != expected { - t.Fatalf("azure: got wrong StatusCode=%v Expected=%d", azErr.StatusCode, expected) - } - if expected := uuid; azErr.RequestID != expected { - t.Fatalf("azure: wrong request ID in error. expected=%q; got=%q", expected, azErr.RequestID) - } - - _ = azErr.Error() - - // the error body should still be there - defer r.Body.Close() - b, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatal(err) - } - if string(b) != j { - t.Fatalf("response body is wrong. got=%q expected=%q", string(b), j) - } - -} - -func TestWithErrorUnlessStatusCode_NoAzureError(t *testing.T) { - j := `{ - "Status":"NotFound" - }` - uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" - r := mocks.NewResponseWithContent(j) - mocks.SetResponseHeader(r, HeaderRequestID, uuid) - r.Request = mocks.NewRequest() - r.StatusCode = http.StatusInternalServerError - r.Status = http.StatusText(r.StatusCode) - - err := autorest.Respond(r, - WithErrorUnlessStatusCode(http.StatusOK), - autorest.ByClosing()) - if err == nil { - t.Fatalf("azure: returned nil error for proper error response") - } - azErr, ok := err.(*RequestError) - if !ok { - t.Fatalf("azure: returned error is not azure.RequestError: %T", err) - } - - expected := &ServiceError{ - Code: "Unknown", - Message: "Unknown service error", - Details: []map[string]interface{}{ - {"Status": "NotFound"}, - }, - } - - if !reflect.DeepEqual(expected, azErr.ServiceError) { - t.Fatalf("azure: service error is not unmarshaled properly. expected=%q\ngot=%q", expected, azErr.ServiceError) - } - - if expected := http.StatusInternalServerError; azErr.StatusCode != expected { - t.Fatalf("azure: got wrong StatusCode=%v Expected=%d", azErr.StatusCode, expected) - } - if expected := uuid; azErr.RequestID != expected { - t.Fatalf("azure: wrong request ID in error. expected=%q; got=%q", expected, azErr.RequestID) - } - - _ = azErr.Error() - - // the error body should still be there - defer r.Body.Close() - b, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatal(err) - } - if string(b) != j { - t.Fatalf("response body is wrong. got=%q expected=%q", string(b), j) - } - -} - -func TestWithErrorUnlessStatusCode_UnwrappedError(t *testing.T) { - j := `{ - "code": "InternalError", - "message": "Azure is having trouble right now.", - "target": "target1", - "details": [{"code": "conflict1", "message":"error message1"}, - {"code": "conflict2", "message":"error message2"}], - "innererror": { "customKey": "customValue" }, - "additionalInfo": [{"type": "someErrorType", "info": {"someProperty": "someValue"}}] - }` - uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" - r := mocks.NewResponseWithContent(j) - mocks.SetResponseHeader(r, HeaderRequestID, uuid) - r.Request = mocks.NewRequest() - r.StatusCode = http.StatusInternalServerError - r.Status = http.StatusText(r.StatusCode) - - err := autorest.Respond(r, - WithErrorUnlessStatusCode(http.StatusOK), - autorest.ByClosing()) - - if err == nil { - t.Fatal("azure: returned nil error for proper error response") - } - - azErr, ok := err.(*RequestError) - if !ok { - t.Fatalf("returned error is not azure.RequestError: %T", err) - } - - if expected := http.StatusInternalServerError; azErr.StatusCode != expected { - t.Logf("Incorrect StatusCode got: %v want: %d", azErr.StatusCode, expected) - t.Fail() - } - - if expected := "Azure is having trouble right now."; azErr.Message != expected { - t.Logf("Incorrect Message\n\tgot: %q\n\twant: %q", azErr.Message, expected) - t.Fail() - } - - if expected := uuid; azErr.RequestID != expected { - t.Logf("Incorrect request ID\n\tgot: %q\n\twant: %q", azErr.RequestID, expected) - t.Fail() - } - - if azErr.ServiceError == nil { - t.Logf("`ServiceError` was nil when it shouldn't have been.") - t.Fail() - } - - if expected := "target1"; *azErr.ServiceError.Target != expected { - t.Logf("Incorrect Target\n\tgot: %q\n\twant: %q", *azErr.ServiceError.Target, expected) - t.Fail() - } - - expectedServiceErrorDetails := `[{"code":"conflict1","message":"error message1"},{"code":"conflict2","message":"error message2"}]` - if azErr.ServiceError.Details == nil { - t.Logf("`ServiceError.Details` was nil when it should have been %q", expectedServiceErrorDetails) - t.Fail() - } else if details, _ := json.Marshal(azErr.ServiceError.Details); expectedServiceErrorDetails != string(details) { - t.Logf("Error details was not unmarshaled properly.\n\tgot: %q\n\twant: %q", string(details), expectedServiceErrorDetails) - t.Fail() - } - - expectedServiceErrorInnerError := `{"customKey":"customValue"}` - if azErr.ServiceError.InnerError == nil { - t.Logf("`ServiceError.InnerError` was nil when it should have been %q", expectedServiceErrorInnerError) - t.Fail() - } else if innerError, _ := json.Marshal(azErr.ServiceError.InnerError); expectedServiceErrorInnerError != string(innerError) { - t.Logf("Inner error was not unmarshaled properly.\n\tgot: %q\n\twant: %q", string(innerError), expectedServiceErrorInnerError) - t.Fail() - } - - expectedServiceErrorAdditionalInfo := `[{"info":{"someProperty":"someValue"},"type":"someErrorType"}]` - if azErr.ServiceError.AdditionalInfo == nil { - t.Logf("`ServiceError.AdditionalInfo` was nil when it should have been %q", expectedServiceErrorAdditionalInfo) - t.Fail() - } else if additionalInfo, _ := json.Marshal(azErr.ServiceError.AdditionalInfo); expectedServiceErrorAdditionalInfo != string(additionalInfo) { - t.Logf("Additional info was not unmarshaled properly.\n\tgot: %q\n\twant: %q", string(additionalInfo), expectedServiceErrorAdditionalInfo) - t.Fail() - } - - // the error body should still be there - defer r.Body.Close() - b, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Error(err) - } - if string(b) != j { - t.Fatalf("response body is wrong. got=%q expected=%q", string(b), j) - } - -} - -func TestRequestErrorString_WithError(t *testing.T) { - j := `{ - "error": { - "code": "InternalError", - "message": "Conflict", - "target": "target1", - "details": [{"code": "conflict1", "message":"error message1"}], - "innererror": { "customKey": "customValue" }, - "additionalInfo": [{"type": "someErrorType", "info": {"someProperty": "someValue"}}] - } - }` - uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" - r := mocks.NewResponseWithContent(j) - mocks.SetResponseHeader(r, HeaderRequestID, uuid) - r.Request = mocks.NewRequest() - r.StatusCode = http.StatusInternalServerError - r.Status = http.StatusText(r.StatusCode) - - err := autorest.Respond(r, - WithErrorUnlessStatusCode(http.StatusOK), - autorest.ByClosing()) - - if err == nil { - t.Fatalf("azure: returned nil error for proper error response") - } - azErr, _ := err.(*RequestError) - expected := "autorest/azure: Service returned an error. Status=500 Code=\"InternalError\" Message=\"Conflict\" Target=\"target1\" Details=[{\"code\":\"conflict1\",\"message\":\"error message1\"}] InnerError={\"customKey\":\"customValue\"} AdditionalInfo=[{\"info\":{\"someProperty\":\"someValue\"},\"type\":\"someErrorType\"}]" - if expected != azErr.Error() { - t.Fatalf("azure: send wrong RequestError.\nexpected=%v\ngot=%v", expected, azErr.Error()) - } -} - -func TestRequestErrorString_WithErrorNonConforming(t *testing.T) { - j := `{ - "error": { - "code": "InternalError", - "message": "Conflict", - "details": {"code": "conflict1", "message":"error message1"} - } - }` - uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" - r := mocks.NewResponseWithContent(j) - mocks.SetResponseHeader(r, HeaderRequestID, uuid) - r.Request = mocks.NewRequest() - r.StatusCode = http.StatusInternalServerError - r.Status = http.StatusText(r.StatusCode) - - err := autorest.Respond(r, - WithErrorUnlessStatusCode(http.StatusOK), - autorest.ByClosing()) - - if err == nil { - t.Fatalf("azure: returned nil error for proper error response") - } - azErr, _ := err.(*RequestError) - expected := "autorest/azure: Service returned an error. Status=500 Code=\"InternalError\" Message=\"Conflict\" Details=[{\"code\":\"conflict1\",\"message\":\"error message1\"}]" - if expected != azErr.Error() { - t.Fatalf("azure: send wrong RequestError.\nexpected=%v\ngot=%v", expected, azErr.Error()) - } -} - -func TestParseResourceID_WithValidBasicResourceID(t *testing.T) { - - basicResourceID := "/subscriptions/subid-3-3-4/resourceGroups/regGroupVladdb/providers/Microsoft.Network/LoadBalancer/testResourceName" - want := Resource{ - SubscriptionID: "subid-3-3-4", - ResourceGroup: "regGroupVladdb", - Provider: "Microsoft.Network", - ResourceType: "LoadBalancer", - ResourceName: "testResourceName", - } - got, err := ParseResourceID(basicResourceID) - - if err != nil { - t.Fatalf("azure: error returned while parsing valid resourceId") - } - - if got != want { - t.Logf("got: %+v\nwant: %+v", got, want) - t.Fail() - } -} - -func TestParseResourceID_WithValidSubResourceID(t *testing.T) { - subresourceID := "/subscriptions/subid-3-3-4/resourceGroups/regGroupVladdb/providers/Microsoft.Network/LoadBalancer/resource/is/a/subresource/actualresourceName" - want := Resource{ - SubscriptionID: "subid-3-3-4", - ResourceGroup: "regGroupVladdb", - Provider: "Microsoft.Network", - ResourceType: "LoadBalancer", - ResourceName: "actualresourceName", - } - got, err := ParseResourceID(subresourceID) - - if err != nil { - t.Fatalf("azure: error returned while parsing valid resourceId") - } - - if got != want { - t.Logf("got: %+v\nwant: %+v", got, want) - t.Fail() - } -} - -func TestParseResourceID_WithIncompleteResourceID(t *testing.T) { - basicResourceID := "/subscriptions/subid-3-3-4/resourceGroups/regGroupVladdb/providers/Microsoft.Network/" - want := Resource{} - - got, err := ParseResourceID(basicResourceID) - - if err == nil { - t.Fatalf("azure: no error returned on incomplete resource id") - } - - if got != want { - t.Logf("got: %+v\nwant: %+v", got, want) - t.Fail() - } -} - -func TestParseResourceID_WithMalformedResourceID(t *testing.T) { - malformedResourceID := "/providers/subid-3-3-4/resourceGroups/regGroupVladdb/subscriptions/Microsoft.Network/LoadBalancer/testResourceName" - want := Resource{} - - got, err := ParseResourceID(malformedResourceID) - - if err == nil { - t.Fatalf("azure: error returned while parsing malformed resourceID") - } - - if got != want { - t.Logf("got: %+v\nwant: %+v", got, want) - t.Fail() - } -} - -func withErrorPrepareDecorator(e *error) autorest.PrepareDecorator { - return func(p autorest.Preparer) autorest.Preparer { - return autorest.PreparerFunc(func(r *http.Request) (*http.Request, error) { - *e = fmt.Errorf("azure: Faux Prepare Error") - return r, *e - }) - } -} - -func withAsyncResponseDecorator(n int) autorest.SendDecorator { - i := 0 - return func(s autorest.Sender) autorest.Sender { - return autorest.SenderFunc(func(r *http.Request) (*http.Response, error) { - resp, err := s.Do(r) - if err == nil { - if i < n { - resp.StatusCode = http.StatusCreated - resp.Header = http.Header{} - resp.Header.Add(http.CanonicalHeaderKey(headerAsyncOperation), mocks.TestURL) - i++ - } else { - resp.StatusCode = http.StatusOK - resp.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - } - } - return resp, err - }) - } -} - -type mockAuthorizer struct{} - -func (ma mockAuthorizer) WithAuthorization() autorest.PrepareDecorator { - return autorest.WithHeader(headerAuthorization, mocks.TestAuthorizationHeader) -} - -type mockFailingAuthorizer struct{} - -func (mfa mockFailingAuthorizer) WithAuthorization() autorest.PrepareDecorator { - return func(p autorest.Preparer) autorest.Preparer { - return autorest.PreparerFunc(func(r *http.Request) (*http.Request, error) { - return r, fmt.Errorf("ERROR: mockFailingAuthorizer returned expected error") - }) - } -} - -type mockInspector struct { - wasInvoked bool -} - -func (mi *mockInspector) WithInspection() autorest.PrepareDecorator { - return func(p autorest.Preparer) autorest.Preparer { - return autorest.PreparerFunc(func(r *http.Request) (*http.Request, error) { - mi.wasInvoked = true - return p.Prepare(r) - }) - } -} - -func (mi *mockInspector) ByInspecting() autorest.RespondDecorator { - return func(r autorest.Responder) autorest.Responder { - return autorest.ResponderFunc(func(resp *http.Response) error { - mi.wasInvoked = true - return r.Respond(resp) - }) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/environments_test.go b/vendor/github.com/Azure/go-autorest/autorest/azure/environments_test.go deleted file mode 100644 index a75adb6f..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/azure/environments_test.go +++ /dev/null @@ -1,348 +0,0 @@ -// test -package azure - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "encoding/json" - "io/ioutil" - "net/http" - "net/http/httptest" - "os" - "path" - "path/filepath" - "runtime" - "testing" -) - -// This correlates to the expected contents of ./testdata/test_environment_1.json -var testEnvironment1 = Environment{ - Name: "--unit-test--", - ManagementPortalURL: "--management-portal-url", - PublishSettingsURL: "--publish-settings-url--", - ServiceManagementEndpoint: "--service-management-endpoint--", - ResourceManagerEndpoint: "--resource-management-endpoint--", - ActiveDirectoryEndpoint: "--active-directory-endpoint--", - GalleryEndpoint: "--gallery-endpoint--", - KeyVaultEndpoint: "--key-vault--endpoint--", - GraphEndpoint: "--graph-endpoint--", - StorageEndpointSuffix: "--storage-endpoint-suffix--", - SQLDatabaseDNSSuffix: "--sql-database-dns-suffix--", - TrafficManagerDNSSuffix: "--traffic-manager-dns-suffix--", - KeyVaultDNSSuffix: "--key-vault-dns-suffix--", - ServiceBusEndpointSuffix: "--service-bus-endpoint-suffix--", - ServiceManagementVMDNSSuffix: "--asm-vm-dns-suffix--", - ResourceManagerVMDNSSuffix: "--arm-vm-dns-suffix--", - ContainerRegistryDNSSuffix: "--container-registry-dns-suffix--", - TokenAudience: "--token-audience", -} - -func TestEnvironment_EnvironmentFromURL_NoOverride_Success(t *testing.T) { - fileContents, _ := ioutil.ReadFile(filepath.Join("testdata", "test_metadata_environment_1.json")) - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) - w.Write([]byte(fileContents)) - })) - defer ts.Close() - - got, err := EnvironmentFromURL(ts.URL) - - if err != nil { - t.Error(err) - } - if got.Name != "HybridEnvironment" { - t.Logf("got: %v want: HybridEnvironment", got.Name) - t.Fail() - } -} - -func TestEnvironment_EnvironmentFromURL_OverrideStorageSuffix_Success(t *testing.T) { - fileContents, _ := ioutil.ReadFile(filepath.Join("testdata", "test_metadata_environment_1.json")) - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) - w.Write([]byte(fileContents)) - })) - defer ts.Close() - overrideProperty := OverrideProperty{ - Key: EnvironmentStorageEndpointSuffix, - Value: "fakeStorageSuffix", - } - got, err := EnvironmentFromURL(ts.URL, overrideProperty) - - if err != nil { - t.Error(err) - } - if got.StorageEndpointSuffix != "fakeStorageSuffix" { - t.Logf("got: %v want: fakeStorageSuffix", got.StorageEndpointSuffix) - t.Fail() - } -} - -func TestEnvironment_EnvironmentFromURL_EmptyEndpoint_Failure(t *testing.T) { - _, err := EnvironmentFromURL("") - - if err == nil { - t.Fail() - } - if err.Error() != "Metadata resource manager endpoint is empty" { - t.Fail() - } -} - -func TestEnvironment_EnvironmentFromFile(t *testing.T) { - got, err := EnvironmentFromFile(filepath.Join("testdata", "test_environment_1.json")) - if err != nil { - t.Error(err) - } - - if got != testEnvironment1 { - t.Logf("got: %v want: %v", got, testEnvironment1) - t.Fail() - } -} - -func TestEnvironment_EnvironmentFromName_Stack(t *testing.T) { - _, currentFile, _, _ := runtime.Caller(0) - prevEnvFilepathValue := os.Getenv(EnvironmentFilepathName) - os.Setenv(EnvironmentFilepathName, filepath.Join(path.Dir(currentFile), "testdata", "test_environment_1.json")) - defer os.Setenv(EnvironmentFilepathName, prevEnvFilepathValue) - - got, err := EnvironmentFromName("AZURESTACKCLOUD") - if err != nil { - t.Error(err) - } - - if got != testEnvironment1 { - t.Logf("got: %v want: %v", got, testEnvironment1) - t.Fail() - } -} - -func TestEnvironmentFromName(t *testing.T) { - name := "azurechinacloud" - if env, _ := EnvironmentFromName(name); env != ChinaCloud { - t.Errorf("Expected to get ChinaCloud for %q", name) - } - - name = "AzureChinaCloud" - if env, _ := EnvironmentFromName(name); env != ChinaCloud { - t.Errorf("Expected to get ChinaCloud for %q", name) - } - - name = "azuregermancloud" - if env, _ := EnvironmentFromName(name); env != GermanCloud { - t.Errorf("Expected to get GermanCloud for %q", name) - } - - name = "AzureGermanCloud" - if env, _ := EnvironmentFromName(name); env != GermanCloud { - t.Errorf("Expected to get GermanCloud for %q", name) - } - - name = "azurepubliccloud" - if env, _ := EnvironmentFromName(name); env != PublicCloud { - t.Errorf("Expected to get PublicCloud for %q", name) - } - - name = "AzurePublicCloud" - if env, _ := EnvironmentFromName(name); env != PublicCloud { - t.Errorf("Expected to get PublicCloud for %q", name) - } - - name = "azureusgovernmentcloud" - if env, _ := EnvironmentFromName(name); env != USGovernmentCloud { - t.Errorf("Expected to get USGovernmentCloud for %q", name) - } - - name = "AzureUSGovernmentCloud" - if env, _ := EnvironmentFromName(name); env != USGovernmentCloud { - t.Errorf("Expected to get USGovernmentCloud for %q", name) - } - - name = "thisisnotarealcloudenv" - if _, err := EnvironmentFromName(name); err == nil { - t.Errorf("Expected to get an error for %q", name) - } -} - -func TestDeserializeEnvironment(t *testing.T) { - env := `{ - "name": "--name--", - "ActiveDirectoryEndpoint": "--active-directory-endpoint--", - "galleryEndpoint": "--gallery-endpoint--", - "graphEndpoint": "--graph-endpoint--", - "serviceBusEndpoint": "--service-bus-endpoint--", - "keyVaultDNSSuffix": "--key-vault-dns-suffix--", - "keyVaultEndpoint": "--key-vault-endpoint--", - "managementPortalURL": "--management-portal-url--", - "publishSettingsURL": "--publish-settings-url--", - "resourceManagerEndpoint": "--resource-manager-endpoint--", - "serviceBusEndpointSuffix": "--service-bus-endpoint-suffix--", - "serviceManagementEndpoint": "--service-management-endpoint--", - "sqlDatabaseDNSSuffix": "--sql-database-dns-suffix--", - "storageEndpointSuffix": "--storage-endpoint-suffix--", - "trafficManagerDNSSuffix": "--traffic-manager-dns-suffix--", - "serviceManagementVMDNSSuffix": "--asm-vm-dns-suffix--", - "resourceManagerVMDNSSuffix": "--arm-vm-dns-suffix--", - "containerRegistryDNSSuffix": "--container-registry-dns-suffix--" - }` - - testSubject := Environment{} - err := json.Unmarshal([]byte(env), &testSubject) - if err != nil { - t.Fatalf("failed to unmarshal: %s", err) - } - - if "--name--" != testSubject.Name { - t.Errorf("Expected Name to be \"--name--\", but got %q", testSubject.Name) - } - if "--management-portal-url--" != testSubject.ManagementPortalURL { - t.Errorf("Expected ManagementPortalURL to be \"--management-portal-url--\", but got %q", testSubject.ManagementPortalURL) - } - if "--publish-settings-url--" != testSubject.PublishSettingsURL { - t.Errorf("Expected PublishSettingsURL to be \"--publish-settings-url--\", but got %q", testSubject.PublishSettingsURL) - } - if "--service-management-endpoint--" != testSubject.ServiceManagementEndpoint { - t.Errorf("Expected ServiceManagementEndpoint to be \"--service-management-endpoint--\", but got %q", testSubject.ServiceManagementEndpoint) - } - if "--resource-manager-endpoint--" != testSubject.ResourceManagerEndpoint { - t.Errorf("Expected ResourceManagerEndpoint to be \"--resource-manager-endpoint--\", but got %q", testSubject.ResourceManagerEndpoint) - } - if "--active-directory-endpoint--" != testSubject.ActiveDirectoryEndpoint { - t.Errorf("Expected ActiveDirectoryEndpoint to be \"--active-directory-endpoint--\", but got %q", testSubject.ActiveDirectoryEndpoint) - } - if "--gallery-endpoint--" != testSubject.GalleryEndpoint { - t.Errorf("Expected GalleryEndpoint to be \"--gallery-endpoint--\", but got %q", testSubject.GalleryEndpoint) - } - if "--key-vault-endpoint--" != testSubject.KeyVaultEndpoint { - t.Errorf("Expected KeyVaultEndpoint to be \"--key-vault-endpoint--\", but got %q", testSubject.KeyVaultEndpoint) - } - if "--service-bus-endpoint--" != testSubject.ServiceBusEndpoint { - t.Errorf("Expected ServiceBusEndpoint to be \"--service-bus-endpoint--\", but goet %q", testSubject.ServiceBusEndpoint) - } - if "--graph-endpoint--" != testSubject.GraphEndpoint { - t.Errorf("Expected GraphEndpoint to be \"--graph-endpoint--\", but got %q", testSubject.GraphEndpoint) - } - if "--storage-endpoint-suffix--" != testSubject.StorageEndpointSuffix { - t.Errorf("Expected StorageEndpointSuffix to be \"--storage-endpoint-suffix--\", but got %q", testSubject.StorageEndpointSuffix) - } - if "--sql-database-dns-suffix--" != testSubject.SQLDatabaseDNSSuffix { - t.Errorf("Expected sql-database-dns-suffix to be \"--sql-database-dns-suffix--\", but got %q", testSubject.SQLDatabaseDNSSuffix) - } - if "--key-vault-dns-suffix--" != testSubject.KeyVaultDNSSuffix { - t.Errorf("Expected StorageEndpointSuffix to be \"--key-vault-dns-suffix--\", but got %q", testSubject.KeyVaultDNSSuffix) - } - if "--service-bus-endpoint-suffix--" != testSubject.ServiceBusEndpointSuffix { - t.Errorf("Expected StorageEndpointSuffix to be \"--service-bus-endpoint-suffix--\", but got %q", testSubject.ServiceBusEndpointSuffix) - } - if "--asm-vm-dns-suffix--" != testSubject.ServiceManagementVMDNSSuffix { - t.Errorf("Expected ServiceManagementVMDNSSuffix to be \"--asm-vm-dns-suffix--\", but got %q", testSubject.ServiceManagementVMDNSSuffix) - } - if "--arm-vm-dns-suffix--" != testSubject.ResourceManagerVMDNSSuffix { - t.Errorf("Expected ResourceManagerVMDNSSuffix to be \"--arm-vm-dns-suffix--\", but got %q", testSubject.ResourceManagerVMDNSSuffix) - } - if "--container-registry-dns-suffix--" != testSubject.ContainerRegistryDNSSuffix { - t.Errorf("Expected ContainerRegistryDNSSuffix to be \"--container-registry-dns-suffix--\", but got %q", testSubject.ContainerRegistryDNSSuffix) - } -} - -func TestRoundTripSerialization(t *testing.T) { - env := Environment{ - Name: "--unit-test--", - ManagementPortalURL: "--management-portal-url", - PublishSettingsURL: "--publish-settings-url--", - ServiceManagementEndpoint: "--service-management-endpoint--", - ResourceManagerEndpoint: "--resource-management-endpoint--", - ActiveDirectoryEndpoint: "--active-directory-endpoint--", - GalleryEndpoint: "--gallery-endpoint--", - KeyVaultEndpoint: "--key-vault--endpoint--", - GraphEndpoint: "--graph-endpoint--", - ServiceBusEndpoint: "--service-bus-endpoint--", - StorageEndpointSuffix: "--storage-endpoint-suffix--", - SQLDatabaseDNSSuffix: "--sql-database-dns-suffix--", - TrafficManagerDNSSuffix: "--traffic-manager-dns-suffix--", - KeyVaultDNSSuffix: "--key-vault-dns-suffix--", - ServiceBusEndpointSuffix: "--service-bus-endpoint-suffix--", - ServiceManagementVMDNSSuffix: "--asm-vm-dns-suffix--", - ResourceManagerVMDNSSuffix: "--arm-vm-dns-suffix--", - ContainerRegistryDNSSuffix: "--container-registry-dns-suffix--", - } - - bytes, err := json.Marshal(env) - if err != nil { - t.Fatalf("failed to marshal: %s", err) - } - - testSubject := Environment{} - err = json.Unmarshal(bytes, &testSubject) - if err != nil { - t.Fatalf("failed to unmarshal: %s", err) - } - - if env.Name != testSubject.Name { - t.Errorf("Expected Name to be %q, but got %q", env.Name, testSubject.Name) - } - if env.ManagementPortalURL != testSubject.ManagementPortalURL { - t.Errorf("Expected ManagementPortalURL to be %q, but got %q", env.ManagementPortalURL, testSubject.ManagementPortalURL) - } - if env.PublishSettingsURL != testSubject.PublishSettingsURL { - t.Errorf("Expected PublishSettingsURL to be %q, but got %q", env.PublishSettingsURL, testSubject.PublishSettingsURL) - } - if env.ServiceManagementEndpoint != testSubject.ServiceManagementEndpoint { - t.Errorf("Expected ServiceManagementEndpoint to be %q, but got %q", env.ServiceManagementEndpoint, testSubject.ServiceManagementEndpoint) - } - if env.ResourceManagerEndpoint != testSubject.ResourceManagerEndpoint { - t.Errorf("Expected ResourceManagerEndpoint to be %q, but got %q", env.ResourceManagerEndpoint, testSubject.ResourceManagerEndpoint) - } - if env.ActiveDirectoryEndpoint != testSubject.ActiveDirectoryEndpoint { - t.Errorf("Expected ActiveDirectoryEndpoint to be %q, but got %q", env.ActiveDirectoryEndpoint, testSubject.ActiveDirectoryEndpoint) - } - if env.GalleryEndpoint != testSubject.GalleryEndpoint { - t.Errorf("Expected GalleryEndpoint to be %q, but got %q", env.GalleryEndpoint, testSubject.GalleryEndpoint) - } - if env.ServiceBusEndpoint != testSubject.ServiceBusEndpoint { - t.Errorf("Expected ServiceBusEnpoint to be %q, but got %q", env.ServiceBusEndpoint, testSubject.ServiceBusEndpoint) - } - if env.KeyVaultEndpoint != testSubject.KeyVaultEndpoint { - t.Errorf("Expected KeyVaultEndpoint to be %q, but got %q", env.KeyVaultEndpoint, testSubject.KeyVaultEndpoint) - } - if env.GraphEndpoint != testSubject.GraphEndpoint { - t.Errorf("Expected GraphEndpoint to be %q, but got %q", env.GraphEndpoint, testSubject.GraphEndpoint) - } - if env.StorageEndpointSuffix != testSubject.StorageEndpointSuffix { - t.Errorf("Expected StorageEndpointSuffix to be %q, but got %q", env.StorageEndpointSuffix, testSubject.StorageEndpointSuffix) - } - if env.SQLDatabaseDNSSuffix != testSubject.SQLDatabaseDNSSuffix { - t.Errorf("Expected SQLDatabaseDNSSuffix to be %q, but got %q", env.SQLDatabaseDNSSuffix, testSubject.SQLDatabaseDNSSuffix) - } - if env.TrafficManagerDNSSuffix != testSubject.TrafficManagerDNSSuffix { - t.Errorf("Expected TrafficManagerDNSSuffix to be %q, but got %q", env.TrafficManagerDNSSuffix, testSubject.TrafficManagerDNSSuffix) - } - if env.KeyVaultDNSSuffix != testSubject.KeyVaultDNSSuffix { - t.Errorf("Expected KeyVaultDNSSuffix to be %q, but got %q", env.KeyVaultDNSSuffix, testSubject.KeyVaultDNSSuffix) - } - if env.ServiceBusEndpointSuffix != testSubject.ServiceBusEndpointSuffix { - t.Errorf("Expected ServiceBusEndpointSuffix to be %q, but got %q", env.ServiceBusEndpointSuffix, testSubject.ServiceBusEndpointSuffix) - } - if env.ServiceManagementVMDNSSuffix != testSubject.ServiceManagementVMDNSSuffix { - t.Errorf("Expected ServiceManagementVMDNSSuffix to be %q, but got %q", env.ServiceManagementVMDNSSuffix, testSubject.ServiceManagementVMDNSSuffix) - } - if env.ResourceManagerVMDNSSuffix != testSubject.ResourceManagerVMDNSSuffix { - t.Errorf("Expected ResourceManagerVMDNSSuffix to be %q, but got %q", env.ResourceManagerVMDNSSuffix, testSubject.ResourceManagerVMDNSSuffix) - } - if env.ContainerRegistryDNSSuffix != testSubject.ContainerRegistryDNSSuffix { - t.Errorf("Expected ContainerRegistryDNSSuffix to be %q, but got %q", env.ContainerRegistryDNSSuffix, testSubject.ContainerRegistryDNSSuffix) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/rp_test.go b/vendor/github.com/Azure/go-autorest/autorest/azure/rp_test.go deleted file mode 100644 index f01355c0..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/azure/rp_test.go +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package azure - -import ( - "context" - "net/http" - "sync" - "testing" - "time" - - "github.com/Azure/go-autorest/autorest" - "github.com/Azure/go-autorest/autorest/mocks" -) - -func TestDoRetryWithRegistration(t *testing.T) { - client := mocks.NewSender() - // first response, should retry because it is a transient error - client.AppendResponse(mocks.NewResponseWithStatus("Internal server error", http.StatusInternalServerError)) - // response indicates the resource provider has not been registered - client.AppendResponse(mocks.NewResponseWithBodyAndStatus(mocks.NewBody(`{ - "error":{ - "code":"MissingSubscriptionRegistration", - "message":"The subscription registration is in 'Unregistered' state. The subscription must be registered to use namespace 'Microsoft.EventGrid'. See https://aka.ms/rps-not-found for how to register subscriptions.", - "details":[ - { - "code":"MissingSubscriptionRegistration", - "target":"Microsoft.EventGrid", - "message":"The subscription registration is in 'Unregistered' state. The subscription must be registered to use namespace 'Microsoft.EventGrid'. See https://aka.ms/rps-not-found for how to register subscriptions." - } - ] - } -} -`), http.StatusConflict, "MissingSubscriptionRegistration")) - // first poll response, still not ready - client.AppendResponse(mocks.NewResponseWithBodyAndStatus(mocks.NewBody(`{ - "registrationState": "Registering" -} -`), http.StatusOK, "200 OK")) - // last poll response, respurce provider has been registered - client.AppendResponse(mocks.NewResponseWithBodyAndStatus(mocks.NewBody(`{ - "registrationState": "Registered" -} -`), http.StatusOK, "200 OK")) - // retry original request, response is successful - client.AppendResponse(mocks.NewResponseWithStatus("200 OK", http.StatusOK)) - - req := mocks.NewRequestForURL("https://lol/subscriptions/rofl") - req.Body = mocks.NewBody("lolol") - r, err := autorest.SendWithSender(client, req, - DoRetryWithRegistration(autorest.Client{ - PollingDelay: time.Second, - PollingDuration: time.Second * 10, - RetryAttempts: 5, - RetryDuration: time.Second, - Sender: client, - }), - ) - if err != nil { - t.Fatalf("got error: %v", err) - } - - autorest.Respond(r, - autorest.ByDiscardingBody(), - autorest.ByClosing(), - ) - - if r.StatusCode != http.StatusOK { - t.Fatalf("azure: Sender#DoRetryWithRegistration -- Got: StatusCode %v; Want: StatusCode 200 OK", r.StatusCode) - } -} - -func TestDoRetrySkipRegistration(t *testing.T) { - client := mocks.NewSender() - // first response, should retry because it is a transient error - client.AppendResponse(mocks.NewResponseWithStatus("Internal server error", http.StatusInternalServerError)) - // response indicates the resource provider has not been registered - client.AppendResponse(mocks.NewResponseWithBodyAndStatus(mocks.NewBody(`{ - "error":{ - "code":"MissingSubscriptionRegistration", - "message":"The subscription registration is in 'Unregistered' state. The subscription must be registered to use namespace 'Microsoft.EventGrid'. See https://aka.ms/rps-not-found for how to register subscriptions.", - "details":[ - { - "code":"MissingSubscriptionRegistration", - "target":"Microsoft.EventGrid", - "message":"The subscription registration is in 'Unregistered' state. The subscription must be registered to use namespace 'Microsoft.EventGrid'. See https://aka.ms/rps-not-found for how to register subscriptions." - } - ] - } -}`), http.StatusConflict, "MissingSubscriptionRegistration")) - - req := mocks.NewRequestForURL("https://lol/subscriptions/rofl") - req.Body = mocks.NewBody("lolol") - r, err := autorest.SendWithSender(client, req, - DoRetryWithRegistration(autorest.Client{ - PollingDelay: time.Second, - PollingDuration: time.Second * 10, - RetryAttempts: 5, - RetryDuration: time.Second, - Sender: client, - SkipResourceProviderRegistration: true, - }), - ) - if err != nil { - t.Fatalf("got error: %v", err) - } - - autorest.Respond(r, - autorest.ByDiscardingBody(), - autorest.ByClosing(), - ) - - if r.StatusCode != http.StatusConflict { - t.Fatalf("azure: Sender#DoRetryWithRegistration -- Got: StatusCode %v; Want: StatusCode 409 Conflict", r.StatusCode) - } -} - -func TestDoRetryWithRegistration_CanBeCancelled(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - delay := 5 * time.Second - - client := mocks.NewSender() - client.AppendAndRepeatResponse(mocks.NewResponseWithStatus("Internal server error", http.StatusInternalServerError), 5) - - var wg sync.WaitGroup - wg.Add(1) - start := time.Now() - end := time.Now() - var err error - - go func() { - req := mocks.NewRequestForURL("https://lol/subscriptions/rofl") - req = req.WithContext(ctx) - req.Body = mocks.NewBody("lolol") - _, err = autorest.SendWithSender(client, req, - DoRetryWithRegistration(autorest.Client{ - PollingDelay: time.Second, - PollingDuration: delay, - RetryAttempts: 5, - RetryDuration: time.Second, - Sender: client, - SkipResourceProviderRegistration: true, - }), - ) - end = time.Now() - wg.Done() - }() - cancel() - wg.Wait() - time.Sleep(5 * time.Millisecond) - if err == nil { - t.Fatalf("azure: DoRetryWithRegistration didn't cancel") - } - if end.Sub(start) >= delay { - t.Fatalf("azure: DoRetryWithRegistration failed to cancel") - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/client_test.go b/vendor/github.com/Azure/go-autorest/autorest/client_test.go deleted file mode 100644 index d2d800ea..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/client_test.go +++ /dev/null @@ -1,415 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "bytes" - "fmt" - "io/ioutil" - "log" - "math/rand" - "net/http" - "net/http/httptest" - "reflect" - "testing" - "time" - - "github.com/Azure/go-autorest/autorest/mocks" - "github.com/Azure/go-autorest/tracing" -) - -func TestLoggingInspectorWithInspection(t *testing.T) { - b := bytes.Buffer{} - c := Client{} - li := LoggingInspector{Logger: log.New(&b, "", 0)} - c.RequestInspector = li.WithInspection() - - Prepare(mocks.NewRequestWithContent("Content"), - c.WithInspection()) - - if len(b.String()) <= 0 { - t.Fatal("autorest: LoggingInspector#WithInspection did not record Request to the log") - } -} - -func TestLoggingInspectorWithInspectionEmitsErrors(t *testing.T) { - b := bytes.Buffer{} - c := Client{} - r := mocks.NewRequestWithContent("Content") - li := LoggingInspector{Logger: log.New(&b, "", 0)} - c.RequestInspector = li.WithInspection() - - if _, err := Prepare(r, - c.WithInspection()); err != nil { - t.Error(err) - } - - if len(b.String()) <= 0 { - t.Fatal("autorest: LoggingInspector#WithInspection did not record Request to the log") - } -} - -func TestLoggingInspectorWithInspectionRestoresBody(t *testing.T) { - b := bytes.Buffer{} - c := Client{} - r := mocks.NewRequestWithContent("Content") - li := LoggingInspector{Logger: log.New(&b, "", 0)} - c.RequestInspector = li.WithInspection() - - Prepare(r, - c.WithInspection()) - - s, _ := ioutil.ReadAll(r.Body) - if len(s) <= 0 { - t.Fatal("autorest: LoggingInspector#WithInspection did not restore the Request body") - } -} - -func TestLoggingInspectorByInspecting(t *testing.T) { - b := bytes.Buffer{} - c := Client{} - li := LoggingInspector{Logger: log.New(&b, "", 0)} - c.ResponseInspector = li.ByInspecting() - - Respond(mocks.NewResponseWithContent("Content"), - c.ByInspecting()) - - if len(b.String()) <= 0 { - t.Fatal("autorest: LoggingInspector#ByInspection did not record Response to the log") - } -} - -func TestLoggingInspectorByInspectingEmitsErrors(t *testing.T) { - b := bytes.Buffer{} - c := Client{} - r := mocks.NewResponseWithContent("Content") - li := LoggingInspector{Logger: log.New(&b, "", 0)} - c.ResponseInspector = li.ByInspecting() - - if err := Respond(r, - c.ByInspecting()); err != nil { - t.Fatal(err) - } - - if len(b.String()) <= 0 { - t.Fatal("autorest: LoggingInspector#ByInspection did not record Response to the log") - } -} - -func TestLoggingInspectorByInspectingRestoresBody(t *testing.T) { - b := bytes.Buffer{} - c := Client{} - r := mocks.NewResponseWithContent("Content") - li := LoggingInspector{Logger: log.New(&b, "", 0)} - c.ResponseInspector = li.ByInspecting() - - Respond(r, - c.ByInspecting()) - - s, _ := ioutil.ReadAll(r.Body) - if len(s) <= 0 { - t.Fatal("autorest: LoggingInspector#ByInspecting did not restore the Response body") - } -} - -func TestNewClientWithUserAgent(t *testing.T) { - ua := "UserAgent" - c := NewClientWithUserAgent(ua) - completeUA := fmt.Sprintf("%s %s", UserAgent(), ua) - - if c.UserAgent != completeUA { - t.Fatalf("autorest: NewClientWithUserAgent failed to set the UserAgent -- expected %s, received %s", - completeUA, c.UserAgent) - } -} - -func TestAddToUserAgent(t *testing.T) { - ua := "UserAgent" - c := NewClientWithUserAgent(ua) - ext := "extension" - err := c.AddToUserAgent(ext) - if err != nil { - t.Fatalf("autorest: AddToUserAgent returned error -- expected nil, received %s", err) - } - completeUA := fmt.Sprintf("%s %s %s", UserAgent(), ua, ext) - - if c.UserAgent != completeUA { - t.Fatalf("autorest: AddToUserAgent failed to add an extension to the UserAgent -- expected %s, received %s", - completeUA, c.UserAgent) - } - - err = c.AddToUserAgent("") - if err == nil { - t.Fatalf("autorest: AddToUserAgent didn't return error -- expected %s, received nil", - fmt.Errorf("Extension was empty, User Agent stayed as %s", c.UserAgent)) - } - if c.UserAgent != completeUA { - t.Fatalf("autorest: AddToUserAgent failed to not add an empty extension to the UserAgent -- expected %s, received %s", - completeUA, c.UserAgent) - } -} - -func TestClientSenderReturnsHttpClientByDefault(t *testing.T) { - c := Client{} - - if fmt.Sprintf("%T", c.sender()) != "*http.Client" { - t.Fatal("autorest: Client#sender failed to return http.Client by default") - } -} - -func TestClientSenderReturnsSetSender(t *testing.T) { - c := Client{} - - s := mocks.NewSender() - c.Sender = s - - if c.sender() != s { - t.Fatal("autorest: Client#sender failed to return set Sender") - } -} - -func TestClientDoInvokesSender(t *testing.T) { - c := Client{} - - s := mocks.NewSender() - c.Sender = s - - c.Do(&http.Request{}) - if s.Attempts() != 1 { - t.Fatal("autorest: Client#Do failed to invoke the Sender") - } -} - -func TestClientDoSetsUserAgent(t *testing.T) { - ua := "UserAgent" - c := Client{UserAgent: ua} - r := mocks.NewRequest() - s := mocks.NewSender() - c.Sender = s - - c.Do(r) - - if r.UserAgent() != ua { - t.Fatalf("autorest: Client#Do failed to correctly set User-Agent header: %s=%s", - http.CanonicalHeaderKey(headerUserAgent), r.UserAgent()) - } -} - -func TestClientDoSetsAuthorization(t *testing.T) { - r := mocks.NewRequest() - s := mocks.NewSender() - c := Client{Authorizer: mockAuthorizer{}, Sender: s} - - c.Do(r) - if len(r.Header.Get(http.CanonicalHeaderKey(headerAuthorization))) <= 0 { - t.Fatalf("autorest: Client#Send failed to set Authorization header -- %s=%s", - http.CanonicalHeaderKey(headerAuthorization), - r.Header.Get(http.CanonicalHeaderKey(headerAuthorization))) - } -} - -func TestClientDoInvokesRequestInspector(t *testing.T) { - r := mocks.NewRequest() - s := mocks.NewSender() - i := &mockInspector{} - c := Client{RequestInspector: i.WithInspection(), Sender: s} - - c.Do(r) - if !i.wasInvoked { - t.Fatal("autorest: Client#Send failed to invoke the RequestInspector") - } -} - -func TestClientDoInvokesResponseInspector(t *testing.T) { - r := mocks.NewRequest() - s := mocks.NewSender() - i := &mockInspector{} - c := Client{ResponseInspector: i.ByInspecting(), Sender: s} - - c.Do(r) - if !i.wasInvoked { - t.Fatal("autorest: Client#Send failed to invoke the ResponseInspector") - } -} - -func TestClientDoReturnsErrorIfPrepareFails(t *testing.T) { - c := Client{} - s := mocks.NewSender() - c.Authorizer = mockFailingAuthorizer{} - c.Sender = s - - _, err := c.Do(&http.Request{}) - if err == nil { - t.Fatalf("autorest: Client#Do failed to return an error when Prepare failed") - } -} - -func TestClientDoDoesNotSendIfPrepareFails(t *testing.T) { - c := Client{} - s := mocks.NewSender() - c.Authorizer = mockFailingAuthorizer{} - c.Sender = s - - c.Do(&http.Request{}) - if s.Attempts() > 0 { - t.Fatal("autorest: Client#Do failed to invoke the Sender") - } -} - -func TestClientAuthorizerReturnsNullAuthorizerByDefault(t *testing.T) { - c := Client{} - - if fmt.Sprintf("%T", c.authorizer()) != "autorest.NullAuthorizer" { - t.Fatal("autorest: Client#authorizer failed to return the NullAuthorizer by default") - } -} - -func TestClientAuthorizerReturnsSetAuthorizer(t *testing.T) { - c := Client{} - c.Authorizer = mockAuthorizer{} - - if fmt.Sprintf("%T", c.authorizer()) != "autorest.mockAuthorizer" { - t.Fatal("autorest: Client#authorizer failed to return the set Authorizer") - } -} - -func TestClientWithAuthorizer(t *testing.T) { - c := Client{} - c.Authorizer = mockAuthorizer{} - - req, _ := Prepare(&http.Request{}, - c.WithAuthorization()) - - if req.Header.Get(headerAuthorization) == "" { - t.Fatal("autorest: Client#WithAuthorizer failed to return the WithAuthorizer from the active Authorizer") - } -} - -func TestClientWithInspection(t *testing.T) { - c := Client{} - r := &mockInspector{} - c.RequestInspector = r.WithInspection() - - Prepare(&http.Request{}, - c.WithInspection()) - - if !r.wasInvoked { - t.Fatal("autorest: Client#WithInspection failed to invoke RequestInspector") - } -} - -func TestClientWithInspectionSetsDefault(t *testing.T) { - c := Client{} - - r1 := &http.Request{} - r2, _ := Prepare(r1, - c.WithInspection()) - - if !reflect.DeepEqual(r1, r2) { - t.Fatal("autorest: Client#WithInspection failed to provide a default RequestInspector") - } -} - -func TestClientByInspecting(t *testing.T) { - c := Client{} - r := &mockInspector{} - c.ResponseInspector = r.ByInspecting() - - Respond(&http.Response{}, - c.ByInspecting()) - - if !r.wasInvoked { - t.Fatal("autorest: Client#ByInspecting failed to invoke ResponseInspector") - } -} - -func TestClientByInspectingSetsDefault(t *testing.T) { - c := Client{} - - r := &http.Response{} - Respond(r, - c.ByInspecting()) - - if !reflect.DeepEqual(r, &http.Response{}) { - t.Fatal("autorest: Client#ByInspecting failed to provide a default ResponseInspector") - } -} - -func TestClientTracing(t *testing.T) { - c := Client{} - - httpClient, ok := c.sender().(*http.Client) - if !ok { - t.Fatal("autorest: Client#sender failed to return http.Client by default") - } - if httpClient.Transport != tracing.Transport { - t.Fatal("autorest: Client.Sender Default transport is not the tracing transport") - } -} - -func TestCookies(t *testing.T) { - second := "second" - expected := http.Cookie{ - Name: "tastes", - Value: "delicious", - } - - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - http.SetCookie(w, &expected) - b, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatalf("autorest: ioutil.ReadAll failed reading request body: %s", err) - } - if string(b) == second { - cookie, err := r.Cookie(expected.Name) - if err != nil { - t.Fatalf("autorest: r.Cookie could not get request cookie: %s", err) - } - if cookie == nil { - t.Fatalf("autorest: got nil cookie, expecting %v", expected) - } - if cookie.Value != expected.Value { - t.Fatalf("autorest: got cookie value '%s', expecting '%s'", cookie.Value, expected.Name) - } - } - })) - defer server.Close() - - client := NewClientWithUserAgent("") - _, err := SendWithSender(client, mocks.NewRequestForURL(server.URL)) - if err != nil { - t.Fatalf("autorest: first request failed: %s", err) - } - - r2, err := http.NewRequest(http.MethodGet, server.URL, mocks.NewBody(second)) - if err != nil { - t.Fatalf("autorest: failed creating second request: %s", err) - } - - _, err = SendWithSender(client, r2) - if err != nil { - t.Fatalf("autorest: second request failed: %s", err) - } -} - -func randomString(n int) string { - const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - r := rand.New(rand.NewSource(time.Now().UTC().UnixNano())) - s := make([]byte, n) - for i := range s { - s[i] = chars[r.Intn(len(chars))] - } - return string(s) -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/date/date_test.go b/vendor/github.com/Azure/go-autorest/autorest/date/date_test.go deleted file mode 100644 index 4a40bbc3..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/date/date_test.go +++ /dev/null @@ -1,237 +0,0 @@ -package date - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "encoding/json" - "fmt" - "reflect" - "testing" - "time" -) - -func ExampleParseDate() { - d, err := ParseDate("2001-02-03") - if err != nil { - fmt.Println(err) - } - fmt.Println(d) - // Output: 2001-02-03 -} - -func ExampleDate() { - d, err := ParseDate("2001-02-03") - if err != nil { - fmt.Println(err) - } - - t, err := time.Parse(time.RFC3339, "2001-02-04T00:00:00Z") - if err != nil { - fmt.Println(err) - } - - // Date acts as time.Time when the receiver - if d.Before(t) { - fmt.Printf("Before ") - } else { - fmt.Printf("After ") - } - - // Convert Date when needing a time.Time - if t.After(d.ToTime()) { - fmt.Printf("After") - } else { - fmt.Printf("Before") - } - // Output: Before After -} - -func ExampleDate_MarshalBinary() { - d, err := ParseDate("2001-02-03") - if err != nil { - fmt.Println(err) - } - t, err := d.MarshalBinary() - if err != nil { - fmt.Println(err) - } - fmt.Println(string(t)) - // Output: 2001-02-03 -} - -func ExampleDate_UnmarshalBinary() { - d := Date{} - t := "2001-02-03" - - if err := d.UnmarshalBinary([]byte(t)); err != nil { - fmt.Println(err) - } - fmt.Println(d) - // Output: 2001-02-03 -} - -func ExampleDate_MarshalJSON() { - d, err := ParseDate("2001-02-03") - if err != nil { - fmt.Println(err) - } - j, err := json.Marshal(d) - if err != nil { - fmt.Println(err) - } - fmt.Println(string(j)) - // Output: "2001-02-03" -} - -func ExampleDate_UnmarshalJSON() { - var d struct { - Date Date `json:"date"` - } - j := `{"date" : "2001-02-03"}` - - if err := json.Unmarshal([]byte(j), &d); err != nil { - fmt.Println(err) - } - fmt.Println(d.Date) - // Output: 2001-02-03 -} - -func ExampleDate_MarshalText() { - d, err := ParseDate("2001-02-03") - if err != nil { - fmt.Println(err) - } - t, err := d.MarshalText() - if err != nil { - fmt.Println(err) - } - fmt.Println(string(t)) - // Output: 2001-02-03 -} - -func ExampleDate_UnmarshalText() { - d := Date{} - t := "2001-02-03" - - if err := d.UnmarshalText([]byte(t)); err != nil { - fmt.Println(err) - } - fmt.Println(d) - // Output: 2001-02-03 -} - -func TestDateString(t *testing.T) { - d, err := ParseDate("2001-02-03") - if err != nil { - t.Fatalf("date: String failed (%v)", err) - } - if d.String() != "2001-02-03" { - t.Fatalf("date: String failed (%v)", d.String()) - } -} - -func TestDateBinaryRoundTrip(t *testing.T) { - d1, err := ParseDate("2001-02-03") - if err != nil { - t.Fatalf("date: ParseDate failed (%v)", err) - } - t1, err := d1.MarshalBinary() - if err != nil { - t.Fatalf("date: MarshalBinary failed (%v)", err) - } - - d2 := Date{} - if err = d2.UnmarshalBinary(t1); err != nil { - t.Fatalf("date: UnmarshalBinary failed (%v)", err) - } - - if !reflect.DeepEqual(d1, d2) { - t.Fatalf("date: Round-trip Binary failed (%v, %v)", d1, d2) - } -} - -func TestDateJSONRoundTrip(t *testing.T) { - type s struct { - Date Date `json:"date"` - } - var err error - d1 := s{} - d1.Date, err = ParseDate("2001-02-03") - if err != nil { - t.Fatalf("date: ParseDate failed (%v)", err) - } - - j, err := json.Marshal(d1) - if err != nil { - t.Fatalf("date: MarshalJSON failed (%v)", err) - } - - d2 := s{} - if err = json.Unmarshal(j, &d2); err != nil { - t.Fatalf("date: UnmarshalJSON failed (%v)", err) - } - - if !reflect.DeepEqual(d1, d2) { - t.Fatalf("date: Round-trip JSON failed (%v, %v)", d1, d2) - } -} - -func TestDateTextRoundTrip(t *testing.T) { - d1, err := ParseDate("2001-02-03") - if err != nil { - t.Fatalf("date: ParseDate failed (%v)", err) - } - t1, err := d1.MarshalText() - if err != nil { - t.Fatalf("date: MarshalText failed (%v)", err) - } - d2 := Date{} - if err = d2.UnmarshalText(t1); err != nil { - t.Fatalf("date: UnmarshalText failed (%v)", err) - } - - if !reflect.DeepEqual(d1, d2) { - t.Fatalf("date: Round-trip Text failed (%v, %v)", d1, d2) - } -} - -func TestDateToTime(t *testing.T) { - var d Date - d, err := ParseDate("2001-02-03") - if err != nil { - t.Fatalf("date: ParseDate failed (%v)", err) - } - var _ time.Time = d.ToTime() -} - -func TestDateUnmarshalJSONReturnsError(t *testing.T) { - var d struct { - Date Date `json:"date"` - } - j := `{"date" : "February 3, 2001"}` - - if err := json.Unmarshal([]byte(j), &d); err == nil { - t.Fatal("date: Date failed to return error for malformed JSON date") - } -} - -func TestDateUnmarshalTextReturnsError(t *testing.T) { - d := Date{} - txt := "February 3, 2001" - - if err := d.UnmarshalText([]byte(txt)); err == nil { - t.Fatal("date: Date failed to return error for malformed Text date") - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/date/time_test.go b/vendor/github.com/Azure/go-autorest/autorest/date/time_test.go deleted file mode 100644 index d8c81170..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/date/time_test.go +++ /dev/null @@ -1,277 +0,0 @@ -package date - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "encoding/json" - "fmt" - "reflect" - "testing" - "time" -) - -func ExampleParseTime() { - d, _ := ParseTime(rfc3339, "2001-02-03T04:05:06Z") - fmt.Println(d) - // Output: 2001-02-03 04:05:06 +0000 UTC -} - -func ExampleTime_MarshalBinary() { - ti, err := ParseTime(rfc3339, "2001-02-03T04:05:06Z") - if err != nil { - fmt.Println(err) - } - d := Time{ti} - t, err := d.MarshalBinary() - if err != nil { - fmt.Println(err) - } - fmt.Println(string(t)) - // Output: 2001-02-03T04:05:06Z -} - -func ExampleTime_UnmarshalBinary() { - d := Time{} - t := "2001-02-03T04:05:06Z" - - if err := d.UnmarshalBinary([]byte(t)); err != nil { - fmt.Println(err) - } - fmt.Println(d) - // Output: 2001-02-03T04:05:06Z -} - -func ExampleTime_MarshalJSON() { - d, err := ParseTime(rfc3339, "2001-02-03T04:05:06Z") - if err != nil { - fmt.Println(err) - } - j, err := json.Marshal(d) - if err != nil { - fmt.Println(err) - } - fmt.Println(string(j)) - // Output: "2001-02-03T04:05:06Z" -} - -func ExampleTime_UnmarshalJSON() { - var d struct { - Time Time `json:"datetime"` - } - j := `{"datetime" : "2001-02-03T04:05:06Z"}` - - if err := json.Unmarshal([]byte(j), &d); err != nil { - fmt.Println(err) - } - fmt.Println(d.Time) - // Output: 2001-02-03T04:05:06Z -} - -func ExampleTime_MarshalText() { - d, err := ParseTime(rfc3339, "2001-02-03T04:05:06Z") - if err != nil { - fmt.Println(err) - } - t, err := d.MarshalText() - if err != nil { - fmt.Println(err) - } - fmt.Println(string(t)) - // Output: 2001-02-03T04:05:06Z -} - -func ExampleTime_UnmarshalText() { - d := Time{} - t := "2001-02-03T04:05:06Z" - - if err := d.UnmarshalText([]byte(t)); err != nil { - fmt.Println(err) - } - fmt.Println(d) - // Output: 2001-02-03T04:05:06Z -} - -func TestUnmarshalTextforInvalidDate(t *testing.T) { - d := Time{} - dt := "2001-02-03T04:05:06AAA" - - if err := d.UnmarshalText([]byte(dt)); err == nil { - t.Fatalf("date: Time#Unmarshal was expecting error for invalid date") - } -} - -func TestUnmarshalJSONforInvalidDate(t *testing.T) { - d := Time{} - dt := `"2001-02-03T04:05:06AAA"` - - if err := d.UnmarshalJSON([]byte(dt)); err == nil { - t.Fatalf("date: Time#Unmarshal was expecting error for invalid date") - } -} - -func TestTimeString(t *testing.T) { - ti, err := ParseTime(rfc3339, "2001-02-03T04:05:06Z") - if err != nil { - fmt.Println(err) - } - d := Time{ti} - if d.String() != "2001-02-03T04:05:06Z" { - t.Fatalf("date: Time#String failed (%v)", d.String()) - } -} - -func TestTimeStringReturnsEmptyStringForError(t *testing.T) { - d := Time{Time: time.Date(20000, 01, 01, 01, 01, 01, 01, time.UTC)} - if d.String() != "" { - t.Fatalf("date: Time#String failed empty string for an error") - } -} - -func TestTimeBinaryRoundTrip(t *testing.T) { - ti, err := ParseTime(rfc3339, "2001-02-03T04:05:06Z") - if err != nil { - t.Fatalf("date: Time#ParseTime failed (%v)", err) - } - d1 := Time{ti} - t1, err := d1.MarshalBinary() - if err != nil { - t.Fatalf("date: Time#MarshalBinary failed (%v)", err) - } - - d2 := Time{} - if err = d2.UnmarshalBinary(t1); err != nil { - t.Fatalf("date: Time#UnmarshalBinary failed (%v)", err) - } - - if !reflect.DeepEqual(d1, d2) { - t.Fatalf("date:Round-trip Binary failed (%v, %v)", d1, d2) - } -} - -func TestTimeJSONRoundTrip(t *testing.T) { - type s struct { - Time Time `json:"datetime"` - } - - ti, err := ParseTime(rfc3339, "2001-02-03T04:05:06Z") - if err != nil { - t.Fatalf("date: Time#ParseTime failed (%v)", err) - } - - d1 := s{Time: Time{ti}} - j, err := json.Marshal(d1) - if err != nil { - t.Fatalf("date: Time#MarshalJSON failed (%v)", err) - } - - d2 := s{} - if err = json.Unmarshal(j, &d2); err != nil { - t.Fatalf("date: Time#UnmarshalJSON failed (%v)", err) - } - - if !reflect.DeepEqual(d1, d2) { - t.Fatalf("date: Round-trip JSON failed (%v, %v)", d1, d2) - } -} - -func TestTimeTextRoundTrip(t *testing.T) { - ti, err := ParseTime(rfc3339, "2001-02-03T04:05:06Z") - if err != nil { - t.Fatalf("date: Time#ParseTime failed (%v)", err) - } - d1 := Time{Time: ti} - t1, err := d1.MarshalText() - if err != nil { - t.Fatalf("date: Time#MarshalText failed (%v)", err) - } - - d2 := Time{} - if err = d2.UnmarshalText(t1); err != nil { - t.Fatalf("date: Time#UnmarshalText failed (%v)", err) - } - - if !reflect.DeepEqual(d1, d2) { - t.Fatalf("date: Round-trip Text failed (%v, %v)", d1, d2) - } -} - -func TestTimeToTime(t *testing.T) { - ti, err := ParseTime(rfc3339, "2001-02-03T04:05:06Z") - d := Time{ti} - if err != nil { - t.Fatalf("date: Time#ParseTime failed (%v)", err) - } - var _ time.Time = d.ToTime() -} - -func TestUnmarshalJSONNoOffset(t *testing.T) { - var d struct { - Time Time `json:"datetime"` - } - j := `{"datetime" : "2001-02-03T04:05:06.789"}` - - if err := json.Unmarshal([]byte(j), &d); err != nil { - t.Fatalf("date: Time#Unmarshal failed (%v)", err) - } -} - -func TestUnmarshalJSONPosOffset(t *testing.T) { - var d struct { - Time Time `json:"datetime"` - } - j := `{"datetime" : "1980-01-02T00:11:35.01+01:00"}` - - if err := json.Unmarshal([]byte(j), &d); err != nil { - t.Fatalf("date: Time#Unmarshal failed (%v)", err) - } -} - -func TestUnmarshalJSONNegOffset(t *testing.T) { - var d struct { - Time Time `json:"datetime"` - } - j := `{"datetime" : "1492-10-12T10:15:01.789-08:00"}` - - if err := json.Unmarshal([]byte(j), &d); err != nil { - t.Fatalf("date: Time#Unmarshal failed (%v)", err) - } -} - -func TestUnmarshalTextNoOffset(t *testing.T) { - d := Time{} - t1 := "2001-02-03T04:05:06" - - if err := d.UnmarshalText([]byte(t1)); err != nil { - t.Fatalf("date: Time#UnmarshalText failed (%v)", err) - } -} - -func TestUnmarshalTextPosOffset(t *testing.T) { - d := Time{} - t1 := "2001-02-03T04:05:06+00:30" - - if err := d.UnmarshalText([]byte(t1)); err != nil { - t.Fatalf("date: Time#UnmarshalText failed (%v)", err) - } -} - -func TestUnmarshalTextNegOffset(t *testing.T) { - d := Time{} - t1 := "2001-02-03T04:05:06-11:00" - - if err := d.UnmarshalText([]byte(t1)); err != nil { - t.Fatalf("date: Time#UnmarshalText failed (%v)", err) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/date/timerfc1123_test.go b/vendor/github.com/Azure/go-autorest/autorest/date/timerfc1123_test.go deleted file mode 100644 index dfd64051..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/date/timerfc1123_test.go +++ /dev/null @@ -1,226 +0,0 @@ -package date - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "encoding/json" - "fmt" - "reflect" - "testing" - "time" -) - -func ExampleTimeRFC1123() { - d, err := ParseTime(rfc1123, "Mon, 02 Jan 2006 15:04:05 MST") - if err != nil { - fmt.Println(err) - } - fmt.Println(d) - // Output: 2006-01-02 15:04:05 +0000 MST -} - -func ExampleTimeRFC1123_MarshalBinary() { - ti, err := ParseTime(rfc1123, "Mon, 02 Jan 2006 15:04:05 MST") - if err != nil { - fmt.Println(err) - } - d := TimeRFC1123{ti} - b, err := d.MarshalBinary() - if err != nil { - fmt.Println(err) - } - fmt.Println(string(b)) - // Output: Mon, 02 Jan 2006 15:04:05 MST -} - -func ExampleTimeRFC1123_UnmarshalBinary() { - d := TimeRFC1123{} - t := "Mon, 02 Jan 2006 15:04:05 MST" - if err := d.UnmarshalBinary([]byte(t)); err != nil { - fmt.Println(err) - } - fmt.Println(d) - // Output: Mon, 02 Jan 2006 15:04:05 MST -} - -func ExampleTimeRFC1123_MarshalJSON() { - ti, err := ParseTime(rfc1123, "Mon, 02 Jan 2006 15:04:05 MST") - if err != nil { - fmt.Println(err) - } - d := TimeRFC1123{ti} - j, err := json.Marshal(d) - if err != nil { - fmt.Println(err) - } - fmt.Println(string(j)) - // Output: "Mon, 02 Jan 2006 15:04:05 MST" -} - -func TestTimeRFC1123MarshalJSONInvalid(t *testing.T) { - ti := time.Date(20000, 01, 01, 00, 00, 00, 00, time.UTC) - d := TimeRFC1123{ti} - if _, err := json.Marshal(d); err == nil { - t.Fatalf("date: TimeRFC1123#Marshal failed for invalid date") - } -} - -func ExampleTimeRFC1123_UnmarshalJSON() { - var d struct { - Time TimeRFC1123 `json:"datetime"` - } - j := `{"datetime" : "Mon, 02 Jan 2006 15:04:05 MST"}` - - if err := json.Unmarshal([]byte(j), &d); err != nil { - fmt.Println(err) - } - fmt.Println(d.Time) - // Output: Mon, 02 Jan 2006 15:04:05 MST -} - -func ExampleTimeRFC1123_MarshalText() { - ti, err := ParseTime(rfc3339, "2001-02-03T04:05:06Z") - if err != nil { - fmt.Println(err) - } - d := TimeRFC1123{ti} - t, err := d.MarshalText() - if err != nil { - fmt.Println(err) - } - fmt.Println(string(t)) - // Output: Sat, 03 Feb 2001 04:05:06 UTC -} - -func ExampleTimeRFC1123_UnmarshalText() { - d := TimeRFC1123{} - t := "Sat, 03 Feb 2001 04:05:06 UTC" - - if err := d.UnmarshalText([]byte(t)); err != nil { - fmt.Println(err) - } - fmt.Println(d) - // Output: Sat, 03 Feb 2001 04:05:06 UTC -} - -func TestUnmarshalJSONforInvalidDateRfc1123(t *testing.T) { - dt := `"Mon, 02 Jan 2000000 15:05 MST"` - d := TimeRFC1123{} - if err := d.UnmarshalJSON([]byte(dt)); err == nil { - t.Fatalf("date: TimeRFC1123#Unmarshal failed for invalid date") - } -} - -func TestUnmarshalTextforInvalidDateRfc1123(t *testing.T) { - dt := "Mon, 02 Jan 2000000 15:05 MST" - d := TimeRFC1123{} - if err := d.UnmarshalText([]byte(dt)); err == nil { - t.Fatalf("date: TimeRFC1123#Unmarshal failed for invalid date") - } -} - -func TestTimeStringRfc1123(t *testing.T) { - ti, err := ParseTime(rfc1123, "Mon, 02 Jan 2006 15:04:05 MST") - if err != nil { - fmt.Println(err) - } - d := TimeRFC1123{ti} - if d.String() != "Mon, 02 Jan 2006 15:04:05 MST" { - t.Fatalf("date: TimeRFC1123#String failed (%v)", d.String()) - } -} - -func TestTimeStringReturnsEmptyStringForErrorRfc1123(t *testing.T) { - d := TimeRFC1123{Time: time.Date(20000, 01, 01, 01, 01, 01, 01, time.UTC)} - if d.String() != "" { - t.Fatalf("date: TimeRFC1123#String failed empty string for an error") - } -} - -func TestTimeBinaryRoundTripRfc1123(t *testing.T) { - ti, err := ParseTime(rfc3339, "2001-02-03T04:05:06Z") - if err != nil { - t.Fatalf("date: TimeRFC1123#ParseTime failed (%v)", err) - } - d1 := TimeRFC1123{ti} - t1, err := d1.MarshalBinary() - if err != nil { - t.Fatalf("date: TimeRFC1123#MarshalBinary failed (%v)", err) - } - - d2 := TimeRFC1123{} - if err = d2.UnmarshalBinary(t1); err != nil { - t.Fatalf("date: TimeRFC1123#UnmarshalBinary failed (%v)", err) - } - - if !reflect.DeepEqual(d1, d2) { - t.Fatalf("date: Round-trip Binary failed (%v, %v)", d1, d2) - } -} - -func TestTimeJSONRoundTripRfc1123(t *testing.T) { - type s struct { - Time TimeRFC1123 `json:"datetime"` - } - var err error - ti, err := ParseTime(rfc1123, "Mon, 02 Jan 2006 15:04:05 MST") - if err != nil { - t.Fatalf("date: TimeRFC1123#ParseTime failed (%v)", err) - } - d1 := s{Time: TimeRFC1123{ti}} - j, err := json.Marshal(d1) - if err != nil { - t.Fatalf("date: TimeRFC1123#MarshalJSON failed (%v)", err) - } - - d2 := s{} - if err = json.Unmarshal(j, &d2); err != nil { - t.Fatalf("date: TimeRFC1123#UnmarshalJSON failed (%v)", err) - } - - if !reflect.DeepEqual(d1, d2) { - t.Fatalf("date: Round-trip JSON failed (%v, %v)", d1, d2) - } -} - -func TestTimeTextRoundTripRfc1123(t *testing.T) { - ti, err := ParseTime(rfc1123, "Mon, 02 Jan 2006 15:04:05 MST") - if err != nil { - t.Fatalf("date: TimeRFC1123#ParseTime failed (%v)", err) - } - d1 := TimeRFC1123{Time: ti} - t1, err := d1.MarshalText() - if err != nil { - t.Fatalf("date: TimeRFC1123#MarshalText failed (%v)", err) - } - - d2 := TimeRFC1123{} - if err = d2.UnmarshalText(t1); err != nil { - t.Fatalf("date: TimeRFC1123#UnmarshalText failed (%v)", err) - } - - if !reflect.DeepEqual(d1, d2) { - t.Fatalf("date: Round-trip Text failed (%v, %v)", d1, d2) - } -} - -func TestTimeToTimeRFC1123(t *testing.T) { - ti, err := ParseTime(rfc1123, "Mon, 02 Jan 2006 15:04:05 MST") - d := TimeRFC1123{ti} - if err != nil { - t.Fatalf("date: TimeRFC1123#ParseTime failed (%v)", err) - } - var _ time.Time = d.ToTime() -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/date/unixtime_test.go b/vendor/github.com/Azure/go-autorest/autorest/date/unixtime_test.go deleted file mode 100644 index 3fa347c0..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/date/unixtime_test.go +++ /dev/null @@ -1,283 +0,0 @@ -// +build go1.7 - -package date - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "bytes" - "encoding/binary" - "encoding/json" - "fmt" - "math" - "testing" - "time" -) - -func ExampleUnixTime_MarshalJSON() { - epoch := UnixTime(UnixEpoch()) - text, _ := json.Marshal(epoch) - fmt.Print(string(text)) - // Output: 0 -} - -func ExampleUnixTime_UnmarshalJSON() { - var myTime UnixTime - json.Unmarshal([]byte("1.3e2"), &myTime) - fmt.Printf("%v", time.Time(myTime)) - // Output: 1970-01-01 00:02:10 +0000 UTC -} - -func TestUnixTime_MarshalJSON(t *testing.T) { - testCases := []time.Time{ - UnixEpoch().Add(-1 * time.Second), // One second befote the Unix Epoch - time.Date(2017, time.April, 14, 20, 27, 47, 0, time.UTC), // The time this test was written - UnixEpoch(), - time.Date(1800, 01, 01, 0, 0, 0, 0, time.UTC), - time.Date(2200, 12, 29, 00, 01, 37, 82, time.UTC), - } - - for _, tc := range testCases { - t.Run(tc.String(), func(subT *testing.T) { - var actual, expected float64 - var marshaled []byte - - target := UnixTime(tc) - expected = float64(target.Duration().Nanoseconds()) / 1e9 - - if temp, err := json.Marshal(target); err == nil { - marshaled = temp - } else { - subT.Error(err) - return - } - - dec := json.NewDecoder(bytes.NewReader(marshaled)) - if err := dec.Decode(&actual); err != nil { - subT.Error(err) - return - } - - diff := math.Abs(actual - expected) - subT.Logf("\ngot :\t%g\nwant:\t%g\ndiff:\t%g", actual, expected, diff) - if diff > 1e-9 { //Must be within 1 nanosecond of one another - subT.Fail() - } - }) - } -} - -func TestUnixTime_UnmarshalJSON(t *testing.T) { - testCases := []struct { - text string - expected time.Time - }{ - {"1", UnixEpoch().Add(time.Second)}, - {"0", UnixEpoch()}, - {"1492203742", time.Date(2017, time.April, 14, 21, 02, 22, 0, time.UTC)}, // The time this test was written - {"-1", time.Date(1969, time.December, 31, 23, 59, 59, 0, time.UTC)}, - {"1.5", UnixEpoch().Add(1500 * time.Millisecond)}, - {"0e1", UnixEpoch()}, // See http://json.org for 'number' format definition. - {"1.3e+2", UnixEpoch().Add(130 * time.Second)}, - {"1.6E-10", UnixEpoch()}, // This is so small, it should get truncated into the UnixEpoch - {"2E-6", UnixEpoch().Add(2 * time.Microsecond)}, - {"1.289345e9", UnixEpoch().Add(1289345000 * time.Second)}, - {"1e-9", UnixEpoch().Add(time.Nanosecond)}, - } - - for _, tc := range testCases { - t.Run(tc.text, func(subT *testing.T) { - var rehydrated UnixTime - if err := json.Unmarshal([]byte(tc.text), &rehydrated); err != nil { - subT.Error(err) - return - } - - if time.Time(rehydrated) != tc.expected { - subT.Logf("\ngot: \t%v\nwant:\t%v\ndiff:\t%v", time.Time(rehydrated), tc.expected, time.Time(rehydrated).Sub(tc.expected)) - subT.Fail() - } - }) - } -} - -func TestUnixTime_JSONRoundTrip(t *testing.T) { - testCases := []time.Time{ - UnixEpoch(), - time.Date(2005, time.November, 5, 0, 0, 0, 0, time.UTC), // The day V for Vendetta (film) was released. - UnixEpoch().Add(-6 * time.Second), - UnixEpoch().Add(800 * time.Hour), - UnixEpoch().Add(time.Nanosecond), - time.Date(2015, time.September, 05, 4, 30, 12, 9992, time.UTC), - } - - for _, tc := range testCases { - t.Run(tc.String(), func(subT *testing.T) { - subject := UnixTime(tc) - var marshaled []byte - if temp, err := json.Marshal(subject); err == nil { - marshaled = temp - } else { - subT.Error(err) - return - } - - var unmarshaled UnixTime - if err := json.Unmarshal(marshaled, &unmarshaled); err != nil { - subT.Error(err) - } - - actual := time.Time(unmarshaled) - diff := actual.Sub(tc) - subT.Logf("\ngot :\t%s\nwant:\t%s\ndiff:\t%s", actual.String(), tc.String(), diff.String()) - - if diff > time.Duration(100) { // We lose some precision be working in floats. We shouldn't lose more than 100 nanoseconds. - subT.Fail() - } - }) - } -} - -func TestUnixTime_MarshalBinary(t *testing.T) { - testCases := []struct { - expected int64 - subject time.Time - }{ - {0, UnixEpoch()}, - {-15 * int64(time.Second), UnixEpoch().Add(-15 * time.Second)}, - {54, UnixEpoch().Add(54 * time.Nanosecond)}, - } - - for _, tc := range testCases { - t.Run("", func(subT *testing.T) { - var marshaled []byte - - if temp, err := UnixTime(tc.subject).MarshalBinary(); err == nil { - marshaled = temp - } else { - subT.Error(err) - return - } - - var unmarshaled int64 - if err := binary.Read(bytes.NewReader(marshaled), binary.LittleEndian, &unmarshaled); err != nil { - subT.Error(err) - return - } - - if unmarshaled != tc.expected { - subT.Logf("\ngot: \t%d\nwant:\t%d", unmarshaled, tc.expected) - subT.Fail() - } - }) - } -} - -func TestUnixTime_BinaryRoundTrip(t *testing.T) { - testCases := []time.Time{ - UnixEpoch(), - UnixEpoch().Add(800 * time.Minute), - UnixEpoch().Add(7 * time.Hour), - UnixEpoch().Add(-1 * time.Nanosecond), - } - - for _, tc := range testCases { - t.Run(tc.String(), func(subT *testing.T) { - original := UnixTime(tc) - var marshaled []byte - - if temp, err := original.MarshalBinary(); err == nil { - marshaled = temp - } else { - subT.Error(err) - return - } - - var traveled UnixTime - if err := traveled.UnmarshalBinary(marshaled); err != nil { - subT.Error(err) - return - } - - if traveled != original { - subT.Logf("\ngot: \t%s\nwant:\t%s", time.Time(original).String(), time.Time(traveled).String()) - subT.Fail() - } - }) - } -} - -func TestUnixTime_MarshalText(t *testing.T) { - testCases := []time.Time{ - UnixEpoch(), - UnixEpoch().Add(45 * time.Second), - UnixEpoch().Add(time.Nanosecond), - UnixEpoch().Add(-100000 * time.Second), - } - - for _, tc := range testCases { - expected, _ := tc.MarshalText() - t.Run("", func(subT *testing.T) { - var marshaled []byte - - if temp, err := UnixTime(tc).MarshalText(); err == nil { - marshaled = temp - } else { - subT.Error(err) - return - } - - if string(marshaled) != string(expected) { - subT.Logf("\ngot: \t%s\nwant:\t%s", string(marshaled), string(expected)) - subT.Fail() - } - }) - } -} - -func TestUnixTime_TextRoundTrip(t *testing.T) { - testCases := []time.Time{ - UnixEpoch(), - UnixEpoch().Add(-1 * time.Nanosecond), - UnixEpoch().Add(1 * time.Nanosecond), - time.Date(2017, time.April, 17, 21, 00, 00, 00, time.UTC), - } - - for _, tc := range testCases { - t.Run(tc.String(), func(subT *testing.T) { - unixTC := UnixTime(tc) - - var marshaled []byte - - if temp, err := unixTC.MarshalText(); err == nil { - marshaled = temp - } else { - subT.Error(err) - return - } - - var unmarshaled UnixTime - if err := unmarshaled.UnmarshalText(marshaled); err != nil { - subT.Error(err) - return - } - - if unmarshaled != unixTC { - t.Logf("\ngot: \t%s\nwant:\t%s", time.Time(unmarshaled).String(), tc.String()) - t.Fail() - } - }) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/error_test.go b/vendor/github.com/Azure/go-autorest/autorest/error_test.go deleted file mode 100644 index 177f7f26..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/error_test.go +++ /dev/null @@ -1,202 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "fmt" - "net/http" - "reflect" - "regexp" - "testing" -) - -func TestNewErrorWithError_AssignsPackageType(t *testing.T) { - e := NewErrorWithError(fmt.Errorf("original"), "packageType", "method", nil, "message") - - if e.PackageType != "packageType" { - t.Fatalf("autorest: Error failed to set package type -- expected %v, received %v", "packageType", e.PackageType) - } -} - -func TestNewErrorWithError_AssignsMethod(t *testing.T) { - e := NewErrorWithError(fmt.Errorf("original"), "packageType", "method", nil, "message") - - if e.Method != "method" { - t.Fatalf("autorest: Error failed to set method -- expected %v, received %v", "method", e.Method) - } -} - -func TestNewErrorWithError_AssignsMessage(t *testing.T) { - e := NewErrorWithError(fmt.Errorf("original"), "packageType", "method", nil, "message") - - if e.Message != "message" { - t.Fatalf("autorest: Error failed to set message -- expected %v, received %v", "message", e.Message) - } -} - -func TestNewErrorWithError_AssignsUndefinedStatusCodeIfRespNil(t *testing.T) { - e := NewErrorWithError(nil, "packageType", "method", nil, "message") - if e.StatusCode != UndefinedStatusCode { - t.Fatalf("autorest: Error failed to set status code -- expected %v, received %v", UndefinedStatusCode, e.StatusCode) - } -} - -func TestNewErrorWithError_AssignsStatusCode(t *testing.T) { - e := NewErrorWithError(fmt.Errorf("original"), "packageType", "method", &http.Response{ - StatusCode: http.StatusBadRequest, - Status: http.StatusText(http.StatusBadRequest)}, "message") - - if e.StatusCode != http.StatusBadRequest { - t.Fatalf("autorest: Error failed to set status code -- expected %v, received %v", http.StatusBadRequest, e.StatusCode) - } -} - -func TestNewErrorWithError_AcceptsArgs(t *testing.T) { - e := NewErrorWithError(fmt.Errorf("original"), "packageType", "method", nil, "message %s", "arg") - - if matched, _ := regexp.MatchString(`.*arg.*`, e.Message); !matched { - t.Fatalf("autorest: Error failed to apply message arguments -- expected %v, received %v", - `.*arg.*`, e.Message) - } -} - -func TestNewErrorWithError_AssignsError(t *testing.T) { - err := fmt.Errorf("original") - e := NewErrorWithError(err, "packageType", "method", nil, "message") - - if e.Original != err { - t.Fatalf("autorest: Error failed to set error -- expected %v, received %v", err, e.Original) - } -} - -func TestNewErrorWithResponse_ContainsStatusCode(t *testing.T) { - e := NewErrorWithResponse("packageType", "method", &http.Response{ - StatusCode: http.StatusBadRequest, - Status: http.StatusText(http.StatusBadRequest)}, "message") - - if e.StatusCode != http.StatusBadRequest { - t.Fatalf("autorest: Error failed to set status code -- expected %v, received %v", http.StatusBadRequest, e.StatusCode) - } -} - -func TestNewErrorWithResponse_nilResponse_ReportsUndefinedStatusCode(t *testing.T) { - e := NewErrorWithResponse("packageType", "method", nil, "message") - - if e.StatusCode != UndefinedStatusCode { - t.Fatalf("autorest: Error failed to set status code -- expected %v, received %v", UndefinedStatusCode, e.StatusCode) - } -} - -func TestNewErrorWithResponse_Forwards(t *testing.T) { - e1 := NewError("packageType", "method", "message %s", "arg") - e2 := NewErrorWithResponse("packageType", "method", nil, "message %s", "arg") - - if !reflect.DeepEqual(e1, e2) { - t.Fatal("autorest: NewError did not return an error equivalent to NewErrorWithError") - } -} - -func TestNewErrorWithError_Forwards(t *testing.T) { - e1 := NewError("packageType", "method", "message %s", "arg") - e2 := NewErrorWithError(nil, "packageType", "method", nil, "message %s", "arg") - - if !reflect.DeepEqual(e1, e2) { - t.Fatal("autorest: NewError did not return an error equivalent to NewErrorWithError") - } -} - -func TestNewErrorWithError_DoesNotWrapADetailedError(t *testing.T) { - e1 := NewError("packageType1", "method1", "message1 %s", "arg1") - e2 := NewErrorWithError(e1, "packageType2", "method2", nil, "message2 %s", "arg2") - - if !reflect.DeepEqual(e1, e2) { - t.Fatalf("autorest: NewErrorWithError incorrectly wrapped a DetailedError -- expected %v, received %v", e1, e2) - } -} - -func TestNewErrorWithError_WrapsAnError(t *testing.T) { - e1 := fmt.Errorf("Inner Error") - var e2 interface{} = NewErrorWithError(e1, "packageType", "method", nil, "message") - - if _, ok := e2.(DetailedError); !ok { - t.Fatalf("autorest: NewErrorWithError failed to wrap a standard error -- received %T", e2) - } -} - -func TestDetailedError(t *testing.T) { - err := fmt.Errorf("original") - e := NewErrorWithError(err, "packageType", "method", nil, "message") - - if matched, _ := regexp.MatchString(`.*original.*`, e.Error()); !matched { - t.Fatalf("autorest: Error#Error failed to return original error message -- expected %v, received %v", - `.*original.*`, e.Error()) - } -} - -func TestDetailedErrorConstainsPackageType(t *testing.T) { - e := NewErrorWithError(fmt.Errorf("original"), "packageType", "method", nil, "message") - - if matched, _ := regexp.MatchString(`.*packageType.*`, e.Error()); !matched { - t.Fatalf("autorest: Error#String failed to include PackageType -- expected %v, received %v", - `.*packageType.*`, e.Error()) - } -} - -func TestDetailedErrorConstainsMethod(t *testing.T) { - e := NewErrorWithError(fmt.Errorf("original"), "packageType", "method", nil, "message") - - if matched, _ := regexp.MatchString(`.*method.*`, e.Error()); !matched { - t.Fatalf("autorest: Error#String failed to include Method -- expected %v, received %v", - `.*method.*`, e.Error()) - } -} - -func TestDetailedErrorConstainsMessage(t *testing.T) { - e := NewErrorWithError(fmt.Errorf("original"), "packageType", "method", nil, "message") - - if matched, _ := regexp.MatchString(`.*message.*`, e.Error()); !matched { - t.Fatalf("autorest: Error#String failed to include Message -- expected %v, received %v", - `.*message.*`, e.Error()) - } -} - -func TestDetailedErrorConstainsStatusCode(t *testing.T) { - e := NewErrorWithError(fmt.Errorf("original"), "packageType", "method", &http.Response{ - StatusCode: http.StatusBadRequest, - Status: http.StatusText(http.StatusBadRequest)}, "message") - - if matched, _ := regexp.MatchString(`.*400.*`, e.Error()); !matched { - t.Fatalf("autorest: Error#String failed to include Status Code -- expected %v, received %v", - `.*400.*`, e.Error()) - } -} - -func TestDetailedErrorConstainsOriginal(t *testing.T) { - e := NewErrorWithError(fmt.Errorf("original"), "packageType", "method", nil, "message") - - if matched, _ := regexp.MatchString(`.*original.*`, e.Error()); !matched { - t.Fatalf("autorest: Error#String failed to include Original error -- expected %v, received %v", - `.*original.*`, e.Error()) - } -} - -func TestDetailedErrorSkipsOriginal(t *testing.T) { - e := NewError("packageType", "method", "message") - - if matched, _ := regexp.MatchString(`.*Original.*`, e.Error()); matched { - t.Fatalf("autorest: Error#String included missing Original error -- unexpected %v, received %v", - `.*Original.*`, e.Error()) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/preparer_test.go b/vendor/github.com/Azure/go-autorest/autorest/preparer_test.go deleted file mode 100644 index b4d19967..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/preparer_test.go +++ /dev/null @@ -1,802 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "fmt" - "io/ioutil" - "net/http" - "net/url" - "reflect" - "strconv" - "strings" - "testing" - - "github.com/Azure/go-autorest/autorest/mocks" -) - -// PrepareDecorators wrap and invoke a Preparer. Most often, the decorator invokes the passed -// Preparer and decorates the response. -func ExamplePrepareDecorator() { - path := "a/b/c/" - pd := func() PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err == nil { - if r.URL == nil { - return r, fmt.Errorf("ERROR: URL is not set") - } - r.URL.Path += path - } - return r, err - }) - } - } - - r, _ := Prepare(&http.Request{}, - WithBaseURL("https://microsoft.com/"), - pd()) - - fmt.Printf("Path is %s\n", r.URL) - // Output: Path is https://microsoft.com/a/b/c/ -} - -// PrepareDecorators may also modify and then invoke the Preparer. -func ExamplePrepareDecorator_pre() { - pd := func() PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r.Header.Add(http.CanonicalHeaderKey("ContentType"), "application/json") - return p.Prepare(r) - }) - } - } - - r, _ := Prepare(&http.Request{Header: http.Header{}}, - pd()) - - fmt.Printf("ContentType is %s\n", r.Header.Get("ContentType")) - // Output: ContentType is application/json -} - -// Create a sequence of three Preparers that build up the URL path. -func ExampleCreatePreparer() { - p := CreatePreparer( - WithBaseURL("https://microsoft.com/"), - WithPath("a"), - WithPath("b"), - WithPath("c")) - r, err := p.Prepare(&http.Request{}) - if err != nil { - fmt.Printf("ERROR: %v\n", err) - } else { - fmt.Println(r.URL) - } - // Output: https://microsoft.com/a/b/c -} - -// Create and apply separate Preparers -func ExampleCreatePreparer_multiple() { - params := map[string]interface{}{ - "param1": "a", - "param2": "c", - } - - p1 := CreatePreparer(WithBaseURL("https://microsoft.com/")) - p2 := CreatePreparer(WithPathParameters("/{param1}/b/{param2}/", params)) - - r, err := p1.Prepare(&http.Request{}) - if err != nil { - fmt.Printf("ERROR: %v\n", err) - } - - r, err = p2.Prepare(r) - if err != nil { - fmt.Printf("ERROR: %v\n", err) - } else { - fmt.Println(r.URL) - } - // Output: https://microsoft.com/a/b/c/ -} - -// Create and chain separate Preparers -func ExampleCreatePreparer_chain() { - params := map[string]interface{}{ - "param1": "a", - "param2": "c", - } - - p := CreatePreparer(WithBaseURL("https://microsoft.com/")) - p = DecoratePreparer(p, WithPathParameters("/{param1}/b/{param2}/", params)) - - r, err := p.Prepare(&http.Request{}) - if err != nil { - fmt.Printf("ERROR: %v\n", err) - } else { - fmt.Println(r.URL) - } - // Output: https://microsoft.com/a/b/c/ -} - -// Create and prepare an http.Request in one call -func ExamplePrepare() { - r, err := Prepare(&http.Request{}, - AsGet(), - WithBaseURL("https://microsoft.com/"), - WithPath("a/b/c/")) - if err != nil { - fmt.Printf("ERROR: %v\n", err) - } else { - fmt.Printf("%s %s", r.Method, r.URL) - } - // Output: GET https://microsoft.com/a/b/c/ -} - -// Create a request for a supplied base URL and path -func ExampleWithBaseURL() { - r, err := Prepare(&http.Request{}, - WithBaseURL("https://microsoft.com/a/b/c/")) - if err != nil { - fmt.Printf("ERROR: %v\n", err) - } else { - fmt.Println(r.URL) - } - // Output: https://microsoft.com/a/b/c/ -} - -func ExampleWithBaseURL_second() { - _, err := Prepare(&http.Request{}, WithBaseURL(":")) - fmt.Println(err) - // Output: parse :: missing protocol scheme -} - -func ExampleWithCustomBaseURL() { - r, err := Prepare(&http.Request{}, - WithCustomBaseURL("https://{account}.{service}.core.windows.net/", - map[string]interface{}{ - "account": "myaccount", - "service": "blob", - })) - if err != nil { - fmt.Printf("ERROR: %v\n", err) - } else { - fmt.Println(r.URL) - } - // Output: https://myaccount.blob.core.windows.net/ -} - -func ExampleWithCustomBaseURL_second() { - _, err := Prepare(&http.Request{}, - WithCustomBaseURL(":", map[string]interface{}{})) - fmt.Println(err) - // Output: parse :: missing protocol scheme -} - -// Create a request with a custom HTTP header -func ExampleWithHeader() { - r, err := Prepare(&http.Request{}, - WithBaseURL("https://microsoft.com/a/b/c/"), - WithHeader("x-foo", "bar")) - if err != nil { - fmt.Printf("ERROR: %v\n", err) - } else { - fmt.Printf("Header %s=%s\n", "x-foo", r.Header.Get("x-foo")) - } - // Output: Header x-foo=bar -} - -// Create a request whose Body is the JSON encoding of a structure -func ExampleWithFormData() { - v := url.Values{} - v.Add("name", "Rob Pike") - v.Add("age", "42") - - r, err := Prepare(&http.Request{}, - WithFormData(v)) - if err != nil { - fmt.Printf("ERROR: %v\n", err) - } - - b, err := ioutil.ReadAll(r.Body) - if err != nil { - fmt.Printf("ERROR: %v\n", err) - } else { - fmt.Printf("Request Body contains %s\n", string(b)) - } - // Output: Request Body contains age=42&name=Rob+Pike -} - -// Create a request whose Body is the JSON encoding of a structure -func ExampleWithJSON() { - t := mocks.T{Name: "Rob Pike", Age: 42} - - r, err := Prepare(&http.Request{}, - WithJSON(&t)) - if err != nil { - fmt.Printf("ERROR: %v\n", err) - } - - b, err := ioutil.ReadAll(r.Body) - if err != nil { - fmt.Printf("ERROR: %v\n", err) - } else { - fmt.Printf("Request Body contains %s\n", string(b)) - } - // Output: Request Body contains {"name":"Rob Pike","age":42} -} - -// Create a request from a path with escaped parameters -func ExampleWithEscapedPathParameters() { - params := map[string]interface{}{ - "param1": "a b c", - "param2": "d e f", - } - r, err := Prepare(&http.Request{}, - WithBaseURL("https://microsoft.com/"), - WithEscapedPathParameters("/{param1}/b/{param2}/", params)) - if err != nil { - fmt.Printf("ERROR: %v\n", err) - } else { - fmt.Println(r.URL) - } - // Output: https://microsoft.com/a+b+c/b/d+e+f/ -} - -// Create a request from a path with parameters -func ExampleWithPathParameters() { - params := map[string]interface{}{ - "param1": "a", - "param2": "c", - } - r, err := Prepare(&http.Request{}, - WithBaseURL("https://microsoft.com/"), - WithPathParameters("/{param1}/b/{param2}/", params)) - if err != nil { - fmt.Printf("ERROR: %v\n", err) - } else { - fmt.Println(r.URL) - } - // Output: https://microsoft.com/a/b/c/ -} - -// Create a request with query parameters -func ExampleWithQueryParameters() { - params := map[string]interface{}{ - "q1": "value1", - "q2": "value2", - } - r, err := Prepare(&http.Request{}, - WithBaseURL("https://microsoft.com/"), - WithPath("/a/b/c/"), - WithQueryParameters(params)) - if err != nil { - fmt.Printf("ERROR: %v\n", err) - } else { - fmt.Println(r.URL) - } - // Output: https://microsoft.com/a/b/c/?q1=value1&q2=value2 -} - -func TestWithCustomBaseURL(t *testing.T) { - r, err := Prepare(&http.Request{}, WithCustomBaseURL("https://{account}.{service}.core.windows.net/", - map[string]interface{}{ - "account": "myaccount", - "service": "blob", - })) - if err != nil { - t.Fatalf("autorest: WithCustomBaseURL should not fail") - } - if r.URL.String() != "https://myaccount.blob.core.windows.net/" { - t.Fatalf("autorest: WithCustomBaseURL expected https://myaccount.blob.core.windows.net/, got %s", r.URL) - } -} - -func TestWithCustomBaseURLwithInvalidURL(t *testing.T) { - _, err := Prepare(&http.Request{}, WithCustomBaseURL("hello/{account}.{service}.core.windows.net/", - map[string]interface{}{ - "account": "myaccount", - "service": "blob", - })) - if err == nil { - t.Fatalf("autorest: WithCustomBaseURL should fail fo URL parse error") - } -} - -func TestWithPathWithInvalidPath(t *testing.T) { - p := "path%2*end" - if _, err := Prepare(&http.Request{}, WithBaseURL("https://microsoft.com/"), WithPath(p)); err == nil { - t.Fatalf("autorest: WithPath should fail for invalid URL escape error for path '%v' ", p) - } - -} - -func TestWithPathParametersWithInvalidPath(t *testing.T) { - p := "path%2*end" - m := map[string]interface{}{ - "path1": p, - } - if _, err := Prepare(&http.Request{}, WithBaseURL("https://microsoft.com/"), WithPathParameters("/{path1}/", m)); err == nil { - t.Fatalf("autorest: WithPath should fail for invalid URL escape for path '%v' ", p) - } - -} - -func TestCreatePreparerDoesNotModify(t *testing.T) { - r1 := &http.Request{} - p := CreatePreparer() - r2, err := p.Prepare(r1) - if err != nil { - t.Fatalf("autorest: CreatePreparer failed (%v)", err) - } - if !reflect.DeepEqual(r1, r2) { - t.Fatalf("autorest: CreatePreparer without decorators modified the request") - } -} - -func TestCreatePreparerRunsDecoratorsInOrder(t *testing.T) { - p := CreatePreparer(WithBaseURL("https://microsoft.com/"), WithPath("1"), WithPath("2"), WithPath("3")) - r, err := p.Prepare(&http.Request{}) - if err != nil { - t.Fatalf("autorest: CreatePreparer failed (%v)", err) - } - if r.URL.String() != "https:/1/2/3" && r.URL.Host != "microsoft.com" { - t.Fatalf("autorest: CreatePreparer failed to run decorators in order") - } -} - -func TestAsContentType(t *testing.T) { - r, err := Prepare(mocks.NewRequest(), AsContentType("application/text")) - if err != nil { - fmt.Printf("ERROR: %v", err) - } - if r.Header.Get(headerContentType) != "application/text" { - t.Fatalf("autorest: AsContentType failed to add header (%s=%s)", headerContentType, r.Header.Get(headerContentType)) - } -} - -func TestAsFormURLEncoded(t *testing.T) { - r, err := Prepare(mocks.NewRequest(), AsFormURLEncoded()) - if err != nil { - fmt.Printf("ERROR: %v", err) - } - if r.Header.Get(headerContentType) != mimeTypeFormPost { - t.Fatalf("autorest: AsFormURLEncoded failed to add header (%s=%s)", headerContentType, r.Header.Get(headerContentType)) - } -} - -func TestAsJSON(t *testing.T) { - r, err := Prepare(mocks.NewRequest(), AsJSON()) - if err != nil { - fmt.Printf("ERROR: %v", err) - } - if r.Header.Get(headerContentType) != mimeTypeJSON { - t.Fatalf("autorest: AsJSON failed to add header (%s=%s)", headerContentType, r.Header.Get(headerContentType)) - } -} - -func TestWithNothing(t *testing.T) { - r1 := mocks.NewRequest() - r2, err := Prepare(r1, WithNothing()) - if err != nil { - t.Fatalf("autorest: WithNothing returned an unexpected error (%v)", err) - } - - if !reflect.DeepEqual(r1, r2) { - t.Fatal("azure: WithNothing modified the passed HTTP Request") - } -} - -func TestWithBearerAuthorization(t *testing.T) { - r, err := Prepare(mocks.NewRequest(), WithBearerAuthorization("SOME-TOKEN")) - if err != nil { - fmt.Printf("ERROR: %v", err) - } - if r.Header.Get(headerAuthorization) != "Bearer SOME-TOKEN" { - t.Fatalf("autorest: WithBearerAuthorization failed to add header (%s=%s)", headerAuthorization, r.Header.Get(headerAuthorization)) - } -} - -func TestWithUserAgent(t *testing.T) { - ua := "User Agent Go" - r, err := Prepare(mocks.NewRequest(), WithUserAgent(ua)) - if err != nil { - fmt.Printf("ERROR: %v", err) - } - if r.UserAgent() != ua || r.Header.Get(headerUserAgent) != ua { - t.Fatalf("autorest: WithUserAgent failed to add header (%s=%s)", headerUserAgent, r.Header.Get(headerUserAgent)) - } -} - -func TestWithMethod(t *testing.T) { - r, _ := Prepare(mocks.NewRequest(), WithMethod("HEAD")) - if r.Method != "HEAD" { - t.Fatal("autorest: WithMethod failed to set HTTP method header") - } -} - -func TestAsDelete(t *testing.T) { - r, _ := Prepare(mocks.NewRequest(), AsDelete()) - if r.Method != "DELETE" { - t.Fatal("autorest: AsDelete failed to set HTTP method header to DELETE") - } -} - -func TestAsGet(t *testing.T) { - r, _ := Prepare(mocks.NewRequest(), AsGet()) - if r.Method != "GET" { - t.Fatal("autorest: AsGet failed to set HTTP method header to GET") - } -} - -func TestAsHead(t *testing.T) { - r, _ := Prepare(mocks.NewRequest(), AsHead()) - if r.Method != "HEAD" { - t.Fatal("autorest: AsHead failed to set HTTP method header to HEAD") - } -} - -func TestAsOptions(t *testing.T) { - r, _ := Prepare(mocks.NewRequest(), AsOptions()) - if r.Method != "OPTIONS" { - t.Fatal("autorest: AsOptions failed to set HTTP method header to OPTIONS") - } -} - -func TestAsPatch(t *testing.T) { - r, _ := Prepare(mocks.NewRequest(), AsPatch()) - if r.Method != "PATCH" { - t.Fatal("autorest: AsPatch failed to set HTTP method header to PATCH") - } -} - -func TestAsPost(t *testing.T) { - r, _ := Prepare(mocks.NewRequest(), AsPost()) - if r.Method != "POST" { - t.Fatal("autorest: AsPost failed to set HTTP method header to POST") - } -} - -func TestAsPut(t *testing.T) { - r, _ := Prepare(mocks.NewRequest(), AsPut()) - if r.Method != "PUT" { - t.Fatal("autorest: AsPut failed to set HTTP method header to PUT") - } -} - -func TestPrepareWithNullRequest(t *testing.T) { - _, err := Prepare(nil) - if err == nil { - t.Fatal("autorest: Prepare failed to return an error when given a null http.Request") - } -} - -func TestWithFormData(t *testing.T) { - v := url.Values{} - v.Add("name", "Rob Pike") - v.Add("age", "42") - - r, err := Prepare(&http.Request{}, - WithFormData(v)) - if err != nil { - t.Fatalf("autorest: WithFormData failed with error (%v)", err) - } - - b, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatalf("autorest: WithFormData failed with error (%v)", err) - } - - expected := "name=Rob+Pike&age=42" - if !(string(b) == "name=Rob+Pike&age=42" || string(b) == "age=42&name=Rob+Pike") { - t.Fatalf("autorest:WithFormData failed to return correct string got (%v), expected (%v)", string(b), expected) - } - - if r.ContentLength != int64(len(b)) { - t.Fatalf("autorest:WithFormData set Content-Length to %v, expected %v", r.ContentLength, len(b)) - } - - if expected, got := r.Header.Get(http.CanonicalHeaderKey(headerContentType)), mimeTypeFormPost; expected != got { - t.Fatalf("autorest:WithFormData Content Type not set or set to wrong value. Expected %v and got %v", expected, got) - } -} - -func TestWithMultiPartFormDataSetsContentLength(t *testing.T) { - v := map[string]interface{}{ - "file": ioutil.NopCloser(strings.NewReader("Hello Gopher")), - "age": "42", - } - - r, err := Prepare(&http.Request{}, - WithMultiPartFormData(v)) - if err != nil { - t.Fatalf("autorest: WithMultiPartFormData failed with error (%v)", err) - } - - b, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatalf("autorest: WithMultiPartFormData failed with error (%v)", err) - } - - if r.ContentLength != int64(len(b)) { - t.Fatalf("autorest:WithMultiPartFormData set Content-Length to %v, expected %v", r.ContentLength, len(b)) - } -} - -func TestWithMultiPartFormDataWithNoFile(t *testing.T) { - v := map[string]interface{}{ - "file": "no file", - "age": "42", - } - - r, err := Prepare(&http.Request{}, - WithMultiPartFormData(v)) - if err != nil { - t.Fatalf("autorest: WithMultiPartFormData failed with error (%v)", err) - } - - b, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatalf("autorest: WithMultiPartFormData failed with error (%v)", err) - } - - if r.ContentLength != int64(len(b)) { - t.Fatalf("autorest:WithMultiPartFormData set Content-Length to %v, expected %v", r.ContentLength, len(b)) - } -} - -func TestWithFile(t *testing.T) { - r, err := Prepare(&http.Request{}, - WithFile(ioutil.NopCloser(strings.NewReader("Hello Gopher")))) - if err != nil { - t.Fatalf("autorest: WithFile failed with error (%v)", err) - } - - b, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatalf("autorest: WithFile failed with error (%v)", err) - } - if r.ContentLength != int64(len(b)) { - t.Fatalf("autorest:WithFile set Content-Length to %v, expected %v", r.ContentLength, len(b)) - } -} - -func TestWithBool_SetsTheBody(t *testing.T) { - r, err := Prepare(&http.Request{}, - WithBool(false)) - if err != nil { - t.Fatalf("autorest: WithBool failed with error (%v)", err) - } - - s, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatalf("autorest: WithBool failed with error (%v)", err) - } - - if r.ContentLength != int64(len(fmt.Sprintf("%v", false))) { - t.Fatalf("autorest: WithBool set Content-Length to %v, expected %v", r.ContentLength, int64(len(fmt.Sprintf("%v", false)))) - } - - v, err := strconv.ParseBool(string(s)) - if err != nil || v { - t.Fatalf("autorest: WithBool incorrectly encoded the boolean as %v", s) - } -} - -func TestWithFloat32_SetsTheBody(t *testing.T) { - r, err := Prepare(&http.Request{}, - WithFloat32(42.0)) - if err != nil { - t.Fatalf("autorest: WithFloat32 failed with error (%v)", err) - } - - s, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatalf("autorest: WithFloat32 failed with error (%v)", err) - } - - if r.ContentLength != int64(len(fmt.Sprintf("%v", 42.0))) { - t.Fatalf("autorest: WithFloat32 set Content-Length to %v, expected %v", r.ContentLength, int64(len(fmt.Sprintf("%v", 42.0)))) - } - - v, err := strconv.ParseFloat(string(s), 32) - if err != nil || float32(v) != float32(42.0) { - t.Fatalf("autorest: WithFloat32 incorrectly encoded the boolean as %v", s) - } -} - -func TestWithFloat64_SetsTheBody(t *testing.T) { - r, err := Prepare(&http.Request{}, - WithFloat64(42.0)) - if err != nil { - t.Fatalf("autorest: WithFloat64 failed with error (%v)", err) - } - - s, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatalf("autorest: WithFloat64 failed with error (%v)", err) - } - - if r.ContentLength != int64(len(fmt.Sprintf("%v", 42.0))) { - t.Fatalf("autorest: WithFloat64 set Content-Length to %v, expected %v", r.ContentLength, int64(len(fmt.Sprintf("%v", 42.0)))) - } - - v, err := strconv.ParseFloat(string(s), 64) - if err != nil || v != float64(42.0) { - t.Fatalf("autorest: WithFloat64 incorrectly encoded the boolean as %v", s) - } -} - -func TestWithInt32_SetsTheBody(t *testing.T) { - r, err := Prepare(&http.Request{}, - WithInt32(42)) - if err != nil { - t.Fatalf("autorest: WithInt32 failed with error (%v)", err) - } - - s, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatalf("autorest: WithInt32 failed with error (%v)", err) - } - - if r.ContentLength != int64(len(fmt.Sprintf("%v", 42))) { - t.Fatalf("autorest: WithInt32 set Content-Length to %v, expected %v", r.ContentLength, int64(len(fmt.Sprintf("%v", 42)))) - } - - v, err := strconv.ParseInt(string(s), 10, 32) - if err != nil || int32(v) != int32(42) { - t.Fatalf("autorest: WithInt32 incorrectly encoded the boolean as %v", s) - } -} - -func TestWithInt64_SetsTheBody(t *testing.T) { - r, err := Prepare(&http.Request{}, - WithInt64(42)) - if err != nil { - t.Fatalf("autorest: WithInt64 failed with error (%v)", err) - } - - s, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatalf("autorest: WithInt64 failed with error (%v)", err) - } - - if r.ContentLength != int64(len(fmt.Sprintf("%v", 42))) { - t.Fatalf("autorest: WithInt64 set Content-Length to %v, expected %v", r.ContentLength, int64(len(fmt.Sprintf("%v", 42)))) - } - - v, err := strconv.ParseInt(string(s), 10, 64) - if err != nil || v != int64(42) { - t.Fatalf("autorest: WithInt64 incorrectly encoded the boolean as %v", s) - } -} - -func TestWithString_SetsTheBody(t *testing.T) { - r, err := Prepare(&http.Request{}, - WithString("value")) - if err != nil { - t.Fatalf("autorest: WithString failed with error (%v)", err) - } - - s, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatalf("autorest: WithString failed with error (%v)", err) - } - - if r.ContentLength != int64(len("value")) { - t.Fatalf("autorest: WithString set Content-Length to %v, expected %v", r.ContentLength, int64(len("value"))) - } - - if string(s) != "value" { - t.Fatalf("autorest: WithString incorrectly encoded the string as %v", s) - } -} - -func TestWithJSONSetsContentLength(t *testing.T) { - r, err := Prepare(&http.Request{}, - WithJSON(&mocks.T{Name: "Rob Pike", Age: 42})) - if err != nil { - t.Fatalf("autorest: WithJSON failed with error (%v)", err) - } - - b, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatalf("autorest: WithJSON failed with error (%v)", err) - } - - if r.ContentLength != int64(len(b)) { - t.Fatalf("autorest:WithJSON set Content-Length to %v, expected %v", r.ContentLength, len(b)) - } -} - -func TestWithHeaderAllocatesHeaders(t *testing.T) { - r, err := Prepare(mocks.NewRequest(), WithHeader("x-foo", "bar")) - if err != nil { - t.Fatalf("autorest: WithHeader failed (%v)", err) - } - if r.Header.Get("x-foo") != "bar" { - t.Fatalf("autorest: WithHeader failed to add header (%s=%s)", "x-foo", r.Header.Get("x-foo")) - } -} - -func TestWithPathCatchesNilURL(t *testing.T) { - _, err := Prepare(&http.Request{}, WithPath("a")) - if err == nil { - t.Fatalf("autorest: WithPath failed to catch a nil URL") - } -} - -func TestWithEscapedPathParametersCatchesNilURL(t *testing.T) { - _, err := Prepare(&http.Request{}, WithEscapedPathParameters("", map[string]interface{}{"foo": "bar"})) - if err == nil { - t.Fatalf("autorest: WithEscapedPathParameters failed to catch a nil URL") - } -} - -func TestWithPathParametersCatchesNilURL(t *testing.T) { - _, err := Prepare(&http.Request{}, WithPathParameters("", map[string]interface{}{"foo": "bar"})) - if err == nil { - t.Fatalf("autorest: WithPathParameters failed to catch a nil URL") - } -} - -func TestWithQueryParametersCatchesNilURL(t *testing.T) { - _, err := Prepare(&http.Request{}, WithQueryParameters(map[string]interface{}{"foo": "bar"})) - if err == nil { - t.Fatalf("autorest: WithQueryParameters failed to catch a nil URL") - } -} - -func TestModifyingExistingRequest(t *testing.T) { - r, err := Prepare(mocks.NewRequestForURL("https://bing.com"), WithPath("search"), WithQueryParameters(map[string]interface{}{"q": "golang"})) - if err != nil { - t.Fatalf("autorest: Preparing an existing request returned an error (%v)", err) - } - if r.URL.Host != "bing.com" { - t.Fatalf("autorest: Preparing an existing request failed when setting the host (%s)", r.URL) - } - - if r.URL.Path != "/search" { - t.Fatalf("autorest: Preparing an existing request failed when setting the path (%s)", r.URL.Path) - } - - if r.URL.RawQuery != "q=golang" { - t.Fatalf("autorest: Preparing an existing request failed when setting the query parameters (%s)", r.URL.RawQuery) - } -} - -func TestModifyingRequestWithExistingQueryParameters(t *testing.T) { - r, err := Prepare( - mocks.NewRequestForURL("https://bing.com"), - WithPath("search"), - WithQueryParameters(map[string]interface{}{"q": "golang the best"}), - WithQueryParameters(map[string]interface{}{"pq": "golang+encoded"}), - ) - if err != nil { - t.Fatalf("autorest: Preparing an existing request returned an error (%v)", err) - } - - if r.URL.Host != "bing.com" { - t.Fatalf("autorest: Preparing an existing request failed when setting the host (%s)", r.URL) - } - - if r.URL.Path != "/search" { - t.Fatalf("autorest: Preparing an existing request failed when setting the path (%s)", r.URL.Path) - } - - if r.URL.RawQuery != "pq=golang+encoded&q=golang+the+best" { - t.Fatalf("autorest: Preparing an existing request failed when setting the query parameters (%s)", r.URL.RawQuery) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/responder_test.go b/vendor/github.com/Azure/go-autorest/autorest/responder_test.go deleted file mode 100644 index 4a57b1e3..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/responder_test.go +++ /dev/null @@ -1,665 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "bytes" - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "reflect" - "strings" - "testing" - - "github.com/Azure/go-autorest/autorest/mocks" -) - -func ExampleWithErrorUnlessOK() { - r := mocks.NewResponse() - r.Request = mocks.NewRequest() - - // Respond and leave the response body open (for a subsequent responder to close) - err := Respond(r, - WithErrorUnlessOK(), - ByDiscardingBody(), - ByClosingIfError()) - - if err == nil { - fmt.Printf("%s of %s returned HTTP 200", r.Request.Method, r.Request.URL) - - // Complete handling the response and close the body - Respond(r, - ByDiscardingBody(), - ByClosing()) - } - // Output: GET of https://microsoft.com/a/b/c/ returned HTTP 200 -} - -func ExampleByUnmarshallingJSON() { - c := ` - { - "name" : "Rob Pike", - "age" : 42 - } - ` - - type V struct { - Name string `json:"name"` - Age int `json:"age"` - } - - v := &V{} - - Respond(mocks.NewResponseWithContent(c), - ByUnmarshallingJSON(v), - ByClosing()) - - fmt.Printf("%s is %d years old\n", v.Name, v.Age) - // Output: Rob Pike is 42 years old -} - -func ExampleByUnmarshallingXML() { - c := ` - - Rob Pike - 42 - ` - - type V struct { - Name string `xml:"Name"` - Age int `xml:"Age"` - } - - v := &V{} - - Respond(mocks.NewResponseWithContent(c), - ByUnmarshallingXML(v), - ByClosing()) - - fmt.Printf("%s is %d years old\n", v.Name, v.Age) - // Output: Rob Pike is 42 years old -} - -func TestCreateResponderDoesNotModify(t *testing.T) { - r1 := mocks.NewResponse() - r2 := mocks.NewResponse() - p := CreateResponder() - err := p.Respond(r1) - if err != nil { - t.Fatalf("autorest: CreateResponder failed (%v)", err) - } - if !reflect.DeepEqual(r1, r2) { - t.Fatalf("autorest: CreateResponder without decorators modified the response") - } -} - -func TestCreateResponderRunsDecoratorsInOrder(t *testing.T) { - s := "" - - d := func(n int) RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - err := r.Respond(resp) - if err == nil { - s += fmt.Sprintf("%d", n) - } - return err - }) - } - } - - p := CreateResponder(d(1), d(2), d(3)) - err := p.Respond(&http.Response{}) - if err != nil { - t.Fatalf("autorest: Respond failed (%v)", err) - } - - if s != "123" { - t.Fatalf("autorest: CreateResponder invoked decorators in an incorrect order; expected '123', received '%s'", s) - } -} - -func TestByIgnoring(t *testing.T) { - r := mocks.NewResponse() - - Respond(r, - (func() RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(r2 *http.Response) error { - r1 := mocks.NewResponse() - if !reflect.DeepEqual(r1, r2) { - t.Fatalf("autorest: ByIgnoring modified the HTTP Response -- received %v, expected %v", r2, r1) - } - return nil - }) - } - })(), - ByIgnoring(), - ByClosing()) -} - -func TestByCopying_Copies(t *testing.T) { - r := mocks.NewResponseWithContent(jsonT) - b := &bytes.Buffer{} - - err := Respond(r, - ByCopying(b), - ByUnmarshallingJSON(&mocks.T{}), - ByClosing()) - if err != nil { - t.Fatalf("autorest: ByCopying returned an unexpected error -- %v", err) - } - if b.String() != jsonT { - t.Fatalf("autorest: ByCopying failed to copy the bytes read") - } -} - -func TestByCopying_ReturnsNestedErrors(t *testing.T) { - r := mocks.NewResponseWithContent(jsonT) - - r.Body.Close() - err := Respond(r, - ByCopying(&bytes.Buffer{}), - ByUnmarshallingJSON(&mocks.T{}), - ByClosing()) - if err == nil { - t.Fatalf("autorest: ByCopying failed to return the expected error") - } -} - -func TestByCopying_AcceptsNilReponse(t *testing.T) { - r := mocks.NewResponse() - - Respond(r, - (func() RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - resp.Body.Close() - r.Respond(nil) - return nil - }) - } - })(), - ByCopying(&bytes.Buffer{})) -} - -func TestByCopying_AcceptsNilBody(t *testing.T) { - r := mocks.NewResponse() - - Respond(r, - (func() RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - resp.Body.Close() - resp.Body = nil - r.Respond(resp) - return nil - }) - } - })(), - ByCopying(&bytes.Buffer{})) -} - -func TestByClosing(t *testing.T) { - r := mocks.NewResponse() - err := Respond(r, ByClosing()) - if err != nil { - t.Fatalf("autorest: ByClosing failed (%v)", err) - } - if r.Body.(*mocks.Body).IsOpen() { - t.Fatalf("autorest: ByClosing did not close the response body") - } -} - -func TestByClosingAcceptsNilResponse(t *testing.T) { - r := mocks.NewResponse() - - Respond(r, - (func() RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - resp.Body.Close() - r.Respond(nil) - return nil - }) - } - })(), - ByClosing()) -} - -func TestByClosingAcceptsNilBody(t *testing.T) { - r := mocks.NewResponse() - - Respond(r, - (func() RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - resp.Body.Close() - resp.Body = nil - r.Respond(resp) - return nil - }) - } - })(), - ByClosing()) -} - -func TestByClosingClosesEvenAfterErrors(t *testing.T) { - var e error - - r := mocks.NewResponse() - Respond(r, - withErrorRespondDecorator(&e), - ByClosing()) - - if r.Body.(*mocks.Body).IsOpen() { - t.Fatalf("autorest: ByClosing did not close the response body after an error occurred") - } -} - -func TestByClosingClosesReturnsNestedErrors(t *testing.T) { - var e error - - r := mocks.NewResponse() - err := Respond(r, - withErrorRespondDecorator(&e), - ByClosing()) - - if err == nil || !reflect.DeepEqual(e, err) { - t.Fatalf("autorest: ByClosing failed to return a nested error") - } -} - -func TestByClosingIfErrorAcceptsNilResponse(t *testing.T) { - var e error - - r := mocks.NewResponse() - - Respond(r, - withErrorRespondDecorator(&e), - (func() RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - resp.Body.Close() - r.Respond(nil) - return nil - }) - } - })(), - ByClosingIfError()) -} - -func TestByClosingIfErrorAcceptsNilBody(t *testing.T) { - var e error - - r := mocks.NewResponse() - - Respond(r, - withErrorRespondDecorator(&e), - (func() RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - resp.Body.Close() - resp.Body = nil - r.Respond(resp) - return nil - }) - } - })(), - ByClosingIfError()) -} - -func TestByClosingIfErrorClosesIfAnErrorOccurs(t *testing.T) { - var e error - - r := mocks.NewResponse() - Respond(r, - withErrorRespondDecorator(&e), - ByClosingIfError()) - - if r.Body.(*mocks.Body).IsOpen() { - t.Fatalf("autorest: ByClosingIfError did not close the response body after an error occurred") - } -} - -func TestByClosingIfErrorDoesNotClosesIfNoErrorOccurs(t *testing.T) { - r := mocks.NewResponse() - Respond(r, - ByClosingIfError()) - - if !r.Body.(*mocks.Body).IsOpen() { - t.Fatalf("autorest: ByClosingIfError closed the response body even though no error occurred") - } -} - -func TestByDiscardingBody(t *testing.T) { - r := mocks.NewResponse() - err := Respond(r, - ByDiscardingBody()) - if err != nil { - t.Fatalf("autorest: ByDiscardingBody failed (%v)", err) - } - buf, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatalf("autorest: Reading result of ByDiscardingBody failed (%v)", err) - } - - if len(buf) != 0 { - t.Logf("autorest: Body was not empty after calling ByDiscardingBody.") - t.Fail() - } -} - -func TestByDiscardingBodyAcceptsNilResponse(t *testing.T) { - var e error - - r := mocks.NewResponse() - - Respond(r, - withErrorRespondDecorator(&e), - (func() RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - resp.Body.Close() - r.Respond(nil) - return nil - }) - } - })(), - ByDiscardingBody()) -} - -func TestByDiscardingBodyAcceptsNilBody(t *testing.T) { - var e error - - r := mocks.NewResponse() - - Respond(r, - withErrorRespondDecorator(&e), - (func() RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - resp.Body.Close() - resp.Body = nil - r.Respond(resp) - return nil - }) - } - })(), - ByDiscardingBody()) -} - -func TestByUnmarshallingJSON(t *testing.T) { - v := &mocks.T{} - r := mocks.NewResponseWithContent(jsonT) - err := Respond(r, - ByUnmarshallingJSON(v), - ByClosing()) - if err != nil { - t.Fatalf("autorest: ByUnmarshallingJSON failed (%v)", err) - } - if v.Name != "Rob Pike" || v.Age != 42 { - t.Fatalf("autorest: ByUnmarshallingJSON failed to properly unmarshal") - } -} - -func TestByUnmarshallingJSON_HandlesReadErrors(t *testing.T) { - v := &mocks.T{} - r := mocks.NewResponseWithContent(jsonT) - r.Body.(*mocks.Body).Close() - - err := Respond(r, - ByUnmarshallingJSON(v), - ByClosing()) - if err == nil { - t.Fatalf("autorest: ByUnmarshallingJSON failed to receive / respond to read error") - } -} - -func TestByUnmarshallingJSONIncludesJSONInErrors(t *testing.T) { - v := &mocks.T{} - j := jsonT[0 : len(jsonT)-2] - r := mocks.NewResponseWithContent(j) - err := Respond(r, - ByUnmarshallingJSON(v), - ByClosing()) - if err == nil || !strings.Contains(err.Error(), j) { - t.Fatalf("autorest: ByUnmarshallingJSON failed to return JSON in error (%v)", err) - } -} - -func TestByUnmarshallingJSONEmptyInput(t *testing.T) { - v := &mocks.T{} - r := mocks.NewResponseWithContent(``) - err := Respond(r, - ByUnmarshallingJSON(v), - ByClosing()) - if err != nil { - t.Fatalf("autorest: ByUnmarshallingJSON failed to return nil in case of empty JSON (%v)", err) - } -} - -func TestByUnmarshallingXML(t *testing.T) { - v := &mocks.T{} - r := mocks.NewResponseWithContent(xmlT) - err := Respond(r, - ByUnmarshallingXML(v), - ByClosing()) - if err != nil { - t.Fatalf("autorest: ByUnmarshallingXML failed (%v)", err) - } - if v.Name != "Rob Pike" || v.Age != 42 { - t.Fatalf("autorest: ByUnmarshallingXML failed to properly unmarshal") - } -} - -func TestByUnmarshallingXML_HandlesReadErrors(t *testing.T) { - v := &mocks.T{} - r := mocks.NewResponseWithContent(xmlT) - r.Body.(*mocks.Body).Close() - - err := Respond(r, - ByUnmarshallingXML(v), - ByClosing()) - if err == nil { - t.Fatalf("autorest: ByUnmarshallingXML failed to receive / respond to read error") - } -} - -func TestByUnmarshallingXMLIncludesXMLInErrors(t *testing.T) { - v := &mocks.T{} - x := xmlT[0 : len(xmlT)-2] - r := mocks.NewResponseWithContent(x) - err := Respond(r, - ByUnmarshallingXML(v), - ByClosing()) - if err == nil || !strings.Contains(err.Error(), x) { - t.Fatalf("autorest: ByUnmarshallingXML failed to return XML in error (%v)", err) - } -} - -func TestRespondAcceptsNullResponse(t *testing.T) { - err := Respond(nil) - if err != nil { - t.Fatalf("autorest: Respond returned an unexpected error when given a null Response (%v)", err) - } -} - -func TestWithErrorUnlessStatusCodeOKResponse(t *testing.T) { - v := &mocks.T{} - r := mocks.NewResponseWithContent(jsonT) - err := Respond(r, - WithErrorUnlessStatusCode(http.StatusOK), - ByUnmarshallingJSON(v), - ByClosing()) - - if err != nil { - t.Fatalf("autorest: WithErrorUnlessStatusCode(http.StatusOK) failed on okay response. (%v)", err) - } - - if v.Name != "Rob Pike" || v.Age != 42 { - t.Fatalf("autorest: WithErrorUnlessStatusCode(http.StatusOK) corrupted the response body of okay response.") - } -} - -func TesWithErrorUnlessStatusCodeErrorResponse(t *testing.T) { - v := &mocks.T{} - e := &mocks.T{} - r := mocks.NewResponseWithContent(jsonT) - r.Status = "400 BadRequest" - r.StatusCode = http.StatusBadRequest - - err := Respond(r, - WithErrorUnlessStatusCode(http.StatusOK), - ByUnmarshallingJSON(v), - ByClosing()) - - if err == nil { - t.Fatal("autorest: WithErrorUnlessStatusCode(http.StatusOK) did not return error, on a response to a bad request.") - } - - var errorRespBody []byte - if derr, ok := err.(DetailedError); !ok { - t.Fatalf("autorest: WithErrorUnlessStatusCode(http.StatusOK) got wrong error type : %T, expected: DetailedError, on a response to a bad request.", err) - } else { - errorRespBody = derr.ServiceError - } - - if errorRespBody == nil { - t.Fatalf("autorest: WithErrorUnlessStatusCode(http.StatusOK) ServiceError not returned in DetailedError on a response to a bad request.") - } - - err = json.Unmarshal(errorRespBody, e) - if err != nil { - t.Fatalf("autorest: WithErrorUnlessStatusCode(http.StatusOK) cannot parse error returned in ServiceError into json. %v", err) - } - - expected := &mocks.T{Name: "Rob Pike", Age: 42} - if e != expected { - t.Fatalf("autorest: WithErrorUnlessStatusCode(http.StatusOK wrong value from parsed ServiceError: got=%#v expected=%#v", e, expected) - } -} - -func TestWithErrorUnlessStatusCode(t *testing.T) { - r := mocks.NewResponse() - r.Request = mocks.NewRequest() - r.Status = "400 BadRequest" - r.StatusCode = http.StatusBadRequest - - err := Respond(r, - WithErrorUnlessStatusCode(http.StatusBadRequest, http.StatusUnauthorized, http.StatusInternalServerError), - ByClosingIfError()) - - if err != nil { - t.Fatalf("autorest: WithErrorUnlessStatusCode returned an error (%v) for an acceptable status code (%s)", err, r.Status) - } -} - -func TestWithErrorUnlessStatusCodeEmitsErrorForUnacceptableStatusCode(t *testing.T) { - r := mocks.NewResponse() - r.Request = mocks.NewRequest() - r.Status = "400 BadRequest" - r.StatusCode = http.StatusBadRequest - - err := Respond(r, - WithErrorUnlessStatusCode(http.StatusOK, http.StatusUnauthorized, http.StatusInternalServerError), - ByClosingIfError()) - - if err == nil { - t.Fatalf("autorest: WithErrorUnlessStatusCode failed to return an error for an unacceptable status code (%s)", r.Status) - } -} - -func TestWithErrorUnlessOK(t *testing.T) { - r := mocks.NewResponse() - r.Request = mocks.NewRequest() - - err := Respond(r, - WithErrorUnlessOK(), - ByClosingIfError()) - - if err != nil { - t.Fatalf("autorest: WithErrorUnlessOK returned an error for OK status code (%v)", err) - } -} - -func TestWithErrorUnlessOKEmitsErrorIfNotOK(t *testing.T) { - r := mocks.NewResponse() - r.Request = mocks.NewRequest() - r.Status = "400 BadRequest" - r.StatusCode = http.StatusBadRequest - - err := Respond(r, - WithErrorUnlessOK(), - ByClosingIfError()) - - if err == nil { - t.Fatalf("autorest: WithErrorUnlessOK failed to return an error for a non-OK status code (%v)", err) - } -} - -func TestExtractHeader(t *testing.T) { - r := mocks.NewResponse() - v := []string{"v1", "v2", "v3"} - mocks.SetResponseHeaderValues(r, mocks.TestHeader, v) - - if !reflect.DeepEqual(ExtractHeader(mocks.TestHeader, r), v) { - t.Fatalf("autorest: ExtractHeader failed to retrieve the expected header -- expected [%s]%v, received [%s]%v", - mocks.TestHeader, v, mocks.TestHeader, ExtractHeader(mocks.TestHeader, r)) - } -} - -func TestExtractHeaderHandlesMissingHeader(t *testing.T) { - var v []string - r := mocks.NewResponse() - - if !reflect.DeepEqual(ExtractHeader(mocks.TestHeader, r), v) { - t.Fatalf("autorest: ExtractHeader failed to handle a missing header -- expected %v, received %v", - v, ExtractHeader(mocks.TestHeader, r)) - } -} - -func TestExtractHeaderValue(t *testing.T) { - r := mocks.NewResponse() - v := "v1" - mocks.SetResponseHeader(r, mocks.TestHeader, v) - - if ExtractHeaderValue(mocks.TestHeader, r) != v { - t.Fatalf("autorest: ExtractHeader failed to retrieve the expected header -- expected [%s]%v, received [%s]%v", - mocks.TestHeader, v, mocks.TestHeader, ExtractHeaderValue(mocks.TestHeader, r)) - } -} - -func TestExtractHeaderValueHandlesMissingHeader(t *testing.T) { - r := mocks.NewResponse() - v := "" - - if ExtractHeaderValue(mocks.TestHeader, r) != v { - t.Fatalf("autorest: ExtractHeader failed to retrieve the expected header -- expected [%s]%v, received [%s]%v", - mocks.TestHeader, v, mocks.TestHeader, ExtractHeaderValue(mocks.TestHeader, r)) - } -} - -func TestExtractHeaderValueRetrievesFirstValue(t *testing.T) { - r := mocks.NewResponse() - v := []string{"v1", "v2", "v3"} - mocks.SetResponseHeaderValues(r, mocks.TestHeader, v) - - if ExtractHeaderValue(mocks.TestHeader, r) != v[0] { - t.Fatalf("autorest: ExtractHeader failed to retrieve the expected header -- expected [%s]%v, received [%s]%v", - mocks.TestHeader, v[0], mocks.TestHeader, ExtractHeaderValue(mocks.TestHeader, r)) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/sender_test.go b/vendor/github.com/Azure/go-autorest/autorest/sender_test.go deleted file mode 100644 index 21863739..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/sender_test.go +++ /dev/null @@ -1,954 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "bytes" - "context" - "fmt" - "log" - "net/http" - "net/http/httptest" - "os" - "reflect" - "sync" - "testing" - "time" - - "github.com/Azure/go-autorest/autorest/mocks" -) - -func ExampleSendWithSender() { - r := mocks.NewResponseWithStatus("202 Accepted", http.StatusAccepted) - mocks.SetAcceptedHeaders(r) - - client := mocks.NewSender() - client.AppendAndRepeatResponse(r, 10) - - logger := log.New(os.Stdout, "autorest: ", 0) - na := NullAuthorizer{} - - req, _ := Prepare(&http.Request{}, - AsGet(), - WithBaseURL("https://microsoft.com/a/b/c/"), - na.WithAuthorization()) - - r, _ = SendWithSender(client, req, - WithLogging(logger), - DoErrorIfStatusCode(http.StatusAccepted), - DoCloseIfError(), - DoRetryForAttempts(5, time.Duration(0))) - - Respond(r, - ByDiscardingBody(), - ByClosing()) - - // Output: - // autorest: Sending GET https://microsoft.com/a/b/c/ - // autorest: GET https://microsoft.com/a/b/c/ received 202 Accepted - // autorest: Sending GET https://microsoft.com/a/b/c/ - // autorest: GET https://microsoft.com/a/b/c/ received 202 Accepted - // autorest: Sending GET https://microsoft.com/a/b/c/ - // autorest: GET https://microsoft.com/a/b/c/ received 202 Accepted - // autorest: Sending GET https://microsoft.com/a/b/c/ - // autorest: GET https://microsoft.com/a/b/c/ received 202 Accepted - // autorest: Sending GET https://microsoft.com/a/b/c/ - // autorest: GET https://microsoft.com/a/b/c/ received 202 Accepted -} - -func ExampleDoRetryForAttempts() { - client := mocks.NewSender() - client.SetAndRepeatError(fmt.Errorf("Faux Error"), 10) - - // Retry with backoff -- ensure returned Bodies are closed - r, _ := SendWithSender(client, mocks.NewRequest(), - DoCloseIfError(), - DoRetryForAttempts(5, time.Duration(0))) - - Respond(r, - ByDiscardingBody(), - ByClosing()) - - fmt.Printf("Retry stopped after %d attempts", client.Attempts()) - // Output: Retry stopped after 5 attempts -} - -func ExampleDoErrorIfStatusCode() { - client := mocks.NewSender() - client.AppendAndRepeatResponse(mocks.NewResponseWithStatus("204 NoContent", http.StatusNoContent), 10) - - // Chain decorators to retry the request, up to five times, if the status code is 204 - r, _ := SendWithSender(client, mocks.NewRequest(), - DoErrorIfStatusCode(http.StatusNoContent), - DoCloseIfError(), - DoRetryForAttempts(5, time.Duration(0))) - - Respond(r, - ByDiscardingBody(), - ByClosing()) - - fmt.Printf("Retry stopped after %d attempts with code %s", client.Attempts(), r.Status) - // Output: Retry stopped after 5 attempts with code 204 NoContent -} - -func TestSendWithSenderRunsDecoratorsInOrder(t *testing.T) { - client := mocks.NewSender() - s := "" - - r, err := SendWithSender(client, mocks.NewRequest(), - withMessage(&s, "a"), - withMessage(&s, "b"), - withMessage(&s, "c")) - if err != nil { - t.Fatalf("autorest: SendWithSender returned an error (%v)", err) - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) - - if s != "abc" { - t.Fatalf("autorest: SendWithSender invoke decorators out of order; expected 'abc', received '%s'", s) - } -} - -func TestCreateSender(t *testing.T) { - f := false - - s := CreateSender( - (func() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - f = true - return nil, nil - }) - } - })()) - s.Do(&http.Request{}) - - if !f { - t.Fatal("autorest: CreateSender failed to apply supplied decorator") - } -} - -func TestSend(t *testing.T) { - f := false - - Send(&http.Request{}, - (func() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - f = true - return nil, nil - }) - } - })()) - - if !f { - t.Fatal("autorest: Send failed to apply supplied decorator") - } -} - -func TestAfterDelayWaits(t *testing.T) { - client := mocks.NewSender() - - d := 2 * time.Second - - tt := time.Now() - r, _ := SendWithSender(client, mocks.NewRequest(), - AfterDelay(d)) - s := time.Since(tt) - if s < d { - t.Fatal("autorest: AfterDelay failed to wait for at least the specified duration") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestAfterDelay_Cancels(t *testing.T) { - client := mocks.NewSender() - ctx, cancel := context.WithCancel(context.Background()) - delay := 5 * time.Second - - var wg sync.WaitGroup - wg.Add(1) - start := time.Now() - end := time.Now() - var err error - go func() { - req := mocks.NewRequest() - req = req.WithContext(ctx) - _, err = SendWithSender(client, req, - AfterDelay(delay)) - end = time.Now() - wg.Done() - }() - cancel() - wg.Wait() - time.Sleep(5 * time.Millisecond) - if end.Sub(start) >= delay { - t.Fatal("autorest: AfterDelay elapsed") - } - if err == nil { - t.Fatal("autorest: AfterDelay didn't cancel") - } -} - -func TestAfterDelayDoesNotWaitTooLong(t *testing.T) { - client := mocks.NewSender() - - d := 5 * time.Millisecond - start := time.Now() - r, _ := SendWithSender(client, mocks.NewRequest(), - AfterDelay(d)) - - if time.Since(start) > (5 * d) { - t.Fatal("autorest: AfterDelay waited too long (exceeded 5 times specified duration)") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestAsIs(t *testing.T) { - client := mocks.NewSender() - - r1 := mocks.NewResponse() - client.AppendResponse(r1) - - r2, err := SendWithSender(client, mocks.NewRequest(), - AsIs()) - if err != nil { - t.Fatalf("autorest: AsIs returned an unexpected error (%v)", err) - } else if !reflect.DeepEqual(r1, r2) { - t.Fatalf("autorest: AsIs modified the response -- received %v, expected %v", r2, r1) - } - - Respond(r1, - ByDiscardingBody(), - ByClosing()) - Respond(r2, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoCloseIfError(t *testing.T) { - client := mocks.NewSender() - client.AppendResponse(mocks.NewResponseWithStatus("400 BadRequest", http.StatusBadRequest)) - - r, _ := SendWithSender(client, mocks.NewRequest(), - DoErrorIfStatusCode(http.StatusBadRequest), - DoCloseIfError()) - - if r.Body.(*mocks.Body).IsOpen() { - t.Fatal("autorest: Expected DoCloseIfError to close response body -- it was left open") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoCloseIfErrorAcceptsNilResponse(t *testing.T) { - client := mocks.NewSender() - - SendWithSender(client, mocks.NewRequest(), - (func() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - resp, err := s.Do(r) - if err != nil { - resp.Body.Close() - } - return nil, fmt.Errorf("Faux Error") - }) - } - })(), - DoCloseIfError()) -} - -func TestDoCloseIfErrorAcceptsNilBody(t *testing.T) { - client := mocks.NewSender() - - SendWithSender(client, mocks.NewRequest(), - (func() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - resp, err := s.Do(r) - if err != nil { - resp.Body.Close() - } - resp.Body = nil - return resp, fmt.Errorf("Faux Error") - }) - } - })(), - DoCloseIfError()) -} - -func TestDoErrorIfStatusCode(t *testing.T) { - client := mocks.NewSender() - client.AppendResponse(mocks.NewResponseWithStatus("400 BadRequest", http.StatusBadRequest)) - - r, err := SendWithSender(client, mocks.NewRequest(), - DoErrorIfStatusCode(http.StatusBadRequest), - DoCloseIfError()) - if err == nil { - t.Fatal("autorest: DoErrorIfStatusCode failed to emit an error for passed code") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoErrorIfStatusCodeIgnoresStatusCodes(t *testing.T) { - client := mocks.NewSender() - client.AppendResponse(newAcceptedResponse()) - - r, err := SendWithSender(client, mocks.NewRequest(), - DoErrorIfStatusCode(http.StatusBadRequest), - DoCloseIfError()) - if err != nil { - t.Fatal("autorest: DoErrorIfStatusCode failed to ignore a status code") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoErrorUnlessStatusCode(t *testing.T) { - client := mocks.NewSender() - client.AppendResponse(mocks.NewResponseWithStatus("400 BadRequest", http.StatusBadRequest)) - - r, err := SendWithSender(client, mocks.NewRequest(), - DoErrorUnlessStatusCode(http.StatusAccepted), - DoCloseIfError()) - if err == nil { - t.Fatal("autorest: DoErrorUnlessStatusCode failed to emit an error for an unknown status code") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoErrorUnlessStatusCodeIgnoresStatusCodes(t *testing.T) { - client := mocks.NewSender() - client.AppendResponse(newAcceptedResponse()) - - r, err := SendWithSender(client, mocks.NewRequest(), - DoErrorUnlessStatusCode(http.StatusAccepted), - DoCloseIfError()) - if err != nil { - t.Fatal("autorest: DoErrorUnlessStatusCode emitted an error for a knonwn status code") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoRetryForAttemptsStopsAfterSuccess(t *testing.T) { - client := mocks.NewSender() - - r, err := SendWithSender(client, mocks.NewRequest(), - DoRetryForAttempts(5, time.Duration(0))) - if client.Attempts() != 1 { - t.Fatalf("autorest: DoRetryForAttempts failed to stop after success -- expected attempts %v, actual %v", - 1, client.Attempts()) - } - if err != nil { - t.Fatalf("autorest: DoRetryForAttempts returned an unexpected error (%v)", err) - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoRetryForAttemptsStopsAfterAttempts(t *testing.T) { - client := mocks.NewSender() - client.SetAndRepeatError(fmt.Errorf("Faux Error"), 10) - - r, err := SendWithSender(client, mocks.NewRequest(), - DoRetryForAttempts(5, time.Duration(0)), - DoCloseIfError()) - if err == nil { - t.Fatal("autorest: Mock client failed to emit errors") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) - - if client.Attempts() != 5 { - t.Fatal("autorest: DoRetryForAttempts failed to stop after specified number of attempts") - } -} - -func TestDoRetryForAttemptsReturnsResponse(t *testing.T) { - client := mocks.NewSender() - client.SetError(fmt.Errorf("Faux Error")) - - r, err := SendWithSender(client, mocks.NewRequest(), - DoRetryForAttempts(1, time.Duration(0))) - if err == nil { - t.Fatal("autorest: Mock client failed to emit errors") - } - - if r == nil { - t.Fatal("autorest: DoRetryForAttempts failed to return the underlying response") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoRetryForDurationStopsAfterSuccess(t *testing.T) { - client := mocks.NewSender() - - r, err := SendWithSender(client, mocks.NewRequest(), - DoRetryForDuration(10*time.Millisecond, time.Duration(0))) - if client.Attempts() != 1 { - t.Fatalf("autorest: DoRetryForDuration failed to stop after success -- expected attempts %v, actual %v", - 1, client.Attempts()) - } - if err != nil { - t.Fatalf("autorest: DoRetryForDuration returned an unexpected error (%v)", err) - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoRetryForDurationStopsAfterDuration(t *testing.T) { - client := mocks.NewSender() - client.SetAndRepeatError(fmt.Errorf("Faux Error"), -1) - - d := 5 * time.Millisecond - start := time.Now() - r, err := SendWithSender(client, mocks.NewRequest(), - DoRetryForDuration(d, time.Duration(0)), - DoCloseIfError()) - if err == nil { - t.Fatal("autorest: Mock client failed to emit errors") - } - - if time.Since(start) < d { - t.Fatal("autorest: DoRetryForDuration failed stopped too soon") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoRetryForDurationStopsWithinReason(t *testing.T) { - client := mocks.NewSender() - client.SetAndRepeatError(fmt.Errorf("Faux Error"), -1) - - d := 5 * time.Second - start := time.Now() - r, err := SendWithSender(client, mocks.NewRequest(), - DoRetryForDuration(d, time.Duration(0)), - DoCloseIfError()) - if err == nil { - t.Fatal("autorest: Mock client failed to emit errors") - } - - if time.Since(start) > (5 * d) { - t.Fatal("autorest: DoRetryForDuration failed stopped soon enough (exceeded 5 times specified duration)") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoRetryForDurationReturnsResponse(t *testing.T) { - client := mocks.NewSender() - client.SetAndRepeatError(fmt.Errorf("Faux Error"), -1) - - r, err := SendWithSender(client, mocks.NewRequest(), - DoRetryForDuration(10*time.Millisecond, time.Duration(0)), - DoCloseIfError()) - if err == nil { - t.Fatal("autorest: Mock client failed to emit errors") - } - - if r == nil { - t.Fatal("autorest: DoRetryForDuration failed to return the underlying response") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDelayForBackoff(t *testing.T) { - d := 2 * time.Second - start := time.Now() - DelayForBackoff(d, 0, nil) - if time.Since(start) < d { - t.Fatal("autorest: DelayForBackoff did not delay as long as expected") - } -} - -func TestDelayForBackoff_Cancels(t *testing.T) { - cancel := make(chan struct{}) - delay := 5 * time.Second - - var wg sync.WaitGroup - wg.Add(1) - start := time.Now() - go func() { - wg.Done() - DelayForBackoff(delay, 0, cancel) - }() - wg.Wait() - close(cancel) - time.Sleep(5 * time.Millisecond) - if time.Since(start) >= delay { - t.Fatal("autorest: DelayForBackoff failed to cancel") - } -} - -func TestDelayForBackoffWithinReason(t *testing.T) { - d := 5 * time.Second - maxCoefficient := 2 - start := time.Now() - DelayForBackoff(d, 0, nil) - if time.Since(start) > (time.Duration(maxCoefficient) * d) { - - t.Fatalf("autorest: DelayForBackoff delayed too long (exceeded %d times the specified duration)", maxCoefficient) - } -} - -func TestDoPollForStatusCodes_IgnoresUnspecifiedStatusCodes(t *testing.T) { - client := mocks.NewSender() - - r, _ := SendWithSender(client, mocks.NewRequest(), - DoPollForStatusCodes(time.Duration(0), time.Duration(0))) - - if client.Attempts() != 1 { - t.Fatalf("autorest: Sender#DoPollForStatusCodes polled for unspecified status code") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoPollForStatusCodes_PollsForSpecifiedStatusCodes(t *testing.T) { - client := mocks.NewSender() - client.AppendResponse(newAcceptedResponse()) - - r, _ := SendWithSender(client, mocks.NewRequest(), - DoPollForStatusCodes(time.Millisecond, time.Millisecond, http.StatusAccepted)) - - if client.Attempts() != 2 { - t.Fatalf("autorest: Sender#DoPollForStatusCodes failed to poll for specified status code") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoPollForStatusCodes_CanBeCanceled(t *testing.T) { - cancel := make(chan struct{}) - delay := 5 * time.Second - - r := mocks.NewResponse() - mocks.SetAcceptedHeaders(r) - client := mocks.NewSender() - client.AppendAndRepeatResponse(r, 100) - - var wg sync.WaitGroup - wg.Add(1) - start := time.Now() - go func() { - wg.Done() - r, _ := SendWithSender(client, mocks.NewRequest(), - DoPollForStatusCodes(time.Millisecond, time.Millisecond, http.StatusAccepted)) - Respond(r, - ByDiscardingBody(), - ByClosing()) - }() - wg.Wait() - close(cancel) - time.Sleep(5 * time.Millisecond) - if time.Since(start) >= delay { - t.Fatalf("autorest: Sender#DoPollForStatusCodes failed to cancel") - } -} - -func TestDoPollForStatusCodes_ClosesAllNonreturnedResponseBodiesWhenPolling(t *testing.T) { - resp := newAcceptedResponse() - - client := mocks.NewSender() - client.AppendAndRepeatResponse(resp, 2) - - r, _ := SendWithSender(client, mocks.NewRequest(), - DoPollForStatusCodes(time.Millisecond, time.Millisecond, http.StatusAccepted)) - - if resp.Body.(*mocks.Body).IsOpen() || resp.Body.(*mocks.Body).CloseAttempts() < 2 { - t.Fatalf("autorest: Sender#DoPollForStatusCodes did not close unreturned response bodies") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoPollForStatusCodes_LeavesLastResponseBodyOpen(t *testing.T) { - client := mocks.NewSender() - client.AppendResponse(newAcceptedResponse()) - - r, _ := SendWithSender(client, mocks.NewRequest(), - DoPollForStatusCodes(time.Millisecond, time.Millisecond, http.StatusAccepted)) - - if !r.Body.(*mocks.Body).IsOpen() { - t.Fatalf("autorest: Sender#DoPollForStatusCodes did not leave open the body of the last response") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoPollForStatusCodes_StopsPollingAfterAnError(t *testing.T) { - client := mocks.NewSender() - client.AppendAndRepeatResponse(newAcceptedResponse(), 5) - client.SetError(fmt.Errorf("Faux Error")) - client.SetEmitErrorAfter(1) - - r, _ := SendWithSender(client, mocks.NewRequest(), - DoPollForStatusCodes(time.Millisecond, time.Millisecond, http.StatusAccepted)) - - if client.Attempts() > 2 { - t.Fatalf("autorest: Sender#DoPollForStatusCodes failed to stop polling after receiving an error") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoPollForStatusCodes_ReturnsPollingError(t *testing.T) { - client := mocks.NewSender() - client.AppendAndRepeatResponse(newAcceptedResponse(), 5) - client.SetError(fmt.Errorf("Faux Error")) - client.SetEmitErrorAfter(1) - - r, err := SendWithSender(client, mocks.NewRequest(), - DoPollForStatusCodes(time.Millisecond, time.Millisecond, http.StatusAccepted)) - - if err == nil { - t.Fatalf("autorest: Sender#DoPollForStatusCodes failed to return error from polling") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestWithLogging_Logs(t *testing.T) { - buf := &bytes.Buffer{} - logger := log.New(buf, "autorest: ", 0) - client := mocks.NewSender() - - r, _ := SendWithSender(client, &http.Request{}, - WithLogging(logger)) - - if buf.String() == "" { - t.Fatal("autorest: Sender#WithLogging failed to log the request") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestWithLogging_HandlesMissingResponse(t *testing.T) { - buf := &bytes.Buffer{} - logger := log.New(buf, "autorest: ", 0) - client := mocks.NewSender() - client.AppendResponse(nil) - client.SetError(fmt.Errorf("Faux Error")) - - r, err := SendWithSender(client, &http.Request{}, - WithLogging(logger)) - - if r != nil || err == nil { - t.Fatal("autorest: Sender#WithLogging returned a valid response -- expecting nil") - } - if buf.String() == "" { - t.Fatal("autorest: Sender#WithLogging failed to log the request for a nil response") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoRetryForStatusCodesWithSuccess(t *testing.T) { - client := mocks.NewSender() - client.AppendAndRepeatResponse(mocks.NewResponseWithStatus("408 Request Timeout", http.StatusRequestTimeout), 2) - client.AppendResponse(mocks.NewResponseWithStatus("200 OK", http.StatusOK)) - - r, _ := SendWithSender(client, mocks.NewRequest(), - DoRetryForStatusCodes(5, time.Duration(2*time.Second), http.StatusRequestTimeout), - ) - - Respond(r, - ByDiscardingBody(), - ByClosing()) - - if client.Attempts() != 3 { - t.Fatalf("autorest: Sender#DoRetryForStatusCodes -- Got: StatusCode %v in %v attempts; Want: StatusCode 200 OK in 2 attempts -- ", - r.Status, client.Attempts()-1) - } -} - -func TestDoRetryForStatusCodesWithNoSuccess(t *testing.T) { - client := mocks.NewSender() - client.AppendAndRepeatResponse(mocks.NewResponseWithStatus("504 Gateway Timeout", http.StatusGatewayTimeout), 5) - - r, _ := SendWithSender(client, mocks.NewRequest(), - DoRetryForStatusCodes(2, time.Duration(2*time.Second), http.StatusGatewayTimeout), - ) - Respond(r, - ByDiscardingBody(), - ByClosing()) - - if client.Attempts() != 3 { - t.Fatalf("autorest: Sender#DoRetryForStatusCodes -- Got: failed stop after %v retry attempts; Want: Stop after 2 retry attempts", - client.Attempts()-1) - } -} - -func TestDoRetryForStatusCodes_CodeNotInRetryList(t *testing.T) { - client := mocks.NewSender() - client.AppendAndRepeatResponse(mocks.NewResponseWithStatus("204 No Content", http.StatusNoContent), 1) - - r, _ := SendWithSender(client, mocks.NewRequest(), - DoRetryForStatusCodes(6, time.Duration(2*time.Second), http.StatusGatewayTimeout), - ) - - Respond(r, - ByDiscardingBody(), - ByClosing()) - - if client.Attempts() != 1 || r.Status != "204 No Content" { - t.Fatalf("autorest: Sender#DoRetryForStatusCodes -- Got: Retry attempts %v for StatusCode %v; Want: 0 attempts for StatusCode 204", - client.Attempts(), r.Status) - } -} - -func TestDoRetryForStatusCodes_RequestBodyReadError(t *testing.T) { - client := mocks.NewSender() - client.AppendAndRepeatResponse(mocks.NewResponseWithStatus("204 No Content", http.StatusNoContent), 2) - - r, err := SendWithSender(client, mocks.NewRequestWithCloseBody(), - DoRetryForStatusCodes(6, time.Duration(2*time.Second), http.StatusGatewayTimeout), - ) - - Respond(r, - ByDiscardingBody(), - ByClosing()) - - if err == nil || client.Attempts() != 0 { - t.Fatalf("autorest: Sender#DoRetryForStatusCodes -- Got: Not failed for request body read error; Want: Failed for body read error - %v", err) - } -} - -func newAcceptedResponse() *http.Response { - resp := mocks.NewResponseWithStatus("202 Accepted", http.StatusAccepted) - mocks.SetAcceptedHeaders(resp) - return resp -} - -func TestDelayWithRetryAfterWithSuccess(t *testing.T) { - after, retries := 2, 2 - totalSecs := after * retries - - client := mocks.NewSender() - resp := mocks.NewResponseWithStatus("429 Too many requests", http.StatusTooManyRequests) - mocks.SetResponseHeader(resp, "Retry-After", fmt.Sprintf("%v", after)) - client.AppendAndRepeatResponse(resp, retries) - client.AppendResponse(mocks.NewResponseWithStatus("200 OK", http.StatusOK)) - - d := time.Second * time.Duration(totalSecs) - start := time.Now() - r, _ := SendWithSender(client, mocks.NewRequest(), - DoRetryForStatusCodes(1, time.Duration(time.Second), http.StatusTooManyRequests), - ) - - if time.Since(start) < d { - t.Fatal("autorest: DelayWithRetryAfter failed stopped too soon") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) - - if client.Attempts() != 3 { - t.Fatalf("autorest: Sender#DelayWithRetryAfter -- Got: StatusCode %v in %v attempts; Want: StatusCode 200 OK in 2 attempts -- ", - r.Status, client.Attempts()-1) - } -} - -type temporaryError struct { - message string -} - -func (te temporaryError) Error() string { - return te.message -} - -func (te temporaryError) Timeout() bool { - return true -} - -func (te temporaryError) Temporary() bool { - return true -} - -func TestDoRetryForStatusCodes_NilResponseTemporaryError(t *testing.T) { - client := mocks.NewSender() - client.AppendResponse(nil) - client.SetError(temporaryError{message: "faux error"}) - - r, err := SendWithSender(client, mocks.NewRequest(), - DoRetryForStatusCodes(3, time.Duration(1*time.Second), StatusCodesForRetry...), - ) - - Respond(r, - ByDiscardingBody(), - ByClosing()) - - if err != nil || client.Attempts() != 2 { - t.Fatalf("autorest: Sender#TestDoRetryForStatusCodes_NilResponseTemporaryError -- Got: non-nil error or wrong number of attempts - %v", err) - } -} - -func TestDoRetryForStatusCodes_NilResponseTemporaryError2(t *testing.T) { - client := mocks.NewSender() - client.AppendResponse(nil) - client.SetError(fmt.Errorf("faux error")) - - r, err := SendWithSender(client, mocks.NewRequest(), - DoRetryForStatusCodes(3, time.Duration(1*time.Second), StatusCodesForRetry...), - ) - - Respond(r, - ByDiscardingBody(), - ByClosing()) - - if err != nil || client.Attempts() != 2 { - t.Fatalf("autorest: Sender#TestDoRetryForStatusCodes_NilResponseTemporaryError2 -- Got: nil error or wrong number of attempts - %v", err) - } -} - -type fatalError struct { - message string -} - -func (fe fatalError) Error() string { - return fe.message -} - -func (fe fatalError) Timeout() bool { - return false -} - -func (fe fatalError) Temporary() bool { - return false -} - -func TestDoRetryForStatusCodes_NilResponseFatalError(t *testing.T) { - client := mocks.NewSender() - client.AppendResponse(nil) - client.SetError(fatalError{"fatal error"}) - - r, err := SendWithSender(client, mocks.NewRequest(), - DoRetryForStatusCodes(3, time.Duration(1*time.Second), StatusCodesForRetry...), - ) - - Respond(r, - ByDiscardingBody(), - ByClosing()) - - if err == nil || client.Attempts() > 1 { - t.Fatalf("autorest: Sender#TestDoRetryForStatusCodes_NilResponseFatalError -- Got: nil error or wrong number of attempts - %v", err) - } -} - -func TestDoRetryForStatusCodes_Cancel429(t *testing.T) { - retries := 6 - client := mocks.NewSender() - resp := mocks.NewResponseWithStatus("429 Too many requests", http.StatusTooManyRequests) - client.AppendAndRepeatResponse(resp, retries) - - ctx, cancel := context.WithTimeout(context.Background(), time.Duration(retries/2)*time.Second) - defer cancel() - req := mocks.NewRequest().WithContext(ctx) - r, err := SendWithSender(client, req, - DoRetryForStatusCodes(1, time.Duration(time.Second), http.StatusTooManyRequests), - ) - - if err == nil { - t.Fatal("unexpected nil-error") - } - if r == nil { - t.Fatal("unexpected nil response") - } - if r.StatusCode != http.StatusTooManyRequests { - t.Fatalf("expected status code 429, got: %d", r.StatusCode) - } - if client.Attempts() >= retries { - t.Fatalf("too many attempts: %d", client.Attempts()) - } -} - -func TestDoRetryForStatusCodes_Race(t *testing.T) { - // cannot use the mock sender as it's not safe for concurrent use - s := httptest.NewServer(http.HandlerFunc(func(http.ResponseWriter, *http.Request) {})) - defer s.Close() - - sender := DecorateSender(s.Client(), - DoRetryForStatusCodes(0, 0, http.StatusRequestTimeout)) - - var wg sync.WaitGroup - for i := 0; i < 2; i++ { - wg.Add(1) - go func() { - defer wg.Done() - req, _ := http.NewRequest(http.MethodGet, s.URL, nil) - if _, err := sender.Do(req); err != nil { - t.Fatal(err) - } - }() - } - wg.Wait() -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/to/convert_test.go b/vendor/github.com/Azure/go-autorest/autorest/to/convert_test.go deleted file mode 100644 index f8177a16..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/to/convert_test.go +++ /dev/null @@ -1,234 +0,0 @@ -package to - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "reflect" - "testing" -) - -func TestString(t *testing.T) { - v := "" - if String(&v) != v { - t.Fatalf("to: String failed to return the correct string -- expected %v, received %v", - v, String(&v)) - } -} - -func TestStringHandlesNil(t *testing.T) { - if String(nil) != "" { - t.Fatalf("to: String failed to correctly convert nil -- expected %v, received %v", - "", String(nil)) - } -} - -func TestStringPtr(t *testing.T) { - v := "" - if *StringPtr(v) != v { - t.Fatalf("to: StringPtr failed to return the correct string -- expected %v, received %v", - v, *StringPtr(v)) - } -} - -func TestStringSlice(t *testing.T) { - v := []string{} - if out := StringSlice(&v); !reflect.DeepEqual(out, v) { - t.Fatalf("to: StringSlice failed to return the correct slice -- expected %v, received %v", - v, out) - } -} - -func TestStringSliceHandlesNil(t *testing.T) { - if out := StringSlice(nil); out != nil { - t.Fatalf("to: StringSlice failed to correctly convert nil -- expected %v, received %v", - nil, out) - } -} - -func TestStringSlicePtr(t *testing.T) { - v := []string{"a", "b"} - if out := StringSlicePtr(v); !reflect.DeepEqual(*out, v) { - t.Fatalf("to: StringSlicePtr failed to return the correct slice -- expected %v, received %v", - v, *out) - } -} - -func TestStringMap(t *testing.T) { - msp := map[string]*string{"foo": StringPtr("foo"), "bar": StringPtr("bar"), "baz": StringPtr("baz")} - for k, v := range StringMap(msp) { - if *msp[k] != v { - t.Fatalf("to: StringMap incorrectly converted an entry -- expected [%s]%v, received[%s]%v", - k, v, k, *msp[k]) - } - } -} - -func TestStringMapHandlesNil(t *testing.T) { - msp := map[string]*string{"foo": StringPtr("foo"), "bar": nil, "baz": StringPtr("baz")} - for k, v := range StringMap(msp) { - if msp[k] == nil && v != "" { - t.Fatalf("to: StringMap incorrectly converted a nil entry -- expected [%s]%v, received[%s]%v", - k, v, k, *msp[k]) - } - } -} - -func TestStringMapPtr(t *testing.T) { - ms := map[string]string{"foo": "foo", "bar": "bar", "baz": "baz"} - for k, msp := range *StringMapPtr(ms) { - if ms[k] != *msp { - t.Fatalf("to: StringMapPtr incorrectly converted an entry -- expected [%s]%v, received[%s]%v", - k, ms[k], k, *msp) - } - } -} - -func TestBool(t *testing.T) { - v := false - if Bool(&v) != v { - t.Fatalf("to: Bool failed to return the correct string -- expected %v, received %v", - v, Bool(&v)) - } -} - -func TestBoolHandlesNil(t *testing.T) { - if Bool(nil) != false { - t.Fatalf("to: Bool failed to correctly convert nil -- expected %v, received %v", - false, Bool(nil)) - } -} - -func TestBoolPtr(t *testing.T) { - v := false - if *BoolPtr(v) != v { - t.Fatalf("to: BoolPtr failed to return the correct string -- expected %v, received %v", - v, *BoolPtr(v)) - } -} - -func TestInt(t *testing.T) { - v := 0 - if Int(&v) != v { - t.Fatalf("to: Int failed to return the correct string -- expected %v, received %v", - v, Int(&v)) - } -} - -func TestIntHandlesNil(t *testing.T) { - if Int(nil) != 0 { - t.Fatalf("to: Int failed to correctly convert nil -- expected %v, received %v", - 0, Int(nil)) - } -} - -func TestIntPtr(t *testing.T) { - v := 0 - if *IntPtr(v) != v { - t.Fatalf("to: IntPtr failed to return the correct string -- expected %v, received %v", - v, *IntPtr(v)) - } -} - -func TestInt32(t *testing.T) { - v := int32(0) - if Int32(&v) != v { - t.Fatalf("to: Int32 failed to return the correct string -- expected %v, received %v", - v, Int32(&v)) - } -} - -func TestInt32HandlesNil(t *testing.T) { - if Int32(nil) != int32(0) { - t.Fatalf("to: Int32 failed to correctly convert nil -- expected %v, received %v", - 0, Int32(nil)) - } -} - -func TestInt32Ptr(t *testing.T) { - v := int32(0) - if *Int32Ptr(v) != v { - t.Fatalf("to: Int32Ptr failed to return the correct string -- expected %v, received %v", - v, *Int32Ptr(v)) - } -} - -func TestInt64(t *testing.T) { - v := int64(0) - if Int64(&v) != v { - t.Fatalf("to: Int64 failed to return the correct string -- expected %v, received %v", - v, Int64(&v)) - } -} - -func TestInt64HandlesNil(t *testing.T) { - if Int64(nil) != int64(0) { - t.Fatalf("to: Int64 failed to correctly convert nil -- expected %v, received %v", - 0, Int64(nil)) - } -} - -func TestInt64Ptr(t *testing.T) { - v := int64(0) - if *Int64Ptr(v) != v { - t.Fatalf("to: Int64Ptr failed to return the correct string -- expected %v, received %v", - v, *Int64Ptr(v)) - } -} - -func TestFloat32(t *testing.T) { - v := float32(0) - if Float32(&v) != v { - t.Fatalf("to: Float32 failed to return the correct string -- expected %v, received %v", - v, Float32(&v)) - } -} - -func TestFloat32HandlesNil(t *testing.T) { - if Float32(nil) != float32(0) { - t.Fatalf("to: Float32 failed to correctly convert nil -- expected %v, received %v", - 0, Float32(nil)) - } -} - -func TestFloat32Ptr(t *testing.T) { - v := float32(0) - if *Float32Ptr(v) != v { - t.Fatalf("to: Float32Ptr failed to return the correct string -- expected %v, received %v", - v, *Float32Ptr(v)) - } -} - -func TestFloat64(t *testing.T) { - v := float64(0) - if Float64(&v) != v { - t.Fatalf("to: Float64 failed to return the correct string -- expected %v, received %v", - v, Float64(&v)) - } -} - -func TestFloat64HandlesNil(t *testing.T) { - if Float64(nil) != float64(0) { - t.Fatalf("to: Float64 failed to correctly convert nil -- expected %v, received %v", - 0, Float64(nil)) - } -} - -func TestFloat64Ptr(t *testing.T) { - v := float64(0) - if *Float64Ptr(v) != v { - t.Fatalf("to: Float64Ptr failed to return the correct string -- expected %v, received %v", - v, *Float64Ptr(v)) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/utility_test.go b/vendor/github.com/Azure/go-autorest/autorest/utility_test.go deleted file mode 100644 index 16665443..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/utility_test.go +++ /dev/null @@ -1,462 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "bytes" - "encoding/json" - "encoding/xml" - "errors" - "fmt" - "net/http" - "net/url" - "reflect" - "sort" - "strings" - "testing" - - "github.com/Azure/go-autorest/autorest/mocks" -) - -const ( - jsonT = ` - { - "name":"Rob Pike", - "age":42 - }` - xmlT = ` - - Rob Pike - 42 - ` -) - -func TestNewDecoderCreatesJSONDecoder(t *testing.T) { - d := NewDecoder(EncodedAsJSON, strings.NewReader(jsonT)) - _, ok := d.(*json.Decoder) - if d == nil || !ok { - t.Fatal("autorest: NewDecoder failed to create a JSON decoder when requested") - } -} - -func TestNewDecoderCreatesXMLDecoder(t *testing.T) { - d := NewDecoder(EncodedAsXML, strings.NewReader(xmlT)) - _, ok := d.(*xml.Decoder) - if d == nil || !ok { - t.Fatal("autorest: NewDecoder failed to create an XML decoder when requested") - } -} - -func TestNewDecoderReturnsNilForUnknownEncoding(t *testing.T) { - d := NewDecoder("unknown", strings.NewReader(xmlT)) - if d != nil { - t.Fatal("autorest: NewDecoder created a decoder for an unknown encoding") - } -} - -func TestCopyAndDecodeDecodesJSON(t *testing.T) { - _, err := CopyAndDecode(EncodedAsJSON, strings.NewReader(jsonT), &mocks.T{}) - if err != nil { - t.Fatalf("autorest: CopyAndDecode returned an error with valid JSON - %v", err) - } -} - -func TestCopyAndDecodeDecodesXML(t *testing.T) { - _, err := CopyAndDecode(EncodedAsXML, strings.NewReader(xmlT), &mocks.T{}) - if err != nil { - t.Fatalf("autorest: CopyAndDecode returned an error with valid XML - %v", err) - } -} - -func TestCopyAndDecodeReturnsJSONDecodingErrors(t *testing.T) { - _, err := CopyAndDecode(EncodedAsJSON, strings.NewReader(jsonT[0:len(jsonT)-2]), &mocks.T{}) - if err == nil { - t.Fatalf("autorest: CopyAndDecode failed to return an error with invalid JSON") - } -} - -func TestCopyAndDecodeReturnsXMLDecodingErrors(t *testing.T) { - _, err := CopyAndDecode(EncodedAsXML, strings.NewReader(xmlT[0:len(xmlT)-2]), &mocks.T{}) - if err == nil { - t.Fatalf("autorest: CopyAndDecode failed to return an error with invalid XML") - } -} - -func TestCopyAndDecodeAlwaysReturnsACopy(t *testing.T) { - b, _ := CopyAndDecode(EncodedAsJSON, strings.NewReader(jsonT), &mocks.T{}) - if b.String() != jsonT { - t.Fatalf("autorest: CopyAndDecode failed to return a valid copy of the data - %v", b.String()) - } -} - -func TestTeeReadCloser_Copies(t *testing.T) { - v := &mocks.T{} - r := mocks.NewResponseWithContent(jsonT) - b := &bytes.Buffer{} - - r.Body = TeeReadCloser(r.Body, b) - - err := Respond(r, - ByUnmarshallingJSON(v), - ByClosing()) - if err != nil { - t.Fatalf("autorest: TeeReadCloser returned an unexpected error -- %v", err) - } - if b.String() != jsonT { - t.Fatalf("autorest: TeeReadCloser failed to copy the bytes read") - } -} - -func TestTeeReadCloser_PassesReadErrors(t *testing.T) { - v := &mocks.T{} - r := mocks.NewResponseWithContent(jsonT) - - r.Body.(*mocks.Body).Close() - r.Body = TeeReadCloser(r.Body, &bytes.Buffer{}) - - err := Respond(r, - ByUnmarshallingJSON(v), - ByClosing()) - if err == nil { - t.Fatalf("autorest: TeeReadCloser failed to return the expected error") - } -} - -func TestTeeReadCloser_ClosesWrappedReader(t *testing.T) { - v := &mocks.T{} - r := mocks.NewResponseWithContent(jsonT) - - b := r.Body.(*mocks.Body) - r.Body = TeeReadCloser(r.Body, &bytes.Buffer{}) - err := Respond(r, - ByUnmarshallingJSON(v), - ByClosing()) - if err != nil { - t.Fatalf("autorest: TeeReadCloser returned an unexpected error -- %v", err) - } - if b.IsOpen() { - t.Fatalf("autorest: TeeReadCloser failed to close the nested io.ReadCloser") - } -} - -func TestContainsIntFindsValue(t *testing.T) { - ints := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} - v := 5 - if !containsInt(ints, v) { - t.Fatalf("autorest: containsInt failed to find %v in %v", v, ints) - } -} - -func TestContainsIntDoesNotFindValue(t *testing.T) { - ints := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} - v := 42 - if containsInt(ints, v) { - t.Fatalf("autorest: containsInt unexpectedly found %v in %v", v, ints) - } -} - -func TestContainsIntAcceptsEmptyList(t *testing.T) { - ints := make([]int, 10) - if containsInt(ints, 42) { - t.Fatalf("autorest: containsInt failed to handle an empty list") - } -} - -func TestContainsIntAcceptsNilList(t *testing.T) { - var ints []int - if containsInt(ints, 42) { - t.Fatalf("autorest: containsInt failed to handle an nil list") - } -} - -func TestEscapeStrings(t *testing.T) { - m := map[string]string{ - "string": "a long string with = odd characters", - "int": "42", - "nil": "", - } - r := map[string]string{ - "string": "a+long+string+with+%3D+odd+characters", - "int": "42", - "nil": "", - } - v := escapeValueStrings(m) - if !reflect.DeepEqual(v, r) { - t.Fatalf("autorest: ensureValueStrings returned %v\n", v) - } -} - -func TestEnsureStrings(t *testing.T) { - m := map[string]interface{}{ - "string": "string", - "int": 42, - "nil": nil, - "bytes": []byte{255, 254, 253}, - } - r := map[string]string{ - "string": "string", - "int": "42", - "nil": "", - "bytes": string([]byte{255, 254, 253}), - } - v := ensureValueStrings(m) - if !reflect.DeepEqual(v, r) { - t.Fatalf("autorest: ensureValueStrings returned %v\n", v) - } -} - -func ExampleString() { - m := []string{ - "string1", - "string2", - "string3", - } - - fmt.Println(String(m, ",")) - // Output: string1,string2,string3 -} - -func TestStringWithValidString(t *testing.T) { - i := 123 - if got, want := String(i), "123"; got != want { - t.Logf("got: %q\nwant: %q", got, want) - t.Fail() - } -} - -func TestStringWithStringSlice(t *testing.T) { - s := []string{"string1", "string2"} - if got, want := String(s, ","), "string1,string2"; got != want { - t.Logf("got: %q\nwant: %q", got, want) - t.Fail() - } -} - -func TestStringWithEnum(t *testing.T) { - type TestEnumType string - s := TestEnumType("string1") - if got, want := String(s), "string1"; got != want { - t.Logf("got: %q\nwant: %q", got, want) - t.Fail() - } -} - -func TestStringWithEnumSlice(t *testing.T) { - type TestEnumType string - s := []TestEnumType{"string1", "string2"} - if got, want := String(s, ","), "string1,string2"; got != want { - t.Logf("got: %q\nwant: %q", got, want) - t.Fail() - } -} - -func ExampleAsStringSlice() { - type TestEnumType string - - a := []TestEnumType{"value1", "value2"} - b, _ := AsStringSlice(a) - for _, c := range b { - fmt.Println(c) - } - // Output: - // value1 - // value2 -} - -func TestEncodeWithValidPath(t *testing.T) { - s := Encode("Path", "Hello Gopher") - if s != "Hello%20Gopher" { - t.Fatalf("autorest: Encode method failed for valid path encoding. Got: %v; Want: %v", s, "Hello%20Gopher") - } -} - -func TestEncodeWithValidQuery(t *testing.T) { - s := Encode("Query", "Hello Gopher") - if s != "Hello+Gopher" { - t.Fatalf("autorest: Encode method failed for valid query encoding. Got: '%v'; Want: 'Hello+Gopher'", s) - } -} - -func TestEncodeWithValidNotPathQuery(t *testing.T) { - s := Encode("Host", "Hello Gopher") - if s != "Hello Gopher" { - t.Fatalf("autorest: Encode method failed for parameter not query or path. Got: '%v'; Want: 'Hello Gopher'", s) - } -} - -func TestMapToValues(t *testing.T) { - m := map[string]interface{}{ - "a": "a", - "b": 2, - } - v := url.Values{} - v.Add("a", "a") - v.Add("b", "2") - if !isEqual(v, MapToValues(m)) { - t.Fatalf("autorest: MapToValues method failed to return correct values - expected(%v) got(%v)", v, MapToValues(m)) - } -} - -func TestMapToValuesWithArrayValues(t *testing.T) { - m := map[string]interface{}{ - "a": []string{"a", "b"}, - "b": 2, - "c": []int{3, 4}, - } - v := url.Values{} - v.Add("a", "a") - v.Add("a", "b") - v.Add("b", "2") - v.Add("c", "3") - v.Add("c", "4") - - if !isEqual(v, MapToValues(m)) { - t.Fatalf("autorest: MapToValues method failed to return correct values - expected(%v) got(%v)", v, MapToValues(m)) - } -} - -type someTempError struct{} - -func (s someTempError) Error() string { - return "temporary error" -} -func (s someTempError) Timeout() bool { - return true -} -func (s someTempError) Temporary() bool { - return true -} - -func TestIsTemporaryNetworkErrorTrue(t *testing.T) { - if !IsTemporaryNetworkError(someTempError{}) { - t.Fatal("expected someTempError to be a temporary network error") - } - if !IsTemporaryNetworkError(errors.New("non-temporary network error")) { - t.Fatal("expected random error to be a temporary network error") - } -} - -type someFatalError struct{} - -func (s someFatalError) Error() string { - return "fatal error" -} -func (s someFatalError) Timeout() bool { - return false -} -func (s someFatalError) Temporary() bool { - return false -} - -func TestIsTemporaryNetworkErrorFalse(t *testing.T) { - if IsTemporaryNetworkError(someFatalError{}) { - t.Fatal("expected someFatalError to be a fatal network error") - } -} - -func isEqual(v, u url.Values) bool { - for key, value := range v { - if len(u[key]) == 0 { - return false - } - sort.Strings(value) - sort.Strings(u[key]) - for i := range value { - if value[i] != u[key][i] { - return false - } - } - u.Del(key) - } - if len(u) > 0 { - return false - } - return true -} - -func doEnsureBodyClosed(t *testing.T) SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - resp, err := s.Do(r) - if resp != nil && resp.Body != nil && resp.Body.(*mocks.Body).IsOpen() { - t.Fatal("autorest: Expected Body to be closed -- it was left open") - } - return resp, err - }) - } -} - -type mockAuthorizer struct{} - -func (ma mockAuthorizer) WithAuthorization() PrepareDecorator { - return WithHeader(headerAuthorization, mocks.TestAuthorizationHeader) -} - -type mockFailingAuthorizer struct{} - -func (mfa mockFailingAuthorizer) WithAuthorization() PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - return r, fmt.Errorf("ERROR: mockFailingAuthorizer returned expected error") - }) - } -} - -type mockInspector struct { - wasInvoked bool -} - -func (mi *mockInspector) WithInspection() PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - mi.wasInvoked = true - return p.Prepare(r) - }) - } -} - -func (mi *mockInspector) ByInspecting() RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - mi.wasInvoked = true - return r.Respond(resp) - }) - } -} - -func withMessage(output *string, msg string) SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - resp, err := s.Do(r) - if err == nil { - *output += msg - } - return resp, err - }) - } -} - -func withErrorRespondDecorator(e *error) RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - err := r.Respond(resp) - if err != nil { - return err - } - *e = fmt.Errorf("autorest: Faux Respond Error") - return *e - }) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/validation/validation_test.go b/vendor/github.com/Azure/go-autorest/autorest/validation/validation_test.go deleted file mode 100644 index e34e29ec..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/validation/validation_test.go +++ /dev/null @@ -1,2450 +0,0 @@ -package validation - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "fmt" - "reflect" - "strings" - "testing" - - "github.com/stretchr/testify/require" -) - -func TestCheckForUniqueInArrayTrue(t *testing.T) { - require.Equal(t, checkForUniqueInArray(reflect.ValueOf([]int{1, 2, 3})), true) -} - -func TestCheckForUniqueInArrayFalse(t *testing.T) { - require.Equal(t, checkForUniqueInArray(reflect.ValueOf([]int{1, 2, 3, 3})), false) -} - -func TestCheckForUniqueInArrayEmpty(t *testing.T) { - require.Equal(t, checkForUniqueInArray(reflect.ValueOf([]int{})), false) -} - -func TestCheckForUniqueInMapTrue(t *testing.T) { - require.Equal(t, checkForUniqueInMap(reflect.ValueOf(map[string]int{"one": 1, "two": 2})), true) -} - -func TestCheckForUniqueInMapFalse(t *testing.T) { - require.Equal(t, checkForUniqueInMap(reflect.ValueOf(map[int]string{1: "one", 2: "one"})), false) -} - -func TestCheckForUniqueInMapEmpty(t *testing.T) { - require.Equal(t, checkForUniqueInMap(reflect.ValueOf(map[int]string{})), false) -} - -func TestCheckEmpty_WithValueEmptyRuleTrue(t *testing.T) { - var x interface{} - v := Constraint{ - Target: "str", - Name: Empty, - Rule: true, - Chain: nil, - } - expected := createError(reflect.ValueOf(x), v, "value can not be null or empty; required parameter") - require.Equal(t, checkEmpty(reflect.ValueOf(x), v).Error(), expected.Error()) -} - -func TestCheckEmpty_WithEmptyStringRuleFalse(t *testing.T) { - var x interface{} - v := Constraint{ - Target: "str", - Name: Empty, - Rule: false, - Chain: nil, - } - require.Nil(t, checkEmpty(reflect.ValueOf(x), v)) -} - -func TestCheckEmpty_IncorrectRule(t *testing.T) { - var x interface{} - v := Constraint{ - Target: "str", - Name: Empty, - Rule: 10, - Chain: nil, - } - expected := createError(reflect.ValueOf(x), v, fmt.Sprintf("rule must be bool value for %v constraint; got: %v", v.Name, v.Rule)) - require.Equal(t, checkEmpty(reflect.ValueOf(x), v).Error(), expected.Error()) -} - -func TestCheckEmpty_WithErrorArray(t *testing.T) { - var x interface{} = []string{} - v := Constraint{ - Target: "str", - Name: Empty, - Rule: true, - Chain: nil, - } - expected := createError(reflect.ValueOf(x), v, "value can not be null or empty; required parameter") - require.Equal(t, checkEmpty(reflect.ValueOf(x), v).Error(), expected.Error()) -} - -func TestCheckNil_WithNilValueRuleTrue(t *testing.T) { - var x interface{} - v := Constraint{ - Target: "x", - Name: Null, - Rule: true, - Chain: []Constraint{ - {"x", MaxItems, 4, nil}, - }, - } - expected := createError(reflect.ValueOf(x), v, "value can not be null; required parameter") - require.Equal(t, checkNil(reflect.ValueOf(x), v).Error(), expected.Error()) -} - -func TestCheckNil_WithNilValueRuleFalse(t *testing.T) { - var x interface{} - v := Constraint{ - Target: "x", - Name: Null, - Rule: false, - Chain: []Constraint{ - {"x", MaxItems, 4, nil}, - }, - } - require.Nil(t, checkNil(reflect.ValueOf(x), v)) -} - -func TestCheckNil_IncorrectRule(t *testing.T) { - var x interface{} - c := Constraint{ - Target: "str", - Name: Null, - Rule: 10, - Chain: nil, - } - expected := createError(reflect.ValueOf(x), c, fmt.Sprintf("rule must be bool value for %v constraint; got: %v", c.Name, c.Rule)) - require.Equal(t, checkNil(reflect.ValueOf(x), c).Error(), expected.Error()) -} - -func TestValidateArrayMap_WithNilValueRuleTrue(t *testing.T) { - var a []string - var x interface{} = a - c := Constraint{ - Target: "arr", - Name: Null, - Rule: true, - Chain: nil, - } - expected := createError(reflect.ValueOf(x), c, "value can not be null; required parameter") - require.Equal(t, validateArrayMap(reflect.ValueOf(x), c), expected) -} - -func TestValidateArrayMap_WithNilValueRuleFalse(t *testing.T) { - var x interface{} = []string{} - c := Constraint{ - Target: "arr", - Name: Null, - Rule: false, - Chain: nil, - } - require.Nil(t, validateArrayMap(reflect.ValueOf(x), c)) -} - -func TestValidateArrayMap_WithValueRuleNullTrue(t *testing.T) { - var x interface{} = []string{"1", "2"} - c := Constraint{ - Target: "arr", - Name: Null, - Rule: false, - Chain: nil, - } - require.Nil(t, validateArrayMap(reflect.ValueOf(x), c)) -} - -func TestValidateArrayMap_WithEmptyValueRuleTrue(t *testing.T) { - var x interface{} = []string{} - c := Constraint{ - Target: "arr", - Name: Empty, - Rule: true, - Chain: nil, - } - expected := createError(reflect.ValueOf(x), c, "value can not be null or empty; required parameter") - require.Equal(t, validateArrayMap(reflect.ValueOf(x), c), expected) -} - -func TestValidateArrayMap_WithEmptyValueRuleFalse(t *testing.T) { - var x interface{} = []string{} - c := Constraint{ - Target: "arr", - Name: Empty, - Rule: false, - Chain: nil, - } - require.Nil(t, validateArrayMap(reflect.ValueOf(x), c)) -} - -func TestValidateArrayMap_WithEmptyRuleEmptyTrue(t *testing.T) { - var x interface{} = []string{"1", "2"} - c := Constraint{ - Target: "arr", - Name: Empty, - Rule: false, - Chain: nil, - } - require.Nil(t, validateArrayMap(reflect.ValueOf(x), c)) -} - -func TestValidateArrayMap_MaxItemsIncorrectRule(t *testing.T) { - var x interface{} = []string{"1", "2"} - c := Constraint{ - Target: "arr", - Name: MaxItems, - Rule: false, - Chain: nil, - } - expected := createError(reflect.ValueOf(x), c, fmt.Sprintf("rule must be integer for %v constraint; got: %v", c.Name, c.Rule)) - require.Equal(t, validateArrayMap(reflect.ValueOf(x), c).Error(), expected.Error()) -} - -func TestValidateArrayMap_MaxItemsNoError(t *testing.T) { - var x interface{} = []string{"1", "2"} - c := Constraint{ - Target: "arr", - Name: MaxItems, - Rule: 2, - Chain: nil, - } - require.Nil(t, validateArrayMap(reflect.ValueOf(x), c)) -} - -func TestValidateArrayMap_MaxItemsWithError(t *testing.T) { - var x interface{} = []string{"1", "2", "3"} - c := Constraint{ - Target: "arr", - Name: MaxItems, - Rule: 2, - Chain: nil, - } - expected := createError(reflect.ValueOf(x), c, fmt.Sprintf("maximum item limit is %v; got: 3", c.Rule)) - require.Equal(t, validateArrayMap(reflect.ValueOf(x), c).Error(), expected.Error()) -} - -func TestValidateArrayMap_MaxItemsWithEmpty(t *testing.T) { - var x interface{} = []string{} - c := Constraint{ - Target: "arr", - Name: MaxItems, - Rule: 2, - Chain: nil, - } - require.Nil(t, validateArrayMap(reflect.ValueOf(x), c)) -} - -func TestValidateArrayMap_MinItemsIncorrectRule(t *testing.T) { - var x interface{} = []int{1, 2} - c := Constraint{ - Target: "arr", - Name: MinItems, - Rule: false, - Chain: nil, - } - expected := createError(reflect.ValueOf(x), c, fmt.Sprintf("rule must be integer for %v constraint; got: %v", c.Name, c.Rule)) - require.Equal(t, validateArrayMap(reflect.ValueOf(x), c).Error(), expected.Error()) -} - -func TestValidateArrayMap_MinItemsNoError1(t *testing.T) { - c := Constraint{ - Target: "arr", - Name: MinItems, - Rule: 2, - Chain: nil, - } - require.Nil(t, validateArrayMap(reflect.ValueOf([]int{1, 2}), c)) -} - -func TestValidateArrayMap_MinItemsNoError2(t *testing.T) { - c := Constraint{ - Target: "arr", - Name: MinItems, - Rule: 2, - Chain: nil, - } - require.Nil(t, validateArrayMap(reflect.ValueOf([]int{1, 2, 3}), c)) -} - -func TestValidateArrayMap_MinItemsWithError(t *testing.T) { - var x interface{} = []int{1} - c := Constraint{ - Target: "arr", - Name: MinItems, - Rule: 2, - Chain: nil, - } - expected := createError(reflect.ValueOf(x), c, fmt.Sprintf("minimum item limit is %v; got: 1", c.Rule)) - require.Equal(t, validateArrayMap(reflect.ValueOf(x), c).Error(), expected.Error()) -} - -func TestValidateArrayMap_MinItemsWithEmpty(t *testing.T) { - var x interface{} = []int{} - c := Constraint{ - Target: "arr", - Name: MinItems, - Rule: 2, - Chain: nil, - } - expected := createError(reflect.ValueOf(x), c, fmt.Sprintf("minimum item limit is %v; got: 0", c.Rule)) - require.Equal(t, validateArrayMap(reflect.ValueOf(x), c).Error(), expected.Error()) -} - -func TestValidateArrayMap_Map_MaxItemsIncorrectRule(t *testing.T) { - var x interface{} = map[int]string{1: "1", 2: "2"} - c := Constraint{ - Target: "arr", - Name: MaxItems, - Rule: false, - Chain: nil, - } - require.Equal(t, strings.Contains(validateArrayMap(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("rule must be integer for %v constraint; got: %v", c.Name, c.Rule)), true) -} - -func TestValidateArrayMap_Map_MaxItemsNoError(t *testing.T) { - var x interface{} = map[int]string{1: "1", 2: "2"} - c := Constraint{ - Target: "arr", - Name: MaxItems, - Rule: 2, - Chain: nil, - } - require.Nil(t, validateArrayMap(reflect.ValueOf(x), c)) -} - -func TestValidateArrayMap_Map_MaxItemsWithError(t *testing.T) { - a := map[int]string{1: "1", 2: "2", 3: "3"} - var x interface{} = a - c := Constraint{ - Target: "arr", - Name: MaxItems, - Rule: 2, - Chain: nil, - } - require.Equal(t, strings.Contains(validateArrayMap(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("maximum item limit is %v; got: %v", c.Rule, len(a))), true) -} - -func TestValidateArrayMap_Map_MaxItemsWithEmpty(t *testing.T) { - a := map[int]string{} - var x interface{} = a - c := Constraint{ - Target: "arr", - Name: MaxItems, - Rule: 2, - Chain: nil, - } - require.Nil(t, validateArrayMap(reflect.ValueOf(x), c)) -} - -func TestValidateArrayMap_Map_MinItemsIncorrectRule(t *testing.T) { - var x interface{} = map[int]string{1: "1", 2: "2"} - c := Constraint{ - Target: "arr", - Name: MinItems, - Rule: false, - Chain: nil, - } - require.Equal(t, strings.Contains(validateArrayMap(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("rule must be integer for %v constraint; got: %v", c.Name, c.Rule)), true) -} - -func TestValidateArrayMap_Map_MinItemsNoError1(t *testing.T) { - var x interface{} = map[int]string{1: "1", 2: "2"} - require.Nil(t, validateArrayMap(reflect.ValueOf(x), - Constraint{ - Target: "arr", - Name: MinItems, - Rule: 2, - Chain: nil, - })) -} - -func TestValidateArrayMap_Map_MinItemsNoError2(t *testing.T) { - var x interface{} = map[int]string{1: "1", 2: "2", 3: "3"} - c := Constraint{ - Target: "arr", - Name: MinItems, - Rule: 2, - Chain: nil, - } - require.Nil(t, validateArrayMap(reflect.ValueOf(x), c)) -} - -func TestValidateArrayMap_Map_MinItemsWithError(t *testing.T) { - a := map[int]string{1: "1"} - var x interface{} = a - c := Constraint{ - Target: "arr", - Name: MinItems, - Rule: 2, - Chain: nil, - } - expected := createError(reflect.ValueOf(x), c, fmt.Sprintf("minimum item limit is %v; got: %v", c.Rule, len(a))) - require.Equal(t, validateArrayMap(reflect.ValueOf(x), c).Error(), expected.Error()) -} - -func TestValidateArrayMap_Map_MinItemsWithEmpty(t *testing.T) { - a := map[int]string{} - var x interface{} = a - c := Constraint{ - Target: "arr", - Name: MinItems, - Rule: 2, - Chain: nil, - } - expected := createError(reflect.ValueOf(x), c, fmt.Sprintf("minimum item limit is %v; got: %v", c.Rule, len(a))) - require.Equal(t, validateArrayMap(reflect.ValueOf(x), c).Error(), expected.Error()) -} - -// func TestValidateArrayMap_Map_MinItemsNil(t *testing.T) { -// var a map[int]float64 -// var x interface{} = a -// c := Constraint{ -// Target: "str", -// Name: MinItems, -// Rule: true, -// Chain: nil, -// } -// expected := createError(reflect.Value(x), c, fmt.Sprintf("all items in parameter %v must be unique; got:%v", c.Target, x)) -// if z := validateArrayMap(reflect.ValueOf(x), c); strings.Contains(z.Error(), "all items in parameter str must be unique;") { -// t.Fatalf("autorest/validation: valiateArrayMap failed to return error \nexpect: %v;\ngot: %v", expected, z) -// } -// } - -func TestValidateArrayMap_Map_UniqueItemsTrue(t *testing.T) { - var x interface{} = map[float64]int{1.2: 1, 1.4: 2} - c := Constraint{ - Target: "str", - Name: UniqueItems, - Rule: true, - Chain: nil, - } - require.Nil(t, validateArrayMap(reflect.ValueOf(x), c)) -} - -func TestValidateArrayMap_Map_UniqueItemsFalse(t *testing.T) { - var x interface{} = map[string]string{"1": "1", "2": "2", "3": "1"} - c := Constraint{ - Target: "str", - Name: UniqueItems, - Rule: true, - Chain: nil, - } - z := validateArrayMap(reflect.ValueOf(x), c) - require.Equal(t, strings.Contains(z.Error(), - fmt.Sprintf("all items in parameter %q must be unique", c.Target)), true) -} - -func TestValidateArrayMap_Map_UniqueItemsEmpty(t *testing.T) { - // Consider Empty map as not unique returns false - var x interface{} = map[int]float64{} - c := Constraint{ - Target: "str", - Name: UniqueItems, - Rule: true, - Chain: nil, - } - z := validateArrayMap(reflect.ValueOf(x), c) - require.Equal(t, strings.Contains(z.Error(), - fmt.Sprintf("all items in parameter %q must be unique", c.Target)), true) -} - -func TestValidateArrayMap_Map_UniqueItemsNil(t *testing.T) { - var a map[int]float64 - var x interface{} = a - c := Constraint{ - Target: "str", - Name: UniqueItems, - Rule: true, - Chain: nil, - } - z := validateArrayMap(reflect.ValueOf(x), c) - require.Equal(t, strings.Contains(z.Error(), - fmt.Sprintf("all items in parameter %q must be unique; got:%v", c.Target, x)), true) -} - -func TestValidateArrayMap_Array_UniqueItemsTrue(t *testing.T) { - var x interface{} = []int{1, 2} - c := Constraint{ - Target: "str", - Name: UniqueItems, - Rule: true, - Chain: nil, - } - require.Nil(t, validateArrayMap(reflect.ValueOf(x), c)) -} - -func TestValidateArrayMap_Array_UniqueItemsFalse(t *testing.T) { - var x interface{} = []string{"1", "2", "1"} - c := Constraint{ - Target: "str", - Name: UniqueItems, - Rule: true, - Chain: nil, - } - z := validateArrayMap(reflect.ValueOf(x), c) - require.Equal(t, strings.Contains(z.Error(), - fmt.Sprintf("all items in parameter %q must be unique; got:%v", c.Target, x)), true) -} - -func TestValidateArrayMap_Array_UniqueItemsEmpty(t *testing.T) { - // Consider Empty array as not unique returns false - var x interface{} = []float64{} - c := Constraint{ - Target: "str", - Name: UniqueItems, - Rule: true, - Chain: nil, - } - z := validateArrayMap(reflect.ValueOf(x), c) - require.Equal(t, strings.Contains(z.Error(), - fmt.Sprintf("all items in parameter %q must be unique; got:%v", c.Target, x)), true) -} - -func TestValidateArrayMap_Array_UniqueItemsNil(t *testing.T) { - // Consider nil array as not unique returns false - var a []float64 - var x interface{} = a - c := Constraint{ - Target: "str", - Name: UniqueItems, - Rule: true, - Chain: nil, - } - z := validateArrayMap(reflect.ValueOf(x), c) - require.Equal(t, strings.Contains(z.Error(), - fmt.Sprintf("all items in parameter %q must be unique; got:%v", c.Target, x)), true) -} - -func TestValidateArrayMap_Array_UniqueItemsInvalidType(t *testing.T) { - var x interface{} = "hello" - c := Constraint{ - Target: "str", - Name: UniqueItems, - Rule: true, - Chain: nil, - } - z := validateArrayMap(reflect.ValueOf(x), c) - require.Equal(t, strings.Contains(z.Error(), - fmt.Sprintf("type must be array, slice or map for constraint %v; got: %v", c.Name, reflect.ValueOf(x).Kind())), true) -} - -func TestValidateArrayMap_Array_UniqueItemsInvalidConstraint(t *testing.T) { - var x interface{} = "hello" - c := Constraint{ - Target: "str", - Name: "sdad", - Rule: true, - Chain: nil, - } - z := validateArrayMap(reflect.ValueOf(x), c) - require.Equal(t, strings.Contains(z.Error(), - fmt.Sprintf("constraint %v is not applicable to array, slice and map type", c.Name)), true) -} - -func TestValidateArrayMap_ValidateChainConstraint1(t *testing.T) { - a := []int{1, 2, 3, 4} - var x interface{} = a - c := Constraint{ - Target: "str", - Name: Null, - Rule: true, - Chain: []Constraint{ - {"str", MaxItems, 3, nil}, - }, - } - z := validateArrayMap(reflect.ValueOf(x), c) - require.Equal(t, strings.Contains(z.Error(), - fmt.Sprintf("maximum item limit is %v; got: %v", (c.Chain)[0].Rule, len(a))), true) -} - -func TestValidateArrayMap_ValidateChainConstraint2(t *testing.T) { - a := []int{1, 2, 3, 4} - var x interface{} = a - c := Constraint{ - Target: "str", - Name: Empty, - Rule: true, - Chain: []Constraint{ - {"str", MaxItems, 3, nil}, - }, - } - z := validateArrayMap(reflect.ValueOf(x), c) - require.Equal(t, strings.Contains(z.Error(), - fmt.Sprintf("maximum item limit is %v; got: %v", (c.Chain)[0].Rule, len(a))), true) -} - -func TestValidateArrayMap_ValidateChainConstraint3(t *testing.T) { - var a []string - var x interface{} = a - c := Constraint{ - Target: "str", - Name: Null, - Rule: true, - Chain: []Constraint{ - {"str", MaxItems, 3, nil}, - }, - } - z := validateArrayMap(reflect.ValueOf(x), c) - require.Equal(t, strings.Contains(z.Error(), - fmt.Sprintf("value can not be null; required parameter")), true) -} - -func TestValidateArrayMap_ValidateChainConstraint4(t *testing.T) { - var x interface{} = []int{} - c := Constraint{ - Target: "str", - Name: Empty, - Rule: true, - Chain: []Constraint{ - {"str", MaxItems, 3, nil}, - }, - } - z := validateArrayMap(reflect.ValueOf(x), c) - require.Equal(t, strings.Contains(z.Error(), - fmt.Sprintf("value can not be null or empty; required parameter")), true) -} - -func TestValidateArrayMap_ValidateChainConstraintNilNotRequired(t *testing.T) { - var a []int - var x interface{} = a - c := Constraint{ - Target: "str", - Name: Null, - Rule: false, - Chain: []Constraint{ - {"str", MaxItems, 3, nil}, - }, - } - require.Nil(t, validateArrayMap(reflect.ValueOf(x), c)) -} - -func TestValidateArrayMap_ValidateChainConstraintEmptyNotRequired(t *testing.T) { - var x interface{} = map[string]int{} - c := Constraint{ - Target: "str", - Name: Empty, - Rule: false, - Chain: []Constraint{ - {"str", MaxItems, 3, nil}, - }, - } - require.Nil(t, validateArrayMap(reflect.ValueOf(x), c)) -} - -func TestValidateArrayMap_ReadOnlyWithError(t *testing.T) { - var x interface{} = []int{1, 2} - c := Constraint{ - Target: "str", - Name: ReadOnly, - Rule: true, - Chain: []Constraint{ - {"str", MaxItems, 3, nil}, - }, - } - z := validateArrayMap(reflect.ValueOf(x), c) - require.Equal(t, strings.Contains(z.Error(), - fmt.Sprintf("readonly parameter; must send as nil or empty in request")), true) -} - -func TestValidateArrayMap_ReadOnlyWithoutError(t *testing.T) { - var x interface{} = []int{} - c := Constraint{ - Target: "str", - Name: ReadOnly, - Rule: true, - Chain: nil, - } - require.Nil(t, validateArrayMap(reflect.ValueOf(x), c)) -} - -func TestValidateString_ReadOnly(t *testing.T) { - var x interface{} = "Hello Gopher" - c := Constraint{ - Target: "str", - Name: ReadOnly, - Rule: true, - Chain: nil, - } - require.Equal(t, strings.Contains(validateString(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("readonly parameter; must send as nil or empty in request")), true) -} - -func TestValidateString_EmptyTrue(t *testing.T) { - // Empty true means parameter is required but Empty returns error - c := Constraint{ - Target: "str", - Name: Empty, - Rule: true, - Chain: nil, - } - require.Equal(t, strings.Contains(validateString(reflect.ValueOf(""), c).Error(), - fmt.Sprintf("value can not be null or empty; required parameter")), true) -} - -func TestValidateString_EmptyFalse(t *testing.T) { - // Empty false means parameter is not required and Empty return nil - var x interface{} - c := Constraint{ - Target: "str", - Name: Empty, - Rule: false, - Chain: nil, - } - require.Nil(t, validateString(reflect.ValueOf(x), c)) -} - -func TestValidateString_MaxLengthInvalid(t *testing.T) { - // Empty true means parameter is required but Empty returns error - var x interface{} = "Hello" - c := Constraint{ - Target: "str", - Name: MaxLength, - Rule: 4, - Chain: nil, - } - require.Equal(t, strings.Contains(validateString(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("value length must be less than or equal to %v", c.Rule)), true) -} - -func TestValidateString_MaxLengthValid(t *testing.T) { - // Empty false means parameter is not required and Empty return nil - c := Constraint{ - Target: "str", - Name: MaxLength, - Rule: 7, - Chain: nil, - } - require.Nil(t, validateString(reflect.ValueOf("Hello"), c)) -} - -func TestValidateString_MaxLengthRuleInvalid(t *testing.T) { - var x interface{} = "Hello" - c := Constraint{ - Target: "str", - Name: MaxLength, - Rule: true, // must be int for maxLength - Chain: nil, - } - require.Equal(t, strings.Contains(validateString(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("rule must be integer value for %v constraint; got: %v", c.Name, c.Rule)), true) -} - -func TestValidateString_MinLengthInvalid(t *testing.T) { - var x interface{} = "Hello" - c := Constraint{ - Target: "str", - Name: MinLength, - Rule: 10, - Chain: nil, - } - require.Equal(t, strings.Contains(validateString(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("value length must be greater than or equal to %v", c.Rule)), true) -} - -func TestValidateString_MinLengthValid(t *testing.T) { - c := Constraint{ - Target: "str", - Name: MinLength, - Rule: 2, - Chain: nil, - } - require.Nil(t, validateString(reflect.ValueOf("Hello"), c)) -} - -func TestValidateString_MinLengthRuleInvalid(t *testing.T) { - var x interface{} = "Hello" - c := Constraint{ - Target: "str", - Name: MinLength, - Rule: true, // must be int for minLength - Chain: nil, - } - require.Equal(t, strings.Contains(validateString(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("rule must be integer value for %v constraint; got: %v", c.Name, c.Rule)), true) -} - -func TestValidateString_PatternInvalidPattern(t *testing.T) { - var x interface{} = "Hello" - c := Constraint{ - Target: "str", - Name: Pattern, - Rule: `^[[:alnum:$`, - Chain: nil, - } - require.Equal(t, strings.Contains(validateString(reflect.ValueOf(x), c).Error(), - "error parsing regexp: missing closing ]"), true) -} - -func TestValidateString_PatternMatch1(t *testing.T) { - c := Constraint{ - Target: "str", - Name: Pattern, - Rule: `^http://\w+$`, - Chain: nil, - } - require.Nil(t, validateString(reflect.ValueOf("http://masd"), c)) -} - -func TestValidateString_PatternMatch2(t *testing.T) { - c := Constraint{ - Target: "str", - Name: Pattern, - Rule: `^[a-zA-Z0-9]+$`, - Chain: nil, - } - require.Nil(t, validateString(reflect.ValueOf("asdadad2323sad"), c)) -} - -func TestValidateString_PatternNotMatch(t *testing.T) { - var x interface{} = "asdad@@ad2323sad" - c := Constraint{ - Target: "str", - Name: Pattern, - Rule: `^[a-zA-Z0-9]+$`, - Chain: nil, - } - require.Equal(t, strings.Contains(validateString(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("value doesn't match pattern %v", c.Rule)), true) -} - -func TestValidateString_InvalidConstraint(t *testing.T) { - var x interface{} = "asdad@@ad2323sad" - c := Constraint{ - Target: "str", - Name: UniqueItems, - Rule: "^[a-zA-Z0-9]+$", - Chain: nil, - } - require.Equal(t, strings.Contains(validateString(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("constraint %s is not applicable to string type", c.Name)), true) -} - -func TestValidateFloat_InvalidConstraint(t *testing.T) { - var x interface{} = 1.4 - c := Constraint{ - Target: "str", - Name: UniqueItems, - Rule: 3.0, - Chain: nil, - } - require.Equal(t, strings.Contains(validateFloat(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("constraint %v is not applicable for type float", c.Name)), true) -} - -func TestValidateFloat_InvalidRuleValue(t *testing.T) { - var x interface{} = 1.4 - c := Constraint{ - Target: "str", - Name: ExclusiveMinimum, - Rule: 3, - Chain: nil, - } - require.Equal(t, strings.Contains(validateFloat(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("rule must be float value for %v constraint; got: %v", c.Name, c.Rule)), true) -} - -func TestValidateFloat_ExclusiveMinimumConstraintValid(t *testing.T) { - c := Constraint{ - Target: "str", - Name: ExclusiveMinimum, - Rule: 1.0, - Chain: nil, - } - require.Nil(t, validateFloat(reflect.ValueOf(1.42), c)) -} - -func TestValidateFloat_ExclusiveMinimumConstraintInvalid(t *testing.T) { - var x interface{} = 1.4 - c := Constraint{ - Target: "str", - Name: ExclusiveMinimum, - Rule: 1.5, - Chain: nil, - } - require.Equal(t, strings.Contains(validateFloat(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("value must be greater than %v", c.Rule)), true) -} - -func TestValidateFloat_ExclusiveMinimumConstraintBoundary(t *testing.T) { - var x interface{} = 1.42 - c := Constraint{ - Target: "str", - Name: ExclusiveMinimum, - Rule: 1.42, - Chain: nil, - } - require.Equal(t, strings.Contains(validateFloat(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("value must be greater than %v", c.Rule)), true) -} - -func TestValidateFloat_exclusiveMaximumConstraintValid(t *testing.T) { - c := Constraint{ - Target: "str", - Name: ExclusiveMaximum, - Rule: 2.0, - Chain: nil, - } - require.Nil(t, validateFloat(reflect.ValueOf(1.42), c)) -} - -func TestValidateFloat_exclusiveMaximumConstraintInvalid(t *testing.T) { - var x interface{} = 1.42 - c := Constraint{ - Target: "str", - Name: ExclusiveMaximum, - Rule: 1.2, - Chain: nil, - } - require.Equal(t, strings.Contains(validateFloat(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("value must be less than %v", c.Rule)), true) -} - -func TestValidateFloat_exclusiveMaximumConstraintBoundary(t *testing.T) { - var x interface{} = 1.42 - c := Constraint{ - Target: "str", - Name: ExclusiveMaximum, - Rule: 1.42, - Chain: nil, - } - require.Equal(t, strings.Contains(validateFloat(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("value must be less than %v", c.Rule)), true) -} - -func TestValidateFloat_inclusiveMaximumConstraintValid(t *testing.T) { - c := Constraint{ - Target: "str", - Name: InclusiveMaximum, - Rule: 2.0, - Chain: nil, - } - require.Nil(t, validateFloat(reflect.ValueOf(1.42), c)) -} - -func TestValidateFloat_inclusiveMaximumConstraintInvalid(t *testing.T) { - var x interface{} = 1.42 - c := Constraint{ - Target: "str", - Name: InclusiveMaximum, - Rule: 1.2, - Chain: nil, - } - require.Equal(t, strings.Contains(validateFloat(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("value must be less than or equal to %v", c.Rule)), true) - -} - -func TestValidateFloat_inclusiveMaximumConstraintBoundary(t *testing.T) { - c := Constraint{ - Target: "str", - Name: InclusiveMaximum, - Rule: 1.42, - Chain: nil, - } - require.Nil(t, validateFloat(reflect.ValueOf(1.42), c)) -} - -func TestValidateFloat_InclusiveMinimumConstraintValid(t *testing.T) { - c := Constraint{ - Target: "str", - Name: InclusiveMinimum, - Rule: 1.0, - Chain: nil, - } - require.Nil(t, validateFloat(reflect.ValueOf(1.42), c)) -} - -func TestValidateFloat_InclusiveMinimumConstraintInvalid(t *testing.T) { - var x interface{} = 1.42 - c := Constraint{ - Target: "str", - Name: InclusiveMinimum, - Rule: 1.5, - Chain: nil, - } - require.Equal(t, strings.Contains(validateFloat(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("value must be greater than or equal to %v", c.Rule)), true) - -} - -func TestValidateFloat_InclusiveMinimumConstraintBoundary(t *testing.T) { - c := Constraint{ - Target: "str", - Name: InclusiveMinimum, - Rule: 1.42, - Chain: nil, - } - require.Nil(t, validateFloat(reflect.ValueOf(1.42), c)) -} - -func TestValidateInt_InvalidConstraint(t *testing.T) { - var x interface{} = 1 - c := Constraint{ - Target: "str", - Name: UniqueItems, - Rule: 3, - Chain: nil, - } - require.Equal(t, strings.Contains(validateInt(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("constraint %s is not applicable for type integer", c.Name)), true) -} - -func TestValidateInt_InvalidRuleValue(t *testing.T) { - var x interface{} = 1 - c := Constraint{ - Target: "str", - Name: ExclusiveMinimum, - Rule: 3.4, - Chain: nil, - } - require.Equal(t, strings.Contains(validateInt(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("rule must be integer value for %v constraint; got: %v", c.Name, c.Rule)), true) -} - -func TestValidateInt_ExclusiveMinimumConstraintValid(t *testing.T) { - c := Constraint{ - Target: "str", - Name: ExclusiveMinimum, - Rule: 1, - Chain: nil, - } - require.Nil(t, validateInt(reflect.ValueOf(3), c)) -} - -func TestValidateInt_ExclusiveMinimumConstraintInvalid(t *testing.T) { - var x interface{} = 1 - c := Constraint{ - Target: "str", - Name: ExclusiveMinimum, - Rule: 3, - Chain: nil, - } - require.Equal(t, validateInt(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(x), c, fmt.Sprintf("value must be greater than %v", c.Rule)).Error()) -} - -func TestValidateInt_ExclusiveMinimumConstraintBoundary(t *testing.T) { - var x interface{} = 1 - c := Constraint{ - Target: "str", - Name: ExclusiveMinimum, - Rule: 1, - Chain: nil, - } - require.Equal(t, validateInt(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(x), c, fmt.Sprintf("value must be greater than %v", c.Rule)).Error()) -} - -func TestValidateInt_exclusiveMaximumConstraintValid(t *testing.T) { - c := Constraint{ - Target: "str", - Name: ExclusiveMaximum, - Rule: 2, - Chain: nil, - } - require.Nil(t, validateInt(reflect.ValueOf(1), c)) -} - -func TestValidateInt_exclusiveMaximumConstraintInvalid(t *testing.T) { - var x interface{} = 2 - c := Constraint{ - Target: "str", - Name: ExclusiveMaximum, - Rule: 1, - Chain: nil, - } - require.Equal(t, validateInt(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(x), c, fmt.Sprintf("value must be less than %v", c.Rule)).Error()) -} - -func TestValidateInt_exclusiveMaximumConstraintBoundary(t *testing.T) { - var x interface{} = 1 - c := Constraint{ - Target: "str", - Name: ExclusiveMaximum, - Rule: 1, - Chain: nil, - } - require.Equal(t, validateInt(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(x), c, fmt.Sprintf("value must be less than %v", c.Rule)).Error()) -} - -func TestValidateInt_inclusiveMaximumConstraintValid(t *testing.T) { - c := Constraint{ - Target: "str", - Name: InclusiveMaximum, - Rule: int64(2), - Chain: nil, - } - require.Nil(t, validateInt(reflect.ValueOf(1), c)) -} - -func TestValidateInt_inclusiveMaximumConstraintInvalid(t *testing.T) { - var x interface{} = 2 - c := Constraint{ - Target: "str", - Name: InclusiveMaximum, - Rule: int64(1), - Chain: nil, - } - require.Equal(t, validateInt(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(x), c, fmt.Sprintf("value must be less than or equal to %v", c.Rule)).Error()) -} - -func TestValidateInt_inclusiveMaximumConstraintBoundary(t *testing.T) { - c := Constraint{ - Target: "str", - Name: InclusiveMaximum, - Rule: int64(1), - Chain: nil, - } - require.Nil(t, validateInt(reflect.ValueOf(1), c)) -} - -func TestValidateInt_InclusiveMinimumConstraintValid(t *testing.T) { - c := Constraint{ - Target: "str", - Name: InclusiveMinimum, - Rule: 1, - Chain: nil, - } - require.Nil(t, validateInt(reflect.ValueOf(1), c)) -} - -func TestValidateInt_InclusiveMinimumConstraintInvalid(t *testing.T) { - var x interface{} = 1 - c := Constraint{ - Target: "str", - Name: InclusiveMinimum, - Rule: 2, - Chain: nil, - } - require.Equal(t, validateInt(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(x), c, fmt.Sprintf("value must be greater than or equal to %v", c.Rule)).Error()) -} - -func TestValidateInt_InclusiveMinimumConstraintBoundary(t *testing.T) { - c := Constraint{ - Target: "str", - Name: InclusiveMinimum, - Rule: 1, - Chain: nil, - } - require.Nil(t, validateInt(reflect.ValueOf(1), c)) -} - -func TestValidateInt_MultipleOfWithoutError(t *testing.T) { - c := Constraint{ - Target: "str", - Name: MultipleOf, - Rule: 10, - Chain: nil, - } - require.Nil(t, validateInt(reflect.ValueOf(2300), c)) -} - -func TestValidateInt_MultipleOfWithError(t *testing.T) { - c := Constraint{ - Target: "str", - Name: MultipleOf, - Rule: 11, - Chain: nil, - } - require.Equal(t, validateInt(reflect.ValueOf(2300), c).Error(), - createError(reflect.ValueOf(2300), c, fmt.Sprintf("value must be a multiple of %v", c.Rule)).Error()) -} - -func TestValidatePointer_NilTrue(t *testing.T) { - var z *int - var x interface{} = z - c := Constraint{ - Target: "ptr", - Name: Null, - Rule: true, // Required property - Chain: nil, - } - require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(x), c, "value can not be null; required parameter").Error()) -} - -func TestValidatePointer_NilFalse(t *testing.T) { - var z *int - var x interface{} = z - c := Constraint{ - Target: "ptr", - Name: Null, - Rule: false, // not required property - Chain: nil, - } - require.Nil(t, validatePtr(reflect.ValueOf(x), c)) -} - -func TestValidatePointer_NilReadonlyValid(t *testing.T) { - var z *int - var x interface{} = z - c := Constraint{ - Target: "ptr", - Name: ReadOnly, - Rule: true, - Chain: nil, - } - require.Nil(t, validatePtr(reflect.ValueOf(x), c)) -} - -func TestValidatePointer_NilReadonlyInvalid(t *testing.T) { - z := 10 - var x interface{} = &z - c := Constraint{ - Target: "ptr", - Name: ReadOnly, - Rule: true, - Chain: nil, - } - require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(z), c, "readonly parameter; must send as nil or empty in request").Error()) -} - -func TestValidatePointer_IntValid(t *testing.T) { - z := 10 - var x interface{} = &z - c := Constraint{ - Target: "ptr", - Name: InclusiveMinimum, - Rule: 3, - Chain: nil, - } - require.Nil(t, validatePtr(reflect.ValueOf(x), c)) -} - -func TestValidatePointer_IntInvalid(t *testing.T) { - z := 10 - var x interface{} = &z - c := Constraint{ - Target: "ptr", - Name: Null, - Rule: true, - Chain: []Constraint{ - { - Target: "ptr", - Name: InclusiveMinimum, - Rule: 11, - Chain: nil, - }, - }, - } - require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(10), c.Chain[0], "value must be greater than or equal to 11").Error()) -} - -func TestValidatePointer_IntInvalidConstraint(t *testing.T) { - z := 10 - var x interface{} = &z - c := Constraint{ - Target: "ptr", - Name: Null, - Rule: true, - Chain: []Constraint{ - { - Target: "ptr", - Name: MaxItems, - Rule: 3, - Chain: nil, - }, - }, - } - require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(10), c.Chain[0], - fmt.Sprintf("constraint %v is not applicable for type integer", MaxItems)).Error()) -} - -func TestValidatePointer_ValidInt64(t *testing.T) { - z := int64(10) - var x interface{} = &z - c := Constraint{ - Target: "ptr", - Name: Null, - Rule: true, - Chain: []Constraint{ - { - Target: "ptr", - Name: InclusiveMinimum, - Rule: 3, - Chain: nil, - }, - }} - require.Nil(t, validatePtr(reflect.ValueOf(x), c)) -} - -func TestValidatePointer_InvalidConstraintInt64(t *testing.T) { - z := int64(10) - var x interface{} = &z - c := Constraint{ - Target: "ptr", - Name: Null, - Rule: true, - Chain: []Constraint{ - { - Target: "ptr", - Name: MaxItems, - Rule: 3, - Chain: nil, - }, - }, - } - require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(10), c.Chain[0], - fmt.Sprintf("constraint %v is not applicable for type integer", MaxItems)).Error()) -} - -func TestValidatePointer_ValidFloat(t *testing.T) { - z := 10.1 - var x interface{} = &z - c := Constraint{ - Target: "ptr", - Name: Null, - Rule: true, - Chain: []Constraint{ - { - Target: "ptr", - Name: InclusiveMinimum, - Rule: 3.0, - Chain: nil, - }}} - require.Nil(t, validatePtr(reflect.ValueOf(x), c)) -} - -func TestValidatePointer_InvalidFloat(t *testing.T) { - z := 10.1 - var x interface{} = &z - c := Constraint{ - Target: "ptr", - Name: Null, - Rule: true, - Chain: []Constraint{ - { - Target: "ptr", - Name: InclusiveMinimum, - Rule: 12.0, - Chain: nil, - }}, - } - require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(10.1), c.Chain[0], - "value must be greater than or equal to 12").Error()) -} - -func TestValidatePointer_InvalidConstraintFloat(t *testing.T) { - z := 10.1 - var x interface{} = &z - c := Constraint{ - Target: "ptr", - Name: Null, - Rule: true, - Chain: []Constraint{ - { - Target: "ptr", - Name: MaxItems, - Rule: 3.0, - Chain: nil, - }}, - } - require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(10.1), c.Chain[0], - fmt.Sprintf("constraint %v is not applicable for type float", MaxItems)).Error()) -} - -func TestValidatePointer_StringValid(t *testing.T) { - z := "hello" - var x interface{} = &z - c := Constraint{ - Target: "ptr", - Name: Null, - Rule: true, - Chain: []Constraint{ - { - Target: "ptr", - Name: Pattern, - Rule: "^[a-z]+$", - Chain: nil, - }}} - require.Nil(t, validatePtr(reflect.ValueOf(x), c)) -} - -func TestValidatePointer_StringInvalid(t *testing.T) { - z := "hello" - var x interface{} = &z - c := Constraint{ - Target: "ptr", - Name: Null, - Rule: true, - Chain: []Constraint{ - { - Target: "ptr", - Name: MaxLength, - Rule: 2, - Chain: nil, - }}} - require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf("hello"), c.Chain[0], - "value length must be less than or equal to 2").Error()) -} - -func TestValidatePointer_ArrayValid(t *testing.T) { - c := Constraint{ - Target: "ptr", - Name: Null, - Rule: true, - Chain: []Constraint{ - { - Target: "ptr", - Name: UniqueItems, - Rule: "true", - Chain: nil, - }}} - require.Nil(t, validatePtr(reflect.ValueOf(&[]string{"1", "2"}), c)) -} - -func TestValidatePointer_ArrayInvalid(t *testing.T) { - z := []string{"1", "2", "2"} - var x interface{} = &z - c := Constraint{ - Target: "ptr", - Name: Null, - Rule: true, - Chain: []Constraint{{ - Target: "ptr", - Name: UniqueItems, - Rule: true, - Chain: nil, - }}, - } - require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(z), c.Chain[0], - fmt.Sprintf("all items in parameter %q must be unique; got:%v", c.Target, z)).Error()) -} - -func TestValidatePointer_MapValid(t *testing.T) { - c := Constraint{ - Target: "ptr", - Name: Null, - Rule: true, - Chain: []Constraint{ - { - Target: "ptr", - Name: UniqueItems, - Rule: true, - Chain: nil, - }}} - require.Nil(t, validatePtr(reflect.ValueOf(&map[interface{}]string{1: "1", "1": "2"}), c)) -} - -func TestValidatePointer_MapInvalid(t *testing.T) { - z := map[interface{}]string{1: "1", "1": "2", 1.3: "2"} - var x interface{} = &z - c := Constraint{ - Target: "ptr", - Name: Null, - Rule: true, - Chain: []Constraint{{ - Target: "ptr", - Name: UniqueItems, - Rule: true, - Chain: nil, - }}, - } - require.Equal(t, strings.Contains(validatePtr(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("all items in parameter %q must be unique;", c.Target)), true) -} - -type Child struct { - I string -} -type Product struct { - C *Child - Str *string - Name string - Arr *[]string - M *map[string]string - Num *int32 -} - -type Sample struct { - M *map[string]*string - Name string -} - -func TestValidatePointer_StructWithError(t *testing.T) { - s := "hello" - var x interface{} = &Product{ - C: &Child{"100"}, - Str: &s, - Name: "Gopher", - } - c := Constraint{ - "p", Null, "True", - []Constraint{ - {"C", Null, true, - []Constraint{ - {"I", MaxLength, 2, nil}, - }}, - {"Str", MaxLength, 2, nil}, - {"Name", MaxLength, 5, nil}, - }, - } - require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf("100"), c.Chain[0].Chain[0], - "value length must be less than or equal to 2").Error()) -} - -func TestValidatePointer_WithNilStruct(t *testing.T) { - var p *Product - var x interface{} = p - c := Constraint{ - "p", Null, true, - []Constraint{ - {"C", Null, true, - []Constraint{ - {"I", Empty, true, - []Constraint{ - {"I", MaxLength, 5, nil}, - }}, - }}, - {"Str", MaxLength, 2, nil}, - {"Name", MaxLength, 5, nil}, - }, - } - require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(x), c, - fmt.Sprintf("value can not be null; required parameter")).Error()) -} - -func TestValidatePointer_StructWithNoError(t *testing.T) { - s := "hello" - var x interface{} = &Product{ - C: &Child{"100"}, - Str: &s, - Name: "Gopher", - } - c := Constraint{ - "p", Null, true, - []Constraint{ - {"C", Null, true, - []Constraint{ - {"I", Empty, true, - []Constraint{ - {"I", MaxLength, 5, nil}, - }}, - }}, - }, - } - require.Nil(t, validatePtr(reflect.ValueOf(x), c)) -} - -func TestValidateStruct_FieldNotExist(t *testing.T) { - s := "hello" - var x interface{} = Product{ - C: &Child{"100"}, - Str: &s, - Name: "Gopher", - } - c := Constraint{ - "C", Null, true, - []Constraint{ - {"Name", Empty, true, nil}, - }, - } - s = "Name" - require.Equal(t, validateStruct(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(Child{"100"}), c.Chain[0], - fmt.Sprintf("field %q doesn't exist", s)).Error()) -} - -func TestValidateStruct_WithChainConstraint(t *testing.T) { - s := "hello" - var x interface{} = Product{ - C: &Child{"100"}, - Str: &s, - Name: "Gopher", - } - c := Constraint{ - "C", Null, true, - []Constraint{ - {"I", Empty, true, - []Constraint{ - {"I", MaxLength, 2, nil}, - }}, - }, - } - require.Equal(t, validateStruct(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf("100"), c.Chain[0].Chain[0], "value length must be less than or equal to 2").Error()) -} - -func TestValidateStruct_WithoutChainConstraint(t *testing.T) { - s := "hello" - var x interface{} = Product{ - C: &Child{""}, - Str: &s, - Name: "Gopher", - } - c := Constraint{"C", Null, true, - []Constraint{ - {"I", Empty, true, nil}, // throw error for Empty - }} - require.Equal(t, validateStruct(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(""), c.Chain[0], "value can not be null or empty; required parameter").Error()) -} - -func TestValidateStruct_WithArrayNull(t *testing.T) { - s := "hello" - var x interface{} = Product{ - C: &Child{""}, - Str: &s, - Name: "Gopher", - Arr: nil, - } - c := Constraint{"Arr", Null, true, - []Constraint{ - {"Arr", MaxItems, 4, nil}, - {"Arr", MinItems, 2, nil}, - }, - } - require.Equal(t, validateStruct(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(x.(Product).Arr), c, "value can not be null; required parameter").Error()) -} - -func TestValidateStruct_WithArrayEmptyError(t *testing.T) { - // arr := []string{} - var x interface{} = Product{ - Arr: &[]string{}, - } - c := Constraint{ - "Arr", Null, true, - []Constraint{ - {"Arr", Empty, true, nil}, - {"Arr", MaxItems, 4, nil}, - {"Arr", MinItems, 2, nil}, - }} - - require.Equal(t, validateStruct(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(*(x.(Product).Arr)), c.Chain[0], - fmt.Sprintf("value can not be null or empty; required parameter")).Error()) -} - -func TestValidateStruct_WithArrayEmptyWithoutError(t *testing.T) { - var x interface{} = Product{ - Arr: &[]string{}, - } - c := Constraint{ - "Arr", Null, true, - []Constraint{ - {"Arr", Empty, false, nil}, - {"Arr", MaxItems, 4, nil}, - }, - } - require.Nil(t, validateStruct(reflect.ValueOf(x), c)) -} - -func TestValidateStruct_ArrayWithError(t *testing.T) { - arr := []string{"1", "1"} - var x interface{} = Product{ - Arr: &arr, - } - c := Constraint{ - "Arr", Null, true, - []Constraint{ - {"Arr", Empty, true, nil}, - {"Arr", MaxItems, 4, nil}, - {"Arr", UniqueItems, true, nil}, - }, - } - s := "Arr" - require.Equal(t, validateStruct(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(*(x.(Product).Arr)), c.Chain[2], - fmt.Sprintf("all items in parameter %q must be unique; got:%v", s, *(x.(Product).Arr))).Error()) -} - -func TestValidateStruct_MapWithError(t *testing.T) { - m := map[string]string{ - "a": "hello", - "b": "hello", - } - var x interface{} = Product{ - M: &m, - } - c := Constraint{ - "M", Null, true, - []Constraint{ - {"M", Empty, true, nil}, - {"M", MaxItems, 4, nil}, - {"M", UniqueItems, true, nil}, - }, - } - - s := "M" - require.Equal(t, strings.Contains(validateStruct(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("all items in parameter %q must be unique;", s)), true) -} - -func TestValidateStruct_MapWithNoError(t *testing.T) { - m := map[string]string{} - var x interface{} = Product{ - M: &m, - } - c := Constraint{ - "M", Null, true, - []Constraint{ - {"M", Empty, false, nil}, - {"M", MaxItems, 4, nil}, - }, - } - require.Nil(t, validateStruct(reflect.ValueOf(x), c)) -} - -func TestValidateStruct_MapNilNoError(t *testing.T) { - var m map[string]string - var x interface{} = Product{ - M: &m, - } - c := Constraint{ - "M", Null, false, - []Constraint{ - {"M", Empty, false, nil}, - {"M", MaxItems, 4, nil}, - }, - } - require.Nil(t, validateStruct(reflect.ValueOf(x), c)) -} - -func TestValidate_MapValidationWithError(t *testing.T) { - var x1 interface{} = &Product{ - Arr: &[]string{"1", "2"}, - M: &map[string]string{"a": "hello"}, - } - s := "hello" - var x2 interface{} = &Sample{ - M: &map[string]*string{"a": &s}, - } - v := []Validation{ - {x1, - []Constraint{{"x1", Null, true, - []Constraint{ - {"Arr", Null, true, - []Constraint{ - {"Arr", Empty, true, nil}, - {"Arr", MaxItems, 4, nil}, - {"Arr", UniqueItems, true, nil}, - }, - }, - {"M", Null, false, - []Constraint{ - {"M", Empty, false, nil}, - {"M", MinItems, 1, nil}, - {"M", UniqueItems, true, nil}, - }, - }, - }, - }}}, - {x2, - []Constraint{ - {"x2", Null, true, - []Constraint{ - {"M", Null, false, - []Constraint{ - {"M", Empty, false, nil}, - {"M", MinItems, 2, nil}, - {"M", UniqueItems, true, nil}, - }, - }, - }, - }, - {"Name", Empty, true, nil}, - }}, - } - - z := Validate(v).Error() - require.Equal(t, strings.Contains(z, "minimum item limit is 2; got: 1"), true) - require.Equal(t, strings.Contains(z, "MinItems"), true) -} - -func TestValidate_MapValidationWithoutError(t *testing.T) { - var x1 interface{} = &Product{ - Arr: &[]string{"1", "2"}, - M: &map[string]string{"a": "hello"}, - } - s := "hello" - var x2 interface{} = &Sample{ - M: &map[string]*string{"a": &s}, - } - v := []Validation{ - {x1, - []Constraint{{"x1", Null, true, - []Constraint{ - {"Arr", Null, true, - []Constraint{ - {"Arr", Empty, true, nil}, - {"Arr", MaxItems, 4, nil}, - {"Arr", UniqueItems, true, nil}, - }, - }, - {"M", Null, false, - []Constraint{ - {"M", Empty, false, nil}, - {"M", MinItems, 1, nil}, - {"M", UniqueItems, true, nil}, - {"M", Pattern, "^[a-z]+$", nil}, - }, - }, - }, - }}}, - {x2, - []Constraint{ - {"x2", Null, true, - []Constraint{ - {"M", Null, false, - []Constraint{ - {"M", Empty, false, nil}, - {"M", MinItems, 1, nil}, - {"M", UniqueItems, true, nil}, - {"M", Pattern, "^[a-z]+$", nil}, - }, - }, - }, - }, - {"Name", Empty, true, nil}, - }}, - } - require.Nil(t, Validate(v)) -} - -func TestValidate_UnknownType(t *testing.T) { - var c chan int - v := []Validation{ - {c, - []Constraint{{"c", Null, true, nil}}}, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(c), v[0].Constraints[0], - fmt.Sprintf("unknown type %v", reflect.ValueOf(c).Kind())).Error()) -} - -func TestValidate_example1(t *testing.T) { - var x1 interface{} = Product{ - Arr: &[]string{"1", "1"}, - M: &map[string]string{"a": "hello"}, - } - s := "hello" - var x2 interface{} = Sample{ - M: &map[string]*string{"a": &s}, - } - v := []Validation{ - {x1, - []Constraint{{"Arr", Null, true, - []Constraint{ - {"Arr", Empty, true, nil}, - {"Arr", MaxItems, 4, nil}, - {"Arr", UniqueItems, true, nil}, - }}, - {"M", Null, false, - []Constraint{ - {"M", Empty, false, nil}, - {"M", MinItems, 1, nil}, - {"M", UniqueItems, true, nil}, - }, - }, - }}, - {x2, - []Constraint{ - {"M", Null, false, - []Constraint{ - {"M", Empty, false, nil}, - {"M", MinItems, 1, nil}, - {"M", UniqueItems, true, nil}, - }, - }, - {"Name", Empty, true, nil}, - }}, - } - s = "Arr" - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf([]string{"1", "1"}), v[0].Constraints[0].Chain[2], - fmt.Sprintf("all items in parameter %q must be unique; got:%v", s, []string{"1", "1"})).Error()) -} - -func TestValidate_Int(t *testing.T) { - n := int32(100) - v := []Validation{ - {n, - []Constraint{ - {"n", MultipleOf, 10, nil}, - {"n", ExclusiveMinimum, 100, nil}, - }, - }, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(n), v[0].Constraints[1], - "value must be greater than 100").Error()) -} - -func TestValidate_IntPointer(t *testing.T) { - n := int32(100) - p := &n - v := []Validation{ - {p, - []Constraint{ - {"p", Null, true, []Constraint{ - {"p", ExclusiveMinimum, 100, nil}, - }}, - }, - }, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(n), v[0].Constraints[0].Chain[0], - "value must be greater than 100").Error()) - - // required parameter - p = nil - v = []Validation{ - {p, - []Constraint{ - {"p", Null, true, []Constraint{ - {"p", ExclusiveMinimum, 100, nil}, - }}, - }, - }, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(v[0].TargetValue), v[0].Constraints[0], - "value can not be null; required parameter").Error()) - - // Not required - p = nil - v = []Validation{ - {p, - []Constraint{ - {"p", Null, false, []Constraint{ - {"p", ExclusiveMinimum, 100, nil}, - }}, - }, - }, - } - require.Nil(t, Validate(v)) -} - -func TestValidate_IntStruct(t *testing.T) { - n := int32(100) - p := &Product{ - Num: &n, - } - - v := []Validation{ - {p, []Constraint{{"p", Null, true, - []Constraint{ - {"Num", Null, true, []Constraint{ - {"Num", ExclusiveMinimum, 100, nil}, - }}, - }, - }}}, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(n), v[0].Constraints[0].Chain[0].Chain[0], - "value must be greater than 100").Error()) - - // required parameter - p = &Product{} - v = []Validation{ - {p, []Constraint{{"p", Null, true, - []Constraint{ - {"p.Num", Null, true, []Constraint{ - {"p.Num", ExclusiveMinimum, 100, nil}, - }}, - }, - }}}, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(p.Num), v[0].Constraints[0].Chain[0], - "value can not be null; required parameter").Error()) - - // Not required - p = &Product{} - v = []Validation{ - {p, []Constraint{{"p", Null, true, - []Constraint{ - {"Num", Null, false, []Constraint{ - {"Num", ExclusiveMinimum, 100, nil}, - }}, - }, - }}}, - } - require.Nil(t, Validate(v)) - - // Parent not required - p = nil - v = []Validation{ - {p, []Constraint{{"p", Null, false, - []Constraint{ - {"Num", Null, false, []Constraint{ - {"Num", ExclusiveMinimum, 100, nil}, - }}, - }, - }}}, - } - require.Nil(t, Validate(v)) -} - -func TestValidate_String(t *testing.T) { - s := "hello" - v := []Validation{ - {s, - []Constraint{ - {"s", Empty, true, nil}, - {"s", Empty, true, - []Constraint{{"s", MaxLength, 3, nil}}}, - }, - }, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(s), v[0].Constraints[1].Chain[0], - "value length must be less than or equal to 3").Error()) - - // required parameter - s = "" - v = []Validation{ - {s, - []Constraint{ - {"s", Empty, true, nil}, - {"s", Empty, true, - []Constraint{{"s", MaxLength, 3, nil}}}, - }, - }, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(s), v[0].Constraints[1], - "value can not be null or empty; required parameter").Error()) - - // not required parameter - s = "" - v = []Validation{ - {s, - []Constraint{ - {"s", Empty, false, nil}, - {"s", Empty, false, - []Constraint{{"s", MaxLength, 3, nil}}}, - }, - }, - } - require.Nil(t, Validate(v)) -} - -func TestValidate_StringStruct(t *testing.T) { - s := "hello" - p := &Product{ - Str: &s, - } - - v := []Validation{ - {p, []Constraint{{"p", Null, true, - []Constraint{ - {"p.Str", Null, true, []Constraint{ - {"p.Str", Empty, true, nil}, - {"p.Str", MaxLength, 3, nil}, - }}, - }, - }}}, - } - // e := ValidationError{ - // Constraint: MaxLength, - // Target: "Str", - // TargetValue: s, - // Details: fmt.Sprintf("value length must be less than 3", s), - // } - // if z := Validate(v); !reflect.DeepEqual(e, z) { - // t.Fatalf("autorest/validation: Validate failed to return error \nexpect: %v\ngot: %v", e, z) - // } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(s), v[0].Constraints[0].Chain[0].Chain[1], - "value length must be less than or equal to 3").Error()) - - // required parameter - can't be Empty - s = "" - p = &Product{ - Str: &s, - } - v = []Validation{ - {p, []Constraint{{"p", Null, true, - []Constraint{ - {"Str", Null, true, []Constraint{ - {"Str", Empty, true, nil}, - {"Str", MaxLength, 3, nil}, - }}, - }, - }}}, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(s), v[0].Constraints[0].Chain[0].Chain[0], - "value can not be null or empty; required parameter").Error()) - - // required parameter - can't be null - p = &Product{} - v = []Validation{ - {p, []Constraint{{"p", Null, true, - []Constraint{ - {"p.Str", Null, true, []Constraint{ - {"p.Str", Empty, true, nil}, - {"p.Str", MaxLength, 3, nil}, - }}, - }, - }}}, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(p.Str), v[0].Constraints[0].Chain[0], - "value can not be null; required parameter").Error()) - - // Not required - p = &Product{} - v = []Validation{ - {p, []Constraint{{"p", Null, true, - []Constraint{ - {"Str", Null, false, []Constraint{ - {"Str", Empty, true, nil}, - {"Str", MaxLength, 3, nil}, - }}, - }, - }}}, - } - require.Nil(t, Validate(v)) - - // Parent not required - p = nil - v = []Validation{ - {p, []Constraint{{"p", Null, false, - []Constraint{ - {"Str", Null, true, []Constraint{ - {"Str", Empty, true, nil}, - {"Str", MaxLength, 3, nil}, - }}, - }, - }}}, - } - require.Nil(t, Validate(v)) -} - -func TestValidate_Array(t *testing.T) { - s := []string{"hello"} - v := []Validation{ - {s, - []Constraint{ - {"s", Null, true, - []Constraint{ - {"s", Empty, true, nil}, - {"s", MinItems, 2, nil}, - }}, - }, - }, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(s), v[0].Constraints[0].Chain[1], - fmt.Sprintf("minimum item limit is 2; got: %v", len(s))).Error()) - - // Empty array - v = []Validation{ - {[]string{}, - []Constraint{ - {"s", Null, true, - []Constraint{ - {"s", Empty, true, nil}, - {"s", MinItems, 2, nil}}}, - }, - }, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf([]string{}), v[0].Constraints[0].Chain[0], - "value can not be null or empty; required parameter").Error()) - - // null array - var s1 []string - v = []Validation{ - {s1, - []Constraint{ - {"s1", Null, true, - []Constraint{ - {"s1", Empty, true, nil}, - {"s1", MinItems, 2, nil}}}, - }, - }, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(s1), v[0].Constraints[0], - "value can not be null; required parameter").Error()) - - // not required parameter - v = []Validation{ - {s1, - []Constraint{ - {"s1", Null, false, - []Constraint{ - {"s1", Empty, true, nil}, - {"s1", MinItems, 2, nil}}}, - }, - }, - } - require.Nil(t, Validate(v)) -} - -func TestValidate_ArrayPointer(t *testing.T) { - s := []string{"hello"} - v := []Validation{ - {&s, - []Constraint{ - {"s", Null, true, - []Constraint{ - {"s", Empty, true, nil}, - {"s", MinItems, 2, nil}, - }}, - }, - }, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(s), v[0].Constraints[0].Chain[1], - fmt.Sprintf("minimum item limit is 2; got: %v", len(s))).Error()) - - // Empty array - v = []Validation{ - {&[]string{}, - []Constraint{ - {"s", Null, true, - []Constraint{ - {"s", Empty, true, nil}, - {"s", MinItems, 2, nil}}}, - }, - }, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf([]string{}), v[0].Constraints[0].Chain[0], - "value can not be null or empty; required parameter").Error()) - - // null array - var s1 *[]string - v = []Validation{ - {s1, - []Constraint{ - {"s1", Null, true, - []Constraint{ - {"s1", Empty, true, nil}, - {"s1", MinItems, 2, nil}}}, - }, - }, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(s1), v[0].Constraints[0], - "value can not be null; required parameter").Error()) - - // not required parameter - v = []Validation{ - {s1, - []Constraint{ - {"s1", Null, false, - []Constraint{ - {"s1", Empty, true, nil}, - {"s1", MinItems, 2, nil}}}, - }, - }, - } - require.Nil(t, Validate(v)) -} - -func TestValidate_ArrayInStruct(t *testing.T) { - s := []string{"hello"} - p := &Product{ - Arr: &s, - } - - v := []Validation{ - {p, []Constraint{{"p", Null, true, - []Constraint{ - {"p.Arr", Null, true, []Constraint{ - {"p.Arr", Empty, true, nil}, - {"p.Arr", MinItems, 2, nil}, - }}, - }, - }}}, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(s), v[0].Constraints[0].Chain[0].Chain[1], - fmt.Sprintf("minimum item limit is 2; got: %v", len(s))).Error()) - - // required parameter - can't be Empty - p = &Product{ - Arr: &[]string{}, - } - v = []Validation{ - {p, []Constraint{{"p", Null, true, - []Constraint{ - {"p.Arr", Null, true, []Constraint{ - {"p.Arr", Empty, true, nil}, - {"p.Arr", MinItems, 2, nil}, - }}, - }, - }}}, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf([]string{}), v[0].Constraints[0].Chain[0].Chain[0], - "value can not be null or empty; required parameter").Error()) - - // required parameter - can't be null - p = &Product{} - v = []Validation{ - {p, []Constraint{{"p", Null, true, - []Constraint{ - {"p.Arr", Null, true, []Constraint{ - {"p.Arr", Empty, true, nil}, - {"p.Arr", MinItems, 2, nil}, - }}, - }, - }}}, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(p.Arr), v[0].Constraints[0].Chain[0], - "value can not be null; required parameter").Error()) - - // Not required - v = []Validation{ - {&Product{}, []Constraint{{"p", Null, true, - []Constraint{ - {"Arr", Null, false, []Constraint{ - {"Arr", Empty, true, nil}, - {"Arr", MinItems, 2, nil}, - }}, - }, - }}}, - } - require.Nil(t, Validate(v)) - - // Parent not required - p = nil - v = []Validation{ - {p, []Constraint{{"p", Null, false, - []Constraint{ - {"Arr", Null, true, []Constraint{ - {"Arr", Empty, true, nil}, - {"Arr", MinItems, 2, nil}, - }}, - }, - }}}, - } - require.Nil(t, Validate(v)) -} - -func TestValidate_StructInStruct(t *testing.T) { - p := &Product{ - C: &Child{I: "hello"}, - } - v := []Validation{ - {p, []Constraint{{"p", Null, true, - []Constraint{{"C", Null, true, - []Constraint{{"I", MinLength, 7, nil}}}, - }, - }}}, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(p.C.I), v[0].Constraints[0].Chain[0].Chain[0], - "value length must be greater than or equal to 7").Error()) - - // required parameter - can't be Empty - p = &Product{ - C: &Child{I: ""}, - } - - v = []Validation{ - {p, []Constraint{{"p", Null, true, - []Constraint{{"C", Null, true, - []Constraint{{"I", Empty, true, nil}}}, - }, - }}}, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(p.C.I), v[0].Constraints[0].Chain[0].Chain[0], - "value can not be null or empty; required parameter").Error()) - - // required parameter - can't be null - p = &Product{} - v = []Validation{ - {p, []Constraint{{"p", Null, true, - []Constraint{{"C", Null, true, - []Constraint{{"I", Empty, true, nil}}}, - }, - }}}, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(p.C), v[0].Constraints[0].Chain[0], - "value can not be null; required parameter").Error()) - - // Not required - v = []Validation{ - {&Product{}, []Constraint{{"p", Null, true, - []Constraint{{"p.C", Null, false, - []Constraint{{"p.C.I", Empty, true, nil}}}, - }, - }}}, - } - require.Nil(t, Validate(v)) - - // Parent not required - p = nil - v = []Validation{ - {p, []Constraint{{"p", Null, false, - []Constraint{{"p.C", Null, false, - []Constraint{{"p.C.I", Empty, true, nil}}}, - }, - }}}, - } - require.Nil(t, Validate(v)) -} - -func TestNewError(t *testing.T) { - p := &Product{} - v := []Validation{ - {p, []Constraint{{"p", Null, true, - []Constraint{{"p.C", Null, true, - []Constraint{{"p.C.I", Empty, true, nil}}}, - }, - }}}, - } - err := createError(reflect.ValueOf(p.C), v[0].Constraints[0].Chain[0], "value can not be null; required parameter") - z := fmt.Sprintf("batch.AccountClient#Create: Invalid input: %s", - err.Error()) - require.Equal(t, NewError("batch.AccountClient", "Create", err.Error()).Error(), z) -} - -func TestNewErrorWithValidationError(t *testing.T) { - p := &Product{} - v := []Validation{ - {p, []Constraint{{"p", Null, true, - []Constraint{{"p.C", Null, true, - []Constraint{{"p.C.I", Empty, true, nil}}}, - }, - }}}, - } - err := createError(reflect.ValueOf(p.C), v[0].Constraints[0].Chain[0], "value can not be null; required parameter") - z := fmt.Sprintf("batch.AccountClient#Create: Invalid input: %s", - err.Error()) - valError := NewErrorWithValidationError(err, "batch.AccountClient", "Create") - require.IsType(t, valError, Error{}) - require.Equal(t, valError.Error(), z) -} diff --git a/vendor/github.com/Azure/go-autorest/logger/logger_test.go b/vendor/github.com/Azure/go-autorest/logger/logger_test.go deleted file mode 100644 index 5838b252..00000000 --- a/vendor/github.com/Azure/go-autorest/logger/logger_test.go +++ /dev/null @@ -1,185 +0,0 @@ -package logger - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "fmt" - "io/ioutil" - "net/http" - "os" - "path" - "regexp" - "strings" - "testing" -) - -func TestNilLogger(t *testing.T) { - // verify no crash with no logging - Instance.WriteRequest(nil, Filter{}) -} - -const ( - reqURL = "https://fakething/dot/com" - reqHeaderKey = "x-header" - reqHeaderVal = "value" - reqBody = "the request body" - respHeaderKey = "response-header" - respHeaderVal = "something" - respBody = "the response body" - logFileTimeStampRegex = `\(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{7}(-\d{2}:\d{2}|Z)\)` -) - -func TestLogReqRespNoBody(t *testing.T) { - err := os.Setenv("AZURE_GO_SDK_LOG_LEVEL", "info") - if err != nil { - t.Fatalf("failed to set log level: %v", err) - } - lf := path.Join(os.TempDir(), "testloggingbasic.log") - err = os.Setenv("AZURE_GO_SDK_LOG_FILE", lf) - if err != nil { - t.Fatalf("failed to set log file: %v", err) - } - initDefaultLogger() - if Level() != LogInfo { - t.Fatalf("wrong log level: %d", Level()) - } - // create mock request and response for logging - req, err := http.NewRequest(http.MethodGet, reqURL, nil) - if err != nil { - t.Fatalf("failed to create mock request: %v", err) - } - req.Header.Add(reqHeaderKey, reqHeaderVal) - Instance.WriteRequest(req, Filter{}) - resp := &http.Response{ - Status: "200 OK", - StatusCode: 200, - Proto: "HTTP/1.0", - ProtoMajor: 1, - ProtoMinor: 0, - Request: req, - Header: http.Header{}, - } - resp.Header.Add(respHeaderKey, respHeaderVal) - Instance.WriteResponse(resp, Filter{}) - if fl, ok := Instance.(fileLogger); ok { - fl.logFile.Close() - } else { - t.Fatal("expected Instance to be fileLogger") - } - // parse log file to ensure contents match - b, err := ioutil.ReadFile(lf) - if err != nil { - t.Fatalf("failed to read log file: %v", err) - } - parts := strings.Split(string(b), "\n") - reqMatch := fmt.Sprintf("%s INFO: REQUEST: %s %s", logFileTimeStampRegex, req.Method, req.URL.String()) - respMatch := fmt.Sprintf("%s INFO: RESPONSE: %d %s", logFileTimeStampRegex, resp.StatusCode, resp.Request.URL.String()) - if !matchRegex(t, reqMatch, parts[0]) { - t.Fatalf("request header doesn't match: %s", parts[0]) - } - if !matchRegex(t, fmt.Sprintf("(?i)%s: %s", reqHeaderKey, reqHeaderVal), parts[1]) { - t.Fatalf("request header entry doesn't match: %s", parts[1]) - } - if !matchRegex(t, respMatch, parts[2]) { - t.Fatalf("response header doesn't match: %s", parts[2]) - } - if !matchRegex(t, fmt.Sprintf("(?i)%s: %s", respHeaderKey, respHeaderVal), parts[3]) { - t.Fatalf("response header value doesn't match: %s", parts[3]) - } - // disable logging - err = os.Setenv("AZURE_GO_SDK_LOG_LEVEL", "") - if err != nil { - t.Fatalf("failed to clear log level: %v", err) - } -} - -func TestLogReqRespWithBody(t *testing.T) { - err := os.Setenv("AZURE_GO_SDK_LOG_LEVEL", "debug") - if err != nil { - t.Fatalf("failed to set log level: %v", err) - } - lf := path.Join(os.TempDir(), "testloggingfull.log") - err = os.Setenv("AZURE_GO_SDK_LOG_FILE", lf) - if err != nil { - t.Fatalf("failed to set log file: %v", err) - } - initDefaultLogger() - if Level() != LogDebug { - t.Fatalf("wrong log level: %d", Level()) - } - // create mock request and response for logging - req, err := http.NewRequest(http.MethodGet, reqURL, strings.NewReader(reqBody)) - if err != nil { - t.Fatalf("failed to create mock request: %v", err) - } - req.Header.Add(reqHeaderKey, reqHeaderVal) - Instance.WriteRequest(req, Filter{}) - resp := &http.Response{ - Status: "200 OK", - StatusCode: 200, - Proto: "HTTP/1.0", - ProtoMajor: 1, - ProtoMinor: 0, - Request: req, - Header: http.Header{}, - Body: ioutil.NopCloser(strings.NewReader(respBody)), - } - resp.Header.Add(respHeaderKey, respHeaderVal) - Instance.WriteResponse(resp, Filter{}) - if fl, ok := Instance.(fileLogger); ok { - fl.logFile.Close() - } else { - t.Fatal("expected Instance to be fileLogger") - } - // parse log file to ensure contents match - b, err := ioutil.ReadFile(lf) - if err != nil { - t.Fatalf("failed to read log file: %v", err) - } - parts := strings.Split(string(b), "\n") - reqMatch := fmt.Sprintf("%s INFO: REQUEST: %s %s", logFileTimeStampRegex, req.Method, req.URL.String()) - respMatch := fmt.Sprintf("%s INFO: RESPONSE: %d %s", logFileTimeStampRegex, resp.StatusCode, resp.Request.URL.String()) - if !matchRegex(t, reqMatch, parts[0]) { - t.Fatalf("request header doesn't match: %s", parts[0]) - } - if !matchRegex(t, fmt.Sprintf("(?i)%s: %s", reqHeaderKey, reqHeaderVal), parts[1]) { - t.Fatalf("request header value doesn't match: %s", parts[1]) - } - if !matchRegex(t, reqBody, parts[2]) { - t.Fatalf("request body doesn't match: %s", parts[2]) - } - if !matchRegex(t, respMatch, parts[3]) { - t.Fatalf("response header doesn't match: %s", parts[3]) - } - if !matchRegex(t, fmt.Sprintf("(?i)%s: %s", respHeaderKey, respHeaderVal), parts[4]) { - t.Fatalf("response header value doesn't match: %s", parts[4]) - } - if !matchRegex(t, respBody, parts[5]) { - t.Fatalf("response body doesn't match: %s", parts[5]) - } - // disable logging - err = os.Setenv("AZURE_GO_SDK_LOG_LEVEL", "") - if err != nil { - t.Fatalf("failed to clear log level: %v", err) - } -} - -func matchRegex(t *testing.T, pattern, s string) bool { - match, err := regexp.MatchString(pattern, s) - if err != nil { - t.Fatalf("regexp failure: %v", err) - } - return match -} diff --git a/vendor/github.com/Azure/go-autorest/tracing/tracing_test.go b/vendor/github.com/Azure/go-autorest/tracing/tracing_test.go deleted file mode 100644 index 66f6ae59..00000000 --- a/vendor/github.com/Azure/go-autorest/tracing/tracing_test.go +++ /dev/null @@ -1,155 +0,0 @@ -package tracing - -// Copyright 2018 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "context" - "fmt" - "net/http" - "os" - "reflect" - "testing" - - "contrib.go.opencensus.io/exporter/ocagent" - "go.opencensus.io/stats/view" - "go.opencensus.io/trace" -) - -func TestNoTracingByDefault(t *testing.T) { - if expected, got := false, IsEnabled(); expected != got { - t.Fatalf("By default expected %t, got %t", expected, got) - } - - if sampler == nil { - t.Fatal("By default expected non nil sampler") - } - - if Transport.GetStartOptions(&http.Request{}).Sampler == nil { - t.Fatalf("By default expected configured Sampler to be non-nil") - } - - for n := range views { - v := view.Find(n) - if v != nil { - t.Fatalf("By default expected no registered views, found %s", v.Name) - } - } -} - -func TestEnableTracing(t *testing.T) { - err := Enable() - - if err != nil { - t.Fatalf("Enable failed, got error %v", err) - } - if !IsEnabled() { - t.Fatalf("Enable failed, IsEnabled() is %t", IsEnabled()) - } - if sampler != nil { - t.Fatalf("Enable failed, expected nil sampler, got %v", sampler) - } - - if Transport.GetStartOptions(&http.Request{}).Sampler != nil { - t.Fatalf("Enable failed, expected Transport.GetStartOptions.Sampler to be nil") - } - - for n, v := range views { - fv := view.Find(n) - if fv == nil || !reflect.DeepEqual(v, fv) { - t.Fatalf("Enable failed, view %s was not registered", n) - } - } -} - -func TestTracingByEnv(t *testing.T) { - os.Setenv("AZURE_SDK_TRACING_ENABLED", "") - enableFromEnv() - if !IsEnabled() { - t.Fatalf("Enable failed, IsEnabled() is %t", IsEnabled()) - } - if sampler != nil { - t.Fatalf("Enable failed, expected nil sampler, got %v", sampler) - } - - if Transport.GetStartOptions(&http.Request{}).Sampler != nil { - t.Fatalf("Enable failed, expected Transport.GetStartOptions.Sampler to be nil") - } - - for n, v := range views { - fv := view.Find(n) - if fv == nil || !reflect.DeepEqual(v, fv) { - t.Fatalf("Enable failed, view %s was not registered", n) - } - } -} - -func TestEnableTracingWithAIError(t *testing.T) { - agentEndpoint := fmt.Sprintf("%s:%d", ocagent.DefaultAgentHost, ocagent.DefaultAgentPort) - err := EnableWithAIForwarding(agentEndpoint) - if !IsEnabled() { - t.Fatalf("Enable failed, IsEnabled() is %t", IsEnabled()) - } - if sampler != nil { - t.Fatalf("Enable failed, expected nil sampler, got %v", sampler) - } - - if Transport.GetStartOptions(&http.Request{}).Sampler != nil { - t.Fatalf("Enable failed, expected Transport.GetStartOptions.Sampler to be nil") - } - - for n, v := range views { - fv := view.Find(n) - if fv == nil || !reflect.DeepEqual(v, fv) { - t.Fatalf("Enable failed, view %s was not registered", n) - } - } - - if err == nil { - t.Fatal("Expected error on no agent running, got nil") - } -} - -func TestDisableTracing(t *testing.T) { - Enable() - Disable() - if expected, got := false, IsEnabled(); expected != got { - t.Fatalf("By default expected %t, got %t", expected, got) - } - - if sampler == nil { - t.Fatal("By default expected non nil sampler") - } - - if Transport.GetStartOptions(&http.Request{}).Sampler == nil { - t.Fatalf("By default expected configured Sampler to be non-nil") - } - - for n := range views { - v := view.Find(n) - if v != nil { - t.Fatalf("By default expected no registered views, found %s", v.Name) - } - } -} - -func TestStartSpan(t *testing.T) { - ctx := StartSpan(context.Background(), "testSpan") - defer EndSpan(ctx, 200, nil) - - span := trace.FromContext(ctx) - if span == nil { - t.Fatal("StartSpan failed, expected non-nil span") - } -} diff --git a/vendor/github.com/census-instrumentation/opencensus-proto/CONTRIBUTING.md b/vendor/github.com/census-instrumentation/opencensus-proto/CONTRIBUTING.md deleted file mode 100644 index f6a2112b..00000000 --- a/vendor/github.com/census-instrumentation/opencensus-proto/CONTRIBUTING.md +++ /dev/null @@ -1,26 +0,0 @@ -# How to submit a bug report - -If you received an error message, please include it and any exceptions. - -We commonly need to know which language you are using (e.g. Java) and what -platform you are on: - * Operating system (i.e., ```uname -a```) - -# How to contribute - -We definitely welcome patches and contributions to Census! Here are some -guideline and information about how to do so. - -## Before getting started - -In order to protect both you and ourselves, you will need to sign the -[Contributor License Agreement](https://cla.developers.google.com/clas). - -We follow the [Google Proto Style Guide]( -https://developers.google.com/protocol-buffers/docs/style). - -## Proposing changes - -Make sure that `bazel build :all` completes successfully without any new warnings. -Then create a Pull Request with your changes. When the changes are accepted, they -will be merged or cherry-picked by a Census core developer. diff --git a/vendor/github.com/census-instrumentation/opencensus-proto/README.md b/vendor/github.com/census-instrumentation/opencensus-proto/README.md deleted file mode 100644 index 372f5f54..00000000 --- a/vendor/github.com/census-instrumentation/opencensus-proto/README.md +++ /dev/null @@ -1,80 +0,0 @@ -OpenCensus Proto - Language Independent Interface Types For OpenCensus -=============================================================== -[![Build Status][travis-image]][travis-url] -[![Maven Central][maven-image]][maven-url] - -Census provides a framework to define and collect stats against metrics and to -break those stats down across user-defined dimensions. - -The Census framework is natively available in many languages (e.g. C++, Go, -and Java). The API interface types are defined using protos to ensure -consistency and interoperability for the different implementations. - -## Quickstart - -### Install to Go - -```bash -$ go get -u github.com/census-instrumentation/opencensus-proto -``` - -In most cases you should depend on the gen-go files directly. If you are -building with Bazel, there are also go_proto_library build rules available. -See [PR/132](https://github.com/census-instrumentation/opencensus-proto/pull/132) -for details. However, please note that Bazel doesn't generate the final -artifacts. - -### Add the dependencies to your Java project - -For Maven add to `pom.xml`: -```xml - - io.opencensus - opencensus-proto - 0.0.2 - -``` - -For Gradle add to dependencies: -```gradle -compile 'io.opencensus:opencensus-proto:0.0.2' -``` - -[travis-image]: https://travis-ci.org/census-instrumentation/opencensus-proto.svg?branch=master -[travis-url]: https://travis-ci.org/census-instrumentation/opencensus-proto -[maven-image]: https://maven-badges.herokuapp.com/maven-central/io.opencensus/opencensus-proto/badge.svg -[maven-url]: https://maven-badges.herokuapp.com/maven-central/io.opencensus/opencensus-proto - -### Add the dependencies to Bazel project - -In WORKSPACE, add: -``` -git_repository( - name = "io_opencensus_proto", - strip_prefix = "src", - tag = "v0.0.2", # CURRENT_OPENCENSUS_PROTO_VERSION - remote = "https://github.com/census-instrumentation/opencensus-proto", -) -``` -or - -``` -http_archive( - name = "io_opencensus_proto", - strip_prefix = "opencensus-proto-master/src", - urls = ["https://github.com/census-instrumentation/opencensus-proto/archive/master.zip"], -) -``` - -In BUILD.bazel: -```bazel -proto_library( - name = "foo_proto", - srcs = ["foo.proto"], - deps = [ - "@io_opencensus_proto//opencensus/proto/metrics/v1:metrics_proto", - "@io_opencensus_proto//opencensus/proto/trace/v1:trace_proto", - # etc. - ], -) -``` diff --git a/vendor/github.com/census-instrumentation/opencensus-proto/RELEASING.md b/vendor/github.com/census-instrumentation/opencensus-proto/RELEASING.md deleted file mode 100644 index 0268ffc3..00000000 --- a/vendor/github.com/census-instrumentation/opencensus-proto/RELEASING.md +++ /dev/null @@ -1,190 +0,0 @@ -# How to Create a Release of OpenCensus Proto (for Maintainers Only) - -## Build Environments - -We re-generate gen-go files and deploy jars to Maven Central under the following systems: - -- Ubuntu 14.04 - -Other systems may also work, but we haven't verified them. - -## Release Go files - -To generate the Go files from protos, you'll need to install protoc and protoc-gen-go plugin first. -Follow the instructions [here](http://google.github.io/proto-lens/installing-protoc.html) and -[here](https://github.com/golang/protobuf#installation). - -Then run the following commands to re-generate the gen-go files: - -```bash -$ cd $(go env GOPATH)/src/github.com/census-instrumentation/opencensus-proto -$ git checkout -b update-gen-go -$ rm -rf gen-go -$ cd src -$ ./mkgogen.sh -$ git add -A -$ git commit -m "Update gen-go files." -``` - -Go through PR review and merge the changes to GitHub. - -## Tagging the Release - -Our release branches follow the naming convention of `v..x`, while the tags include the -patch version `v..`. For example, the same branch `v0.4.x` would be used to create -all `v0.4` tags (e.g. `v0.4.0`, `v0.4.1`). - -In this section upstream repository refers to the main opencensus-proto github -repository. - -Before any push to the upstream repository you need to create a [personal access -token](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/). - -1. Create the release branch and push it to GitHub: - - ```bash - $ MAJOR=0 MINOR=4 PATCH=0 # Set appropriately for new release - $ VERSION_FILES=( - build.gradle - pom.xml - ) - $ git checkout -b v$MAJOR.$MINOR.x master - $ git push upstream v$MAJOR.$MINOR.x - ``` - -2. Enable branch protection for the new branch, if you have admin access. - Otherwise, let someone with admin access know that there is a new release - branch. - - - Open the branch protection settings for the new branch, by following - [Github's instructions](https://help.github.com/articles/configuring-protected-branches/). - - Copy the settings from a previous branch, i.e., check - - `Protect this branch` - - `Require pull request reviews before merging` - - `Require status checks to pass before merging` - - `Include administrators` - - Enable the following required status checks: - - `cla/google` - - `continuous-integration/travis-ci` - - Uncheck everything else. - - Click "Save changes". - -3. For `master` branch: - - - Change root build files to the next minor snapshot (e.g. - `0.5.0-SNAPSHOT`). - - ```bash - $ git checkout -b bump-version master - # Change version to next minor (and keep -SNAPSHOT) - $ sed -i 's/[0-9]\+\.[0-9]\+\.[0-9]\+\(.*CURRENT_OPENCENSUS_PROTO_VERSION\)/'$MAJOR.$((MINOR+1)).0'\1/' \ - "${VERSION_FILES[@]}" - $ ./gradlew build - $ git commit -a -m "Start $MAJOR.$((MINOR+1)).0 development cycle" - ``` - - - Go through PR review and push the master branch to GitHub: - - ```bash - $ git checkout master - $ git merge --ff-only bump-version - $ git push upstream master - ``` - -4. For `vMajor.Minor.x` branch: - - - Change root build files to remove "-SNAPSHOT" for the next release - version (e.g. `0.4.0`). Commit the result and make a tag: - - ```bash - $ git checkout -b release v$MAJOR.$MINOR.x - # Change version to remove -SNAPSHOT - $ sed -i 's/-SNAPSHOT\(.*CURRENT_OPENCENSUS_PROTO_VERSION\)/\1/' "${VERSION_FILES[@]}" - $ ./gradlew build - $ git commit -a -m "Bump version to $MAJOR.$MINOR.$PATCH" - $ git tag -a v$MAJOR.$MINOR.$PATCH -m "Version $MAJOR.$MINOR.$PATCH" - ``` - - - Change root build files to the next snapshot version (e.g. - `0.4.1-SNAPSHOT`). Commit the result: - - ```bash - # Change version to next patch and add -SNAPSHOT - $ sed -i 's/[0-9]\+\.[0-9]\+\.[0-9]\+\(.*CURRENT_OPENCENSUS_PROTO_VERSION\)/'$MAJOR.$MINOR.$((PATCH+1))-SNAPSHOT'\1/' \ - "${VERSION_FILES[@]}" - $ ./gradlew build - $ git commit -a -m "Bump version to $MAJOR.$MINOR.$((PATCH+1))-SNAPSHOT" - ``` - - - Go through PR review and push the release tag and updated release branch - to GitHub: - - ```bash - $ git checkout v$MAJOR.$MINOR.x - $ git merge --ff-only release - $ git push upstream v$MAJOR.$MINOR.$PATCH - $ git push upstream v$MAJOR.$MINOR.x - ``` - -## Release Java Jar - -Deployment to Maven Central (or the snapshot repo) is for all of the artifacts -from the project. - -### Prerequisites - -If you haven't done already, please follow the instructions -[here](https://github.com/census-instrumentation/opencensus-java/blob/master/RELEASING.md#prerequisites) -to set up the OSSRH (OSS Repository Hosting) account and signing keys. This is required for releasing -to Maven Central. - -### Branch - -Before building/deploying, be sure to switch to the appropriate tag. The tag -must reference a commit that has been pushed to the main repository, i.e., has -gone through code review. For the current release use: - -```bash -$ git checkout -b v$MAJOR.$MINOR.$PATCH tags/v$MAJOR.$MINOR.$PATCH -``` - -### Initial Deployment - -The following command will build the whole project and upload it to Maven -Central. Parallel building [is not safe during -uploadArchives](https://issues.gradle.org/browse/GRADLE-3420). - -```bash -$ ./gradlew clean build && ./gradlew -Dorg.gradle.parallel=false uploadArchives -``` - -If the version has the `-SNAPSHOT` suffix, the artifacts will automatically go -to the snapshot repository. Otherwise it's a release deployment and the -artifacts will go to a staging repository. - -When deploying a Release, the deployment will create [a new staging -repository](https://oss.sonatype.org/#stagingRepositories). You'll need to look -up the ID in the OSSRH UI (usually in the form of `opencensus-*`). - -### Releasing on Maven Central - -Once all of the artifacts have been pushed to the staging repository, the -repository must first be `closed`, which will trigger several sanity checks on -the repository. If this completes successfully, the repository can then be -`released`, which will begin the process of pushing the new artifacts to Maven -Central (the staging repository will be destroyed in the process). You can see -the complete process for releasing to Maven Central on the [OSSRH -site](http://central.sonatype.org/pages/releasing-the-deployment.html). - -## Announcement - -Once deployment is done, go to Github [release -page](https://github.com/census-instrumentation/opencensus-proto/releases), press -`Draft a new release` to write release notes about the new release. - -You can use `git log upstream/v$MAJOR.$((MINOR-1)).x..upstream/v$MAJOR.$MINOR.x --graph --first-parent` -or the Github [compare tool](https://github.com/census-instrumentation/opencensus-proto/compare/) -to view a summary of all commits since last release as a reference. - -Please pick major or important user-visible changes only. diff --git a/vendor/github.com/census-instrumentation/opencensus-proto/build.gradle b/vendor/github.com/census-instrumentation/opencensus-proto/build.gradle deleted file mode 100644 index 8b996605..00000000 --- a/vendor/github.com/census-instrumentation/opencensus-proto/build.gradle +++ /dev/null @@ -1,170 +0,0 @@ -description = 'Opencensus Proto' - -apply plugin: 'idea' -apply plugin: 'java' -apply plugin: 'com.google.protobuf' -apply plugin: 'maven' -apply plugin: "signing" - -group = "io.opencensus" -version = "0.1.0" // CURRENT_OPENCENSUS_PROTO_VERSION - -sourceCompatibility = 1.6 -targetCompatibility = 1.6 - -repositories { - maven { url "https://plugins.gradle.org/m2/" } -} - -jar.manifest { - attributes('Implementation-Title': name, - 'Implementation-Version': version, - 'Built-By': System.getProperty('user.name'), - 'Built-JDK': System.getProperty('java.version'), - 'Source-Compatibility': sourceCompatibility, - 'Target-Compatibility': targetCompatibility) -} - -def protobufVersion = '3.5.1' -def protocVersion = '3.5.1' -def grpcVersion = "1.14.0" // CURRENT_GRPC_VERSION - -buildscript { - repositories { - maven { url "https://plugins.gradle.org/m2/" } - } - dependencies { - classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.6" - } -} - -sourceSets { - main { - proto { - srcDir 'src' - } - } -} - -dependencies { - compile "com.google.protobuf:protobuf-java:${protobufVersion}", - "io.grpc:grpc-protobuf:${grpcVersion}", - "io.grpc:grpc-stub:${grpcVersion}" - - compileOnly "javax.annotation:javax.annotation-api:1.2" -} - -protobuf { - protoc { - // The artifact spec for the Protobuf Compiler - artifact = "com.google.protobuf:protoc:${protocVersion}" - } - plugins { - grpc { - artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}" - } - } - generateProtoTasks { - all()*.plugins { - grpc {} - } - ofSourceSet('main') - } - - generatedFilesBaseDir = "$projectDir/gen_gradle/src" -} - -// Disable all java warnings for proto generated files build -compileJava { - options.compilerArgs += ["-Xlint:none"] - options.encoding = "UTF-8" -} - -clean { - delete protobuf.generatedFilesBaseDir -} - -// IntelliJ complains that the generated classes are not found, ask IntelliJ to include the -// generated Java directories as source folders. -idea { - module { - sourceDirs += file("${protobuf.generatedFilesBaseDir}/main/java"); - // If you have additional sourceSets and/or codegen plugins, add all of them - } -} - -signing { - required false - sign configurations.archives -} - -javadoc.source = "$projectDir/gen_gradle/src" - -javadoc.options { - encoding = 'UTF-8' - links 'https://docs.oracle.com/javase/8/docs/api/' -} - -task javadocJar(type: Jar) { - classifier = 'javadoc' - from javadoc -} - -task sourcesJar(type: Jar) { - classifier = 'sources' - from sourceSets.main.allSource -} - -artifacts { - archives javadocJar, sourcesJar -} - -uploadArchives { - repositories { - mavenDeployer { - beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } - - def configureAuth = { - if (rootProject.hasProperty('ossrhUsername') && rootProject.hasProperty('ossrhPassword')) { - authentication(userName:rootProject.ossrhUsername, password: rootProject.ossrhPassword) - } - } - - repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/", configureAuth) - - snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/", configureAuth) - - pom.project { - name "OpenCensus" - packaging 'jar' - description project.description - url 'https://github.com/census-instrumentation/opencensus-proto' - - scm { - connection 'scm:svn:https://github.com/census-instrumentation/opencensus-proto' - developerConnection 'scm:git:git@github.com/census-instrumentation/opencensus-proto' - url 'https://github.com/census-instrumentation/opencensus-proto' - } - - licenses { - license { - name 'The Apache License, Version 2.0' - url 'http://www.apache.org/licenses/LICENSE-2.0.txt' - } - } - - developers { - developer { - id 'io.opencensus' - name 'OpenCensus Contributors' - email 'census-developers@googlegroups.com' - url 'opencensus.io' - // https://issues.gradle.org/browse/GRADLE-2719 - organization = 'OpenCensus Authors' - organizationUrl 'https://www.opencensus.io' - } - } - } - } - } - } diff --git a/vendor/github.com/census-instrumentation/opencensus-proto/gradlew b/vendor/github.com/census-instrumentation/opencensus-proto/gradlew deleted file mode 100755 index cccdd3d5..00000000 --- a/vendor/github.com/census-instrumentation/opencensus-proto/gradlew +++ /dev/null @@ -1,172 +0,0 @@ -#!/usr/bin/env sh - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn () { - echo "$*" -} - -die () { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - -exec "$JAVACMD" "$@" diff --git a/vendor/github.com/census-instrumentation/opencensus-proto/gradlew.bat b/vendor/github.com/census-instrumentation/opencensus-proto/gradlew.bat deleted file mode 100644 index e95643d6..00000000 --- a/vendor/github.com/census-instrumentation/opencensus-proto/gradlew.bat +++ /dev/null @@ -1,84 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/vendor/github.com/census-instrumentation/opencensus-proto/settings.gradle b/vendor/github.com/census-instrumentation/opencensus-proto/settings.gradle deleted file mode 100644 index 52ecb4e1..00000000 --- a/vendor/github.com/census-instrumentation/opencensus-proto/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = "opencensus-proto" diff --git a/vendor/github.com/denisenkom/go-mssqldb/README.md b/vendor/github.com/denisenkom/go-mssqldb/README.md deleted file mode 100644 index ea06b900..00000000 --- a/vendor/github.com/denisenkom/go-mssqldb/README.md +++ /dev/null @@ -1,215 +0,0 @@ -# A pure Go MSSQL driver for Go's database/sql package - -[![GoDoc](https://godoc.org/github.com/denisenkom/go-mssqldb?status.svg)](http://godoc.org/github.com/denisenkom/go-mssqldb) -[![Build status](https://ci.appveyor.com/api/projects/status/jrln8cs62wj9i0a2?svg=true)](https://ci.appveyor.com/project/denisenkom/go-mssqldb) -[![codecov](https://codecov.io/gh/denisenkom/go-mssqldb/branch/master/graph/badge.svg)](https://codecov.io/gh/denisenkom/go-mssqldb) - -## Install - -Requires Go 1.8 or above. - -Install with `go get github.com/denisenkom/go-mssqldb` . - -## Connection Parameters and DSN - -The recommended connection string uses a URL format: -`sqlserver://username:password@host/instance?param1=value¶m2=value` -Other supported formats are listed below. - -### Common parameters: - -* `user id` - enter the SQL Server Authentication user id or the Windows Authentication user id in the DOMAIN\User format. On Windows, if user id is empty or missing Single-Sign-On is used. -* `password` -* `database` -* `connection timeout` - in seconds (default is 0 for no timeout), set to 0 for no timeout. Recommended to set to 0 and use context to manage query and connection timeouts. -* `dial timeout` - in seconds (default is 15), set to 0 for no timeout -* `encrypt` - * `disable` - Data send between client and server is not encrypted. - * `false` - Data sent between client and server is not encrypted beyond the login packet. (Default) - * `true` - Data sent between client and server is encrypted. -* `app name` - The application name (default is go-mssqldb) - -### Connection parameters for ODBC and ADO style connection strings: - -* `server` - host or host\instance (default localhost) -* `port` - used only when there is no instance in server (default 1433) - -### Less common parameters: - -* `keepAlive` - in seconds; 0 to disable (default is 30) -* `failoverpartner` - host or host\instance (default is no partner). -* `failoverport` - used only when there is no instance in failoverpartner (default 1433) -* `packet size` - in bytes; 512 to 32767 (default is 4096) - * Encrypted connections have a maximum packet size of 16383 bytes - * Further information on usage: https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/configure-the-network-packet-size-server-configuration-option -* `log` - logging flags (default 0/no logging, 63 for full logging) - * 1 log errors - * 2 log messages - * 4 log rows affected - * 8 trace sql statements - * 16 log statement parameters - * 32 log transaction begin/end -* `TrustServerCertificate` - * false - Server certificate is checked. Default is false if encypt is specified. - * true - Server certificate is not checked. Default is true if encrypt is not specified. If trust server certificate is true, driver accepts any certificate presented by the server and any host name in that certificate. In this mode, TLS is susceptible to man-in-the-middle attacks. This should be used only for testing. -* `certificate` - The file that contains the public key certificate of the CA that signed the SQL Server certificate. The specified certificate overrides the go platform specific CA certificates. -* `hostNameInCertificate` - Specifies the Common Name (CN) in the server certificate. Default value is the server host. -* `ServerSPN` - The kerberos SPN (Service Principal Name) for the server. Default is MSSQLSvc/host:port. -* `Workstation ID` - The workstation name (default is the host name) -* `ApplicationIntent` - Can be given the value `ReadOnly` to initiate a read-only connection to an Availability Group listener. - -### The connection string can be specified in one of three formats: - - -1. URL: with `sqlserver` scheme. username and password appears before the host. Any instance appears as - the first segment in the path. All other options are query parameters. Examples: - - * `sqlserver://username:password@host/instance?param1=value¶m2=value` - * `sqlserver://username:password@host:port?param1=value¶m2=value` - * `sqlserver://sa@localhost/SQLExpress?database=master&connection+timeout=30` // `SQLExpress instance. - * `sqlserver://sa:mypass@localhost?database=master&connection+timeout=30` // username=sa, password=mypass. - * `sqlserver://sa:mypass@localhost:1234?database=master&connection+timeout=30` // port 1234 on localhost. - * `sqlserver://sa:my%7Bpass@somehost?connection+timeout=30` // password is "my{pass" - - A string of this format can be constructed using the `URL` type in the `net/url` package. - -```go - query := url.Values{} - query.Add("app name", "MyAppName") - - u := &url.URL{ - Scheme: "sqlserver", - User: url.UserPassword(username, password), - Host: fmt.Sprintf("%s:%d", hostname, port), - // Path: instance, // if connecting to an instance instead of a port - RawQuery: query.Encode(), - } - db, err := sql.Open("sqlserver", u.String()) -``` - -2. ADO: `key=value` pairs separated by `;`. Values may not contain `;`, leading and trailing whitespace is ignored. - Examples: - - * `server=localhost\\SQLExpress;user id=sa;database=master;app name=MyAppName` - * `server=localhost;user id=sa;database=master;app name=MyAppName` - -3. ODBC: Prefix with `odbc`, `key=value` pairs separated by `;`. Allow `;` by wrapping - values in `{}`. Examples: - - * `odbc:server=localhost\\SQLExpress;user id=sa;database=master;app name=MyAppName` - * `odbc:server=localhost;user id=sa;database=master;app name=MyAppName` - * `odbc:server=localhost;user id=sa;password={foo;bar}` // Value marked with `{}`, password is "foo;bar" - * `odbc:server=localhost;user id=sa;password={foo{bar}` // Value marked with `{}`, password is "foo{bar" - * `odbc:server=localhost;user id=sa;password={foobar }` // Value marked with `{}`, password is "foobar " - * `odbc:server=localhost;user id=sa;password=foo{bar` // Literal `{`, password is "foo{bar" - * `odbc:server=localhost;user id=sa;password=foo}bar` // Literal `}`, password is "foo}bar" - * `odbc:server=localhost;user id=sa;password={foo{bar}` // Literal `{`, password is "foo{bar" - * `odbc:server=localhost;user id=sa;password={foo}}bar}` // Escaped `} with `}}`, password is "foo}bar" - -## Executing Stored Procedures - -To run a stored procedure, set the query text to the procedure name: -```go -var account = "abc" -_, err := db.ExecContext(ctx, "sp_RunMe", - sql.Named("ID", 123), - sql.Named("Account", sql.Out{Dest: &account}), -) -``` - -## Return Status - -To get the procedure return status, pass into the parameters a -`*mssql.ReturnStatus`. For example: -``` -var rs mssql.ReturnStatus -_, err := db.ExecContext(ctx, "theproc", &rs) -log.Printf("status=%d", rs) -``` - -## Parameters - -The `sqlserver` driver uses normal MS SQL Server syntax and expects parameters in -the sql query to be in the form of either `@Name` or `@p1` to `@pN` (ordinal position). - -```go -db.QueryContext(ctx, `select * from t where ID = @ID and Name = @p2;`, sql.Named("ID", 6), "Bob") -``` - -### Parameter Types - -To pass specific types to the query parameters, say `varchar` or `date` types, -you must convert the types to the type before passing in. The following types -are supported: - - * string -> nvarchar - * mssql.VarChar -> varchar - * time.Time -> datetimeoffset or datetime (TDS version dependent) - * mssql.DateTime1 -> datetime - * mssql.DateTimeOffset -> datetimeoffset - * "cloud.google.com/go/civil".Date -> date - * "cloud.google.com/go/civil".DateTime -> datetime2 - * "cloud.google.com/go/civil".Time -> time - -## Important Notes - - * [LastInsertId](https://golang.org/pkg/database/sql/#Result.LastInsertId) should - not be used with this driver (or SQL Server) due to how the TDS protocol - works. Please use the [OUTPUT Clause](https://docs.microsoft.com/en-us/sql/t-sql/queries/output-clause-transact-sql) - or add a `select ID = convert(bigint, SCOPE_IDENTITY());` to the end of your - query (ref [SCOPE_IDENTITY](https://docs.microsoft.com/en-us/sql/t-sql/functions/scope-identity-transact-sql)). - This will ensure you are getting the correct ID and will prevent a network round trip. - * [NewConnector](https://godoc.org/github.com/denisenkom/go-mssqldb#NewConnector) - may be used with [OpenDB](https://golang.org/pkg/database/sql/#OpenDB). - * [Connector.SessionInitSQL](https://godoc.org/github.com/denisenkom/go-mssqldb#Connector.SessionInitSQL) - may be set to set any driver specific session settings after the session - has been reset. If empty the session will still be reset but use the database - defaults in Go1.10+. - -## Features - -* Can be used with SQL Server 2005 or newer -* Can be used with Microsoft Azure SQL Database -* Can be used on all go supported platforms (e.g. Linux, Mac OS X and Windows) -* Supports new date/time types: date, time, datetime2, datetimeoffset -* Supports string parameters longer than 8000 characters -* Supports encryption using SSL/TLS -* Supports SQL Server and Windows Authentication -* Supports Single-Sign-On on Windows -* Supports connections to AlwaysOn Availability Group listeners, including re-direction to read-only replicas. -* Supports query notifications - -## Tests - -`go test` is used for testing. A running instance of MSSQL server is required. -Environment variables are used to pass login information. - -Example: - - env SQLSERVER_DSN=sqlserver://user:pass@hostname/instance?database=test1 go test - -## Deprecated - -These features still exist in the driver, but they are are deprecated. - -### Query Parameter Token Replace (driver "mssql") - -If you use the driver name "mssql" (rather then "sqlserver") the SQL text -will be loosly parsed and an attempt to extract identifiers using one of - -* ? -* ?nnn -* :nnn -* $nnn - -will be used. This is not recommended with SQL Server. -There is at least one existing `won't fix` issue with the query parsing. - -Use the native "@Name" parameters instead with the "sqlserver" driver name. - -## Known Issues - -* SQL Server 2008 and 2008 R2 engine cannot handle login records when SSL encryption is not disabled. -To fix SQL Server 2008 R2 issue, install SQL Server 2008 R2 Service Pack 2. -To fix SQL Server 2008 issue, install Microsoft SQL Server 2008 Service Pack 3 and Cumulative update package 3 for SQL Server 2008 SP3. -More information: http://support.microsoft.com/kb/2653857 diff --git a/vendor/github.com/denisenkom/go-mssqldb/appveyor.yml b/vendor/github.com/denisenkom/go-mssqldb/appveyor.yml deleted file mode 100644 index 2ae5456d..00000000 --- a/vendor/github.com/denisenkom/go-mssqldb/appveyor.yml +++ /dev/null @@ -1,48 +0,0 @@ -version: 1.0.{build} - -os: Windows Server 2012 R2 - -clone_folder: c:\gopath\src\github.com\denisenkom\go-mssqldb - -environment: - GOPATH: c:\gopath - HOST: localhost - SQLUSER: sa - SQLPASSWORD: Password12! - DATABASE: test - GOVERSION: 110 - matrix: - - GOVERSION: 18 - SQLINSTANCE: SQL2016 - - GOVERSION: 19 - SQLINSTANCE: SQL2016 - - GOVERSION: 110 - SQLINSTANCE: SQL2016 - - SQLINSTANCE: SQL2014 - - SQLINSTANCE: SQL2012SP1 - - SQLINSTANCE: SQL2008R2SP2 - -install: - - set GOROOT=c:\go%GOVERSION% - - set PATH=%GOPATH%\bin;%GOROOT%\bin;%PATH% - - go version - - go env - - go get -u cloud.google.com/go/civil - -build_script: - - go build - -before_test: - # setup SQL Server - - ps: | - $instanceName = $env:SQLINSTANCE - Start-Service "MSSQL`$$instanceName" - Start-Service "SQLBrowser" - - sqlcmd -S "(local)\%SQLINSTANCE%" -Q "Use [master]; CREATE DATABASE test;" - - sqlcmd -S "(local)\%SQLINSTANCE%" -h -1 -Q "set nocount on; Select @@version" - - pip install codecov - - -test_script: - - go test -race -cpu 4 -coverprofile=coverage.txt -covermode=atomic - - codecov -f coverage.txt diff --git a/vendor/github.com/denisenkom/go-mssqldb/buf_test.go b/vendor/github.com/denisenkom/go-mssqldb/buf_test.go deleted file mode 100644 index 9d681665..00000000 --- a/vendor/github.com/denisenkom/go-mssqldb/buf_test.go +++ /dev/null @@ -1,284 +0,0 @@ -package mssql - -import ( - "bytes" - "errors" - "testing" -) - -type closableBuffer struct { - *bytes.Buffer -} - -func (closableBuffer) Close() error { - return nil -} - -type failBuffer struct { -} - -func (failBuffer) Read([]byte) (int, error) { - return 0, errors.New("read failed") -} - -func (failBuffer) Write([]byte) (int, error) { - return 0, errors.New("write failed") -} - -func (failBuffer) Close() error { - return nil -} - -func makeBuf(bufSize uint16, testData []byte) *tdsBuffer { - buffer := closableBuffer{bytes.NewBuffer(testData)} - return newTdsBuffer(bufSize, &buffer) -} - -func TestStreamShorterThanHeader(t *testing.T) { - //buffer := closableBuffer{*bytes.NewBuffer([]byte{0xFF, 0xFF})} - //buffer := closableBuffer{*bytes.NewBuffer([]byte{0x6F, 0x96, 0x19, 0xFF, 0x8B, 0x86, 0xD0, 0x11, 0xB4, 0x2D, 0x00, 0xC0, 0x4F, 0xC9, 0x64, 0xFF})} - //tdsBuffer := newTdsBuffer(100, &buffer) - buffer := makeBuf(100, []byte{0xFF, 0xFF}) - _, err := buffer.BeginRead() - if err == nil { - t.Fatal("BeginRead was expected to return error but it didn't") - } else { - t.Log("BeginRead failed as expected with error:", err.Error()) - } -} - -func TestInvalidLengthInHeaderTooLong(t *testing.T) { - buffer := makeBuf(8, []byte{0xFF, 0xFF, 0x0, 0x9, 0xff, 0xff, 0xff, 0xff}) - _, err := buffer.BeginRead() - if err == nil { - t.Fatal("BeginRead was expected to return error but it didn't") - } else { - if err.Error() != "Invalid packet size, it is longer than buffer size" { - t.Fatal("BeginRead failed with incorrect error", err) - } else { - t.Log("BeginRead failed as expected with error:", err.Error()) - } - } -} - -func TestInvalidLengthInHeaderTooShort(t *testing.T) { - buffer := makeBuf(100, []byte{0xFF, 0xFF, 0x0, 0x1, 0xff, 0xff, 0xff, 0xff}) - _, err := buffer.BeginRead() - if err == nil { - t.Fatal("BeginRead was expected to return error but it didn't") - } else { - t.Log("BeginRead failed as expected with error:", err.Error()) - } -} - -func TestInvalidLengthInHeaderLongerThanIncomingBuffer(t *testing.T) { - buffer := makeBuf(9, []byte{0xFF, 0xFF, 0x0, 0x9, 0xff, 0xff, 0xff, 0xff}) - _, err := buffer.BeginRead() - if err == nil { - t.Fatal("BeginRead was expected to return error but it didn't") - } else { - t.Log("BeginRead failed as expected with error:", err.Error()) - } -} - -func TestBeginReadSucceeds(t *testing.T) { - buffer := makeBuf(9, []byte{0x01 /*id*/, 0xFF /*status*/, 0x0, 0x9 /*size*/, 0xff, 0xff, 0xff, 0xff, 0x02 /*test byte*/}) - - id, err := buffer.BeginRead() - if err != nil { - t.Fatal("BeginRead failed:", err.Error()) - } - if id != 1 { - t.Fatalf("Expected id to be 1 but it is %d", id) - } - - b, err := buffer.ReadByte() - if err != nil { - t.Fatal("ReadByte failed:", err.Error()) - } - if b != 2 { - t.Fatalf("Expected read byte to be 2 but it is %d", b) - } - - // should fail because no more bytes left - _, err = buffer.ReadByte() - if err == nil { - t.Fatal("ReadByte was expected to return error but it didn't") - } else { - t.Log("ReadByte failed as expected with error:", err.Error()) - } - - testBuf := []byte{0, 1, 2} - // should fail because no more bytes left - _, err = buffer.Read(testBuf) - if err == nil { - t.Fatal("Read was expected to return error but it didn't") - } else { - t.Log("Read failed as expected with error:", err.Error()) - } -} - -func TestReadByteFailsOnSecondPacket(t *testing.T) { - buffer := makeBuf(9, []byte{ - 0x01 /*id*/, 0x0 /*not final*/, 0x0, 0x9 /*size*/, 0xff, 0xff, 0xff, 0xff, 0x02, /*test byte*/ - 0x01 /*next id, this packet is invalid, it is too short*/}) - - _, err := buffer.BeginRead() - if err != nil { - t.Fatal("BeginRead failed:", err.Error()) - } - - _, err = buffer.ReadByte() - if err != nil { - t.Fatal("ReadByte failed:", err.Error()) - } - - _, err = buffer.ReadByte() - if err == nil { - t.Fatal("ReadByte was expected to return error but it didn't") - } else { - t.Log("ReadByte failed as expected with error:", err.Error()) - } - - t.Run("test byte() panic", func(t *testing.T) { - defer func() { - recover() - }() - buffer.byte() - t.Fatal("byte() should panic, but it didn't") - }) - - t.Run("test ReadFull() panic", func(t *testing.T) { - defer func() { - recover() - }() - buf := make([]byte, 10) - buffer.ReadFull(buf) - t.Fatal("ReadFull() should panic, but it didn't") - }) -} - -func TestReadFailsOnSecondPacket(t *testing.T) { - buffer := makeBuf(9, []byte{ - 0x01 /*id*/, 0x0 /*not final*/, 0x0, 0x9 /*size*/, 0xff, 0xff, 0xff, 0xff, 0x02, /*test byte*/ - 0x01 /*next id, this packet is invalid, it is too short*/}) - - _, err := buffer.BeginRead() - if err != nil { - t.Fatal("BeginRead failed:", err.Error()) - } - - testBuf := []byte{0} - _, err = buffer.Read(testBuf) - if err != nil { - t.Fatal("Read failed:", err.Error()) - } - if testBuf[0] != 2 { - t.Fatal("Read returned invalid value") - } - - _, err = buffer.Read(testBuf) - if err == nil { - t.Fatal("ReadByte was expected to return error but it didn't") - } else { - t.Log("ReadByte failed as expected with error:", err.Error()) - } -} - -func TestWrite(t *testing.T) { - memBuf := bytes.NewBuffer([]byte{}) - buf := newTdsBuffer(11, closableBuffer{memBuf}) - buf.BeginPacket(1, false) - err := buf.WriteByte(2) - if err != nil { - t.Fatal("WriteByte failed:", err.Error()) - } - wrote, err := buf.Write([]byte{3, 4}) - if err != nil { - t.Fatal("Write failed:", err.Error()) - } - if wrote != 2 { - t.Fatalf("Write returned invalid value of written bytes %d", wrote) - } - - err = buf.FinishPacket() - if err != nil { - t.Fatal("FinishPacket failed:", err.Error()) - } - if bytes.Compare(memBuf.Bytes(), []byte{1, 1, 0, 11, 0, 0, 1, 0, 2, 3, 4}) != 0 { - t.Fatalf("Written buffer has invalid content: %v", memBuf.Bytes()) - } - - buf.BeginPacket(2, false) - wrote, err = buf.Write([]byte{3, 4, 5, 6}) - if err != nil { - t.Fatal("Write failed:", err.Error()) - } - if wrote != 4 { - t.Fatalf("Write returned invalid value of written bytes %d", wrote) - } - err = buf.FinishPacket() - if err != nil { - t.Fatal("FinishPacket failed:", err.Error()) - } - expectedBuf := []byte{ - 1, 1, 0, 11, 0, 0, 1, 0, 2, 3, 4, // packet 1 - 2, 0, 0, 11, 0, 0, 1, 0, 3, 4, 5, // packet 2 - 2, 1, 0, 9, 0, 0, 2, 0, 6, // packet 3 - } - if bytes.Compare(memBuf.Bytes(), expectedBuf) != 0 { - t.Fatalf("Written buffer has invalid content:\n got: %v\nwant: %v", memBuf.Bytes(), expectedBuf) - } -} - -func TestWriteErrors(t *testing.T) { - // write should fail if underlying transport fails - buf := newTdsBuffer(uint16(headerSize)+1, failBuffer{}) - buf.BeginPacket(1, false) - wrote, err := buf.Write([]byte{0, 0}) - // may change from error to panic in future - if err == nil { - t.Fatal("Write should fail but it didn't") - } - if wrote != 1 { - t.Fatal("Should write 1 byte but it wrote ", wrote) - } - - // writebyte should fail if underlying transport fails - buf = newTdsBuffer(uint16(headerSize)+1, failBuffer{}) - buf.BeginPacket(1, false) - // first write should not fail because if fits in the buffer - err = buf.WriteByte(0) - if err != nil { - t.Fatal("First WriteByte should not fail because it should fit in the buffer, but it failed", err) - } - err = buf.WriteByte(0) - // may change from error to panic in future - if err == nil { - t.Fatal("Second WriteByte should fail but it didn't") - } -} - -func TestWrite_BufferBounds(t *testing.T) { - memBuf := bytes.NewBuffer([]byte{}) - buf := newTdsBuffer(11, closableBuffer{memBuf}) - - buf.BeginPacket(1, false) - // write bytes enough to complete a package - _, err := buf.Write([]byte{1, 1, 1}) - if err != nil { - t.Fatal("Write failed:", err.Error()) - } - err = buf.WriteByte(1) - if err != nil { - t.Fatal("WriteByte failed:", err.Error()) - } - _, err = buf.Write([]byte{1, 1, 1}) - if err != nil { - t.Fatal("Write failed:", err.Error()) - } - err = buf.FinishPacket() - if err != nil { - t.Fatal("FinishPacket failed:", err.Error()) - } -} diff --git a/vendor/github.com/denisenkom/go-mssqldb/bulkcopy_test.go b/vendor/github.com/denisenkom/go-mssqldb/bulkcopy_test.go deleted file mode 100644 index c0c89885..00000000 --- a/vendor/github.com/denisenkom/go-mssqldb/bulkcopy_test.go +++ /dev/null @@ -1,237 +0,0 @@ -// +build go1.9 - -package mssql - -import ( - "context" - "database/sql" - "encoding/hex" - "math" - "reflect" - "strings" - "testing" - "time" -) - -func TestBulkcopy(t *testing.T) { - // TDS level Bulk Insert is not supported on Azure SQL Server. - if dsn := makeConnStr(t); strings.HasSuffix(strings.Split(dsn.Host, ":")[0], ".database.windows.net") { - t.Skip("TDS level bulk copy is not supported on Azure SQL Server") - } - type testValue struct { - colname string - val interface{} - } - - tableName := "#table_test" - geom, _ := hex.DecodeString("E6100000010C00000000000034400000000000004440") - bin, _ := hex.DecodeString("ba8b7782168d4033a299333aec17bd33") - testValues := []testValue{ - - {"test_nvarchar", "ab©ĎéⒻghïjklmnopqЯ☀tuvwxyz"}, - {"test_varchar", "abcdefg"}, - {"test_char", "abcdefg "}, - {"test_nchar", "abcdefg "}, - {"test_text", "abcdefg"}, - {"test_ntext", "abcdefg"}, - {"test_float", 1234.56}, - {"test_floatn", 1234.56}, - {"test_real", 1234.56}, - {"test_realn", 1234.56}, - {"test_bit", true}, - {"test_bitn", nil}, - {"test_smalldatetime", time.Date(2010, 11, 12, 13, 14, 0, 0, time.UTC)}, - {"test_smalldatetimen", time.Date(2010, 11, 12, 13, 14, 0, 0, time.UTC)}, - {"test_datetime", time.Date(2010, 11, 12, 13, 14, 15, 120000000, time.UTC)}, - {"test_datetimen", time.Date(2010, 11, 12, 13, 14, 15, 120000000, time.UTC)}, - {"test_datetimen_1", time.Date(4010, 11, 12, 13, 14, 15, 120000000, time.UTC)}, - {"test_datetime2_1", time.Date(2010, 11, 12, 13, 14, 15, 0, time.UTC)}, - {"test_datetime2_3", time.Date(2010, 11, 12, 13, 14, 15, 123000000, time.UTC)}, - {"test_datetime2_7", time.Date(2010, 11, 12, 13, 14, 15, 123000000, time.UTC)}, - {"test_date", time.Date(2010, 11, 12, 00, 00, 00, 0, time.UTC)}, - {"test_tinyint", 255}, - {"test_smallint", 32767}, - {"test_smallintn", nil}, - {"test_int", 2147483647}, - {"test_bigint", 9223372036854775807}, - {"test_bigintn", nil}, - {"test_geom", geom}, - {"test_uniqueidentifier", []byte{0x6F, 0x96, 0x19, 0xFF, 0x8B, 0x86, 0xD0, 0x11, 0xB4, 0x2D, 0x00, 0xC0, 0x4F, 0xC9, 0x64, 0xFF}}, - // {"test_smallmoney", 1234.56}, - // {"test_money", 1234.56}, - {"test_decimal_18_0", 1234.0001}, - {"test_decimal_9_2", 1234.560001}, - {"test_decimal_20_0", 1234.0001}, - {"test_numeric_30_10", 1234567.1234567}, - {"test_varbinary", []byte("1")}, - {"test_varbinary_16", bin}, - {"test_varbinary_max", bin}, - {"test_binary", []byte("1")}, - {"test_binary_16", bin}, - } - - columns := make([]string, len(testValues)) - for i, val := range testValues { - columns[i] = val.colname - } - - values := make([]interface{}, len(testValues)) - for i, val := range testValues { - values[i] = val.val - } - - pool := open(t) - defer pool.Close() - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - // Now that session resetting is supported, the use of the per session - // temp table requires the use of a dedicated connection from the connection - // pool. - conn, err := pool.Conn(ctx) - if err != nil { - t.Fatal("failed to pull connection from pool", err) - } - defer conn.Close() - - err = setupTable(ctx, t, conn, tableName) - if err != nil { - t.Error("Setup table failed: ", err) - return - } - - t.Log("Preparing copy in statement") - - stmt, err := conn.PrepareContext(ctx, CopyIn(tableName, BulkOptions{}, columns...)) - - for i := 0; i < 10; i++ { - t.Logf("Executing copy in statement %d time with %d values", i+1, len(values)) - _, err = stmt.Exec(values...) - if err != nil { - t.Error("AddRow failed: ", err.Error()) - return - } - } - - result, err := stmt.Exec() - if err != nil { - t.Fatal("bulkcopy failed: ", err.Error()) - } - - insertedRowCount, _ := result.RowsAffected() - if insertedRowCount == 0 { - t.Fatal("0 row inserted!") - } - - //check that all rows are present - var rowCount int - err = conn.QueryRowContext(ctx, "select count(*) c from "+tableName).Scan(&rowCount) - - if rowCount != 10 { - t.Errorf("unexpected row count %d", rowCount) - } - - //data verification - rows, err := conn.QueryContext(ctx, "select "+strings.Join(columns, ",")+" from "+tableName) - if err != nil { - t.Fatal(err) - } - defer rows.Close() - for rows.Next() { - - ptrs := make([]interface{}, len(columns)) - container := make([]interface{}, len(columns)) - for i, _ := range ptrs { - ptrs[i] = &container[i] - } - if err := rows.Scan(ptrs...); err != nil { - t.Fatal(err) - } - for i, c := range testValues { - if !compareValue(container[i], c.val) { - t.Errorf("columns %s : expected: %v, got: %v\n", c.colname, c.val, container[i]) - } - } - } - if err := rows.Err(); err != nil { - t.Error(err) - } -} - -func compareValue(a interface{}, expected interface{}) bool { - switch expected := expected.(type) { - case int: - return int64(expected) == a - case int32: - return int64(expected) == a - case int64: - return int64(expected) == a - case float64: - if got, ok := a.([]uint8); ok { - var nf sql.NullFloat64 - nf.Scan(got) - a = nf.Float64 - } - return math.Abs(expected-a.(float64)) < 0.0001 - default: - return reflect.DeepEqual(expected, a) - } -} - -func setupTable(ctx context.Context, t *testing.T, conn *sql.Conn, tableName string) (err error) { - tablesql := `CREATE TABLE ` + tableName + ` ( - [id] [int] IDENTITY(1,1) NOT NULL, - [test_nvarchar] [nvarchar](50) NULL, - [test_varchar] [varchar](50) NULL, - [test_char] [char](10) NULL, - [test_nchar] [nchar](10) NULL, - [test_text] [text] NULL, - [test_ntext] [ntext] NULL, - [test_float] [float] NOT NULL, - [test_floatn] [float] NULL, - [test_real] [real] NULL, - [test_realn] [real] NULL, - [test_bit] [bit] NOT NULL, - [test_bitn] [bit] NULL, - [test_smalldatetime] [smalldatetime] NOT NULL, - [test_smalldatetimen] [smalldatetime] NULL, - [test_datetime] [datetime] NOT NULL, - [test_datetimen] [datetime] NULL, - [test_datetimen_1] [datetime] NULL, - [test_datetime2_1] [datetime2](1) NULL, - [test_datetime2_3] [datetime2](3) NULL, - [test_datetime2_7] [datetime2](7) NULL, - [test_date] [date] NULL, - [test_smallmoney] [smallmoney] NULL, - [test_money] [money] NULL, - [test_tinyint] [tinyint] NULL, - [test_smallint] [smallint] NOT NULL, - [test_smallintn] [smallint] NULL, - [test_int] [int] NULL, - [test_bigint] [bigint] NOT NULL, - [test_bigintn] [bigint] NULL, - [test_geom] [geometry] NULL, - [test_geog] [geography] NULL, - [text_xml] [xml] NULL, - [test_uniqueidentifier] [uniqueidentifier] NULL, - [test_decimal_18_0] [decimal](18, 0) NULL, - [test_decimal_9_2] [decimal](9, 2) NULL, - [test_decimal_20_0] [decimal](20, 0) NULL, - [test_numeric_30_10] [decimal](30, 10) NULL, - [test_varbinary] VARBINARY NOT NULL, - [test_varbinary_16] VARBINARY(16) NOT NULL, - [test_varbinary_max] VARBINARY(max) NOT NULL, - [test_binary] BINARY NOT NULL, - [test_binary_16] BINARY(16) NOT NULL, - CONSTRAINT [PK_` + tableName + `_id] PRIMARY KEY CLUSTERED -( - [id] ASC -)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] -) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY];` - _, err = conn.ExecContext(ctx, tablesql) - if err != nil { - t.Fatal("tablesql failed:", err) - } - return -} diff --git a/vendor/github.com/denisenkom/go-mssqldb/decimal_test.go b/vendor/github.com/denisenkom/go-mssqldb/decimal_test.go deleted file mode 100644 index bf38d20d..00000000 --- a/vendor/github.com/denisenkom/go-mssqldb/decimal_test.go +++ /dev/null @@ -1,107 +0,0 @@ -package mssql - -import ( - "math" - "testing" -) - -func TestToString(t *testing.T) { - values := []struct { - dec Decimal - s string - }{ - {Decimal{positive: true, prec: 10, scale: 0, integer: [4]uint32{1, 0, 0, 0}}, "1"}, - {Decimal{positive: false, prec: 10, scale: 0, integer: [4]uint32{1, 0, 0, 0}}, "-1"}, - {Decimal{positive: true, prec: 10, scale: 1, integer: [4]uint32{1, 0, 0, 0}}, "0.1"}, - {Decimal{positive: true, prec: 10, scale: 2, integer: [4]uint32{1, 0, 0, 0}}, "0.01"}, - {Decimal{positive: false, prec: 10, scale: 1, integer: [4]uint32{1, 0, 0, 0}}, "-0.1"}, - {Decimal{positive: true, prec: 10, scale: 2, integer: [4]uint32{100, 0, 0, 0}}, "1.00"}, - {Decimal{positive: false, prec: 10, scale: 2, integer: [4]uint32{100, 0, 0, 0}}, "-1.00"}, - {Decimal{positive: true, prec: 30, scale: 0, integer: [4]uint32{0, 1, 0, 0}}, "4294967296"}, // 2^32 - {Decimal{positive: true, prec: 30, scale: 0, integer: [4]uint32{0, 0, 1, 0}}, "18446744073709551616"}, // 2^64 - {Decimal{positive: true, prec: 30, scale: 0, integer: [4]uint32{0, 1, 1, 0}}, "18446744078004518912"}, // 2^64+2^32 - } - for _, v := range values { - if v.dec.String() != v.s { - t.Error("String values don't match ", v.dec.String(), v.s) - } - } -} - -func TestToFloat64(t *testing.T) { - values := []struct { - dec Decimal - flt float64 - }{ - {Decimal{positive: true, prec: 1}, - 0.0}, - {Decimal{positive: true, prec: 1, integer: [4]uint32{1}}, - 1.0}, - {Decimal{positive: false, prec: 1, integer: [4]uint32{1}}, - -1.0}, - {Decimal{positive: true, prec: 1, scale: 1, integer: [4]uint32{5}}, - 0.5}, - {Decimal{positive: true, prec: 38, integer: [4]uint32{0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}}, - 3.402823669209385e+38}, - {Decimal{positive: true, prec: 38, scale: 3, integer: [4]uint32{0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}}, - 3.402823669209385e+35}, - } - for _, v := range values { - if v.dec.ToFloat64() != v.flt { - t.Error("ToFloat values don't match ", v.dec.ToFloat64(), v.flt) - } - } -} - -func TestFromFloat64(t *testing.T) { - values := []struct { - dec Decimal - flt float64 - }{ - {Decimal{positive: true, prec: 20}, - 0.0}, - {Decimal{positive: true, prec: 20, integer: [4]uint32{1}}, - 1.0}, - {Decimal{positive: false, prec: 20, integer: [4]uint32{1}}, - -1.0}, - {Decimal{positive: true, prec: 20, scale: 1, integer: [4]uint32{5}}, - 0.5}, - {Decimal{positive: true, prec: 20, integer: [4]uint32{0, 0, 0xfffff000, 0xffffffff}}, - 3.402823669209384e+38}, - //{Decimal{positive: true, prec: 20, scale: 3, integer: [4]uint32{0, 0, 0xfffff000, 0xffffffff}}, - // 3.402823669209385e+35}, - } - for _, v := range values { - decfromflt, err := Float64ToDecimal(v.flt) - if err == nil { - if decfromflt != v.dec { - t.Error("FromFloat values don't match ", decfromflt, v.dec) - } - } else { - t.Error("Float64ToDecimal failed with error:", err.Error()) - } - } - - _, err := Float64ToDecimal(math.NaN()) - if err == nil { - t.Error("Expected to get error for conversion from NaN, but didn't") - } - - _, err = Float64ToDecimal(math.Inf(1)) - if err == nil { - t.Error("Expected to get error for conversion from positive infinity, but didn't") - } - - _, err = Float64ToDecimal(math.Inf(-1)) - if err == nil { - t.Error("Expected to get error for conversion from negative infinity, but didn't") - } - _, err = Float64ToDecimal(3.402823669209386e+38) - if err == nil { - t.Error("Expected to get error for conversion from too big number, but didn't") - } - _, err = Float64ToDecimal(-3.402823669209386e+38) - if err == nil { - t.Error("Expected to get error for conversion from too big number, but didn't") - } -} diff --git a/vendor/github.com/denisenkom/go-mssqldb/error_example_test.go b/vendor/github.com/denisenkom/go-mssqldb/error_example_test.go deleted file mode 100644 index 05549755..00000000 --- a/vendor/github.com/denisenkom/go-mssqldb/error_example_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package mssql - -import "fmt" - -func ExampleError_1() { - // call a function that might return a mssql error - err := callUsingMSSQL() - - type ErrorWithNumber interface { - SQLErrorNumber() int32 - } - - if errorWithNumber, ok := err.(ErrorWithNumber); ok { - if errorWithNumber.SQLErrorNumber() == 1205 { - fmt.Println("deadlock error") - } - } -} - -func ExampleError_2() { - // call a function that might return a mssql error - err := callUsingMSSQL() - - type SQLError interface { - SQLErrorNumber() int32 - SQLErrorMessage() string - } - - if sqlError, ok := err.(SQLError); ok { - if sqlError.SQLErrorNumber() == 1205 { - fmt.Println("deadlock error", sqlError.SQLErrorMessage()) - } - } -} - -func callUsingMSSQL() error { - return nil -} diff --git a/vendor/github.com/denisenkom/go-mssqldb/mssql_test.go b/vendor/github.com/denisenkom/go-mssqldb/mssql_test.go deleted file mode 100644 index 2ec8b956..00000000 --- a/vendor/github.com/denisenkom/go-mssqldb/mssql_test.go +++ /dev/null @@ -1,39 +0,0 @@ -package mssql - -import ( - "context" - "testing" -) - -func TestBadOpen(t *testing.T) { - drv := driverWithProcess(t) - _, err := drv.open(context.Background(), "port=bad") - if err == nil { - t.Fail() - } -} - -func TestIsProc(t *testing.T) { - list := []struct { - s string - is bool - }{ - {"proc", true}, - {"select 1;", false}, - {"select 1", false}, - {"[proc 1]", true}, - {"[proc\n1]", false}, - {"schema.name", true}, - {"[schema].[name]", true}, - {"schema.[name]", true}, - {"[schema].name", true}, - {"schema.[proc name]", true}, - } - - for _, item := range list { - got := isProc(item.s) - if got != item.is { - t.Errorf("for %q, got %t want %t", item.s, got, item.is) - } - } -} diff --git a/vendor/github.com/denisenkom/go-mssqldb/ntlm_test.go b/vendor/github.com/denisenkom/go-mssqldb/ntlm_test.go deleted file mode 100644 index db56f4e3..00000000 --- a/vendor/github.com/denisenkom/go-mssqldb/ntlm_test.go +++ /dev/null @@ -1,76 +0,0 @@ -// +build !windows - -package mssql - -import ( - "encoding/hex" - "testing" -) - -func TestLMOWFv1(t *testing.T) { - hash := lmHash("Password") - val := [21]byte{ - 0xe5, 0x2c, 0xac, 0x67, 0x41, 0x9a, 0x9a, 0x22, - 0x4a, 0x3b, 0x10, 0x8f, 0x3f, 0xa6, 0xcb, 0x6d, - 0, 0, 0, 0, 0, - } - if hash != val { - t.Errorf("got:\n%sexpected:\n%s", hex.Dump(hash[:]), hex.Dump(val[:])) - } -} - -func TestNTLMOWFv1(t *testing.T) { - hash := ntlmHash("Password") - val := [21]byte{ - 0xa4, 0xf4, 0x9c, 0x40, 0x65, 0x10, 0xbd, 0xca, 0xb6, 0x82, 0x4e, 0xe7, 0xc3, 0x0f, 0xd8, 0x52, - 0, 0, 0, 0, 0, - } - if hash != val { - t.Errorf("got:\n%sexpected:\n%s", hex.Dump(hash[:]), hex.Dump(val[:])) - } -} - -func TestNTLMv1Response(t *testing.T) { - challenge := [8]byte{ - 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, - } - nt := ntResponse(challenge, "Password") - val := [24]byte{ - 0x67, 0xc4, 0x30, 0x11, 0xf3, 0x02, 0x98, 0xa2, 0xad, 0x35, 0xec, 0xe6, 0x4f, 0x16, 0x33, 0x1c, - 0x44, 0xbd, 0xbe, 0xd9, 0x27, 0x84, 0x1f, 0x94, - } - if nt != val { - t.Errorf("got:\n%sexpected:\n%s", hex.Dump(nt[:]), hex.Dump(val[:])) - } -} - -func TestLMv1Response(t *testing.T) { - challenge := [8]byte{ - 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, - } - nt := lmResponse(challenge, "Password") - val := [24]byte{ - 0x98, 0xde, 0xf7, 0xb8, 0x7f, 0x88, 0xaa, 0x5d, 0xaf, 0xe2, 0xdf, 0x77, 0x96, 0x88, 0xa1, 0x72, - 0xde, 0xf1, 0x1c, 0x7d, 0x5c, 0xcd, 0xef, 0x13, - } - if nt != val { - t.Errorf("got:\n%sexpected:\n%s", hex.Dump(nt[:]), hex.Dump(val[:])) - } -} - -func TestNTLMSessionResponse(t *testing.T) { - challenge := [8]byte{ - 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, - } - nonce := [8]byte{ - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - } - nt := ntlmSessionResponse(nonce, challenge, "Password") - val := [24]byte{ - 0x75, 0x37, 0xf8, 0x03, 0xae, 0x36, 0x71, 0x28, 0xca, 0x45, 0x82, 0x04, 0xbd, 0xe7, 0xca, 0xf8, - 0x1e, 0x97, 0xed, 0x26, 0x83, 0x26, 0x72, 0x32, - } - if nt != val { - t.Errorf("got:\n%sexpected:\n%s", hex.Dump(nt[:]), hex.Dump(val[:])) - } -} diff --git a/vendor/github.com/denisenkom/go-mssqldb/parser_test.go b/vendor/github.com/denisenkom/go-mssqldb/parser_test.go deleted file mode 100644 index d09250df..00000000 --- a/vendor/github.com/denisenkom/go-mssqldb/parser_test.go +++ /dev/null @@ -1,60 +0,0 @@ -package mssql - -import ( - "testing" -) - -func TestParseParams(t *testing.T) { - values := []struct { - s string - d string - n int - }{ - {"select ?", "select @p1", 1}, - {"select ?, ?", "select @p1, @p2", 2}, - {"select ? -- ?", "select @p1 -- ?", 1}, - {"select ? -- ?\n, ?", "select @p1 -- ?\n, @p2", 2}, - {"select ? - ?", "select @p1 - @p2", 2}, - {"select ? /* ? */, ?", "select @p1 /* ? */, @p2", 2}, - {"select ? /* ? * ? */, ?", "select @p1 /* ? * ? */, @p2", 2}, - {"select \"foo?\", [foo?], 'foo?', ?", "select \"foo?\", [foo?], 'foo?', @p1", 1}, - {"select \"x\"\"y\", [x]]y], 'x''y', ?", "select \"x\"\"y\", [x]]y], 'x''y', @p1", 1}, - {"select \"foo?\", ?", "select \"foo?\", @p1", 1}, - {"select 'foo?', ?", "select 'foo?', @p1", 1}, - {"select [foo?], ?", "select [foo?], @p1", 1}, - {"select $1", "select @p1", 1}, - {"select $1, $2", "select @p1, @p2", 2}, - {"select $1, $1", "select @p1, @p1", 1}, - {"select :1", "select @p1", 1}, - {"select :1, :2", "select @p1, @p2", 2}, - {"select :1, :1", "select @p1, @p1", 1}, - {"select ?1", "select @p1", 1}, - {"select ?1, ?2", "select @p1, @p2", 2}, - {"select ?1, ?1", "select @p1, @p1", 1}, - {"select $12", "select @p12", 12}, - {"select ? /* ? /* ? */ ? */ ?", "select @p1 /* ? /* ? */ ? */ @p2", 2}, - {"select ? /* ? / ? */ ?", "select @p1 /* ? / ? */ @p2", 2}, - {"select $", "select $", 0}, - {"select x::y", "select x:@y", 1}, - {"select '", "select '", 0}, - {"select \"", "select \"", 0}, - {"select [", "select [", 0}, - {"select []", "select []", 0}, - {"select -", "select -", 0}, - {"select /", "select /", 0}, - {"select 1/1", "select 1/1", 0}, - {"select /*", "select /*", 0}, - {"select /**", "select /**", 0}, - {"select /*/", "select /*/", 0}, - } - - for _, v := range values { - d, n := parseParams(v.s) - if d != v.d { - t.Errorf("Parse params don't match for %s, got %s but expected %s", v.s, d, v.d) - } - if n != v.n { - t.Errorf("Parse number of params don't match for %s, got %d but expected %d", v.s, n, v.n) - } - } -} diff --git a/vendor/github.com/denisenkom/go-mssqldb/queries_go110_test.go b/vendor/github.com/denisenkom/go-mssqldb/queries_go110_test.go deleted file mode 100644 index 197ddedb..00000000 --- a/vendor/github.com/denisenkom/go-mssqldb/queries_go110_test.go +++ /dev/null @@ -1,189 +0,0 @@ -// +build go1.10 - -package mssql - -import ( - "context" - "database/sql" - "strings" - "testing" - "time" - - "cloud.google.com/go/civil" -) - -func TestSessionInitSQL(t *testing.T) { - checkConnStr(t) - SetLogger(testLogger{t}) - - d := &Driver{} - connector, err := d.OpenConnector(makeConnStr(t).String()) - if err != nil { - t.Fatal("unable to open connector", err) - } - - // Do not use these settings in your application - // unless you know what they do. - // Thes are for this unit test only. - // - // Sessions will be reset even if SessionInitSQL is not set. - connector.SessionInitSQL = ` -SET XACT_ABORT ON; -- 16384 -SET ANSI_NULLS ON; -- 32 -SET ARITHIGNORE ON; -- 128 -` - - pool := sql.OpenDB(connector) - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - var opt int32 - err = pool.QueryRowContext(ctx, ` -select Options = @@OPTIONS; -`).Scan(&opt) - if err != nil { - t.Fatal("failed to run query", err) - } - mask := int32(16384 | 128 | 32) - - if opt&mask != mask { - t.Fatal("incorrect session settings", opt) - } -} - -func TestParameterTypes(t *testing.T) { - checkConnStr(t) - pool, err := sql.Open("sqlserver", makeConnStr(t).String()) - if err != nil { - t.Fatal(err) - } - defer pool.Close() - - tin, err := time.Parse(time.RFC3339, "2006-01-02T22:04:05-07:00") - if err != nil { - t.Fatal(err) - } - - var nv, v, nvcm, vcm, dt1, dt2, tm, d, dto string - row := pool.QueryRow(` -select - nv = SQL_VARIANT_PROPERTY(@nv,'BaseType'), - v = SQL_VARIANT_PROPERTY(@v,'BaseType'), - @nvcm, - @vcm, - dt1 = SQL_VARIANT_PROPERTY(@dt1,'BaseType'), - dt2 = SQL_VARIANT_PROPERTY(@dt2,'BaseType'), - d = SQL_VARIANT_PROPERTY(@d,'BaseType'), - tm = SQL_VARIANT_PROPERTY(@tm,'BaseType'), - dto = SQL_VARIANT_PROPERTY(@dto,'BaseType') -; - `, - sql.Named("nv", "base type nvarchar"), - sql.Named("v", VarChar("base type varchar")), - sql.Named("nvcm", NVarCharMax(strings.Repeat("x", 5000))), - sql.Named("vcm", VarCharMax(strings.Repeat("x", 5000))), - sql.Named("dt1", DateTime1(tin)), - sql.Named("dt2", civil.DateTimeOf(tin)), - sql.Named("d", civil.DateOf(tin)), - sql.Named("tm", civil.TimeOf(tin)), - sql.Named("dto", DateTimeOffset(tin)), - ) - err = row.Scan(&nv, &v, &nvcm, &vcm, &dt1, &dt2, &d, &tm, &dto) - if err != nil { - t.Fatal(err) - } - - if nv != "nvarchar" { - t.Errorf(`want "nvarchar" got %q`, nv) - } - if v != "varchar" { - t.Errorf(`want "varchar" got %q`, v) - } - if nvcm != strings.Repeat("x", 5000) { - t.Errorf(`incorrect value returned for nvarchar(max): %q`, nvcm) - } - if vcm != strings.Repeat("x", 5000) { - t.Errorf(`incorrect value returned for varchar(max): %q`, vcm) - } - if dt1 != "datetime" { - t.Errorf(`want "datetime" got %q`, dt1) - } - if dt2 != "datetime2" { - t.Errorf(`want "datetime2" got %q`, dt2) - } - if d != "date" { - t.Errorf(`want "date" got %q`, d) - } - if tm != "time" { - t.Errorf(`want "time" got %q`, tm) - } - if dto != "datetimeoffset" { - t.Errorf(`want "datetimeoffset" got %q`, dto) - } -} - -func TestParameterValues(t *testing.T) { - checkConnStr(t) - pool, err := sql.Open("sqlserver", makeConnStr(t).String()) - if err != nil { - t.Fatal(err) - } - defer pool.Close() - - sin := "high five" - tin, err := time.Parse(time.RFC3339, "2006-01-02T22:04:05-07:00") - if err != nil { - t.Fatal(err) - } - - var nv, v, tgo, dt1, dt2, tm, d, dto string - err = pool.QueryRow(` -select - nv = @nv, - v = @v, - tgo = @tgo, - dt1 = convert(nvarchar(200), @dt1, 121), - dt2 = convert(nvarchar(200), @dt2, 121), - d = convert(nvarchar(200), @d, 121), - tm = convert(nvarchar(200), @tm, 121), - dto = convert(nvarchar(200), @dto, 121) -; - `, - sql.Named("nv", sin), - sql.Named("v", sin), - sql.Named("tgo", tin), - sql.Named("dt1", DateTime1(tin)), - sql.Named("dt2", civil.DateTimeOf(tin)), - sql.Named("d", civil.DateOf(tin)), - sql.Named("tm", civil.TimeOf(tin)), - sql.Named("dto", DateTimeOffset(tin)), - ).Scan(&nv, &v, &tgo, &dt1, &dt2, &d, &tm, &dto) - if err != nil { - t.Fatal(err) - } - if want := sin; nv != want { - t.Errorf(`want %q got %q`, want, nv) - } - if want := sin; v != want { - t.Errorf(`want %q got %q`, want, v) - } - if want := "2006-01-02T22:04:05-07:00"; tgo != want { - t.Errorf(`want %q got %q`, want, tgo) - } - if want := "2006-01-02 22:04:05.000"; dt1 != want { - t.Errorf(`want %q got %q`, want, dt1) - } - if want := "2006-01-02 22:04:05.0000000"; dt2 != want { - t.Errorf(`want %q got %q`, want, dt2) - } - if want := "2006-01-02"; d != want { - t.Errorf(`want %q got %q`, want, d) - } - if want := "22:04:05.0000000"; tm != want { - t.Errorf(`want %q got %q`, want, tm) - } - if want := "2006-01-02 22:04:05.0000000 -07:00"; dto != want { - t.Errorf(`want %q got %q`, want, dto) - } -} diff --git a/vendor/github.com/denisenkom/go-mssqldb/queries_go19_test.go b/vendor/github.com/denisenkom/go-mssqldb/queries_go19_test.go deleted file mode 100644 index 9e855eef..00000000 --- a/vendor/github.com/denisenkom/go-mssqldb/queries_go19_test.go +++ /dev/null @@ -1,856 +0,0 @@ -// +build go1.9 - -package mssql - -import ( - "bytes" - "context" - "database/sql" - "fmt" - "regexp" - "testing" - "time" -) - -func TestOutputParam(t *testing.T) { - checkConnStr(t) - SetLogger(testLogger{t}) - - db, err := sql.Open("sqlserver", makeConnStr(t).String()) - if err != nil { - t.Fatalf("failed to open driver sqlserver") - } - defer db.Close() - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - t.Run("sp with rows", func(t *testing.T) { - sqltextcreate := ` -CREATE PROCEDURE spwithrows - @intparam INT = NULL OUTPUT -AS -BEGIN - -- return 2 rows - SELECT @intparam - union - SELECT 20 - - -- set output parameter value - SELECT @intparam = 10 -END; -` - sqltextdrop := `DROP PROCEDURE spwithrows;` - sqltextrun := `spwithrows` - - db.ExecContext(ctx, sqltextdrop) - _, err = db.ExecContext(ctx, sqltextcreate) - if err != nil { - t.Fatal(err) - } - defer db.ExecContext(ctx, sqltextdrop) - if err != nil { - t.Error(err) - } - - var intparam int = 5 - rows, err := db.QueryContext(ctx, sqltextrun, - sql.Named("intparam", sql.Out{Dest: &intparam}), - ) - if err != nil { - t.Error(err) - } - // reading first row - if !rows.Next() { - t.Error("Next returned false") - } - var rowval int - err = rows.Scan(&rowval) - if err != nil { - t.Error(err) - } - if rowval != 5 { - t.Errorf("expected 5, got %d", rowval) - } - - // if uncommented would trigger race condition warning - //if intparam != 10 { - // t.Log("output parameter value is not yet 10, it is ", intparam) - //} - - // reading second row - if !rows.Next() { - t.Error("Next returned false") - } - err = rows.Scan(&rowval) - if err != nil { - t.Error(err) - } - if rowval != 20 { - t.Errorf("expected 20, got %d", rowval) - } - - if rows.Next() { - t.Error("Next returned true but should return false after last row was returned") - } - - if intparam != 10 { - t.Errorf("expected 10, got %d", intparam) - } - }) - - t.Run("sp with no rows", func(t *testing.T) { - sqltextcreate := ` -CREATE PROCEDURE abassign - @aid INT = 5, - @bid INT = NULL OUTPUT, - @cstr NVARCHAR(2000) = NULL OUTPUT, - @datetime datetime = NULL OUTPUT -AS -BEGIN - SELECT @bid = @aid, @cstr = 'OK', @datetime = '2010-01-01T00:00:00'; -END; -` - sqltextdrop := `DROP PROCEDURE abassign;` - sqltextrun := `abassign` - - db.ExecContext(ctx, sqltextdrop) - _, err = db.ExecContext(ctx, sqltextcreate) - if err != nil { - t.Fatal(err) - } - defer db.ExecContext(ctx, sqltextdrop) - if err != nil { - t.Error(err) - } - - t.Run("should work", func(t *testing.T) { - var bout int64 - var cout string - _, err = db.ExecContext(ctx, sqltextrun, - sql.Named("aid", 5), - sql.Named("bid", sql.Out{Dest: &bout}), - sql.Named("cstr", sql.Out{Dest: &cout}), - ) - if err != nil { - t.Error(err) - } - - if bout != 5 { - t.Errorf("expected 5, got %d", bout) - } - - if cout != "OK" { - t.Errorf("expected OK, got %s", cout) - } - }) - - t.Run("should work if aid is not passed", func(t *testing.T) { - var bout int64 - var cout string - _, err = db.ExecContext(ctx, sqltextrun, - sql.Named("bid", sql.Out{Dest: &bout}), - sql.Named("cstr", sql.Out{Dest: &cout}), - ) - if err != nil { - t.Error(err) - } - - if bout != 5 { - t.Errorf("expected 5, got %d", bout) - } - - if cout != "OK" { - t.Errorf("expected OK, got %s", cout) - } - }) - - t.Run("should work for DateTime1 parameter", func(t *testing.T) { - tin, err := time.Parse(time.RFC3339, "2006-01-02T22:04:05-07:00") - if err != nil { - t.Fatal(err) - } - expected, err := time.Parse(time.RFC3339, "2010-01-01T00:00:00-00:00") - if err != nil { - t.Fatal(err) - } - var datetime_param DateTime1 - datetime_param = DateTime1(tin) - _, err = db.ExecContext(ctx, sqltextrun, - sql.Named("datetime", sql.Out{Dest: &datetime_param}), - ) - if err != nil { - t.Error(err) - } - if time.Time(datetime_param).UTC() != expected.UTC() { - t.Errorf("Datetime returned '%v' does not match expected value '%v'", - time.Time(datetime_param).UTC(), expected.UTC()) - } - }) - - t.Run("destination is not a pointer", func(t *testing.T) { - var int_out int64 - var str_out string - // test when destination is not a pointer - _, actual := db.ExecContext(ctx, sqltextrun, - sql.Named("bid", sql.Out{Dest: int_out}), - sql.Named("cstr", sql.Out{Dest: &str_out}), - ) - pattern := ".*destination not a pointer.*" - match, err := regexp.MatchString(pattern, actual.Error()) - if err != nil { - t.Error(err) - } - if !match { - t.Errorf("Error '%v', does not match pattern '%v'.", actual, pattern) - } - }) - - t.Run("should convert int64 to int", func(t *testing.T) { - var bout int - var cout string - _, err := db.ExecContext(ctx, sqltextrun, - sql.Named("bid", sql.Out{Dest: &bout}), - sql.Named("cstr", sql.Out{Dest: &cout}), - ) - if err != nil { - t.Error(err) - } - - if bout != 5 { - t.Errorf("expected 5, got %d", bout) - } - }) - - t.Run("should fail if destination has invalid type", func(t *testing.T) { - // Error type should not be supported - var err_out Error - _, err := db.ExecContext(ctx, sqltextrun, - sql.Named("bid", sql.Out{Dest: &err_out}), - ) - if err == nil { - t.Error("Expected to fail but it didn't") - } - - // double inderection should not work - var out_out = sql.Out{Dest: &err_out} - _, err = db.ExecContext(ctx, sqltextrun, - sql.Named("bid", sql.Out{Dest: out_out}), - ) - if err == nil { - t.Error("Expected to fail but it didn't") - } - }) - - t.Run("should fail if parameter has invalid type", func(t *testing.T) { - // passing invalid parameter type - var err_val Error - _, err = db.ExecContext(ctx, sqltextrun, err_val) - if err == nil { - t.Error("Expected to fail but it didn't") - } - }) - - t.Run("destination is a nil pointer", func(t *testing.T) { - var str_out string - // test when destination is nil pointer - _, actual := db.ExecContext(ctx, sqltextrun, - sql.Named("bid", sql.Out{Dest: nil}), - sql.Named("cstr", sql.Out{Dest: &str_out}), - ) - pattern := ".*destination is a nil pointer.*" - match, err := regexp.MatchString(pattern, actual.Error()) - if err != nil { - t.Error(err) - } - if !match { - t.Errorf("Error '%v', does not match pattern '%v'.", actual, pattern) - } - }) - - t.Run("destination is a nil pointer 2", func(t *testing.T) { - var int_ptr *int - _, actual := db.ExecContext(ctx, sqltextrun, - sql.Named("bid", sql.Out{Dest: int_ptr}), - ) - pattern := ".*destination is a nil pointer.*" - match, err := regexp.MatchString(pattern, actual.Error()) - if err != nil { - t.Error(err) - } - if !match { - t.Errorf("Error '%v', does not match pattern '%v'.", actual, pattern) - } - }) - - t.Run("pointer to a pointer", func(t *testing.T) { - var str_out *string - _, actual := db.ExecContext(ctx, sqltextrun, - sql.Named("cstr", sql.Out{Dest: &str_out}), - ) - pattern := ".*destination is a pointer to a pointer.*" - match, err := regexp.MatchString(pattern, actual.Error()) - if err != nil { - t.Error(err) - } - if !match { - t.Errorf("Error '%v', does not match pattern '%v'.", actual, pattern) - } - }) - }) -} - -func TestOutputINOUTParam(t *testing.T) { - sqltextcreate := ` -CREATE PROCEDURE abinout - @aid INT = 1, - @bid INT = 2 OUTPUT, - @cstr NVARCHAR(2000) = NULL OUTPUT, - @vout VARCHAR(2000) = NULL OUTPUT, - @nullint INT = NULL OUTPUT, - @nullfloat FLOAT = NULL OUTPUT, - @nullstr NVARCHAR(10) = NULL OUTPUT, - @nullbit BIT = NULL OUTPUT, - @varbin VARBINARY(10) = NULL OUTPUT -AS -BEGIN - SELECT - @bid = @aid + @bid, - @cstr = 'OK', - @Vout = 'DREAM' - ; -END; -` - sqltextdrop := `DROP PROCEDURE abinout;` - sqltextrun := `abinout` - - checkConnStr(t) - SetLogger(testLogger{t}) - - db, err := sql.Open("sqlserver", makeConnStr(t).String()) - if err != nil { - t.Fatalf("failed to open driver sqlserver") - } - defer db.Close() - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - db.ExecContext(ctx, sqltextdrop) - _, err = db.ExecContext(ctx, sqltextcreate) - if err != nil { - t.Fatal(err) - } - defer db.ExecContext(ctx, sqltextdrop) - - t.Run("original test", func(t *testing.T) { - var bout int64 = 3 - var cout string - var vout VarChar - _, err = db.ExecContext(ctx, sqltextrun, - sql.Named("aid", 5), - sql.Named("bid", sql.Out{Dest: &bout}), - sql.Named("cstr", sql.Out{Dest: &cout}), - sql.Named("vout", sql.Out{Dest: &vout}), - ) - if err != nil { - t.Error(err) - } - - if bout != 8 { - t.Errorf("expected 8, got %d", bout) - } - - if cout != "OK" { - t.Errorf("expected OK, got %s", cout) - } - if string(vout) != "DREAM" { - t.Errorf("expected DREAM, got %s", vout) - } - }) - - t.Run("test null values returned into nullable", func(t *testing.T) { - var nullint sql.NullInt64 - var nullfloat sql.NullFloat64 - var nullstr sql.NullString - var nullbit sql.NullBool - _, err = db.ExecContext(ctx, sqltextrun, - sql.Named("nullint", sql.Out{Dest: &nullint}), - sql.Named("nullfloat", sql.Out{Dest: &nullfloat}), - sql.Named("nullstr", sql.Out{Dest: &nullstr}), - sql.Named("nullbit", sql.Out{Dest: &nullbit}), - ) - if err != nil { - t.Error(err) - } - - if nullint.Valid { - t.Errorf("expected NULL, got %v", nullint) - } - if nullfloat.Valid { - t.Errorf("expected NULL, got %v", nullfloat) - } - if nullstr.Valid { - t.Errorf("expected NULL, got %v", nullstr) - } - if nullbit.Valid { - t.Errorf("expected NULL, got %v", nullbit) - } - }) - - // Not yet supported - //t.Run("test null values returned into pointers", func(t *testing.T) { - // var nullint *int64 - // var nullfloat *float64 - // var nullstr *string - // var nullbit *bool - // _, err = db.ExecContext(ctx, sqltextrun, - // sql.Named("nullint", sql.Out{Dest: &nullint}), - // sql.Named("nullfloat", sql.Out{Dest: &nullfloat}), - // sql.Named("nullstr", sql.Out{Dest: &nullstr}), - // sql.Named("nullbit", sql.Out{Dest: &nullbit}), - // ) - // if err != nil { - // t.Error(err) - // } - - // if nullint != nil { - // t.Errorf("expected NULL, got %v", nullint) - // } - // if nullfloat != nil { - // t.Errorf("expected NULL, got %v", nullfloat) - // } - // if nullstr != nil { - // t.Errorf("expected NULL, got %v", nullstr) - // } - // if nullbit != nil { - // t.Errorf("expected NULL, got %v", nullbit) - // } - //}) - - t.Run("test non null values into nullable", func(t *testing.T) { - nullint := sql.NullInt64{10, true} - nullfloat := sql.NullFloat64{1.5, true} - nullstr := sql.NullString{"hello", true} - nullbit := sql.NullBool{true, true} - _, err = db.ExecContext(ctx, sqltextrun, - sql.Named("nullint", sql.Out{Dest: &nullint}), - sql.Named("nullfloat", sql.Out{Dest: &nullfloat}), - sql.Named("nullstr", sql.Out{Dest: &nullstr}), - sql.Named("nullbit", sql.Out{Dest: &nullbit}), - ) - if err != nil { - t.Error(err) - } - if !nullint.Valid { - t.Error("expected non null value, but got null") - } - if nullint.Int64 != 10 { - t.Errorf("expected 10, got %d", nullint.Int64) - } - if !nullfloat.Valid { - t.Error("expected non null value, but got null") - } - if nullfloat.Float64 != 1.5 { - t.Errorf("expected 1.5, got %v", nullfloat.Float64) - } - if !nullstr.Valid { - t.Error("expected non null value, but got null") - } - if nullstr.String != "hello" { - t.Errorf("expected hello, got %s", nullstr.String) - } - }) - t.Run("test return into byte[]", func(t *testing.T) { - cstr := []byte{1, 2, 3} - _, err = db.ExecContext(ctx, sqltextrun, - sql.Named("varbin", sql.Out{Dest: &cstr}), - ) - if err != nil { - t.Error(err) - } - expected := []byte{1, 2, 3} - if bytes.Compare(cstr, expected) != 0 { - t.Errorf("expected [1,2,3], got %v", cstr) - } - }) - t.Run("test int into string", func(t *testing.T) { - var str string - _, err = db.ExecContext(ctx, sqltextrun, - sql.Named("bid", sql.Out{Dest: &str}), - ) - if err != nil { - t.Error(err) - } - if str != "1" { - t.Errorf("expected '1', got %v", str) - } - }) - t.Run("typeless null for output parameter should return error", func(t *testing.T) { - var val interface{} - _, actual := db.ExecContext(ctx, sqltextrun, - sql.Named("bid", sql.Out{Dest: &val}), - ) - if actual == nil { - t.Error("Expected to fail but didn't") - } - pattern := ".*MSSQL does not allow NULL value without type for OUTPUT parameters.*" - match, err := regexp.MatchString(pattern, actual.Error()) - if err != nil { - t.Error(err) - } - if !match { - t.Errorf("Error '%v', does not match pattern '%v'.", actual, pattern) - } - }) -} - -// TestTLSServerReadClose tests writing to an encrypted database connection. -// Currently the database server will close the connection while the server is -// reading the TDS packets and before any of the data has been parsed. -// -// When two queries are sent in reverse order, they PASS, but if we send only -// a single ping (SELECT 1;) first, then the long query the query fails. -// -// The long query text is never parsed. In fact, you can comment out, return -// early, or have malformed sql in the long query text. Just the length matters. -// The error happens when sending the TDS Batch packet to SQL Server the server -// closes the connection.. -// -// It appears the driver sends valid TDS packets. In fact, if prefixed with 4 -// "SELECT 1;" TDS Batch queries then the long query works, but if zero or one -// "SELECT 1;" TDS Batch queries are send prior the long query fails to send. -// -// Lastly, this only manafests itself with an encrypted connection. This has been -// observed with SQL Server Azure, SQL Server 13.0.1742 on Windows, and SQL Server -// 14.0.900.75 on Linux. It also fails when using the "dev.boringcrypto" (a C based -// TLS crypto). I haven't found any knobs on SQL Server to expose the error message -// nor have I found a good way to decrypt the TDS stream. KeyLogWriter in the TLS -// config may help with that, but wireshark wasn't decrypting TDS based TLS streams -// even when using that. -// -// Issue https://github.com/denisenkom/go-mssqldb/issues/166 -func TestTLSServerReadClose(t *testing.T) { - query := ` -with - config_cte (config) as ( - select * - from ( values - ('_partition:{\"Fill\":{\"PatternType\":\"solid\",\"FgColor\":\"99ff99\"}}') - , ('_separation:{\"Fill\":{\"PatternType\":\"solid\",\"FgColor\":\"99ffff\"}}') - , ('Monthly Earnings:\$#,##0.00 ;(\$#,##0.00)') - , ('Weekly Earnings:\$#,##0.00 ;(\$#,##0.00)') - , ('Total Earnings:\$#,##0.00 ;(\$#,##0.00)') - , ('Average Earnings:\$#,##0.00 ;(\$#,##0.00)') - , ('Last Month Earning:#,##0.00 ;(#,##0.00)') - , ('Award:\$#,##0.00 ;(\$#,##0.00)') - , ('Amount:\$#,##0.00 ;(\$#,##0.00)') - , ('Grand Total:\$#,##0.00 ;(\$#,##0.00)') - , ('Total:\$#,##0.00 ;(\$#,##0.00)') - , ('Price Each:\$#,##0.00 ;(\$#,##0.00)') - , ('Hyperwallet:\$#,##0.00 ;(\$#,##0.00)') - , ('Credit/Debit:\$#,##0.00 ;(\$#,##0.00)') - , ('Earning:#,##0.00 ;(#,##0.00)') - , ('Change Earning:#,##0.00 ;(#,##0.00)') - , ('CheckAmount:#,##0.00 ;(#,##0.00)') - , ('Residual:#,##0.00 ;(#,##0.00)') - , ('Prev Residual:#,##0.00 ;(#,##0.00)') - , ('Team Bonuses:#,##0.00 ;(#,##0.00)') - , ('Change:#,##0.00 ;(#,##0.00)') - , ('Shipping Total:#,##0.00 ;(#,##0.00)') - , ('SubTotal:\$#,##0.00 ;(\$#,##0.00)') - , ('Total Diff:#,##0.00 ;(#,##0.00)') - , ('SubTotal Diff:#,##0.00 ;(#,##0.00)') - , ('Return Total:#,##0.00 ;(#,##0.00)') - , ('Return SubTotal:#,##0.00 ;(#,##0.00)') - , ('Return Total Diff:#,##0.00 ;(#,##0.00)') - , ('Return SubTotal Diff:#,##0.00 ;(#,##0.00)') - , ('Cancel Total:#,##0.00 ;(#,##0.00)') - , ('Cancel SubTotal:#,##0.00 ;(#,##0.00)') - , ('Cancel Total Diff:#,##0.00 ;(#,##0.00)') - , ('Cancel SubTotal Diff:#,##0.00 ;(#,##0.00)') - , ('Replacement Total:#,##0.00 ;(#,##0.00)') - , ('Replacement SubTotal:#,##0.00 ;(#,##0.00)') - , ('Replacement Total Diff:#,##0.00 ;(#,##0.00)') - , ('Replacement SubTotal Diff:#,##0.00 ;(#,##0.00)') - , ('Jan Residual:#,##0.00 ;(#,##0.00)') - , ('Jan Bonus:#,##0.00 ;(#,##0.00)') - , ('Jan Total:#,##0.00 ;(#,##0.00)') - , ('January Residual:#,##0.00 ;(#,##0.00)') - , ('Feb Residual:#,##0.00 ;(#,##0.00)') - , ('Feb Bonus:#,##0.00 ;(#,##0.00)') - , ('Feb Total:#,##0.00 ;(#,##0.00)') - , ('February Residual:#,##0.00 ;(#,##0.00)') - , ('Mar Residual:#,##0.00 ;(#,##0.00)') - , ('Mar Bonus:#,##0.00 ;(#,##0.00)') - , ('Mar Total:#,##0.00 ;(#,##0.00)') - , ('March Residual:#,##0.00 ;(#,##0.00)') - , ('Apr Residual:#,##0.00 ;(#,##0.00)') - , ('Apr Bonus:#,##0.00 ;(#,##0.00)') - , ('Apr Total:#,##0.00 ;(#,##0.00)') - , ('April Residual:#,##0.00 ;(#,##0.00)') - , ('May Residual:#,##0.00 ;(#,##0.00)') - , ('May Bonus:#,##0.00 ;(#,##0.00)') - , ('May Total:#,##0.00 ;(#,##0.00)') - , ('Jun Residual:#,##0.00 ;(#,##0.00)') - , ('Jun Bonus:#,##0.00 ;(#,##0.00)') - , ('Jun Total:#,##0.00 ;(#,##0.00)') - , ('June Residual:#,##0.00 ;(#,##0.00)') - , ('Jul Residual:#,##0.00 ;(#,##0.00)') - , ('Jul Bonus:#,##0.00 ;(#,##0.00)') - , ('Jul Total:#,##0.00 ;(#,##0.00)') - , ('July Residual:#,##0.00 ;(#,##0.00)') - , ('Aug Residual:#,##0.00 ;(#,##0.00)') - , ('Aug Bonus:#,##0.00 ;(#,##0.00)') - , ('Aug Total:#,##0.00 ;(#,##0.00)') - , ('August Residual:#,##0.00 ;(#,##0.00)') - , ('Sep Residual:#,##0.00 ;(#,##0.00)') - , ('Sep Bonus:#,##0.00 ;(#,##0.00)') - , ('Sep Total:#,##0.00 ;(#,##0.00)') - , ('September Residual:#,##0.00 ;(#,##0.00)') - , ('Oct Residual:#,##0.00 ;(#,##0.00)') - , ('Oct Bonus:#,##0.00 ;(#,##0.00)') - , ('Oct Total:#,##0.00 ;(#,##0.00)') - , ('October Residual:#,##0.00 ;(#,##0.00)') - , ('Nov Residual:#,##0.00 ;(#,##0.00)') - , ('Nov Bonus:#,##0.00 ;(#,##0.00)') - , ('Nov Total:#,##0.00 ;(#,##0.00)') - , ('November Residual:#,##0.00 ;(#,##0.00)') - , ('Dec Residual:#,##0.00 ;(#,##0.00)') - , ('Dec Bonus:#,##0.00 ;(#,##0.00)') - , ('Dec Total:#,##0.00 ;(#,##0.00)') - , ('December Residual:#,##0.00 ;(#,##0.00)') - , ('January Bonus:#,##0.00 ;(#,##0.00)') - , ('February Bonus:#,##0.00 ;(#,##0.00)') - , ('March Bonus:#,##0.00 ;(#,##0.00)') - , ('April Bonus:#,##0.00 ;(#,##0.00)') - , ('May Bonus:#,##0.00 ;(#,##0.00)') - , ('June Bonus:#,##0.00 ;(#,##0.00)') - , ('July Bonus:#,##0.00 ;(#,##0.00)') - , ('August Bonus:#,##0.00 ;(#,##0.00)') - , ('September Bonus:#,##0.00 ;(#,##0.00)') - , ('October Bonus:#,##0.00 ;(#,##0.00)') - , ('November Bonus:#,##0.00 ;(#,##0.00)') - , ('December Bonus:#,##0.00 ;(#,##0.00)') - , ('January Adj:#,##0.00 ;(#,##0.00)') - , ('February Adj:#,##0.00 ;(#,##0.00)') - , ('March Adj:#,##0.00 ;(#,##0.00)') - , ('April Adj:#,##0.00 ;(#,##0.00)') - , ('May Adj:#,##0.00 ;(#,##0.00)') - , ('June Adj:#,##0.00 ;(#,##0.00)') - , ('July Adj:#,##0.00 ;(#,##0.00)') - , ('August Adj:#,##0.00 ;(#,##0.00)') - , ('September Adj:#,##0.00 ;(#,##0.00)') - , ('October Adj:#,##0.00 ;(#,##0.00)') - , ('November Adj:#,##0.00 ;(#,##0.00)') - , ('December Adj:#,##0.00 ;(#,##0.00)') - , ('2016- 2015 YTD Dif:#,##0.00 ;(#,##0.00)') - , ('2017- 2016 YTD Dif:#,##0.00 ;(#,##0.00)') - , ('2018- 2017 YTD Dif:#,##0.00 ;(#,##0.00)') - , ('Dec to Jan Dif Residual:#,##0.00 ;(#,##0.00)') - , ('Jan to Feb Dif Residual:#,##0.00 ;(#,##0.00)') - , ('Feb to Mar Dif Residual:#,##0.00 ;(#,##0.00)') - , ('Mar to Apr Dif Residual:#,##0.00 ;(#,##0.00)') - , ('Apr to May Dif Residual:#,##0.00 ;(#,##0.00)') - , ('May to Jun Dif Residual:#,##0.00 ;(#,##0.00)') - , ('Jun to Jul Dif Residual:#,##0.00 ;(#,##0.00)') - , ('Jul to Aug Dif Residual:#,##0.00 ;(#,##0.00)') - , ('Aug to Sep Dif Residual:#,##0.00 ;(#,##0.00)') - , ('Sep to Oct Dif Residual:#,##0.00 ;(#,##0.00)') - , ('Oct to Nov Dif Residual:#,##0.00 ;(#,##0.00)') - , ('Nov to Dec Dif Residual:#,##0.00 ;(#,##0.00)') - , ('Dec to Jan Dif Bonus:#,##0.00 ;(#,##0.00)') - , ('Jan to Feb Dif Bonus:#,##0.00 ;(#,##0.00)') - , ('Feb to Mar Dif Bonus:#,##0.00 ;(#,##0.00)') - , ('Mar to Apr Dif Bonus:#,##0.00 ;(#,##0.00)') - , ('Apr to May Dif Bonus:#,##0.00 ;(#,##0.00)') - , ('May to Jun Dif Bonus:#,##0.00 ;(#,##0.00)') - , ('Jun to Jul Dif Bonus:#,##0.00 ;(#,##0.00)') - , ('Jul to Aug Dif Bonus:#,##0.00 ;(#,##0.00)') - , ('Aug to Sep Dif Bonus:#,##0.00 ;(#,##0.00)') - , ('Sep to Oct Dif Bonus:#,##0.00 ;(#,##0.00)') - , ('Oct to Nov Dif Bonus:#,##0.00 ;(#,##0.00)') - , ('Nov to Dec Dif Bonus:#,##0.00 ;(#,##0.00)') - , ('Dec to Jan Dif Total:#,##0.00 ;(#,##0.00)') - , ('Jan to Feb Dif Total:#,##0.00 ;(#,##0.00)') - , ('Feb to Mar Dif Total:#,##0.00 ;(#,##0.00)') - , ('Mar to Apr Dif Total:#,##0.00 ;(#,##0.00)') - , ('Apr to May Dif Total:#,##0.00 ;(#,##0.00)') - , ('May to Jun Dif Total:#,##0.00 ;(#,##0.00)') - , ('Jun to Jul Dif Total:#,##0.00 ;(#,##0.00)') - , ('Jul to Aug Dif Total:#,##0.00 ;(#,##0.00)') - , ('Aug to Sep Dif Total:#,##0.00 ;(#,##0.00)') - , ('Sep to Oct Dif Total:#,##0.00 ;(#,##0.00)') - , ('Oct to Nov Dif Total:#,##0.00 ;(#,##0.00)') - , ('Nov to Dec Dif Total:#,##0.00 ;(#,##0.00)') - , ('Jan Refund Cnt:#,##0 ;(#,##0)') - , ('Feb Refund Cnt:#,##0 ;(#,##0)') - , ('Mar Refund Cnt:#,##0 ;(#,##0)') - , ('Apr Refund Cnt:#,##0 ;(#,##0)') - , ('May Refund Cnt:#,##0 ;(#,##0)') - , ('Jun Refund Cnt:#,##0 ;(#,##0)') - , ('Jul Refund Cnt:#,##0 ;(#,##0)') - , ('Aug Refund Cnt:#,##0 ;(#,##0)') - , ('Sep Refund Cnt:#,##0 ;(#,##0)') - , ('Oct Refund Cnt:#,##0 ;(#,##0)') - , ('Nov Refund Cnt:#,##0 ;(#,##0)') - , ('Dec Refund Cnt:#,##0 ;(#,##0)') - , ('Jan Purchase Cnt:#,##0 ;(#,##0)') - , ('Feb Purchase Cnt:#,##0 ;(#,##0)') - , ('Mar Purchase Cnt:#,##0 ;(#,##0)') - , ('Apr Purchase Cnt:#,##0 ;(#,##0)') - , ('May Purchase Cnt:#,##0 ;(#,##0)') - , ('Jun Purchase Cnt:#,##0 ;(#,##0)') - , ('Jul Purchase Cnt:#,##0 ;(#,##0)') - , ('Aug Purchase Cnt:#,##0 ;(#,##0)') - , ('Sep Purchase Cnt:#,##0 ;(#,##0)') - , ('Oct Purchase Cnt:#,##0 ;(#,##0)') - , ('Nov Purchase Cnt:#,##0 ;(#,##0)') - , ('Dec Purchase Cnt:#,##0 ;(#,##0)') - , ('Jan Refund Amt:#,##0.00 ;(#,##0.00)') - , ('Feb Refund Amt:#,##0.00 ;(#,##0.00)') - , ('Mar Refund Amt:#,##0.00 ;(#,##0.00)') - , ('Apr Refund Amt:#,##0.00 ;(#,##0.00)') - , ('May Refund Amt:#,##0.00 ;(#,##0.00)') - , ('Jun Refund Amt:#,##0.00 ;(#,##0.00)') - , ('Jul Refund Amt:#,##0.00 ;(#,##0.00)') - , ('Aug Refund Amt:#,##0.00 ;(#,##0.00)') - , ('Sep Refund Amt:#,##0.00 ;(#,##0.00)') - , ('Oct Refund Amt:#,##0.00 ;(#,##0.00)') - , ('Nov Refund Amt:#,##0.00 ;(#,##0.00)') - , ('Dec Refund Amt:#,##0.00 ;(#,##0.00)') - , ('Jan Purchase Amt:#,##0.00 ;(#,##0.00)') - , ('Feb Purchase Amt:#,##0.00 ;(#,##0.00)') - , ('Mar Purchase Amt:#,##0.00 ;(#,##0.00)') - , ('Apr Purchase Amt:#,##0.00 ;(#,##0.00)') - , ('May Purchase Amt:#,##0.00 ;(#,##0.00)') - , ('Jun Purchase Amt:#,##0.00 ;(#,##0.00)') - , ('Jul Purchase Amt:#,##0.00 ;(#,##0.00)') - , ('Aug Purchase Amt:#,##0.00 ;(#,##0.00)') - , ('Sep Purchase Amt:#,##0.00 ;(#,##0.00)') - , ('Oct Purchase Amt:#,##0.00 ;(#,##0.00)') - , ('Nov Purchase Amt:#,##0.00 ;(#,##0.00)') - , ('Dec Purchase Amt:#,##0.00 ;(#,##0.00)') - ) X(a)) - select * from config_cte - ` - t.Logf("query len (utf16 bytes)=%d, len/4096=%f\n", len(query)*2, float64(len(query)*2)/4096) - - db := open(t) - defer db.Close() - - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - - type run struct { - name string - pings []int - pass bool - - conn *sql.Conn - } - - // Use separate Conns from the connection pool to ensure separation. - runs := []*run{ - {name: "rev", pings: []int{4, 1}, pass: true}, - {name: "forward", pings: []int{1}, pass: true}, - } - for _, r := range runs { - var err error - r.conn, err = db.Conn(ctx) - if err != nil { - t.Fatal(err) - } - defer r.conn.Close() - } - - for _, r := range runs { - for _, ping := range r.pings { - t.Run(fmt.Sprintf("%s-ping-%d", r.name, ping), func(t *testing.T) { - for i := 0; i < ping; i++ { - if err := r.conn.PingContext(ctx); err != nil { - if r.pass { - t.Error("failed to ping server", err) - } else { - t.Log("failed to ping server", err) - } - return - } - } - - rows, err := r.conn.QueryContext(ctx, query) - if err != nil { - if r.pass { - t.Errorf("QueryContext: %+v", err) - } else { - t.Logf("QueryContext: %+v", err) - } - return - } - for rows.Next() { - // Nothing. - } - rows.Close() - }) - } - } -} - -func TestDateTimeParam19(t *testing.T) { - conn := open(t) - defer conn.Close() - - // testing DateTime1, only supported on go 1.9 - var emptydate time.Time - mindate1 := time.Date(1753, 1, 1, 0, 0, 0, 0, time.UTC) - maxdate1 := time.Date(9999, 12, 31, 23, 59, 59, 997000000, time.UTC) - testdates1 := []DateTime1{ - DateTime1(mindate1), - DateTime1(maxdate1), - DateTime1(time.Date(1752, 12, 31, 23, 59, 59, 997000000, time.UTC)), // just a little below minimum date - DateTime1(time.Date(10000, 1, 1, 0, 0, 0, 0, time.UTC)), // just a little over maximum date - DateTime1(emptydate), - } - - for _, test := range testdates1 { - t.Run(fmt.Sprintf("Test datetime for %v", test), func(t *testing.T) { - var res time.Time - expected := time.Time(test) - queryParamRoundTrip(conn, test, &res) - // clip value - if expected.Before(mindate1) { - expected = mindate1 - } - if expected.After(maxdate1) { - expected = maxdate1 - } - if expected.Sub(res) != 0 { - t.Errorf("expected: '%s', got: '%s' delta: %d", expected, res, expected.Sub(res)) - } - }) - } -} - -func TestReturnStatus(t *testing.T) { - conn := open(t) - defer conn.Close() - - _, err := conn.Exec("if object_id('retstatus') is not null drop proc retstatus;") - if err != nil { - t.Fatal(err) - } - _, err = conn.Exec("create proc retstatus as return 2;") - if err != nil { - t.Fatal(err) - } - - var rs ReturnStatus - _, err = conn.Exec("retstatus", &rs) - conn.Exec("drop proc retstatus;") - if err != nil { - t.Fatal(err) - } - if rs != 2 { - t.Errorf("expected status=2, got %d", rs) - } -} diff --git a/vendor/github.com/denisenkom/go-mssqldb/queries_test.go b/vendor/github.com/denisenkom/go-mssqldb/queries_test.go deleted file mode 100644 index 255de306..00000000 --- a/vendor/github.com/denisenkom/go-mssqldb/queries_test.go +++ /dev/null @@ -1,2186 +0,0 @@ -package mssql - -import ( - "bytes" - "context" - "database/sql" - "database/sql/driver" - "fmt" - "log" - "math" - "net" - "reflect" - "strings" - "sync" - "testing" - "time" -) - -func driverWithProcess(t *testing.T) *Driver { - return &Driver{ - log: optionalLogger{testLogger{t}}, - processQueryText: true, - } -} -func driverNoProcess(t *testing.T) *Driver { - return &Driver{ - log: optionalLogger{testLogger{t}}, - processQueryText: false, - } -} - -func TestSelect(t *testing.T) { - conn := open(t) - defer conn.Close() - - t.Run("scan into interface{}", func(t *testing.T) { - type testStruct struct { - sql string - val interface{} - } - - longstr := strings.Repeat("x", 10000) - - values := []testStruct{ - {"1", int64(1)}, - {"-1", int64(-1)}, - {"cast(1 as int)", int64(1)}, - {"cast(-1 as int)", int64(-1)}, - {"cast(1 as tinyint)", int64(1)}, - {"cast(255 as tinyint)", int64(255)}, - {"cast(1 as smallint)", int64(1)}, - {"cast(-1 as smallint)", int64(-1)}, - {"cast(1 as bigint)", int64(1)}, - {"cast(-1 as bigint)", int64(-1)}, - {"cast(1 as bit)", true}, - {"cast(0 as bit)", false}, - {"'abc'", string("abc")}, - {"cast(0.5 as float)", float64(0.5)}, - {"cast(0.5 as real)", float64(0.5)}, - {"cast(1 as decimal)", []byte("1")}, - {"cast(1.2345 as money)", []byte("1.2345")}, - {"cast(-1.2345 as money)", []byte("-1.2345")}, - {"cast(1.2345 as smallmoney)", []byte("1.2345")}, - {"cast(-1.2345 as smallmoney)", []byte("-1.2345")}, - {"cast(0.5 as decimal(18,1))", []byte("0.5")}, - {"cast(-0.5 as decimal(18,1))", []byte("-0.5")}, - {"cast(-0.5 as numeric(18,1))", []byte("-0.5")}, - {"cast(4294967296 as numeric(20,0))", []byte("4294967296")}, - {"cast(-0.5 as numeric(18,2))", []byte("-0.50")}, - {"N'abc'", string("abc")}, - {"cast(null as nvarchar(3))", nil}, - {"NULL", nil}, - {"cast('1753-01-01' as datetime)", time.Date(1753, 1, 1, 0, 0, 0, 0, time.UTC)}, - {"cast('2000-01-01' as datetime)", time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)}, - {"cast('2000-01-01T12:13:14.12' as datetime)", - time.Date(2000, 1, 1, 12, 13, 14, 120000000, time.UTC)}, - {"cast('2014-06-26 11:08:09.673' as datetime)", time.Date(2014, 06, 26, 11, 8, 9, 673000000, time.UTC)}, - {"cast('9999-12-31T23:59:59.997' as datetime)", time.Date(9999, 12, 31, 23, 59, 59, 997000000, time.UTC)}, - {"cast(NULL as datetime)", nil}, - {"cast('1900-01-01T00:00:00' as smalldatetime)", - time.Date(1900, 1, 1, 0, 0, 0, 0, time.UTC)}, - {"cast('2000-01-01T12:13:00' as smalldatetime)", - time.Date(2000, 1, 1, 12, 13, 0, 0, time.UTC)}, - {"cast('2079-06-06T23:59:00' as smalldatetime)", - time.Date(2079, 6, 6, 23, 59, 0, 0, time.UTC)}, - {"cast(NULL as smalldatetime)", nil}, - {"cast(0x6F9619FF8B86D011B42D00C04FC964FF as uniqueidentifier)", - []byte{0x6F, 0x96, 0x19, 0xFF, 0x8B, 0x86, 0xD0, 0x11, 0xB4, 0x2D, 0x00, 0xC0, 0x4F, 0xC9, 0x64, 0xFF}}, - {"cast(NULL as uniqueidentifier)", nil}, - {"cast(0x1234 as varbinary(2))", []byte{0x12, 0x34}}, - {"cast(N'abc' as nvarchar(max))", "abc"}, - {"cast(null as nvarchar(max))", nil}, - {"cast('' as xml)", ""}, - {"cast('abc' as text)", "abc"}, - {"cast(null as text)", nil}, - {"cast(N'abc' as ntext)", "abc"}, - {"cast(0x1234 as image)", []byte{0x12, 0x34}}, - {"cast('abc' as char(3))", "abc"}, - {"cast('abc' as varchar(3))", "abc"}, - {"cast(N'проверка' as nvarchar(max))", "проверка"}, - {"cast(N'Δοκιμή' as nvarchar(max))", "Δοκιμή"}, - {"cast(cast(N'สวัสดี' as nvarchar(max)) collate Thai_CI_AI as varchar(max))", "สวัสดี"}, // cp874 - {"cast(cast(N'你好' as nvarchar(max)) collate Chinese_PRC_CI_AI as varchar(max))", "你好"}, // cp936 - {"cast(cast(N'こんにちは' as nvarchar(max)) collate Japanese_CI_AI as varchar(max))", "こんにちは"}, // cp939 - {"cast(cast(N'안녕하세요.' as nvarchar(max)) collate Korean_90_CI_AI as varchar(max))", "안녕하세요."}, // cp949 - {"cast(cast(N'你好' as nvarchar(max)) collate Chinese_Hong_Kong_Stroke_90_CI_AI as varchar(max))", "你好"}, // cp950 - {"cast(cast(N'cześć' as nvarchar(max)) collate Polish_CI_AI as varchar(max))", "cześć"}, // cp1250 - {"cast(cast(N'Алло' as nvarchar(max)) collate Cyrillic_General_CI_AI as varchar(max))", "Алло"}, // cp1251 - {"cast(cast(N'Bonjour' as nvarchar(max)) collate French_CI_AI as varchar(max))", "Bonjour"}, // cp1252 - {"cast(cast(N'Γεια σας' as nvarchar(max)) collate Greek_CI_AI as varchar(max))", "Γεια σας"}, // cp1253 - {"cast(cast(N'Merhaba' as nvarchar(max)) collate Turkish_CI_AI as varchar(max))", "Merhaba"}, // cp1254 - {"cast(cast(N'שלום' as nvarchar(max)) collate Hebrew_CI_AI as varchar(max))", "שלום"}, // cp1255 - {"cast(cast(N'مرحبا' as nvarchar(max)) collate Arabic_CI_AI as varchar(max))", "مرحبا"}, // cp1256 - {"cast(cast(N'Sveiki' as nvarchar(max)) collate Lithuanian_CI_AI as varchar(max))", "Sveiki"}, // cp1257 - {"cast(cast(N'chào' as nvarchar(max)) collate Vietnamese_CI_AI as varchar(max))", "chào"}, // cp1258 - {fmt.Sprintf("cast(N'%s' as nvarchar(max))", longstr), longstr}, - {"cast(NULL as sql_variant)", nil}, - {"cast(cast(0x6F9619FF8B86D011B42D00C04FC964FF as uniqueidentifier) as sql_variant)", - []byte{0x6F, 0x96, 0x19, 0xFF, 0x8B, 0x86, 0xD0, 0x11, 0xB4, 0x2D, 0x00, 0xC0, 0x4F, 0xC9, 0x64, 0xFF}}, - {"cast(cast(1 as bit) as sql_variant)", true}, - {"cast(cast(10 as tinyint) as sql_variant)", int64(10)}, - {"cast(cast(-10 as smallint) as sql_variant)", int64(-10)}, - {"cast(cast(-20 as int) as sql_variant)", int64(-20)}, - {"cast(cast(-20 as bigint) as sql_variant)", int64(-20)}, - {"cast(cast('2000-01-01' as datetime) as sql_variant)", time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)}, - {"cast(cast('2000-01-01T12:13:00' as smalldatetime) as sql_variant)", - time.Date(2000, 1, 1, 12, 13, 0, 0, time.UTC)}, - {"cast(cast(0.125 as real) as sql_variant)", float64(0.125)}, - {"cast(cast(0.125 as float) as sql_variant)", float64(0.125)}, - {"cast(cast(1.2345 as smallmoney) as sql_variant)", []byte("1.2345")}, - {"cast(cast(1.2345 as money) as sql_variant)", []byte("1.2345")}, - {"cast(cast(0x1234 as varbinary(2)) as sql_variant)", []byte{0x12, 0x34}}, - {"cast(cast(0x1234 as binary(2)) as sql_variant)", []byte{0x12, 0x34}}, - {"cast(cast(-0.5 as decimal(18,1)) as sql_variant)", []byte("-0.5")}, - {"cast(cast(-0.5 as numeric(18,1)) as sql_variant)", []byte("-0.5")}, - {"cast(cast('abc' as varchar(3)) as sql_variant)", "abc"}, - {"cast(cast('abc' as char(3)) as sql_variant)", "abc"}, - {"cast(N'abc' as sql_variant)", "abc"}, - } - - for _, test := range values { - t.Run(test.sql, func(t *testing.T) { - stmt, err := conn.Prepare("select " + test.sql) - if err != nil { - t.Error("Prepare failed:", test.sql, err.Error()) - return - } - defer stmt.Close() - - row := stmt.QueryRow() - var retval interface{} - err = row.Scan(&retval) - if err != nil { - t.Error("Scan failed:", test.sql, err.Error()) - return - } - var same bool - switch decodedval := retval.(type) { - case []byte: - switch decodedvaltest := test.val.(type) { - case []byte: - same = bytes.Equal(decodedval, decodedvaltest) - default: - same = false - } - default: - same = retval == test.val - } - if !same { - t.Errorf("Values don't match '%s' '%s' for test: %s", retval, test.val, test.sql) - return - } - }) - } - }) - t.Run("scan into *int64", func(t *testing.T) { - t.Run("from integer", func(t *testing.T) { - row := conn.QueryRow("select 11") - var retval *int64 - err := row.Scan(&retval) - if err != nil { - t.Error("Scan failed", err.Error()) - return - } - if *retval != 11 { - t.Errorf("Expected 11, got %v", retval) - } - }) - t.Run("from null", func(t *testing.T) { - row := conn.QueryRow("select null") - var retval *int64 - err := row.Scan(&retval) - if err != nil { - t.Error("Scan failed", err.Error()) - return - } - if retval != nil { - t.Errorf("Expected nil, got %v", retval) - } - }) - }) -} - -func TestSelectDateTimeOffset(t *testing.T) { - type testStruct struct { - sql string - val time.Time - } - values := []testStruct{ - {"cast('2010-11-15T11:56:45.123+14:00' as datetimeoffset(3))", - time.Date(2010, 11, 15, 11, 56, 45, 123000000, time.FixedZone("", 14*60*60))}, - {"cast(cast('2010-11-15T11:56:45.123-14:00' as datetimeoffset(3)) as sql_variant)", - time.Date(2010, 11, 15, 11, 56, 45, 123000000, time.FixedZone("", -14*60*60))}, - {"cast('0001-01-01T00:00:00.0000000+00:00' as datetimeoffset(7))", - time.Date(1, 1, 1, 0, 0, 0, 0, time.FixedZone("", 0))}, - {"cast('9999-12-31T23:59:59.9999999+00:00' as datetimeoffset(7))", - time.Date(9999, 12, 31, 23, 59, 59, 999999900, time.FixedZone("", 0))}, - } - - conn := open(t) - defer conn.Close() - for _, test := range values { - row := conn.QueryRow("select " + test.sql) - var retval interface{} - err := row.Scan(&retval) - if err != nil { - t.Error("Scan failed:", test.sql, err.Error()) - continue - } - retvalDate := retval.(time.Time) - if retvalDate.UTC() != test.val.UTC() { - t.Errorf("UTC values don't match '%v' '%v' for test: %s", retvalDate, test.val, test.sql) - continue - } - if retvalDate.String() != test.val.String() { - t.Errorf("Locations don't match '%v' '%v' for test: %s", retvalDate.String(), test.val.String(), test.sql) - continue - } - } -} - -func TestSelectNewTypes(t *testing.T) { - conn := open(t) - defer conn.Close() - var ver string - err := conn.QueryRow("select SERVERPROPERTY('productversion')").Scan(&ver) - if err != nil { - t.Fatalf("cannot select productversion: %s", err) - } - var n int - _, err = fmt.Sscanf(ver, "%d", &n) - if err != nil { - t.Fatalf("cannot parse productversion: %s", err) - } - // 8 is SQL 2000, 9 is SQL 2005, 10 is SQL 2008, 11 is SQL 2012 - if n < 10 { - return - } - // run tests for new data types available only in SQL Server 2008 and later - type testStruct struct { - sql string - val interface{} - } - values := []testStruct{ - {"cast('0001-01-01' as date)", - time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC)}, - {"cast('2000-01-01' as date)", - time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)}, - {"cast('9999-12-31' as date)", - time.Date(9999, 12, 31, 0, 0, 0, 0, time.UTC)}, - {"cast(NULL as date)", nil}, - {"cast('00:00:00.0000000' as time(7))", - time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC)}, - {"cast('00:00:45.123' as time(3))", - time.Date(1, 1, 1, 00, 00, 45, 123000000, time.UTC)}, - {"cast('11:56:45.123' as time(3))", - time.Date(1, 1, 1, 11, 56, 45, 123000000, time.UTC)}, - {"cast('11:56:45' as time(0))", - time.Date(1, 1, 1, 11, 56, 45, 0, time.UTC)}, - {"cast('23:59:59.9999999' as time(7))", - time.Date(1, 1, 1, 23, 59, 59, 999999900, time.UTC)}, - {"cast(null as time(0))", nil}, - {"cast('0001-01-01T00:00:00.0000000' as datetime2(7))", - time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC)}, - {"cast('2010-11-15T11:56:45.123' as datetime2(3))", - time.Date(2010, 11, 15, 11, 56, 45, 123000000, time.UTC)}, - {"cast('2010-11-15T11:56:45' as datetime2(0))", - time.Date(2010, 11, 15, 11, 56, 45, 0, time.UTC)}, - {"cast(cast('2000-01-01' as date) as sql_variant)", - time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)}, - {"cast(cast('00:00:45.123' as time(3)) as sql_variant)", - time.Date(1, 1, 1, 00, 00, 45, 123000000, time.UTC)}, - {"cast(cast('2010-11-15T11:56:45.123' as datetime2(3)) as sql_variant)", - time.Date(2010, 11, 15, 11, 56, 45, 123000000, time.UTC)}, - {"cast('9999-12-31T23:59:59.9999999' as datetime2(7))", - time.Date(9999, 12, 31, 23, 59, 59, 999999900, time.UTC)}, - {"cast(null as datetime2(3))", nil}, - } - for _, test := range values { - stmt, err := conn.Prepare("select " + test.sql) - if err != nil { - t.Error("Prepare failed:", test.sql, err.Error()) - return - } - defer stmt.Close() - - row := stmt.QueryRow() - var retval interface{} - err = row.Scan(&retval) - if err != nil { - t.Error("Scan failed:", test.sql, err.Error()) - continue - } - if retval != test.val { - t.Errorf("Values don't match '%s' '%s' for test: %s", retval, test.val, test.sql) - continue - } - } -} - -func TestTrans(t *testing.T) { - conn := open(t) - defer conn.Close() - - var tx *sql.Tx - var err error - if tx, err = conn.Begin(); err != nil { - t.Fatal("Begin failed", err.Error()) - } - if err = tx.Commit(); err != nil { - t.Fatal("Commit failed", err.Error()) - } - - if tx, err = conn.Begin(); err != nil { - t.Fatal("Begin failed", err.Error()) - } - if _, err = tx.Exec("create table #abc (fld int)"); err != nil { - t.Fatal("Create table failed", err.Error()) - } - if err = tx.Rollback(); err != nil { - t.Fatal("Rollback failed", err.Error()) - } -} - -func TestNull(t *testing.T) { - conn := open(t) - defer conn.Close() - - t.Run("scan into interface{}", func(t *testing.T) { - types := []string{ - "tinyint", - "smallint", - "int", - "bigint", - "real", - "float", - "smallmoney", - "money", - "decimal", - //"varbinary(15)", - //"binary(15)", - "nvarchar(15)", - "nchar(15)", - "varchar(15)", - "char(15)", - "bit", - "smalldatetime", - "date", - "time", - "datetime", - "datetime2", - "datetimeoffset", - "uniqueidentifier", - "sql_variant", - } - for _, typ := range types { - t.Run(typ, func(t *testing.T) { - row := conn.QueryRow("declare @x "+typ+" = ?; select @x", nil) - var retval interface{} - err := row.Scan(&retval) - if err != nil { - t.Error("Scan failed for type "+typ, err.Error()) - return - } - if retval != nil { - t.Error("Value should be nil, but it is ", retval) - return - } - }) - } - }) - - t.Run("scan into NullInt64", func(t *testing.T) { - types := []string{ - "tinyint", - "smallint", - "int", - "bigint", - "real", - "float", - "smallmoney", - "money", - "decimal", - //"varbinary(15)", - //"binary(15)", - "nvarchar(15)", - "nchar(15)", - "varchar(15)", - "char(15)", - "bit", - "smalldatetime", - "date", - "time", - "datetime", - "datetime2", - "datetimeoffset", - "uniqueidentifier", - "sql_variant", - } - for _, typ := range types { - row := conn.QueryRow("declare @x "+typ+" = ?; select @x", nil) - var retval sql.NullInt64 - err := row.Scan(&retval) - if err != nil { - t.Error("Scan failed for type "+typ, err.Error()) - return - } - if retval.Valid { - t.Error("Value should be nil, but it is ", retval) - return - } - } - }) - - t.Run("scan into *int", func(t *testing.T) { - types := []string{ - "tinyint", - "smallint", - "int", - "bigint", - "real", - "float", - "smallmoney", - "money", - "decimal", - //"varbinary(15)", - //"binary(15)", - "nvarchar(15)", - "nchar(15)", - "varchar(15)", - "char(15)", - "bit", - "smalldatetime", - "date", - "time", - "datetime", - "datetime2", - "datetimeoffset", - "uniqueidentifier", - "sql_variant", - } - for _, typ := range types { - row := conn.QueryRow("declare @x "+typ+" = ?; select @x", nil) - var retval *int - err := row.Scan(&retval) - if err != nil { - t.Error("Scan failed for type "+typ, err.Error()) - return - } - if retval != nil { - t.Error("Value should be nil, but it is ", retval) - return - } - } - }) -} - -func TestParams(t *testing.T) { - longstr := strings.Repeat("x", 10000) - longbytes := make([]byte, 10000) - testdate, err := time.Parse(time.RFC3339, "2010-01-01T00:00:00-00:00") - if err != nil { - t.Fatal(err) - } - values := []interface{}{ - int64(5), - "hello", - "", - []byte{1, 2, 3}, - []byte{}, - float64(1.12313554), - true, - false, - nil, - longstr, - longbytes, - testdate.UTC(), - } - - conn := open(t) - defer conn.Close() - - for _, val := range values { - t.Run(fmt.Sprintf("%T:%#v", val, val), func(t *testing.T) { - row := conn.QueryRow("select ?", val) - var retval interface{} - err := row.Scan(&retval) - if err != nil { - t.Error("Scan failed", err.Error()) - return - } - var same bool - switch decodedval := retval.(type) { - case []byte: - switch decodedvaltest := val.(type) { - case []byte: - same = bytes.Equal(decodedval, decodedvaltest) - default: - same = false - } - case time.Time: - same = decodedval.UTC() == val - default: - same = retval == val - } - if !same { - t.Error("Value don't match", retval, val) - return - } - }) - } -} - -func TestExec(t *testing.T) { - conn := open(t) - defer conn.Close() - - res, err := conn.Exec("create table #abc (fld int)") - if err != nil { - t.Fatal("Exec failed", err.Error()) - } - _ = res -} - -func TestShortTimeout(t *testing.T) { - if testing.Short() { - t.Skip("short") - } - checkConnStr(t) - SetLogger(testLogger{t}) - dsn := makeConnStr(t) - dsnParams := dsn.Query() - dsnParams.Set("Connection Timeout", "2") - dsn.RawQuery = dsnParams.Encode() - conn, err := sql.Open("mssql", dsn.String()) - if err != nil { - t.Fatal("Open connection failed:", err.Error()) - } - defer conn.Close() - - _, err = conn.Exec("waitfor delay '00:00:15'") - if err == nil { - t.Fatal("Exec should fail with timeout, but no failure occurred") - } - if neterr, ok := err.(net.Error); !ok || !neterr.Timeout() { - t.Fatal("failure not a timeout, failed with", err) - } - - // connection should be usable after timeout - row := conn.QueryRow("select 1") - var val int64 - err = row.Scan(&val) - if err != nil { - t.Fatal("Scan failed with", err) - } -} - -func TestTwoQueries(t *testing.T) { - conn := open(t) - defer conn.Close() - - rows, err := conn.Query("select 1") - if err != nil { - t.Fatal("First exec failed", err) - } - if !rows.Next() { - t.Fatal("First query didn't return row") - } - var i int - if err = rows.Scan(&i); err != nil { - t.Fatal("Scan failed", err) - } - if i != 1 { - t.Fatalf("Wrong value returned %d, should be 1", i) - } - - if rows, err = conn.Query("select 2"); err != nil { - t.Fatal("Second query failed", err) - } - if !rows.Next() { - t.Fatal("Second query didn't return row") - } - if err = rows.Scan(&i); err != nil { - t.Fatal("Scan failed", err) - } - if i != 2 { - t.Fatalf("Wrong value returned %d, should be 2", i) - } -} - -func TestError(t *testing.T) { - conn := open(t) - defer conn.Close() - - _, err := conn.Query("exec bad") - if err == nil { - t.Fatal("Query should fail") - } - - if sqlerr, ok := err.(Error); !ok { - t.Fatalf("Should be sql error, actually %T, %v", err, err) - } else { - if sqlerr.Number != 2812 { // Could not find stored procedure 'bad' - t.Fatalf("Should be specific error code 2812, actually %d %s", sqlerr.Number, sqlerr) - } - } -} - -func TestQueryNoRows(t *testing.T) { - conn := open(t) - defer conn.Close() - - var rows *sql.Rows - var err error - if rows, err = conn.Query("create table #abc (fld int)"); err != nil { - t.Fatal("Query failed", err) - } - if rows.Next() { - t.Fatal("Query shoulnd't return any rows") - } -} - -func TestQueryManyNullsRow(t *testing.T) { - conn := open(t) - defer conn.Close() - - var row *sql.Row - var err error - if row = conn.QueryRow("select null, null, null, null, null, null, null, null"); err != nil { - t.Fatal("Query failed", err) - } - var v [8]sql.NullInt64 - if err = row.Scan(&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7]); err != nil { - t.Fatal("Scan failed", err) - } -} - -func TestOrderBy(t *testing.T) { - conn := open(t) - defer conn.Close() - - tx, err := conn.Begin() - if err != nil { - t.Fatal("Begin tran failed", err) - } - defer tx.Rollback() - - _, err = tx.Exec("if (exists(select * from INFORMATION_SCHEMA.TABLES where TABLE_NAME='tbl')) drop table tbl") - if err != nil { - t.Fatal("Drop table failed", err) - } - - _, err = tx.Exec("create table tbl (fld1 int primary key, fld2 int)") - if err != nil { - t.Fatal("Create table failed", err) - } - _, err = tx.Exec("insert into tbl (fld1, fld2) values (1, 2)") - if err != nil { - t.Fatal("Insert failed", err) - } - _, err = tx.Exec("insert into tbl (fld1, fld2) values (2, 1)") - if err != nil { - t.Fatal("Insert failed", err) - } - - rows, err := tx.Query("select * from tbl order by fld1") - if err != nil { - t.Fatal("Query failed", err) - } - - for rows.Next() { - var fld1 int32 - var fld2 int32 - err = rows.Scan(&fld1, &fld2) - if err != nil { - t.Fatal("Scan failed", err) - } - } - - err = rows.Err() - if err != nil { - t.Fatal("Rows have errors", err) - } -} - -func TestScanDecimal(t *testing.T) { - conn := open(t) - defer conn.Close() - - var f float64 - err := conn.QueryRow("select cast(0.5 as numeric(25,1))").Scan(&f) - if err != nil { - t.Error("query row / scan failed:", err.Error()) - return - } - if math.Abs(f-0.5) > 0.000001 { - t.Error("Value is not 0.5:", f) - return - } - - var s string - err = conn.QueryRow("select cast(-0.05 as numeric(25,2))").Scan(&s) - if err != nil { - t.Error("query row / scan failed:", err.Error()) - return - } - if s != "-0.05" { - t.Error("Value is not -0.05:", s) - return - } -} - -func TestAffectedRows(t *testing.T) { - conn := open(t) - defer conn.Close() - - tx, err := conn.Begin() - if err != nil { - t.Fatal("Begin tran failed", err) - } - defer tx.Rollback() - - res, err := tx.Exec("create table #foo (bar int)") - if err != nil { - t.Fatal("create table failed") - } - n, err := res.RowsAffected() - if err != nil { - t.Fatal("rows affected failed") - } - if n != 0 { - t.Error("Expected 0 rows affected, got ", n) - } - - res, err = tx.Exec("insert into #foo (bar) values (1)") - if err != nil { - t.Fatal("insert failed") - } - n, err = res.RowsAffected() - if err != nil { - t.Fatal("rows affected failed") - } - if n != 1 { - t.Error("Expected 1 row affected, got ", n) - } - - res, err = tx.Exec("insert into #foo (bar) values (?)", 2) - if err != nil { - t.Fatal("insert failed", err) - } - n, err = res.RowsAffected() - if err != nil { - t.Fatal("rows affected failed") - } - if n != 1 { - t.Error("Expected 1 row affected, got ", n) - } -} - -func TestIdentity(t *testing.T) { - conn := open(t) - defer conn.Close() - - tx, err := conn.Begin() - if err != nil { - t.Fatal("Begin tran failed", err) - } - defer tx.Rollback() - - res, err := tx.Exec("create table #foo (bar int identity, baz int unique)") - if err != nil { - t.Fatal("create table failed") - } - - res, err = tx.Exec("insert into #foo (baz) values (1)") - if err != nil { - t.Fatal("insert failed") - } - n, err := res.LastInsertId() - if err != nil { - t.Fatal("last insert id failed") - } - if n != 1 { - t.Error("Expected 1 for identity, got ", n) - } - - res, err = tx.Exec("insert into #foo (baz) values (20)") - if err != nil { - t.Fatal("insert failed") - } - n, err = res.LastInsertId() - if err != nil { - t.Fatal("last insert id failed") - } - if n != 2 { - t.Error("Expected 2 for identity, got ", n) - } - - res, err = tx.Exec("insert into #foo (baz) values (1)") - if err == nil { - t.Fatal("insert should fail") - } - - res, err = tx.Exec("insert into #foo (baz) values (?)", 1) - if err == nil { - t.Fatal("insert should fail") - } -} - -func queryParamRoundTrip(db *sql.DB, param interface{}, dest interface{}) { - err := db.QueryRow("select ?", param).Scan(dest) - if err != nil { - log.Panicf("select / scan failed: %v", err.Error()) - } -} - -func TestDateTimeParam(t *testing.T) { - conn := open(t) - defer conn.Close() - type testStruct struct { - t time.Time - } - var emptydate time.Time - mindate := time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC) - maxdate := time.Date(9999, 12, 31, 23, 59, 59, 999999900, time.UTC) - values := []testStruct{ - {time.Date(2015, time.October, 12, 10, 22, 0, 0, time.FixedZone("PST", -8*60*60))}, // back to the future day - {time.Date(1961, time.April, 12, 9, 7, 0, 0, time.FixedZone("MSK", 3*60*60))}, // First man in space - {time.Date(1969, time.July, 20, 20, 18, 0, 0, time.UTC)}, // First man on the Moon - {time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC)}, // UNIX date - {time.Date(1982, 1, 3, 12, 13, 14, 300, time.FixedZone("YAKT", 9*60*60))}, // some random date - {time.Date(4, 6, 3, 12, 13, 14, 150000000, time.UTC)}, // some random date - {mindate}, // minimal value - {maxdate}, // maximum value - {time.Date(10000, 1, 1, 0, 0, 0, 0, time.UTC)}, // just over limit - {emptydate}, - } - for _, test := range values { - t.Run(fmt.Sprintf("Test for %v", test.t), func(t *testing.T) { - var t2 time.Time - queryParamRoundTrip(conn, test.t, &t2) - expected := test.t - // clip value - if test.t.Before(mindate) { - expected = mindate - } - if test.t.After(maxdate) { - expected = maxdate - } - - if expected.Sub(t2) != 0 { - t.Errorf("expected: '%s', got: '%s' delta: %d", expected, t2, expected.Sub(t2)) - } - }) - } - -} - -func TestUniqueIdentifierParam(t *testing.T) { - conn := open(t) - defer conn.Close() - type testStruct struct { - name string - uuid interface{} - } - - expected := UniqueIdentifier{0x01, 0x23, 0x45, 0x67, - 0x89, 0xAB, - 0xCD, 0xEF, - 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, - } - - values := []testStruct{ - { - "[]byte", - []byte{0x67, 0x45, 0x23, 0x01, - 0xAB, 0x89, - 0xEF, 0xCD, - 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}}, - { - "string", - "01234567-89ab-cdef-0123-456789abcdef"}, - } - - for _, test := range values { - t.Run(test.name, func(t *testing.T) { - var uuid2 UniqueIdentifier - err := conn.QueryRow("select ?", test.uuid).Scan(&uuid2) - if err != nil { - t.Fatal("select / scan failed", err.Error()) - } - - if expected != uuid2 { - t.Errorf("uniqueidentifier does not match: '%s' '%s'", expected, uuid2) - } - }) - } -} - -func TestBigQuery(t *testing.T) { - conn := open(t) - defer conn.Close() - rows, err := conn.Query(`WITH n(n) AS - ( - SELECT 1 - UNION ALL - SELECT n+1 FROM n WHERE n < 10000 - ) - SELECT n, @@version FROM n ORDER BY n - OPTION (MAXRECURSION 10000);`) - if err != nil { - t.Fatal("cannot exec query", err) - } - rows.Next() - rows.Close() - var res int - err = conn.QueryRow("select 0").Scan(&res) - if err != nil { - t.Fatal("cannot scan value", err) - } - if res != 0 { - t.Fatal("expected 0, got ", res) - } -} - -func TestBug32(t *testing.T) { - conn := open(t) - defer conn.Close() - - tx, err := conn.Begin() - if err != nil { - t.Fatal("Begin tran failed", err) - } - defer tx.Rollback() - - _, err = tx.Exec("if (exists(select * from INFORMATION_SCHEMA.TABLES where TABLE_NAME='tbl')) drop table tbl") - if err != nil { - t.Fatal("Drop table failed", err) - } - - _, err = tx.Exec("create table tbl(a int primary key,fld bit null)") - if err != nil { - t.Fatal("Create table failed", err) - } - - _, err = tx.Exec("insert into tbl (a,fld) values (1,nullif(?, ''))", "") - if err != nil { - t.Fatal("Insert failed", err) - } -} - -func TestIgnoreEmptyResults(t *testing.T) { - conn := open(t) - defer conn.Close() - rows, err := conn.Query("set nocount on; select 2") - if err != nil { - t.Fatal("Query failed", err.Error()) - } - if !rows.Next() { - t.Fatal("Query didn't return row") - } - var fld1 int32 - err = rows.Scan(&fld1) - if err != nil { - t.Fatal("Scan failed", err) - } - if fld1 != 2 { - t.Fatal("Returned value doesn't match") - } -} - -func TestStmt_SetQueryNotification(t *testing.T) { - checkConnStr(t) - mssqldriver := driverWithProcess(t) - cn, err := mssqldriver.Open(makeConnStr(t).String()) - if err != nil { - t.Fatalf("failed to open connection: %v", err) - } - stmt, err := cn.Prepare("SELECT 1") - if err != nil { - t.Error("Connection failed", err) - } - - sqlstmt := stmt.(*Stmt) - sqlstmt.SetQueryNotification("ABC", "service=WebCacheNotifications", time.Hour) - - rows, err := sqlstmt.Query(nil) - if err == nil { - rows.Close() - } - // notifications are sent to Service Broker - // see for more info: https://github.com/denisenkom/go-mssqldb/pull/90 -} - -func TestErrorInfo(t *testing.T) { - conn := open(t) - defer conn.Close() - - _, err := conn.Exec("select bad") - if sqlError, ok := err.(Error); ok { - if sqlError.SQLErrorNumber() != 207 /*invalid column name*/ { - t.Errorf("Query failed with unexpected error number %d %s", sqlError.SQLErrorNumber(), sqlError.SQLErrorMessage()) - } - if sqlError.SQLErrorLineNo() != 1 { - t.Errorf("Unexpected line number returned %v, expected %v", sqlError.SQLErrorLineNo(), 1) - } - } else { - t.Error("Failed to convert error to SQLErorr", err) - } - _, err = conn.Exec("RAISERROR('test message', 18, 111)") - if sqlError, ok := err.(Error); ok { - if sqlError.SQLErrorNumber() != 50000 { - t.Errorf("Query failed with unexpected error number %d %s", sqlError.SQLErrorNumber(), sqlError.SQLErrorMessage()) - } - if sqlError.SQLErrorMessage() != "test message" { - t.Fail() - } - if sqlError.SQLErrorClass() != 18 { - t.Fail() - } - if sqlError.SQLErrorState() != 111 { - t.Fail() - } - if sqlError.SQLErrorLineNo() != 1 { - t.Errorf("Unexpected line number returned %v, expected %v", sqlError.SQLErrorLineNo(), 1) - } - // just call those methods to make sure we have some coverage for them - sqlError.SQLErrorServerName() - sqlError.SQLErrorProcName() - } else { - t.Error("Failed to convert error to SQLErorr", err) - } -} - -func TestSetLanguage(t *testing.T) { - conn := open(t) - defer conn.Close() - - _, err := conn.Exec("set language russian") - if err != nil { - t.Errorf("Query failed with unexpected error %s", err) - } - - row := conn.QueryRow("select cast(getdate() as varchar(50))") - var val interface{} - err = row.Scan(&val) - if err != nil { - t.Errorf("Query failed with unexpected error %s", err) - } - t.Log("Returned value", val) -} - -func TestConnectionClosing(t *testing.T) { - pool := open(t) - defer pool.Close() - for i := 1; i <= 100; i++ { - if pool.Stats().OpenConnections > 1 { - t.Errorf("Open connections is expected to stay <= 1, but it is %d", pool.Stats().OpenConnections) - return - } - - stmt, err := pool.Query("select 1") - if err != nil { - t.Fatalf("Query failed with unexpected error %s", err) - } - for stmt.Next() { - var val interface{} - err := stmt.Scan(&val) - if err != nil { - t.Fatalf("Query failed with unexpected error %s", err) - } - } - } -} - -func TestBeginTranError(t *testing.T) { - checkConnStr(t) - drv := driverWithProcess(t) - conn, err := drv.open(context.Background(), makeConnStr(t).String()) - if err != nil { - t.Fatalf("Open failed with error %v", err) - } - - defer conn.Close() - // close actual connection to make begin transaction to fail during sending of a packet - conn.sess.buf.transport.Close() - - ctx := context.Background() - _, err = conn.begin(ctx, isolationSnapshot) - if err == nil || conn.connectionGood == true { - t.Errorf("begin should fail as a bad connection, err=%v", err) - } - - // reopen connection - conn, err = drv.open(context.Background(), makeConnStr(t).String()) - if err != nil { - t.Fatalf("Open failed with error %v", err) - } - err = conn.sendBeginRequest(ctx, isolationSerializable) - if err != nil { - t.Fatalf("sendBeginRequest failed with error %v", err) - } - - // close connection to cause processBeginResponse to fail - conn.sess.buf.transport.Close() - _, err = conn.processBeginResponse(ctx) - switch err { - case nil: - t.Error("processBeginResponse should fail but it succeeded") - case driver.ErrBadConn: - t.Error("processBeginResponse should fail with error different from ErrBadConn but it did") - } - - if conn.connectionGood { - t.Fatal("Connection should be in a bad state") - } -} - -func TestCommitTranError(t *testing.T) { - checkConnStr(t) - drv := driverWithProcess(t) - conn, err := drv.open(context.Background(), makeConnStr(t).String()) - if err != nil { - t.Fatalf("Open failed with error %v", err) - } - - defer conn.Close() - // close actual connection to make commit transaction to fail during sending of a packet - conn.sess.buf.transport.Close() - - ctx := context.Background() - err = conn.Commit() - if err == nil || conn.connectionGood { - t.Errorf("begin should fail and set the connection to bad, but it returned %v", err) - } - - // reopen connection - conn, err = drv.open(context.Background(), makeConnStr(t).String()) - if err != nil { - t.Fatalf("Open failed with error %v", err) - } - err = conn.sendCommitRequest() - if err != nil { - t.Fatalf("sendCommitRequest failed with error %v", err) - } - - // close connection to cause processBeginResponse to fail - conn.sess.buf.transport.Close() - err = conn.simpleProcessResp(ctx) - switch err { - case nil: - t.Error("simpleProcessResp should fail but it succeeded") - case driver.ErrBadConn: - t.Error("simpleProcessResp should fail with error different from ErrBadConn but it did") - } - - if conn.connectionGood { - t.Fatal("Connection should be in a bad state") - } - - // reopen connection - conn, err = drv.open(context.Background(), makeConnStr(t).String()) - defer conn.Close() - if err != nil { - t.Fatalf("Open failed with error %v", err) - } - // should fail because there is no transaction - err = conn.Commit() - switch err { - case nil: - t.Error("Commit should fail but it succeeded") - case driver.ErrBadConn: - t.Error("Commit should fail with error different from ErrBadConn but it did") - } -} - -func TestRollbackTranError(t *testing.T) { - checkConnStr(t) - drv := driverWithProcess(t) - conn, err := drv.open(context.Background(), makeConnStr(t).String()) - if err != nil { - t.Fatalf("Open failed with error %v", err) - } - - defer conn.Close() - // close actual connection to make commit transaction to fail during sending of a packet - conn.sess.buf.transport.Close() - - ctx := context.Background() - err = conn.Rollback() - if err == nil || conn.connectionGood { - t.Errorf("Rollback should fail and set connection to bad but it returned %v", err) - } - - // reopen connection - conn, err = drv.open(context.Background(), makeConnStr(t).String()) - if err != nil { - t.Fatalf("Open failed with error %v", err) - } - err = conn.sendRollbackRequest() - if err != nil { - t.Fatalf("sendCommitRequest failed with error %v", err) - } - - // close connection to cause processBeginResponse to fail - conn.sess.buf.transport.Close() - err = conn.simpleProcessResp(ctx) - switch err { - case nil: - t.Error("simpleProcessResp should fail but it succeeded") - case driver.ErrBadConn: - t.Error("simpleProcessResp should fail with error different from ErrBadConn but it did") - } - - if conn.connectionGood { - t.Fatal("Connection should be in a bad state") - } - - // reopen connection - conn, err = drv.open(context.Background(), makeConnStr(t).String()) - defer conn.Close() - if err != nil { - t.Fatalf("Open failed with error %v", err) - } - // should fail because there is no transaction - err = conn.Rollback() - switch err { - case nil: - t.Error("Commit should fail but it succeeded") - case driver.ErrBadConn: - t.Error("Commit should fail with error different from ErrBadConn but it did") - } -} - -func TestSendQueryErrors(t *testing.T) { - checkConnStr(t) - drv := driverWithProcess(t) - conn, err := drv.open(context.Background(), makeConnStr(t).String()) - if err != nil { - t.FailNow() - } - - defer conn.Close() - stmt, err := conn.prepareContext(context.Background(), "select 1") - if err != nil { - t.FailNow() - } - - // should fail because parameter is invalid - _, err = stmt.Query([]driver.Value{conn}) - if err == nil { - t.Fail() - } - - // close actual connection to make commit transaction to fail during sending of a packet - conn.sess.buf.transport.Close() - - // should fail because connection is closed - _, err = stmt.Query([]driver.Value{}) - if err == nil || stmt.c.connectionGood { - t.Fail() - } - - stmt, err = conn.prepareContext(context.Background(), "select ?") - if err != nil { - t.FailNow() - } - // should fail because connection is closed - _, err = stmt.Query([]driver.Value{int64(1)}) - if err == nil || stmt.c.connectionGood { - t.Fail() - } -} - -func TestProcessQueryErrors(t *testing.T) { - checkConnStr(t) - drv := driverWithProcess(t) - conn, err := drv.open(context.Background(), makeConnStr(t).String()) - if err != nil { - t.Fatal("open expected to succeed, but it failed with", err) - } - stmt, err := conn.prepareContext(context.Background(), "select 1") - if err != nil { - t.Fatal("prepareContext expected to succeed, but it failed with", err) - } - err = stmt.sendQuery([]namedValue{}) - if err != nil { - t.Fatal("sendQuery expected to succeed, but it failed with", err) - } - // close actual connection to make reading response to fail - conn.sess.buf.transport.Close() - _, err = stmt.processQueryResponse(context.Background()) - if err == nil { - t.Error("processQueryResponse expected to fail but it succeeded") - } - // should not fail with ErrBadConn because query was successfully sent to server - if err == driver.ErrBadConn { - t.Error("processQueryResponse expected to fail with error other than ErrBadConn but it failed with it") - } - - if conn.connectionGood { - t.Fatal("Connection should be in a bad state") - } -} - -func TestSendExecErrors(t *testing.T) { - checkConnStr(t) - drv := driverWithProcess(t) - conn, err := drv.open(context.Background(), makeConnStr(t).String()) - if err != nil { - t.FailNow() - } - - defer conn.Close() - stmt, err := conn.prepareContext(context.Background(), "select 1") - if err != nil { - t.FailNow() - } - - // should fail because parameter is invalid - _, err = stmt.Exec([]driver.Value{conn}) - if err == nil { - t.Fail() - } - - // close actual connection to make commit transaction to fail during sending of a packet - conn.sess.buf.transport.Close() - - // should fail because connection is closed - _, err = stmt.Exec([]driver.Value{}) - if err == nil || stmt.c.connectionGood { - t.Fail() - } - - stmt, err = conn.prepareContext(context.Background(), "select ?") - if err != nil { - t.FailNow() - } - // should fail because connection is closed - _, err = stmt.Exec([]driver.Value{int64(1)}) - if err == nil || stmt.c.connectionGood { - t.Fail() - } -} - -func TestLongConnection(t *testing.T) { - checkConnStr(t) - - list := []struct { - connTimeout string - queryTimeout string - ctxTimeout time.Duration - wantFail bool - }{ - {"1", "00:00:02", 6 * time.Second, true}, - {"2", "00:00:01", 6 * time.Second, false}, - - // Check no connection timeout. - {"0", "00:00:01", 2 * time.Second, false}, - // {"0", "00:00:45", 60 * time.Second, false}, // Skip for normal testing to limit time. - } - - for i, item := range list { - t.Run(fmt.Sprintf("item-index-%d,want-fail=%t", i, item.wantFail), func(t *testing.T) { - dsn := makeConnStr(t) - dsnParams := dsn.Query() - dsnParams.Set("connection timeout", item.connTimeout) - dsn.RawQuery = dsnParams.Encode() - - db, err := sql.Open("sqlserver", dsn.String()) - if err != nil { - t.Fatalf("failed to open driver sqlserver") - } - defer db.Close() - - ctx, cancel := context.WithTimeout(context.Background(), item.ctxTimeout) - defer cancel() - - _, err = db.ExecContext(ctx, "WAITFOR DELAY '"+item.queryTimeout+"';") - if item.wantFail && err == nil { - t.Fatal("exec no error") - } - if !item.wantFail && err != nil { - t.Fatal("exec error", err) - } - }) - } -} - -func TestNextResultSet(t *testing.T) { - conn := open(t) - defer conn.Close() - rows, err := conn.Query("select 1; select 2") - if err != nil { - t.Fatal("Query failed", err.Error()) - } - defer func() { - err := rows.Err() - if err != nil { - t.Error("unexpected error:", err) - } - }() - - defer rows.Close() - - if !rows.Next() { - t.Fatal("Query didn't return row") - } - var fld1, fld2 int32 - err = rows.Scan(&fld1) - if err != nil { - t.Fatal("Scan failed", err) - } - if fld1 != 1 { - t.Fatal("Returned value doesn't match") - } - if rows.Next() { - t.Fatal("Query returned unexpected second row.") - } - // calling next again should still return false - if rows.Next() { - t.Fatal("Query returned unexpected second row.") - } - if !rows.NextResultSet() { - t.Fatal("NextResultSet should return true but returned false") - } - if !rows.Next() { - t.Fatal("Query didn't return row") - } - err = rows.Scan(&fld2) - if err != nil { - t.Fatal("Scan failed", err) - } - if fld2 != 2 { - t.Fatal("Returned value doesn't match") - } - if rows.NextResultSet() { - t.Fatal("NextResultSet should return false but returned true") - } -} - -func TestColumnTypeIntrospection(t *testing.T) { - type tst struct { - expr string - typeName string - reflType reflect.Type - hasSize bool - size int64 - hasPrecScale bool - precision int64 - scale int64 - } - tests := []tst{ - {"cast(1 as bit)", "BIT", reflect.TypeOf(true), false, 0, false, 0, 0}, - {"cast(1 as tinyint)", "TINYINT", reflect.TypeOf(int64(0)), false, 0, false, 0, 0}, - {"cast(1 as smallint)", "SMALLINT", reflect.TypeOf(int64(0)), false, 0, false, 0, 0}, - {"1", "INT", reflect.TypeOf(int64(0)), false, 0, false, 0, 0}, - {"cast(1 as bigint)", "BIGINT", reflect.TypeOf(int64(0)), false, 0, false, 0, 0}, - {"cast(1 as real)", "REAL", reflect.TypeOf(0.0), false, 0, false, 0, 0}, - {"cast(1 as float)", "FLOAT", reflect.TypeOf(0.0), false, 0, false, 0, 0}, - {"cast('abc' as varbinary(3))", "VARBINARY", reflect.TypeOf([]byte{}), true, 3, false, 0, 0}, - {"cast('abc' as varbinary(max))", "VARBINARY", reflect.TypeOf([]byte{}), true, 2147483645, false, 0, 0}, - {"cast(1 as datetime)", "DATETIME", reflect.TypeOf(time.Time{}), false, 0, false, 0, 0}, - {"cast(1 as smalldatetime)", "SMALLDATETIME", reflect.TypeOf(time.Time{}), false, 0, false, 0, 0}, - {"cast(getdate() as datetime2(7))", "DATETIME2", reflect.TypeOf(time.Time{}), false, 0, false, 0, 0}, - {"cast(getdate() as datetimeoffset(7))", "DATETIMEOFFSET", reflect.TypeOf(time.Time{}), false, 0, false, 0, 0}, - {"cast(getdate() as date)", "DATE", reflect.TypeOf(time.Time{}), false, 0, false, 0, 0}, - {"cast(getdate() as time)", "TIME", reflect.TypeOf(time.Time{}), false, 0, false, 0, 0}, - {"'abc'", "VARCHAR", reflect.TypeOf(""), true, 3, false, 0, 0}, - {"cast('abc' as varchar(max))", "VARCHAR", reflect.TypeOf(""), true, 2147483645, false, 0, 0}, - {"N'abc'", "NVARCHAR", reflect.TypeOf(""), true, 3, false, 0, 0}, - {"cast(N'abc' as NVARCHAR(MAX))", "NVARCHAR", reflect.TypeOf(""), true, 1073741822, false, 0, 0}, - {"cast(1 as decimal)", "DECIMAL", reflect.TypeOf([]byte{}), false, 0, true, 18, 0}, - {"cast(1 as decimal(5, 2))", "DECIMAL", reflect.TypeOf([]byte{}), false, 0, true, 5, 2}, - {"cast(1 as numeric(10, 4))", "DECIMAL", reflect.TypeOf([]byte{}), false, 0, true, 10, 4}, - {"cast(1 as money)", "MONEY", reflect.TypeOf([]byte{}), false, 0, false, 0, 0}, - {"cast(1 as smallmoney)", "SMALLMONEY", reflect.TypeOf([]byte{}), false, 0, false, 0, 0}, - {"cast(0x6F9619FF8B86D011B42D00C04FC964FF as uniqueidentifier)", "UNIQUEIDENTIFIER", reflect.TypeOf([]byte{}), false, 0, false, 0, 0}, - {"cast('' as xml)", "XML", reflect.TypeOf(""), true, 1073741822, false, 0, 0}, - {"cast('abc' as text)", "TEXT", reflect.TypeOf(""), true, 2147483647, false, 0, 0}, - {"cast(N'abc' as ntext)", "NTEXT", reflect.TypeOf(""), true, 1073741823, false, 0, 0}, - {"cast('abc' as image)", "IMAGE", reflect.TypeOf([]byte{}), true, 2147483647, false, 0, 0}, - {"cast('abc' as char(3))", "CHAR", reflect.TypeOf(""), true, 3, false, 0, 0}, - {"cast(N'abc' as nchar(3))", "NCHAR", reflect.TypeOf(""), true, 3, false, 0, 0}, - {"cast(1 as sql_variant)", "SQL_VARIANT", reflect.TypeOf(nil), false, 0, false, 0, 0}, - } - conn := open(t) - defer conn.Close() - for _, tt := range tests { - rows, err := conn.Query("select " + tt.expr) - if err != nil { - t.Fatalf("Query failed with unexpected error %s", err) - } - ct, err := rows.ColumnTypes() - if err != nil { - t.Fatalf("Query failed with unexpected error %s", err) - } - if ct[0].DatabaseTypeName() != tt.typeName { - t.Errorf("Expected type %s but returned %s", tt.typeName, ct[0].DatabaseTypeName()) - } - size, ok := ct[0].Length() - if ok != tt.hasSize { - t.Errorf("Expected has size %v but returned %v for %s", tt.hasSize, ok, tt.expr) - } else { - if ok && size != tt.size { - t.Errorf("Expected size %d but returned %d for %s", tt.size, size, tt.expr) - } - } - - prec, scale, ok := ct[0].DecimalSize() - if ok != tt.hasPrecScale { - t.Errorf("Expected has prec/scale %v but returned %v for %s", tt.hasPrecScale, ok, tt.expr) - } else { - if ok && prec != tt.precision { - t.Errorf("Expected precision %d but returned %d for %s", tt.precision, prec, tt.expr) - } - if ok && scale != tt.scale { - t.Errorf("Expected scale %d but returned %d for %s", tt.scale, scale, tt.expr) - } - } - - if ct[0].ScanType() != tt.reflType { - t.Errorf("Expected ScanType %v but got %v for %s", tt.reflType, ct[0].ScanType(), tt.expr) - } - } -} - -func TestColumnIntrospection(t *testing.T) { - type tst struct { - expr string - fieldName string - typeName string - nullable bool - hasSize bool - size int64 - hasPrecScale bool - precision int64 - scale int64 - } - tests := []tst{ - {"f1 int null", "f1", "INT", true, false, 0, false, 0, 0}, - {"f2 varchar(15) not null", "f2", "VARCHAR", false, true, 15, false, 0, 0}, - {"f3 decimal(5, 2) null", "f3", "DECIMAL", true, false, 0, true, 5, 2}, - } - conn := open(t) - defer conn.Close() - - // making table variable with specified fields and making a select from it - exprs := make([]string, len(tests)) - for i, test := range tests { - exprs[i] = test.expr - } - exprJoined := strings.Join(exprs, ",") - rows, err := conn.Query(fmt.Sprintf("declare @tbl table(%s); select * from @tbl", exprJoined)) - if err != nil { - t.Fatalf("Query failed with unexpected error %s", err) - } - - ct, err := rows.ColumnTypes() - if err != nil { - t.Fatalf("ColumnTypes failed with unexpected error %s", err) - } - for i, test := range tests { - if ct[i].Name() != test.fieldName { - t.Errorf("Field expected have name %s but it has name %s", test.fieldName, ct[i].Name()) - } - - if ct[i].DatabaseTypeName() != test.typeName { - t.Errorf("Invalid type name returned %s expected %s", ct[i].DatabaseTypeName(), test.typeName) - } - - nullable, ok := ct[i].Nullable() - if ok { - if nullable != test.nullable { - t.Errorf("Invalid nullable value returned %v", nullable) - } - } else { - t.Error("Nullable was expected to support Nullable but it didn't") - } - - size, ok := ct[i].Length() - if ok != test.hasSize { - t.Errorf("Expected has size %v but returned %v for %s", test.hasSize, ok, test.expr) - } else { - if ok && size != test.size { - t.Errorf("Expected size %d but returned %d for %s", test.size, size, test.expr) - } - } - - prec, scale, ok := ct[i].DecimalSize() - if ok != test.hasPrecScale { - t.Errorf("Expected has prec/scale %v but returned %v for %s", test.hasPrecScale, ok, test.expr) - } else { - if ok && prec != test.precision { - t.Errorf("Expected precision %d but returned %d for %s", test.precision, prec, test.expr) - } - if ok && scale != test.scale { - t.Errorf("Expected scale %d but returned %d for %s", test.scale, scale, test.expr) - } - } - } -} - -func TestContext(t *testing.T) { - conn := open(t) - defer conn.Close() - - opts := &sql.TxOptions{ - Isolation: sql.LevelSerializable, - } - ctx := context.Background() - tx, err := conn.BeginTx(ctx, opts) - if err != nil { - t.Errorf("BeginTx failed with unexpected error %s", err) - return - } - rows, err := tx.QueryContext(ctx, "DBCC USEROPTIONS") - properties := make(map[string]string) - for rows.Next() { - var name, value string - if err = rows.Scan(&name, &value); err != nil { - t.Errorf("Scan failed with unexpected error %s", err) - } - properties[name] = value - } - - if properties["isolation level"] != "serializable" { - t.Errorf("Expected isolation level to be serializable but it is %s", properties["isolation level"]) - } - - row := tx.QueryRowContext(ctx, "select 1") - var val int64 - if err = row.Scan(&val); err != nil { - t.Errorf("QueryRowContext failed with unexpected error %s", err) - } - if val != 1 { - t.Error("Incorrect value returned from query") - } - - _, err = tx.ExecContext(ctx, "select 1") - if err != nil { - t.Errorf("ExecContext failed with unexpected error %s", err) - return - } - - _, err = tx.PrepareContext(ctx, "select 1") - if err != nil { - t.Errorf("PrepareContext failed with unexpected error %s", err) - return - } -} - -func TestBeginTxtReadOnlyNotSupported(t *testing.T) { - conn := open(t) - defer conn.Close() - opts := &sql.TxOptions{ReadOnly: true} - _, err := conn.BeginTx(context.Background(), opts) - if err == nil { - t.Error("BeginTx expected to fail for read only transaction because MSSQL doesn't support it, but it succeeded") - } -} - -func TestConn_BeginTx(t *testing.T) { - conn := open(t) - defer conn.Close() - _, err := conn.Exec("create table test (f int)") - defer conn.Exec("drop table test") - if err != nil { - t.Fatal("create table failed with error", err) - } - - tx1, err := conn.BeginTx(context.Background(), nil) - if err != nil { - t.Fatal("BeginTx failed with error", err) - } - tx2, err := conn.BeginTx(context.Background(), nil) - if err != nil { - t.Fatal("BeginTx failed with error", err) - } - _, err = tx1.Exec("insert into test (f) values (1)") - if err != nil { - t.Fatal("insert failed with error", err) - } - _, err = tx2.Exec("insert into test (f) values (2)") - if err != nil { - t.Fatal("insert failed with error", err) - } - tx1.Rollback() - tx2.Commit() - - rows, err := conn.Query("select f from test") - if err != nil { - t.Fatal("select failed with error", err) - } - values := []int64{} - for rows.Next() { - var val int64 - err = rows.Scan(&val) - if err != nil { - t.Fatal("scan failed with error", err) - } - values = append(values, val) - } - if !reflect.DeepEqual(values, []int64{2}) { - t.Errorf("Values is expected to be [1] but it is %v", values) - } -} - -func TestNamedParameters(t *testing.T) { - conn := open(t) - defer conn.Close() - row := conn.QueryRow( - "select :param2, :param1, :param2", - sql.Named("param1", 1), - sql.Named("param2", 2)) - var col1, col2, col3 int64 - err := row.Scan(&col1, &col2, &col3) - if err != nil { - t.Errorf("Scan failed with unexpected error %s", err) - return - } - if col1 != 2 || col2 != 1 || col3 != 2 { - t.Errorf("Unexpected values returned col1=%d, col2=%d, col3=%d", col1, col2, col3) - } -} - -func TestBadNamedParameters(t *testing.T) { - conn := open(t) - defer conn.Close() - row := conn.QueryRow( - "select :param2, :param1, :param2", - sql.Named("badparam1", 1), - sql.Named("param2", 2)) - var col1, col2, col3 int64 - err := row.Scan(&col1, &col2, &col3) - if err == nil { - t.Error("Scan succeeded unexpectedly") - return - } - t.Logf("Scan failed as expected with error %s", err) -} - -func TestMixedParameters(t *testing.T) { - conn := open(t) - defer conn.Close() - row := conn.QueryRow( - "select :2, :param1, :param2", - 5, // this parameter will be unused - 6, - sql.Named("param1", 1), - sql.Named("param2", 2)) - var col1, col2, col3 int64 - err := row.Scan(&col1, &col2, &col3) - if err != nil { - t.Errorf("Scan failed with unexpected error %s", err) - return - } - if col1 != 6 || col2 != 1 || col3 != 2 { - t.Errorf("Unexpected values returned col1=%d, col2=%d, col3=%d", col1, col2, col3) - } -} - -/* -func TestMixedParametersExample(t *testing.T) { - conn := open(t) - defer conn.Close() - row := conn.QueryRow( - "select :id, ?", - sql.Named("id", 1), - 2, - ) - var col1, col2 int64 - err := row.Scan(&col1, &col2) - if err != nil { - t.Errorf("Scan failed with unexpected error %s", err) - return - } - if col1 != 1 || col2 != 2 { - t.Errorf("Unexpected values returned col1=%d, col2=%d", col1, col2) - } -} -*/ - -func TestPinger(t *testing.T) { - conn := open(t) - defer conn.Close() - err := conn.Ping() - if err != nil { - t.Errorf("Failed to hit database") - } -} - -func TestQueryCancelLowLevel(t *testing.T) { - checkConnStr(t) - drv := driverWithProcess(t) - conn, err := drv.open(context.Background(), makeConnStr(t).String()) - if err != nil { - t.Fatalf("Open failed with error %v", err) - } - - defer conn.Close() - ctx, cancel := context.WithCancel(context.Background()) - stmt, err := conn.prepareContext(ctx, "waitfor delay '00:00:03'") - if err != nil { - t.Fatalf("Prepare failed with error %v", err) - } - err = stmt.sendQuery([]namedValue{}) - if err != nil { - t.Fatalf("sendQuery failed with error %v", err) - } - - cancel() - - _, err = stmt.processExec(ctx) - if err != context.Canceled { - t.Errorf("Expected error to be Cancelled but got %v", err) - } - - // same connection should be usable again after it was cancelled - stmt, err = conn.prepareContext(context.Background(), "select 1") - if err != nil { - t.Fatalf("Prepare failed with error %v", err) - } - rows, err := stmt.Query([]driver.Value{}) - if err != nil { - t.Fatalf("Query failed with error %v", err) - } - - values := []driver.Value{nil} - err = rows.Next(values) - if err != nil { - t.Fatalf("Next failed with error %v", err) - } -} - -func TestQueryCancelHighLevel(t *testing.T) { - conn := open(t) - defer conn.Close() - - ctx, cancel := context.WithCancel(context.Background()) - go func() { - time.Sleep(200 * time.Millisecond) - cancel() - }() - _, err := conn.ExecContext(ctx, "waitfor delay '00:00:03'") - if err != context.Canceled { - t.Errorf("ExecContext expected to fail with Cancelled but it returned %v", err) - } - - // connection should be usable after timeout - row := conn.QueryRow("select 1") - var val int64 - err = row.Scan(&val) - if err != nil { - t.Fatal("Scan failed with", err) - } -} - -func TestQueryTimeout(t *testing.T) { - conn := open(t) - defer conn.Close() - ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond) - defer cancel() - _, err := conn.ExecContext(ctx, "waitfor delay '00:00:03'") - if err != context.DeadlineExceeded { - t.Errorf("ExecContext expected to fail with DeadlineExceeded but it returned %v", err) - } - - // connection should be usable after timeout - row := conn.QueryRow("select 1") - var val int64 - err = row.Scan(&val) - if err != nil { - t.Fatal("Scan failed with", err) - } -} - -func TestDriverParams(t *testing.T) { - checkConnStr(t) - SetLogger(testLogger{t}) - type sqlCmd struct { - Name string - Driver string - Query string - Param []interface{} - Expect []interface{} - } - - list := []sqlCmd{ - { - Name: "preprocess-ordinal", - Driver: "mssql", - Query: `select V1=:1`, - Param: []interface{}{"abc"}, - Expect: []interface{}{"abc"}, - }, - { - Name: "preprocess-name", - Driver: "mssql", - Query: `select V1=:First`, - Param: []interface{}{sql.Named("First", "abc")}, - Expect: []interface{}{"abc"}, - }, - { - Name: "raw-ordinal", - Driver: "sqlserver", - Query: `select V1=@p1`, - Param: []interface{}{"abc"}, - Expect: []interface{}{"abc"}, - }, - { - Name: "raw-name", - Driver: "sqlserver", - Query: `select V1=@First`, - Param: []interface{}{sql.Named("First", "abc")}, - Expect: []interface{}{"abc"}, - }, - } - - for cmdIndex, cmd := range list { - t.Run(cmd.Name, func(t *testing.T) { - db, err := sql.Open(cmd.Driver, makeConnStr(t).String()) - if err != nil { - t.Fatalf("failed to open driver %q", cmd.Driver) - } - defer db.Close() - - rows, err := db.Query(cmd.Query, cmd.Param...) - if err != nil { - t.Fatalf("failed to run query %q %v", cmd.Query, err) - } - defer rows.Close() - - columns, err := rows.Columns() - if err != nil { - t.Fatalf("failed to get column schema %v", err) - } - clen := len(columns) - - if clen != len(cmd.Expect) { - t.Fatalf("query column has %d, expect %d columns", clen, len(cmd.Expect)) - } - - values := make([]interface{}, clen) - into := make([]interface{}, clen) - for i := 0; i < clen; i++ { - into[i] = &values[i] - } - for rows.Next() { - err = rows.Scan(into...) - if err != nil { - t.Fatalf("failed to scan into row for %d %q", cmdIndex, cmd.Driver) - } - for i := range cmd.Expect { - if values[i] != cmd.Expect[i] { - t.Fatalf("expected value in index %d %v != actual value %v", i, cmd.Expect[i], values[i]) - } - } - } - }) - } -} - -type connInterrupt struct { - net.Conn - - mu sync.Mutex - disruptRead bool - disruptWrite bool -} - -func (c *connInterrupt) Interrupt(write bool) { - c.mu.Lock() - if write { - c.disruptWrite = true - } else { - c.disruptRead = true - } - c.mu.Unlock() -} - -func (c *connInterrupt) Read(b []byte) (n int, err error) { - c.mu.Lock() - dis := c.disruptRead - c.mu.Unlock() - if dis { - return 0, disconnectError{} - } - return c.Conn.Read(b) -} - -func (c *connInterrupt) Write(b []byte) (n int, err error) { - c.mu.Lock() - dis := c.disruptWrite - c.mu.Unlock() - if dis { - return 0, disconnectError{} - } - return c.Conn.Write(b) -} - -type dialerInterrupt struct { - nd netDialer - - mu sync.Mutex - list []*connInterrupt -} - -func (d *dialerInterrupt) DialContext(ctx context.Context, network, addr string) (net.Conn, error) { - conn, err := d.nd.DialContext(ctx, network, addr) - if err != nil { - return nil, err - } - ci := &connInterrupt{Conn: conn} - d.mu.Lock() - d.list = append(d.list, ci) - d.mu.Unlock() - return ci, err -} - -func (d *dialerInterrupt) Interrupt(write bool) { - d.mu.Lock() - defer d.mu.Unlock() - - for _, ci := range d.list { - ci.Interrupt(write) - } -} - -var _ net.Error = disconnectError{} - -type disconnectError struct{} - -func (disconnectError) Error() string { - return "disconnect" -} - -func (disconnectError) Timeout() bool { - return true -} - -func (disconnectError) Temporary() bool { - return true -} - -// TestDisconnect1 ensures errors and states are handled correctly if -// the server is disconnected mid-query. -func TestDisconnect1(t *testing.T) { - if testing.Short() { - t.Skip("short") - } - checkConnStr(t) - SetLogger(testLogger{t}) - - // Revert to the normal dialer after the test is done. - normalCreateDialer := createDialer - defer func() { - createDialer = normalCreateDialer - }() - - waitDisrupt := make(chan struct{}) - ctx, cancel := context.WithTimeout(context.Background(), time.Second*2) - defer cancel() - - createDialer = func(p *connectParams) Dialer { - nd := netDialer{&net.Dialer{Timeout: p.dial_timeout, KeepAlive: p.keepAlive}} - di := &dialerInterrupt{nd: nd} - go func() { - <-waitDisrupt - di.Interrupt(true) - di.Interrupt(false) - }() - return di - } - db, err := sql.Open("sqlserver", makeConnStr(t).String()) - if err != nil { - t.Fatal(err) - } - - if err := db.PingContext(ctx); err != nil { - t.Fatal(err) - } - defer db.Close() - - _, err = db.ExecContext(ctx, `SET LOCK_TIMEOUT 1800;`) - if err != nil { - t.Fatal(err) - } - - go func() { - time.Sleep(time.Second * 1) - close(waitDisrupt) - }() - t.Log("prepare for query") - _, err = db.ExecContext(ctx, `waitfor delay '00:00:3';`) - if err != nil { - t.Log("expected error after disconnect", err) - return - } - t.Fatal("wanted error after Exec") -} - -// TestDisconnect2 tests a read error so the query is started -// but results cannot be read. -func TestDisconnect2(t *testing.T) { - if testing.Short() { - t.Skip("short") - } - checkConnStr(t) - SetLogger(testLogger{t}) - - // Revert to the normal dialer after the test is done. - normalCreateDialer := createDialer - defer func() { - createDialer = normalCreateDialer - }() - - end := make(chan error) - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - go func() { - waitDisrupt := make(chan struct{}) - ctx, cancel = context.WithTimeout(ctx, time.Second*2) - defer cancel() - - createDialer = func(p *connectParams) Dialer { - nd := netDialer{&net.Dialer{Timeout: p.dial_timeout, KeepAlive: p.keepAlive}} - di := &dialerInterrupt{nd: nd} - go func() { - <-waitDisrupt - di.Interrupt(false) - }() - return di - } - db, err := sql.Open("sqlserver", makeConnStr(t).String()) - if err != nil { - t.Fatal(err) - } - - if err := db.PingContext(ctx); err != nil { - t.Fatal(err) - } - defer db.Close() - - _, err = db.ExecContext(ctx, `SET LOCK_TIMEOUT 1800;`) - if err != nil { - t.Fatal(err) - } - close(waitDisrupt) - - _, err = db.ExecContext(ctx, `waitfor delay '00:00:3';`) - end <- err - }() - - timeout := time.After(10 * time.Second) - select { - case err := <-end: - if err == nil { - t.Fatal("test err") - } - case <-timeout: - t.Fatal("timeout") - } -} diff --git a/vendor/github.com/denisenkom/go-mssqldb/tds_test.go b/vendor/github.com/denisenkom/go-mssqldb/tds_test.go deleted file mode 100644 index eeb3dfd6..00000000 --- a/vendor/github.com/denisenkom/go-mssqldb/tds_test.go +++ /dev/null @@ -1,522 +0,0 @@ -package mssql - -import ( - "bytes" - "context" - "database/sql" - "encoding/hex" - "fmt" - "net/url" - "os" - "testing" - "time" -) - -type MockTransport struct { - bytes.Buffer -} - -func (t *MockTransport) Close() error { - return nil -} - -func TestSendLogin(t *testing.T) { - memBuf := new(MockTransport) - buf := newTdsBuffer(1024, memBuf) - login := login{ - TDSVersion: verTDS73, - PacketSize: 0x1000, - ClientProgVer: 0x01060100, - ClientPID: 100, - ClientTimeZone: -4 * 60, - ClientID: [6]byte{0x12, 0x34, 0x56, 0x78, 0x90, 0xab}, - OptionFlags1: 0xe0, - OptionFlags3: 8, - HostName: "subdev1", - UserName: "test", - Password: "testpwd", - AppName: "appname", - ServerName: "servername", - CtlIntName: "library", - Language: "en", - Database: "database", - ClientLCID: 0x204, - AtchDBFile: "filepath", - } - err := sendLogin(buf, login) - if err != nil { - t.Error("sendLogin should succeed") - } - ref := []byte{ - 16, 1, 0, 222, 0, 0, 1, 0, 198 + 16, 0, 0, 0, 3, 0, 10, 115, 0, 16, 0, 0, 0, 1, - 6, 1, 100, 0, 0, 0, 0, 0, 0, 0, 224, 0, 0, 8, 16, 255, 255, 255, 4, 2, 0, - 0, 94, 0, 7, 0, 108, 0, 4, 0, 116, 0, 7, 0, 130, 0, 7, 0, 144, 0, 10, 0, 0, - 0, 0, 0, 164, 0, 7, 0, 178, 0, 2, 0, 182, 0, 8, 0, 18, 52, 86, 120, 144, 171, - 198, 0, 0, 0, 198, 0, 8, 0, 214, 0, 0, 0, 0, 0, 0, 0, 115, 0, 117, 0, 98, - 0, 100, 0, 101, 0, 118, 0, 49, 0, 116, 0, 101, 0, 115, 0, 116, 0, 226, 165, - 243, 165, 146, 165, 226, 165, 162, 165, 210, 165, 227, 165, 97, 0, 112, - 0, 112, 0, 110, 0, 97, 0, 109, 0, 101, 0, 115, 0, 101, 0, 114, 0, 118, 0, - 101, 0, 114, 0, 110, 0, 97, 0, 109, 0, 101, 0, 108, 0, 105, 0, 98, 0, 114, - 0, 97, 0, 114, 0, 121, 0, 101, 0, 110, 0, 100, 0, 97, 0, 116, 0, 97, 0, 98, - 0, 97, 0, 115, 0, 101, 0, 102, 0, 105, 0, 108, 0, 101, 0, 112, 0, 97, 0, - 116, 0, 104, 0} - out := memBuf.Bytes() - if !bytes.Equal(ref, out) { - fmt.Println("Expected:") - fmt.Print(hex.Dump(ref)) - fmt.Println("Returned:") - fmt.Print(hex.Dump(out)) - t.Error("input output don't match") - } -} - -func TestSendSqlBatch(t *testing.T) { - checkConnStr(t) - p, err := parseConnectParams(makeConnStr(t).String()) - if err != nil { - t.Error("parseConnectParams failed:", err.Error()) - return - } - - conn, err := connect(context.Background(), nil, optionalLogger{testLogger{t}}, p) - if err != nil { - t.Error("Open connection failed:", err.Error()) - return - } - defer conn.buf.transport.Close() - - headers := []headerStruct{ - {hdrtype: dataStmHdrTransDescr, - data: transDescrHdr{0, 1}.pack()}, - } - err = sendSqlBatch72(conn.buf, "select 1", headers, true) - if err != nil { - t.Error("Sending sql batch failed", err.Error()) - return - } - - ch := make(chan tokenStruct, 5) - go processResponse(context.Background(), conn, ch, nil) - - var lastRow []interface{} -loop: - for tok := range ch { - switch token := tok.(type) { - case doneStruct: - break loop - case []columnStruct: - conn.columns = token - case []interface{}: - lastRow = token - default: - fmt.Println("unknown token", tok) - } - } - - if len(lastRow) == 0 { - t.Fatal("expected row but no row set") - } - - switch value := lastRow[0].(type) { - case int32: - if value != 1 { - t.Error("Invalid value returned, should be 1", value) - return - } - } -} - -func checkConnStr(t *testing.T) { - if len(os.Getenv("SQLSERVER_DSN")) > 0 { - return - } - if len(os.Getenv("HOST")) > 0 && len(os.Getenv("DATABASE")) > 0 { - return - } - t.Skip("no database connection string") -} - -// makeConnStr returns a URL struct so it may be modified by various -// tests before used as a DSN. -func makeConnStr(t *testing.T) *url.URL { - dsn := os.Getenv("SQLSERVER_DSN") - if len(dsn) > 0 { - parsed, err := url.Parse(dsn) - if err != nil { - t.Fatal("unable to parse SQLSERVER_DSN as URL", err) - } - values := parsed.Query() - if values.Get("log") == "" { - values.Set("log", "127") - } - parsed.RawQuery = values.Encode() - return parsed - } - values := url.Values{} - values.Set("log", "127") - values.Set("database", os.Getenv("DATABASE")) - return &url.URL{ - Scheme: "sqlserver", - Host: os.Getenv("HOST"), - Path: os.Getenv("INSTANCE"), - User: url.UserPassword(os.Getenv("SQLUSER"), os.Getenv("SQLPASSWORD")), - RawQuery: values.Encode(), - } -} - -type testLogger struct { - t *testing.T -} - -func (l testLogger) Printf(format string, v ...interface{}) { - l.t.Logf(format, v...) -} - -func (l testLogger) Println(v ...interface{}) { - l.t.Log(v...) -} - -func open(t *testing.T) *sql.DB { - checkConnStr(t) - SetLogger(testLogger{t}) - conn, err := sql.Open("mssql", makeConnStr(t).String()) - if err != nil { - t.Error("Open connection failed:", err.Error()) - return nil - } - - return conn -} - -func TestConnect(t *testing.T) { - checkConnStr(t) - SetLogger(testLogger{t}) - conn, err := sql.Open("mssql", makeConnStr(t).String()) - if err != nil { - t.Error("Open connection failed:", err.Error()) - return - } - defer conn.Close() -} - -func simpleQuery(conn *sql.DB, t *testing.T) (stmt *sql.Stmt) { - stmt, err := conn.Prepare("select 1 as a") - if err != nil { - t.Error("Prepare failed:", err.Error()) - return nil - } - return stmt -} - -func checkSimpleQuery(rows *sql.Rows, t *testing.T) { - numrows := 0 - for rows.Next() { - var val int - err := rows.Scan(&val) - if err != nil { - t.Error("Scan failed:", err.Error()) - } - if val != 1 { - t.Error("query should return 1") - } - numrows++ - } - if numrows != 1 { - t.Error("query should return 1 row, returned", numrows) - } -} - -func TestQuery(t *testing.T) { - conn := open(t) - if conn == nil { - return - } - defer conn.Close() - - stmt := simpleQuery(conn, t) - if stmt == nil { - return - } - defer stmt.Close() - - rows, err := stmt.Query() - if err != nil { - t.Error("Query failed:", err.Error()) - } - defer rows.Close() - - columns, err := rows.Columns() - if err != nil { - t.Error("getting columns failed", err.Error()) - } - if len(columns) != 1 && columns[0] != "a" { - t.Error("returned incorrect columns (expected ['a']):", columns) - } - - checkSimpleQuery(rows, t) -} - -func TestMultipleQueriesSequentialy(t *testing.T) { - - conn := open(t) - defer conn.Close() - - stmt, err := conn.Prepare("select 1 as a") - if err != nil { - t.Error("Prepare failed:", err.Error()) - return - } - defer stmt.Close() - - rows, err := stmt.Query() - if err != nil { - t.Error("Query failed:", err.Error()) - return - } - defer rows.Close() - checkSimpleQuery(rows, t) - - rows, err = stmt.Query() - if err != nil { - t.Error("Query failed:", err.Error()) - return - } - defer rows.Close() - checkSimpleQuery(rows, t) -} - -func TestMultipleQueryClose(t *testing.T) { - conn := open(t) - defer conn.Close() - - stmt, err := conn.Prepare("select 1 as a") - if err != nil { - t.Error("Prepare failed:", err.Error()) - return - } - defer stmt.Close() - - rows, err := stmt.Query() - if err != nil { - t.Error("Query failed:", err.Error()) - return - } - rows.Close() - - rows, err = stmt.Query() - if err != nil { - t.Error("Query failed:", err.Error()) - return - } - defer rows.Close() - checkSimpleQuery(rows, t) -} - -func TestPing(t *testing.T) { - conn := open(t) - defer conn.Close() - conn.Ping() -} - -func TestSecureWithInvalidHostName(t *testing.T) { - checkConnStr(t) - SetLogger(testLogger{t}) - - dsn := makeConnStr(t) - dsnParams := dsn.Query() - dsnParams.Set("encrypt", "true") - dsnParams.Set("TrustServerCertificate", "false") - dsnParams.Set("hostNameInCertificate", "foo.bar") - dsn.RawQuery = dsnParams.Encode() - - conn, err := sql.Open("mssql", dsn.String()) - if err != nil { - t.Fatal("Open connection failed:", err.Error()) - } - defer conn.Close() - err = conn.Ping() - if err == nil { - t.Fatal("Connected to fake foo.bar server") - } -} - -func TestSecureConnection(t *testing.T) { - checkConnStr(t) - SetLogger(testLogger{t}) - - dsn := makeConnStr(t) - dsnParams := dsn.Query() - dsnParams.Set("encrypt", "true") - dsnParams.Set("TrustServerCertificate", "true") - dsn.RawQuery = dsnParams.Encode() - - conn, err := sql.Open("mssql", dsn.String()) - if err != nil { - t.Fatal("Open connection failed:", err.Error()) - } - defer conn.Close() - var msg string - err = conn.QueryRow("select 'secret'").Scan(&msg) - if err != nil { - t.Fatal("cannot scan value", err) - } - if msg != "secret" { - t.Fatal("expected secret, got: ", msg) - } - var secure bool - err = conn.QueryRow("select encrypt_option from sys.dm_exec_connections where session_id=@@SPID").Scan(&secure) - if err != nil { - t.Fatal("cannot scan value", err) - } - if !secure { - t.Fatal("connection is not encrypted") - } -} - -func TestInvalidConnectionString(t *testing.T) { - connStrings := []string{ - "log=invalid", - "port=invalid", - "packet size=invalid", - "connection timeout=invalid", - "dial timeout=invalid", - "keepalive=invalid", - "encrypt=invalid", - "trustservercertificate=invalid", - "failoverport=invalid", - - // ODBC mode - "odbc:password={", - "odbc:password={somepass", - "odbc:password={somepass}}", - "odbc:password={some}pass", - } - for _, connStr := range connStrings { - _, err := parseConnectParams(connStr) - if err == nil { - t.Errorf("Connection expected to fail for connection string %s but it didn't", connStr) - continue - } else { - t.Logf("Connection failed for %s as expected with error %v", connStr, err) - } - } -} - -func TestValidConnectionString(t *testing.T) { - type testStruct struct { - connStr string - check func(connectParams) bool - } - connStrings := []testStruct{ - {"server=server\\instance;database=testdb;user id=tester;password=pwd", func(p connectParams) bool { - return p.host == "server" && p.instance == "instance" && p.user == "tester" && p.password == "pwd" - }}, - {"server=.", func(p connectParams) bool { return p.host == "localhost" }}, - {"server=(local)", func(p connectParams) bool { return p.host == "localhost" }}, - {"ServerSPN=serverspn;Workstation ID=workstid", func(p connectParams) bool { return p.serverSPN == "serverspn" && p.workstation == "workstid" }}, - {"failoverpartner=fopartner;failoverport=2000", func(p connectParams) bool { return p.failOverPartner == "fopartner" && p.failOverPort == 2000 }}, - {"app name=appname;applicationintent=ReadOnly", func(p connectParams) bool { return p.appname == "appname" && (p.typeFlags&fReadOnlyIntent != 0) }}, - {"encrypt=disable", func(p connectParams) bool { return p.disableEncryption }}, - {"encrypt=true", func(p connectParams) bool { return p.encrypt && !p.disableEncryption }}, - {"encrypt=false", func(p connectParams) bool { return !p.encrypt && !p.disableEncryption }}, - {"trustservercertificate=true", func(p connectParams) bool { return p.trustServerCertificate }}, - {"trustservercertificate=false", func(p connectParams) bool { return !p.trustServerCertificate }}, - {"certificate=abc", func(p connectParams) bool { return p.certificate == "abc" }}, - {"hostnameincertificate=abc", func(p connectParams) bool { return p.hostInCertificate == "abc" }}, - {"connection timeout=3;dial timeout=4;keepalive=5", func(p connectParams) bool { - return p.conn_timeout == 3*time.Second && p.dial_timeout == 4*time.Second && p.keepAlive == 5*time.Second - }}, - {"log=63", func(p connectParams) bool { return p.logFlags == 63 && p.port == 1433 }}, - {"log=63;port=1000", func(p connectParams) bool { return p.logFlags == 63 && p.port == 1000 }}, - {"log=64", func(p connectParams) bool { return p.logFlags == 64 && p.packetSize == 4096 }}, - {"log=64;packet size=0", func(p connectParams) bool { return p.logFlags == 64 && p.packetSize == 512 }}, - {"log=64;packet size=300", func(p connectParams) bool { return p.logFlags == 64 && p.packetSize == 512 }}, - {"log=64;packet size=8192", func(p connectParams) bool { return p.logFlags == 64 && p.packetSize == 8192 }}, - {"log=64;packet size=48000", func(p connectParams) bool { return p.logFlags == 64 && p.packetSize == 32767 }}, - - // those are supported currently, but maybe should not be - {"someparam", func(p connectParams) bool { return true }}, - {";;=;", func(p connectParams) bool { return true }}, - - // ODBC mode - {"odbc:server=somehost;user id=someuser;password=somepass", func(p connectParams) bool { - return p.host == "somehost" && p.user == "someuser" && p.password == "somepass" - }}, - {"odbc:server=somehost;user id=someuser;password=some{pass", func(p connectParams) bool { - return p.host == "somehost" && p.user == "someuser" && p.password == "some{pass" - }}, - {"odbc:server={somehost};user id={someuser};password={somepass}", func(p connectParams) bool { - return p.host == "somehost" && p.user == "someuser" && p.password == "somepass" - }}, - {"odbc:server={somehost};user id={someuser};password={some=pass}", func(p connectParams) bool { - return p.host == "somehost" && p.user == "someuser" && p.password == "some=pass" - }}, - {"odbc:server={somehost};user id={someuser};password={some;pass}", func(p connectParams) bool { - return p.host == "somehost" && p.user == "someuser" && p.password == "some;pass" - }}, - {"odbc:server={somehost};user id={someuser};password={some{pass}", func(p connectParams) bool { - return p.host == "somehost" && p.user == "someuser" && p.password == "some{pass" - }}, - {"odbc:server={somehost};user id={someuser};password={some}}pass}", func(p connectParams) bool { - return p.host == "somehost" && p.user == "someuser" && p.password == "some}pass" - }}, - {"odbc:server={somehost};user id={someuser};password={some{}}p=a;ss}", func(p connectParams) bool { - return p.host == "somehost" && p.user == "someuser" && p.password == "some{}p=a;ss" - }}, - {"odbc: server = somehost; user id = someuser ; password = {some pass } ", func(p connectParams) bool { - return p.host == "somehost" && p.user == "someuser" && p.password == "some pass " - }}, - - // URL mode - {"sqlserver://somehost?connection+timeout=30", func(p connectParams) bool { - return p.host == "somehost" && p.port == 1433 && p.instance == "" && p.conn_timeout == 30*time.Second - }}, - {"sqlserver://someuser@somehost?connection+timeout=30", func(p connectParams) bool { - return p.host == "somehost" && p.port == 1433 && p.instance == "" && p.user == "someuser" && p.password == "" && p.conn_timeout == 30*time.Second - }}, - {"sqlserver://someuser:@somehost?connection+timeout=30", func(p connectParams) bool { - return p.host == "somehost" && p.port == 1433 && p.instance == "" && p.user == "someuser" && p.password == "" && p.conn_timeout == 30*time.Second - }}, - {"sqlserver://someuser:foo%3A%2F%5C%21~%40;bar@somehost?connection+timeout=30", func(p connectParams) bool { - return p.host == "somehost" && p.port == 1433 && p.instance == "" && p.user == "someuser" && p.password == "foo:/\\!~@;bar" && p.conn_timeout == 30*time.Second - }}, - {"sqlserver://someuser:foo%3A%2F%5C%21~%40;bar@somehost:1434?connection+timeout=30", func(p connectParams) bool { - return p.host == "somehost" && p.port == 1434 && p.instance == "" && p.user == "someuser" && p.password == "foo:/\\!~@;bar" && p.conn_timeout == 30*time.Second - }}, - {"sqlserver://someuser:foo%3A%2F%5C%21~%40;bar@somehost:1434/someinstance?connection+timeout=30", func(p connectParams) bool { - return p.host == "somehost" && p.port == 1434 && p.instance == "someinstance" && p.user == "someuser" && p.password == "foo:/\\!~@;bar" && p.conn_timeout == 30*time.Second - }}, - } - for _, ts := range connStrings { - p, err := parseConnectParams(ts.connStr) - if err == nil { - t.Logf("Connection string was parsed successfully %s", ts.connStr) - } else { - t.Errorf("Connection string %s failed to parse with error %s", ts.connStr, err) - continue - } - - if !ts.check(p) { - t.Errorf("Check failed on conn str %s", ts.connStr) - } - } -} - -func TestBadConnect(t *testing.T) { - checkConnStr(t) - SetLogger(testLogger{t}) - connURL := makeConnStr(t) - connURL.User = url.UserPassword("baduser", "badpwd") - badDSN := connURL.String() - - conn, err := sql.Open("mssql", badDSN) - if err != nil { - t.Error("Open connection failed:", err.Error()) - } - defer conn.Close() - - err = conn.Ping() - if err == nil { - t.Error("Ping should fail for connection: ", badDSN) - } -} diff --git a/vendor/github.com/denisenkom/go-mssqldb/types_test.go b/vendor/github.com/denisenkom/go-mssqldb/types_test.go deleted file mode 100644 index 38d8a4b5..00000000 --- a/vendor/github.com/denisenkom/go-mssqldb/types_test.go +++ /dev/null @@ -1,123 +0,0 @@ -package mssql - -import ( - "reflect" - "testing" - "time" -) - -func TestMakeGoLangScanType(t *testing.T) { - if (reflect.TypeOf(int64(0)) != makeGoLangScanType(typeInfo{TypeId: typeInt8})) { - t.Errorf("invalid type returned for typeDateTime") - } - if (reflect.TypeOf(float64(0)) != makeGoLangScanType(typeInfo{TypeId: typeFlt4})) { - t.Errorf("invalid type returned for typeDateTime") - } - if (reflect.TypeOf(float64(0)) != makeGoLangScanType(typeInfo{TypeId: typeFlt8})) { - t.Errorf("invalid type returned for typeDateTime") - } - if (reflect.TypeOf("") != makeGoLangScanType(typeInfo{TypeId: typeVarChar})) { - t.Errorf("invalid type returned for typeDateTime") - } - if (reflect.TypeOf(time.Time{}) != makeGoLangScanType(typeInfo{TypeId: typeDateTime})) { - t.Errorf("invalid type returned for typeDateTime") - } - if (reflect.TypeOf(time.Time{}) != makeGoLangScanType(typeInfo{TypeId: typeDateTim4})) { - t.Errorf("invalid type returned for typeDateTim4") - } - if (reflect.TypeOf(int64(0)) != makeGoLangScanType(typeInfo{TypeId: typeInt1})) { - t.Errorf("invalid type returned for typeInt1") - } - if (reflect.TypeOf(int64(0)) != makeGoLangScanType(typeInfo{TypeId: typeInt2})) { - t.Errorf("invalid type returned for typeInt2") - } - if (reflect.TypeOf(int64(0)) != makeGoLangScanType(typeInfo{TypeId: typeInt4})) { - t.Errorf("invalid type returned for typeInt4") - } - if (reflect.TypeOf(int64(0)) != makeGoLangScanType(typeInfo{TypeId: typeIntN, Size: 4})) { - t.Errorf("invalid type returned for typeIntN") - } - if (reflect.TypeOf([]byte{}) != makeGoLangScanType(typeInfo{TypeId: typeMoney, Size: 8})) { - t.Errorf("invalid type returned for typeIntN") - } -} - -func TestMakeGoLangTypeName(t *testing.T) { - defer handlePanic(t) - - tests := []struct { - typeName string - typeString string - typeID uint8 - }{ - {"typeDateTime", "DATETIME", typeDateTime}, - {"typeDateTim4", "SMALLDATETIME", typeDateTim4}, - {"typeBigBinary", "BINARY", typeBigBinary}, - //TODO: Add other supported types - } - - for _, tt := range tests { - if makeGoLangTypeName(typeInfo{TypeId: tt.typeID}) != tt.typeString { - t.Errorf("invalid type name returned for %s", tt.typeName) - } - } -} - -func TestMakeGoLangTypeLength(t *testing.T) { - defer handlePanic(t) - - tests := []struct { - typeName string - typeVarLen bool - typeLen int64 - typeID uint8 - }{ - {"typeDateTime", false, 0, typeDateTime}, - {"typeDateTim4", false, 0, typeDateTim4}, - {"typeBigBinary", false, 0, typeBigBinary}, - //TODO: Add other supported types - } - - for _, tt := range tests { - n, v := makeGoLangTypeLength(typeInfo{TypeId: tt.typeID}) - if v != tt.typeVarLen { - t.Errorf("invalid type length variability returned for %s", tt.typeName) - } - if n != tt.typeLen { - t.Errorf("invalid type length returned for %s", tt.typeName) - } - } -} - -func TestMakeGoLangTypePrecisionScale(t *testing.T) { - defer handlePanic(t) - - tests := []struct { - typeName string - typeID uint8 - typeVarLen bool - typePrec int64 - typeScale int64 - }{ - {"typeDateTime", typeDateTime, false, 0, 0}, - {"typeDateTim4", typeDateTim4, false, 0, 0}, - {"typeBigBinary", typeBigBinary, false, 0, 0}, - //TODO: Add other supported types - } - - for _, tt := range tests { - prec, scale, varLen := makeGoLangTypePrecisionScale(typeInfo{TypeId: tt.typeID}) - if varLen != tt.typeVarLen { - t.Errorf("invalid type length variability returned for %s", tt.typeName) - } - if prec != tt.typePrec || scale != tt.typeScale { - t.Errorf("invalid type precision and/or scale returned for %s", tt.typeName) - } - } -} - -func handlePanic(t *testing.T) { - if r := recover(); r != nil { - t.Errorf("recovered panic") - } -} diff --git a/vendor/github.com/denisenkom/go-mssqldb/uniqueidentifier_test.go b/vendor/github.com/denisenkom/go-mssqldb/uniqueidentifier_test.go deleted file mode 100644 index 2a29133a..00000000 --- a/vendor/github.com/denisenkom/go-mssqldb/uniqueidentifier_test.go +++ /dev/null @@ -1,70 +0,0 @@ -package mssql - -import ( - "bytes" - "database/sql" - "database/sql/driver" - "fmt" - "testing" -) - -func TestUniqueIdentifier(t *testing.T) { - dbUUID := UniqueIdentifier{0x67, 0x45, 0x23, 0x01, - 0xAB, 0x89, - 0xEF, 0xCD, - 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, - } - - uuid := UniqueIdentifier{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF} - - t.Run("Scan", func(t *testing.T) { - t.Run("[]byte", func(t *testing.T) { - var sut UniqueIdentifier - if err := sut.Scan(dbUUID[:]); err != nil { - t.Fatal(err) - } - if sut != uuid { - t.Errorf("bytes not swapped correctly: got %q; want %q", sut, uuid) - } - }) - - t.Run("string", func(t *testing.T) { - var sut UniqueIdentifier - if err := sut.Scan(uuid.String()); err != nil { - t.Fatal(err) - } - if sut != uuid { - t.Errorf("string not scanned correctly: got %q; want %q", sut, uuid) - } - }) - }) - - t.Run("Value", func(t *testing.T) { - sut := uuid - v, err := sut.Value() - if err != nil { - t.Fatal(err) - } - - b, ok := v.([]byte) - if !ok { - t.Fatalf("(%T) is not []byte", v) - } - - if !bytes.Equal(b, dbUUID[:]) { - t.Errorf("got %q; want %q", b, dbUUID) - } - }) -} - -func TestUniqueIdentifierString(t *testing.T) { - sut := UniqueIdentifier{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF} - expected := "01234567-89AB-CDEF-0123-456789ABCDEF" - if actual := sut.String(); actual != expected { - t.Errorf("sut.String() = %s; want %s", sut, expected) - } -} - -var _ fmt.Stringer = UniqueIdentifier{} -var _ sql.Scanner = &UniqueIdentifier{} -var _ driver.Valuer = UniqueIdentifier{} diff --git a/vendor/github.com/dgrijalva/jwt-go/MIGRATION_GUIDE.md b/vendor/github.com/dgrijalva/jwt-go/MIGRATION_GUIDE.md deleted file mode 100644 index 7fc1f793..00000000 --- a/vendor/github.com/dgrijalva/jwt-go/MIGRATION_GUIDE.md +++ /dev/null @@ -1,97 +0,0 @@ -## Migration Guide from v2 -> v3 - -Version 3 adds several new, frequently requested features. To do so, it introduces a few breaking changes. We've worked to keep these as minimal as possible. This guide explains the breaking changes and how you can quickly update your code. - -### `Token.Claims` is now an interface type - -The most requested feature from the 2.0 verison of this library was the ability to provide a custom type to the JSON parser for claims. This was implemented by introducing a new interface, `Claims`, to replace `map[string]interface{}`. We also included two concrete implementations of `Claims`: `MapClaims` and `StandardClaims`. - -`MapClaims` is an alias for `map[string]interface{}` with built in validation behavior. It is the default claims type when using `Parse`. The usage is unchanged except you must type cast the claims property. - -The old example for parsing a token looked like this.. - -```go - if token, err := jwt.Parse(tokenString, keyLookupFunc); err == nil { - fmt.Printf("Token for user %v expires %v", token.Claims["user"], token.Claims["exp"]) - } -``` - -is now directly mapped to... - -```go - if token, err := jwt.Parse(tokenString, keyLookupFunc); err == nil { - claims := token.Claims.(jwt.MapClaims) - fmt.Printf("Token for user %v expires %v", claims["user"], claims["exp"]) - } -``` - -`StandardClaims` is designed to be embedded in your custom type. You can supply a custom claims type with the new `ParseWithClaims` function. Here's an example of using a custom claims type. - -```go - type MyCustomClaims struct { - User string - *StandardClaims - } - - if token, err := jwt.ParseWithClaims(tokenString, &MyCustomClaims{}, keyLookupFunc); err == nil { - claims := token.Claims.(*MyCustomClaims) - fmt.Printf("Token for user %v expires %v", claims.User, claims.StandardClaims.ExpiresAt) - } -``` - -### `ParseFromRequest` has been moved - -To keep this library focused on the tokens without becoming overburdened with complex request processing logic, `ParseFromRequest` and its new companion `ParseFromRequestWithClaims` have been moved to a subpackage, `request`. The method signatues have also been augmented to receive a new argument: `Extractor`. - -`Extractors` do the work of picking the token string out of a request. The interface is simple and composable. - -This simple parsing example: - -```go - if token, err := jwt.ParseFromRequest(tokenString, req, keyLookupFunc); err == nil { - fmt.Printf("Token for user %v expires %v", token.Claims["user"], token.Claims["exp"]) - } -``` - -is directly mapped to: - -```go - if token, err := request.ParseFromRequest(req, request.OAuth2Extractor, keyLookupFunc); err == nil { - claims := token.Claims.(jwt.MapClaims) - fmt.Printf("Token for user %v expires %v", claims["user"], claims["exp"]) - } -``` - -There are several concrete `Extractor` types provided for your convenience: - -* `HeaderExtractor` will search a list of headers until one contains content. -* `ArgumentExtractor` will search a list of keys in request query and form arguments until one contains content. -* `MultiExtractor` will try a list of `Extractors` in order until one returns content. -* `AuthorizationHeaderExtractor` will look in the `Authorization` header for a `Bearer` token. -* `OAuth2Extractor` searches the places an OAuth2 token would be specified (per the spec): `Authorization` header and `access_token` argument -* `PostExtractionFilter` wraps an `Extractor`, allowing you to process the content before it's parsed. A simple example is stripping the `Bearer ` text from a header - - -### RSA signing methods no longer accept `[]byte` keys - -Due to a [critical vulnerability](https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/), we've decided the convenience of accepting `[]byte` instead of `rsa.PublicKey` or `rsa.PrivateKey` isn't worth the risk of misuse. - -To replace this behavior, we've added two helper methods: `ParseRSAPrivateKeyFromPEM(key []byte) (*rsa.PrivateKey, error)` and `ParseRSAPublicKeyFromPEM(key []byte) (*rsa.PublicKey, error)`. These are just simple helpers for unpacking PEM encoded PKCS1 and PKCS8 keys. If your keys are encoded any other way, all you need to do is convert them to the `crypto/rsa` package's types. - -```go - func keyLookupFunc(*Token) (interface{}, error) { - // Don't forget to validate the alg is what you expect: - if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok { - return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"]) - } - - // Look up key - key, err := lookupPublicKey(token.Header["kid"]) - if err != nil { - return nil, err - } - - // Unpack key from PEM encoded PKCS8 - return jwt.ParseRSAPublicKeyFromPEM(key) - } -``` diff --git a/vendor/github.com/dgrijalva/jwt-go/README.md b/vendor/github.com/dgrijalva/jwt-go/README.md deleted file mode 100644 index d358d881..00000000 --- a/vendor/github.com/dgrijalva/jwt-go/README.md +++ /dev/null @@ -1,100 +0,0 @@ -# jwt-go - -[![Build Status](https://travis-ci.org/dgrijalva/jwt-go.svg?branch=master)](https://travis-ci.org/dgrijalva/jwt-go) -[![GoDoc](https://godoc.org/github.com/dgrijalva/jwt-go?status.svg)](https://godoc.org/github.com/dgrijalva/jwt-go) - -A [go](http://www.golang.org) (or 'golang' for search engine friendliness) implementation of [JSON Web Tokens](http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html) - -**NEW VERSION COMING:** There have been a lot of improvements suggested since the version 3.0.0 released in 2016. I'm working now on cutting two different releases: 3.2.0 will contain any non-breaking changes or enhancements. 4.0.0 will follow shortly which will include breaking changes. See the 4.0.0 milestone to get an idea of what's coming. If you have other ideas, or would like to participate in 4.0.0, now's the time. If you depend on this library and don't want to be interrupted, I recommend you use your dependency mangement tool to pin to version 3. - -**SECURITY NOTICE:** Some older versions of Go have a security issue in the cryotp/elliptic. Recommendation is to upgrade to at least 1.8.3. See issue #216 for more detail. - -**SECURITY NOTICE:** It's important that you [validate the `alg` presented is what you expect](https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/). This library attempts to make it easy to do the right thing by requiring key types match the expected alg, but you should take the extra step to verify it in your usage. See the examples provided. - -## What the heck is a JWT? - -JWT.io has [a great introduction](https://jwt.io/introduction) to JSON Web Tokens. - -In short, it's a signed JSON object that does something useful (for example, authentication). It's commonly used for `Bearer` tokens in Oauth 2. A token is made of three parts, separated by `.`'s. The first two parts are JSON objects, that have been [base64url](http://tools.ietf.org/html/rfc4648) encoded. The last part is the signature, encoded the same way. - -The first part is called the header. It contains the necessary information for verifying the last part, the signature. For example, which encryption method was used for signing and what key was used. - -The part in the middle is the interesting bit. It's called the Claims and contains the actual stuff you care about. Refer to [the RFC](http://self-issued.info/docs/draft-jones-json-web-token.html) for information about reserved keys and the proper way to add your own. - -## What's in the box? - -This library supports the parsing and verification as well as the generation and signing of JWTs. Current supported signing algorithms are HMAC SHA, RSA, RSA-PSS, and ECDSA, though hooks are present for adding your own. - -## Examples - -See [the project documentation](https://godoc.org/github.com/dgrijalva/jwt-go) for examples of usage: - -* [Simple example of parsing and validating a token](https://godoc.org/github.com/dgrijalva/jwt-go#example-Parse--Hmac) -* [Simple example of building and signing a token](https://godoc.org/github.com/dgrijalva/jwt-go#example-New--Hmac) -* [Directory of Examples](https://godoc.org/github.com/dgrijalva/jwt-go#pkg-examples) - -## Extensions - -This library publishes all the necessary components for adding your own signing methods. Simply implement the `SigningMethod` interface and register a factory method using `RegisterSigningMethod`. - -Here's an example of an extension that integrates with the Google App Engine signing tools: https://github.com/someone1/gcp-jwt-go - -## Compliance - -This library was last reviewed to comply with [RTF 7519](http://www.rfc-editor.org/info/rfc7519) dated May 2015 with a few notable differences: - -* In order to protect against accidental use of [Unsecured JWTs](http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#UnsecuredJWT), tokens using `alg=none` will only be accepted if the constant `jwt.UnsafeAllowNoneSignatureType` is provided as the key. - -## Project Status & Versioning - -This library is considered production ready. Feedback and feature requests are appreciated. The API should be considered stable. There should be very few backwards-incompatible changes outside of major version updates (and only with good reason). - -This project uses [Semantic Versioning 2.0.0](http://semver.org). Accepted pull requests will land on `master`. Periodically, versions will be tagged from `master`. You can find all the releases on [the project releases page](https://github.com/dgrijalva/jwt-go/releases). - -While we try to make it obvious when we make breaking changes, there isn't a great mechanism for pushing announcements out to users. You may want to use this alternative package include: `gopkg.in/dgrijalva/jwt-go.v3`. It will do the right thing WRT semantic versioning. - -**BREAKING CHANGES:*** -* Version 3.0.0 includes _a lot_ of changes from the 2.x line, including a few that break the API. We've tried to break as few things as possible, so there should just be a few type signature changes. A full list of breaking changes is available in `VERSION_HISTORY.md`. See `MIGRATION_GUIDE.md` for more information on updating your code. - -## Usage Tips - -### Signing vs Encryption - -A token is simply a JSON object that is signed by its author. this tells you exactly two things about the data: - -* The author of the token was in the possession of the signing secret -* The data has not been modified since it was signed - -It's important to know that JWT does not provide encryption, which means anyone who has access to the token can read its contents. If you need to protect (encrypt) the data, there is a companion spec, `JWE`, that provides this functionality. JWE is currently outside the scope of this library. - -### Choosing a Signing Method - -There are several signing methods available, and you should probably take the time to learn about the various options before choosing one. The principal design decision is most likely going to be symmetric vs asymmetric. - -Symmetric signing methods, such as HSA, use only a single secret. This is probably the simplest signing method to use since any `[]byte` can be used as a valid secret. They are also slightly computationally faster to use, though this rarely is enough to matter. Symmetric signing methods work the best when both producers and consumers of tokens are trusted, or even the same system. Since the same secret is used to both sign and validate tokens, you can't easily distribute the key for validation. - -Asymmetric signing methods, such as RSA, use different keys for signing and verifying tokens. This makes it possible to produce tokens with a private key, and allow any consumer to access the public key for verification. - -### Signing Methods and Key Types - -Each signing method expects a different object type for its signing keys. See the package documentation for details. Here are the most common ones: - -* The [HMAC signing method](https://godoc.org/github.com/dgrijalva/jwt-go#SigningMethodHMAC) (`HS256`,`HS384`,`HS512`) expect `[]byte` values for signing and validation -* The [RSA signing method](https://godoc.org/github.com/dgrijalva/jwt-go#SigningMethodRSA) (`RS256`,`RS384`,`RS512`) expect `*rsa.PrivateKey` for signing and `*rsa.PublicKey` for validation -* The [ECDSA signing method](https://godoc.org/github.com/dgrijalva/jwt-go#SigningMethodECDSA) (`ES256`,`ES384`,`ES512`) expect `*ecdsa.PrivateKey` for signing and `*ecdsa.PublicKey` for validation - -### JWT and OAuth - -It's worth mentioning that OAuth and JWT are not the same thing. A JWT token is simply a signed JSON object. It can be used anywhere such a thing is useful. There is some confusion, though, as JWT is the most common type of bearer token used in OAuth2 authentication. - -Without going too far down the rabbit hole, here's a description of the interaction of these technologies: - -* OAuth is a protocol for allowing an identity provider to be separate from the service a user is logging in to. For example, whenever you use Facebook to log into a different service (Yelp, Spotify, etc), you are using OAuth. -* OAuth defines several options for passing around authentication data. One popular method is called a "bearer token". A bearer token is simply a string that _should_ only be held by an authenticated user. Thus, simply presenting this token proves your identity. You can probably derive from here why a JWT might make a good bearer token. -* Because bearer tokens are used for authentication, it's important they're kept secret. This is why transactions that use bearer tokens typically happen over SSL. - -## More - -Documentation can be found [on godoc.org](http://godoc.org/github.com/dgrijalva/jwt-go). - -The command line utility included in this project (cmd/jwt) provides a straightforward example of token creation and parsing as well as a useful tool for debugging your own integration. You'll also find several implementation examples in the documentation. diff --git a/vendor/github.com/dgrijalva/jwt-go/VERSION_HISTORY.md b/vendor/github.com/dgrijalva/jwt-go/VERSION_HISTORY.md deleted file mode 100644 index 63702983..00000000 --- a/vendor/github.com/dgrijalva/jwt-go/VERSION_HISTORY.md +++ /dev/null @@ -1,118 +0,0 @@ -## `jwt-go` Version History - -#### 3.2.0 - -* Added method `ParseUnverified` to allow users to split up the tasks of parsing and validation -* HMAC signing method returns `ErrInvalidKeyType` instead of `ErrInvalidKey` where appropriate -* Added options to `request.ParseFromRequest`, which allows for an arbitrary list of modifiers to parsing behavior. Initial set include `WithClaims` and `WithParser`. Existing usage of this function will continue to work as before. -* Deprecated `ParseFromRequestWithClaims` to simplify API in the future. - -#### 3.1.0 - -* Improvements to `jwt` command line tool -* Added `SkipClaimsValidation` option to `Parser` -* Documentation updates - -#### 3.0.0 - -* **Compatibility Breaking Changes**: See MIGRATION_GUIDE.md for tips on updating your code - * Dropped support for `[]byte` keys when using RSA signing methods. This convenience feature could contribute to security vulnerabilities involving mismatched key types with signing methods. - * `ParseFromRequest` has been moved to `request` subpackage and usage has changed - * The `Claims` property on `Token` is now type `Claims` instead of `map[string]interface{}`. The default value is type `MapClaims`, which is an alias to `map[string]interface{}`. This makes it possible to use a custom type when decoding claims. -* Other Additions and Changes - * Added `Claims` interface type to allow users to decode the claims into a custom type - * Added `ParseWithClaims`, which takes a third argument of type `Claims`. Use this function instead of `Parse` if you have a custom type you'd like to decode into. - * Dramatically improved the functionality and flexibility of `ParseFromRequest`, which is now in the `request` subpackage - * Added `ParseFromRequestWithClaims` which is the `FromRequest` equivalent of `ParseWithClaims` - * Added new interface type `Extractor`, which is used for extracting JWT strings from http requests. Used with `ParseFromRequest` and `ParseFromRequestWithClaims`. - * Added several new, more specific, validation errors to error type bitmask - * Moved examples from README to executable example files - * Signing method registry is now thread safe - * Added new property to `ValidationError`, which contains the raw error returned by calls made by parse/verify (such as those returned by keyfunc or json parser) - -#### 2.7.0 - -This will likely be the last backwards compatible release before 3.0.0, excluding essential bug fixes. - -* Added new option `-show` to the `jwt` command that will just output the decoded token without verifying -* Error text for expired tokens includes how long it's been expired -* Fixed incorrect error returned from `ParseRSAPublicKeyFromPEM` -* Documentation updates - -#### 2.6.0 - -* Exposed inner error within ValidationError -* Fixed validation errors when using UseJSONNumber flag -* Added several unit tests - -#### 2.5.0 - -* Added support for signing method none. You shouldn't use this. The API tries to make this clear. -* Updated/fixed some documentation -* Added more helpful error message when trying to parse tokens that begin with `BEARER ` - -#### 2.4.0 - -* Added new type, Parser, to allow for configuration of various parsing parameters - * You can now specify a list of valid signing methods. Anything outside this set will be rejected. - * You can now opt to use the `json.Number` type instead of `float64` when parsing token JSON -* Added support for [Travis CI](https://travis-ci.org/dgrijalva/jwt-go) -* Fixed some bugs with ECDSA parsing - -#### 2.3.0 - -* Added support for ECDSA signing methods -* Added support for RSA PSS signing methods (requires go v1.4) - -#### 2.2.0 - -* Gracefully handle a `nil` `Keyfunc` being passed to `Parse`. Result will now be the parsed token and an error, instead of a panic. - -#### 2.1.0 - -Backwards compatible API change that was missed in 2.0.0. - -* The `SignedString` method on `Token` now takes `interface{}` instead of `[]byte` - -#### 2.0.0 - -There were two major reasons for breaking backwards compatibility with this update. The first was a refactor required to expand the width of the RSA and HMAC-SHA signing implementations. There will likely be no required code changes to support this change. - -The second update, while unfortunately requiring a small change in integration, is required to open up this library to other signing methods. Not all keys used for all signing methods have a single standard on-disk representation. Requiring `[]byte` as the type for all keys proved too limiting. Additionally, this implementation allows for pre-parsed tokens to be reused, which might matter in an application that parses a high volume of tokens with a small set of keys. Backwards compatibilty has been maintained for passing `[]byte` to the RSA signing methods, but they will also accept `*rsa.PublicKey` and `*rsa.PrivateKey`. - -It is likely the only integration change required here will be to change `func(t *jwt.Token) ([]byte, error)` to `func(t *jwt.Token) (interface{}, error)` when calling `Parse`. - -* **Compatibility Breaking Changes** - * `SigningMethodHS256` is now `*SigningMethodHMAC` instead of `type struct` - * `SigningMethodRS256` is now `*SigningMethodRSA` instead of `type struct` - * `KeyFunc` now returns `interface{}` instead of `[]byte` - * `SigningMethod.Sign` now takes `interface{}` instead of `[]byte` for the key - * `SigningMethod.Verify` now takes `interface{}` instead of `[]byte` for the key -* Renamed type `SigningMethodHS256` to `SigningMethodHMAC`. Specific sizes are now just instances of this type. - * Added public package global `SigningMethodHS256` - * Added public package global `SigningMethodHS384` - * Added public package global `SigningMethodHS512` -* Renamed type `SigningMethodRS256` to `SigningMethodRSA`. Specific sizes are now just instances of this type. - * Added public package global `SigningMethodRS256` - * Added public package global `SigningMethodRS384` - * Added public package global `SigningMethodRS512` -* Moved sample private key for HMAC tests from an inline value to a file on disk. Value is unchanged. -* Refactored the RSA implementation to be easier to read -* Exposed helper methods `ParseRSAPrivateKeyFromPEM` and `ParseRSAPublicKeyFromPEM` - -#### 1.0.2 - -* Fixed bug in parsing public keys from certificates -* Added more tests around the parsing of keys for RS256 -* Code refactoring in RS256 implementation. No functional changes - -#### 1.0.1 - -* Fixed panic if RS256 signing method was passed an invalid key - -#### 1.0.0 - -* First versioned release -* API stabilized -* Supports creating, signing, parsing, and validating JWT tokens -* Supports RS256 and HS256 signing methods \ No newline at end of file diff --git a/vendor/github.com/dgrijalva/jwt-go/ecdsa_test.go b/vendor/github.com/dgrijalva/jwt-go/ecdsa_test.go deleted file mode 100644 index 753047b1..00000000 --- a/vendor/github.com/dgrijalva/jwt-go/ecdsa_test.go +++ /dev/null @@ -1,100 +0,0 @@ -package jwt_test - -import ( - "crypto/ecdsa" - "io/ioutil" - "strings" - "testing" - - "github.com/dgrijalva/jwt-go" -) - -var ecdsaTestData = []struct { - name string - keys map[string]string - tokenString string - alg string - claims map[string]interface{} - valid bool -}{ - { - "Basic ES256", - map[string]string{"private": "test/ec256-private.pem", "public": "test/ec256-public.pem"}, - "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJmb28iOiJiYXIifQ.feG39E-bn8HXAKhzDZq7yEAPWYDhZlwTn3sePJnU9VrGMmwdXAIEyoOnrjreYlVM_Z4N13eK9-TmMTWyfKJtHQ", - "ES256", - map[string]interface{}{"foo": "bar"}, - true, - }, - { - "Basic ES384", - map[string]string{"private": "test/ec384-private.pem", "public": "test/ec384-public.pem"}, - "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzM4NCJ9.eyJmb28iOiJiYXIifQ.ngAfKMbJUh0WWubSIYe5GMsA-aHNKwFbJk_wq3lq23aPp8H2anb1rRILIzVR0gUf4a8WzDtrzmiikuPWyCS6CN4-PwdgTk-5nehC7JXqlaBZU05p3toM3nWCwm_LXcld", - "ES384", - map[string]interface{}{"foo": "bar"}, - true, - }, - { - "Basic ES512", - map[string]string{"private": "test/ec512-private.pem", "public": "test/ec512-public.pem"}, - "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzUxMiJ9.eyJmb28iOiJiYXIifQ.AAU0TvGQOcdg2OvrwY73NHKgfk26UDekh9Prz-L_iWuTBIBqOFCWwwLsRiHB1JOddfKAls5do1W0jR_F30JpVd-6AJeTjGKA4C1A1H6gIKwRY0o_tFDIydZCl_lMBMeG5VNFAjO86-WCSKwc3hqaGkq1MugPRq_qrF9AVbuEB4JPLyL5", - "ES512", - map[string]interface{}{"foo": "bar"}, - true, - }, - { - "basic ES256 invalid: foo => bar", - map[string]string{"private": "test/ec256-private.pem", "public": "test/ec256-public.pem"}, - "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.MEQCIHoSJnmGlPaVQDqacx_2XlXEhhqtWceVopjomc2PJLtdAiAUTeGPoNYxZw0z8mgOnnIcjoxRuNDVZvybRZF3wR1l8W", - "ES256", - map[string]interface{}{"foo": "bar"}, - false, - }, -} - -func TestECDSAVerify(t *testing.T) { - for _, data := range ecdsaTestData { - var err error - - key, _ := ioutil.ReadFile(data.keys["public"]) - - var ecdsaKey *ecdsa.PublicKey - if ecdsaKey, err = jwt.ParseECPublicKeyFromPEM(key); err != nil { - t.Errorf("Unable to parse ECDSA public key: %v", err) - } - - parts := strings.Split(data.tokenString, ".") - - method := jwt.GetSigningMethod(data.alg) - err = method.Verify(strings.Join(parts[0:2], "."), parts[2], ecdsaKey) - if data.valid && err != nil { - t.Errorf("[%v] Error while verifying key: %v", data.name, err) - } - if !data.valid && err == nil { - t.Errorf("[%v] Invalid key passed validation", data.name) - } - } -} - -func TestECDSASign(t *testing.T) { - for _, data := range ecdsaTestData { - var err error - key, _ := ioutil.ReadFile(data.keys["private"]) - - var ecdsaKey *ecdsa.PrivateKey - if ecdsaKey, err = jwt.ParseECPrivateKeyFromPEM(key); err != nil { - t.Errorf("Unable to parse ECDSA private key: %v", err) - } - - if data.valid { - parts := strings.Split(data.tokenString, ".") - method := jwt.GetSigningMethod(data.alg) - sig, err := method.Sign(strings.Join(parts[0:2], "."), ecdsaKey) - if err != nil { - t.Errorf("[%v] Error signing token: %v", data.name, err) - } - if sig == parts[2] { - t.Errorf("[%v] Identical signatures\nbefore:\n%v\nafter:\n%v", data.name, parts[2], sig) - } - } - } -} diff --git a/vendor/github.com/dgrijalva/jwt-go/example_test.go b/vendor/github.com/dgrijalva/jwt-go/example_test.go deleted file mode 100644 index ae8b788a..00000000 --- a/vendor/github.com/dgrijalva/jwt-go/example_test.go +++ /dev/null @@ -1,114 +0,0 @@ -package jwt_test - -import ( - "fmt" - "github.com/dgrijalva/jwt-go" - "time" -) - -// Example (atypical) using the StandardClaims type by itself to parse a token. -// The StandardClaims type is designed to be embedded into your custom types -// to provide standard validation features. You can use it alone, but there's -// no way to retrieve other fields after parsing. -// See the CustomClaimsType example for intended usage. -func ExampleNewWithClaims_standardClaims() { - mySigningKey := []byte("AllYourBase") - - // Create the Claims - claims := &jwt.StandardClaims{ - ExpiresAt: 15000, - Issuer: "test", - } - - token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) - ss, err := token.SignedString(mySigningKey) - fmt.Printf("%v %v", ss, err) - //Output: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1MDAwLCJpc3MiOiJ0ZXN0In0.QsODzZu3lUZMVdhbO76u3Jv02iYCvEHcYVUI1kOWEU0 -} - -// Example creating a token using a custom claims type. The StandardClaim is embedded -// in the custom type to allow for easy encoding, parsing and validation of standard claims. -func ExampleNewWithClaims_customClaimsType() { - mySigningKey := []byte("AllYourBase") - - type MyCustomClaims struct { - Foo string `json:"foo"` - jwt.StandardClaims - } - - // Create the Claims - claims := MyCustomClaims{ - "bar", - jwt.StandardClaims{ - ExpiresAt: 15000, - Issuer: "test", - }, - } - - token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) - ss, err := token.SignedString(mySigningKey) - fmt.Printf("%v %v", ss, err) - //Output: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJleHAiOjE1MDAwLCJpc3MiOiJ0ZXN0In0.HE7fK0xOQwFEr4WDgRWj4teRPZ6i3GLwD5YCm6Pwu_c -} - -// Example creating a token using a custom claims type. The StandardClaim is embedded -// in the custom type to allow for easy encoding, parsing and validation of standard claims. -func ExampleParseWithClaims_customClaimsType() { - tokenString := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJleHAiOjE1MDAwLCJpc3MiOiJ0ZXN0In0.HE7fK0xOQwFEr4WDgRWj4teRPZ6i3GLwD5YCm6Pwu_c" - - type MyCustomClaims struct { - Foo string `json:"foo"` - jwt.StandardClaims - } - - // sample token is expired. override time so it parses as valid - at(time.Unix(0, 0), func() { - token, err := jwt.ParseWithClaims(tokenString, &MyCustomClaims{}, func(token *jwt.Token) (interface{}, error) { - return []byte("AllYourBase"), nil - }) - - if claims, ok := token.Claims.(*MyCustomClaims); ok && token.Valid { - fmt.Printf("%v %v", claims.Foo, claims.StandardClaims.ExpiresAt) - } else { - fmt.Println(err) - } - }) - - // Output: bar 15000 -} - -// Override time value for tests. Restore default value after. -func at(t time.Time, f func()) { - jwt.TimeFunc = func() time.Time { - return t - } - f() - jwt.TimeFunc = time.Now -} - -// An example of parsing the error types using bitfield checks -func ExampleParse_errorChecking() { - // Token from another example. This token is expired - var tokenString = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJleHAiOjE1MDAwLCJpc3MiOiJ0ZXN0In0.HE7fK0xOQwFEr4WDgRWj4teRPZ6i3GLwD5YCm6Pwu_c" - - token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { - return []byte("AllYourBase"), nil - }) - - if token.Valid { - fmt.Println("You look nice today") - } else if ve, ok := err.(*jwt.ValidationError); ok { - if ve.Errors&jwt.ValidationErrorMalformed != 0 { - fmt.Println("That's not even a token") - } else if ve.Errors&(jwt.ValidationErrorExpired|jwt.ValidationErrorNotValidYet) != 0 { - // Token is either expired or not active yet - fmt.Println("Timing is everything") - } else { - fmt.Println("Couldn't handle this token:", err) - } - } else { - fmt.Println("Couldn't handle this token:", err) - } - - // Output: Timing is everything -} diff --git a/vendor/github.com/dgrijalva/jwt-go/hmac_example_test.go b/vendor/github.com/dgrijalva/jwt-go/hmac_example_test.go deleted file mode 100644 index 00278314..00000000 --- a/vendor/github.com/dgrijalva/jwt-go/hmac_example_test.go +++ /dev/null @@ -1,66 +0,0 @@ -package jwt_test - -import ( - "fmt" - "github.com/dgrijalva/jwt-go" - "io/ioutil" - "time" -) - -// For HMAC signing method, the key can be any []byte. It is recommended to generate -// a key using crypto/rand or something equivalent. You need the same key for signing -// and validating. -var hmacSampleSecret []byte - -func init() { - // Load sample key data - if keyData, e := ioutil.ReadFile("test/hmacTestKey"); e == nil { - hmacSampleSecret = keyData - } else { - panic(e) - } -} - -// Example creating, signing, and encoding a JWT token using the HMAC signing method -func ExampleNew_hmac() { - // Create a new token object, specifying signing method and the claims - // you would like it to contain. - token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ - "foo": "bar", - "nbf": time.Date(2015, 10, 10, 12, 0, 0, 0, time.UTC).Unix(), - }) - - // Sign and get the complete encoded token as a string using the secret - tokenString, err := token.SignedString(hmacSampleSecret) - - fmt.Println(tokenString, err) - // Output: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJuYmYiOjE0NDQ0Nzg0MDB9.u1riaD1rW97opCoAuRCTy4w58Br-Zk-bh7vLiRIsrpU -} - -// Example parsing and validating a token using the HMAC signing method -func ExampleParse_hmac() { - // sample token string taken from the New example - tokenString := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJuYmYiOjE0NDQ0Nzg0MDB9.u1riaD1rW97opCoAuRCTy4w58Br-Zk-bh7vLiRIsrpU" - - // Parse takes the token string and a function for looking up the key. The latter is especially - // useful if you use multiple keys for your application. The standard is to use 'kid' in the - // head of the token to identify which key to use, but the parsed token (head and claims) is provided - // to the callback, providing flexibility. - token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { - // Don't forget to validate the alg is what you expect: - if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { - return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"]) - } - - // hmacSampleSecret is a []byte containing your secret, e.g. []byte("my_secret_key") - return hmacSampleSecret, nil - }) - - if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid { - fmt.Println(claims["foo"], claims["nbf"]) - } else { - fmt.Println(err) - } - - // Output: bar 1.4444784e+09 -} diff --git a/vendor/github.com/dgrijalva/jwt-go/hmac_test.go b/vendor/github.com/dgrijalva/jwt-go/hmac_test.go deleted file mode 100644 index c7e114f4..00000000 --- a/vendor/github.com/dgrijalva/jwt-go/hmac_test.go +++ /dev/null @@ -1,91 +0,0 @@ -package jwt_test - -import ( - "github.com/dgrijalva/jwt-go" - "io/ioutil" - "strings" - "testing" -) - -var hmacTestData = []struct { - name string - tokenString string - alg string - claims map[string]interface{} - valid bool -}{ - { - "web sample", - "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk", - "HS256", - map[string]interface{}{"iss": "joe", "exp": 1300819380, "http://example.com/is_root": true}, - true, - }, - { - "HS384", - "eyJhbGciOiJIUzM4NCIsInR5cCI6IkpXVCJ9.eyJleHAiOjEuMzAwODE5MzhlKzA5LCJodHRwOi8vZXhhbXBsZS5jb20vaXNfcm9vdCI6dHJ1ZSwiaXNzIjoiam9lIn0.KWZEuOD5lbBxZ34g7F-SlVLAQ_r5KApWNWlZIIMyQVz5Zs58a7XdNzj5_0EcNoOy", - "HS384", - map[string]interface{}{"iss": "joe", "exp": 1300819380, "http://example.com/is_root": true}, - true, - }, - { - "HS512", - "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjEuMzAwODE5MzhlKzA5LCJodHRwOi8vZXhhbXBsZS5jb20vaXNfcm9vdCI6dHJ1ZSwiaXNzIjoiam9lIn0.CN7YijRX6Aw1n2jyI2Id1w90ja-DEMYiWixhYCyHnrZ1VfJRaFQz1bEbjjA5Fn4CLYaUG432dEYmSbS4Saokmw", - "HS512", - map[string]interface{}{"iss": "joe", "exp": 1300819380, "http://example.com/is_root": true}, - true, - }, - { - "web sample: invalid", - "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXo", - "HS256", - map[string]interface{}{"iss": "joe", "exp": 1300819380, "http://example.com/is_root": true}, - false, - }, -} - -// Sample data from http://tools.ietf.org/html/draft-jones-json-web-signature-04#appendix-A.1 -var hmacTestKey, _ = ioutil.ReadFile("test/hmacTestKey") - -func TestHMACVerify(t *testing.T) { - for _, data := range hmacTestData { - parts := strings.Split(data.tokenString, ".") - - method := jwt.GetSigningMethod(data.alg) - err := method.Verify(strings.Join(parts[0:2], "."), parts[2], hmacTestKey) - if data.valid && err != nil { - t.Errorf("[%v] Error while verifying key: %v", data.name, err) - } - if !data.valid && err == nil { - t.Errorf("[%v] Invalid key passed validation", data.name) - } - } -} - -func TestHMACSign(t *testing.T) { - for _, data := range hmacTestData { - if data.valid { - parts := strings.Split(data.tokenString, ".") - method := jwt.GetSigningMethod(data.alg) - sig, err := method.Sign(strings.Join(parts[0:2], "."), hmacTestKey) - if err != nil { - t.Errorf("[%v] Error signing token: %v", data.name, err) - } - if sig != parts[2] { - t.Errorf("[%v] Incorrect signature.\nwas:\n%v\nexpecting:\n%v", data.name, sig, parts[2]) - } - } - } -} - -func BenchmarkHS256Signing(b *testing.B) { - benchmarkSigning(b, jwt.SigningMethodHS256, hmacTestKey) -} - -func BenchmarkHS384Signing(b *testing.B) { - benchmarkSigning(b, jwt.SigningMethodHS384, hmacTestKey) -} - -func BenchmarkHS512Signing(b *testing.B) { - benchmarkSigning(b, jwt.SigningMethodHS512, hmacTestKey) -} diff --git a/vendor/github.com/dgrijalva/jwt-go/http_example_test.go b/vendor/github.com/dgrijalva/jwt-go/http_example_test.go deleted file mode 100644 index 82e9c50a..00000000 --- a/vendor/github.com/dgrijalva/jwt-go/http_example_test.go +++ /dev/null @@ -1,216 +0,0 @@ -package jwt_test - -// Example HTTP auth using asymmetric crypto/RSA keys -// This is based on a (now outdated) example at https://gist.github.com/cryptix/45c33ecf0ae54828e63b - -import ( - "bytes" - "crypto/rsa" - "fmt" - "github.com/dgrijalva/jwt-go" - "github.com/dgrijalva/jwt-go/request" - "io" - "io/ioutil" - "log" - "net" - "net/http" - "net/url" - "strings" - "time" -) - -// location of the files used for signing and verification -const ( - privKeyPath = "test/sample_key" // openssl genrsa -out app.rsa keysize - pubKeyPath = "test/sample_key.pub" // openssl rsa -in app.rsa -pubout > app.rsa.pub -) - -var ( - verifyKey *rsa.PublicKey - signKey *rsa.PrivateKey - serverPort int - // storing sample username/password pairs - // don't do this on a real server - users = map[string]string{ - "test": "known", - } -) - -// read the key files before starting http handlers -func init() { - signBytes, err := ioutil.ReadFile(privKeyPath) - fatal(err) - - signKey, err = jwt.ParseRSAPrivateKeyFromPEM(signBytes) - fatal(err) - - verifyBytes, err := ioutil.ReadFile(pubKeyPath) - fatal(err) - - verifyKey, err = jwt.ParseRSAPublicKeyFromPEM(verifyBytes) - fatal(err) - - http.HandleFunc("/authenticate", authHandler) - http.HandleFunc("/restricted", restrictedHandler) - - // Setup listener - listener, err := net.ListenTCP("tcp", &net.TCPAddr{}) - serverPort = listener.Addr().(*net.TCPAddr).Port - - log.Println("Listening...") - go func() { - fatal(http.Serve(listener, nil)) - }() -} - -var start func() - -func fatal(err error) { - if err != nil { - log.Fatal(err) - } -} - -// Define some custom types were going to use within our tokens -type CustomerInfo struct { - Name string - Kind string -} - -type CustomClaimsExample struct { - *jwt.StandardClaims - TokenType string - CustomerInfo -} - -func Example_getTokenViaHTTP() { - // See func authHandler for an example auth handler that produces a token - res, err := http.PostForm(fmt.Sprintf("http://localhost:%v/authenticate", serverPort), url.Values{ - "user": {"test"}, - "pass": {"known"}, - }) - if err != nil { - fatal(err) - } - - if res.StatusCode != 200 { - fmt.Println("Unexpected status code", res.StatusCode) - } - - // Read the token out of the response body - buf := new(bytes.Buffer) - io.Copy(buf, res.Body) - res.Body.Close() - tokenString := strings.TrimSpace(buf.String()) - - // Parse the token - token, err := jwt.ParseWithClaims(tokenString, &CustomClaimsExample{}, func(token *jwt.Token) (interface{}, error) { - // since we only use the one private key to sign the tokens, - // we also only use its public counter part to verify - return verifyKey, nil - }) - fatal(err) - - claims := token.Claims.(*CustomClaimsExample) - fmt.Println(claims.CustomerInfo.Name) - - //Output: test -} - -func Example_useTokenViaHTTP() { - - // Make a sample token - // In a real world situation, this token will have been acquired from - // some other API call (see Example_getTokenViaHTTP) - token, err := createToken("foo") - fatal(err) - - // Make request. See func restrictedHandler for example request processor - req, err := http.NewRequest("GET", fmt.Sprintf("http://localhost:%v/restricted", serverPort), nil) - fatal(err) - req.Header.Set("Authorization", fmt.Sprintf("Bearer %v", token)) - res, err := http.DefaultClient.Do(req) - fatal(err) - - // Read the response body - buf := new(bytes.Buffer) - io.Copy(buf, res.Body) - res.Body.Close() - fmt.Println(buf.String()) - - // Output: Welcome, foo -} - -func createToken(user string) (string, error) { - // create a signer for rsa 256 - t := jwt.New(jwt.GetSigningMethod("RS256")) - - // set our claims - t.Claims = &CustomClaimsExample{ - &jwt.StandardClaims{ - // set the expire time - // see http://tools.ietf.org/html/draft-ietf-oauth-json-web-token-20#section-4.1.4 - ExpiresAt: time.Now().Add(time.Minute * 1).Unix(), - }, - "level1", - CustomerInfo{user, "human"}, - } - - // Creat token string - return t.SignedString(signKey) -} - -// reads the form values, checks them and creates the token -func authHandler(w http.ResponseWriter, r *http.Request) { - // make sure its post - if r.Method != "POST" { - w.WriteHeader(http.StatusBadRequest) - fmt.Fprintln(w, "No POST", r.Method) - return - } - - user := r.FormValue("user") - pass := r.FormValue("pass") - - log.Printf("Authenticate: user[%s] pass[%s]\n", user, pass) - - // check values - if user != "test" || pass != "known" { - w.WriteHeader(http.StatusForbidden) - fmt.Fprintln(w, "Wrong info") - return - } - - tokenString, err := createToken(user) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - fmt.Fprintln(w, "Sorry, error while Signing Token!") - log.Printf("Token Signing error: %v\n", err) - return - } - - w.Header().Set("Content-Type", "application/jwt") - w.WriteHeader(http.StatusOK) - fmt.Fprintln(w, tokenString) -} - -// only accessible with a valid token -func restrictedHandler(w http.ResponseWriter, r *http.Request) { - // Get token from request - token, err := request.ParseFromRequestWithClaims(r, request.OAuth2Extractor, &CustomClaimsExample{}, func(token *jwt.Token) (interface{}, error) { - // since we only use the one private key to sign the tokens, - // we also only use its public counter part to verify - return verifyKey, nil - }) - - // If the token is missing or invalid, return error - if err != nil { - w.WriteHeader(http.StatusUnauthorized) - fmt.Fprintln(w, "Invalid token:", err) - return - } - - // Token is valid - fmt.Fprintln(w, "Welcome,", token.Claims.(*CustomClaimsExample).Name) - return -} diff --git a/vendor/github.com/dgrijalva/jwt-go/none_test.go b/vendor/github.com/dgrijalva/jwt-go/none_test.go deleted file mode 100644 index 29a69efe..00000000 --- a/vendor/github.com/dgrijalva/jwt-go/none_test.go +++ /dev/null @@ -1,72 +0,0 @@ -package jwt_test - -import ( - "github.com/dgrijalva/jwt-go" - "strings" - "testing" -) - -var noneTestData = []struct { - name string - tokenString string - alg string - key interface{} - claims map[string]interface{} - valid bool -}{ - { - "Basic", - "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.", - "none", - jwt.UnsafeAllowNoneSignatureType, - map[string]interface{}{"foo": "bar"}, - true, - }, - { - "Basic - no key", - "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.", - "none", - nil, - map[string]interface{}{"foo": "bar"}, - false, - }, - { - "Signed", - "eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.W-jEzRfBigtCWsinvVVuldiuilzVdU5ty0MvpLaSaqK9PlAWWlDQ1VIQ_qSKzwL5IXaZkvZFJXT3yL3n7OUVu7zCNJzdwznbC8Z-b0z2lYvcklJYi2VOFRcGbJtXUqgjk2oGsiqUMUMOLP70TTefkpsgqDxbRh9CDUfpOJgW-dU7cmgaoswe3wjUAUi6B6G2YEaiuXC0XScQYSYVKIzgKXJV8Zw-7AN_DBUI4GkTpsvQ9fVVjZM9csQiEXhYekyrKu1nu_POpQonGd8yqkIyXPECNmmqH5jH4sFiF67XhD7_JpkvLziBpI-uh86evBUadmHhb9Otqw3uV3NTaXLzJw", - "none", - jwt.UnsafeAllowNoneSignatureType, - map[string]interface{}{"foo": "bar"}, - false, - }, -} - -func TestNoneVerify(t *testing.T) { - for _, data := range noneTestData { - parts := strings.Split(data.tokenString, ".") - - method := jwt.GetSigningMethod(data.alg) - err := method.Verify(strings.Join(parts[0:2], "."), parts[2], data.key) - if data.valid && err != nil { - t.Errorf("[%v] Error while verifying key: %v", data.name, err) - } - if !data.valid && err == nil { - t.Errorf("[%v] Invalid key passed validation", data.name) - } - } -} - -func TestNoneSign(t *testing.T) { - for _, data := range noneTestData { - if data.valid { - parts := strings.Split(data.tokenString, ".") - method := jwt.GetSigningMethod(data.alg) - sig, err := method.Sign(strings.Join(parts[0:2], "."), data.key) - if err != nil { - t.Errorf("[%v] Error signing token: %v", data.name, err) - } - if sig != parts[2] { - t.Errorf("[%v] Incorrect signature.\nwas:\n%v\nexpecting:\n%v", data.name, sig, parts[2]) - } - } - } -} diff --git a/vendor/github.com/dgrijalva/jwt-go/parser_test.go b/vendor/github.com/dgrijalva/jwt-go/parser_test.go deleted file mode 100644 index 39077978..00000000 --- a/vendor/github.com/dgrijalva/jwt-go/parser_test.go +++ /dev/null @@ -1,301 +0,0 @@ -package jwt_test - -import ( - "crypto/rsa" - "encoding/json" - "fmt" - "reflect" - "testing" - "time" - - "github.com/dgrijalva/jwt-go" - "github.com/dgrijalva/jwt-go/test" -) - -var keyFuncError error = fmt.Errorf("error loading key") - -var ( - jwtTestDefaultKey *rsa.PublicKey - defaultKeyFunc jwt.Keyfunc = func(t *jwt.Token) (interface{}, error) { return jwtTestDefaultKey, nil } - emptyKeyFunc jwt.Keyfunc = func(t *jwt.Token) (interface{}, error) { return nil, nil } - errorKeyFunc jwt.Keyfunc = func(t *jwt.Token) (interface{}, error) { return nil, keyFuncError } - nilKeyFunc jwt.Keyfunc = nil -) - -func init() { - jwtTestDefaultKey = test.LoadRSAPublicKeyFromDisk("test/sample_key.pub") -} - -var jwtTestData = []struct { - name string - tokenString string - keyfunc jwt.Keyfunc - claims jwt.Claims - valid bool - errors uint32 - parser *jwt.Parser -}{ - { - "basic", - "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.FhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg", - defaultKeyFunc, - jwt.MapClaims{"foo": "bar"}, - true, - 0, - nil, - }, - { - "basic expired", - "", // autogen - defaultKeyFunc, - jwt.MapClaims{"foo": "bar", "exp": float64(time.Now().Unix() - 100)}, - false, - jwt.ValidationErrorExpired, - nil, - }, - { - "basic nbf", - "", // autogen - defaultKeyFunc, - jwt.MapClaims{"foo": "bar", "nbf": float64(time.Now().Unix() + 100)}, - false, - jwt.ValidationErrorNotValidYet, - nil, - }, - { - "expired and nbf", - "", // autogen - defaultKeyFunc, - jwt.MapClaims{"foo": "bar", "nbf": float64(time.Now().Unix() + 100), "exp": float64(time.Now().Unix() - 100)}, - false, - jwt.ValidationErrorNotValidYet | jwt.ValidationErrorExpired, - nil, - }, - { - "basic invalid", - "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.EhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg", - defaultKeyFunc, - jwt.MapClaims{"foo": "bar"}, - false, - jwt.ValidationErrorSignatureInvalid, - nil, - }, - { - "basic nokeyfunc", - "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.FhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg", - nilKeyFunc, - jwt.MapClaims{"foo": "bar"}, - false, - jwt.ValidationErrorUnverifiable, - nil, - }, - { - "basic nokey", - "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.FhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg", - emptyKeyFunc, - jwt.MapClaims{"foo": "bar"}, - false, - jwt.ValidationErrorSignatureInvalid, - nil, - }, - { - "basic errorkey", - "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.FhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg", - errorKeyFunc, - jwt.MapClaims{"foo": "bar"}, - false, - jwt.ValidationErrorUnverifiable, - nil, - }, - { - "invalid signing method", - "", - defaultKeyFunc, - jwt.MapClaims{"foo": "bar"}, - false, - jwt.ValidationErrorSignatureInvalid, - &jwt.Parser{ValidMethods: []string{"HS256"}}, - }, - { - "valid signing method", - "", - defaultKeyFunc, - jwt.MapClaims{"foo": "bar"}, - true, - 0, - &jwt.Parser{ValidMethods: []string{"RS256", "HS256"}}, - }, - { - "JSON Number", - "", - defaultKeyFunc, - jwt.MapClaims{"foo": json.Number("123.4")}, - true, - 0, - &jwt.Parser{UseJSONNumber: true}, - }, - { - "Standard Claims", - "", - defaultKeyFunc, - &jwt.StandardClaims{ - ExpiresAt: time.Now().Add(time.Second * 10).Unix(), - }, - true, - 0, - &jwt.Parser{UseJSONNumber: true}, - }, - { - "JSON Number - basic expired", - "", // autogen - defaultKeyFunc, - jwt.MapClaims{"foo": "bar", "exp": json.Number(fmt.Sprintf("%v", time.Now().Unix()-100))}, - false, - jwt.ValidationErrorExpired, - &jwt.Parser{UseJSONNumber: true}, - }, - { - "JSON Number - basic nbf", - "", // autogen - defaultKeyFunc, - jwt.MapClaims{"foo": "bar", "nbf": json.Number(fmt.Sprintf("%v", time.Now().Unix()+100))}, - false, - jwt.ValidationErrorNotValidYet, - &jwt.Parser{UseJSONNumber: true}, - }, - { - "JSON Number - expired and nbf", - "", // autogen - defaultKeyFunc, - jwt.MapClaims{"foo": "bar", "nbf": json.Number(fmt.Sprintf("%v", time.Now().Unix()+100)), "exp": json.Number(fmt.Sprintf("%v", time.Now().Unix()-100))}, - false, - jwt.ValidationErrorNotValidYet | jwt.ValidationErrorExpired, - &jwt.Parser{UseJSONNumber: true}, - }, - { - "SkipClaimsValidation during token parsing", - "", // autogen - defaultKeyFunc, - jwt.MapClaims{"foo": "bar", "nbf": json.Number(fmt.Sprintf("%v", time.Now().Unix()+100))}, - true, - 0, - &jwt.Parser{UseJSONNumber: true, SkipClaimsValidation: true}, - }, -} - -func TestParser_Parse(t *testing.T) { - privateKey := test.LoadRSAPrivateKeyFromDisk("test/sample_key") - - // Iterate over test data set and run tests - for _, data := range jwtTestData { - // If the token string is blank, use helper function to generate string - if data.tokenString == "" { - data.tokenString = test.MakeSampleToken(data.claims, privateKey) - } - - // Parse the token - var token *jwt.Token - var err error - var parser = data.parser - if parser == nil { - parser = new(jwt.Parser) - } - // Figure out correct claims type - switch data.claims.(type) { - case jwt.MapClaims: - token, err = parser.ParseWithClaims(data.tokenString, jwt.MapClaims{}, data.keyfunc) - case *jwt.StandardClaims: - token, err = parser.ParseWithClaims(data.tokenString, &jwt.StandardClaims{}, data.keyfunc) - } - - // Verify result matches expectation - if !reflect.DeepEqual(data.claims, token.Claims) { - t.Errorf("[%v] Claims mismatch. Expecting: %v Got: %v", data.name, data.claims, token.Claims) - } - - if data.valid && err != nil { - t.Errorf("[%v] Error while verifying token: %T:%v", data.name, err, err) - } - - if !data.valid && err == nil { - t.Errorf("[%v] Invalid token passed validation", data.name) - } - - if (err == nil && !token.Valid) || (err != nil && token.Valid) { - t.Errorf("[%v] Inconsistent behavior between returned error and token.Valid", data.name) - } - - if data.errors != 0 { - if err == nil { - t.Errorf("[%v] Expecting error. Didn't get one.", data.name) - } else { - - ve := err.(*jwt.ValidationError) - // compare the bitfield part of the error - if e := ve.Errors; e != data.errors { - t.Errorf("[%v] Errors don't match expectation. %v != %v", data.name, e, data.errors) - } - - if err.Error() == keyFuncError.Error() && ve.Inner != keyFuncError { - t.Errorf("[%v] Inner error does not match expectation. %v != %v", data.name, ve.Inner, keyFuncError) - } - } - } - if data.valid && token.Signature == "" { - t.Errorf("[%v] Signature is left unpopulated after parsing", data.name) - } - } -} - -func TestParser_ParseUnverified(t *testing.T) { - privateKey := test.LoadRSAPrivateKeyFromDisk("test/sample_key") - - // Iterate over test data set and run tests - for _, data := range jwtTestData { - // If the token string is blank, use helper function to generate string - if data.tokenString == "" { - data.tokenString = test.MakeSampleToken(data.claims, privateKey) - } - - // Parse the token - var token *jwt.Token - var err error - var parser = data.parser - if parser == nil { - parser = new(jwt.Parser) - } - // Figure out correct claims type - switch data.claims.(type) { - case jwt.MapClaims: - token, _, err = parser.ParseUnverified(data.tokenString, jwt.MapClaims{}) - case *jwt.StandardClaims: - token, _, err = parser.ParseUnverified(data.tokenString, &jwt.StandardClaims{}) - } - - if err != nil { - t.Errorf("[%v] Invalid token", data.name) - } - - // Verify result matches expectation - if !reflect.DeepEqual(data.claims, token.Claims) { - t.Errorf("[%v] Claims mismatch. Expecting: %v Got: %v", data.name, data.claims, token.Claims) - } - - if data.valid && err != nil { - t.Errorf("[%v] Error while verifying token: %T:%v", data.name, err, err) - } - } -} - -// Helper method for benchmarking various methods -func benchmarkSigning(b *testing.B, method jwt.SigningMethod, key interface{}) { - t := jwt.New(method) - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - if _, err := t.SignedString(key); err != nil { - b.Fatal(err) - } - } - }) - -} diff --git a/vendor/github.com/dgrijalva/jwt-go/rsa_pss_test.go b/vendor/github.com/dgrijalva/jwt-go/rsa_pss_test.go deleted file mode 100644 index 9045aaf3..00000000 --- a/vendor/github.com/dgrijalva/jwt-go/rsa_pss_test.go +++ /dev/null @@ -1,96 +0,0 @@ -// +build go1.4 - -package jwt_test - -import ( - "crypto/rsa" - "io/ioutil" - "strings" - "testing" - - "github.com/dgrijalva/jwt-go" -) - -var rsaPSSTestData = []struct { - name string - tokenString string - alg string - claims map[string]interface{} - valid bool -}{ - { - "Basic PS256", - "eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.PPG4xyDVY8ffp4CcxofNmsTDXsrVG2npdQuibLhJbv4ClyPTUtR5giNSvuxo03kB6I8VXVr0Y9X7UxhJVEoJOmULAwRWaUsDnIewQa101cVhMa6iR8X37kfFoiZ6NkS-c7henVkkQWu2HtotkEtQvN5hFlk8IevXXPmvZlhQhwzB1sGzGYnoi1zOfuL98d3BIjUjtlwii5w6gYG2AEEzp7HnHCsb3jIwUPdq86Oe6hIFjtBwduIK90ca4UqzARpcfwxHwVLMpatKask00AgGVI0ysdk0BLMjmLutquD03XbThHScC2C2_Pp4cHWgMzvbgLU2RYYZcZRKr46QeNgz9w", - "PS256", - map[string]interface{}{"foo": "bar"}, - true, - }, - { - "Basic PS384", - "eyJhbGciOiJQUzM4NCIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.w7-qqgj97gK4fJsq_DCqdYQiylJjzWONvD0qWWWhqEOFk2P1eDULPnqHRnjgTXoO4HAw4YIWCsZPet7nR3Xxq4ZhMqvKW8b7KlfRTb9cH8zqFvzMmybQ4jv2hKc3bXYqVow3AoR7hN_CWXI3Dv6Kd2X5xhtxRHI6IL39oTVDUQ74LACe-9t4c3QRPuj6Pq1H4FAT2E2kW_0KOc6EQhCLWEhm2Z2__OZskDC8AiPpP8Kv4k2vB7l0IKQu8Pr4RcNBlqJdq8dA5D3hk5TLxP8V5nG1Ib80MOMMqoS3FQvSLyolFX-R_jZ3-zfq6Ebsqr0yEb0AH2CfsECF7935Pa0FKQ", - "PS384", - map[string]interface{}{"foo": "bar"}, - true, - }, - { - "Basic PS512", - "eyJhbGciOiJQUzUxMiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.GX1HWGzFaJevuSLavqqFYaW8_TpvcjQ8KfC5fXiSDzSiT9UD9nB_ikSmDNyDILNdtjZLSvVKfXxZJqCfefxAtiozEDDdJthZ-F0uO4SPFHlGiXszvKeodh7BuTWRI2wL9-ZO4mFa8nq3GMeQAfo9cx11i7nfN8n2YNQ9SHGovG7_T_AvaMZB_jT6jkDHpwGR9mz7x1sycckEo6teLdHRnH_ZdlHlxqknmyTu8Odr5Xh0sJFOL8BepWbbvIIn-P161rRHHiDWFv6nhlHwZnVzjx7HQrWSGb6-s2cdLie9QL_8XaMcUpjLkfOMKkDOfHo6AvpL7Jbwi83Z2ZTHjJWB-A", - "PS512", - map[string]interface{}{"foo": "bar"}, - true, - }, - { - "basic PS256 invalid: foo => bar", - "eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.PPG4xyDVY8ffp4CcxofNmsTDXsrVG2npdQuibLhJbv4ClyPTUtR5giNSvuxo03kB6I8VXVr0Y9X7UxhJVEoJOmULAwRWaUsDnIewQa101cVhMa6iR8X37kfFoiZ6NkS-c7henVkkQWu2HtotkEtQvN5hFlk8IevXXPmvZlhQhwzB1sGzGYnoi1zOfuL98d3BIjUjtlwii5w6gYG2AEEzp7HnHCsb3jIwUPdq86Oe6hIFjtBwduIK90ca4UqzARpcfwxHwVLMpatKask00AgGVI0ysdk0BLMjmLutquD03XbThHScC2C2_Pp4cHWgMzvbgLU2RYYZcZRKr46QeNgz9W", - "PS256", - map[string]interface{}{"foo": "bar"}, - false, - }, -} - -func TestRSAPSSVerify(t *testing.T) { - var err error - - key, _ := ioutil.ReadFile("test/sample_key.pub") - var rsaPSSKey *rsa.PublicKey - if rsaPSSKey, err = jwt.ParseRSAPublicKeyFromPEM(key); err != nil { - t.Errorf("Unable to parse RSA public key: %v", err) - } - - for _, data := range rsaPSSTestData { - parts := strings.Split(data.tokenString, ".") - - method := jwt.GetSigningMethod(data.alg) - err := method.Verify(strings.Join(parts[0:2], "."), parts[2], rsaPSSKey) - if data.valid && err != nil { - t.Errorf("[%v] Error while verifying key: %v", data.name, err) - } - if !data.valid && err == nil { - t.Errorf("[%v] Invalid key passed validation", data.name) - } - } -} - -func TestRSAPSSSign(t *testing.T) { - var err error - - key, _ := ioutil.ReadFile("test/sample_key") - var rsaPSSKey *rsa.PrivateKey - if rsaPSSKey, err = jwt.ParseRSAPrivateKeyFromPEM(key); err != nil { - t.Errorf("Unable to parse RSA private key: %v", err) - } - - for _, data := range rsaPSSTestData { - if data.valid { - parts := strings.Split(data.tokenString, ".") - method := jwt.GetSigningMethod(data.alg) - sig, err := method.Sign(strings.Join(parts[0:2], "."), rsaPSSKey) - if err != nil { - t.Errorf("[%v] Error signing token: %v", data.name, err) - } - if sig == parts[2] { - t.Errorf("[%v] Signatures shouldn't match\nnew:\n%v\noriginal:\n%v", data.name, sig, parts[2]) - } - } - } -} diff --git a/vendor/github.com/dgrijalva/jwt-go/rsa_test.go b/vendor/github.com/dgrijalva/jwt-go/rsa_test.go deleted file mode 100644 index 7f67c5db..00000000 --- a/vendor/github.com/dgrijalva/jwt-go/rsa_test.go +++ /dev/null @@ -1,185 +0,0 @@ -package jwt_test - -import ( - "github.com/dgrijalva/jwt-go" - "io/ioutil" - "strings" - "testing" -) - -var rsaTestData = []struct { - name string - tokenString string - alg string - claims map[string]interface{} - valid bool -}{ - { - "Basic RS256", - "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.FhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg", - "RS256", - map[string]interface{}{"foo": "bar"}, - true, - }, - { - "Basic RS384", - "eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.W-jEzRfBigtCWsinvVVuldiuilzVdU5ty0MvpLaSaqK9PlAWWlDQ1VIQ_qSKzwL5IXaZkvZFJXT3yL3n7OUVu7zCNJzdwznbC8Z-b0z2lYvcklJYi2VOFRcGbJtXUqgjk2oGsiqUMUMOLP70TTefkpsgqDxbRh9CDUfpOJgW-dU7cmgaoswe3wjUAUi6B6G2YEaiuXC0XScQYSYVKIzgKXJV8Zw-7AN_DBUI4GkTpsvQ9fVVjZM9csQiEXhYekyrKu1nu_POpQonGd8yqkIyXPECNmmqH5jH4sFiF67XhD7_JpkvLziBpI-uh86evBUadmHhb9Otqw3uV3NTaXLzJw", - "RS384", - map[string]interface{}{"foo": "bar"}, - true, - }, - { - "Basic RS512", - "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.zBlLlmRrUxx4SJPUbV37Q1joRcI9EW13grnKduK3wtYKmDXbgDpF1cZ6B-2Jsm5RB8REmMiLpGms-EjXhgnyh2TSHE-9W2gA_jvshegLWtwRVDX40ODSkTb7OVuaWgiy9y7llvcknFBTIg-FnVPVpXMmeV_pvwQyhaz1SSwSPrDyxEmksz1hq7YONXhXPpGaNbMMeDTNP_1oj8DZaqTIL9TwV8_1wb2Odt_Fy58Ke2RVFijsOLdnyEAjt2n9Mxihu9i3PhNBkkxa2GbnXBfq3kzvZ_xxGGopLdHhJjcGWXO-NiwI9_tiu14NRv4L2xC0ItD9Yz68v2ZIZEp_DuzwRQ", - "RS512", - map[string]interface{}{"foo": "bar"}, - true, - }, - { - "basic invalid: foo => bar", - "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.EhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg", - "RS256", - map[string]interface{}{"foo": "bar"}, - false, - }, -} - -func TestRSAVerify(t *testing.T) { - keyData, _ := ioutil.ReadFile("test/sample_key.pub") - key, _ := jwt.ParseRSAPublicKeyFromPEM(keyData) - - for _, data := range rsaTestData { - parts := strings.Split(data.tokenString, ".") - - method := jwt.GetSigningMethod(data.alg) - err := method.Verify(strings.Join(parts[0:2], "."), parts[2], key) - if data.valid && err != nil { - t.Errorf("[%v] Error while verifying key: %v", data.name, err) - } - if !data.valid && err == nil { - t.Errorf("[%v] Invalid key passed validation", data.name) - } - } -} - -func TestRSASign(t *testing.T) { - keyData, _ := ioutil.ReadFile("test/sample_key") - key, _ := jwt.ParseRSAPrivateKeyFromPEM(keyData) - - for _, data := range rsaTestData { - if data.valid { - parts := strings.Split(data.tokenString, ".") - method := jwt.GetSigningMethod(data.alg) - sig, err := method.Sign(strings.Join(parts[0:2], "."), key) - if err != nil { - t.Errorf("[%v] Error signing token: %v", data.name, err) - } - if sig != parts[2] { - t.Errorf("[%v] Incorrect signature.\nwas:\n%v\nexpecting:\n%v", data.name, sig, parts[2]) - } - } - } -} - -func TestRSAVerifyWithPreParsedPrivateKey(t *testing.T) { - key, _ := ioutil.ReadFile("test/sample_key.pub") - parsedKey, err := jwt.ParseRSAPublicKeyFromPEM(key) - if err != nil { - t.Fatal(err) - } - testData := rsaTestData[0] - parts := strings.Split(testData.tokenString, ".") - err = jwt.SigningMethodRS256.Verify(strings.Join(parts[0:2], "."), parts[2], parsedKey) - if err != nil { - t.Errorf("[%v] Error while verifying key: %v", testData.name, err) - } -} - -func TestRSAWithPreParsedPrivateKey(t *testing.T) { - key, _ := ioutil.ReadFile("test/sample_key") - parsedKey, err := jwt.ParseRSAPrivateKeyFromPEM(key) - if err != nil { - t.Fatal(err) - } - testData := rsaTestData[0] - parts := strings.Split(testData.tokenString, ".") - sig, err := jwt.SigningMethodRS256.Sign(strings.Join(parts[0:2], "."), parsedKey) - if err != nil { - t.Errorf("[%v] Error signing token: %v", testData.name, err) - } - if sig != parts[2] { - t.Errorf("[%v] Incorrect signature.\nwas:\n%v\nexpecting:\n%v", testData.name, sig, parts[2]) - } -} - -func TestRSAKeyParsing(t *testing.T) { - key, _ := ioutil.ReadFile("test/sample_key") - secureKey, _ := ioutil.ReadFile("test/privateSecure.pem") - pubKey, _ := ioutil.ReadFile("test/sample_key.pub") - badKey := []byte("All your base are belong to key") - - // Test parsePrivateKey - if _, e := jwt.ParseRSAPrivateKeyFromPEM(key); e != nil { - t.Errorf("Failed to parse valid private key: %v", e) - } - - if k, e := jwt.ParseRSAPrivateKeyFromPEM(pubKey); e == nil { - t.Errorf("Parsed public key as valid private key: %v", k) - } - - if k, e := jwt.ParseRSAPrivateKeyFromPEM(badKey); e == nil { - t.Errorf("Parsed invalid key as valid private key: %v", k) - } - - if _, e := jwt.ParseRSAPrivateKeyFromPEMWithPassword(secureKey, "password"); e != nil { - t.Errorf("Failed to parse valid private key with password: %v", e) - } - - if k, e := jwt.ParseRSAPrivateKeyFromPEMWithPassword(secureKey, "123132"); e == nil { - t.Errorf("Parsed private key with invalid password %v", k) - } - - // Test parsePublicKey - if _, e := jwt.ParseRSAPublicKeyFromPEM(pubKey); e != nil { - t.Errorf("Failed to parse valid public key: %v", e) - } - - if k, e := jwt.ParseRSAPublicKeyFromPEM(key); e == nil { - t.Errorf("Parsed private key as valid public key: %v", k) - } - - if k, e := jwt.ParseRSAPublicKeyFromPEM(badKey); e == nil { - t.Errorf("Parsed invalid key as valid private key: %v", k) - } - -} - -func BenchmarkRS256Signing(b *testing.B) { - key, _ := ioutil.ReadFile("test/sample_key") - parsedKey, err := jwt.ParseRSAPrivateKeyFromPEM(key) - if err != nil { - b.Fatal(err) - } - - benchmarkSigning(b, jwt.SigningMethodRS256, parsedKey) -} - -func BenchmarkRS384Signing(b *testing.B) { - key, _ := ioutil.ReadFile("test/sample_key") - parsedKey, err := jwt.ParseRSAPrivateKeyFromPEM(key) - if err != nil { - b.Fatal(err) - } - - benchmarkSigning(b, jwt.SigningMethodRS384, parsedKey) -} - -func BenchmarkRS512Signing(b *testing.B) { - key, _ := ioutil.ReadFile("test/sample_key") - parsedKey, err := jwt.ParseRSAPrivateKeyFromPEM(key) - if err != nil { - b.Fatal(err) - } - - benchmarkSigning(b, jwt.SigningMethodRS512, parsedKey) -} diff --git a/vendor/github.com/go-sql-driver/mysql/CHANGELOG.md b/vendor/github.com/go-sql-driver/mysql/CHANGELOG.md deleted file mode 100644 index ce1b5330..00000000 --- a/vendor/github.com/go-sql-driver/mysql/CHANGELOG.md +++ /dev/null @@ -1,178 +0,0 @@ -## Version 1.4.1 (2018-11-14) - -Bugfixes: - - - Fix TIME format for binary columns (#818) - - Fix handling of empty auth plugin names (#835) - - Fix caching_sha2_password with empty password (#826) - - Fix canceled context broke mysqlConn (#862) - - Fix OldAuthSwitchRequest support (#870) - - Fix Auth Response packet for cleartext password (#887) - -## Version 1.4 (2018-06-03) - -Changes: - - - Documentation fixes (#530, #535, #567) - - Refactoring (#575, #579, #580, #581, #603, #615, #704) - - Cache column names (#444) - - Sort the DSN parameters in DSNs generated from a config (#637) - - Allow native password authentication by default (#644) - - Use the default port if it is missing in the DSN (#668) - - Removed the `strict` mode (#676) - - Do not query `max_allowed_packet` by default (#680) - - Dropped support Go 1.6 and lower (#696) - - Updated `ConvertValue()` to match the database/sql/driver implementation (#760) - - Document the usage of `0000-00-00T00:00:00` as the time.Time zero value (#783) - - Improved the compatibility of the authentication system (#807) - -New Features: - - - Multi-Results support (#537) - - `rejectReadOnly` DSN option (#604) - - `context.Context` support (#608, #612, #627, #761) - - Transaction isolation level support (#619, #744) - - Read-Only transactions support (#618, #634) - - `NewConfig` function which initializes a config with default values (#679) - - Implemented the `ColumnType` interfaces (#667, #724) - - Support for custom string types in `ConvertValue` (#623) - - Implemented `NamedValueChecker`, improving support for uint64 with high bit set (#690, #709, #710) - - `caching_sha2_password` authentication plugin support (#794, #800, #801, #802) - - Implemented `driver.SessionResetter` (#779) - - `sha256_password` authentication plugin support (#808) - -Bugfixes: - - - Use the DSN hostname as TLS default ServerName if `tls=true` (#564, #718) - - Fixed LOAD LOCAL DATA INFILE for empty files (#590) - - Removed columns definition cache since it sometimes cached invalid data (#592) - - Don't mutate registered TLS configs (#600) - - Make RegisterTLSConfig concurrency-safe (#613) - - Handle missing auth data in the handshake packet correctly (#646) - - Do not retry queries when data was written to avoid data corruption (#302, #736) - - Cache the connection pointer for error handling before invalidating it (#678) - - Fixed imports for appengine/cloudsql (#700) - - Fix sending STMT_LONG_DATA for 0 byte data (#734) - - Set correct capacity for []bytes read from length-encoded strings (#766) - - Make RegisterDial concurrency-safe (#773) - - -## Version 1.3 (2016-12-01) - -Changes: - - - Go 1.1 is no longer supported - - Use decimals fields in MySQL to format time types (#249) - - Buffer optimizations (#269) - - TLS ServerName defaults to the host (#283) - - Refactoring (#400, #410, #437) - - Adjusted documentation for second generation CloudSQL (#485) - - Documented DSN system var quoting rules (#502) - - Made statement.Close() calls idempotent to avoid errors in Go 1.6+ (#512) - -New Features: - - - Enable microsecond resolution on TIME, DATETIME and TIMESTAMP (#249) - - Support for returning table alias on Columns() (#289, #359, #382) - - Placeholder interpolation, can be actived with the DSN parameter `interpolateParams=true` (#309, #318, #490) - - Support for uint64 parameters with high bit set (#332, #345) - - Cleartext authentication plugin support (#327) - - Exported ParseDSN function and the Config struct (#403, #419, #429) - - Read / Write timeouts (#401) - - Support for JSON field type (#414) - - Support for multi-statements and multi-results (#411, #431) - - DSN parameter to set the driver-side max_allowed_packet value manually (#489) - - Native password authentication plugin support (#494, #524) - -Bugfixes: - - - Fixed handling of queries without columns and rows (#255) - - Fixed a panic when SetKeepAlive() failed (#298) - - Handle ERR packets while reading rows (#321) - - Fixed reading NULL length-encoded integers in MySQL 5.6+ (#349) - - Fixed absolute paths support in LOAD LOCAL DATA INFILE (#356) - - Actually zero out bytes in handshake response (#378) - - Fixed race condition in registering LOAD DATA INFILE handler (#383) - - Fixed tests with MySQL 5.7.9+ (#380) - - QueryUnescape TLS config names (#397) - - Fixed "broken pipe" error by writing to closed socket (#390) - - Fixed LOAD LOCAL DATA INFILE buffering (#424) - - Fixed parsing of floats into float64 when placeholders are used (#434) - - Fixed DSN tests with Go 1.7+ (#459) - - Handle ERR packets while waiting for EOF (#473) - - Invalidate connection on error while discarding additional results (#513) - - Allow terminating packets of length 0 (#516) - - -## Version 1.2 (2014-06-03) - -Changes: - - - We switched back to a "rolling release". `go get` installs the current master branch again - - Version v1 of the driver will not be maintained anymore. Go 1.0 is no longer supported by this driver - - Exported errors to allow easy checking from application code - - Enabled TCP Keepalives on TCP connections - - Optimized INFILE handling (better buffer size calculation, lazy init, ...) - - The DSN parser also checks for a missing separating slash - - Faster binary date / datetime to string formatting - - Also exported the MySQLWarning type - - mysqlConn.Close returns the first error encountered instead of ignoring all errors - - writePacket() automatically writes the packet size to the header - - readPacket() uses an iterative approach instead of the recursive approach to merge splitted packets - -New Features: - - - `RegisterDial` allows the usage of a custom dial function to establish the network connection - - Setting the connection collation is possible with the `collation` DSN parameter. This parameter should be preferred over the `charset` parameter - - Logging of critical errors is configurable with `SetLogger` - - Google CloudSQL support - -Bugfixes: - - - Allow more than 32 parameters in prepared statements - - Various old_password fixes - - Fixed TestConcurrent test to pass Go's race detection - - Fixed appendLengthEncodedInteger for large numbers - - Renamed readLengthEnodedString to readLengthEncodedString and skipLengthEnodedString to skipLengthEncodedString (fixed typo) - - -## Version 1.1 (2013-11-02) - -Changes: - - - Go-MySQL-Driver now requires Go 1.1 - - Connections now use the collation `utf8_general_ci` by default. Adding `&charset=UTF8` to the DSN should not be necessary anymore - - Made closing rows and connections error tolerant. This allows for example deferring rows.Close() without checking for errors - - `[]byte(nil)` is now treated as a NULL value. Before, it was treated like an empty string / `[]byte("")` - - DSN parameter values must now be url.QueryEscape'ed. This allows text values to contain special characters, such as '&'. - - Use the IO buffer also for writing. This results in zero allocations (by the driver) for most queries - - Optimized the buffer for reading - - stmt.Query now caches column metadata - - New Logo - - Changed the copyright header to include all contributors - - Improved the LOAD INFILE documentation - - The driver struct is now exported to make the driver directly accessible - - Refactored the driver tests - - Added more benchmarks and moved all to a separate file - - Other small refactoring - -New Features: - - - Added *old_passwords* support: Required in some cases, but must be enabled by adding `allowOldPasswords=true` to the DSN since it is insecure - - Added a `clientFoundRows` parameter: Return the number of matching rows instead of the number of rows changed on UPDATEs - - Added TLS/SSL support: Use a TLS/SSL encrypted connection to the server. Custom TLS configs can be registered and used - -Bugfixes: - - - Fixed MySQL 4.1 support: MySQL 4.1 sends packets with lengths which differ from the specification - - Convert to DB timezone when inserting `time.Time` - - Splitted packets (more than 16MB) are now merged correctly - - Fixed false positive `io.EOF` errors when the data was fully read - - Avoid panics on reuse of closed connections - - Fixed empty string producing false nil values - - Fixed sign byte for positive TIME fields - - -## Version 1.0 (2013-05-14) - -Initial Release diff --git a/vendor/github.com/go-sql-driver/mysql/CONTRIBUTING.md b/vendor/github.com/go-sql-driver/mysql/CONTRIBUTING.md deleted file mode 100644 index 8fe16bcb..00000000 --- a/vendor/github.com/go-sql-driver/mysql/CONTRIBUTING.md +++ /dev/null @@ -1,23 +0,0 @@ -# Contributing Guidelines - -## Reporting Issues - -Before creating a new Issue, please check first if a similar Issue [already exists](https://github.com/go-sql-driver/mysql/issues?state=open) or was [recently closed](https://github.com/go-sql-driver/mysql/issues?direction=desc&page=1&sort=updated&state=closed). - -## Contributing Code - -By contributing to this project, you share your code under the Mozilla Public License 2, as specified in the LICENSE file. -Don't forget to add yourself to the AUTHORS file. - -### Code Review - -Everyone is invited to review and comment on pull requests. -If it looks fine to you, comment with "LGTM" (Looks good to me). - -If changes are required, notice the reviewers with "PTAL" (Please take another look) after committing the fixes. - -Before merging the Pull Request, at least one [team member](https://github.com/go-sql-driver?tab=members) must have commented with "LGTM". - -## Development Ideas - -If you are looking for ideas for code contributions, please check our [Development Ideas](https://github.com/go-sql-driver/mysql/wiki/Development-Ideas) Wiki page. diff --git a/vendor/github.com/go-sql-driver/mysql/README.md b/vendor/github.com/go-sql-driver/mysql/README.md deleted file mode 100644 index 2e9b07ee..00000000 --- a/vendor/github.com/go-sql-driver/mysql/README.md +++ /dev/null @@ -1,490 +0,0 @@ -# Go-MySQL-Driver - -A MySQL-Driver for Go's [database/sql](https://golang.org/pkg/database/sql/) package - -![Go-MySQL-Driver logo](https://raw.github.com/wiki/go-sql-driver/mysql/gomysql_m.png "Golang Gopher holding the MySQL Dolphin") - ---------------------------------------- - * [Features](#features) - * [Requirements](#requirements) - * [Installation](#installation) - * [Usage](#usage) - * [DSN (Data Source Name)](#dsn-data-source-name) - * [Password](#password) - * [Protocol](#protocol) - * [Address](#address) - * [Parameters](#parameters) - * [Examples](#examples) - * [Connection pool and timeouts](#connection-pool-and-timeouts) - * [context.Context Support](#contextcontext-support) - * [ColumnType Support](#columntype-support) - * [LOAD DATA LOCAL INFILE support](#load-data-local-infile-support) - * [time.Time support](#timetime-support) - * [Unicode support](#unicode-support) - * [Testing / Development](#testing--development) - * [License](#license) - ---------------------------------------- - -## Features - * Lightweight and [fast](https://github.com/go-sql-driver/sql-benchmark "golang MySQL-Driver performance") - * Native Go implementation. No C-bindings, just pure Go - * Connections over TCP/IPv4, TCP/IPv6, Unix domain sockets or [custom protocols](https://godoc.org/github.com/go-sql-driver/mysql#DialFunc) - * Automatic handling of broken connections - * Automatic Connection Pooling *(by database/sql package)* - * Supports queries larger than 16MB - * Full [`sql.RawBytes`](https://golang.org/pkg/database/sql/#RawBytes) support. - * Intelligent `LONG DATA` handling in prepared statements - * Secure `LOAD DATA LOCAL INFILE` support with file Whitelisting and `io.Reader` support - * Optional `time.Time` parsing - * Optional placeholder interpolation - -## Requirements - * Go 1.7 or higher. We aim to support the 3 latest versions of Go. - * MySQL (4.1+), MariaDB, Percona Server, Google CloudSQL or Sphinx (2.2.3+) - ---------------------------------------- - -## Installation -Simple install the package to your [$GOPATH](https://github.com/golang/go/wiki/GOPATH "GOPATH") with the [go tool](https://golang.org/cmd/go/ "go command") from shell: -```bash -$ go get -u github.com/go-sql-driver/mysql -``` -Make sure [Git is installed](https://git-scm.com/downloads) on your machine and in your system's `PATH`. - -## Usage -_Go MySQL Driver_ is an implementation of Go's `database/sql/driver` interface. You only need to import the driver and can use the full [`database/sql`](https://golang.org/pkg/database/sql/) API then. - -Use `mysql` as `driverName` and a valid [DSN](#dsn-data-source-name) as `dataSourceName`: -```go -import "database/sql" -import _ "github.com/go-sql-driver/mysql" - -db, err := sql.Open("mysql", "user:password@/dbname") -``` - -[Examples are available in our Wiki](https://github.com/go-sql-driver/mysql/wiki/Examples "Go-MySQL-Driver Examples"). - - -### DSN (Data Source Name) - -The Data Source Name has a common format, like e.g. [PEAR DB](http://pear.php.net/manual/en/package.database.db.intro-dsn.php) uses it, but without type-prefix (optional parts marked by squared brackets): -``` -[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...¶mN=valueN] -``` - -A DSN in its fullest form: -``` -username:password@protocol(address)/dbname?param=value -``` - -Except for the databasename, all values are optional. So the minimal DSN is: -``` -/dbname -``` - -If you do not want to preselect a database, leave `dbname` empty: -``` -/ -``` -This has the same effect as an empty DSN string: -``` - -``` - -Alternatively, [Config.FormatDSN](https://godoc.org/github.com/go-sql-driver/mysql#Config.FormatDSN) can be used to create a DSN string by filling a struct. - -#### Password -Passwords can consist of any character. Escaping is **not** necessary. - -#### Protocol -See [net.Dial](https://golang.org/pkg/net/#Dial) for more information which networks are available. -In general you should use an Unix domain socket if available and TCP otherwise for best performance. - -#### Address -For TCP and UDP networks, addresses have the form `host[:port]`. -If `port` is omitted, the default port will be used. -If `host` is a literal IPv6 address, it must be enclosed in square brackets. -The functions [net.JoinHostPort](https://golang.org/pkg/net/#JoinHostPort) and [net.SplitHostPort](https://golang.org/pkg/net/#SplitHostPort) manipulate addresses in this form. - -For Unix domain sockets the address is the absolute path to the MySQL-Server-socket, e.g. `/var/run/mysqld/mysqld.sock` or `/tmp/mysql.sock`. - -#### Parameters -*Parameters are case-sensitive!* - -Notice that any of `true`, `TRUE`, `True` or `1` is accepted to stand for a true boolean value. Not surprisingly, false can be specified as any of: `false`, `FALSE`, `False` or `0`. - -##### `allowAllFiles` - -``` -Type: bool -Valid Values: true, false -Default: false -``` - -`allowAllFiles=true` disables the file Whitelist for `LOAD DATA LOCAL INFILE` and allows *all* files. -[*Might be insecure!*](http://dev.mysql.com/doc/refman/5.7/en/load-data-local.html) - -##### `allowCleartextPasswords` - -``` -Type: bool -Valid Values: true, false -Default: false -``` - -`allowCleartextPasswords=true` allows using the [cleartext client side plugin](http://dev.mysql.com/doc/en/cleartext-authentication-plugin.html) if required by an account, such as one defined with the [PAM authentication plugin](http://dev.mysql.com/doc/en/pam-authentication-plugin.html). Sending passwords in clear text may be a security problem in some configurations. To avoid problems if there is any possibility that the password would be intercepted, clients should connect to MySQL Server using a method that protects the password. Possibilities include [TLS / SSL](#tls), IPsec, or a private network. - -##### `allowNativePasswords` - -``` -Type: bool -Valid Values: true, false -Default: true -``` -`allowNativePasswords=false` disallows the usage of MySQL native password method. - -##### `allowOldPasswords` - -``` -Type: bool -Valid Values: true, false -Default: false -``` -`allowOldPasswords=true` allows the usage of the insecure old password method. This should be avoided, but is necessary in some cases. See also [the old_passwords wiki page](https://github.com/go-sql-driver/mysql/wiki/old_passwords). - -##### `charset` - -``` -Type: string -Valid Values: -Default: none -``` - -Sets the charset used for client-server interaction (`"SET NAMES "`). If multiple charsets are set (separated by a comma), the following charset is used if setting the charset failes. This enables for example support for `utf8mb4` ([introduced in MySQL 5.5.3](http://dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html)) with fallback to `utf8` for older servers (`charset=utf8mb4,utf8`). - -Usage of the `charset` parameter is discouraged because it issues additional queries to the server. -Unless you need the fallback behavior, please use `collation` instead. - -##### `collation` - -``` -Type: string -Valid Values: -Default: utf8_general_ci -``` - -Sets the collation used for client-server interaction on connection. In contrast to `charset`, `collation` does not issue additional queries. If the specified collation is unavailable on the target server, the connection will fail. - -A list of valid charsets for a server is retrievable with `SHOW COLLATION`. - -##### `clientFoundRows` - -``` -Type: bool -Valid Values: true, false -Default: false -``` - -`clientFoundRows=true` causes an UPDATE to return the number of matching rows instead of the number of rows changed. - -##### `columnsWithAlias` - -``` -Type: bool -Valid Values: true, false -Default: false -``` - -When `columnsWithAlias` is true, calls to `sql.Rows.Columns()` will return the table alias and the column name separated by a dot. For example: - -``` -SELECT u.id FROM users as u -``` - -will return `u.id` instead of just `id` if `columnsWithAlias=true`. - -##### `interpolateParams` - -``` -Type: bool -Valid Values: true, false -Default: false -``` - -If `interpolateParams` is true, placeholders (`?`) in calls to `db.Query()` and `db.Exec()` are interpolated into a single query string with given parameters. This reduces the number of roundtrips, since the driver has to prepare a statement, execute it with given parameters and close the statement again with `interpolateParams=false`. - -*This can not be used together with the multibyte encodings BIG5, CP932, GB2312, GBK or SJIS. These are blacklisted as they may [introduce a SQL injection vulnerability](http://stackoverflow.com/a/12118602/3430118)!* - -##### `loc` - -``` -Type: string -Valid Values: -Default: UTC -``` - -Sets the location for time.Time values (when using `parseTime=true`). *"Local"* sets the system's location. See [time.LoadLocation](https://golang.org/pkg/time/#LoadLocation) for details. - -Note that this sets the location for time.Time values but does not change MySQL's [time_zone setting](https://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html). For that see the [time_zone system variable](#system-variables), which can also be set as a DSN parameter. - -Please keep in mind, that param values must be [url.QueryEscape](https://golang.org/pkg/net/url/#QueryEscape)'ed. Alternatively you can manually replace the `/` with `%2F`. For example `US/Pacific` would be `loc=US%2FPacific`. - -##### `maxAllowedPacket` -``` -Type: decimal number -Default: 4194304 -``` - -Max packet size allowed in bytes. The default value is 4 MiB and should be adjusted to match the server settings. `maxAllowedPacket=0` can be used to automatically fetch the `max_allowed_packet` variable from server *on every connection*. - -##### `multiStatements` - -``` -Type: bool -Valid Values: true, false -Default: false -``` - -Allow multiple statements in one query. While this allows batch queries, it also greatly increases the risk of SQL injections. Only the result of the first query is returned, all other results are silently discarded. - -When `multiStatements` is used, `?` parameters must only be used in the first statement. - -##### `parseTime` - -``` -Type: bool -Valid Values: true, false -Default: false -``` - -`parseTime=true` changes the output type of `DATE` and `DATETIME` values to `time.Time` instead of `[]byte` / `string` -The date or datetime like `0000-00-00 00:00:00` is converted into zero value of `time.Time`. - - -##### `readTimeout` - -``` -Type: duration -Default: 0 -``` - -I/O read timeout. The value must be a decimal number with a unit suffix (*"ms"*, *"s"*, *"m"*, *"h"*), such as *"30s"*, *"0.5m"* or *"1m30s"*. - -##### `rejectReadOnly` - -``` -Type: bool -Valid Values: true, false -Default: false -``` - - -`rejectReadOnly=true` causes the driver to reject read-only connections. This -is for a possible race condition during an automatic failover, where the mysql -client gets connected to a read-only replica after the failover. - -Note that this should be a fairly rare case, as an automatic failover normally -happens when the primary is down, and the race condition shouldn't happen -unless it comes back up online as soon as the failover is kicked off. On the -other hand, when this happens, a MySQL application can get stuck on a -read-only connection until restarted. It is however fairly easy to reproduce, -for example, using a manual failover on AWS Aurora's MySQL-compatible cluster. - -If you are not relying on read-only transactions to reject writes that aren't -supposed to happen, setting this on some MySQL providers (such as AWS Aurora) -is safer for failovers. - -Note that ERROR 1290 can be returned for a `read-only` server and this option will -cause a retry for that error. However the same error number is used for some -other cases. You should ensure your application will never cause an ERROR 1290 -except for `read-only` mode when enabling this option. - - -##### `serverPubKey` - -``` -Type: string -Valid Values: -Default: none -``` - -Server public keys can be registered with [`mysql.RegisterServerPubKey`](https://godoc.org/github.com/go-sql-driver/mysql#RegisterServerPubKey), which can then be used by the assigned name in the DSN. -Public keys are used to transmit encrypted data, e.g. for authentication. -If the server's public key is known, it should be set manually to avoid expensive and potentially insecure transmissions of the public key from the server to the client each time it is required. - - -##### `timeout` - -``` -Type: duration -Default: OS default -``` - -Timeout for establishing connections, aka dial timeout. The value must be a decimal number with a unit suffix (*"ms"*, *"s"*, *"m"*, *"h"*), such as *"30s"*, *"0.5m"* or *"1m30s"*. - - -##### `tls` - -``` -Type: bool / string -Valid Values: true, false, skip-verify, -Default: false -``` - -`tls=true` enables TLS / SSL encrypted connection to the server. Use `skip-verify` if you want to use a self-signed or invalid certificate (server side). Use a custom value registered with [`mysql.RegisterTLSConfig`](https://godoc.org/github.com/go-sql-driver/mysql#RegisterTLSConfig). - - -##### `writeTimeout` - -``` -Type: duration -Default: 0 -``` - -I/O write timeout. The value must be a decimal number with a unit suffix (*"ms"*, *"s"*, *"m"*, *"h"*), such as *"30s"*, *"0.5m"* or *"1m30s"*. - - -##### System Variables - -Any other parameters are interpreted as system variables: - * `=`: `SET =` - * `=`: `SET =` - * `=%27%27`: `SET =''` - -Rules: -* The values for string variables must be quoted with `'`. -* The values must also be [url.QueryEscape](http://golang.org/pkg/net/url/#QueryEscape)'ed! - (which implies values of string variables must be wrapped with `%27`). - -Examples: - * `autocommit=1`: `SET autocommit=1` - * [`time_zone=%27Europe%2FParis%27`](https://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html): `SET time_zone='Europe/Paris'` - * [`tx_isolation=%27REPEATABLE-READ%27`](https://dev.mysql.com/doc/refman/5.5/en/server-system-variables.html#sysvar_tx_isolation): `SET tx_isolation='REPEATABLE-READ'` - - -#### Examples -``` -user@unix(/path/to/socket)/dbname -``` - -``` -root:pw@unix(/tmp/mysql.sock)/myDatabase?loc=Local -``` - -``` -user:password@tcp(localhost:5555)/dbname?tls=skip-verify&autocommit=true -``` - -Treat warnings as errors by setting the system variable [`sql_mode`](https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html): -``` -user:password@/dbname?sql_mode=TRADITIONAL -``` - -TCP via IPv6: -``` -user:password@tcp([de:ad:be:ef::ca:fe]:80)/dbname?timeout=90s&collation=utf8mb4_unicode_ci -``` - -TCP on a remote host, e.g. Amazon RDS: -``` -id:password@tcp(your-amazonaws-uri.com:3306)/dbname -``` - -Google Cloud SQL on App Engine (First Generation MySQL Server): -``` -user@cloudsql(project-id:instance-name)/dbname -``` - -Google Cloud SQL on App Engine (Second Generation MySQL Server): -``` -user@cloudsql(project-id:regionname:instance-name)/dbname -``` - -TCP using default port (3306) on localhost: -``` -user:password@tcp/dbname?charset=utf8mb4,utf8&sys_var=esc%40ped -``` - -Use the default protocol (tcp) and host (localhost:3306): -``` -user:password@/dbname -``` - -No Database preselected: -``` -user:password@/ -``` - - -### Connection pool and timeouts -The connection pool is managed by Go's database/sql package. For details on how to configure the size of the pool and how long connections stay in the pool see `*DB.SetMaxOpenConns`, `*DB.SetMaxIdleConns`, and `*DB.SetConnMaxLifetime` in the [database/sql documentation](https://golang.org/pkg/database/sql/). The read, write, and dial timeouts for each individual connection are configured with the DSN parameters [`readTimeout`](#readtimeout), [`writeTimeout`](#writetimeout), and [`timeout`](#timeout), respectively. - -## `ColumnType` Support -This driver supports the [`ColumnType` interface](https://golang.org/pkg/database/sql/#ColumnType) introduced in Go 1.8, with the exception of [`ColumnType.Length()`](https://golang.org/pkg/database/sql/#ColumnType.Length), which is currently not supported. - -## `context.Context` Support -Go 1.8 added `database/sql` support for `context.Context`. This driver supports query timeouts and cancellation via contexts. -See [context support in the database/sql package](https://golang.org/doc/go1.8#database_sql) for more details. - - -### `LOAD DATA LOCAL INFILE` support -For this feature you need direct access to the package. Therefore you must change the import path (no `_`): -```go -import "github.com/go-sql-driver/mysql" -``` - -Files must be whitelisted by registering them with `mysql.RegisterLocalFile(filepath)` (recommended) or the Whitelist check must be deactivated by using the DSN parameter `allowAllFiles=true` ([*Might be insecure!*](http://dev.mysql.com/doc/refman/5.7/en/load-data-local.html)). - -To use a `io.Reader` a handler function must be registered with `mysql.RegisterReaderHandler(name, handler)` which returns a `io.Reader` or `io.ReadCloser`. The Reader is available with the filepath `Reader::` then. Choose different names for different handlers and `DeregisterReaderHandler` when you don't need it anymore. - -See the [godoc of Go-MySQL-Driver](https://godoc.org/github.com/go-sql-driver/mysql "golang mysql driver documentation") for details. - - -### `time.Time` support -The default internal output type of MySQL `DATE` and `DATETIME` values is `[]byte` which allows you to scan the value into a `[]byte`, `string` or `sql.RawBytes` variable in your program. - -However, many want to scan MySQL `DATE` and `DATETIME` values into `time.Time` variables, which is the logical opposite in Go to `DATE` and `DATETIME` in MySQL. You can do that by changing the internal output type from `[]byte` to `time.Time` with the DSN parameter `parseTime=true`. You can set the default [`time.Time` location](https://golang.org/pkg/time/#Location) with the `loc` DSN parameter. - -**Caution:** As of Go 1.1, this makes `time.Time` the only variable type you can scan `DATE` and `DATETIME` values into. This breaks for example [`sql.RawBytes` support](https://github.com/go-sql-driver/mysql/wiki/Examples#rawbytes). - -Alternatively you can use the [`NullTime`](https://godoc.org/github.com/go-sql-driver/mysql#NullTime) type as the scan destination, which works with both `time.Time` and `string` / `[]byte`. - - -### Unicode support -Since version 1.1 Go-MySQL-Driver automatically uses the collation `utf8_general_ci` by default. - -Other collations / charsets can be set using the [`collation`](#collation) DSN parameter. - -Version 1.0 of the driver recommended adding `&charset=utf8` (alias for `SET NAMES utf8`) to the DSN to enable proper UTF-8 support. This is not necessary anymore. The [`collation`](#collation) parameter should be preferred to set another collation / charset than the default. - -See http://dev.mysql.com/doc/refman/5.7/en/charset-unicode.html for more details on MySQL's Unicode support. - -## Testing / Development -To run the driver tests you may need to adjust the configuration. See the [Testing Wiki-Page](https://github.com/go-sql-driver/mysql/wiki/Testing "Testing") for details. - -Go-MySQL-Driver is not feature-complete yet. Your help is very appreciated. -If you want to contribute, you can work on an [open issue](https://github.com/go-sql-driver/mysql/issues?state=open) or review a [pull request](https://github.com/go-sql-driver/mysql/pulls). - -See the [Contribution Guidelines](https://github.com/go-sql-driver/mysql/blob/master/CONTRIBUTING.md) for details. - ---------------------------------------- - -## License -Go-MySQL-Driver is licensed under the [Mozilla Public License Version 2.0](https://raw.github.com/go-sql-driver/mysql/master/LICENSE) - -Mozilla summarizes the license scope as follows: -> MPL: The copyleft applies to any files containing MPLed code. - - -That means: - * You can **use** the **unchanged** source code both in private and commercially. - * When distributing, you **must publish** the source code of any **changed files** licensed under the MPL 2.0 under a) the MPL 2.0 itself or b) a compatible license (e.g. GPL 3.0 or Apache License 2.0). - * You **needn't publish** the source code of your library as long as the files licensed under the MPL 2.0 are **unchanged**. - -Please read the [MPL 2.0 FAQ](https://www.mozilla.org/en-US/MPL/2.0/FAQ/) if you have further questions regarding the license. - -You can read the full terms here: [LICENSE](https://raw.github.com/go-sql-driver/mysql/master/LICENSE). - -![Go Gopher and MySQL Dolphin](https://raw.github.com/wiki/go-sql-driver/mysql/go-mysql-driver_m.jpg "Golang Gopher transporting the MySQL Dolphin in a wheelbarrow") - diff --git a/vendor/github.com/go-sql-driver/mysql/auth_test.go b/vendor/github.com/go-sql-driver/mysql/auth_test.go deleted file mode 100644 index 1920ef39..00000000 --- a/vendor/github.com/go-sql-driver/mysql/auth_test.go +++ /dev/null @@ -1,1330 +0,0 @@ -// Go MySQL Driver - A MySQL-Driver for Go's database/sql package -// -// Copyright 2018 The Go-MySQL-Driver Authors. All rights reserved. -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this file, -// You can obtain one at http://mozilla.org/MPL/2.0/. - -package mysql - -import ( - "bytes" - "crypto/rsa" - "crypto/tls" - "crypto/x509" - "encoding/pem" - "fmt" - "testing" -) - -var testPubKey = []byte("-----BEGIN PUBLIC KEY-----\n" + - "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAol0Z8G8U+25Btxk/g/fm\n" + - "UAW/wEKjQCTjkibDE4B+qkuWeiumg6miIRhtilU6m9BFmLQSy1ltYQuu4k17A4tQ\n" + - "rIPpOQYZges/qsDFkZh3wyK5jL5WEFVdOasf6wsfszExnPmcZS4axxoYJfiuilrN\n" + - "hnwinBAqfi3S0sw5MpSI4Zl1AbOrHG4zDI62Gti2PKiMGyYDZTS9xPrBLbN95Kby\n" + - "FFclQLEzA9RJcS1nHFsWtRgHjGPhhjCQxEm9NQ1nePFhCfBfApyfH1VM2VCOQum6\n" + - "Ci9bMuHWjTjckC84mzF99kOxOWVU7mwS6gnJqBzpuz8t3zq8/iQ2y7QrmZV+jTJP\n" + - "WQIDAQAB\n" + - "-----END PUBLIC KEY-----\n") - -var testPubKeyRSA *rsa.PublicKey - -func init() { - block, _ := pem.Decode(testPubKey) - pub, err := x509.ParsePKIXPublicKey(block.Bytes) - if err != nil { - panic(err) - } - testPubKeyRSA = pub.(*rsa.PublicKey) -} - -func TestScrambleOldPass(t *testing.T) { - scramble := []byte{9, 8, 7, 6, 5, 4, 3, 2} - vectors := []struct { - pass string - out string - }{ - {" pass", "47575c5a435b4251"}, - {"pass ", "47575c5a435b4251"}, - {"123\t456", "575c47505b5b5559"}, - {"C0mpl!ca ted#PASS123", "5d5d554849584a45"}, - } - for _, tuple := range vectors { - ours := scrambleOldPassword(scramble, tuple.pass) - if tuple.out != fmt.Sprintf("%x", ours) { - t.Errorf("Failed old password %q", tuple.pass) - } - } -} - -func TestScrambleSHA256Pass(t *testing.T) { - scramble := []byte{10, 47, 74, 111, 75, 73, 34, 48, 88, 76, 114, 74, 37, 13, 3, 80, 82, 2, 23, 21} - vectors := []struct { - pass string - out string - }{ - {"secret", "f490e76f66d9d86665ce54d98c78d0acfe2fb0b08b423da807144873d30b312c"}, - {"secret2", "abc3934a012cf342e876071c8ee202de51785b430258a7a0138bc79c4d800bc6"}, - } - for _, tuple := range vectors { - ours := scrambleSHA256Password(scramble, tuple.pass) - if tuple.out != fmt.Sprintf("%x", ours) { - t.Errorf("Failed SHA256 password %q", tuple.pass) - } - } -} - -func TestAuthFastCachingSHA256PasswordCached(t *testing.T) { - conn, mc := newRWMockConn(1) - mc.cfg.User = "root" - mc.cfg.Passwd = "secret" - - authData := []byte{90, 105, 74, 126, 30, 48, 37, 56, 3, 23, 115, 127, 69, - 22, 41, 84, 32, 123, 43, 118} - plugin := "caching_sha2_password" - - // Send Client Authentication Packet - authResp, err := mc.auth(authData, plugin) - if err != nil { - t.Fatal(err) - } - err = mc.writeHandshakeResponsePacket(authResp, plugin) - if err != nil { - t.Fatal(err) - } - - // check written auth response - authRespStart := 4 + 4 + 4 + 1 + 23 + len(mc.cfg.User) + 1 - authRespEnd := authRespStart + 1 + len(authResp) - writtenAuthRespLen := conn.written[authRespStart] - writtenAuthResp := conn.written[authRespStart+1 : authRespEnd] - expectedAuthResp := []byte{102, 32, 5, 35, 143, 161, 140, 241, 171, 232, 56, - 139, 43, 14, 107, 196, 249, 170, 147, 60, 220, 204, 120, 178, 214, 15, - 184, 150, 26, 61, 57, 235} - if writtenAuthRespLen != 32 || !bytes.Equal(writtenAuthResp, expectedAuthResp) { - t.Fatalf("unexpected written auth response (%d bytes): %v", writtenAuthRespLen, writtenAuthResp) - } - conn.written = nil - - // auth response - conn.data = []byte{ - 2, 0, 0, 2, 1, 3, // Fast Auth Success - 7, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, // OK - } - conn.maxReads = 1 - - // Handle response to auth packet - if err := mc.handleAuthResult(authData, plugin); err != nil { - t.Errorf("got error: %v", err) - } -} - -func TestAuthFastCachingSHA256PasswordEmpty(t *testing.T) { - conn, mc := newRWMockConn(1) - mc.cfg.User = "root" - mc.cfg.Passwd = "" - - authData := []byte{90, 105, 74, 126, 30, 48, 37, 56, 3, 23, 115, 127, 69, - 22, 41, 84, 32, 123, 43, 118} - plugin := "caching_sha2_password" - - // Send Client Authentication Packet - authResp, err := mc.auth(authData, plugin) - if err != nil { - t.Fatal(err) - } - err = mc.writeHandshakeResponsePacket(authResp, plugin) - if err != nil { - t.Fatal(err) - } - - // check written auth response - authRespStart := 4 + 4 + 4 + 1 + 23 + len(mc.cfg.User) + 1 - authRespEnd := authRespStart + 1 + len(authResp) - writtenAuthRespLen := conn.written[authRespStart] - writtenAuthResp := conn.written[authRespStart+1 : authRespEnd] - if writtenAuthRespLen != 0 { - t.Fatalf("unexpected written auth response (%d bytes): %v", - writtenAuthRespLen, writtenAuthResp) - } - conn.written = nil - - // auth response - conn.data = []byte{ - 7, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, // OK - } - conn.maxReads = 1 - - // Handle response to auth packet - if err := mc.handleAuthResult(authData, plugin); err != nil { - t.Errorf("got error: %v", err) - } -} - -func TestAuthFastCachingSHA256PasswordFullRSA(t *testing.T) { - conn, mc := newRWMockConn(1) - mc.cfg.User = "root" - mc.cfg.Passwd = "secret" - - authData := []byte{6, 81, 96, 114, 14, 42, 50, 30, 76, 47, 1, 95, 126, 81, - 62, 94, 83, 80, 52, 85} - plugin := "caching_sha2_password" - - // Send Client Authentication Packet - authResp, err := mc.auth(authData, plugin) - if err != nil { - t.Fatal(err) - } - err = mc.writeHandshakeResponsePacket(authResp, plugin) - if err != nil { - t.Fatal(err) - } - - // check written auth response - authRespStart := 4 + 4 + 4 + 1 + 23 + len(mc.cfg.User) + 1 - authRespEnd := authRespStart + 1 + len(authResp) - writtenAuthRespLen := conn.written[authRespStart] - writtenAuthResp := conn.written[authRespStart+1 : authRespEnd] - expectedAuthResp := []byte{171, 201, 138, 146, 89, 159, 11, 170, 0, 67, 165, - 49, 175, 94, 218, 68, 177, 109, 110, 86, 34, 33, 44, 190, 67, 240, 70, - 110, 40, 139, 124, 41} - if writtenAuthRespLen != 32 || !bytes.Equal(writtenAuthResp, expectedAuthResp) { - t.Fatalf("unexpected written auth response (%d bytes): %v", writtenAuthRespLen, writtenAuthResp) - } - conn.written = nil - - // auth response - conn.data = []byte{ - 2, 0, 0, 2, 1, 4, // Perform Full Authentication - } - conn.queuedReplies = [][]byte{ - // pub key response - append([]byte{byte(1 + len(testPubKey)), 1, 0, 4, 1}, testPubKey...), - - // OK - {7, 0, 0, 6, 0, 0, 0, 2, 0, 0, 0}, - } - conn.maxReads = 3 - - // Handle response to auth packet - if err := mc.handleAuthResult(authData, plugin); err != nil { - t.Errorf("got error: %v", err) - } - - if !bytes.HasPrefix(conn.written, []byte{1, 0, 0, 3, 2, 0, 1, 0, 5}) { - t.Errorf("unexpected written data: %v", conn.written) - } -} - -func TestAuthFastCachingSHA256PasswordFullRSAWithKey(t *testing.T) { - conn, mc := newRWMockConn(1) - mc.cfg.User = "root" - mc.cfg.Passwd = "secret" - mc.cfg.pubKey = testPubKeyRSA - - authData := []byte{6, 81, 96, 114, 14, 42, 50, 30, 76, 47, 1, 95, 126, 81, - 62, 94, 83, 80, 52, 85} - plugin := "caching_sha2_password" - - // Send Client Authentication Packet - authResp, err := mc.auth(authData, plugin) - if err != nil { - t.Fatal(err) - } - err = mc.writeHandshakeResponsePacket(authResp, plugin) - if err != nil { - t.Fatal(err) - } - - // check written auth response - authRespStart := 4 + 4 + 4 + 1 + 23 + len(mc.cfg.User) + 1 - authRespEnd := authRespStart + 1 + len(authResp) - writtenAuthRespLen := conn.written[authRespStart] - writtenAuthResp := conn.written[authRespStart+1 : authRespEnd] - expectedAuthResp := []byte{171, 201, 138, 146, 89, 159, 11, 170, 0, 67, 165, - 49, 175, 94, 218, 68, 177, 109, 110, 86, 34, 33, 44, 190, 67, 240, 70, - 110, 40, 139, 124, 41} - if writtenAuthRespLen != 32 || !bytes.Equal(writtenAuthResp, expectedAuthResp) { - t.Fatalf("unexpected written auth response (%d bytes): %v", writtenAuthRespLen, writtenAuthResp) - } - conn.written = nil - - // auth response - conn.data = []byte{ - 2, 0, 0, 2, 1, 4, // Perform Full Authentication - } - conn.queuedReplies = [][]byte{ - // OK - {7, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0}, - } - conn.maxReads = 2 - - // Handle response to auth packet - if err := mc.handleAuthResult(authData, plugin); err != nil { - t.Errorf("got error: %v", err) - } - - if !bytes.HasPrefix(conn.written, []byte{0, 1, 0, 3}) { - t.Errorf("unexpected written data: %v", conn.written) - } -} - -func TestAuthFastCachingSHA256PasswordFullSecure(t *testing.T) { - conn, mc := newRWMockConn(1) - mc.cfg.User = "root" - mc.cfg.Passwd = "secret" - - authData := []byte{6, 81, 96, 114, 14, 42, 50, 30, 76, 47, 1, 95, 126, 81, - 62, 94, 83, 80, 52, 85} - plugin := "caching_sha2_password" - - // Send Client Authentication Packet - authResp, err := mc.auth(authData, plugin) - if err != nil { - t.Fatal(err) - } - err = mc.writeHandshakeResponsePacket(authResp, plugin) - if err != nil { - t.Fatal(err) - } - - // Hack to make the caching_sha2_password plugin believe that the connection - // is secure - mc.cfg.tls = &tls.Config{InsecureSkipVerify: true} - - // check written auth response - authRespStart := 4 + 4 + 4 + 1 + 23 + len(mc.cfg.User) + 1 - authRespEnd := authRespStart + 1 + len(authResp) - writtenAuthRespLen := conn.written[authRespStart] - writtenAuthResp := conn.written[authRespStart+1 : authRespEnd] - expectedAuthResp := []byte{171, 201, 138, 146, 89, 159, 11, 170, 0, 67, 165, - 49, 175, 94, 218, 68, 177, 109, 110, 86, 34, 33, 44, 190, 67, 240, 70, - 110, 40, 139, 124, 41} - if writtenAuthRespLen != 32 || !bytes.Equal(writtenAuthResp, expectedAuthResp) { - t.Fatalf("unexpected written auth response (%d bytes): %v", writtenAuthRespLen, writtenAuthResp) - } - conn.written = nil - - // auth response - conn.data = []byte{ - 2, 0, 0, 2, 1, 4, // Perform Full Authentication - } - conn.queuedReplies = [][]byte{ - // OK - {7, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0}, - } - conn.maxReads = 3 - - // Handle response to auth packet - if err := mc.handleAuthResult(authData, plugin); err != nil { - t.Errorf("got error: %v", err) - } - - if !bytes.Equal(conn.written, []byte{7, 0, 0, 3, 115, 101, 99, 114, 101, 116, 0}) { - t.Errorf("unexpected written data: %v", conn.written) - } -} - -func TestAuthFastCleartextPasswordNotAllowed(t *testing.T) { - _, mc := newRWMockConn(1) - mc.cfg.User = "root" - mc.cfg.Passwd = "secret" - - authData := []byte{70, 114, 92, 94, 1, 38, 11, 116, 63, 114, 23, 101, 126, - 103, 26, 95, 81, 17, 24, 21} - plugin := "mysql_clear_password" - - // Send Client Authentication Packet - _, err := mc.auth(authData, plugin) - if err != ErrCleartextPassword { - t.Errorf("expected ErrCleartextPassword, got %v", err) - } -} - -func TestAuthFastCleartextPassword(t *testing.T) { - conn, mc := newRWMockConn(1) - mc.cfg.User = "root" - mc.cfg.Passwd = "secret" - mc.cfg.AllowCleartextPasswords = true - - authData := []byte{70, 114, 92, 94, 1, 38, 11, 116, 63, 114, 23, 101, 126, - 103, 26, 95, 81, 17, 24, 21} - plugin := "mysql_clear_password" - - // Send Client Authentication Packet - authResp, err := mc.auth(authData, plugin) - if err != nil { - t.Fatal(err) - } - err = mc.writeHandshakeResponsePacket(authResp, plugin) - if err != nil { - t.Fatal(err) - } - - // check written auth response - authRespStart := 4 + 4 + 4 + 1 + 23 + len(mc.cfg.User) + 1 - authRespEnd := authRespStart + 1 + len(authResp) - writtenAuthRespLen := conn.written[authRespStart] - writtenAuthResp := conn.written[authRespStart+1 : authRespEnd] - expectedAuthResp := []byte{115, 101, 99, 114, 101, 116, 0} - if writtenAuthRespLen != 7 || !bytes.Equal(writtenAuthResp, expectedAuthResp) { - t.Fatalf("unexpected written auth response (%d bytes): %v", writtenAuthRespLen, writtenAuthResp) - } - conn.written = nil - - // auth response - conn.data = []byte{ - 7, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, // OK - } - conn.maxReads = 1 - - // Handle response to auth packet - if err := mc.handleAuthResult(authData, plugin); err != nil { - t.Errorf("got error: %v", err) - } -} - -func TestAuthFastCleartextPasswordEmpty(t *testing.T) { - conn, mc := newRWMockConn(1) - mc.cfg.User = "root" - mc.cfg.Passwd = "" - mc.cfg.AllowCleartextPasswords = true - - authData := []byte{70, 114, 92, 94, 1, 38, 11, 116, 63, 114, 23, 101, 126, - 103, 26, 95, 81, 17, 24, 21} - plugin := "mysql_clear_password" - - // Send Client Authentication Packet - authResp, err := mc.auth(authData, plugin) - if err != nil { - t.Fatal(err) - } - err = mc.writeHandshakeResponsePacket(authResp, plugin) - if err != nil { - t.Fatal(err) - } - - // check written auth response - authRespStart := 4 + 4 + 4 + 1 + 23 + len(mc.cfg.User) + 1 - authRespEnd := authRespStart + 1 + len(authResp) - writtenAuthRespLen := conn.written[authRespStart] - writtenAuthResp := conn.written[authRespStart+1 : authRespEnd] - expectedAuthResp := []byte{0} - if writtenAuthRespLen != 1 || !bytes.Equal(writtenAuthResp, expectedAuthResp) { - t.Fatalf("unexpected written auth response (%d bytes): %v", writtenAuthRespLen, writtenAuthResp) - } - conn.written = nil - - // auth response - conn.data = []byte{ - 7, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, // OK - } - conn.maxReads = 1 - - // Handle response to auth packet - if err := mc.handleAuthResult(authData, plugin); err != nil { - t.Errorf("got error: %v", err) - } -} - -func TestAuthFastNativePasswordNotAllowed(t *testing.T) { - _, mc := newRWMockConn(1) - mc.cfg.User = "root" - mc.cfg.Passwd = "secret" - mc.cfg.AllowNativePasswords = false - - authData := []byte{70, 114, 92, 94, 1, 38, 11, 116, 63, 114, 23, 101, 126, - 103, 26, 95, 81, 17, 24, 21} - plugin := "mysql_native_password" - - // Send Client Authentication Packet - _, err := mc.auth(authData, plugin) - if err != ErrNativePassword { - t.Errorf("expected ErrNativePassword, got %v", err) - } -} - -func TestAuthFastNativePassword(t *testing.T) { - conn, mc := newRWMockConn(1) - mc.cfg.User = "root" - mc.cfg.Passwd = "secret" - - authData := []byte{70, 114, 92, 94, 1, 38, 11, 116, 63, 114, 23, 101, 126, - 103, 26, 95, 81, 17, 24, 21} - plugin := "mysql_native_password" - - // Send Client Authentication Packet - authResp, err := mc.auth(authData, plugin) - if err != nil { - t.Fatal(err) - } - err = mc.writeHandshakeResponsePacket(authResp, plugin) - if err != nil { - t.Fatal(err) - } - - // check written auth response - authRespStart := 4 + 4 + 4 + 1 + 23 + len(mc.cfg.User) + 1 - authRespEnd := authRespStart + 1 + len(authResp) - writtenAuthRespLen := conn.written[authRespStart] - writtenAuthResp := conn.written[authRespStart+1 : authRespEnd] - expectedAuthResp := []byte{53, 177, 140, 159, 251, 189, 127, 53, 109, 252, - 172, 50, 211, 192, 240, 164, 26, 48, 207, 45} - if writtenAuthRespLen != 20 || !bytes.Equal(writtenAuthResp, expectedAuthResp) { - t.Fatalf("unexpected written auth response (%d bytes): %v", writtenAuthRespLen, writtenAuthResp) - } - conn.written = nil - - // auth response - conn.data = []byte{ - 7, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, // OK - } - conn.maxReads = 1 - - // Handle response to auth packet - if err := mc.handleAuthResult(authData, plugin); err != nil { - t.Errorf("got error: %v", err) - } -} - -func TestAuthFastNativePasswordEmpty(t *testing.T) { - conn, mc := newRWMockConn(1) - mc.cfg.User = "root" - mc.cfg.Passwd = "" - - authData := []byte{70, 114, 92, 94, 1, 38, 11, 116, 63, 114, 23, 101, 126, - 103, 26, 95, 81, 17, 24, 21} - plugin := "mysql_native_password" - - // Send Client Authentication Packet - authResp, err := mc.auth(authData, plugin) - if err != nil { - t.Fatal(err) - } - err = mc.writeHandshakeResponsePacket(authResp, plugin) - if err != nil { - t.Fatal(err) - } - - // check written auth response - authRespStart := 4 + 4 + 4 + 1 + 23 + len(mc.cfg.User) + 1 - authRespEnd := authRespStart + 1 + len(authResp) - writtenAuthRespLen := conn.written[authRespStart] - writtenAuthResp := conn.written[authRespStart+1 : authRespEnd] - if writtenAuthRespLen != 0 { - t.Fatalf("unexpected written auth response (%d bytes): %v", - writtenAuthRespLen, writtenAuthResp) - } - conn.written = nil - - // auth response - conn.data = []byte{ - 7, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, // OK - } - conn.maxReads = 1 - - // Handle response to auth packet - if err := mc.handleAuthResult(authData, plugin); err != nil { - t.Errorf("got error: %v", err) - } -} - -func TestAuthFastSHA256PasswordEmpty(t *testing.T) { - conn, mc := newRWMockConn(1) - mc.cfg.User = "root" - mc.cfg.Passwd = "" - - authData := []byte{6, 81, 96, 114, 14, 42, 50, 30, 76, 47, 1, 95, 126, 81, - 62, 94, 83, 80, 52, 85} - plugin := "sha256_password" - - // Send Client Authentication Packet - authResp, err := mc.auth(authData, plugin) - if err != nil { - t.Fatal(err) - } - err = mc.writeHandshakeResponsePacket(authResp, plugin) - if err != nil { - t.Fatal(err) - } - - // check written auth response - authRespStart := 4 + 4 + 4 + 1 + 23 + len(mc.cfg.User) + 1 - authRespEnd := authRespStart + 1 + len(authResp) - writtenAuthRespLen := conn.written[authRespStart] - writtenAuthResp := conn.written[authRespStart+1 : authRespEnd] - expectedAuthResp := []byte{0} - if writtenAuthRespLen != 1 || !bytes.Equal(writtenAuthResp, expectedAuthResp) { - t.Fatalf("unexpected written auth response (%d bytes): %v", writtenAuthRespLen, writtenAuthResp) - } - conn.written = nil - - // auth response (pub key response) - conn.data = append([]byte{byte(1 + len(testPubKey)), 1, 0, 2, 1}, testPubKey...) - conn.queuedReplies = [][]byte{ - // OK - {7, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0}, - } - conn.maxReads = 2 - - // Handle response to auth packet - if err := mc.handleAuthResult(authData, plugin); err != nil { - t.Errorf("got error: %v", err) - } - - if !bytes.HasPrefix(conn.written, []byte{0, 1, 0, 3}) { - t.Errorf("unexpected written data: %v", conn.written) - } -} - -func TestAuthFastSHA256PasswordRSA(t *testing.T) { - conn, mc := newRWMockConn(1) - mc.cfg.User = "root" - mc.cfg.Passwd = "secret" - - authData := []byte{6, 81, 96, 114, 14, 42, 50, 30, 76, 47, 1, 95, 126, 81, - 62, 94, 83, 80, 52, 85} - plugin := "sha256_password" - - // Send Client Authentication Packet - authResp, err := mc.auth(authData, plugin) - if err != nil { - t.Fatal(err) - } - err = mc.writeHandshakeResponsePacket(authResp, plugin) - if err != nil { - t.Fatal(err) - } - - // check written auth response - authRespStart := 4 + 4 + 4 + 1 + 23 + len(mc.cfg.User) + 1 - authRespEnd := authRespStart + 1 + len(authResp) - writtenAuthRespLen := conn.written[authRespStart] - writtenAuthResp := conn.written[authRespStart+1 : authRespEnd] - expectedAuthResp := []byte{1} - if writtenAuthRespLen != 1 || !bytes.Equal(writtenAuthResp, expectedAuthResp) { - t.Fatalf("unexpected written auth response (%d bytes): %v", writtenAuthRespLen, writtenAuthResp) - } - conn.written = nil - - // auth response (pub key response) - conn.data = append([]byte{byte(1 + len(testPubKey)), 1, 0, 2, 1}, testPubKey...) - conn.queuedReplies = [][]byte{ - // OK - {7, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0}, - } - conn.maxReads = 2 - - // Handle response to auth packet - if err := mc.handleAuthResult(authData, plugin); err != nil { - t.Errorf("got error: %v", err) - } - - if !bytes.HasPrefix(conn.written, []byte{0, 1, 0, 3}) { - t.Errorf("unexpected written data: %v", conn.written) - } -} - -func TestAuthFastSHA256PasswordRSAWithKey(t *testing.T) { - conn, mc := newRWMockConn(1) - mc.cfg.User = "root" - mc.cfg.Passwd = "secret" - mc.cfg.pubKey = testPubKeyRSA - - authData := []byte{6, 81, 96, 114, 14, 42, 50, 30, 76, 47, 1, 95, 126, 81, - 62, 94, 83, 80, 52, 85} - plugin := "sha256_password" - - // Send Client Authentication Packet - authResp, err := mc.auth(authData, plugin) - if err != nil { - t.Fatal(err) - } - err = mc.writeHandshakeResponsePacket(authResp, plugin) - if err != nil { - t.Fatal(err) - } - - // auth response (OK) - conn.data = []byte{7, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0} - conn.maxReads = 1 - - // Handle response to auth packet - if err := mc.handleAuthResult(authData, plugin); err != nil { - t.Errorf("got error: %v", err) - } -} - -func TestAuthFastSHA256PasswordSecure(t *testing.T) { - conn, mc := newRWMockConn(1) - mc.cfg.User = "root" - mc.cfg.Passwd = "secret" - - // hack to make the caching_sha2_password plugin believe that the connection - // is secure - mc.cfg.tls = &tls.Config{InsecureSkipVerify: true} - - authData := []byte{6, 81, 96, 114, 14, 42, 50, 30, 76, 47, 1, 95, 126, 81, - 62, 94, 83, 80, 52, 85} - plugin := "sha256_password" - - // send Client Authentication Packet - authResp, err := mc.auth(authData, plugin) - if err != nil { - t.Fatal(err) - } - - // unset TLS config to prevent the actual establishment of a TLS wrapper - mc.cfg.tls = nil - - err = mc.writeHandshakeResponsePacket(authResp, plugin) - if err != nil { - t.Fatal(err) - } - - // check written auth response - authRespStart := 4 + 4 + 4 + 1 + 23 + len(mc.cfg.User) + 1 - authRespEnd := authRespStart + 1 + len(authResp) - writtenAuthRespLen := conn.written[authRespStart] - writtenAuthResp := conn.written[authRespStart+1 : authRespEnd] - expectedAuthResp := []byte{115, 101, 99, 114, 101, 116, 0} - if writtenAuthRespLen != 7 || !bytes.Equal(writtenAuthResp, expectedAuthResp) { - t.Fatalf("unexpected written auth response (%d bytes): %v", writtenAuthRespLen, writtenAuthResp) - } - conn.written = nil - - // auth response (OK) - conn.data = []byte{7, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0} - conn.maxReads = 1 - - // Handle response to auth packet - if err := mc.handleAuthResult(authData, plugin); err != nil { - t.Errorf("got error: %v", err) - } - - if !bytes.Equal(conn.written, []byte{}) { - t.Errorf("unexpected written data: %v", conn.written) - } -} - -func TestAuthSwitchCachingSHA256PasswordCached(t *testing.T) { - conn, mc := newRWMockConn(2) - mc.cfg.Passwd = "secret" - - // auth switch request - conn.data = []byte{44, 0, 0, 2, 254, 99, 97, 99, 104, 105, 110, 103, 95, - 115, 104, 97, 50, 95, 112, 97, 115, 115, 119, 111, 114, 100, 0, 101, - 11, 26, 18, 94, 97, 22, 72, 2, 46, 70, 106, 29, 55, 45, 94, 76, 90, 84, - 50, 0} - - // auth response - conn.queuedReplies = [][]byte{ - {7, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0}, // OK - } - conn.maxReads = 3 - - authData := []byte{123, 87, 15, 84, 20, 58, 37, 121, 91, 117, 51, 24, 19, - 47, 43, 9, 41, 112, 67, 110} - plugin := "mysql_native_password" - - if err := mc.handleAuthResult(authData, plugin); err != nil { - t.Errorf("got error: %v", err) - } - - expectedReply := []byte{ - // 1. Packet: Hash - 32, 0, 0, 3, 129, 93, 132, 95, 114, 48, 79, 215, 128, 62, 193, 118, 128, - 54, 75, 208, 159, 252, 227, 215, 129, 15, 242, 97, 19, 159, 31, 20, 58, - 153, 9, 130, - } - if !bytes.Equal(conn.written, expectedReply) { - t.Errorf("got unexpected data: %v", conn.written) - } -} - -func TestAuthSwitchCachingSHA256PasswordEmpty(t *testing.T) { - conn, mc := newRWMockConn(2) - mc.cfg.Passwd = "" - - // auth switch request - conn.data = []byte{44, 0, 0, 2, 254, 99, 97, 99, 104, 105, 110, 103, 95, - 115, 104, 97, 50, 95, 112, 97, 115, 115, 119, 111, 114, 100, 0, 101, - 11, 26, 18, 94, 97, 22, 72, 2, 46, 70, 106, 29, 55, 45, 94, 76, 90, 84, - 50, 0} - - // auth response - conn.queuedReplies = [][]byte{{7, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0}} - conn.maxReads = 2 - - authData := []byte{123, 87, 15, 84, 20, 58, 37, 121, 91, 117, 51, 24, 19, - 47, 43, 9, 41, 112, 67, 110} - plugin := "mysql_native_password" - - if err := mc.handleAuthResult(authData, plugin); err != nil { - t.Errorf("got error: %v", err) - } - - expectedReply := []byte{0, 0, 0, 3} - if !bytes.Equal(conn.written, expectedReply) { - t.Errorf("got unexpected data: %v", conn.written) - } -} - -func TestAuthSwitchCachingSHA256PasswordFullRSA(t *testing.T) { - conn, mc := newRWMockConn(2) - mc.cfg.Passwd = "secret" - - // auth switch request - conn.data = []byte{44, 0, 0, 2, 254, 99, 97, 99, 104, 105, 110, 103, 95, - 115, 104, 97, 50, 95, 112, 97, 115, 115, 119, 111, 114, 100, 0, 101, - 11, 26, 18, 94, 97, 22, 72, 2, 46, 70, 106, 29, 55, 45, 94, 76, 90, 84, - 50, 0} - - conn.queuedReplies = [][]byte{ - // Perform Full Authentication - {2, 0, 0, 4, 1, 4}, - - // Pub Key Response - append([]byte{byte(1 + len(testPubKey)), 1, 0, 6, 1}, testPubKey...), - - // OK - {7, 0, 0, 8, 0, 0, 0, 2, 0, 0, 0}, - } - conn.maxReads = 4 - - authData := []byte{123, 87, 15, 84, 20, 58, 37, 121, 91, 117, 51, 24, 19, - 47, 43, 9, 41, 112, 67, 110} - plugin := "mysql_native_password" - - if err := mc.handleAuthResult(authData, plugin); err != nil { - t.Errorf("got error: %v", err) - } - - expectedReplyPrefix := []byte{ - // 1. Packet: Hash - 32, 0, 0, 3, 129, 93, 132, 95, 114, 48, 79, 215, 128, 62, 193, 118, 128, - 54, 75, 208, 159, 252, 227, 215, 129, 15, 242, 97, 19, 159, 31, 20, 58, - 153, 9, 130, - - // 2. Packet: Pub Key Request - 1, 0, 0, 5, 2, - - // 3. Packet: Encrypted Password - 0, 1, 0, 7, // [changing bytes] - } - if !bytes.HasPrefix(conn.written, expectedReplyPrefix) { - t.Errorf("got unexpected data: %v", conn.written) - } -} - -func TestAuthSwitchCachingSHA256PasswordFullRSAWithKey(t *testing.T) { - conn, mc := newRWMockConn(2) - mc.cfg.Passwd = "secret" - mc.cfg.pubKey = testPubKeyRSA - - // auth switch request - conn.data = []byte{44, 0, 0, 2, 254, 99, 97, 99, 104, 105, 110, 103, 95, - 115, 104, 97, 50, 95, 112, 97, 115, 115, 119, 111, 114, 100, 0, 101, - 11, 26, 18, 94, 97, 22, 72, 2, 46, 70, 106, 29, 55, 45, 94, 76, 90, 84, - 50, 0} - - conn.queuedReplies = [][]byte{ - // Perform Full Authentication - {2, 0, 0, 4, 1, 4}, - - // OK - {7, 0, 0, 6, 0, 0, 0, 2, 0, 0, 0}, - } - conn.maxReads = 3 - - authData := []byte{123, 87, 15, 84, 20, 58, 37, 121, 91, 117, 51, 24, 19, - 47, 43, 9, 41, 112, 67, 110} - plugin := "mysql_native_password" - - if err := mc.handleAuthResult(authData, plugin); err != nil { - t.Errorf("got error: %v", err) - } - - expectedReplyPrefix := []byte{ - // 1. Packet: Hash - 32, 0, 0, 3, 129, 93, 132, 95, 114, 48, 79, 215, 128, 62, 193, 118, 128, - 54, 75, 208, 159, 252, 227, 215, 129, 15, 242, 97, 19, 159, 31, 20, 58, - 153, 9, 130, - - // 2. Packet: Encrypted Password - 0, 1, 0, 5, // [changing bytes] - } - if !bytes.HasPrefix(conn.written, expectedReplyPrefix) { - t.Errorf("got unexpected data: %v", conn.written) - } -} - -func TestAuthSwitchCachingSHA256PasswordFullSecure(t *testing.T) { - conn, mc := newRWMockConn(2) - mc.cfg.Passwd = "secret" - - // Hack to make the caching_sha2_password plugin believe that the connection - // is secure - mc.cfg.tls = &tls.Config{InsecureSkipVerify: true} - - // auth switch request - conn.data = []byte{44, 0, 0, 2, 254, 99, 97, 99, 104, 105, 110, 103, 95, - 115, 104, 97, 50, 95, 112, 97, 115, 115, 119, 111, 114, 100, 0, 101, - 11, 26, 18, 94, 97, 22, 72, 2, 46, 70, 106, 29, 55, 45, 94, 76, 90, 84, - 50, 0} - - // auth response - conn.queuedReplies = [][]byte{ - {2, 0, 0, 4, 1, 4}, // Perform Full Authentication - {7, 0, 0, 6, 0, 0, 0, 2, 0, 0, 0}, // OK - } - conn.maxReads = 3 - - authData := []byte{123, 87, 15, 84, 20, 58, 37, 121, 91, 117, 51, 24, 19, - 47, 43, 9, 41, 112, 67, 110} - plugin := "mysql_native_password" - - if err := mc.handleAuthResult(authData, plugin); err != nil { - t.Errorf("got error: %v", err) - } - - expectedReply := []byte{ - // 1. Packet: Hash - 32, 0, 0, 3, 129, 93, 132, 95, 114, 48, 79, 215, 128, 62, 193, 118, 128, - 54, 75, 208, 159, 252, 227, 215, 129, 15, 242, 97, 19, 159, 31, 20, 58, - 153, 9, 130, - - // 2. Packet: Cleartext password - 7, 0, 0, 5, 115, 101, 99, 114, 101, 116, 0, - } - if !bytes.Equal(conn.written, expectedReply) { - t.Errorf("got unexpected data: %v", conn.written) - } -} - -func TestAuthSwitchCleartextPasswordNotAllowed(t *testing.T) { - conn, mc := newRWMockConn(2) - - conn.data = []byte{22, 0, 0, 2, 254, 109, 121, 115, 113, 108, 95, 99, 108, - 101, 97, 114, 95, 112, 97, 115, 115, 119, 111, 114, 100, 0} - conn.maxReads = 1 - authData := []byte{123, 87, 15, 84, 20, 58, 37, 121, 91, 117, 51, 24, 19, - 47, 43, 9, 41, 112, 67, 110} - plugin := "mysql_native_password" - err := mc.handleAuthResult(authData, plugin) - if err != ErrCleartextPassword { - t.Errorf("expected ErrCleartextPassword, got %v", err) - } -} - -func TestAuthSwitchCleartextPassword(t *testing.T) { - conn, mc := newRWMockConn(2) - mc.cfg.AllowCleartextPasswords = true - mc.cfg.Passwd = "secret" - - // auth switch request - conn.data = []byte{22, 0, 0, 2, 254, 109, 121, 115, 113, 108, 95, 99, 108, - 101, 97, 114, 95, 112, 97, 115, 115, 119, 111, 114, 100, 0} - - // auth response - conn.queuedReplies = [][]byte{{7, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0}} - conn.maxReads = 2 - - authData := []byte{123, 87, 15, 84, 20, 58, 37, 121, 91, 117, 51, 24, 19, - 47, 43, 9, 41, 112, 67, 110} - plugin := "mysql_native_password" - - if err := mc.handleAuthResult(authData, plugin); err != nil { - t.Errorf("got error: %v", err) - } - - expectedReply := []byte{7, 0, 0, 3, 115, 101, 99, 114, 101, 116, 0} - if !bytes.Equal(conn.written, expectedReply) { - t.Errorf("got unexpected data: %v", conn.written) - } -} - -func TestAuthSwitchCleartextPasswordEmpty(t *testing.T) { - conn, mc := newRWMockConn(2) - mc.cfg.AllowCleartextPasswords = true - mc.cfg.Passwd = "" - - // auth switch request - conn.data = []byte{22, 0, 0, 2, 254, 109, 121, 115, 113, 108, 95, 99, 108, - 101, 97, 114, 95, 112, 97, 115, 115, 119, 111, 114, 100, 0} - - // auth response - conn.queuedReplies = [][]byte{{7, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0}} - conn.maxReads = 2 - - authData := []byte{123, 87, 15, 84, 20, 58, 37, 121, 91, 117, 51, 24, 19, - 47, 43, 9, 41, 112, 67, 110} - plugin := "mysql_native_password" - - if err := mc.handleAuthResult(authData, plugin); err != nil { - t.Errorf("got error: %v", err) - } - - expectedReply := []byte{1, 0, 0, 3, 0} - if !bytes.Equal(conn.written, expectedReply) { - t.Errorf("got unexpected data: %v", conn.written) - } -} - -func TestAuthSwitchNativePasswordNotAllowed(t *testing.T) { - conn, mc := newRWMockConn(2) - mc.cfg.AllowNativePasswords = false - - conn.data = []byte{44, 0, 0, 2, 254, 109, 121, 115, 113, 108, 95, 110, 97, - 116, 105, 118, 101, 95, 112, 97, 115, 115, 119, 111, 114, 100, 0, 96, - 71, 63, 8, 1, 58, 75, 12, 69, 95, 66, 60, 117, 31, 48, 31, 89, 39, 55, - 31, 0} - conn.maxReads = 1 - authData := []byte{96, 71, 63, 8, 1, 58, 75, 12, 69, 95, 66, 60, 117, 31, - 48, 31, 89, 39, 55, 31} - plugin := "caching_sha2_password" - err := mc.handleAuthResult(authData, plugin) - if err != ErrNativePassword { - t.Errorf("expected ErrNativePassword, got %v", err) - } -} - -func TestAuthSwitchNativePassword(t *testing.T) { - conn, mc := newRWMockConn(2) - mc.cfg.AllowNativePasswords = true - mc.cfg.Passwd = "secret" - - // auth switch request - conn.data = []byte{44, 0, 0, 2, 254, 109, 121, 115, 113, 108, 95, 110, 97, - 116, 105, 118, 101, 95, 112, 97, 115, 115, 119, 111, 114, 100, 0, 96, - 71, 63, 8, 1, 58, 75, 12, 69, 95, 66, 60, 117, 31, 48, 31, 89, 39, 55, - 31, 0} - - // auth response - conn.queuedReplies = [][]byte{{7, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0}} - conn.maxReads = 2 - - authData := []byte{96, 71, 63, 8, 1, 58, 75, 12, 69, 95, 66, 60, 117, 31, - 48, 31, 89, 39, 55, 31} - plugin := "caching_sha2_password" - - if err := mc.handleAuthResult(authData, plugin); err != nil { - t.Errorf("got error: %v", err) - } - - expectedReply := []byte{20, 0, 0, 3, 202, 41, 195, 164, 34, 226, 49, 103, - 21, 211, 167, 199, 227, 116, 8, 48, 57, 71, 149, 146} - if !bytes.Equal(conn.written, expectedReply) { - t.Errorf("got unexpected data: %v", conn.written) - } -} - -func TestAuthSwitchNativePasswordEmpty(t *testing.T) { - conn, mc := newRWMockConn(2) - mc.cfg.AllowNativePasswords = true - mc.cfg.Passwd = "" - - // auth switch request - conn.data = []byte{44, 0, 0, 2, 254, 109, 121, 115, 113, 108, 95, 110, 97, - 116, 105, 118, 101, 95, 112, 97, 115, 115, 119, 111, 114, 100, 0, 96, - 71, 63, 8, 1, 58, 75, 12, 69, 95, 66, 60, 117, 31, 48, 31, 89, 39, 55, - 31, 0} - - // auth response - conn.queuedReplies = [][]byte{{7, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0}} - conn.maxReads = 2 - - authData := []byte{96, 71, 63, 8, 1, 58, 75, 12, 69, 95, 66, 60, 117, 31, - 48, 31, 89, 39, 55, 31} - plugin := "caching_sha2_password" - - if err := mc.handleAuthResult(authData, plugin); err != nil { - t.Errorf("got error: %v", err) - } - - expectedReply := []byte{0, 0, 0, 3} - if !bytes.Equal(conn.written, expectedReply) { - t.Errorf("got unexpected data: %v", conn.written) - } -} - -func TestAuthSwitchOldPasswordNotAllowed(t *testing.T) { - conn, mc := newRWMockConn(2) - - conn.data = []byte{41, 0, 0, 2, 254, 109, 121, 115, 113, 108, 95, 111, 108, - 100, 95, 112, 97, 115, 115, 119, 111, 114, 100, 0, 95, 84, 103, 43, 61, - 49, 123, 61, 91, 50, 40, 113, 35, 84, 96, 101, 92, 123, 121, 107, 0} - conn.maxReads = 1 - authData := []byte{95, 84, 103, 43, 61, 49, 123, 61, 91, 50, 40, 113, 35, - 84, 96, 101, 92, 123, 121, 107} - plugin := "mysql_native_password" - err := mc.handleAuthResult(authData, plugin) - if err != ErrOldPassword { - t.Errorf("expected ErrOldPassword, got %v", err) - } -} - -// Same to TestAuthSwitchOldPasswordNotAllowed, but use OldAuthSwitch request. -func TestOldAuthSwitchNotAllowed(t *testing.T) { - conn, mc := newRWMockConn(2) - - // OldAuthSwitch request - conn.data = []byte{1, 0, 0, 2, 0xfe} - conn.maxReads = 1 - authData := []byte{95, 84, 103, 43, 61, 49, 123, 61, 91, 50, 40, 113, 35, - 84, 96, 101, 92, 123, 121, 107} - plugin := "mysql_native_password" - err := mc.handleAuthResult(authData, plugin) - if err != ErrOldPassword { - t.Errorf("expected ErrOldPassword, got %v", err) - } -} - -func TestAuthSwitchOldPassword(t *testing.T) { - conn, mc := newRWMockConn(2) - mc.cfg.AllowOldPasswords = true - mc.cfg.Passwd = "secret" - - // auth switch request - conn.data = []byte{41, 0, 0, 2, 254, 109, 121, 115, 113, 108, 95, 111, 108, - 100, 95, 112, 97, 115, 115, 119, 111, 114, 100, 0, 95, 84, 103, 43, 61, - 49, 123, 61, 91, 50, 40, 113, 35, 84, 96, 101, 92, 123, 121, 107, 0} - - // auth response - conn.queuedReplies = [][]byte{{8, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 0}} - conn.maxReads = 2 - - authData := []byte{95, 84, 103, 43, 61, 49, 123, 61, 91, 50, 40, 113, 35, - 84, 96, 101, 92, 123, 121, 107} - plugin := "mysql_native_password" - - if err := mc.handleAuthResult(authData, plugin); err != nil { - t.Errorf("got error: %v", err) - } - - expectedReply := []byte{9, 0, 0, 3, 86, 83, 83, 79, 74, 78, 65, 66, 0} - if !bytes.Equal(conn.written, expectedReply) { - t.Errorf("got unexpected data: %v", conn.written) - } -} - -// Same to TestAuthSwitchOldPassword, but use OldAuthSwitch request. -func TestOldAuthSwitch(t *testing.T) { - conn, mc := newRWMockConn(2) - mc.cfg.AllowOldPasswords = true - mc.cfg.Passwd = "secret" - - // OldAuthSwitch request - conn.data = []byte{1, 0, 0, 2, 0xfe} - - // auth response - conn.queuedReplies = [][]byte{{8, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 0}} - conn.maxReads = 2 - - authData := []byte{95, 84, 103, 43, 61, 49, 123, 61, 91, 50, 40, 113, 35, - 84, 96, 101, 92, 123, 121, 107} - plugin := "mysql_native_password" - - if err := mc.handleAuthResult(authData, plugin); err != nil { - t.Errorf("got error: %v", err) - } - - expectedReply := []byte{9, 0, 0, 3, 86, 83, 83, 79, 74, 78, 65, 66, 0} - if !bytes.Equal(conn.written, expectedReply) { - t.Errorf("got unexpected data: %v", conn.written) - } -} -func TestAuthSwitchOldPasswordEmpty(t *testing.T) { - conn, mc := newRWMockConn(2) - mc.cfg.AllowOldPasswords = true - mc.cfg.Passwd = "" - - // auth switch request - conn.data = []byte{41, 0, 0, 2, 254, 109, 121, 115, 113, 108, 95, 111, 108, - 100, 95, 112, 97, 115, 115, 119, 111, 114, 100, 0, 95, 84, 103, 43, 61, - 49, 123, 61, 91, 50, 40, 113, 35, 84, 96, 101, 92, 123, 121, 107, 0} - - // auth response - conn.queuedReplies = [][]byte{{8, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 0}} - conn.maxReads = 2 - - authData := []byte{95, 84, 103, 43, 61, 49, 123, 61, 91, 50, 40, 113, 35, - 84, 96, 101, 92, 123, 121, 107} - plugin := "mysql_native_password" - - if err := mc.handleAuthResult(authData, plugin); err != nil { - t.Errorf("got error: %v", err) - } - - expectedReply := []byte{1, 0, 0, 3, 0} - if !bytes.Equal(conn.written, expectedReply) { - t.Errorf("got unexpected data: %v", conn.written) - } -} - -// Same to TestAuthSwitchOldPasswordEmpty, but use OldAuthSwitch request. -func TestOldAuthSwitchPasswordEmpty(t *testing.T) { - conn, mc := newRWMockConn(2) - mc.cfg.AllowOldPasswords = true - mc.cfg.Passwd = "" - - // OldAuthSwitch request. - conn.data = []byte{1, 0, 0, 2, 0xfe} - - // auth response - conn.queuedReplies = [][]byte{{8, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 0}} - conn.maxReads = 2 - - authData := []byte{95, 84, 103, 43, 61, 49, 123, 61, 91, 50, 40, 113, 35, - 84, 96, 101, 92, 123, 121, 107} - plugin := "mysql_native_password" - - if err := mc.handleAuthResult(authData, plugin); err != nil { - t.Errorf("got error: %v", err) - } - - expectedReply := []byte{1, 0, 0, 3, 0} - if !bytes.Equal(conn.written, expectedReply) { - t.Errorf("got unexpected data: %v", conn.written) - } -} - -func TestAuthSwitchSHA256PasswordEmpty(t *testing.T) { - conn, mc := newRWMockConn(2) - mc.cfg.Passwd = "" - - // auth switch request - conn.data = []byte{38, 0, 0, 2, 254, 115, 104, 97, 50, 53, 54, 95, 112, 97, - 115, 115, 119, 111, 114, 100, 0, 78, 82, 62, 40, 100, 1, 59, 31, 44, 69, - 33, 112, 8, 81, 51, 96, 65, 82, 16, 114, 0} - - conn.queuedReplies = [][]byte{ - // OK - {7, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0}, - } - conn.maxReads = 3 - - authData := []byte{123, 87, 15, 84, 20, 58, 37, 121, 91, 117, 51, 24, 19, - 47, 43, 9, 41, 112, 67, 110} - plugin := "mysql_native_password" - - if err := mc.handleAuthResult(authData, plugin); err != nil { - t.Errorf("got error: %v", err) - } - - expectedReplyPrefix := []byte{ - // 1. Packet: Empty Password - 1, 0, 0, 3, 0, - } - if !bytes.HasPrefix(conn.written, expectedReplyPrefix) { - t.Errorf("got unexpected data: %v", conn.written) - } -} - -func TestAuthSwitchSHA256PasswordRSA(t *testing.T) { - conn, mc := newRWMockConn(2) - mc.cfg.Passwd = "secret" - - // auth switch request - conn.data = []byte{38, 0, 0, 2, 254, 115, 104, 97, 50, 53, 54, 95, 112, 97, - 115, 115, 119, 111, 114, 100, 0, 78, 82, 62, 40, 100, 1, 59, 31, 44, 69, - 33, 112, 8, 81, 51, 96, 65, 82, 16, 114, 0} - - conn.queuedReplies = [][]byte{ - // Pub Key Response - append([]byte{byte(1 + len(testPubKey)), 1, 0, 4, 1}, testPubKey...), - - // OK - {7, 0, 0, 6, 0, 0, 0, 2, 0, 0, 0}, - } - conn.maxReads = 3 - - authData := []byte{123, 87, 15, 84, 20, 58, 37, 121, 91, 117, 51, 24, 19, - 47, 43, 9, 41, 112, 67, 110} - plugin := "mysql_native_password" - - if err := mc.handleAuthResult(authData, plugin); err != nil { - t.Errorf("got error: %v", err) - } - - expectedReplyPrefix := []byte{ - // 1. Packet: Pub Key Request - 1, 0, 0, 3, 1, - - // 2. Packet: Encrypted Password - 0, 1, 0, 5, // [changing bytes] - } - if !bytes.HasPrefix(conn.written, expectedReplyPrefix) { - t.Errorf("got unexpected data: %v", conn.written) - } -} - -func TestAuthSwitchSHA256PasswordRSAWithKey(t *testing.T) { - conn, mc := newRWMockConn(2) - mc.cfg.Passwd = "secret" - mc.cfg.pubKey = testPubKeyRSA - - // auth switch request - conn.data = []byte{38, 0, 0, 2, 254, 115, 104, 97, 50, 53, 54, 95, 112, 97, - 115, 115, 119, 111, 114, 100, 0, 78, 82, 62, 40, 100, 1, 59, 31, 44, 69, - 33, 112, 8, 81, 51, 96, 65, 82, 16, 114, 0} - - conn.queuedReplies = [][]byte{ - // OK - {7, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0}, - } - conn.maxReads = 2 - - authData := []byte{123, 87, 15, 84, 20, 58, 37, 121, 91, 117, 51, 24, 19, - 47, 43, 9, 41, 112, 67, 110} - plugin := "mysql_native_password" - - if err := mc.handleAuthResult(authData, plugin); err != nil { - t.Errorf("got error: %v", err) - } - - expectedReplyPrefix := []byte{ - // 1. Packet: Encrypted Password - 0, 1, 0, 3, // [changing bytes] - } - if !bytes.HasPrefix(conn.written, expectedReplyPrefix) { - t.Errorf("got unexpected data: %v", conn.written) - } -} - -func TestAuthSwitchSHA256PasswordSecure(t *testing.T) { - conn, mc := newRWMockConn(2) - mc.cfg.Passwd = "secret" - - // Hack to make the caching_sha2_password plugin believe that the connection - // is secure - mc.cfg.tls = &tls.Config{InsecureSkipVerify: true} - - // auth switch request - conn.data = []byte{38, 0, 0, 2, 254, 115, 104, 97, 50, 53, 54, 95, 112, 97, - 115, 115, 119, 111, 114, 100, 0, 78, 82, 62, 40, 100, 1, 59, 31, 44, 69, - 33, 112, 8, 81, 51, 96, 65, 82, 16, 114, 0} - - conn.queuedReplies = [][]byte{ - // OK - {7, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0}, - } - conn.maxReads = 2 - - authData := []byte{123, 87, 15, 84, 20, 58, 37, 121, 91, 117, 51, 24, 19, - 47, 43, 9, 41, 112, 67, 110} - plugin := "mysql_native_password" - - if err := mc.handleAuthResult(authData, plugin); err != nil { - t.Errorf("got error: %v", err) - } - - expectedReplyPrefix := []byte{ - // 1. Packet: Cleartext Password - 7, 0, 0, 3, 115, 101, 99, 114, 101, 116, 0, - } - if !bytes.Equal(conn.written, expectedReplyPrefix) { - t.Errorf("got unexpected data: %v", conn.written) - } -} diff --git a/vendor/github.com/go-sql-driver/mysql/benchmark_go18_test.go b/vendor/github.com/go-sql-driver/mysql/benchmark_go18_test.go deleted file mode 100644 index d6a7e9d6..00000000 --- a/vendor/github.com/go-sql-driver/mysql/benchmark_go18_test.go +++ /dev/null @@ -1,93 +0,0 @@ -// Go MySQL Driver - A MySQL-Driver for Go's database/sql package -// -// Copyright 2017 The Go-MySQL-Driver Authors. All rights reserved. -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this file, -// You can obtain one at http://mozilla.org/MPL/2.0/. - -// +build go1.8 - -package mysql - -import ( - "context" - "database/sql" - "fmt" - "runtime" - "testing" -) - -func benchmarkQueryContext(b *testing.B, db *sql.DB, p int) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - db.SetMaxIdleConns(p * runtime.GOMAXPROCS(0)) - - tb := (*TB)(b) - stmt := tb.checkStmt(db.PrepareContext(ctx, "SELECT val FROM foo WHERE id=?")) - defer stmt.Close() - - b.SetParallelism(p) - b.ReportAllocs() - b.ResetTimer() - b.RunParallel(func(pb *testing.PB) { - var got string - for pb.Next() { - tb.check(stmt.QueryRow(1).Scan(&got)) - if got != "one" { - b.Fatalf("query = %q; want one", got) - } - } - }) -} - -func BenchmarkQueryContext(b *testing.B) { - db := initDB(b, - "DROP TABLE IF EXISTS foo", - "CREATE TABLE foo (id INT PRIMARY KEY, val CHAR(50))", - `INSERT INTO foo VALUES (1, "one")`, - `INSERT INTO foo VALUES (2, "two")`, - ) - defer db.Close() - for _, p := range []int{1, 2, 3, 4} { - b.Run(fmt.Sprintf("%d", p), func(b *testing.B) { - benchmarkQueryContext(b, db, p) - }) - } -} - -func benchmarkExecContext(b *testing.B, db *sql.DB, p int) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - db.SetMaxIdleConns(p * runtime.GOMAXPROCS(0)) - - tb := (*TB)(b) - stmt := tb.checkStmt(db.PrepareContext(ctx, "DO 1")) - defer stmt.Close() - - b.SetParallelism(p) - b.ReportAllocs() - b.ResetTimer() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - if _, err := stmt.ExecContext(ctx); err != nil { - b.Fatal(err) - } - } - }) -} - -func BenchmarkExecContext(b *testing.B) { - db := initDB(b, - "DROP TABLE IF EXISTS foo", - "CREATE TABLE foo (id INT PRIMARY KEY, val CHAR(50))", - `INSERT INTO foo VALUES (1, "one")`, - `INSERT INTO foo VALUES (2, "two")`, - ) - defer db.Close() - for _, p := range []int{1, 2, 3, 4} { - b.Run(fmt.Sprintf("%d", p), func(b *testing.B) { - benchmarkQueryContext(b, db, p) - }) - } -} diff --git a/vendor/github.com/go-sql-driver/mysql/benchmark_test.go b/vendor/github.com/go-sql-driver/mysql/benchmark_test.go deleted file mode 100644 index c1de8672..00000000 --- a/vendor/github.com/go-sql-driver/mysql/benchmark_test.go +++ /dev/null @@ -1,242 +0,0 @@ -// Go MySQL Driver - A MySQL-Driver for Go's database/sql package -// -// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved. -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this file, -// You can obtain one at http://mozilla.org/MPL/2.0/. - -package mysql - -import ( - "bytes" - "database/sql" - "database/sql/driver" - "math" - "strings" - "sync" - "sync/atomic" - "testing" - "time" -) - -type TB testing.B - -func (tb *TB) check(err error) { - if err != nil { - tb.Fatal(err) - } -} - -func (tb *TB) checkDB(db *sql.DB, err error) *sql.DB { - tb.check(err) - return db -} - -func (tb *TB) checkRows(rows *sql.Rows, err error) *sql.Rows { - tb.check(err) - return rows -} - -func (tb *TB) checkStmt(stmt *sql.Stmt, err error) *sql.Stmt { - tb.check(err) - return stmt -} - -func initDB(b *testing.B, queries ...string) *sql.DB { - tb := (*TB)(b) - db := tb.checkDB(sql.Open("mysql", dsn)) - for _, query := range queries { - if _, err := db.Exec(query); err != nil { - b.Fatalf("error on %q: %v", query, err) - } - } - return db -} - -const concurrencyLevel = 10 - -func BenchmarkQuery(b *testing.B) { - tb := (*TB)(b) - b.StopTimer() - b.ReportAllocs() - db := initDB(b, - "DROP TABLE IF EXISTS foo", - "CREATE TABLE foo (id INT PRIMARY KEY, val CHAR(50))", - `INSERT INTO foo VALUES (1, "one")`, - `INSERT INTO foo VALUES (2, "two")`, - ) - db.SetMaxIdleConns(concurrencyLevel) - defer db.Close() - - stmt := tb.checkStmt(db.Prepare("SELECT val FROM foo WHERE id=?")) - defer stmt.Close() - - remain := int64(b.N) - var wg sync.WaitGroup - wg.Add(concurrencyLevel) - defer wg.Wait() - b.StartTimer() - - for i := 0; i < concurrencyLevel; i++ { - go func() { - for { - if atomic.AddInt64(&remain, -1) < 0 { - wg.Done() - return - } - - var got string - tb.check(stmt.QueryRow(1).Scan(&got)) - if got != "one" { - b.Errorf("query = %q; want one", got) - wg.Done() - return - } - } - }() - } -} - -func BenchmarkExec(b *testing.B) { - tb := (*TB)(b) - b.StopTimer() - b.ReportAllocs() - db := tb.checkDB(sql.Open("mysql", dsn)) - db.SetMaxIdleConns(concurrencyLevel) - defer db.Close() - - stmt := tb.checkStmt(db.Prepare("DO 1")) - defer stmt.Close() - - remain := int64(b.N) - var wg sync.WaitGroup - wg.Add(concurrencyLevel) - defer wg.Wait() - b.StartTimer() - - for i := 0; i < concurrencyLevel; i++ { - go func() { - for { - if atomic.AddInt64(&remain, -1) < 0 { - wg.Done() - return - } - - if _, err := stmt.Exec(); err != nil { - b.Fatal(err.Error()) - } - } - }() - } -} - -// data, but no db writes -var roundtripSample []byte - -func initRoundtripBenchmarks() ([]byte, int, int) { - if roundtripSample == nil { - roundtripSample = []byte(strings.Repeat("0123456789abcdef", 1024*1024)) - } - return roundtripSample, 16, len(roundtripSample) -} - -func BenchmarkRoundtripTxt(b *testing.B) { - b.StopTimer() - sample, min, max := initRoundtripBenchmarks() - sampleString := string(sample) - b.ReportAllocs() - tb := (*TB)(b) - db := tb.checkDB(sql.Open("mysql", dsn)) - defer db.Close() - b.StartTimer() - var result string - for i := 0; i < b.N; i++ { - length := min + i - if length > max { - length = max - } - test := sampleString[0:length] - rows := tb.checkRows(db.Query(`SELECT "` + test + `"`)) - if !rows.Next() { - rows.Close() - b.Fatalf("crashed") - } - err := rows.Scan(&result) - if err != nil { - rows.Close() - b.Fatalf("crashed") - } - if result != test { - rows.Close() - b.Errorf("mismatch") - } - rows.Close() - } -} - -func BenchmarkRoundtripBin(b *testing.B) { - b.StopTimer() - sample, min, max := initRoundtripBenchmarks() - b.ReportAllocs() - tb := (*TB)(b) - db := tb.checkDB(sql.Open("mysql", dsn)) - defer db.Close() - stmt := tb.checkStmt(db.Prepare("SELECT ?")) - defer stmt.Close() - b.StartTimer() - var result sql.RawBytes - for i := 0; i < b.N; i++ { - length := min + i - if length > max { - length = max - } - test := sample[0:length] - rows := tb.checkRows(stmt.Query(test)) - if !rows.Next() { - rows.Close() - b.Fatalf("crashed") - } - err := rows.Scan(&result) - if err != nil { - rows.Close() - b.Fatalf("crashed") - } - if !bytes.Equal(result, test) { - rows.Close() - b.Errorf("mismatch") - } - rows.Close() - } -} - -func BenchmarkInterpolation(b *testing.B) { - mc := &mysqlConn{ - cfg: &Config{ - InterpolateParams: true, - Loc: time.UTC, - }, - maxAllowedPacket: maxPacketSize, - maxWriteSize: maxPacketSize - 1, - buf: newBuffer(nil), - } - - args := []driver.Value{ - int64(42424242), - float64(math.Pi), - false, - time.Unix(1423411542, 807015000), - []byte("bytes containing special chars ' \" \a \x00"), - "string containing special chars ' \" \a \x00", - } - q := "SELECT ?, ?, ?, ?, ?, ?" - - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, err := mc.interpolateParams(q, args) - if err != nil { - b.Fatal(err) - } - } -} diff --git a/vendor/github.com/go-sql-driver/mysql/connection_go18_test.go b/vendor/github.com/go-sql-driver/mysql/connection_go18_test.go deleted file mode 100644 index 98367c10..00000000 --- a/vendor/github.com/go-sql-driver/mysql/connection_go18_test.go +++ /dev/null @@ -1,59 +0,0 @@ -// Go MySQL Driver - A MySQL-Driver for Go's database/sql package -// -// Copyright 2017 The Go-MySQL-Driver Authors. All rights reserved. -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this file, -// You can obtain one at http://mozilla.org/MPL/2.0/. - -// +build go1.8 - -package mysql - -import ( - "context" - "database/sql/driver" - "testing" -) - -func TestCheckNamedValue(t *testing.T) { - value := driver.NamedValue{Value: ^uint64(0)} - x := &mysqlConn{} - err := x.CheckNamedValue(&value) - - if err != nil { - t.Fatal("uint64 high-bit not convertible", err) - } - - if value.Value != "18446744073709551615" { - t.Fatalf("uint64 high-bit not converted, got %#v %T", value.Value, value.Value) - } -} - -// TestCleanCancel tests passed context is cancelled at start. -// No packet should be sent. Connection should keep current status. -func TestCleanCancel(t *testing.T) { - mc := &mysqlConn{ - closech: make(chan struct{}), - } - mc.startWatcher() - defer mc.cleanup() - - ctx, cancel := context.WithCancel(context.Background()) - cancel() - - for i := 0; i < 3; i++ { // Repeat same behavior - err := mc.Ping(ctx) - if err != context.Canceled { - t.Errorf("expected context.Canceled, got %#v", err) - } - - if mc.closed.IsSet() { - t.Error("expected mc is not closed, closed actually") - } - - if mc.watching { - t.Error("expected watching is false, but true") - } - } -} diff --git a/vendor/github.com/go-sql-driver/mysql/connection_test.go b/vendor/github.com/go-sql-driver/mysql/connection_test.go deleted file mode 100644 index 65325f10..00000000 --- a/vendor/github.com/go-sql-driver/mysql/connection_test.go +++ /dev/null @@ -1,67 +0,0 @@ -// Go MySQL Driver - A MySQL-Driver for Go's database/sql package -// -// Copyright 2016 The Go-MySQL-Driver Authors. All rights reserved. -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this file, -// You can obtain one at http://mozilla.org/MPL/2.0/. - -package mysql - -import ( - "database/sql/driver" - "testing" -) - -func TestInterpolateParams(t *testing.T) { - mc := &mysqlConn{ - buf: newBuffer(nil), - maxAllowedPacket: maxPacketSize, - cfg: &Config{ - InterpolateParams: true, - }, - } - - q, err := mc.interpolateParams("SELECT ?+?", []driver.Value{int64(42), "gopher"}) - if err != nil { - t.Errorf("Expected err=nil, got %#v", err) - return - } - expected := `SELECT 42+'gopher'` - if q != expected { - t.Errorf("Expected: %q\nGot: %q", expected, q) - } -} - -func TestInterpolateParamsTooManyPlaceholders(t *testing.T) { - mc := &mysqlConn{ - buf: newBuffer(nil), - maxAllowedPacket: maxPacketSize, - cfg: &Config{ - InterpolateParams: true, - }, - } - - q, err := mc.interpolateParams("SELECT ?+?", []driver.Value{int64(42)}) - if err != driver.ErrSkip { - t.Errorf("Expected err=driver.ErrSkip, got err=%#v, q=%#v", err, q) - } -} - -// We don't support placeholder in string literal for now. -// https://github.com/go-sql-driver/mysql/pull/490 -func TestInterpolateParamsPlaceholderInString(t *testing.T) { - mc := &mysqlConn{ - buf: newBuffer(nil), - maxAllowedPacket: maxPacketSize, - cfg: &Config{ - InterpolateParams: true, - }, - } - - q, err := mc.interpolateParams("SELECT 'abc?xyz',?", []driver.Value{int64(42)}) - // When InterpolateParams support string literal, this should return `"SELECT 'abc?xyz', 42` - if err != driver.ErrSkip { - t.Errorf("Expected err=driver.ErrSkip, got err=%#v, q=%#v", err, q) - } -} diff --git a/vendor/github.com/go-sql-driver/mysql/driver_go18_test.go b/vendor/github.com/go-sql-driver/mysql/driver_go18_test.go deleted file mode 100644 index 005e7620..00000000 --- a/vendor/github.com/go-sql-driver/mysql/driver_go18_test.go +++ /dev/null @@ -1,806 +0,0 @@ -// Go MySQL Driver - A MySQL-Driver for Go's database/sql package -// -// Copyright 2017 The Go-MySQL-Driver Authors. All rights reserved. -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this file, -// You can obtain one at http://mozilla.org/MPL/2.0/. - -// +build go1.8 - -package mysql - -import ( - "context" - "database/sql" - "database/sql/driver" - "fmt" - "math" - "reflect" - "testing" - "time" -) - -// static interface implementation checks of mysqlConn -var ( - _ driver.ConnBeginTx = &mysqlConn{} - _ driver.ConnPrepareContext = &mysqlConn{} - _ driver.ExecerContext = &mysqlConn{} - _ driver.Pinger = &mysqlConn{} - _ driver.QueryerContext = &mysqlConn{} -) - -// static interface implementation checks of mysqlStmt -var ( - _ driver.StmtExecContext = &mysqlStmt{} - _ driver.StmtQueryContext = &mysqlStmt{} -) - -// Ensure that all the driver interfaces are implemented -var ( - // _ driver.RowsColumnTypeLength = &binaryRows{} - // _ driver.RowsColumnTypeLength = &textRows{} - _ driver.RowsColumnTypeDatabaseTypeName = &binaryRows{} - _ driver.RowsColumnTypeDatabaseTypeName = &textRows{} - _ driver.RowsColumnTypeNullable = &binaryRows{} - _ driver.RowsColumnTypeNullable = &textRows{} - _ driver.RowsColumnTypePrecisionScale = &binaryRows{} - _ driver.RowsColumnTypePrecisionScale = &textRows{} - _ driver.RowsColumnTypeScanType = &binaryRows{} - _ driver.RowsColumnTypeScanType = &textRows{} - _ driver.RowsNextResultSet = &binaryRows{} - _ driver.RowsNextResultSet = &textRows{} -) - -func TestMultiResultSet(t *testing.T) { - type result struct { - values [][]int - columns []string - } - - // checkRows is a helper test function to validate rows containing 3 result - // sets with specific values and columns. The basic query would look like this: - // - // SELECT 1 AS col1, 2 AS col2 UNION SELECT 3, 4; - // SELECT 0 UNION SELECT 1; - // SELECT 1 AS col1, 2 AS col2, 3 AS col3 UNION SELECT 4, 5, 6; - // - // to distinguish test cases the first string argument is put in front of - // every error or fatal message. - checkRows := func(desc string, rows *sql.Rows, dbt *DBTest) { - expected := []result{ - { - values: [][]int{{1, 2}, {3, 4}}, - columns: []string{"col1", "col2"}, - }, - { - values: [][]int{{1, 2, 3}, {4, 5, 6}}, - columns: []string{"col1", "col2", "col3"}, - }, - } - - var res1 result - for rows.Next() { - var res [2]int - if err := rows.Scan(&res[0], &res[1]); err != nil { - dbt.Fatal(err) - } - res1.values = append(res1.values, res[:]) - } - - cols, err := rows.Columns() - if err != nil { - dbt.Fatal(desc, err) - } - res1.columns = cols - - if !reflect.DeepEqual(expected[0], res1) { - dbt.Error(desc, "want =", expected[0], "got =", res1) - } - - if !rows.NextResultSet() { - dbt.Fatal(desc, "expected next result set") - } - - // ignoring one result set - - if !rows.NextResultSet() { - dbt.Fatal(desc, "expected next result set") - } - - var res2 result - cols, err = rows.Columns() - if err != nil { - dbt.Fatal(desc, err) - } - res2.columns = cols - - for rows.Next() { - var res [3]int - if err := rows.Scan(&res[0], &res[1], &res[2]); err != nil { - dbt.Fatal(desc, err) - } - res2.values = append(res2.values, res[:]) - } - - if !reflect.DeepEqual(expected[1], res2) { - dbt.Error(desc, "want =", expected[1], "got =", res2) - } - - if rows.NextResultSet() { - dbt.Error(desc, "unexpected next result set") - } - - if err := rows.Err(); err != nil { - dbt.Error(desc, err) - } - } - - runTestsWithMultiStatement(t, dsn, func(dbt *DBTest) { - rows := dbt.mustQuery(`DO 1; - SELECT 1 AS col1, 2 AS col2 UNION SELECT 3, 4; - DO 1; - SELECT 0 UNION SELECT 1; - SELECT 1 AS col1, 2 AS col2, 3 AS col3 UNION SELECT 4, 5, 6;`) - defer rows.Close() - checkRows("query: ", rows, dbt) - }) - - runTestsWithMultiStatement(t, dsn, func(dbt *DBTest) { - queries := []string{ - ` - DROP PROCEDURE IF EXISTS test_mrss; - CREATE PROCEDURE test_mrss() - BEGIN - DO 1; - SELECT 1 AS col1, 2 AS col2 UNION SELECT 3, 4; - DO 1; - SELECT 0 UNION SELECT 1; - SELECT 1 AS col1, 2 AS col2, 3 AS col3 UNION SELECT 4, 5, 6; - END - `, - ` - DROP PROCEDURE IF EXISTS test_mrss; - CREATE PROCEDURE test_mrss() - BEGIN - SELECT 1 AS col1, 2 AS col2 UNION SELECT 3, 4; - SELECT 0 UNION SELECT 1; - SELECT 1 AS col1, 2 AS col2, 3 AS col3 UNION SELECT 4, 5, 6; - END - `, - } - - defer dbt.mustExec("DROP PROCEDURE IF EXISTS test_mrss") - - for i, query := range queries { - dbt.mustExec(query) - - stmt, err := dbt.db.Prepare("CALL test_mrss()") - if err != nil { - dbt.Fatalf("%v (i=%d)", err, i) - } - defer stmt.Close() - - for j := 0; j < 2; j++ { - rows, err := stmt.Query() - if err != nil { - dbt.Fatalf("%v (i=%d) (j=%d)", err, i, j) - } - checkRows(fmt.Sprintf("prepared stmt query (i=%d) (j=%d): ", i, j), rows, dbt) - } - } - }) -} - -func TestMultiResultSetNoSelect(t *testing.T) { - runTestsWithMultiStatement(t, dsn, func(dbt *DBTest) { - rows := dbt.mustQuery("DO 1; DO 2;") - defer rows.Close() - - if rows.Next() { - dbt.Error("unexpected row") - } - - if rows.NextResultSet() { - dbt.Error("unexpected next result set") - } - - if err := rows.Err(); err != nil { - dbt.Error("expected nil; got ", err) - } - }) -} - -// tests if rows are set in a proper state if some results were ignored before -// calling rows.NextResultSet. -func TestSkipResults(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - rows := dbt.mustQuery("SELECT 1, 2") - defer rows.Close() - - if !rows.Next() { - dbt.Error("expected row") - } - - if rows.NextResultSet() { - dbt.Error("unexpected next result set") - } - - if err := rows.Err(); err != nil { - dbt.Error("expected nil; got ", err) - } - }) -} - -func TestPingContext(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - ctx, cancel := context.WithCancel(context.Background()) - cancel() - if err := dbt.db.PingContext(ctx); err != context.Canceled { - dbt.Errorf("expected context.Canceled, got %v", err) - } - }) -} - -func TestContextCancelExec(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - dbt.mustExec("CREATE TABLE test (v INTEGER)") - ctx, cancel := context.WithCancel(context.Background()) - - // Delay execution for just a bit until db.ExecContext has begun. - defer time.AfterFunc(250*time.Millisecond, cancel).Stop() - - // This query will be canceled. - startTime := time.Now() - if _, err := dbt.db.ExecContext(ctx, "INSERT INTO test VALUES (SLEEP(1))"); err != context.Canceled { - dbt.Errorf("expected context.Canceled, got %v", err) - } - if d := time.Since(startTime); d > 500*time.Millisecond { - dbt.Errorf("too long execution time: %s", d) - } - - // Wait for the INSERT query to be done. - time.Sleep(time.Second) - - // Check how many times the query is executed. - var v int - if err := dbt.db.QueryRow("SELECT COUNT(*) FROM test").Scan(&v); err != nil { - dbt.Fatalf("%s", err.Error()) - } - if v != 1 { // TODO: need to kill the query, and v should be 0. - dbt.Skipf("[WARN] expected val to be 1, got %d", v) - } - - // Context is already canceled, so error should come before execution. - if _, err := dbt.db.ExecContext(ctx, "INSERT INTO test VALUES (1)"); err == nil { - dbt.Error("expected error") - } else if err.Error() != "context canceled" { - dbt.Fatalf("unexpected error: %s", err) - } - - // The second insert query will fail, so the table has no changes. - if err := dbt.db.QueryRow("SELECT COUNT(*) FROM test").Scan(&v); err != nil { - dbt.Fatalf("%s", err.Error()) - } - if v != 1 { - dbt.Skipf("[WARN] expected val to be 1, got %d", v) - } - }) -} - -func TestContextCancelQuery(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - dbt.mustExec("CREATE TABLE test (v INTEGER)") - ctx, cancel := context.WithCancel(context.Background()) - - // Delay execution for just a bit until db.ExecContext has begun. - defer time.AfterFunc(250*time.Millisecond, cancel).Stop() - - // This query will be canceled. - startTime := time.Now() - if _, err := dbt.db.QueryContext(ctx, "INSERT INTO test VALUES (SLEEP(1))"); err != context.Canceled { - dbt.Errorf("expected context.Canceled, got %v", err) - } - if d := time.Since(startTime); d > 500*time.Millisecond { - dbt.Errorf("too long execution time: %s", d) - } - - // Wait for the INSERT query to be done. - time.Sleep(time.Second) - - // Check how many times the query is executed. - var v int - if err := dbt.db.QueryRow("SELECT COUNT(*) FROM test").Scan(&v); err != nil { - dbt.Fatalf("%s", err.Error()) - } - if v != 1 { // TODO: need to kill the query, and v should be 0. - dbt.Skipf("[WARN] expected val to be 1, got %d", v) - } - - // Context is already canceled, so error should come before execution. - if _, err := dbt.db.QueryContext(ctx, "INSERT INTO test VALUES (1)"); err != context.Canceled { - dbt.Errorf("expected context.Canceled, got %v", err) - } - - // The second insert query will fail, so the table has no changes. - if err := dbt.db.QueryRow("SELECT COUNT(*) FROM test").Scan(&v); err != nil { - dbt.Fatalf("%s", err.Error()) - } - if v != 1 { - dbt.Skipf("[WARN] expected val to be 1, got %d", v) - } - }) -} - -func TestContextCancelQueryRow(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - dbt.mustExec("CREATE TABLE test (v INTEGER)") - dbt.mustExec("INSERT INTO test VALUES (1), (2), (3)") - ctx, cancel := context.WithCancel(context.Background()) - - rows, err := dbt.db.QueryContext(ctx, "SELECT v FROM test") - if err != nil { - dbt.Fatalf("%s", err.Error()) - } - - // the first row will be succeed. - var v int - if !rows.Next() { - dbt.Fatalf("unexpected end") - } - if err := rows.Scan(&v); err != nil { - dbt.Fatalf("%s", err.Error()) - } - - cancel() - // make sure the driver receives the cancel request. - time.Sleep(100 * time.Millisecond) - - if rows.Next() { - dbt.Errorf("expected end, but not") - } - if err := rows.Err(); err != context.Canceled { - dbt.Errorf("expected context.Canceled, got %v", err) - } - }) -} - -func TestContextCancelPrepare(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - ctx, cancel := context.WithCancel(context.Background()) - cancel() - if _, err := dbt.db.PrepareContext(ctx, "SELECT 1"); err != context.Canceled { - dbt.Errorf("expected context.Canceled, got %v", err) - } - }) -} - -func TestContextCancelStmtExec(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - dbt.mustExec("CREATE TABLE test (v INTEGER)") - ctx, cancel := context.WithCancel(context.Background()) - stmt, err := dbt.db.PrepareContext(ctx, "INSERT INTO test VALUES (SLEEP(1))") - if err != nil { - dbt.Fatalf("unexpected error: %v", err) - } - - // Delay execution for just a bit until db.ExecContext has begun. - defer time.AfterFunc(250*time.Millisecond, cancel).Stop() - - // This query will be canceled. - startTime := time.Now() - if _, err := stmt.ExecContext(ctx); err != context.Canceled { - dbt.Errorf("expected context.Canceled, got %v", err) - } - if d := time.Since(startTime); d > 500*time.Millisecond { - dbt.Errorf("too long execution time: %s", d) - } - - // Wait for the INSERT query to be done. - time.Sleep(time.Second) - - // Check how many times the query is executed. - var v int - if err := dbt.db.QueryRow("SELECT COUNT(*) FROM test").Scan(&v); err != nil { - dbt.Fatalf("%s", err.Error()) - } - if v != 1 { // TODO: need to kill the query, and v should be 0. - dbt.Skipf("[WARN] expected val to be 1, got %d", v) - } - }) -} - -func TestContextCancelStmtQuery(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - dbt.mustExec("CREATE TABLE test (v INTEGER)") - ctx, cancel := context.WithCancel(context.Background()) - stmt, err := dbt.db.PrepareContext(ctx, "INSERT INTO test VALUES (SLEEP(1))") - if err != nil { - dbt.Fatalf("unexpected error: %v", err) - } - - // Delay execution for just a bit until db.ExecContext has begun. - defer time.AfterFunc(250*time.Millisecond, cancel).Stop() - - // This query will be canceled. - startTime := time.Now() - if _, err := stmt.QueryContext(ctx); err != context.Canceled { - dbt.Errorf("expected context.Canceled, got %v", err) - } - if d := time.Since(startTime); d > 500*time.Millisecond { - dbt.Errorf("too long execution time: %s", d) - } - - // Wait for the INSERT query has done. - time.Sleep(time.Second) - - // Check how many times the query is executed. - var v int - if err := dbt.db.QueryRow("SELECT COUNT(*) FROM test").Scan(&v); err != nil { - dbt.Fatalf("%s", err.Error()) - } - if v != 1 { // TODO: need to kill the query, and v should be 0. - dbt.Skipf("[WARN] expected val to be 1, got %d", v) - } - }) -} - -func TestContextCancelBegin(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - dbt.mustExec("CREATE TABLE test (v INTEGER)") - ctx, cancel := context.WithCancel(context.Background()) - tx, err := dbt.db.BeginTx(ctx, nil) - if err != nil { - dbt.Fatal(err) - } - - // Delay execution for just a bit until db.ExecContext has begun. - defer time.AfterFunc(100*time.Millisecond, cancel).Stop() - - // This query will be canceled. - startTime := time.Now() - if _, err := tx.ExecContext(ctx, "INSERT INTO test VALUES (SLEEP(1))"); err != context.Canceled { - dbt.Errorf("expected context.Canceled, got %v", err) - } - if d := time.Since(startTime); d > 500*time.Millisecond { - dbt.Errorf("too long execution time: %s", d) - } - - // Transaction is canceled, so expect an error. - switch err := tx.Commit(); err { - case sql.ErrTxDone: - // because the transaction has already been rollbacked. - // the database/sql package watches ctx - // and rollbacks when ctx is canceled. - case context.Canceled: - // the database/sql package rollbacks on another goroutine, - // so the transaction may not be rollbacked depending on goroutine scheduling. - default: - dbt.Errorf("expected sql.ErrTxDone or context.Canceled, got %v", err) - } - - // Context is canceled, so cannot begin a transaction. - if _, err := dbt.db.BeginTx(ctx, nil); err != context.Canceled { - dbt.Errorf("expected context.Canceled, got %v", err) - } - }) -} - -func TestContextBeginIsolationLevel(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - dbt.mustExec("CREATE TABLE test (v INTEGER)") - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - tx1, err := dbt.db.BeginTx(ctx, &sql.TxOptions{ - Isolation: sql.LevelRepeatableRead, - }) - if err != nil { - dbt.Fatal(err) - } - - tx2, err := dbt.db.BeginTx(ctx, &sql.TxOptions{ - Isolation: sql.LevelReadCommitted, - }) - if err != nil { - dbt.Fatal(err) - } - - _, err = tx1.ExecContext(ctx, "INSERT INTO test VALUES (1)") - if err != nil { - dbt.Fatal(err) - } - - var v int - row := tx2.QueryRowContext(ctx, "SELECT COUNT(*) FROM test") - if err := row.Scan(&v); err != nil { - dbt.Fatal(err) - } - // Because writer transaction wasn't commited yet, it should be available - if v != 0 { - dbt.Errorf("expected val to be 0, got %d", v) - } - - err = tx1.Commit() - if err != nil { - dbt.Fatal(err) - } - - row = tx2.QueryRowContext(ctx, "SELECT COUNT(*) FROM test") - if err := row.Scan(&v); err != nil { - dbt.Fatal(err) - } - // Data written by writer transaction is already commited, it should be selectable - if v != 1 { - dbt.Errorf("expected val to be 1, got %d", v) - } - tx2.Commit() - }) -} - -func TestContextBeginReadOnly(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - dbt.mustExec("CREATE TABLE test (v INTEGER)") - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - tx, err := dbt.db.BeginTx(ctx, &sql.TxOptions{ - ReadOnly: true, - }) - if _, ok := err.(*MySQLError); ok { - dbt.Skip("It seems that your MySQL does not support READ ONLY transactions") - return - } else if err != nil { - dbt.Fatal(err) - } - - // INSERT queries fail in a READ ONLY transaction. - _, err = tx.ExecContext(ctx, "INSERT INTO test VALUES (1)") - if _, ok := err.(*MySQLError); !ok { - dbt.Errorf("expected MySQLError, got %v", err) - } - - // SELECT queries can be executed. - var v int - row := tx.QueryRowContext(ctx, "SELECT COUNT(*) FROM test") - if err := row.Scan(&v); err != nil { - dbt.Fatal(err) - } - if v != 0 { - dbt.Errorf("expected val to be 0, got %d", v) - } - - if err := tx.Commit(); err != nil { - dbt.Fatal(err) - } - }) -} - -func TestRowsColumnTypes(t *testing.T) { - niNULL := sql.NullInt64{Int64: 0, Valid: false} - ni0 := sql.NullInt64{Int64: 0, Valid: true} - ni1 := sql.NullInt64{Int64: 1, Valid: true} - ni42 := sql.NullInt64{Int64: 42, Valid: true} - nfNULL := sql.NullFloat64{Float64: 0.0, Valid: false} - nf0 := sql.NullFloat64{Float64: 0.0, Valid: true} - nf1337 := sql.NullFloat64{Float64: 13.37, Valid: true} - nt0 := NullTime{Time: time.Date(2006, 01, 02, 15, 04, 05, 0, time.UTC), Valid: true} - nt1 := NullTime{Time: time.Date(2006, 01, 02, 15, 04, 05, 100000000, time.UTC), Valid: true} - nt2 := NullTime{Time: time.Date(2006, 01, 02, 15, 04, 05, 110000000, time.UTC), Valid: true} - nt6 := NullTime{Time: time.Date(2006, 01, 02, 15, 04, 05, 111111000, time.UTC), Valid: true} - nd1 := NullTime{Time: time.Date(2006, 01, 02, 0, 0, 0, 0, time.UTC), Valid: true} - nd2 := NullTime{Time: time.Date(2006, 03, 04, 0, 0, 0, 0, time.UTC), Valid: true} - ndNULL := NullTime{Time: time.Time{}, Valid: false} - rbNULL := sql.RawBytes(nil) - rb0 := sql.RawBytes("0") - rb42 := sql.RawBytes("42") - rbTest := sql.RawBytes("Test") - rb0pad4 := sql.RawBytes("0\x00\x00\x00") // BINARY right-pads values with 0x00 - rbx0 := sql.RawBytes("\x00") - rbx42 := sql.RawBytes("\x42") - - var columns = []struct { - name string - fieldType string // type used when creating table schema - databaseTypeName string // actual type used by MySQL - scanType reflect.Type - nullable bool - precision int64 // 0 if not ok - scale int64 - valuesIn [3]string - valuesOut [3]interface{} - }{ - {"bit8null", "BIT(8)", "BIT", scanTypeRawBytes, true, 0, 0, [3]string{"0x0", "NULL", "0x42"}, [3]interface{}{rbx0, rbNULL, rbx42}}, - {"boolnull", "BOOL", "TINYINT", scanTypeNullInt, true, 0, 0, [3]string{"NULL", "true", "0"}, [3]interface{}{niNULL, ni1, ni0}}, - {"bool", "BOOL NOT NULL", "TINYINT", scanTypeInt8, false, 0, 0, [3]string{"1", "0", "FALSE"}, [3]interface{}{int8(1), int8(0), int8(0)}}, - {"intnull", "INTEGER", "INT", scanTypeNullInt, true, 0, 0, [3]string{"0", "NULL", "42"}, [3]interface{}{ni0, niNULL, ni42}}, - {"smallint", "SMALLINT NOT NULL", "SMALLINT", scanTypeInt16, false, 0, 0, [3]string{"0", "-32768", "32767"}, [3]interface{}{int16(0), int16(-32768), int16(32767)}}, - {"smallintnull", "SMALLINT", "SMALLINT", scanTypeNullInt, true, 0, 0, [3]string{"0", "NULL", "42"}, [3]interface{}{ni0, niNULL, ni42}}, - {"int3null", "INT(3)", "INT", scanTypeNullInt, true, 0, 0, [3]string{"0", "NULL", "42"}, [3]interface{}{ni0, niNULL, ni42}}, - {"int7", "INT(7) NOT NULL", "INT", scanTypeInt32, false, 0, 0, [3]string{"0", "-1337", "42"}, [3]interface{}{int32(0), int32(-1337), int32(42)}}, - {"mediumintnull", "MEDIUMINT", "MEDIUMINT", scanTypeNullInt, true, 0, 0, [3]string{"0", "42", "NULL"}, [3]interface{}{ni0, ni42, niNULL}}, - {"bigint", "BIGINT NOT NULL", "BIGINT", scanTypeInt64, false, 0, 0, [3]string{"0", "65535", "-42"}, [3]interface{}{int64(0), int64(65535), int64(-42)}}, - {"bigintnull", "BIGINT", "BIGINT", scanTypeNullInt, true, 0, 0, [3]string{"NULL", "1", "42"}, [3]interface{}{niNULL, ni1, ni42}}, - {"tinyuint", "TINYINT UNSIGNED NOT NULL", "TINYINT", scanTypeUint8, false, 0, 0, [3]string{"0", "255", "42"}, [3]interface{}{uint8(0), uint8(255), uint8(42)}}, - {"smalluint", "SMALLINT UNSIGNED NOT NULL", "SMALLINT", scanTypeUint16, false, 0, 0, [3]string{"0", "65535", "42"}, [3]interface{}{uint16(0), uint16(65535), uint16(42)}}, - {"biguint", "BIGINT UNSIGNED NOT NULL", "BIGINT", scanTypeUint64, false, 0, 0, [3]string{"0", "65535", "42"}, [3]interface{}{uint64(0), uint64(65535), uint64(42)}}, - {"uint13", "INT(13) UNSIGNED NOT NULL", "INT", scanTypeUint32, false, 0, 0, [3]string{"0", "1337", "42"}, [3]interface{}{uint32(0), uint32(1337), uint32(42)}}, - {"float", "FLOAT NOT NULL", "FLOAT", scanTypeFloat32, false, math.MaxInt64, math.MaxInt64, [3]string{"0", "42", "13.37"}, [3]interface{}{float32(0), float32(42), float32(13.37)}}, - {"floatnull", "FLOAT", "FLOAT", scanTypeNullFloat, true, math.MaxInt64, math.MaxInt64, [3]string{"0", "NULL", "13.37"}, [3]interface{}{nf0, nfNULL, nf1337}}, - {"float74null", "FLOAT(7,4)", "FLOAT", scanTypeNullFloat, true, math.MaxInt64, 4, [3]string{"0", "NULL", "13.37"}, [3]interface{}{nf0, nfNULL, nf1337}}, - {"double", "DOUBLE NOT NULL", "DOUBLE", scanTypeFloat64, false, math.MaxInt64, math.MaxInt64, [3]string{"0", "42", "13.37"}, [3]interface{}{float64(0), float64(42), float64(13.37)}}, - {"doublenull", "DOUBLE", "DOUBLE", scanTypeNullFloat, true, math.MaxInt64, math.MaxInt64, [3]string{"0", "NULL", "13.37"}, [3]interface{}{nf0, nfNULL, nf1337}}, - {"decimal1", "DECIMAL(10,6) NOT NULL", "DECIMAL", scanTypeRawBytes, false, 10, 6, [3]string{"0", "13.37", "1234.123456"}, [3]interface{}{sql.RawBytes("0.000000"), sql.RawBytes("13.370000"), sql.RawBytes("1234.123456")}}, - {"decimal1null", "DECIMAL(10,6)", "DECIMAL", scanTypeRawBytes, true, 10, 6, [3]string{"0", "NULL", "1234.123456"}, [3]interface{}{sql.RawBytes("0.000000"), rbNULL, sql.RawBytes("1234.123456")}}, - {"decimal2", "DECIMAL(8,4) NOT NULL", "DECIMAL", scanTypeRawBytes, false, 8, 4, [3]string{"0", "13.37", "1234.123456"}, [3]interface{}{sql.RawBytes("0.0000"), sql.RawBytes("13.3700"), sql.RawBytes("1234.1235")}}, - {"decimal2null", "DECIMAL(8,4)", "DECIMAL", scanTypeRawBytes, true, 8, 4, [3]string{"0", "NULL", "1234.123456"}, [3]interface{}{sql.RawBytes("0.0000"), rbNULL, sql.RawBytes("1234.1235")}}, - {"decimal3", "DECIMAL(5,0) NOT NULL", "DECIMAL", scanTypeRawBytes, false, 5, 0, [3]string{"0", "13.37", "-12345.123456"}, [3]interface{}{rb0, sql.RawBytes("13"), sql.RawBytes("-12345")}}, - {"decimal3null", "DECIMAL(5,0)", "DECIMAL", scanTypeRawBytes, true, 5, 0, [3]string{"0", "NULL", "-12345.123456"}, [3]interface{}{rb0, rbNULL, sql.RawBytes("-12345")}}, - {"char25null", "CHAR(25)", "CHAR", scanTypeRawBytes, true, 0, 0, [3]string{"0", "NULL", "'Test'"}, [3]interface{}{rb0, rbNULL, rbTest}}, - {"varchar42", "VARCHAR(42) NOT NULL", "VARCHAR", scanTypeRawBytes, false, 0, 0, [3]string{"0", "'Test'", "42"}, [3]interface{}{rb0, rbTest, rb42}}, - {"binary4null", "BINARY(4)", "BINARY", scanTypeRawBytes, true, 0, 0, [3]string{"0", "NULL", "'Test'"}, [3]interface{}{rb0pad4, rbNULL, rbTest}}, - {"varbinary42", "VARBINARY(42) NOT NULL", "VARBINARY", scanTypeRawBytes, false, 0, 0, [3]string{"0", "'Test'", "42"}, [3]interface{}{rb0, rbTest, rb42}}, - {"tinyblobnull", "TINYBLOB", "BLOB", scanTypeRawBytes, true, 0, 0, [3]string{"0", "NULL", "'Test'"}, [3]interface{}{rb0, rbNULL, rbTest}}, - {"tinytextnull", "TINYTEXT", "TEXT", scanTypeRawBytes, true, 0, 0, [3]string{"0", "NULL", "'Test'"}, [3]interface{}{rb0, rbNULL, rbTest}}, - {"blobnull", "BLOB", "BLOB", scanTypeRawBytes, true, 0, 0, [3]string{"0", "NULL", "'Test'"}, [3]interface{}{rb0, rbNULL, rbTest}}, - {"textnull", "TEXT", "TEXT", scanTypeRawBytes, true, 0, 0, [3]string{"0", "NULL", "'Test'"}, [3]interface{}{rb0, rbNULL, rbTest}}, - {"mediumblob", "MEDIUMBLOB NOT NULL", "BLOB", scanTypeRawBytes, false, 0, 0, [3]string{"0", "'Test'", "42"}, [3]interface{}{rb0, rbTest, rb42}}, - {"mediumtext", "MEDIUMTEXT NOT NULL", "TEXT", scanTypeRawBytes, false, 0, 0, [3]string{"0", "'Test'", "42"}, [3]interface{}{rb0, rbTest, rb42}}, - {"longblob", "LONGBLOB NOT NULL", "BLOB", scanTypeRawBytes, false, 0, 0, [3]string{"0", "'Test'", "42"}, [3]interface{}{rb0, rbTest, rb42}}, - {"longtext", "LONGTEXT NOT NULL", "TEXT", scanTypeRawBytes, false, 0, 0, [3]string{"0", "'Test'", "42"}, [3]interface{}{rb0, rbTest, rb42}}, - {"datetime", "DATETIME", "DATETIME", scanTypeNullTime, true, 0, 0, [3]string{"'2006-01-02 15:04:05'", "'2006-01-02 15:04:05.1'", "'2006-01-02 15:04:05.111111'"}, [3]interface{}{nt0, nt0, nt0}}, - {"datetime2", "DATETIME(2)", "DATETIME", scanTypeNullTime, true, 2, 2, [3]string{"'2006-01-02 15:04:05'", "'2006-01-02 15:04:05.1'", "'2006-01-02 15:04:05.111111'"}, [3]interface{}{nt0, nt1, nt2}}, - {"datetime6", "DATETIME(6)", "DATETIME", scanTypeNullTime, true, 6, 6, [3]string{"'2006-01-02 15:04:05'", "'2006-01-02 15:04:05.1'", "'2006-01-02 15:04:05.111111'"}, [3]interface{}{nt0, nt1, nt6}}, - {"date", "DATE", "DATE", scanTypeNullTime, true, 0, 0, [3]string{"'2006-01-02'", "NULL", "'2006-03-04'"}, [3]interface{}{nd1, ndNULL, nd2}}, - {"year", "YEAR NOT NULL", "YEAR", scanTypeUint16, false, 0, 0, [3]string{"2006", "2000", "1994"}, [3]interface{}{uint16(2006), uint16(2000), uint16(1994)}}, - } - - schema := "" - values1 := "" - values2 := "" - values3 := "" - for _, column := range columns { - schema += fmt.Sprintf("`%s` %s, ", column.name, column.fieldType) - values1 += column.valuesIn[0] + ", " - values2 += column.valuesIn[1] + ", " - values3 += column.valuesIn[2] + ", " - } - schema = schema[:len(schema)-2] - values1 = values1[:len(values1)-2] - values2 = values2[:len(values2)-2] - values3 = values3[:len(values3)-2] - - dsns := []string{ - dsn + "&parseTime=true", - dsn + "&parseTime=false", - } - for _, testdsn := range dsns { - runTests(t, testdsn, func(dbt *DBTest) { - dbt.mustExec("CREATE TABLE test (" + schema + ")") - dbt.mustExec("INSERT INTO test VALUES (" + values1 + "), (" + values2 + "), (" + values3 + ")") - - rows, err := dbt.db.Query("SELECT * FROM test") - if err != nil { - t.Fatalf("Query: %v", err) - } - - tt, err := rows.ColumnTypes() - if err != nil { - t.Fatalf("ColumnTypes: %v", err) - } - - if len(tt) != len(columns) { - t.Fatalf("unexpected number of columns: expected %d, got %d", len(columns), len(tt)) - } - - types := make([]reflect.Type, len(tt)) - for i, tp := range tt { - column := columns[i] - - // Name - name := tp.Name() - if name != column.name { - t.Errorf("column name mismatch %s != %s", name, column.name) - continue - } - - // DatabaseTypeName - databaseTypeName := tp.DatabaseTypeName() - if databaseTypeName != column.databaseTypeName { - t.Errorf("databasetypename name mismatch for column %q: %s != %s", name, databaseTypeName, column.databaseTypeName) - continue - } - - // ScanType - scanType := tp.ScanType() - if scanType != column.scanType { - if scanType == nil { - t.Errorf("scantype is null for column %q", name) - } else { - t.Errorf("scantype mismatch for column %q: %s != %s", name, scanType.Name(), column.scanType.Name()) - } - continue - } - types[i] = scanType - - // Nullable - nullable, ok := tp.Nullable() - if !ok { - t.Errorf("nullable not ok %q", name) - continue - } - if nullable != column.nullable { - t.Errorf("nullable mismatch for column %q: %t != %t", name, nullable, column.nullable) - } - - // Length - // length, ok := tp.Length() - // if length != column.length { - // if !ok { - // t.Errorf("length not ok for column %q", name) - // } else { - // t.Errorf("length mismatch for column %q: %d != %d", name, length, column.length) - // } - // continue - // } - - // Precision and Scale - precision, scale, ok := tp.DecimalSize() - if precision != column.precision { - if !ok { - t.Errorf("precision not ok for column %q", name) - } else { - t.Errorf("precision mismatch for column %q: %d != %d", name, precision, column.precision) - } - continue - } - if scale != column.scale { - if !ok { - t.Errorf("scale not ok for column %q", name) - } else { - t.Errorf("scale mismatch for column %q: %d != %d", name, scale, column.scale) - } - continue - } - } - - values := make([]interface{}, len(tt)) - for i := range values { - values[i] = reflect.New(types[i]).Interface() - } - i := 0 - for rows.Next() { - err = rows.Scan(values...) - if err != nil { - t.Fatalf("failed to scan values in %v", err) - } - for j := range values { - value := reflect.ValueOf(values[j]).Elem().Interface() - if !reflect.DeepEqual(value, columns[j].valuesOut[i]) { - if columns[j].scanType == scanTypeRawBytes { - t.Errorf("row %d, column %d: %v != %v", i, j, string(value.(sql.RawBytes)), string(columns[j].valuesOut[i].(sql.RawBytes))) - } else { - t.Errorf("row %d, column %d: %v != %v", i, j, value, columns[j].valuesOut[i]) - } - } - } - i++ - } - if i != 3 { - t.Errorf("expected 3 rows, got %d", i) - } - - if err := rows.Close(); err != nil { - t.Errorf("error closing rows: %s", err) - } - }) - } -} - -func TestValuerWithValueReceiverGivenNilValue(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - dbt.mustExec("CREATE TABLE test (value VARCHAR(255))") - dbt.db.Exec("INSERT INTO test VALUES (?)", (*testValuer)(nil)) - // This test will panic on the INSERT if ConvertValue() does not check for typed nil before calling Value() - }) -} diff --git a/vendor/github.com/go-sql-driver/mysql/driver_test.go b/vendor/github.com/go-sql-driver/mysql/driver_test.go deleted file mode 100644 index 3cbd98c8..00000000 --- a/vendor/github.com/go-sql-driver/mysql/driver_test.go +++ /dev/null @@ -1,2075 +0,0 @@ -// Go MySQL Driver - A MySQL-Driver for Go's database/sql package -// -// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved. -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this file, -// You can obtain one at http://mozilla.org/MPL/2.0/. - -package mysql - -import ( - "bytes" - "crypto/tls" - "database/sql" - "database/sql/driver" - "fmt" - "io" - "io/ioutil" - "log" - "net" - "net/url" - "os" - "strings" - "sync" - "sync/atomic" - "testing" - "time" -) - -// Ensure that all the driver interfaces are implemented -var ( - _ driver.Rows = &binaryRows{} - _ driver.Rows = &textRows{} -) - -var ( - user string - pass string - prot string - addr string - dbname string - dsn string - netAddr string - available bool -) - -var ( - tDate = time.Date(2012, 6, 14, 0, 0, 0, 0, time.UTC) - sDate = "2012-06-14" - tDateTime = time.Date(2011, 11, 20, 21, 27, 37, 0, time.UTC) - sDateTime = "2011-11-20 21:27:37" - tDate0 = time.Time{} - sDate0 = "0000-00-00" - sDateTime0 = "0000-00-00 00:00:00" -) - -// See https://github.com/go-sql-driver/mysql/wiki/Testing -func init() { - // get environment variables - env := func(key, defaultValue string) string { - if value := os.Getenv(key); value != "" { - return value - } - return defaultValue - } - user = env("MYSQL_TEST_USER", "root") - pass = env("MYSQL_TEST_PASS", "") - prot = env("MYSQL_TEST_PROT", "tcp") - addr = env("MYSQL_TEST_ADDR", "localhost:3306") - dbname = env("MYSQL_TEST_DBNAME", "gotest") - netAddr = fmt.Sprintf("%s(%s)", prot, addr) - dsn = fmt.Sprintf("%s:%s@%s/%s?timeout=30s", user, pass, netAddr, dbname) - c, err := net.Dial(prot, addr) - if err == nil { - available = true - c.Close() - } -} - -type DBTest struct { - *testing.T - db *sql.DB -} - -func runTestsWithMultiStatement(t *testing.T, dsn string, tests ...func(dbt *DBTest)) { - if !available { - t.Skipf("MySQL server not running on %s", netAddr) - } - - dsn += "&multiStatements=true" - var db *sql.DB - if _, err := ParseDSN(dsn); err != errInvalidDSNUnsafeCollation { - db, err = sql.Open("mysql", dsn) - if err != nil { - t.Fatalf("error connecting: %s", err.Error()) - } - defer db.Close() - } - - dbt := &DBTest{t, db} - for _, test := range tests { - test(dbt) - dbt.db.Exec("DROP TABLE IF EXISTS test") - } -} - -func runTests(t *testing.T, dsn string, tests ...func(dbt *DBTest)) { - if !available { - t.Skipf("MySQL server not running on %s", netAddr) - } - - db, err := sql.Open("mysql", dsn) - if err != nil { - t.Fatalf("error connecting: %s", err.Error()) - } - defer db.Close() - - db.Exec("DROP TABLE IF EXISTS test") - - dsn2 := dsn + "&interpolateParams=true" - var db2 *sql.DB - if _, err := ParseDSN(dsn2); err != errInvalidDSNUnsafeCollation { - db2, err = sql.Open("mysql", dsn2) - if err != nil { - t.Fatalf("error connecting: %s", err.Error()) - } - defer db2.Close() - } - - dsn3 := dsn + "&multiStatements=true" - var db3 *sql.DB - if _, err := ParseDSN(dsn3); err != errInvalidDSNUnsafeCollation { - db3, err = sql.Open("mysql", dsn3) - if err != nil { - t.Fatalf("error connecting: %s", err.Error()) - } - defer db3.Close() - } - - dbt := &DBTest{t, db} - dbt2 := &DBTest{t, db2} - dbt3 := &DBTest{t, db3} - for _, test := range tests { - test(dbt) - dbt.db.Exec("DROP TABLE IF EXISTS test") - if db2 != nil { - test(dbt2) - dbt2.db.Exec("DROP TABLE IF EXISTS test") - } - if db3 != nil { - test(dbt3) - dbt3.db.Exec("DROP TABLE IF EXISTS test") - } - } -} - -func (dbt *DBTest) fail(method, query string, err error) { - if len(query) > 300 { - query = "[query too large to print]" - } - dbt.Fatalf("error on %s %s: %s", method, query, err.Error()) -} - -func (dbt *DBTest) mustExec(query string, args ...interface{}) (res sql.Result) { - res, err := dbt.db.Exec(query, args...) - if err != nil { - dbt.fail("exec", query, err) - } - return res -} - -func (dbt *DBTest) mustQuery(query string, args ...interface{}) (rows *sql.Rows) { - rows, err := dbt.db.Query(query, args...) - if err != nil { - dbt.fail("query", query, err) - } - return rows -} - -func maybeSkip(t *testing.T, err error, skipErrno uint16) { - mySQLErr, ok := err.(*MySQLError) - if !ok { - return - } - - if mySQLErr.Number == skipErrno { - t.Skipf("skipping test for error: %v", err) - } -} - -func TestEmptyQuery(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - // just a comment, no query - rows := dbt.mustQuery("--") - // will hang before #255 - if rows.Next() { - dbt.Errorf("next on rows must be false") - } - }) -} - -func TestCRUD(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - // Create Table - dbt.mustExec("CREATE TABLE test (value BOOL)") - - // Test for unexpected data - var out bool - rows := dbt.mustQuery("SELECT * FROM test") - if rows.Next() { - dbt.Error("unexpected data in empty table") - } - - // Create Data - res := dbt.mustExec("INSERT INTO test VALUES (1)") - count, err := res.RowsAffected() - if err != nil { - dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error()) - } - if count != 1 { - dbt.Fatalf("expected 1 affected row, got %d", count) - } - - id, err := res.LastInsertId() - if err != nil { - dbt.Fatalf("res.LastInsertId() returned error: %s", err.Error()) - } - if id != 0 { - dbt.Fatalf("expected InsertId 0, got %d", id) - } - - // Read - rows = dbt.mustQuery("SELECT value FROM test") - if rows.Next() { - rows.Scan(&out) - if true != out { - dbt.Errorf("true != %t", out) - } - - if rows.Next() { - dbt.Error("unexpected data") - } - } else { - dbt.Error("no data") - } - - // Update - res = dbt.mustExec("UPDATE test SET value = ? WHERE value = ?", false, true) - count, err = res.RowsAffected() - if err != nil { - dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error()) - } - if count != 1 { - dbt.Fatalf("expected 1 affected row, got %d", count) - } - - // Check Update - rows = dbt.mustQuery("SELECT value FROM test") - if rows.Next() { - rows.Scan(&out) - if false != out { - dbt.Errorf("false != %t", out) - } - - if rows.Next() { - dbt.Error("unexpected data") - } - } else { - dbt.Error("no data") - } - - // Delete - res = dbt.mustExec("DELETE FROM test WHERE value = ?", false) - count, err = res.RowsAffected() - if err != nil { - dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error()) - } - if count != 1 { - dbt.Fatalf("expected 1 affected row, got %d", count) - } - - // Check for unexpected rows - res = dbt.mustExec("DELETE FROM test") - count, err = res.RowsAffected() - if err != nil { - dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error()) - } - if count != 0 { - dbt.Fatalf("expected 0 affected row, got %d", count) - } - }) -} - -func TestMultiQuery(t *testing.T) { - runTestsWithMultiStatement(t, dsn, func(dbt *DBTest) { - // Create Table - dbt.mustExec("CREATE TABLE `test` (`id` int(11) NOT NULL, `value` int(11) NOT NULL) ") - - // Create Data - res := dbt.mustExec("INSERT INTO test VALUES (1, 1)") - count, err := res.RowsAffected() - if err != nil { - dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error()) - } - if count != 1 { - dbt.Fatalf("expected 1 affected row, got %d", count) - } - - // Update - res = dbt.mustExec("UPDATE test SET value = 3 WHERE id = 1; UPDATE test SET value = 4 WHERE id = 1; UPDATE test SET value = 5 WHERE id = 1;") - count, err = res.RowsAffected() - if err != nil { - dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error()) - } - if count != 1 { - dbt.Fatalf("expected 1 affected row, got %d", count) - } - - // Read - var out int - rows := dbt.mustQuery("SELECT value FROM test WHERE id=1;") - if rows.Next() { - rows.Scan(&out) - if 5 != out { - dbt.Errorf("5 != %d", out) - } - - if rows.Next() { - dbt.Error("unexpected data") - } - } else { - dbt.Error("no data") - } - - }) -} - -func TestInt(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - types := [5]string{"TINYINT", "SMALLINT", "MEDIUMINT", "INT", "BIGINT"} - in := int64(42) - var out int64 - var rows *sql.Rows - - // SIGNED - for _, v := range types { - dbt.mustExec("CREATE TABLE test (value " + v + ")") - - dbt.mustExec("INSERT INTO test VALUES (?)", in) - - rows = dbt.mustQuery("SELECT value FROM test") - if rows.Next() { - rows.Scan(&out) - if in != out { - dbt.Errorf("%s: %d != %d", v, in, out) - } - } else { - dbt.Errorf("%s: no data", v) - } - - dbt.mustExec("DROP TABLE IF EXISTS test") - } - - // UNSIGNED ZEROFILL - for _, v := range types { - dbt.mustExec("CREATE TABLE test (value " + v + " ZEROFILL)") - - dbt.mustExec("INSERT INTO test VALUES (?)", in) - - rows = dbt.mustQuery("SELECT value FROM test") - if rows.Next() { - rows.Scan(&out) - if in != out { - dbt.Errorf("%s ZEROFILL: %d != %d", v, in, out) - } - } else { - dbt.Errorf("%s ZEROFILL: no data", v) - } - - dbt.mustExec("DROP TABLE IF EXISTS test") - } - }) -} - -func TestFloat32(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - types := [2]string{"FLOAT", "DOUBLE"} - in := float32(42.23) - var out float32 - var rows *sql.Rows - for _, v := range types { - dbt.mustExec("CREATE TABLE test (value " + v + ")") - dbt.mustExec("INSERT INTO test VALUES (?)", in) - rows = dbt.mustQuery("SELECT value FROM test") - if rows.Next() { - rows.Scan(&out) - if in != out { - dbt.Errorf("%s: %g != %g", v, in, out) - } - } else { - dbt.Errorf("%s: no data", v) - } - dbt.mustExec("DROP TABLE IF EXISTS test") - } - }) -} - -func TestFloat64(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - types := [2]string{"FLOAT", "DOUBLE"} - var expected float64 = 42.23 - var out float64 - var rows *sql.Rows - for _, v := range types { - dbt.mustExec("CREATE TABLE test (value " + v + ")") - dbt.mustExec("INSERT INTO test VALUES (42.23)") - rows = dbt.mustQuery("SELECT value FROM test") - if rows.Next() { - rows.Scan(&out) - if expected != out { - dbt.Errorf("%s: %g != %g", v, expected, out) - } - } else { - dbt.Errorf("%s: no data", v) - } - dbt.mustExec("DROP TABLE IF EXISTS test") - } - }) -} - -func TestFloat64Placeholder(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - types := [2]string{"FLOAT", "DOUBLE"} - var expected float64 = 42.23 - var out float64 - var rows *sql.Rows - for _, v := range types { - dbt.mustExec("CREATE TABLE test (id int, value " + v + ")") - dbt.mustExec("INSERT INTO test VALUES (1, 42.23)") - rows = dbt.mustQuery("SELECT value FROM test WHERE id = ?", 1) - if rows.Next() { - rows.Scan(&out) - if expected != out { - dbt.Errorf("%s: %g != %g", v, expected, out) - } - } else { - dbt.Errorf("%s: no data", v) - } - dbt.mustExec("DROP TABLE IF EXISTS test") - } - }) -} - -func TestString(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - types := [6]string{"CHAR(255)", "VARCHAR(255)", "TINYTEXT", "TEXT", "MEDIUMTEXT", "LONGTEXT"} - in := "κόσμε üöäßñóùéàâÿœ'îë Árvíztűrő いろはにほへとちりぬるを イロハニホヘト דג סקרן чащах น่าฟังเอย" - var out string - var rows *sql.Rows - - for _, v := range types { - dbt.mustExec("CREATE TABLE test (value " + v + ") CHARACTER SET utf8") - - dbt.mustExec("INSERT INTO test VALUES (?)", in) - - rows = dbt.mustQuery("SELECT value FROM test") - if rows.Next() { - rows.Scan(&out) - if in != out { - dbt.Errorf("%s: %s != %s", v, in, out) - } - } else { - dbt.Errorf("%s: no data", v) - } - - dbt.mustExec("DROP TABLE IF EXISTS test") - } - - // BLOB - dbt.mustExec("CREATE TABLE test (id int, value BLOB) CHARACTER SET utf8") - - id := 2 - in = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, " + - "sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, " + - "sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. " + - "Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. " + - "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, " + - "sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, " + - "sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. " + - "Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet." - dbt.mustExec("INSERT INTO test VALUES (?, ?)", id, in) - - err := dbt.db.QueryRow("SELECT value FROM test WHERE id = ?", id).Scan(&out) - if err != nil { - dbt.Fatalf("Error on BLOB-Query: %s", err.Error()) - } else if out != in { - dbt.Errorf("BLOB: %s != %s", in, out) - } - }) -} - -func TestRawBytes(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - v1 := []byte("aaa") - v2 := []byte("bbb") - rows := dbt.mustQuery("SELECT ?, ?", v1, v2) - if rows.Next() { - var o1, o2 sql.RawBytes - if err := rows.Scan(&o1, &o2); err != nil { - dbt.Errorf("Got error: %v", err) - } - if !bytes.Equal(v1, o1) { - dbt.Errorf("expected %v, got %v", v1, o1) - } - if !bytes.Equal(v2, o2) { - dbt.Errorf("expected %v, got %v", v2, o2) - } - // https://github.com/go-sql-driver/mysql/issues/765 - // Appending to RawBytes shouldn't overwrite next RawBytes. - o1 = append(o1, "xyzzy"...) - if !bytes.Equal(v2, o2) { - dbt.Errorf("expected %v, got %v", v2, o2) - } - } else { - dbt.Errorf("no data") - } - }) -} - -type testValuer struct { - value string -} - -func (tv testValuer) Value() (driver.Value, error) { - return tv.value, nil -} - -func TestValuer(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - in := testValuer{"a_value"} - var out string - var rows *sql.Rows - - dbt.mustExec("CREATE TABLE test (value VARCHAR(255)) CHARACTER SET utf8") - dbt.mustExec("INSERT INTO test VALUES (?)", in) - rows = dbt.mustQuery("SELECT value FROM test") - if rows.Next() { - rows.Scan(&out) - if in.value != out { - dbt.Errorf("Valuer: %v != %s", in, out) - } - } else { - dbt.Errorf("Valuer: no data") - } - - dbt.mustExec("DROP TABLE IF EXISTS test") - }) -} - -type testValuerWithValidation struct { - value string -} - -func (tv testValuerWithValidation) Value() (driver.Value, error) { - if len(tv.value) == 0 { - return nil, fmt.Errorf("Invalid string valuer. Value must not be empty") - } - - return tv.value, nil -} - -func TestValuerWithValidation(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - in := testValuerWithValidation{"a_value"} - var out string - var rows *sql.Rows - - dbt.mustExec("CREATE TABLE testValuer (value VARCHAR(255)) CHARACTER SET utf8") - dbt.mustExec("INSERT INTO testValuer VALUES (?)", in) - - rows = dbt.mustQuery("SELECT value FROM testValuer") - defer rows.Close() - - if rows.Next() { - rows.Scan(&out) - if in.value != out { - dbt.Errorf("Valuer: %v != %s", in, out) - } - } else { - dbt.Errorf("Valuer: no data") - } - - if _, err := dbt.db.Exec("INSERT INTO testValuer VALUES (?)", testValuerWithValidation{""}); err == nil { - dbt.Errorf("Failed to check valuer error") - } - - if _, err := dbt.db.Exec("INSERT INTO testValuer VALUES (?)", nil); err != nil { - dbt.Errorf("Failed to check nil") - } - - if _, err := dbt.db.Exec("INSERT INTO testValuer VALUES (?)", map[string]bool{}); err == nil { - dbt.Errorf("Failed to check not valuer") - } - - dbt.mustExec("DROP TABLE IF EXISTS testValuer") - }) -} - -type timeTests struct { - dbtype string - tlayout string - tests []timeTest -} - -type timeTest struct { - s string // leading "!": do not use t as value in queries - t time.Time -} - -type timeMode byte - -func (t timeMode) String() string { - switch t { - case binaryString: - return "binary:string" - case binaryTime: - return "binary:time.Time" - case textString: - return "text:string" - } - panic("unsupported timeMode") -} - -func (t timeMode) Binary() bool { - switch t { - case binaryString, binaryTime: - return true - } - return false -} - -const ( - binaryString timeMode = iota - binaryTime - textString -) - -func (t timeTest) genQuery(dbtype string, mode timeMode) string { - var inner string - if mode.Binary() { - inner = "?" - } else { - inner = `"%s"` - } - return `SELECT cast(` + inner + ` as ` + dbtype + `)` -} - -func (t timeTest) run(dbt *DBTest, dbtype, tlayout string, mode timeMode) { - var rows *sql.Rows - query := t.genQuery(dbtype, mode) - switch mode { - case binaryString: - rows = dbt.mustQuery(query, t.s) - case binaryTime: - rows = dbt.mustQuery(query, t.t) - case textString: - query = fmt.Sprintf(query, t.s) - rows = dbt.mustQuery(query) - default: - panic("unsupported mode") - } - defer rows.Close() - var err error - if !rows.Next() { - err = rows.Err() - if err == nil { - err = fmt.Errorf("no data") - } - dbt.Errorf("%s [%s]: %s", dbtype, mode, err) - return - } - var dst interface{} - err = rows.Scan(&dst) - if err != nil { - dbt.Errorf("%s [%s]: %s", dbtype, mode, err) - return - } - switch val := dst.(type) { - case []uint8: - str := string(val) - if str == t.s { - return - } - if mode.Binary() && dbtype == "DATETIME" && len(str) == 26 && str[:19] == t.s { - // a fix mainly for TravisCI: - // accept full microsecond resolution in result for DATETIME columns - // where the binary protocol was used - return - } - dbt.Errorf("%s [%s] to string: expected %q, got %q", - dbtype, mode, - t.s, str, - ) - case time.Time: - if val == t.t { - return - } - dbt.Errorf("%s [%s] to string: expected %q, got %q", - dbtype, mode, - t.s, val.Format(tlayout), - ) - default: - fmt.Printf("%#v\n", []interface{}{dbtype, tlayout, mode, t.s, t.t}) - dbt.Errorf("%s [%s]: unhandled type %T (is '%v')", - dbtype, mode, - val, val, - ) - } -} - -func TestDateTime(t *testing.T) { - afterTime := func(t time.Time, d string) time.Time { - dur, err := time.ParseDuration(d) - if err != nil { - panic(err) - } - return t.Add(dur) - } - // NOTE: MySQL rounds DATETIME(x) up - but that's not included in the tests - format := "2006-01-02 15:04:05.999999" - t0 := time.Time{} - tstr0 := "0000-00-00 00:00:00.000000" - testcases := []timeTests{ - {"DATE", format[:10], []timeTest{ - {t: time.Date(2011, 11, 20, 0, 0, 0, 0, time.UTC)}, - {t: t0, s: tstr0[:10]}, - }}, - {"DATETIME", format[:19], []timeTest{ - {t: time.Date(2011, 11, 20, 21, 27, 37, 0, time.UTC)}, - {t: t0, s: tstr0[:19]}, - }}, - {"DATETIME(0)", format[:21], []timeTest{ - {t: time.Date(2011, 11, 20, 21, 27, 37, 0, time.UTC)}, - {t: t0, s: tstr0[:19]}, - }}, - {"DATETIME(1)", format[:21], []timeTest{ - {t: time.Date(2011, 11, 20, 21, 27, 37, 100000000, time.UTC)}, - {t: t0, s: tstr0[:21]}, - }}, - {"DATETIME(6)", format, []timeTest{ - {t: time.Date(2011, 11, 20, 21, 27, 37, 123456000, time.UTC)}, - {t: t0, s: tstr0}, - }}, - {"TIME", format[11:19], []timeTest{ - {t: afterTime(t0, "12345s")}, - {s: "!-12:34:56"}, - {s: "!-838:59:59"}, - {s: "!838:59:59"}, - {t: t0, s: tstr0[11:19]}, - }}, - {"TIME(0)", format[11:19], []timeTest{ - {t: afterTime(t0, "12345s")}, - {s: "!-12:34:56"}, - {s: "!-838:59:59"}, - {s: "!838:59:59"}, - {t: t0, s: tstr0[11:19]}, - }}, - {"TIME(1)", format[11:21], []timeTest{ - {t: afterTime(t0, "12345600ms")}, - {s: "!-12:34:56.7"}, - {s: "!-838:59:58.9"}, - {s: "!838:59:58.9"}, - {t: t0, s: tstr0[11:21]}, - }}, - {"TIME(6)", format[11:], []timeTest{ - {t: afterTime(t0, "1234567890123000ns")}, - {s: "!-12:34:56.789012"}, - {s: "!-838:59:58.999999"}, - {s: "!838:59:58.999999"}, - {t: t0, s: tstr0[11:]}, - }}, - } - dsns := []string{ - dsn + "&parseTime=true", - dsn + "&parseTime=false", - } - for _, testdsn := range dsns { - runTests(t, testdsn, func(dbt *DBTest) { - microsecsSupported := false - zeroDateSupported := false - var rows *sql.Rows - var err error - rows, err = dbt.db.Query(`SELECT cast("00:00:00.1" as TIME(1)) = "00:00:00.1"`) - if err == nil { - rows.Scan(µsecsSupported) - rows.Close() - } - rows, err = dbt.db.Query(`SELECT cast("0000-00-00" as DATE) = "0000-00-00"`) - if err == nil { - rows.Scan(&zeroDateSupported) - rows.Close() - } - for _, setups := range testcases { - if t := setups.dbtype; !microsecsSupported && t[len(t)-1:] == ")" { - // skip fractional second tests if unsupported by server - continue - } - for _, setup := range setups.tests { - allowBinTime := true - if setup.s == "" { - // fill time string wherever Go can reliable produce it - setup.s = setup.t.Format(setups.tlayout) - } else if setup.s[0] == '!' { - // skip tests using setup.t as source in queries - allowBinTime = false - // fix setup.s - remove the "!" - setup.s = setup.s[1:] - } - if !zeroDateSupported && setup.s == tstr0[:len(setup.s)] { - // skip disallowed 0000-00-00 date - continue - } - setup.run(dbt, setups.dbtype, setups.tlayout, textString) - setup.run(dbt, setups.dbtype, setups.tlayout, binaryString) - if allowBinTime { - setup.run(dbt, setups.dbtype, setups.tlayout, binaryTime) - } - } - } - }) - } -} - -func TestTimestampMicros(t *testing.T) { - format := "2006-01-02 15:04:05.999999" - f0 := format[:19] - f1 := format[:21] - f6 := format[:26] - runTests(t, dsn, func(dbt *DBTest) { - // check if microseconds are supported. - // Do not use timestamp(x) for that check - before 5.5.6, x would mean display width - // and not precision. - // Se last paragraph at http://dev.mysql.com/doc/refman/5.6/en/fractional-seconds.html - microsecsSupported := false - if rows, err := dbt.db.Query(`SELECT cast("00:00:00.1" as TIME(1)) = "00:00:00.1"`); err == nil { - rows.Scan(µsecsSupported) - rows.Close() - } - if !microsecsSupported { - // skip test - return - } - _, err := dbt.db.Exec(` - CREATE TABLE test ( - value0 TIMESTAMP NOT NULL DEFAULT '` + f0 + `', - value1 TIMESTAMP(1) NOT NULL DEFAULT '` + f1 + `', - value6 TIMESTAMP(6) NOT NULL DEFAULT '` + f6 + `' - )`, - ) - if err != nil { - dbt.Error(err) - } - defer dbt.mustExec("DROP TABLE IF EXISTS test") - dbt.mustExec("INSERT INTO test SET value0=?, value1=?, value6=?", f0, f1, f6) - var res0, res1, res6 string - rows := dbt.mustQuery("SELECT * FROM test") - if !rows.Next() { - dbt.Errorf("test contained no selectable values") - } - err = rows.Scan(&res0, &res1, &res6) - if err != nil { - dbt.Error(err) - } - if res0 != f0 { - dbt.Errorf("expected %q, got %q", f0, res0) - } - if res1 != f1 { - dbt.Errorf("expected %q, got %q", f1, res1) - } - if res6 != f6 { - dbt.Errorf("expected %q, got %q", f6, res6) - } - }) -} - -func TestNULL(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - nullStmt, err := dbt.db.Prepare("SELECT NULL") - if err != nil { - dbt.Fatal(err) - } - defer nullStmt.Close() - - nonNullStmt, err := dbt.db.Prepare("SELECT 1") - if err != nil { - dbt.Fatal(err) - } - defer nonNullStmt.Close() - - // NullBool - var nb sql.NullBool - // Invalid - if err = nullStmt.QueryRow().Scan(&nb); err != nil { - dbt.Fatal(err) - } - if nb.Valid { - dbt.Error("valid NullBool which should be invalid") - } - // Valid - if err = nonNullStmt.QueryRow().Scan(&nb); err != nil { - dbt.Fatal(err) - } - if !nb.Valid { - dbt.Error("invalid NullBool which should be valid") - } else if nb.Bool != true { - dbt.Errorf("Unexpected NullBool value: %t (should be true)", nb.Bool) - } - - // NullFloat64 - var nf sql.NullFloat64 - // Invalid - if err = nullStmt.QueryRow().Scan(&nf); err != nil { - dbt.Fatal(err) - } - if nf.Valid { - dbt.Error("valid NullFloat64 which should be invalid") - } - // Valid - if err = nonNullStmt.QueryRow().Scan(&nf); err != nil { - dbt.Fatal(err) - } - if !nf.Valid { - dbt.Error("invalid NullFloat64 which should be valid") - } else if nf.Float64 != float64(1) { - dbt.Errorf("unexpected NullFloat64 value: %f (should be 1.0)", nf.Float64) - } - - // NullInt64 - var ni sql.NullInt64 - // Invalid - if err = nullStmt.QueryRow().Scan(&ni); err != nil { - dbt.Fatal(err) - } - if ni.Valid { - dbt.Error("valid NullInt64 which should be invalid") - } - // Valid - if err = nonNullStmt.QueryRow().Scan(&ni); err != nil { - dbt.Fatal(err) - } - if !ni.Valid { - dbt.Error("invalid NullInt64 which should be valid") - } else if ni.Int64 != int64(1) { - dbt.Errorf("unexpected NullInt64 value: %d (should be 1)", ni.Int64) - } - - // NullString - var ns sql.NullString - // Invalid - if err = nullStmt.QueryRow().Scan(&ns); err != nil { - dbt.Fatal(err) - } - if ns.Valid { - dbt.Error("valid NullString which should be invalid") - } - // Valid - if err = nonNullStmt.QueryRow().Scan(&ns); err != nil { - dbt.Fatal(err) - } - if !ns.Valid { - dbt.Error("invalid NullString which should be valid") - } else if ns.String != `1` { - dbt.Error("unexpected NullString value:" + ns.String + " (should be `1`)") - } - - // nil-bytes - var b []byte - // Read nil - if err = nullStmt.QueryRow().Scan(&b); err != nil { - dbt.Fatal(err) - } - if b != nil { - dbt.Error("non-nil []byte which should be nil") - } - // Read non-nil - if err = nonNullStmt.QueryRow().Scan(&b); err != nil { - dbt.Fatal(err) - } - if b == nil { - dbt.Error("nil []byte which should be non-nil") - } - // Insert nil - b = nil - success := false - if err = dbt.db.QueryRow("SELECT ? IS NULL", b).Scan(&success); err != nil { - dbt.Fatal(err) - } - if !success { - dbt.Error("inserting []byte(nil) as NULL failed") - } - // Check input==output with input==nil - b = nil - if err = dbt.db.QueryRow("SELECT ?", b).Scan(&b); err != nil { - dbt.Fatal(err) - } - if b != nil { - dbt.Error("non-nil echo from nil input") - } - // Check input==output with input!=nil - b = []byte("") - if err = dbt.db.QueryRow("SELECT ?", b).Scan(&b); err != nil { - dbt.Fatal(err) - } - if b == nil { - dbt.Error("nil echo from non-nil input") - } - - // Insert NULL - dbt.mustExec("CREATE TABLE test (dummmy1 int, value int, dummy2 int)") - - dbt.mustExec("INSERT INTO test VALUES (?, ?, ?)", 1, nil, 2) - - var out interface{} - rows := dbt.mustQuery("SELECT * FROM test") - if rows.Next() { - rows.Scan(&out) - if out != nil { - dbt.Errorf("%v != nil", out) - } - } else { - dbt.Error("no data") - } - }) -} - -func TestUint64(t *testing.T) { - const ( - u0 = uint64(0) - uall = ^u0 - uhigh = uall >> 1 - utop = ^uhigh - s0 = int64(0) - sall = ^s0 - shigh = int64(uhigh) - stop = ^shigh - ) - runTests(t, dsn, func(dbt *DBTest) { - stmt, err := dbt.db.Prepare(`SELECT ?, ?, ? ,?, ?, ?, ?, ?`) - if err != nil { - dbt.Fatal(err) - } - defer stmt.Close() - row := stmt.QueryRow( - u0, uhigh, utop, uall, - s0, shigh, stop, sall, - ) - - var ua, ub, uc, ud uint64 - var sa, sb, sc, sd int64 - - err = row.Scan(&ua, &ub, &uc, &ud, &sa, &sb, &sc, &sd) - if err != nil { - dbt.Fatal(err) - } - switch { - case ua != u0, - ub != uhigh, - uc != utop, - ud != uall, - sa != s0, - sb != shigh, - sc != stop, - sd != sall: - dbt.Fatal("unexpected result value") - } - }) -} - -func TestLongData(t *testing.T) { - runTests(t, dsn+"&maxAllowedPacket=0", func(dbt *DBTest) { - var maxAllowedPacketSize int - err := dbt.db.QueryRow("select @@max_allowed_packet").Scan(&maxAllowedPacketSize) - if err != nil { - dbt.Fatal(err) - } - maxAllowedPacketSize-- - - // don't get too ambitious - if maxAllowedPacketSize > 1<<25 { - maxAllowedPacketSize = 1 << 25 - } - - dbt.mustExec("CREATE TABLE test (value LONGBLOB)") - - in := strings.Repeat(`a`, maxAllowedPacketSize+1) - var out string - var rows *sql.Rows - - // Long text data - const nonDataQueryLen = 28 // length query w/o value - inS := in[:maxAllowedPacketSize-nonDataQueryLen] - dbt.mustExec("INSERT INTO test VALUES('" + inS + "')") - rows = dbt.mustQuery("SELECT value FROM test") - if rows.Next() { - rows.Scan(&out) - if inS != out { - dbt.Fatalf("LONGBLOB: length in: %d, length out: %d", len(inS), len(out)) - } - if rows.Next() { - dbt.Error("LONGBLOB: unexpexted row") - } - } else { - dbt.Fatalf("LONGBLOB: no data") - } - - // Empty table - dbt.mustExec("TRUNCATE TABLE test") - - // Long binary data - dbt.mustExec("INSERT INTO test VALUES(?)", in) - rows = dbt.mustQuery("SELECT value FROM test WHERE 1=?", 1) - if rows.Next() { - rows.Scan(&out) - if in != out { - dbt.Fatalf("LONGBLOB: length in: %d, length out: %d", len(in), len(out)) - } - if rows.Next() { - dbt.Error("LONGBLOB: unexpexted row") - } - } else { - if err = rows.Err(); err != nil { - dbt.Fatalf("LONGBLOB: no data (err: %s)", err.Error()) - } else { - dbt.Fatal("LONGBLOB: no data (err: )") - } - } - }) -} - -func TestLoadData(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - verifyLoadDataResult := func() { - rows, err := dbt.db.Query("SELECT * FROM test") - if err != nil { - dbt.Fatal(err.Error()) - } - - i := 0 - values := [4]string{ - "a string", - "a string containing a \t", - "a string containing a \n", - "a string containing both \t\n", - } - - var id int - var value string - - for rows.Next() { - i++ - err = rows.Scan(&id, &value) - if err != nil { - dbt.Fatal(err.Error()) - } - if i != id { - dbt.Fatalf("%d != %d", i, id) - } - if values[i-1] != value { - dbt.Fatalf("%q != %q", values[i-1], value) - } - } - err = rows.Err() - if err != nil { - dbt.Fatal(err.Error()) - } - - if i != 4 { - dbt.Fatalf("rows count mismatch. Got %d, want 4", i) - } - } - - dbt.db.Exec("DROP TABLE IF EXISTS test") - dbt.mustExec("CREATE TABLE test (id INT NOT NULL PRIMARY KEY, value TEXT NOT NULL) CHARACTER SET utf8") - - // Local File - file, err := ioutil.TempFile("", "gotest") - defer os.Remove(file.Name()) - if err != nil { - dbt.Fatal(err) - } - RegisterLocalFile(file.Name()) - - // Try first with empty file - dbt.mustExec(fmt.Sprintf("LOAD DATA LOCAL INFILE %q INTO TABLE test", file.Name())) - var count int - err = dbt.db.QueryRow("SELECT COUNT(*) FROM test").Scan(&count) - if err != nil { - dbt.Fatal(err.Error()) - } - if count != 0 { - dbt.Fatalf("unexpected row count: got %d, want 0", count) - } - - // Then fille File with data and try to load it - file.WriteString("1\ta string\n2\ta string containing a \\t\n3\ta string containing a \\n\n4\ta string containing both \\t\\n\n") - file.Close() - dbt.mustExec(fmt.Sprintf("LOAD DATA LOCAL INFILE %q INTO TABLE test", file.Name())) - verifyLoadDataResult() - - // Try with non-existing file - _, err = dbt.db.Exec("LOAD DATA LOCAL INFILE 'doesnotexist' INTO TABLE test") - if err == nil { - dbt.Fatal("load non-existent file didn't fail") - } else if err.Error() != "local file 'doesnotexist' is not registered" { - dbt.Fatal(err.Error()) - } - - // Empty table - dbt.mustExec("TRUNCATE TABLE test") - - // Reader - RegisterReaderHandler("test", func() io.Reader { - file, err = os.Open(file.Name()) - if err != nil { - dbt.Fatal(err) - } - return file - }) - dbt.mustExec("LOAD DATA LOCAL INFILE 'Reader::test' INTO TABLE test") - verifyLoadDataResult() - // negative test - _, err = dbt.db.Exec("LOAD DATA LOCAL INFILE 'Reader::doesnotexist' INTO TABLE test") - if err == nil { - dbt.Fatal("load non-existent Reader didn't fail") - } else if err.Error() != "Reader 'doesnotexist' is not registered" { - dbt.Fatal(err.Error()) - } - }) -} - -func TestFoundRows(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - dbt.mustExec("CREATE TABLE test (id INT NOT NULL ,data INT NOT NULL)") - dbt.mustExec("INSERT INTO test (id, data) VALUES (0, 0),(0, 0),(1, 0),(1, 0),(1, 1)") - - res := dbt.mustExec("UPDATE test SET data = 1 WHERE id = 0") - count, err := res.RowsAffected() - if err != nil { - dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error()) - } - if count != 2 { - dbt.Fatalf("Expected 2 affected rows, got %d", count) - } - res = dbt.mustExec("UPDATE test SET data = 1 WHERE id = 1") - count, err = res.RowsAffected() - if err != nil { - dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error()) - } - if count != 2 { - dbt.Fatalf("Expected 2 affected rows, got %d", count) - } - }) - runTests(t, dsn+"&clientFoundRows=true", func(dbt *DBTest) { - dbt.mustExec("CREATE TABLE test (id INT NOT NULL ,data INT NOT NULL)") - dbt.mustExec("INSERT INTO test (id, data) VALUES (0, 0),(0, 0),(1, 0),(1, 0),(1, 1)") - - res := dbt.mustExec("UPDATE test SET data = 1 WHERE id = 0") - count, err := res.RowsAffected() - if err != nil { - dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error()) - } - if count != 2 { - dbt.Fatalf("Expected 2 matched rows, got %d", count) - } - res = dbt.mustExec("UPDATE test SET data = 1 WHERE id = 1") - count, err = res.RowsAffected() - if err != nil { - dbt.Fatalf("res.RowsAffected() returned error: %s", err.Error()) - } - if count != 3 { - dbt.Fatalf("Expected 3 matched rows, got %d", count) - } - }) -} - -func TestTLS(t *testing.T) { - tlsTest := func(dbt *DBTest) { - if err := dbt.db.Ping(); err != nil { - if err == ErrNoTLS { - dbt.Skip("server does not support TLS") - } else { - dbt.Fatalf("error on Ping: %s", err.Error()) - } - } - - rows := dbt.mustQuery("SHOW STATUS LIKE 'Ssl_cipher'") - - var variable, value *sql.RawBytes - for rows.Next() { - if err := rows.Scan(&variable, &value); err != nil { - dbt.Fatal(err.Error()) - } - - if value == nil { - dbt.Fatal("no Cipher") - } - } - } - - runTests(t, dsn+"&tls=skip-verify", tlsTest) - - // Verify that registering / using a custom cfg works - RegisterTLSConfig("custom-skip-verify", &tls.Config{ - InsecureSkipVerify: true, - }) - runTests(t, dsn+"&tls=custom-skip-verify", tlsTest) -} - -func TestReuseClosedConnection(t *testing.T) { - // this test does not use sql.database, it uses the driver directly - if !available { - t.Skipf("MySQL server not running on %s", netAddr) - } - - md := &MySQLDriver{} - conn, err := md.Open(dsn) - if err != nil { - t.Fatalf("error connecting: %s", err.Error()) - } - stmt, err := conn.Prepare("DO 1") - if err != nil { - t.Fatalf("error preparing statement: %s", err.Error()) - } - _, err = stmt.Exec(nil) - if err != nil { - t.Fatalf("error executing statement: %s", err.Error()) - } - err = conn.Close() - if err != nil { - t.Fatalf("error closing connection: %s", err.Error()) - } - - defer func() { - if err := recover(); err != nil { - t.Errorf("panic after reusing a closed connection: %v", err) - } - }() - _, err = stmt.Exec(nil) - if err != nil && err != driver.ErrBadConn { - t.Errorf("unexpected error '%s', expected '%s'", - err.Error(), driver.ErrBadConn.Error()) - } -} - -func TestCharset(t *testing.T) { - if !available { - t.Skipf("MySQL server not running on %s", netAddr) - } - - mustSetCharset := func(charsetParam, expected string) { - runTests(t, dsn+"&"+charsetParam, func(dbt *DBTest) { - rows := dbt.mustQuery("SELECT @@character_set_connection") - defer rows.Close() - - if !rows.Next() { - dbt.Fatalf("error getting connection charset: %s", rows.Err()) - } - - var got string - rows.Scan(&got) - - if got != expected { - dbt.Fatalf("expected connection charset %s but got %s", expected, got) - } - }) - } - - // non utf8 test - mustSetCharset("charset=ascii", "ascii") - - // when the first charset is invalid, use the second - mustSetCharset("charset=none,utf8", "utf8") - - // when the first charset is valid, use it - mustSetCharset("charset=ascii,utf8", "ascii") - mustSetCharset("charset=utf8,ascii", "utf8") -} - -func TestFailingCharset(t *testing.T) { - runTests(t, dsn+"&charset=none", func(dbt *DBTest) { - // run query to really establish connection... - _, err := dbt.db.Exec("SELECT 1") - if err == nil { - dbt.db.Close() - t.Fatalf("connection must not succeed without a valid charset") - } - }) -} - -func TestCollation(t *testing.T) { - if !available { - t.Skipf("MySQL server not running on %s", netAddr) - } - - defaultCollation := "utf8_general_ci" - testCollations := []string{ - "", // do not set - defaultCollation, // driver default - "latin1_general_ci", - "binary", - "utf8_unicode_ci", - "cp1257_bin", - } - - for _, collation := range testCollations { - var expected, tdsn string - if collation != "" { - tdsn = dsn + "&collation=" + collation - expected = collation - } else { - tdsn = dsn - expected = defaultCollation - } - - runTests(t, tdsn, func(dbt *DBTest) { - var got string - if err := dbt.db.QueryRow("SELECT @@collation_connection").Scan(&got); err != nil { - dbt.Fatal(err) - } - - if got != expected { - dbt.Fatalf("expected connection collation %s but got %s", expected, got) - } - }) - } -} - -func TestColumnsWithAlias(t *testing.T) { - runTests(t, dsn+"&columnsWithAlias=true", func(dbt *DBTest) { - rows := dbt.mustQuery("SELECT 1 AS A") - defer rows.Close() - cols, _ := rows.Columns() - if len(cols) != 1 { - t.Fatalf("expected 1 column, got %d", len(cols)) - } - if cols[0] != "A" { - t.Fatalf("expected column name \"A\", got \"%s\"", cols[0]) - } - rows.Close() - - rows = dbt.mustQuery("SELECT * FROM (SELECT 1 AS one) AS A") - cols, _ = rows.Columns() - if len(cols) != 1 { - t.Fatalf("expected 1 column, got %d", len(cols)) - } - if cols[0] != "A.one" { - t.Fatalf("expected column name \"A.one\", got \"%s\"", cols[0]) - } - }) -} - -func TestRawBytesResultExceedsBuffer(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - // defaultBufSize from buffer.go - expected := strings.Repeat("abc", defaultBufSize) - - rows := dbt.mustQuery("SELECT '" + expected + "'") - defer rows.Close() - if !rows.Next() { - dbt.Error("expected result, got none") - } - var result sql.RawBytes - rows.Scan(&result) - if expected != string(result) { - dbt.Error("result did not match expected value") - } - }) -} - -func TestTimezoneConversion(t *testing.T) { - zones := []string{"UTC", "US/Central", "US/Pacific", "Local"} - - // Regression test for timezone handling - tzTest := func(dbt *DBTest) { - // Create table - dbt.mustExec("CREATE TABLE test (ts TIMESTAMP)") - - // Insert local time into database (should be converted) - usCentral, _ := time.LoadLocation("US/Central") - reftime := time.Date(2014, 05, 30, 18, 03, 17, 0, time.UTC).In(usCentral) - dbt.mustExec("INSERT INTO test VALUE (?)", reftime) - - // Retrieve time from DB - rows := dbt.mustQuery("SELECT ts FROM test") - if !rows.Next() { - dbt.Fatal("did not get any rows out") - } - - var dbTime time.Time - err := rows.Scan(&dbTime) - if err != nil { - dbt.Fatal("Err", err) - } - - // Check that dates match - if reftime.Unix() != dbTime.Unix() { - dbt.Errorf("times do not match.\n") - dbt.Errorf(" Now(%v)=%v\n", usCentral, reftime) - dbt.Errorf(" Now(UTC)=%v\n", dbTime) - } - } - - for _, tz := range zones { - runTests(t, dsn+"&parseTime=true&loc="+url.QueryEscape(tz), tzTest) - } -} - -// Special cases - -func TestRowsClose(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - rows, err := dbt.db.Query("SELECT 1") - if err != nil { - dbt.Fatal(err) - } - - err = rows.Close() - if err != nil { - dbt.Fatal(err) - } - - if rows.Next() { - dbt.Fatal("unexpected row after rows.Close()") - } - - err = rows.Err() - if err != nil { - dbt.Fatal(err) - } - }) -} - -// dangling statements -// http://code.google.com/p/go/issues/detail?id=3865 -func TestCloseStmtBeforeRows(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - stmt, err := dbt.db.Prepare("SELECT 1") - if err != nil { - dbt.Fatal(err) - } - - rows, err := stmt.Query() - if err != nil { - stmt.Close() - dbt.Fatal(err) - } - defer rows.Close() - - err = stmt.Close() - if err != nil { - dbt.Fatal(err) - } - - if !rows.Next() { - dbt.Fatal("getting row failed") - } else { - err = rows.Err() - if err != nil { - dbt.Fatal(err) - } - - var out bool - err = rows.Scan(&out) - if err != nil { - dbt.Fatalf("error on rows.Scan(): %s", err.Error()) - } - if out != true { - dbt.Errorf("true != %t", out) - } - } - }) -} - -// It is valid to have multiple Rows for the same Stmt -// http://code.google.com/p/go/issues/detail?id=3734 -func TestStmtMultiRows(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - stmt, err := dbt.db.Prepare("SELECT 1 UNION SELECT 0") - if err != nil { - dbt.Fatal(err) - } - - rows1, err := stmt.Query() - if err != nil { - stmt.Close() - dbt.Fatal(err) - } - defer rows1.Close() - - rows2, err := stmt.Query() - if err != nil { - stmt.Close() - dbt.Fatal(err) - } - defer rows2.Close() - - var out bool - - // 1 - if !rows1.Next() { - dbt.Fatal("first rows1.Next failed") - } else { - err = rows1.Err() - if err != nil { - dbt.Fatal(err) - } - - err = rows1.Scan(&out) - if err != nil { - dbt.Fatalf("error on rows.Scan(): %s", err.Error()) - } - if out != true { - dbt.Errorf("true != %t", out) - } - } - - if !rows2.Next() { - dbt.Fatal("first rows2.Next failed") - } else { - err = rows2.Err() - if err != nil { - dbt.Fatal(err) - } - - err = rows2.Scan(&out) - if err != nil { - dbt.Fatalf("error on rows.Scan(): %s", err.Error()) - } - if out != true { - dbt.Errorf("true != %t", out) - } - } - - // 2 - if !rows1.Next() { - dbt.Fatal("second rows1.Next failed") - } else { - err = rows1.Err() - if err != nil { - dbt.Fatal(err) - } - - err = rows1.Scan(&out) - if err != nil { - dbt.Fatalf("error on rows.Scan(): %s", err.Error()) - } - if out != false { - dbt.Errorf("false != %t", out) - } - - if rows1.Next() { - dbt.Fatal("unexpected row on rows1") - } - err = rows1.Close() - if err != nil { - dbt.Fatal(err) - } - } - - if !rows2.Next() { - dbt.Fatal("second rows2.Next failed") - } else { - err = rows2.Err() - if err != nil { - dbt.Fatal(err) - } - - err = rows2.Scan(&out) - if err != nil { - dbt.Fatalf("error on rows.Scan(): %s", err.Error()) - } - if out != false { - dbt.Errorf("false != %t", out) - } - - if rows2.Next() { - dbt.Fatal("unexpected row on rows2") - } - err = rows2.Close() - if err != nil { - dbt.Fatal(err) - } - } - }) -} - -// Regression test for -// * more than 32 NULL parameters (issue 209) -// * more parameters than fit into the buffer (issue 201) -// * parameters * 64 > max_allowed_packet (issue 734) -func TestPreparedManyCols(t *testing.T) { - numParams := 65535 - runTests(t, dsn, func(dbt *DBTest) { - query := "SELECT ?" + strings.Repeat(",?", numParams-1) - stmt, err := dbt.db.Prepare(query) - if err != nil { - dbt.Fatal(err) - } - defer stmt.Close() - - // create more parameters than fit into the buffer - // which will take nil-values - params := make([]interface{}, numParams) - rows, err := stmt.Query(params...) - if err != nil { - dbt.Fatal(err) - } - rows.Close() - - // Create 0byte string which we can't send via STMT_LONG_DATA. - for i := 0; i < numParams; i++ { - params[i] = "" - } - rows, err = stmt.Query(params...) - if err != nil { - dbt.Fatal(err) - } - rows.Close() - }) -} - -func TestConcurrent(t *testing.T) { - if enabled, _ := readBool(os.Getenv("MYSQL_TEST_CONCURRENT")); !enabled { - t.Skip("MYSQL_TEST_CONCURRENT env var not set") - } - - runTests(t, dsn, func(dbt *DBTest) { - var max int - err := dbt.db.QueryRow("SELECT @@max_connections").Scan(&max) - if err != nil { - dbt.Fatalf("%s", err.Error()) - } - dbt.Logf("testing up to %d concurrent connections \r\n", max) - - var remaining, succeeded int32 = int32(max), 0 - - var wg sync.WaitGroup - wg.Add(max) - - var fatalError string - var once sync.Once - fatalf := func(s string, vals ...interface{}) { - once.Do(func() { - fatalError = fmt.Sprintf(s, vals...) - }) - } - - for i := 0; i < max; i++ { - go func(id int) { - defer wg.Done() - - tx, err := dbt.db.Begin() - atomic.AddInt32(&remaining, -1) - - if err != nil { - if err.Error() != "Error 1040: Too many connections" { - fatalf("error on conn %d: %s", id, err.Error()) - } - return - } - - // keep the connection busy until all connections are open - for remaining > 0 { - if _, err = tx.Exec("DO 1"); err != nil { - fatalf("error on conn %d: %s", id, err.Error()) - return - } - } - - if err = tx.Commit(); err != nil { - fatalf("error on conn %d: %s", id, err.Error()) - return - } - - // everything went fine with this connection - atomic.AddInt32(&succeeded, 1) - }(i) - } - - // wait until all conections are open - wg.Wait() - - if fatalError != "" { - dbt.Fatal(fatalError) - } - - dbt.Logf("reached %d concurrent connections\r\n", succeeded) - }) -} - -// Tests custom dial functions -func TestCustomDial(t *testing.T) { - if !available { - t.Skipf("MySQL server not running on %s", netAddr) - } - - // our custom dial function which justs wraps net.Dial here - RegisterDial("mydial", func(addr string) (net.Conn, error) { - return net.Dial(prot, addr) - }) - - db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@mydial(%s)/%s?timeout=30s", user, pass, addr, dbname)) - if err != nil { - t.Fatalf("error connecting: %s", err.Error()) - } - defer db.Close() - - if _, err = db.Exec("DO 1"); err != nil { - t.Fatalf("connection failed: %s", err.Error()) - } -} - -func TestSQLInjection(t *testing.T) { - createTest := func(arg string) func(dbt *DBTest) { - return func(dbt *DBTest) { - dbt.mustExec("CREATE TABLE test (v INTEGER)") - dbt.mustExec("INSERT INTO test VALUES (?)", 1) - - var v int - // NULL can't be equal to anything, the idea here is to inject query so it returns row - // This test verifies that escapeQuotes and escapeBackslash are working properly - err := dbt.db.QueryRow("SELECT v FROM test WHERE NULL = ?", arg).Scan(&v) - if err == sql.ErrNoRows { - return // success, sql injection failed - } else if err == nil { - dbt.Errorf("sql injection successful with arg: %s", arg) - } else { - dbt.Errorf("error running query with arg: %s; err: %s", arg, err.Error()) - } - } - } - - dsns := []string{ - dsn, - dsn + "&sql_mode='NO_BACKSLASH_ESCAPES'", - } - for _, testdsn := range dsns { - runTests(t, testdsn, createTest("1 OR 1=1")) - runTests(t, testdsn, createTest("' OR '1'='1")) - } -} - -// Test if inserted data is correctly retrieved after being escaped -func TestInsertRetrieveEscapedData(t *testing.T) { - testData := func(dbt *DBTest) { - dbt.mustExec("CREATE TABLE test (v VARCHAR(255))") - - // All sequences that are escaped by escapeQuotes and escapeBackslash - v := "foo \x00\n\r\x1a\"'\\" - dbt.mustExec("INSERT INTO test VALUES (?)", v) - - var out string - err := dbt.db.QueryRow("SELECT v FROM test").Scan(&out) - if err != nil { - dbt.Fatalf("%s", err.Error()) - } - - if out != v { - dbt.Errorf("%q != %q", out, v) - } - } - - dsns := []string{ - dsn, - dsn + "&sql_mode='NO_BACKSLASH_ESCAPES'", - } - for _, testdsn := range dsns { - runTests(t, testdsn, testData) - } -} - -func TestUnixSocketAuthFail(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - // Save the current logger so we can restore it. - oldLogger := errLog - - // Set a new logger so we can capture its output. - buffer := bytes.NewBuffer(make([]byte, 0, 64)) - newLogger := log.New(buffer, "prefix: ", 0) - SetLogger(newLogger) - - // Restore the logger. - defer SetLogger(oldLogger) - - // Make a new DSN that uses the MySQL socket file and a bad password, which - // we can make by simply appending any character to the real password. - badPass := pass + "x" - socket := "" - if prot == "unix" { - socket = addr - } else { - // Get socket file from MySQL. - err := dbt.db.QueryRow("SELECT @@socket").Scan(&socket) - if err != nil { - t.Fatalf("error on SELECT @@socket: %s", err.Error()) - } - } - t.Logf("socket: %s", socket) - badDSN := fmt.Sprintf("%s:%s@unix(%s)/%s?timeout=30s", user, badPass, socket, dbname) - db, err := sql.Open("mysql", badDSN) - if err != nil { - t.Fatalf("error connecting: %s", err.Error()) - } - defer db.Close() - - // Connect to MySQL for real. This will cause an auth failure. - err = db.Ping() - if err == nil { - t.Error("expected Ping() to return an error") - } - - // The driver should not log anything. - if actual := buffer.String(); actual != "" { - t.Errorf("expected no output, got %q", actual) - } - }) -} - -// See Issue #422 -func TestInterruptBySignal(t *testing.T) { - runTestsWithMultiStatement(t, dsn, func(dbt *DBTest) { - dbt.mustExec(` - DROP PROCEDURE IF EXISTS test_signal; - CREATE PROCEDURE test_signal(ret INT) - BEGIN - SELECT ret; - SIGNAL SQLSTATE - '45001' - SET - MESSAGE_TEXT = "an error", - MYSQL_ERRNO = 45001; - END - `) - defer dbt.mustExec("DROP PROCEDURE test_signal") - - var val int - - // text protocol - rows, err := dbt.db.Query("CALL test_signal(42)") - if err != nil { - dbt.Fatalf("error on text query: %s", err.Error()) - } - for rows.Next() { - if err := rows.Scan(&val); err != nil { - dbt.Error(err) - } else if val != 42 { - dbt.Errorf("expected val to be 42") - } - } - - // binary protocol - rows, err = dbt.db.Query("CALL test_signal(?)", 42) - if err != nil { - dbt.Fatalf("error on binary query: %s", err.Error()) - } - for rows.Next() { - if err := rows.Scan(&val); err != nil { - dbt.Error(err) - } else if val != 42 { - dbt.Errorf("expected val to be 42") - } - } - }) -} - -func TestColumnsReusesSlice(t *testing.T) { - rows := mysqlRows{ - rs: resultSet{ - columns: []mysqlField{ - { - tableName: "test", - name: "A", - }, - { - tableName: "test", - name: "B", - }, - }, - }, - } - - allocs := testing.AllocsPerRun(1, func() { - cols := rows.Columns() - - if len(cols) != 2 { - t.Fatalf("expected 2 columns, got %d", len(cols)) - } - }) - - if allocs != 0 { - t.Fatalf("expected 0 allocations, got %d", int(allocs)) - } - - if rows.rs.columnNames == nil { - t.Fatalf("expected columnNames to be set, got nil") - } -} - -func TestRejectReadOnly(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - // Create Table - dbt.mustExec("CREATE TABLE test (value BOOL)") - // Set the session to read-only. We didn't set the `rejectReadOnly` - // option, so any writes after this should fail. - _, err := dbt.db.Exec("SET SESSION TRANSACTION READ ONLY") - // Error 1193: Unknown system variable 'TRANSACTION' => skip test, - // MySQL server version is too old - maybeSkip(t, err, 1193) - if _, err := dbt.db.Exec("DROP TABLE test"); err == nil { - t.Fatalf("writing to DB in read-only session without " + - "rejectReadOnly did not error") - } - // Set the session back to read-write so runTests() can properly clean - // up the table `test`. - dbt.mustExec("SET SESSION TRANSACTION READ WRITE") - }) - - // Enable the `rejectReadOnly` option. - runTests(t, dsn+"&rejectReadOnly=true", func(dbt *DBTest) { - // Create Table - dbt.mustExec("CREATE TABLE test (value BOOL)") - // Set the session to read only. Any writes after this should error on - // a driver.ErrBadConn, and cause `database/sql` to initiate a new - // connection. - dbt.mustExec("SET SESSION TRANSACTION READ ONLY") - // This would error, but `database/sql` should automatically retry on a - // new connection which is not read-only, and eventually succeed. - dbt.mustExec("DROP TABLE test") - }) -} - -func TestPing(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - if err := dbt.db.Ping(); err != nil { - dbt.fail("Ping", "Ping", err) - } - }) -} - -// See Issue #799 -func TestEmptyPassword(t *testing.T) { - if !available { - t.Skipf("MySQL server not running on %s", netAddr) - } - - dsn := fmt.Sprintf("%s:%s@%s/%s?timeout=30s", user, "", netAddr, dbname) - db, err := sql.Open("mysql", dsn) - if err == nil { - defer db.Close() - err = db.Ping() - } - - if pass == "" { - if err != nil { - t.Fatal(err.Error()) - } - } else { - if err == nil { - t.Fatal("expected authentication error") - } - if !strings.HasPrefix(err.Error(), "Error 1045") { - t.Fatal(err.Error()) - } - } -} diff --git a/vendor/github.com/go-sql-driver/mysql/dsn_test.go b/vendor/github.com/go-sql-driver/mysql/dsn_test.go deleted file mode 100644 index 1cd09549..00000000 --- a/vendor/github.com/go-sql-driver/mysql/dsn_test.go +++ /dev/null @@ -1,331 +0,0 @@ -// Go MySQL Driver - A MySQL-Driver for Go's database/sql package -// -// Copyright 2016 The Go-MySQL-Driver Authors. All rights reserved. -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this file, -// You can obtain one at http://mozilla.org/MPL/2.0/. - -package mysql - -import ( - "crypto/tls" - "fmt" - "net/url" - "reflect" - "testing" - "time" -) - -var testDSNs = []struct { - in string - out *Config -}{{ - "username:password@protocol(address)/dbname?param=value", - &Config{User: "username", Passwd: "password", Net: "protocol", Addr: "address", DBName: "dbname", Params: map[string]string{"param": "value"}, Collation: "utf8_general_ci", Loc: time.UTC, MaxAllowedPacket: defaultMaxAllowedPacket, AllowNativePasswords: true}, -}, { - "username:password@protocol(address)/dbname?param=value&columnsWithAlias=true", - &Config{User: "username", Passwd: "password", Net: "protocol", Addr: "address", DBName: "dbname", Params: map[string]string{"param": "value"}, Collation: "utf8_general_ci", Loc: time.UTC, MaxAllowedPacket: defaultMaxAllowedPacket, AllowNativePasswords: true, ColumnsWithAlias: true}, -}, { - "username:password@protocol(address)/dbname?param=value&columnsWithAlias=true&multiStatements=true", - &Config{User: "username", Passwd: "password", Net: "protocol", Addr: "address", DBName: "dbname", Params: map[string]string{"param": "value"}, Collation: "utf8_general_ci", Loc: time.UTC, MaxAllowedPacket: defaultMaxAllowedPacket, AllowNativePasswords: true, ColumnsWithAlias: true, MultiStatements: true}, -}, { - "user@unix(/path/to/socket)/dbname?charset=utf8", - &Config{User: "user", Net: "unix", Addr: "/path/to/socket", DBName: "dbname", Params: map[string]string{"charset": "utf8"}, Collation: "utf8_general_ci", Loc: time.UTC, MaxAllowedPacket: defaultMaxAllowedPacket, AllowNativePasswords: true}, -}, { - "user:password@tcp(localhost:5555)/dbname?charset=utf8&tls=true", - &Config{User: "user", Passwd: "password", Net: "tcp", Addr: "localhost:5555", DBName: "dbname", Params: map[string]string{"charset": "utf8"}, Collation: "utf8_general_ci", Loc: time.UTC, MaxAllowedPacket: defaultMaxAllowedPacket, AllowNativePasswords: true, TLSConfig: "true"}, -}, { - "user:password@tcp(localhost:5555)/dbname?charset=utf8mb4,utf8&tls=skip-verify", - &Config{User: "user", Passwd: "password", Net: "tcp", Addr: "localhost:5555", DBName: "dbname", Params: map[string]string{"charset": "utf8mb4,utf8"}, Collation: "utf8_general_ci", Loc: time.UTC, MaxAllowedPacket: defaultMaxAllowedPacket, AllowNativePasswords: true, TLSConfig: "skip-verify"}, -}, { - "user:password@/dbname?loc=UTC&timeout=30s&readTimeout=1s&writeTimeout=1s&allowAllFiles=1&clientFoundRows=true&allowOldPasswords=TRUE&collation=utf8mb4_unicode_ci&maxAllowedPacket=16777216", - &Config{User: "user", Passwd: "password", Net: "tcp", Addr: "127.0.0.1:3306", DBName: "dbname", Collation: "utf8mb4_unicode_ci", Loc: time.UTC, AllowNativePasswords: true, Timeout: 30 * time.Second, ReadTimeout: time.Second, WriteTimeout: time.Second, AllowAllFiles: true, AllowOldPasswords: true, ClientFoundRows: true, MaxAllowedPacket: 16777216}, -}, { - "user:password@/dbname?allowNativePasswords=false&maxAllowedPacket=0", - &Config{User: "user", Passwd: "password", Net: "tcp", Addr: "127.0.0.1:3306", DBName: "dbname", Collation: "utf8_general_ci", Loc: time.UTC, MaxAllowedPacket: 0, AllowNativePasswords: false}, -}, { - "user:p@ss(word)@tcp([de:ad:be:ef::ca:fe]:80)/dbname?loc=Local", - &Config{User: "user", Passwd: "p@ss(word)", Net: "tcp", Addr: "[de:ad:be:ef::ca:fe]:80", DBName: "dbname", Collation: "utf8_general_ci", Loc: time.Local, MaxAllowedPacket: defaultMaxAllowedPacket, AllowNativePasswords: true}, -}, { - "/dbname", - &Config{Net: "tcp", Addr: "127.0.0.1:3306", DBName: "dbname", Collation: "utf8_general_ci", Loc: time.UTC, MaxAllowedPacket: defaultMaxAllowedPacket, AllowNativePasswords: true}, -}, { - "@/", - &Config{Net: "tcp", Addr: "127.0.0.1:3306", Collation: "utf8_general_ci", Loc: time.UTC, MaxAllowedPacket: defaultMaxAllowedPacket, AllowNativePasswords: true}, -}, { - "/", - &Config{Net: "tcp", Addr: "127.0.0.1:3306", Collation: "utf8_general_ci", Loc: time.UTC, MaxAllowedPacket: defaultMaxAllowedPacket, AllowNativePasswords: true}, -}, { - "", - &Config{Net: "tcp", Addr: "127.0.0.1:3306", Collation: "utf8_general_ci", Loc: time.UTC, MaxAllowedPacket: defaultMaxAllowedPacket, AllowNativePasswords: true}, -}, { - "user:p@/ssword@/", - &Config{User: "user", Passwd: "p@/ssword", Net: "tcp", Addr: "127.0.0.1:3306", Collation: "utf8_general_ci", Loc: time.UTC, MaxAllowedPacket: defaultMaxAllowedPacket, AllowNativePasswords: true}, -}, { - "unix/?arg=%2Fsome%2Fpath.ext", - &Config{Net: "unix", Addr: "/tmp/mysql.sock", Params: map[string]string{"arg": "/some/path.ext"}, Collation: "utf8_general_ci", Loc: time.UTC, MaxAllowedPacket: defaultMaxAllowedPacket, AllowNativePasswords: true}, -}, { - "tcp(127.0.0.1)/dbname", - &Config{Net: "tcp", Addr: "127.0.0.1:3306", DBName: "dbname", Collation: "utf8_general_ci", Loc: time.UTC, MaxAllowedPacket: defaultMaxAllowedPacket, AllowNativePasswords: true}, -}, { - "tcp(de:ad:be:ef::ca:fe)/dbname", - &Config{Net: "tcp", Addr: "[de:ad:be:ef::ca:fe]:3306", DBName: "dbname", Collation: "utf8_general_ci", Loc: time.UTC, MaxAllowedPacket: defaultMaxAllowedPacket, AllowNativePasswords: true}, -}, -} - -func TestDSNParser(t *testing.T) { - for i, tst := range testDSNs { - cfg, err := ParseDSN(tst.in) - if err != nil { - t.Error(err.Error()) - } - - // pointer not static - cfg.tls = nil - - if !reflect.DeepEqual(cfg, tst.out) { - t.Errorf("%d. ParseDSN(%q) mismatch:\ngot %+v\nwant %+v", i, tst.in, cfg, tst.out) - } - } -} - -func TestDSNParserInvalid(t *testing.T) { - var invalidDSNs = []string{ - "@net(addr/", // no closing brace - "@tcp(/", // no closing brace - "tcp(/", // no closing brace - "(/", // no closing brace - "net(addr)//", // unescaped - "User:pass@tcp(1.2.3.4:3306)", // no trailing slash - "net()/", // unknown default addr - //"/dbname?arg=/some/unescaped/path", - } - - for i, tst := range invalidDSNs { - if _, err := ParseDSN(tst); err == nil { - t.Errorf("invalid DSN #%d. (%s) didn't error!", i, tst) - } - } -} - -func TestDSNReformat(t *testing.T) { - for i, tst := range testDSNs { - dsn1 := tst.in - cfg1, err := ParseDSN(dsn1) - if err != nil { - t.Error(err.Error()) - continue - } - cfg1.tls = nil // pointer not static - res1 := fmt.Sprintf("%+v", cfg1) - - dsn2 := cfg1.FormatDSN() - cfg2, err := ParseDSN(dsn2) - if err != nil { - t.Error(err.Error()) - continue - } - cfg2.tls = nil // pointer not static - res2 := fmt.Sprintf("%+v", cfg2) - - if res1 != res2 { - t.Errorf("%d. %q does not match %q", i, res2, res1) - } - } -} - -func TestDSNServerPubKey(t *testing.T) { - baseDSN := "User:password@tcp(localhost:5555)/dbname?serverPubKey=" - - RegisterServerPubKey("testKey", testPubKeyRSA) - defer DeregisterServerPubKey("testKey") - - tst := baseDSN + "testKey" - cfg, err := ParseDSN(tst) - if err != nil { - t.Error(err.Error()) - } - - if cfg.ServerPubKey != "testKey" { - t.Errorf("unexpected cfg.ServerPubKey value: %v", cfg.ServerPubKey) - } - if cfg.pubKey != testPubKeyRSA { - t.Error("pub key pointer doesn't match") - } - - // Key is missing - tst = baseDSN + "invalid_name" - cfg, err = ParseDSN(tst) - if err == nil { - t.Errorf("invalid name in DSN (%s) but did not error. Got config: %#v", tst, cfg) - } -} - -func TestDSNServerPubKeyQueryEscape(t *testing.T) { - const name = "&%!:" - dsn := "User:password@tcp(localhost:5555)/dbname?serverPubKey=" + url.QueryEscape(name) - - RegisterServerPubKey(name, testPubKeyRSA) - defer DeregisterServerPubKey(name) - - cfg, err := ParseDSN(dsn) - if err != nil { - t.Error(err.Error()) - } - - if cfg.pubKey != testPubKeyRSA { - t.Error("pub key pointer doesn't match") - } -} - -func TestDSNWithCustomTLS(t *testing.T) { - baseDSN := "User:password@tcp(localhost:5555)/dbname?tls=" - tlsCfg := tls.Config{} - - RegisterTLSConfig("utils_test", &tlsCfg) - defer DeregisterTLSConfig("utils_test") - - // Custom TLS is missing - tst := baseDSN + "invalid_tls" - cfg, err := ParseDSN(tst) - if err == nil { - t.Errorf("invalid custom TLS in DSN (%s) but did not error. Got config: %#v", tst, cfg) - } - - tst = baseDSN + "utils_test" - - // Custom TLS with a server name - name := "foohost" - tlsCfg.ServerName = name - cfg, err = ParseDSN(tst) - - if err != nil { - t.Error(err.Error()) - } else if cfg.tls.ServerName != name { - t.Errorf("did not get the correct TLS ServerName (%s) parsing DSN (%s).", name, tst) - } - - // Custom TLS without a server name - name = "localhost" - tlsCfg.ServerName = "" - cfg, err = ParseDSN(tst) - - if err != nil { - t.Error(err.Error()) - } else if cfg.tls.ServerName != name { - t.Errorf("did not get the correct ServerName (%s) parsing DSN (%s).", name, tst) - } else if tlsCfg.ServerName != "" { - t.Errorf("tlsCfg was mutated ServerName (%s) should be empty parsing DSN (%s).", name, tst) - } -} - -func TestDSNTLSConfig(t *testing.T) { - expectedServerName := "example.com" - dsn := "tcp(example.com:1234)/?tls=true" - - cfg, err := ParseDSN(dsn) - if err != nil { - t.Error(err.Error()) - } - if cfg.tls == nil { - t.Error("cfg.tls should not be nil") - } - if cfg.tls.ServerName != expectedServerName { - t.Errorf("cfg.tls.ServerName should be %q, got %q (host with port)", expectedServerName, cfg.tls.ServerName) - } - - dsn = "tcp(example.com)/?tls=true" - cfg, err = ParseDSN(dsn) - if err != nil { - t.Error(err.Error()) - } - if cfg.tls == nil { - t.Error("cfg.tls should not be nil") - } - if cfg.tls.ServerName != expectedServerName { - t.Errorf("cfg.tls.ServerName should be %q, got %q (host without port)", expectedServerName, cfg.tls.ServerName) - } -} - -func TestDSNWithCustomTLSQueryEscape(t *testing.T) { - const configKey = "&%!:" - dsn := "User:password@tcp(localhost:5555)/dbname?tls=" + url.QueryEscape(configKey) - name := "foohost" - tlsCfg := tls.Config{ServerName: name} - - RegisterTLSConfig(configKey, &tlsCfg) - defer DeregisterTLSConfig(configKey) - - cfg, err := ParseDSN(dsn) - - if err != nil { - t.Error(err.Error()) - } else if cfg.tls.ServerName != name { - t.Errorf("did not get the correct TLS ServerName (%s) parsing DSN (%s).", name, dsn) - } -} - -func TestDSNUnsafeCollation(t *testing.T) { - _, err := ParseDSN("/dbname?collation=gbk_chinese_ci&interpolateParams=true") - if err != errInvalidDSNUnsafeCollation { - t.Errorf("expected %v, got %v", errInvalidDSNUnsafeCollation, err) - } - - _, err = ParseDSN("/dbname?collation=gbk_chinese_ci&interpolateParams=false") - if err != nil { - t.Errorf("expected %v, got %v", nil, err) - } - - _, err = ParseDSN("/dbname?collation=gbk_chinese_ci") - if err != nil { - t.Errorf("expected %v, got %v", nil, err) - } - - _, err = ParseDSN("/dbname?collation=ascii_bin&interpolateParams=true") - if err != nil { - t.Errorf("expected %v, got %v", nil, err) - } - - _, err = ParseDSN("/dbname?collation=latin1_german1_ci&interpolateParams=true") - if err != nil { - t.Errorf("expected %v, got %v", nil, err) - } - - _, err = ParseDSN("/dbname?collation=utf8_general_ci&interpolateParams=true") - if err != nil { - t.Errorf("expected %v, got %v", nil, err) - } - - _, err = ParseDSN("/dbname?collation=utf8mb4_general_ci&interpolateParams=true") - if err != nil { - t.Errorf("expected %v, got %v", nil, err) - } -} - -func TestParamsAreSorted(t *testing.T) { - expected := "/dbname?interpolateParams=true&foobar=baz&quux=loo" - cfg := NewConfig() - cfg.DBName = "dbname" - cfg.InterpolateParams = true - cfg.Params = map[string]string{ - "quux": "loo", - "foobar": "baz", - } - actual := cfg.FormatDSN() - if actual != expected { - t.Errorf("generic Config.Params were not sorted: want %#v, got %#v", expected, actual) - } -} - -func BenchmarkParseDSN(b *testing.B) { - b.ReportAllocs() - - for i := 0; i < b.N; i++ { - for _, tst := range testDSNs { - if _, err := ParseDSN(tst.in); err != nil { - b.Error(err.Error()) - } - } - } -} diff --git a/vendor/github.com/go-sql-driver/mysql/errors_test.go b/vendor/github.com/go-sql-driver/mysql/errors_test.go deleted file mode 100644 index 96f9126d..00000000 --- a/vendor/github.com/go-sql-driver/mysql/errors_test.go +++ /dev/null @@ -1,42 +0,0 @@ -// Go MySQL Driver - A MySQL-Driver for Go's database/sql package -// -// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved. -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this file, -// You can obtain one at http://mozilla.org/MPL/2.0/. - -package mysql - -import ( - "bytes" - "log" - "testing" -) - -func TestErrorsSetLogger(t *testing.T) { - previous := errLog - defer func() { - errLog = previous - }() - - // set up logger - const expected = "prefix: test\n" - buffer := bytes.NewBuffer(make([]byte, 0, 64)) - logger := log.New(buffer, "prefix: ", 0) - - // print - SetLogger(logger) - errLog.Print("test") - - // check result - if actual := buffer.String(); actual != expected { - t.Errorf("expected %q, got %q", expected, actual) - } -} - -func TestErrorsStrictIgnoreNotes(t *testing.T) { - runTests(t, dsn+"&sql_notes=false", func(dbt *DBTest) { - dbt.mustExec("DROP TABLE IF EXISTS does_not_exist") - }) -} diff --git a/vendor/github.com/go-sql-driver/mysql/packets_test.go b/vendor/github.com/go-sql-driver/mysql/packets_test.go deleted file mode 100644 index b61e4dbf..00000000 --- a/vendor/github.com/go-sql-driver/mysql/packets_test.go +++ /dev/null @@ -1,336 +0,0 @@ -// Go MySQL Driver - A MySQL-Driver for Go's database/sql package -// -// Copyright 2016 The Go-MySQL-Driver Authors. All rights reserved. -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this file, -// You can obtain one at http://mozilla.org/MPL/2.0/. - -package mysql - -import ( - "bytes" - "errors" - "net" - "testing" - "time" -) - -var ( - errConnClosed = errors.New("connection is closed") - errConnTooManyReads = errors.New("too many reads") - errConnTooManyWrites = errors.New("too many writes") -) - -// struct to mock a net.Conn for testing purposes -type mockConn struct { - laddr net.Addr - raddr net.Addr - data []byte - written []byte - queuedReplies [][]byte - closed bool - read int - reads int - writes int - maxReads int - maxWrites int -} - -func (m *mockConn) Read(b []byte) (n int, err error) { - if m.closed { - return 0, errConnClosed - } - - m.reads++ - if m.maxReads > 0 && m.reads > m.maxReads { - return 0, errConnTooManyReads - } - - n = copy(b, m.data) - m.read += n - m.data = m.data[n:] - return -} -func (m *mockConn) Write(b []byte) (n int, err error) { - if m.closed { - return 0, errConnClosed - } - - m.writes++ - if m.maxWrites > 0 && m.writes > m.maxWrites { - return 0, errConnTooManyWrites - } - - n = len(b) - m.written = append(m.written, b...) - - if n > 0 && len(m.queuedReplies) > 0 { - m.data = m.queuedReplies[0] - m.queuedReplies = m.queuedReplies[1:] - } - return -} -func (m *mockConn) Close() error { - m.closed = true - return nil -} -func (m *mockConn) LocalAddr() net.Addr { - return m.laddr -} -func (m *mockConn) RemoteAddr() net.Addr { - return m.raddr -} -func (m *mockConn) SetDeadline(t time.Time) error { - return nil -} -func (m *mockConn) SetReadDeadline(t time.Time) error { - return nil -} -func (m *mockConn) SetWriteDeadline(t time.Time) error { - return nil -} - -// make sure mockConn implements the net.Conn interface -var _ net.Conn = new(mockConn) - -func newRWMockConn(sequence uint8) (*mockConn, *mysqlConn) { - conn := new(mockConn) - mc := &mysqlConn{ - buf: newBuffer(conn), - cfg: NewConfig(), - netConn: conn, - closech: make(chan struct{}), - maxAllowedPacket: defaultMaxAllowedPacket, - sequence: sequence, - } - return conn, mc -} - -func TestReadPacketSingleByte(t *testing.T) { - conn := new(mockConn) - mc := &mysqlConn{ - buf: newBuffer(conn), - } - - conn.data = []byte{0x01, 0x00, 0x00, 0x00, 0xff} - conn.maxReads = 1 - packet, err := mc.readPacket() - if err != nil { - t.Fatal(err) - } - if len(packet) != 1 { - t.Fatalf("unexpected packet length: expected %d, got %d", 1, len(packet)) - } - if packet[0] != 0xff { - t.Fatalf("unexpected packet content: expected %x, got %x", 0xff, packet[0]) - } -} - -func TestReadPacketWrongSequenceID(t *testing.T) { - conn := new(mockConn) - mc := &mysqlConn{ - buf: newBuffer(conn), - } - - // too low sequence id - conn.data = []byte{0x01, 0x00, 0x00, 0x00, 0xff} - conn.maxReads = 1 - mc.sequence = 1 - _, err := mc.readPacket() - if err != ErrPktSync { - t.Errorf("expected ErrPktSync, got %v", err) - } - - // reset - conn.reads = 0 - mc.sequence = 0 - mc.buf = newBuffer(conn) - - // too high sequence id - conn.data = []byte{0x01, 0x00, 0x00, 0x42, 0xff} - _, err = mc.readPacket() - if err != ErrPktSyncMul { - t.Errorf("expected ErrPktSyncMul, got %v", err) - } -} - -func TestReadPacketSplit(t *testing.T) { - conn := new(mockConn) - mc := &mysqlConn{ - buf: newBuffer(conn), - } - - data := make([]byte, maxPacketSize*2+4*3) - const pkt2ofs = maxPacketSize + 4 - const pkt3ofs = 2 * (maxPacketSize + 4) - - // case 1: payload has length maxPacketSize - data = data[:pkt2ofs+4] - - // 1st packet has maxPacketSize length and sequence id 0 - // ff ff ff 00 ... - data[0] = 0xff - data[1] = 0xff - data[2] = 0xff - - // mark the payload start and end of 1st packet so that we can check if the - // content was correctly appended - data[4] = 0x11 - data[maxPacketSize+3] = 0x22 - - // 2nd packet has payload length 0 and squence id 1 - // 00 00 00 01 - data[pkt2ofs+3] = 0x01 - - conn.data = data - conn.maxReads = 3 - packet, err := mc.readPacket() - if err != nil { - t.Fatal(err) - } - if len(packet) != maxPacketSize { - t.Fatalf("unexpected packet length: expected %d, got %d", maxPacketSize, len(packet)) - } - if packet[0] != 0x11 { - t.Fatalf("unexpected payload start: expected %x, got %x", 0x11, packet[0]) - } - if packet[maxPacketSize-1] != 0x22 { - t.Fatalf("unexpected payload end: expected %x, got %x", 0x22, packet[maxPacketSize-1]) - } - - // case 2: payload has length which is a multiple of maxPacketSize - data = data[:cap(data)] - - // 2nd packet now has maxPacketSize length - data[pkt2ofs] = 0xff - data[pkt2ofs+1] = 0xff - data[pkt2ofs+2] = 0xff - - // mark the payload start and end of the 2nd packet - data[pkt2ofs+4] = 0x33 - data[pkt2ofs+maxPacketSize+3] = 0x44 - - // 3rd packet has payload length 0 and squence id 2 - // 00 00 00 02 - data[pkt3ofs+3] = 0x02 - - conn.data = data - conn.reads = 0 - conn.maxReads = 5 - mc.sequence = 0 - packet, err = mc.readPacket() - if err != nil { - t.Fatal(err) - } - if len(packet) != 2*maxPacketSize { - t.Fatalf("unexpected packet length: expected %d, got %d", 2*maxPacketSize, len(packet)) - } - if packet[0] != 0x11 { - t.Fatalf("unexpected payload start: expected %x, got %x", 0x11, packet[0]) - } - if packet[2*maxPacketSize-1] != 0x44 { - t.Fatalf("unexpected payload end: expected %x, got %x", 0x44, packet[2*maxPacketSize-1]) - } - - // case 3: payload has a length larger maxPacketSize, which is not an exact - // multiple of it - data = data[:pkt2ofs+4+42] - data[pkt2ofs] = 0x2a - data[pkt2ofs+1] = 0x00 - data[pkt2ofs+2] = 0x00 - data[pkt2ofs+4+41] = 0x44 - - conn.data = data - conn.reads = 0 - conn.maxReads = 4 - mc.sequence = 0 - packet, err = mc.readPacket() - if err != nil { - t.Fatal(err) - } - if len(packet) != maxPacketSize+42 { - t.Fatalf("unexpected packet length: expected %d, got %d", maxPacketSize+42, len(packet)) - } - if packet[0] != 0x11 { - t.Fatalf("unexpected payload start: expected %x, got %x", 0x11, packet[0]) - } - if packet[maxPacketSize+41] != 0x44 { - t.Fatalf("unexpected payload end: expected %x, got %x", 0x44, packet[maxPacketSize+41]) - } -} - -func TestReadPacketFail(t *testing.T) { - conn := new(mockConn) - mc := &mysqlConn{ - buf: newBuffer(conn), - closech: make(chan struct{}), - } - - // illegal empty (stand-alone) packet - conn.data = []byte{0x00, 0x00, 0x00, 0x00} - conn.maxReads = 1 - _, err := mc.readPacket() - if err != ErrInvalidConn { - t.Errorf("expected ErrInvalidConn, got %v", err) - } - - // reset - conn.reads = 0 - mc.sequence = 0 - mc.buf = newBuffer(conn) - - // fail to read header - conn.closed = true - _, err = mc.readPacket() - if err != ErrInvalidConn { - t.Errorf("expected ErrInvalidConn, got %v", err) - } - - // reset - conn.closed = false - conn.reads = 0 - mc.sequence = 0 - mc.buf = newBuffer(conn) - - // fail to read body - conn.maxReads = 1 - _, err = mc.readPacket() - if err != ErrInvalidConn { - t.Errorf("expected ErrInvalidConn, got %v", err) - } -} - -// https://github.com/go-sql-driver/mysql/pull/801 -// not-NUL terminated plugin_name in init packet -func TestRegression801(t *testing.T) { - conn := new(mockConn) - mc := &mysqlConn{ - buf: newBuffer(conn), - cfg: new(Config), - sequence: 42, - closech: make(chan struct{}), - } - - conn.data = []byte{72, 0, 0, 42, 10, 53, 46, 53, 46, 56, 0, 165, 0, 0, 0, - 60, 70, 63, 58, 68, 104, 34, 97, 0, 223, 247, 33, 2, 0, 15, 128, 21, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 120, 114, 47, 85, 75, 109, 99, 51, 77, - 50, 64, 0, 109, 121, 115, 113, 108, 95, 110, 97, 116, 105, 118, 101, 95, - 112, 97, 115, 115, 119, 111, 114, 100} - conn.maxReads = 1 - - authData, pluginName, err := mc.readHandshakePacket() - if err != nil { - t.Fatalf("got error: %v", err) - } - - if pluginName != "mysql_native_password" { - t.Errorf("expected plugin name 'mysql_native_password', got '%s'", pluginName) - } - - expectedAuthData := []byte{60, 70, 63, 58, 68, 104, 34, 97, 98, 120, 114, - 47, 85, 75, 109, 99, 51, 77, 50, 64} - if !bytes.Equal(authData, expectedAuthData) { - t.Errorf("expected authData '%v', got '%v'", expectedAuthData, authData) - } -} diff --git a/vendor/github.com/go-sql-driver/mysql/statement_test.go b/vendor/github.com/go-sql-driver/mysql/statement_test.go deleted file mode 100644 index 98a6c193..00000000 --- a/vendor/github.com/go-sql-driver/mysql/statement_test.go +++ /dev/null @@ -1,126 +0,0 @@ -// Go MySQL Driver - A MySQL-Driver for Go's database/sql package -// -// Copyright 2017 The Go-MySQL-Driver Authors. All rights reserved. -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this file, -// You can obtain one at http://mozilla.org/MPL/2.0/. - -package mysql - -import ( - "bytes" - "testing" -) - -func TestConvertDerivedString(t *testing.T) { - type derived string - - output, err := converter{}.ConvertValue(derived("value")) - if err != nil { - t.Fatal("Derived string type not convertible", err) - } - - if output != "value" { - t.Fatalf("Derived string type not converted, got %#v %T", output, output) - } -} - -func TestConvertDerivedByteSlice(t *testing.T) { - type derived []uint8 - - output, err := converter{}.ConvertValue(derived("value")) - if err != nil { - t.Fatal("Byte slice not convertible", err) - } - - if bytes.Compare(output.([]byte), []byte("value")) != 0 { - t.Fatalf("Byte slice not converted, got %#v %T", output, output) - } -} - -func TestConvertDerivedUnsupportedSlice(t *testing.T) { - type derived []int - - _, err := converter{}.ConvertValue(derived{1}) - if err == nil || err.Error() != "unsupported type mysql.derived, a slice of int" { - t.Fatal("Unexpected error", err) - } -} - -func TestConvertDerivedBool(t *testing.T) { - type derived bool - - output, err := converter{}.ConvertValue(derived(true)) - if err != nil { - t.Fatal("Derived bool type not convertible", err) - } - - if output != true { - t.Fatalf("Derived bool type not converted, got %#v %T", output, output) - } -} - -func TestConvertPointer(t *testing.T) { - str := "value" - - output, err := converter{}.ConvertValue(&str) - if err != nil { - t.Fatal("Pointer type not convertible", err) - } - - if output != "value" { - t.Fatalf("Pointer type not converted, got %#v %T", output, output) - } -} - -func TestConvertSignedIntegers(t *testing.T) { - values := []interface{}{ - int8(-42), - int16(-42), - int32(-42), - int64(-42), - int(-42), - } - - for _, value := range values { - output, err := converter{}.ConvertValue(value) - if err != nil { - t.Fatalf("%T type not convertible %s", value, err) - } - - if output != int64(-42) { - t.Fatalf("%T type not converted, got %#v %T", value, output, output) - } - } -} - -func TestConvertUnsignedIntegers(t *testing.T) { - values := []interface{}{ - uint8(42), - uint16(42), - uint32(42), - uint64(42), - uint(42), - } - - for _, value := range values { - output, err := converter{}.ConvertValue(value) - if err != nil { - t.Fatalf("%T type not convertible %s", value, err) - } - - if output != int64(42) { - t.Fatalf("%T type not converted, got %#v %T", value, output, output) - } - } - - output, err := converter{}.ConvertValue(^uint64(0)) - if err != nil { - t.Fatal("uint64 high-bit not convertible", err) - } - - if output != "18446744073709551615" { - t.Fatalf("uint64 high-bit not converted, got %#v %T", output, output) - } -} diff --git a/vendor/github.com/go-sql-driver/mysql/utils_go18_test.go b/vendor/github.com/go-sql-driver/mysql/utils_go18_test.go deleted file mode 100644 index f63dbecc..00000000 --- a/vendor/github.com/go-sql-driver/mysql/utils_go18_test.go +++ /dev/null @@ -1,57 +0,0 @@ -// Go MySQL Driver - A MySQL-Driver for Go's database/sql package -// -// Copyright 2017 The Go-MySQL-Driver Authors. All rights reserved. -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this file, -// You can obtain one at http://mozilla.org/MPL/2.0/. - -// +build go1.8 - -package mysql - -import ( - "database/sql" - "database/sql/driver" - "testing" -) - -func TestIsolationLevelMapping(t *testing.T) { - data := []struct { - level driver.IsolationLevel - expected string - }{ - { - level: driver.IsolationLevel(sql.LevelReadCommitted), - expected: "READ COMMITTED", - }, - { - level: driver.IsolationLevel(sql.LevelRepeatableRead), - expected: "REPEATABLE READ", - }, - { - level: driver.IsolationLevel(sql.LevelReadUncommitted), - expected: "READ UNCOMMITTED", - }, - { - level: driver.IsolationLevel(sql.LevelSerializable), - expected: "SERIALIZABLE", - }, - } - - for i, td := range data { - if actual, err := mapIsolationLevel(td.level); actual != td.expected || err != nil { - t.Fatal(i, td.expected, actual, err) - } - } - - // check unsupported mapping - expectedErr := "mysql: unsupported isolation level: 7" - actual, err := mapIsolationLevel(driver.IsolationLevel(sql.LevelLinearizable)) - if actual != "" || err == nil { - t.Fatal("Expected error on unsupported isolation level") - } - if err.Error() != expectedErr { - t.Fatalf("Expected error to be %q, got %q", expectedErr, err) - } -} diff --git a/vendor/github.com/go-sql-driver/mysql/utils_test.go b/vendor/github.com/go-sql-driver/mysql/utils_test.go deleted file mode 100644 index 4a72a108..00000000 --- a/vendor/github.com/go-sql-driver/mysql/utils_test.go +++ /dev/null @@ -1,292 +0,0 @@ -// Go MySQL Driver - A MySQL-Driver for Go's database/sql package -// -// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved. -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this file, -// You can obtain one at http://mozilla.org/MPL/2.0/. - -package mysql - -import ( - "bytes" - "encoding/binary" - "testing" - "time" -) - -func TestScanNullTime(t *testing.T) { - var scanTests = []struct { - in interface{} - error bool - valid bool - time time.Time - }{ - {tDate, false, true, tDate}, - {sDate, false, true, tDate}, - {[]byte(sDate), false, true, tDate}, - {tDateTime, false, true, tDateTime}, - {sDateTime, false, true, tDateTime}, - {[]byte(sDateTime), false, true, tDateTime}, - {tDate0, false, true, tDate0}, - {sDate0, false, true, tDate0}, - {[]byte(sDate0), false, true, tDate0}, - {sDateTime0, false, true, tDate0}, - {[]byte(sDateTime0), false, true, tDate0}, - {"", true, false, tDate0}, - {"1234", true, false, tDate0}, - {0, true, false, tDate0}, - } - - var nt = NullTime{} - var err error - - for _, tst := range scanTests { - err = nt.Scan(tst.in) - if (err != nil) != tst.error { - t.Errorf("%v: expected error status %t, got %t", tst.in, tst.error, (err != nil)) - } - if nt.Valid != tst.valid { - t.Errorf("%v: expected valid status %t, got %t", tst.in, tst.valid, nt.Valid) - } - if nt.Time != tst.time { - t.Errorf("%v: expected time %v, got %v", tst.in, tst.time, nt.Time) - } - } -} - -func TestLengthEncodedInteger(t *testing.T) { - var integerTests = []struct { - num uint64 - encoded []byte - }{ - {0x0000000000000000, []byte{0x00}}, - {0x0000000000000012, []byte{0x12}}, - {0x00000000000000fa, []byte{0xfa}}, - {0x0000000000000100, []byte{0xfc, 0x00, 0x01}}, - {0x0000000000001234, []byte{0xfc, 0x34, 0x12}}, - {0x000000000000ffff, []byte{0xfc, 0xff, 0xff}}, - {0x0000000000010000, []byte{0xfd, 0x00, 0x00, 0x01}}, - {0x0000000000123456, []byte{0xfd, 0x56, 0x34, 0x12}}, - {0x0000000000ffffff, []byte{0xfd, 0xff, 0xff, 0xff}}, - {0x0000000001000000, []byte{0xfe, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}}, - {0x123456789abcdef0, []byte{0xfe, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12}}, - {0xffffffffffffffff, []byte{0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, - } - - for _, tst := range integerTests { - num, isNull, numLen := readLengthEncodedInteger(tst.encoded) - if isNull { - t.Errorf("%x: expected %d, got NULL", tst.encoded, tst.num) - } - if num != tst.num { - t.Errorf("%x: expected %d, got %d", tst.encoded, tst.num, num) - } - if numLen != len(tst.encoded) { - t.Errorf("%x: expected size %d, got %d", tst.encoded, len(tst.encoded), numLen) - } - encoded := appendLengthEncodedInteger(nil, num) - if !bytes.Equal(encoded, tst.encoded) { - t.Errorf("%v: expected %x, got %x", num, tst.encoded, encoded) - } - } -} - -func TestFormatBinaryDateTime(t *testing.T) { - rawDate := [11]byte{} - binary.LittleEndian.PutUint16(rawDate[:2], 1978) // years - rawDate[2] = 12 // months - rawDate[3] = 30 // days - rawDate[4] = 15 // hours - rawDate[5] = 46 // minutes - rawDate[6] = 23 // seconds - binary.LittleEndian.PutUint32(rawDate[7:], 987654) // microseconds - expect := func(expected string, inlen, outlen uint8) { - actual, _ := formatBinaryDateTime(rawDate[:inlen], outlen) - bytes, ok := actual.([]byte) - if !ok { - t.Errorf("formatBinaryDateTime must return []byte, was %T", actual) - } - if string(bytes) != expected { - t.Errorf( - "expected %q, got %q for length in %d, out %d", - expected, actual, inlen, outlen, - ) - } - } - expect("0000-00-00", 0, 10) - expect("0000-00-00 00:00:00", 0, 19) - expect("1978-12-30", 4, 10) - expect("1978-12-30 15:46:23", 7, 19) - expect("1978-12-30 15:46:23.987654", 11, 26) -} - -func TestFormatBinaryTime(t *testing.T) { - expect := func(expected string, src []byte, outlen uint8) { - actual, _ := formatBinaryTime(src, outlen) - bytes, ok := actual.([]byte) - if !ok { - t.Errorf("formatBinaryDateTime must return []byte, was %T", actual) - } - if string(bytes) != expected { - t.Errorf( - "expected %q, got %q for src=%q and outlen=%d", - expected, actual, src, outlen) - } - } - - // binary format: - // sign (0: positive, 1: negative), days(4), hours, minutes, seconds, micro(4) - - // Zeros - expect("00:00:00", []byte{}, 8) - expect("00:00:00.0", []byte{}, 10) - expect("00:00:00.000000", []byte{}, 15) - - // Without micro(4) - expect("12:34:56", []byte{0, 0, 0, 0, 0, 12, 34, 56}, 8) - expect("-12:34:56", []byte{1, 0, 0, 0, 0, 12, 34, 56}, 8) - expect("12:34:56.00", []byte{0, 0, 0, 0, 0, 12, 34, 56}, 11) - expect("24:34:56", []byte{0, 1, 0, 0, 0, 0, 34, 56}, 8) - expect("-99:34:56", []byte{1, 4, 0, 0, 0, 3, 34, 56}, 8) - expect("103079215103:34:56", []byte{0, 255, 255, 255, 255, 23, 34, 56}, 8) - - // With micro(4) - expect("12:34:56.00", []byte{0, 0, 0, 0, 0, 12, 34, 56, 99, 0, 0, 0}, 11) - expect("12:34:56.000099", []byte{0, 0, 0, 0, 0, 12, 34, 56, 99, 0, 0, 0}, 15) -} - -func TestEscapeBackslash(t *testing.T) { - expect := func(expected, value string) { - actual := string(escapeBytesBackslash([]byte{}, []byte(value))) - if actual != expected { - t.Errorf( - "expected %s, got %s", - expected, actual, - ) - } - - actual = string(escapeStringBackslash([]byte{}, value)) - if actual != expected { - t.Errorf( - "expected %s, got %s", - expected, actual, - ) - } - } - - expect("foo\\0bar", "foo\x00bar") - expect("foo\\nbar", "foo\nbar") - expect("foo\\rbar", "foo\rbar") - expect("foo\\Zbar", "foo\x1abar") - expect("foo\\\"bar", "foo\"bar") - expect("foo\\\\bar", "foo\\bar") - expect("foo\\'bar", "foo'bar") -} - -func TestEscapeQuotes(t *testing.T) { - expect := func(expected, value string) { - actual := string(escapeBytesQuotes([]byte{}, []byte(value))) - if actual != expected { - t.Errorf( - "expected %s, got %s", - expected, actual, - ) - } - - actual = string(escapeStringQuotes([]byte{}, value)) - if actual != expected { - t.Errorf( - "expected %s, got %s", - expected, actual, - ) - } - } - - expect("foo\x00bar", "foo\x00bar") // not affected - expect("foo\nbar", "foo\nbar") // not affected - expect("foo\rbar", "foo\rbar") // not affected - expect("foo\x1abar", "foo\x1abar") // not affected - expect("foo''bar", "foo'bar") // affected - expect("foo\"bar", "foo\"bar") // not affected -} - -func TestAtomicBool(t *testing.T) { - var ab atomicBool - if ab.IsSet() { - t.Fatal("Expected value to be false") - } - - ab.Set(true) - if ab.value != 1 { - t.Fatal("Set(true) did not set value to 1") - } - if !ab.IsSet() { - t.Fatal("Expected value to be true") - } - - ab.Set(true) - if !ab.IsSet() { - t.Fatal("Expected value to be true") - } - - ab.Set(false) - if ab.value != 0 { - t.Fatal("Set(false) did not set value to 0") - } - if ab.IsSet() { - t.Fatal("Expected value to be false") - } - - ab.Set(false) - if ab.IsSet() { - t.Fatal("Expected value to be false") - } - if ab.TrySet(false) { - t.Fatal("Expected TrySet(false) to fail") - } - if !ab.TrySet(true) { - t.Fatal("Expected TrySet(true) to succeed") - } - if !ab.IsSet() { - t.Fatal("Expected value to be true") - } - - ab.Set(true) - if !ab.IsSet() { - t.Fatal("Expected value to be true") - } - if ab.TrySet(true) { - t.Fatal("Expected TrySet(true) to fail") - } - if !ab.TrySet(false) { - t.Fatal("Expected TrySet(false) to succeed") - } - if ab.IsSet() { - t.Fatal("Expected value to be false") - } - - ab._noCopy.Lock() // we've "tested" it ¯\_(ツ)_/¯ -} - -func TestAtomicError(t *testing.T) { - var ae atomicError - if ae.Value() != nil { - t.Fatal("Expected value to be nil") - } - - ae.Set(ErrMalformPkt) - if v := ae.Value(); v != ErrMalformPkt { - if v == nil { - t.Fatal("Value is still nil") - } - t.Fatal("Error did not match") - } - ae.Set(ErrPktSync) - if ae.Value() == ErrMalformPkt { - t.Fatal("Error still matches old error") - } - if v := ae.Value(); v != ErrPktSync { - t.Fatal("Error did not match") - } -} diff --git a/vendor/github.com/gokyle/sshkey/README b/vendor/github.com/gokyle/sshkey/README deleted file mode 100644 index df6c1aae..00000000 --- a/vendor/github.com/gokyle/sshkey/README +++ /dev/null @@ -1,22 +0,0 @@ -sshkey: a small package for loading OpenSSH ECDSA and RSA keys. - -The key may be loaded via file, HTTP(S), or as byte slices. - -Example: - - pub, keytype, err := sshkey.LoadPublicKeyFile("/home/user/.ssh/id_rsa.pub", false) - switch keytype { - case KEY_RSA: doSomethingRSA(pub.(*rsa.PublicKey)) - case KEY_ECDSA: doSomethingEC(pub.(*ecdsa.PublicKey)) - default: // unknown key type - } - - priv, keytype, err := sshkey.LoadPrivateKeyFile("/home/user/.ssh/id_rsa") - switch keytype { - case KEY_RSA: doSomethingSecretRSA(pub.(*rsa.PrivateKey)) - case KEY_ECDSA: doSomethingSecretEC(pub.(*ecdsa.PrivateKey)) - default: // unknown key type - } - -License: -sshkey is released under an ISC license. diff --git a/vendor/github.com/gokyle/sshkey/TODO b/vendor/github.com/gokyle/sshkey/TODO deleted file mode 100644 index e51b9d1f..00000000 --- a/vendor/github.com/gokyle/sshkey/TODO +++ /dev/null @@ -1,2 +0,0 @@ -* Determine the best way to get DefaultPasswordPrompt to not echo -* Add support for PKCS #8-protected keys. diff --git a/vendor/github.com/gokyle/sshkey/sshkey_test.go b/vendor/github.com/gokyle/sshkey/sshkey_test.go deleted file mode 100644 index 12254df3..00000000 --- a/vendor/github.com/gokyle/sshkey/sshkey_test.go +++ /dev/null @@ -1,108 +0,0 @@ -package sshkey - -import ( - "fmt" - "testing" -) - -func StubPasswordPrompt(prompt string) (password string, err error) { - return "foo bar", nil -} - -type pubTest struct { - FileName string - Fingerprint string - Type Type - Size int -} - -var pubTests = []pubTest{ - pubTest{ - FileName: "testdata/test_rsa.pub", - Fingerprint: "d3:86:5e:77:d4:b7:52:fb:61:39:38:43:31:bb:a2:76", - Type: KEY_RSA, - Size: 2048, - }, - pubTest{ - FileName: "testdata/test2_rsa.pub", - Fingerprint: "a8:02:c1:3f:d8:08:16:84:5f:82:4f:08:6c:2e:98:5b", - Type: KEY_RSA, - Size: 2048, - }, - pubTest{ - FileName: "testdata/test_ecdsa.pub", - Fingerprint: "04:12:2a:3f:e6:ef:da:05:ad:86:72:44:e2:bb:45:d9", - Type: KEY_ECDSA, - Size: 256, - }, - pubTest{ - FileName: "testdata/test2_ecdsa.pub", - Fingerprint: "1f:7f:1d:f1:72:b5:f9:21:dd:38:bf:d0:68:80:85:78", - Type: KEY_ECDSA, - Size: 256, - }, - pubTest{ - FileName: "testdata/test_dsa.pub", - Fingerprint: "a0:21:8c:1c:f4:4f:45:b4:1c:2a:a9:47:4b:7f:ba:f0", - Type: KEY_DSA, - Size: 1024, - }, - pubTest{ - FileName: "testdata/test2_dsa.pub", - Fingerprint: "04:65:87:9f:ae:6d:d6:56:6d:b3:a9:e6:4f:d7:e9:25", - Type: KEY_DSA, - Size: 1024, - }, -} - -var fingerprintList map[string]string -var privList = []string{ - "testdata/test_rsa", - "testdata/test2_rsa", - "testdata/test_ecdsa", - "testdata/test2_ecdsa", - "testdata/test_dsa", - "testdata/test2_dsa", -} - -func init() { - PasswordPrompt = StubPasswordPrompt -} - -func TestLoadPublicKeys(t *testing.T) { - for _, tc := range pubTests { - pub, err := LoadPublicKeyFile(tc.FileName, true) - if err != nil { - fmt.Println(tc.FileName) - fmt.Println(err.Error()) - t.FailNow() - } - fpr, err := FingerprintPretty(pub, 0) - if err != nil { - fmt.Println(tc.FileName) - fmt.Println(err.Error()) - t.FailNow() - } - if fpr != tc.Fingerprint { - fmt.Printf("sshkey: bad fingerprint %s\n\texpected: %s\n", - fpr, tc.Fingerprint) - t.FailNow() - } else if pub.Size() != tc.Size { - fmt.Println(tc.FileName) - fmt.Printf("sshkey: bad key size %d bits: expected %d bits\n", - pub.Size(), tc.Size) - t.FailNow() - } - } -} - -func TestLoadPrivateKeys(t *testing.T) { - for _, keyFile := range privList { - _, _, err := LoadPrivateKeyFile(keyFile) - if err != nil { - fmt.Println(keyFile) - fmt.Println(err.Error()) - t.FailNow() - } - } -} diff --git a/vendor/github.com/golang/protobuf/Makefile b/vendor/github.com/golang/protobuf/Makefile deleted file mode 100644 index 7a51c95b..00000000 --- a/vendor/github.com/golang/protobuf/Makefile +++ /dev/null @@ -1,50 +0,0 @@ -# Go support for Protocol Buffers - Google's data interchange format -# -# Copyright 2010 The Go Authors. All rights reserved. -# https://github.com/golang/protobuf -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -all: install - -install: - go install ./proto ./jsonpb ./ptypes ./protoc-gen-go - -test: - go test ./... ./protoc-gen-go/testdata - go test -tags purego ./... ./protoc-gen-go/testdata - go build ./protoc-gen-go/testdata/grpc/grpc.pb.go - make -C conformance test - -clean: - go clean ./... - -nuke: - go clean -i ./... - -regenerate: - ./regenerate.sh diff --git a/vendor/github.com/golang/protobuf/README.md b/vendor/github.com/golang/protobuf/README.md deleted file mode 100644 index 61820bed..00000000 --- a/vendor/github.com/golang/protobuf/README.md +++ /dev/null @@ -1,281 +0,0 @@ -# Go support for Protocol Buffers - Google's data interchange format - -[![Build Status](https://travis-ci.org/golang/protobuf.svg?branch=master)](https://travis-ci.org/golang/protobuf) -[![GoDoc](https://godoc.org/github.com/golang/protobuf?status.svg)](https://godoc.org/github.com/golang/protobuf) - -Google's data interchange format. -Copyright 2010 The Go Authors. -https://github.com/golang/protobuf - -This package and the code it generates requires at least Go 1.6. - -This software implements Go bindings for protocol buffers. For -information about protocol buffers themselves, see - https://developers.google.com/protocol-buffers/ - -## Installation ## - -To use this software, you must: -- Install the standard C++ implementation of protocol buffers from - https://developers.google.com/protocol-buffers/ -- Of course, install the Go compiler and tools from - https://golang.org/ - See - https://golang.org/doc/install - for details or, if you are using gccgo, follow the instructions at - https://golang.org/doc/install/gccgo -- Grab the code from the repository and install the proto package. - The simplest way is to run `go get -u github.com/golang/protobuf/protoc-gen-go`. - The compiler plugin, protoc-gen-go, will be installed in $GOBIN, - defaulting to $GOPATH/bin. It must be in your $PATH for the protocol - compiler, protoc, to find it. - -This software has two parts: a 'protocol compiler plugin' that -generates Go source files that, once compiled, can access and manage -protocol buffers; and a library that implements run-time support for -encoding (marshaling), decoding (unmarshaling), and accessing protocol -buffers. - -There is support for gRPC in Go using protocol buffers. -See the note at the bottom of this file for details. - -There are no insertion points in the plugin. - - -## Using protocol buffers with Go ## - -Once the software is installed, there are two steps to using it. -First you must compile the protocol buffer definitions and then import -them, with the support library, into your program. - -To compile the protocol buffer definition, run protoc with the --go_out -parameter set to the directory you want to output the Go code to. - - protoc --go_out=. *.proto - -The generated files will be suffixed .pb.go. See the Test code below -for an example using such a file. - -## Packages and input paths ## - -The protocol buffer language has a concept of "packages" which does not -correspond well to the Go notion of packages. In generated Go code, -each source `.proto` file is associated with a single Go package. The -name and import path for this package is specified with the `go_package` -proto option: - - option go_package = "github.com/golang/protobuf/ptypes/any"; - -The protocol buffer compiler will attempt to derive a package name and -import path if a `go_package` option is not present, but it is -best to always specify one explicitly. - -There is a one-to-one relationship between source `.proto` files and -generated `.pb.go` files, but any number of `.pb.go` files may be -contained in the same Go package. - -The output name of a generated file is produced by replacing the -`.proto` suffix with `.pb.go` (e.g., `foo.proto` produces `foo.pb.go`). -However, the output directory is selected in one of two ways. Let -us say we have `inputs/x.proto` with a `go_package` option of -`github.com/golang/protobuf/p`. The corresponding output file may -be: - -- Relative to the import path: - -```shell - protoc --go_out=. inputs/x.proto - # writes ./github.com/golang/protobuf/p/x.pb.go -``` - - (This can work well with `--go_out=$GOPATH`.) - -- Relative to the input file: - -```shell -protoc --go_out=paths=source_relative:. inputs/x.proto -# generate ./inputs/x.pb.go -``` - -## Generated code ## - -The package comment for the proto library contains text describing -the interface provided in Go for protocol buffers. Here is an edited -version. - -The proto package converts data structures to and from the -wire format of protocol buffers. It works in concert with the -Go source code generated for .proto files by the protocol compiler. - -A summary of the properties of the protocol buffer interface -for a protocol buffer variable v: - - - Names are turned from camel_case to CamelCase for export. - - There are no methods on v to set fields; just treat - them as structure fields. - - There are getters that return a field's value if set, - and return the field's default value if unset. - The getters work even if the receiver is a nil message. - - The zero value for a struct is its correct initialization state. - All desired fields must be set before marshaling. - - A Reset() method will restore a protobuf struct to its zero state. - - Non-repeated fields are pointers to the values; nil means unset. - That is, optional or required field int32 f becomes F *int32. - - Repeated fields are slices. - - Helper functions are available to aid the setting of fields. - Helpers for getting values are superseded by the - GetFoo methods and their use is deprecated. - msg.Foo = proto.String("hello") // set field - - Constants are defined to hold the default values of all fields that - have them. They have the form Default_StructName_FieldName. - Because the getter methods handle defaulted values, - direct use of these constants should be rare. - - Enums are given type names and maps from names to values. - Enum values are prefixed with the enum's type name. Enum types have - a String method, and a Enum method to assist in message construction. - - Nested groups and enums have type names prefixed with the name of - the surrounding message type. - - Extensions are given descriptor names that start with E_, - followed by an underscore-delimited list of the nested messages - that contain it (if any) followed by the CamelCased name of the - extension field itself. HasExtension, ClearExtension, GetExtension - and SetExtension are functions for manipulating extensions. - - Oneof field sets are given a single field in their message, - with distinguished wrapper types for each possible field value. - - Marshal and Unmarshal are functions to encode and decode the wire format. - -When the .proto file specifies `syntax="proto3"`, there are some differences: - - - Non-repeated fields of non-message type are values instead of pointers. - - Enum types do not get an Enum method. - -Consider file test.proto, containing - -```proto - syntax = "proto2"; - package example; - - enum FOO { X = 17; }; - - message Test { - required string label = 1; - optional int32 type = 2 [default=77]; - repeated int64 reps = 3; - } -``` - -To create and play with a Test object from the example package, - -```go - package main - - import ( - "log" - - "github.com/golang/protobuf/proto" - "path/to/example" - ) - - func main() { - test := &example.Test{ - Label: proto.String("hello"), - Type: proto.Int32(17), - Reps: []int64{1, 2, 3}, - } - data, err := proto.Marshal(test) - if err != nil { - log.Fatal("marshaling error: ", err) - } - newTest := &example.Test{} - err = proto.Unmarshal(data, newTest) - if err != nil { - log.Fatal("unmarshaling error: ", err) - } - // Now test and newTest contain the same data. - if test.GetLabel() != newTest.GetLabel() { - log.Fatalf("data mismatch %q != %q", test.GetLabel(), newTest.GetLabel()) - } - // etc. - } -``` - -## Parameters ## - -To pass extra parameters to the plugin, use a comma-separated -parameter list separated from the output directory by a colon: - - protoc --go_out=plugins=grpc,import_path=mypackage:. *.proto - -- `paths=(import | source_relative)` - specifies how the paths of - generated files are structured. See the "Packages and imports paths" - section above. The default is `import`. -- `plugins=plugin1+plugin2` - specifies the list of sub-plugins to - load. The only plugin in this repo is `grpc`. -- `Mfoo/bar.proto=quux/shme` - declares that foo/bar.proto is - associated with Go package quux/shme. This is subject to the - import_prefix parameter. - -The following parameters are deprecated and should not be used: - -- `import_prefix=xxx` - a prefix that is added onto the beginning of - all imports. -- `import_path=foo/bar` - used as the package if no input files - declare `go_package`. If it contains slashes, everything up to the - rightmost slash is ignored. - -## gRPC Support ## - -If a proto file specifies RPC services, protoc-gen-go can be instructed to -generate code compatible with gRPC (http://www.grpc.io/). To do this, pass -the `plugins` parameter to protoc-gen-go; the usual way is to insert it into -the --go_out argument to protoc: - - protoc --go_out=plugins=grpc:. *.proto - -## Compatibility ## - -The library and the generated code are expected to be stable over time. -However, we reserve the right to make breaking changes without notice for the -following reasons: - -- Security. A security issue in the specification or implementation may come to - light whose resolution requires breaking compatibility. We reserve the right - to address such security issues. -- Unspecified behavior. There are some aspects of the Protocol Buffers - specification that are undefined. Programs that depend on such unspecified - behavior may break in future releases. -- Specification errors or changes. If it becomes necessary to address an - inconsistency, incompleteness, or change in the Protocol Buffers - specification, resolving the issue could affect the meaning or legality of - existing programs. We reserve the right to address such issues, including - updating the implementations. -- Bugs. If the library has a bug that violates the specification, a program - that depends on the buggy behavior may break if the bug is fixed. We reserve - the right to fix such bugs. -- Adding methods or fields to generated structs. These may conflict with field - names that already exist in a schema, causing applications to break. When the - code generator encounters a field in the schema that would collide with a - generated field or method name, the code generator will append an underscore - to the generated field or method name. -- Adding, removing, or changing methods or fields in generated structs that - start with `XXX`. These parts of the generated code are exported out of - necessity, but should not be considered part of the public API. -- Adding, removing, or changing unexported symbols in generated code. - -Any breaking changes outside of these will be announced 6 months in advance to -protobuf@googlegroups.com. - -You should, whenever possible, use generated code created by the `protoc-gen-go` -tool built at the same commit as the `proto` package. The `proto` package -declares package-level constants in the form `ProtoPackageIsVersionX`. -Application code and generated code may depend on one of these constants to -ensure that compilation will fail if the available version of the proto library -is too old. Whenever we make a change to the generated code that requires newer -library support, in the same commit we will increment the version number of the -generated code and declare a new package-level constant whose name incorporates -the latest version number. Removing a compatibility constant is considered a -breaking change and would be subject to the announcement policy stated above. - -The `protoc-gen-go/generator` package exposes a plugin interface, -which is used by the gRPC code generation. This interface is not -supported and is subject to incompatible changes without notice. diff --git a/vendor/github.com/golang/protobuf/proto/all_test.go b/vendor/github.com/golang/protobuf/proto/all_test.go deleted file mode 100644 index 1bea4b6e..00000000 --- a/vendor/github.com/golang/protobuf/proto/all_test.go +++ /dev/null @@ -1,2492 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2010 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto_test - -import ( - "bytes" - "encoding/json" - "errors" - "fmt" - "math" - "math/rand" - "reflect" - "runtime/debug" - "strings" - "sync" - "testing" - "time" - - . "github.com/golang/protobuf/proto" - pb3 "github.com/golang/protobuf/proto/proto3_proto" - . "github.com/golang/protobuf/proto/test_proto" -) - -var globalO *Buffer - -func old() *Buffer { - if globalO == nil { - globalO = NewBuffer(nil) - } - globalO.Reset() - return globalO -} - -func equalbytes(b1, b2 []byte, t *testing.T) { - if len(b1) != len(b2) { - t.Errorf("wrong lengths: 2*%d != %d", len(b1), len(b2)) - return - } - for i := 0; i < len(b1); i++ { - if b1[i] != b2[i] { - t.Errorf("bad byte[%d]:%x %x: %s %s", i, b1[i], b2[i], b1, b2) - } - } -} - -func initGoTestField() *GoTestField { - f := new(GoTestField) - f.Label = String("label") - f.Type = String("type") - return f -} - -// These are all structurally equivalent but the tag numbers differ. -// (It's remarkable that required, optional, and repeated all have -// 8 letters.) -func initGoTest_RequiredGroup() *GoTest_RequiredGroup { - return &GoTest_RequiredGroup{ - RequiredField: String("required"), - } -} - -func initGoTest_OptionalGroup() *GoTest_OptionalGroup { - return &GoTest_OptionalGroup{ - RequiredField: String("optional"), - } -} - -func initGoTest_RepeatedGroup() *GoTest_RepeatedGroup { - return &GoTest_RepeatedGroup{ - RequiredField: String("repeated"), - } -} - -func initGoTest(setdefaults bool) *GoTest { - pb := new(GoTest) - if setdefaults { - pb.F_BoolDefaulted = Bool(Default_GoTest_F_BoolDefaulted) - pb.F_Int32Defaulted = Int32(Default_GoTest_F_Int32Defaulted) - pb.F_Int64Defaulted = Int64(Default_GoTest_F_Int64Defaulted) - pb.F_Fixed32Defaulted = Uint32(Default_GoTest_F_Fixed32Defaulted) - pb.F_Fixed64Defaulted = Uint64(Default_GoTest_F_Fixed64Defaulted) - pb.F_Uint32Defaulted = Uint32(Default_GoTest_F_Uint32Defaulted) - pb.F_Uint64Defaulted = Uint64(Default_GoTest_F_Uint64Defaulted) - pb.F_FloatDefaulted = Float32(Default_GoTest_F_FloatDefaulted) - pb.F_DoubleDefaulted = Float64(Default_GoTest_F_DoubleDefaulted) - pb.F_StringDefaulted = String(Default_GoTest_F_StringDefaulted) - pb.F_BytesDefaulted = Default_GoTest_F_BytesDefaulted - pb.F_Sint32Defaulted = Int32(Default_GoTest_F_Sint32Defaulted) - pb.F_Sint64Defaulted = Int64(Default_GoTest_F_Sint64Defaulted) - pb.F_Sfixed32Defaulted = Int32(Default_GoTest_F_Sfixed32Defaulted) - pb.F_Sfixed64Defaulted = Int64(Default_GoTest_F_Sfixed64Defaulted) - } - - pb.Kind = GoTest_TIME.Enum() - pb.RequiredField = initGoTestField() - pb.F_BoolRequired = Bool(true) - pb.F_Int32Required = Int32(3) - pb.F_Int64Required = Int64(6) - pb.F_Fixed32Required = Uint32(32) - pb.F_Fixed64Required = Uint64(64) - pb.F_Uint32Required = Uint32(3232) - pb.F_Uint64Required = Uint64(6464) - pb.F_FloatRequired = Float32(3232) - pb.F_DoubleRequired = Float64(6464) - pb.F_StringRequired = String("string") - pb.F_BytesRequired = []byte("bytes") - pb.F_Sint32Required = Int32(-32) - pb.F_Sint64Required = Int64(-64) - pb.F_Sfixed32Required = Int32(-32) - pb.F_Sfixed64Required = Int64(-64) - pb.Requiredgroup = initGoTest_RequiredGroup() - - return pb -} - -func hex(c uint8) uint8 { - if '0' <= c && c <= '9' { - return c - '0' - } - if 'a' <= c && c <= 'f' { - return 10 + c - 'a' - } - if 'A' <= c && c <= 'F' { - return 10 + c - 'A' - } - return 0 -} - -func equal(b []byte, s string, t *testing.T) bool { - if 2*len(b) != len(s) { - // fail(fmt.Sprintf("wrong lengths: 2*%d != %d", len(b), len(s)), b, s, t) - fmt.Printf("wrong lengths: 2*%d != %d\n", len(b), len(s)) - return false - } - for i, j := 0, 0; i < len(b); i, j = i+1, j+2 { - x := hex(s[j])*16 + hex(s[j+1]) - if b[i] != x { - // fail(fmt.Sprintf("bad byte[%d]:%x %x", i, b[i], x), b, s, t) - fmt.Printf("bad byte[%d]:%x %x", i, b[i], x) - return false - } - } - return true -} - -func overify(t *testing.T, pb *GoTest, expected string) { - o := old() - err := o.Marshal(pb) - if err != nil { - fmt.Printf("overify marshal-1 err = %v", err) - o.DebugPrint("", o.Bytes()) - t.Fatalf("expected = %s", expected) - } - if !equal(o.Bytes(), expected, t) { - o.DebugPrint("overify neq 1", o.Bytes()) - t.Fatalf("expected = %s", expected) - } - - // Now test Unmarshal by recreating the original buffer. - pbd := new(GoTest) - err = o.Unmarshal(pbd) - if err != nil { - t.Fatalf("overify unmarshal err = %v", err) - o.DebugPrint("", o.Bytes()) - t.Fatalf("string = %s", expected) - } - o.Reset() - err = o.Marshal(pbd) - if err != nil { - t.Errorf("overify marshal-2 err = %v", err) - o.DebugPrint("", o.Bytes()) - t.Fatalf("string = %s", expected) - } - if !equal(o.Bytes(), expected, t) { - o.DebugPrint("overify neq 2", o.Bytes()) - t.Fatalf("string = %s", expected) - } -} - -// Simple tests for numeric encode/decode primitives (varint, etc.) -func TestNumericPrimitives(t *testing.T) { - for i := uint64(0); i < 1e6; i += 111 { - o := old() - if o.EncodeVarint(i) != nil { - t.Error("EncodeVarint") - break - } - x, e := o.DecodeVarint() - if e != nil { - t.Fatal("DecodeVarint") - } - if x != i { - t.Fatal("varint decode fail:", i, x) - } - - o = old() - if o.EncodeFixed32(i) != nil { - t.Fatal("encFixed32") - } - x, e = o.DecodeFixed32() - if e != nil { - t.Fatal("decFixed32") - } - if x != i { - t.Fatal("fixed32 decode fail:", i, x) - } - - o = old() - if o.EncodeFixed64(i*1234567) != nil { - t.Error("encFixed64") - break - } - x, e = o.DecodeFixed64() - if e != nil { - t.Error("decFixed64") - break - } - if x != i*1234567 { - t.Error("fixed64 decode fail:", i*1234567, x) - break - } - - o = old() - i32 := int32(i - 12345) - if o.EncodeZigzag32(uint64(i32)) != nil { - t.Fatal("EncodeZigzag32") - } - x, e = o.DecodeZigzag32() - if e != nil { - t.Fatal("DecodeZigzag32") - } - if x != uint64(uint32(i32)) { - t.Fatal("zigzag32 decode fail:", i32, x) - } - - o = old() - i64 := int64(i - 12345) - if o.EncodeZigzag64(uint64(i64)) != nil { - t.Fatal("EncodeZigzag64") - } - x, e = o.DecodeZigzag64() - if e != nil { - t.Fatal("DecodeZigzag64") - } - if x != uint64(i64) { - t.Fatal("zigzag64 decode fail:", i64, x) - } - } -} - -// fakeMarshaler is a simple struct implementing Marshaler and Message interfaces. -type fakeMarshaler struct { - b []byte - err error -} - -func (f *fakeMarshaler) Marshal() ([]byte, error) { return f.b, f.err } -func (f *fakeMarshaler) String() string { return fmt.Sprintf("Bytes: %v Error: %v", f.b, f.err) } -func (f *fakeMarshaler) ProtoMessage() {} -func (f *fakeMarshaler) Reset() {} - -type msgWithFakeMarshaler struct { - M *fakeMarshaler `protobuf:"bytes,1,opt,name=fake"` -} - -func (m *msgWithFakeMarshaler) String() string { return CompactTextString(m) } -func (m *msgWithFakeMarshaler) ProtoMessage() {} -func (m *msgWithFakeMarshaler) Reset() {} - -// Simple tests for proto messages that implement the Marshaler interface. -func TestMarshalerEncoding(t *testing.T) { - tests := []struct { - name string - m Message - want []byte - errType reflect.Type - }{ - { - name: "Marshaler that fails", - m: &fakeMarshaler{ - err: errors.New("some marshal err"), - b: []byte{5, 6, 7}, - }, - // Since the Marshal method returned bytes, they should be written to the - // buffer. (For efficiency, we assume that Marshal implementations are - // always correct w.r.t. RequiredNotSetError and output.) - want: []byte{5, 6, 7}, - errType: reflect.TypeOf(errors.New("some marshal err")), - }, - { - name: "Marshaler that fails with RequiredNotSetError", - m: &msgWithFakeMarshaler{ - M: &fakeMarshaler{ - err: &RequiredNotSetError{}, - b: []byte{5, 6, 7}, - }, - }, - // Since there's an error that can be continued after, - // the buffer should be written. - want: []byte{ - 10, 3, // for &msgWithFakeMarshaler - 5, 6, 7, // for &fakeMarshaler - }, - errType: reflect.TypeOf(&RequiredNotSetError{}), - }, - { - name: "Marshaler that succeeds", - m: &fakeMarshaler{ - b: []byte{0, 1, 2, 3, 4, 127, 255}, - }, - want: []byte{0, 1, 2, 3, 4, 127, 255}, - }, - } - for _, test := range tests { - b := NewBuffer(nil) - err := b.Marshal(test.m) - if reflect.TypeOf(err) != test.errType { - t.Errorf("%s: got err %T(%v) wanted %T", test.name, err, err, test.errType) - } - if !reflect.DeepEqual(test.want, b.Bytes()) { - t.Errorf("%s: got bytes %v wanted %v", test.name, b.Bytes(), test.want) - } - if size := Size(test.m); size != len(b.Bytes()) { - t.Errorf("%s: Size(_) = %v, but marshaled to %v bytes", test.name, size, len(b.Bytes())) - } - - m, mErr := Marshal(test.m) - if !bytes.Equal(b.Bytes(), m) { - t.Errorf("%s: Marshal returned %v, but (*Buffer).Marshal wrote %v", test.name, m, b.Bytes()) - } - if !reflect.DeepEqual(err, mErr) { - t.Errorf("%s: Marshal err = %q, but (*Buffer).Marshal returned %q", - test.name, fmt.Sprint(mErr), fmt.Sprint(err)) - } - } -} - -// Ensure that Buffer.Marshal uses O(N) memory for N messages -func TestBufferMarshalAllocs(t *testing.T) { - value := &OtherMessage{Key: Int64(1)} - msg := &MyMessage{Count: Int32(1), Others: []*OtherMessage{value}} - - reallocSize := func(t *testing.T, items int, prealloc int) (int64, int64) { - var b Buffer - b.SetBuf(make([]byte, 0, prealloc)) - - var allocSpace int64 - prevCap := cap(b.Bytes()) - for i := 0; i < items; i++ { - err := b.Marshal(msg) - if err != nil { - t.Errorf("Marshal err = %q", err) - break - } - if c := cap(b.Bytes()); prevCap != c { - allocSpace += int64(c) - prevCap = c - } - } - needSpace := int64(len(b.Bytes())) - return allocSpace, needSpace - } - - for _, prealloc := range []int{0, 100, 10000} { - for _, items := range []int{1, 2, 5, 10, 20, 50, 100, 200, 500, 1000} { - runtimeSpace, need := reallocSize(t, items, prealloc) - totalSpace := int64(prealloc) + runtimeSpace - - runtimeRatio := float64(runtimeSpace) / float64(need) - totalRatio := float64(totalSpace) / float64(need) - - if totalRatio < 1 || runtimeRatio > 4 { - t.Errorf("needed %dB, allocated %dB total (ratio %.1f), allocated %dB at runtime (ratio %.1f)", - need, totalSpace, totalRatio, runtimeSpace, runtimeRatio) - } - } - } -} - -// Simple tests for bytes -func TestBytesPrimitives(t *testing.T) { - o := old() - bytes := []byte{'n', 'o', 'w', ' ', 'i', 's', ' ', 't', 'h', 'e', ' ', 't', 'i', 'm', 'e'} - if o.EncodeRawBytes(bytes) != nil { - t.Error("EncodeRawBytes") - } - decb, e := o.DecodeRawBytes(false) - if e != nil { - t.Error("DecodeRawBytes") - } - equalbytes(bytes, decb, t) -} - -// Simple tests for strings -func TestStringPrimitives(t *testing.T) { - o := old() - s := "now is the time" - if o.EncodeStringBytes(s) != nil { - t.Error("enc_string") - } - decs, e := o.DecodeStringBytes() - if e != nil { - t.Error("dec_string") - } - if s != decs { - t.Error("string encode/decode fail:", s, decs) - } -} - -// Do we catch the "required bit not set" case? -func TestRequiredBit(t *testing.T) { - o := old() - pb := new(GoTest) - err := o.Marshal(pb) - if err == nil { - t.Error("did not catch missing required fields") - } else if !strings.Contains(err.Error(), "Kind") { - t.Error("wrong error type:", err) - } -} - -// Check that all fields are nil. -// Clearly silly, and a residue from a more interesting test with an earlier, -// different initialization property, but it once caught a compiler bug so -// it lives. -func checkInitialized(pb *GoTest, t *testing.T) { - if pb.F_BoolDefaulted != nil { - t.Error("New or Reset did not set boolean:", *pb.F_BoolDefaulted) - } - if pb.F_Int32Defaulted != nil { - t.Error("New or Reset did not set int32:", *pb.F_Int32Defaulted) - } - if pb.F_Int64Defaulted != nil { - t.Error("New or Reset did not set int64:", *pb.F_Int64Defaulted) - } - if pb.F_Fixed32Defaulted != nil { - t.Error("New or Reset did not set fixed32:", *pb.F_Fixed32Defaulted) - } - if pb.F_Fixed64Defaulted != nil { - t.Error("New or Reset did not set fixed64:", *pb.F_Fixed64Defaulted) - } - if pb.F_Uint32Defaulted != nil { - t.Error("New or Reset did not set uint32:", *pb.F_Uint32Defaulted) - } - if pb.F_Uint64Defaulted != nil { - t.Error("New or Reset did not set uint64:", *pb.F_Uint64Defaulted) - } - if pb.F_FloatDefaulted != nil { - t.Error("New or Reset did not set float:", *pb.F_FloatDefaulted) - } - if pb.F_DoubleDefaulted != nil { - t.Error("New or Reset did not set double:", *pb.F_DoubleDefaulted) - } - if pb.F_StringDefaulted != nil { - t.Error("New or Reset did not set string:", *pb.F_StringDefaulted) - } - if pb.F_BytesDefaulted != nil { - t.Error("New or Reset did not set bytes:", string(pb.F_BytesDefaulted)) - } - if pb.F_Sint32Defaulted != nil { - t.Error("New or Reset did not set int32:", *pb.F_Sint32Defaulted) - } - if pb.F_Sint64Defaulted != nil { - t.Error("New or Reset did not set int64:", *pb.F_Sint64Defaulted) - } -} - -// Does Reset() reset? -func TestReset(t *testing.T) { - pb := initGoTest(true) - // muck with some values - pb.F_BoolDefaulted = Bool(false) - pb.F_Int32Defaulted = Int32(237) - pb.F_Int64Defaulted = Int64(12346) - pb.F_Fixed32Defaulted = Uint32(32000) - pb.F_Fixed64Defaulted = Uint64(666) - pb.F_Uint32Defaulted = Uint32(323232) - pb.F_Uint64Defaulted = nil - pb.F_FloatDefaulted = nil - pb.F_DoubleDefaulted = Float64(0) - pb.F_StringDefaulted = String("gotcha") - pb.F_BytesDefaulted = []byte("asdfasdf") - pb.F_Sint32Defaulted = Int32(123) - pb.F_Sint64Defaulted = Int64(789) - pb.Reset() - checkInitialized(pb, t) -} - -// All required fields set, no defaults provided. -func TestEncodeDecode1(t *testing.T) { - pb := initGoTest(false) - overify(t, pb, - "0807"+ // field 1, encoding 0, value 7 - "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) - "5001"+ // field 10, encoding 0, value 1 - "5803"+ // field 11, encoding 0, value 3 - "6006"+ // field 12, encoding 0, value 6 - "6d20000000"+ // field 13, encoding 5, value 0x20 - "714000000000000000"+ // field 14, encoding 1, value 0x40 - "78a019"+ // field 15, encoding 0, value 0xca0 = 3232 - "8001c032"+ // field 16, encoding 0, value 0x1940 = 6464 - "8d0100004a45"+ // field 17, encoding 5, value 3232.0 - "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 - "9a0106"+"737472696e67"+ // field 19, encoding 2, string "string" - "b304"+ // field 70, encoding 3, start group - "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" - "b404"+ // field 70, encoding 4, end group - "aa0605"+"6279746573"+ // field 101, encoding 2, string "bytes" - "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 - "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 - "c506e0ffffff"+ // field 104, encoding 5, -32 fixed32 - "c906c0ffffffffffffff") // field 105, encoding 1, -64 fixed64 -} - -// All required fields set, defaults provided. -func TestEncodeDecode2(t *testing.T) { - pb := initGoTest(true) - overify(t, pb, - "0807"+ // field 1, encoding 0, value 7 - "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) - "5001"+ // field 10, encoding 0, value 1 - "5803"+ // field 11, encoding 0, value 3 - "6006"+ // field 12, encoding 0, value 6 - "6d20000000"+ // field 13, encoding 5, value 32 - "714000000000000000"+ // field 14, encoding 1, value 64 - "78a019"+ // field 15, encoding 0, value 3232 - "8001c032"+ // field 16, encoding 0, value 6464 - "8d0100004a45"+ // field 17, encoding 5, value 3232.0 - "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 - "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" - "c00201"+ // field 40, encoding 0, value 1 - "c80220"+ // field 41, encoding 0, value 32 - "d00240"+ // field 42, encoding 0, value 64 - "dd0240010000"+ // field 43, encoding 5, value 320 - "e1028002000000000000"+ // field 44, encoding 1, value 640 - "e8028019"+ // field 45, encoding 0, value 3200 - "f0028032"+ // field 46, encoding 0, value 6400 - "fd02e0659948"+ // field 47, encoding 5, value 314159.0 - "81030000000050971041"+ // field 48, encoding 1, value 271828.0 - "8a0310"+"68656c6c6f2c2022776f726c6421220a"+ // field 49, encoding 2 string "hello, \"world!\"\n" - "b304"+ // start group field 70 level 1 - "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" - "b404"+ // end group field 70 level 1 - "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" - "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 - "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 - "c506e0ffffff"+ // field 104, encoding 5, -32 fixed32 - "c906c0ffffffffffffff"+ // field 105, encoding 1, -64 fixed64 - "8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose" - "90193f"+ // field 402, encoding 0, value 63 - "98197f"+ // field 403, encoding 0, value 127 - "a519e0ffffff"+ // field 404, encoding 5, -32 fixed32 - "a919c0ffffffffffffff") // field 405, encoding 1, -64 fixed64 - -} - -// All default fields set to their default value by hand -func TestEncodeDecode3(t *testing.T) { - pb := initGoTest(false) - pb.F_BoolDefaulted = Bool(true) - pb.F_Int32Defaulted = Int32(32) - pb.F_Int64Defaulted = Int64(64) - pb.F_Fixed32Defaulted = Uint32(320) - pb.F_Fixed64Defaulted = Uint64(640) - pb.F_Uint32Defaulted = Uint32(3200) - pb.F_Uint64Defaulted = Uint64(6400) - pb.F_FloatDefaulted = Float32(314159) - pb.F_DoubleDefaulted = Float64(271828) - pb.F_StringDefaulted = String("hello, \"world!\"\n") - pb.F_BytesDefaulted = []byte("Bignose") - pb.F_Sint32Defaulted = Int32(-32) - pb.F_Sint64Defaulted = Int64(-64) - pb.F_Sfixed32Defaulted = Int32(-32) - pb.F_Sfixed64Defaulted = Int64(-64) - - overify(t, pb, - "0807"+ // field 1, encoding 0, value 7 - "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) - "5001"+ // field 10, encoding 0, value 1 - "5803"+ // field 11, encoding 0, value 3 - "6006"+ // field 12, encoding 0, value 6 - "6d20000000"+ // field 13, encoding 5, value 32 - "714000000000000000"+ // field 14, encoding 1, value 64 - "78a019"+ // field 15, encoding 0, value 3232 - "8001c032"+ // field 16, encoding 0, value 6464 - "8d0100004a45"+ // field 17, encoding 5, value 3232.0 - "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 - "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" - "c00201"+ // field 40, encoding 0, value 1 - "c80220"+ // field 41, encoding 0, value 32 - "d00240"+ // field 42, encoding 0, value 64 - "dd0240010000"+ // field 43, encoding 5, value 320 - "e1028002000000000000"+ // field 44, encoding 1, value 640 - "e8028019"+ // field 45, encoding 0, value 3200 - "f0028032"+ // field 46, encoding 0, value 6400 - "fd02e0659948"+ // field 47, encoding 5, value 314159.0 - "81030000000050971041"+ // field 48, encoding 1, value 271828.0 - "8a0310"+"68656c6c6f2c2022776f726c6421220a"+ // field 49, encoding 2 string "hello, \"world!\"\n" - "b304"+ // start group field 70 level 1 - "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" - "b404"+ // end group field 70 level 1 - "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" - "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 - "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 - "c506e0ffffff"+ // field 104, encoding 5, -32 fixed32 - "c906c0ffffffffffffff"+ // field 105, encoding 1, -64 fixed64 - "8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose" - "90193f"+ // field 402, encoding 0, value 63 - "98197f"+ // field 403, encoding 0, value 127 - "a519e0ffffff"+ // field 404, encoding 5, -32 fixed32 - "a919c0ffffffffffffff") // field 405, encoding 1, -64 fixed64 - -} - -// All required fields set, defaults provided, all non-defaulted optional fields have values. -func TestEncodeDecode4(t *testing.T) { - pb := initGoTest(true) - pb.Table = String("hello") - pb.Param = Int32(7) - pb.OptionalField = initGoTestField() - pb.F_BoolOptional = Bool(true) - pb.F_Int32Optional = Int32(32) - pb.F_Int64Optional = Int64(64) - pb.F_Fixed32Optional = Uint32(3232) - pb.F_Fixed64Optional = Uint64(6464) - pb.F_Uint32Optional = Uint32(323232) - pb.F_Uint64Optional = Uint64(646464) - pb.F_FloatOptional = Float32(32.) - pb.F_DoubleOptional = Float64(64.) - pb.F_StringOptional = String("hello") - pb.F_BytesOptional = []byte("Bignose") - pb.F_Sint32Optional = Int32(-32) - pb.F_Sint64Optional = Int64(-64) - pb.F_Sfixed32Optional = Int32(-32) - pb.F_Sfixed64Optional = Int64(-64) - pb.Optionalgroup = initGoTest_OptionalGroup() - - overify(t, pb, - "0807"+ // field 1, encoding 0, value 7 - "1205"+"68656c6c6f"+ // field 2, encoding 2, string "hello" - "1807"+ // field 3, encoding 0, value 7 - "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) - "320d"+"0a056c6162656c120474797065"+ // field 6, encoding 2 (GoTestField) - "5001"+ // field 10, encoding 0, value 1 - "5803"+ // field 11, encoding 0, value 3 - "6006"+ // field 12, encoding 0, value 6 - "6d20000000"+ // field 13, encoding 5, value 32 - "714000000000000000"+ // field 14, encoding 1, value 64 - "78a019"+ // field 15, encoding 0, value 3232 - "8001c032"+ // field 16, encoding 0, value 6464 - "8d0100004a45"+ // field 17, encoding 5, value 3232.0 - "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 - "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" - "f00101"+ // field 30, encoding 0, value 1 - "f80120"+ // field 31, encoding 0, value 32 - "800240"+ // field 32, encoding 0, value 64 - "8d02a00c0000"+ // field 33, encoding 5, value 3232 - "91024019000000000000"+ // field 34, encoding 1, value 6464 - "9802a0dd13"+ // field 35, encoding 0, value 323232 - "a002c0ba27"+ // field 36, encoding 0, value 646464 - "ad0200000042"+ // field 37, encoding 5, value 32.0 - "b1020000000000005040"+ // field 38, encoding 1, value 64.0 - "ba0205"+"68656c6c6f"+ // field 39, encoding 2, string "hello" - "c00201"+ // field 40, encoding 0, value 1 - "c80220"+ // field 41, encoding 0, value 32 - "d00240"+ // field 42, encoding 0, value 64 - "dd0240010000"+ // field 43, encoding 5, value 320 - "e1028002000000000000"+ // field 44, encoding 1, value 640 - "e8028019"+ // field 45, encoding 0, value 3200 - "f0028032"+ // field 46, encoding 0, value 6400 - "fd02e0659948"+ // field 47, encoding 5, value 314159.0 - "81030000000050971041"+ // field 48, encoding 1, value 271828.0 - "8a0310"+"68656c6c6f2c2022776f726c6421220a"+ // field 49, encoding 2 string "hello, \"world!\"\n" - "b304"+ // start group field 70 level 1 - "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" - "b404"+ // end group field 70 level 1 - "d305"+ // start group field 90 level 1 - "da0508"+"6f7074696f6e616c"+ // field 91, encoding 2, string "optional" - "d405"+ // end group field 90 level 1 - "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" - "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 - "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 - "c506e0ffffff"+ // field 104, encoding 5, -32 fixed32 - "c906c0ffffffffffffff"+ // field 105, encoding 1, -64 fixed64 - "ea1207"+"4269676e6f7365"+ // field 301, encoding 2, string "Bignose" - "f0123f"+ // field 302, encoding 0, value 63 - "f8127f"+ // field 303, encoding 0, value 127 - "8513e0ffffff"+ // field 304, encoding 5, -32 fixed32 - "8913c0ffffffffffffff"+ // field 305, encoding 1, -64 fixed64 - "8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose" - "90193f"+ // field 402, encoding 0, value 63 - "98197f"+ // field 403, encoding 0, value 127 - "a519e0ffffff"+ // field 404, encoding 5, -32 fixed32 - "a919c0ffffffffffffff") // field 405, encoding 1, -64 fixed64 - -} - -// All required fields set, defaults provided, all repeated fields given two values. -func TestEncodeDecode5(t *testing.T) { - pb := initGoTest(true) - pb.RepeatedField = []*GoTestField{initGoTestField(), initGoTestField()} - pb.F_BoolRepeated = []bool{false, true} - pb.F_Int32Repeated = []int32{32, 33} - pb.F_Int64Repeated = []int64{64, 65} - pb.F_Fixed32Repeated = []uint32{3232, 3333} - pb.F_Fixed64Repeated = []uint64{6464, 6565} - pb.F_Uint32Repeated = []uint32{323232, 333333} - pb.F_Uint64Repeated = []uint64{646464, 656565} - pb.F_FloatRepeated = []float32{32., 33.} - pb.F_DoubleRepeated = []float64{64., 65.} - pb.F_StringRepeated = []string{"hello", "sailor"} - pb.F_BytesRepeated = [][]byte{[]byte("big"), []byte("nose")} - pb.F_Sint32Repeated = []int32{32, -32} - pb.F_Sint64Repeated = []int64{64, -64} - pb.F_Sfixed32Repeated = []int32{32, -32} - pb.F_Sfixed64Repeated = []int64{64, -64} - pb.Repeatedgroup = []*GoTest_RepeatedGroup{initGoTest_RepeatedGroup(), initGoTest_RepeatedGroup()} - - overify(t, pb, - "0807"+ // field 1, encoding 0, value 7 - "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) - "2a0d"+"0a056c6162656c120474797065"+ // field 5, encoding 2 (GoTestField) - "2a0d"+"0a056c6162656c120474797065"+ // field 5, encoding 2 (GoTestField) - "5001"+ // field 10, encoding 0, value 1 - "5803"+ // field 11, encoding 0, value 3 - "6006"+ // field 12, encoding 0, value 6 - "6d20000000"+ // field 13, encoding 5, value 32 - "714000000000000000"+ // field 14, encoding 1, value 64 - "78a019"+ // field 15, encoding 0, value 3232 - "8001c032"+ // field 16, encoding 0, value 6464 - "8d0100004a45"+ // field 17, encoding 5, value 3232.0 - "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 - "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" - "a00100"+ // field 20, encoding 0, value 0 - "a00101"+ // field 20, encoding 0, value 1 - "a80120"+ // field 21, encoding 0, value 32 - "a80121"+ // field 21, encoding 0, value 33 - "b00140"+ // field 22, encoding 0, value 64 - "b00141"+ // field 22, encoding 0, value 65 - "bd01a00c0000"+ // field 23, encoding 5, value 3232 - "bd01050d0000"+ // field 23, encoding 5, value 3333 - "c1014019000000000000"+ // field 24, encoding 1, value 6464 - "c101a519000000000000"+ // field 24, encoding 1, value 6565 - "c801a0dd13"+ // field 25, encoding 0, value 323232 - "c80195ac14"+ // field 25, encoding 0, value 333333 - "d001c0ba27"+ // field 26, encoding 0, value 646464 - "d001b58928"+ // field 26, encoding 0, value 656565 - "dd0100000042"+ // field 27, encoding 5, value 32.0 - "dd0100000442"+ // field 27, encoding 5, value 33.0 - "e1010000000000005040"+ // field 28, encoding 1, value 64.0 - "e1010000000000405040"+ // field 28, encoding 1, value 65.0 - "ea0105"+"68656c6c6f"+ // field 29, encoding 2, string "hello" - "ea0106"+"7361696c6f72"+ // field 29, encoding 2, string "sailor" - "c00201"+ // field 40, encoding 0, value 1 - "c80220"+ // field 41, encoding 0, value 32 - "d00240"+ // field 42, encoding 0, value 64 - "dd0240010000"+ // field 43, encoding 5, value 320 - "e1028002000000000000"+ // field 44, encoding 1, value 640 - "e8028019"+ // field 45, encoding 0, value 3200 - "f0028032"+ // field 46, encoding 0, value 6400 - "fd02e0659948"+ // field 47, encoding 5, value 314159.0 - "81030000000050971041"+ // field 48, encoding 1, value 271828.0 - "8a0310"+"68656c6c6f2c2022776f726c6421220a"+ // field 49, encoding 2 string "hello, \"world!\"\n" - "b304"+ // start group field 70 level 1 - "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" - "b404"+ // end group field 70 level 1 - "8305"+ // start group field 80 level 1 - "8a0508"+"7265706561746564"+ // field 81, encoding 2, string "repeated" - "8405"+ // end group field 80 level 1 - "8305"+ // start group field 80 level 1 - "8a0508"+"7265706561746564"+ // field 81, encoding 2, string "repeated" - "8405"+ // end group field 80 level 1 - "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" - "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 - "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 - "c506e0ffffff"+ // field 104, encoding 5, -32 fixed32 - "c906c0ffffffffffffff"+ // field 105, encoding 1, -64 fixed64 - "ca0c03"+"626967"+ // field 201, encoding 2, string "big" - "ca0c04"+"6e6f7365"+ // field 201, encoding 2, string "nose" - "d00c40"+ // field 202, encoding 0, value 32 - "d00c3f"+ // field 202, encoding 0, value -32 - "d80c8001"+ // field 203, encoding 0, value 64 - "d80c7f"+ // field 203, encoding 0, value -64 - "e50c20000000"+ // field 204, encoding 5, 32 fixed32 - "e50ce0ffffff"+ // field 204, encoding 5, -32 fixed32 - "e90c4000000000000000"+ // field 205, encoding 1, 64 fixed64 - "e90cc0ffffffffffffff"+ // field 205, encoding 1, -64 fixed64 - "8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose" - "90193f"+ // field 402, encoding 0, value 63 - "98197f"+ // field 403, encoding 0, value 127 - "a519e0ffffff"+ // field 404, encoding 5, -32 fixed32 - "a919c0ffffffffffffff") // field 405, encoding 1, -64 fixed64 - -} - -// All required fields set, all packed repeated fields given two values. -func TestEncodeDecode6(t *testing.T) { - pb := initGoTest(false) - pb.F_BoolRepeatedPacked = []bool{false, true} - pb.F_Int32RepeatedPacked = []int32{32, 33} - pb.F_Int64RepeatedPacked = []int64{64, 65} - pb.F_Fixed32RepeatedPacked = []uint32{3232, 3333} - pb.F_Fixed64RepeatedPacked = []uint64{6464, 6565} - pb.F_Uint32RepeatedPacked = []uint32{323232, 333333} - pb.F_Uint64RepeatedPacked = []uint64{646464, 656565} - pb.F_FloatRepeatedPacked = []float32{32., 33.} - pb.F_DoubleRepeatedPacked = []float64{64., 65.} - pb.F_Sint32RepeatedPacked = []int32{32, -32} - pb.F_Sint64RepeatedPacked = []int64{64, -64} - pb.F_Sfixed32RepeatedPacked = []int32{32, -32} - pb.F_Sfixed64RepeatedPacked = []int64{64, -64} - - overify(t, pb, - "0807"+ // field 1, encoding 0, value 7 - "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) - "5001"+ // field 10, encoding 0, value 1 - "5803"+ // field 11, encoding 0, value 3 - "6006"+ // field 12, encoding 0, value 6 - "6d20000000"+ // field 13, encoding 5, value 32 - "714000000000000000"+ // field 14, encoding 1, value 64 - "78a019"+ // field 15, encoding 0, value 3232 - "8001c032"+ // field 16, encoding 0, value 6464 - "8d0100004a45"+ // field 17, encoding 5, value 3232.0 - "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 - "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" - "9203020001"+ // field 50, encoding 2, 2 bytes, value 0, value 1 - "9a03022021"+ // field 51, encoding 2, 2 bytes, value 32, value 33 - "a203024041"+ // field 52, encoding 2, 2 bytes, value 64, value 65 - "aa0308"+ // field 53, encoding 2, 8 bytes - "a00c0000050d0000"+ // value 3232, value 3333 - "b20310"+ // field 54, encoding 2, 16 bytes - "4019000000000000a519000000000000"+ // value 6464, value 6565 - "ba0306"+ // field 55, encoding 2, 6 bytes - "a0dd1395ac14"+ // value 323232, value 333333 - "c20306"+ // field 56, encoding 2, 6 bytes - "c0ba27b58928"+ // value 646464, value 656565 - "ca0308"+ // field 57, encoding 2, 8 bytes - "0000004200000442"+ // value 32.0, value 33.0 - "d20310"+ // field 58, encoding 2, 16 bytes - "00000000000050400000000000405040"+ // value 64.0, value 65.0 - "b304"+ // start group field 70 level 1 - "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" - "b404"+ // end group field 70 level 1 - "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" - "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 - "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 - "c506e0ffffff"+ // field 104, encoding 5, -32 fixed32 - "c906c0ffffffffffffff"+ // field 105, encoding 1, -64 fixed64 - "b21f02"+ // field 502, encoding 2, 2 bytes - "403f"+ // value 32, value -32 - "ba1f03"+ // field 503, encoding 2, 3 bytes - "80017f"+ // value 64, value -64 - "c21f08"+ // field 504, encoding 2, 8 bytes - "20000000e0ffffff"+ // value 32, value -32 - "ca1f10"+ // field 505, encoding 2, 16 bytes - "4000000000000000c0ffffffffffffff") // value 64, value -64 - -} - -// Test that we can encode empty bytes fields. -func TestEncodeDecodeBytes1(t *testing.T) { - pb := initGoTest(false) - - // Create our bytes - pb.F_BytesRequired = []byte{} - pb.F_BytesRepeated = [][]byte{{}} - pb.F_BytesOptional = []byte{} - - d, err := Marshal(pb) - if err != nil { - t.Error(err) - } - - pbd := new(GoTest) - if err := Unmarshal(d, pbd); err != nil { - t.Error(err) - } - - if pbd.F_BytesRequired == nil || len(pbd.F_BytesRequired) != 0 { - t.Error("required empty bytes field is incorrect") - } - if pbd.F_BytesRepeated == nil || len(pbd.F_BytesRepeated) == 1 && pbd.F_BytesRepeated[0] == nil { - t.Error("repeated empty bytes field is incorrect") - } - if pbd.F_BytesOptional == nil || len(pbd.F_BytesOptional) != 0 { - t.Error("optional empty bytes field is incorrect") - } -} - -// Test that we encode nil-valued fields of a repeated bytes field correctly. -// Since entries in a repeated field cannot be nil, nil must mean empty value. -func TestEncodeDecodeBytes2(t *testing.T) { - pb := initGoTest(false) - - // Create our bytes - pb.F_BytesRepeated = [][]byte{nil} - - d, err := Marshal(pb) - if err != nil { - t.Error(err) - } - - pbd := new(GoTest) - if err := Unmarshal(d, pbd); err != nil { - t.Error(err) - } - - if len(pbd.F_BytesRepeated) != 1 || pbd.F_BytesRepeated[0] == nil { - t.Error("Unexpected value for repeated bytes field") - } -} - -// All required fields set, defaults provided, all repeated fields given two values. -func TestSkippingUnrecognizedFields(t *testing.T) { - o := old() - pb := initGoTestField() - - // Marshal it normally. - o.Marshal(pb) - - // Now new a GoSkipTest record. - skip := &GoSkipTest{ - SkipInt32: Int32(32), - SkipFixed32: Uint32(3232), - SkipFixed64: Uint64(6464), - SkipString: String("skipper"), - Skipgroup: &GoSkipTest_SkipGroup{ - GroupInt32: Int32(75), - GroupString: String("wxyz"), - }, - } - - // Marshal it into same buffer. - o.Marshal(skip) - - pbd := new(GoTestField) - o.Unmarshal(pbd) - - // The __unrecognized field should be a marshaling of GoSkipTest - skipd := new(GoSkipTest) - - o.SetBuf(pbd.XXX_unrecognized) - o.Unmarshal(skipd) - - if *skipd.SkipInt32 != *skip.SkipInt32 { - t.Error("skip int32", skipd.SkipInt32) - } - if *skipd.SkipFixed32 != *skip.SkipFixed32 { - t.Error("skip fixed32", skipd.SkipFixed32) - } - if *skipd.SkipFixed64 != *skip.SkipFixed64 { - t.Error("skip fixed64", skipd.SkipFixed64) - } - if *skipd.SkipString != *skip.SkipString { - t.Error("skip string", *skipd.SkipString) - } - if *skipd.Skipgroup.GroupInt32 != *skip.Skipgroup.GroupInt32 { - t.Error("skip group int32", skipd.Skipgroup.GroupInt32) - } - if *skipd.Skipgroup.GroupString != *skip.Skipgroup.GroupString { - t.Error("skip group string", *skipd.Skipgroup.GroupString) - } -} - -// Check that unrecognized fields of a submessage are preserved. -func TestSubmessageUnrecognizedFields(t *testing.T) { - nm := &NewMessage{ - Nested: &NewMessage_Nested{ - Name: String("Nigel"), - FoodGroup: String("carbs"), - }, - } - b, err := Marshal(nm) - if err != nil { - t.Fatalf("Marshal of NewMessage: %v", err) - } - - // Unmarshal into an OldMessage. - om := new(OldMessage) - if err := Unmarshal(b, om); err != nil { - t.Fatalf("Unmarshal to OldMessage: %v", err) - } - exp := &OldMessage{ - Nested: &OldMessage_Nested{ - Name: String("Nigel"), - // normal protocol buffer users should not do this - XXX_unrecognized: []byte("\x12\x05carbs"), - }, - } - if !Equal(om, exp) { - t.Errorf("om = %v, want %v", om, exp) - } - - // Clone the OldMessage. - om = Clone(om).(*OldMessage) - if !Equal(om, exp) { - t.Errorf("Clone(om) = %v, want %v", om, exp) - } - - // Marshal the OldMessage, then unmarshal it into an empty NewMessage. - if b, err = Marshal(om); err != nil { - t.Fatalf("Marshal of OldMessage: %v", err) - } - t.Logf("Marshal(%v) -> %q", om, b) - nm2 := new(NewMessage) - if err := Unmarshal(b, nm2); err != nil { - t.Fatalf("Unmarshal to NewMessage: %v", err) - } - if !Equal(nm, nm2) { - t.Errorf("NewMessage round-trip: %v => %v", nm, nm2) - } -} - -// Check that an int32 field can be upgraded to an int64 field. -func TestNegativeInt32(t *testing.T) { - om := &OldMessage{ - Num: Int32(-1), - } - b, err := Marshal(om) - if err != nil { - t.Fatalf("Marshal of OldMessage: %v", err) - } - - // Check the size. It should be 11 bytes; - // 1 for the field/wire type, and 10 for the negative number. - if len(b) != 11 { - t.Errorf("%v marshaled as %q, wanted 11 bytes", om, b) - } - - // Unmarshal into a NewMessage. - nm := new(NewMessage) - if err := Unmarshal(b, nm); err != nil { - t.Fatalf("Unmarshal to NewMessage: %v", err) - } - want := &NewMessage{ - Num: Int64(-1), - } - if !Equal(nm, want) { - t.Errorf("nm = %v, want %v", nm, want) - } -} - -// Check that we can grow an array (repeated field) to have many elements. -// This test doesn't depend only on our encoding; for variety, it makes sure -// we create, encode, and decode the correct contents explicitly. It's therefore -// a bit messier. -// This test also uses (and hence tests) the Marshal/Unmarshal functions -// instead of the methods. -func TestBigRepeated(t *testing.T) { - pb := initGoTest(true) - - // Create the arrays - const N = 50 // Internally the library starts much smaller. - pb.Repeatedgroup = make([]*GoTest_RepeatedGroup, N) - pb.F_Sint64Repeated = make([]int64, N) - pb.F_Sint32Repeated = make([]int32, N) - pb.F_BytesRepeated = make([][]byte, N) - pb.F_StringRepeated = make([]string, N) - pb.F_DoubleRepeated = make([]float64, N) - pb.F_FloatRepeated = make([]float32, N) - pb.F_Uint64Repeated = make([]uint64, N) - pb.F_Uint32Repeated = make([]uint32, N) - pb.F_Fixed64Repeated = make([]uint64, N) - pb.F_Fixed32Repeated = make([]uint32, N) - pb.F_Int64Repeated = make([]int64, N) - pb.F_Int32Repeated = make([]int32, N) - pb.F_BoolRepeated = make([]bool, N) - pb.RepeatedField = make([]*GoTestField, N) - - // Fill in the arrays with checkable values. - igtf := initGoTestField() - igtrg := initGoTest_RepeatedGroup() - for i := 0; i < N; i++ { - pb.Repeatedgroup[i] = igtrg - pb.F_Sint64Repeated[i] = int64(i) - pb.F_Sint32Repeated[i] = int32(i) - s := fmt.Sprint(i) - pb.F_BytesRepeated[i] = []byte(s) - pb.F_StringRepeated[i] = s - pb.F_DoubleRepeated[i] = float64(i) - pb.F_FloatRepeated[i] = float32(i) - pb.F_Uint64Repeated[i] = uint64(i) - pb.F_Uint32Repeated[i] = uint32(i) - pb.F_Fixed64Repeated[i] = uint64(i) - pb.F_Fixed32Repeated[i] = uint32(i) - pb.F_Int64Repeated[i] = int64(i) - pb.F_Int32Repeated[i] = int32(i) - pb.F_BoolRepeated[i] = i%2 == 0 - pb.RepeatedField[i] = igtf - } - - // Marshal. - buf, _ := Marshal(pb) - - // Now test Unmarshal by recreating the original buffer. - pbd := new(GoTest) - Unmarshal(buf, pbd) - - // Check the checkable values - for i := uint64(0); i < N; i++ { - if pbd.Repeatedgroup[i] == nil { // TODO: more checking? - t.Error("pbd.Repeatedgroup bad") - } - if x := uint64(pbd.F_Sint64Repeated[i]); x != i { - t.Error("pbd.F_Sint64Repeated bad", x, i) - } - if x := uint64(pbd.F_Sint32Repeated[i]); x != i { - t.Error("pbd.F_Sint32Repeated bad", x, i) - } - s := fmt.Sprint(i) - equalbytes(pbd.F_BytesRepeated[i], []byte(s), t) - if pbd.F_StringRepeated[i] != s { - t.Error("pbd.F_Sint32Repeated bad", pbd.F_StringRepeated[i], i) - } - if x := uint64(pbd.F_DoubleRepeated[i]); x != i { - t.Error("pbd.F_DoubleRepeated bad", x, i) - } - if x := uint64(pbd.F_FloatRepeated[i]); x != i { - t.Error("pbd.F_FloatRepeated bad", x, i) - } - if x := pbd.F_Uint64Repeated[i]; x != i { - t.Error("pbd.F_Uint64Repeated bad", x, i) - } - if x := uint64(pbd.F_Uint32Repeated[i]); x != i { - t.Error("pbd.F_Uint32Repeated bad", x, i) - } - if x := pbd.F_Fixed64Repeated[i]; x != i { - t.Error("pbd.F_Fixed64Repeated bad", x, i) - } - if x := uint64(pbd.F_Fixed32Repeated[i]); x != i { - t.Error("pbd.F_Fixed32Repeated bad", x, i) - } - if x := uint64(pbd.F_Int64Repeated[i]); x != i { - t.Error("pbd.F_Int64Repeated bad", x, i) - } - if x := uint64(pbd.F_Int32Repeated[i]); x != i { - t.Error("pbd.F_Int32Repeated bad", x, i) - } - if x := pbd.F_BoolRepeated[i]; x != (i%2 == 0) { - t.Error("pbd.F_BoolRepeated bad", x, i) - } - if pbd.RepeatedField[i] == nil { // TODO: more checking? - t.Error("pbd.RepeatedField bad") - } - } -} - -func TestBadWireTypeUnknown(t *testing.T) { - var b []byte - fmt.Sscanf("0a01780d00000000080b101612036161611521000000202c220362626225370000002203636363214200000000000000584d5a036464645900000000000056405d63000000", "%x", &b) - - m := new(MyMessage) - if err := Unmarshal(b, m); err != nil { - t.Errorf("unexpected Unmarshal error: %v", err) - } - - var unknown []byte - fmt.Sscanf("0a01780d0000000010161521000000202c2537000000214200000000000000584d5a036464645d63000000", "%x", &unknown) - if !bytes.Equal(m.XXX_unrecognized, unknown) { - t.Errorf("unknown bytes mismatch:\ngot %x\nwant %x", m.XXX_unrecognized, unknown) - } - DiscardUnknown(m) - - want := &MyMessage{Count: Int32(11), Name: String("aaa"), Pet: []string{"bbb", "ccc"}, Bigfloat: Float64(88)} - if !Equal(m, want) { - t.Errorf("message mismatch:\ngot %v\nwant %v", m, want) - } -} - -func encodeDecode(t *testing.T, in, out Message, msg string) { - buf, err := Marshal(in) - if err != nil { - t.Fatalf("failed marshaling %v: %v", msg, err) - } - if err := Unmarshal(buf, out); err != nil { - t.Fatalf("failed unmarshaling %v: %v", msg, err) - } -} - -func TestPackedNonPackedDecoderSwitching(t *testing.T) { - np, p := new(NonPackedTest), new(PackedTest) - - // non-packed -> packed - np.A = []int32{0, 1, 1, 2, 3, 5} - encodeDecode(t, np, p, "non-packed -> packed") - if !reflect.DeepEqual(np.A, p.B) { - t.Errorf("failed non-packed -> packed; np.A=%+v, p.B=%+v", np.A, p.B) - } - - // packed -> non-packed - np.Reset() - p.B = []int32{3, 1, 4, 1, 5, 9} - encodeDecode(t, p, np, "packed -> non-packed") - if !reflect.DeepEqual(p.B, np.A) { - t.Errorf("failed packed -> non-packed; p.B=%+v, np.A=%+v", p.B, np.A) - } -} - -func TestProto1RepeatedGroup(t *testing.T) { - pb := &MessageList{ - Message: []*MessageList_Message{ - { - Name: String("blah"), - Count: Int32(7), - }, - // NOTE: pb.Message[1] is a nil - nil, - }, - } - - o := old() - err := o.Marshal(pb) - if err == nil || !strings.Contains(err.Error(), "repeated field Message has nil") { - t.Fatalf("unexpected or no error when marshaling: %v", err) - } -} - -// Test that enums work. Checks for a bug introduced by making enums -// named types instead of int32: newInt32FromUint64 would crash with -// a type mismatch in reflect.PointTo. -func TestEnum(t *testing.T) { - pb := new(GoEnum) - pb.Foo = FOO_FOO1.Enum() - o := old() - if err := o.Marshal(pb); err != nil { - t.Fatal("error encoding enum:", err) - } - pb1 := new(GoEnum) - if err := o.Unmarshal(pb1); err != nil { - t.Fatal("error decoding enum:", err) - } - if *pb1.Foo != FOO_FOO1 { - t.Error("expected 7 but got ", *pb1.Foo) - } -} - -// Enum types have String methods. Check that enum fields can be printed. -// We don't care what the value actually is, just as long as it doesn't crash. -func TestPrintingNilEnumFields(t *testing.T) { - pb := new(GoEnum) - _ = fmt.Sprintf("%+v", pb) -} - -// Verify that absent required fields cause Marshal/Unmarshal to return errors. -func TestRequiredFieldEnforcement(t *testing.T) { - pb := new(GoTestField) - _, err := Marshal(pb) - if err == nil { - t.Error("marshal: expected error, got nil") - } else if _, ok := err.(*RequiredNotSetError); !ok || !strings.Contains(err.Error(), "Label") { - t.Errorf("marshal: bad error type: %v", err) - } - - // A slightly sneaky, yet valid, proto. It encodes the same required field twice, - // so simply counting the required fields is insufficient. - // field 1, encoding 2, value "hi" - buf := []byte("\x0A\x02hi\x0A\x02hi") - err = Unmarshal(buf, pb) - if err == nil { - t.Error("unmarshal: expected error, got nil") - } else if _, ok := err.(*RequiredNotSetError); !ok || !strings.Contains(err.Error(), "Type") && !strings.Contains(err.Error(), "{Unknown}") { - // TODO: remove unknown cases once we commit to the new unmarshaler. - t.Errorf("unmarshal: bad error type: %v", err) - } -} - -// Verify that absent required fields in groups cause Marshal/Unmarshal to return errors. -func TestRequiredFieldEnforcementGroups(t *testing.T) { - pb := &GoTestRequiredGroupField{Group: &GoTestRequiredGroupField_Group{}} - if _, err := Marshal(pb); err == nil { - t.Error("marshal: expected error, got nil") - } else if _, ok := err.(*RequiredNotSetError); !ok || !strings.Contains(err.Error(), "Group.Field") { - t.Errorf("marshal: bad error type: %v", err) - } - - buf := []byte{11, 12} - if err := Unmarshal(buf, pb); err == nil { - t.Error("unmarshal: expected error, got nil") - } else if _, ok := err.(*RequiredNotSetError); !ok || !strings.Contains(err.Error(), "Group.Field") && !strings.Contains(err.Error(), "Group.{Unknown}") { - t.Errorf("unmarshal: bad error type: %v", err) - } -} - -func TestTypedNilMarshal(t *testing.T) { - // A typed nil should return ErrNil and not crash. - { - var m *GoEnum - if _, err := Marshal(m); err != ErrNil { - t.Errorf("Marshal(%#v): got %v, want ErrNil", m, err) - } - } - - { - m := &Communique{Union: &Communique_Msg{nil}} - if _, err := Marshal(m); err == nil || err == ErrNil { - t.Errorf("Marshal(%#v): got %v, want errOneofHasNil", m, err) - } - } -} - -// A type that implements the Marshaler interface, but is not nillable. -type nonNillableInt uint64 - -func (nni nonNillableInt) Marshal() ([]byte, error) { - return EncodeVarint(uint64(nni)), nil -} - -type NNIMessage struct { - nni nonNillableInt -} - -func (*NNIMessage) Reset() {} -func (*NNIMessage) String() string { return "" } -func (*NNIMessage) ProtoMessage() {} - -type NMMessage struct{} - -func (*NMMessage) Reset() {} -func (*NMMessage) String() string { return "" } -func (*NMMessage) ProtoMessage() {} - -// Verify a type that uses the Marshaler interface, but has a nil pointer. -func TestNilMarshaler(t *testing.T) { - // Try a struct with a Marshaler field that is nil. - // It should be directly marshable. - nmm := new(NMMessage) - if _, err := Marshal(nmm); err != nil { - t.Error("unexpected error marshaling nmm: ", err) - } - - // Try a struct with a Marshaler field that is not nillable. - nnim := new(NNIMessage) - nnim.nni = 7 - var _ Marshaler = nnim.nni // verify it is truly a Marshaler - if _, err := Marshal(nnim); err != nil { - t.Error("unexpected error marshaling nnim: ", err) - } -} - -func TestAllSetDefaults(t *testing.T) { - // Exercise SetDefaults with all scalar field types. - m := &Defaults{ - // NaN != NaN, so override that here. - F_Nan: Float32(1.7), - } - expected := &Defaults{ - F_Bool: Bool(true), - F_Int32: Int32(32), - F_Int64: Int64(64), - F_Fixed32: Uint32(320), - F_Fixed64: Uint64(640), - F_Uint32: Uint32(3200), - F_Uint64: Uint64(6400), - F_Float: Float32(314159), - F_Double: Float64(271828), - F_String: String(`hello, "world!"` + "\n"), - F_Bytes: []byte("Bignose"), - F_Sint32: Int32(-32), - F_Sint64: Int64(-64), - F_Enum: Defaults_GREEN.Enum(), - F_Pinf: Float32(float32(math.Inf(1))), - F_Ninf: Float32(float32(math.Inf(-1))), - F_Nan: Float32(1.7), - StrZero: String(""), - } - SetDefaults(m) - if !Equal(m, expected) { - t.Errorf("SetDefaults failed\n got %v\nwant %v", m, expected) - } -} - -func TestSetDefaultsWithSetField(t *testing.T) { - // Check that a set value is not overridden. - m := &Defaults{ - F_Int32: Int32(12), - } - SetDefaults(m) - if v := m.GetF_Int32(); v != 12 { - t.Errorf("m.FInt32 = %v, want 12", v) - } -} - -func TestSetDefaultsWithSubMessage(t *testing.T) { - m := &OtherMessage{ - Key: Int64(123), - Inner: &InnerMessage{ - Host: String("gopher"), - }, - } - expected := &OtherMessage{ - Key: Int64(123), - Inner: &InnerMessage{ - Host: String("gopher"), - Port: Int32(4000), - }, - } - SetDefaults(m) - if !Equal(m, expected) { - t.Errorf("\n got %v\nwant %v", m, expected) - } -} - -func TestSetDefaultsWithRepeatedSubMessage(t *testing.T) { - m := &MyMessage{ - RepInner: []*InnerMessage{{}}, - } - expected := &MyMessage{ - RepInner: []*InnerMessage{{ - Port: Int32(4000), - }}, - } - SetDefaults(m) - if !Equal(m, expected) { - t.Errorf("\n got %v\nwant %v", m, expected) - } -} - -func TestSetDefaultWithRepeatedNonMessage(t *testing.T) { - m := &MyMessage{ - Pet: []string{"turtle", "wombat"}, - } - expected := Clone(m) - SetDefaults(m) - if !Equal(m, expected) { - t.Errorf("\n got %v\nwant %v", m, expected) - } -} - -func TestMaximumTagNumber(t *testing.T) { - m := &MaxTag{ - LastField: String("natural goat essence"), - } - buf, err := Marshal(m) - if err != nil { - t.Fatalf("proto.Marshal failed: %v", err) - } - m2 := new(MaxTag) - if err := Unmarshal(buf, m2); err != nil { - t.Fatalf("proto.Unmarshal failed: %v", err) - } - if got, want := m2.GetLastField(), *m.LastField; got != want { - t.Errorf("got %q, want %q", got, want) - } -} - -func TestJSON(t *testing.T) { - m := &MyMessage{ - Count: Int32(4), - Pet: []string{"bunny", "kitty"}, - Inner: &InnerMessage{ - Host: String("cauchy"), - }, - Bikeshed: MyMessage_GREEN.Enum(), - } - const expected = `{"count":4,"pet":["bunny","kitty"],"inner":{"host":"cauchy"},"bikeshed":1}` - - b, err := json.Marshal(m) - if err != nil { - t.Fatalf("json.Marshal failed: %v", err) - } - s := string(b) - if s != expected { - t.Errorf("got %s\nwant %s", s, expected) - } - - received := new(MyMessage) - if err := json.Unmarshal(b, received); err != nil { - t.Fatalf("json.Unmarshal failed: %v", err) - } - if !Equal(received, m) { - t.Fatalf("got %s, want %s", received, m) - } - - // Test unmarshalling of JSON with symbolic enum name. - const old = `{"count":4,"pet":["bunny","kitty"],"inner":{"host":"cauchy"},"bikeshed":"GREEN"}` - received.Reset() - if err := json.Unmarshal([]byte(old), received); err != nil { - t.Fatalf("json.Unmarshal failed: %v", err) - } - if !Equal(received, m) { - t.Fatalf("got %s, want %s", received, m) - } -} - -func TestBadWireType(t *testing.T) { - b := []byte{7<<3 | 6} // field 7, wire type 6 - pb := new(OtherMessage) - if err := Unmarshal(b, pb); err == nil { - t.Errorf("Unmarshal did not fail") - } else if !strings.Contains(err.Error(), "unknown wire type") { - t.Errorf("wrong error: %v", err) - } -} - -func TestBytesWithInvalidLength(t *testing.T) { - // If a byte sequence has an invalid (negative) length, Unmarshal should not panic. - b := []byte{2<<3 | WireBytes, 0xff, 0xff, 0xff, 0xff, 0xff, 0} - Unmarshal(b, new(MyMessage)) -} - -func TestLengthOverflow(t *testing.T) { - // Overflowing a length should not panic. - b := []byte{2<<3 | WireBytes, 1, 1, 3<<3 | WireBytes, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x01} - Unmarshal(b, new(MyMessage)) -} - -func TestVarintOverflow(t *testing.T) { - // Overflowing a 64-bit length should not be allowed. - b := []byte{1<<3 | WireVarint, 0x01, 3<<3 | WireBytes, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01} - if err := Unmarshal(b, new(MyMessage)); err == nil { - t.Fatalf("Overflowed uint64 length without error") - } -} - -func TestBytesWithInvalidLengthInGroup(t *testing.T) { - // Overflowing a 64-bit length should not be allowed. - b := []byte{0xbb, 0x30, 0xb2, 0x30, 0xb0, 0xb2, 0x83, 0xf1, 0xb0, 0xb2, 0xef, 0xbf, 0xbd, 0x01} - if err := Unmarshal(b, new(MyMessage)); err == nil { - t.Fatalf("Overflowed uint64 length without error") - } -} - -func TestUnmarshalFuzz(t *testing.T) { - const N = 1000 - seed := time.Now().UnixNano() - t.Logf("RNG seed is %d", seed) - rng := rand.New(rand.NewSource(seed)) - buf := make([]byte, 20) - for i := 0; i < N; i++ { - for j := range buf { - buf[j] = byte(rng.Intn(256)) - } - fuzzUnmarshal(t, buf) - } -} - -func TestMergeMessages(t *testing.T) { - pb := &MessageList{Message: []*MessageList_Message{{Name: String("x"), Count: Int32(1)}}} - data, err := Marshal(pb) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - - pb1 := new(MessageList) - if err := Unmarshal(data, pb1); err != nil { - t.Fatalf("first Unmarshal: %v", err) - } - if err := Unmarshal(data, pb1); err != nil { - t.Fatalf("second Unmarshal: %v", err) - } - if len(pb1.Message) != 1 { - t.Errorf("two Unmarshals produced %d Messages, want 1", len(pb1.Message)) - } - - pb2 := new(MessageList) - if err := UnmarshalMerge(data, pb2); err != nil { - t.Fatalf("first UnmarshalMerge: %v", err) - } - if err := UnmarshalMerge(data, pb2); err != nil { - t.Fatalf("second UnmarshalMerge: %v", err) - } - if len(pb2.Message) != 2 { - t.Errorf("two UnmarshalMerges produced %d Messages, want 2", len(pb2.Message)) - } -} - -func TestExtensionMarshalOrder(t *testing.T) { - m := &MyMessage{Count: Int(123)} - if err := SetExtension(m, E_Ext_More, &Ext{Data: String("alpha")}); err != nil { - t.Fatalf("SetExtension: %v", err) - } - if err := SetExtension(m, E_Ext_Text, String("aleph")); err != nil { - t.Fatalf("SetExtension: %v", err) - } - if err := SetExtension(m, E_Ext_Number, Int32(1)); err != nil { - t.Fatalf("SetExtension: %v", err) - } - - // Serialize m several times, and check we get the same bytes each time. - var orig []byte - for i := 0; i < 100; i++ { - b, err := Marshal(m) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - if i == 0 { - orig = b - continue - } - if !bytes.Equal(b, orig) { - t.Errorf("Bytes differ on attempt #%d", i) - } - } -} - -func TestExtensionMapFieldMarshalDeterministic(t *testing.T) { - m := &MyMessage{Count: Int(123)} - if err := SetExtension(m, E_Ext_More, &Ext{MapField: map[int32]int32{1: 1, 2: 2, 3: 3, 4: 4}}); err != nil { - t.Fatalf("SetExtension: %v", err) - } - marshal := func(m Message) []byte { - var b Buffer - b.SetDeterministic(true) - if err := b.Marshal(m); err != nil { - t.Fatalf("Marshal failed: %v", err) - } - return b.Bytes() - } - - want := marshal(m) - for i := 0; i < 100; i++ { - if got := marshal(m); !bytes.Equal(got, want) { - t.Errorf("Marshal produced inconsistent output with determinism enabled (pass %d).\n got %v\nwant %v", i, got, want) - } - } -} - -// Many extensions, because small maps might not iterate differently on each iteration. -var exts = []*ExtensionDesc{ - E_X201, - E_X202, - E_X203, - E_X204, - E_X205, - E_X206, - E_X207, - E_X208, - E_X209, - E_X210, - E_X211, - E_X212, - E_X213, - E_X214, - E_X215, - E_X216, - E_X217, - E_X218, - E_X219, - E_X220, - E_X221, - E_X222, - E_X223, - E_X224, - E_X225, - E_X226, - E_X227, - E_X228, - E_X229, - E_X230, - E_X231, - E_X232, - E_X233, - E_X234, - E_X235, - E_X236, - E_X237, - E_X238, - E_X239, - E_X240, - E_X241, - E_X242, - E_X243, - E_X244, - E_X245, - E_X246, - E_X247, - E_X248, - E_X249, - E_X250, -} - -func TestMessageSetMarshalOrder(t *testing.T) { - m := &MyMessageSet{} - for _, x := range exts { - if err := SetExtension(m, x, &Empty{}); err != nil { - t.Fatalf("SetExtension: %v", err) - } - } - - buf, err := Marshal(m) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - - // Serialize m several times, and check we get the same bytes each time. - for i := 0; i < 10; i++ { - b1, err := Marshal(m) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - if !bytes.Equal(b1, buf) { - t.Errorf("Bytes differ on re-Marshal #%d", i) - } - - m2 := &MyMessageSet{} - if err := Unmarshal(buf, m2); err != nil { - t.Errorf("Unmarshal: %v", err) - } - b2, err := Marshal(m2) - if err != nil { - t.Errorf("re-Marshal: %v", err) - } - if !bytes.Equal(b2, buf) { - t.Errorf("Bytes differ on round-trip #%d", i) - } - } -} - -func TestUnmarshalMergesMessages(t *testing.T) { - // If a nested message occurs twice in the input, - // the fields should be merged when decoding. - a := &OtherMessage{ - Key: Int64(123), - Inner: &InnerMessage{ - Host: String("polhode"), - Port: Int32(1234), - }, - } - aData, err := Marshal(a) - if err != nil { - t.Fatalf("Marshal(a): %v", err) - } - b := &OtherMessage{ - Weight: Float32(1.2), - Inner: &InnerMessage{ - Host: String("herpolhode"), - Connected: Bool(true), - }, - } - bData, err := Marshal(b) - if err != nil { - t.Fatalf("Marshal(b): %v", err) - } - want := &OtherMessage{ - Key: Int64(123), - Weight: Float32(1.2), - Inner: &InnerMessage{ - Host: String("herpolhode"), - Port: Int32(1234), - Connected: Bool(true), - }, - } - got := new(OtherMessage) - if err := Unmarshal(append(aData, bData...), got); err != nil { - t.Fatalf("Unmarshal: %v", err) - } - if !Equal(got, want) { - t.Errorf("\n got %v\nwant %v", got, want) - } -} - -func TestUnmarshalMergesGroups(t *testing.T) { - // If a nested group occurs twice in the input, - // the fields should be merged when decoding. - a := &GroupNew{ - G: &GroupNew_G{ - X: Int32(7), - Y: Int32(8), - }, - } - aData, err := Marshal(a) - if err != nil { - t.Fatalf("Marshal(a): %v", err) - } - b := &GroupNew{ - G: &GroupNew_G{ - X: Int32(9), - }, - } - bData, err := Marshal(b) - if err != nil { - t.Fatalf("Marshal(b): %v", err) - } - want := &GroupNew{ - G: &GroupNew_G{ - X: Int32(9), - Y: Int32(8), - }, - } - got := new(GroupNew) - if err := Unmarshal(append(aData, bData...), got); err != nil { - t.Fatalf("Unmarshal: %v", err) - } - if !Equal(got, want) { - t.Errorf("\n got %v\nwant %v", got, want) - } -} - -func TestEncodingSizes(t *testing.T) { - tests := []struct { - m Message - n int - }{ - {&Defaults{F_Int32: Int32(math.MaxInt32)}, 6}, - {&Defaults{F_Int32: Int32(math.MinInt32)}, 11}, - {&Defaults{F_Uint32: Uint32(uint32(math.MaxInt32) + 1)}, 6}, - {&Defaults{F_Uint32: Uint32(math.MaxUint32)}, 6}, - } - for _, test := range tests { - b, err := Marshal(test.m) - if err != nil { - t.Errorf("Marshal(%v): %v", test.m, err) - continue - } - if len(b) != test.n { - t.Errorf("Marshal(%v) yielded %d bytes, want %d bytes", test.m, len(b), test.n) - } - } -} - -func TestRequiredNotSetError(t *testing.T) { - pb := initGoTest(false) - pb.RequiredField.Label = nil - pb.F_Int32Required = nil - pb.F_Int64Required = nil - - expected := "0807" + // field 1, encoding 0, value 7 - "2206" + "120474797065" + // field 4, encoding 2 (GoTestField) - "5001" + // field 10, encoding 0, value 1 - "6d20000000" + // field 13, encoding 5, value 0x20 - "714000000000000000" + // field 14, encoding 1, value 0x40 - "78a019" + // field 15, encoding 0, value 0xca0 = 3232 - "8001c032" + // field 16, encoding 0, value 0x1940 = 6464 - "8d0100004a45" + // field 17, encoding 5, value 3232.0 - "9101000000000040b940" + // field 18, encoding 1, value 6464.0 - "9a0106" + "737472696e67" + // field 19, encoding 2, string "string" - "b304" + // field 70, encoding 3, start group - "ba0408" + "7265717569726564" + // field 71, encoding 2, string "required" - "b404" + // field 70, encoding 4, end group - "aa0605" + "6279746573" + // field 101, encoding 2, string "bytes" - "b0063f" + // field 102, encoding 0, 0x3f zigzag32 - "b8067f" + // field 103, encoding 0, 0x7f zigzag64 - "c506e0ffffff" + // field 104, encoding 5, -32 fixed32 - "c906c0ffffffffffffff" // field 105, encoding 1, -64 fixed64 - - o := old() - bytes, err := Marshal(pb) - if _, ok := err.(*RequiredNotSetError); !ok { - fmt.Printf("marshal-1 err = %v, want *RequiredNotSetError", err) - o.DebugPrint("", bytes) - t.Fatalf("expected = %s", expected) - } - if !strings.Contains(err.Error(), "RequiredField.Label") { - t.Errorf("marshal-1 wrong err msg: %v", err) - } - if !equal(bytes, expected, t) { - o.DebugPrint("neq 1", bytes) - t.Fatalf("expected = %s", expected) - } - - // Now test Unmarshal by recreating the original buffer. - pbd := new(GoTest) - err = Unmarshal(bytes, pbd) - if _, ok := err.(*RequiredNotSetError); !ok { - t.Fatalf("unmarshal err = %v, want *RequiredNotSetError", err) - o.DebugPrint("", bytes) - t.Fatalf("string = %s", expected) - } - if !strings.Contains(err.Error(), "RequiredField.Label") && !strings.Contains(err.Error(), "RequiredField.{Unknown}") { - t.Errorf("unmarshal wrong err msg: %v", err) - } - bytes, err = Marshal(pbd) - if _, ok := err.(*RequiredNotSetError); !ok { - t.Errorf("marshal-2 err = %v, want *RequiredNotSetError", err) - o.DebugPrint("", bytes) - t.Fatalf("string = %s", expected) - } - if !strings.Contains(err.Error(), "RequiredField.Label") { - t.Errorf("marshal-2 wrong err msg: %v", err) - } - if !equal(bytes, expected, t) { - o.DebugPrint("neq 2", bytes) - t.Fatalf("string = %s", expected) - } -} - -func TestRequiredNotSetErrorWithBadWireTypes(t *testing.T) { - // Required field expects a varint, and properly found a varint. - if err := Unmarshal([]byte{0x08, 0x00}, new(GoEnum)); err != nil { - t.Errorf("Unmarshal = %v, want nil", err) - } - // Required field expects a varint, but found a fixed32 instead. - if err := Unmarshal([]byte{0x0d, 0x00, 0x00, 0x00, 0x00}, new(GoEnum)); err == nil { - t.Errorf("Unmarshal = nil, want RequiredNotSetError") - } - // Required field expects a varint, and found both a varint and fixed32 (ignored). - m := new(GoEnum) - if err := Unmarshal([]byte{0x08, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00}, m); err != nil { - t.Errorf("Unmarshal = %v, want nil", err) - } - if !bytes.Equal(m.XXX_unrecognized, []byte{0x0d, 0x00, 0x00, 0x00, 0x00}) { - t.Errorf("expected fixed32 to appear as unknown bytes: %x", m.XXX_unrecognized) - } -} - -func fuzzUnmarshal(t *testing.T, data []byte) { - defer func() { - if e := recover(); e != nil { - t.Errorf("These bytes caused a panic: %+v", data) - t.Logf("Stack:\n%s", debug.Stack()) - t.FailNow() - } - }() - - pb := new(MyMessage) - Unmarshal(data, pb) -} - -func TestMapFieldMarshal(t *testing.T) { - m := &MessageWithMap{ - NameMapping: map[int32]string{ - 1: "Rob", - 4: "Ian", - 8: "Dave", - }, - } - b, err := Marshal(m) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - - // b should be the concatenation of these three byte sequences in some order. - parts := []string{ - "\n\a\b\x01\x12\x03Rob", - "\n\a\b\x04\x12\x03Ian", - "\n\b\b\x08\x12\x04Dave", - } - ok := false - for i := range parts { - for j := range parts { - if j == i { - continue - } - for k := range parts { - if k == i || k == j { - continue - } - try := parts[i] + parts[j] + parts[k] - if bytes.Equal(b, []byte(try)) { - ok = true - break - } - } - } - } - if !ok { - t.Fatalf("Incorrect Marshal output.\n got %q\nwant %q (or a permutation of that)", b, parts[0]+parts[1]+parts[2]) - } - t.Logf("FYI b: %q", b) - - (new(Buffer)).DebugPrint("Dump of b", b) -} - -func TestMapFieldDeterministicMarshal(t *testing.T) { - m := &MessageWithMap{ - NameMapping: map[int32]string{ - 1: "Rob", - 4: "Ian", - 8: "Dave", - }, - } - - marshal := func(m Message) []byte { - var b Buffer - b.SetDeterministic(true) - if err := b.Marshal(m); err != nil { - t.Fatalf("Marshal failed: %v", err) - } - return b.Bytes() - } - - want := marshal(m) - for i := 0; i < 10; i++ { - if got := marshal(m); !bytes.Equal(got, want) { - t.Errorf("Marshal produced inconsistent output with determinism enabled (pass %d).\n got %v\nwant %v", i, got, want) - } - } -} - -func TestMapFieldRoundTrips(t *testing.T) { - m := &MessageWithMap{ - NameMapping: map[int32]string{ - 1: "Rob", - 4: "Ian", - 8: "Dave", - }, - MsgMapping: map[int64]*FloatingPoint{ - 0x7001: {F: Float64(2.0)}, - }, - ByteMapping: map[bool][]byte{ - false: []byte("that's not right!"), - true: []byte("aye, 'tis true!"), - }, - } - b, err := Marshal(m) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - t.Logf("FYI b: %q", b) - m2 := new(MessageWithMap) - if err := Unmarshal(b, m2); err != nil { - t.Fatalf("Unmarshal: %v", err) - } - if !Equal(m, m2) { - t.Errorf("Map did not survive a round trip.\ninitial: %v\n final: %v", m, m2) - } -} - -func TestMapFieldWithNil(t *testing.T) { - m1 := &MessageWithMap{ - MsgMapping: map[int64]*FloatingPoint{ - 1: nil, - }, - } - b, err := Marshal(m1) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - m2 := new(MessageWithMap) - if err := Unmarshal(b, m2); err != nil { - t.Fatalf("Unmarshal: %v, got these bytes: %v", err, b) - } - if v, ok := m2.MsgMapping[1]; !ok { - t.Error("msg_mapping[1] not present") - } else if v != nil { - t.Errorf("msg_mapping[1] not nil: %v", v) - } -} - -func TestMapFieldWithNilBytes(t *testing.T) { - m1 := &MessageWithMap{ - ByteMapping: map[bool][]byte{ - false: {}, - true: nil, - }, - } - n := Size(m1) - b, err := Marshal(m1) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - if n != len(b) { - t.Errorf("Size(m1) = %d; want len(Marshal(m1)) = %d", n, len(b)) - } - m2 := new(MessageWithMap) - if err := Unmarshal(b, m2); err != nil { - t.Fatalf("Unmarshal: %v, got these bytes: %v", err, b) - } - if v, ok := m2.ByteMapping[false]; !ok { - t.Error("byte_mapping[false] not present") - } else if len(v) != 0 { - t.Errorf("byte_mapping[false] not empty: %#v", v) - } - if v, ok := m2.ByteMapping[true]; !ok { - t.Error("byte_mapping[true] not present") - } else if len(v) != 0 { - t.Errorf("byte_mapping[true] not empty: %#v", v) - } -} - -func TestDecodeMapFieldMissingKey(t *testing.T) { - b := []byte{ - 0x0A, 0x03, // message, tag 1 (name_mapping), of length 3 bytes - // no key - 0x12, 0x01, 0x6D, // string value of length 1 byte, value "m" - } - got := &MessageWithMap{} - err := Unmarshal(b, got) - if err != nil { - t.Fatalf("failed to marshal map with missing key: %v", err) - } - want := &MessageWithMap{NameMapping: map[int32]string{0: "m"}} - if !Equal(got, want) { - t.Errorf("Unmarshaled map with no key was not as expected. got: %v, want %v", got, want) - } -} - -func TestDecodeMapFieldMissingValue(t *testing.T) { - b := []byte{ - 0x0A, 0x02, // message, tag 1 (name_mapping), of length 2 bytes - 0x08, 0x01, // varint key, value 1 - // no value - } - got := &MessageWithMap{} - err := Unmarshal(b, got) - if err != nil { - t.Fatalf("failed to marshal map with missing value: %v", err) - } - want := &MessageWithMap{NameMapping: map[int32]string{1: ""}} - if !Equal(got, want) { - t.Errorf("Unmarshaled map with no value was not as expected. got: %v, want %v", got, want) - } -} - -func TestOneof(t *testing.T) { - m := &Communique{} - b, err := Marshal(m) - if err != nil { - t.Fatalf("Marshal of empty message with oneof: %v", err) - } - if len(b) != 0 { - t.Errorf("Marshal of empty message yielded too many bytes: %v", b) - } - - m = &Communique{ - Union: &Communique_Name{"Barry"}, - } - - // Round-trip. - b, err = Marshal(m) - if err != nil { - t.Fatalf("Marshal of message with oneof: %v", err) - } - if len(b) != 7 { // name tag/wire (1) + name len (1) + name (5) - t.Errorf("Incorrect marshal of message with oneof: %v", b) - } - m.Reset() - if err := Unmarshal(b, m); err != nil { - t.Fatalf("Unmarshal of message with oneof: %v", err) - } - if x, ok := m.Union.(*Communique_Name); !ok || x.Name != "Barry" { - t.Errorf("After round trip, Union = %+v", m.Union) - } - if name := m.GetName(); name != "Barry" { - t.Errorf("After round trip, GetName = %q, want %q", name, "Barry") - } - - // Let's try with a message in the oneof. - m.Union = &Communique_Msg{&Strings{StringField: String("deep deep string")}} - b, err = Marshal(m) - if err != nil { - t.Fatalf("Marshal of message with oneof set to message: %v", err) - } - if len(b) != 20 { // msg tag/wire (1) + msg len (1) + msg (1 + 1 + 16) - t.Errorf("Incorrect marshal of message with oneof set to message: %v", b) - } - m.Reset() - if err := Unmarshal(b, m); err != nil { - t.Fatalf("Unmarshal of message with oneof set to message: %v", err) - } - ss, ok := m.Union.(*Communique_Msg) - if !ok || ss.Msg.GetStringField() != "deep deep string" { - t.Errorf("After round trip with oneof set to message, Union = %+v", m.Union) - } -} - -func TestOneofNilBytes(t *testing.T) { - // A oneof with nil byte slice should marshal to tag + 0 (size), with no error. - m := &Communique{Union: &Communique_Data{Data: nil}} - b, err := Marshal(m) - if err != nil { - t.Fatalf("Marshal failed: %v", err) - } - want := []byte{ - 7<<3 | 2, // tag 7, wire type 2 - 0, // size - } - if !bytes.Equal(b, want) { - t.Errorf("Wrong result of Marshal: got %x, want %x", b, want) - } -} - -func TestInefficientPackedBool(t *testing.T) { - // https://github.com/golang/protobuf/issues/76 - inp := []byte{ - 0x12, 0x02, // 0x12 = 2<<3|2; 2 bytes - // Usually a bool should take a single byte, - // but it is permitted to be any varint. - 0xb9, 0x30, - } - if err := Unmarshal(inp, new(MoreRepeated)); err != nil { - t.Error(err) - } -} - -// Make sure pure-reflect-based implementation handles -// []int32-[]enum conversion correctly. -func TestRepeatedEnum2(t *testing.T) { - pb := &RepeatedEnum{ - Color: []RepeatedEnum_Color{RepeatedEnum_RED}, - } - b, err := Marshal(pb) - if err != nil { - t.Fatalf("Marshal failed: %v", err) - } - x := new(RepeatedEnum) - err = Unmarshal(b, x) - if err != nil { - t.Fatalf("Unmarshal failed: %v", err) - } - if !Equal(pb, x) { - t.Errorf("Incorrect result: want: %v got: %v", pb, x) - } -} - -// TestConcurrentMarshal makes sure that it is safe to marshal -// same message in multiple goroutines concurrently. -func TestConcurrentMarshal(t *testing.T) { - pb := initGoTest(true) - const N = 100 - b := make([][]byte, N) - - var wg sync.WaitGroup - for i := 0; i < N; i++ { - wg.Add(1) - go func(i int) { - defer wg.Done() - var err error - b[i], err = Marshal(pb) - if err != nil { - t.Errorf("marshal error: %v", err) - } - }(i) - } - - wg.Wait() - for i := 1; i < N; i++ { - if !bytes.Equal(b[0], b[i]) { - t.Errorf("concurrent marshal result not same: b[0] = %v, b[%d] = %v", b[0], i, b[i]) - } - } -} - -func TestInvalidUTF8(t *testing.T) { - const invalidUTF8 = "\xde\xad\xbe\xef\x80\x00\xff" - tests := []struct { - label string - proto2 Message - proto3 Message - want []byte - }{{ - label: "Scalar", - proto2: &TestUTF8{Scalar: String(invalidUTF8)}, - proto3: &pb3.TestUTF8{Scalar: invalidUTF8}, - want: []byte{0x0a, 0x07, 0xde, 0xad, 0xbe, 0xef, 0x80, 0x00, 0xff}, - }, { - label: "Vector", - proto2: &TestUTF8{Vector: []string{invalidUTF8}}, - proto3: &pb3.TestUTF8{Vector: []string{invalidUTF8}}, - want: []byte{0x12, 0x07, 0xde, 0xad, 0xbe, 0xef, 0x80, 0x00, 0xff}, - }, { - label: "Oneof", - proto2: &TestUTF8{Oneof: &TestUTF8_Field{invalidUTF8}}, - proto3: &pb3.TestUTF8{Oneof: &pb3.TestUTF8_Field{invalidUTF8}}, - want: []byte{0x1a, 0x07, 0xde, 0xad, 0xbe, 0xef, 0x80, 0x00, 0xff}, - }, { - label: "MapKey", - proto2: &TestUTF8{MapKey: map[string]int64{invalidUTF8: 0}}, - proto3: &pb3.TestUTF8{MapKey: map[string]int64{invalidUTF8: 0}}, - want: []byte{0x22, 0x0b, 0x0a, 0x07, 0xde, 0xad, 0xbe, 0xef, 0x80, 0x00, 0xff, 0x10, 0x00}, - }, { - label: "MapValue", - proto2: &TestUTF8{MapValue: map[int64]string{0: invalidUTF8}}, - proto3: &pb3.TestUTF8{MapValue: map[int64]string{0: invalidUTF8}}, - want: []byte{0x2a, 0x0b, 0x08, 0x00, 0x12, 0x07, 0xde, 0xad, 0xbe, 0xef, 0x80, 0x00, 0xff}, - }} - - for _, tt := range tests { - // Proto2 should not validate UTF-8. - b, err := Marshal(tt.proto2) - if err != nil { - t.Errorf("Marshal(proto2.%s) = %v, want nil", tt.label, err) - } - if !bytes.Equal(b, tt.want) { - t.Errorf("Marshal(proto2.%s) = %x, want %x", tt.label, b, tt.want) - } - - m := Clone(tt.proto2) - m.Reset() - if err = Unmarshal(tt.want, m); err != nil { - t.Errorf("Unmarshal(proto2.%s) = %v, want nil", tt.label, err) - } - if !Equal(m, tt.proto2) { - t.Errorf("proto2.%s: output mismatch:\ngot %v\nwant %v", tt.label, m, tt.proto2) - } - - // Proto3 should validate UTF-8. - b, err = Marshal(tt.proto3) - if err == nil { - t.Errorf("Marshal(proto3.%s) = %v, want non-nil", tt.label, err) - } - if !bytes.Equal(b, tt.want) { - t.Errorf("Marshal(proto3.%s) = %x, want %x", tt.label, b, tt.want) - } - - m = Clone(tt.proto3) - m.Reset() - err = Unmarshal(tt.want, m) - if err == nil { - t.Errorf("Unmarshal(proto3.%s) = %v, want non-nil", tt.label, err) - } - if !Equal(m, tt.proto3) { - t.Errorf("proto3.%s: output mismatch:\ngot %v\nwant %v", tt.label, m, tt.proto2) - } - } -} - -func TestRequired(t *testing.T) { - // The F_BoolRequired field appears after all of the required fields. - // It should still be handled even after multiple required field violations. - m := &GoTest{F_BoolRequired: Bool(true)} - got, err := Marshal(m) - if _, ok := err.(*RequiredNotSetError); !ok { - t.Errorf("Marshal() = %v, want RequiredNotSetError error", err) - } - if want := []byte{0x50, 0x01}; !bytes.Equal(got, want) { - t.Errorf("Marshal() = %x, want %x", got, want) - } - - m = new(GoTest) - err = Unmarshal(got, m) - if _, ok := err.(*RequiredNotSetError); !ok { - t.Errorf("Marshal() = %v, want RequiredNotSetError error", err) - } - if !m.GetF_BoolRequired() { - t.Error("m.F_BoolRequired = false, want true") - } -} - -// Benchmarks - -func testMsg() *GoTest { - pb := initGoTest(true) - const N = 1000 // Internally the library starts much smaller. - pb.F_Int32Repeated = make([]int32, N) - pb.F_DoubleRepeated = make([]float64, N) - for i := 0; i < N; i++ { - pb.F_Int32Repeated[i] = int32(i) - pb.F_DoubleRepeated[i] = float64(i) - } - return pb -} - -func bytesMsg() *GoTest { - pb := initGoTest(true) - buf := make([]byte, 4000) - for i := range buf { - buf[i] = byte(i) - } - pb.F_BytesDefaulted = buf - return pb -} - -func benchmarkMarshal(b *testing.B, pb Message, marshal func(Message) ([]byte, error)) { - d, _ := marshal(pb) - b.SetBytes(int64(len(d))) - b.ResetTimer() - for i := 0; i < b.N; i++ { - marshal(pb) - } -} - -func benchmarkBufferMarshal(b *testing.B, pb Message) { - p := NewBuffer(nil) - benchmarkMarshal(b, pb, func(pb0 Message) ([]byte, error) { - p.Reset() - err := p.Marshal(pb0) - return p.Bytes(), err - }) -} - -func benchmarkSize(b *testing.B, pb Message) { - benchmarkMarshal(b, pb, func(pb0 Message) ([]byte, error) { - Size(pb) - return nil, nil - }) -} - -func newOf(pb Message) Message { - in := reflect.ValueOf(pb) - if in.IsNil() { - return pb - } - return reflect.New(in.Type().Elem()).Interface().(Message) -} - -func benchmarkUnmarshal(b *testing.B, pb Message, unmarshal func([]byte, Message) error) { - d, _ := Marshal(pb) - b.SetBytes(int64(len(d))) - pbd := newOf(pb) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - unmarshal(d, pbd) - } -} - -func benchmarkBufferUnmarshal(b *testing.B, pb Message) { - p := NewBuffer(nil) - benchmarkUnmarshal(b, pb, func(d []byte, pb0 Message) error { - p.SetBuf(d) - return p.Unmarshal(pb0) - }) -} - -// Benchmark{Marshal,BufferMarshal,Size,Unmarshal,BufferUnmarshal}{,Bytes} - -func BenchmarkMarshal(b *testing.B) { - benchmarkMarshal(b, testMsg(), Marshal) -} - -func BenchmarkBufferMarshal(b *testing.B) { - benchmarkBufferMarshal(b, testMsg()) -} - -func BenchmarkSize(b *testing.B) { - benchmarkSize(b, testMsg()) -} - -func BenchmarkUnmarshal(b *testing.B) { - benchmarkUnmarshal(b, testMsg(), Unmarshal) -} - -func BenchmarkBufferUnmarshal(b *testing.B) { - benchmarkBufferUnmarshal(b, testMsg()) -} - -func BenchmarkMarshalBytes(b *testing.B) { - benchmarkMarshal(b, bytesMsg(), Marshal) -} - -func BenchmarkBufferMarshalBytes(b *testing.B) { - benchmarkBufferMarshal(b, bytesMsg()) -} - -func BenchmarkSizeBytes(b *testing.B) { - benchmarkSize(b, bytesMsg()) -} - -func BenchmarkUnmarshalBytes(b *testing.B) { - benchmarkUnmarshal(b, bytesMsg(), Unmarshal) -} - -func BenchmarkBufferUnmarshalBytes(b *testing.B) { - benchmarkBufferUnmarshal(b, bytesMsg()) -} - -func BenchmarkUnmarshalUnrecognizedFields(b *testing.B) { - b.StopTimer() - pb := initGoTestField() - skip := &GoSkipTest{ - SkipInt32: Int32(32), - SkipFixed32: Uint32(3232), - SkipFixed64: Uint64(6464), - SkipString: String("skipper"), - Skipgroup: &GoSkipTest_SkipGroup{ - GroupInt32: Int32(75), - GroupString: String("wxyz"), - }, - } - - pbd := new(GoTestField) - p := NewBuffer(nil) - p.Marshal(pb) - p.Marshal(skip) - p2 := NewBuffer(nil) - - b.StartTimer() - for i := 0; i < b.N; i++ { - p2.SetBuf(p.Bytes()) - p2.Unmarshal(pbd) - } -} diff --git a/vendor/github.com/golang/protobuf/proto/any_test.go b/vendor/github.com/golang/protobuf/proto/any_test.go deleted file mode 100644 index 56fc97c1..00000000 --- a/vendor/github.com/golang/protobuf/proto/any_test.go +++ /dev/null @@ -1,300 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2016 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto_test - -import ( - "strings" - "testing" - - "github.com/golang/protobuf/proto" - - pb "github.com/golang/protobuf/proto/proto3_proto" - testpb "github.com/golang/protobuf/proto/test_proto" - anypb "github.com/golang/protobuf/ptypes/any" -) - -var ( - expandedMarshaler = proto.TextMarshaler{ExpandAny: true} - expandedCompactMarshaler = proto.TextMarshaler{Compact: true, ExpandAny: true} -) - -// anyEqual reports whether two messages which may be google.protobuf.Any or may -// contain google.protobuf.Any fields are equal. We can't use proto.Equal for -// comparison, because semantically equivalent messages may be marshaled to -// binary in different tag order. Instead, trust that TextMarshaler with -// ExpandAny option works and compare the text marshaling results. -func anyEqual(got, want proto.Message) bool { - // if messages are proto.Equal, no need to marshal. - if proto.Equal(got, want) { - return true - } - g := expandedMarshaler.Text(got) - w := expandedMarshaler.Text(want) - return g == w -} - -type golden struct { - m proto.Message - t, c string -} - -var goldenMessages = makeGolden() - -func makeGolden() []golden { - nested := &pb.Nested{Bunny: "Monty"} - nb, err := proto.Marshal(nested) - if err != nil { - panic(err) - } - m1 := &pb.Message{ - Name: "David", - ResultCount: 47, - Anything: &anypb.Any{TypeUrl: "type.googleapis.com/" + proto.MessageName(nested), Value: nb}, - } - m2 := &pb.Message{ - Name: "David", - ResultCount: 47, - Anything: &anypb.Any{TypeUrl: "http://[::1]/type.googleapis.com/" + proto.MessageName(nested), Value: nb}, - } - m3 := &pb.Message{ - Name: "David", - ResultCount: 47, - Anything: &anypb.Any{TypeUrl: `type.googleapis.com/"/` + proto.MessageName(nested), Value: nb}, - } - m4 := &pb.Message{ - Name: "David", - ResultCount: 47, - Anything: &anypb.Any{TypeUrl: "type.googleapis.com/a/path/" + proto.MessageName(nested), Value: nb}, - } - m5 := &anypb.Any{TypeUrl: "type.googleapis.com/" + proto.MessageName(nested), Value: nb} - - any1 := &testpb.MyMessage{Count: proto.Int32(47), Name: proto.String("David")} - proto.SetExtension(any1, testpb.E_Ext_More, &testpb.Ext{Data: proto.String("foo")}) - proto.SetExtension(any1, testpb.E_Ext_Text, proto.String("bar")) - any1b, err := proto.Marshal(any1) - if err != nil { - panic(err) - } - any2 := &testpb.MyMessage{Count: proto.Int32(42), Bikeshed: testpb.MyMessage_GREEN.Enum(), RepBytes: [][]byte{[]byte("roboto")}} - proto.SetExtension(any2, testpb.E_Ext_More, &testpb.Ext{Data: proto.String("baz")}) - any2b, err := proto.Marshal(any2) - if err != nil { - panic(err) - } - m6 := &pb.Message{ - Name: "David", - ResultCount: 47, - Anything: &anypb.Any{TypeUrl: "type.googleapis.com/" + proto.MessageName(any1), Value: any1b}, - ManyThings: []*anypb.Any{ - &anypb.Any{TypeUrl: "type.googleapis.com/" + proto.MessageName(any2), Value: any2b}, - &anypb.Any{TypeUrl: "type.googleapis.com/" + proto.MessageName(any1), Value: any1b}, - }, - } - - const ( - m1Golden = ` -name: "David" -result_count: 47 -anything: < - [type.googleapis.com/proto3_proto.Nested]: < - bunny: "Monty" - > -> -` - m2Golden = ` -name: "David" -result_count: 47 -anything: < - ["http://[::1]/type.googleapis.com/proto3_proto.Nested"]: < - bunny: "Monty" - > -> -` - m3Golden = ` -name: "David" -result_count: 47 -anything: < - ["type.googleapis.com/\"/proto3_proto.Nested"]: < - bunny: "Monty" - > -> -` - m4Golden = ` -name: "David" -result_count: 47 -anything: < - [type.googleapis.com/a/path/proto3_proto.Nested]: < - bunny: "Monty" - > -> -` - m5Golden = ` -[type.googleapis.com/proto3_proto.Nested]: < - bunny: "Monty" -> -` - m6Golden = ` -name: "David" -result_count: 47 -anything: < - [type.googleapis.com/test_proto.MyMessage]: < - count: 47 - name: "David" - [test_proto.Ext.more]: < - data: "foo" - > - [test_proto.Ext.text]: "bar" - > -> -many_things: < - [type.googleapis.com/test_proto.MyMessage]: < - count: 42 - bikeshed: GREEN - rep_bytes: "roboto" - [test_proto.Ext.more]: < - data: "baz" - > - > -> -many_things: < - [type.googleapis.com/test_proto.MyMessage]: < - count: 47 - name: "David" - [test_proto.Ext.more]: < - data: "foo" - > - [test_proto.Ext.text]: "bar" - > -> -` - ) - return []golden{ - {m1, strings.TrimSpace(m1Golden) + "\n", strings.TrimSpace(compact(m1Golden)) + " "}, - {m2, strings.TrimSpace(m2Golden) + "\n", strings.TrimSpace(compact(m2Golden)) + " "}, - {m3, strings.TrimSpace(m3Golden) + "\n", strings.TrimSpace(compact(m3Golden)) + " "}, - {m4, strings.TrimSpace(m4Golden) + "\n", strings.TrimSpace(compact(m4Golden)) + " "}, - {m5, strings.TrimSpace(m5Golden) + "\n", strings.TrimSpace(compact(m5Golden)) + " "}, - {m6, strings.TrimSpace(m6Golden) + "\n", strings.TrimSpace(compact(m6Golden)) + " "}, - } -} - -func TestMarshalGolden(t *testing.T) { - for _, tt := range goldenMessages { - if got, want := expandedMarshaler.Text(tt.m), tt.t; got != want { - t.Errorf("message %v: got:\n%s\nwant:\n%s", tt.m, got, want) - } - if got, want := expandedCompactMarshaler.Text(tt.m), tt.c; got != want { - t.Errorf("message %v: got:\n`%s`\nwant:\n`%s`", tt.m, got, want) - } - } -} - -func TestUnmarshalGolden(t *testing.T) { - for _, tt := range goldenMessages { - want := tt.m - got := proto.Clone(tt.m) - got.Reset() - if err := proto.UnmarshalText(tt.t, got); err != nil { - t.Errorf("failed to unmarshal\n%s\nerror: %v", tt.t, err) - } - if !anyEqual(got, want) { - t.Errorf("message:\n%s\ngot:\n%s\nwant:\n%s", tt.t, got, want) - } - got.Reset() - if err := proto.UnmarshalText(tt.c, got); err != nil { - t.Errorf("failed to unmarshal\n%s\nerror: %v", tt.c, err) - } - if !anyEqual(got, want) { - t.Errorf("message:\n%s\ngot:\n%s\nwant:\n%s", tt.c, got, want) - } - } -} - -func TestMarshalUnknownAny(t *testing.T) { - m := &pb.Message{ - Anything: &anypb.Any{ - TypeUrl: "foo", - Value: []byte("bar"), - }, - } - want := `anything: < - type_url: "foo" - value: "bar" -> -` - got := expandedMarshaler.Text(m) - if got != want { - t.Errorf("got\n`%s`\nwant\n`%s`", got, want) - } -} - -func TestAmbiguousAny(t *testing.T) { - pb := &anypb.Any{} - err := proto.UnmarshalText(` - type_url: "ttt/proto3_proto.Nested" - value: "\n\x05Monty" - `, pb) - t.Logf("result: %v (error: %v)", expandedMarshaler.Text(pb), err) - if err != nil { - t.Errorf("failed to parse ambiguous Any message: %v", err) - } -} - -func TestUnmarshalOverwriteAny(t *testing.T) { - pb := &anypb.Any{} - err := proto.UnmarshalText(` - [type.googleapis.com/a/path/proto3_proto.Nested]: < - bunny: "Monty" - > - [type.googleapis.com/a/path/proto3_proto.Nested]: < - bunny: "Rabbit of Caerbannog" - > - `, pb) - want := `line 7: Any message unpacked multiple times, or "type_url" already set` - if err.Error() != want { - t.Errorf("incorrect error.\nHave: %v\nWant: %v", err.Error(), want) - } -} - -func TestUnmarshalAnyMixAndMatch(t *testing.T) { - pb := &anypb.Any{} - err := proto.UnmarshalText(` - value: "\n\x05Monty" - [type.googleapis.com/a/path/proto3_proto.Nested]: < - bunny: "Rabbit of Caerbannog" - > - `, pb) - want := `line 5: Any message unpacked multiple times, or "value" already set` - if err.Error() != want { - t.Errorf("incorrect error.\nHave: %v\nWant: %v", err.Error(), want) - } -} diff --git a/vendor/github.com/golang/protobuf/proto/clone_test.go b/vendor/github.com/golang/protobuf/proto/clone_test.go deleted file mode 100644 index 0d3b1273..00000000 --- a/vendor/github.com/golang/protobuf/proto/clone_test.go +++ /dev/null @@ -1,390 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2011 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto_test - -import ( - "testing" - - "github.com/golang/protobuf/proto" - - proto3pb "github.com/golang/protobuf/proto/proto3_proto" - pb "github.com/golang/protobuf/proto/test_proto" -) - -var cloneTestMessage = &pb.MyMessage{ - Count: proto.Int32(42), - Name: proto.String("Dave"), - Pet: []string{"bunny", "kitty", "horsey"}, - Inner: &pb.InnerMessage{ - Host: proto.String("niles"), - Port: proto.Int32(9099), - Connected: proto.Bool(true), - }, - Others: []*pb.OtherMessage{ - { - Value: []byte("some bytes"), - }, - }, - Somegroup: &pb.MyMessage_SomeGroup{ - GroupField: proto.Int32(6), - }, - RepBytes: [][]byte{[]byte("sham"), []byte("wow")}, -} - -func init() { - ext := &pb.Ext{ - Data: proto.String("extension"), - } - if err := proto.SetExtension(cloneTestMessage, pb.E_Ext_More, ext); err != nil { - panic("SetExtension: " + err.Error()) - } -} - -func TestClone(t *testing.T) { - m := proto.Clone(cloneTestMessage).(*pb.MyMessage) - if !proto.Equal(m, cloneTestMessage) { - t.Fatalf("Clone(%v) = %v", cloneTestMessage, m) - } - - // Verify it was a deep copy. - *m.Inner.Port++ - if proto.Equal(m, cloneTestMessage) { - t.Error("Mutating clone changed the original") - } - // Byte fields and repeated fields should be copied. - if &m.Pet[0] == &cloneTestMessage.Pet[0] { - t.Error("Pet: repeated field not copied") - } - if &m.Others[0] == &cloneTestMessage.Others[0] { - t.Error("Others: repeated field not copied") - } - if &m.Others[0].Value[0] == &cloneTestMessage.Others[0].Value[0] { - t.Error("Others[0].Value: bytes field not copied") - } - if &m.RepBytes[0] == &cloneTestMessage.RepBytes[0] { - t.Error("RepBytes: repeated field not copied") - } - if &m.RepBytes[0][0] == &cloneTestMessage.RepBytes[0][0] { - t.Error("RepBytes[0]: bytes field not copied") - } -} - -func TestCloneNil(t *testing.T) { - var m *pb.MyMessage - if c := proto.Clone(m); !proto.Equal(m, c) { - t.Errorf("Clone(%v) = %v", m, c) - } -} - -var mergeTests = []struct { - src, dst, want proto.Message -}{ - { - src: &pb.MyMessage{ - Count: proto.Int32(42), - }, - dst: &pb.MyMessage{ - Name: proto.String("Dave"), - }, - want: &pb.MyMessage{ - Count: proto.Int32(42), - Name: proto.String("Dave"), - }, - }, - { - src: &pb.MyMessage{ - Inner: &pb.InnerMessage{ - Host: proto.String("hey"), - Connected: proto.Bool(true), - }, - Pet: []string{"horsey"}, - Others: []*pb.OtherMessage{ - { - Value: []byte("some bytes"), - }, - }, - }, - dst: &pb.MyMessage{ - Inner: &pb.InnerMessage{ - Host: proto.String("niles"), - Port: proto.Int32(9099), - }, - Pet: []string{"bunny", "kitty"}, - Others: []*pb.OtherMessage{ - { - Key: proto.Int64(31415926535), - }, - { - // Explicitly test a src=nil field - Inner: nil, - }, - }, - }, - want: &pb.MyMessage{ - Inner: &pb.InnerMessage{ - Host: proto.String("hey"), - Connected: proto.Bool(true), - Port: proto.Int32(9099), - }, - Pet: []string{"bunny", "kitty", "horsey"}, - Others: []*pb.OtherMessage{ - { - Key: proto.Int64(31415926535), - }, - {}, - { - Value: []byte("some bytes"), - }, - }, - }, - }, - { - src: &pb.MyMessage{ - RepBytes: [][]byte{[]byte("wow")}, - }, - dst: &pb.MyMessage{ - Somegroup: &pb.MyMessage_SomeGroup{ - GroupField: proto.Int32(6), - }, - RepBytes: [][]byte{[]byte("sham")}, - }, - want: &pb.MyMessage{ - Somegroup: &pb.MyMessage_SomeGroup{ - GroupField: proto.Int32(6), - }, - RepBytes: [][]byte{[]byte("sham"), []byte("wow")}, - }, - }, - // Check that a scalar bytes field replaces rather than appends. - { - src: &pb.OtherMessage{Value: []byte("foo")}, - dst: &pb.OtherMessage{Value: []byte("bar")}, - want: &pb.OtherMessage{Value: []byte("foo")}, - }, - { - src: &pb.MessageWithMap{ - NameMapping: map[int32]string{6: "Nigel"}, - MsgMapping: map[int64]*pb.FloatingPoint{ - 0x4001: &pb.FloatingPoint{F: proto.Float64(2.0)}, - 0x4002: &pb.FloatingPoint{ - F: proto.Float64(2.0), - }, - }, - ByteMapping: map[bool][]byte{true: []byte("wowsa")}, - }, - dst: &pb.MessageWithMap{ - NameMapping: map[int32]string{ - 6: "Bruce", // should be overwritten - 7: "Andrew", - }, - MsgMapping: map[int64]*pb.FloatingPoint{ - 0x4002: &pb.FloatingPoint{ - F: proto.Float64(3.0), - Exact: proto.Bool(true), - }, // the entire message should be overwritten - }, - }, - want: &pb.MessageWithMap{ - NameMapping: map[int32]string{ - 6: "Nigel", - 7: "Andrew", - }, - MsgMapping: map[int64]*pb.FloatingPoint{ - 0x4001: &pb.FloatingPoint{F: proto.Float64(2.0)}, - 0x4002: &pb.FloatingPoint{ - F: proto.Float64(2.0), - }, - }, - ByteMapping: map[bool][]byte{true: []byte("wowsa")}, - }, - }, - // proto3 shouldn't merge zero values, - // in the same way that proto2 shouldn't merge nils. - { - src: &proto3pb.Message{ - Name: "Aaron", - Data: []byte(""), // zero value, but not nil - }, - dst: &proto3pb.Message{ - HeightInCm: 176, - Data: []byte("texas!"), - }, - want: &proto3pb.Message{ - Name: "Aaron", - HeightInCm: 176, - Data: []byte("texas!"), - }, - }, - { // Oneof fields should merge by assignment. - src: &pb.Communique{Union: &pb.Communique_Number{41}}, - dst: &pb.Communique{Union: &pb.Communique_Name{"Bobby Tables"}}, - want: &pb.Communique{Union: &pb.Communique_Number{41}}, - }, - { // Oneof nil is the same as not set. - src: &pb.Communique{}, - dst: &pb.Communique{Union: &pb.Communique_Name{"Bobby Tables"}}, - want: &pb.Communique{Union: &pb.Communique_Name{"Bobby Tables"}}, - }, - { - src: &pb.Communique{Union: &pb.Communique_Number{1337}}, - dst: &pb.Communique{}, - want: &pb.Communique{Union: &pb.Communique_Number{1337}}, - }, - { - src: &pb.Communique{Union: &pb.Communique_Col{pb.MyMessage_RED}}, - dst: &pb.Communique{}, - want: &pb.Communique{Union: &pb.Communique_Col{pb.MyMessage_RED}}, - }, - { - src: &pb.Communique{Union: &pb.Communique_Data{[]byte("hello")}}, - dst: &pb.Communique{}, - want: &pb.Communique{Union: &pb.Communique_Data{[]byte("hello")}}, - }, - { - src: &pb.Communique{Union: &pb.Communique_Msg{&pb.Strings{BytesField: []byte{1, 2, 3}}}}, - dst: &pb.Communique{}, - want: &pb.Communique{Union: &pb.Communique_Msg{&pb.Strings{BytesField: []byte{1, 2, 3}}}}, - }, - { - src: &pb.Communique{Union: &pb.Communique_Msg{}}, - dst: &pb.Communique{}, - want: &pb.Communique{Union: &pb.Communique_Msg{}}, - }, - { - src: &pb.Communique{Union: &pb.Communique_Msg{&pb.Strings{StringField: proto.String("123")}}}, - dst: &pb.Communique{Union: &pb.Communique_Msg{&pb.Strings{BytesField: []byte{1, 2, 3}}}}, - want: &pb.Communique{Union: &pb.Communique_Msg{&pb.Strings{StringField: proto.String("123"), BytesField: []byte{1, 2, 3}}}}, - }, - { - src: &proto3pb.Message{ - Terrain: map[string]*proto3pb.Nested{ - "kay_a": &proto3pb.Nested{Cute: true}, // replace - "kay_b": &proto3pb.Nested{Bunny: "rabbit"}, // insert - }, - }, - dst: &proto3pb.Message{ - Terrain: map[string]*proto3pb.Nested{ - "kay_a": &proto3pb.Nested{Bunny: "lost"}, // replaced - "kay_c": &proto3pb.Nested{Bunny: "bunny"}, // keep - }, - }, - want: &proto3pb.Message{ - Terrain: map[string]*proto3pb.Nested{ - "kay_a": &proto3pb.Nested{Cute: true}, - "kay_b": &proto3pb.Nested{Bunny: "rabbit"}, - "kay_c": &proto3pb.Nested{Bunny: "bunny"}, - }, - }, - }, - { - src: &pb.GoTest{ - F_BoolRepeated: []bool{}, - F_Int32Repeated: []int32{}, - F_Int64Repeated: []int64{}, - F_Uint32Repeated: []uint32{}, - F_Uint64Repeated: []uint64{}, - F_FloatRepeated: []float32{}, - F_DoubleRepeated: []float64{}, - F_StringRepeated: []string{}, - F_BytesRepeated: [][]byte{}, - }, - dst: &pb.GoTest{}, - want: &pb.GoTest{ - F_BoolRepeated: []bool{}, - F_Int32Repeated: []int32{}, - F_Int64Repeated: []int64{}, - F_Uint32Repeated: []uint32{}, - F_Uint64Repeated: []uint64{}, - F_FloatRepeated: []float32{}, - F_DoubleRepeated: []float64{}, - F_StringRepeated: []string{}, - F_BytesRepeated: [][]byte{}, - }, - }, - { - src: &pb.GoTest{}, - dst: &pb.GoTest{ - F_BoolRepeated: []bool{}, - F_Int32Repeated: []int32{}, - F_Int64Repeated: []int64{}, - F_Uint32Repeated: []uint32{}, - F_Uint64Repeated: []uint64{}, - F_FloatRepeated: []float32{}, - F_DoubleRepeated: []float64{}, - F_StringRepeated: []string{}, - F_BytesRepeated: [][]byte{}, - }, - want: &pb.GoTest{ - F_BoolRepeated: []bool{}, - F_Int32Repeated: []int32{}, - F_Int64Repeated: []int64{}, - F_Uint32Repeated: []uint32{}, - F_Uint64Repeated: []uint64{}, - F_FloatRepeated: []float32{}, - F_DoubleRepeated: []float64{}, - F_StringRepeated: []string{}, - F_BytesRepeated: [][]byte{}, - }, - }, - { - src: &pb.GoTest{ - F_BytesRepeated: [][]byte{nil, []byte{}, []byte{0}}, - }, - dst: &pb.GoTest{}, - want: &pb.GoTest{ - F_BytesRepeated: [][]byte{nil, []byte{}, []byte{0}}, - }, - }, - { - src: &pb.MyMessage{ - Others: []*pb.OtherMessage{}, - }, - dst: &pb.MyMessage{}, - want: &pb.MyMessage{ - Others: []*pb.OtherMessage{}, - }, - }, -} - -func TestMerge(t *testing.T) { - for _, m := range mergeTests { - got := proto.Clone(m.dst) - if !proto.Equal(got, m.dst) { - t.Errorf("Clone()\ngot %v\nwant %v", got, m.dst) - continue - } - proto.Merge(got, m.src) - if !proto.Equal(got, m.want) { - t.Errorf("Merge(%v, %v)\ngot %v\nwant %v", m.dst, m.src, got, m.want) - } - } -} diff --git a/vendor/github.com/golang/protobuf/proto/decode_test.go b/vendor/github.com/golang/protobuf/proto/decode_test.go deleted file mode 100644 index 949be3ab..00000000 --- a/vendor/github.com/golang/protobuf/proto/decode_test.go +++ /dev/null @@ -1,255 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2010 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// +build go1.7 - -package proto_test - -import ( - "fmt" - "testing" - - "github.com/golang/protobuf/proto" - tpb "github.com/golang/protobuf/proto/proto3_proto" -) - -var msgBlackhole = new(tpb.Message) - -// BenchmarkVarint32ArraySmall shows the performance on an array of small int32 fields (1 and -// 2 bytes long). -func BenchmarkVarint32ArraySmall(b *testing.B) { - for i := uint(1); i <= 10; i++ { - dist := genInt32Dist([7]int{0, 3, 1}, 1<unmarshal. -} - -func TestMarshalUnmarshalRepeatedExtension(t *testing.T) { - // Add a repeated extension to the result. - tests := []struct { - name string - ext []*pb.ComplexExtension - }{ - { - "two fields", - []*pb.ComplexExtension{ - {First: proto.Int32(7)}, - {Second: proto.Int32(11)}, - }, - }, - { - "repeated field", - []*pb.ComplexExtension{ - {Third: []int32{1000}}, - {Third: []int32{2000}}, - }, - }, - { - "two fields and repeated field", - []*pb.ComplexExtension{ - {Third: []int32{1000}}, - {First: proto.Int32(9)}, - {Second: proto.Int32(21)}, - {Third: []int32{2000}}, - }, - }, - } - for _, test := range tests { - // Marshal message with a repeated extension. - msg1 := new(pb.OtherMessage) - err := proto.SetExtension(msg1, pb.E_RComplex, test.ext) - if err != nil { - t.Fatalf("[%s] Error setting extension: %v", test.name, err) - } - b, err := proto.Marshal(msg1) - if err != nil { - t.Fatalf("[%s] Error marshaling message: %v", test.name, err) - } - - // Unmarshal and read the merged proto. - msg2 := new(pb.OtherMessage) - err = proto.Unmarshal(b, msg2) - if err != nil { - t.Fatalf("[%s] Error unmarshaling message: %v", test.name, err) - } - e, err := proto.GetExtension(msg2, pb.E_RComplex) - if err != nil { - t.Fatalf("[%s] Error getting extension: %v", test.name, err) - } - ext := e.([]*pb.ComplexExtension) - if ext == nil { - t.Fatalf("[%s] Invalid extension", test.name) - } - if len(ext) != len(test.ext) { - t.Errorf("[%s] Wrong length of ComplexExtension: got: %v want: %v\n", test.name, len(ext), len(test.ext)) - } - for i := range test.ext { - if !proto.Equal(ext[i], test.ext[i]) { - t.Errorf("[%s] Wrong value for ComplexExtension[%d]: got: %v want: %v\n", test.name, i, ext[i], test.ext[i]) - } - } - } -} - -func TestUnmarshalRepeatingNonRepeatedExtension(t *testing.T) { - // We may see multiple instances of the same extension in the wire - // format. For example, the proto compiler may encode custom options in - // this way. Here, we verify that we merge the extensions together. - tests := []struct { - name string - ext []*pb.ComplexExtension - }{ - { - "two fields", - []*pb.ComplexExtension{ - {First: proto.Int32(7)}, - {Second: proto.Int32(11)}, - }, - }, - { - "repeated field", - []*pb.ComplexExtension{ - {Third: []int32{1000}}, - {Third: []int32{2000}}, - }, - }, - { - "two fields and repeated field", - []*pb.ComplexExtension{ - {Third: []int32{1000}}, - {First: proto.Int32(9)}, - {Second: proto.Int32(21)}, - {Third: []int32{2000}}, - }, - }, - } - for _, test := range tests { - var buf bytes.Buffer - var want pb.ComplexExtension - - // Generate a serialized representation of a repeated extension - // by catenating bytes together. - for i, e := range test.ext { - // Merge to create the wanted proto. - proto.Merge(&want, e) - - // serialize the message - msg := new(pb.OtherMessage) - err := proto.SetExtension(msg, pb.E_Complex, e) - if err != nil { - t.Fatalf("[%s] Error setting extension %d: %v", test.name, i, err) - } - b, err := proto.Marshal(msg) - if err != nil { - t.Fatalf("[%s] Error marshaling message %d: %v", test.name, i, err) - } - buf.Write(b) - } - - // Unmarshal and read the merged proto. - msg2 := new(pb.OtherMessage) - err := proto.Unmarshal(buf.Bytes(), msg2) - if err != nil { - t.Fatalf("[%s] Error unmarshaling message: %v", test.name, err) - } - e, err := proto.GetExtension(msg2, pb.E_Complex) - if err != nil { - t.Fatalf("[%s] Error getting extension: %v", test.name, err) - } - ext := e.(*pb.ComplexExtension) - if ext == nil { - t.Fatalf("[%s] Invalid extension", test.name) - } - if !proto.Equal(ext, &want) { - t.Errorf("[%s] Wrong value for ComplexExtension: got: %s want: %s\n", test.name, ext, &want) - } - } -} - -func TestClearAllExtensions(t *testing.T) { - // unregistered extension - desc := &proto.ExtensionDesc{ - ExtendedType: (*pb.MyMessage)(nil), - ExtensionType: (*bool)(nil), - Field: 101010100, - Name: "emptyextension", - Tag: "varint,0,opt", - } - m := &pb.MyMessage{} - if proto.HasExtension(m, desc) { - t.Errorf("proto.HasExtension(%s): got true, want false", proto.MarshalTextString(m)) - } - if err := proto.SetExtension(m, desc, proto.Bool(true)); err != nil { - t.Errorf("proto.SetExtension(m, desc, true): got error %q, want nil", err) - } - if !proto.HasExtension(m, desc) { - t.Errorf("proto.HasExtension(%s): got false, want true", proto.MarshalTextString(m)) - } - proto.ClearAllExtensions(m) - if proto.HasExtension(m, desc) { - t.Errorf("proto.HasExtension(%s): got true, want false", proto.MarshalTextString(m)) - } -} - -func TestMarshalRace(t *testing.T) { - ext := &pb.Ext{} - m := &pb.MyMessage{Count: proto.Int32(4)} - if err := proto.SetExtension(m, pb.E_Ext_More, ext); err != nil { - t.Fatalf("proto.SetExtension(m, desc, true): got error %q, want nil", err) - } - - b, err := proto.Marshal(m) - if err != nil { - t.Fatalf("Could not marshal message: %v", err) - } - if err := proto.Unmarshal(b, m); err != nil { - t.Fatalf("Could not unmarshal message: %v", err) - } - // after Unmarshal, the extension is in undecoded form. - // GetExtension will decode it lazily. Make sure this does - // not race against Marshal. - - var g errgroup.Group - for n := 3; n > 0; n-- { - g.Go(func() error { - _, err := proto.Marshal(m) - return err - }) - g.Go(func() error { - _, err := proto.GetExtension(m, pb.E_Ext_More) - return err - }) - } - if err := g.Wait(); err != nil { - t.Fatal(err) - } -} diff --git a/vendor/github.com/golang/protobuf/proto/map_test.go b/vendor/github.com/golang/protobuf/proto/map_test.go deleted file mode 100644 index b1e1529e..00000000 --- a/vendor/github.com/golang/protobuf/proto/map_test.go +++ /dev/null @@ -1,70 +0,0 @@ -package proto_test - -import ( - "fmt" - "reflect" - "testing" - - "github.com/golang/protobuf/proto" - ppb "github.com/golang/protobuf/proto/proto3_proto" -) - -func TestMap(t *testing.T) { - var b []byte - fmt.Sscanf("a2010c0a044b657931120456616c31a201130a044b657932120556616c3261120456616c32a201240a044b6579330d05000000120556616c33621a0556616c3361120456616c331505000000a20100a201260a044b657934130a07536f6d6555524c1209536f6d655469746c651a08536e69707065743114", "%x", &b) - - var m ppb.Message - if err := proto.Unmarshal(b, &m); err != nil { - t.Fatalf("proto.Unmarshal error: %v", err) - } - - got := m.StringMap - want := map[string]string{ - "": "", - "Key1": "Val1", - "Key2": "Val2", - "Key3": "Val3", - "Key4": "", - } - - if !reflect.DeepEqual(got, want) { - t.Errorf("maps differ:\ngot %#v\nwant %#v", got, want) - } -} - -func marshalled() []byte { - m := &ppb.IntMaps{} - for i := 0; i < 1000; i++ { - m.Maps = append(m.Maps, &ppb.IntMap{ - Rtt: map[int32]int32{1: 2}, - }) - } - b, err := proto.Marshal(m) - if err != nil { - panic(fmt.Sprintf("Can't marshal %+v: %v", m, err)) - } - return b -} - -func BenchmarkConcurrentMapUnmarshal(b *testing.B) { - in := marshalled() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - var out ppb.IntMaps - if err := proto.Unmarshal(in, &out); err != nil { - b.Errorf("Can't unmarshal ppb.IntMaps: %v", err) - } - } - }) -} - -func BenchmarkSequentialMapUnmarshal(b *testing.B) { - in := marshalled() - b.ResetTimer() - for i := 0; i < b.N; i++ { - var out ppb.IntMaps - if err := proto.Unmarshal(in, &out); err != nil { - b.Errorf("Can't unmarshal ppb.IntMaps: %v", err) - } - } -} diff --git a/vendor/github.com/golang/protobuf/proto/message_set_test.go b/vendor/github.com/golang/protobuf/proto/message_set_test.go deleted file mode 100644 index 2c170c5f..00000000 --- a/vendor/github.com/golang/protobuf/proto/message_set_test.go +++ /dev/null @@ -1,77 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2014 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto - -import ( - "bytes" - "testing" -) - -func TestUnmarshalMessageSetWithDuplicate(t *testing.T) { - // Check that a repeated message set entry will be concatenated. - in := &messageSet{ - Item: []*_MessageSet_Item{ - {TypeId: Int32(12345), Message: []byte("hoo")}, - {TypeId: Int32(12345), Message: []byte("hah")}, - }, - } - b, err := Marshal(in) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - t.Logf("Marshaled bytes: %q", b) - - var extensions XXX_InternalExtensions - if err := UnmarshalMessageSet(b, &extensions); err != nil { - t.Fatalf("UnmarshalMessageSet: %v", err) - } - ext, ok := extensions.p.extensionMap[12345] - if !ok { - t.Fatalf("Didn't retrieve extension 12345; map is %v", extensions.p.extensionMap) - } - // Skip wire type/field number and length varints. - got := skipVarint(skipVarint(ext.enc)) - if want := []byte("hoohah"); !bytes.Equal(got, want) { - t.Errorf("Combined extension is %q, want %q", got, want) - } -} - -func TestMarshalMessageSetJSON_UnknownType(t *testing.T) { - extMap := map[int32]Extension{12345: Extension{}} - got, err := MarshalMessageSetJSON(extMap) - if err != nil { - t.Fatalf("MarshalMessageSetJSON: %v", err) - } - if want := []byte("{}"); !bytes.Equal(got, want) { - t.Errorf("MarshalMessageSetJSON(%v) = %q, want %q", extMap, got, want) - } -} diff --git a/vendor/github.com/golang/protobuf/proto/proto3_test.go b/vendor/github.com/golang/protobuf/proto/proto3_test.go deleted file mode 100644 index 73eed6c0..00000000 --- a/vendor/github.com/golang/protobuf/proto/proto3_test.go +++ /dev/null @@ -1,151 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2014 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto_test - -import ( - "bytes" - "testing" - - "github.com/golang/protobuf/proto" - pb "github.com/golang/protobuf/proto/proto3_proto" - tpb "github.com/golang/protobuf/proto/test_proto" -) - -func TestProto3ZeroValues(t *testing.T) { - tests := []struct { - desc string - m proto.Message - }{ - {"zero message", &pb.Message{}}, - {"empty bytes field", &pb.Message{Data: []byte{}}}, - } - for _, test := range tests { - b, err := proto.Marshal(test.m) - if err != nil { - t.Errorf("%s: proto.Marshal: %v", test.desc, err) - continue - } - if len(b) > 0 { - t.Errorf("%s: Encoding is non-empty: %q", test.desc, b) - } - } -} - -func TestRoundTripProto3(t *testing.T) { - m := &pb.Message{ - Name: "David", // (2 | 1<<3): 0x0a 0x05 "David" - Hilarity: pb.Message_PUNS, // (0 | 2<<3): 0x10 0x01 - HeightInCm: 178, // (0 | 3<<3): 0x18 0xb2 0x01 - Data: []byte("roboto"), // (2 | 4<<3): 0x20 0x06 "roboto" - ResultCount: 47, // (0 | 7<<3): 0x38 0x2f - TrueScotsman: true, // (0 | 8<<3): 0x40 0x01 - Score: 8.1, // (5 | 9<<3): 0x4d <8.1> - - Key: []uint64{1, 0xdeadbeef}, - Nested: &pb.Nested{ - Bunny: "Monty", - }, - } - t.Logf(" m: %v", m) - - b, err := proto.Marshal(m) - if err != nil { - t.Fatalf("proto.Marshal: %v", err) - } - t.Logf(" b: %q", b) - - m2 := new(pb.Message) - if err := proto.Unmarshal(b, m2); err != nil { - t.Fatalf("proto.Unmarshal: %v", err) - } - t.Logf("m2: %v", m2) - - if !proto.Equal(m, m2) { - t.Errorf("proto.Equal returned false:\n m: %v\nm2: %v", m, m2) - } -} - -func TestGettersForBasicTypesExist(t *testing.T) { - var m pb.Message - if got := m.GetNested().GetBunny(); got != "" { - t.Errorf("m.GetNested().GetBunny() = %q, want empty string", got) - } - if got := m.GetNested().GetCute(); got { - t.Errorf("m.GetNested().GetCute() = %t, want false", got) - } -} - -func TestProto3SetDefaults(t *testing.T) { - in := &pb.Message{ - Terrain: map[string]*pb.Nested{ - "meadow": new(pb.Nested), - }, - Proto2Field: new(tpb.SubDefaults), - Proto2Value: map[string]*tpb.SubDefaults{ - "badlands": new(tpb.SubDefaults), - }, - } - - got := proto.Clone(in).(*pb.Message) - proto.SetDefaults(got) - - // There are no defaults in proto3. Everything should be the zero value, but - // we need to remember to set defaults for nested proto2 messages. - want := &pb.Message{ - Terrain: map[string]*pb.Nested{ - "meadow": new(pb.Nested), - }, - Proto2Field: &tpb.SubDefaults{N: proto.Int64(7)}, - Proto2Value: map[string]*tpb.SubDefaults{ - "badlands": &tpb.SubDefaults{N: proto.Int64(7)}, - }, - } - - if !proto.Equal(got, want) { - t.Errorf("with in = %v\nproto.SetDefaults(in) =>\ngot %v\nwant %v", in, got, want) - } -} - -func TestUnknownFieldPreservation(t *testing.T) { - b1 := "\x0a\x05David" // Known tag 1 - b2 := "\xc2\x0c\x06Google" // Unknown tag 200 - b := []byte(b1 + b2) - - m := new(pb.Message) - if err := proto.Unmarshal(b, m); err != nil { - t.Fatalf("proto.Unmarshal: %v", err) - } - - if !bytes.Equal(m.XXX_unrecognized, []byte(b2)) { - t.Fatalf("mismatching unknown fields:\ngot %q\nwant %q", m.XXX_unrecognized, b2) - } -} diff --git a/vendor/github.com/golang/protobuf/proto/size2_test.go b/vendor/github.com/golang/protobuf/proto/size2_test.go deleted file mode 100644 index 7846b061..00000000 --- a/vendor/github.com/golang/protobuf/proto/size2_test.go +++ /dev/null @@ -1,63 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2012 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto - -import ( - "testing" -) - -// This is a separate file and package from size_test.go because that one uses -// generated messages and thus may not be in package proto without having a circular -// dependency, whereas this file tests unexported details of size.go. - -func TestVarintSize(t *testing.T) { - // Check the edge cases carefully. - testCases := []struct { - n uint64 - size int - }{ - {0, 1}, - {1, 1}, - {127, 1}, - {128, 2}, - {16383, 2}, - {16384, 3}, - {1<<63 - 1, 9}, - {1 << 63, 10}, - } - for _, tc := range testCases { - size := SizeVarint(tc.n) - if size != tc.size { - t.Errorf("sizeVarint(%d) = %d, want %d", tc.n, size, tc.size) - } - } -} diff --git a/vendor/github.com/golang/protobuf/proto/size_test.go b/vendor/github.com/golang/protobuf/proto/size_test.go deleted file mode 100644 index 3abac418..00000000 --- a/vendor/github.com/golang/protobuf/proto/size_test.go +++ /dev/null @@ -1,191 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2012 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto_test - -import ( - "log" - "strings" - "testing" - - . "github.com/golang/protobuf/proto" - proto3pb "github.com/golang/protobuf/proto/proto3_proto" - pb "github.com/golang/protobuf/proto/test_proto" -) - -var messageWithExtension1 = &pb.MyMessage{Count: Int32(7)} - -// messageWithExtension2 is in equal_test.go. -var messageWithExtension3 = &pb.MyMessage{Count: Int32(8)} - -func init() { - if err := SetExtension(messageWithExtension1, pb.E_Ext_More, &pb.Ext{Data: String("Abbott")}); err != nil { - log.Panicf("SetExtension: %v", err) - } - if err := SetExtension(messageWithExtension3, pb.E_Ext_More, &pb.Ext{Data: String("Costello")}); err != nil { - log.Panicf("SetExtension: %v", err) - } - - // Force messageWithExtension3 to have the extension encoded. - Marshal(messageWithExtension3) - -} - -// non-pointer custom message -type nonptrMessage struct{} - -func (m nonptrMessage) ProtoMessage() {} -func (m nonptrMessage) Reset() {} -func (m nonptrMessage) String() string { return "" } - -func (m nonptrMessage) Marshal() ([]byte, error) { - return []byte{42}, nil -} - -// custom message embedding a proto.Message -type messageWithEmbedding struct { - *pb.OtherMessage -} - -func (m *messageWithEmbedding) ProtoMessage() {} -func (m *messageWithEmbedding) Reset() {} -func (m *messageWithEmbedding) String() string { return "" } - -func (m *messageWithEmbedding) Marshal() ([]byte, error) { - return []byte{42}, nil -} - -var SizeTests = []struct { - desc string - pb Message -}{ - {"empty", &pb.OtherMessage{}}, - // Basic types. - {"bool", &pb.Defaults{F_Bool: Bool(true)}}, - {"int32", &pb.Defaults{F_Int32: Int32(12)}}, - {"negative int32", &pb.Defaults{F_Int32: Int32(-1)}}, - {"small int64", &pb.Defaults{F_Int64: Int64(1)}}, - {"big int64", &pb.Defaults{F_Int64: Int64(1 << 20)}}, - {"negative int64", &pb.Defaults{F_Int64: Int64(-1)}}, - {"fixed32", &pb.Defaults{F_Fixed32: Uint32(71)}}, - {"fixed64", &pb.Defaults{F_Fixed64: Uint64(72)}}, - {"uint32", &pb.Defaults{F_Uint32: Uint32(123)}}, - {"uint64", &pb.Defaults{F_Uint64: Uint64(124)}}, - {"float", &pb.Defaults{F_Float: Float32(12.6)}}, - {"double", &pb.Defaults{F_Double: Float64(13.9)}}, - {"string", &pb.Defaults{F_String: String("niles")}}, - {"bytes", &pb.Defaults{F_Bytes: []byte("wowsa")}}, - {"bytes, empty", &pb.Defaults{F_Bytes: []byte{}}}, - {"sint32", &pb.Defaults{F_Sint32: Int32(65)}}, - {"sint64", &pb.Defaults{F_Sint64: Int64(67)}}, - {"enum", &pb.Defaults{F_Enum: pb.Defaults_BLUE.Enum()}}, - // Repeated. - {"empty repeated bool", &pb.MoreRepeated{Bools: []bool{}}}, - {"repeated bool", &pb.MoreRepeated{Bools: []bool{false, true, true, false}}}, - {"packed repeated bool", &pb.MoreRepeated{BoolsPacked: []bool{false, true, true, false, true, true, true}}}, - {"repeated int32", &pb.MoreRepeated{Ints: []int32{1, 12203, 1729, -1}}}, - {"repeated int32 packed", &pb.MoreRepeated{IntsPacked: []int32{1, 12203, 1729}}}, - {"repeated int64 packed", &pb.MoreRepeated{Int64SPacked: []int64{ - // Need enough large numbers to verify that the header is counting the number of bytes - // for the field, not the number of elements. - 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, - 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, - }}}, - {"repeated string", &pb.MoreRepeated{Strings: []string{"r", "ken", "gri"}}}, - {"repeated fixed", &pb.MoreRepeated{Fixeds: []uint32{1, 2, 3, 4}}}, - // Nested. - {"nested", &pb.OldMessage{Nested: &pb.OldMessage_Nested{Name: String("whatever")}}}, - {"group", &pb.GroupOld{G: &pb.GroupOld_G{X: Int32(12345)}}}, - // Other things. - {"unrecognized", &pb.MoreRepeated{XXX_unrecognized: []byte{13<<3 | 0, 4}}}, - {"extension (unencoded)", messageWithExtension1}, - {"extension (encoded)", messageWithExtension3}, - // proto3 message - {"proto3 empty", &proto3pb.Message{}}, - {"proto3 bool", &proto3pb.Message{TrueScotsman: true}}, - {"proto3 int64", &proto3pb.Message{ResultCount: 1}}, - {"proto3 uint32", &proto3pb.Message{HeightInCm: 123}}, - {"proto3 float", &proto3pb.Message{Score: 12.6}}, - {"proto3 string", &proto3pb.Message{Name: "Snezana"}}, - {"proto3 bytes", &proto3pb.Message{Data: []byte("wowsa")}}, - {"proto3 bytes, empty", &proto3pb.Message{Data: []byte{}}}, - {"proto3 enum", &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}}, - {"proto3 map field with empty bytes", &proto3pb.MessageWithMap{ByteMapping: map[bool][]byte{false: []byte{}}}}, - - {"map field", &pb.MessageWithMap{NameMapping: map[int32]string{1: "Rob", 7: "Andrew"}}}, - {"map field with message", &pb.MessageWithMap{MsgMapping: map[int64]*pb.FloatingPoint{0x7001: &pb.FloatingPoint{F: Float64(2.0)}}}}, - {"map field with bytes", &pb.MessageWithMap{ByteMapping: map[bool][]byte{true: []byte("this time for sure")}}}, - {"map field with empty bytes", &pb.MessageWithMap{ByteMapping: map[bool][]byte{true: []byte{}}}}, - - {"map field with big entry", &pb.MessageWithMap{NameMapping: map[int32]string{8: strings.Repeat("x", 125)}}}, - {"map field with big key and val", &pb.MessageWithMap{StrToStr: map[string]string{strings.Repeat("x", 70): strings.Repeat("y", 70)}}}, - {"map field with big numeric key", &pb.MessageWithMap{NameMapping: map[int32]string{0xf00d: "om nom nom"}}}, - - {"oneof not set", &pb.Oneof{}}, - {"oneof bool", &pb.Oneof{Union: &pb.Oneof_F_Bool{true}}}, - {"oneof zero int32", &pb.Oneof{Union: &pb.Oneof_F_Int32{0}}}, - {"oneof big int32", &pb.Oneof{Union: &pb.Oneof_F_Int32{1 << 20}}}, - {"oneof int64", &pb.Oneof{Union: &pb.Oneof_F_Int64{42}}}, - {"oneof fixed32", &pb.Oneof{Union: &pb.Oneof_F_Fixed32{43}}}, - {"oneof fixed64", &pb.Oneof{Union: &pb.Oneof_F_Fixed64{44}}}, - {"oneof uint32", &pb.Oneof{Union: &pb.Oneof_F_Uint32{45}}}, - {"oneof uint64", &pb.Oneof{Union: &pb.Oneof_F_Uint64{46}}}, - {"oneof float", &pb.Oneof{Union: &pb.Oneof_F_Float{47.1}}}, - {"oneof double", &pb.Oneof{Union: &pb.Oneof_F_Double{48.9}}}, - {"oneof string", &pb.Oneof{Union: &pb.Oneof_F_String{"Rhythmic Fman"}}}, - {"oneof bytes", &pb.Oneof{Union: &pb.Oneof_F_Bytes{[]byte("let go")}}}, - {"oneof sint32", &pb.Oneof{Union: &pb.Oneof_F_Sint32{50}}}, - {"oneof sint64", &pb.Oneof{Union: &pb.Oneof_F_Sint64{51}}}, - {"oneof enum", &pb.Oneof{Union: &pb.Oneof_F_Enum{pb.MyMessage_BLUE}}}, - {"message for oneof", &pb.GoTestField{Label: String("k"), Type: String("v")}}, - {"oneof message", &pb.Oneof{Union: &pb.Oneof_F_Message{&pb.GoTestField{Label: String("k"), Type: String("v")}}}}, - {"oneof group", &pb.Oneof{Union: &pb.Oneof_FGroup{&pb.Oneof_F_Group{X: Int32(52)}}}}, - {"oneof largest tag", &pb.Oneof{Union: &pb.Oneof_F_Largest_Tag{1}}}, - {"multiple oneofs", &pb.Oneof{Union: &pb.Oneof_F_Int32{1}, Tormato: &pb.Oneof_Value{2}}}, - - {"non-pointer message", nonptrMessage{}}, - {"custom message with embedding", &messageWithEmbedding{&pb.OtherMessage{}}}, -} - -func TestSize(t *testing.T) { - for _, tc := range SizeTests { - size := Size(tc.pb) - b, err := Marshal(tc.pb) - if err != nil { - t.Errorf("%v: Marshal failed: %v", tc.desc, err) - continue - } - if size != len(b) { - t.Errorf("%v: Size(%v) = %d, want %d", tc.desc, tc.pb, size, len(b)) - t.Logf("%v: bytes: %#v", tc.desc, b) - } - } -} diff --git a/vendor/github.com/golang/protobuf/proto/text_parser_test.go b/vendor/github.com/golang/protobuf/proto/text_parser_test.go deleted file mode 100644 index a8198087..00000000 --- a/vendor/github.com/golang/protobuf/proto/text_parser_test.go +++ /dev/null @@ -1,706 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2010 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto_test - -import ( - "fmt" - "math" - "testing" - - . "github.com/golang/protobuf/proto" - proto3pb "github.com/golang/protobuf/proto/proto3_proto" - . "github.com/golang/protobuf/proto/test_proto" -) - -type UnmarshalTextTest struct { - in string - err string // if "", no error expected - out *MyMessage -} - -func buildExtStructTest(text string) UnmarshalTextTest { - msg := &MyMessage{ - Count: Int32(42), - } - SetExtension(msg, E_Ext_More, &Ext{ - Data: String("Hello, world!"), - }) - return UnmarshalTextTest{in: text, out: msg} -} - -func buildExtDataTest(text string) UnmarshalTextTest { - msg := &MyMessage{ - Count: Int32(42), - } - SetExtension(msg, E_Ext_Text, String("Hello, world!")) - SetExtension(msg, E_Ext_Number, Int32(1729)) - return UnmarshalTextTest{in: text, out: msg} -} - -func buildExtRepStringTest(text string) UnmarshalTextTest { - msg := &MyMessage{ - Count: Int32(42), - } - if err := SetExtension(msg, E_Greeting, []string{"bula", "hola"}); err != nil { - panic(err) - } - return UnmarshalTextTest{in: text, out: msg} -} - -var unMarshalTextTests = []UnmarshalTextTest{ - // Basic - { - in: " count:42\n name:\"Dave\" ", - out: &MyMessage{ - Count: Int32(42), - Name: String("Dave"), - }, - }, - - // Empty quoted string - { - in: `count:42 name:""`, - out: &MyMessage{ - Count: Int32(42), - Name: String(""), - }, - }, - - // Quoted string concatenation with double quotes - { - in: `count:42 name: "My name is "` + "\n" + `"elsewhere"`, - out: &MyMessage{ - Count: Int32(42), - Name: String("My name is elsewhere"), - }, - }, - - // Quoted string concatenation with single quotes - { - in: "count:42 name: 'My name is '\n'elsewhere'", - out: &MyMessage{ - Count: Int32(42), - Name: String("My name is elsewhere"), - }, - }, - - // Quoted string concatenations with mixed quotes - { - in: "count:42 name: 'My name is '\n\"elsewhere\"", - out: &MyMessage{ - Count: Int32(42), - Name: String("My name is elsewhere"), - }, - }, - { - in: "count:42 name: \"My name is \"\n'elsewhere'", - out: &MyMessage{ - Count: Int32(42), - Name: String("My name is elsewhere"), - }, - }, - - // Quoted string with escaped apostrophe - { - in: `count:42 name: "HOLIDAY - New Year\'s Day"`, - out: &MyMessage{ - Count: Int32(42), - Name: String("HOLIDAY - New Year's Day"), - }, - }, - - // Quoted string with single quote - { - in: `count:42 name: 'Roger "The Ramster" Ramjet'`, - out: &MyMessage{ - Count: Int32(42), - Name: String(`Roger "The Ramster" Ramjet`), - }, - }, - - // Quoted string with all the accepted special characters from the C++ test - { - in: `count:42 name: ` + "\"\\\"A string with \\' characters \\n and \\r newlines and \\t tabs and \\001 slashes \\\\ and multiple spaces\"", - out: &MyMessage{ - Count: Int32(42), - Name: String("\"A string with ' characters \n and \r newlines and \t tabs and \001 slashes \\ and multiple spaces"), - }, - }, - - // Quoted string with quoted backslash - { - in: `count:42 name: "\\'xyz"`, - out: &MyMessage{ - Count: Int32(42), - Name: String(`\'xyz`), - }, - }, - - // Quoted string with UTF-8 bytes. - { - in: "count:42 name: '\303\277\302\201\x00\xAB\xCD\xEF'", - out: &MyMessage{ - Count: Int32(42), - Name: String("\303\277\302\201\x00\xAB\xCD\xEF"), - }, - }, - - // Quoted string with unicode escapes. - { - in: `count: 42 name: "\u0047\U00000047\uffff\U0010ffff"`, - out: &MyMessage{ - Count: Int32(42), - Name: String("GG\uffff\U0010ffff"), - }, - }, - - // Bad quoted string - { - in: `inner: < host: "\0" >` + "\n", - err: `line 1.15: invalid quoted string "\0": \0 requires 2 following digits`, - }, - - // Bad \u escape - { - in: `count: 42 name: "\u000"`, - err: `line 1.16: invalid quoted string "\u000": \u requires 4 following digits`, - }, - - // Bad \U escape - { - in: `count: 42 name: "\U0000000"`, - err: `line 1.16: invalid quoted string "\U0000000": \U requires 8 following digits`, - }, - - // Bad \U escape - { - in: `count: 42 name: "\xxx"`, - err: `line 1.16: invalid quoted string "\xxx": \xxx contains non-hexadecimal digits`, - }, - - // Number too large for int64 - { - in: "count: 1 others { key: 123456789012345678901 }", - err: "line 1.23: invalid int64: 123456789012345678901", - }, - - // Number too large for int32 - { - in: "count: 1234567890123", - err: "line 1.7: invalid int32: 1234567890123", - }, - - // Number in hexadecimal - { - in: "count: 0x2beef", - out: &MyMessage{ - Count: Int32(0x2beef), - }, - }, - - // Number in octal - { - in: "count: 024601", - out: &MyMessage{ - Count: Int32(024601), - }, - }, - - // Floating point number with "f" suffix - { - in: "count: 4 others:< weight: 17.0f >", - out: &MyMessage{ - Count: Int32(4), - Others: []*OtherMessage{ - { - Weight: Float32(17), - }, - }, - }, - }, - - // Floating point positive infinity - { - in: "count: 4 bigfloat: inf", - out: &MyMessage{ - Count: Int32(4), - Bigfloat: Float64(math.Inf(1)), - }, - }, - - // Floating point negative infinity - { - in: "count: 4 bigfloat: -inf", - out: &MyMessage{ - Count: Int32(4), - Bigfloat: Float64(math.Inf(-1)), - }, - }, - - // Number too large for float32 - { - in: "others:< weight: 12345678901234567890123456789012345678901234567890 >", - err: "line 1.17: invalid float32: 12345678901234567890123456789012345678901234567890", - }, - - // Number posing as a quoted string - { - in: `inner: < host: 12 >` + "\n", - err: `line 1.15: invalid string: 12`, - }, - - // Quoted string posing as int32 - { - in: `count: "12"`, - err: `line 1.7: invalid int32: "12"`, - }, - - // Quoted string posing a float32 - { - in: `others:< weight: "17.4" >`, - err: `line 1.17: invalid float32: "17.4"`, - }, - - // unclosed bracket doesn't cause infinite loop - { - in: `[`, - err: `line 1.0: unclosed type_url or extension name`, - }, - - // Enum - { - in: `count:42 bikeshed: BLUE`, - out: &MyMessage{ - Count: Int32(42), - Bikeshed: MyMessage_BLUE.Enum(), - }, - }, - - // Repeated field - { - in: `count:42 pet: "horsey" pet:"bunny"`, - out: &MyMessage{ - Count: Int32(42), - Pet: []string{"horsey", "bunny"}, - }, - }, - - // Repeated field with list notation - { - in: `count:42 pet: ["horsey", "bunny"]`, - out: &MyMessage{ - Count: Int32(42), - Pet: []string{"horsey", "bunny"}, - }, - }, - - // Repeated message with/without colon and <>/{} - { - in: `count:42 others:{} others{} others:<> others:{}`, - out: &MyMessage{ - Count: Int32(42), - Others: []*OtherMessage{ - {}, - {}, - {}, - {}, - }, - }, - }, - - // Missing colon for inner message - { - in: `count:42 inner < host: "cauchy.syd" >`, - out: &MyMessage{ - Count: Int32(42), - Inner: &InnerMessage{ - Host: String("cauchy.syd"), - }, - }, - }, - - // Missing colon for string field - { - in: `name "Dave"`, - err: `line 1.5: expected ':', found "\"Dave\""`, - }, - - // Missing colon for int32 field - { - in: `count 42`, - err: `line 1.6: expected ':', found "42"`, - }, - - // Missing required field - { - in: `name: "Pawel"`, - err: fmt.Sprintf(`proto: required field "%T.count" not set`, MyMessage{}), - out: &MyMessage{ - Name: String("Pawel"), - }, - }, - - // Missing required field in a required submessage - { - in: `count: 42 we_must_go_deeper < leo_finally_won_an_oscar <> >`, - err: fmt.Sprintf(`proto: required field "%T.host" not set`, InnerMessage{}), - out: &MyMessage{ - Count: Int32(42), - WeMustGoDeeper: &RequiredInnerMessage{LeoFinallyWonAnOscar: &InnerMessage{}}, - }, - }, - - // Repeated non-repeated field - { - in: `name: "Rob" name: "Russ"`, - err: `line 1.12: non-repeated field "name" was repeated`, - }, - - // Group - { - in: `count: 17 SomeGroup { group_field: 12 }`, - out: &MyMessage{ - Count: Int32(17), - Somegroup: &MyMessage_SomeGroup{ - GroupField: Int32(12), - }, - }, - }, - - // Semicolon between fields - { - in: `count:3;name:"Calvin"`, - out: &MyMessage{ - Count: Int32(3), - Name: String("Calvin"), - }, - }, - // Comma between fields - { - in: `count:4,name:"Ezekiel"`, - out: &MyMessage{ - Count: Int32(4), - Name: String("Ezekiel"), - }, - }, - - // Boolean false - { - in: `count:42 inner { host: "example.com" connected: false }`, - out: &MyMessage{ - Count: Int32(42), - Inner: &InnerMessage{ - Host: String("example.com"), - Connected: Bool(false), - }, - }, - }, - // Boolean true - { - in: `count:42 inner { host: "example.com" connected: true }`, - out: &MyMessage{ - Count: Int32(42), - Inner: &InnerMessage{ - Host: String("example.com"), - Connected: Bool(true), - }, - }, - }, - // Boolean 0 - { - in: `count:42 inner { host: "example.com" connected: 0 }`, - out: &MyMessage{ - Count: Int32(42), - Inner: &InnerMessage{ - Host: String("example.com"), - Connected: Bool(false), - }, - }, - }, - // Boolean 1 - { - in: `count:42 inner { host: "example.com" connected: 1 }`, - out: &MyMessage{ - Count: Int32(42), - Inner: &InnerMessage{ - Host: String("example.com"), - Connected: Bool(true), - }, - }, - }, - // Boolean f - { - in: `count:42 inner { host: "example.com" connected: f }`, - out: &MyMessage{ - Count: Int32(42), - Inner: &InnerMessage{ - Host: String("example.com"), - Connected: Bool(false), - }, - }, - }, - // Boolean t - { - in: `count:42 inner { host: "example.com" connected: t }`, - out: &MyMessage{ - Count: Int32(42), - Inner: &InnerMessage{ - Host: String("example.com"), - Connected: Bool(true), - }, - }, - }, - // Boolean False - { - in: `count:42 inner { host: "example.com" connected: False }`, - out: &MyMessage{ - Count: Int32(42), - Inner: &InnerMessage{ - Host: String("example.com"), - Connected: Bool(false), - }, - }, - }, - // Boolean True - { - in: `count:42 inner { host: "example.com" connected: True }`, - out: &MyMessage{ - Count: Int32(42), - Inner: &InnerMessage{ - Host: String("example.com"), - Connected: Bool(true), - }, - }, - }, - - // Extension - buildExtStructTest(`count: 42 [test_proto.Ext.more]:`), - buildExtStructTest(`count: 42 [test_proto.Ext.more] {data:"Hello, world!"}`), - buildExtDataTest(`count: 42 [test_proto.Ext.text]:"Hello, world!" [test_proto.Ext.number]:1729`), - buildExtRepStringTest(`count: 42 [test_proto.greeting]:"bula" [test_proto.greeting]:"hola"`), - - // Big all-in-one - { - in: "count:42 # Meaning\n" + - `name:"Dave" ` + - `quote:"\"I didn't want to go.\"" ` + - `pet:"bunny" ` + - `pet:"kitty" ` + - `pet:"horsey" ` + - `inner:<` + - ` host:"footrest.syd" ` + - ` port:7001 ` + - ` connected:true ` + - `> ` + - `others:<` + - ` key:3735928559 ` + - ` value:"\x01A\a\f" ` + - `> ` + - `others:<` + - " weight:58.9 # Atomic weight of Co\n" + - ` inner:<` + - ` host:"lesha.mtv" ` + - ` port:8002 ` + - ` >` + - `>`, - out: &MyMessage{ - Count: Int32(42), - Name: String("Dave"), - Quote: String(`"I didn't want to go."`), - Pet: []string{"bunny", "kitty", "horsey"}, - Inner: &InnerMessage{ - Host: String("footrest.syd"), - Port: Int32(7001), - Connected: Bool(true), - }, - Others: []*OtherMessage{ - { - Key: Int64(3735928559), - Value: []byte{0x1, 'A', '\a', '\f'}, - }, - { - Weight: Float32(58.9), - Inner: &InnerMessage{ - Host: String("lesha.mtv"), - Port: Int32(8002), - }, - }, - }, - }, - }, -} - -func TestUnmarshalText(t *testing.T) { - for i, test := range unMarshalTextTests { - pb := new(MyMessage) - err := UnmarshalText(test.in, pb) - if test.err == "" { - // We don't expect failure. - if err != nil { - t.Errorf("Test %d: Unexpected error: %v", i, err) - } else if !Equal(pb, test.out) { - t.Errorf("Test %d: Incorrect populated \nHave: %v\nWant: %v", - i, pb, test.out) - } - } else { - // We do expect failure. - if err == nil { - t.Errorf("Test %d: Didn't get expected error: %v", i, test.err) - } else if err.Error() != test.err { - t.Errorf("Test %d: Incorrect error.\nHave: %v\nWant: %v", - i, err.Error(), test.err) - } else if _, ok := err.(*RequiredNotSetError); ok && test.out != nil && !Equal(pb, test.out) { - t.Errorf("Test %d: Incorrect populated \nHave: %v\nWant: %v", - i, pb, test.out) - } - } - } -} - -func TestUnmarshalTextCustomMessage(t *testing.T) { - msg := &textMessage{} - if err := UnmarshalText("custom", msg); err != nil { - t.Errorf("Unexpected error from custom unmarshal: %v", err) - } - if UnmarshalText("not custom", msg) == nil { - t.Errorf("Didn't get expected error from custom unmarshal") - } -} - -// Regression test; this caused a panic. -func TestRepeatedEnum(t *testing.T) { - pb := new(RepeatedEnum) - if err := UnmarshalText("color: RED", pb); err != nil { - t.Fatal(err) - } - exp := &RepeatedEnum{ - Color: []RepeatedEnum_Color{RepeatedEnum_RED}, - } - if !Equal(pb, exp) { - t.Errorf("Incorrect populated \nHave: %v\nWant: %v", pb, exp) - } -} - -func TestProto3TextParsing(t *testing.T) { - m := new(proto3pb.Message) - const in = `name: "Wallace" true_scotsman: true` - want := &proto3pb.Message{ - Name: "Wallace", - TrueScotsman: true, - } - if err := UnmarshalText(in, m); err != nil { - t.Fatal(err) - } - if !Equal(m, want) { - t.Errorf("\n got %v\nwant %v", m, want) - } -} - -func TestMapParsing(t *testing.T) { - m := new(MessageWithMap) - const in = `name_mapping: name_mapping:` + - `msg_mapping:,>` + // separating commas are okay - `msg_mapping>` + // no colon after "value" - `msg_mapping:>` + // omitted key - `msg_mapping:` + // omitted value - `byte_mapping:` + - `byte_mapping:<>` // omitted key and value - want := &MessageWithMap{ - NameMapping: map[int32]string{ - 1: "Beatles", - 1234: "Feist", - }, - MsgMapping: map[int64]*FloatingPoint{ - -4: {F: Float64(2.0)}, - -2: {F: Float64(4.0)}, - 0: {F: Float64(5.0)}, - 1: nil, - }, - ByteMapping: map[bool][]byte{ - false: nil, - true: []byte("so be it"), - }, - } - if err := UnmarshalText(in, m); err != nil { - t.Fatal(err) - } - if !Equal(m, want) { - t.Errorf("\n got %v\nwant %v", m, want) - } -} - -func TestOneofParsing(t *testing.T) { - const in = `name:"Shrek"` - m := new(Communique) - want := &Communique{Union: &Communique_Name{"Shrek"}} - if err := UnmarshalText(in, m); err != nil { - t.Fatal(err) - } - if !Equal(m, want) { - t.Errorf("\n got %v\nwant %v", m, want) - } - - const inOverwrite = `name:"Shrek" number:42` - m = new(Communique) - testErr := "line 1.13: field 'number' would overwrite already parsed oneof 'Union'" - if err := UnmarshalText(inOverwrite, m); err == nil { - t.Errorf("TestOneofParsing: Didn't get expected error: %v", testErr) - } else if err.Error() != testErr { - t.Errorf("TestOneofParsing: Incorrect error.\nHave: %v\nWant: %v", - err.Error(), testErr) - } - -} - -var benchInput string - -func init() { - benchInput = "count: 4\n" - for i := 0; i < 1000; i++ { - benchInput += "pet: \"fido\"\n" - } - - // Check it is valid input. - pb := new(MyMessage) - err := UnmarshalText(benchInput, pb) - if err != nil { - panic("Bad benchmark input: " + err.Error()) - } -} - -func BenchmarkUnmarshalText(b *testing.B) { - pb := new(MyMessage) - for i := 0; i < b.N; i++ { - UnmarshalText(benchInput, pb) - } - b.SetBytes(int64(len(benchInput))) -} diff --git a/vendor/github.com/golang/protobuf/proto/text_test.go b/vendor/github.com/golang/protobuf/proto/text_test.go deleted file mode 100644 index 3c8b033c..00000000 --- a/vendor/github.com/golang/protobuf/proto/text_test.go +++ /dev/null @@ -1,518 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2010 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto_test - -import ( - "bytes" - "errors" - "io/ioutil" - "math" - "strings" - "sync" - "testing" - - "github.com/golang/protobuf/proto" - - proto3pb "github.com/golang/protobuf/proto/proto3_proto" - pb "github.com/golang/protobuf/proto/test_proto" - anypb "github.com/golang/protobuf/ptypes/any" -) - -// textMessage implements the methods that allow it to marshal and unmarshal -// itself as text. -type textMessage struct { -} - -func (*textMessage) MarshalText() ([]byte, error) { - return []byte("custom"), nil -} - -func (*textMessage) UnmarshalText(bytes []byte) error { - if string(bytes) != "custom" { - return errors.New("expected 'custom'") - } - return nil -} - -func (*textMessage) Reset() {} -func (*textMessage) String() string { return "" } -func (*textMessage) ProtoMessage() {} - -func newTestMessage() *pb.MyMessage { - msg := &pb.MyMessage{ - Count: proto.Int32(42), - Name: proto.String("Dave"), - Quote: proto.String(`"I didn't want to go."`), - Pet: []string{"bunny", "kitty", "horsey"}, - Inner: &pb.InnerMessage{ - Host: proto.String("footrest.syd"), - Port: proto.Int32(7001), - Connected: proto.Bool(true), - }, - Others: []*pb.OtherMessage{ - { - Key: proto.Int64(0xdeadbeef), - Value: []byte{1, 65, 7, 12}, - }, - { - Weight: proto.Float32(6.022), - Inner: &pb.InnerMessage{ - Host: proto.String("lesha.mtv"), - Port: proto.Int32(8002), - }, - }, - }, - Bikeshed: pb.MyMessage_BLUE.Enum(), - Somegroup: &pb.MyMessage_SomeGroup{ - GroupField: proto.Int32(8), - }, - // One normally wouldn't do this. - // This is an undeclared tag 13, as a varint (wire type 0) with value 4. - XXX_unrecognized: []byte{13<<3 | 0, 4}, - } - ext := &pb.Ext{ - Data: proto.String("Big gobs for big rats"), - } - if err := proto.SetExtension(msg, pb.E_Ext_More, ext); err != nil { - panic(err) - } - greetings := []string{"adg", "easy", "cow"} - if err := proto.SetExtension(msg, pb.E_Greeting, greetings); err != nil { - panic(err) - } - - // Add an unknown extension. We marshal a pb.Ext, and fake the ID. - b, err := proto.Marshal(&pb.Ext{Data: proto.String("3G skiing")}) - if err != nil { - panic(err) - } - b = append(proto.EncodeVarint(201<<3|proto.WireBytes), b...) - proto.SetRawExtension(msg, 201, b) - - // Extensions can be plain fields, too, so let's test that. - b = append(proto.EncodeVarint(202<<3|proto.WireVarint), 19) - proto.SetRawExtension(msg, 202, b) - - return msg -} - -const text = `count: 42 -name: "Dave" -quote: "\"I didn't want to go.\"" -pet: "bunny" -pet: "kitty" -pet: "horsey" -inner: < - host: "footrest.syd" - port: 7001 - connected: true -> -others: < - key: 3735928559 - value: "\001A\007\014" -> -others: < - weight: 6.022 - inner: < - host: "lesha.mtv" - port: 8002 - > -> -bikeshed: BLUE -SomeGroup { - group_field: 8 -} -/* 2 unknown bytes */ -13: 4 -[test_proto.Ext.more]: < - data: "Big gobs for big rats" -> -[test_proto.greeting]: "adg" -[test_proto.greeting]: "easy" -[test_proto.greeting]: "cow" -/* 13 unknown bytes */ -201: "\t3G skiing" -/* 3 unknown bytes */ -202: 19 -` - -func TestMarshalText(t *testing.T) { - buf := new(bytes.Buffer) - if err := proto.MarshalText(buf, newTestMessage()); err != nil { - t.Fatalf("proto.MarshalText: %v", err) - } - s := buf.String() - if s != text { - t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v===\n", s, text) - } -} - -func TestMarshalTextCustomMessage(t *testing.T) { - buf := new(bytes.Buffer) - if err := proto.MarshalText(buf, &textMessage{}); err != nil { - t.Fatalf("proto.MarshalText: %v", err) - } - s := buf.String() - if s != "custom" { - t.Errorf("Got %q, expected %q", s, "custom") - } -} -func TestMarshalTextNil(t *testing.T) { - want := "" - tests := []proto.Message{nil, (*pb.MyMessage)(nil)} - for i, test := range tests { - buf := new(bytes.Buffer) - if err := proto.MarshalText(buf, test); err != nil { - t.Fatal(err) - } - if got := buf.String(); got != want { - t.Errorf("%d: got %q want %q", i, got, want) - } - } -} - -func TestMarshalTextUnknownEnum(t *testing.T) { - // The Color enum only specifies values 0-2. - m := &pb.MyMessage{Bikeshed: pb.MyMessage_Color(3).Enum()} - got := m.String() - const want = `bikeshed:3 ` - if got != want { - t.Errorf("\n got %q\nwant %q", got, want) - } -} - -func TestTextOneof(t *testing.T) { - tests := []struct { - m proto.Message - want string - }{ - // zero message - {&pb.Communique{}, ``}, - // scalar field - {&pb.Communique{Union: &pb.Communique_Number{4}}, `number:4`}, - // message field - {&pb.Communique{Union: &pb.Communique_Msg{ - &pb.Strings{StringField: proto.String("why hello!")}, - }}, `msg:`}, - // bad oneof (should not panic) - {&pb.Communique{Union: &pb.Communique_Msg{nil}}, `msg:/* nil */`}, - } - for _, test := range tests { - got := strings.TrimSpace(test.m.String()) - if got != test.want { - t.Errorf("\n got %s\nwant %s", got, test.want) - } - } -} - -func BenchmarkMarshalTextBuffered(b *testing.B) { - buf := new(bytes.Buffer) - m := newTestMessage() - for i := 0; i < b.N; i++ { - buf.Reset() - proto.MarshalText(buf, m) - } -} - -func BenchmarkMarshalTextUnbuffered(b *testing.B) { - w := ioutil.Discard - m := newTestMessage() - for i := 0; i < b.N; i++ { - proto.MarshalText(w, m) - } -} - -func compact(src string) string { - // s/[ \n]+/ /g; s/ $//; - dst := make([]byte, len(src)) - space, comment := false, false - j := 0 - for i := 0; i < len(src); i++ { - if strings.HasPrefix(src[i:], "/*") { - comment = true - i++ - continue - } - if comment && strings.HasPrefix(src[i:], "*/") { - comment = false - i++ - continue - } - if comment { - continue - } - c := src[i] - if c == ' ' || c == '\n' { - space = true - continue - } - if j > 0 && (dst[j-1] == ':' || dst[j-1] == '<' || dst[j-1] == '{') { - space = false - } - if c == '{' { - space = false - } - if space { - dst[j] = ' ' - j++ - space = false - } - dst[j] = c - j++ - } - if space { - dst[j] = ' ' - j++ - } - return string(dst[0:j]) -} - -var compactText = compact(text) - -func TestCompactText(t *testing.T) { - s := proto.CompactTextString(newTestMessage()) - if s != compactText { - t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v\n===\n", s, compactText) - } -} - -func TestStringEscaping(t *testing.T) { - testCases := []struct { - in *pb.Strings - out string - }{ - { - // Test data from C++ test (TextFormatTest.StringEscape). - // Single divergence: we don't escape apostrophes. - &pb.Strings{StringField: proto.String("\"A string with ' characters \n and \r newlines and \t tabs and \001 slashes \\ and multiple spaces")}, - "string_field: \"\\\"A string with ' characters \\n and \\r newlines and \\t tabs and \\001 slashes \\\\ and multiple spaces\"\n", - }, - { - // Test data from the same C++ test. - &pb.Strings{StringField: proto.String("\350\260\267\346\255\214")}, - "string_field: \"\\350\\260\\267\\346\\255\\214\"\n", - }, - { - // Some UTF-8. - &pb.Strings{StringField: proto.String("\x00\x01\xff\x81")}, - `string_field: "\000\001\377\201"` + "\n", - }, - } - - for i, tc := range testCases { - var buf bytes.Buffer - if err := proto.MarshalText(&buf, tc.in); err != nil { - t.Errorf("proto.MarsalText: %v", err) - continue - } - s := buf.String() - if s != tc.out { - t.Errorf("#%d: Got:\n%s\nExpected:\n%s\n", i, s, tc.out) - continue - } - - // Check round-trip. - pb := new(pb.Strings) - if err := proto.UnmarshalText(s, pb); err != nil { - t.Errorf("#%d: UnmarshalText: %v", i, err) - continue - } - if !proto.Equal(pb, tc.in) { - t.Errorf("#%d: Round-trip failed:\nstart: %v\n end: %v", i, tc.in, pb) - } - } -} - -// A limitedWriter accepts some output before it fails. -// This is a proxy for something like a nearly-full or imminently-failing disk, -// or a network connection that is about to die. -type limitedWriter struct { - b bytes.Buffer - limit int -} - -var outOfSpace = errors.New("proto: insufficient space") - -func (w *limitedWriter) Write(p []byte) (n int, err error) { - var avail = w.limit - w.b.Len() - if avail <= 0 { - return 0, outOfSpace - } - if len(p) <= avail { - return w.b.Write(p) - } - n, _ = w.b.Write(p[:avail]) - return n, outOfSpace -} - -func TestMarshalTextFailing(t *testing.T) { - // Try lots of different sizes to exercise more error code-paths. - for lim := 0; lim < len(text); lim++ { - buf := new(limitedWriter) - buf.limit = lim - err := proto.MarshalText(buf, newTestMessage()) - // We expect a certain error, but also some partial results in the buffer. - if err != outOfSpace { - t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v===\n", err, outOfSpace) - } - s := buf.b.String() - x := text[:buf.limit] - if s != x { - t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v===\n", s, x) - } - } -} - -func TestFloats(t *testing.T) { - tests := []struct { - f float64 - want string - }{ - {0, "0"}, - {4.7, "4.7"}, - {math.Inf(1), "inf"}, - {math.Inf(-1), "-inf"}, - {math.NaN(), "nan"}, - } - for _, test := range tests { - msg := &pb.FloatingPoint{F: &test.f} - got := strings.TrimSpace(msg.String()) - want := `f:` + test.want - if got != want { - t.Errorf("f=%f: got %q, want %q", test.f, got, want) - } - } -} - -func TestRepeatedNilText(t *testing.T) { - m := &pb.MessageList{ - Message: []*pb.MessageList_Message{ - nil, - &pb.MessageList_Message{ - Name: proto.String("Horse"), - }, - nil, - }, - } - want := `Message -Message { - name: "Horse" -} -Message -` - if s := proto.MarshalTextString(m); s != want { - t.Errorf(" got: %s\nwant: %s", s, want) - } -} - -func TestProto3Text(t *testing.T) { - tests := []struct { - m proto.Message - want string - }{ - // zero message - {&proto3pb.Message{}, ``}, - // zero message except for an empty byte slice - {&proto3pb.Message{Data: []byte{}}, ``}, - // trivial case - {&proto3pb.Message{Name: "Rob", HeightInCm: 175}, `name:"Rob" height_in_cm:175`}, - // empty map - {&pb.MessageWithMap{}, ``}, - // non-empty map; map format is the same as a repeated struct, - // and they are sorted by key (numerically for numeric keys). - { - &pb.MessageWithMap{NameMapping: map[int32]string{ - -1: "Negatory", - 7: "Lucky", - 1234: "Feist", - 6345789: "Otis", - }}, - `name_mapping: ` + - `name_mapping: ` + - `name_mapping: ` + - `name_mapping:`, - }, - // map with nil value; not well-defined, but we shouldn't crash - { - &pb.MessageWithMap{MsgMapping: map[int64]*pb.FloatingPoint{7: nil}}, - `msg_mapping:`, - }, - } - for _, test := range tests { - got := strings.TrimSpace(test.m.String()) - if got != test.want { - t.Errorf("\n got %s\nwant %s", got, test.want) - } - } -} - -func TestRacyMarshal(t *testing.T) { - // This test should be run with the race detector. - - any := &pb.MyMessage{Count: proto.Int32(47), Name: proto.String("David")} - proto.SetExtension(any, pb.E_Ext_Text, proto.String("bar")) - b, err := proto.Marshal(any) - if err != nil { - panic(err) - } - m := &proto3pb.Message{ - Name: "David", - ResultCount: 47, - Anything: &anypb.Any{TypeUrl: "type.googleapis.com/" + proto.MessageName(any), Value: b}, - } - - wantText := proto.MarshalTextString(m) - wantBytes, err := proto.Marshal(m) - if err != nil { - t.Fatalf("proto.Marshal error: %v", err) - } - - var wg sync.WaitGroup - defer wg.Wait() - wg.Add(20) - for i := 0; i < 10; i++ { - go func() { - defer wg.Done() - got := proto.MarshalTextString(m) - if got != wantText { - t.Errorf("proto.MarshalTextString = %q, want %q", got, wantText) - } - }() - go func() { - defer wg.Done() - got, err := proto.Marshal(m) - if !bytes.Equal(got, wantBytes) || err != nil { - t.Errorf("proto.Marshal = (%x, %v), want (%x, nil)", got, err, wantBytes) - } - }() - } -} diff --git a/vendor/github.com/golang/protobuf/ptypes/any/any.proto b/vendor/github.com/golang/protobuf/ptypes/any/any.proto deleted file mode 100644 index c7486676..00000000 --- a/vendor/github.com/golang/protobuf/ptypes/any/any.proto +++ /dev/null @@ -1,149 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -syntax = "proto3"; - -package google.protobuf; - -option csharp_namespace = "Google.Protobuf.WellKnownTypes"; -option go_package = "github.com/golang/protobuf/ptypes/any"; -option java_package = "com.google.protobuf"; -option java_outer_classname = "AnyProto"; -option java_multiple_files = true; -option objc_class_prefix = "GPB"; - -// `Any` contains an arbitrary serialized protocol buffer message along with a -// URL that describes the type of the serialized message. -// -// Protobuf library provides support to pack/unpack Any values in the form -// of utility functions or additional generated methods of the Any type. -// -// Example 1: Pack and unpack a message in C++. -// -// Foo foo = ...; -// Any any; -// any.PackFrom(foo); -// ... -// if (any.UnpackTo(&foo)) { -// ... -// } -// -// Example 2: Pack and unpack a message in Java. -// -// Foo foo = ...; -// Any any = Any.pack(foo); -// ... -// if (any.is(Foo.class)) { -// foo = any.unpack(Foo.class); -// } -// -// Example 3: Pack and unpack a message in Python. -// -// foo = Foo(...) -// any = Any() -// any.Pack(foo) -// ... -// if any.Is(Foo.DESCRIPTOR): -// any.Unpack(foo) -// ... -// -// Example 4: Pack and unpack a message in Go -// -// foo := &pb.Foo{...} -// any, err := ptypes.MarshalAny(foo) -// ... -// foo := &pb.Foo{} -// if err := ptypes.UnmarshalAny(any, foo); err != nil { -// ... -// } -// -// The pack methods provided by protobuf library will by default use -// 'type.googleapis.com/full.type.name' as the type URL and the unpack -// methods only use the fully qualified type name after the last '/' -// in the type URL, for example "foo.bar.com/x/y.z" will yield type -// name "y.z". -// -// -// JSON -// ==== -// The JSON representation of an `Any` value uses the regular -// representation of the deserialized, embedded message, with an -// additional field `@type` which contains the type URL. Example: -// -// package google.profile; -// message Person { -// string first_name = 1; -// string last_name = 2; -// } -// -// { -// "@type": "type.googleapis.com/google.profile.Person", -// "firstName": , -// "lastName": -// } -// -// If the embedded message type is well-known and has a custom JSON -// representation, that representation will be embedded adding a field -// `value` which holds the custom JSON in addition to the `@type` -// field. Example (for message [google.protobuf.Duration][]): -// -// { -// "@type": "type.googleapis.com/google.protobuf.Duration", -// "value": "1.212s" -// } -// -message Any { - // A URL/resource name whose content describes the type of the - // serialized protocol buffer message. - // - // For URLs which use the scheme `http`, `https`, or no scheme, the - // following restrictions and interpretations apply: - // - // * If no scheme is provided, `https` is assumed. - // * The last segment of the URL's path must represent the fully - // qualified name of the type (as in `path/google.protobuf.Duration`). - // The name should be in a canonical form (e.g., leading "." is - // not accepted). - // * An HTTP GET on the URL must yield a [google.protobuf.Type][] - // value in binary format, or produce an error. - // * Applications are allowed to cache lookup results based on the - // URL, or have them precompiled into a binary to avoid any - // lookup. Therefore, binary compatibility needs to be preserved - // on changes to types. (Use versioned type names to manage - // breaking changes.) - // - // Schemes other than `http`, `https` (or the empty scheme) might be - // used with implementation specific semantics. - // - string type_url = 1; - - // Must be a valid serialized protocol buffer of the above specified type. - bytes value = 2; -} diff --git a/vendor/github.com/golang/protobuf/ptypes/any_test.go b/vendor/github.com/golang/protobuf/ptypes/any_test.go deleted file mode 100644 index 871c6de1..00000000 --- a/vendor/github.com/golang/protobuf/ptypes/any_test.go +++ /dev/null @@ -1,154 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2016 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package ptypes - -import ( - "testing" - - "github.com/golang/protobuf/proto" - pb "github.com/golang/protobuf/protoc-gen-go/descriptor" - "github.com/golang/protobuf/ptypes/any" -) - -func TestMarshalUnmarshal(t *testing.T) { - orig := &any.Any{Value: []byte("test")} - - packed, err := MarshalAny(orig) - if err != nil { - t.Errorf("MarshalAny(%+v): got: _, %v exp: _, nil", orig, err) - } - - unpacked := &any.Any{} - err = UnmarshalAny(packed, unpacked) - if err != nil || !proto.Equal(unpacked, orig) { - t.Errorf("got: %v, %+v; want nil, %+v", err, unpacked, orig) - } -} - -func TestIs(t *testing.T) { - a, err := MarshalAny(&pb.FileDescriptorProto{}) - if err != nil { - t.Fatal(err) - } - if Is(a, &pb.DescriptorProto{}) { - // No spurious match for message names of different length. - t.Error("FileDescriptorProto is not a DescriptorProto, but Is says it is") - } - if Is(a, &pb.EnumDescriptorProto{}) { - // No spurious match for message names of equal length. - t.Error("FileDescriptorProto is not an EnumDescriptorProto, but Is says it is") - } - if !Is(a, &pb.FileDescriptorProto{}) { - t.Error("FileDescriptorProto is indeed a FileDescriptorProto, but Is says it is not") - } -} - -func TestIsDifferentUrlPrefixes(t *testing.T) { - m := &pb.FileDescriptorProto{} - a := &any.Any{TypeUrl: "foo/bar/" + proto.MessageName(m)} - if !Is(a, m) { - t.Errorf("message with type url %q didn't satisfy Is for type %q", a.TypeUrl, proto.MessageName(m)) - } -} - -func TestIsCornerCases(t *testing.T) { - m := &pb.FileDescriptorProto{} - if Is(nil, m) { - t.Errorf("message with nil type url incorrectly claimed to be %q", proto.MessageName(m)) - } - noPrefix := &any.Any{TypeUrl: proto.MessageName(m)} - if Is(noPrefix, m) { - t.Errorf("message with type url %q incorrectly claimed to be %q", noPrefix.TypeUrl, proto.MessageName(m)) - } - shortPrefix := &any.Any{TypeUrl: "/" + proto.MessageName(m)} - if !Is(shortPrefix, m) { - t.Errorf("message with type url %q didn't satisfy Is for type %q", shortPrefix.TypeUrl, proto.MessageName(m)) - } -} - -func TestUnmarshalDynamic(t *testing.T) { - want := &pb.FileDescriptorProto{Name: proto.String("foo")} - a, err := MarshalAny(want) - if err != nil { - t.Fatal(err) - } - var got DynamicAny - if err := UnmarshalAny(a, &got); err != nil { - t.Fatal(err) - } - if !proto.Equal(got.Message, want) { - t.Errorf("invalid result from UnmarshalAny, got %q want %q", got.Message, want) - } -} - -func TestEmpty(t *testing.T) { - want := &pb.FileDescriptorProto{} - a, err := MarshalAny(want) - if err != nil { - t.Fatal(err) - } - got, err := Empty(a) - if err != nil { - t.Fatal(err) - } - if !proto.Equal(got, want) { - t.Errorf("unequal empty message, got %q, want %q", got, want) - } - - // that's a valid type_url for a message which shouldn't be linked into this - // test binary. We want an error. - a.TypeUrl = "type.googleapis.com/google.protobuf.FieldMask" - if _, err := Empty(a); err == nil { - t.Errorf("got no error for an attempt to create a message of type %q, which shouldn't be linked in", a.TypeUrl) - } -} - -func TestEmptyCornerCases(t *testing.T) { - _, err := Empty(nil) - if err == nil { - t.Error("expected Empty for nil to fail") - } - want := &pb.FileDescriptorProto{} - noPrefix := &any.Any{TypeUrl: proto.MessageName(want)} - _, err = Empty(noPrefix) - if err == nil { - t.Errorf("expected Empty for any type %q to fail", noPrefix.TypeUrl) - } - shortPrefix := &any.Any{TypeUrl: "/" + proto.MessageName(want)} - got, err := Empty(shortPrefix) - if err != nil { - t.Errorf("Empty for any type %q failed: %s", shortPrefix.TypeUrl, err) - } - if !proto.Equal(got, want) { - t.Errorf("Empty for any type %q differs, got %q, want %q", shortPrefix.TypeUrl, got, want) - } -} diff --git a/vendor/github.com/golang/protobuf/ptypes/duration/duration.proto b/vendor/github.com/golang/protobuf/ptypes/duration/duration.proto deleted file mode 100644 index 975fce41..00000000 --- a/vendor/github.com/golang/protobuf/ptypes/duration/duration.proto +++ /dev/null @@ -1,117 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -syntax = "proto3"; - -package google.protobuf; - -option csharp_namespace = "Google.Protobuf.WellKnownTypes"; -option cc_enable_arenas = true; -option go_package = "github.com/golang/protobuf/ptypes/duration"; -option java_package = "com.google.protobuf"; -option java_outer_classname = "DurationProto"; -option java_multiple_files = true; -option objc_class_prefix = "GPB"; - -// A Duration represents a signed, fixed-length span of time represented -// as a count of seconds and fractions of seconds at nanosecond -// resolution. It is independent of any calendar and concepts like "day" -// or "month". It is related to Timestamp in that the difference between -// two Timestamp values is a Duration and it can be added or subtracted -// from a Timestamp. Range is approximately +-10,000 years. -// -// # Examples -// -// Example 1: Compute Duration from two Timestamps in pseudo code. -// -// Timestamp start = ...; -// Timestamp end = ...; -// Duration duration = ...; -// -// duration.seconds = end.seconds - start.seconds; -// duration.nanos = end.nanos - start.nanos; -// -// if (duration.seconds < 0 && duration.nanos > 0) { -// duration.seconds += 1; -// duration.nanos -= 1000000000; -// } else if (durations.seconds > 0 && duration.nanos < 0) { -// duration.seconds -= 1; -// duration.nanos += 1000000000; -// } -// -// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code. -// -// Timestamp start = ...; -// Duration duration = ...; -// Timestamp end = ...; -// -// end.seconds = start.seconds + duration.seconds; -// end.nanos = start.nanos + duration.nanos; -// -// if (end.nanos < 0) { -// end.seconds -= 1; -// end.nanos += 1000000000; -// } else if (end.nanos >= 1000000000) { -// end.seconds += 1; -// end.nanos -= 1000000000; -// } -// -// Example 3: Compute Duration from datetime.timedelta in Python. -// -// td = datetime.timedelta(days=3, minutes=10) -// duration = Duration() -// duration.FromTimedelta(td) -// -// # JSON Mapping -// -// In JSON format, the Duration type is encoded as a string rather than an -// object, where the string ends in the suffix "s" (indicating seconds) and -// is preceded by the number of seconds, with nanoseconds expressed as -// fractional seconds. For example, 3 seconds with 0 nanoseconds should be -// encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should -// be expressed in JSON format as "3.000000001s", and 3 seconds and 1 -// microsecond should be expressed in JSON format as "3.000001s". -// -// -message Duration { - - // Signed seconds of the span of time. Must be from -315,576,000,000 - // to +315,576,000,000 inclusive. Note: these bounds are computed from: - // 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years - int64 seconds = 1; - - // Signed fractions of a second at nanosecond resolution of the span - // of time. Durations less than one second are represented with a 0 - // `seconds` field and a positive or negative `nanos` field. For durations - // of one second or more, a non-zero value for the `nanos` field must be - // of the same sign as the `seconds` field. Must be from -999,999,999 - // to +999,999,999 inclusive. - int32 nanos = 2; -} diff --git a/vendor/github.com/golang/protobuf/ptypes/duration_test.go b/vendor/github.com/golang/protobuf/ptypes/duration_test.go deleted file mode 100644 index e00491a3..00000000 --- a/vendor/github.com/golang/protobuf/ptypes/duration_test.go +++ /dev/null @@ -1,121 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2016 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package ptypes - -import ( - "math" - "testing" - "time" - - "github.com/golang/protobuf/proto" - durpb "github.com/golang/protobuf/ptypes/duration" -) - -const ( - minGoSeconds = math.MinInt64 / int64(1e9) - maxGoSeconds = math.MaxInt64 / int64(1e9) -) - -var durationTests = []struct { - proto *durpb.Duration - isValid bool - inRange bool - dur time.Duration -}{ - // The zero duration. - {&durpb.Duration{Seconds: 0, Nanos: 0}, true, true, 0}, - // Some ordinary non-zero durations. - {&durpb.Duration{Seconds: 100, Nanos: 0}, true, true, 100 * time.Second}, - {&durpb.Duration{Seconds: -100, Nanos: 0}, true, true, -100 * time.Second}, - {&durpb.Duration{Seconds: 100, Nanos: 987}, true, true, 100*time.Second + 987}, - {&durpb.Duration{Seconds: -100, Nanos: -987}, true, true, -(100*time.Second + 987)}, - // The largest duration representable in Go. - {&durpb.Duration{Seconds: maxGoSeconds, Nanos: int32(math.MaxInt64 - 1e9*maxGoSeconds)}, true, true, math.MaxInt64}, - // The smallest duration representable in Go. - {&durpb.Duration{Seconds: minGoSeconds, Nanos: int32(math.MinInt64 - 1e9*minGoSeconds)}, true, true, math.MinInt64}, - {nil, false, false, 0}, - {&durpb.Duration{Seconds: -100, Nanos: 987}, false, false, 0}, - {&durpb.Duration{Seconds: 100, Nanos: -987}, false, false, 0}, - {&durpb.Duration{Seconds: math.MinInt64, Nanos: 0}, false, false, 0}, - {&durpb.Duration{Seconds: math.MaxInt64, Nanos: 0}, false, false, 0}, - // The largest valid duration. - {&durpb.Duration{Seconds: maxSeconds, Nanos: 1e9 - 1}, true, false, 0}, - // The smallest valid duration. - {&durpb.Duration{Seconds: minSeconds, Nanos: -(1e9 - 1)}, true, false, 0}, - // The smallest invalid duration above the valid range. - {&durpb.Duration{Seconds: maxSeconds + 1, Nanos: 0}, false, false, 0}, - // The largest invalid duration below the valid range. - {&durpb.Duration{Seconds: minSeconds - 1, Nanos: -(1e9 - 1)}, false, false, 0}, - // One nanosecond past the largest duration representable in Go. - {&durpb.Duration{Seconds: maxGoSeconds, Nanos: int32(math.MaxInt64-1e9*maxGoSeconds) + 1}, true, false, 0}, - // One nanosecond past the smallest duration representable in Go. - {&durpb.Duration{Seconds: minGoSeconds, Nanos: int32(math.MinInt64-1e9*minGoSeconds) - 1}, true, false, 0}, - // One second past the largest duration representable in Go. - {&durpb.Duration{Seconds: maxGoSeconds + 1, Nanos: int32(math.MaxInt64 - 1e9*maxGoSeconds)}, true, false, 0}, - // One second past the smallest duration representable in Go. - {&durpb.Duration{Seconds: minGoSeconds - 1, Nanos: int32(math.MinInt64 - 1e9*minGoSeconds)}, true, false, 0}, -} - -func TestValidateDuration(t *testing.T) { - for _, test := range durationTests { - err := validateDuration(test.proto) - gotValid := (err == nil) - if gotValid != test.isValid { - t.Errorf("validateDuration(%v) = %t, want %t", test.proto, gotValid, test.isValid) - } - } -} - -func TestDuration(t *testing.T) { - for _, test := range durationTests { - got, err := Duration(test.proto) - gotOK := (err == nil) - wantOK := test.isValid && test.inRange - if gotOK != wantOK { - t.Errorf("Duration(%v) ok = %t, want %t", test.proto, gotOK, wantOK) - } - if err == nil && got != test.dur { - t.Errorf("Duration(%v) = %v, want %v", test.proto, got, test.dur) - } - } -} - -func TestDurationProto(t *testing.T) { - for _, test := range durationTests { - if test.isValid && test.inRange { - got := DurationProto(test.dur) - if !proto.Equal(got, test.proto) { - t.Errorf("DurationProto(%v) = %v, want %v", test.dur, got, test.proto) - } - } - } -} diff --git a/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto b/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto deleted file mode 100644 index 06750ab1..00000000 --- a/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto +++ /dev/null @@ -1,133 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -syntax = "proto3"; - -package google.protobuf; - -option csharp_namespace = "Google.Protobuf.WellKnownTypes"; -option cc_enable_arenas = true; -option go_package = "github.com/golang/protobuf/ptypes/timestamp"; -option java_package = "com.google.protobuf"; -option java_outer_classname = "TimestampProto"; -option java_multiple_files = true; -option objc_class_prefix = "GPB"; - -// A Timestamp represents a point in time independent of any time zone -// or calendar, represented as seconds and fractions of seconds at -// nanosecond resolution in UTC Epoch time. It is encoded using the -// Proleptic Gregorian Calendar which extends the Gregorian calendar -// backwards to year one. It is encoded assuming all minutes are 60 -// seconds long, i.e. leap seconds are "smeared" so that no leap second -// table is needed for interpretation. Range is from -// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. -// By restricting to that range, we ensure that we can convert to -// and from RFC 3339 date strings. -// See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt). -// -// # Examples -// -// Example 1: Compute Timestamp from POSIX `time()`. -// -// Timestamp timestamp; -// timestamp.set_seconds(time(NULL)); -// timestamp.set_nanos(0); -// -// Example 2: Compute Timestamp from POSIX `gettimeofday()`. -// -// struct timeval tv; -// gettimeofday(&tv, NULL); -// -// Timestamp timestamp; -// timestamp.set_seconds(tv.tv_sec); -// timestamp.set_nanos(tv.tv_usec * 1000); -// -// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. -// -// FILETIME ft; -// GetSystemTimeAsFileTime(&ft); -// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; -// -// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z -// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. -// Timestamp timestamp; -// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); -// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); -// -// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. -// -// long millis = System.currentTimeMillis(); -// -// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) -// .setNanos((int) ((millis % 1000) * 1000000)).build(); -// -// -// Example 5: Compute Timestamp from current time in Python. -// -// timestamp = Timestamp() -// timestamp.GetCurrentTime() -// -// # JSON Mapping -// -// In JSON format, the Timestamp type is encoded as a string in the -// [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the -// format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" -// where {year} is always expressed using four digits while {month}, {day}, -// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional -// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), -// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone -// is required, though only UTC (as indicated by "Z") is presently supported. -// -// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past -// 01:30 UTC on January 15, 2017. -// -// In JavaScript, one can convert a Date object to this format using the -// standard [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString] -// method. In Python, a standard `datetime.datetime` object can be converted -// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) -// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one -// can use the Joda Time's [`ISODateTimeFormat.dateTime()`]( -// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--) -// to obtain a formatter capable of generating timestamps in this format. -// -// -message Timestamp { - - // Represents seconds of UTC time since Unix epoch - // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to - // 9999-12-31T23:59:59Z inclusive. - int64 seconds = 1; - - // Non-negative fractions of a second at nanosecond resolution. Negative - // second values with fractions must still have non-negative nanos values - // that count forward in time. Must be from 0 to 999,999,999 - // inclusive. - int32 nanos = 2; -} diff --git a/vendor/github.com/golang/protobuf/ptypes/timestamp_test.go b/vendor/github.com/golang/protobuf/ptypes/timestamp_test.go deleted file mode 100644 index 6e3c969b..00000000 --- a/vendor/github.com/golang/protobuf/ptypes/timestamp_test.go +++ /dev/null @@ -1,153 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2016 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package ptypes - -import ( - "math" - "testing" - "time" - - "github.com/golang/protobuf/proto" - tspb "github.com/golang/protobuf/ptypes/timestamp" -) - -var tests = []struct { - ts *tspb.Timestamp - valid bool - t time.Time -}{ - // The timestamp representing the Unix epoch date. - {&tspb.Timestamp{Seconds: 0, Nanos: 0}, true, utcDate(1970, 1, 1)}, - // The smallest representable timestamp. - {&tspb.Timestamp{Seconds: math.MinInt64, Nanos: math.MinInt32}, false, - time.Unix(math.MinInt64, math.MinInt32).UTC()}, - // The smallest representable timestamp with non-negative nanos. - {&tspb.Timestamp{Seconds: math.MinInt64, Nanos: 0}, false, time.Unix(math.MinInt64, 0).UTC()}, - // The earliest valid timestamp. - {&tspb.Timestamp{Seconds: minValidSeconds, Nanos: 0}, true, utcDate(1, 1, 1)}, - //"0001-01-01T00:00:00Z"}, - // The largest representable timestamp. - {&tspb.Timestamp{Seconds: math.MaxInt64, Nanos: math.MaxInt32}, false, - time.Unix(math.MaxInt64, math.MaxInt32).UTC()}, - // The largest representable timestamp with nanos in range. - {&tspb.Timestamp{Seconds: math.MaxInt64, Nanos: 1e9 - 1}, false, - time.Unix(math.MaxInt64, 1e9-1).UTC()}, - // The largest valid timestamp. - {&tspb.Timestamp{Seconds: maxValidSeconds - 1, Nanos: 1e9 - 1}, true, - time.Date(9999, 12, 31, 23, 59, 59, 1e9-1, time.UTC)}, - // The smallest invalid timestamp that is larger than the valid range. - {&tspb.Timestamp{Seconds: maxValidSeconds, Nanos: 0}, false, time.Unix(maxValidSeconds, 0).UTC()}, - // A date before the epoch. - {&tspb.Timestamp{Seconds: -281836800, Nanos: 0}, true, utcDate(1961, 1, 26)}, - // A date after the epoch. - {&tspb.Timestamp{Seconds: 1296000000, Nanos: 0}, true, utcDate(2011, 1, 26)}, - // A date after the epoch, in the middle of the day. - {&tspb.Timestamp{Seconds: 1296012345, Nanos: 940483}, true, - time.Date(2011, 1, 26, 3, 25, 45, 940483, time.UTC)}, -} - -func TestValidateTimestamp(t *testing.T) { - for _, s := range tests { - got := validateTimestamp(s.ts) - if (got == nil) != s.valid { - t.Errorf("validateTimestamp(%v) = %v, want %v", s.ts, got, s.valid) - } - } -} - -func TestTimestamp(t *testing.T) { - for _, s := range tests { - got, err := Timestamp(s.ts) - if (err == nil) != s.valid { - t.Errorf("Timestamp(%v) error = %v, but valid = %t", s.ts, err, s.valid) - } else if s.valid && got != s.t { - t.Errorf("Timestamp(%v) = %v, want %v", s.ts, got, s.t) - } - } - // Special case: a nil Timestamp is an error, but returns the 0 Unix time. - got, err := Timestamp(nil) - want := time.Unix(0, 0).UTC() - if got != want { - t.Errorf("Timestamp(nil) = %v, want %v", got, want) - } - if err == nil { - t.Errorf("Timestamp(nil) error = nil, expected error") - } -} - -func TestTimestampProto(t *testing.T) { - for _, s := range tests { - got, err := TimestampProto(s.t) - if (err == nil) != s.valid { - t.Errorf("TimestampProto(%v) error = %v, but valid = %t", s.t, err, s.valid) - } else if s.valid && !proto.Equal(got, s.ts) { - t.Errorf("TimestampProto(%v) = %v, want %v", s.t, got, s.ts) - } - } - // No corresponding special case here: no time.Time results in a nil Timestamp. -} - -func TestTimestampString(t *testing.T) { - for _, test := range []struct { - ts *tspb.Timestamp - want string - }{ - // Not much testing needed because presumably time.Format is - // well-tested. - {&tspb.Timestamp{Seconds: 0, Nanos: 0}, "1970-01-01T00:00:00Z"}, - {&tspb.Timestamp{Seconds: minValidSeconds - 1, Nanos: 0}, "(timestamp: seconds:-62135596801 before 0001-01-01)"}, - } { - got := TimestampString(test.ts) - if got != test.want { - t.Errorf("TimestampString(%v) = %q, want %q", test.ts, got, test.want) - } - } -} - -func utcDate(year, month, day int) time.Time { - return time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC) -} - -func TestTimestampNow(t *testing.T) { - // Bracket the expected time. - before := time.Now() - ts := TimestampNow() - after := time.Now() - - tm, err := Timestamp(ts) - if err != nil { - t.Errorf("between %v and %v\nTimestampNow() = %v\nwhich is invalid (%v)", before, after, ts, err) - } - if tm.Before(before) || tm.After(after) { - t.Errorf("between %v and %v\nTimestamp(TimestampNow()) = %v", before, after, tm) - } -} diff --git a/vendor/github.com/golang/protobuf/ptypes/wrappers/wrappers.proto b/vendor/github.com/golang/protobuf/ptypes/wrappers/wrappers.proto deleted file mode 100644 index 01947639..00000000 --- a/vendor/github.com/golang/protobuf/ptypes/wrappers/wrappers.proto +++ /dev/null @@ -1,118 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Wrappers for primitive (non-message) types. These types are useful -// for embedding primitives in the `google.protobuf.Any` type and for places -// where we need to distinguish between the absence of a primitive -// typed field and its default value. - -syntax = "proto3"; - -package google.protobuf; - -option csharp_namespace = "Google.Protobuf.WellKnownTypes"; -option cc_enable_arenas = true; -option go_package = "github.com/golang/protobuf/ptypes/wrappers"; -option java_package = "com.google.protobuf"; -option java_outer_classname = "WrappersProto"; -option java_multiple_files = true; -option objc_class_prefix = "GPB"; - -// Wrapper message for `double`. -// -// The JSON representation for `DoubleValue` is JSON number. -message DoubleValue { - // The double value. - double value = 1; -} - -// Wrapper message for `float`. -// -// The JSON representation for `FloatValue` is JSON number. -message FloatValue { - // The float value. - float value = 1; -} - -// Wrapper message for `int64`. -// -// The JSON representation for `Int64Value` is JSON string. -message Int64Value { - // The int64 value. - int64 value = 1; -} - -// Wrapper message for `uint64`. -// -// The JSON representation for `UInt64Value` is JSON string. -message UInt64Value { - // The uint64 value. - uint64 value = 1; -} - -// Wrapper message for `int32`. -// -// The JSON representation for `Int32Value` is JSON number. -message Int32Value { - // The int32 value. - int32 value = 1; -} - -// Wrapper message for `uint32`. -// -// The JSON representation for `UInt32Value` is JSON number. -message UInt32Value { - // The uint32 value. - uint32 value = 1; -} - -// Wrapper message for `bool`. -// -// The JSON representation for `BoolValue` is JSON `true` and `false`. -message BoolValue { - // The bool value. - bool value = 1; -} - -// Wrapper message for `string`. -// -// The JSON representation for `StringValue` is JSON string. -message StringValue { - // The string value. - string value = 1; -} - -// Wrapper message for `bytes`. -// -// The JSON representation for `BytesValue` is JSON string. -message BytesValue { - // The bytes value. - bytes value = 1; -} diff --git a/vendor/github.com/golang/protobuf/regenerate.sh b/vendor/github.com/golang/protobuf/regenerate.sh deleted file mode 100755 index dc7e2d1f..00000000 --- a/vendor/github.com/golang/protobuf/regenerate.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/bash - -set -e - -# Install the working tree's protoc-gen-gen in a tempdir. -tmpdir=$(mktemp -d -t regen-wkt.XXXXXX) -trap 'rm -rf $tmpdir' EXIT -mkdir -p $tmpdir/bin -PATH=$tmpdir/bin:$PATH -GOBIN=$tmpdir/bin go install ./protoc-gen-go - -# Public imports require at least Go 1.9. -supportTypeAliases="" -if go list -f '{{context.ReleaseTags}}' runtime | grep -q go1.9; then - supportTypeAliases=1 -fi - -# Generate various test protos. -PROTO_DIRS=( - conformance/internal/conformance_proto - jsonpb/jsonpb_test_proto - proto - protoc-gen-go/testdata -) -for dir in ${PROTO_DIRS[@]}; do - for p in `find $dir -name "*.proto"`; do - if [[ $p == */import_public/* && ! $supportTypeAliases ]]; then - echo "# $p (skipped)" - continue; - fi - echo "# $p" - protoc -I$dir --go_out=plugins=grpc,paths=source_relative:$dir $p - done -done - -# Deriving the location of the source protos from the path to the -# protoc binary may be a bit odd, but this is what protoc itself does. -PROTO_INCLUDE=$(dirname $(dirname $(which protoc)))/include - -# Well-known types. -WKT_PROTOS=(any duration empty struct timestamp wrappers) -for p in ${WKT_PROTOS[@]}; do - echo "# google/protobuf/$p.proto" - protoc --go_out=paths=source_relative:$tmpdir google/protobuf/$p.proto - cp $tmpdir/google/protobuf/$p.pb.go ptypes/$p - cp $PROTO_INCLUDE/google/protobuf/$p.proto ptypes/$p -done - -# descriptor.proto. -echo "# google/protobuf/descriptor.proto" -protoc --go_out=paths=source_relative:$tmpdir google/protobuf/descriptor.proto -cp $tmpdir/google/protobuf/descriptor.pb.go protoc-gen-go/descriptor -cp $PROTO_INCLUDE/google/protobuf/descriptor.proto protoc-gen-go/descriptor diff --git a/vendor/github.com/jessevdk/go-flags/README.md b/vendor/github.com/jessevdk/go-flags/README.md deleted file mode 100644 index 3b02394e..00000000 --- a/vendor/github.com/jessevdk/go-flags/README.md +++ /dev/null @@ -1,134 +0,0 @@ -go-flags: a go library for parsing command line arguments -========================================================= - -[![GoDoc](https://godoc.org/github.com/jessevdk/go-flags?status.png)](https://godoc.org/github.com/jessevdk/go-flags) [![Build Status](https://travis-ci.org/jessevdk/go-flags.svg?branch=master)](https://travis-ci.org/jessevdk/go-flags) [![Coverage Status](https://img.shields.io/coveralls/jessevdk/go-flags.svg)](https://coveralls.io/r/jessevdk/go-flags?branch=master) - -This library provides similar functionality to the builtin flag library of -go, but provides much more functionality and nicer formatting. From the -documentation: - -Package flags provides an extensive command line option parser. -The flags package is similar in functionality to the go builtin flag package -but provides more options and uses reflection to provide a convenient and -succinct way of specifying command line options. - -Supported features: -* Options with short names (-v) -* Options with long names (--verbose) -* Options with and without arguments (bool v.s. other type) -* Options with optional arguments and default values -* Multiple option groups each containing a set of options -* Generate and print well-formatted help message -* Passing remaining command line arguments after -- (optional) -* Ignoring unknown command line options (optional) -* Supports -I/usr/include -I=/usr/include -I /usr/include option argument specification -* Supports multiple short options -aux -* Supports all primitive go types (string, int{8..64}, uint{8..64}, float) -* Supports same option multiple times (can store in slice or last option counts) -* Supports maps -* Supports function callbacks -* Supports namespaces for (nested) option groups - -The flags package uses structs, reflection and struct field tags -to allow users to specify command line options. This results in very simple -and concise specification of your application options. For example: - -```go -type Options struct { - Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"` -} -``` - -This specifies one option with a short name -v and a long name --verbose. -When either -v or --verbose is found on the command line, a 'true' value -will be appended to the Verbose field. e.g. when specifying -vvv, the -resulting value of Verbose will be {[true, true, true]}. - -Example: --------- -```go -var opts struct { - // Slice of bool will append 'true' each time the option - // is encountered (can be set multiple times, like -vvv) - Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"` - - // Example of automatic marshalling to desired type (uint) - Offset uint `long:"offset" description:"Offset"` - - // Example of a callback, called each time the option is found. - Call func(string) `short:"c" description:"Call phone number"` - - // Example of a required flag - Name string `short:"n" long:"name" description:"A name" required:"true"` - - // Example of a value name - File string `short:"f" long:"file" description:"A file" value-name:"FILE"` - - // Example of a pointer - Ptr *int `short:"p" description:"A pointer to an integer"` - - // Example of a slice of strings - StringSlice []string `short:"s" description:"A slice of strings"` - - // Example of a slice of pointers - PtrSlice []*string `long:"ptrslice" description:"A slice of pointers to string"` - - // Example of a map - IntMap map[string]int `long:"intmap" description:"A map from string to int"` -} - -// Callback which will invoke callto: to call a number. -// Note that this works just on OS X (and probably only with -// Skype) but it shows the idea. -opts.Call = func(num string) { - cmd := exec.Command("open", "callto:"+num) - cmd.Start() - cmd.Process.Release() -} - -// Make some fake arguments to parse. -args := []string{ - "-vv", - "--offset=5", - "-n", "Me", - "-p", "3", - "-s", "hello", - "-s", "world", - "--ptrslice", "hello", - "--ptrslice", "world", - "--intmap", "a:1", - "--intmap", "b:5", - "arg1", - "arg2", - "arg3", -} - -// Parse flags from `args'. Note that here we use flags.ParseArgs for -// the sake of making a working example. Normally, you would simply use -// flags.Parse(&opts) which uses os.Args -args, err := flags.ParseArgs(&opts, args) - -if err != nil { - panic(err) -} - -fmt.Printf("Verbosity: %v\n", opts.Verbose) -fmt.Printf("Offset: %d\n", opts.Offset) -fmt.Printf("Name: %s\n", opts.Name) -fmt.Printf("Ptr: %d\n", *opts.Ptr) -fmt.Printf("StringSlice: %v\n", opts.StringSlice) -fmt.Printf("PtrSlice: [%v %v]\n", *opts.PtrSlice[0], *opts.PtrSlice[1]) -fmt.Printf("IntMap: [a:%v b:%v]\n", opts.IntMap["a"], opts.IntMap["b"]) -fmt.Printf("Remaining args: %s\n", strings.Join(args, " ")) - -// Output: Verbosity: [true true] -// Offset: 5 -// Name: Me -// Ptr: 3 -// StringSlice: [hello world] -// PtrSlice: [hello world] -// IntMap: [a:1 b:5] -// Remaining args: arg1 arg2 arg3 -``` - -More information can be found in the godocs: diff --git a/vendor/github.com/jessevdk/go-flags/arg_test.go b/vendor/github.com/jessevdk/go-flags/arg_test.go deleted file mode 100644 index c7c0a612..00000000 --- a/vendor/github.com/jessevdk/go-flags/arg_test.go +++ /dev/null @@ -1,163 +0,0 @@ -package flags - -import ( - "testing" -) - -func TestPositional(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Positional struct { - Command int - Filename string - Rest []string - } `positional-args:"yes" required:"yes"` - }{} - - p := NewParser(&opts, Default) - ret, err := p.ParseArgs([]string{"10", "arg_test.go", "a", "b"}) - - if err != nil { - t.Fatalf("Unexpected error: %v", err) - return - } - - if opts.Positional.Command != 10 { - t.Fatalf("Expected opts.Positional.Command to be 10, but got %v", opts.Positional.Command) - } - - if opts.Positional.Filename != "arg_test.go" { - t.Fatalf("Expected opts.Positional.Filename to be \"arg_test.go\", but got %v", opts.Positional.Filename) - } - - assertStringArray(t, opts.Positional.Rest, []string{"a", "b"}) - assertStringArray(t, ret, []string{}) -} - -func TestPositionalRequired(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Positional struct { - Command int - Filename string - Rest []string - } `positional-args:"yes" required:"yes"` - }{} - - p := NewParser(&opts, None) - _, err := p.ParseArgs([]string{"10"}) - - assertError(t, err, ErrRequired, "the required argument `Filename` was not provided") -} - -func TestPositionalRequiredRest1Fail(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Positional struct { - Rest []string `required:"yes"` - } `positional-args:"yes"` - }{} - - p := NewParser(&opts, None) - _, err := p.ParseArgs([]string{}) - - assertError(t, err, ErrRequired, "the required argument `Rest (at least 1 argument)` was not provided") -} - -func TestPositionalRequiredRest1Pass(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Positional struct { - Rest []string `required:"yes"` - } `positional-args:"yes"` - }{} - - p := NewParser(&opts, None) - _, err := p.ParseArgs([]string{"rest1"}) - - if err != nil { - t.Fatalf("Unexpected error: %v", err) - return - } - - if len(opts.Positional.Rest) != 1 { - t.Fatalf("Expected 1 positional rest argument") - } - - assertString(t, opts.Positional.Rest[0], "rest1") -} - -func TestPositionalRequiredRest2Fail(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Positional struct { - Rest []string `required:"2"` - } `positional-args:"yes"` - }{} - - p := NewParser(&opts, None) - _, err := p.ParseArgs([]string{"rest1"}) - - assertError(t, err, ErrRequired, "the required argument `Rest (at least 2 arguments, but got only 1)` was not provided") -} - -func TestPositionalRequiredRest2Pass(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Positional struct { - Rest []string `required:"2"` - } `positional-args:"yes"` - }{} - - p := NewParser(&opts, None) - _, err := p.ParseArgs([]string{"rest1", "rest2", "rest3"}) - - if err != nil { - t.Fatalf("Unexpected error: %v", err) - return - } - - if len(opts.Positional.Rest) != 3 { - t.Fatalf("Expected 3 positional rest argument") - } - - assertString(t, opts.Positional.Rest[0], "rest1") - assertString(t, opts.Positional.Rest[1], "rest2") - assertString(t, opts.Positional.Rest[2], "rest3") -} - -func TestPositionalRequiredRestRangeFail(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Positional struct { - Rest []string `required:"1-2"` - } `positional-args:"yes"` - }{} - - p := NewParser(&opts, None) - _, err := p.ParseArgs([]string{"rest1", "rest2", "rest3"}) - - assertError(t, err, ErrRequired, "the required argument `Rest (at most 2 arguments, but got 3)` was not provided") -} - -func TestPositionalRequiredRestRangeEmptyFail(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Positional struct { - Rest []string `required:"0-0"` - } `positional-args:"yes"` - }{} - - p := NewParser(&opts, None) - _, err := p.ParseArgs([]string{"some", "thing"}) - - assertError(t, err, ErrRequired, "the required argument `Rest (zero arguments)` was not provided") -} diff --git a/vendor/github.com/jessevdk/go-flags/assert_test.go b/vendor/github.com/jessevdk/go-flags/assert_test.go deleted file mode 100644 index 8e06636b..00000000 --- a/vendor/github.com/jessevdk/go-flags/assert_test.go +++ /dev/null @@ -1,177 +0,0 @@ -package flags - -import ( - "fmt" - "io" - "io/ioutil" - "os" - "os/exec" - "path" - "runtime" - "testing" -) - -func assertCallerInfo() (string, int) { - ptr := make([]uintptr, 15) - n := runtime.Callers(1, ptr) - - if n == 0 { - return "", 0 - } - - mef := runtime.FuncForPC(ptr[0]) - mefile, meline := mef.FileLine(ptr[0]) - - for i := 2; i < n; i++ { - f := runtime.FuncForPC(ptr[i]) - file, line := f.FileLine(ptr[i]) - - if file != mefile { - return file, line - } - } - - return mefile, meline -} - -func assertErrorf(t *testing.T, format string, args ...interface{}) { - msg := fmt.Sprintf(format, args...) - - file, line := assertCallerInfo() - - t.Errorf("%s:%d: %s", path.Base(file), line, msg) -} - -func assertFatalf(t *testing.T, format string, args ...interface{}) { - msg := fmt.Sprintf(format, args...) - - file, line := assertCallerInfo() - - t.Fatalf("%s:%d: %s", path.Base(file), line, msg) -} - -func assertString(t *testing.T, a string, b string) { - if a != b { - assertErrorf(t, "Expected %#v, but got %#v", b, a) - } -} - -func assertStringArray(t *testing.T, a []string, b []string) { - if len(a) != len(b) { - assertErrorf(t, "Expected %#v, but got %#v", b, a) - return - } - - for i, v := range a { - if b[i] != v { - assertErrorf(t, "Expected %#v, but got %#v", b, a) - return - } - } -} - -func assertBoolArray(t *testing.T, a []bool, b []bool) { - if len(a) != len(b) { - assertErrorf(t, "Expected %#v, but got %#v", b, a) - return - } - - for i, v := range a { - if b[i] != v { - assertErrorf(t, "Expected %#v, but got %#v", b, a) - return - } - } -} - -func assertParserSuccess(t *testing.T, data interface{}, args ...string) (*Parser, []string) { - parser := NewParser(data, Default&^PrintErrors) - ret, err := parser.ParseArgs(args) - - if err != nil { - t.Fatalf("Unexpected parse error: %s", err) - return nil, nil - } - - return parser, ret -} - -func assertParseSuccess(t *testing.T, data interface{}, args ...string) []string { - _, ret := assertParserSuccess(t, data, args...) - return ret -} - -func assertError(t *testing.T, err error, typ ErrorType, msg string) { - if err == nil { - assertFatalf(t, "Expected error: %s", msg) - return - } - - if e, ok := err.(*Error); !ok { - assertFatalf(t, "Expected Error type, but got %#v", err) - } else { - if e.Type != typ { - assertErrorf(t, "Expected error type {%s}, but got {%s}", typ, e.Type) - } - - if e.Message != msg { - assertErrorf(t, "Expected error message %#v, but got %#v", msg, e.Message) - } - } -} - -func assertParseFail(t *testing.T, typ ErrorType, msg string, data interface{}, args ...string) []string { - parser := NewParser(data, Default&^PrintErrors) - ret, err := parser.ParseArgs(args) - - assertError(t, err, typ, msg) - return ret -} - -func diff(a, b string) (string, error) { - atmp, err := ioutil.TempFile("", "help-diff") - - if err != nil { - return "", err - } - - btmp, err := ioutil.TempFile("", "help-diff") - - if err != nil { - return "", err - } - - if _, err := io.WriteString(atmp, a); err != nil { - return "", err - } - - if _, err := io.WriteString(btmp, b); err != nil { - return "", err - } - - ret, err := exec.Command("diff", "-u", "-d", "--label", "got", atmp.Name(), "--label", "expected", btmp.Name()).Output() - - os.Remove(atmp.Name()) - os.Remove(btmp.Name()) - - if err.Error() == "exit status 1" { - return string(ret), nil - } - - return string(ret), err -} - -func assertDiff(t *testing.T, actual, expected, msg string) { - if actual == expected { - return - } - - ret, err := diff(actual, expected) - - if err != nil { - assertErrorf(t, "Unexpected diff error: %s", err) - assertErrorf(t, "Unexpected %s, expected:\n\n%s\n\nbut got\n\n%s", msg, expected, actual) - } else { - assertErrorf(t, "Unexpected %s:\n\n%s", msg, ret) - } -} diff --git a/vendor/github.com/jessevdk/go-flags/check_crosscompile.sh b/vendor/github.com/jessevdk/go-flags/check_crosscompile.sh deleted file mode 100755 index c494f611..00000000 --- a/vendor/github.com/jessevdk/go-flags/check_crosscompile.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -set -e - -echo '# linux arm7' -GOARM=7 GOARCH=arm GOOS=linux go build -echo '# linux arm5' -GOARM=5 GOARCH=arm GOOS=linux go build -echo '# windows 386' -GOARCH=386 GOOS=windows go build -echo '# windows amd64' -GOARCH=amd64 GOOS=windows go build -echo '# darwin' -GOARCH=amd64 GOOS=darwin go build -echo '# freebsd' -GOARCH=amd64 GOOS=freebsd go build diff --git a/vendor/github.com/jessevdk/go-flags/command_test.go b/vendor/github.com/jessevdk/go-flags/command_test.go deleted file mode 100644 index dc04b66c..00000000 --- a/vendor/github.com/jessevdk/go-flags/command_test.go +++ /dev/null @@ -1,582 +0,0 @@ -package flags - -import ( - "fmt" - "testing" -) - -func TestCommandInline(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Command struct { - G bool `short:"g"` - } `command:"cmd"` - }{} - - p, ret := assertParserSuccess(t, &opts, "-v", "cmd", "-g") - - assertStringArray(t, ret, []string{}) - - if p.Active == nil { - t.Errorf("Expected active command") - } - - if !opts.Value { - t.Errorf("Expected Value to be true") - } - - if !opts.Command.G { - t.Errorf("Expected Command.G to be true") - } - - if p.Command.Find("cmd") != p.Active { - t.Errorf("Expected to find command `cmd' to be active") - } -} - -func TestCommandInlineMulti(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - C1 struct { - } `command:"c1"` - - C2 struct { - G bool `short:"g"` - } `command:"c2"` - }{} - - p, ret := assertParserSuccess(t, &opts, "-v", "c2", "-g") - - assertStringArray(t, ret, []string{}) - - if p.Active == nil { - t.Errorf("Expected active command") - } - - if !opts.Value { - t.Errorf("Expected Value to be true") - } - - if !opts.C2.G { - t.Errorf("Expected C2.G to be true") - } - - if p.Command.Find("c1") == nil { - t.Errorf("Expected to find command `c1'") - } - - if c2 := p.Command.Find("c2"); c2 == nil { - t.Errorf("Expected to find command `c2'") - } else if c2 != p.Active { - t.Errorf("Expected to find command `c2' to be active") - } -} - -func TestCommandFlagOrder1(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Command struct { - G bool `short:"g"` - } `command:"cmd"` - }{} - - assertParseFail(t, ErrUnknownFlag, "unknown flag `g'", &opts, "-v", "-g", "cmd") -} - -func TestCommandFlagOrder2(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Command struct { - G bool `short:"g"` - } `command:"cmd"` - }{} - - assertParseSuccess(t, &opts, "cmd", "-v", "-g") - - if !opts.Value { - t.Errorf("Expected Value to be true") - } - - if !opts.Command.G { - t.Errorf("Expected Command.G to be true") - } -} - -func TestCommandFlagOrderSub(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Command struct { - G bool `short:"g"` - - SubCommand struct { - B bool `short:"b"` - } `command:"sub"` - } `command:"cmd"` - }{} - - assertParseSuccess(t, &opts, "cmd", "sub", "-v", "-g", "-b") - - if !opts.Value { - t.Errorf("Expected Value to be true") - } - - if !opts.Command.G { - t.Errorf("Expected Command.G to be true") - } - - if !opts.Command.SubCommand.B { - t.Errorf("Expected Command.SubCommand.B to be true") - } -} - -func TestCommandFlagOverride1(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Command struct { - Value bool `short:"v"` - } `command:"cmd"` - }{} - - assertParseSuccess(t, &opts, "-v", "cmd") - - if !opts.Value { - t.Errorf("Expected Value to be true") - } - - if opts.Command.Value { - t.Errorf("Expected Command.Value to be false") - } -} - -func TestCommandFlagOverride2(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Command struct { - Value bool `short:"v"` - } `command:"cmd"` - }{} - - assertParseSuccess(t, &opts, "cmd", "-v") - - if opts.Value { - t.Errorf("Expected Value to be false") - } - - if !opts.Command.Value { - t.Errorf("Expected Command.Value to be true") - } -} - -func TestCommandFlagOverrideSub(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Command struct { - Value bool `short:"v"` - - SubCommand struct { - Value bool `short:"v"` - } `command:"sub"` - } `command:"cmd"` - }{} - - assertParseSuccess(t, &opts, "cmd", "sub", "-v") - - if opts.Value { - t.Errorf("Expected Value to be false") - } - - if opts.Command.Value { - t.Errorf("Expected Command.Value to be false") - } - - if !opts.Command.SubCommand.Value { - t.Errorf("Expected Command.Value to be true") - } -} - -func TestCommandFlagOverrideSub2(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Command struct { - Value bool `short:"v"` - - SubCommand struct { - G bool `short:"g"` - } `command:"sub"` - } `command:"cmd"` - }{} - - assertParseSuccess(t, &opts, "cmd", "sub", "-v") - - if opts.Value { - t.Errorf("Expected Value to be false") - } - - if !opts.Command.Value { - t.Errorf("Expected Command.Value to be true") - } -} - -func TestCommandEstimate(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Cmd1 struct { - } `command:"remove"` - - Cmd2 struct { - } `command:"add"` - }{} - - p := NewParser(&opts, None) - _, err := p.ParseArgs([]string{}) - - assertError(t, err, ErrCommandRequired, "Please specify one command of: add or remove") -} - -func TestCommandEstimate2(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Cmd1 struct { - } `command:"remove"` - - Cmd2 struct { - } `command:"add"` - }{} - - p := NewParser(&opts, None) - _, err := p.ParseArgs([]string{"rmive"}) - - assertError(t, err, ErrUnknownCommand, "Unknown command `rmive', did you mean `remove'?") -} - -type testCommand struct { - G bool `short:"g"` - Executed bool - EArgs []string -} - -func (c *testCommand) Execute(args []string) error { - c.Executed = true - c.EArgs = args - - return nil -} - -func TestCommandExecute(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Command testCommand `command:"cmd"` - }{} - - assertParseSuccess(t, &opts, "-v", "cmd", "-g", "a", "b") - - if !opts.Value { - t.Errorf("Expected Value to be true") - } - - if !opts.Command.Executed { - t.Errorf("Did not execute command") - } - - if !opts.Command.G { - t.Errorf("Expected Command.C to be true") - } - - assertStringArray(t, opts.Command.EArgs, []string{"a", "b"}) -} - -func TestCommandClosest(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Cmd1 struct { - } `command:"remove"` - - Cmd2 struct { - } `command:"add"` - }{} - - args := assertParseFail(t, ErrUnknownCommand, "Unknown command `addd', did you mean `add'?", &opts, "-v", "addd") - - assertStringArray(t, args, []string{"addd"}) -} - -func TestCommandAdd(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - }{} - - var cmd = struct { - G bool `short:"g"` - }{} - - p := NewParser(&opts, Default) - c, err := p.AddCommand("cmd", "", "", &cmd) - - if err != nil { - t.Fatalf("Unexpected error: %v", err) - return - } - - ret, err := p.ParseArgs([]string{"-v", "cmd", "-g", "rest"}) - - if err != nil { - t.Fatalf("Unexpected error: %v", err) - return - } - - assertStringArray(t, ret, []string{"rest"}) - - if !opts.Value { - t.Errorf("Expected Value to be true") - } - - if !cmd.G { - t.Errorf("Expected Command.G to be true") - } - - if p.Command.Find("cmd") != c { - t.Errorf("Expected to find command `cmd'") - } - - if p.Commands()[0] != c { - t.Errorf("Expected command %#v, but got %#v", c, p.Commands()[0]) - } - - if c.Options()[0].ShortName != 'g' { - t.Errorf("Expected short name `g' but got %v", c.Options()[0].ShortName) - } -} - -func TestCommandNestedInline(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Command struct { - G bool `short:"g"` - - Nested struct { - N string `long:"n"` - } `command:"nested"` - } `command:"cmd"` - }{} - - p, ret := assertParserSuccess(t, &opts, "-v", "cmd", "-g", "nested", "--n", "n", "rest") - - assertStringArray(t, ret, []string{"rest"}) - - if !opts.Value { - t.Errorf("Expected Value to be true") - } - - if !opts.Command.G { - t.Errorf("Expected Command.G to be true") - } - - assertString(t, opts.Command.Nested.N, "n") - - if c := p.Command.Find("cmd"); c == nil { - t.Errorf("Expected to find command `cmd'") - } else { - if c != p.Active { - t.Errorf("Expected `cmd' to be the active parser command") - } - - if nested := c.Find("nested"); nested == nil { - t.Errorf("Expected to find command `nested'") - } else if nested != c.Active { - t.Errorf("Expected to find command `nested' to be the active `cmd' command") - } - } -} - -func TestRequiredOnCommand(t *testing.T) { - var opts = struct { - Value bool `short:"v" required:"true"` - - Command struct { - G bool `short:"g"` - } `command:"cmd"` - }{} - - assertParseFail(t, ErrRequired, fmt.Sprintf("the required flag `%cv' was not specified", defaultShortOptDelimiter), &opts, "cmd") -} - -func TestRequiredAllOnCommand(t *testing.T) { - var opts = struct { - Value bool `short:"v" required:"true"` - Missing bool `long:"missing" required:"true"` - - Command struct { - G bool `short:"g"` - } `command:"cmd"` - }{} - - assertParseFail(t, ErrRequired, fmt.Sprintf("the required flags `%smissing' and `%cv' were not specified", defaultLongOptDelimiter, defaultShortOptDelimiter), &opts, "cmd") -} - -func TestDefaultOnCommand(t *testing.T) { - var opts = struct { - Command struct { - G string `short:"g" default:"value"` - } `command:"cmd"` - }{} - - assertParseSuccess(t, &opts, "cmd") - - if opts.Command.G != "value" { - t.Errorf("Expected G to be \"value\"") - } -} - -func TestAfterNonCommand(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Cmd1 struct { - } `command:"remove"` - - Cmd2 struct { - } `command:"add"` - }{} - - assertParseFail(t, ErrUnknownCommand, "Unknown command `nocmd'. Please specify one command of: add or remove", &opts, "nocmd", "remove") -} - -func TestSubcommandsOptional(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Cmd1 struct { - } `command:"remove"` - - Cmd2 struct { - } `command:"add"` - }{} - - p := NewParser(&opts, None) - p.SubcommandsOptional = true - - _, err := p.ParseArgs([]string{"-v"}) - - if err != nil { - t.Fatalf("Unexpected error: %v", err) - return - } - - if !opts.Value { - t.Errorf("Expected Value to be true") - } -} - -func TestSubcommandsOptionalAfterNonCommand(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Cmd1 struct { - } `command:"remove"` - - Cmd2 struct { - } `command:"add"` - }{} - - p := NewParser(&opts, None) - p.SubcommandsOptional = true - - retargs, err := p.ParseArgs([]string{"nocmd", "remove"}) - - if err != nil { - t.Fatalf("Unexpected error: %v", err) - return - } - - assertStringArray(t, retargs, []string{"nocmd", "remove"}) -} - -func TestCommandAlias(t *testing.T) { - var opts = struct { - Command struct { - G string `short:"g" default:"value"` - } `command:"cmd" alias:"cm"` - }{} - - assertParseSuccess(t, &opts, "cm") - - if opts.Command.G != "value" { - t.Errorf("Expected G to be \"value\"") - } -} - -func TestSubCommandFindOptionByLongFlag(t *testing.T) { - var opts struct { - Testing bool `long:"testing" description:"Testing"` - } - - var cmd struct { - Other bool `long:"other" description:"Other"` - } - - p := NewParser(&opts, Default) - c, _ := p.AddCommand("command", "Short", "Long", &cmd) - - opt := c.FindOptionByLongName("other") - - if opt == nil { - t.Errorf("Expected option, but found none") - } - - assertString(t, opt.LongName, "other") - - opt = c.FindOptionByLongName("testing") - - if opt == nil { - t.Errorf("Expected option, but found none") - } - - assertString(t, opt.LongName, "testing") -} - -func TestSubCommandFindOptionByShortFlag(t *testing.T) { - var opts struct { - Testing bool `short:"t" description:"Testing"` - } - - var cmd struct { - Other bool `short:"o" description:"Other"` - } - - p := NewParser(&opts, Default) - c, _ := p.AddCommand("command", "Short", "Long", &cmd) - - opt := c.FindOptionByShortName('o') - - if opt == nil { - t.Errorf("Expected option, but found none") - } - - if opt.ShortName != 'o' { - t.Errorf("Expected 'o', but got %v", opt.ShortName) - } - - opt = c.FindOptionByShortName('t') - - if opt == nil { - t.Errorf("Expected option, but found none") - } - - if opt.ShortName != 't' { - t.Errorf("Expected 'o', but got %v", opt.ShortName) - } -} diff --git a/vendor/github.com/jessevdk/go-flags/completion_test.go b/vendor/github.com/jessevdk/go-flags/completion_test.go deleted file mode 100644 index 26f70e42..00000000 --- a/vendor/github.com/jessevdk/go-flags/completion_test.go +++ /dev/null @@ -1,315 +0,0 @@ -package flags - -import ( - "bytes" - "io" - "os" - "path" - "path/filepath" - "reflect" - "runtime" - "strings" - "testing" -) - -type TestComplete struct { -} - -func (t *TestComplete) Complete(match string) []Completion { - options := []string{ - "hello world", - "hello universe", - "hello multiverse", - } - - ret := make([]Completion, 0, len(options)) - - for _, o := range options { - if strings.HasPrefix(o, match) { - ret = append(ret, Completion{ - Item: o, - }) - } - } - - return ret -} - -var completionTestOptions struct { - Verbose bool `short:"v" long:"verbose" description:"Verbose messages"` - Debug bool `short:"d" long:"debug" description:"Enable debug"` - Info bool `short:"i" description:"Display info"` - Version bool `long:"version" description:"Show version"` - Required bool `long:"required" required:"true" description:"This is required"` - Hidden bool `long:"hidden" hidden:"true" description:"This is hidden"` - - AddCommand struct { - Positional struct { - Filename Filename - } `positional-args:"yes"` - } `command:"add" description:"add an item"` - - AddMultiCommand struct { - Positional struct { - Filename []Filename - } `positional-args:"yes"` - Extra []Filename `short:"f"` - } `command:"add-multi" description:"add multiple items"` - - AddMultiCommandFlag struct { - Files []Filename `short:"f"` - } `command:"add-multi-flag" description:"add multiple items via flags"` - - RemoveCommand struct { - Other bool `short:"o"` - File Filename `short:"f" long:"filename"` - } `command:"rm" description:"remove an item"` - - RenameCommand struct { - Completed TestComplete `short:"c" long:"completed"` - } `command:"rename" description:"rename an item"` -} - -type completionTest struct { - Args []string - Completed []string - ShowDescriptions bool -} - -var completionTests []completionTest - -func init() { - _, sourcefile, _, _ := runtime.Caller(0) - completionTestSourcedir := filepath.Join(filepath.SplitList(path.Dir(sourcefile))...) - - completionTestFilename := []string{filepath.Join(completionTestSourcedir, "completion.go"), filepath.Join(completionTestSourcedir, "completion_test.go")} - - completionTests = []completionTest{ - { - // Short names - []string{"-"}, - []string{"--debug", "--required", "--verbose", "--version", "-i"}, - false, - }, - - { - // Short names full - []string{"-i"}, - []string{"-i"}, - false, - }, - - { - // Short names concatenated - []string{"-dv"}, - []string{"-dv"}, - false, - }, - - { - // Long names - []string{"--"}, - []string{"--debug", "--required", "--verbose", "--version"}, - false, - }, - - { - // Long names with descriptions - []string{"--"}, - []string{ - "--debug # Enable debug", - "--required # This is required", - "--verbose # Verbose messages", - "--version # Show version", - }, - true, - }, - - { - // Long names partial - []string{"--ver"}, - []string{"--verbose", "--version"}, - false, - }, - - { - // Commands - []string{""}, - []string{"add", "add-multi", "add-multi-flag", "rename", "rm"}, - false, - }, - - { - // Commands with descriptions - []string{""}, - []string{ - "add # add an item", - "add-multi # add multiple items", - "add-multi-flag # add multiple items via flags", - "rename # rename an item", - "rm # remove an item", - }, - true, - }, - - { - // Commands partial - []string{"r"}, - []string{"rename", "rm"}, - false, - }, - - { - // Positional filename - []string{"add", filepath.Join(completionTestSourcedir, "completion")}, - completionTestFilename, - false, - }, - - { - // Multiple positional filename (1 arg) - []string{"add-multi", filepath.Join(completionTestSourcedir, "completion")}, - completionTestFilename, - false, - }, - { - // Multiple positional filename (2 args) - []string{"add-multi", filepath.Join(completionTestSourcedir, "completion.go"), filepath.Join(completionTestSourcedir, "completion")}, - completionTestFilename, - false, - }, - { - // Multiple positional filename (3 args) - []string{"add-multi", filepath.Join(completionTestSourcedir, "completion.go"), filepath.Join(completionTestSourcedir, "completion.go"), filepath.Join(completionTestSourcedir, "completion")}, - completionTestFilename, - false, - }, - - { - // Flag filename - []string{"rm", "-f", path.Join(completionTestSourcedir, "completion")}, - completionTestFilename, - false, - }, - - { - // Flag short concat last filename - []string{"rm", "-of", path.Join(completionTestSourcedir, "completion")}, - completionTestFilename, - false, - }, - - { - // Flag concat filename - []string{"rm", "-f" + path.Join(completionTestSourcedir, "completion")}, - []string{"-f" + completionTestFilename[0], "-f" + completionTestFilename[1]}, - false, - }, - - { - // Flag equal concat filename - []string{"rm", "-f=" + path.Join(completionTestSourcedir, "completion")}, - []string{"-f=" + completionTestFilename[0], "-f=" + completionTestFilename[1]}, - false, - }, - - { - // Flag concat long filename - []string{"rm", "--filename=" + path.Join(completionTestSourcedir, "completion")}, - []string{"--filename=" + completionTestFilename[0], "--filename=" + completionTestFilename[1]}, - false, - }, - - { - // Flag long filename - []string{"rm", "--filename", path.Join(completionTestSourcedir, "completion")}, - completionTestFilename, - false, - }, - - { - // Custom completed - []string{"rename", "-c", "hello un"}, - []string{"hello universe"}, - false, - }, - { - // Multiple flag filename - []string{"add-multi-flag", "-f", filepath.Join(completionTestSourcedir, "completion")}, - completionTestFilename, - false, - }, - } -} - -func TestCompletion(t *testing.T) { - p := NewParser(&completionTestOptions, Default) - c := &completion{parser: p} - - for _, test := range completionTests { - if test.ShowDescriptions { - continue - } - - ret := c.complete(test.Args) - items := make([]string, len(ret)) - - for i, v := range ret { - items[i] = v.Item - } - - if !reflect.DeepEqual(items, test.Completed) { - t.Errorf("Args: %#v, %#v\n Expected: %#v\n Got: %#v", test.Args, test.ShowDescriptions, test.Completed, items) - } - } -} - -func TestParserCompletion(t *testing.T) { - for _, test := range completionTests { - if test.ShowDescriptions { - os.Setenv("GO_FLAGS_COMPLETION", "verbose") - } else { - os.Setenv("GO_FLAGS_COMPLETION", "1") - } - - tmp := os.Stdout - - r, w, _ := os.Pipe() - os.Stdout = w - - out := make(chan string) - - go func() { - var buf bytes.Buffer - - io.Copy(&buf, r) - - out <- buf.String() - }() - - p := NewParser(&completionTestOptions, None) - - p.CompletionHandler = func(items []Completion) { - comp := &completion{parser: p} - comp.print(items, test.ShowDescriptions) - } - - _, err := p.ParseArgs(test.Args) - - w.Close() - - os.Stdout = tmp - - if err != nil { - t.Fatalf("Unexpected error: %s", err) - } - - got := strings.Split(strings.Trim(<-out, "\n"), "\n") - - if !reflect.DeepEqual(got, test.Completed) { - t.Errorf("Expected: %#v\nGot: %#v", test.Completed, got) - } - } - - os.Setenv("GO_FLAGS_COMPLETION", "") -} diff --git a/vendor/github.com/jessevdk/go-flags/convert_test.go b/vendor/github.com/jessevdk/go-flags/convert_test.go deleted file mode 100644 index ef131dc8..00000000 --- a/vendor/github.com/jessevdk/go-flags/convert_test.go +++ /dev/null @@ -1,159 +0,0 @@ -package flags - -import ( - "testing" - "time" -) - -func expectConvert(t *testing.T, o *Option, expected string) { - s, err := convertToString(o.value, o.tag) - - if err != nil { - t.Errorf("Unexpected error: %v", err) - return - } - - assertString(t, s, expected) -} - -func TestConvertToString(t *testing.T) { - d, _ := time.ParseDuration("1h2m4s") - - var opts = struct { - String string `long:"string"` - - Int int `long:"int"` - Int8 int8 `long:"int8"` - Int16 int16 `long:"int16"` - Int32 int32 `long:"int32"` - Int64 int64 `long:"int64"` - - Uint uint `long:"uint"` - Uint8 uint8 `long:"uint8"` - Uint16 uint16 `long:"uint16"` - Uint32 uint32 `long:"uint32"` - Uint64 uint64 `long:"uint64"` - - Float32 float32 `long:"float32"` - Float64 float64 `long:"float64"` - - Duration time.Duration `long:"duration"` - - Bool bool `long:"bool"` - - IntSlice []int `long:"int-slice"` - IntFloatMap map[int]float64 `long:"int-float-map"` - - PtrBool *bool `long:"ptr-bool"` - Interface interface{} `long:"interface"` - - Int32Base int32 `long:"int32-base" base:"16"` - Uint32Base uint32 `long:"uint32-base" base:"16"` - }{ - "string", - - -2, - -1, - 0, - 1, - 2, - - 1, - 2, - 3, - 4, - 5, - - 1.2, - -3.4, - - d, - true, - - []int{-3, 4, -2}, - map[int]float64{-2: 4.5}, - - new(bool), - float32(5.2), - - -5823, - 4232, - } - - p := NewNamedParser("test", Default) - grp, _ := p.AddGroup("test group", "", &opts) - - expects := []string{ - "string", - "-2", - "-1", - "0", - "1", - "2", - - "1", - "2", - "3", - "4", - "5", - - "1.2", - "-3.4", - - "1h2m4s", - "true", - - "[-3, 4, -2]", - "{-2:4.5}", - - "false", - "5.2", - - "-16bf", - "1088", - } - - for i, v := range grp.Options() { - expectConvert(t, v, expects[i]) - } -} - -func TestConvertToStringInvalidIntBase(t *testing.T) { - var opts = struct { - Int int `long:"int" base:"no"` - }{ - 2, - } - - p := NewNamedParser("test", Default) - grp, _ := p.AddGroup("test group", "", &opts) - o := grp.Options()[0] - - _, err := convertToString(o.value, o.tag) - - if err != nil { - err = newErrorf(ErrMarshal, "%v", err) - } - - assertError(t, err, ErrMarshal, "strconv.ParseInt: parsing \"no\": invalid syntax") -} - -func TestConvertToStringInvalidUintBase(t *testing.T) { - var opts = struct { - Uint uint `long:"uint" base:"no"` - }{ - 2, - } - - p := NewNamedParser("test", Default) - grp, _ := p.AddGroup("test group", "", &opts) - o := grp.Options()[0] - - _, err := convertToString(o.value, o.tag) - - if err != nil { - err = newErrorf(ErrMarshal, "%v", err) - } - - assertError(t, err, ErrMarshal, "strconv.ParseInt: parsing \"no\": invalid syntax") -} diff --git a/vendor/github.com/jessevdk/go-flags/example_test.go b/vendor/github.com/jessevdk/go-flags/example_test.go deleted file mode 100644 index 4321ed8e..00000000 --- a/vendor/github.com/jessevdk/go-flags/example_test.go +++ /dev/null @@ -1,110 +0,0 @@ -// Example of use of the flags package. -package flags - -import ( - "fmt" - "os/exec" -) - -func Example() { - var opts struct { - // Slice of bool will append 'true' each time the option - // is encountered (can be set multiple times, like -vvv) - Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"` - - // Example of automatic marshalling to desired type (uint) - Offset uint `long:"offset" description:"Offset"` - - // Example of a callback, called each time the option is found. - Call func(string) `short:"c" description:"Call phone number"` - - // Example of a required flag - Name string `short:"n" long:"name" description:"A name" required:"true"` - - // Example of a value name - File string `short:"f" long:"file" description:"A file" value-name:"FILE"` - - // Example of a pointer - Ptr *int `short:"p" description:"A pointer to an integer"` - - // Example of a slice of strings - StringSlice []string `short:"s" description:"A slice of strings"` - - // Example of a slice of pointers - PtrSlice []*string `long:"ptrslice" description:"A slice of pointers to string"` - - // Example of a map - IntMap map[string]int `long:"intmap" description:"A map from string to int"` - - // Example of a filename (useful for completion) - Filename Filename `long:"filename" description:"A filename"` - - // Example of positional arguments - Args struct { - ID string - Num int - Rest []string - } `positional-args:"yes" required:"yes"` - } - - // Callback which will invoke callto: to call a number. - // Note that this works just on OS X (and probably only with - // Skype) but it shows the idea. - opts.Call = func(num string) { - cmd := exec.Command("open", "callto:"+num) - cmd.Start() - cmd.Process.Release() - } - - // Make some fake arguments to parse. - args := []string{ - "-vv", - "--offset=5", - "-n", "Me", - "-p", "3", - "-s", "hello", - "-s", "world", - "--ptrslice", "hello", - "--ptrslice", "world", - "--intmap", "a:1", - "--intmap", "b:5", - "--filename", "hello.go", - "id", - "10", - "remaining1", - "remaining2", - } - - // Parse flags from `args'. Note that here we use flags.ParseArgs for - // the sake of making a working example. Normally, you would simply use - // flags.Parse(&opts) which uses os.Args - _, err := ParseArgs(&opts, args) - - if err != nil { - panic(err) - } - - fmt.Printf("Verbosity: %v\n", opts.Verbose) - fmt.Printf("Offset: %d\n", opts.Offset) - fmt.Printf("Name: %s\n", opts.Name) - fmt.Printf("Ptr: %d\n", *opts.Ptr) - fmt.Printf("StringSlice: %v\n", opts.StringSlice) - fmt.Printf("PtrSlice: [%v %v]\n", *opts.PtrSlice[0], *opts.PtrSlice[1]) - fmt.Printf("IntMap: [a:%v b:%v]\n", opts.IntMap["a"], opts.IntMap["b"]) - fmt.Printf("Filename: %v\n", opts.Filename) - fmt.Printf("Args.ID: %s\n", opts.Args.ID) - fmt.Printf("Args.Num: %d\n", opts.Args.Num) - fmt.Printf("Args.Rest: %v\n", opts.Args.Rest) - - // Output: Verbosity: [true true] - // Offset: 5 - // Name: Me - // Ptr: 3 - // StringSlice: [hello world] - // PtrSlice: [hello world] - // IntMap: [a:1 b:5] - // Filename: hello.go - // Args.ID: id - // Args.Num: 10 - // Args.Rest: [remaining1 remaining2] -} diff --git a/vendor/github.com/jessevdk/go-flags/group_test.go b/vendor/github.com/jessevdk/go-flags/group_test.go deleted file mode 100644 index 18cd6c17..00000000 --- a/vendor/github.com/jessevdk/go-flags/group_test.go +++ /dev/null @@ -1,255 +0,0 @@ -package flags - -import ( - "testing" -) - -func TestGroupInline(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Group struct { - G bool `short:"g"` - } `group:"Grouped Options"` - }{} - - p, ret := assertParserSuccess(t, &opts, "-v", "-g") - - assertStringArray(t, ret, []string{}) - - if !opts.Value { - t.Errorf("Expected Value to be true") - } - - if !opts.Group.G { - t.Errorf("Expected Group.G to be true") - } - - if p.Command.Group.Find("Grouped Options") == nil { - t.Errorf("Expected to find group `Grouped Options'") - } -} - -func TestGroupAdd(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - }{} - - var grp = struct { - G bool `short:"g"` - }{} - - p := NewParser(&opts, Default) - g, err := p.AddGroup("Grouped Options", "", &grp) - - if err != nil { - t.Fatalf("Unexpected error: %v", err) - return - } - - ret, err := p.ParseArgs([]string{"-v", "-g", "rest"}) - - if err != nil { - t.Fatalf("Unexpected error: %v", err) - return - } - - assertStringArray(t, ret, []string{"rest"}) - - if !opts.Value { - t.Errorf("Expected Value to be true") - } - - if !grp.G { - t.Errorf("Expected Group.G to be true") - } - - if p.Command.Group.Find("Grouped Options") != g { - t.Errorf("Expected to find group `Grouped Options'") - } - - if p.Groups()[1] != g { - t.Errorf("Expected group %#v, but got %#v", g, p.Groups()[0]) - } - - if g.Options()[0].ShortName != 'g' { - t.Errorf("Expected short name `g' but got %v", g.Options()[0].ShortName) - } -} - -func TestGroupNestedInline(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Group struct { - G bool `short:"g"` - - Nested struct { - N string `long:"n"` - } `group:"Nested Options"` - } `group:"Grouped Options"` - }{} - - p, ret := assertParserSuccess(t, &opts, "-v", "-g", "--n", "n", "rest") - - assertStringArray(t, ret, []string{"rest"}) - - if !opts.Value { - t.Errorf("Expected Value to be true") - } - - if !opts.Group.G { - t.Errorf("Expected Group.G to be true") - } - - assertString(t, opts.Group.Nested.N, "n") - - if p.Command.Group.Find("Grouped Options") == nil { - t.Errorf("Expected to find group `Grouped Options'") - } - - if p.Command.Group.Find("Nested Options") == nil { - t.Errorf("Expected to find group `Nested Options'") - } -} - -func TestGroupNestedInlineNamespace(t *testing.T) { - var opts = struct { - Opt string `long:"opt"` - - Group struct { - Opt string `long:"opt"` - Group struct { - Opt string `long:"opt"` - } `group:"Subsubgroup" namespace:"sap"` - } `group:"Subgroup" namespace:"sip"` - }{} - - p, ret := assertParserSuccess(t, &opts, "--opt", "a", "--sip.opt", "b", "--sip.sap.opt", "c", "rest") - - assertStringArray(t, ret, []string{"rest"}) - - assertString(t, opts.Opt, "a") - assertString(t, opts.Group.Opt, "b") - assertString(t, opts.Group.Group.Opt, "c") - - for _, name := range []string{"Subgroup", "Subsubgroup"} { - if p.Command.Group.Find(name) == nil { - t.Errorf("Expected to find group '%s'", name) - } - } -} - -func TestDuplicateShortFlags(t *testing.T) { - var opts struct { - Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"` - Variables []string `short:"v" long:"variable" description:"Set a variable value."` - } - - args := []string{ - "--verbose", - "-v", "123", - "-v", "456", - } - - _, err := ParseArgs(&opts, args) - - if err == nil { - t.Errorf("Expected an error with type ErrDuplicatedFlag") - } else { - err2 := err.(*Error) - if err2.Type != ErrDuplicatedFlag { - t.Errorf("Expected an error with type ErrDuplicatedFlag") - } - } -} - -func TestDuplicateLongFlags(t *testing.T) { - var opts struct { - Test1 []bool `short:"a" long:"testing" description:"Test 1"` - Test2 []string `short:"b" long:"testing" description:"Test 2."` - } - - args := []string{ - "--testing", - } - - _, err := ParseArgs(&opts, args) - - if err == nil { - t.Errorf("Expected an error with type ErrDuplicatedFlag") - } else { - err2 := err.(*Error) - if err2.Type != ErrDuplicatedFlag { - t.Errorf("Expected an error with type ErrDuplicatedFlag") - } - } -} - -func TestFindOptionByLongFlag(t *testing.T) { - var opts struct { - Testing bool `long:"testing" description:"Testing"` - } - - p := NewParser(&opts, Default) - opt := p.FindOptionByLongName("testing") - - if opt == nil { - t.Errorf("Expected option, but found none") - } - - assertString(t, opt.LongName, "testing") -} - -func TestFindOptionByShortFlag(t *testing.T) { - var opts struct { - Testing bool `short:"t" description:"Testing"` - } - - p := NewParser(&opts, Default) - opt := p.FindOptionByShortName('t') - - if opt == nil { - t.Errorf("Expected option, but found none") - } - - if opt.ShortName != 't' { - t.Errorf("Expected 't', but got %v", opt.ShortName) - } -} - -func TestFindOptionByLongFlagInSubGroup(t *testing.T) { - var opts struct { - Group struct { - Testing bool `long:"testing" description:"Testing"` - } `group:"sub-group"` - } - - p := NewParser(&opts, Default) - opt := p.FindOptionByLongName("testing") - - if opt == nil { - t.Errorf("Expected option, but found none") - } - - assertString(t, opt.LongName, "testing") -} - -func TestFindOptionByShortFlagInSubGroup(t *testing.T) { - var opts struct { - Group struct { - Testing bool `short:"t" description:"Testing"` - } `group:"sub-group"` - } - - p := NewParser(&opts, Default) - opt := p.FindOptionByShortName('t') - - if opt == nil { - t.Errorf("Expected option, but found none") - } - - if opt.ShortName != 't' { - t.Errorf("Expected 't', but got %v", opt.ShortName) - } -} diff --git a/vendor/github.com/jessevdk/go-flags/help_test.go b/vendor/github.com/jessevdk/go-flags/help_test.go deleted file mode 100644 index bb766405..00000000 --- a/vendor/github.com/jessevdk/go-flags/help_test.go +++ /dev/null @@ -1,538 +0,0 @@ -package flags - -import ( - "bufio" - "bytes" - "fmt" - "os" - "runtime" - "strings" - "testing" - "time" -) - -type helpOptions struct { - Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information" ini-name:"verbose"` - Call func(string) `short:"c" description:"Call phone number" ini-name:"call"` - PtrSlice []*string `long:"ptrslice" description:"A slice of pointers to string"` - EmptyDescription bool `long:"empty-description"` - - Default string `long:"default" default:"Some\nvalue" description:"Test default value"` - DefaultArray []string `long:"default-array" default:"Some value" default:"Other\tvalue" description:"Test default array value"` - DefaultMap map[string]string `long:"default-map" default:"some:value" default:"another:value" description:"Testdefault map value"` - EnvDefault1 string `long:"env-default1" default:"Some value" env:"ENV_DEFAULT" description:"Test env-default1 value"` - EnvDefault2 string `long:"env-default2" env:"ENV_DEFAULT" description:"Test env-default2 value"` - OptionWithArgName string `long:"opt-with-arg-name" value-name:"something" description:"Option with named argument"` - OptionWithChoices string `long:"opt-with-choices" value-name:"choice" choice:"dog" choice:"cat" description:"Option with choices"` - Hidden string `long:"hidden" description:"Hidden option" hidden:"yes"` - - OnlyIni string `ini-name:"only-ini" description:"Option only available in ini"` - - Other struct { - StringSlice []string `short:"s" default:"some" default:"value" description:"A slice of strings"` - IntMap map[string]int `long:"intmap" default:"a:1" description:"A map from string to int" ini-name:"int-map"` - } `group:"Other Options"` - - HiddenGroup struct { - InsideHiddenGroup string `long:"inside-hidden-group" description:"Inside hidden group"` - } `group:"Hidden group" hidden:"yes"` - - Group struct { - Opt string `long:"opt" description:"This is a subgroup option"` - HiddenInsideGroup string `long:"hidden-inside-group" description:"Hidden inside group" hidden:"yes"` - NotHiddenInsideGroup string `long:"not-hidden-inside-group" description:"Not hidden inside group" hidden:"false"` - - Group struct { - Opt string `long:"opt" description:"This is a subsubgroup option"` - } `group:"Subsubgroup" namespace:"sap"` - } `group:"Subgroup" namespace:"sip"` - - Command struct { - ExtraVerbose []bool `long:"extra-verbose" description:"Use for extra verbosity"` - } `command:"command" alias:"cm" alias:"cmd" description:"A command"` - - HiddenCommand struct { - ExtraVerbose []bool `long:"extra-verbose" description:"Use for extra verbosity"` - } `command:"hidden-command" description:"A hidden command" hidden:"yes"` - - Args struct { - Filename string `positional-arg-name:"filename" description:"A filename with a long description to trigger line wrapping"` - Number int `positional-arg-name:"num" description:"A number"` - HiddenInHelp float32 `positional-arg-name:"hidden-in-help" required:"yes"` - } `positional-args:"yes"` -} - -func TestHelp(t *testing.T) { - oldEnv := EnvSnapshot() - defer oldEnv.Restore() - os.Setenv("ENV_DEFAULT", "env-def") - - var opts helpOptions - p := NewNamedParser("TestHelp", HelpFlag) - p.AddGroup("Application Options", "The application options", &opts) - - _, err := p.ParseArgs([]string{"--help"}) - - if err == nil { - t.Fatalf("Expected help error") - } - - if e, ok := err.(*Error); !ok { - t.Fatalf("Expected flags.Error, but got %T", err) - } else { - if e.Type != ErrHelp { - t.Errorf("Expected flags.ErrHelp type, but got %s", e.Type) - } - - var expected string - - if runtime.GOOS == "windows" { - expected = `Usage: - TestHelp [OPTIONS] [filename] [num] [hidden-in-help] - -Application Options: - /v, /verbose Show verbose debug information - /c: Call phone number - /ptrslice: A slice of pointers to string - /empty-description - /default: Test default value (default: - "Some\nvalue") - /default-array: Test default array value (default: - Some value, "Other\tvalue") - /default-map: Testdefault map value (default: - some:value, another:value) - /env-default1: Test env-default1 value (default: - Some value) [%ENV_DEFAULT%] - /env-default2: Test env-default2 value - [%ENV_DEFAULT%] - /opt-with-arg-name:something Option with named argument - /opt-with-choices:choice[dog|cat] Option with choices - -Other Options: - /s: A slice of strings (default: some, - value) - /intmap: A map from string to int (default: - a:1) - -Subgroup: - /sip.opt: This is a subgroup option - /sip.not-hidden-inside-group: Not hidden inside group - -Subsubgroup: - /sip.sap.opt: This is a subsubgroup option - -Help Options: - /? Show this help message - /h, /help Show this help message - -Arguments: - filename: A filename with a long description - to trigger line wrapping - num: A number - -Available commands: - command A command (aliases: cm, cmd) -` - } else { - expected = `Usage: - TestHelp [OPTIONS] [filename] [num] [hidden-in-help] - -Application Options: - -v, --verbose Show verbose debug information - -c= Call phone number - --ptrslice= A slice of pointers to string - --empty-description - --default= Test default value (default: - "Some\nvalue") - --default-array= Test default array value (default: - Some value, "Other\tvalue") - --default-map= Testdefault map value (default: - some:value, another:value) - --env-default1= Test env-default1 value (default: - Some value) [$ENV_DEFAULT] - --env-default2= Test env-default2 value - [$ENV_DEFAULT] - --opt-with-arg-name=something Option with named argument - --opt-with-choices=choice[dog|cat] Option with choices - -Other Options: - -s= A slice of strings (default: some, - value) - --intmap= A map from string to int (default: - a:1) - -Subgroup: - --sip.opt= This is a subgroup option - --sip.not-hidden-inside-group= Not hidden inside group - -Subsubgroup: - --sip.sap.opt= This is a subsubgroup option - -Help Options: - -h, --help Show this help message - -Arguments: - filename: A filename with a long description - to trigger line wrapping - num: A number - -Available commands: - command A command (aliases: cm, cmd) -` - } - - assertDiff(t, e.Message, expected, "help message") - } -} - -func TestMan(t *testing.T) { - oldEnv := EnvSnapshot() - defer oldEnv.Restore() - os.Setenv("ENV_DEFAULT", "env-def") - - var opts helpOptions - p := NewNamedParser("TestMan", HelpFlag) - p.ShortDescription = "Test manpage generation" - p.LongDescription = "This is a somewhat `longer' description of what this does" - p.AddGroup("Application Options", "The application options", &opts) - - p.Commands()[0].LongDescription = "Longer `command' description" - - var buf bytes.Buffer - p.WriteManPage(&buf) - - got := buf.String() - - tt := time.Now() - - var envDefaultName string - - if runtime.GOOS == "windows" { - envDefaultName = "%ENV_DEFAULT%" - } else { - envDefaultName = "$ENV_DEFAULT" - } - - expected := fmt.Sprintf(`.TH TestMan 1 "%s" -.SH NAME -TestMan \- Test manpage generation -.SH SYNOPSIS -\fBTestMan\fP [OPTIONS] -.SH DESCRIPTION -This is a somewhat \fBlonger\fP description of what this does -.SH OPTIONS -.SS Application Options -The application options -.TP -\fB\fB\-v\fR, \fB\-\-verbose\fR\fP -Show verbose debug information -.TP -\fB\fB\-c\fR\fP -Call phone number -.TP -\fB\fB\-\-ptrslice\fR\fP -A slice of pointers to string -.TP -\fB\fB\-\-empty-description\fR\fP -.TP -\fB\fB\-\-default\fR \fP -Test default value -.TP -\fB\fB\-\-default-array\fR \fP -Test default array value -.TP -\fB\fB\-\-default-map\fR \fP -Testdefault map value -.TP -\fB\fB\-\-env-default1\fR \fP -Test env-default1 value -.TP -\fB\fB\-\-env-default2\fR \fP -Test env-default2 value -.TP -\fB\fB\-\-opt-with-arg-name\fR \fIsomething\fR\fP -Option with named argument -.TP -\fB\fB\-\-opt-with-choices\fR \fIchoice\fR\fP -Option with choices -.SS Other Options -.TP -\fB\fB\-s\fR \fP -A slice of strings -.TP -\fB\fB\-\-intmap\fR \fP -A map from string to int -.SS Subgroup -.TP -\fB\fB\-\-sip.opt\fR\fP -This is a subgroup option -.TP -\fB\fB\-\-sip.not-hidden-inside-group\fR\fP -Not hidden inside group -.SS Subsubgroup -.TP -\fB\fB\-\-sip.sap.opt\fR\fP -This is a subsubgroup option -.SH COMMANDS -.SS command -A command - -Longer \fBcommand\fP description - -\fBUsage\fP: TestMan [OPTIONS] command [command-OPTIONS] -.TP - -\fBAliases\fP: cm, cmd - -.TP -\fB\fB\-\-extra-verbose\fR\fP -Use for extra verbosity -`, tt.Format("2 January 2006"), envDefaultName) - - assertDiff(t, got, expected, "man page") -} - -type helpCommandNoOptions struct { - Command struct { - } `command:"command" description:"A command"` -} - -func TestHelpCommand(t *testing.T) { - oldEnv := EnvSnapshot() - defer oldEnv.Restore() - os.Setenv("ENV_DEFAULT", "env-def") - - var opts helpCommandNoOptions - p := NewNamedParser("TestHelpCommand", HelpFlag) - p.AddGroup("Application Options", "The application options", &opts) - - _, err := p.ParseArgs([]string{"command", "--help"}) - - if err == nil { - t.Fatalf("Expected help error") - } - - if e, ok := err.(*Error); !ok { - t.Fatalf("Expected flags.Error, but got %T", err) - } else { - if e.Type != ErrHelp { - t.Errorf("Expected flags.ErrHelp type, but got %s", e.Type) - } - - var expected string - - if runtime.GOOS == "windows" { - expected = `Usage: - TestHelpCommand [OPTIONS] command - -Help Options: - /? Show this help message - /h, /help Show this help message -` - } else { - expected = `Usage: - TestHelpCommand [OPTIONS] command - -Help Options: - -h, --help Show this help message -` - } - - assertDiff(t, e.Message, expected, "help message") - } -} - -func TestHelpDefaults(t *testing.T) { - var expected string - - if runtime.GOOS == "windows" { - expected = `Usage: - TestHelpDefaults [OPTIONS] - -Application Options: - /with-default: With default (default: default-value) - /without-default: Without default - /with-programmatic-default: With programmatic default (default: - default-value) - -Help Options: - /? Show this help message - /h, /help Show this help message -` - } else { - expected = `Usage: - TestHelpDefaults [OPTIONS] - -Application Options: - --with-default= With default (default: default-value) - --without-default= Without default - --with-programmatic-default= With programmatic default (default: - default-value) - -Help Options: - -h, --help Show this help message -` - } - - tests := []struct { - Args []string - Output string - }{ - { - Args: []string{"-h"}, - Output: expected, - }, - { - Args: []string{"--with-default", "other-value", "--with-programmatic-default", "other-value", "-h"}, - Output: expected, - }, - } - - for _, test := range tests { - var opts struct { - WithDefault string `long:"with-default" default:"default-value" description:"With default"` - WithoutDefault string `long:"without-default" description:"Without default"` - WithProgrammaticDefault string `long:"with-programmatic-default" description:"With programmatic default"` - } - - opts.WithProgrammaticDefault = "default-value" - - p := NewNamedParser("TestHelpDefaults", HelpFlag) - p.AddGroup("Application Options", "The application options", &opts) - - _, err := p.ParseArgs(test.Args) - - if err == nil { - t.Fatalf("Expected help error") - } - - if e, ok := err.(*Error); !ok { - t.Fatalf("Expected flags.Error, but got %T", err) - } else { - if e.Type != ErrHelp { - t.Errorf("Expected flags.ErrHelp type, but got %s", e.Type) - } - - assertDiff(t, e.Message, test.Output, "help message") - } - } -} - -func TestHelpRestArgs(t *testing.T) { - opts := struct { - Verbose bool `short:"v"` - }{} - - p := NewNamedParser("TestHelpDefaults", HelpFlag) - p.AddGroup("Application Options", "The application options", &opts) - - retargs, err := p.ParseArgs([]string{"-h", "-v", "rest"}) - - if err == nil { - t.Fatalf("Expected help error") - } - - assertStringArray(t, retargs, []string{"-v", "rest"}) -} - -func TestWrapText(t *testing.T) { - s := "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." - - got := wrapText(s, 60, " ") - expected := `Lorem ipsum dolor sit amet, consectetur adipisicing elit, - sed do eiusmod tempor incididunt ut labore et dolore magna - aliqua. Ut enim ad minim veniam, quis nostrud exercitation - ullamco laboris nisi ut aliquip ex ea commodo consequat. - Duis aute irure dolor in reprehenderit in voluptate velit - esse cillum dolore eu fugiat nulla pariatur. Excepteur sint - occaecat cupidatat non proident, sunt in culpa qui officia - deserunt mollit anim id est laborum.` - - assertDiff(t, got, expected, "wrapped text") -} - -func TestWrapParagraph(t *testing.T) { - s := "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n\n" - s += "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n\n" - s += "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n\n" - s += "Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n" - - got := wrapText(s, 60, " ") - expected := `Lorem ipsum dolor sit amet, consectetur adipisicing elit, - sed do eiusmod tempor incididunt ut labore et dolore magna - aliqua. - - Ut enim ad minim veniam, quis nostrud exercitation ullamco - laboris nisi ut aliquip ex ea commodo consequat. - - Duis aute irure dolor in reprehenderit in voluptate velit - esse cillum dolore eu fugiat nulla pariatur. - - Excepteur sint occaecat cupidatat non proident, sunt in - culpa qui officia deserunt mollit anim id est laborum. -` - - assertDiff(t, got, expected, "wrapped paragraph") -} - -func TestHelpDefaultMask(t *testing.T) { - var tests = []struct { - opts interface{} - present string - }{ - { - opts: &struct { - Value string `short:"v" default:"123" description:"V"` - }{}, - present: "V (default: 123)\n", - }, - { - opts: &struct { - Value string `short:"v" default:"123" default-mask:"abc" description:"V"` - }{}, - present: "V (default: abc)\n", - }, - { - opts: &struct { - Value string `short:"v" default:"123" default-mask:"-" description:"V"` - }{}, - present: "V\n", - }, - { - opts: &struct { - Value string `short:"v" description:"V"` - }{Value: "123"}, - present: "V (default: 123)\n", - }, - { - opts: &struct { - Value string `short:"v" default-mask:"abc" description:"V"` - }{Value: "123"}, - present: "V (default: abc)\n", - }, - { - opts: &struct { - Value string `short:"v" default-mask:"-" description:"V"` - }{Value: "123"}, - present: "V\n", - }, - } - - for _, test := range tests { - p := NewParser(test.opts, HelpFlag) - _, err := p.ParseArgs([]string{"-h"}) - if flagsErr, ok := err.(*Error); ok && flagsErr.Type == ErrHelp { - err = nil - } - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - h := &bytes.Buffer{} - w := bufio.NewWriter(h) - p.writeHelpOption(w, p.FindOptionByShortName('v'), p.getAlignmentInfo()) - w.Flush() - if strings.Index(h.String(), test.present) < 0 { - t.Errorf("Not present %q\n%s", test.present, h.String()) - } - } -} diff --git a/vendor/github.com/jessevdk/go-flags/ini_test.go b/vendor/github.com/jessevdk/go-flags/ini_test.go deleted file mode 100644 index ad4852e8..00000000 --- a/vendor/github.com/jessevdk/go-flags/ini_test.go +++ /dev/null @@ -1,1053 +0,0 @@ -package flags - -import ( - "bytes" - "fmt" - "io/ioutil" - "os" - "reflect" - "strings" - "testing" -) - -func TestWriteIni(t *testing.T) { - oldEnv := EnvSnapshot() - defer oldEnv.Restore() - os.Setenv("ENV_DEFAULT", "env-def") - - var tests = []struct { - args []string - options IniOptions - expected string - }{ - { - []string{"-vv", "--intmap=a:2", "--intmap", "b:3", "filename", "0", "3.14", "command"}, - IniDefault, - `[Application Options] -; Show verbose debug information -verbose = true -verbose = true - -; Test env-default1 value -EnvDefault1 = env-def - -; Test env-default2 value -EnvDefault2 = env-def - -[Other Options] -; A map from string to int -int-map = a:2 -int-map = b:3 - -`, - }, - { - []string{"-vv", "--intmap=a:2", "--intmap", "b:3", "filename", "0", "3.14", "command"}, - IniDefault | IniIncludeDefaults, - `[Application Options] -; Show verbose debug information -verbose = true -verbose = true - -; A slice of pointers to string -; PtrSlice = - -EmptyDescription = false - -; Test default value -Default = "Some\nvalue" - -; Test default array value -DefaultArray = Some value -DefaultArray = "Other\tvalue" - -; Testdefault map value -DefaultMap = another:value -DefaultMap = some:value - -; Test env-default1 value -EnvDefault1 = env-def - -; Test env-default2 value -EnvDefault2 = env-def - -; Option with named argument -OptionWithArgName = - -; Option with choices -OptionWithChoices = - -; Option only available in ini -only-ini = - -[Other Options] -; A slice of strings -StringSlice = some -StringSlice = value - -; A map from string to int -int-map = a:2 -int-map = b:3 - -[Subgroup] -; This is a subgroup option -Opt = - -; Not hidden inside group -NotHiddenInsideGroup = - -[Subsubgroup] -; This is a subsubgroup option -Opt = - -[command] -; Use for extra verbosity -; ExtraVerbose = - -`, - }, - { - []string{"filename", "0", "3.14", "command"}, - IniDefault | IniIncludeDefaults | IniCommentDefaults, - `[Application Options] -; Show verbose debug information -; verbose = - -; A slice of pointers to string -; PtrSlice = - -; EmptyDescription = false - -; Test default value -; Default = "Some\nvalue" - -; Test default array value -; DefaultArray = Some value -; DefaultArray = "Other\tvalue" - -; Testdefault map value -; DefaultMap = another:value -; DefaultMap = some:value - -; Test env-default1 value -EnvDefault1 = env-def - -; Test env-default2 value -EnvDefault2 = env-def - -; Option with named argument -; OptionWithArgName = - -; Option with choices -; OptionWithChoices = - -; Option only available in ini -; only-ini = - -[Other Options] -; A slice of strings -; StringSlice = some -; StringSlice = value - -; A map from string to int -; int-map = a:1 - -[Subgroup] -; This is a subgroup option -; Opt = - -; Not hidden inside group -; NotHiddenInsideGroup = - -[Subsubgroup] -; This is a subsubgroup option -; Opt = - -[command] -; Use for extra verbosity -; ExtraVerbose = - -`, - }, - { - []string{"--default=New value", "--default-array=New value", "--default-map=new:value", "filename", "0", "3.14", "command"}, - IniDefault | IniIncludeDefaults | IniCommentDefaults, - `[Application Options] -; Show verbose debug information -; verbose = - -; A slice of pointers to string -; PtrSlice = - -; EmptyDescription = false - -; Test default value -Default = New value - -; Test default array value -DefaultArray = New value - -; Testdefault map value -DefaultMap = new:value - -; Test env-default1 value -EnvDefault1 = env-def - -; Test env-default2 value -EnvDefault2 = env-def - -; Option with named argument -; OptionWithArgName = - -; Option with choices -; OptionWithChoices = - -; Option only available in ini -; only-ini = - -[Other Options] -; A slice of strings -; StringSlice = some -; StringSlice = value - -; A map from string to int -; int-map = a:1 - -[Subgroup] -; This is a subgroup option -; Opt = - -; Not hidden inside group -; NotHiddenInsideGroup = - -[Subsubgroup] -; This is a subsubgroup option -; Opt = - -[command] -; Use for extra verbosity -; ExtraVerbose = - -`, - }, - } - - for _, test := range tests { - var opts helpOptions - - p := NewNamedParser("TestIni", Default) - p.AddGroup("Application Options", "The application options", &opts) - - _, err := p.ParseArgs(test.args) - - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - inip := NewIniParser(p) - - var b bytes.Buffer - inip.Write(&b, test.options) - - got := b.String() - expected := test.expected - - msg := fmt.Sprintf("with arguments %+v and ini options %b", test.args, test.options) - assertDiff(t, got, expected, msg) - } -} - -func TestReadIni_flagEquivalent(t *testing.T) { - type options struct { - Opt1 bool `long:"opt1"` - - Group1 struct { - Opt2 bool `long:"opt2"` - } `group:"group1"` - - Group2 struct { - Opt3 bool `long:"opt3"` - } `group:"group2" namespace:"ns1"` - - Cmd1 struct { - Opt4 bool `long:"opt4"` - Opt5 bool `long:"foo.opt5"` - - Group1 struct { - Opt6 bool `long:"opt6"` - Opt7 bool `long:"foo.opt7"` - } `group:"group1"` - - Group2 struct { - Opt8 bool `long:"opt8"` - } `group:"group2" namespace:"ns1"` - } `command:"cmd1"` - } - - a := ` -opt1=true - -[group1] -opt2=true - -[group2] -ns1.opt3=true - -[cmd1] -opt4=true -foo.opt5=true - -[cmd1.group1] -opt6=true -foo.opt7=true - -[cmd1.group2] -ns1.opt8=true -` - b := ` -opt1=true -opt2=true -ns1.opt3=true - -[cmd1] -opt4=true -foo.opt5=true -opt6=true -foo.opt7=true -ns1.opt8=true -` - - parse := func(readIni string) (opts options, writeIni string) { - p := NewNamedParser("TestIni", Default) - p.AddGroup("Application Options", "The application options", &opts) - - inip := NewIniParser(p) - err := inip.Parse(strings.NewReader(readIni)) - - if err != nil { - t.Fatalf("Unexpected error: %s\n\nFile:\n%s", err, readIni) - } - - var b bytes.Buffer - inip.Write(&b, Default) - - return opts, b.String() - } - - aOpt, aIni := parse(a) - bOpt, bIni := parse(b) - - assertDiff(t, aIni, bIni, "") - if !reflect.DeepEqual(aOpt, bOpt) { - t.Errorf("not equal") - } -} - -func TestReadIni(t *testing.T) { - var opts helpOptions - - p := NewNamedParser("TestIni", Default) - p.AddGroup("Application Options", "The application options", &opts) - - inip := NewIniParser(p) - - inic := ` -; Show verbose debug information -verbose = true -verbose = true - -DefaultMap = another:"value\n1" -DefaultMap = some:value 2 - -[Application Options] -; A slice of pointers to string -; PtrSlice = - -; Test default value -Default = "New\nvalue" - -; Test env-default1 value -EnvDefault1 = New value - -[Other Options] -# A slice of strings -StringSlice = "some\nvalue" -StringSlice = another value - -; A map from string to int -int-map = a:2 -int-map = b:3 - -` - - b := strings.NewReader(inic) - err := inip.Parse(b) - - if err != nil { - t.Fatalf("Unexpected error: %s", err) - } - - assertBoolArray(t, opts.Verbose, []bool{true, true}) - - if v := map[string]string{"another": "value\n1", "some": "value 2"}; !reflect.DeepEqual(opts.DefaultMap, v) { - t.Fatalf("Expected %#v for DefaultMap but got %#v", v, opts.DefaultMap) - } - - assertString(t, opts.Default, "New\nvalue") - - assertString(t, opts.EnvDefault1, "New value") - - assertStringArray(t, opts.Other.StringSlice, []string{"some\nvalue", "another value"}) - - if v, ok := opts.Other.IntMap["a"]; !ok { - t.Errorf("Expected \"a\" in Other.IntMap") - } else if v != 2 { - t.Errorf("Expected Other.IntMap[\"a\"] = 2, but got %v", v) - } - - if v, ok := opts.Other.IntMap["b"]; !ok { - t.Errorf("Expected \"b\" in Other.IntMap") - } else if v != 3 { - t.Errorf("Expected Other.IntMap[\"b\"] = 3, but got %v", v) - } -} - -func TestReadAndWriteIni(t *testing.T) { - var tests = []struct { - options IniOptions - read string - write string - }{ - { - IniIncludeComments, - `[Application Options] -; Show verbose debug information -verbose = true -verbose = true - -; Test default value -Default = "quote me" - -; Test default array value -DefaultArray = 1 -DefaultArray = "2" -DefaultArray = 3 - -; Testdefault map value -; DefaultMap = - -; Test env-default1 value -EnvDefault1 = env-def - -; Test env-default2 value -EnvDefault2 = env-def - -[Other Options] -; A slice of strings -; StringSlice = - -; A map from string to int -int-map = a:2 -int-map = b:"3" - -`, - `[Application Options] -; Show verbose debug information -verbose = true -verbose = true - -; Test default value -Default = "quote me" - -; Test default array value -DefaultArray = 1 -DefaultArray = 2 -DefaultArray = 3 - -; Testdefault map value -; DefaultMap = - -; Test env-default1 value -EnvDefault1 = env-def - -; Test env-default2 value -EnvDefault2 = env-def - -[Other Options] -; A slice of strings -; StringSlice = - -; A map from string to int -int-map = a:2 -int-map = b:3 - -`, - }, - { - IniIncludeComments, - `[Application Options] -; Show verbose debug information -verbose = true -verbose = true - -; Test default value -Default = "quote me" - -; Test default array value -DefaultArray = "1" -DefaultArray = "2" -DefaultArray = "3" - -; Testdefault map value -; DefaultMap = - -; Test env-default1 value -EnvDefault1 = env-def - -; Test env-default2 value -EnvDefault2 = env-def - -[Other Options] -; A slice of strings -; StringSlice = - -; A map from string to int -int-map = a:"2" -int-map = b:"3" - -`, - `[Application Options] -; Show verbose debug information -verbose = true -verbose = true - -; Test default value -Default = "quote me" - -; Test default array value -DefaultArray = "1" -DefaultArray = "2" -DefaultArray = "3" - -; Testdefault map value -; DefaultMap = - -; Test env-default1 value -EnvDefault1 = env-def - -; Test env-default2 value -EnvDefault2 = env-def - -[Other Options] -; A slice of strings -; StringSlice = - -; A map from string to int -int-map = a:"2" -int-map = b:"3" - -`, - }, - } - - for _, test := range tests { - var opts helpOptions - - p := NewNamedParser("TestIni", Default) - p.AddGroup("Application Options", "The application options", &opts) - - inip := NewIniParser(p) - - read := strings.NewReader(test.read) - err := inip.Parse(read) - if err != nil { - t.Fatalf("Unexpected error: %s", err) - } - - var write bytes.Buffer - inip.Write(&write, test.options) - - got := write.String() - - msg := fmt.Sprintf("with ini options %b", test.options) - assertDiff(t, got, test.write, msg) - } -} - -func TestReadIniWrongQuoting(t *testing.T) { - var tests = []struct { - iniFile string - lineNumber uint - }{ - { - iniFile: `Default = "New\nvalue`, - lineNumber: 1, - }, - { - iniFile: `StringSlice = "New\nvalue`, - lineNumber: 1, - }, - { - iniFile: `StringSlice = "New\nvalue" - StringSlice = "Second\nvalue`, - lineNumber: 2, - }, - { - iniFile: `DefaultMap = some:"value`, - lineNumber: 1, - }, - { - iniFile: `DefaultMap = some:value - DefaultMap = another:"value`, - lineNumber: 2, - }, - } - - for _, test := range tests { - var opts helpOptions - - p := NewNamedParser("TestIni", Default) - p.AddGroup("Application Options", "The application options", &opts) - - inip := NewIniParser(p) - - inic := test.iniFile - - b := strings.NewReader(inic) - err := inip.Parse(b) - - if err == nil { - t.Fatalf("Expect error") - } - - iniError := err.(*IniError) - - if iniError.LineNumber != test.lineNumber { - t.Fatalf("Expect error on line %d", test.lineNumber) - } - } -} - -func TestIniCommands(t *testing.T) { - var opts struct { - Value string `short:"v" long:"value"` - - Add struct { - Name int `short:"n" long:"name" ini-name:"AliasName"` - - Other struct { - O string `short:"o" long:"other"` - } `group:"Other Options"` - } `command:"add"` - } - - p := NewNamedParser("TestIni", Default) - p.AddGroup("Application Options", "The application options", &opts) - - inip := NewIniParser(p) - - inic := `[Application Options] -value = some value - -[add] -AliasName = 5 - -[add.Other Options] -other = subgroup - -` - - b := strings.NewReader(inic) - err := inip.Parse(b) - - if err != nil { - t.Fatalf("Unexpected error: %s", err) - } - - assertString(t, opts.Value, "some value") - - if opts.Add.Name != 5 { - t.Errorf("Expected opts.Add.Name to be 5, but got %v", opts.Add.Name) - } - - assertString(t, opts.Add.Other.O, "subgroup") - - // Test writing it back - buf := &bytes.Buffer{} - - inip.Write(buf, IniDefault) - - assertDiff(t, buf.String(), inic, "ini contents") -} - -func TestIniNoIni(t *testing.T) { - var opts struct { - NoValue string `short:"n" long:"novalue" no-ini:"yes"` - Value string `short:"v" long:"value"` - } - - p := NewNamedParser("TestIni", Default) - p.AddGroup("Application Options", "The application options", &opts) - - inip := NewIniParser(p) - - // read INI - inic := `[Application Options] -novalue = some value -value = some other value -` - - b := strings.NewReader(inic) - err := inip.Parse(b) - - if err == nil { - t.Fatalf("Expected error") - } - - iniError := err.(*IniError) - - if v := uint(2); iniError.LineNumber != v { - t.Errorf("Expected opts.Add.Name to be %d, but got %d", v, iniError.LineNumber) - } - - if v := "unknown option: novalue"; iniError.Message != v { - t.Errorf("Expected opts.Add.Name to be %s, but got %s", v, iniError.Message) - } - - // write INI - opts.NoValue = "some value" - opts.Value = "some other value" - - file, err := ioutil.TempFile("", "") - if err != nil { - t.Fatalf("Cannot create temporary file: %s", err) - } - defer os.Remove(file.Name()) - - err = inip.WriteFile(file.Name(), IniIncludeDefaults) - if err != nil { - t.Fatalf("Could not write ini file: %s", err) - } - - found, err := ioutil.ReadFile(file.Name()) - if err != nil { - t.Fatalf("Could not read written ini file: %s", err) - } - - expected := "[Application Options]\nValue = some other value\n\n" - - assertDiff(t, string(found), expected, "ini content") -} - -func TestIniParse(t *testing.T) { - file, err := ioutil.TempFile("", "") - if err != nil { - t.Fatalf("Cannot create temporary file: %s", err) - } - defer os.Remove(file.Name()) - - _, err = file.WriteString("value = 123") - if err != nil { - t.Fatalf("Cannot write to temporary file: %s", err) - } - - file.Close() - - var opts struct { - Value int `long:"value"` - } - - err = IniParse(file.Name(), &opts) - if err != nil { - t.Fatalf("Could not parse ini: %s", err) - } - - if opts.Value != 123 { - t.Fatalf("Expected Value to be \"123\" but was \"%d\"", opts.Value) - } -} - -func TestIniCliOverrides(t *testing.T) { - file, err := ioutil.TempFile("", "") - - if err != nil { - t.Fatalf("Cannot create temporary file: %s", err) - } - - defer os.Remove(file.Name()) - - _, err = file.WriteString("values = 123\n") - _, err = file.WriteString("values = 456\n") - - if err != nil { - t.Fatalf("Cannot write to temporary file: %s", err) - } - - file.Close() - - var opts struct { - Values []int `long:"values"` - } - - p := NewParser(&opts, Default) - err = NewIniParser(p).ParseFile(file.Name()) - - if err != nil { - t.Fatalf("Could not parse ini: %s", err) - } - - _, err = p.ParseArgs([]string{"--values", "111", "--values", "222"}) - - if err != nil { - t.Fatalf("Failed to parse arguments: %s", err) - } - - if len(opts.Values) != 2 { - t.Fatalf("Expected Values to contain two elements, but got %d", len(opts.Values)) - } - - if opts.Values[0] != 111 { - t.Fatalf("Expected Values[0] to be 111, but got '%d'", opts.Values[0]) - } - - if opts.Values[1] != 222 { - t.Fatalf("Expected Values[1] to be 222, but got '%d'", opts.Values[1]) - } -} - -func TestIniOverrides(t *testing.T) { - file, err := ioutil.TempFile("", "") - - if err != nil { - t.Fatalf("Cannot create temporary file: %s", err) - } - - defer os.Remove(file.Name()) - - _, err = file.WriteString("value-with-default = \"ini-value\"\n") - _, err = file.WriteString("value-with-default-override-cli = \"ini-value\"\n") - - if err != nil { - t.Fatalf("Cannot write to temporary file: %s", err) - } - - file.Close() - - var opts struct { - ValueWithDefault string `long:"value-with-default" default:"value"` - ValueWithDefaultOverrideCli string `long:"value-with-default-override-cli" default:"value"` - } - - p := NewParser(&opts, Default) - err = NewIniParser(p).ParseFile(file.Name()) - - if err != nil { - t.Fatalf("Could not parse ini: %s", err) - } - - _, err = p.ParseArgs([]string{"--value-with-default-override-cli", "cli-value"}) - - if err != nil { - t.Fatalf("Failed to parse arguments: %s", err) - } - - assertString(t, opts.ValueWithDefault, "ini-value") - assertString(t, opts.ValueWithDefaultOverrideCli, "cli-value") -} - -func TestIniRequired(t *testing.T) { - var opts struct { - Required string `short:"r" required:"yes" description:"required"` - Config func(s string) error `long:"config" default:"no-ini-file" no-ini:"true"` - } - - p := NewParser(&opts, Default) - - opts.Config = func(s string) error { - inip := NewIniParser(p) - inip.ParseAsDefaults = true - return inip.Parse(strings.NewReader("Required = ini-value\n")) - } - - _, err := p.ParseArgs([]string{"-r", "cli-value"}) - - if err != nil { - t.Fatalf("Failed to parse arguments: %s", err) - } - - assertString(t, opts.Required, "cli-value") -} - -func TestWriteFile(t *testing.T) { - file, err := ioutil.TempFile("", "") - if err != nil { - t.Fatalf("Cannot create temporary file: %s", err) - } - defer os.Remove(file.Name()) - - var opts struct { - Value int `long:"value"` - } - - opts.Value = 123 - - p := NewParser(&opts, Default) - ini := NewIniParser(p) - - err = ini.WriteFile(file.Name(), IniIncludeDefaults) - if err != nil { - t.Fatalf("Could not write ini file: %s", err) - } - - found, err := ioutil.ReadFile(file.Name()) - if err != nil { - t.Fatalf("Could not read written ini file: %s", err) - } - - expected := "[Application Options]\nValue = 123\n\n" - - assertDiff(t, string(found), expected, "ini content") -} - -func TestOverwriteRequiredOptions(t *testing.T) { - var tests = []struct { - args []string - expected []string - }{ - { - args: []string{"--value", "from CLI"}, - expected: []string{ - "from CLI", - "from default", - }, - }, - { - args: []string{"--value", "from CLI", "--default", "from CLI"}, - expected: []string{ - "from CLI", - "from CLI", - }, - }, - { - args: []string{"--config", "no file name"}, - expected: []string{ - "from INI", - "from INI", - }, - }, - { - args: []string{"--value", "from CLI before", "--default", "from CLI before", "--config", "no file name"}, - expected: []string{ - "from INI", - "from INI", - }, - }, - { - args: []string{"--value", "from CLI before", "--default", "from CLI before", "--config", "no file name", "--value", "from CLI after", "--default", "from CLI after"}, - expected: []string{ - "from CLI after", - "from CLI after", - }, - }, - } - - for _, test := range tests { - var opts struct { - Config func(s string) error `long:"config" no-ini:"true"` - Value string `long:"value" required:"true"` - Default string `long:"default" required:"true" default:"from default"` - } - - p := NewParser(&opts, Default) - - opts.Config = func(s string) error { - ini := NewIniParser(p) - - return ini.Parse(bytes.NewBufferString("value = from INI\ndefault = from INI")) - } - - _, err := p.ParseArgs(test.args) - if err != nil { - t.Fatalf("Unexpected error %s with args %+v", err, test.args) - } - - if opts.Value != test.expected[0] { - t.Fatalf("Expected Value to be \"%s\" but was \"%s\" with args %+v", test.expected[0], opts.Value, test.args) - } - - if opts.Default != test.expected[1] { - t.Fatalf("Expected Default to be \"%s\" but was \"%s\" with args %+v", test.expected[1], opts.Default, test.args) - } - } -} - -func TestIniOverwriteOptions(t *testing.T) { - var tests = []struct { - args []string - expected string - toggled bool - }{ - { - args: []string{}, - expected: "from default", - }, - { - args: []string{"--value", "from CLI"}, - expected: "from CLI", - }, - { - args: []string{"--config", "no file name"}, - expected: "from INI", - toggled: true, - }, - { - args: []string{"--value", "from CLI before", "--config", "no file name"}, - expected: "from CLI before", - toggled: true, - }, - { - args: []string{"--config", "no file name", "--value", "from CLI after"}, - expected: "from CLI after", - toggled: true, - }, - { - args: []string{"--toggle"}, - toggled: true, - expected: "from default", - }, - } - - for _, test := range tests { - var opts struct { - Config string `long:"config" no-ini:"true"` - Value string `long:"value" default:"from default"` - Toggle bool `long:"toggle"` - } - - p := NewParser(&opts, Default) - - _, err := p.ParseArgs(test.args) - if err != nil { - t.Fatalf("Unexpected error %s with args %+v", err, test.args) - } - - if opts.Config != "" { - inip := NewIniParser(p) - inip.ParseAsDefaults = true - - err = inip.Parse(bytes.NewBufferString("value = from INI\ntoggle = true")) - if err != nil { - t.Fatalf("Unexpected error %s with args %+v", err, test.args) - } - } - - if opts.Value != test.expected { - t.Fatalf("Expected Value to be \"%s\" but was \"%s\" with args %+v", test.expected, opts.Value, test.args) - } - - if opts.Toggle != test.toggled { - t.Fatalf("Expected Toggle to be \"%v\" but was \"%v\" with args %+v", test.toggled, opts.Toggle, test.args) - } - - } -} diff --git a/vendor/github.com/jessevdk/go-flags/long_test.go b/vendor/github.com/jessevdk/go-flags/long_test.go deleted file mode 100644 index 02fc8c70..00000000 --- a/vendor/github.com/jessevdk/go-flags/long_test.go +++ /dev/null @@ -1,85 +0,0 @@ -package flags - -import ( - "testing" -) - -func TestLong(t *testing.T) { - var opts = struct { - Value bool `long:"value"` - }{} - - ret := assertParseSuccess(t, &opts, "--value") - - assertStringArray(t, ret, []string{}) - - if !opts.Value { - t.Errorf("Expected Value to be true") - } -} - -func TestLongArg(t *testing.T) { - var opts = struct { - Value string `long:"value"` - }{} - - ret := assertParseSuccess(t, &opts, "--value", "value") - - assertStringArray(t, ret, []string{}) - assertString(t, opts.Value, "value") -} - -func TestLongArgEqual(t *testing.T) { - var opts = struct { - Value string `long:"value"` - }{} - - ret := assertParseSuccess(t, &opts, "--value=value") - - assertStringArray(t, ret, []string{}) - assertString(t, opts.Value, "value") -} - -func TestLongDefault(t *testing.T) { - var opts = struct { - Value string `long:"value" default:"value"` - }{} - - ret := assertParseSuccess(t, &opts) - - assertStringArray(t, ret, []string{}) - assertString(t, opts.Value, "value") -} - -func TestLongOptional(t *testing.T) { - var opts = struct { - Value string `long:"value" optional:"yes" optional-value:"value"` - }{} - - ret := assertParseSuccess(t, &opts, "--value") - - assertStringArray(t, ret, []string{}) - assertString(t, opts.Value, "value") -} - -func TestLongOptionalArg(t *testing.T) { - var opts = struct { - Value string `long:"value" optional:"yes" optional-value:"value"` - }{} - - ret := assertParseSuccess(t, &opts, "--value", "no") - - assertStringArray(t, ret, []string{"no"}) - assertString(t, opts.Value, "value") -} - -func TestLongOptionalArgEqual(t *testing.T) { - var opts = struct { - Value string `long:"value" optional:"yes" optional-value:"value"` - }{} - - ret := assertParseSuccess(t, &opts, "--value=value", "no") - - assertStringArray(t, ret, []string{"no"}) - assertString(t, opts.Value, "value") -} diff --git a/vendor/github.com/jessevdk/go-flags/marshal_test.go b/vendor/github.com/jessevdk/go-flags/marshal_test.go deleted file mode 100644 index 4cfe8656..00000000 --- a/vendor/github.com/jessevdk/go-flags/marshal_test.go +++ /dev/null @@ -1,119 +0,0 @@ -package flags - -import ( - "fmt" - "testing" -) - -type marshalled string - -func (m *marshalled) UnmarshalFlag(value string) error { - if value == "yes" { - *m = "true" - } else if value == "no" { - *m = "false" - } else { - return fmt.Errorf("`%s' is not a valid value, please specify `yes' or `no'", value) - } - - return nil -} - -func (m marshalled) MarshalFlag() (string, error) { - if m == "true" { - return "yes", nil - } - - return "no", nil -} - -type marshalledError bool - -func (m marshalledError) MarshalFlag() (string, error) { - return "", newErrorf(ErrMarshal, "Failed to marshal") -} - -func TestUnmarshal(t *testing.T) { - var opts = struct { - Value marshalled `short:"v"` - }{} - - ret := assertParseSuccess(t, &opts, "-v=yes") - - assertStringArray(t, ret, []string{}) - - if opts.Value != "true" { - t.Errorf("Expected Value to be \"true\"") - } -} - -func TestUnmarshalDefault(t *testing.T) { - var opts = struct { - Value marshalled `short:"v" default:"yes"` - }{} - - ret := assertParseSuccess(t, &opts) - - assertStringArray(t, ret, []string{}) - - if opts.Value != "true" { - t.Errorf("Expected Value to be \"true\"") - } -} - -func TestUnmarshalOptional(t *testing.T) { - var opts = struct { - Value marshalled `short:"v" optional:"yes" optional-value:"yes"` - }{} - - ret := assertParseSuccess(t, &opts, "-v") - - assertStringArray(t, ret, []string{}) - - if opts.Value != "true" { - t.Errorf("Expected Value to be \"true\"") - } -} - -func TestUnmarshalError(t *testing.T) { - var opts = struct { - Value marshalled `short:"v"` - }{} - - assertParseFail(t, ErrMarshal, fmt.Sprintf("invalid argument for flag `%cv' (expected flags.marshalled): `invalid' is not a valid value, please specify `yes' or `no'", defaultShortOptDelimiter), &opts, "-vinvalid") -} - -func TestUnmarshalPositionalError(t *testing.T) { - var opts = struct { - Args struct { - Value marshalled - } `positional-args:"yes"` - }{} - - parser := NewParser(&opts, Default&^PrintErrors) - _, err := parser.ParseArgs([]string{"invalid"}) - - msg := "`invalid' is not a valid value, please specify `yes' or `no'" - - if err == nil { - assertFatalf(t, "Expected error: %s", msg) - return - } - - if err.Error() != msg { - assertErrorf(t, "Expected error message %#v, but got %#v", msg, err.Error()) - } -} - -func TestMarshalError(t *testing.T) { - var opts = struct { - Value marshalledError `short:"v"` - }{} - - p := NewParser(&opts, Default) - o := p.Command.Groups()[0].Options()[0] - - _, err := convertToString(o.value, o.tag) - - assertError(t, err, ErrMarshal, "Failed to marshal") -} diff --git a/vendor/github.com/jessevdk/go-flags/options_test.go b/vendor/github.com/jessevdk/go-flags/options_test.go deleted file mode 100644 index b0fe9f45..00000000 --- a/vendor/github.com/jessevdk/go-flags/options_test.go +++ /dev/null @@ -1,45 +0,0 @@ -package flags - -import ( - "testing" -) - -func TestPassDoubleDash(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - }{} - - p := NewParser(&opts, PassDoubleDash) - ret, err := p.ParseArgs([]string{"-v", "--", "-v", "-g"}) - - if err != nil { - t.Fatalf("Unexpected error: %v", err) - return - } - - if !opts.Value { - t.Errorf("Expected Value to be true") - } - - assertStringArray(t, ret, []string{"-v", "-g"}) -} - -func TestPassAfterNonOption(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - }{} - - p := NewParser(&opts, PassAfterNonOption) - ret, err := p.ParseArgs([]string{"-v", "arg", "-v", "-g"}) - - if err != nil { - t.Fatalf("Unexpected error: %v", err) - return - } - - if !opts.Value { - t.Errorf("Expected Value to be true") - } - - assertStringArray(t, ret, []string{"arg", "-v", "-g"}) -} diff --git a/vendor/github.com/jessevdk/go-flags/parser_test.go b/vendor/github.com/jessevdk/go-flags/parser_test.go deleted file mode 100644 index 374f21cc..00000000 --- a/vendor/github.com/jessevdk/go-flags/parser_test.go +++ /dev/null @@ -1,612 +0,0 @@ -package flags - -import ( - "fmt" - "os" - "reflect" - "runtime" - "strconv" - "strings" - "testing" - "time" -) - -type defaultOptions struct { - Int int `long:"i"` - IntDefault int `long:"id" default:"1"` - - Float64 float64 `long:"f"` - Float64Default float64 `long:"fd" default:"-3.14"` - - NumericFlag bool `short:"3"` - - String string `long:"str"` - StringDefault string `long:"strd" default:"abc"` - StringNotUnquoted string `long:"strnot" unquote:"false"` - - Time time.Duration `long:"t"` - TimeDefault time.Duration `long:"td" default:"1m"` - - Map map[string]int `long:"m"` - MapDefault map[string]int `long:"md" default:"a:1"` - - Slice []int `long:"s"` - SliceDefault []int `long:"sd" default:"1" default:"2"` -} - -func TestDefaults(t *testing.T) { - var tests = []struct { - msg string - args []string - expected defaultOptions - }{ - { - msg: "no arguments, expecting default values", - args: []string{}, - expected: defaultOptions{ - Int: 0, - IntDefault: 1, - - Float64: 0.0, - Float64Default: -3.14, - - NumericFlag: false, - - String: "", - StringDefault: "abc", - - Time: 0, - TimeDefault: time.Minute, - - Map: map[string]int{}, - MapDefault: map[string]int{"a": 1}, - - Slice: []int{}, - SliceDefault: []int{1, 2}, - }, - }, - { - msg: "non-zero value arguments, expecting overwritten arguments", - args: []string{"--i=3", "--id=3", "--f=-2.71", "--fd=2.71", "-3", "--str=def", "--strd=def", "--t=3ms", "--td=3ms", "--m=c:3", "--md=c:3", "--s=3", "--sd=3"}, - expected: defaultOptions{ - Int: 3, - IntDefault: 3, - - Float64: -2.71, - Float64Default: 2.71, - - NumericFlag: true, - - String: "def", - StringDefault: "def", - - Time: 3 * time.Millisecond, - TimeDefault: 3 * time.Millisecond, - - Map: map[string]int{"c": 3}, - MapDefault: map[string]int{"c": 3}, - - Slice: []int{3}, - SliceDefault: []int{3}, - }, - }, - { - msg: "zero value arguments, expecting overwritten arguments", - args: []string{"--i=0", "--id=0", "--f=0", "--fd=0", "--str", "", "--strd=\"\"", "--t=0ms", "--td=0s", "--m=:0", "--md=:0", "--s=0", "--sd=0"}, - expected: defaultOptions{ - Int: 0, - IntDefault: 0, - - Float64: 0, - Float64Default: 0, - - String: "", - StringDefault: "", - - Time: 0, - TimeDefault: 0, - - Map: map[string]int{"": 0}, - MapDefault: map[string]int{"": 0}, - - Slice: []int{0}, - SliceDefault: []int{0}, - }, - }, - } - - for _, test := range tests { - var opts defaultOptions - - _, err := ParseArgs(&opts, test.args) - if err != nil { - t.Fatalf("%s:\nUnexpected error: %v", test.msg, err) - } - - if opts.Slice == nil { - opts.Slice = []int{} - } - - if !reflect.DeepEqual(opts, test.expected) { - t.Errorf("%s:\nUnexpected options with arguments %+v\nexpected\n%+v\nbut got\n%+v\n", test.msg, test.args, test.expected, opts) - } - } -} - -func TestNoDefaultsForBools(t *testing.T) { - var opts struct { - DefaultBool bool `short:"d" default:"true"` - } - - if runtime.GOOS == "windows" { - assertParseFail(t, ErrInvalidTag, "boolean flag `/d' may not have default values, they always default to `false' and can only be turned on", &opts) - } else { - assertParseFail(t, ErrInvalidTag, "boolean flag `-d' may not have default values, they always default to `false' and can only be turned on", &opts) - } -} - -func TestUnquoting(t *testing.T) { - var tests = []struct { - arg string - err error - value string - }{ - { - arg: "\"abc", - err: strconv.ErrSyntax, - value: "", - }, - { - arg: "\"\"abc\"", - err: strconv.ErrSyntax, - value: "", - }, - { - arg: "\"abc\"", - err: nil, - value: "abc", - }, - { - arg: "\"\\\"abc\\\"\"", - err: nil, - value: "\"abc\"", - }, - { - arg: "\"\\\"abc\"", - err: nil, - value: "\"abc", - }, - } - - for _, test := range tests { - var opts defaultOptions - - for _, delimiter := range []bool{false, true} { - p := NewParser(&opts, None) - - var err error - if delimiter { - _, err = p.ParseArgs([]string{"--str=" + test.arg, "--strnot=" + test.arg}) - } else { - _, err = p.ParseArgs([]string{"--str", test.arg, "--strnot", test.arg}) - } - - if test.err == nil { - if err != nil { - t.Fatalf("Expected no error but got: %v", err) - } - - if test.value != opts.String { - t.Fatalf("Expected String to be %q but got %q", test.value, opts.String) - } - if q := strconv.Quote(test.value); q != opts.StringNotUnquoted { - t.Fatalf("Expected StringDefault to be %q but got %q", q, opts.StringNotUnquoted) - } - } else { - if err == nil { - t.Fatalf("Expected error") - } else if e, ok := err.(*Error); ok { - if strings.HasPrefix(e.Message, test.err.Error()) { - t.Fatalf("Expected error message to end with %q but got %v", test.err.Error(), e.Message) - } - } - } - } - } -} - -// EnvRestorer keeps a copy of a set of env variables and can restore the env from them -type EnvRestorer struct { - env map[string]string -} - -func (r *EnvRestorer) Restore() { - os.Clearenv() - - for k, v := range r.env { - os.Setenv(k, v) - } -} - -// EnvSnapshot returns a snapshot of the currently set env variables -func EnvSnapshot() *EnvRestorer { - r := EnvRestorer{make(map[string]string)} - - for _, kv := range os.Environ() { - parts := strings.SplitN(kv, "=", 2) - - if len(parts) != 2 { - panic("got a weird env variable: " + kv) - } - - r.env[parts[0]] = parts[1] - } - - return &r -} - -type envDefaultOptions struct { - Int int `long:"i" default:"1" env:"TEST_I"` - Time time.Duration `long:"t" default:"1m" env:"TEST_T"` - Map map[string]int `long:"m" default:"a:1" env:"TEST_M" env-delim:";"` - Slice []int `long:"s" default:"1" default:"2" env:"TEST_S" env-delim:","` -} - -func TestEnvDefaults(t *testing.T) { - var tests = []struct { - msg string - args []string - expected envDefaultOptions - env map[string]string - }{ - { - msg: "no arguments, no env, expecting default values", - args: []string{}, - expected: envDefaultOptions{ - Int: 1, - Time: time.Minute, - Map: map[string]int{"a": 1}, - Slice: []int{1, 2}, - }, - }, - { - msg: "no arguments, env defaults, expecting env default values", - args: []string{}, - expected: envDefaultOptions{ - Int: 2, - Time: 2 * time.Minute, - Map: map[string]int{"a": 2, "b": 3}, - Slice: []int{4, 5, 6}, - }, - env: map[string]string{ - "TEST_I": "2", - "TEST_T": "2m", - "TEST_M": "a:2;b:3", - "TEST_S": "4,5,6", - }, - }, - { - msg: "non-zero value arguments, expecting overwritten arguments", - args: []string{"--i=3", "--t=3ms", "--m=c:3", "--s=3"}, - expected: envDefaultOptions{ - Int: 3, - Time: 3 * time.Millisecond, - Map: map[string]int{"c": 3}, - Slice: []int{3}, - }, - env: map[string]string{ - "TEST_I": "2", - "TEST_T": "2m", - "TEST_M": "a:2;b:3", - "TEST_S": "4,5,6", - }, - }, - { - msg: "zero value arguments, expecting overwritten arguments", - args: []string{"--i=0", "--t=0ms", "--m=:0", "--s=0"}, - expected: envDefaultOptions{ - Int: 0, - Time: 0, - Map: map[string]int{"": 0}, - Slice: []int{0}, - }, - env: map[string]string{ - "TEST_I": "2", - "TEST_T": "2m", - "TEST_M": "a:2;b:3", - "TEST_S": "4,5,6", - }, - }, - } - - oldEnv := EnvSnapshot() - defer oldEnv.Restore() - - for _, test := range tests { - var opts envDefaultOptions - oldEnv.Restore() - for envKey, envValue := range test.env { - os.Setenv(envKey, envValue) - } - _, err := ParseArgs(&opts, test.args) - if err != nil { - t.Fatalf("%s:\nUnexpected error: %v", test.msg, err) - } - - if opts.Slice == nil { - opts.Slice = []int{} - } - - if !reflect.DeepEqual(opts, test.expected) { - t.Errorf("%s:\nUnexpected options with arguments %+v\nexpected\n%+v\nbut got\n%+v\n", test.msg, test.args, test.expected, opts) - } - } -} - -func TestOptionAsArgument(t *testing.T) { - var tests = []struct { - args []string - expectError bool - errType ErrorType - errMsg string - rest []string - }{ - { - // short option must not be accepted as argument - args: []string{"--string-slice", "foobar", "--string-slice", "-o"}, - expectError: true, - errType: ErrExpectedArgument, - errMsg: "expected argument for flag `" + defaultLongOptDelimiter + "string-slice', but got option `-o'", - }, - { - // long option must not be accepted as argument - args: []string{"--string-slice", "foobar", "--string-slice", "--other-option"}, - expectError: true, - errType: ErrExpectedArgument, - errMsg: "expected argument for flag `" + defaultLongOptDelimiter + "string-slice', but got option `--other-option'", - }, - { - // long option must not be accepted as argument - args: []string{"--string-slice", "--"}, - expectError: true, - errType: ErrExpectedArgument, - errMsg: "expected argument for flag `" + defaultLongOptDelimiter + "string-slice', but got double dash `--'", - }, - { - // quoted and appended option should be accepted as argument (even if it looks like an option) - args: []string{"--string-slice", "foobar", "--string-slice=\"--other-option\""}, - }, - { - // Accept any single character arguments including '-' - args: []string{"--string-slice", "-"}, - }, - { - // Do not accept arguments which start with '-' even if the next character is a digit - args: []string{"--string-slice", "-3.14"}, - expectError: true, - errType: ErrExpectedArgument, - errMsg: "expected argument for flag `" + defaultLongOptDelimiter + "string-slice', but got option `-3.14'", - }, - { - // Do not accept arguments which start with '-' if the next character is not a digit - args: []string{"--string-slice", "-character"}, - expectError: true, - errType: ErrExpectedArgument, - errMsg: "expected argument for flag `" + defaultLongOptDelimiter + "string-slice', but got option `-character'", - }, - { - args: []string{"-o", "-", "-"}, - rest: []string{"-", "-"}, - }, - { - // Accept arguments which start with '-' if the next character is a digit, for number options only - args: []string{"--int-slice", "-3"}, - }, - { - // Accept arguments which start with '-' if the next character is a digit, for number options only - args: []string{"--int16", "-3"}, - }, - { - // Accept arguments which start with '-' if the next character is a digit, for number options only - args: []string{"--float32", "-3.2"}, - }, - { - // Accept arguments which start with '-' if the next character is a digit, for number options only - args: []string{"--float32ptr", "-3.2"}, - }, - } - - var opts struct { - StringSlice []string `long:"string-slice"` - IntSlice []int `long:"int-slice"` - Int16 int16 `long:"int16"` - Float32 float32 `long:"float32"` - Float32Ptr *float32 `long:"float32ptr"` - OtherOption bool `long:"other-option" short:"o"` - } - - for _, test := range tests { - if test.expectError { - assertParseFail(t, test.errType, test.errMsg, &opts, test.args...) - } else { - args := assertParseSuccess(t, &opts, test.args...) - - assertStringArray(t, args, test.rest) - } - } -} - -func TestUnknownFlagHandler(t *testing.T) { - - var opts struct { - Flag1 string `long:"flag1"` - Flag2 string `long:"flag2"` - } - - p := NewParser(&opts, None) - - var unknownFlag1 string - var unknownFlag2 bool - var unknownFlag3 string - - // Set up a callback to intercept unknown options during parsing - p.UnknownOptionHandler = func(option string, arg SplitArgument, args []string) ([]string, error) { - if option == "unknownFlag1" { - if argValue, ok := arg.Value(); ok { - unknownFlag1 = argValue - return args, nil - } - // consume a value from remaining args list - unknownFlag1 = args[0] - return args[1:], nil - } else if option == "unknownFlag2" { - // treat this one as a bool switch, don't consume any args - unknownFlag2 = true - return args, nil - } else if option == "unknownFlag3" { - if argValue, ok := arg.Value(); ok { - unknownFlag3 = argValue - return args, nil - } - // consume a value from remaining args list - unknownFlag3 = args[0] - return args[1:], nil - } - - return args, fmt.Errorf("Unknown flag: %v", option) - } - - // Parse args containing some unknown flags, verify that - // our callback can handle all of them - _, err := p.ParseArgs([]string{"--flag1=stuff", "--unknownFlag1", "blah", "--unknownFlag2", "--unknownFlag3=baz", "--flag2=foo"}) - - if err != nil { - assertErrorf(t, "Parser returned unexpected error %v", err) - } - - assertString(t, opts.Flag1, "stuff") - assertString(t, opts.Flag2, "foo") - assertString(t, unknownFlag1, "blah") - assertString(t, unknownFlag3, "baz") - - if !unknownFlag2 { - assertErrorf(t, "Flag should have been set by unknown handler, but had value: %v", unknownFlag2) - } - - // Parse args with unknown flags that callback doesn't handle, verify it returns error - _, err = p.ParseArgs([]string{"--flag1=stuff", "--unknownFlagX", "blah", "--flag2=foo"}) - - if err == nil { - assertErrorf(t, "Parser should have returned error, but returned nil") - } -} - -func TestChoices(t *testing.T) { - var opts struct { - Choice string `long:"choose" choice:"v1" choice:"v2"` - } - - assertParseFail(t, ErrInvalidChoice, "Invalid value `invalid' for option `"+defaultLongOptDelimiter+"choose'. Allowed values are: v1 or v2", &opts, "--choose", "invalid") - assertParseSuccess(t, &opts, "--choose", "v2") - assertString(t, opts.Choice, "v2") -} - -func TestEmbedded(t *testing.T) { - type embedded struct { - V bool `short:"v"` - } - var opts struct { - embedded - } - - assertParseSuccess(t, &opts, "-v") - - if !opts.V { - t.Errorf("Expected V to be true") - } -} - -type command struct { -} - -func (c *command) Execute(args []string) error { - return nil -} - -func TestCommandHandlerNoCommand(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - }{} - - parser := NewParser(&opts, Default&^PrintErrors) - - var executedCommand Commander - var executedArgs []string - - executed := false - - parser.CommandHandler = func(command Commander, args []string) error { - executed = true - - executedCommand = command - executedArgs = args - - return nil - } - - _, err := parser.ParseArgs([]string{"arg1", "arg2"}) - - if err != nil { - t.Fatalf("Unexpected parse error: %s", err) - } - - if !executed { - t.Errorf("Expected command handler to be executed") - } - - if executedCommand != nil { - t.Errorf("Did not exect an executed command") - } - - assertStringArray(t, executedArgs, []string{"arg1", "arg2"}) -} - -func TestCommandHandler(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Command command `command:"cmd"` - }{} - - parser := NewParser(&opts, Default&^PrintErrors) - - var executedCommand Commander - var executedArgs []string - - executed := false - - parser.CommandHandler = func(command Commander, args []string) error { - executed = true - - executedCommand = command - executedArgs = args - - return nil - } - - _, err := parser.ParseArgs([]string{"cmd", "arg1", "arg2"}) - - if err != nil { - t.Fatalf("Unexpected parse error: %s", err) - } - - if !executed { - t.Errorf("Expected command handler to be executed") - } - - if executedCommand == nil { - t.Errorf("Expected command handler to be executed") - } - - assertStringArray(t, executedArgs, []string{"arg1", "arg2"}) -} diff --git a/vendor/github.com/jessevdk/go-flags/pointer_test.go b/vendor/github.com/jessevdk/go-flags/pointer_test.go deleted file mode 100644 index dc779c78..00000000 --- a/vendor/github.com/jessevdk/go-flags/pointer_test.go +++ /dev/null @@ -1,164 +0,0 @@ -package flags - -import ( - "testing" -) - -func TestPointerBool(t *testing.T) { - var opts = struct { - Value *bool `short:"v"` - }{} - - ret := assertParseSuccess(t, &opts, "-v") - - assertStringArray(t, ret, []string{}) - - if !*opts.Value { - t.Errorf("Expected Value to be true") - } -} - -func TestPointerString(t *testing.T) { - var opts = struct { - Value *string `short:"v"` - }{} - - ret := assertParseSuccess(t, &opts, "-v", "value") - - assertStringArray(t, ret, []string{}) - assertString(t, *opts.Value, "value") -} - -func TestPointerSlice(t *testing.T) { - var opts = struct { - Value *[]string `short:"v"` - }{} - - ret := assertParseSuccess(t, &opts, "-v", "value1", "-v", "value2") - - assertStringArray(t, ret, []string{}) - assertStringArray(t, *opts.Value, []string{"value1", "value2"}) -} - -func TestPointerMap(t *testing.T) { - var opts = struct { - Value *map[string]int `short:"v"` - }{} - - ret := assertParseSuccess(t, &opts, "-v", "k1:2", "-v", "k2:-5") - - assertStringArray(t, ret, []string{}) - - if v, ok := (*opts.Value)["k1"]; !ok { - t.Errorf("Expected key \"k1\" to exist") - } else if v != 2 { - t.Errorf("Expected \"k1\" to be 2, but got %#v", v) - } - - if v, ok := (*opts.Value)["k2"]; !ok { - t.Errorf("Expected key \"k2\" to exist") - } else if v != -5 { - t.Errorf("Expected \"k2\" to be -5, but got %#v", v) - } -} - -type marshalledString string - -func (m *marshalledString) UnmarshalFlag(value string) error { - *m = marshalledString(value) - return nil -} - -func (m marshalledString) MarshalFlag() (string, error) { - return string(m), nil -} - -func TestPointerStringMarshalled(t *testing.T) { - var opts = struct { - Value *marshalledString `short:"v"` - }{} - - ret := assertParseSuccess(t, &opts, "-v", "value") - - assertStringArray(t, ret, []string{}) - - if opts.Value == nil { - t.Error("Expected value not to be nil") - return - } - - assertString(t, string(*opts.Value), "value") -} - -type marshalledStruct struct { - Value string -} - -func (m *marshalledStruct) UnmarshalFlag(value string) error { - m.Value = value - return nil -} - -func (m marshalledStruct) MarshalFlag() (string, error) { - return m.Value, nil -} - -func TestPointerStructMarshalled(t *testing.T) { - var opts = struct { - Value *marshalledStruct `short:"v"` - }{} - - ret := assertParseSuccess(t, &opts, "-v", "value") - - assertStringArray(t, ret, []string{}) - - if opts.Value == nil { - t.Error("Expected value not to be nil") - return - } - - assertString(t, opts.Value.Value, "value") -} - -type PointerGroup struct { - Value bool `short:"v"` -} - -func TestPointerGroup(t *testing.T) { - var opts = struct { - Group *PointerGroup `group:"Group Options"` - }{} - - ret := assertParseSuccess(t, &opts, "-v") - - assertStringArray(t, ret, []string{}) - - if !opts.Group.Value { - t.Errorf("Expected Group.Value to be true") - } -} - -func TestDoNotChangeNonTaggedFields(t *testing.T) { - var opts struct { - A struct { - Pointer *int - } - B *struct { - Pointer *int - } - } - - ret := assertParseSuccess(t, &opts) - - assertStringArray(t, ret, []string{}) - - if opts.A.Pointer != nil { - t.Error("Expected A.Pointer to be nil") - } - if opts.B != nil { - t.Error("Expected B to be nil") - } - if opts.B != nil && opts.B.Pointer != nil { - t.Error("Expected B.Pointer to be nil") - } -} diff --git a/vendor/github.com/jessevdk/go-flags/short_test.go b/vendor/github.com/jessevdk/go-flags/short_test.go deleted file mode 100644 index 5f4106b0..00000000 --- a/vendor/github.com/jessevdk/go-flags/short_test.go +++ /dev/null @@ -1,234 +0,0 @@ -package flags - -import ( - "fmt" - "testing" -) - -func TestShort(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - }{} - - ret := assertParseSuccess(t, &opts, "-v") - - assertStringArray(t, ret, []string{}) - - if !opts.Value { - t.Errorf("Expected Value to be true") - } -} - -func TestShortTooLong(t *testing.T) { - var opts = struct { - Value bool `short:"vv"` - }{} - - assertParseFail(t, ErrShortNameTooLong, "short names can only be 1 character long, not `vv'", &opts) -} - -func TestShortRequired(t *testing.T) { - var opts = struct { - Value bool `short:"v" required:"true"` - }{} - - assertParseFail(t, ErrRequired, fmt.Sprintf("the required flag `%cv' was not specified", defaultShortOptDelimiter), &opts) -} - -func TestShortRequiredFalsy1(t *testing.T) { - var opts = struct { - Value bool `short:"v" required:"false"` - }{} - - assertParseSuccess(t, &opts) -} - -func TestShortRequiredFalsy2(t *testing.T) { - var opts = struct { - Value bool `short:"v" required:"no"` - }{} - - assertParseSuccess(t, &opts) -} - -func TestShortMultiConcat(t *testing.T) { - var opts = struct { - V bool `short:"v"` - O bool `short:"o"` - F bool `short:"f"` - }{} - - ret := assertParseSuccess(t, &opts, "-vo", "-f") - - assertStringArray(t, ret, []string{}) - - if !opts.V { - t.Errorf("Expected V to be true") - } - - if !opts.O { - t.Errorf("Expected O to be true") - } - - if !opts.F { - t.Errorf("Expected F to be true") - } -} - -func TestShortMultiRequiredConcat(t *testing.T) { - var opts = struct { - V bool `short:"v" required:"true"` - O bool `short:"o" required:"true"` - F bool `short:"f" required:"true"` - }{} - - ret := assertParseSuccess(t, &opts, "-vo", "-f") - - assertStringArray(t, ret, []string{}) - - if !opts.V { - t.Errorf("Expected V to be true") - } - - if !opts.O { - t.Errorf("Expected O to be true") - } - - if !opts.F { - t.Errorf("Expected F to be true") - } -} - -func TestShortMultiSlice(t *testing.T) { - var opts = struct { - Values []bool `short:"v"` - }{} - - ret := assertParseSuccess(t, &opts, "-v", "-v") - - assertStringArray(t, ret, []string{}) - assertBoolArray(t, opts.Values, []bool{true, true}) -} - -func TestShortMultiSliceConcat(t *testing.T) { - var opts = struct { - Values []bool `short:"v"` - }{} - - ret := assertParseSuccess(t, &opts, "-vvv") - - assertStringArray(t, ret, []string{}) - assertBoolArray(t, opts.Values, []bool{true, true, true}) -} - -func TestShortWithEqualArg(t *testing.T) { - var opts = struct { - Value string `short:"v"` - }{} - - ret := assertParseSuccess(t, &opts, "-v=value") - - assertStringArray(t, ret, []string{}) - assertString(t, opts.Value, "value") -} - -func TestShortWithArg(t *testing.T) { - var opts = struct { - Value string `short:"v"` - }{} - - ret := assertParseSuccess(t, &opts, "-vvalue") - - assertStringArray(t, ret, []string{}) - assertString(t, opts.Value, "value") -} - -func TestShortArg(t *testing.T) { - var opts = struct { - Value string `short:"v"` - }{} - - ret := assertParseSuccess(t, &opts, "-v", "value") - - assertStringArray(t, ret, []string{}) - assertString(t, opts.Value, "value") -} - -func TestShortMultiWithEqualArg(t *testing.T) { - var opts = struct { - F []bool `short:"f"` - Value string `short:"v"` - }{} - - assertParseFail(t, ErrExpectedArgument, fmt.Sprintf("expected argument for flag `%cv'", defaultShortOptDelimiter), &opts, "-ffv=value") -} - -func TestShortMultiArg(t *testing.T) { - var opts = struct { - F []bool `short:"f"` - Value string `short:"v"` - }{} - - ret := assertParseSuccess(t, &opts, "-ffv", "value") - - assertStringArray(t, ret, []string{}) - assertBoolArray(t, opts.F, []bool{true, true}) - assertString(t, opts.Value, "value") -} - -func TestShortMultiArgConcatFail(t *testing.T) { - var opts = struct { - F []bool `short:"f"` - Value string `short:"v"` - }{} - - assertParseFail(t, ErrExpectedArgument, fmt.Sprintf("expected argument for flag `%cv'", defaultShortOptDelimiter), &opts, "-ffvvalue") -} - -func TestShortMultiArgConcat(t *testing.T) { - var opts = struct { - F []bool `short:"f"` - Value string `short:"v"` - }{} - - ret := assertParseSuccess(t, &opts, "-vff") - - assertStringArray(t, ret, []string{}) - assertString(t, opts.Value, "ff") -} - -func TestShortOptional(t *testing.T) { - var opts = struct { - F []bool `short:"f"` - Value string `short:"v" optional:"yes" optional-value:"value"` - }{} - - ret := assertParseSuccess(t, &opts, "-fv", "f") - - assertStringArray(t, ret, []string{"f"}) - assertString(t, opts.Value, "value") -} - -func TestShortOptionalFalsy1(t *testing.T) { - var opts = struct { - F []bool `short:"f"` - Value string `short:"v" optional:"false" optional-value:"value"` - }{} - - ret := assertParseSuccess(t, &opts, "-fv", "f") - - assertStringArray(t, ret, []string{}) - assertString(t, opts.Value, "f") -} - -func TestShortOptionalFalsy2(t *testing.T) { - var opts = struct { - F []bool `short:"f"` - Value string `short:"v" optional:"no" optional-value:"value"` - }{} - - ret := assertParseSuccess(t, &opts, "-fv", "f") - - assertStringArray(t, ret, []string{}) - assertString(t, opts.Value, "f") -} diff --git a/vendor/github.com/jessevdk/go-flags/tag_test.go b/vendor/github.com/jessevdk/go-flags/tag_test.go deleted file mode 100644 index 9daa7401..00000000 --- a/vendor/github.com/jessevdk/go-flags/tag_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package flags - -import ( - "testing" -) - -func TestTagMissingColon(t *testing.T) { - var opts = struct { - Value bool `short` - }{} - - assertParseFail(t, ErrTag, "expected `:' after key name, but got end of tag (in `short`)", &opts, "") -} - -func TestTagMissingValue(t *testing.T) { - var opts = struct { - Value bool `short:` - }{} - - assertParseFail(t, ErrTag, "expected `\"' to start tag value at end of tag (in `short:`)", &opts, "") -} - -func TestTagMissingQuote(t *testing.T) { - var opts = struct { - Value bool `short:"v` - }{} - - assertParseFail(t, ErrTag, "expected end of tag value `\"' at end of tag (in `short:\"v`)", &opts, "") -} - -func TestTagNewline(t *testing.T) { - var opts = struct { - Value bool `long:"verbose" description:"verbose -something"` - }{} - - assertParseFail(t, ErrTag, "unexpected newline in tag value `description' (in `long:\"verbose\" description:\"verbose\nsomething\"`)", &opts, "") -} diff --git a/vendor/github.com/jessevdk/go-flags/unknown_test.go b/vendor/github.com/jessevdk/go-flags/unknown_test.go deleted file mode 100644 index 858be458..00000000 --- a/vendor/github.com/jessevdk/go-flags/unknown_test.go +++ /dev/null @@ -1,66 +0,0 @@ -package flags - -import ( - "testing" -) - -func TestUnknownFlags(t *testing.T) { - var opts = struct { - Verbose []bool `short:"v" long:"verbose" description:"Verbose output"` - }{} - - args := []string{ - "-f", - } - - p := NewParser(&opts, 0) - args, err := p.ParseArgs(args) - - if err == nil { - t.Fatal("Expected error for unknown argument") - } -} - -func TestIgnoreUnknownFlags(t *testing.T) { - var opts = struct { - Verbose []bool `short:"v" long:"verbose" description:"Verbose output"` - }{} - - args := []string{ - "hello", - "world", - "-v", - "--foo=bar", - "--verbose", - "-f", - } - - p := NewParser(&opts, IgnoreUnknown) - args, err := p.ParseArgs(args) - - if err != nil { - t.Fatal(err) - } - - exargs := []string{ - "hello", - "world", - "--foo=bar", - "-f", - } - - issame := (len(args) == len(exargs)) - - if issame { - for i := 0; i < len(args); i++ { - if args[i] != exargs[i] { - issame = false - break - } - } - } - - if !issame { - t.Fatalf("Expected %v but got %v", exargs, args) - } -} diff --git a/vendor/github.com/jinzhu/gorm/README.md b/vendor/github.com/jinzhu/gorm/README.md deleted file mode 100644 index 0c5c7ea6..00000000 --- a/vendor/github.com/jinzhu/gorm/README.md +++ /dev/null @@ -1,40 +0,0 @@ -# GORM - -The fantastic ORM library for Golang, aims to be developer friendly. - -[![go report card](https://goreportcard.com/badge/github.com/jinzhu/gorm "go report card")](https://goreportcard.com/report/github.com/jinzhu/gorm) -[![wercker status](https://app.wercker.com/status/8596cace912c9947dd9c8542ecc8cb8b/s/master "wercker status")](https://app.wercker.com/project/byKey/8596cace912c9947dd9c8542ecc8cb8b) -[![Join the chat at https://gitter.im/jinzhu/gorm](https://img.shields.io/gitter/room/jinzhu/gorm.svg)](https://gitter.im/jinzhu/gorm?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -[![Open Collective Backer](https://opencollective.com/gorm/tiers/backer/badge.svg?label=backer&color=brightgreen "Open Collective Backer")](https://opencollective.com/gorm) -[![Open Collective Sponsor](https://opencollective.com/gorm/tiers/sponsor/badge.svg?label=sponsor&color=brightgreen "Open Collective Sponsor")](https://opencollective.com/gorm) -[![MIT license](http://img.shields.io/badge/license-MIT-brightgreen.svg)](http://opensource.org/licenses/MIT) -[![GoDoc](https://godoc.org/github.com/jinzhu/gorm?status.svg)](https://godoc.org/github.com/jinzhu/gorm) - -## Overview - -* Full-Featured ORM (almost) -* Associations (Has One, Has Many, Belongs To, Many To Many, Polymorphism) -* Hooks (Before/After Create/Save/Update/Delete/Find) -* Preloading (eager loading) -* Transactions -* Composite Primary Key -* SQL Builder -* Auto Migrations -* Logger -* Extendable, write Plugins based on GORM callbacks -* Every feature comes with tests -* Developer Friendly - -## Getting Started - -* GORM Guides [http://gorm.io](http://gorm.io) - -## Contributing - -[You can help to deliver a better GORM, check out things you can do](http://gorm.io/contribute.html) - -## License - -© Jinzhu, 2013~time.Now - -Released under the [MIT License](https://github.com/jinzhu/gorm/blob/master/License) diff --git a/vendor/github.com/jinzhu/gorm/association_test.go b/vendor/github.com/jinzhu/gorm/association_test.go deleted file mode 100644 index 60d0cf48..00000000 --- a/vendor/github.com/jinzhu/gorm/association_test.go +++ /dev/null @@ -1,1050 +0,0 @@ -package gorm_test - -import ( - "fmt" - "os" - "reflect" - "sort" - "testing" - - "github.com/jinzhu/gorm" -) - -func TestBelongsTo(t *testing.T) { - post := Post{ - Title: "post belongs to", - Body: "body belongs to", - Category: Category{Name: "Category 1"}, - MainCategory: Category{Name: "Main Category 1"}, - } - - if err := DB.Save(&post).Error; err != nil { - t.Error("Got errors when save post", err) - } - - if post.Category.ID == 0 || post.MainCategory.ID == 0 { - t.Errorf("Category's primary key should be updated") - } - - if post.CategoryId.Int64 == 0 || post.MainCategoryId == 0 { - t.Errorf("post's foreign key should be updated") - } - - // Query - var category1 Category - DB.Model(&post).Association("Category").Find(&category1) - if category1.Name != "Category 1" { - t.Errorf("Query belongs to relations with Association") - } - - var mainCategory1 Category - DB.Model(&post).Association("MainCategory").Find(&mainCategory1) - if mainCategory1.Name != "Main Category 1" { - t.Errorf("Query belongs to relations with Association") - } - - var category11 Category - DB.Model(&post).Related(&category11) - if category11.Name != "Category 1" { - t.Errorf("Query belongs to relations with Related") - } - - if DB.Model(&post).Association("Category").Count() != 1 { - t.Errorf("Post's category count should be 1") - } - - if DB.Model(&post).Association("MainCategory").Count() != 1 { - t.Errorf("Post's main category count should be 1") - } - - // Append - var category2 = Category{ - Name: "Category 2", - } - DB.Model(&post).Association("Category").Append(&category2) - - if category2.ID == 0 { - t.Errorf("Category should has ID when created with Append") - } - - var category21 Category - DB.Model(&post).Related(&category21) - - if category21.Name != "Category 2" { - t.Errorf("Category should be updated with Append") - } - - if DB.Model(&post).Association("Category").Count() != 1 { - t.Errorf("Post's category count should be 1") - } - - // Replace - var category3 = Category{ - Name: "Category 3", - } - DB.Model(&post).Association("Category").Replace(&category3) - - if category3.ID == 0 { - t.Errorf("Category should has ID when created with Replace") - } - - var category31 Category - DB.Model(&post).Related(&category31) - if category31.Name != "Category 3" { - t.Errorf("Category should be updated with Replace") - } - - if DB.Model(&post).Association("Category").Count() != 1 { - t.Errorf("Post's category count should be 1") - } - - // Delete - DB.Model(&post).Association("Category").Delete(&category2) - if DB.Model(&post).Related(&Category{}).RecordNotFound() { - t.Errorf("Should not delete any category when Delete a unrelated Category") - } - - if post.Category.Name == "" { - t.Errorf("Post's category should not be reseted when Delete a unrelated Category") - } - - DB.Model(&post).Association("Category").Delete(&category3) - - if post.Category.Name != "" { - t.Errorf("Post's category should be reseted after Delete") - } - - var category41 Category - DB.Model(&post).Related(&category41) - if category41.Name != "" { - t.Errorf("Category should be deleted with Delete") - } - - if count := DB.Model(&post).Association("Category").Count(); count != 0 { - t.Errorf("Post's category count should be 0 after Delete, but got %v", count) - } - - // Clear - DB.Model(&post).Association("Category").Append(&Category{ - Name: "Category 2", - }) - - if DB.Model(&post).Related(&Category{}).RecordNotFound() { - t.Errorf("Should find category after append") - } - - if post.Category.Name == "" { - t.Errorf("Post's category should has value after Append") - } - - DB.Model(&post).Association("Category").Clear() - - if post.Category.Name != "" { - t.Errorf("Post's category should be cleared after Clear") - } - - if !DB.Model(&post).Related(&Category{}).RecordNotFound() { - t.Errorf("Should not find any category after Clear") - } - - if count := DB.Model(&post).Association("Category").Count(); count != 0 { - t.Errorf("Post's category count should be 0 after Clear, but got %v", count) - } - - // Check Association mode with soft delete - category6 := Category{ - Name: "Category 6", - } - DB.Model(&post).Association("Category").Append(&category6) - - if count := DB.Model(&post).Association("Category").Count(); count != 1 { - t.Errorf("Post's category count should be 1 after Append, but got %v", count) - } - - DB.Delete(&category6) - - if count := DB.Model(&post).Association("Category").Count(); count != 0 { - t.Errorf("Post's category count should be 0 after the category has been deleted, but got %v", count) - } - - if err := DB.Model(&post).Association("Category").Find(&Category{}).Error; err == nil { - t.Errorf("Post's category is not findable after Delete") - } - - if count := DB.Unscoped().Model(&post).Association("Category").Count(); count != 1 { - t.Errorf("Post's category count should be 1 when query with Unscoped, but got %v", count) - } - - if err := DB.Unscoped().Model(&post).Association("Category").Find(&Category{}).Error; err != nil { - t.Errorf("Post's category should be findable when query with Unscoped, got %v", err) - } -} - -func TestBelongsToOverrideForeignKey1(t *testing.T) { - type Profile struct { - gorm.Model - Name string - } - - type User struct { - gorm.Model - Profile Profile `gorm:"ForeignKey:ProfileRefer"` - ProfileRefer int - } - - if relation, ok := DB.NewScope(&User{}).FieldByName("Profile"); ok { - if relation.Relationship.Kind != "belongs_to" || - !reflect.DeepEqual(relation.Relationship.ForeignFieldNames, []string{"ProfileRefer"}) || - !reflect.DeepEqual(relation.Relationship.AssociationForeignFieldNames, []string{"ID"}) { - t.Errorf("Override belongs to foreign key with tag") - } - } -} - -func TestBelongsToOverrideForeignKey2(t *testing.T) { - type Profile struct { - gorm.Model - Refer string - Name string - } - - type User struct { - gorm.Model - Profile Profile `gorm:"ForeignKey:ProfileID;AssociationForeignKey:Refer"` - ProfileID int - } - - if relation, ok := DB.NewScope(&User{}).FieldByName("Profile"); ok { - if relation.Relationship.Kind != "belongs_to" || - !reflect.DeepEqual(relation.Relationship.ForeignFieldNames, []string{"ProfileID"}) || - !reflect.DeepEqual(relation.Relationship.AssociationForeignFieldNames, []string{"Refer"}) { - t.Errorf("Override belongs to foreign key with tag") - } - } -} - -func TestHasOne(t *testing.T) { - user := User{ - Name: "has one", - CreditCard: CreditCard{Number: "411111111111"}, - } - - if err := DB.Save(&user).Error; err != nil { - t.Error("Got errors when save user", err.Error()) - } - - if user.CreditCard.UserId.Int64 == 0 { - t.Errorf("CreditCard's foreign key should be updated") - } - - // Query - var creditCard1 CreditCard - DB.Model(&user).Related(&creditCard1) - - if creditCard1.Number != "411111111111" { - t.Errorf("Query has one relations with Related") - } - - var creditCard11 CreditCard - DB.Model(&user).Association("CreditCard").Find(&creditCard11) - - if creditCard11.Number != "411111111111" { - t.Errorf("Query has one relations with Related") - } - - if DB.Model(&user).Association("CreditCard").Count() != 1 { - t.Errorf("User's credit card count should be 1") - } - - // Append - var creditcard2 = CreditCard{ - Number: "411111111112", - } - DB.Model(&user).Association("CreditCard").Append(&creditcard2) - - if creditcard2.ID == 0 { - t.Errorf("Creditcard should has ID when created with Append") - } - - var creditcard21 CreditCard - DB.Model(&user).Related(&creditcard21) - if creditcard21.Number != "411111111112" { - t.Errorf("CreditCard should be updated with Append") - } - - if DB.Model(&user).Association("CreditCard").Count() != 1 { - t.Errorf("User's credit card count should be 1") - } - - // Replace - var creditcard3 = CreditCard{ - Number: "411111111113", - } - DB.Model(&user).Association("CreditCard").Replace(&creditcard3) - - if creditcard3.ID == 0 { - t.Errorf("Creditcard should has ID when created with Replace") - } - - var creditcard31 CreditCard - DB.Model(&user).Related(&creditcard31) - if creditcard31.Number != "411111111113" { - t.Errorf("CreditCard should be updated with Replace") - } - - if DB.Model(&user).Association("CreditCard").Count() != 1 { - t.Errorf("User's credit card count should be 1") - } - - // Delete - DB.Model(&user).Association("CreditCard").Delete(&creditcard2) - var creditcard4 CreditCard - DB.Model(&user).Related(&creditcard4) - if creditcard4.Number != "411111111113" { - t.Errorf("Should not delete credit card when Delete a unrelated CreditCard") - } - - if DB.Model(&user).Association("CreditCard").Count() != 1 { - t.Errorf("User's credit card count should be 1") - } - - DB.Model(&user).Association("CreditCard").Delete(&creditcard3) - if !DB.Model(&user).Related(&CreditCard{}).RecordNotFound() { - t.Errorf("Should delete credit card with Delete") - } - - if DB.Model(&user).Association("CreditCard").Count() != 0 { - t.Errorf("User's credit card count should be 0 after Delete") - } - - // Clear - var creditcard5 = CreditCard{ - Number: "411111111115", - } - DB.Model(&user).Association("CreditCard").Append(&creditcard5) - - if DB.Model(&user).Related(&CreditCard{}).RecordNotFound() { - t.Errorf("Should added credit card with Append") - } - - if DB.Model(&user).Association("CreditCard").Count() != 1 { - t.Errorf("User's credit card count should be 1") - } - - DB.Model(&user).Association("CreditCard").Clear() - if !DB.Model(&user).Related(&CreditCard{}).RecordNotFound() { - t.Errorf("Credit card should be deleted with Clear") - } - - if DB.Model(&user).Association("CreditCard").Count() != 0 { - t.Errorf("User's credit card count should be 0 after Clear") - } - - // Check Association mode with soft delete - var creditcard6 = CreditCard{ - Number: "411111111116", - } - DB.Model(&user).Association("CreditCard").Append(&creditcard6) - - if count := DB.Model(&user).Association("CreditCard").Count(); count != 1 { - t.Errorf("User's credit card count should be 1 after Append, but got %v", count) - } - - DB.Delete(&creditcard6) - - if count := DB.Model(&user).Association("CreditCard").Count(); count != 0 { - t.Errorf("User's credit card count should be 0 after credit card deleted, but got %v", count) - } - - if err := DB.Model(&user).Association("CreditCard").Find(&CreditCard{}).Error; err == nil { - t.Errorf("User's creditcard is not findable after Delete") - } - - if count := DB.Unscoped().Model(&user).Association("CreditCard").Count(); count != 1 { - t.Errorf("User's credit card count should be 1 when query with Unscoped, but got %v", count) - } - - if err := DB.Unscoped().Model(&user).Association("CreditCard").Find(&CreditCard{}).Error; err != nil { - t.Errorf("User's creditcard should be findable when query with Unscoped, got %v", err) - } -} - -func TestHasOneOverrideForeignKey1(t *testing.T) { - type Profile struct { - gorm.Model - Name string - UserRefer uint - } - - type User struct { - gorm.Model - Profile Profile `gorm:"ForeignKey:UserRefer"` - } - - if relation, ok := DB.NewScope(&User{}).FieldByName("Profile"); ok { - if relation.Relationship.Kind != "has_one" || - !reflect.DeepEqual(relation.Relationship.ForeignFieldNames, []string{"UserRefer"}) || - !reflect.DeepEqual(relation.Relationship.AssociationForeignFieldNames, []string{"ID"}) { - t.Errorf("Override belongs to foreign key with tag") - } - } -} - -func TestHasOneOverrideForeignKey2(t *testing.T) { - type Profile struct { - gorm.Model - Name string - UserID uint - } - - type User struct { - gorm.Model - Refer string - Profile Profile `gorm:"ForeignKey:UserID;AssociationForeignKey:Refer"` - } - - if relation, ok := DB.NewScope(&User{}).FieldByName("Profile"); ok { - if relation.Relationship.Kind != "has_one" || - !reflect.DeepEqual(relation.Relationship.ForeignFieldNames, []string{"UserID"}) || - !reflect.DeepEqual(relation.Relationship.AssociationForeignFieldNames, []string{"Refer"}) { - t.Errorf("Override belongs to foreign key with tag") - } - } -} - -func TestHasMany(t *testing.T) { - post := Post{ - Title: "post has many", - Body: "body has many", - Comments: []*Comment{{Content: "Comment 1"}, {Content: "Comment 2"}}, - } - - if err := DB.Save(&post).Error; err != nil { - t.Error("Got errors when save post", err) - } - - for _, comment := range post.Comments { - if comment.PostId == 0 { - t.Errorf("comment's PostID should be updated") - } - } - - var compareComments = func(comments []Comment, contents []string) bool { - var commentContents []string - for _, comment := range comments { - commentContents = append(commentContents, comment.Content) - } - sort.Strings(commentContents) - sort.Strings(contents) - return reflect.DeepEqual(commentContents, contents) - } - - // Query - if DB.First(&Comment{}, "content = ?", "Comment 1").Error != nil { - t.Errorf("Comment 1 should be saved") - } - - var comments1 []Comment - DB.Model(&post).Association("Comments").Find(&comments1) - if !compareComments(comments1, []string{"Comment 1", "Comment 2"}) { - t.Errorf("Query has many relations with Association") - } - - var comments11 []Comment - DB.Model(&post).Related(&comments11) - if !compareComments(comments11, []string{"Comment 1", "Comment 2"}) { - t.Errorf("Query has many relations with Related") - } - - if DB.Model(&post).Association("Comments").Count() != 2 { - t.Errorf("Post's comments count should be 2") - } - - // Append - DB.Model(&post).Association("Comments").Append(&Comment{Content: "Comment 3"}) - - var comments2 []Comment - DB.Model(&post).Related(&comments2) - if !compareComments(comments2, []string{"Comment 1", "Comment 2", "Comment 3"}) { - t.Errorf("Append new record to has many relations") - } - - if DB.Model(&post).Association("Comments").Count() != 3 { - t.Errorf("Post's comments count should be 3 after Append") - } - - // Delete - DB.Model(&post).Association("Comments").Delete(comments11) - - var comments3 []Comment - DB.Model(&post).Related(&comments3) - if !compareComments(comments3, []string{"Comment 3"}) { - t.Errorf("Delete an existing resource for has many relations") - } - - if DB.Model(&post).Association("Comments").Count() != 1 { - t.Errorf("Post's comments count should be 1 after Delete 2") - } - - // Replace - DB.Model(&Post{Id: 999}).Association("Comments").Replace() - - var comments4 []Comment - DB.Model(&post).Related(&comments4) - if len(comments4) == 0 { - t.Errorf("Replace for other resource should not clear all comments") - } - - DB.Model(&post).Association("Comments").Replace(&Comment{Content: "Comment 4"}, &Comment{Content: "Comment 5"}) - - var comments41 []Comment - DB.Model(&post).Related(&comments41) - if !compareComments(comments41, []string{"Comment 4", "Comment 5"}) { - t.Errorf("Replace has many relations") - } - - // Clear - DB.Model(&Post{Id: 999}).Association("Comments").Clear() - - var comments5 []Comment - DB.Model(&post).Related(&comments5) - if len(comments5) == 0 { - t.Errorf("Clear should not clear all comments") - } - - DB.Model(&post).Association("Comments").Clear() - - var comments51 []Comment - DB.Model(&post).Related(&comments51) - if len(comments51) != 0 { - t.Errorf("Clear has many relations") - } - - // Check Association mode with soft delete - var comment6 = Comment{ - Content: "comment 6", - } - DB.Model(&post).Association("Comments").Append(&comment6) - - if count := DB.Model(&post).Association("Comments").Count(); count != 1 { - t.Errorf("post's comments count should be 1 after Append, but got %v", count) - } - - DB.Delete(&comment6) - - if count := DB.Model(&post).Association("Comments").Count(); count != 0 { - t.Errorf("post's comments count should be 0 after comment been deleted, but got %v", count) - } - - var comments6 []Comment - if DB.Model(&post).Association("Comments").Find(&comments6); len(comments6) != 0 { - t.Errorf("post's comments count should be 0 when find with Find, but got %v", len(comments6)) - } - - if count := DB.Unscoped().Model(&post).Association("Comments").Count(); count != 1 { - t.Errorf("post's comments count should be 1 when query with Unscoped, but got %v", count) - } - - var comments61 []Comment - if DB.Unscoped().Model(&post).Association("Comments").Find(&comments61); len(comments61) != 1 { - t.Errorf("post's comments count should be 1 when query with Unscoped, but got %v", len(comments61)) - } -} - -func TestHasManyOverrideForeignKey1(t *testing.T) { - type Profile struct { - gorm.Model - Name string - UserRefer uint - } - - type User struct { - gorm.Model - Profile []Profile `gorm:"ForeignKey:UserRefer"` - } - - if relation, ok := DB.NewScope(&User{}).FieldByName("Profile"); ok { - if relation.Relationship.Kind != "has_many" || - !reflect.DeepEqual(relation.Relationship.ForeignFieldNames, []string{"UserRefer"}) || - !reflect.DeepEqual(relation.Relationship.AssociationForeignFieldNames, []string{"ID"}) { - t.Errorf("Override belongs to foreign key with tag") - } - } -} - -func TestHasManyOverrideForeignKey2(t *testing.T) { - type Profile struct { - gorm.Model - Name string - UserID uint - } - - type User struct { - gorm.Model - Refer string - Profile []Profile `gorm:"ForeignKey:UserID;AssociationForeignKey:Refer"` - } - - if relation, ok := DB.NewScope(&User{}).FieldByName("Profile"); ok { - if relation.Relationship.Kind != "has_many" || - !reflect.DeepEqual(relation.Relationship.ForeignFieldNames, []string{"UserID"}) || - !reflect.DeepEqual(relation.Relationship.AssociationForeignFieldNames, []string{"Refer"}) { - t.Errorf("Override belongs to foreign key with tag") - } - } -} - -func TestManyToMany(t *testing.T) { - DB.Raw("delete from languages") - var languages = []Language{{Name: "ZH"}, {Name: "EN"}} - user := User{Name: "Many2Many", Languages: languages} - DB.Save(&user) - - // Query - var newLanguages []Language - DB.Model(&user).Related(&newLanguages, "Languages") - if len(newLanguages) != len([]string{"ZH", "EN"}) { - t.Errorf("Query many to many relations") - } - - DB.Model(&user).Association("Languages").Find(&newLanguages) - if len(newLanguages) != len([]string{"ZH", "EN"}) { - t.Errorf("Should be able to find many to many relations") - } - - if DB.Model(&user).Association("Languages").Count() != len([]string{"ZH", "EN"}) { - t.Errorf("Count should return correct result") - } - - // Append - DB.Model(&user).Association("Languages").Append(&Language{Name: "DE"}) - if DB.Where("name = ?", "DE").First(&Language{}).RecordNotFound() { - t.Errorf("New record should be saved when append") - } - - languageA := Language{Name: "AA"} - DB.Save(&languageA) - DB.Model(&User{Id: user.Id}).Association("Languages").Append(&languageA) - - languageC := Language{Name: "CC"} - DB.Save(&languageC) - DB.Model(&user).Association("Languages").Append(&[]Language{{Name: "BB"}, languageC}) - - DB.Model(&User{Id: user.Id}).Association("Languages").Append(&[]Language{{Name: "DD"}, {Name: "EE"}}) - - totalLanguages := []string{"ZH", "EN", "DE", "AA", "BB", "CC", "DD", "EE"} - - if DB.Model(&user).Association("Languages").Count() != len(totalLanguages) { - t.Errorf("All appended languages should be saved") - } - - // Delete - user.Languages = []Language{} - DB.Model(&user).Association("Languages").Find(&user.Languages) - - var language Language - DB.Where("name = ?", "EE").First(&language) - DB.Model(&user).Association("Languages").Delete(language, &language) - - if DB.Model(&user).Association("Languages").Count() != len(totalLanguages)-1 || len(user.Languages) != len(totalLanguages)-1 { - t.Errorf("Relations should be deleted with Delete") - } - if DB.Where("name = ?", "EE").First(&Language{}).RecordNotFound() { - t.Errorf("Language EE should not be deleted") - } - - DB.Where("name IN (?)", []string{"CC", "DD"}).Find(&languages) - - user2 := User{Name: "Many2Many_User2", Languages: languages} - DB.Save(&user2) - - DB.Model(&user).Association("Languages").Delete(languages, &languages) - if DB.Model(&user).Association("Languages").Count() != len(totalLanguages)-3 || len(user.Languages) != len(totalLanguages)-3 { - t.Errorf("Relations should be deleted with Delete") - } - - if DB.Model(&user2).Association("Languages").Count() == 0 { - t.Errorf("Other user's relations should not be deleted") - } - - // Replace - var languageB Language - DB.Where("name = ?", "BB").First(&languageB) - DB.Model(&user).Association("Languages").Replace(languageB) - if len(user.Languages) != 1 || DB.Model(&user).Association("Languages").Count() != 1 { - t.Errorf("Relations should be replaced") - } - - DB.Model(&user).Association("Languages").Replace() - if len(user.Languages) != 0 || DB.Model(&user).Association("Languages").Count() != 0 { - t.Errorf("Relations should be replaced with empty") - } - - DB.Model(&user).Association("Languages").Replace(&[]Language{{Name: "FF"}, {Name: "JJ"}}) - if len(user.Languages) != 2 || DB.Model(&user).Association("Languages").Count() != len([]string{"FF", "JJ"}) { - t.Errorf("Relations should be replaced") - } - - // Clear - DB.Model(&user).Association("Languages").Clear() - if len(user.Languages) != 0 || DB.Model(&user).Association("Languages").Count() != 0 { - t.Errorf("Relations should be cleared") - } - - // Check Association mode with soft delete - var language6 = Language{ - Name: "language 6", - } - DB.Model(&user).Association("Languages").Append(&language6) - - if count := DB.Model(&user).Association("Languages").Count(); count != 1 { - t.Errorf("user's languages count should be 1 after Append, but got %v", count) - } - - DB.Delete(&language6) - - if count := DB.Model(&user).Association("Languages").Count(); count != 0 { - t.Errorf("user's languages count should be 0 after language been deleted, but got %v", count) - } - - var languages6 []Language - if DB.Model(&user).Association("Languages").Find(&languages6); len(languages6) != 0 { - t.Errorf("user's languages count should be 0 when find with Find, but got %v", len(languages6)) - } - - if count := DB.Unscoped().Model(&user).Association("Languages").Count(); count != 1 { - t.Errorf("user's languages count should be 1 when query with Unscoped, but got %v", count) - } - - var languages61 []Language - if DB.Unscoped().Model(&user).Association("Languages").Find(&languages61); len(languages61) != 1 { - t.Errorf("user's languages count should be 1 when query with Unscoped, but got %v", len(languages61)) - } -} - -func TestRelated(t *testing.T) { - user := User{ - Name: "jinzhu", - BillingAddress: Address{Address1: "Billing Address - Address 1"}, - ShippingAddress: Address{Address1: "Shipping Address - Address 1"}, - Emails: []Email{{Email: "jinzhu@example.com"}, {Email: "jinzhu-2@example@example.com"}}, - CreditCard: CreditCard{Number: "1234567890"}, - Company: Company{Name: "company1"}, - } - - if err := DB.Save(&user).Error; err != nil { - t.Errorf("No error should happen when saving user") - } - - if user.CreditCard.ID == 0 { - t.Errorf("After user save, credit card should have id") - } - - if user.BillingAddress.ID == 0 { - t.Errorf("After user save, billing address should have id") - } - - if user.Emails[0].Id == 0 { - t.Errorf("After user save, billing address should have id") - } - - var emails []Email - DB.Model(&user).Related(&emails) - if len(emails) != 2 { - t.Errorf("Should have two emails") - } - - var emails2 []Email - DB.Model(&user).Where("email = ?", "jinzhu@example.com").Related(&emails2) - if len(emails2) != 1 { - t.Errorf("Should have two emails") - } - - var emails3 []*Email - DB.Model(&user).Related(&emails3) - if len(emails3) != 2 { - t.Errorf("Should have two emails") - } - - var user1 User - DB.Model(&user).Related(&user1.Emails) - if len(user1.Emails) != 2 { - t.Errorf("Should have only one email match related condition") - } - - var address1 Address - DB.Model(&user).Related(&address1, "BillingAddressId") - if address1.Address1 != "Billing Address - Address 1" { - t.Errorf("Should get billing address from user correctly") - } - - user1 = User{} - DB.Model(&address1).Related(&user1, "BillingAddressId") - if DB.NewRecord(user1) { - t.Errorf("Should get user from address correctly") - } - - var user2 User - DB.Model(&emails[0]).Related(&user2) - if user2.Id != user.Id || user2.Name != user.Name { - t.Errorf("Should get user from email correctly") - } - - var creditcard CreditCard - var user3 User - DB.First(&creditcard, "number = ?", "1234567890") - DB.Model(&creditcard).Related(&user3) - if user3.Id != user.Id || user3.Name != user.Name { - t.Errorf("Should get user from credit card correctly") - } - - if !DB.Model(&CreditCard{}).Related(&User{}).RecordNotFound() { - t.Errorf("RecordNotFound for Related") - } - - var company Company - if DB.Model(&user).Related(&company, "Company").RecordNotFound() || company.Name != "company1" { - t.Errorf("RecordNotFound for Related") - } -} - -func TestForeignKey(t *testing.T) { - for _, structField := range DB.NewScope(&User{}).GetStructFields() { - for _, foreignKey := range []string{"BillingAddressID", "ShippingAddressId", "CompanyID"} { - if structField.Name == foreignKey && !structField.IsForeignKey { - t.Errorf(fmt.Sprintf("%v should be foreign key", foreignKey)) - } - } - } - - for _, structField := range DB.NewScope(&Email{}).GetStructFields() { - for _, foreignKey := range []string{"UserId"} { - if structField.Name == foreignKey && !structField.IsForeignKey { - t.Errorf(fmt.Sprintf("%v should be foreign key", foreignKey)) - } - } - } - - for _, structField := range DB.NewScope(&Post{}).GetStructFields() { - for _, foreignKey := range []string{"CategoryId", "MainCategoryId"} { - if structField.Name == foreignKey && !structField.IsForeignKey { - t.Errorf(fmt.Sprintf("%v should be foreign key", foreignKey)) - } - } - } - - for _, structField := range DB.NewScope(&Comment{}).GetStructFields() { - for _, foreignKey := range []string{"PostId"} { - if structField.Name == foreignKey && !structField.IsForeignKey { - t.Errorf(fmt.Sprintf("%v should be foreign key", foreignKey)) - } - } - } -} - -func testForeignKey(t *testing.T, source interface{}, sourceFieldName string, target interface{}, targetFieldName string) { - if dialect := os.Getenv("GORM_DIALECT"); dialect == "" || dialect == "sqlite" { - // sqlite does not support ADD CONSTRAINT in ALTER TABLE - return - } - targetScope := DB.NewScope(target) - targetTableName := targetScope.TableName() - modelScope := DB.NewScope(source) - modelField, ok := modelScope.FieldByName(sourceFieldName) - if !ok { - t.Fatalf(fmt.Sprintf("Failed to get field by name: %v", sourceFieldName)) - } - targetField, ok := targetScope.FieldByName(targetFieldName) - if !ok { - t.Fatalf(fmt.Sprintf("Failed to get field by name: %v", targetFieldName)) - } - dest := fmt.Sprintf("%v(%v)", targetTableName, targetField.DBName) - err := DB.Model(source).AddForeignKey(modelField.DBName, dest, "CASCADE", "CASCADE").Error - if err != nil { - t.Fatalf(fmt.Sprintf("Failed to create foreign key: %v", err)) - } -} - -func TestLongForeignKey(t *testing.T) { - testForeignKey(t, &NotSoLongTableName{}, "ReallyLongThingID", &ReallyLongTableNameToTestMySQLNameLengthLimit{}, "ID") -} - -func TestLongForeignKeyWithShortDest(t *testing.T) { - testForeignKey(t, &ReallyLongThingThatReferencesShort{}, "ShortID", &Short{}, "ID") -} - -func TestHasManyChildrenWithOneStruct(t *testing.T) { - category := Category{ - Name: "main", - Categories: []Category{ - {Name: "sub1"}, - {Name: "sub2"}, - }, - } - - DB.Save(&category) -} - -func TestAutoSaveBelongsToAssociation(t *testing.T) { - type Company struct { - gorm.Model - Name string - } - - type User struct { - gorm.Model - Name string - CompanyID uint - Company Company `gorm:"association_autoupdate:false;association_autocreate:false;"` - } - - DB.Where("name = ?", "auto_save_association").Delete(&Company{}) - DB.AutoMigrate(&Company{}, &User{}) - - DB.Save(&User{Name: "jinzhu", Company: Company{Name: "auto_save_association"}}) - - if !DB.Where("name = ?", "auto_save_association").First(&Company{}).RecordNotFound() { - t.Errorf("Company auto_save_association should not have been saved when autosave is false") - } - - // if foreign key is set, this should be saved even if association isn't - company := Company{Name: "auto_save_association"} - DB.Save(&company) - - company.Name = "auto_save_association_new_name" - user := User{Name: "jinzhu", Company: company} - - DB.Save(&user) - - if !DB.Where("name = ?", "auto_save_association_new_name").First(&Company{}).RecordNotFound() { - t.Errorf("Company should not have been updated") - } - - if DB.Where("id = ? AND company_id = ?", user.ID, company.ID).First(&User{}).RecordNotFound() { - t.Errorf("User's foreign key should have been saved") - } - - user2 := User{Name: "jinzhu_2", Company: Company{Name: "auto_save_association_2"}} - DB.Set("gorm:association_autocreate", true).Save(&user2) - if DB.Where("name = ?", "auto_save_association_2").First(&Company{}).RecordNotFound() { - t.Errorf("Company auto_save_association_2 should been created when autocreate is true") - } - - user2.Company.Name = "auto_save_association_2_newname" - DB.Set("gorm:association_autoupdate", true).Save(&user2) - - if DB.Where("name = ?", "auto_save_association_2_newname").First(&Company{}).RecordNotFound() { - t.Errorf("Company should been updated") - } -} - -func TestAutoSaveHasOneAssociation(t *testing.T) { - type Company struct { - gorm.Model - UserID uint - Name string - } - - type User struct { - gorm.Model - Name string - Company Company `gorm:"association_autoupdate:false;association_autocreate:false;"` - } - - DB.Where("name = ?", "auto_save_has_one_association").Delete(&Company{}) - DB.AutoMigrate(&Company{}, &User{}) - - DB.Save(&User{Name: "jinzhu", Company: Company{Name: "auto_save_has_one_association"}}) - - if !DB.Where("name = ?", "auto_save_has_one_association").First(&Company{}).RecordNotFound() { - t.Errorf("Company auto_save_has_one_association should not have been saved when autosave is false") - } - - company := Company{Name: "auto_save_has_one_association"} - DB.Save(&company) - - company.Name = "auto_save_has_one_association_new_name" - user := User{Name: "jinzhu", Company: company} - - DB.Save(&user) - - if !DB.Where("name = ?", "auto_save_has_one_association_new_name").First(&Company{}).RecordNotFound() { - t.Errorf("Company should not have been updated") - } - - if !DB.Where("name = ? AND user_id = ?", "auto_save_has_one_association", user.ID).First(&Company{}).RecordNotFound() { - t.Errorf("Company should not have been updated") - } - - if user.Company.UserID == 0 { - t.Errorf("UserID should be assigned") - } - - company.Name = "auto_save_has_one_association_2_new_name" - DB.Set("gorm:association_autoupdate", true).Save(&user) - - if DB.Where("name = ? AND user_id = ?", "auto_save_has_one_association_new_name", user.ID).First(&Company{}).RecordNotFound() { - t.Errorf("Company should been updated") - } - - user2 := User{Name: "jinzhu_2", Company: Company{Name: "auto_save_has_one_association_2"}} - DB.Set("gorm:association_autocreate", true).Save(&user2) - if DB.Where("name = ?", "auto_save_has_one_association_2").First(&Company{}).RecordNotFound() { - t.Errorf("Company auto_save_has_one_association_2 should been created when autocreate is true") - } -} - -func TestAutoSaveMany2ManyAssociation(t *testing.T) { - type Company struct { - gorm.Model - Name string - } - - type User struct { - gorm.Model - Name string - Companies []Company `gorm:"many2many:user_companies;association_autoupdate:false;association_autocreate:false;"` - } - - DB.AutoMigrate(&Company{}, &User{}) - - DB.Save(&User{Name: "jinzhu", Companies: []Company{{Name: "auto_save_m2m_association"}}}) - - if !DB.Where("name = ?", "auto_save_m2m_association").First(&Company{}).RecordNotFound() { - t.Errorf("Company auto_save_m2m_association should not have been saved when autosave is false") - } - - company := Company{Name: "auto_save_m2m_association"} - DB.Save(&company) - - company.Name = "auto_save_m2m_association_new_name" - user := User{Name: "jinzhu", Companies: []Company{company, {Name: "auto_save_m2m_association_new_name_2"}}} - - DB.Save(&user) - - if !DB.Where("name = ?", "auto_save_m2m_association_new_name").First(&Company{}).RecordNotFound() { - t.Errorf("Company should not have been updated") - } - - if !DB.Where("name = ?", "auto_save_m2m_association_new_name_2").First(&Company{}).RecordNotFound() { - t.Errorf("Company should not been created") - } - - if DB.Model(&user).Association("Companies").Count() != 1 { - t.Errorf("Relationship should been saved") - } - - DB.Set("gorm:association_autoupdate", true).Set("gorm:association_autocreate", true).Save(&user) - - if DB.Where("name = ?", "auto_save_m2m_association_new_name").First(&Company{}).RecordNotFound() { - t.Errorf("Company should been updated") - } - - if DB.Where("name = ?", "auto_save_m2m_association_new_name_2").First(&Company{}).RecordNotFound() { - t.Errorf("Company should been created") - } - - if DB.Model(&user).Association("Companies").Count() != 2 { - t.Errorf("Relationship should been updated") - } -} diff --git a/vendor/github.com/jinzhu/gorm/callback_system_test.go b/vendor/github.com/jinzhu/gorm/callback_system_test.go deleted file mode 100644 index 13ca3f42..00000000 --- a/vendor/github.com/jinzhu/gorm/callback_system_test.go +++ /dev/null @@ -1,112 +0,0 @@ -package gorm - -import ( - "reflect" - "runtime" - "strings" - "testing" -) - -func equalFuncs(funcs []*func(s *Scope), fnames []string) bool { - var names []string - for _, f := range funcs { - fnames := strings.Split(runtime.FuncForPC(reflect.ValueOf(*f).Pointer()).Name(), ".") - names = append(names, fnames[len(fnames)-1]) - } - return reflect.DeepEqual(names, fnames) -} - -func create(s *Scope) {} -func beforeCreate1(s *Scope) {} -func beforeCreate2(s *Scope) {} -func afterCreate1(s *Scope) {} -func afterCreate2(s *Scope) {} - -func TestRegisterCallback(t *testing.T) { - var callback = &Callback{} - - callback.Create().Register("before_create1", beforeCreate1) - callback.Create().Register("before_create2", beforeCreate2) - callback.Create().Register("create", create) - callback.Create().Register("after_create1", afterCreate1) - callback.Create().Register("after_create2", afterCreate2) - - if !equalFuncs(callback.creates, []string{"beforeCreate1", "beforeCreate2", "create", "afterCreate1", "afterCreate2"}) { - t.Errorf("register callback") - } -} - -func TestRegisterCallbackWithOrder(t *testing.T) { - var callback1 = &Callback{} - callback1.Create().Register("before_create1", beforeCreate1) - callback1.Create().Register("create", create) - callback1.Create().Register("after_create1", afterCreate1) - callback1.Create().Before("after_create1").Register("after_create2", afterCreate2) - if !equalFuncs(callback1.creates, []string{"beforeCreate1", "create", "afterCreate2", "afterCreate1"}) { - t.Errorf("register callback with order") - } - - var callback2 = &Callback{} - - callback2.Update().Register("create", create) - callback2.Update().Before("create").Register("before_create1", beforeCreate1) - callback2.Update().After("after_create2").Register("after_create1", afterCreate1) - callback2.Update().Before("before_create1").Register("before_create2", beforeCreate2) - callback2.Update().Register("after_create2", afterCreate2) - - if !equalFuncs(callback2.updates, []string{"beforeCreate2", "beforeCreate1", "create", "afterCreate2", "afterCreate1"}) { - t.Errorf("register callback with order") - } -} - -func TestRegisterCallbackWithComplexOrder(t *testing.T) { - var callback1 = &Callback{} - - callback1.Query().Before("after_create1").After("before_create1").Register("create", create) - callback1.Query().Register("before_create1", beforeCreate1) - callback1.Query().Register("after_create1", afterCreate1) - - if !equalFuncs(callback1.queries, []string{"beforeCreate1", "create", "afterCreate1"}) { - t.Errorf("register callback with order") - } - - var callback2 = &Callback{} - - callback2.Delete().Before("after_create1").After("before_create1").Register("create", create) - callback2.Delete().Before("create").Register("before_create1", beforeCreate1) - callback2.Delete().After("before_create1").Register("before_create2", beforeCreate2) - callback2.Delete().Register("after_create1", afterCreate1) - callback2.Delete().After("after_create1").Register("after_create2", afterCreate2) - - if !equalFuncs(callback2.deletes, []string{"beforeCreate1", "beforeCreate2", "create", "afterCreate1", "afterCreate2"}) { - t.Errorf("register callback with order") - } -} - -func replaceCreate(s *Scope) {} - -func TestReplaceCallback(t *testing.T) { - var callback = &Callback{} - - callback.Create().Before("after_create1").After("before_create1").Register("create", create) - callback.Create().Register("before_create1", beforeCreate1) - callback.Create().Register("after_create1", afterCreate1) - callback.Create().Replace("create", replaceCreate) - - if !equalFuncs(callback.creates, []string{"beforeCreate1", "replaceCreate", "afterCreate1"}) { - t.Errorf("replace callback") - } -} - -func TestRemoveCallback(t *testing.T) { - var callback = &Callback{} - - callback.Create().Before("after_create1").After("before_create1").Register("create", create) - callback.Create().Register("before_create1", beforeCreate1) - callback.Create().Register("after_create1", afterCreate1) - callback.Create().Remove("create") - - if !equalFuncs(callback.creates, []string{"beforeCreate1", "afterCreate1"}) { - t.Errorf("remove callback") - } -} diff --git a/vendor/github.com/jinzhu/gorm/callbacks_test.go b/vendor/github.com/jinzhu/gorm/callbacks_test.go deleted file mode 100644 index a58913d7..00000000 --- a/vendor/github.com/jinzhu/gorm/callbacks_test.go +++ /dev/null @@ -1,177 +0,0 @@ -package gorm_test - -import ( - "errors" - - "github.com/jinzhu/gorm" - - "reflect" - "testing" -) - -func (s *Product) BeforeCreate() (err error) { - if s.Code == "Invalid" { - err = errors.New("invalid product") - } - s.BeforeCreateCallTimes = s.BeforeCreateCallTimes + 1 - return -} - -func (s *Product) BeforeUpdate() (err error) { - if s.Code == "dont_update" { - err = errors.New("can't update") - } - s.BeforeUpdateCallTimes = s.BeforeUpdateCallTimes + 1 - return -} - -func (s *Product) BeforeSave() (err error) { - if s.Code == "dont_save" { - err = errors.New("can't save") - } - s.BeforeSaveCallTimes = s.BeforeSaveCallTimes + 1 - return -} - -func (s *Product) AfterFind() { - s.AfterFindCallTimes = s.AfterFindCallTimes + 1 -} - -func (s *Product) AfterCreate(tx *gorm.DB) { - tx.Model(s).UpdateColumn(Product{AfterCreateCallTimes: s.AfterCreateCallTimes + 1}) -} - -func (s *Product) AfterUpdate() { - s.AfterUpdateCallTimes = s.AfterUpdateCallTimes + 1 -} - -func (s *Product) AfterSave() (err error) { - if s.Code == "after_save_error" { - err = errors.New("can't save") - } - s.AfterSaveCallTimes = s.AfterSaveCallTimes + 1 - return -} - -func (s *Product) BeforeDelete() (err error) { - if s.Code == "dont_delete" { - err = errors.New("can't delete") - } - s.BeforeDeleteCallTimes = s.BeforeDeleteCallTimes + 1 - return -} - -func (s *Product) AfterDelete() (err error) { - if s.Code == "after_delete_error" { - err = errors.New("can't delete") - } - s.AfterDeleteCallTimes = s.AfterDeleteCallTimes + 1 - return -} - -func (s *Product) GetCallTimes() []int64 { - return []int64{s.BeforeCreateCallTimes, s.BeforeSaveCallTimes, s.BeforeUpdateCallTimes, s.AfterCreateCallTimes, s.AfterSaveCallTimes, s.AfterUpdateCallTimes, s.BeforeDeleteCallTimes, s.AfterDeleteCallTimes, s.AfterFindCallTimes} -} - -func TestRunCallbacks(t *testing.T) { - p := Product{Code: "unique_code", Price: 100} - DB.Save(&p) - - if !reflect.DeepEqual(p.GetCallTimes(), []int64{1, 1, 0, 1, 1, 0, 0, 0, 0}) { - t.Errorf("Callbacks should be invoked successfully, %v", p.GetCallTimes()) - } - - DB.Where("Code = ?", "unique_code").First(&p) - if !reflect.DeepEqual(p.GetCallTimes(), []int64{1, 1, 0, 1, 0, 0, 0, 0, 1}) { - t.Errorf("After callbacks values are not saved, %v", p.GetCallTimes()) - } - - p.Price = 200 - DB.Save(&p) - if !reflect.DeepEqual(p.GetCallTimes(), []int64{1, 2, 1, 1, 1, 1, 0, 0, 1}) { - t.Errorf("After update callbacks should be invoked successfully, %v", p.GetCallTimes()) - } - - var products []Product - DB.Find(&products, "code = ?", "unique_code") - if products[0].AfterFindCallTimes != 2 { - t.Errorf("AfterFind callbacks should work with slice") - } - - DB.Where("Code = ?", "unique_code").First(&p) - if !reflect.DeepEqual(p.GetCallTimes(), []int64{1, 2, 1, 1, 0, 0, 0, 0, 2}) { - t.Errorf("After update callbacks values are not saved, %v", p.GetCallTimes()) - } - - DB.Delete(&p) - if !reflect.DeepEqual(p.GetCallTimes(), []int64{1, 2, 1, 1, 0, 0, 1, 1, 2}) { - t.Errorf("After delete callbacks should be invoked successfully, %v", p.GetCallTimes()) - } - - if DB.Where("Code = ?", "unique_code").First(&p).Error == nil { - t.Errorf("Can't find a deleted record") - } -} - -func TestCallbacksWithErrors(t *testing.T) { - p := Product{Code: "Invalid", Price: 100} - if DB.Save(&p).Error == nil { - t.Errorf("An error from before create callbacks happened when create with invalid value") - } - - if DB.Where("code = ?", "Invalid").First(&Product{}).Error == nil { - t.Errorf("Should not save record that have errors") - } - - if DB.Save(&Product{Code: "dont_save", Price: 100}).Error == nil { - t.Errorf("An error from after create callbacks happened when create with invalid value") - } - - p2 := Product{Code: "update_callback", Price: 100} - DB.Save(&p2) - - p2.Code = "dont_update" - if DB.Save(&p2).Error == nil { - t.Errorf("An error from before update callbacks happened when update with invalid value") - } - - if DB.Where("code = ?", "update_callback").First(&Product{}).Error != nil { - t.Errorf("Record Should not be updated due to errors happened in before update callback") - } - - if DB.Where("code = ?", "dont_update").First(&Product{}).Error == nil { - t.Errorf("Record Should not be updated due to errors happened in before update callback") - } - - p2.Code = "dont_save" - if DB.Save(&p2).Error == nil { - t.Errorf("An error from before save callbacks happened when update with invalid value") - } - - p3 := Product{Code: "dont_delete", Price: 100} - DB.Save(&p3) - if DB.Delete(&p3).Error == nil { - t.Errorf("An error from before delete callbacks happened when delete") - } - - if DB.Where("Code = ?", "dont_delete").First(&p3).Error != nil { - t.Errorf("An error from before delete callbacks happened") - } - - p4 := Product{Code: "after_save_error", Price: 100} - DB.Save(&p4) - if err := DB.First(&Product{}, "code = ?", "after_save_error").Error; err == nil { - t.Errorf("Record should be reverted if get an error in after save callback") - } - - p5 := Product{Code: "after_delete_error", Price: 100} - DB.Save(&p5) - if err := DB.First(&Product{}, "code = ?", "after_delete_error").Error; err != nil { - t.Errorf("Record should be found") - } - - DB.Delete(&p5) - if err := DB.First(&Product{}, "code = ?", "after_delete_error").Error; err != nil { - t.Errorf("Record shouldn't be deleted because of an error happened in after delete callback") - } -} diff --git a/vendor/github.com/jinzhu/gorm/create_test.go b/vendor/github.com/jinzhu/gorm/create_test.go deleted file mode 100644 index 92560643..00000000 --- a/vendor/github.com/jinzhu/gorm/create_test.go +++ /dev/null @@ -1,231 +0,0 @@ -package gorm_test - -import ( - "os" - "reflect" - "testing" - "time" - - "github.com/jinzhu/now" -) - -func TestCreate(t *testing.T) { - float := 35.03554004971999 - now := time.Now() - user := User{Name: "CreateUser", Age: 18, Birthday: &now, UserNum: Num(111), PasswordHash: []byte{'f', 'a', 'k', '4'}, Latitude: float} - - if !DB.NewRecord(user) || !DB.NewRecord(&user) { - t.Error("User should be new record before create") - } - - if count := DB.Save(&user).RowsAffected; count != 1 { - t.Error("There should be one record be affected when create record") - } - - if DB.NewRecord(user) || DB.NewRecord(&user) { - t.Error("User should not new record after save") - } - - var newUser User - if err := DB.First(&newUser, user.Id).Error; err != nil { - t.Errorf("No error should happen, but got %v", err) - } - - if !reflect.DeepEqual(newUser.PasswordHash, []byte{'f', 'a', 'k', '4'}) { - t.Errorf("User's PasswordHash should be saved ([]byte)") - } - - if newUser.Age != 18 { - t.Errorf("User's Age should be saved (int)") - } - - if newUser.UserNum != Num(111) { - t.Errorf("User's UserNum should be saved (custom type), but got %v", newUser.UserNum) - } - - if newUser.Latitude != float { - t.Errorf("Float64 should not be changed after save") - } - - if user.CreatedAt.IsZero() { - t.Errorf("Should have created_at after create") - } - - if newUser.CreatedAt.IsZero() { - t.Errorf("Should have created_at after create") - } - - DB.Model(user).Update("name", "create_user_new_name") - DB.First(&user, user.Id) - if user.CreatedAt.Format(time.RFC3339Nano) != newUser.CreatedAt.Format(time.RFC3339Nano) { - t.Errorf("CreatedAt should not be changed after update") - } -} - -func TestCreateEmptyStrut(t *testing.T) { - type EmptyStruct struct { - ID uint - } - DB.AutoMigrate(&EmptyStruct{}) - - if err := DB.Create(&EmptyStruct{}).Error; err != nil { - t.Errorf("No error should happen when creating user, but got %v", err) - } -} - -func TestCreateWithExistingTimestamp(t *testing.T) { - user := User{Name: "CreateUserExistingTimestamp"} - - timeA := now.MustParse("2016-01-01") - user.CreatedAt = timeA - user.UpdatedAt = timeA - DB.Save(&user) - - if user.CreatedAt.UTC().Format(time.RFC3339) != timeA.UTC().Format(time.RFC3339) { - t.Errorf("CreatedAt should not be changed") - } - - if user.UpdatedAt.UTC().Format(time.RFC3339) != timeA.UTC().Format(time.RFC3339) { - t.Errorf("UpdatedAt should not be changed") - } - - var newUser User - DB.First(&newUser, user.Id) - - if newUser.CreatedAt.UTC().Format(time.RFC3339) != timeA.UTC().Format(time.RFC3339) { - t.Errorf("CreatedAt should not be changed") - } - - if newUser.UpdatedAt.UTC().Format(time.RFC3339) != timeA.UTC().Format(time.RFC3339) { - t.Errorf("UpdatedAt should not be changed") - } -} - -type AutoIncrementUser struct { - User - Sequence uint `gorm:"AUTO_INCREMENT"` -} - -func TestCreateWithAutoIncrement(t *testing.T) { - if dialect := os.Getenv("GORM_DIALECT"); dialect != "postgres" { - t.Skip("Skipping this because only postgres properly support auto_increment on a non-primary_key column") - } - - DB.AutoMigrate(&AutoIncrementUser{}) - - user1 := AutoIncrementUser{} - user2 := AutoIncrementUser{} - - DB.Create(&user1) - DB.Create(&user2) - - if user2.Sequence-user1.Sequence != 1 { - t.Errorf("Auto increment should apply on Sequence") - } -} - -func TestCreateWithNoGORMPrimayKey(t *testing.T) { - if dialect := os.Getenv("GORM_DIALECT"); dialect == "mssql" { - t.Skip("Skipping this because MSSQL will return identity only if the table has an Id column") - } - - jt := JoinTable{From: 1, To: 2} - err := DB.Create(&jt).Error - if err != nil { - t.Errorf("No error should happen when create a record without a GORM primary key. But in the database this primary key exists and is the union of 2 or more fields\n But got: %s", err) - } -} - -func TestCreateWithNoStdPrimaryKeyAndDefaultValues(t *testing.T) { - animal := Animal{Name: "Ferdinand"} - if DB.Save(&animal).Error != nil { - t.Errorf("No error should happen when create a record without std primary key") - } - - if animal.Counter == 0 { - t.Errorf("No std primary key should be filled value after create") - } - - if animal.Name != "Ferdinand" { - t.Errorf("Default value should be overrided") - } - - // Test create with default value not overrided - an := Animal{From: "nerdz"} - - if DB.Save(&an).Error != nil { - t.Errorf("No error should happen when create an record without std primary key") - } - - // We must fetch the value again, to have the default fields updated - // (We can't do this in the update statements, since sql default can be expressions - // And be different from the fields' type (eg. a time.Time fields has a default value of "now()" - DB.Model(Animal{}).Where(&Animal{Counter: an.Counter}).First(&an) - - if an.Name != "galeone" { - t.Errorf("Default value should fill the field. But got %v", an.Name) - } -} - -func TestAnonymousScanner(t *testing.T) { - user := User{Name: "anonymous_scanner", Role: Role{Name: "admin"}} - DB.Save(&user) - - var user2 User - DB.First(&user2, "name = ?", "anonymous_scanner") - if user2.Role.Name != "admin" { - t.Errorf("Should be able to get anonymous scanner") - } - - if !user2.Role.IsAdmin() { - t.Errorf("Should be able to get anonymous scanner") - } -} - -func TestAnonymousField(t *testing.T) { - user := User{Name: "anonymous_field", Company: Company{Name: "company"}} - DB.Save(&user) - - var user2 User - DB.First(&user2, "name = ?", "anonymous_field") - DB.Model(&user2).Related(&user2.Company) - if user2.Company.Name != "company" { - t.Errorf("Should be able to get anonymous field") - } -} - -func TestSelectWithCreate(t *testing.T) { - user := getPreparedUser("select_user", "select_with_create") - DB.Select("Name", "BillingAddress", "CreditCard", "Company", "Emails").Create(user) - - var queryuser User - DB.Preload("BillingAddress").Preload("ShippingAddress"). - Preload("CreditCard").Preload("Emails").Preload("Company").First(&queryuser, user.Id) - - if queryuser.Name != user.Name || queryuser.Age == user.Age { - t.Errorf("Should only create users with name column") - } - - if queryuser.BillingAddressID.Int64 == 0 || queryuser.ShippingAddressId != 0 || - queryuser.CreditCard.ID == 0 || len(queryuser.Emails) == 0 { - t.Errorf("Should only create selected relationships") - } -} - -func TestOmitWithCreate(t *testing.T) { - user := getPreparedUser("omit_user", "omit_with_create") - DB.Omit("Name", "BillingAddress", "CreditCard", "Company", "Emails").Create(user) - - var queryuser User - DB.Preload("BillingAddress").Preload("ShippingAddress"). - Preload("CreditCard").Preload("Emails").Preload("Company").First(&queryuser, user.Id) - - if queryuser.Name == user.Name || queryuser.Age != user.Age { - t.Errorf("Should only create users with age column") - } - - if queryuser.BillingAddressID.Int64 != 0 || queryuser.ShippingAddressId == 0 || - queryuser.CreditCard.ID != 0 || len(queryuser.Emails) != 0 { - t.Errorf("Should not create omitted relationships") - } -} diff --git a/vendor/github.com/jinzhu/gorm/customize_column_test.go b/vendor/github.com/jinzhu/gorm/customize_column_test.go deleted file mode 100644 index 5e19d6f4..00000000 --- a/vendor/github.com/jinzhu/gorm/customize_column_test.go +++ /dev/null @@ -1,346 +0,0 @@ -package gorm_test - -import ( - "testing" - "time" - - "github.com/jinzhu/gorm" -) - -type CustomizeColumn struct { - ID int64 `gorm:"column:mapped_id; primary_key:yes"` - Name string `gorm:"column:mapped_name"` - Date *time.Time `gorm:"column:mapped_time"` -} - -// Make sure an ignored field does not interfere with another field's custom -// column name that matches the ignored field. -type CustomColumnAndIgnoredFieldClash struct { - Body string `sql:"-"` - RawBody string `gorm:"column:body"` -} - -func TestCustomizeColumn(t *testing.T) { - col := "mapped_name" - DB.DropTable(&CustomizeColumn{}) - DB.AutoMigrate(&CustomizeColumn{}) - - scope := DB.NewScope(&CustomizeColumn{}) - if !scope.Dialect().HasColumn(scope.TableName(), col) { - t.Errorf("CustomizeColumn should have column %s", col) - } - - col = "mapped_id" - if scope.PrimaryKey() != col { - t.Errorf("CustomizeColumn should have primary key %s, but got %q", col, scope.PrimaryKey()) - } - - expected := "foo" - now := time.Now() - cc := CustomizeColumn{ID: 666, Name: expected, Date: &now} - - if count := DB.Create(&cc).RowsAffected; count != 1 { - t.Error("There should be one record be affected when create record") - } - - var cc1 CustomizeColumn - DB.First(&cc1, 666) - - if cc1.Name != expected { - t.Errorf("Failed to query CustomizeColumn") - } - - cc.Name = "bar" - DB.Save(&cc) - - var cc2 CustomizeColumn - DB.First(&cc2, 666) - if cc2.Name != "bar" { - t.Errorf("Failed to query CustomizeColumn") - } -} - -func TestCustomColumnAndIgnoredFieldClash(t *testing.T) { - DB.DropTable(&CustomColumnAndIgnoredFieldClash{}) - if err := DB.AutoMigrate(&CustomColumnAndIgnoredFieldClash{}).Error; err != nil { - t.Errorf("Should not raise error: %s", err) - } -} - -type CustomizePerson struct { - IdPerson string `gorm:"column:idPerson;primary_key:true"` - Accounts []CustomizeAccount `gorm:"many2many:PersonAccount;associationforeignkey:idAccount;foreignkey:idPerson"` -} - -type CustomizeAccount struct { - IdAccount string `gorm:"column:idAccount;primary_key:true"` - Name string -} - -func TestManyToManyWithCustomizedColumn(t *testing.T) { - DB.DropTable(&CustomizePerson{}, &CustomizeAccount{}, "PersonAccount") - DB.AutoMigrate(&CustomizePerson{}, &CustomizeAccount{}) - - account := CustomizeAccount{IdAccount: "account", Name: "id1"} - person := CustomizePerson{ - IdPerson: "person", - Accounts: []CustomizeAccount{account}, - } - - if err := DB.Create(&account).Error; err != nil { - t.Errorf("no error should happen, but got %v", err) - } - - if err := DB.Create(&person).Error; err != nil { - t.Errorf("no error should happen, but got %v", err) - } - - var person1 CustomizePerson - scope := DB.NewScope(nil) - if err := DB.Preload("Accounts").First(&person1, scope.Quote("idPerson")+" = ?", person.IdPerson).Error; err != nil { - t.Errorf("no error should happen when preloading customized column many2many relations, but got %v", err) - } - - if len(person1.Accounts) != 1 || person1.Accounts[0].IdAccount != "account" { - t.Errorf("should preload correct accounts") - } -} - -type CustomizeUser struct { - gorm.Model - Email string `sql:"column:email_address"` -} - -type CustomizeInvitation struct { - gorm.Model - Address string `sql:"column:invitation"` - Person *CustomizeUser `gorm:"foreignkey:Email;associationforeignkey:invitation"` -} - -func TestOneToOneWithCustomizedColumn(t *testing.T) { - DB.DropTable(&CustomizeUser{}, &CustomizeInvitation{}) - DB.AutoMigrate(&CustomizeUser{}, &CustomizeInvitation{}) - - user := CustomizeUser{ - Email: "hello@example.com", - } - invitation := CustomizeInvitation{ - Address: "hello@example.com", - } - - DB.Create(&user) - DB.Create(&invitation) - - var invitation2 CustomizeInvitation - if err := DB.Preload("Person").Find(&invitation2, invitation.ID).Error; err != nil { - t.Errorf("no error should happen, but got %v", err) - } - - if invitation2.Person.Email != user.Email { - t.Errorf("Should preload one to one relation with customize foreign keys") - } -} - -type PromotionDiscount struct { - gorm.Model - Name string - Coupons []*PromotionCoupon `gorm:"ForeignKey:discount_id"` - Rule *PromotionRule `gorm:"ForeignKey:discount_id"` - Benefits []PromotionBenefit `gorm:"ForeignKey:promotion_id"` -} - -type PromotionBenefit struct { - gorm.Model - Name string - PromotionID uint - Discount PromotionDiscount `gorm:"ForeignKey:promotion_id"` -} - -type PromotionCoupon struct { - gorm.Model - Code string - DiscountID uint - Discount PromotionDiscount -} - -type PromotionRule struct { - gorm.Model - Name string - Begin *time.Time - End *time.Time - DiscountID uint - Discount *PromotionDiscount -} - -func TestOneToManyWithCustomizedColumn(t *testing.T) { - DB.DropTable(&PromotionDiscount{}, &PromotionCoupon{}) - DB.AutoMigrate(&PromotionDiscount{}, &PromotionCoupon{}) - - discount := PromotionDiscount{ - Name: "Happy New Year", - Coupons: []*PromotionCoupon{ - {Code: "newyear1"}, - {Code: "newyear2"}, - }, - } - - if err := DB.Create(&discount).Error; err != nil { - t.Errorf("no error should happen but got %v", err) - } - - var discount1 PromotionDiscount - if err := DB.Preload("Coupons").First(&discount1, "id = ?", discount.ID).Error; err != nil { - t.Errorf("no error should happen but got %v", err) - } - - if len(discount.Coupons) != 2 { - t.Errorf("should find two coupons") - } - - var coupon PromotionCoupon - if err := DB.Preload("Discount").First(&coupon, "code = ?", "newyear1").Error; err != nil { - t.Errorf("no error should happen but got %v", err) - } - - if coupon.Discount.Name != "Happy New Year" { - t.Errorf("should preload discount from coupon") - } -} - -func TestHasOneWithPartialCustomizedColumn(t *testing.T) { - DB.DropTable(&PromotionDiscount{}, &PromotionRule{}) - DB.AutoMigrate(&PromotionDiscount{}, &PromotionRule{}) - - var begin = time.Now() - var end = time.Now().Add(24 * time.Hour) - discount := PromotionDiscount{ - Name: "Happy New Year 2", - Rule: &PromotionRule{ - Name: "time_limited", - Begin: &begin, - End: &end, - }, - } - - if err := DB.Create(&discount).Error; err != nil { - t.Errorf("no error should happen but got %v", err) - } - - var discount1 PromotionDiscount - if err := DB.Preload("Rule").First(&discount1, "id = ?", discount.ID).Error; err != nil { - t.Errorf("no error should happen but got %v", err) - } - - if discount.Rule.Begin.Format(time.RFC3339Nano) != begin.Format(time.RFC3339Nano) { - t.Errorf("Should be able to preload Rule") - } - - var rule PromotionRule - if err := DB.Preload("Discount").First(&rule, "name = ?", "time_limited").Error; err != nil { - t.Errorf("no error should happen but got %v", err) - } - - if rule.Discount.Name != "Happy New Year 2" { - t.Errorf("should preload discount from rule") - } -} - -func TestBelongsToWithPartialCustomizedColumn(t *testing.T) { - DB.DropTable(&PromotionDiscount{}, &PromotionBenefit{}) - DB.AutoMigrate(&PromotionDiscount{}, &PromotionBenefit{}) - - discount := PromotionDiscount{ - Name: "Happy New Year 3", - Benefits: []PromotionBenefit{ - {Name: "free cod"}, - {Name: "free shipping"}, - }, - } - - if err := DB.Create(&discount).Error; err != nil { - t.Errorf("no error should happen but got %v", err) - } - - var discount1 PromotionDiscount - if err := DB.Preload("Benefits").First(&discount1, "id = ?", discount.ID).Error; err != nil { - t.Errorf("no error should happen but got %v", err) - } - - if len(discount.Benefits) != 2 { - t.Errorf("should find two benefits") - } - - var benefit PromotionBenefit - if err := DB.Preload("Discount").First(&benefit, "name = ?", "free cod").Error; err != nil { - t.Errorf("no error should happen but got %v", err) - } - - if benefit.Discount.Name != "Happy New Year 3" { - t.Errorf("should preload discount from coupon") - } -} - -type SelfReferencingUser struct { - gorm.Model - Name string - Friends []*SelfReferencingUser `gorm:"many2many:UserFriends;association_jointable_foreignkey:friend_id"` -} - -func TestSelfReferencingMany2ManyColumn(t *testing.T) { - DB.DropTable(&SelfReferencingUser{}, "UserFriends") - DB.AutoMigrate(&SelfReferencingUser{}) - - friend1 := SelfReferencingUser{Name: "friend1_m2m"} - if err := DB.Create(&friend1).Error; err != nil { - t.Errorf("no error should happen, but got %v", err) - } - - friend2 := SelfReferencingUser{Name: "friend2_m2m"} - if err := DB.Create(&friend2).Error; err != nil { - t.Errorf("no error should happen, but got %v", err) - } - - user := SelfReferencingUser{ - Name: "self_m2m", - Friends: []*SelfReferencingUser{&friend1, &friend2}, - } - - if err := DB.Create(&user).Error; err != nil { - t.Errorf("no error should happen, but got %v", err) - } - - if DB.Model(&user).Association("Friends").Count() != 2 { - t.Errorf("Should find created friends correctly") - } - - var newUser = SelfReferencingUser{} - - if err := DB.Preload("Friends").First(&newUser, "id = ?", user.ID).Error; err != nil { - t.Errorf("no error should happen, but got %v", err) - } - - if len(newUser.Friends) != 2 { - t.Errorf("Should preload created frineds for self reference m2m") - } - - DB.Model(&newUser).Association("Friends").Append(&SelfReferencingUser{Name: "friend3_m2m"}) - if DB.Model(&user).Association("Friends").Count() != 3 { - t.Errorf("Should find created friends correctly") - } - - DB.Model(&newUser).Association("Friends").Replace(&SelfReferencingUser{Name: "friend4_m2m"}) - if DB.Model(&user).Association("Friends").Count() != 1 { - t.Errorf("Should find created friends correctly") - } - - friend := SelfReferencingUser{} - DB.Model(&newUser).Association("Friends").Find(&friend) - if friend.Name != "friend4_m2m" { - t.Errorf("Should find created friends correctly") - } - - DB.Model(&newUser).Association("Friends").Delete(friend) - if DB.Model(&user).Association("Friends").Count() != 0 { - t.Errorf("All friends should be deleted") - } -} diff --git a/vendor/github.com/jinzhu/gorm/delete_test.go b/vendor/github.com/jinzhu/gorm/delete_test.go deleted file mode 100644 index 043641f7..00000000 --- a/vendor/github.com/jinzhu/gorm/delete_test.go +++ /dev/null @@ -1,91 +0,0 @@ -package gorm_test - -import ( - "testing" - "time" -) - -func TestDelete(t *testing.T) { - user1, user2 := User{Name: "delete1"}, User{Name: "delete2"} - DB.Save(&user1) - DB.Save(&user2) - - if err := DB.Delete(&user1).Error; err != nil { - t.Errorf("No error should happen when delete a record, err=%s", err) - } - - if !DB.Where("name = ?", user1.Name).First(&User{}).RecordNotFound() { - t.Errorf("User can't be found after delete") - } - - if DB.Where("name = ?", user2.Name).First(&User{}).RecordNotFound() { - t.Errorf("Other users that not deleted should be found-able") - } -} - -func TestInlineDelete(t *testing.T) { - user1, user2 := User{Name: "inline_delete1"}, User{Name: "inline_delete2"} - DB.Save(&user1) - DB.Save(&user2) - - if DB.Delete(&User{}, user1.Id).Error != nil { - t.Errorf("No error should happen when delete a record") - } else if !DB.Where("name = ?", user1.Name).First(&User{}).RecordNotFound() { - t.Errorf("User can't be found after delete") - } - - if err := DB.Delete(&User{}, "name = ?", user2.Name).Error; err != nil { - t.Errorf("No error should happen when delete a record, err=%s", err) - } else if !DB.Where("name = ?", user2.Name).First(&User{}).RecordNotFound() { - t.Errorf("User can't be found after delete") - } -} - -func TestSoftDelete(t *testing.T) { - type User struct { - Id int64 - Name string - DeletedAt *time.Time - } - DB.AutoMigrate(&User{}) - - user := User{Name: "soft_delete"} - DB.Save(&user) - DB.Delete(&user) - - if DB.First(&User{}, "name = ?", user.Name).Error == nil { - t.Errorf("Can't find a soft deleted record") - } - - if err := DB.Unscoped().First(&User{}, "name = ?", user.Name).Error; err != nil { - t.Errorf("Should be able to find soft deleted record with Unscoped, but err=%s", err) - } - - DB.Unscoped().Delete(&user) - if !DB.Unscoped().First(&User{}, "name = ?", user.Name).RecordNotFound() { - t.Errorf("Can't find permanently deleted record") - } -} - -func TestSoftDeleteWithCustomizedDeletedAtColumnName(t *testing.T) { - creditCard := CreditCard{Number: "411111111234567"} - DB.Save(&creditCard) - DB.Delete(&creditCard) - - if deletedAtField, ok := DB.NewScope(&CreditCard{}).FieldByName("DeletedAt"); !ok || deletedAtField.DBName != "deleted_time" { - t.Errorf("CreditCard's DeletedAt's column name should be `deleted_time`") - } - - if DB.First(&CreditCard{}, "number = ?", creditCard.Number).Error == nil { - t.Errorf("Can't find a soft deleted record") - } - - if err := DB.Unscoped().First(&CreditCard{}, "number = ?", creditCard.Number).Error; err != nil { - t.Errorf("Should be able to find soft deleted record with Unscoped, but err=%s", err) - } - - DB.Unscoped().Delete(&creditCard) - if !DB.Unscoped().First(&CreditCard{}, "number = ?", creditCard.Number).RecordNotFound() { - t.Errorf("Can't find permanently deleted record") - } -} diff --git a/vendor/github.com/jinzhu/gorm/docker-compose.yml b/vendor/github.com/jinzhu/gorm/docker-compose.yml deleted file mode 100644 index 79bf5fc3..00000000 --- a/vendor/github.com/jinzhu/gorm/docker-compose.yml +++ /dev/null @@ -1,30 +0,0 @@ -version: '3' - -services: - mysql: - image: 'mysql:latest' - ports: - - 9910:3306 - environment: - - MYSQL_DATABASE=gorm - - MYSQL_USER=gorm - - MYSQL_PASSWORD=gorm - - MYSQL_RANDOM_ROOT_PASSWORD="yes" - postgres: - image: 'postgres:latest' - ports: - - 9920:5432 - environment: - - POSTGRES_USER=gorm - - POSTGRES_DB=gorm - - POSTGRES_PASSWORD=gorm - mssql: - image: 'mcmoe/mssqldocker:latest' - ports: - - 9930:1433 - environment: - - ACCEPT_EULA=Y - - SA_PASSWORD=LoremIpsum86 - - MSSQL_DB=gorm - - MSSQL_USER=gorm - - MSSQL_PASSWORD=LoremIpsum86 diff --git a/vendor/github.com/jinzhu/gorm/embedded_struct_test.go b/vendor/github.com/jinzhu/gorm/embedded_struct_test.go deleted file mode 100644 index 5f8ece57..00000000 --- a/vendor/github.com/jinzhu/gorm/embedded_struct_test.go +++ /dev/null @@ -1,91 +0,0 @@ -package gorm_test - -import "testing" - -type BasePost struct { - Id int64 - Title string - URL string -} - -type Author struct { - ID string - Name string - Email string -} - -type HNPost struct { - BasePost - Author `gorm:"embedded_prefix:user_"` // Embedded struct - Upvotes int32 -} - -type EngadgetPost struct { - BasePost BasePost `gorm:"embedded"` - Author Author `gorm:"embedded;embedded_prefix:author_"` // Embedded struct - ImageUrl string -} - -func TestPrefixColumnNameForEmbeddedStruct(t *testing.T) { - dialect := DB.NewScope(&EngadgetPost{}).Dialect() - engadgetPostScope := DB.NewScope(&EngadgetPost{}) - if !dialect.HasColumn(engadgetPostScope.TableName(), "author_id") || !dialect.HasColumn(engadgetPostScope.TableName(), "author_name") || !dialect.HasColumn(engadgetPostScope.TableName(), "author_email") { - t.Errorf("should has prefix for embedded columns") - } - - if len(engadgetPostScope.PrimaryFields()) != 1 { - t.Errorf("should have only one primary field with embedded struct, but got %v", len(engadgetPostScope.PrimaryFields())) - } - - hnScope := DB.NewScope(&HNPost{}) - if !dialect.HasColumn(hnScope.TableName(), "user_id") || !dialect.HasColumn(hnScope.TableName(), "user_name") || !dialect.HasColumn(hnScope.TableName(), "user_email") { - t.Errorf("should has prefix for embedded columns") - } -} - -func TestSaveAndQueryEmbeddedStruct(t *testing.T) { - DB.Save(&HNPost{BasePost: BasePost{Title: "news"}}) - DB.Save(&HNPost{BasePost: BasePost{Title: "hn_news"}}) - var news HNPost - if err := DB.First(&news, "title = ?", "hn_news").Error; err != nil { - t.Errorf("no error should happen when query with embedded struct, but got %v", err) - } else if news.Title != "hn_news" { - t.Errorf("embedded struct's value should be scanned correctly") - } - - DB.Save(&EngadgetPost{BasePost: BasePost{Title: "engadget_news"}}) - var egNews EngadgetPost - if err := DB.First(&egNews, "title = ?", "engadget_news").Error; err != nil { - t.Errorf("no error should happen when query with embedded struct, but got %v", err) - } else if egNews.BasePost.Title != "engadget_news" { - t.Errorf("embedded struct's value should be scanned correctly") - } - - if DB.NewScope(&HNPost{}).PrimaryField() == nil { - t.Errorf("primary key with embedded struct should works") - } - - for _, field := range DB.NewScope(&HNPost{}).Fields() { - if field.Name == "BasePost" { - t.Errorf("scope Fields should not contain embedded struct") - } - } -} - -func TestEmbeddedPointerTypeStruct(t *testing.T) { - type HNPost struct { - *BasePost - Upvotes int32 - } - - DB.Create(&HNPost{BasePost: &BasePost{Title: "embedded_pointer_type"}}) - - var hnPost HNPost - if err := DB.First(&hnPost, "title = ?", "embedded_pointer_type").Error; err != nil { - t.Errorf("No error should happen when find embedded pointer type, but got %v", err) - } - - if hnPost.Title != "embedded_pointer_type" { - t.Errorf("Should find correct value for embedded pointer type") - } -} diff --git a/vendor/github.com/jinzhu/gorm/errors_test.go b/vendor/github.com/jinzhu/gorm/errors_test.go deleted file mode 100644 index 9a428dec..00000000 --- a/vendor/github.com/jinzhu/gorm/errors_test.go +++ /dev/null @@ -1,20 +0,0 @@ -package gorm_test - -import ( - "errors" - "testing" - - "github.com/jinzhu/gorm" -) - -func TestErrorsCanBeUsedOutsideGorm(t *testing.T) { - errs := []error{errors.New("First"), errors.New("Second")} - - gErrs := gorm.Errors(errs) - gErrs = gErrs.Add(errors.New("Third")) - gErrs = gErrs.Add(gErrs) - - if gErrs.Error() != "First; Second; Third" { - t.Fatalf("Gave wrong error, got %s", gErrs.Error()) - } -} diff --git a/vendor/github.com/jinzhu/gorm/field_test.go b/vendor/github.com/jinzhu/gorm/field_test.go deleted file mode 100644 index 03a3b3b7..00000000 --- a/vendor/github.com/jinzhu/gorm/field_test.go +++ /dev/null @@ -1,67 +0,0 @@ -package gorm_test - -import ( - "testing" - - "github.com/gofrs/uuid" - "github.com/jinzhu/gorm" -) - -type CalculateField struct { - gorm.Model - Name string - Children []CalculateFieldChild - Category CalculateFieldCategory - EmbeddedField -} - -type EmbeddedField struct { - EmbeddedName string `sql:"NOT NULL;DEFAULT:'hello'"` -} - -type CalculateFieldChild struct { - gorm.Model - CalculateFieldID uint - Name string -} - -type CalculateFieldCategory struct { - gorm.Model - CalculateFieldID uint - Name string -} - -func TestCalculateField(t *testing.T) { - var field CalculateField - var scope = DB.NewScope(&field) - if field, ok := scope.FieldByName("Children"); !ok || field.Relationship == nil { - t.Errorf("Should calculate fields correctly for the first time") - } - - if field, ok := scope.FieldByName("Category"); !ok || field.Relationship == nil { - t.Errorf("Should calculate fields correctly for the first time") - } - - if field, ok := scope.FieldByName("embedded_name"); !ok { - t.Errorf("should find embedded field") - } else if _, ok := field.TagSettingsGet("NOT NULL"); !ok { - t.Errorf("should find embedded field's tag settings") - } -} - -func TestFieldSet(t *testing.T) { - type TestFieldSetNullUUID struct { - NullUUID uuid.NullUUID - } - scope := DB.NewScope(&TestFieldSetNullUUID{}) - field := scope.Fields()[0] - err := field.Set(uuid.FromStringOrNil("3034d44a-da03-11e8-b366-4a00070b9f00")) - if err != nil { - t.Fatal(err) - } - if id, ok := field.Field.Addr().Interface().(*uuid.NullUUID); !ok { - t.Fatal() - } else if !id.Valid || id.UUID.String() != "3034d44a-da03-11e8-b366-4a00070b9f00" { - t.Fatal(id) - } -} diff --git a/vendor/github.com/jinzhu/gorm/join_table_test.go b/vendor/github.com/jinzhu/gorm/join_table_test.go deleted file mode 100644 index 6d5f427d..00000000 --- a/vendor/github.com/jinzhu/gorm/join_table_test.go +++ /dev/null @@ -1,117 +0,0 @@ -package gorm_test - -import ( - "fmt" - "strconv" - "testing" - "time" - - "github.com/jinzhu/gorm" -) - -type Person struct { - Id int - Name string - Addresses []*Address `gorm:"many2many:person_addresses;"` -} - -type PersonAddress struct { - gorm.JoinTableHandler - PersonID int - AddressID int - DeletedAt *time.Time - CreatedAt time.Time -} - -func (*PersonAddress) Add(handler gorm.JoinTableHandlerInterface, db *gorm.DB, foreignValue interface{}, associationValue interface{}) error { - foreignPrimaryKey, _ := strconv.Atoi(fmt.Sprint(db.NewScope(foreignValue).PrimaryKeyValue())) - associationPrimaryKey, _ := strconv.Atoi(fmt.Sprint(db.NewScope(associationValue).PrimaryKeyValue())) - if result := db.Unscoped().Model(&PersonAddress{}).Where(map[string]interface{}{ - "person_id": foreignPrimaryKey, - "address_id": associationPrimaryKey, - }).Update(map[string]interface{}{ - "person_id": foreignPrimaryKey, - "address_id": associationPrimaryKey, - "deleted_at": gorm.Expr("NULL"), - }).RowsAffected; result == 0 { - return db.Create(&PersonAddress{ - PersonID: foreignPrimaryKey, - AddressID: associationPrimaryKey, - }).Error - } - - return nil -} - -func (*PersonAddress) Delete(handler gorm.JoinTableHandlerInterface, db *gorm.DB, sources ...interface{}) error { - return db.Delete(&PersonAddress{}).Error -} - -func (pa *PersonAddress) JoinWith(handler gorm.JoinTableHandlerInterface, db *gorm.DB, source interface{}) *gorm.DB { - table := pa.Table(db) - return db.Joins("INNER JOIN person_addresses ON person_addresses.address_id = addresses.id").Where(fmt.Sprintf("%v.deleted_at IS NULL OR %v.deleted_at <= '0001-01-02'", table, table)) -} - -func TestJoinTable(t *testing.T) { - DB.Exec("drop table person_addresses;") - DB.AutoMigrate(&Person{}) - DB.SetJoinTableHandler(&Person{}, "Addresses", &PersonAddress{}) - - address1 := &Address{Address1: "address 1"} - address2 := &Address{Address1: "address 2"} - person := &Person{Name: "person", Addresses: []*Address{address1, address2}} - DB.Save(person) - - DB.Model(person).Association("Addresses").Delete(address1) - - if DB.Find(&[]PersonAddress{}, "person_id = ?", person.Id).RowsAffected != 1 { - t.Errorf("Should found one address") - } - - if DB.Model(person).Association("Addresses").Count() != 1 { - t.Errorf("Should found one address") - } - - if DB.Unscoped().Find(&[]PersonAddress{}, "person_id = ?", person.Id).RowsAffected != 2 { - t.Errorf("Found two addresses with Unscoped") - } - - if DB.Model(person).Association("Addresses").Clear(); DB.Model(person).Association("Addresses").Count() != 0 { - t.Errorf("Should deleted all addresses") - } -} - -func TestEmbeddedMany2ManyRelationship(t *testing.T) { - type EmbeddedPerson struct { - ID int - Name string - Addresses []*Address `gorm:"many2many:person_addresses;"` - } - - type NewPerson struct { - EmbeddedPerson - ExternalID uint - } - DB.Exec("drop table person_addresses;") - DB.AutoMigrate(&NewPerson{}) - - address1 := &Address{Address1: "address 1"} - address2 := &Address{Address1: "address 2"} - person := &NewPerson{ExternalID: 100, EmbeddedPerson: EmbeddedPerson{Name: "person", Addresses: []*Address{address1, address2}}} - if err := DB.Save(person).Error; err != nil { - t.Errorf("no error should return when save embedded many2many relationship, but got %v", err) - } - - if err := DB.Model(person).Association("Addresses").Delete(address1).Error; err != nil { - t.Errorf("no error should return when delete embedded many2many relationship, but got %v", err) - } - - association := DB.Model(person).Association("Addresses") - if count := association.Count(); count != 1 || association.Error != nil { - t.Errorf("Should found one address, but got %v, error is %v", count, association.Error) - } - - if association.Clear(); association.Count() != 0 { - t.Errorf("Should deleted all addresses") - } -} diff --git a/vendor/github.com/jinzhu/gorm/main_test.go b/vendor/github.com/jinzhu/gorm/main_test.go deleted file mode 100644 index 94d2fa39..00000000 --- a/vendor/github.com/jinzhu/gorm/main_test.go +++ /dev/null @@ -1,1108 +0,0 @@ -package gorm_test - -import ( - "database/sql" - "database/sql/driver" - "fmt" - "os" - "path/filepath" - "reflect" - "strconv" - "strings" - "testing" - "time" - - "github.com/erikstmartin/go-testdb" - "github.com/jinzhu/gorm" - _ "github.com/jinzhu/gorm/dialects/mssql" - _ "github.com/jinzhu/gorm/dialects/mysql" - "github.com/jinzhu/gorm/dialects/postgres" - _ "github.com/jinzhu/gorm/dialects/sqlite" - "github.com/jinzhu/now" -) - -var ( - DB *gorm.DB - t1, t2, t3, t4, t5 time.Time -) - -func init() { - var err error - - if DB, err = OpenTestConnection(); err != nil { - panic(fmt.Sprintf("No error should happen when connecting to test database, but got err=%+v", err)) - } - - runMigration() -} - -func OpenTestConnection() (db *gorm.DB, err error) { - dbDSN := os.Getenv("GORM_DSN") - switch os.Getenv("GORM_DIALECT") { - case "mysql": - fmt.Println("testing mysql...") - if dbDSN == "" { - dbDSN = "gorm:gorm@tcp(localhost:9910)/gorm?charset=utf8&parseTime=True" - } - db, err = gorm.Open("mysql", dbDSN) - case "postgres": - fmt.Println("testing postgres...") - if dbDSN == "" { - dbDSN = "user=gorm password=gorm DB.name=gorm port=9920 sslmode=disable" - } - db, err = gorm.Open("postgres", dbDSN) - case "mssql": - // CREATE LOGIN gorm WITH PASSWORD = 'LoremIpsum86'; - // CREATE DATABASE gorm; - // USE gorm; - // CREATE USER gorm FROM LOGIN gorm; - // sp_changedbowner 'gorm'; - fmt.Println("testing mssql...") - if dbDSN == "" { - dbDSN = "sqlserver://gorm:LoremIpsum86@localhost:9930?database=gorm" - } - db, err = gorm.Open("mssql", dbDSN) - default: - fmt.Println("testing sqlite3...") - db, err = gorm.Open("sqlite3", filepath.Join(os.TempDir(), "gorm.db")) - } - - // db.SetLogger(Logger{log.New(os.Stdout, "\r\n", 0)}) - // db.SetLogger(log.New(os.Stdout, "\r\n", 0)) - if debug := os.Getenv("DEBUG"); debug == "true" { - db.LogMode(true) - } else if debug == "false" { - db.LogMode(false) - } - - db.DB().SetMaxIdleConns(10) - - return -} - -func TestOpen_ReturnsError_WithBadArgs(t *testing.T) { - stringRef := "foo" - testCases := []interface{}{42, time.Now(), &stringRef} - for _, tc := range testCases { - t.Run(fmt.Sprintf("%v", tc), func(t *testing.T) { - _, err := gorm.Open("postgresql", tc) - if err == nil { - t.Error("Should got error with invalid database source") - } - if !strings.HasPrefix(err.Error(), "invalid database source:") { - t.Errorf("Should got error starting with \"invalid database source:\", but got %q", err.Error()) - } - }) - } -} - -func TestStringPrimaryKey(t *testing.T) { - type UUIDStruct struct { - ID string `gorm:"primary_key"` - Name string - } - DB.DropTable(&UUIDStruct{}) - DB.AutoMigrate(&UUIDStruct{}) - - data := UUIDStruct{ID: "uuid", Name: "hello"} - if err := DB.Save(&data).Error; err != nil || data.ID != "uuid" || data.Name != "hello" { - t.Errorf("string primary key should not be populated") - } - - data = UUIDStruct{ID: "uuid", Name: "hello world"} - if err := DB.Save(&data).Error; err != nil || data.ID != "uuid" || data.Name != "hello world" { - t.Errorf("string primary key should not be populated") - } -} - -func TestExceptionsWithInvalidSql(t *testing.T) { - var columns []string - if DB.Where("sdsd.zaaa = ?", "sd;;;aa").Pluck("aaa", &columns).Error == nil { - t.Errorf("Should got error with invalid SQL") - } - - if DB.Model(&User{}).Where("sdsd.zaaa = ?", "sd;;;aa").Pluck("aaa", &columns).Error == nil { - t.Errorf("Should got error with invalid SQL") - } - - if DB.Where("sdsd.zaaa = ?", "sd;;;aa").Find(&User{}).Error == nil { - t.Errorf("Should got error with invalid SQL") - } - - var count1, count2 int64 - DB.Model(&User{}).Count(&count1) - if count1 <= 0 { - t.Errorf("Should find some users") - } - - if DB.Where("name = ?", "jinzhu; delete * from users").First(&User{}).Error == nil { - t.Errorf("Should got error with invalid SQL") - } - - DB.Model(&User{}).Count(&count2) - if count1 != count2 { - t.Errorf("No user should not be deleted by invalid SQL") - } -} - -func TestSetTable(t *testing.T) { - DB.Create(getPreparedUser("pluck_user1", "pluck_user")) - DB.Create(getPreparedUser("pluck_user2", "pluck_user")) - DB.Create(getPreparedUser("pluck_user3", "pluck_user")) - - if err := DB.Table("users").Where("role = ?", "pluck_user").Pluck("age", &[]int{}).Error; err != nil { - t.Error("No errors should happen if set table for pluck", err) - } - - var users []User - if DB.Table("users").Find(&[]User{}).Error != nil { - t.Errorf("No errors should happen if set table for find") - } - - if DB.Table("invalid_table").Find(&users).Error == nil { - t.Errorf("Should got error when table is set to an invalid table") - } - - DB.Exec("drop table deleted_users;") - if DB.Table("deleted_users").CreateTable(&User{}).Error != nil { - t.Errorf("Create table with specified table") - } - - DB.Table("deleted_users").Save(&User{Name: "DeletedUser"}) - - var deletedUsers []User - DB.Table("deleted_users").Find(&deletedUsers) - if len(deletedUsers) != 1 { - t.Errorf("Query from specified table") - } - - DB.Save(getPreparedUser("normal_user", "reset_table")) - DB.Table("deleted_users").Save(getPreparedUser("deleted_user", "reset_table")) - var user1, user2, user3 User - DB.Where("role = ?", "reset_table").First(&user1).Table("deleted_users").First(&user2).Table("").First(&user3) - if (user1.Name != "normal_user") || (user2.Name != "deleted_user") || (user3.Name != "normal_user") { - t.Errorf("unset specified table with blank string") - } -} - -type Order struct { -} - -type Cart struct { -} - -func (c Cart) TableName() string { - return "shopping_cart" -} - -func TestHasTable(t *testing.T) { - type Foo struct { - Id int - Stuff string - } - DB.DropTable(&Foo{}) - - // Table should not exist at this point, HasTable should return false - if ok := DB.HasTable("foos"); ok { - t.Errorf("Table should not exist, but does") - } - if ok := DB.HasTable(&Foo{}); ok { - t.Errorf("Table should not exist, but does") - } - - // We create the table - if err := DB.CreateTable(&Foo{}).Error; err != nil { - t.Errorf("Table should be created") - } - - // And now it should exits, and HasTable should return true - if ok := DB.HasTable("foos"); !ok { - t.Errorf("Table should exist, but HasTable informs it does not") - } - if ok := DB.HasTable(&Foo{}); !ok { - t.Errorf("Table should exist, but HasTable informs it does not") - } -} - -func TestTableName(t *testing.T) { - DB := DB.Model("") - if DB.NewScope(Order{}).TableName() != "orders" { - t.Errorf("Order's table name should be orders") - } - - if DB.NewScope(&Order{}).TableName() != "orders" { - t.Errorf("&Order's table name should be orders") - } - - if DB.NewScope([]Order{}).TableName() != "orders" { - t.Errorf("[]Order's table name should be orders") - } - - if DB.NewScope(&[]Order{}).TableName() != "orders" { - t.Errorf("&[]Order's table name should be orders") - } - - DB.SingularTable(true) - if DB.NewScope(Order{}).TableName() != "order" { - t.Errorf("Order's singular table name should be order") - } - - if DB.NewScope(&Order{}).TableName() != "order" { - t.Errorf("&Order's singular table name should be order") - } - - if DB.NewScope([]Order{}).TableName() != "order" { - t.Errorf("[]Order's singular table name should be order") - } - - if DB.NewScope(&[]Order{}).TableName() != "order" { - t.Errorf("&[]Order's singular table name should be order") - } - - if DB.NewScope(&Cart{}).TableName() != "shopping_cart" { - t.Errorf("&Cart's singular table name should be shopping_cart") - } - - if DB.NewScope(Cart{}).TableName() != "shopping_cart" { - t.Errorf("Cart's singular table name should be shopping_cart") - } - - if DB.NewScope(&[]Cart{}).TableName() != "shopping_cart" { - t.Errorf("&[]Cart's singular table name should be shopping_cart") - } - - if DB.NewScope([]Cart{}).TableName() != "shopping_cart" { - t.Errorf("[]Cart's singular table name should be shopping_cart") - } - DB.SingularTable(false) -} - -func TestNullValues(t *testing.T) { - DB.DropTable(&NullValue{}) - DB.AutoMigrate(&NullValue{}) - - if err := DB.Save(&NullValue{ - Name: sql.NullString{String: "hello", Valid: true}, - Gender: &sql.NullString{String: "M", Valid: true}, - Age: sql.NullInt64{Int64: 18, Valid: true}, - Male: sql.NullBool{Bool: true, Valid: true}, - Height: sql.NullFloat64{Float64: 100.11, Valid: true}, - AddedAt: NullTime{Time: time.Now(), Valid: true}, - }).Error; err != nil { - t.Errorf("Not error should raise when test null value") - } - - var nv NullValue - DB.First(&nv, "name = ?", "hello") - - if nv.Name.String != "hello" || nv.Gender.String != "M" || nv.Age.Int64 != 18 || nv.Male.Bool != true || nv.Height.Float64 != 100.11 || nv.AddedAt.Valid != true { - t.Errorf("Should be able to fetch null value") - } - - if err := DB.Save(&NullValue{ - Name: sql.NullString{String: "hello-2", Valid: true}, - Gender: &sql.NullString{String: "F", Valid: true}, - Age: sql.NullInt64{Int64: 18, Valid: false}, - Male: sql.NullBool{Bool: true, Valid: true}, - Height: sql.NullFloat64{Float64: 100.11, Valid: true}, - AddedAt: NullTime{Time: time.Now(), Valid: false}, - }).Error; err != nil { - t.Errorf("Not error should raise when test null value") - } - - var nv2 NullValue - DB.First(&nv2, "name = ?", "hello-2") - if nv2.Name.String != "hello-2" || nv2.Gender.String != "F" || nv2.Age.Int64 != 0 || nv2.Male.Bool != true || nv2.Height.Float64 != 100.11 || nv2.AddedAt.Valid != false { - t.Errorf("Should be able to fetch null value") - } - - if err := DB.Save(&NullValue{ - Name: sql.NullString{String: "hello-3", Valid: false}, - Gender: &sql.NullString{String: "M", Valid: true}, - Age: sql.NullInt64{Int64: 18, Valid: false}, - Male: sql.NullBool{Bool: true, Valid: true}, - Height: sql.NullFloat64{Float64: 100.11, Valid: true}, - AddedAt: NullTime{Time: time.Now(), Valid: false}, - }).Error; err == nil { - t.Errorf("Can't save because of name can't be null") - } -} - -func TestNullValuesWithFirstOrCreate(t *testing.T) { - var nv1 = NullValue{ - Name: sql.NullString{String: "first_or_create", Valid: true}, - Gender: &sql.NullString{String: "M", Valid: true}, - } - - var nv2 NullValue - result := DB.Where(nv1).FirstOrCreate(&nv2) - - if result.RowsAffected != 1 { - t.Errorf("RowsAffected should be 1 after create some record") - } - - if result.Error != nil { - t.Errorf("Should not raise any error, but got %v", result.Error) - } - - if nv2.Name.String != "first_or_create" || nv2.Gender.String != "M" { - t.Errorf("first or create with nullvalues") - } - - if err := DB.Where(nv1).Assign(NullValue{Age: sql.NullInt64{Int64: 18, Valid: true}}).FirstOrCreate(&nv2).Error; err != nil { - t.Errorf("Should not raise any error, but got %v", err) - } - - if nv2.Age.Int64 != 18 { - t.Errorf("should update age to 18") - } -} - -func TestTransaction(t *testing.T) { - tx := DB.Begin() - u := User{Name: "transcation"} - if err := tx.Save(&u).Error; err != nil { - t.Errorf("No error should raise") - } - - if err := tx.First(&User{}, "name = ?", "transcation").Error; err != nil { - t.Errorf("Should find saved record") - } - - if sqlTx, ok := tx.CommonDB().(*sql.Tx); !ok || sqlTx == nil { - t.Errorf("Should return the underlying sql.Tx") - } - - tx.Rollback() - - if err := tx.First(&User{}, "name = ?", "transcation").Error; err == nil { - t.Errorf("Should not find record after rollback") - } - - tx2 := DB.Begin() - u2 := User{Name: "transcation-2"} - if err := tx2.Save(&u2).Error; err != nil { - t.Errorf("No error should raise") - } - - if err := tx2.First(&User{}, "name = ?", "transcation-2").Error; err != nil { - t.Errorf("Should find saved record") - } - - tx2.Commit() - - if err := DB.First(&User{}, "name = ?", "transcation-2").Error; err != nil { - t.Errorf("Should be able to find committed record") - } -} - -func TestRow(t *testing.T) { - user1 := User{Name: "RowUser1", Age: 1, Birthday: parseTime("2000-1-1")} - user2 := User{Name: "RowUser2", Age: 10, Birthday: parseTime("2010-1-1")} - user3 := User{Name: "RowUser3", Age: 20, Birthday: parseTime("2020-1-1")} - DB.Save(&user1).Save(&user2).Save(&user3) - - row := DB.Table("users").Where("name = ?", user2.Name).Select("age").Row() - var age int64 - row.Scan(&age) - if age != 10 { - t.Errorf("Scan with Row") - } -} - -func TestRows(t *testing.T) { - user1 := User{Name: "RowsUser1", Age: 1, Birthday: parseTime("2000-1-1")} - user2 := User{Name: "RowsUser2", Age: 10, Birthday: parseTime("2010-1-1")} - user3 := User{Name: "RowsUser3", Age: 20, Birthday: parseTime("2020-1-1")} - DB.Save(&user1).Save(&user2).Save(&user3) - - rows, err := DB.Table("users").Where("name = ? or name = ?", user2.Name, user3.Name).Select("name, age").Rows() - if err != nil { - t.Errorf("Not error should happen, got %v", err) - } - - count := 0 - for rows.Next() { - var name string - var age int64 - rows.Scan(&name, &age) - count++ - } - - if count != 2 { - t.Errorf("Should found two records") - } -} - -func TestScanRows(t *testing.T) { - user1 := User{Name: "ScanRowsUser1", Age: 1, Birthday: parseTime("2000-1-1")} - user2 := User{Name: "ScanRowsUser2", Age: 10, Birthday: parseTime("2010-1-1")} - user3 := User{Name: "ScanRowsUser3", Age: 20, Birthday: parseTime("2020-1-1")} - DB.Save(&user1).Save(&user2).Save(&user3) - - rows, err := DB.Table("users").Where("name = ? or name = ?", user2.Name, user3.Name).Select("name, age").Rows() - if err != nil { - t.Errorf("Not error should happen, got %v", err) - } - - type Result struct { - Name string - Age int - } - - var results []Result - for rows.Next() { - var result Result - if err := DB.ScanRows(rows, &result); err != nil { - t.Errorf("should get no error, but got %v", err) - } - results = append(results, result) - } - - if !reflect.DeepEqual(results, []Result{{Name: "ScanRowsUser2", Age: 10}, {Name: "ScanRowsUser3", Age: 20}}) { - t.Errorf("Should find expected results") - } -} - -func TestScan(t *testing.T) { - user1 := User{Name: "ScanUser1", Age: 1, Birthday: parseTime("2000-1-1")} - user2 := User{Name: "ScanUser2", Age: 10, Birthday: parseTime("2010-1-1")} - user3 := User{Name: "ScanUser3", Age: 20, Birthday: parseTime("2020-1-1")} - DB.Save(&user1).Save(&user2).Save(&user3) - - type result struct { - Name string - Age int - } - - var res result - DB.Table("users").Select("name, age").Where("name = ?", user3.Name).Scan(&res) - if res.Name != user3.Name { - t.Errorf("Scan into struct should work") - } - - var doubleAgeRes = &result{} - if err := DB.Table("users").Select("age + age as age").Where("name = ?", user3.Name).Scan(&doubleAgeRes).Error; err != nil { - t.Errorf("Scan to pointer of pointer") - } - if doubleAgeRes.Age != res.Age*2 { - t.Errorf("Scan double age as age") - } - - var ress []result - DB.Table("users").Select("name, age").Where("name in (?)", []string{user2.Name, user3.Name}).Scan(&ress) - if len(ress) != 2 || ress[0].Name != user2.Name || ress[1].Name != user3.Name { - t.Errorf("Scan into struct map") - } -} - -func TestRaw(t *testing.T) { - user1 := User{Name: "ExecRawSqlUser1", Age: 1, Birthday: parseTime("2000-1-1")} - user2 := User{Name: "ExecRawSqlUser2", Age: 10, Birthday: parseTime("2010-1-1")} - user3 := User{Name: "ExecRawSqlUser3", Age: 20, Birthday: parseTime("2020-1-1")} - DB.Save(&user1).Save(&user2).Save(&user3) - - type result struct { - Name string - Email string - } - - var ress []result - DB.Raw("SELECT name, age FROM users WHERE name = ? or name = ?", user2.Name, user3.Name).Scan(&ress) - if len(ress) != 2 || ress[0].Name != user2.Name || ress[1].Name != user3.Name { - t.Errorf("Raw with scan") - } - - rows, _ := DB.Raw("select name, age from users where name = ?", user3.Name).Rows() - count := 0 - for rows.Next() { - count++ - } - if count != 1 { - t.Errorf("Raw with Rows should find one record with name 3") - } - - DB.Exec("update users set name=? where name in (?)", "jinzhu", []string{user1.Name, user2.Name, user3.Name}) - if DB.Where("name in (?)", []string{user1.Name, user2.Name, user3.Name}).First(&User{}).Error != gorm.ErrRecordNotFound { - t.Error("Raw sql to update records") - } -} - -func TestGroup(t *testing.T) { - rows, err := DB.Select("name").Table("users").Group("name").Rows() - - if err == nil { - defer rows.Close() - for rows.Next() { - var name string - rows.Scan(&name) - } - } else { - t.Errorf("Should not raise any error") - } -} - -func TestJoins(t *testing.T) { - var user = User{ - Name: "joins", - CreditCard: CreditCard{Number: "411111111111"}, - Emails: []Email{{Email: "join1@example.com"}, {Email: "join2@example.com"}}, - } - DB.Save(&user) - - var users1 []User - DB.Joins("left join emails on emails.user_id = users.id").Where("name = ?", "joins").Find(&users1) - if len(users1) != 2 { - t.Errorf("should find two users using left join") - } - - var users2 []User - DB.Joins("left join emails on emails.user_id = users.id AND emails.email = ?", "join1@example.com").Where("name = ?", "joins").First(&users2) - if len(users2) != 1 { - t.Errorf("should find one users using left join with conditions") - } - - var users3 []User - DB.Joins("join emails on emails.user_id = users.id AND emails.email = ?", "join1@example.com").Joins("join credit_cards on credit_cards.user_id = users.id AND credit_cards.number = ?", "411111111111").Where("name = ?", "joins").First(&users3) - if len(users3) != 1 { - t.Errorf("should find one users using multiple left join conditions") - } - - var users4 []User - DB.Joins("join emails on emails.user_id = users.id AND emails.email = ?", "join1@example.com").Joins("join credit_cards on credit_cards.user_id = users.id AND credit_cards.number = ?", "422222222222").Where("name = ?", "joins").First(&users4) - if len(users4) != 0 { - t.Errorf("should find no user when searching with unexisting credit card") - } - - var users5 []User - db5 := DB.Joins("join emails on emails.user_id = users.id AND emails.email = ?", "join1@example.com").Joins("join credit_cards on credit_cards.user_id = users.id AND credit_cards.number = ?", "411111111111").Where(User{Id: 1}).Where(Email{Id: 1}).Not(Email{Id: 10}).First(&users5) - if db5.Error != nil { - t.Errorf("Should not raise error for join where identical fields in different tables. Error: %s", db5.Error.Error()) - } -} - -type JoinedIds struct { - UserID int64 `gorm:"column:id"` - BillingAddressID int64 `gorm:"column:id"` - EmailID int64 `gorm:"column:id"` -} - -func TestScanIdenticalColumnNames(t *testing.T) { - var user = User{ - Name: "joinsIds", - Email: "joinIds@example.com", - BillingAddress: Address{ - Address1: "One Park Place", - }, - Emails: []Email{{Email: "join1@example.com"}, {Email: "join2@example.com"}}, - } - DB.Save(&user) - - var users []JoinedIds - DB.Select("users.id, addresses.id, emails.id").Table("users"). - Joins("left join addresses on users.billing_address_id = addresses.id"). - Joins("left join emails on emails.user_id = users.id"). - Where("name = ?", "joinsIds").Scan(&users) - - if len(users) != 2 { - t.Fatal("should find two rows using left join") - } - - if user.Id != users[0].UserID { - t.Errorf("Expected result row to contain UserID %d, but got %d", user.Id, users[0].UserID) - } - if user.Id != users[1].UserID { - t.Errorf("Expected result row to contain UserID %d, but got %d", user.Id, users[1].UserID) - } - - if user.BillingAddressID.Int64 != users[0].BillingAddressID { - t.Errorf("Expected result row to contain BillingAddressID %d, but got %d", user.BillingAddressID.Int64, users[0].BillingAddressID) - } - if user.BillingAddressID.Int64 != users[1].BillingAddressID { - t.Errorf("Expected result row to contain BillingAddressID %d, but got %d", user.BillingAddressID.Int64, users[0].BillingAddressID) - } - - if users[0].EmailID == users[1].EmailID { - t.Errorf("Email ids should be unique. Got %d and %d", users[0].EmailID, users[1].EmailID) - } - - if int64(user.Emails[0].Id) != users[0].EmailID && int64(user.Emails[1].Id) != users[0].EmailID { - t.Errorf("Expected result row ID to be either %d or %d, but was %d", user.Emails[0].Id, user.Emails[1].Id, users[0].EmailID) - } - - if int64(user.Emails[0].Id) != users[1].EmailID && int64(user.Emails[1].Id) != users[1].EmailID { - t.Errorf("Expected result row ID to be either %d or %d, but was %d", user.Emails[0].Id, user.Emails[1].Id, users[1].EmailID) - } -} - -func TestJoinsWithSelect(t *testing.T) { - type result struct { - Name string - Email string - } - - user := User{ - Name: "joins_with_select", - Emails: []Email{{Email: "join1@example.com"}, {Email: "join2@example.com"}}, - } - DB.Save(&user) - - var results []result - DB.Table("users").Select("name, emails.email").Joins("left join emails on emails.user_id = users.id").Where("name = ?", "joins_with_select").Scan(&results) - if len(results) != 2 || results[0].Email != "join1@example.com" || results[1].Email != "join2@example.com" { - t.Errorf("Should find all two emails with Join select") - } -} - -func TestHaving(t *testing.T) { - rows, err := DB.Select("name, count(*) as total").Table("users").Group("name").Having("name IN (?)", []string{"2", "3"}).Rows() - - if err == nil { - defer rows.Close() - for rows.Next() { - var name string - var total int64 - rows.Scan(&name, &total) - - if name == "2" && total != 1 { - t.Errorf("Should have one user having name 2") - } - if name == "3" && total != 2 { - t.Errorf("Should have two users having name 3") - } - } - } else { - t.Errorf("Should not raise any error") - } -} - -func TestQueryBuilderSubselectInWhere(t *testing.T) { - user := User{Name: "query_expr_select_ruser1", Email: "root@user1.com", Age: 32} - DB.Save(&user) - user = User{Name: "query_expr_select_ruser2", Email: "nobody@user2.com", Age: 16} - DB.Save(&user) - user = User{Name: "query_expr_select_ruser3", Email: "root@user3.com", Age: 64} - DB.Save(&user) - user = User{Name: "query_expr_select_ruser4", Email: "somebody@user3.com", Age: 128} - DB.Save(&user) - - var users []User - DB.Select("*").Where("name IN (?)", DB. - Select("name").Table("users").Where("name LIKE ?", "query_expr_select%").QueryExpr()).Find(&users) - - if len(users) != 4 { - t.Errorf("Four users should be found, instead found %d", len(users)) - } - - DB.Select("*").Where("name LIKE ?", "query_expr_select%").Where("age >= (?)", DB. - Select("AVG(age)").Table("users").Where("name LIKE ?", "query_expr_select%").QueryExpr()).Find(&users) - - if len(users) != 2 { - t.Errorf("Two users should be found, instead found %d", len(users)) - } -} - -func TestQueryBuilderRawQueryWithSubquery(t *testing.T) { - user := User{Name: "subquery_test_user1", Age: 10} - DB.Save(&user) - user = User{Name: "subquery_test_user2", Age: 11} - DB.Save(&user) - user = User{Name: "subquery_test_user3", Age: 12} - DB.Save(&user) - - var count int - err := DB.Raw("select count(*) from (?) tmp", - DB.Table("users"). - Select("name"). - Where("age >= ? and name in (?)", 10, []string{"subquery_test_user1", "subquery_test_user2"}). - Group("name"). - QueryExpr(), - ).Count(&count).Error - - if err != nil { - t.Errorf("Expected to get no errors, but got %v", err) - } - if count != 2 { - t.Errorf("Row count must be 2, instead got %d", count) - } - - err = DB.Raw("select count(*) from (?) tmp", - DB.Table("users"). - Select("name"). - Where("name LIKE ?", "subquery_test%"). - Not("age <= ?", 10).Not("name in (?)", []string{"subquery_test_user1", "subquery_test_user2"}). - Group("name"). - QueryExpr(), - ).Count(&count).Error - - if err != nil { - t.Errorf("Expected to get no errors, but got %v", err) - } - if count != 1 { - t.Errorf("Row count must be 1, instead got %d", count) - } -} - -func TestQueryBuilderSubselectInHaving(t *testing.T) { - user := User{Name: "query_expr_having_ruser1", Email: "root@user1.com", Age: 64} - DB.Save(&user) - user = User{Name: "query_expr_having_ruser2", Email: "root@user2.com", Age: 128} - DB.Save(&user) - user = User{Name: "query_expr_having_ruser3", Email: "root@user1.com", Age: 64} - DB.Save(&user) - user = User{Name: "query_expr_having_ruser4", Email: "root@user2.com", Age: 128} - DB.Save(&user) - - var users []User - DB.Select("AVG(age) as avgage").Where("name LIKE ?", "query_expr_having_%").Group("email").Having("AVG(age) > (?)", DB. - Select("AVG(age)").Where("name LIKE ?", "query_expr_having_%").Table("users").QueryExpr()).Find(&users) - - if len(users) != 1 { - t.Errorf("Two user group should be found, instead found %d", len(users)) - } -} - -func DialectHasTzSupport() bool { - // NB: mssql and FoundationDB do not support time zones. - if dialect := os.Getenv("GORM_DIALECT"); dialect == "foundation" { - return false - } - return true -} - -func TestTimeWithZone(t *testing.T) { - var format = "2006-01-02 15:04:05 -0700" - var times []time.Time - GMT8, _ := time.LoadLocation("Asia/Shanghai") - times = append(times, time.Date(2013, 02, 19, 1, 51, 49, 123456789, GMT8)) - times = append(times, time.Date(2013, 02, 18, 17, 51, 49, 123456789, time.UTC)) - - for index, vtime := range times { - name := "time_with_zone_" + strconv.Itoa(index) - user := User{Name: name, Birthday: &vtime} - - if !DialectHasTzSupport() { - // If our driver dialect doesn't support TZ's, just use UTC for everything here. - utcBirthday := user.Birthday.UTC() - user.Birthday = &utcBirthday - } - - DB.Save(&user) - expectedBirthday := "2013-02-18 17:51:49 +0000" - foundBirthday := user.Birthday.UTC().Format(format) - if foundBirthday != expectedBirthday { - t.Errorf("User's birthday should not be changed after save for name=%s, expected bday=%+v but actual value=%+v", name, expectedBirthday, foundBirthday) - } - - var findUser, findUser2, findUser3 User - DB.First(&findUser, "name = ?", name) - foundBirthday = findUser.Birthday.UTC().Format(format) - if foundBirthday != expectedBirthday { - t.Errorf("User's birthday should not be changed after find for name=%s, expected bday=%+v but actual value=%+v", name, expectedBirthday, foundBirthday) - } - - if DB.Where("id = ? AND birthday >= ?", findUser.Id, user.Birthday.Add(-time.Minute)).First(&findUser2).RecordNotFound() { - t.Errorf("User should be found") - } - - if !DB.Where("id = ? AND birthday >= ?", findUser.Id, user.Birthday.Add(time.Minute)).First(&findUser3).RecordNotFound() { - t.Errorf("User should not be found") - } - } -} - -func TestHstore(t *testing.T) { - type Details struct { - Id int64 - Bulk postgres.Hstore - } - - if dialect := os.Getenv("GORM_DIALECT"); dialect != "postgres" { - t.Skip() - } - - if err := DB.Exec("CREATE EXTENSION IF NOT EXISTS hstore").Error; err != nil { - fmt.Println("\033[31mHINT: Must be superuser to create hstore extension (ALTER USER gorm WITH SUPERUSER;)\033[0m") - panic(fmt.Sprintf("No error should happen when create hstore extension, but got %+v", err)) - } - - DB.Exec("drop table details") - - if err := DB.CreateTable(&Details{}).Error; err != nil { - panic(fmt.Sprintf("No error should happen when create table, but got %+v", err)) - } - - bankAccountId, phoneNumber, opinion := "123456", "14151321232", "sharkbait" - bulk := map[string]*string{ - "bankAccountId": &bankAccountId, - "phoneNumber": &phoneNumber, - "opinion": &opinion, - } - d := Details{Bulk: bulk} - DB.Save(&d) - - var d2 Details - if err := DB.First(&d2).Error; err != nil { - t.Errorf("Got error when tried to fetch details: %+v", err) - } - - for k := range bulk { - if r, ok := d2.Bulk[k]; ok { - if res, _ := bulk[k]; *res != *r { - t.Errorf("Details should be equal") - } - } else { - t.Errorf("Details should be existed") - } - } -} - -func TestSetAndGet(t *testing.T) { - if value, ok := DB.Set("hello", "world").Get("hello"); !ok { - t.Errorf("Should be able to get setting after set") - } else { - if value.(string) != "world" { - t.Errorf("Setted value should not be changed") - } - } - - if _, ok := DB.Get("non_existing"); ok { - t.Errorf("Get non existing key should return error") - } -} - -func TestCompatibilityMode(t *testing.T) { - DB, _ := gorm.Open("testdb", "") - testdb.SetQueryFunc(func(query string) (driver.Rows, error) { - columns := []string{"id", "name", "age"} - result := ` - 1,Tim,20 - 2,Joe,25 - 3,Bob,30 - ` - return testdb.RowsFromCSVString(columns, result), nil - }) - - var users []User - DB.Find(&users) - if (users[0].Name != "Tim") || len(users) != 3 { - t.Errorf("Unexcepted result returned") - } -} - -func TestOpenExistingDB(t *testing.T) { - DB.Save(&User{Name: "jnfeinstein"}) - dialect := os.Getenv("GORM_DIALECT") - - db, err := gorm.Open(dialect, DB.DB()) - if err != nil { - t.Errorf("Should have wrapped the existing DB connection") - } - - var user User - if db.Where("name = ?", "jnfeinstein").First(&user).Error == gorm.ErrRecordNotFound { - t.Errorf("Should have found existing record") - } -} - -func TestDdlErrors(t *testing.T) { - var err error - - if err = DB.Close(); err != nil { - t.Errorf("Closing DDL test db connection err=%s", err) - } - defer func() { - // Reopen DB connection. - if DB, err = OpenTestConnection(); err != nil { - t.Fatalf("Failed re-opening db connection: %s", err) - } - }() - - if err := DB.Find(&User{}).Error; err == nil { - t.Errorf("Expected operation on closed db to produce an error, but err was nil") - } -} - -func TestOpenWithOneParameter(t *testing.T) { - db, err := gorm.Open("dialect") - if db != nil { - t.Error("Open with one parameter returned non nil for db") - } - if err == nil { - t.Error("Open with one parameter returned err as nil") - } -} - -func TestSaveAssociations(t *testing.T) { - db := DB.New() - deltaAddressCount := 0 - if err := db.Model(&Address{}).Count(&deltaAddressCount).Error; err != nil { - t.Errorf("failed to fetch address count") - t.FailNow() - } - - placeAddress := &Address{ - Address1: "somewhere on earth", - } - ownerAddress1 := &Address{ - Address1: "near place address", - } - ownerAddress2 := &Address{ - Address1: "address2", - } - db.Create(placeAddress) - - addressCountShouldBe := func(t *testing.T, expectedCount int) { - countFromDB := 0 - t.Helper() - err := db.Model(&Address{}).Count(&countFromDB).Error - if err != nil { - t.Error("failed to fetch address count") - } - if countFromDB != expectedCount { - t.Errorf("address count mismatch: %d", countFromDB) - } - } - addressCountShouldBe(t, deltaAddressCount+1) - - // owner address should be created, place address should be reused - place1 := &Place{ - PlaceAddressID: placeAddress.ID, - PlaceAddress: placeAddress, - OwnerAddress: ownerAddress1, - } - err := db.Create(place1).Error - if err != nil { - t.Errorf("failed to store place: %s", err.Error()) - } - addressCountShouldBe(t, deltaAddressCount+2) - - // owner address should be created again, place address should be reused - place2 := &Place{ - PlaceAddressID: placeAddress.ID, - PlaceAddress: &Address{ - ID: 777, - Address1: "address1", - }, - OwnerAddress: ownerAddress2, - OwnerAddressID: 778, - } - err = db.Create(place2).Error - if err != nil { - t.Errorf("failed to store place: %s", err.Error()) - } - addressCountShouldBe(t, deltaAddressCount+3) - - count := 0 - db.Model(&Place{}).Where(&Place{ - PlaceAddressID: placeAddress.ID, - OwnerAddressID: ownerAddress1.ID, - }).Count(&count) - if count != 1 { - t.Errorf("only one instance of (%d, %d) should be available, found: %d", - placeAddress.ID, ownerAddress1.ID, count) - } - - db.Model(&Place{}).Where(&Place{ - PlaceAddressID: placeAddress.ID, - OwnerAddressID: ownerAddress2.ID, - }).Count(&count) - if count != 1 { - t.Errorf("only one instance of (%d, %d) should be available, found: %d", - placeAddress.ID, ownerAddress2.ID, count) - } - - db.Model(&Place{}).Where(&Place{ - PlaceAddressID: placeAddress.ID, - }).Count(&count) - if count != 2 { - t.Errorf("two instances of (%d) should be available, found: %d", - placeAddress.ID, count) - } -} - -func TestBlockGlobalUpdate(t *testing.T) { - db := DB.New() - db.Create(&Toy{Name: "Stuffed Animal", OwnerType: "Nobody"}) - - err := db.Model(&Toy{}).Update("OwnerType", "Human").Error - if err != nil { - t.Error("Unexpected error on global update") - } - - err = db.Delete(&Toy{}).Error - if err != nil { - t.Error("Unexpected error on global delete") - } - - db.BlockGlobalUpdate(true) - - db.Create(&Toy{Name: "Stuffed Animal", OwnerType: "Nobody"}) - - err = db.Model(&Toy{}).Update("OwnerType", "Human").Error - if err == nil { - t.Error("Expected error on global update") - } - - err = db.Model(&Toy{}).Where(&Toy{OwnerType: "Martian"}).Update("OwnerType", "Astronaut").Error - if err != nil { - t.Error("Unxpected error on conditional update") - } - - err = db.Delete(&Toy{}).Error - if err == nil { - t.Error("Expected error on global delete") - } - err = db.Where(&Toy{OwnerType: "Martian"}).Delete(&Toy{}).Error - if err != nil { - t.Error("Unexpected error on conditional delete") - } -} - -func BenchmarkGorm(b *testing.B) { - b.N = 2000 - for x := 0; x < b.N; x++ { - e := strconv.Itoa(x) + "benchmark@example.org" - now := time.Now() - email := EmailWithIdx{Email: e, UserAgent: "pc", RegisteredAt: &now} - // Insert - DB.Save(&email) - // Query - DB.First(&EmailWithIdx{}, "email = ?", e) - // Update - DB.Model(&email).UpdateColumn("email", "new-"+e) - // Delete - DB.Delete(&email) - } -} - -func BenchmarkRawSql(b *testing.B) { - DB, _ := sql.Open("postgres", "user=gorm DB.ame=gorm sslmode=disable") - DB.SetMaxIdleConns(10) - insertSql := "INSERT INTO emails (user_id,email,user_agent,registered_at,created_at,updated_at) VALUES ($1,$2,$3,$4,$5,$6) RETURNING id" - querySql := "SELECT * FROM emails WHERE email = $1 ORDER BY id LIMIT 1" - updateSql := "UPDATE emails SET email = $1, updated_at = $2 WHERE id = $3" - deleteSql := "DELETE FROM orders WHERE id = $1" - - b.N = 2000 - for x := 0; x < b.N; x++ { - var id int64 - e := strconv.Itoa(x) + "benchmark@example.org" - now := time.Now() - email := EmailWithIdx{Email: e, UserAgent: "pc", RegisteredAt: &now} - // Insert - DB.QueryRow(insertSql, email.UserId, email.Email, email.UserAgent, email.RegisteredAt, time.Now(), time.Now()).Scan(&id) - // Query - rows, _ := DB.Query(querySql, email.Email) - rows.Close() - // Update - DB.Exec(updateSql, "new-"+e, time.Now(), id) - // Delete - DB.Exec(deleteSql, id) - } -} - -func parseTime(str string) *time.Time { - t := now.New(time.Now().UTC()).MustParse(str) - return &t -} diff --git a/vendor/github.com/jinzhu/gorm/migration_test.go b/vendor/github.com/jinzhu/gorm/migration_test.go deleted file mode 100644 index 3fb06648..00000000 --- a/vendor/github.com/jinzhu/gorm/migration_test.go +++ /dev/null @@ -1,540 +0,0 @@ -package gorm_test - -import ( - "database/sql" - "database/sql/driver" - "errors" - "fmt" - "os" - "reflect" - "strconv" - "testing" - "time" - - "github.com/jinzhu/gorm" -) - -type User struct { - Id int64 - Age int64 - UserNum Num - Name string `sql:"size:255"` - Email string - Birthday *time.Time // Time - CreatedAt time.Time // CreatedAt: Time of record is created, will be insert automatically - UpdatedAt time.Time // UpdatedAt: Time of record is updated, will be updated automatically - Emails []Email // Embedded structs - BillingAddress Address // Embedded struct - BillingAddressID sql.NullInt64 // Embedded struct's foreign key - ShippingAddress Address // Embedded struct - ShippingAddressId int64 // Embedded struct's foreign key - CreditCard CreditCard - Latitude float64 - Languages []Language `gorm:"many2many:user_languages;"` - CompanyID *int - Company Company - Role Role - Password EncryptedData - PasswordHash []byte - IgnoreMe int64 `sql:"-"` - IgnoreStringSlice []string `sql:"-"` - Ignored struct{ Name string } `sql:"-"` - IgnoredPointer *User `sql:"-"` -} - -type NotSoLongTableName struct { - Id int64 - ReallyLongThingID int64 - ReallyLongThing ReallyLongTableNameToTestMySQLNameLengthLimit -} - -type ReallyLongTableNameToTestMySQLNameLengthLimit struct { - Id int64 -} - -type ReallyLongThingThatReferencesShort struct { - Id int64 - ShortID int64 - Short Short -} - -type Short struct { - Id int64 -} - -type CreditCard struct { - ID int8 - Number string - UserId sql.NullInt64 - CreatedAt time.Time `sql:"not null"` - UpdatedAt time.Time - DeletedAt *time.Time `sql:"column:deleted_time"` -} - -type Email struct { - Id int16 - UserId int - Email string `sql:"type:varchar(100);"` - CreatedAt time.Time - UpdatedAt time.Time -} - -type Address struct { - ID int - Address1 string - Address2 string - Post string - CreatedAt time.Time - UpdatedAt time.Time - DeletedAt *time.Time -} - -type Language struct { - gorm.Model - Name string - Users []User `gorm:"many2many:user_languages;"` -} - -type Product struct { - Id int64 - Code string - Price int64 - CreatedAt time.Time - UpdatedAt time.Time - AfterFindCallTimes int64 - BeforeCreateCallTimes int64 - AfterCreateCallTimes int64 - BeforeUpdateCallTimes int64 - AfterUpdateCallTimes int64 - BeforeSaveCallTimes int64 - AfterSaveCallTimes int64 - BeforeDeleteCallTimes int64 - AfterDeleteCallTimes int64 -} - -type Company struct { - Id int64 - Name string - Owner *User `sql:"-"` -} - -type Place struct { - Id int64 - PlaceAddressID int - PlaceAddress *Address `gorm:"save_associations:false"` - OwnerAddressID int - OwnerAddress *Address `gorm:"save_associations:true"` -} - -type EncryptedData []byte - -func (data *EncryptedData) Scan(value interface{}) error { - if b, ok := value.([]byte); ok { - if len(b) < 3 || b[0] != '*' || b[1] != '*' || b[2] != '*' { - return errors.New("Too short") - } - - *data = b[3:] - return nil - } - - return errors.New("Bytes expected") -} - -func (data EncryptedData) Value() (driver.Value, error) { - if len(data) > 0 && data[0] == 'x' { - //needed to test failures - return nil, errors.New("Should not start with 'x'") - } - - //prepend asterisks - return append([]byte("***"), data...), nil -} - -type Role struct { - Name string `gorm:"size:256"` -} - -func (role *Role) Scan(value interface{}) error { - if b, ok := value.([]uint8); ok { - role.Name = string(b) - } else { - role.Name = value.(string) - } - return nil -} - -func (role Role) Value() (driver.Value, error) { - return role.Name, nil -} - -func (role Role) IsAdmin() bool { - return role.Name == "admin" -} - -type Num int64 - -func (i *Num) Scan(src interface{}) error { - switch s := src.(type) { - case []byte: - n, _ := strconv.Atoi(string(s)) - *i = Num(n) - case int64: - *i = Num(s) - default: - return errors.New("Cannot scan NamedInt from " + reflect.ValueOf(src).String()) - } - return nil -} - -type Animal struct { - Counter uint64 `gorm:"primary_key:yes"` - Name string `sql:"DEFAULT:'galeone'"` - From string //test reserved sql keyword as field name - Age time.Time `sql:"DEFAULT:current_timestamp"` - unexported string // unexported value - CreatedAt time.Time - UpdatedAt time.Time -} - -type JoinTable struct { - From uint64 - To uint64 - Time time.Time `sql:"default: null"` -} - -type Post struct { - Id int64 - CategoryId sql.NullInt64 - MainCategoryId int64 - Title string - Body string - Comments []*Comment - Category Category - MainCategory Category -} - -type Category struct { - gorm.Model - Name string - - Categories []Category - CategoryID *uint -} - -type Comment struct { - gorm.Model - PostId int64 - Content string - Post Post -} - -// Scanner -type NullValue struct { - Id int64 - Name sql.NullString `sql:"not null"` - Gender *sql.NullString `sql:"not null"` - Age sql.NullInt64 - Male sql.NullBool - Height sql.NullFloat64 - AddedAt NullTime -} - -type NullTime struct { - Time time.Time - Valid bool -} - -func (nt *NullTime) Scan(value interface{}) error { - if value == nil { - nt.Valid = false - return nil - } - nt.Time, nt.Valid = value.(time.Time), true - return nil -} - -func (nt NullTime) Value() (driver.Value, error) { - if !nt.Valid { - return nil, nil - } - return nt.Time, nil -} - -func getPreparedUser(name string, role string) *User { - var company Company - DB.Where(Company{Name: role}).FirstOrCreate(&company) - - return &User{ - Name: name, - Age: 20, - Role: Role{role}, - BillingAddress: Address{Address1: fmt.Sprintf("Billing Address %v", name)}, - ShippingAddress: Address{Address1: fmt.Sprintf("Shipping Address %v", name)}, - CreditCard: CreditCard{Number: fmt.Sprintf("123456%v", name)}, - Emails: []Email{ - {Email: fmt.Sprintf("user_%v@example1.com", name)}, {Email: fmt.Sprintf("user_%v@example2.com", name)}, - }, - Company: company, - Languages: []Language{ - {Name: fmt.Sprintf("lang_1_%v", name)}, - {Name: fmt.Sprintf("lang_2_%v", name)}, - }, - } -} - -func runMigration() { - if err := DB.DropTableIfExists(&User{}).Error; err != nil { - fmt.Printf("Got error when try to delete table users, %+v\n", err) - } - - for _, table := range []string{"animals", "user_languages"} { - DB.Exec(fmt.Sprintf("drop table %v;", table)) - } - - values := []interface{}{&Short{}, &ReallyLongThingThatReferencesShort{}, &ReallyLongTableNameToTestMySQLNameLengthLimit{}, &NotSoLongTableName{}, &Product{}, &Email{}, &Address{}, &CreditCard{}, &Company{}, &Role{}, &Language{}, &HNPost{}, &EngadgetPost{}, &Animal{}, &User{}, &JoinTable{}, &Post{}, &Category{}, &Comment{}, &Cat{}, &Dog{}, &Hamster{}, &Toy{}, &ElementWithIgnoredField{}, &Place{}} - for _, value := range values { - DB.DropTable(value) - } - if err := DB.AutoMigrate(values...).Error; err != nil { - panic(fmt.Sprintf("No error should happen when create table, but got %+v", err)) - } -} - -func TestIndexes(t *testing.T) { - if err := DB.Model(&Email{}).AddIndex("idx_email_email", "email").Error; err != nil { - t.Errorf("Got error when tried to create index: %+v", err) - } - - scope := DB.NewScope(&Email{}) - if !scope.Dialect().HasIndex(scope.TableName(), "idx_email_email") { - t.Errorf("Email should have index idx_email_email") - } - - if err := DB.Model(&Email{}).RemoveIndex("idx_email_email").Error; err != nil { - t.Errorf("Got error when tried to remove index: %+v", err) - } - - if scope.Dialect().HasIndex(scope.TableName(), "idx_email_email") { - t.Errorf("Email's index idx_email_email should be deleted") - } - - if err := DB.Model(&Email{}).AddIndex("idx_email_email_and_user_id", "user_id", "email").Error; err != nil { - t.Errorf("Got error when tried to create index: %+v", err) - } - - if !scope.Dialect().HasIndex(scope.TableName(), "idx_email_email_and_user_id") { - t.Errorf("Email should have index idx_email_email_and_user_id") - } - - if err := DB.Model(&Email{}).RemoveIndex("idx_email_email_and_user_id").Error; err != nil { - t.Errorf("Got error when tried to remove index: %+v", err) - } - - if scope.Dialect().HasIndex(scope.TableName(), "idx_email_email_and_user_id") { - t.Errorf("Email's index idx_email_email_and_user_id should be deleted") - } - - if err := DB.Model(&Email{}).AddUniqueIndex("idx_email_email_and_user_id", "user_id", "email").Error; err != nil { - t.Errorf("Got error when tried to create index: %+v", err) - } - - if !scope.Dialect().HasIndex(scope.TableName(), "idx_email_email_and_user_id") { - t.Errorf("Email should have index idx_email_email_and_user_id") - } - - if DB.Save(&User{Name: "unique_indexes", Emails: []Email{{Email: "user1@example.comiii"}, {Email: "user1@example.com"}, {Email: "user1@example.com"}}}).Error == nil { - t.Errorf("Should get to create duplicate record when having unique index") - } - - var user = User{Name: "sample_user"} - DB.Save(&user) - if DB.Model(&user).Association("Emails").Append(Email{Email: "not-1duplicated@gmail.com"}, Email{Email: "not-duplicated2@gmail.com"}).Error != nil { - t.Errorf("Should get no error when append two emails for user") - } - - if DB.Model(&user).Association("Emails").Append(Email{Email: "duplicated@gmail.com"}, Email{Email: "duplicated@gmail.com"}).Error == nil { - t.Errorf("Should get no duplicated email error when insert duplicated emails for a user") - } - - if err := DB.Model(&Email{}).RemoveIndex("idx_email_email_and_user_id").Error; err != nil { - t.Errorf("Got error when tried to remove index: %+v", err) - } - - if scope.Dialect().HasIndex(scope.TableName(), "idx_email_email_and_user_id") { - t.Errorf("Email's index idx_email_email_and_user_id should be deleted") - } - - if DB.Save(&User{Name: "unique_indexes", Emails: []Email{{Email: "user1@example.com"}, {Email: "user1@example.com"}}}).Error != nil { - t.Errorf("Should be able to create duplicated emails after remove unique index") - } -} - -type EmailWithIdx struct { - Id int64 - UserId int64 - Email string `sql:"index:idx_email_agent"` - UserAgent string `sql:"index:idx_email_agent"` - RegisteredAt *time.Time `sql:"unique_index"` - CreatedAt time.Time - UpdatedAt time.Time -} - -func TestAutoMigration(t *testing.T) { - DB.AutoMigrate(&Address{}) - DB.DropTable(&EmailWithIdx{}) - if err := DB.AutoMigrate(&EmailWithIdx{}).Error; err != nil { - t.Errorf("Auto Migrate should not raise any error") - } - - now := time.Now() - DB.Save(&EmailWithIdx{Email: "jinzhu@example.org", UserAgent: "pc", RegisteredAt: &now}) - - scope := DB.NewScope(&EmailWithIdx{}) - if !scope.Dialect().HasIndex(scope.TableName(), "idx_email_agent") { - t.Errorf("Failed to create index") - } - - if !scope.Dialect().HasIndex(scope.TableName(), "uix_email_with_idxes_registered_at") { - t.Errorf("Failed to create index") - } - - var bigemail EmailWithIdx - DB.First(&bigemail, "user_agent = ?", "pc") - if bigemail.Email != "jinzhu@example.org" || bigemail.UserAgent != "pc" || bigemail.RegisteredAt.IsZero() { - t.Error("Big Emails should be saved and fetched correctly") - } -} - -func TestCreateAndAutomigrateTransaction(t *testing.T) { - tx := DB.Begin() - - func() { - type Bar struct { - ID uint - } - DB.DropTableIfExists(&Bar{}) - - if ok := DB.HasTable("bars"); ok { - t.Errorf("Table should not exist, but does") - } - - if ok := tx.HasTable("bars"); ok { - t.Errorf("Table should not exist, but does") - } - }() - - func() { - type Bar struct { - Name string - } - err := tx.CreateTable(&Bar{}).Error - - if err != nil { - t.Errorf("Should have been able to create the table, but couldn't: %s", err) - } - - if ok := tx.HasTable(&Bar{}); !ok { - t.Errorf("The transaction should be able to see the table") - } - }() - - func() { - type Bar struct { - Stuff string - } - - err := tx.AutoMigrate(&Bar{}).Error - if err != nil { - t.Errorf("Should have been able to alter the table, but couldn't") - } - }() - - tx.Rollback() -} - -type MultipleIndexes struct { - ID int64 - UserID int64 `sql:"unique_index:uix_multipleindexes_user_name,uix_multipleindexes_user_email;index:idx_multipleindexes_user_other"` - Name string `sql:"unique_index:uix_multipleindexes_user_name"` - Email string `sql:"unique_index:,uix_multipleindexes_user_email"` - Other string `sql:"index:,idx_multipleindexes_user_other"` -} - -func TestMultipleIndexes(t *testing.T) { - if err := DB.DropTableIfExists(&MultipleIndexes{}).Error; err != nil { - fmt.Printf("Got error when try to delete table multiple_indexes, %+v\n", err) - } - - DB.AutoMigrate(&MultipleIndexes{}) - if err := DB.AutoMigrate(&EmailWithIdx{}).Error; err != nil { - t.Errorf("Auto Migrate should not raise any error") - } - - DB.Save(&MultipleIndexes{UserID: 1, Name: "jinzhu", Email: "jinzhu@example.org", Other: "foo"}) - - scope := DB.NewScope(&MultipleIndexes{}) - if !scope.Dialect().HasIndex(scope.TableName(), "uix_multipleindexes_user_name") { - t.Errorf("Failed to create index") - } - - if !scope.Dialect().HasIndex(scope.TableName(), "uix_multipleindexes_user_email") { - t.Errorf("Failed to create index") - } - - if !scope.Dialect().HasIndex(scope.TableName(), "uix_multiple_indexes_email") { - t.Errorf("Failed to create index") - } - - if !scope.Dialect().HasIndex(scope.TableName(), "idx_multipleindexes_user_other") { - t.Errorf("Failed to create index") - } - - if !scope.Dialect().HasIndex(scope.TableName(), "idx_multiple_indexes_other") { - t.Errorf("Failed to create index") - } - - var mutipleIndexes MultipleIndexes - DB.First(&mutipleIndexes, "name = ?", "jinzhu") - if mutipleIndexes.Email != "jinzhu@example.org" || mutipleIndexes.Name != "jinzhu" { - t.Error("MutipleIndexes should be saved and fetched correctly") - } - - // Check unique constraints - if err := DB.Save(&MultipleIndexes{UserID: 1, Name: "name1", Email: "jinzhu@example.org", Other: "foo"}).Error; err == nil { - t.Error("MultipleIndexes unique index failed") - } - - if err := DB.Save(&MultipleIndexes{UserID: 1, Name: "name1", Email: "foo@example.org", Other: "foo"}).Error; err != nil { - t.Error("MultipleIndexes unique index failed") - } - - if err := DB.Save(&MultipleIndexes{UserID: 2, Name: "name1", Email: "jinzhu@example.org", Other: "foo"}).Error; err == nil { - t.Error("MultipleIndexes unique index failed") - } - - if err := DB.Save(&MultipleIndexes{UserID: 2, Name: "name1", Email: "foo2@example.org", Other: "foo"}).Error; err != nil { - t.Error("MultipleIndexes unique index failed") - } -} - -func TestModifyColumnType(t *testing.T) { - if dialect := os.Getenv("GORM_DIALECT"); dialect != "postgres" && dialect != "mysql" && dialect != "mssql" { - t.Skip("Skipping this because only postgres, mysql and mssql support altering a column type") - } - - type ModifyColumnType struct { - gorm.Model - Name1 string `gorm:"length:100"` - Name2 string `gorm:"length:200"` - } - DB.DropTable(&ModifyColumnType{}) - DB.CreateTable(&ModifyColumnType{}) - - name2Field, _ := DB.NewScope(&ModifyColumnType{}).FieldByName("Name2") - name2Type := DB.Dialect().DataTypeOf(name2Field.StructField) - - if err := DB.Model(&ModifyColumnType{}).ModifyColumn("name1", name2Type).Error; err != nil { - t.Errorf("No error should happen when ModifyColumn, but got %v", err) - } -} diff --git a/vendor/github.com/jinzhu/gorm/multi_primary_keys_test.go b/vendor/github.com/jinzhu/gorm/multi_primary_keys_test.go deleted file mode 100644 index 32a14772..00000000 --- a/vendor/github.com/jinzhu/gorm/multi_primary_keys_test.go +++ /dev/null @@ -1,381 +0,0 @@ -package gorm_test - -import ( - "os" - "reflect" - "sort" - "testing" -) - -type Blog struct { - ID uint `gorm:"primary_key"` - Locale string `gorm:"primary_key"` - Subject string - Body string - Tags []Tag `gorm:"many2many:blog_tags;"` - SharedTags []Tag `gorm:"many2many:shared_blog_tags;ForeignKey:id;AssociationForeignKey:id"` - LocaleTags []Tag `gorm:"many2many:locale_blog_tags;ForeignKey:id,locale;AssociationForeignKey:id"` -} - -type Tag struct { - ID uint `gorm:"primary_key"` - Locale string `gorm:"primary_key"` - Value string - Blogs []*Blog `gorm:"many2many:blogs_tags"` -} - -func compareTags(tags []Tag, contents []string) bool { - var tagContents []string - for _, tag := range tags { - tagContents = append(tagContents, tag.Value) - } - sort.Strings(tagContents) - sort.Strings(contents) - return reflect.DeepEqual(tagContents, contents) -} - -func TestManyToManyWithMultiPrimaryKeys(t *testing.T) { - if dialect := os.Getenv("GORM_DIALECT"); dialect != "" && dialect != "sqlite" && dialect != "mssql" { - DB.DropTable(&Blog{}, &Tag{}) - DB.DropTable("blog_tags") - DB.CreateTable(&Blog{}, &Tag{}) - blog := Blog{ - Locale: "ZH", - Subject: "subject", - Body: "body", - Tags: []Tag{ - {Locale: "ZH", Value: "tag1"}, - {Locale: "ZH", Value: "tag2"}, - }, - } - - DB.Save(&blog) - if !compareTags(blog.Tags, []string{"tag1", "tag2"}) { - t.Errorf("Blog should has two tags") - } - - // Append - var tag3 = &Tag{Locale: "ZH", Value: "tag3"} - DB.Model(&blog).Association("Tags").Append([]*Tag{tag3}) - if !compareTags(blog.Tags, []string{"tag1", "tag2", "tag3"}) { - t.Errorf("Blog should has three tags after Append") - } - - if DB.Model(&blog).Association("Tags").Count() != 3 { - t.Errorf("Blog should has three tags after Append") - } - - var tags []Tag - DB.Model(&blog).Related(&tags, "Tags") - if !compareTags(tags, []string{"tag1", "tag2", "tag3"}) { - t.Errorf("Should find 3 tags with Related") - } - - var blog1 Blog - DB.Preload("Tags").Find(&blog1) - if !compareTags(blog1.Tags, []string{"tag1", "tag2", "tag3"}) { - t.Errorf("Preload many2many relations") - } - - // Replace - var tag5 = &Tag{Locale: "ZH", Value: "tag5"} - var tag6 = &Tag{Locale: "ZH", Value: "tag6"} - DB.Model(&blog).Association("Tags").Replace(tag5, tag6) - var tags2 []Tag - DB.Model(&blog).Related(&tags2, "Tags") - if !compareTags(tags2, []string{"tag5", "tag6"}) { - t.Errorf("Should find 2 tags after Replace") - } - - if DB.Model(&blog).Association("Tags").Count() != 2 { - t.Errorf("Blog should has three tags after Replace") - } - - // Delete - DB.Model(&blog).Association("Tags").Delete(tag5) - var tags3 []Tag - DB.Model(&blog).Related(&tags3, "Tags") - if !compareTags(tags3, []string{"tag6"}) { - t.Errorf("Should find 1 tags after Delete") - } - - if DB.Model(&blog).Association("Tags").Count() != 1 { - t.Errorf("Blog should has three tags after Delete") - } - - DB.Model(&blog).Association("Tags").Delete(tag3) - var tags4 []Tag - DB.Model(&blog).Related(&tags4, "Tags") - if !compareTags(tags4, []string{"tag6"}) { - t.Errorf("Tag should not be deleted when Delete with a unrelated tag") - } - - // Clear - DB.Model(&blog).Association("Tags").Clear() - if DB.Model(&blog).Association("Tags").Count() != 0 { - t.Errorf("All tags should be cleared") - } - } -} - -func TestManyToManyWithCustomizedForeignKeys(t *testing.T) { - if dialect := os.Getenv("GORM_DIALECT"); dialect != "" && dialect != "sqlite" && dialect != "mssql" { - DB.DropTable(&Blog{}, &Tag{}) - DB.DropTable("shared_blog_tags") - DB.CreateTable(&Blog{}, &Tag{}) - blog := Blog{ - Locale: "ZH", - Subject: "subject", - Body: "body", - SharedTags: []Tag{ - {Locale: "ZH", Value: "tag1"}, - {Locale: "ZH", Value: "tag2"}, - }, - } - DB.Save(&blog) - - blog2 := Blog{ - ID: blog.ID, - Locale: "EN", - } - DB.Create(&blog2) - - if !compareTags(blog.SharedTags, []string{"tag1", "tag2"}) { - t.Errorf("Blog should has two tags") - } - - // Append - var tag3 = &Tag{Locale: "ZH", Value: "tag3"} - DB.Model(&blog).Association("SharedTags").Append([]*Tag{tag3}) - if !compareTags(blog.SharedTags, []string{"tag1", "tag2", "tag3"}) { - t.Errorf("Blog should has three tags after Append") - } - - if DB.Model(&blog).Association("SharedTags").Count() != 3 { - t.Errorf("Blog should has three tags after Append") - } - - if DB.Model(&blog2).Association("SharedTags").Count() != 3 { - t.Errorf("Blog should has three tags after Append") - } - - var tags []Tag - DB.Model(&blog).Related(&tags, "SharedTags") - if !compareTags(tags, []string{"tag1", "tag2", "tag3"}) { - t.Errorf("Should find 3 tags with Related") - } - - DB.Model(&blog2).Related(&tags, "SharedTags") - if !compareTags(tags, []string{"tag1", "tag2", "tag3"}) { - t.Errorf("Should find 3 tags with Related") - } - - var blog1 Blog - DB.Preload("SharedTags").Find(&blog1) - if !compareTags(blog1.SharedTags, []string{"tag1", "tag2", "tag3"}) { - t.Errorf("Preload many2many relations") - } - - var tag4 = &Tag{Locale: "ZH", Value: "tag4"} - DB.Model(&blog2).Association("SharedTags").Append(tag4) - - DB.Model(&blog).Related(&tags, "SharedTags") - if !compareTags(tags, []string{"tag1", "tag2", "tag3", "tag4"}) { - t.Errorf("Should find 3 tags with Related") - } - - DB.Model(&blog2).Related(&tags, "SharedTags") - if !compareTags(tags, []string{"tag1", "tag2", "tag3", "tag4"}) { - t.Errorf("Should find 3 tags with Related") - } - - // Replace - var tag5 = &Tag{Locale: "ZH", Value: "tag5"} - var tag6 = &Tag{Locale: "ZH", Value: "tag6"} - DB.Model(&blog2).Association("SharedTags").Replace(tag5, tag6) - var tags2 []Tag - DB.Model(&blog).Related(&tags2, "SharedTags") - if !compareTags(tags2, []string{"tag5", "tag6"}) { - t.Errorf("Should find 2 tags after Replace") - } - - DB.Model(&blog2).Related(&tags2, "SharedTags") - if !compareTags(tags2, []string{"tag5", "tag6"}) { - t.Errorf("Should find 2 tags after Replace") - } - - if DB.Model(&blog).Association("SharedTags").Count() != 2 { - t.Errorf("Blog should has three tags after Replace") - } - - // Delete - DB.Model(&blog).Association("SharedTags").Delete(tag5) - var tags3 []Tag - DB.Model(&blog).Related(&tags3, "SharedTags") - if !compareTags(tags3, []string{"tag6"}) { - t.Errorf("Should find 1 tags after Delete") - } - - if DB.Model(&blog).Association("SharedTags").Count() != 1 { - t.Errorf("Blog should has three tags after Delete") - } - - DB.Model(&blog2).Association("SharedTags").Delete(tag3) - var tags4 []Tag - DB.Model(&blog).Related(&tags4, "SharedTags") - if !compareTags(tags4, []string{"tag6"}) { - t.Errorf("Tag should not be deleted when Delete with a unrelated tag") - } - - // Clear - DB.Model(&blog2).Association("SharedTags").Clear() - if DB.Model(&blog).Association("SharedTags").Count() != 0 { - t.Errorf("All tags should be cleared") - } - } -} - -func TestManyToManyWithCustomizedForeignKeys2(t *testing.T) { - if dialect := os.Getenv("GORM_DIALECT"); dialect != "" && dialect != "sqlite" && dialect != "mssql" { - DB.DropTable(&Blog{}, &Tag{}) - DB.DropTable("locale_blog_tags") - DB.CreateTable(&Blog{}, &Tag{}) - blog := Blog{ - Locale: "ZH", - Subject: "subject", - Body: "body", - LocaleTags: []Tag{ - {Locale: "ZH", Value: "tag1"}, - {Locale: "ZH", Value: "tag2"}, - }, - } - DB.Save(&blog) - - blog2 := Blog{ - ID: blog.ID, - Locale: "EN", - } - DB.Create(&blog2) - - // Append - var tag3 = &Tag{Locale: "ZH", Value: "tag3"} - DB.Model(&blog).Association("LocaleTags").Append([]*Tag{tag3}) - if !compareTags(blog.LocaleTags, []string{"tag1", "tag2", "tag3"}) { - t.Errorf("Blog should has three tags after Append") - } - - if DB.Model(&blog).Association("LocaleTags").Count() != 3 { - t.Errorf("Blog should has three tags after Append") - } - - if DB.Model(&blog2).Association("LocaleTags").Count() != 0 { - t.Errorf("EN Blog should has 0 tags after ZH Blog Append") - } - - var tags []Tag - DB.Model(&blog).Related(&tags, "LocaleTags") - if !compareTags(tags, []string{"tag1", "tag2", "tag3"}) { - t.Errorf("Should find 3 tags with Related") - } - - DB.Model(&blog2).Related(&tags, "LocaleTags") - if len(tags) != 0 { - t.Errorf("Should find 0 tags with Related for EN Blog") - } - - var blog1 Blog - DB.Preload("LocaleTags").Find(&blog1, "locale = ? AND id = ?", "ZH", blog.ID) - if !compareTags(blog1.LocaleTags, []string{"tag1", "tag2", "tag3"}) { - t.Errorf("Preload many2many relations") - } - - var tag4 = &Tag{Locale: "ZH", Value: "tag4"} - DB.Model(&blog2).Association("LocaleTags").Append(tag4) - - DB.Model(&blog).Related(&tags, "LocaleTags") - if !compareTags(tags, []string{"tag1", "tag2", "tag3"}) { - t.Errorf("Should find 3 tags with Related for EN Blog") - } - - DB.Model(&blog2).Related(&tags, "LocaleTags") - if !compareTags(tags, []string{"tag4"}) { - t.Errorf("Should find 1 tags with Related for EN Blog") - } - - // Replace - var tag5 = &Tag{Locale: "ZH", Value: "tag5"} - var tag6 = &Tag{Locale: "ZH", Value: "tag6"} - DB.Model(&blog2).Association("LocaleTags").Replace(tag5, tag6) - - var tags2 []Tag - DB.Model(&blog).Related(&tags2, "LocaleTags") - if !compareTags(tags2, []string{"tag1", "tag2", "tag3"}) { - t.Errorf("CN Blog's tags should not be changed after EN Blog Replace") - } - - var blog11 Blog - DB.Preload("LocaleTags").First(&blog11, "id = ? AND locale = ?", blog.ID, blog.Locale) - if !compareTags(blog11.LocaleTags, []string{"tag1", "tag2", "tag3"}) { - t.Errorf("CN Blog's tags should not be changed after EN Blog Replace") - } - - DB.Model(&blog2).Related(&tags2, "LocaleTags") - if !compareTags(tags2, []string{"tag5", "tag6"}) { - t.Errorf("Should find 2 tags after Replace") - } - - var blog21 Blog - DB.Preload("LocaleTags").First(&blog21, "id = ? AND locale = ?", blog2.ID, blog2.Locale) - if !compareTags(blog21.LocaleTags, []string{"tag5", "tag6"}) { - t.Errorf("EN Blog's tags should be changed after Replace") - } - - if DB.Model(&blog).Association("LocaleTags").Count() != 3 { - t.Errorf("ZH Blog should has three tags after Replace") - } - - if DB.Model(&blog2).Association("LocaleTags").Count() != 2 { - t.Errorf("EN Blog should has two tags after Replace") - } - - // Delete - DB.Model(&blog).Association("LocaleTags").Delete(tag5) - - if DB.Model(&blog).Association("LocaleTags").Count() != 3 { - t.Errorf("ZH Blog should has three tags after Delete with EN's tag") - } - - if DB.Model(&blog2).Association("LocaleTags").Count() != 2 { - t.Errorf("EN Blog should has two tags after ZH Blog Delete with EN's tag") - } - - DB.Model(&blog2).Association("LocaleTags").Delete(tag5) - - if DB.Model(&blog).Association("LocaleTags").Count() != 3 { - t.Errorf("ZH Blog should has three tags after EN Blog Delete with EN's tag") - } - - if DB.Model(&blog2).Association("LocaleTags").Count() != 1 { - t.Errorf("EN Blog should has 1 tags after EN Blog Delete with EN's tag") - } - - // Clear - DB.Model(&blog2).Association("LocaleTags").Clear() - if DB.Model(&blog).Association("LocaleTags").Count() != 3 { - t.Errorf("ZH Blog's tags should not be cleared when clear EN Blog's tags") - } - - if DB.Model(&blog2).Association("LocaleTags").Count() != 0 { - t.Errorf("EN Blog's tags should be cleared when clear EN Blog's tags") - } - - DB.Model(&blog).Association("LocaleTags").Clear() - if DB.Model(&blog).Association("LocaleTags").Count() != 0 { - t.Errorf("ZH Blog's tags should be cleared when clear ZH Blog's tags") - } - - if DB.Model(&blog2).Association("LocaleTags").Count() != 0 { - t.Errorf("EN Blog's tags should be cleared") - } - } -} diff --git a/vendor/github.com/jinzhu/gorm/naming_test.go b/vendor/github.com/jinzhu/gorm/naming_test.go deleted file mode 100644 index 0c6f7713..00000000 --- a/vendor/github.com/jinzhu/gorm/naming_test.go +++ /dev/null @@ -1,69 +0,0 @@ -package gorm_test - -import ( - "testing" - - "github.com/jinzhu/gorm" -) - -func TestTheNamingStrategy(t *testing.T) { - - cases := []struct { - name string - namer gorm.Namer - expected string - }{ - {name: "auth", expected: "auth", namer: gorm.TheNamingStrategy.DB}, - {name: "userRestrictions", expected: "user_restrictions", namer: gorm.TheNamingStrategy.Table}, - {name: "clientID", expected: "client_id", namer: gorm.TheNamingStrategy.Column}, - } - - for _, c := range cases { - t.Run(c.name, func(t *testing.T) { - result := c.namer(c.name) - if result != c.expected { - t.Errorf("error in naming strategy. expected: %v got :%v\n", c.expected, result) - } - }) - } - -} - -func TestNamingStrategy(t *testing.T) { - - dbNameNS := func(name string) string { - return "db_" + name - } - tableNameNS := func(name string) string { - return "tbl_" + name - } - columnNameNS := func(name string) string { - return "col_" + name - } - - ns := &gorm.NamingStrategy{ - DB: dbNameNS, - Table: tableNameNS, - Column: columnNameNS, - } - - cases := []struct { - name string - namer gorm.Namer - expected string - }{ - {name: "auth", expected: "db_auth", namer: ns.DB}, - {name: "user", expected: "tbl_user", namer: ns.Table}, - {name: "password", expected: "col_password", namer: ns.Column}, - } - - for _, c := range cases { - t.Run(c.name, func(t *testing.T) { - result := c.namer(c.name) - if result != c.expected { - t.Errorf("error in naming strategy. expected: %v got :%v\n", c.expected, result) - } - }) - } - -} diff --git a/vendor/github.com/jinzhu/gorm/pointer_test.go b/vendor/github.com/jinzhu/gorm/pointer_test.go deleted file mode 100644 index 2a68a5ab..00000000 --- a/vendor/github.com/jinzhu/gorm/pointer_test.go +++ /dev/null @@ -1,84 +0,0 @@ -package gorm_test - -import "testing" - -type PointerStruct struct { - ID int64 - Name *string - Num *int -} - -type NormalStruct struct { - ID int64 - Name string - Num int -} - -func TestPointerFields(t *testing.T) { - DB.DropTable(&PointerStruct{}) - DB.AutoMigrate(&PointerStruct{}) - var name = "pointer struct 1" - var num = 100 - pointerStruct := PointerStruct{Name: &name, Num: &num} - if DB.Create(&pointerStruct).Error != nil { - t.Errorf("Failed to save pointer struct") - } - - var pointerStructResult PointerStruct - if err := DB.First(&pointerStructResult, "id = ?", pointerStruct.ID).Error; err != nil || *pointerStructResult.Name != name || *pointerStructResult.Num != num { - t.Errorf("Failed to query saved pointer struct") - } - - var tableName = DB.NewScope(&PointerStruct{}).TableName() - - var normalStruct NormalStruct - DB.Table(tableName).First(&normalStruct) - if normalStruct.Name != name || normalStruct.Num != num { - t.Errorf("Failed to query saved Normal struct") - } - - var nilPointerStruct = PointerStruct{} - if err := DB.Create(&nilPointerStruct).Error; err != nil { - t.Error("Failed to save nil pointer struct", err) - } - - var pointerStruct2 PointerStruct - if err := DB.First(&pointerStruct2, "id = ?", nilPointerStruct.ID).Error; err != nil { - t.Error("Failed to query saved nil pointer struct", err) - } - - var normalStruct2 NormalStruct - if err := DB.Table(tableName).First(&normalStruct2, "id = ?", nilPointerStruct.ID).Error; err != nil { - t.Error("Failed to query saved nil pointer struct", err) - } - - var partialNilPointerStruct1 = PointerStruct{Num: &num} - if err := DB.Create(&partialNilPointerStruct1).Error; err != nil { - t.Error("Failed to save partial nil pointer struct", err) - } - - var pointerStruct3 PointerStruct - if err := DB.First(&pointerStruct3, "id = ?", partialNilPointerStruct1.ID).Error; err != nil || *pointerStruct3.Num != num { - t.Error("Failed to query saved partial nil pointer struct", err) - } - - var normalStruct3 NormalStruct - if err := DB.Table(tableName).First(&normalStruct3, "id = ?", partialNilPointerStruct1.ID).Error; err != nil || normalStruct3.Num != num { - t.Error("Failed to query saved partial pointer struct", err) - } - - var partialNilPointerStruct2 = PointerStruct{Name: &name} - if err := DB.Create(&partialNilPointerStruct2).Error; err != nil { - t.Error("Failed to save partial nil pointer struct", err) - } - - var pointerStruct4 PointerStruct - if err := DB.First(&pointerStruct4, "id = ?", partialNilPointerStruct2.ID).Error; err != nil || *pointerStruct4.Name != name { - t.Error("Failed to query saved partial nil pointer struct", err) - } - - var normalStruct4 NormalStruct - if err := DB.Table(tableName).First(&normalStruct4, "id = ?", partialNilPointerStruct2.ID).Error; err != nil || normalStruct4.Name != name { - t.Error("Failed to query saved partial pointer struct", err) - } -} diff --git a/vendor/github.com/jinzhu/gorm/polymorphic_test.go b/vendor/github.com/jinzhu/gorm/polymorphic_test.go deleted file mode 100644 index d1ecfbbb..00000000 --- a/vendor/github.com/jinzhu/gorm/polymorphic_test.go +++ /dev/null @@ -1,366 +0,0 @@ -package gorm_test - -import ( - "reflect" - "sort" - "testing" -) - -type Cat struct { - Id int - Name string - Toy Toy `gorm:"polymorphic:Owner;"` -} - -type Dog struct { - Id int - Name string - Toys []Toy `gorm:"polymorphic:Owner;"` -} - -type Hamster struct { - Id int - Name string - PreferredToy Toy `gorm:"polymorphic:Owner;polymorphic_value:hamster_preferred"` - OtherToy Toy `gorm:"polymorphic:Owner;polymorphic_value:hamster_other"` -} - -type Toy struct { - Id int - Name string - OwnerId int - OwnerType string -} - -var compareToys = func(toys []Toy, contents []string) bool { - var toyContents []string - for _, toy := range toys { - toyContents = append(toyContents, toy.Name) - } - sort.Strings(toyContents) - sort.Strings(contents) - return reflect.DeepEqual(toyContents, contents) -} - -func TestPolymorphic(t *testing.T) { - cat := Cat{Name: "Mr. Bigglesworth", Toy: Toy{Name: "cat toy"}} - dog := Dog{Name: "Pluto", Toys: []Toy{{Name: "dog toy 1"}, {Name: "dog toy 2"}}} - DB.Save(&cat).Save(&dog) - - if DB.Model(&cat).Association("Toy").Count() != 1 { - t.Errorf("Cat's toys count should be 1") - } - - if DB.Model(&dog).Association("Toys").Count() != 2 { - t.Errorf("Dog's toys count should be 2") - } - - // Query - var catToys []Toy - if DB.Model(&cat).Related(&catToys, "Toy").RecordNotFound() { - t.Errorf("Did not find any has one polymorphic association") - } else if len(catToys) != 1 { - t.Errorf("Should have found only one polymorphic has one association") - } else if catToys[0].Name != cat.Toy.Name { - t.Errorf("Should have found the proper has one polymorphic association") - } - - var dogToys []Toy - if DB.Model(&dog).Related(&dogToys, "Toys").RecordNotFound() { - t.Errorf("Did not find any polymorphic has many associations") - } else if len(dogToys) != len(dog.Toys) { - t.Errorf("Should have found all polymorphic has many associations") - } - - var catToy Toy - DB.Model(&cat).Association("Toy").Find(&catToy) - if catToy.Name != cat.Toy.Name { - t.Errorf("Should find has one polymorphic association") - } - - var dogToys1 []Toy - DB.Model(&dog).Association("Toys").Find(&dogToys1) - if !compareToys(dogToys1, []string{"dog toy 1", "dog toy 2"}) { - t.Errorf("Should find has many polymorphic association") - } - - // Append - DB.Model(&cat).Association("Toy").Append(&Toy{ - Name: "cat toy 2", - }) - - var catToy2 Toy - DB.Model(&cat).Association("Toy").Find(&catToy2) - if catToy2.Name != "cat toy 2" { - t.Errorf("Should update has one polymorphic association with Append") - } - - if DB.Model(&cat).Association("Toy").Count() != 1 { - t.Errorf("Cat's toys count should be 1 after Append") - } - - if DB.Model(&dog).Association("Toys").Count() != 2 { - t.Errorf("Should return two polymorphic has many associations") - } - - DB.Model(&dog).Association("Toys").Append(&Toy{ - Name: "dog toy 3", - }) - - var dogToys2 []Toy - DB.Model(&dog).Association("Toys").Find(&dogToys2) - if !compareToys(dogToys2, []string{"dog toy 1", "dog toy 2", "dog toy 3"}) { - t.Errorf("Dog's toys should be updated with Append") - } - - if DB.Model(&dog).Association("Toys").Count() != 3 { - t.Errorf("Should return three polymorphic has many associations") - } - - // Replace - DB.Model(&cat).Association("Toy").Replace(&Toy{ - Name: "cat toy 3", - }) - - var catToy3 Toy - DB.Model(&cat).Association("Toy").Find(&catToy3) - if catToy3.Name != "cat toy 3" { - t.Errorf("Should update has one polymorphic association with Replace") - } - - if DB.Model(&cat).Association("Toy").Count() != 1 { - t.Errorf("Cat's toys count should be 1 after Replace") - } - - if DB.Model(&dog).Association("Toys").Count() != 3 { - t.Errorf("Should return three polymorphic has many associations") - } - - DB.Model(&dog).Association("Toys").Replace(&Toy{ - Name: "dog toy 4", - }, []Toy{ - {Name: "dog toy 5"}, {Name: "dog toy 6"}, {Name: "dog toy 7"}, - }) - - var dogToys3 []Toy - DB.Model(&dog).Association("Toys").Find(&dogToys3) - if !compareToys(dogToys3, []string{"dog toy 4", "dog toy 5", "dog toy 6", "dog toy 7"}) { - t.Errorf("Dog's toys should be updated with Replace") - } - - if DB.Model(&dog).Association("Toys").Count() != 4 { - t.Errorf("Should return three polymorphic has many associations") - } - - // Delete - DB.Model(&cat).Association("Toy").Delete(&catToy2) - - var catToy4 Toy - DB.Model(&cat).Association("Toy").Find(&catToy4) - if catToy4.Name != "cat toy 3" { - t.Errorf("Should not update has one polymorphic association when Delete a unrelated Toy") - } - - if DB.Model(&cat).Association("Toy").Count() != 1 { - t.Errorf("Cat's toys count should be 1") - } - - if DB.Model(&dog).Association("Toys").Count() != 4 { - t.Errorf("Dog's toys count should be 4") - } - - DB.Model(&cat).Association("Toy").Delete(&catToy3) - - if !DB.Model(&cat).Related(&Toy{}, "Toy").RecordNotFound() { - t.Errorf("Toy should be deleted with Delete") - } - - if DB.Model(&cat).Association("Toy").Count() != 0 { - t.Errorf("Cat's toys count should be 0 after Delete") - } - - if DB.Model(&dog).Association("Toys").Count() != 4 { - t.Errorf("Dog's toys count should not be changed when delete cat's toy") - } - - DB.Model(&dog).Association("Toys").Delete(&dogToys2) - - if DB.Model(&dog).Association("Toys").Count() != 4 { - t.Errorf("Dog's toys count should not be changed when delete unrelated toys") - } - - DB.Model(&dog).Association("Toys").Delete(&dogToys3) - - if DB.Model(&dog).Association("Toys").Count() != 0 { - t.Errorf("Dog's toys count should be deleted with Delete") - } - - // Clear - DB.Model(&cat).Association("Toy").Append(&Toy{ - Name: "cat toy 2", - }) - - if DB.Model(&cat).Association("Toy").Count() != 1 { - t.Errorf("Cat's toys should be added with Append") - } - - DB.Model(&cat).Association("Toy").Clear() - - if DB.Model(&cat).Association("Toy").Count() != 0 { - t.Errorf("Cat's toys should be cleared with Clear") - } - - DB.Model(&dog).Association("Toys").Append(&Toy{ - Name: "dog toy 8", - }) - - if DB.Model(&dog).Association("Toys").Count() != 1 { - t.Errorf("Dog's toys should be added with Append") - } - - DB.Model(&dog).Association("Toys").Clear() - - if DB.Model(&dog).Association("Toys").Count() != 0 { - t.Errorf("Dog's toys should be cleared with Clear") - } -} - -func TestNamedPolymorphic(t *testing.T) { - hamster := Hamster{Name: "Mr. Hammond", PreferredToy: Toy{Name: "bike"}, OtherToy: Toy{Name: "treadmill"}} - DB.Save(&hamster) - - hamster2 := Hamster{} - DB.Preload("PreferredToy").Preload("OtherToy").Find(&hamster2, hamster.Id) - if hamster2.PreferredToy.Id != hamster.PreferredToy.Id || hamster2.PreferredToy.Name != hamster.PreferredToy.Name { - t.Errorf("Hamster's preferred toy couldn't be preloaded") - } - if hamster2.OtherToy.Id != hamster.OtherToy.Id || hamster2.OtherToy.Name != hamster.OtherToy.Name { - t.Errorf("Hamster's other toy couldn't be preloaded") - } - - // clear to omit Toy.Id in count - hamster2.PreferredToy = Toy{} - hamster2.OtherToy = Toy{} - - if DB.Model(&hamster2).Association("PreferredToy").Count() != 1 { - t.Errorf("Hamster's preferred toy count should be 1") - } - - if DB.Model(&hamster2).Association("OtherToy").Count() != 1 { - t.Errorf("Hamster's other toy count should be 1") - } - - // Query - var hamsterToys []Toy - if DB.Model(&hamster).Related(&hamsterToys, "PreferredToy").RecordNotFound() { - t.Errorf("Did not find any has one polymorphic association") - } else if len(hamsterToys) != 1 { - t.Errorf("Should have found only one polymorphic has one association") - } else if hamsterToys[0].Name != hamster.PreferredToy.Name { - t.Errorf("Should have found the proper has one polymorphic association") - } - - if DB.Model(&hamster).Related(&hamsterToys, "OtherToy").RecordNotFound() { - t.Errorf("Did not find any has one polymorphic association") - } else if len(hamsterToys) != 1 { - t.Errorf("Should have found only one polymorphic has one association") - } else if hamsterToys[0].Name != hamster.OtherToy.Name { - t.Errorf("Should have found the proper has one polymorphic association") - } - - hamsterToy := Toy{} - DB.Model(&hamster).Association("PreferredToy").Find(&hamsterToy) - if hamsterToy.Name != hamster.PreferredToy.Name { - t.Errorf("Should find has one polymorphic association") - } - hamsterToy = Toy{} - DB.Model(&hamster).Association("OtherToy").Find(&hamsterToy) - if hamsterToy.Name != hamster.OtherToy.Name { - t.Errorf("Should find has one polymorphic association") - } - - // Append - DB.Model(&hamster).Association("PreferredToy").Append(&Toy{ - Name: "bike 2", - }) - DB.Model(&hamster).Association("OtherToy").Append(&Toy{ - Name: "treadmill 2", - }) - - hamsterToy = Toy{} - DB.Model(&hamster).Association("PreferredToy").Find(&hamsterToy) - if hamsterToy.Name != "bike 2" { - t.Errorf("Should update has one polymorphic association with Append") - } - - hamsterToy = Toy{} - DB.Model(&hamster).Association("OtherToy").Find(&hamsterToy) - if hamsterToy.Name != "treadmill 2" { - t.Errorf("Should update has one polymorphic association with Append") - } - - if DB.Model(&hamster2).Association("PreferredToy").Count() != 1 { - t.Errorf("Hamster's toys count should be 1 after Append") - } - - if DB.Model(&hamster2).Association("OtherToy").Count() != 1 { - t.Errorf("Hamster's toys count should be 1 after Append") - } - - // Replace - DB.Model(&hamster).Association("PreferredToy").Replace(&Toy{ - Name: "bike 3", - }) - DB.Model(&hamster).Association("OtherToy").Replace(&Toy{ - Name: "treadmill 3", - }) - - hamsterToy = Toy{} - DB.Model(&hamster).Association("PreferredToy").Find(&hamsterToy) - if hamsterToy.Name != "bike 3" { - t.Errorf("Should update has one polymorphic association with Replace") - } - - hamsterToy = Toy{} - DB.Model(&hamster).Association("OtherToy").Find(&hamsterToy) - if hamsterToy.Name != "treadmill 3" { - t.Errorf("Should update has one polymorphic association with Replace") - } - - if DB.Model(&hamster2).Association("PreferredToy").Count() != 1 { - t.Errorf("hamster's toys count should be 1 after Replace") - } - - if DB.Model(&hamster2).Association("OtherToy").Count() != 1 { - t.Errorf("hamster's toys count should be 1 after Replace") - } - - // Clear - DB.Model(&hamster).Association("PreferredToy").Append(&Toy{ - Name: "bike 2", - }) - DB.Model(&hamster).Association("OtherToy").Append(&Toy{ - Name: "treadmill 2", - }) - - if DB.Model(&hamster).Association("PreferredToy").Count() != 1 { - t.Errorf("Hamster's toys should be added with Append") - } - if DB.Model(&hamster).Association("OtherToy").Count() != 1 { - t.Errorf("Hamster's toys should be added with Append") - } - - DB.Model(&hamster).Association("PreferredToy").Clear() - - if DB.Model(&hamster2).Association("PreferredToy").Count() != 0 { - t.Errorf("Hamster's preferred toy should be cleared with Clear") - } - if DB.Model(&hamster2).Association("OtherToy").Count() != 1 { - t.Errorf("Hamster's other toy should be still available") - } - - DB.Model(&hamster).Association("OtherToy").Clear() - if DB.Model(&hamster).Association("OtherToy").Count() != 0 { - t.Errorf("Hamster's other toy should be cleared with Clear") - } -} diff --git a/vendor/github.com/jinzhu/gorm/preload_test.go b/vendor/github.com/jinzhu/gorm/preload_test.go deleted file mode 100644 index 1db625c9..00000000 --- a/vendor/github.com/jinzhu/gorm/preload_test.go +++ /dev/null @@ -1,1700 +0,0 @@ -package gorm_test - -import ( - "database/sql" - "encoding/json" - "os" - "reflect" - "testing" - - "github.com/jinzhu/gorm" -) - -func getPreloadUser(name string) *User { - return getPreparedUser(name, "Preload") -} - -func checkUserHasPreloadData(user User, t *testing.T) { - u := getPreloadUser(user.Name) - if user.BillingAddress.Address1 != u.BillingAddress.Address1 { - t.Error("Failed to preload user's BillingAddress") - } - - if user.ShippingAddress.Address1 != u.ShippingAddress.Address1 { - t.Error("Failed to preload user's ShippingAddress") - } - - if user.CreditCard.Number != u.CreditCard.Number { - t.Error("Failed to preload user's CreditCard") - } - - if user.Company.Name != u.Company.Name { - t.Error("Failed to preload user's Company") - } - - if len(user.Emails) != len(u.Emails) { - t.Error("Failed to preload user's Emails") - } else { - var found int - for _, e1 := range u.Emails { - for _, e2 := range user.Emails { - if e1.Email == e2.Email { - found++ - break - } - } - } - if found != len(u.Emails) { - t.Error("Failed to preload user's email details") - } - } -} - -func TestPreload(t *testing.T) { - user1 := getPreloadUser("user1") - DB.Save(user1) - - preloadDB := DB.Where("role = ?", "Preload").Preload("BillingAddress").Preload("ShippingAddress"). - Preload("CreditCard").Preload("Emails").Preload("Company") - var user User - preloadDB.Find(&user) - checkUserHasPreloadData(user, t) - - user2 := getPreloadUser("user2") - DB.Save(user2) - - user3 := getPreloadUser("user3") - DB.Save(user3) - - var users []User - preloadDB.Find(&users) - - for _, user := range users { - checkUserHasPreloadData(user, t) - } - - var users2 []*User - preloadDB.Find(&users2) - - for _, user := range users2 { - checkUserHasPreloadData(*user, t) - } - - var users3 []*User - preloadDB.Preload("Emails", "email = ?", user3.Emails[0].Email).Find(&users3) - - for _, user := range users3 { - if user.Name == user3.Name { - if len(user.Emails) != 1 { - t.Errorf("should only preload one emails for user3 when with condition") - } - } else if len(user.Emails) != 0 { - t.Errorf("should not preload any emails for other users when with condition") - } else if user.Emails == nil { - t.Errorf("should return an empty slice to indicate zero results") - } - } -} - -func TestAutoPreload(t *testing.T) { - user1 := getPreloadUser("auto_user1") - DB.Save(user1) - - preloadDB := DB.Set("gorm:auto_preload", true).Where("role = ?", "Preload") - var user User - preloadDB.Find(&user) - checkUserHasPreloadData(user, t) - - user2 := getPreloadUser("auto_user2") - DB.Save(user2) - - var users []User - preloadDB.Find(&users) - - for _, user := range users { - checkUserHasPreloadData(user, t) - } - - var users2 []*User - preloadDB.Find(&users2) - - for _, user := range users2 { - checkUserHasPreloadData(*user, t) - } -} - -func TestAutoPreloadFalseDoesntPreload(t *testing.T) { - user1 := getPreloadUser("auto_user1") - DB.Save(user1) - - preloadDB := DB.Set("gorm:auto_preload", false).Where("role = ?", "Preload") - var user User - preloadDB.Find(&user) - - if user.BillingAddress.Address1 != "" { - t.Error("AutoPreload was set to fasle, but still fetched data") - } - - user2 := getPreloadUser("auto_user2") - DB.Save(user2) - - var users []User - preloadDB.Find(&users) - - for _, user := range users { - if user.BillingAddress.Address1 != "" { - t.Error("AutoPreload was set to fasle, but still fetched data") - } - } -} - -func TestNestedPreload1(t *testing.T) { - type ( - Level1 struct { - ID uint - Value string - Level2ID uint - } - Level2 struct { - ID uint - Level1 Level1 - Level3ID uint - } - Level3 struct { - ID uint - Name string - Level2 Level2 - } - ) - DB.DropTableIfExists(&Level3{}) - DB.DropTableIfExists(&Level2{}) - DB.DropTableIfExists(&Level1{}) - if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil { - t.Error(err) - } - - want := Level3{Level2: Level2{Level1: Level1{Value: "value"}}} - if err := DB.Create(&want).Error; err != nil { - t.Error(err) - } - - var got Level3 - if err := DB.Preload("Level2").Preload("Level2.Level1").Find(&got).Error; err != nil { - t.Error(err) - } - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want)) - } - - if err := DB.Preload("Level2").Preload("Level2.Level1").Find(&got, "name = ?", "not_found").Error; err != gorm.ErrRecordNotFound { - t.Error(err) - } -} - -func TestNestedPreload2(t *testing.T) { - type ( - Level1 struct { - ID uint - Value string - Level2ID uint - } - Level2 struct { - ID uint - Level1s []*Level1 - Level3ID uint - } - Level3 struct { - ID uint - Name string - Level2s []Level2 - } - ) - DB.DropTableIfExists(&Level3{}) - DB.DropTableIfExists(&Level2{}) - DB.DropTableIfExists(&Level1{}) - if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil { - t.Error(err) - } - - want := Level3{ - Level2s: []Level2{ - { - Level1s: []*Level1{ - {Value: "value1"}, - {Value: "value2"}, - }, - }, - { - Level1s: []*Level1{ - {Value: "value3"}, - }, - }, - }, - } - if err := DB.Create(&want).Error; err != nil { - t.Error(err) - } - - var got Level3 - if err := DB.Preload("Level2s.Level1s").Find(&got).Error; err != nil { - t.Error(err) - } - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want)) - } -} - -func TestNestedPreload3(t *testing.T) { - type ( - Level1 struct { - ID uint - Value string - Level2ID uint - } - Level2 struct { - ID uint - Level1 Level1 - Level3ID uint - } - Level3 struct { - Name string - ID uint - Level2s []Level2 - } - ) - DB.DropTableIfExists(&Level3{}) - DB.DropTableIfExists(&Level2{}) - DB.DropTableIfExists(&Level1{}) - if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil { - t.Error(err) - } - - want := Level3{ - Level2s: []Level2{ - {Level1: Level1{Value: "value1"}}, - {Level1: Level1{Value: "value2"}}, - }, - } - if err := DB.Create(&want).Error; err != nil { - t.Error(err) - } - - var got Level3 - if err := DB.Preload("Level2s.Level1").Find(&got).Error; err != nil { - t.Error(err) - } - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want)) - } -} - -func TestNestedPreload4(t *testing.T) { - type ( - Level1 struct { - ID uint - Value string - Level2ID uint - } - Level2 struct { - ID uint - Level1s []Level1 - Level3ID uint - } - Level3 struct { - ID uint - Name string - Level2 Level2 - } - ) - DB.DropTableIfExists(&Level3{}) - DB.DropTableIfExists(&Level2{}) - DB.DropTableIfExists(&Level1{}) - if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil { - t.Error(err) - } - - want := Level3{ - Level2: Level2{ - Level1s: []Level1{ - {Value: "value1"}, - {Value: "value2"}, - }, - }, - } - if err := DB.Create(&want).Error; err != nil { - t.Error(err) - } - - var got Level3 - if err := DB.Preload("Level2.Level1s").Find(&got).Error; err != nil { - t.Error(err) - } - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want)) - } -} - -// Slice: []Level3 -func TestNestedPreload5(t *testing.T) { - type ( - Level1 struct { - ID uint - Value string - Level2ID uint - } - Level2 struct { - ID uint - Level1 Level1 - Level3ID uint - } - Level3 struct { - ID uint - Name string - Level2 Level2 - } - ) - DB.DropTableIfExists(&Level3{}) - DB.DropTableIfExists(&Level2{}) - DB.DropTableIfExists(&Level1{}) - if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil { - t.Error(err) - } - - want := make([]Level3, 2) - want[0] = Level3{Level2: Level2{Level1: Level1{Value: "value"}}} - if err := DB.Create(&want[0]).Error; err != nil { - t.Error(err) - } - want[1] = Level3{Level2: Level2{Level1: Level1{Value: "value2"}}} - if err := DB.Create(&want[1]).Error; err != nil { - t.Error(err) - } - - var got []Level3 - if err := DB.Preload("Level2").Preload("Level2.Level1").Find(&got).Error; err != nil { - t.Error(err) - } - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want)) - } -} - -func TestNestedPreload6(t *testing.T) { - type ( - Level1 struct { - ID uint - Value string - Level2ID uint - } - Level2 struct { - ID uint - Level1s []Level1 - Level3ID uint - } - Level3 struct { - ID uint - Name string - Level2s []Level2 - } - ) - DB.DropTableIfExists(&Level3{}) - DB.DropTableIfExists(&Level2{}) - DB.DropTableIfExists(&Level1{}) - if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil { - t.Error(err) - } - - want := make([]Level3, 2) - want[0] = Level3{ - Level2s: []Level2{ - { - Level1s: []Level1{ - {Value: "value1"}, - {Value: "value2"}, - }, - }, - { - Level1s: []Level1{ - {Value: "value3"}, - }, - }, - }, - } - if err := DB.Create(&want[0]).Error; err != nil { - t.Error(err) - } - - want[1] = Level3{ - Level2s: []Level2{ - { - Level1s: []Level1{ - {Value: "value3"}, - {Value: "value4"}, - }, - }, - { - Level1s: []Level1{ - {Value: "value5"}, - }, - }, - }, - } - if err := DB.Create(&want[1]).Error; err != nil { - t.Error(err) - } - - var got []Level3 - if err := DB.Preload("Level2s.Level1s").Find(&got).Error; err != nil { - t.Error(err) - } - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want)) - } -} - -func TestNestedPreload7(t *testing.T) { - type ( - Level1 struct { - ID uint - Value string - Level2ID uint - } - Level2 struct { - ID uint - Level1 Level1 - Level3ID uint - } - Level3 struct { - ID uint - Name string - Level2s []Level2 - } - ) - DB.DropTableIfExists(&Level3{}) - DB.DropTableIfExists(&Level2{}) - DB.DropTableIfExists(&Level1{}) - if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil { - t.Error(err) - } - - want := make([]Level3, 2) - want[0] = Level3{ - Level2s: []Level2{ - {Level1: Level1{Value: "value1"}}, - {Level1: Level1{Value: "value2"}}, - }, - } - if err := DB.Create(&want[0]).Error; err != nil { - t.Error(err) - } - - want[1] = Level3{ - Level2s: []Level2{ - {Level1: Level1{Value: "value3"}}, - {Level1: Level1{Value: "value4"}}, - }, - } - if err := DB.Create(&want[1]).Error; err != nil { - t.Error(err) - } - - var got []Level3 - if err := DB.Preload("Level2s.Level1").Find(&got).Error; err != nil { - t.Error(err) - } - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want)) - } -} - -func TestNestedPreload8(t *testing.T) { - type ( - Level1 struct { - ID uint - Value string - Level2ID uint - } - Level2 struct { - ID uint - Level1s []Level1 - Level3ID uint - } - Level3 struct { - ID uint - Name string - Level2 Level2 - } - ) - DB.DropTableIfExists(&Level3{}) - DB.DropTableIfExists(&Level2{}) - DB.DropTableIfExists(&Level1{}) - if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil { - t.Error(err) - } - - want := make([]Level3, 2) - want[0] = Level3{ - Level2: Level2{ - Level1s: []Level1{ - {Value: "value1"}, - {Value: "value2"}, - }, - }, - } - if err := DB.Create(&want[0]).Error; err != nil { - t.Error(err) - } - want[1] = Level3{ - Level2: Level2{ - Level1s: []Level1{ - {Value: "value3"}, - {Value: "value4"}, - }, - }, - } - if err := DB.Create(&want[1]).Error; err != nil { - t.Error(err) - } - - var got []Level3 - if err := DB.Preload("Level2.Level1s").Find(&got).Error; err != nil { - t.Error(err) - } - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want)) - } -} - -func TestNestedPreload9(t *testing.T) { - type ( - Level0 struct { - ID uint - Value string - Level1ID uint - } - Level1 struct { - ID uint - Value string - Level2ID uint - Level2_1ID uint - Level0s []Level0 - } - Level2 struct { - ID uint - Level1s []Level1 - Level3ID uint - } - Level2_1 struct { - ID uint - Level1s []Level1 - Level3ID uint - } - Level3 struct { - ID uint - Name string - Level2 Level2 - Level2_1 Level2_1 - } - ) - DB.DropTableIfExists(&Level3{}) - DB.DropTableIfExists(&Level2{}) - DB.DropTableIfExists(&Level2_1{}) - DB.DropTableIfExists(&Level1{}) - DB.DropTableIfExists(&Level0{}) - if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}, &Level2_1{}, &Level0{}).Error; err != nil { - t.Error(err) - } - - want := make([]Level3, 2) - want[0] = Level3{ - Level2: Level2{ - Level1s: []Level1{ - {Value: "value1"}, - {Value: "value2"}, - }, - }, - Level2_1: Level2_1{ - Level1s: []Level1{ - { - Value: "value1-1", - Level0s: []Level0{{Value: "Level0-1"}}, - }, - { - Value: "value2-2", - Level0s: []Level0{{Value: "Level0-2"}}, - }, - }, - }, - } - if err := DB.Create(&want[0]).Error; err != nil { - t.Error(err) - } - want[1] = Level3{ - Level2: Level2{ - Level1s: []Level1{ - {Value: "value3"}, - {Value: "value4"}, - }, - }, - Level2_1: Level2_1{ - Level1s: []Level1{ - { - Value: "value3-3", - Level0s: []Level0{}, - }, - { - Value: "value4-4", - Level0s: []Level0{}, - }, - }, - }, - } - if err := DB.Create(&want[1]).Error; err != nil { - t.Error(err) - } - - var got []Level3 - if err := DB.Preload("Level2").Preload("Level2.Level1s").Preload("Level2_1").Preload("Level2_1.Level1s").Preload("Level2_1.Level1s.Level0s").Find(&got).Error; err != nil { - t.Error(err) - } - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want)) - } -} - -type LevelA1 struct { - ID uint - Value string -} - -type LevelA2 struct { - ID uint - Value string - LevelA3s []*LevelA3 -} - -type LevelA3 struct { - ID uint - Value string - LevelA1ID sql.NullInt64 - LevelA1 *LevelA1 - LevelA2ID sql.NullInt64 - LevelA2 *LevelA2 -} - -func TestNestedPreload10(t *testing.T) { - DB.DropTableIfExists(&LevelA3{}) - DB.DropTableIfExists(&LevelA2{}) - DB.DropTableIfExists(&LevelA1{}) - - if err := DB.AutoMigrate(&LevelA1{}, &LevelA2{}, &LevelA3{}).Error; err != nil { - t.Error(err) - } - - levelA1 := &LevelA1{Value: "foo"} - if err := DB.Save(levelA1).Error; err != nil { - t.Error(err) - } - - want := []*LevelA2{ - { - Value: "bar", - LevelA3s: []*LevelA3{ - { - Value: "qux", - LevelA1: levelA1, - }, - }, - }, - { - Value: "bar 2", - LevelA3s: []*LevelA3{}, - }, - } - for _, levelA2 := range want { - if err := DB.Save(levelA2).Error; err != nil { - t.Error(err) - } - } - - var got []*LevelA2 - if err := DB.Preload("LevelA3s.LevelA1").Find(&got).Error; err != nil { - t.Error(err) - } - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want)) - } -} - -type LevelB1 struct { - ID uint - Value string - LevelB3s []*LevelB3 -} - -type LevelB2 struct { - ID uint - Value string -} - -type LevelB3 struct { - ID uint - Value string - LevelB1ID sql.NullInt64 - LevelB1 *LevelB1 - LevelB2s []*LevelB2 `gorm:"many2many:levelb1_levelb3_levelb2s"` -} - -func TestNestedPreload11(t *testing.T) { - DB.DropTableIfExists(&LevelB2{}) - DB.DropTableIfExists(&LevelB3{}) - DB.DropTableIfExists(&LevelB1{}) - if err := DB.AutoMigrate(&LevelB1{}, &LevelB2{}, &LevelB3{}).Error; err != nil { - t.Error(err) - } - - levelB1 := &LevelB1{Value: "foo"} - if err := DB.Create(levelB1).Error; err != nil { - t.Error(err) - } - - levelB3 := &LevelB3{ - Value: "bar", - LevelB1ID: sql.NullInt64{Valid: true, Int64: int64(levelB1.ID)}, - } - if err := DB.Create(levelB3).Error; err != nil { - t.Error(err) - } - levelB1.LevelB3s = []*LevelB3{levelB3} - - want := []*LevelB1{levelB1} - var got []*LevelB1 - if err := DB.Preload("LevelB3s.LevelB2s").Find(&got).Error; err != nil { - t.Error(err) - } - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want)) - } -} - -type LevelC1 struct { - ID uint - Value string - LevelC2ID uint -} - -type LevelC2 struct { - ID uint - Value string - LevelC1 LevelC1 -} - -type LevelC3 struct { - ID uint - Value string - LevelC2ID uint - LevelC2 LevelC2 -} - -func TestNestedPreload12(t *testing.T) { - DB.DropTableIfExists(&LevelC2{}) - DB.DropTableIfExists(&LevelC3{}) - DB.DropTableIfExists(&LevelC1{}) - if err := DB.AutoMigrate(&LevelC1{}, &LevelC2{}, &LevelC3{}).Error; err != nil { - t.Error(err) - } - - level2 := LevelC2{ - Value: "c2", - LevelC1: LevelC1{ - Value: "c1", - }, - } - DB.Create(&level2) - - want := []LevelC3{ - { - Value: "c3-1", - LevelC2: level2, - }, { - Value: "c3-2", - LevelC2: level2, - }, - } - - for i := range want { - if err := DB.Create(&want[i]).Error; err != nil { - t.Error(err) - } - } - - var got []LevelC3 - if err := DB.Preload("LevelC2").Preload("LevelC2.LevelC1").Find(&got).Error; err != nil { - t.Error(err) - } - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want)) - } -} - -func TestManyToManyPreloadWithMultiPrimaryKeys(t *testing.T) { - if dialect := os.Getenv("GORM_DIALECT"); dialect == "" || dialect == "sqlite" || dialect == "mssql" { - return - } - - type ( - Level1 struct { - ID uint `gorm:"primary_key;"` - LanguageCode string `gorm:"primary_key"` - Value string - } - Level2 struct { - ID uint `gorm:"primary_key;"` - LanguageCode string `gorm:"primary_key"` - Value string - Level1s []Level1 `gorm:"many2many:levels;"` - } - ) - - DB.DropTableIfExists(&Level2{}) - DB.DropTableIfExists(&Level1{}) - DB.DropTableIfExists("levels") - - if err := DB.AutoMigrate(&Level2{}, &Level1{}).Error; err != nil { - t.Error(err) - } - - want := Level2{Value: "Bob", LanguageCode: "ru", Level1s: []Level1{ - {Value: "ru", LanguageCode: "ru"}, - {Value: "en", LanguageCode: "en"}, - }} - if err := DB.Save(&want).Error; err != nil { - t.Error(err) - } - - want2 := Level2{Value: "Tom", LanguageCode: "zh", Level1s: []Level1{ - {Value: "zh", LanguageCode: "zh"}, - {Value: "de", LanguageCode: "de"}, - }} - if err := DB.Save(&want2).Error; err != nil { - t.Error(err) - } - - var got Level2 - if err := DB.Preload("Level1s").Find(&got, "value = ?", "Bob").Error; err != nil { - t.Error(err) - } - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want)) - } - - var got2 Level2 - if err := DB.Preload("Level1s").Find(&got2, "value = ?", "Tom").Error; err != nil { - t.Error(err) - } - - if !reflect.DeepEqual(got2, want2) { - t.Errorf("got %s; want %s", toJSONString(got2), toJSONString(want2)) - } - - var got3 []Level2 - if err := DB.Preload("Level1s").Find(&got3, "value IN (?)", []string{"Bob", "Tom"}).Error; err != nil { - t.Error(err) - } - - if !reflect.DeepEqual(got3, []Level2{got, got2}) { - t.Errorf("got %s; want %s", toJSONString(got3), toJSONString([]Level2{got, got2})) - } - - var got4 []Level2 - if err := DB.Preload("Level1s", "value IN (?)", []string{"zh", "ru"}).Find(&got4, "value IN (?)", []string{"Bob", "Tom"}).Error; err != nil { - t.Error(err) - } - - var ruLevel1 Level1 - var zhLevel1 Level1 - DB.First(&ruLevel1, "value = ?", "ru") - DB.First(&zhLevel1, "value = ?", "zh") - - got.Level1s = []Level1{ruLevel1} - got2.Level1s = []Level1{zhLevel1} - if !reflect.DeepEqual(got4, []Level2{got, got2}) { - t.Errorf("got %s; want %s", toJSONString(got4), toJSONString([]Level2{got, got2})) - } - - if err := DB.Preload("Level1s").Find(&got4, "value IN (?)", []string{"non-existing"}).Error; err != nil { - t.Error(err) - } -} - -func TestManyToManyPreloadForNestedPointer(t *testing.T) { - type ( - Level1 struct { - ID uint - Value string - } - Level2 struct { - ID uint - Value string - Level1s []*Level1 `gorm:"many2many:levels;"` - } - Level3 struct { - ID uint - Value string - Level2ID sql.NullInt64 - Level2 *Level2 - } - ) - - DB.DropTableIfExists(&Level3{}) - DB.DropTableIfExists(&Level2{}) - DB.DropTableIfExists(&Level1{}) - DB.DropTableIfExists("levels") - - if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil { - t.Error(err) - } - - want := Level3{ - Value: "Bob", - Level2: &Level2{ - Value: "Foo", - Level1s: []*Level1{ - {Value: "ru"}, - {Value: "en"}, - }, - }, - } - if err := DB.Save(&want).Error; err != nil { - t.Error(err) - } - - want2 := Level3{ - Value: "Tom", - Level2: &Level2{ - Value: "Bar", - Level1s: []*Level1{ - {Value: "zh"}, - {Value: "de"}, - }, - }, - } - if err := DB.Save(&want2).Error; err != nil { - t.Error(err) - } - - var got Level3 - if err := DB.Preload("Level2.Level1s").Find(&got, "value = ?", "Bob").Error; err != nil { - t.Error(err) - } - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want)) - } - - var got2 Level3 - if err := DB.Preload("Level2.Level1s").Find(&got2, "value = ?", "Tom").Error; err != nil { - t.Error(err) - } - - if !reflect.DeepEqual(got2, want2) { - t.Errorf("got %s; want %s", toJSONString(got2), toJSONString(want2)) - } - - var got3 []Level3 - if err := DB.Preload("Level2.Level1s").Find(&got3, "value IN (?)", []string{"Bob", "Tom"}).Error; err != nil { - t.Error(err) - } - - if !reflect.DeepEqual(got3, []Level3{got, got2}) { - t.Errorf("got %s; want %s", toJSONString(got3), toJSONString([]Level3{got, got2})) - } - - var got4 []Level3 - if err := DB.Preload("Level2.Level1s", "value IN (?)", []string{"zh", "ru"}).Find(&got4, "value IN (?)", []string{"Bob", "Tom"}).Error; err != nil { - t.Error(err) - } - - var got5 Level3 - DB.Preload("Level2.Level1s").Find(&got5, "value = ?", "bogus") - - var ruLevel1 Level1 - var zhLevel1 Level1 - DB.First(&ruLevel1, "value = ?", "ru") - DB.First(&zhLevel1, "value = ?", "zh") - - got.Level2.Level1s = []*Level1{&ruLevel1} - got2.Level2.Level1s = []*Level1{&zhLevel1} - if !reflect.DeepEqual(got4, []Level3{got, got2}) { - t.Errorf("got %s; want %s", toJSONString(got4), toJSONString([]Level3{got, got2})) - } -} - -func TestNestedManyToManyPreload(t *testing.T) { - type ( - Level1 struct { - ID uint - Value string - } - Level2 struct { - ID uint - Value string - Level1s []*Level1 `gorm:"many2many:level1_level2;"` - } - Level3 struct { - ID uint - Value string - Level2s []Level2 `gorm:"many2many:level2_level3;"` - } - ) - - DB.DropTableIfExists(&Level1{}) - DB.DropTableIfExists(&Level2{}) - DB.DropTableIfExists(&Level3{}) - DB.DropTableIfExists("level1_level2") - DB.DropTableIfExists("level2_level3") - - if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil { - t.Error(err) - } - - want := Level3{ - Value: "Level3", - Level2s: []Level2{ - { - Value: "Bob", - Level1s: []*Level1{ - {Value: "ru"}, - {Value: "en"}, - }, - }, { - Value: "Tom", - Level1s: []*Level1{ - {Value: "zh"}, - {Value: "de"}, - }, - }, - }, - } - - if err := DB.Save(&want).Error; err != nil { - t.Error(err) - } - - var got Level3 - if err := DB.Preload("Level2s").Preload("Level2s.Level1s").Find(&got, "value = ?", "Level3").Error; err != nil { - t.Error(err) - } - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want)) - } - - if err := DB.Preload("Level2s.Level1s").Find(&got, "value = ?", "not_found").Error; err != gorm.ErrRecordNotFound { - t.Error(err) - } -} - -func TestNestedManyToManyPreload2(t *testing.T) { - type ( - Level1 struct { - ID uint - Value string - } - Level2 struct { - ID uint - Value string - Level1s []*Level1 `gorm:"many2many:level1_level2;"` - } - Level3 struct { - ID uint - Value string - Level2ID sql.NullInt64 - Level2 *Level2 - } - ) - - DB.DropTableIfExists(&Level1{}) - DB.DropTableIfExists(&Level2{}) - DB.DropTableIfExists(&Level3{}) - DB.DropTableIfExists("level1_level2") - - if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil { - t.Error(err) - } - - want := Level3{ - Value: "Level3", - Level2: &Level2{ - Value: "Bob", - Level1s: []*Level1{ - {Value: "ru"}, - {Value: "en"}, - }, - }, - } - - if err := DB.Save(&want).Error; err != nil { - t.Error(err) - } - - var got Level3 - if err := DB.Preload("Level2.Level1s").Find(&got, "value = ?", "Level3").Error; err != nil { - t.Error(err) - } - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want)) - } - - if err := DB.Preload("Level2.Level1s").Find(&got, "value = ?", "not_found").Error; err != gorm.ErrRecordNotFound { - t.Error(err) - } -} - -func TestNestedManyToManyPreload3(t *testing.T) { - type ( - Level1 struct { - ID uint - Value string - } - Level2 struct { - ID uint - Value string - Level1s []*Level1 `gorm:"many2many:level1_level2;"` - } - Level3 struct { - ID uint - Value string - Level2ID sql.NullInt64 - Level2 *Level2 - } - ) - - DB.DropTableIfExists(&Level1{}) - DB.DropTableIfExists(&Level2{}) - DB.DropTableIfExists(&Level3{}) - DB.DropTableIfExists("level1_level2") - - if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil { - t.Error(err) - } - - level1Zh := &Level1{Value: "zh"} - level1Ru := &Level1{Value: "ru"} - level1En := &Level1{Value: "en"} - - level21 := &Level2{ - Value: "Level2-1", - Level1s: []*Level1{level1Zh, level1Ru}, - } - - level22 := &Level2{ - Value: "Level2-2", - Level1s: []*Level1{level1Zh, level1En}, - } - - wants := []*Level3{ - { - Value: "Level3-1", - Level2: level21, - }, - { - Value: "Level3-2", - Level2: level22, - }, - { - Value: "Level3-3", - Level2: level21, - }, - } - - for _, want := range wants { - if err := DB.Save(&want).Error; err != nil { - t.Error(err) - } - } - - var gots []*Level3 - if err := DB.Preload("Level2.Level1s", func(db *gorm.DB) *gorm.DB { - return db.Order("level1.id ASC") - }).Find(&gots).Error; err != nil { - t.Error(err) - } - - if !reflect.DeepEqual(gots, wants) { - t.Errorf("got %s; want %s", toJSONString(gots), toJSONString(wants)) - } -} - -func TestNestedManyToManyPreload3ForStruct(t *testing.T) { - type ( - Level1 struct { - ID uint - Value string - } - Level2 struct { - ID uint - Value string - Level1s []Level1 `gorm:"many2many:level1_level2;"` - } - Level3 struct { - ID uint - Value string - Level2ID sql.NullInt64 - Level2 Level2 - } - ) - - DB.DropTableIfExists(&Level1{}) - DB.DropTableIfExists(&Level2{}) - DB.DropTableIfExists(&Level3{}) - DB.DropTableIfExists("level1_level2") - - if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil { - t.Error(err) - } - - level1Zh := Level1{Value: "zh"} - level1Ru := Level1{Value: "ru"} - level1En := Level1{Value: "en"} - - level21 := Level2{ - Value: "Level2-1", - Level1s: []Level1{level1Zh, level1Ru}, - } - - level22 := Level2{ - Value: "Level2-2", - Level1s: []Level1{level1Zh, level1En}, - } - - wants := []*Level3{ - { - Value: "Level3-1", - Level2: level21, - }, - { - Value: "Level3-2", - Level2: level22, - }, - { - Value: "Level3-3", - Level2: level21, - }, - } - - for _, want := range wants { - if err := DB.Save(&want).Error; err != nil { - t.Error(err) - } - } - - var gots []*Level3 - if err := DB.Preload("Level2.Level1s", func(db *gorm.DB) *gorm.DB { - return db.Order("level1.id ASC") - }).Find(&gots).Error; err != nil { - t.Error(err) - } - - if !reflect.DeepEqual(gots, wants) { - t.Errorf("got %s; want %s", toJSONString(gots), toJSONString(wants)) - } -} - -func TestNestedManyToManyPreload4(t *testing.T) { - type ( - Level4 struct { - ID uint - Value string - Level3ID uint - } - Level3 struct { - ID uint - Value string - Level4s []*Level4 - } - Level2 struct { - ID uint - Value string - Level3s []*Level3 `gorm:"many2many:level2_level3;"` - } - Level1 struct { - ID uint - Value string - Level2s []*Level2 `gorm:"many2many:level1_level2;"` - } - ) - - DB.DropTableIfExists(&Level1{}) - DB.DropTableIfExists(&Level2{}) - DB.DropTableIfExists(&Level3{}) - DB.DropTableIfExists(&Level4{}) - DB.DropTableIfExists("level1_level2") - DB.DropTableIfExists("level2_level3") - - dummy := Level1{ - Value: "Level1", - Level2s: []*Level2{{ - Value: "Level2", - Level3s: []*Level3{{ - Value: "Level3", - Level4s: []*Level4{{ - Value: "Level4", - }}, - }}, - }}, - } - - if err := DB.AutoMigrate(&Level4{}, &Level3{}, &Level2{}, &Level1{}).Error; err != nil { - t.Error(err) - } - - if err := DB.Save(&dummy).Error; err != nil { - t.Error(err) - } - - var level1 Level1 - if err := DB.Preload("Level2s").Preload("Level2s.Level3s").Preload("Level2s.Level3s.Level4s").First(&level1).Error; err != nil { - t.Error(err) - } -} - -func TestManyToManyPreloadForPointer(t *testing.T) { - type ( - Level1 struct { - ID uint - Value string - } - Level2 struct { - ID uint - Value string - Level1s []*Level1 `gorm:"many2many:levels;"` - } - ) - - DB.DropTableIfExists(&Level2{}) - DB.DropTableIfExists(&Level1{}) - DB.DropTableIfExists("levels") - - if err := DB.AutoMigrate(&Level2{}, &Level1{}).Error; err != nil { - t.Error(err) - } - - want := Level2{Value: "Bob", Level1s: []*Level1{ - {Value: "ru"}, - {Value: "en"}, - }} - if err := DB.Save(&want).Error; err != nil { - t.Error(err) - } - - want2 := Level2{Value: "Tom", Level1s: []*Level1{ - {Value: "zh"}, - {Value: "de"}, - }} - if err := DB.Save(&want2).Error; err != nil { - t.Error(err) - } - - var got Level2 - if err := DB.Preload("Level1s").Find(&got, "value = ?", "Bob").Error; err != nil { - t.Error(err) - } - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want)) - } - - var got2 Level2 - if err := DB.Preload("Level1s").Find(&got2, "value = ?", "Tom").Error; err != nil { - t.Error(err) - } - - if !reflect.DeepEqual(got2, want2) { - t.Errorf("got %s; want %s", toJSONString(got2), toJSONString(want2)) - } - - var got3 []Level2 - if err := DB.Preload("Level1s").Find(&got3, "value IN (?)", []string{"Bob", "Tom"}).Error; err != nil { - t.Error(err) - } - - if !reflect.DeepEqual(got3, []Level2{got, got2}) { - t.Errorf("got %s; want %s", toJSONString(got3), toJSONString([]Level2{got, got2})) - } - - var got4 []Level2 - if err := DB.Preload("Level1s", "value IN (?)", []string{"zh", "ru"}).Find(&got4, "value IN (?)", []string{"Bob", "Tom"}).Error; err != nil { - t.Error(err) - } - - var got5 Level2 - DB.Preload("Level1s").First(&got5, "value = ?", "bogus") - - var ruLevel1 Level1 - var zhLevel1 Level1 - DB.First(&ruLevel1, "value = ?", "ru") - DB.First(&zhLevel1, "value = ?", "zh") - - got.Level1s = []*Level1{&ruLevel1} - got2.Level1s = []*Level1{&zhLevel1} - if !reflect.DeepEqual(got4, []Level2{got, got2}) { - t.Errorf("got %s; want %s", toJSONString(got4), toJSONString([]Level2{got, got2})) - } -} - -func TestNilPointerSlice(t *testing.T) { - type ( - Level3 struct { - ID uint - Value string - } - Level2 struct { - ID uint - Value string - Level3ID uint - Level3 *Level3 - } - Level1 struct { - ID uint - Value string - Level2ID uint - Level2 *Level2 - } - ) - - DB.DropTableIfExists(&Level3{}) - DB.DropTableIfExists(&Level2{}) - DB.DropTableIfExists(&Level1{}) - - if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil { - t.Error(err) - } - - want := Level1{ - Value: "Bob", - Level2: &Level2{ - Value: "en", - Level3: &Level3{ - Value: "native", - }, - }, - } - if err := DB.Save(&want).Error; err != nil { - t.Error(err) - } - - want2 := Level1{ - Value: "Tom", - Level2: nil, - } - if err := DB.Save(&want2).Error; err != nil { - t.Error(err) - } - - var got []Level1 - if err := DB.Preload("Level2").Preload("Level2.Level3").Find(&got).Error; err != nil { - t.Error(err) - } - - if len(got) != 2 { - t.Errorf("got %v items, expected 2", len(got)) - } - - if !reflect.DeepEqual(got[0], want) && !reflect.DeepEqual(got[1], want) { - t.Errorf("got %s; want array containing %s", toJSONString(got), toJSONString(want)) - } - - if !reflect.DeepEqual(got[0], want2) && !reflect.DeepEqual(got[1], want2) { - t.Errorf("got %s; want array containing %s", toJSONString(got), toJSONString(want2)) - } -} - -func TestNilPointerSlice2(t *testing.T) { - type ( - Level4 struct { - ID uint - } - Level3 struct { - ID uint - Level4ID sql.NullInt64 `sql:"index"` - Level4 *Level4 - } - Level2 struct { - ID uint - Level3s []*Level3 `gorm:"many2many:level2_level3s"` - } - Level1 struct { - ID uint - Level2ID sql.NullInt64 `sql:"index"` - Level2 *Level2 - } - ) - - DB.DropTableIfExists(new(Level4)) - DB.DropTableIfExists(new(Level3)) - DB.DropTableIfExists(new(Level2)) - DB.DropTableIfExists(new(Level1)) - - if err := DB.AutoMigrate(new(Level4), new(Level3), new(Level2), new(Level1)).Error; err != nil { - t.Error(err) - } - - want := new(Level1) - if err := DB.Save(want).Error; err != nil { - t.Error(err) - } - - got := new(Level1) - err := DB.Preload("Level2.Level3s.Level4").Last(&got).Error - if err != nil { - t.Error(err) - } - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want)) - } -} - -func TestPrefixedPreloadDuplication(t *testing.T) { - type ( - Level4 struct { - ID uint - Name string - Level3ID uint - } - Level3 struct { - ID uint - Name string - Level4s []*Level4 - } - Level2 struct { - ID uint - Name string - Level3ID sql.NullInt64 `sql:"index"` - Level3 *Level3 - } - Level1 struct { - ID uint - Name string - Level2ID sql.NullInt64 `sql:"index"` - Level2 *Level2 - } - ) - - DB.DropTableIfExists(new(Level3)) - DB.DropTableIfExists(new(Level4)) - DB.DropTableIfExists(new(Level2)) - DB.DropTableIfExists(new(Level1)) - - if err := DB.AutoMigrate(new(Level3), new(Level4), new(Level2), new(Level1)).Error; err != nil { - t.Error(err) - } - - lvl := &Level3{} - if err := DB.Save(lvl).Error; err != nil { - t.Error(err) - } - - sublvl1 := &Level4{Level3ID: lvl.ID} - if err := DB.Save(sublvl1).Error; err != nil { - t.Error(err) - } - sublvl2 := &Level4{Level3ID: lvl.ID} - if err := DB.Save(sublvl2).Error; err != nil { - t.Error(err) - } - - lvl.Level4s = []*Level4{sublvl1, sublvl2} - - want1 := Level1{ - Level2: &Level2{ - Level3: lvl, - }, - } - if err := DB.Save(&want1).Error; err != nil { - t.Error(err) - } - - want2 := Level1{ - Level2: &Level2{ - Level3: lvl, - }, - } - if err := DB.Save(&want2).Error; err != nil { - t.Error(err) - } - - want := []Level1{want1, want2} - - var got []Level1 - err := DB.Preload("Level2.Level3.Level4s").Find(&got).Error - if err != nil { - t.Error(err) - } - - if !reflect.DeepEqual(got, want) { - t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want)) - } -} - -func TestPreloadManyToManyCallbacks(t *testing.T) { - type ( - Level2 struct { - ID uint - Name string - } - Level1 struct { - ID uint - Name string - Level2s []Level2 `gorm:"many2many:level1_level2s;AssociationForeignKey:ID;ForeignKey:ID"` - } - ) - - DB.DropTableIfExists("level1_level2s") - DB.DropTableIfExists(new(Level1)) - DB.DropTableIfExists(new(Level2)) - - if err := DB.AutoMigrate(new(Level1), new(Level2)).Error; err != nil { - t.Error(err) - } - - lvl := Level1{ - Name: "l1", - Level2s: []Level2{ - Level2{Name: "l2-1"}, Level2{Name: "l2-2"}, - }, - } - DB.Save(&lvl) - - called := 0 - - DB.Callback().Query().After("gorm:query").Register("TestPreloadManyToManyCallbacks", func(scope *gorm.Scope) { - called = called + 1 - }) - - DB.Preload("Level2s").First(&Level1{}, "id = ?", lvl.ID) - - if called != 3 { - t.Errorf("Wanted callback to be called 3 times but got %d", called) - } -} - -func toJSONString(v interface{}) []byte { - r, _ := json.MarshalIndent(v, "", " ") - return r -} diff --git a/vendor/github.com/jinzhu/gorm/query_test.go b/vendor/github.com/jinzhu/gorm/query_test.go deleted file mode 100644 index 15bf8b3c..00000000 --- a/vendor/github.com/jinzhu/gorm/query_test.go +++ /dev/null @@ -1,773 +0,0 @@ -package gorm_test - -import ( - "fmt" - "reflect" - - "github.com/jinzhu/gorm" - - "testing" - "time" -) - -func TestFirstAndLast(t *testing.T) { - DB.Save(&User{Name: "user1", Emails: []Email{{Email: "user1@example.com"}}}) - DB.Save(&User{Name: "user2", Emails: []Email{{Email: "user2@example.com"}}}) - - var user1, user2, user3, user4 User - DB.First(&user1) - DB.Order("id").Limit(1).Find(&user2) - - ptrOfUser3 := &user3 - DB.Last(&ptrOfUser3) - DB.Order("id desc").Limit(1).Find(&user4) - if user1.Id != user2.Id || user3.Id != user4.Id { - t.Errorf("First and Last should by order by primary key") - } - - var users []User - DB.First(&users) - if len(users) != 1 { - t.Errorf("Find first record as slice") - } - - var user User - if DB.Joins("left join emails on emails.user_id = users.id").First(&user).Error != nil { - t.Errorf("Should not raise any error when order with Join table") - } - - if user.Email != "" { - t.Errorf("User's Email should be blank as no one set it") - } -} - -func TestFirstAndLastWithNoStdPrimaryKey(t *testing.T) { - DB.Save(&Animal{Name: "animal1"}) - DB.Save(&Animal{Name: "animal2"}) - - var animal1, animal2, animal3, animal4 Animal - DB.First(&animal1) - DB.Order("counter").Limit(1).Find(&animal2) - - DB.Last(&animal3) - DB.Order("counter desc").Limit(1).Find(&animal4) - if animal1.Counter != animal2.Counter || animal3.Counter != animal4.Counter { - t.Errorf("First and Last should work correctly") - } -} - -func TestFirstAndLastWithRaw(t *testing.T) { - user1 := User{Name: "user", Emails: []Email{{Email: "user1@example.com"}}} - user2 := User{Name: "user", Emails: []Email{{Email: "user2@example.com"}}} - DB.Save(&user1) - DB.Save(&user2) - - var user3, user4 User - DB.Raw("select * from users WHERE name = ?", "user").First(&user3) - if user3.Id != user1.Id { - t.Errorf("Find first record with raw") - } - - DB.Raw("select * from users WHERE name = ?", "user").Last(&user4) - if user4.Id != user2.Id { - t.Errorf("Find last record with raw") - } -} - -func TestUIntPrimaryKey(t *testing.T) { - var animal Animal - DB.First(&animal, uint64(1)) - if animal.Counter != 1 { - t.Errorf("Fetch a record from with a non-int primary key should work, but failed") - } - - DB.Model(Animal{}).Where(Animal{Counter: uint64(2)}).Scan(&animal) - if animal.Counter != 2 { - t.Errorf("Fetch a record from with a non-int primary key should work, but failed") - } -} - -func TestCustomizedTypePrimaryKey(t *testing.T) { - type ID uint - type CustomizedTypePrimaryKey struct { - ID ID - Name string - } - - DB.AutoMigrate(&CustomizedTypePrimaryKey{}) - - p1 := CustomizedTypePrimaryKey{Name: "p1"} - p2 := CustomizedTypePrimaryKey{Name: "p2"} - p3 := CustomizedTypePrimaryKey{Name: "p3"} - DB.Create(&p1) - DB.Create(&p2) - DB.Create(&p3) - - var p CustomizedTypePrimaryKey - - if err := DB.First(&p, p2.ID).Error; err == nil { - t.Errorf("Should return error for invalid query condition") - } - - if err := DB.First(&p, "id = ?", p2.ID).Error; err != nil { - t.Errorf("No error should happen when querying with customized type for primary key, got err %v", err) - } - - if p.Name != "p2" { - t.Errorf("Should find correct value when querying with customized type for primary key") - } -} - -func TestStringPrimaryKeyForNumericValueStartingWithZero(t *testing.T) { - type AddressByZipCode struct { - ZipCode string `gorm:"primary_key"` - Address string - } - - DB.AutoMigrate(&AddressByZipCode{}) - DB.Create(&AddressByZipCode{ZipCode: "00501", Address: "Holtsville"}) - - var address AddressByZipCode - DB.First(&address, "00501") - if address.ZipCode != "00501" { - t.Errorf("Fetch a record from with a string primary key for a numeric value starting with zero should work, but failed, zip code is %v", address.ZipCode) - } -} - -func TestFindAsSliceOfPointers(t *testing.T) { - DB.Save(&User{Name: "user"}) - - var users []User - DB.Find(&users) - - var userPointers []*User - DB.Find(&userPointers) - - if len(users) == 0 || len(users) != len(userPointers) { - t.Errorf("Find slice of pointers") - } -} - -func TestSearchWithPlainSQL(t *testing.T) { - user1 := User{Name: "PlainSqlUser1", Age: 1, Birthday: parseTime("2000-1-1")} - user2 := User{Name: "PlainSqlUser2", Age: 10, Birthday: parseTime("2010-1-1")} - user3 := User{Name: "PlainSqlUser3", Age: 20, Birthday: parseTime("2020-1-1")} - DB.Save(&user1).Save(&user2).Save(&user3) - scopedb := DB.Where("name LIKE ?", "%PlainSqlUser%") - - if DB.Where("name = ?", user1.Name).First(&User{}).RecordNotFound() { - t.Errorf("Search with plain SQL") - } - - if DB.Where("name LIKE ?", "%"+user1.Name+"%").First(&User{}).RecordNotFound() { - t.Errorf("Search with plan SQL (regexp)") - } - - var users []User - DB.Find(&users, "name LIKE ? and age > ?", "%PlainSqlUser%", 1) - if len(users) != 2 { - t.Errorf("Should found 2 users that age > 1, but got %v", len(users)) - } - - DB.Where("name LIKE ?", "%PlainSqlUser%").Where("age >= ?", 1).Find(&users) - if len(users) != 3 { - t.Errorf("Should found 3 users that age >= 1, but got %v", len(users)) - } - - scopedb.Where("age <> ?", 20).Find(&users) - if len(users) != 2 { - t.Errorf("Should found 2 users age != 20, but got %v", len(users)) - } - - scopedb.Where("birthday > ?", parseTime("2000-1-1")).Find(&users) - if len(users) != 2 { - t.Errorf("Should found 2 users' birthday > 2000-1-1, but got %v", len(users)) - } - - scopedb.Where("birthday > ?", "2002-10-10").Find(&users) - if len(users) != 2 { - t.Errorf("Should found 2 users' birthday >= 2002-10-10, but got %v", len(users)) - } - - scopedb.Where("birthday >= ?", "2010-1-1").Where("birthday < ?", "2020-1-1").Find(&users) - if len(users) != 1 { - t.Errorf("Should found 1 users' birthday < 2020-1-1 and >= 2010-1-1, but got %v", len(users)) - } - - DB.Where("name in (?)", []string{user1.Name, user2.Name}).Find(&users) - if len(users) != 2 { - t.Errorf("Should found 2 users, but got %v", len(users)) - } - - DB.Where("id in (?)", []int64{user1.Id, user2.Id, user3.Id}).Find(&users) - if len(users) != 3 { - t.Errorf("Should found 3 users, but got %v", len(users)) - } - - DB.Where("id in (?)", user1.Id).Find(&users) - if len(users) != 1 { - t.Errorf("Should found 1 users, but got %v", len(users)) - } - - if err := DB.Where("id IN (?)", []string{}).Find(&users).Error; err != nil { - t.Error("no error should happen when query with empty slice, but got: ", err) - } - - if err := DB.Not("id IN (?)", []string{}).Find(&users).Error; err != nil { - t.Error("no error should happen when query with empty slice, but got: ", err) - } - - if DB.Where("name = ?", "none existing").Find(&[]User{}).RecordNotFound() { - t.Errorf("Should not get RecordNotFound error when looking for none existing records") - } -} - -func TestSearchWithTwoDimensionalArray(t *testing.T) { - var users []User - user1 := User{Name: "2DSearchUser1", Age: 1, Birthday: parseTime("2000-1-1")} - user2 := User{Name: "2DSearchUser2", Age: 10, Birthday: parseTime("2010-1-1")} - user3 := User{Name: "2DSearchUser3", Age: 20, Birthday: parseTime("2020-1-1")} - DB.Create(&user1) - DB.Create(&user2) - DB.Create(&user3) - - if dialect := DB.Dialect().GetName(); dialect == "mysql" || dialect == "postgres" { - if err := DB.Where("(name, age) IN (?)", [][]interface{}{{"2DSearchUser1", 1}, {"2DSearchUser2", 10}}).Find(&users).Error; err != nil { - t.Errorf("No error should happen when query with 2D array, but got %v", err) - - if len(users) != 2 { - t.Errorf("Should find 2 users with 2D array, but got %v", len(users)) - } - } - } - - if dialect := DB.Dialect().GetName(); dialect == "mssql" { - if err := DB.Joins("JOIN (VALUES ?) AS x (col1, col2) ON x.col1 = name AND x.col2 = age", [][]interface{}{{"2DSearchUser1", 1}, {"2DSearchUser2", 10}}).Find(&users).Error; err != nil { - t.Errorf("No error should happen when query with 2D array, but got %v", err) - - if len(users) != 2 { - t.Errorf("Should find 2 users with 2D array, but got %v", len(users)) - } - } - } -} - -func TestSearchWithStruct(t *testing.T) { - user1 := User{Name: "StructSearchUser1", Age: 1, Birthday: parseTime("2000-1-1")} - user2 := User{Name: "StructSearchUser2", Age: 10, Birthday: parseTime("2010-1-1")} - user3 := User{Name: "StructSearchUser3", Age: 20, Birthday: parseTime("2020-1-1")} - DB.Save(&user1).Save(&user2).Save(&user3) - - if DB.Where(user1.Id).First(&User{}).RecordNotFound() { - t.Errorf("Search with primary key") - } - - if DB.First(&User{}, user1.Id).RecordNotFound() { - t.Errorf("Search with primary key as inline condition") - } - - if DB.First(&User{}, fmt.Sprintf("%v", user1.Id)).RecordNotFound() { - t.Errorf("Search with primary key as inline condition") - } - - var users []User - DB.Where([]int64{user1.Id, user2.Id, user3.Id}).Find(&users) - if len(users) != 3 { - t.Errorf("Should found 3 users when search with primary keys, but got %v", len(users)) - } - - var user User - DB.First(&user, &User{Name: user1.Name}) - if user.Id == 0 || user.Name != user1.Name { - t.Errorf("Search first record with inline pointer of struct") - } - - DB.First(&user, User{Name: user1.Name}) - if user.Id == 0 || user.Name != user1.Name { - t.Errorf("Search first record with inline struct") - } - - DB.Where(&User{Name: user1.Name}).First(&user) - if user.Id == 0 || user.Name != user1.Name { - t.Errorf("Search first record with where struct") - } - - DB.Find(&users, &User{Name: user2.Name}) - if len(users) != 1 { - t.Errorf("Search all records with inline struct") - } -} - -func TestSearchWithMap(t *testing.T) { - companyID := 1 - user1 := User{Name: "MapSearchUser1", Age: 1, Birthday: parseTime("2000-1-1")} - user2 := User{Name: "MapSearchUser2", Age: 10, Birthday: parseTime("2010-1-1")} - user3 := User{Name: "MapSearchUser3", Age: 20, Birthday: parseTime("2020-1-1")} - user4 := User{Name: "MapSearchUser4", Age: 30, Birthday: parseTime("2020-1-1"), CompanyID: &companyID} - DB.Save(&user1).Save(&user2).Save(&user3).Save(&user4) - - var user User - DB.First(&user, map[string]interface{}{"name": user1.Name}) - if user.Id == 0 || user.Name != user1.Name { - t.Errorf("Search first record with inline map") - } - - user = User{} - DB.Where(map[string]interface{}{"name": user2.Name}).First(&user) - if user.Id == 0 || user.Name != user2.Name { - t.Errorf("Search first record with where map") - } - - var users []User - DB.Where(map[string]interface{}{"name": user3.Name}).Find(&users) - if len(users) != 1 { - t.Errorf("Search all records with inline map") - } - - DB.Find(&users, map[string]interface{}{"name": user3.Name}) - if len(users) != 1 { - t.Errorf("Search all records with inline map") - } - - DB.Find(&users, map[string]interface{}{"name": user4.Name, "company_id": nil}) - if len(users) != 0 { - t.Errorf("Search all records with inline map containing null value finding 0 records") - } - - DB.Find(&users, map[string]interface{}{"name": user1.Name, "company_id": nil}) - if len(users) != 1 { - t.Errorf("Search all records with inline map containing null value finding 1 record") - } - - DB.Find(&users, map[string]interface{}{"name": user4.Name, "company_id": companyID}) - if len(users) != 1 { - t.Errorf("Search all records with inline multiple value map") - } -} - -func TestSearchWithEmptyChain(t *testing.T) { - user1 := User{Name: "ChainSearchUser1", Age: 1, Birthday: parseTime("2000-1-1")} - user2 := User{Name: "ChainearchUser2", Age: 10, Birthday: parseTime("2010-1-1")} - user3 := User{Name: "ChainearchUser3", Age: 20, Birthday: parseTime("2020-1-1")} - DB.Save(&user1).Save(&user2).Save(&user3) - - if DB.Where("").Where("").First(&User{}).Error != nil { - t.Errorf("Should not raise any error if searching with empty strings") - } - - if DB.Where(&User{}).Where("name = ?", user1.Name).First(&User{}).Error != nil { - t.Errorf("Should not raise any error if searching with empty struct") - } - - if DB.Where(map[string]interface{}{}).Where("name = ?", user1.Name).First(&User{}).Error != nil { - t.Errorf("Should not raise any error if searching with empty map") - } -} - -func TestSelect(t *testing.T) { - user1 := User{Name: "SelectUser1"} - DB.Save(&user1) - - var user User - DB.Where("name = ?", user1.Name).Select("name").Find(&user) - if user.Id != 0 { - t.Errorf("Should not have ID because only selected name, %+v", user.Id) - } - - if user.Name != user1.Name { - t.Errorf("Should have user Name when selected it") - } -} - -func TestOrderAndPluck(t *testing.T) { - user1 := User{Name: "OrderPluckUser1", Age: 1} - user2 := User{Name: "OrderPluckUser2", Age: 10} - user3 := User{Name: "OrderPluckUser3", Age: 20} - DB.Save(&user1).Save(&user2).Save(&user3) - scopedb := DB.Model(&User{}).Where("name like ?", "%OrderPluckUser%") - - var user User - scopedb.Order(gorm.Expr("case when name = ? then 0 else 1 end", "OrderPluckUser2")).First(&user) - if user.Name != "OrderPluckUser2" { - t.Errorf("Order with sql expression") - } - - var ages []int64 - scopedb.Order("age desc").Pluck("age", &ages) - if ages[0] != 20 { - t.Errorf("The first age should be 20 when order with age desc") - } - - var ages1, ages2 []int64 - scopedb.Order("age desc").Pluck("age", &ages1).Pluck("age", &ages2) - if !reflect.DeepEqual(ages1, ages2) { - t.Errorf("The first order is the primary order") - } - - var ages3, ages4 []int64 - scopedb.Model(&User{}).Order("age desc").Pluck("age", &ages3).Order("age", true).Pluck("age", &ages4) - if reflect.DeepEqual(ages3, ages4) { - t.Errorf("Reorder should work") - } - - var names []string - var ages5 []int64 - scopedb.Model(User{}).Order("name").Order("age desc").Pluck("age", &ages5).Pluck("name", &names) - if names != nil && ages5 != nil { - if !(names[0] == user1.Name && names[1] == user2.Name && names[2] == user3.Name && ages5[2] == 20) { - t.Errorf("Order with multiple orders") - } - } else { - t.Errorf("Order with multiple orders") - } - - var ages6 []int64 - if err := scopedb.Order("").Pluck("age", &ages6).Error; err != nil { - t.Errorf("An empty string as order clause produces invalid queries") - } - - DB.Model(User{}).Select("name, age").Find(&[]User{}) -} - -func TestLimit(t *testing.T) { - user1 := User{Name: "LimitUser1", Age: 1} - user2 := User{Name: "LimitUser2", Age: 10} - user3 := User{Name: "LimitUser3", Age: 20} - user4 := User{Name: "LimitUser4", Age: 10} - user5 := User{Name: "LimitUser5", Age: 20} - DB.Save(&user1).Save(&user2).Save(&user3).Save(&user4).Save(&user5) - - var users1, users2, users3 []User - DB.Order("age desc").Limit(3).Find(&users1).Limit(5).Find(&users2).Limit(-1).Find(&users3) - - if len(users1) != 3 || len(users2) != 5 || len(users3) <= 5 { - t.Errorf("Limit should works") - } -} - -func TestOffset(t *testing.T) { - for i := 0; i < 20; i++ { - DB.Save(&User{Name: fmt.Sprintf("OffsetUser%v", i)}) - } - var users1, users2, users3, users4 []User - DB.Limit(100).Where("name like ?", "OffsetUser%").Order("age desc").Find(&users1).Offset(3).Find(&users2).Offset(5).Find(&users3).Offset(-1).Find(&users4) - - if (len(users1) != len(users4)) || (len(users1)-len(users2) != 3) || (len(users1)-len(users3) != 5) { - t.Errorf("Offset should work") - } -} - -func TestOr(t *testing.T) { - user1 := User{Name: "OrUser1", Age: 1} - user2 := User{Name: "OrUser2", Age: 10} - user3 := User{Name: "OrUser3", Age: 20} - DB.Save(&user1).Save(&user2).Save(&user3) - - var users []User - DB.Where("name = ?", user1.Name).Or("name = ?", user2.Name).Find(&users) - if len(users) != 2 { - t.Errorf("Find users with or") - } -} - -func TestCount(t *testing.T) { - user1 := User{Name: "CountUser1", Age: 1} - user2 := User{Name: "CountUser2", Age: 10} - user3 := User{Name: "CountUser3", Age: 20} - - DB.Save(&user1).Save(&user2).Save(&user3) - var count, count1, count2 int64 - var users []User - - if err := DB.Where("name = ?", user1.Name).Or("name = ?", user3.Name).Find(&users).Count(&count).Error; err != nil { - t.Errorf(fmt.Sprintf("Count should work, but got err %v", err)) - } - - if count != int64(len(users)) { - t.Errorf("Count() method should get correct value") - } - - DB.Model(&User{}).Where("name = ?", user1.Name).Count(&count1).Or("name in (?)", []string{user2.Name, user3.Name}).Count(&count2) - if count1 != 1 || count2 != 3 { - t.Errorf("Multiple count in chain") - } - - var count3 int - if err := DB.Model(&User{}).Where("name in (?)", []string{user2.Name, user2.Name, user3.Name}).Group("id").Count(&count3).Error; err != nil { - t.Errorf("Not error should happen, but got %v", err) - } - - if count3 != 2 { - t.Errorf("Should get correct count, but got %v", count3) - } -} - -func TestNot(t *testing.T) { - DB.Create(getPreparedUser("user1", "not")) - DB.Create(getPreparedUser("user2", "not")) - DB.Create(getPreparedUser("user3", "not")) - - user4 := getPreparedUser("user4", "not") - user4.Company = Company{} - DB.Create(user4) - - DB := DB.Where("role = ?", "not") - - var users1, users2, users3, users4, users5, users6, users7, users8, users9 []User - if DB.Find(&users1).RowsAffected != 4 { - t.Errorf("should find 4 not users") - } - DB.Not(users1[0].Id).Find(&users2) - - if len(users1)-len(users2) != 1 { - t.Errorf("Should ignore the first users with Not") - } - - DB.Not([]int{}).Find(&users3) - if len(users1)-len(users3) != 0 { - t.Errorf("Should find all users with a blank condition") - } - - var name3Count int64 - DB.Table("users").Where("name = ?", "user3").Count(&name3Count) - DB.Not("name", "user3").Find(&users4) - if len(users1)-len(users4) != int(name3Count) { - t.Errorf("Should find all users' name not equal 3") - } - - DB.Not("name = ?", "user3").Find(&users4) - if len(users1)-len(users4) != int(name3Count) { - t.Errorf("Should find all users' name not equal 3") - } - - DB.Not("name <> ?", "user3").Find(&users4) - if len(users4) != int(name3Count) { - t.Errorf("Should find all users' name not equal 3") - } - - DB.Not(User{Name: "user3"}).Find(&users5) - - if len(users1)-len(users5) != int(name3Count) { - t.Errorf("Should find all users' name not equal 3") - } - - DB.Not(map[string]interface{}{"name": "user3"}).Find(&users6) - if len(users1)-len(users6) != int(name3Count) { - t.Errorf("Should find all users' name not equal 3") - } - - DB.Not(map[string]interface{}{"name": "user3", "company_id": nil}).Find(&users7) - if len(users1)-len(users7) != 2 { // not user3 or user4 - t.Errorf("Should find all user's name not equal to 3 who do not have company id") - } - - DB.Not("name", []string{"user3"}).Find(&users8) - if len(users1)-len(users8) != int(name3Count) { - t.Errorf("Should find all users' name not equal 3") - } - - var name2Count int64 - DB.Table("users").Where("name = ?", "user2").Count(&name2Count) - DB.Not("name", []string{"user3", "user2"}).Find(&users9) - if len(users1)-len(users9) != (int(name3Count) + int(name2Count)) { - t.Errorf("Should find all users' name not equal 3") - } -} - -func TestFillSmallerStruct(t *testing.T) { - user1 := User{Name: "SmallerUser", Age: 100} - DB.Save(&user1) - type SimpleUser struct { - Name string - Id int64 - UpdatedAt time.Time - CreatedAt time.Time - } - - var simpleUser SimpleUser - DB.Table("users").Where("name = ?", user1.Name).First(&simpleUser) - - if simpleUser.Id == 0 || simpleUser.Name == "" { - t.Errorf("Should fill data correctly into smaller struct") - } -} - -func TestFindOrInitialize(t *testing.T) { - var user1, user2, user3, user4, user5, user6 User - DB.Where(&User{Name: "find or init", Age: 33}).FirstOrInit(&user1) - if user1.Name != "find or init" || user1.Id != 0 || user1.Age != 33 { - t.Errorf("user should be initialized with search value") - } - - DB.Where(User{Name: "find or init", Age: 33}).FirstOrInit(&user2) - if user2.Name != "find or init" || user2.Id != 0 || user2.Age != 33 { - t.Errorf("user should be initialized with search value") - } - - DB.FirstOrInit(&user3, map[string]interface{}{"name": "find or init 2"}) - if user3.Name != "find or init 2" || user3.Id != 0 { - t.Errorf("user should be initialized with inline search value") - } - - DB.Where(&User{Name: "find or init"}).Attrs(User{Age: 44}).FirstOrInit(&user4) - if user4.Name != "find or init" || user4.Id != 0 || user4.Age != 44 { - t.Errorf("user should be initialized with search value and attrs") - } - - DB.Where(&User{Name: "find or init"}).Assign("age", 44).FirstOrInit(&user4) - if user4.Name != "find or init" || user4.Id != 0 || user4.Age != 44 { - t.Errorf("user should be initialized with search value and assign attrs") - } - - DB.Save(&User{Name: "find or init", Age: 33}) - DB.Where(&User{Name: "find or init"}).Attrs("age", 44).FirstOrInit(&user5) - if user5.Name != "find or init" || user5.Id == 0 || user5.Age != 33 { - t.Errorf("user should be found and not initialized by Attrs") - } - - DB.Where(&User{Name: "find or init", Age: 33}).FirstOrInit(&user6) - if user6.Name != "find or init" || user6.Id == 0 || user6.Age != 33 { - t.Errorf("user should be found with FirstOrInit") - } - - DB.Where(&User{Name: "find or init"}).Assign(User{Age: 44}).FirstOrInit(&user6) - if user6.Name != "find or init" || user6.Id == 0 || user6.Age != 44 { - t.Errorf("user should be found and updated with assigned attrs") - } -} - -func TestFindOrCreate(t *testing.T) { - var user1, user2, user3, user4, user5, user6, user7, user8 User - DB.Where(&User{Name: "find or create", Age: 33}).FirstOrCreate(&user1) - if user1.Name != "find or create" || user1.Id == 0 || user1.Age != 33 { - t.Errorf("user should be created with search value") - } - - DB.Where(&User{Name: "find or create", Age: 33}).FirstOrCreate(&user2) - if user1.Id != user2.Id || user2.Name != "find or create" || user2.Id == 0 || user2.Age != 33 { - t.Errorf("user should be created with search value") - } - - DB.FirstOrCreate(&user3, map[string]interface{}{"name": "find or create 2"}) - if user3.Name != "find or create 2" || user3.Id == 0 { - t.Errorf("user should be created with inline search value") - } - - DB.Where(&User{Name: "find or create 3"}).Attrs("age", 44).FirstOrCreate(&user4) - if user4.Name != "find or create 3" || user4.Id == 0 || user4.Age != 44 { - t.Errorf("user should be created with search value and attrs") - } - - updatedAt1 := user4.UpdatedAt - DB.Where(&User{Name: "find or create 3"}).Assign("age", 55).FirstOrCreate(&user4) - if updatedAt1.Format(time.RFC3339Nano) == user4.UpdatedAt.Format(time.RFC3339Nano) { - t.Errorf("UpdateAt should be changed when update values with assign") - } - - DB.Where(&User{Name: "find or create 4"}).Assign(User{Age: 44}).FirstOrCreate(&user4) - if user4.Name != "find or create 4" || user4.Id == 0 || user4.Age != 44 { - t.Errorf("user should be created with search value and assigned attrs") - } - - DB.Where(&User{Name: "find or create"}).Attrs("age", 44).FirstOrInit(&user5) - if user5.Name != "find or create" || user5.Id == 0 || user5.Age != 33 { - t.Errorf("user should be found and not initialized by Attrs") - } - - DB.Where(&User{Name: "find or create"}).Assign(User{Age: 44}).FirstOrCreate(&user6) - if user6.Name != "find or create" || user6.Id == 0 || user6.Age != 44 { - t.Errorf("user should be found and updated with assigned attrs") - } - - DB.Where(&User{Name: "find or create"}).Find(&user7) - if user7.Name != "find or create" || user7.Id == 0 || user7.Age != 44 { - t.Errorf("user should be found and updated with assigned attrs") - } - - DB.Where(&User{Name: "find or create embedded struct"}).Assign(User{Age: 44, CreditCard: CreditCard{Number: "1231231231"}, Emails: []Email{{Email: "jinzhu@assign_embedded_struct.com"}, {Email: "jinzhu-2@assign_embedded_struct.com"}}}).FirstOrCreate(&user8) - if DB.Where("email = ?", "jinzhu-2@assign_embedded_struct.com").First(&Email{}).RecordNotFound() { - t.Errorf("embedded struct email should be saved") - } - - if DB.Where("email = ?", "1231231231").First(&CreditCard{}).RecordNotFound() { - t.Errorf("embedded struct credit card should be saved") - } -} - -func TestSelectWithEscapedFieldName(t *testing.T) { - user1 := User{Name: "EscapedFieldNameUser", Age: 1} - user2 := User{Name: "EscapedFieldNameUser", Age: 10} - user3 := User{Name: "EscapedFieldNameUser", Age: 20} - DB.Save(&user1).Save(&user2).Save(&user3) - - var names []string - DB.Model(User{}).Where(&User{Name: "EscapedFieldNameUser"}).Pluck("\"name\"", &names) - - if len(names) != 3 { - t.Errorf("Expected 3 name, but got: %d", len(names)) - } -} - -func TestSelectWithVariables(t *testing.T) { - DB.Save(&User{Name: "jinzhu"}) - - rows, _ := DB.Table("users").Select("? as fake", gorm.Expr("name")).Rows() - - if !rows.Next() { - t.Errorf("Should have returned at least one row") - } else { - columns, _ := rows.Columns() - if !reflect.DeepEqual(columns, []string{"fake"}) { - t.Errorf("Should only contains one column") - } - } - - rows.Close() -} - -func TestSelectWithArrayInput(t *testing.T) { - DB.Save(&User{Name: "jinzhu", Age: 42}) - - var user User - DB.Select([]string{"name", "age"}).Where("age = 42 AND name = 'jinzhu'").First(&user) - - if user.Name != "jinzhu" || user.Age != 42 { - t.Errorf("Should have selected both age and name") - } -} - -func TestPluckWithSelect(t *testing.T) { - var ( - user = User{Name: "matematik7_pluck_with_select", Age: 25} - combinedName = fmt.Sprintf("%v%v", user.Name, user.Age) - combineUserAgeSQL = fmt.Sprintf("concat(%v, %v)", DB.Dialect().Quote("name"), DB.Dialect().Quote("age")) - ) - - if dialect := DB.Dialect().GetName(); dialect == "sqlite3" { - combineUserAgeSQL = fmt.Sprintf("(%v || %v)", DB.Dialect().Quote("name"), DB.Dialect().Quote("age")) - } - - DB.Save(&user) - - selectStr := combineUserAgeSQL + " as user_age" - var userAges []string - err := DB.Model(&User{}).Where("age = ?", 25).Select(selectStr).Pluck("user_age", &userAges).Error - if err != nil { - t.Error(err) - } - - if len(userAges) != 1 || userAges[0] != combinedName { - t.Errorf("Should correctly pluck with select, got: %s", userAges) - } - - selectStr = combineUserAgeSQL + fmt.Sprintf(" as %v", DB.Dialect().Quote("user_age")) - userAges = userAges[:0] - err = DB.Model(&User{}).Where("age = ?", 25).Select(selectStr).Pluck("user_age", &userAges).Error - if err != nil { - t.Error(err) - } - - if len(userAges) != 1 || userAges[0] != combinedName { - t.Errorf("Should correctly pluck with select, got: %s", userAges) - } -} diff --git a/vendor/github.com/jinzhu/gorm/scaner_test.go b/vendor/github.com/jinzhu/gorm/scaner_test.go deleted file mode 100644 index 9e251dd6..00000000 --- a/vendor/github.com/jinzhu/gorm/scaner_test.go +++ /dev/null @@ -1,139 +0,0 @@ -package gorm_test - -import ( - "database/sql/driver" - "encoding/json" - "errors" - "testing" - - "github.com/jinzhu/gorm" -) - -func TestScannableSlices(t *testing.T) { - if err := DB.AutoMigrate(&RecordWithSlice{}).Error; err != nil { - t.Errorf("Should create table with slice values correctly: %s", err) - } - - r1 := RecordWithSlice{ - Strings: ExampleStringSlice{"a", "b", "c"}, - Structs: ExampleStructSlice{ - {"name1", "value1"}, - {"name2", "value2"}, - }, - } - - if err := DB.Save(&r1).Error; err != nil { - t.Errorf("Should save record with slice values") - } - - var r2 RecordWithSlice - - if err := DB.Find(&r2).Error; err != nil { - t.Errorf("Should fetch record with slice values") - } - - if len(r2.Strings) != 3 || r2.Strings[0] != "a" || r2.Strings[1] != "b" || r2.Strings[2] != "c" { - t.Errorf("Should have serialised and deserialised a string array") - } - - if len(r2.Structs) != 2 || r2.Structs[0].Name != "name1" || r2.Structs[0].Value != "value1" || r2.Structs[1].Name != "name2" || r2.Structs[1].Value != "value2" { - t.Errorf("Should have serialised and deserialised a struct array") - } -} - -type RecordWithSlice struct { - ID uint64 - Strings ExampleStringSlice `sql:"type:text"` - Structs ExampleStructSlice `sql:"type:text"` -} - -type ExampleStringSlice []string - -func (l ExampleStringSlice) Value() (driver.Value, error) { - bytes, err := json.Marshal(l) - return string(bytes), err -} - -func (l *ExampleStringSlice) Scan(input interface{}) error { - switch value := input.(type) { - case string: - return json.Unmarshal([]byte(value), l) - case []byte: - return json.Unmarshal(value, l) - default: - return errors.New("not supported") - } -} - -type ExampleStruct struct { - Name string - Value string -} - -type ExampleStructSlice []ExampleStruct - -func (l ExampleStructSlice) Value() (driver.Value, error) { - bytes, err := json.Marshal(l) - return string(bytes), err -} - -func (l *ExampleStructSlice) Scan(input interface{}) error { - switch value := input.(type) { - case string: - return json.Unmarshal([]byte(value), l) - case []byte: - return json.Unmarshal(value, l) - default: - return errors.New("not supported") - } -} - -type ScannerDataType struct { - Street string `sql:"TYPE:varchar(24)"` -} - -func (ScannerDataType) Value() (driver.Value, error) { - return nil, nil -} - -func (*ScannerDataType) Scan(input interface{}) error { - return nil -} - -type ScannerDataTypeTestStruct struct { - Field1 int - ScannerDataType *ScannerDataType `sql:"TYPE:json"` -} - -type ScannerDataType2 struct { - Street string `sql:"TYPE:varchar(24)"` -} - -func (ScannerDataType2) Value() (driver.Value, error) { - return nil, nil -} - -func (*ScannerDataType2) Scan(input interface{}) error { - return nil -} - -type ScannerDataTypeTestStruct2 struct { - Field1 int - ScannerDataType *ScannerDataType2 -} - -func TestScannerDataType(t *testing.T) { - scope := gorm.Scope{Value: &ScannerDataTypeTestStruct{}} - if field, ok := scope.FieldByName("ScannerDataType"); ok { - if DB.Dialect().DataTypeOf(field.StructField) != "json" { - t.Errorf("data type for scanner is wrong") - } - } - - scope = gorm.Scope{Value: &ScannerDataTypeTestStruct2{}} - if field, ok := scope.FieldByName("ScannerDataType"); ok { - if DB.Dialect().DataTypeOf(field.StructField) != "varchar(24)" { - t.Errorf("data type for scanner is wrong") - } - } -} diff --git a/vendor/github.com/jinzhu/gorm/scope_test.go b/vendor/github.com/jinzhu/gorm/scope_test.go deleted file mode 100644 index 3018f350..00000000 --- a/vendor/github.com/jinzhu/gorm/scope_test.go +++ /dev/null @@ -1,80 +0,0 @@ -package gorm_test - -import ( - "encoding/hex" - "math/rand" - "strings" - "testing" - - "github.com/jinzhu/gorm" -) - -func NameIn1And2(d *gorm.DB) *gorm.DB { - return d.Where("name in (?)", []string{"ScopeUser1", "ScopeUser2"}) -} - -func NameIn2And3(d *gorm.DB) *gorm.DB { - return d.Where("name in (?)", []string{"ScopeUser2", "ScopeUser3"}) -} - -func NameIn(names []string) func(d *gorm.DB) *gorm.DB { - return func(d *gorm.DB) *gorm.DB { - return d.Where("name in (?)", names) - } -} - -func TestScopes(t *testing.T) { - user1 := User{Name: "ScopeUser1", Age: 1} - user2 := User{Name: "ScopeUser2", Age: 1} - user3 := User{Name: "ScopeUser3", Age: 2} - DB.Save(&user1).Save(&user2).Save(&user3) - - var users1, users2, users3 []User - DB.Scopes(NameIn1And2).Find(&users1) - if len(users1) != 2 { - t.Errorf("Should found two users's name in 1, 2") - } - - DB.Scopes(NameIn1And2, NameIn2And3).Find(&users2) - if len(users2) != 1 { - t.Errorf("Should found one user's name is 2") - } - - DB.Scopes(NameIn([]string{user1.Name, user3.Name})).Find(&users3) - if len(users3) != 2 { - t.Errorf("Should found two users's name in 1, 3") - } -} - -func randName() string { - data := make([]byte, 8) - rand.Read(data) - - return "n-" + hex.EncodeToString(data) -} - -func TestValuer(t *testing.T) { - name := randName() - - origUser := User{Name: name, Age: 1, Password: EncryptedData("pass1"), PasswordHash: []byte("abc")} - if err := DB.Save(&origUser).Error; err != nil { - t.Errorf("No error should happen when saving user, but got %v", err) - } - - var user2 User - if err := DB.Where("name = ? AND password = ? AND password_hash = ?", name, EncryptedData("pass1"), []byte("abc")).First(&user2).Error; err != nil { - t.Errorf("No error should happen when querying user with valuer, but got %v", err) - } -} - -func TestFailedValuer(t *testing.T) { - name := randName() - - err := DB.Exec("INSERT INTO users(name, password) VALUES(?, ?)", name, EncryptedData("xpass1")).Error - - if err == nil { - t.Errorf("There should be an error should happen when insert data") - } else if !strings.HasPrefix(err.Error(), "Should not start with") { - t.Errorf("The error should be returned from Valuer, but get %v", err) - } -} diff --git a/vendor/github.com/jinzhu/gorm/search_test.go b/vendor/github.com/jinzhu/gorm/search_test.go deleted file mode 100644 index 4db7ab6a..00000000 --- a/vendor/github.com/jinzhu/gorm/search_test.go +++ /dev/null @@ -1,30 +0,0 @@ -package gorm - -import ( - "reflect" - "testing" -) - -func TestCloneSearch(t *testing.T) { - s := new(search) - s.Where("name = ?", "jinzhu").Order("name").Attrs("name", "jinzhu").Select("name, age") - - s1 := s.clone() - s1.Where("age = ?", 20).Order("age").Attrs("email", "a@e.org").Select("email") - - if reflect.DeepEqual(s.whereConditions, s1.whereConditions) { - t.Errorf("Where should be copied") - } - - if reflect.DeepEqual(s.orders, s1.orders) { - t.Errorf("Order should be copied") - } - - if reflect.DeepEqual(s.initAttrs, s1.initAttrs) { - t.Errorf("InitAttrs should be copied") - } - - if reflect.DeepEqual(s.Select, s1.Select) { - t.Errorf("selectStr should be copied") - } -} diff --git a/vendor/github.com/jinzhu/gorm/test_all.sh b/vendor/github.com/jinzhu/gorm/test_all.sh deleted file mode 100755 index 5cfb3321..00000000 --- a/vendor/github.com/jinzhu/gorm/test_all.sh +++ /dev/null @@ -1,5 +0,0 @@ -dialects=("postgres" "mysql" "mssql" "sqlite") - -for dialect in "${dialects[@]}" ; do - DEBUG=false GORM_DIALECT=${dialect} go test -done diff --git a/vendor/github.com/jinzhu/gorm/update_test.go b/vendor/github.com/jinzhu/gorm/update_test.go deleted file mode 100644 index 85d53e5f..00000000 --- a/vendor/github.com/jinzhu/gorm/update_test.go +++ /dev/null @@ -1,465 +0,0 @@ -package gorm_test - -import ( - "testing" - "time" - - "github.com/jinzhu/gorm" -) - -func TestUpdate(t *testing.T) { - product1 := Product{Code: "product1code"} - product2 := Product{Code: "product2code"} - - DB.Save(&product1).Save(&product2).Update("code", "product2newcode") - - if product2.Code != "product2newcode" { - t.Errorf("Record should be updated") - } - - DB.First(&product1, product1.Id) - DB.First(&product2, product2.Id) - updatedAt1 := product1.UpdatedAt - - if DB.First(&Product{}, "code = ?", product1.Code).RecordNotFound() { - t.Errorf("Product1 should not be updated") - } - - if !DB.First(&Product{}, "code = ?", "product2code").RecordNotFound() { - t.Errorf("Product2's code should be updated") - } - - if DB.First(&Product{}, "code = ?", "product2newcode").RecordNotFound() { - t.Errorf("Product2's code should be updated") - } - - DB.Table("products").Where("code in (?)", []string{"product1code"}).Update("code", "product1newcode") - - var product4 Product - DB.First(&product4, product1.Id) - if updatedAt1.Format(time.RFC3339Nano) != product4.UpdatedAt.Format(time.RFC3339Nano) { - t.Errorf("updatedAt should be updated if something changed") - } - - if !DB.First(&Product{}, "code = 'product1code'").RecordNotFound() { - t.Errorf("Product1's code should be updated") - } - - if DB.First(&Product{}, "code = 'product1newcode'").RecordNotFound() { - t.Errorf("Product should not be changed to 789") - } - - if DB.Model(product2).Update("CreatedAt", time.Now().Add(time.Hour)).Error != nil { - t.Error("No error should raise when update with CamelCase") - } - - if DB.Model(&product2).UpdateColumn("CreatedAt", time.Now().Add(time.Hour)).Error != nil { - t.Error("No error should raise when update_column with CamelCase") - } - - var products []Product - DB.Find(&products) - if count := DB.Model(Product{}).Update("CreatedAt", time.Now().Add(2*time.Hour)).RowsAffected; count != int64(len(products)) { - t.Error("RowsAffected should be correct when do batch update") - } - - DB.First(&product4, product4.Id) - updatedAt4 := product4.UpdatedAt - DB.Model(&product4).Update("price", gorm.Expr("price + ? - ?", 100, 50)) - var product5 Product - DB.First(&product5, product4.Id) - if product5.Price != product4.Price+100-50 { - t.Errorf("Update with expression") - } - if product4.UpdatedAt.Format(time.RFC3339Nano) == updatedAt4.Format(time.RFC3339Nano) { - t.Errorf("Update with expression should update UpdatedAt") - } -} - -func TestUpdateWithNoStdPrimaryKeyAndDefaultValues(t *testing.T) { - animal := Animal{Name: "Ferdinand"} - DB.Save(&animal) - updatedAt1 := animal.UpdatedAt - - DB.Save(&animal).Update("name", "Francis") - - if updatedAt1.Format(time.RFC3339Nano) == animal.UpdatedAt.Format(time.RFC3339Nano) { - t.Errorf("updatedAt should not be updated if nothing changed") - } - - var animals []Animal - DB.Find(&animals) - if count := DB.Model(Animal{}).Update("CreatedAt", time.Now().Add(2*time.Hour)).RowsAffected; count != int64(len(animals)) { - t.Error("RowsAffected should be correct when do batch update") - } - - animal = Animal{From: "somewhere"} // No name fields, should be filled with the default value (galeone) - DB.Save(&animal).Update("From", "a nice place") // The name field shoul be untouched - DB.First(&animal, animal.Counter) - if animal.Name != "galeone" { - t.Errorf("Name fields shouldn't be changed if untouched, but got %v", animal.Name) - } - - // When changing a field with a default value, the change must occur - animal.Name = "amazing horse" - DB.Save(&animal) - DB.First(&animal, animal.Counter) - if animal.Name != "amazing horse" { - t.Errorf("Update a filed with a default value should occur. But got %v\n", animal.Name) - } - - // When changing a field with a default value with blank value - animal.Name = "" - DB.Save(&animal) - DB.First(&animal, animal.Counter) - if animal.Name != "" { - t.Errorf("Update a filed to blank with a default value should occur. But got %v\n", animal.Name) - } -} - -func TestUpdates(t *testing.T) { - product1 := Product{Code: "product1code", Price: 10} - product2 := Product{Code: "product2code", Price: 10} - DB.Save(&product1).Save(&product2) - DB.Model(&product1).Updates(map[string]interface{}{"code": "product1newcode", "price": 100}) - if product1.Code != "product1newcode" || product1.Price != 100 { - t.Errorf("Record should be updated also with map") - } - - DB.First(&product1, product1.Id) - DB.First(&product2, product2.Id) - updatedAt2 := product2.UpdatedAt - - if DB.First(&Product{}, "code = ? and price = ?", product2.Code, product2.Price).RecordNotFound() { - t.Errorf("Product2 should not be updated") - } - - if DB.First(&Product{}, "code = ?", "product1newcode").RecordNotFound() { - t.Errorf("Product1 should be updated") - } - - DB.Table("products").Where("code in (?)", []string{"product2code"}).Updates(Product{Code: "product2newcode"}) - if !DB.First(&Product{}, "code = 'product2code'").RecordNotFound() { - t.Errorf("Product2's code should be updated") - } - - var product4 Product - DB.First(&product4, product2.Id) - if updatedAt2.Format(time.RFC3339Nano) != product4.UpdatedAt.Format(time.RFC3339Nano) { - t.Errorf("updatedAt should be updated if something changed") - } - - if DB.First(&Product{}, "code = ?", "product2newcode").RecordNotFound() { - t.Errorf("product2's code should be updated") - } - - updatedAt4 := product4.UpdatedAt - DB.Model(&product4).Updates(map[string]interface{}{"price": gorm.Expr("price + ?", 100)}) - var product5 Product - DB.First(&product5, product4.Id) - if product5.Price != product4.Price+100 { - t.Errorf("Updates with expression") - } - // product4's UpdatedAt will be reset when updating - if product4.UpdatedAt.Format(time.RFC3339Nano) == updatedAt4.Format(time.RFC3339Nano) { - t.Errorf("Updates with expression should update UpdatedAt") - } -} - -func TestUpdateColumn(t *testing.T) { - product1 := Product{Code: "product1code", Price: 10} - product2 := Product{Code: "product2code", Price: 20} - DB.Save(&product1).Save(&product2).UpdateColumn(map[string]interface{}{"code": "product2newcode", "price": 100}) - if product2.Code != "product2newcode" || product2.Price != 100 { - t.Errorf("product 2 should be updated with update column") - } - - var product3 Product - DB.First(&product3, product1.Id) - if product3.Code != "product1code" || product3.Price != 10 { - t.Errorf("product 1 should not be updated") - } - - DB.First(&product2, product2.Id) - updatedAt2 := product2.UpdatedAt - DB.Model(product2).UpdateColumn("code", "update_column_new") - var product4 Product - DB.First(&product4, product2.Id) - if updatedAt2.Format(time.RFC3339Nano) != product4.UpdatedAt.Format(time.RFC3339Nano) { - t.Errorf("updatedAt should not be updated with update column") - } - - DB.Model(&product4).UpdateColumn("price", gorm.Expr("price + 100 - 50")) - var product5 Product - DB.First(&product5, product4.Id) - if product5.Price != product4.Price+100-50 { - t.Errorf("UpdateColumn with expression") - } - if product5.UpdatedAt.Format(time.RFC3339Nano) != product4.UpdatedAt.Format(time.RFC3339Nano) { - t.Errorf("UpdateColumn with expression should not update UpdatedAt") - } -} - -func TestSelectWithUpdate(t *testing.T) { - user := getPreparedUser("select_user", "select_with_update") - DB.Create(user) - - var reloadUser User - DB.First(&reloadUser, user.Id) - reloadUser.Name = "new_name" - reloadUser.Age = 50 - reloadUser.BillingAddress = Address{Address1: "New Billing Address"} - reloadUser.ShippingAddress = Address{Address1: "New ShippingAddress Address"} - reloadUser.CreditCard = CreditCard{Number: "987654321"} - reloadUser.Emails = []Email{ - {Email: "new_user_1@example1.com"}, {Email: "new_user_2@example2.com"}, {Email: "new_user_3@example2.com"}, - } - reloadUser.Company = Company{Name: "new company"} - - DB.Select("Name", "BillingAddress", "CreditCard", "Company", "Emails").Save(&reloadUser) - - var queryUser User - DB.Preload("BillingAddress").Preload("ShippingAddress"). - Preload("CreditCard").Preload("Emails").Preload("Company").First(&queryUser, user.Id) - - if queryUser.Name == user.Name || queryUser.Age != user.Age { - t.Errorf("Should only update users with name column") - } - - if queryUser.BillingAddressID.Int64 == user.BillingAddressID.Int64 || - queryUser.ShippingAddressId != user.ShippingAddressId || - queryUser.CreditCard.ID == user.CreditCard.ID || - len(queryUser.Emails) == len(user.Emails) || queryUser.Company.Id == user.Company.Id { - t.Errorf("Should only update selected relationships") - } -} - -func TestSelectWithUpdateWithMap(t *testing.T) { - user := getPreparedUser("select_user", "select_with_update_map") - DB.Create(user) - - updateValues := map[string]interface{}{ - "Name": "new_name", - "Age": 50, - "BillingAddress": Address{Address1: "New Billing Address"}, - "ShippingAddress": Address{Address1: "New ShippingAddress Address"}, - "CreditCard": CreditCard{Number: "987654321"}, - "Emails": []Email{ - {Email: "new_user_1@example1.com"}, {Email: "new_user_2@example2.com"}, {Email: "new_user_3@example2.com"}, - }, - "Company": Company{Name: "new company"}, - } - - var reloadUser User - DB.First(&reloadUser, user.Id) - DB.Model(&reloadUser).Select("Name", "BillingAddress", "CreditCard", "Company", "Emails").Update(updateValues) - - var queryUser User - DB.Preload("BillingAddress").Preload("ShippingAddress"). - Preload("CreditCard").Preload("Emails").Preload("Company").First(&queryUser, user.Id) - - if queryUser.Name == user.Name || queryUser.Age != user.Age { - t.Errorf("Should only update users with name column") - } - - if queryUser.BillingAddressID.Int64 == user.BillingAddressID.Int64 || - queryUser.ShippingAddressId != user.ShippingAddressId || - queryUser.CreditCard.ID == user.CreditCard.ID || - len(queryUser.Emails) == len(user.Emails) || queryUser.Company.Id == user.Company.Id { - t.Errorf("Should only update selected relationships") - } -} - -func TestOmitWithUpdate(t *testing.T) { - user := getPreparedUser("omit_user", "omit_with_update") - DB.Create(user) - - var reloadUser User - DB.First(&reloadUser, user.Id) - reloadUser.Name = "new_name" - reloadUser.Age = 50 - reloadUser.BillingAddress = Address{Address1: "New Billing Address"} - reloadUser.ShippingAddress = Address{Address1: "New ShippingAddress Address"} - reloadUser.CreditCard = CreditCard{Number: "987654321"} - reloadUser.Emails = []Email{ - {Email: "new_user_1@example1.com"}, {Email: "new_user_2@example2.com"}, {Email: "new_user_3@example2.com"}, - } - reloadUser.Company = Company{Name: "new company"} - - DB.Omit("Name", "BillingAddress", "CreditCard", "Company", "Emails").Save(&reloadUser) - - var queryUser User - DB.Preload("BillingAddress").Preload("ShippingAddress"). - Preload("CreditCard").Preload("Emails").Preload("Company").First(&queryUser, user.Id) - - if queryUser.Name != user.Name || queryUser.Age == user.Age { - t.Errorf("Should only update users with name column") - } - - if queryUser.BillingAddressID.Int64 != user.BillingAddressID.Int64 || - queryUser.ShippingAddressId == user.ShippingAddressId || - queryUser.CreditCard.ID != user.CreditCard.ID || - len(queryUser.Emails) != len(user.Emails) || queryUser.Company.Id != user.Company.Id { - t.Errorf("Should only update relationships that not omitted") - } -} - -func TestOmitWithUpdateWithMap(t *testing.T) { - user := getPreparedUser("select_user", "select_with_update_map") - DB.Create(user) - - updateValues := map[string]interface{}{ - "Name": "new_name", - "Age": 50, - "BillingAddress": Address{Address1: "New Billing Address"}, - "ShippingAddress": Address{Address1: "New ShippingAddress Address"}, - "CreditCard": CreditCard{Number: "987654321"}, - "Emails": []Email{ - {Email: "new_user_1@example1.com"}, {Email: "new_user_2@example2.com"}, {Email: "new_user_3@example2.com"}, - }, - "Company": Company{Name: "new company"}, - } - - var reloadUser User - DB.First(&reloadUser, user.Id) - DB.Model(&reloadUser).Omit("Name", "BillingAddress", "CreditCard", "Company", "Emails").Update(updateValues) - - var queryUser User - DB.Preload("BillingAddress").Preload("ShippingAddress"). - Preload("CreditCard").Preload("Emails").Preload("Company").First(&queryUser, user.Id) - - if queryUser.Name != user.Name || queryUser.Age == user.Age { - t.Errorf("Should only update users with name column") - } - - if queryUser.BillingAddressID.Int64 != user.BillingAddressID.Int64 || - queryUser.ShippingAddressId == user.ShippingAddressId || - queryUser.CreditCard.ID != user.CreditCard.ID || - len(queryUser.Emails) != len(user.Emails) || queryUser.Company.Id != user.Company.Id { - t.Errorf("Should only update relationships not omitted") - } -} - -func TestSelectWithUpdateColumn(t *testing.T) { - user := getPreparedUser("select_user", "select_with_update_map") - DB.Create(user) - - updateValues := map[string]interface{}{"Name": "new_name", "Age": 50} - - var reloadUser User - DB.First(&reloadUser, user.Id) - DB.Model(&reloadUser).Select("Name").UpdateColumn(updateValues) - - var queryUser User - DB.First(&queryUser, user.Id) - - if queryUser.Name == user.Name || queryUser.Age != user.Age { - t.Errorf("Should only update users with name column") - } -} - -func TestOmitWithUpdateColumn(t *testing.T) { - user := getPreparedUser("select_user", "select_with_update_map") - DB.Create(user) - - updateValues := map[string]interface{}{"Name": "new_name", "Age": 50} - - var reloadUser User - DB.First(&reloadUser, user.Id) - DB.Model(&reloadUser).Omit("Name").UpdateColumn(updateValues) - - var queryUser User - DB.First(&queryUser, user.Id) - - if queryUser.Name != user.Name || queryUser.Age == user.Age { - t.Errorf("Should omit name column when update user") - } -} - -func TestUpdateColumnsSkipsAssociations(t *testing.T) { - user := getPreparedUser("update_columns_user", "special_role") - user.Age = 99 - address1 := "first street" - user.BillingAddress = Address{Address1: address1} - DB.Save(user) - - // Update a single field of the user and verify that the changed address is not stored. - newAge := int64(100) - user.BillingAddress.Address1 = "second street" - db := DB.Model(user).UpdateColumns(User{Age: newAge}) - if db.RowsAffected != 1 { - t.Errorf("Expected RowsAffected=1 but instead RowsAffected=%v", DB.RowsAffected) - } - - // Verify that Age now=`newAge`. - freshUser := &User{Id: user.Id} - DB.First(freshUser) - if freshUser.Age != newAge { - t.Errorf("Expected freshly queried user to have Age=%v but instead found Age=%v", newAge, freshUser.Age) - } - - // Verify that user's BillingAddress.Address1 is not changed and is still "first street". - DB.First(&freshUser.BillingAddress, freshUser.BillingAddressID) - if freshUser.BillingAddress.Address1 != address1 { - t.Errorf("Expected user's BillingAddress.Address1=%s to remain unchanged after UpdateColumns invocation, but BillingAddress.Address1=%s", address1, freshUser.BillingAddress.Address1) - } -} - -func TestUpdatesWithBlankValues(t *testing.T) { - product := Product{Code: "product1", Price: 10} - DB.Save(&product) - - DB.Model(&Product{Id: product.Id}).Updates(&Product{Price: 100}) - - var product1 Product - DB.First(&product1, product.Id) - - if product1.Code != "product1" || product1.Price != 100 { - t.Errorf("product's code should not be updated") - } -} - -type ElementWithIgnoredField struct { - Id int64 - Value string - IgnoredField int64 `sql:"-"` -} - -func (e ElementWithIgnoredField) TableName() string { - return "element_with_ignored_field" -} - -func TestUpdatesTableWithIgnoredValues(t *testing.T) { - elem := ElementWithIgnoredField{Value: "foo", IgnoredField: 10} - DB.Save(&elem) - - DB.Table(elem.TableName()). - Where("id = ?", elem.Id). - // DB.Model(&ElementWithIgnoredField{Id: elem.Id}). - Updates(&ElementWithIgnoredField{Value: "bar", IgnoredField: 100}) - - var elem1 ElementWithIgnoredField - err := DB.First(&elem1, elem.Id).Error - if err != nil { - t.Errorf("error getting an element from database: %s", err.Error()) - } - - if elem1.IgnoredField != 0 { - t.Errorf("element's ignored field should not be updated") - } -} - -func TestUpdateDecodeVirtualAttributes(t *testing.T) { - var user = User{ - Name: "jinzhu", - IgnoreMe: 88, - } - - DB.Save(&user) - - DB.Model(&user).Updates(User{Name: "jinzhu2", IgnoreMe: 100}) - - if user.IgnoreMe != 100 { - t.Errorf("should decode virtual attributes to struct, so it could be used in callbacks") - } -} diff --git a/vendor/github.com/jinzhu/gorm/wercker.yml b/vendor/github.com/jinzhu/gorm/wercker.yml deleted file mode 100644 index 0c3e73ef..00000000 --- a/vendor/github.com/jinzhu/gorm/wercker.yml +++ /dev/null @@ -1,148 +0,0 @@ -# use the default golang container from Docker Hub -box: golang - -services: - - name: mariadb - id: mariadb:latest - env: - MYSQL_DATABASE: gorm - MYSQL_USER: gorm - MYSQL_PASSWORD: gorm - MYSQL_RANDOM_ROOT_PASSWORD: "yes" - - name: mysql57 - id: mysql:5.7 - env: - MYSQL_DATABASE: gorm - MYSQL_USER: gorm - MYSQL_PASSWORD: gorm - MYSQL_RANDOM_ROOT_PASSWORD: "yes" - - name: mysql56 - id: mysql:5.6 - env: - MYSQL_DATABASE: gorm - MYSQL_USER: gorm - MYSQL_PASSWORD: gorm - MYSQL_RANDOM_ROOT_PASSWORD: "yes" - - name: mysql55 - id: mysql:5.5 - env: - MYSQL_DATABASE: gorm - MYSQL_USER: gorm - MYSQL_PASSWORD: gorm - MYSQL_RANDOM_ROOT_PASSWORD: "yes" - - name: postgres - id: postgres:latest - env: - POSTGRES_USER: gorm - POSTGRES_PASSWORD: gorm - POSTGRES_DB: gorm - - name: postgres96 - id: postgres:9.6 - env: - POSTGRES_USER: gorm - POSTGRES_PASSWORD: gorm - POSTGRES_DB: gorm - - name: postgres95 - id: postgres:9.5 - env: - POSTGRES_USER: gorm - POSTGRES_PASSWORD: gorm - POSTGRES_DB: gorm - - name: postgres94 - id: postgres:9.4 - env: - POSTGRES_USER: gorm - POSTGRES_PASSWORD: gorm - POSTGRES_DB: gorm - - name: postgres93 - id: postgres:9.3 - env: - POSTGRES_USER: gorm - POSTGRES_PASSWORD: gorm - POSTGRES_DB: gorm - - name: mssql - id: mcmoe/mssqldocker:latest - env: - ACCEPT_EULA: Y - SA_PASSWORD: LoremIpsum86 - MSSQL_DB: gorm - MSSQL_USER: gorm - MSSQL_PASSWORD: LoremIpsum86 - -# The steps that will be executed in the build pipeline -build: - # The steps that will be executed on build - steps: - # Sets the go workspace and places you package - # at the right place in the workspace tree - - setup-go-workspace - - # Gets the dependencies - - script: - name: go get - code: | - cd $WERCKER_SOURCE_DIR - go version - go get -t ./... - - # Build the project - - script: - name: go build - code: | - go build ./... - - # Test the project - - script: - name: test sqlite - code: | - go test ./... - - - script: - name: test mariadb - code: | - GORM_DIALECT=mysql GORM_DSN="gorm:gorm@tcp(mariadb:3306)/gorm?charset=utf8&parseTime=True" go test ./... - - - script: - name: test mysql5.7 - code: | - GORM_DIALECT=mysql GORM_DSN="gorm:gorm@tcp(mysql57:3306)/gorm?charset=utf8&parseTime=True" go test ./... - - - script: - name: test mysql5.6 - code: | - GORM_DIALECT=mysql GORM_DSN="gorm:gorm@tcp(mysql56:3306)/gorm?charset=utf8&parseTime=True" go test ./... - - - script: - name: test mysql5.5 - code: | - GORM_DIALECT=mysql GORM_DSN="gorm:gorm@tcp(mysql55:3306)/gorm?charset=utf8&parseTime=True" go test ./... - - - script: - name: test postgres - code: | - GORM_DIALECT=postgres GORM_DSN="host=postgres user=gorm password=gorm DB.name=gorm port=5432 sslmode=disable" go test ./... - - - script: - name: test postgres96 - code: | - GORM_DIALECT=postgres GORM_DSN="host=postgres96 user=gorm password=gorm DB.name=gorm port=5432 sslmode=disable" go test ./... - - - script: - name: test postgres95 - code: | - GORM_DIALECT=postgres GORM_DSN="host=postgres95 user=gorm password=gorm DB.name=gorm port=5432 sslmode=disable" go test ./... - - - script: - name: test postgres94 - code: | - GORM_DIALECT=postgres GORM_DSN="host=postgres94 user=gorm password=gorm DB.name=gorm port=5432 sslmode=disable" go test ./... - - - script: - name: test postgres93 - code: | - GORM_DIALECT=postgres GORM_DSN="host=postgres93 user=gorm password=gorm DB.name=gorm port=5432 sslmode=disable" go test ./... - - - script: - name: test mssql - code: | - GORM_DIALECT=mssql GORM_DSN="sqlserver://gorm:LoremIpsum86@mssql:1433?database=gorm" go test ./... diff --git a/vendor/github.com/jinzhu/inflection/README.md b/vendor/github.com/jinzhu/inflection/README.md deleted file mode 100644 index a3de3361..00000000 --- a/vendor/github.com/jinzhu/inflection/README.md +++ /dev/null @@ -1,55 +0,0 @@ -# Inflection - -Inflection pluralizes and singularizes English nouns - -[![wercker status](https://app.wercker.com/status/f8c7432b097d1f4ce636879670be0930/s/master "wercker status")](https://app.wercker.com/project/byKey/f8c7432b097d1f4ce636879670be0930) - -## Basic Usage - -```go -inflection.Plural("person") => "people" -inflection.Plural("Person") => "People" -inflection.Plural("PERSON") => "PEOPLE" -inflection.Plural("bus") => "buses" -inflection.Plural("BUS") => "BUSES" -inflection.Plural("Bus") => "Buses" - -inflection.Singular("people") => "person" -inflection.Singular("People") => "Person" -inflection.Singular("PEOPLE") => "PERSON" -inflection.Singular("buses") => "bus" -inflection.Singular("BUSES") => "BUS" -inflection.Singular("Buses") => "Bus" - -inflection.Plural("FancyPerson") => "FancyPeople" -inflection.Singular("FancyPeople") => "FancyPerson" -``` - -## Register Rules - -Standard rules are from Rails's ActiveSupport (https://github.com/rails/rails/blob/master/activesupport/lib/active_support/inflections.rb) - -If you want to register more rules, follow: - -``` -inflection.AddUncountable("fish") -inflection.AddIrregular("person", "people") -inflection.AddPlural("(bu)s$", "${1}ses") # "bus" => "buses" / "BUS" => "BUSES" / "Bus" => "Buses" -inflection.AddSingular("(bus)(es)?$", "${1}") # "buses" => "bus" / "Buses" => "Bus" / "BUSES" => "BUS" -``` - -## Contributing - -You can help to make the project better, check out [http://gorm.io/contribute.html](http://gorm.io/contribute.html) for things you can do. - -## Author - -**jinzhu** - -* -* -* - -## License - -Released under the [MIT License](http://www.opensource.org/licenses/MIT). diff --git a/vendor/github.com/jinzhu/inflection/inflections_test.go b/vendor/github.com/jinzhu/inflection/inflections_test.go deleted file mode 100644 index 689e1dfb..00000000 --- a/vendor/github.com/jinzhu/inflection/inflections_test.go +++ /dev/null @@ -1,213 +0,0 @@ -package inflection - -import ( - "strings" - "testing" -) - -var inflections = map[string]string{ - "star": "stars", - "STAR": "STARS", - "Star": "Stars", - "bus": "buses", - "fish": "fish", - "mouse": "mice", - "query": "queries", - "ability": "abilities", - "agency": "agencies", - "movie": "movies", - "archive": "archives", - "index": "indices", - "wife": "wives", - "safe": "saves", - "half": "halves", - "move": "moves", - "salesperson": "salespeople", - "person": "people", - "spokesman": "spokesmen", - "man": "men", - "woman": "women", - "basis": "bases", - "diagnosis": "diagnoses", - "diagnosis_a": "diagnosis_as", - "datum": "data", - "medium": "media", - "stadium": "stadia", - "analysis": "analyses", - "node_child": "node_children", - "child": "children", - "experience": "experiences", - "day": "days", - "comment": "comments", - "foobar": "foobars", - "newsletter": "newsletters", - "old_news": "old_news", - "news": "news", - "series": "series", - "species": "species", - "quiz": "quizzes", - "perspective": "perspectives", - "ox": "oxen", - "photo": "photos", - "buffalo": "buffaloes", - "tomato": "tomatoes", - "dwarf": "dwarves", - "elf": "elves", - "information": "information", - "equipment": "equipment", - "criterion": "criteria", -} - -// storage is used to restore the state of the global variables -// on each test execution, to ensure no global state pollution -type storage struct { - singulars RegularSlice - plurals RegularSlice - irregulars IrregularSlice - uncountables []string -} - -var backup = storage{} - -func init() { - AddIrregular("criterion", "criteria") - copy(backup.singulars, singularInflections) - copy(backup.plurals, pluralInflections) - copy(backup.irregulars, irregularInflections) - copy(backup.uncountables, uncountableInflections) -} - -func restore() { - copy(singularInflections, backup.singulars) - copy(pluralInflections, backup.plurals) - copy(irregularInflections, backup.irregulars) - copy(uncountableInflections, backup.uncountables) -} - -func TestPlural(t *testing.T) { - for key, value := range inflections { - if v := Plural(strings.ToUpper(key)); v != strings.ToUpper(value) { - t.Errorf("%v's plural should be %v, but got %v", strings.ToUpper(key), strings.ToUpper(value), v) - } - - if v := Plural(strings.Title(key)); v != strings.Title(value) { - t.Errorf("%v's plural should be %v, but got %v", strings.Title(key), strings.Title(value), v) - } - - if v := Plural(key); v != value { - t.Errorf("%v's plural should be %v, but got %v", key, value, v) - } - } -} - -func TestSingular(t *testing.T) { - for key, value := range inflections { - if v := Singular(strings.ToUpper(value)); v != strings.ToUpper(key) { - t.Errorf("%v's singular should be %v, but got %v", strings.ToUpper(value), strings.ToUpper(key), v) - } - - if v := Singular(strings.Title(value)); v != strings.Title(key) { - t.Errorf("%v's singular should be %v, but got %v", strings.Title(value), strings.Title(key), v) - } - - if v := Singular(value); v != key { - t.Errorf("%v's singular should be %v, but got %v", value, key, v) - } - } -} - -func TestAddPlural(t *testing.T) { - defer restore() - ln := len(pluralInflections) - AddPlural("", "") - if ln+1 != len(pluralInflections) { - t.Errorf("Expected len %d, got %d", ln+1, len(pluralInflections)) - } -} - -func TestAddSingular(t *testing.T) { - defer restore() - ln := len(singularInflections) - AddSingular("", "") - if ln+1 != len(singularInflections) { - t.Errorf("Expected len %d, got %d", ln+1, len(singularInflections)) - } -} - -func TestAddIrregular(t *testing.T) { - defer restore() - ln := len(irregularInflections) - AddIrregular("", "") - if ln+1 != len(irregularInflections) { - t.Errorf("Expected len %d, got %d", ln+1, len(irregularInflections)) - } -} - -func TestAddUncountable(t *testing.T) { - defer restore() - ln := len(uncountableInflections) - AddUncountable("", "") - if ln+2 != len(uncountableInflections) { - t.Errorf("Expected len %d, got %d", ln+2, len(uncountableInflections)) - } -} - -func TestGetPlural(t *testing.T) { - plurals := GetPlural() - if len(plurals) != len(pluralInflections) { - t.Errorf("Expected len %d, got %d", len(plurals), len(pluralInflections)) - } -} - -func TestGetSingular(t *testing.T) { - singular := GetSingular() - if len(singular) != len(singularInflections) { - t.Errorf("Expected len %d, got %d", len(singular), len(singularInflections)) - } -} - -func TestGetIrregular(t *testing.T) { - irregular := GetIrregular() - if len(irregular) != len(irregularInflections) { - t.Errorf("Expected len %d, got %d", len(irregular), len(irregularInflections)) - } -} - -func TestGetUncountable(t *testing.T) { - uncountables := GetUncountable() - if len(uncountables) != len(uncountableInflections) { - t.Errorf("Expected len %d, got %d", len(uncountables), len(uncountableInflections)) - } -} - -func TestSetPlural(t *testing.T) { - defer restore() - SetPlural(RegularSlice{{}, {}}) - if len(pluralInflections) != 2 { - t.Errorf("Expected len 2, got %d", len(pluralInflections)) - } -} - -func TestSetSingular(t *testing.T) { - defer restore() - SetSingular(RegularSlice{{}, {}}) - if len(singularInflections) != 2 { - t.Errorf("Expected len 2, got %d", len(singularInflections)) - } -} - -func TestSetIrregular(t *testing.T) { - defer restore() - SetIrregular(IrregularSlice{{}, {}}) - if len(irregularInflections) != 2 { - t.Errorf("Expected len 2, got %d", len(irregularInflections)) - } -} - -func TestSetUncountable(t *testing.T) { - defer restore() - SetUncountable([]string{"", ""}) - if len(uncountableInflections) != 2 { - t.Errorf("Expected len 2, got %d", len(uncountableInflections)) - } -} diff --git a/vendor/github.com/jinzhu/inflection/wercker.yml b/vendor/github.com/jinzhu/inflection/wercker.yml deleted file mode 100644 index 5e6ce981..00000000 --- a/vendor/github.com/jinzhu/inflection/wercker.yml +++ /dev/null @@ -1,23 +0,0 @@ -box: golang - -build: - steps: - - setup-go-workspace - - # Gets the dependencies - - script: - name: go get - code: | - go get - - # Build the project - - script: - name: go build - code: | - go build ./... - - # Test the project - - script: - name: go test - code: | - go test ./... diff --git a/vendor/github.com/lib/pq/CONTRIBUTING.md b/vendor/github.com/lib/pq/CONTRIBUTING.md deleted file mode 100644 index 84c937f1..00000000 --- a/vendor/github.com/lib/pq/CONTRIBUTING.md +++ /dev/null @@ -1,29 +0,0 @@ -## Contributing to pq - -`pq` has a backlog of pull requests, but contributions are still very -much welcome. You can help with patch review, submitting bug reports, -or adding new functionality. There is no formal style guide, but -please conform to the style of existing code and general Go formatting -conventions when submitting patches. - -### Patch review - -Help review existing open pull requests by commenting on the code or -proposed functionality. - -### Bug reports - -We appreciate any bug reports, but especially ones with self-contained -(doesn't depend on code outside of pq), minimal (can't be simplified -further) test cases. It's especially helpful if you can submit a pull -request with just the failing test case (you'll probably want to -pattern it after the tests in -[conn_test.go](https://github.com/lib/pq/blob/master/conn_test.go). - -### New functionality - -There are a number of pending patches for new functionality, so -additional feature patches will take a while to merge. Still, patches -are generally reviewed based on usefulness and complexity in addition -to time-in-queue, so if you have a knockout idea, take a shot. Feel -free to open an issue discussion your proposed patch beforehand. diff --git a/vendor/github.com/lib/pq/README.md b/vendor/github.com/lib/pq/README.md deleted file mode 100644 index d71f3c2c..00000000 --- a/vendor/github.com/lib/pq/README.md +++ /dev/null @@ -1,95 +0,0 @@ -# pq - A pure Go postgres driver for Go's database/sql package - -[![GoDoc](https://godoc.org/github.com/lib/pq?status.svg)](https://godoc.org/github.com/lib/pq) -[![Build Status](https://travis-ci.org/lib/pq.svg?branch=master)](https://travis-ci.org/lib/pq) - -## Install - - go get github.com/lib/pq - -## Docs - -For detailed documentation and basic usage examples, please see the package -documentation at . - -## Tests - -`go test` is used for testing. See [TESTS.md](TESTS.md) for more details. - -## Features - -* SSL -* Handles bad connections for `database/sql` -* Scan `time.Time` correctly (i.e. `timestamp[tz]`, `time[tz]`, `date`) -* Scan binary blobs correctly (i.e. `bytea`) -* Package for `hstore` support -* COPY FROM support -* pq.ParseURL for converting urls to connection strings for sql.Open. -* Many libpq compatible environment variables -* Unix socket support -* Notifications: `LISTEN`/`NOTIFY` -* pgpass support - -## Future / Things you can help with - -* Better COPY FROM / COPY TO (see discussion in #181) - -## Thank you (alphabetical) - -Some of these contributors are from the original library `bmizerany/pq.go` whose -code still exists in here. - -* Andy Balholm (andybalholm) -* Ben Berkert (benburkert) -* Benjamin Heatwole (bheatwole) -* Bill Mill (llimllib) -* Bjørn Madsen (aeons) -* Blake Gentry (bgentry) -* Brad Fitzpatrick (bradfitz) -* Charlie Melbye (cmelbye) -* Chris Bandy (cbandy) -* Chris Gilling (cgilling) -* Chris Walsh (cwds) -* Dan Sosedoff (sosedoff) -* Daniel Farina (fdr) -* Eric Chlebek (echlebek) -* Eric Garrido (minusnine) -* Eric Urban (hydrogen18) -* Everyone at The Go Team -* Evan Shaw (edsrzf) -* Ewan Chou (coocood) -* Fazal Majid (fazalmajid) -* Federico Romero (federomero) -* Fumin (fumin) -* Gary Burd (garyburd) -* Heroku (heroku) -* James Pozdena (jpoz) -* Jason McVetta (jmcvetta) -* Jeremy Jay (pbnjay) -* Joakim Sernbrant (serbaut) -* John Gallagher (jgallagher) -* Jonathan Rudenberg (titanous) -* Joël Stemmer (jstemmer) -* Kamil Kisiel (kisielk) -* Kelly Dunn (kellydunn) -* Keith Rarick (kr) -* Kir Shatrov (kirs) -* Lann Martin (lann) -* Maciek Sakrejda (uhoh-itsmaciek) -* Marc Brinkmann (mbr) -* Marko Tiikkaja (johto) -* Matt Newberry (MattNewberry) -* Matt Robenolt (mattrobenolt) -* Martin Olsen (martinolsen) -* Mike Lewis (mikelikespie) -* Nicolas Patry (Narsil) -* Oliver Tonnhofer (olt) -* Patrick Hayes (phayes) -* Paul Hammond (paulhammond) -* Ryan Smith (ryandotsmith) -* Samuel Stauffer (samuel) -* Timothée Peignier (cyberdelia) -* Travis Cline (tmc) -* TruongSinh Tran-Nguyen (truongsinh) -* Yaismel Miranda (ympons) -* notedit (notedit) diff --git a/vendor/github.com/lib/pq/TESTS.md b/vendor/github.com/lib/pq/TESTS.md deleted file mode 100644 index f0502111..00000000 --- a/vendor/github.com/lib/pq/TESTS.md +++ /dev/null @@ -1,33 +0,0 @@ -# Tests - -## Running Tests - -`go test` is used for testing. A running PostgreSQL -server is required, with the ability to log in. The -database to connect to test with is "pqgotest," on -"localhost" but these can be overridden using [environment -variables](https://www.postgresql.org/docs/9.3/static/libpq-envars.html). - -Example: - - PGHOST=/run/postgresql go test - -## Benchmarks - -A benchmark suite can be run as part of the tests: - - go test -bench . - -## Example setup (Docker) - -Run a postgres container: - -``` -docker run --expose 5432:5432 postgres -``` - -Run tests: - -``` -PGHOST=localhost PGPORT=5432 PGUSER=postgres PGSSLMODE=disable PGDATABASE=postgres go test -``` diff --git a/vendor/github.com/lib/pq/array_test.go b/vendor/github.com/lib/pq/array_test.go deleted file mode 100644 index f724bcd8..00000000 --- a/vendor/github.com/lib/pq/array_test.go +++ /dev/null @@ -1,1311 +0,0 @@ -package pq - -import ( - "bytes" - "database/sql" - "database/sql/driver" - "math/rand" - "reflect" - "strings" - "testing" -) - -func TestParseArray(t *testing.T) { - for _, tt := range []struct { - input string - delim string - dims []int - elems [][]byte - }{ - {`{}`, `,`, nil, [][]byte{}}, - {`{NULL}`, `,`, []int{1}, [][]byte{nil}}, - {`{a}`, `,`, []int{1}, [][]byte{{'a'}}}, - {`{a,b}`, `,`, []int{2}, [][]byte{{'a'}, {'b'}}}, - {`{{a,b}}`, `,`, []int{1, 2}, [][]byte{{'a'}, {'b'}}}, - {`{{a},{b}}`, `,`, []int{2, 1}, [][]byte{{'a'}, {'b'}}}, - {`{{{a,b},{c,d},{e,f}}}`, `,`, []int{1, 3, 2}, [][]byte{ - {'a'}, {'b'}, {'c'}, {'d'}, {'e'}, {'f'}, - }}, - {`{""}`, `,`, []int{1}, [][]byte{{}}}, - {`{","}`, `,`, []int{1}, [][]byte{{','}}}, - {`{",",","}`, `,`, []int{2}, [][]byte{{','}, {','}}}, - {`{{",",","}}`, `,`, []int{1, 2}, [][]byte{{','}, {','}}}, - {`{{","},{","}}`, `,`, []int{2, 1}, [][]byte{{','}, {','}}}, - {`{{{",",","},{",",","},{",",","}}}`, `,`, []int{1, 3, 2}, [][]byte{ - {','}, {','}, {','}, {','}, {','}, {','}, - }}, - {`{"\"}"}`, `,`, []int{1}, [][]byte{{'"', '}'}}}, - {`{"\"","\""}`, `,`, []int{2}, [][]byte{{'"'}, {'"'}}}, - {`{{"\"","\""}}`, `,`, []int{1, 2}, [][]byte{{'"'}, {'"'}}}, - {`{{"\""},{"\""}}`, `,`, []int{2, 1}, [][]byte{{'"'}, {'"'}}}, - {`{{{"\"","\""},{"\"","\""},{"\"","\""}}}`, `,`, []int{1, 3, 2}, [][]byte{ - {'"'}, {'"'}, {'"'}, {'"'}, {'"'}, {'"'}, - }}, - {`{axyzb}`, `xyz`, []int{2}, [][]byte{{'a'}, {'b'}}}, - } { - dims, elems, err := parseArray([]byte(tt.input), []byte(tt.delim)) - - if err != nil { - t.Fatalf("Expected no error for %q, got %q", tt.input, err) - } - if !reflect.DeepEqual(dims, tt.dims) { - t.Errorf("Expected %v dimensions for %q, got %v", tt.dims, tt.input, dims) - } - if !reflect.DeepEqual(elems, tt.elems) { - t.Errorf("Expected %v elements for %q, got %v", tt.elems, tt.input, elems) - } - } -} - -func TestParseArrayError(t *testing.T) { - for _, tt := range []struct { - input, err string - }{ - {``, "expected '{' at offset 0"}, - {`x`, "expected '{' at offset 0"}, - {`}`, "expected '{' at offset 0"}, - {`{`, "expected '}' at offset 1"}, - {`{{}`, "expected '}' at offset 3"}, - {`{}}`, "unexpected '}' at offset 2"}, - {`{,}`, "unexpected ',' at offset 1"}, - {`{,x}`, "unexpected ',' at offset 1"}, - {`{x,}`, "unexpected '}' at offset 3"}, - {`{x,{`, "unexpected '{' at offset 3"}, - {`{x},`, "unexpected ',' at offset 3"}, - {`{x}}`, "unexpected '}' at offset 3"}, - {`{{x}`, "expected '}' at offset 4"}, - {`{""x}`, "unexpected 'x' at offset 3"}, - {`{{a},{b,c}}`, "multidimensional arrays must have elements with matching dimensions"}, - } { - _, _, err := parseArray([]byte(tt.input), []byte{','}) - - if err == nil { - t.Fatalf("Expected error for %q, got none", tt.input) - } - if !strings.Contains(err.Error(), tt.err) { - t.Errorf("Expected error to contain %q for %q, got %q", tt.err, tt.input, err) - } - } -} - -func TestArrayScanner(t *testing.T) { - var s sql.Scanner = Array(&[]bool{}) - if _, ok := s.(*BoolArray); !ok { - t.Errorf("Expected *BoolArray, got %T", s) - } - - s = Array(&[]float64{}) - if _, ok := s.(*Float64Array); !ok { - t.Errorf("Expected *Float64Array, got %T", s) - } - - s = Array(&[]int64{}) - if _, ok := s.(*Int64Array); !ok { - t.Errorf("Expected *Int64Array, got %T", s) - } - - s = Array(&[]string{}) - if _, ok := s.(*StringArray); !ok { - t.Errorf("Expected *StringArray, got %T", s) - } - - for _, tt := range []interface{}{ - &[]sql.Scanner{}, - &[][]bool{}, - &[][]float64{}, - &[][]int64{}, - &[][]string{}, - } { - s = Array(tt) - if _, ok := s.(GenericArray); !ok { - t.Errorf("Expected GenericArray for %T, got %T", tt, s) - } - } -} - -func TestArrayValuer(t *testing.T) { - var v driver.Valuer = Array([]bool{}) - if _, ok := v.(*BoolArray); !ok { - t.Errorf("Expected *BoolArray, got %T", v) - } - - v = Array([]float64{}) - if _, ok := v.(*Float64Array); !ok { - t.Errorf("Expected *Float64Array, got %T", v) - } - - v = Array([]int64{}) - if _, ok := v.(*Int64Array); !ok { - t.Errorf("Expected *Int64Array, got %T", v) - } - - v = Array([]string{}) - if _, ok := v.(*StringArray); !ok { - t.Errorf("Expected *StringArray, got %T", v) - } - - for _, tt := range []interface{}{ - nil, - []driver.Value{}, - [][]bool{}, - [][]float64{}, - [][]int64{}, - [][]string{}, - } { - v = Array(tt) - if _, ok := v.(GenericArray); !ok { - t.Errorf("Expected GenericArray for %T, got %T", tt, v) - } - } -} - -func TestBoolArrayScanUnsupported(t *testing.T) { - var arr BoolArray - err := arr.Scan(1) - - if err == nil { - t.Fatal("Expected error when scanning from int") - } - if !strings.Contains(err.Error(), "int to BoolArray") { - t.Errorf("Expected type to be mentioned when scanning, got %q", err) - } -} - -func TestBoolArrayScanEmpty(t *testing.T) { - var arr BoolArray - err := arr.Scan(`{}`) - - if err != nil { - t.Fatalf("Expected no error, got %v", err) - } - if arr == nil || len(arr) != 0 { - t.Errorf("Expected empty, got %#v", arr) - } -} - -func TestBoolArrayScanNil(t *testing.T) { - arr := BoolArray{true, true, true} - err := arr.Scan(nil) - - if err != nil { - t.Fatalf("Expected no error, got %v", err) - } - if arr != nil { - t.Errorf("Expected nil, got %+v", arr) - } -} - -var BoolArrayStringTests = []struct { - str string - arr BoolArray -}{ - {`{}`, BoolArray{}}, - {`{t}`, BoolArray{true}}, - {`{f,t}`, BoolArray{false, true}}, -} - -func TestBoolArrayScanBytes(t *testing.T) { - for _, tt := range BoolArrayStringTests { - bytes := []byte(tt.str) - arr := BoolArray{true, true, true} - err := arr.Scan(bytes) - - if err != nil { - t.Fatalf("Expected no error for %q, got %v", bytes, err) - } - if !reflect.DeepEqual(arr, tt.arr) { - t.Errorf("Expected %+v for %q, got %+v", tt.arr, bytes, arr) - } - } -} - -func BenchmarkBoolArrayScanBytes(b *testing.B) { - var a BoolArray - var x interface{} = []byte(`{t,f,t,f,t,f,t,f,t,f}`) - - for i := 0; i < b.N; i++ { - a = BoolArray{} - a.Scan(x) - } -} - -func TestBoolArrayScanString(t *testing.T) { - for _, tt := range BoolArrayStringTests { - arr := BoolArray{true, true, true} - err := arr.Scan(tt.str) - - if err != nil { - t.Fatalf("Expected no error for %q, got %v", tt.str, err) - } - if !reflect.DeepEqual(arr, tt.arr) { - t.Errorf("Expected %+v for %q, got %+v", tt.arr, tt.str, arr) - } - } -} - -func TestBoolArrayScanError(t *testing.T) { - for _, tt := range []struct { - input, err string - }{ - {``, "unable to parse array"}, - {`{`, "unable to parse array"}, - {`{{t},{f}}`, "cannot convert ARRAY[2][1] to BoolArray"}, - {`{NULL}`, `could not parse boolean array index 0: invalid boolean ""`}, - {`{a}`, `could not parse boolean array index 0: invalid boolean "a"`}, - {`{t,b}`, `could not parse boolean array index 1: invalid boolean "b"`}, - {`{t,f,cd}`, `could not parse boolean array index 2: invalid boolean "cd"`}, - } { - arr := BoolArray{true, true, true} - err := arr.Scan(tt.input) - - if err == nil { - t.Fatalf("Expected error for %q, got none", tt.input) - } - if !strings.Contains(err.Error(), tt.err) { - t.Errorf("Expected error to contain %q for %q, got %q", tt.err, tt.input, err) - } - if !reflect.DeepEqual(arr, BoolArray{true, true, true}) { - t.Errorf("Expected destination not to change for %q, got %+v", tt.input, arr) - } - } -} - -func TestBoolArrayValue(t *testing.T) { - result, err := BoolArray(nil).Value() - - if err != nil { - t.Fatalf("Expected no error for nil, got %v", err) - } - if result != nil { - t.Errorf("Expected nil, got %q", result) - } - - result, err = BoolArray([]bool{}).Value() - - if err != nil { - t.Fatalf("Expected no error for empty, got %v", err) - } - if expected := `{}`; !reflect.DeepEqual(result, expected) { - t.Errorf("Expected empty, got %q", result) - } - - result, err = BoolArray([]bool{false, true, false}).Value() - - if err != nil { - t.Fatalf("Expected no error, got %v", err) - } - if expected := `{f,t,f}`; !reflect.DeepEqual(result, expected) { - t.Errorf("Expected %q, got %q", expected, result) - } -} - -func BenchmarkBoolArrayValue(b *testing.B) { - rand.Seed(1) - x := make([]bool, 10) - for i := 0; i < len(x); i++ { - x[i] = rand.Intn(2) == 0 - } - a := BoolArray(x) - - for i := 0; i < b.N; i++ { - a.Value() - } -} - -func TestByteaArrayScanUnsupported(t *testing.T) { - var arr ByteaArray - err := arr.Scan(1) - - if err == nil { - t.Fatal("Expected error when scanning from int") - } - if !strings.Contains(err.Error(), "int to ByteaArray") { - t.Errorf("Expected type to be mentioned when scanning, got %q", err) - } -} - -func TestByteaArrayScanEmpty(t *testing.T) { - var arr ByteaArray - err := arr.Scan(`{}`) - - if err != nil { - t.Fatalf("Expected no error, got %v", err) - } - if arr == nil || len(arr) != 0 { - t.Errorf("Expected empty, got %#v", arr) - } -} - -func TestByteaArrayScanNil(t *testing.T) { - arr := ByteaArray{{2}, {6}, {0, 0}} - err := arr.Scan(nil) - - if err != nil { - t.Fatalf("Expected no error, got %v", err) - } - if arr != nil { - t.Errorf("Expected nil, got %+v", arr) - } -} - -var ByteaArrayStringTests = []struct { - str string - arr ByteaArray -}{ - {`{}`, ByteaArray{}}, - {`{NULL}`, ByteaArray{nil}}, - {`{"\\xfeff"}`, ByteaArray{{'\xFE', '\xFF'}}}, - {`{"\\xdead","\\xbeef"}`, ByteaArray{{'\xDE', '\xAD'}, {'\xBE', '\xEF'}}}, -} - -func TestByteaArrayScanBytes(t *testing.T) { - for _, tt := range ByteaArrayStringTests { - bytes := []byte(tt.str) - arr := ByteaArray{{2}, {6}, {0, 0}} - err := arr.Scan(bytes) - - if err != nil { - t.Fatalf("Expected no error for %q, got %v", bytes, err) - } - if !reflect.DeepEqual(arr, tt.arr) { - t.Errorf("Expected %+v for %q, got %+v", tt.arr, bytes, arr) - } - } -} - -func BenchmarkByteaArrayScanBytes(b *testing.B) { - var a ByteaArray - var x interface{} = []byte(`{"\\xfe","\\xff","\\xdead","\\xbeef","\\xfe","\\xff","\\xdead","\\xbeef","\\xfe","\\xff"}`) - - for i := 0; i < b.N; i++ { - a = ByteaArray{} - a.Scan(x) - } -} - -func TestByteaArrayScanString(t *testing.T) { - for _, tt := range ByteaArrayStringTests { - arr := ByteaArray{{2}, {6}, {0, 0}} - err := arr.Scan(tt.str) - - if err != nil { - t.Fatalf("Expected no error for %q, got %v", tt.str, err) - } - if !reflect.DeepEqual(arr, tt.arr) { - t.Errorf("Expected %+v for %q, got %+v", tt.arr, tt.str, arr) - } - } -} - -func TestByteaArrayScanError(t *testing.T) { - for _, tt := range []struct { - input, err string - }{ - {``, "unable to parse array"}, - {`{`, "unable to parse array"}, - {`{{"\\xfeff"},{"\\xbeef"}}`, "cannot convert ARRAY[2][1] to ByteaArray"}, - {`{"\\abc"}`, "could not parse bytea array index 0: could not parse bytea value"}, - } { - arr := ByteaArray{{2}, {6}, {0, 0}} - err := arr.Scan(tt.input) - - if err == nil { - t.Fatalf("Expected error for %q, got none", tt.input) - } - if !strings.Contains(err.Error(), tt.err) { - t.Errorf("Expected error to contain %q for %q, got %q", tt.err, tt.input, err) - } - if !reflect.DeepEqual(arr, ByteaArray{{2}, {6}, {0, 0}}) { - t.Errorf("Expected destination not to change for %q, got %+v", tt.input, arr) - } - } -} - -func TestByteaArrayValue(t *testing.T) { - result, err := ByteaArray(nil).Value() - - if err != nil { - t.Fatalf("Expected no error for nil, got %v", err) - } - if result != nil { - t.Errorf("Expected nil, got %q", result) - } - - result, err = ByteaArray([][]byte{}).Value() - - if err != nil { - t.Fatalf("Expected no error for empty, got %v", err) - } - if expected := `{}`; !reflect.DeepEqual(result, expected) { - t.Errorf("Expected empty, got %q", result) - } - - result, err = ByteaArray([][]byte{{'\xDE', '\xAD', '\xBE', '\xEF'}, {'\xFE', '\xFF'}, {}}).Value() - - if err != nil { - t.Fatalf("Expected no error, got %v", err) - } - if expected := `{"\\xdeadbeef","\\xfeff","\\x"}`; !reflect.DeepEqual(result, expected) { - t.Errorf("Expected %q, got %q", expected, result) - } -} - -func BenchmarkByteaArrayValue(b *testing.B) { - rand.Seed(1) - x := make([][]byte, 10) - for i := 0; i < len(x); i++ { - x[i] = make([]byte, len(x)) - for j := 0; j < len(x); j++ { - x[i][j] = byte(rand.Int()) - } - } - a := ByteaArray(x) - - for i := 0; i < b.N; i++ { - a.Value() - } -} - -func TestFloat64ArrayScanUnsupported(t *testing.T) { - var arr Float64Array - err := arr.Scan(true) - - if err == nil { - t.Fatal("Expected error when scanning from bool") - } - if !strings.Contains(err.Error(), "bool to Float64Array") { - t.Errorf("Expected type to be mentioned when scanning, got %q", err) - } -} - -func TestFloat64ArrayScanEmpty(t *testing.T) { - var arr Float64Array - err := arr.Scan(`{}`) - - if err != nil { - t.Fatalf("Expected no error, got %v", err) - } - if arr == nil || len(arr) != 0 { - t.Errorf("Expected empty, got %#v", arr) - } -} - -func TestFloat64ArrayScanNil(t *testing.T) { - arr := Float64Array{5, 5, 5} - err := arr.Scan(nil) - - if err != nil { - t.Fatalf("Expected no error, got %v", err) - } - if arr != nil { - t.Errorf("Expected nil, got %+v", arr) - } -} - -var Float64ArrayStringTests = []struct { - str string - arr Float64Array -}{ - {`{}`, Float64Array{}}, - {`{1.2}`, Float64Array{1.2}}, - {`{3.456,7.89}`, Float64Array{3.456, 7.89}}, - {`{3,1,2}`, Float64Array{3, 1, 2}}, -} - -func TestFloat64ArrayScanBytes(t *testing.T) { - for _, tt := range Float64ArrayStringTests { - bytes := []byte(tt.str) - arr := Float64Array{5, 5, 5} - err := arr.Scan(bytes) - - if err != nil { - t.Fatalf("Expected no error for %q, got %v", bytes, err) - } - if !reflect.DeepEqual(arr, tt.arr) { - t.Errorf("Expected %+v for %q, got %+v", tt.arr, bytes, arr) - } - } -} - -func BenchmarkFloat64ArrayScanBytes(b *testing.B) { - var a Float64Array - var x interface{} = []byte(`{1.2,3.4,5.6,7.8,9.01,2.34,5.67,8.90,1.234,5.678}`) - - for i := 0; i < b.N; i++ { - a = Float64Array{} - a.Scan(x) - } -} - -func TestFloat64ArrayScanString(t *testing.T) { - for _, tt := range Float64ArrayStringTests { - arr := Float64Array{5, 5, 5} - err := arr.Scan(tt.str) - - if err != nil { - t.Fatalf("Expected no error for %q, got %v", tt.str, err) - } - if !reflect.DeepEqual(arr, tt.arr) { - t.Errorf("Expected %+v for %q, got %+v", tt.arr, tt.str, arr) - } - } -} - -func TestFloat64ArrayScanError(t *testing.T) { - for _, tt := range []struct { - input, err string - }{ - {``, "unable to parse array"}, - {`{`, "unable to parse array"}, - {`{{5.6},{7.8}}`, "cannot convert ARRAY[2][1] to Float64Array"}, - {`{NULL}`, "parsing array element index 0:"}, - {`{a}`, "parsing array element index 0:"}, - {`{5.6,a}`, "parsing array element index 1:"}, - {`{5.6,7.8,a}`, "parsing array element index 2:"}, - } { - arr := Float64Array{5, 5, 5} - err := arr.Scan(tt.input) - - if err == nil { - t.Fatalf("Expected error for %q, got none", tt.input) - } - if !strings.Contains(err.Error(), tt.err) { - t.Errorf("Expected error to contain %q for %q, got %q", tt.err, tt.input, err) - } - if !reflect.DeepEqual(arr, Float64Array{5, 5, 5}) { - t.Errorf("Expected destination not to change for %q, got %+v", tt.input, arr) - } - } -} - -func TestFloat64ArrayValue(t *testing.T) { - result, err := Float64Array(nil).Value() - - if err != nil { - t.Fatalf("Expected no error for nil, got %v", err) - } - if result != nil { - t.Errorf("Expected nil, got %q", result) - } - - result, err = Float64Array([]float64{}).Value() - - if err != nil { - t.Fatalf("Expected no error for empty, got %v", err) - } - if expected := `{}`; !reflect.DeepEqual(result, expected) { - t.Errorf("Expected empty, got %q", result) - } - - result, err = Float64Array([]float64{1.2, 3.4, 5.6}).Value() - - if err != nil { - t.Fatalf("Expected no error, got %v", err) - } - if expected := `{1.2,3.4,5.6}`; !reflect.DeepEqual(result, expected) { - t.Errorf("Expected %q, got %q", expected, result) - } -} - -func BenchmarkFloat64ArrayValue(b *testing.B) { - rand.Seed(1) - x := make([]float64, 10) - for i := 0; i < len(x); i++ { - x[i] = rand.NormFloat64() - } - a := Float64Array(x) - - for i := 0; i < b.N; i++ { - a.Value() - } -} - -func TestInt64ArrayScanUnsupported(t *testing.T) { - var arr Int64Array - err := arr.Scan(true) - - if err == nil { - t.Fatal("Expected error when scanning from bool") - } - if !strings.Contains(err.Error(), "bool to Int64Array") { - t.Errorf("Expected type to be mentioned when scanning, got %q", err) - } -} - -func TestInt64ArrayScanEmpty(t *testing.T) { - var arr Int64Array - err := arr.Scan(`{}`) - - if err != nil { - t.Fatalf("Expected no error, got %v", err) - } - if arr == nil || len(arr) != 0 { - t.Errorf("Expected empty, got %#v", arr) - } -} - -func TestInt64ArrayScanNil(t *testing.T) { - arr := Int64Array{5, 5, 5} - err := arr.Scan(nil) - - if err != nil { - t.Fatalf("Expected no error, got %v", err) - } - if arr != nil { - t.Errorf("Expected nil, got %+v", arr) - } -} - -var Int64ArrayStringTests = []struct { - str string - arr Int64Array -}{ - {`{}`, Int64Array{}}, - {`{12}`, Int64Array{12}}, - {`{345,678}`, Int64Array{345, 678}}, -} - -func TestInt64ArrayScanBytes(t *testing.T) { - for _, tt := range Int64ArrayStringTests { - bytes := []byte(tt.str) - arr := Int64Array{5, 5, 5} - err := arr.Scan(bytes) - - if err != nil { - t.Fatalf("Expected no error for %q, got %v", bytes, err) - } - if !reflect.DeepEqual(arr, tt.arr) { - t.Errorf("Expected %+v for %q, got %+v", tt.arr, bytes, arr) - } - } -} - -func BenchmarkInt64ArrayScanBytes(b *testing.B) { - var a Int64Array - var x interface{} = []byte(`{1,2,3,4,5,6,7,8,9,0}`) - - for i := 0; i < b.N; i++ { - a = Int64Array{} - a.Scan(x) - } -} - -func TestInt64ArrayScanString(t *testing.T) { - for _, tt := range Int64ArrayStringTests { - arr := Int64Array{5, 5, 5} - err := arr.Scan(tt.str) - - if err != nil { - t.Fatalf("Expected no error for %q, got %v", tt.str, err) - } - if !reflect.DeepEqual(arr, tt.arr) { - t.Errorf("Expected %+v for %q, got %+v", tt.arr, tt.str, arr) - } - } -} - -func TestInt64ArrayScanError(t *testing.T) { - for _, tt := range []struct { - input, err string - }{ - {``, "unable to parse array"}, - {`{`, "unable to parse array"}, - {`{{5},{6}}`, "cannot convert ARRAY[2][1] to Int64Array"}, - {`{NULL}`, "parsing array element index 0:"}, - {`{a}`, "parsing array element index 0:"}, - {`{5,a}`, "parsing array element index 1:"}, - {`{5,6,a}`, "parsing array element index 2:"}, - } { - arr := Int64Array{5, 5, 5} - err := arr.Scan(tt.input) - - if err == nil { - t.Fatalf("Expected error for %q, got none", tt.input) - } - if !strings.Contains(err.Error(), tt.err) { - t.Errorf("Expected error to contain %q for %q, got %q", tt.err, tt.input, err) - } - if !reflect.DeepEqual(arr, Int64Array{5, 5, 5}) { - t.Errorf("Expected destination not to change for %q, got %+v", tt.input, arr) - } - } -} - -func TestInt64ArrayValue(t *testing.T) { - result, err := Int64Array(nil).Value() - - if err != nil { - t.Fatalf("Expected no error for nil, got %v", err) - } - if result != nil { - t.Errorf("Expected nil, got %q", result) - } - - result, err = Int64Array([]int64{}).Value() - - if err != nil { - t.Fatalf("Expected no error for empty, got %v", err) - } - if expected := `{}`; !reflect.DeepEqual(result, expected) { - t.Errorf("Expected empty, got %q", result) - } - - result, err = Int64Array([]int64{1, 2, 3}).Value() - - if err != nil { - t.Fatalf("Expected no error, got %v", err) - } - if expected := `{1,2,3}`; !reflect.DeepEqual(result, expected) { - t.Errorf("Expected %q, got %q", expected, result) - } -} - -func BenchmarkInt64ArrayValue(b *testing.B) { - rand.Seed(1) - x := make([]int64, 10) - for i := 0; i < len(x); i++ { - x[i] = rand.Int63() - } - a := Int64Array(x) - - for i := 0; i < b.N; i++ { - a.Value() - } -} - -func TestStringArrayScanUnsupported(t *testing.T) { - var arr StringArray - err := arr.Scan(true) - - if err == nil { - t.Fatal("Expected error when scanning from bool") - } - if !strings.Contains(err.Error(), "bool to StringArray") { - t.Errorf("Expected type to be mentioned when scanning, got %q", err) - } -} - -func TestStringArrayScanEmpty(t *testing.T) { - var arr StringArray - err := arr.Scan(`{}`) - - if err != nil { - t.Fatalf("Expected no error, got %v", err) - } - if arr == nil || len(arr) != 0 { - t.Errorf("Expected empty, got %#v", arr) - } -} - -func TestStringArrayScanNil(t *testing.T) { - arr := StringArray{"x", "x", "x"} - err := arr.Scan(nil) - - if err != nil { - t.Fatalf("Expected no error, got %v", err) - } - if arr != nil { - t.Errorf("Expected nil, got %+v", arr) - } -} - -var StringArrayStringTests = []struct { - str string - arr StringArray -}{ - {`{}`, StringArray{}}, - {`{t}`, StringArray{"t"}}, - {`{f,1}`, StringArray{"f", "1"}}, - {`{"a\\b","c d",","}`, StringArray{"a\\b", "c d", ","}}, -} - -func TestStringArrayScanBytes(t *testing.T) { - for _, tt := range StringArrayStringTests { - bytes := []byte(tt.str) - arr := StringArray{"x", "x", "x"} - err := arr.Scan(bytes) - - if err != nil { - t.Fatalf("Expected no error for %q, got %v", bytes, err) - } - if !reflect.DeepEqual(arr, tt.arr) { - t.Errorf("Expected %+v for %q, got %+v", tt.arr, bytes, arr) - } - } -} - -func BenchmarkStringArrayScanBytes(b *testing.B) { - var a StringArray - var x interface{} = []byte(`{a,b,c,d,e,f,g,h,i,j}`) - var y interface{} = []byte(`{"\a","\b","\c","\d","\e","\f","\g","\h","\i","\j"}`) - - for i := 0; i < b.N; i++ { - a = StringArray{} - a.Scan(x) - a = StringArray{} - a.Scan(y) - } -} - -func TestStringArrayScanString(t *testing.T) { - for _, tt := range StringArrayStringTests { - arr := StringArray{"x", "x", "x"} - err := arr.Scan(tt.str) - - if err != nil { - t.Fatalf("Expected no error for %q, got %v", tt.str, err) - } - if !reflect.DeepEqual(arr, tt.arr) { - t.Errorf("Expected %+v for %q, got %+v", tt.arr, tt.str, arr) - } - } -} - -func TestStringArrayScanError(t *testing.T) { - for _, tt := range []struct { - input, err string - }{ - {``, "unable to parse array"}, - {`{`, "unable to parse array"}, - {`{{a},{b}}`, "cannot convert ARRAY[2][1] to StringArray"}, - {`{NULL}`, "parsing array element index 0: cannot convert nil to string"}, - {`{a,NULL}`, "parsing array element index 1: cannot convert nil to string"}, - {`{a,b,NULL}`, "parsing array element index 2: cannot convert nil to string"}, - } { - arr := StringArray{"x", "x", "x"} - err := arr.Scan(tt.input) - - if err == nil { - t.Fatalf("Expected error for %q, got none", tt.input) - } - if !strings.Contains(err.Error(), tt.err) { - t.Errorf("Expected error to contain %q for %q, got %q", tt.err, tt.input, err) - } - if !reflect.DeepEqual(arr, StringArray{"x", "x", "x"}) { - t.Errorf("Expected destination not to change for %q, got %+v", tt.input, arr) - } - } -} - -func TestStringArrayValue(t *testing.T) { - result, err := StringArray(nil).Value() - - if err != nil { - t.Fatalf("Expected no error for nil, got %v", err) - } - if result != nil { - t.Errorf("Expected nil, got %q", result) - } - - result, err = StringArray([]string{}).Value() - - if err != nil { - t.Fatalf("Expected no error for empty, got %v", err) - } - if expected := `{}`; !reflect.DeepEqual(result, expected) { - t.Errorf("Expected empty, got %q", result) - } - - result, err = StringArray([]string{`a`, `\b`, `c"`, `d,e`}).Value() - - if err != nil { - t.Fatalf("Expected no error, got %v", err) - } - if expected := `{"a","\\b","c\"","d,e"}`; !reflect.DeepEqual(result, expected) { - t.Errorf("Expected %q, got %q", expected, result) - } -} - -func BenchmarkStringArrayValue(b *testing.B) { - x := make([]string, 10) - for i := 0; i < len(x); i++ { - x[i] = strings.Repeat(`abc"def\ghi`, 5) - } - a := StringArray(x) - - for i := 0; i < b.N; i++ { - a.Value() - } -} - -func TestGenericArrayScanUnsupported(t *testing.T) { - var s string - var ss []string - var nsa [1]sql.NullString - - for _, tt := range []struct { - src, dest interface{} - err string - }{ - {nil, nil, "destination is not a pointer to array or slice"}, - {nil, true, "destination bool is not a pointer to array or slice"}, - {nil, &s, "destination *string is not a pointer to array or slice"}, - {nil, ss, "destination []string is not a pointer to array or slice"}, - {nil, &nsa, " to [1]sql.NullString"}, - {true, &ss, "bool to []string"}, - {`{{x}}`, &ss, "multidimensional ARRAY[1][1] is not implemented"}, - {`{{x},{x}}`, &ss, "multidimensional ARRAY[2][1] is not implemented"}, - {`{x}`, &ss, "scanning to string is not implemented"}, - } { - err := GenericArray{tt.dest}.Scan(tt.src) - - if err == nil { - t.Fatalf("Expected error for [%#v %#v]", tt.src, tt.dest) - } - if !strings.Contains(err.Error(), tt.err) { - t.Errorf("Expected error to contain %q for [%#v %#v], got %q", tt.err, tt.src, tt.dest, err) - } - } -} - -func TestGenericArrayScanScannerArrayBytes(t *testing.T) { - src, expected, nsa := []byte(`{NULL,abc,"\""}`), - [3]sql.NullString{{}, {String: `abc`, Valid: true}, {String: `"`, Valid: true}}, - [3]sql.NullString{{String: ``, Valid: true}, {}, {}} - - if err := (GenericArray{&nsa}).Scan(src); err != nil { - t.Fatalf("Expected no error, got %v", err) - } - if !reflect.DeepEqual(nsa, expected) { - t.Errorf("Expected %v, got %v", expected, nsa) - } -} - -func TestGenericArrayScanScannerArrayString(t *testing.T) { - src, expected, nsa := `{NULL,"\"",xyz}`, - [3]sql.NullString{{}, {String: `"`, Valid: true}, {String: `xyz`, Valid: true}}, - [3]sql.NullString{{String: ``, Valid: true}, {}, {}} - - if err := (GenericArray{&nsa}).Scan(src); err != nil { - t.Fatalf("Expected no error, got %v", err) - } - if !reflect.DeepEqual(nsa, expected) { - t.Errorf("Expected %v, got %v", expected, nsa) - } -} - -func TestGenericArrayScanScannerSliceEmpty(t *testing.T) { - var nss []sql.NullString - - if err := (GenericArray{&nss}).Scan(`{}`); err != nil { - t.Fatalf("Expected no error, got %v", err) - } - if nss == nil || len(nss) != 0 { - t.Errorf("Expected empty, got %#v", nss) - } -} - -func TestGenericArrayScanScannerSliceNil(t *testing.T) { - nss := []sql.NullString{{String: ``, Valid: true}, {}} - - if err := (GenericArray{&nss}).Scan(nil); err != nil { - t.Fatalf("Expected no error, got %v", err) - } - if nss != nil { - t.Errorf("Expected nil, got %+v", nss) - } -} - -func TestGenericArrayScanScannerSliceBytes(t *testing.T) { - src, expected, nss := []byte(`{NULL,abc,"\""}`), - []sql.NullString{{}, {String: `abc`, Valid: true}, {String: `"`, Valid: true}}, - []sql.NullString{{String: ``, Valid: true}, {}, {}, {}, {}} - - if err := (GenericArray{&nss}).Scan(src); err != nil { - t.Fatalf("Expected no error, got %v", err) - } - if !reflect.DeepEqual(nss, expected) { - t.Errorf("Expected %v, got %v", expected, nss) - } -} - -func BenchmarkGenericArrayScanScannerSliceBytes(b *testing.B) { - var a GenericArray - var x interface{} = []byte(`{a,b,c,d,e,f,g,h,i,j}`) - var y interface{} = []byte(`{"\a","\b","\c","\d","\e","\f","\g","\h","\i","\j"}`) - - for i := 0; i < b.N; i++ { - a = GenericArray{new([]sql.NullString)} - a.Scan(x) - a = GenericArray{new([]sql.NullString)} - a.Scan(y) - } -} - -func TestGenericArrayScanScannerSliceString(t *testing.T) { - src, expected, nss := `{NULL,"\"",xyz}`, - []sql.NullString{{}, {String: `"`, Valid: true}, {String: `xyz`, Valid: true}}, - []sql.NullString{{String: ``, Valid: true}, {}, {}} - - if err := (GenericArray{&nss}).Scan(src); err != nil { - t.Fatalf("Expected no error, got %v", err) - } - if !reflect.DeepEqual(nss, expected) { - t.Errorf("Expected %v, got %v", expected, nss) - } -} - -type TildeNullInt64 struct{ sql.NullInt64 } - -func (TildeNullInt64) ArrayDelimiter() string { return "~" } - -func TestGenericArrayScanDelimiter(t *testing.T) { - src, expected, tnis := `{12~NULL~76}`, - []TildeNullInt64{{sql.NullInt64{Int64: 12, Valid: true}}, {}, {sql.NullInt64{Int64: 76, Valid: true}}}, - []TildeNullInt64{{sql.NullInt64{Int64: 0, Valid: true}}, {}} - - if err := (GenericArray{&tnis}).Scan(src); err != nil { - t.Fatalf("Expected no error for %#v, got %v", src, err) - } - if !reflect.DeepEqual(tnis, expected) { - t.Errorf("Expected %v for %#v, got %v", expected, src, tnis) - } -} - -func TestGenericArrayScanErrors(t *testing.T) { - var sa [1]string - var nis []sql.NullInt64 - var pss *[]string - - for _, tt := range []struct { - src, dest interface{} - err string - }{ - {nil, pss, "destination *[]string is nil"}, - {`{`, &sa, "unable to parse"}, - {`{}`, &sa, "cannot convert ARRAY[0] to [1]string"}, - {`{x,x}`, &sa, "cannot convert ARRAY[2] to [1]string"}, - {`{x}`, &nis, `parsing array element index 0: converting`}, - } { - err := GenericArray{tt.dest}.Scan(tt.src) - - if err == nil { - t.Fatalf("Expected error for [%#v %#v]", tt.src, tt.dest) - } - if !strings.Contains(err.Error(), tt.err) { - t.Errorf("Expected error to contain %q for [%#v %#v], got %q", tt.err, tt.src, tt.dest, err) - } - } -} - -func TestGenericArrayValueUnsupported(t *testing.T) { - _, err := GenericArray{true}.Value() - - if err == nil { - t.Fatal("Expected error for bool") - } - if !strings.Contains(err.Error(), "bool to array") { - t.Errorf("Expected type to be mentioned, got %q", err) - } -} - -type ByteArrayValuer [1]byte -type ByteSliceValuer []byte -type FuncArrayValuer struct { - delimiter func() string - value func() (driver.Value, error) -} - -func (a ByteArrayValuer) Value() (driver.Value, error) { return a[:], nil } -func (b ByteSliceValuer) Value() (driver.Value, error) { return []byte(b), nil } -func (f FuncArrayValuer) ArrayDelimiter() string { return f.delimiter() } -func (f FuncArrayValuer) Value() (driver.Value, error) { return f.value() } - -func TestGenericArrayValue(t *testing.T) { - result, err := GenericArray{nil}.Value() - - if err != nil { - t.Fatalf("Expected no error for nil, got %v", err) - } - if result != nil { - t.Errorf("Expected nil, got %q", result) - } - - for _, tt := range []interface{}{ - []bool(nil), - [][]int(nil), - []*int(nil), - []sql.NullString(nil), - } { - result, err := GenericArray{tt}.Value() - - if err != nil { - t.Fatalf("Expected no error for %#v, got %v", tt, err) - } - if result != nil { - t.Errorf("Expected nil for %#v, got %q", tt, result) - } - } - - Tilde := func(v driver.Value) FuncArrayValuer { - return FuncArrayValuer{ - func() string { return "~" }, - func() (driver.Value, error) { return v, nil }} - } - - for _, tt := range []struct { - result string - input interface{} - }{ - {`{}`, []bool{}}, - {`{true}`, []bool{true}}, - {`{true,false}`, []bool{true, false}}, - {`{true,false}`, [2]bool{true, false}}, - - {`{}`, [][]int{{}}}, - {`{}`, [][]int{{}, {}}}, - {`{{1}}`, [][]int{{1}}}, - {`{{1},{2}}`, [][]int{{1}, {2}}}, - {`{{1,2},{3,4}}`, [][]int{{1, 2}, {3, 4}}}, - {`{{1,2},{3,4}}`, [2][2]int{{1, 2}, {3, 4}}}, - - {`{"a","\\b","c\"","d,e"}`, []string{`a`, `\b`, `c"`, `d,e`}}, - {`{"a","\\b","c\"","d,e"}`, [][]byte{{'a'}, {'\\', 'b'}, {'c', '"'}, {'d', ',', 'e'}}}, - - {`{NULL}`, []*int{nil}}, - {`{0,NULL}`, []*int{new(int), nil}}, - - {`{NULL}`, []sql.NullString{{}}}, - {`{"\"",NULL}`, []sql.NullString{{String: `"`, Valid: true}, {}}}, - - {`{"a","b"}`, []ByteArrayValuer{{'a'}, {'b'}}}, - {`{{"a","b"},{"c","d"}}`, [][]ByteArrayValuer{{{'a'}, {'b'}}, {{'c'}, {'d'}}}}, - - {`{"e","f"}`, []ByteSliceValuer{{'e'}, {'f'}}}, - {`{{"e","f"},{"g","h"}}`, [][]ByteSliceValuer{{{'e'}, {'f'}}, {{'g'}, {'h'}}}}, - - {`{1~2}`, []FuncArrayValuer{Tilde(int64(1)), Tilde(int64(2))}}, - {`{{1~2}~{3~4}}`, [][]FuncArrayValuer{{Tilde(int64(1)), Tilde(int64(2))}, {Tilde(int64(3)), Tilde(int64(4))}}}, - } { - result, err := GenericArray{tt.input}.Value() - - if err != nil { - t.Fatalf("Expected no error for %q, got %v", tt.input, err) - } - if !reflect.DeepEqual(result, tt.result) { - t.Errorf("Expected %q for %q, got %q", tt.result, tt.input, result) - } - } -} - -func TestGenericArrayValueErrors(t *testing.T) { - v := []interface{}{func() {}} - if _, err := (GenericArray{v}).Value(); err == nil { - t.Errorf("Expected error for %q, got nil", v) - } - - v = []interface{}{nil, func() {}} - if _, err := (GenericArray{v}).Value(); err == nil { - t.Errorf("Expected error for %q, got nil", v) - } -} - -func BenchmarkGenericArrayValueBools(b *testing.B) { - rand.Seed(1) - x := make([]bool, 10) - for i := 0; i < len(x); i++ { - x[i] = rand.Intn(2) == 0 - } - a := GenericArray{x} - - for i := 0; i < b.N; i++ { - a.Value() - } -} - -func BenchmarkGenericArrayValueFloat64s(b *testing.B) { - rand.Seed(1) - x := make([]float64, 10) - for i := 0; i < len(x); i++ { - x[i] = rand.NormFloat64() - } - a := GenericArray{x} - - for i := 0; i < b.N; i++ { - a.Value() - } -} - -func BenchmarkGenericArrayValueInt64s(b *testing.B) { - rand.Seed(1) - x := make([]int64, 10) - for i := 0; i < len(x); i++ { - x[i] = rand.Int63() - } - a := GenericArray{x} - - for i := 0; i < b.N; i++ { - a.Value() - } -} - -func BenchmarkGenericArrayValueByteSlices(b *testing.B) { - x := make([][]byte, 10) - for i := 0; i < len(x); i++ { - x[i] = bytes.Repeat([]byte(`abc"def\ghi`), 5) - } - a := GenericArray{x} - - for i := 0; i < b.N; i++ { - a.Value() - } -} - -func BenchmarkGenericArrayValueStrings(b *testing.B) { - x := make([]string, 10) - for i := 0; i < len(x); i++ { - x[i] = strings.Repeat(`abc"def\ghi`, 5) - } - a := GenericArray{x} - - for i := 0; i < b.N; i++ { - a.Value() - } -} - -func TestArrayScanBackend(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - for _, tt := range []struct { - s string - d sql.Scanner - e interface{} - }{ - {`ARRAY[true, false]`, new(BoolArray), &BoolArray{true, false}}, - {`ARRAY[E'\\xdead', E'\\xbeef']`, new(ByteaArray), &ByteaArray{{'\xDE', '\xAD'}, {'\xBE', '\xEF'}}}, - {`ARRAY[1.2, 3.4]`, new(Float64Array), &Float64Array{1.2, 3.4}}, - {`ARRAY[1, 2, 3]`, new(Int64Array), &Int64Array{1, 2, 3}}, - {`ARRAY['a', E'\\b', 'c"', 'd,e']`, new(StringArray), &StringArray{`a`, `\b`, `c"`, `d,e`}}, - } { - err := db.QueryRow(`SELECT ` + tt.s).Scan(tt.d) - if err != nil { - t.Errorf("Expected no error when scanning %s into %T, got %v", tt.s, tt.d, err) - } - if !reflect.DeepEqual(tt.d, tt.e) { - t.Errorf("Expected %v when scanning %s into %T, got %v", tt.e, tt.s, tt.d, tt.d) - } - } -} - -func TestArrayValueBackend(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - for _, tt := range []struct { - s string - v driver.Valuer - }{ - {`ARRAY[true, false]`, BoolArray{true, false}}, - {`ARRAY[E'\\xdead', E'\\xbeef']`, ByteaArray{{'\xDE', '\xAD'}, {'\xBE', '\xEF'}}}, - {`ARRAY[1.2, 3.4]`, Float64Array{1.2, 3.4}}, - {`ARRAY[1, 2, 3]`, Int64Array{1, 2, 3}}, - {`ARRAY['a', E'\\b', 'c"', 'd,e']`, StringArray{`a`, `\b`, `c"`, `d,e`}}, - } { - var x int - err := db.QueryRow(`SELECT 1 WHERE `+tt.s+` <> $1`, tt.v).Scan(&x) - if err != sql.ErrNoRows { - t.Errorf("Expected %v to equal %s, got %v", tt.v, tt.s, err) - } - } -} diff --git a/vendor/github.com/lib/pq/bench_test.go b/vendor/github.com/lib/pq/bench_test.go deleted file mode 100644 index 33d7a02f..00000000 --- a/vendor/github.com/lib/pq/bench_test.go +++ /dev/null @@ -1,436 +0,0 @@ -// +build go1.1 - -package pq - -import ( - "bufio" - "bytes" - "context" - "database/sql" - "database/sql/driver" - "io" - "math/rand" - "net" - "runtime" - "strconv" - "strings" - "sync" - "testing" - "time" - - "github.com/lib/pq/oid" -) - -var ( - selectStringQuery = "SELECT '" + strings.Repeat("0123456789", 10) + "'" - selectSeriesQuery = "SELECT generate_series(1, 100)" -) - -func BenchmarkSelectString(b *testing.B) { - var result string - benchQuery(b, selectStringQuery, &result) -} - -func BenchmarkSelectSeries(b *testing.B) { - var result int - benchQuery(b, selectSeriesQuery, &result) -} - -func benchQuery(b *testing.B, query string, result interface{}) { - b.StopTimer() - db := openTestConn(b) - defer db.Close() - b.StartTimer() - - for i := 0; i < b.N; i++ { - benchQueryLoop(b, db, query, result) - } -} - -func benchQueryLoop(b *testing.B, db *sql.DB, query string, result interface{}) { - rows, err := db.Query(query) - if err != nil { - b.Fatal(err) - } - defer rows.Close() - for rows.Next() { - err = rows.Scan(result) - if err != nil { - b.Fatal("failed to scan", err) - } - } -} - -// reading from circularConn yields content[:prefixLen] once, followed by -// content[prefixLen:] over and over again. It never returns EOF. -type circularConn struct { - content string - prefixLen int - pos int - net.Conn // for all other net.Conn methods that will never be called -} - -func (r *circularConn) Read(b []byte) (n int, err error) { - n = copy(b, r.content[r.pos:]) - r.pos += n - if r.pos >= len(r.content) { - r.pos = r.prefixLen - } - return -} - -func (r *circularConn) Write(b []byte) (n int, err error) { return len(b), nil } - -func (r *circularConn) Close() error { return nil } - -func fakeConn(content string, prefixLen int) *conn { - c := &circularConn{content: content, prefixLen: prefixLen} - return &conn{buf: bufio.NewReader(c), c: c} -} - -// This benchmark is meant to be the same as BenchmarkSelectString, but takes -// out some of the factors this package can't control. The numbers are less noisy, -// but also the costs of network communication aren't accurately represented. -func BenchmarkMockSelectString(b *testing.B) { - b.StopTimer() - // taken from a recorded run of BenchmarkSelectString - // See: http://www.postgresql.org/docs/current/static/protocol-message-formats.html - const response = "1\x00\x00\x00\x04" + - "t\x00\x00\x00\x06\x00\x00" + - "T\x00\x00\x00!\x00\x01?column?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xc1\xff\xfe\xff\xff\xff\xff\x00\x00" + - "Z\x00\x00\x00\x05I" + - "2\x00\x00\x00\x04" + - "D\x00\x00\x00n\x00\x01\x00\x00\x00d0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" + - "C\x00\x00\x00\rSELECT 1\x00" + - "Z\x00\x00\x00\x05I" + - "3\x00\x00\x00\x04" + - "Z\x00\x00\x00\x05I" - c := fakeConn(response, 0) - b.StartTimer() - - for i := 0; i < b.N; i++ { - benchMockQuery(b, c, selectStringQuery) - } -} - -var seriesRowData = func() string { - var buf bytes.Buffer - for i := 1; i <= 100; i++ { - digits := byte(2) - if i >= 100 { - digits = 3 - } else if i < 10 { - digits = 1 - } - buf.WriteString("D\x00\x00\x00") - buf.WriteByte(10 + digits) - buf.WriteString("\x00\x01\x00\x00\x00") - buf.WriteByte(digits) - buf.WriteString(strconv.Itoa(i)) - } - return buf.String() -}() - -func BenchmarkMockSelectSeries(b *testing.B) { - b.StopTimer() - var response = "1\x00\x00\x00\x04" + - "t\x00\x00\x00\x06\x00\x00" + - "T\x00\x00\x00!\x00\x01?column?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xc1\xff\xfe\xff\xff\xff\xff\x00\x00" + - "Z\x00\x00\x00\x05I" + - "2\x00\x00\x00\x04" + - seriesRowData + - "C\x00\x00\x00\x0fSELECT 100\x00" + - "Z\x00\x00\x00\x05I" + - "3\x00\x00\x00\x04" + - "Z\x00\x00\x00\x05I" - c := fakeConn(response, 0) - b.StartTimer() - - for i := 0; i < b.N; i++ { - benchMockQuery(b, c, selectSeriesQuery) - } -} - -func benchMockQuery(b *testing.B, c *conn, query string) { - stmt, err := c.Prepare(query) - if err != nil { - b.Fatal(err) - } - defer stmt.Close() - rows, err := stmt.(driver.StmtQueryContext).QueryContext(context.Background(), nil) - if err != nil { - b.Fatal(err) - } - defer rows.Close() - var dest [1]driver.Value - for { - if err := rows.Next(dest[:]); err != nil { - if err == io.EOF { - break - } - b.Fatal(err) - } - } -} - -func BenchmarkPreparedSelectString(b *testing.B) { - var result string - benchPreparedQuery(b, selectStringQuery, &result) -} - -func BenchmarkPreparedSelectSeries(b *testing.B) { - var result int - benchPreparedQuery(b, selectSeriesQuery, &result) -} - -func benchPreparedQuery(b *testing.B, query string, result interface{}) { - b.StopTimer() - db := openTestConn(b) - defer db.Close() - stmt, err := db.Prepare(query) - if err != nil { - b.Fatal(err) - } - defer stmt.Close() - b.StartTimer() - - for i := 0; i < b.N; i++ { - benchPreparedQueryLoop(b, db, stmt, result) - } -} - -func benchPreparedQueryLoop(b *testing.B, db *sql.DB, stmt *sql.Stmt, result interface{}) { - rows, err := stmt.Query() - if err != nil { - b.Fatal(err) - } - if !rows.Next() { - rows.Close() - b.Fatal("no rows") - } - defer rows.Close() - for rows.Next() { - err = rows.Scan(&result) - if err != nil { - b.Fatal("failed to scan") - } - } -} - -// See the comment for BenchmarkMockSelectString. -func BenchmarkMockPreparedSelectString(b *testing.B) { - b.StopTimer() - const parseResponse = "1\x00\x00\x00\x04" + - "t\x00\x00\x00\x06\x00\x00" + - "T\x00\x00\x00!\x00\x01?column?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xc1\xff\xfe\xff\xff\xff\xff\x00\x00" + - "Z\x00\x00\x00\x05I" - const responses = parseResponse + - "2\x00\x00\x00\x04" + - "D\x00\x00\x00n\x00\x01\x00\x00\x00d0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" + - "C\x00\x00\x00\rSELECT 1\x00" + - "Z\x00\x00\x00\x05I" - c := fakeConn(responses, len(parseResponse)) - - stmt, err := c.Prepare(selectStringQuery) - if err != nil { - b.Fatal(err) - } - b.StartTimer() - - for i := 0; i < b.N; i++ { - benchPreparedMockQuery(b, c, stmt) - } -} - -func BenchmarkMockPreparedSelectSeries(b *testing.B) { - b.StopTimer() - const parseResponse = "1\x00\x00\x00\x04" + - "t\x00\x00\x00\x06\x00\x00" + - "T\x00\x00\x00!\x00\x01?column?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xc1\xff\xfe\xff\xff\xff\xff\x00\x00" + - "Z\x00\x00\x00\x05I" - var responses = parseResponse + - "2\x00\x00\x00\x04" + - seriesRowData + - "C\x00\x00\x00\x0fSELECT 100\x00" + - "Z\x00\x00\x00\x05I" - c := fakeConn(responses, len(parseResponse)) - - stmt, err := c.Prepare(selectSeriesQuery) - if err != nil { - b.Fatal(err) - } - b.StartTimer() - - for i := 0; i < b.N; i++ { - benchPreparedMockQuery(b, c, stmt) - } -} - -func benchPreparedMockQuery(b *testing.B, c *conn, stmt driver.Stmt) { - rows, err := stmt.(driver.StmtQueryContext).QueryContext(context.Background(), nil) - if err != nil { - b.Fatal(err) - } - defer rows.Close() - var dest [1]driver.Value - for { - if err := rows.Next(dest[:]); err != nil { - if err == io.EOF { - break - } - b.Fatal(err) - } - } -} - -func BenchmarkEncodeInt64(b *testing.B) { - for i := 0; i < b.N; i++ { - encode(¶meterStatus{}, int64(1234), oid.T_int8) - } -} - -func BenchmarkEncodeFloat64(b *testing.B) { - for i := 0; i < b.N; i++ { - encode(¶meterStatus{}, 3.14159, oid.T_float8) - } -} - -var testByteString = []byte("abcdefghijklmnopqrstuvwxyz") - -func BenchmarkEncodeByteaHex(b *testing.B) { - for i := 0; i < b.N; i++ { - encode(¶meterStatus{serverVersion: 90000}, testByteString, oid.T_bytea) - } -} -func BenchmarkEncodeByteaEscape(b *testing.B) { - for i := 0; i < b.N; i++ { - encode(¶meterStatus{serverVersion: 84000}, testByteString, oid.T_bytea) - } -} - -func BenchmarkEncodeBool(b *testing.B) { - for i := 0; i < b.N; i++ { - encode(¶meterStatus{}, true, oid.T_bool) - } -} - -var testTimestamptz = time.Date(2001, time.January, 1, 0, 0, 0, 0, time.Local) - -func BenchmarkEncodeTimestamptz(b *testing.B) { - for i := 0; i < b.N; i++ { - encode(¶meterStatus{}, testTimestamptz, oid.T_timestamptz) - } -} - -var testIntBytes = []byte("1234") - -func BenchmarkDecodeInt64(b *testing.B) { - for i := 0; i < b.N; i++ { - decode(¶meterStatus{}, testIntBytes, oid.T_int8, formatText) - } -} - -var testFloatBytes = []byte("3.14159") - -func BenchmarkDecodeFloat64(b *testing.B) { - for i := 0; i < b.N; i++ { - decode(¶meterStatus{}, testFloatBytes, oid.T_float8, formatText) - } -} - -var testBoolBytes = []byte{'t'} - -func BenchmarkDecodeBool(b *testing.B) { - for i := 0; i < b.N; i++ { - decode(¶meterStatus{}, testBoolBytes, oid.T_bool, formatText) - } -} - -func TestDecodeBool(t *testing.T) { - db := openTestConn(t) - rows, err := db.Query("select true") - if err != nil { - t.Fatal(err) - } - rows.Close() -} - -var testTimestamptzBytes = []byte("2013-09-17 22:15:32.360754-07") - -func BenchmarkDecodeTimestamptz(b *testing.B) { - for i := 0; i < b.N; i++ { - decode(¶meterStatus{}, testTimestamptzBytes, oid.T_timestamptz, formatText) - } -} - -func BenchmarkDecodeTimestamptzMultiThread(b *testing.B) { - oldProcs := runtime.GOMAXPROCS(0) - defer runtime.GOMAXPROCS(oldProcs) - runtime.GOMAXPROCS(runtime.NumCPU()) - globalLocationCache = newLocationCache() - - f := func(wg *sync.WaitGroup, loops int) { - defer wg.Done() - for i := 0; i < loops; i++ { - decode(¶meterStatus{}, testTimestamptzBytes, oid.T_timestamptz, formatText) - } - } - - wg := &sync.WaitGroup{} - b.ResetTimer() - for j := 0; j < 10; j++ { - wg.Add(1) - go f(wg, b.N/10) - } - wg.Wait() -} - -func BenchmarkLocationCache(b *testing.B) { - globalLocationCache = newLocationCache() - for i := 0; i < b.N; i++ { - globalLocationCache.getLocation(rand.Intn(10000)) - } -} - -func BenchmarkLocationCacheMultiThread(b *testing.B) { - oldProcs := runtime.GOMAXPROCS(0) - defer runtime.GOMAXPROCS(oldProcs) - runtime.GOMAXPROCS(runtime.NumCPU()) - globalLocationCache = newLocationCache() - - f := func(wg *sync.WaitGroup, loops int) { - defer wg.Done() - for i := 0; i < loops; i++ { - globalLocationCache.getLocation(rand.Intn(10000)) - } - } - - wg := &sync.WaitGroup{} - b.ResetTimer() - for j := 0; j < 10; j++ { - wg.Add(1) - go f(wg, b.N/10) - } - wg.Wait() -} - -// Stress test the performance of parsing results from the wire. -func BenchmarkResultParsing(b *testing.B) { - b.StopTimer() - - db := openTestConn(b) - defer db.Close() - _, err := db.Exec("BEGIN") - if err != nil { - b.Fatal(err) - } - - b.StartTimer() - for i := 0; i < b.N; i++ { - res, err := db.Query("SELECT generate_series(1, 50000)") - if err != nil { - b.Fatal(err) - } - res.Close() - } -} diff --git a/vendor/github.com/lib/pq/conn_test.go b/vendor/github.com/lib/pq/conn_test.go deleted file mode 100644 index e654b85b..00000000 --- a/vendor/github.com/lib/pq/conn_test.go +++ /dev/null @@ -1,1659 +0,0 @@ -package pq - -import ( - "context" - "database/sql" - "database/sql/driver" - "fmt" - "io" - "net" - "os" - "reflect" - "strings" - "testing" - "time" -) - -type Fatalistic interface { - Fatal(args ...interface{}) -} - -func forceBinaryParameters() bool { - bp := os.Getenv("PQTEST_BINARY_PARAMETERS") - if bp == "yes" { - return true - } else if bp == "" || bp == "no" { - return false - } else { - panic("unexpected value for PQTEST_BINARY_PARAMETERS") - } -} - -func testConninfo(conninfo string) string { - defaultTo := func(envvar string, value string) { - if os.Getenv(envvar) == "" { - os.Setenv(envvar, value) - } - } - defaultTo("PGDATABASE", "pqgotest") - defaultTo("PGSSLMODE", "disable") - defaultTo("PGCONNECT_TIMEOUT", "20") - - if forceBinaryParameters() && - !strings.HasPrefix(conninfo, "postgres://") && - !strings.HasPrefix(conninfo, "postgresql://") { - conninfo = conninfo + " binary_parameters=yes" - } - return conninfo -} - -func openTestConnConninfo(conninfo string) (*sql.DB, error) { - return sql.Open("postgres", testConninfo(conninfo)) -} - -func openTestConn(t Fatalistic) *sql.DB { - conn, err := openTestConnConninfo("") - if err != nil { - t.Fatal(err) - } - - return conn -} - -func getServerVersion(t *testing.T, db *sql.DB) int { - var version int - err := db.QueryRow("SHOW server_version_num").Scan(&version) - if err != nil { - t.Fatal(err) - } - return version -} - -func TestReconnect(t *testing.T) { - db1 := openTestConn(t) - defer db1.Close() - tx, err := db1.Begin() - if err != nil { - t.Fatal(err) - } - var pid1 int - err = tx.QueryRow("SELECT pg_backend_pid()").Scan(&pid1) - if err != nil { - t.Fatal(err) - } - db2 := openTestConn(t) - defer db2.Close() - _, err = db2.Exec("SELECT pg_terminate_backend($1)", pid1) - if err != nil { - t.Fatal(err) - } - // The rollback will probably "fail" because we just killed - // its connection above - _ = tx.Rollback() - - const expected int = 42 - var result int - err = db1.QueryRow(fmt.Sprintf("SELECT %d", expected)).Scan(&result) - if err != nil { - t.Fatal(err) - } - if result != expected { - t.Errorf("got %v; expected %v", result, expected) - } -} - -func TestCommitInFailedTransaction(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - txn, err := db.Begin() - if err != nil { - t.Fatal(err) - } - rows, err := txn.Query("SELECT error") - if err == nil { - rows.Close() - t.Fatal("expected failure") - } - err = txn.Commit() - if err != ErrInFailedTransaction { - t.Fatalf("expected ErrInFailedTransaction; got %#v", err) - } -} - -func TestOpenURL(t *testing.T) { - testURL := func(url string) { - db, err := openTestConnConninfo(url) - if err != nil { - t.Fatal(err) - } - defer db.Close() - // database/sql might not call our Open at all unless we do something with - // the connection - txn, err := db.Begin() - if err != nil { - t.Fatal(err) - } - txn.Rollback() - } - testURL("postgres://") - testURL("postgresql://") -} - -const pgpassFile = "/tmp/pqgotest_pgpass" - -func TestPgpass(t *testing.T) { - if os.Getenv("TRAVIS") != "true" { - t.Skip("not running under Travis, skipping pgpass tests") - } - - testAssert := func(conninfo string, expected string, reason string) { - conn, err := openTestConnConninfo(conninfo) - if err != nil { - t.Fatal(err) - } - defer conn.Close() - - txn, err := conn.Begin() - if err != nil { - if expected != "fail" { - t.Fatalf(reason, err) - } - return - } - rows, err := txn.Query("SELECT USER") - if err != nil { - txn.Rollback() - if expected != "fail" { - t.Fatalf(reason, err) - } - } else { - rows.Close() - if expected != "ok" { - t.Fatalf(reason, err) - } - } - txn.Rollback() - } - testAssert("", "ok", "missing .pgpass, unexpected error %#v") - os.Setenv("PGPASSFILE", pgpassFile) - testAssert("host=/tmp", "fail", ", unexpected error %#v") - os.Remove(pgpassFile) - pgpass, err := os.OpenFile(pgpassFile, os.O_RDWR|os.O_CREATE, 0644) - if err != nil { - t.Fatalf("Unexpected error writing pgpass file %#v", err) - } - _, err = pgpass.WriteString(`# comment -server:5432:some_db:some_user:pass_A -*:5432:some_db:some_user:pass_B -localhost:*:*:*:pass_C -*:*:*:*:pass_fallback -`) - if err != nil { - t.Fatalf("Unexpected error writing pgpass file %#v", err) - } - pgpass.Close() - - assertPassword := func(extra values, expected string) { - o := values{ - "host": "localhost", - "sslmode": "disable", - "connect_timeout": "20", - "user": "majid", - "port": "5432", - "extra_float_digits": "2", - "dbname": "pqgotest", - "client_encoding": "UTF8", - "datestyle": "ISO, MDY", - } - for k, v := range extra { - o[k] = v - } - (&conn{}).handlePgpass(o) - if pw := o["password"]; pw != expected { - t.Fatalf("For %v expected %s got %s", extra, expected, pw) - } - } - // wrong permissions for the pgpass file means it should be ignored - assertPassword(values{"host": "example.com", "user": "foo"}, "") - // fix the permissions and check if it has taken effect - os.Chmod(pgpassFile, 0600) - assertPassword(values{"host": "server", "dbname": "some_db", "user": "some_user"}, "pass_A") - assertPassword(values{"host": "example.com", "user": "foo"}, "pass_fallback") - assertPassword(values{"host": "example.com", "dbname": "some_db", "user": "some_user"}, "pass_B") - // localhost also matches the default "" and UNIX sockets - assertPassword(values{"host": "", "user": "some_user"}, "pass_C") - assertPassword(values{"host": "/tmp", "user": "some_user"}, "pass_C") - // cleanup - os.Remove(pgpassFile) - os.Setenv("PGPASSFILE", "") -} - -func TestExec(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - _, err := db.Exec("CREATE TEMP TABLE temp (a int)") - if err != nil { - t.Fatal(err) - } - - r, err := db.Exec("INSERT INTO temp VALUES (1)") - if err != nil { - t.Fatal(err) - } - - if n, _ := r.RowsAffected(); n != 1 { - t.Fatalf("expected 1 row affected, not %d", n) - } - - r, err = db.Exec("INSERT INTO temp VALUES ($1), ($2), ($3)", 1, 2, 3) - if err != nil { - t.Fatal(err) - } - - if n, _ := r.RowsAffected(); n != 3 { - t.Fatalf("expected 3 rows affected, not %d", n) - } - - // SELECT doesn't send the number of returned rows in the command tag - // before 9.0 - if getServerVersion(t, db) >= 90000 { - r, err = db.Exec("SELECT g FROM generate_series(1, 2) g") - if err != nil { - t.Fatal(err) - } - if n, _ := r.RowsAffected(); n != 2 { - t.Fatalf("expected 2 rows affected, not %d", n) - } - - r, err = db.Exec("SELECT g FROM generate_series(1, $1) g", 3) - if err != nil { - t.Fatal(err) - } - if n, _ := r.RowsAffected(); n != 3 { - t.Fatalf("expected 3 rows affected, not %d", n) - } - } -} - -func TestStatment(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - st, err := db.Prepare("SELECT 1") - if err != nil { - t.Fatal(err) - } - - st1, err := db.Prepare("SELECT 2") - if err != nil { - t.Fatal(err) - } - - r, err := st.Query() - if err != nil { - t.Fatal(err) - } - defer r.Close() - - if !r.Next() { - t.Fatal("expected row") - } - - var i int - err = r.Scan(&i) - if err != nil { - t.Fatal(err) - } - - if i != 1 { - t.Fatalf("expected 1, got %d", i) - } - - // st1 - - r1, err := st1.Query() - if err != nil { - t.Fatal(err) - } - defer r1.Close() - - if !r1.Next() { - if r.Err() != nil { - t.Fatal(r1.Err()) - } - t.Fatal("expected row") - } - - err = r1.Scan(&i) - if err != nil { - t.Fatal(err) - } - - if i != 2 { - t.Fatalf("expected 2, got %d", i) - } -} - -func TestRowsCloseBeforeDone(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - r, err := db.Query("SELECT 1") - if err != nil { - t.Fatal(err) - } - - err = r.Close() - if err != nil { - t.Fatal(err) - } - - if r.Next() { - t.Fatal("unexpected row") - } - - if r.Err() != nil { - t.Fatal(r.Err()) - } -} - -func TestParameterCountMismatch(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - var notused int - err := db.QueryRow("SELECT false", 1).Scan(¬used) - if err == nil { - t.Fatal("expected err") - } - // make sure we clean up correctly - err = db.QueryRow("SELECT 1").Scan(¬used) - if err != nil { - t.Fatal(err) - } - - err = db.QueryRow("SELECT $1").Scan(¬used) - if err == nil { - t.Fatal("expected err") - } - // make sure we clean up correctly - err = db.QueryRow("SELECT 1").Scan(¬used) - if err != nil { - t.Fatal(err) - } -} - -// Test that EmptyQueryResponses are handled correctly. -func TestEmptyQuery(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - res, err := db.Exec("") - if err != nil { - t.Fatal(err) - } - if _, err := res.RowsAffected(); err != errNoRowsAffected { - t.Fatalf("expected %s, got %v", errNoRowsAffected, err) - } - if _, err := res.LastInsertId(); err != errNoLastInsertID { - t.Fatalf("expected %s, got %v", errNoLastInsertID, err) - } - rows, err := db.Query("") - if err != nil { - t.Fatal(err) - } - cols, err := rows.Columns() - if err != nil { - t.Fatal(err) - } - if len(cols) != 0 { - t.Fatalf("unexpected number of columns %d in response to an empty query", len(cols)) - } - if rows.Next() { - t.Fatal("unexpected row") - } - if rows.Err() != nil { - t.Fatal(rows.Err()) - } - - stmt, err := db.Prepare("") - if err != nil { - t.Fatal(err) - } - res, err = stmt.Exec() - if err != nil { - t.Fatal(err) - } - if _, err := res.RowsAffected(); err != errNoRowsAffected { - t.Fatalf("expected %s, got %v", errNoRowsAffected, err) - } - if _, err := res.LastInsertId(); err != errNoLastInsertID { - t.Fatalf("expected %s, got %v", errNoLastInsertID, err) - } - rows, err = stmt.Query() - if err != nil { - t.Fatal(err) - } - cols, err = rows.Columns() - if err != nil { - t.Fatal(err) - } - if len(cols) != 0 { - t.Fatalf("unexpected number of columns %d in response to an empty query", len(cols)) - } - if rows.Next() { - t.Fatal("unexpected row") - } - if rows.Err() != nil { - t.Fatal(rows.Err()) - } -} - -// Test that rows.Columns() is correct even if there are no result rows. -func TestEmptyResultSetColumns(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - rows, err := db.Query("SELECT 1 AS a, text 'bar' AS bar WHERE FALSE") - if err != nil { - t.Fatal(err) - } - cols, err := rows.Columns() - if err != nil { - t.Fatal(err) - } - if len(cols) != 2 { - t.Fatalf("unexpected number of columns %d in response to an empty query", len(cols)) - } - if rows.Next() { - t.Fatal("unexpected row") - } - if rows.Err() != nil { - t.Fatal(rows.Err()) - } - if cols[0] != "a" || cols[1] != "bar" { - t.Fatalf("unexpected Columns result %v", cols) - } - - stmt, err := db.Prepare("SELECT $1::int AS a, text 'bar' AS bar WHERE FALSE") - if err != nil { - t.Fatal(err) - } - rows, err = stmt.Query(1) - if err != nil { - t.Fatal(err) - } - cols, err = rows.Columns() - if err != nil { - t.Fatal(err) - } - if len(cols) != 2 { - t.Fatalf("unexpected number of columns %d in response to an empty query", len(cols)) - } - if rows.Next() { - t.Fatal("unexpected row") - } - if rows.Err() != nil { - t.Fatal(rows.Err()) - } - if cols[0] != "a" || cols[1] != "bar" { - t.Fatalf("unexpected Columns result %v", cols) - } - -} - -func TestEncodeDecode(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - q := ` - SELECT - E'\\000\\001\\002'::bytea, - 'foobar'::text, - NULL::integer, - '2000-1-1 01:02:03.04-7'::timestamptz, - 0::boolean, - 123, - -321, - 3.14::float8 - WHERE - E'\\000\\001\\002'::bytea = $1 - AND 'foobar'::text = $2 - AND $3::integer is NULL - ` - // AND '2000-1-1 12:00:00.000000-7'::timestamp = $3 - - exp1 := []byte{0, 1, 2} - exp2 := "foobar" - - r, err := db.Query(q, exp1, exp2, nil) - if err != nil { - t.Fatal(err) - } - defer r.Close() - - if !r.Next() { - if r.Err() != nil { - t.Fatal(r.Err()) - } - t.Fatal("expected row") - } - - var got1 []byte - var got2 string - var got3 = sql.NullInt64{Valid: true} - var got4 time.Time - var got5, got6, got7, got8 interface{} - - err = r.Scan(&got1, &got2, &got3, &got4, &got5, &got6, &got7, &got8) - if err != nil { - t.Fatal(err) - } - - if !reflect.DeepEqual(exp1, got1) { - t.Errorf("expected %q byte: %q", exp1, got1) - } - - if !reflect.DeepEqual(exp2, got2) { - t.Errorf("expected %q byte: %q", exp2, got2) - } - - if got3.Valid { - t.Fatal("expected invalid") - } - - if got4.Year() != 2000 { - t.Fatal("wrong year") - } - - if got5 != false { - t.Fatalf("expected false, got %q", got5) - } - - if got6 != int64(123) { - t.Fatalf("expected 123, got %d", got6) - } - - if got7 != int64(-321) { - t.Fatalf("expected -321, got %d", got7) - } - - if got8 != float64(3.14) { - t.Fatalf("expected 3.14, got %f", got8) - } -} - -func TestNoData(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - st, err := db.Prepare("SELECT 1 WHERE true = false") - if err != nil { - t.Fatal(err) - } - defer st.Close() - - r, err := st.Query() - if err != nil { - t.Fatal(err) - } - defer r.Close() - - if r.Next() { - if r.Err() != nil { - t.Fatal(r.Err()) - } - t.Fatal("unexpected row") - } - - _, err = db.Query("SELECT * FROM nonexistenttable WHERE age=$1", 20) - if err == nil { - t.Fatal("Should have raised an error on non existent table") - } - - _, err = db.Query("SELECT * FROM nonexistenttable") - if err == nil { - t.Fatal("Should have raised an error on non existent table") - } -} - -func TestErrorDuringStartup(t *testing.T) { - // Don't use the normal connection setup, this is intended to - // blow up in the startup packet from a non-existent user. - db, err := openTestConnConninfo("user=thisuserreallydoesntexist") - if err != nil { - t.Fatal(err) - } - defer db.Close() - - _, err = db.Begin() - if err == nil { - t.Fatal("expected error") - } - - e, ok := err.(*Error) - if !ok { - t.Fatalf("expected Error, got %#v", err) - } else if e.Code.Name() != "invalid_authorization_specification" && e.Code.Name() != "invalid_password" { - t.Fatalf("expected invalid_authorization_specification or invalid_password, got %s (%+v)", e.Code.Name(), err) - } -} - -type testConn struct { - closed bool - net.Conn -} - -func (c *testConn) Close() error { - c.closed = true - return c.Conn.Close() -} - -type testDialer struct { - conns []*testConn -} - -func (d *testDialer) Dial(ntw, addr string) (net.Conn, error) { - c, err := net.Dial(ntw, addr) - if err != nil { - return nil, err - } - tc := &testConn{Conn: c} - d.conns = append(d.conns, tc) - return tc, nil -} - -func (d *testDialer) DialTimeout(ntw, addr string, timeout time.Duration) (net.Conn, error) { - c, err := net.DialTimeout(ntw, addr, timeout) - if err != nil { - return nil, err - } - tc := &testConn{Conn: c} - d.conns = append(d.conns, tc) - return tc, nil -} - -func TestErrorDuringStartupClosesConn(t *testing.T) { - // Don't use the normal connection setup, this is intended to - // blow up in the startup packet from a non-existent user. - var d testDialer - c, err := DialOpen(&d, testConninfo("user=thisuserreallydoesntexist")) - if err == nil { - c.Close() - t.Fatal("expected dial error") - } - if len(d.conns) != 1 { - t.Fatalf("got len(d.conns) = %d, want = %d", len(d.conns), 1) - } - if !d.conns[0].closed { - t.Error("connection leaked") - } -} - -func TestBadConn(t *testing.T) { - var err error - - cn := conn{} - func() { - defer cn.errRecover(&err) - panic(io.EOF) - }() - if err != driver.ErrBadConn { - t.Fatalf("expected driver.ErrBadConn, got: %#v", err) - } - if !cn.bad { - t.Fatalf("expected cn.bad") - } - - cn = conn{} - func() { - defer cn.errRecover(&err) - e := &Error{Severity: Efatal} - panic(e) - }() - if err != driver.ErrBadConn { - t.Fatalf("expected driver.ErrBadConn, got: %#v", err) - } - if !cn.bad { - t.Fatalf("expected cn.bad") - } -} - -// TestCloseBadConn tests that the underlying connection can be closed with -// Close after an error. -func TestCloseBadConn(t *testing.T) { - nc, err := net.Dial("tcp", "localhost:5432") - if err != nil { - t.Fatal(err) - } - cn := conn{c: nc} - func() { - defer cn.errRecover(&err) - panic(io.EOF) - }() - // Verify we can write before closing. - if _, err := nc.Write(nil); err != nil { - t.Fatal(err) - } - // First close should close the connection. - if err := cn.Close(); err != nil { - t.Fatal(err) - } - - // During the Go 1.9 cycle, https://github.com/golang/go/commit/3792db5 - // changed this error from - // - // net.errClosing = errors.New("use of closed network connection") - // - // to - // - // internal/poll.ErrClosing = errors.New("use of closed file or network connection") - const errClosing = "use of closed" - - // Verify write after closing fails. - if _, err := nc.Write(nil); err == nil { - t.Fatal("expected error") - } else if !strings.Contains(err.Error(), errClosing) { - t.Fatalf("expected %s error, got %s", errClosing, err) - } - // Verify second close fails. - if err := cn.Close(); err == nil { - t.Fatal("expected error") - } else if !strings.Contains(err.Error(), errClosing) { - t.Fatalf("expected %s error, got %s", errClosing, err) - } -} - -func TestErrorOnExec(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - txn, err := db.Begin() - if err != nil { - t.Fatal(err) - } - defer txn.Rollback() - - _, err = txn.Exec("CREATE TEMPORARY TABLE foo(f1 int PRIMARY KEY)") - if err != nil { - t.Fatal(err) - } - - _, err = txn.Exec("INSERT INTO foo VALUES (0), (0)") - if err == nil { - t.Fatal("Should have raised error") - } - - e, ok := err.(*Error) - if !ok { - t.Fatalf("expected Error, got %#v", err) - } else if e.Code.Name() != "unique_violation" { - t.Fatalf("expected unique_violation, got %s (%+v)", e.Code.Name(), err) - } -} - -func TestErrorOnQuery(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - txn, err := db.Begin() - if err != nil { - t.Fatal(err) - } - defer txn.Rollback() - - _, err = txn.Exec("CREATE TEMPORARY TABLE foo(f1 int PRIMARY KEY)") - if err != nil { - t.Fatal(err) - } - - _, err = txn.Query("INSERT INTO foo VALUES (0), (0)") - if err == nil { - t.Fatal("Should have raised error") - } - - e, ok := err.(*Error) - if !ok { - t.Fatalf("expected Error, got %#v", err) - } else if e.Code.Name() != "unique_violation" { - t.Fatalf("expected unique_violation, got %s (%+v)", e.Code.Name(), err) - } -} - -func TestErrorOnQueryRowSimpleQuery(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - txn, err := db.Begin() - if err != nil { - t.Fatal(err) - } - defer txn.Rollback() - - _, err = txn.Exec("CREATE TEMPORARY TABLE foo(f1 int PRIMARY KEY)") - if err != nil { - t.Fatal(err) - } - - var v int - err = txn.QueryRow("INSERT INTO foo VALUES (0), (0)").Scan(&v) - if err == nil { - t.Fatal("Should have raised error") - } - - e, ok := err.(*Error) - if !ok { - t.Fatalf("expected Error, got %#v", err) - } else if e.Code.Name() != "unique_violation" { - t.Fatalf("expected unique_violation, got %s (%+v)", e.Code.Name(), err) - } -} - -// Test the QueryRow bug workarounds in stmt.exec() and simpleQuery() -func TestQueryRowBugWorkaround(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - // stmt.exec() - _, err := db.Exec("CREATE TEMP TABLE notnulltemp (a varchar(10) not null)") - if err != nil { - t.Fatal(err) - } - - var a string - err = db.QueryRow("INSERT INTO notnulltemp(a) values($1) RETURNING a", nil).Scan(&a) - if err == sql.ErrNoRows { - t.Fatalf("expected constraint violation error; got: %v", err) - } - pge, ok := err.(*Error) - if !ok { - t.Fatalf("expected *Error; got: %#v", err) - } - if pge.Code.Name() != "not_null_violation" { - t.Fatalf("expected not_null_violation; got: %s (%+v)", pge.Code.Name(), err) - } - - // Test workaround in simpleQuery() - tx, err := db.Begin() - if err != nil { - t.Fatalf("unexpected error %s in Begin", err) - } - defer tx.Rollback() - - _, err = tx.Exec("SET LOCAL check_function_bodies TO FALSE") - if err != nil { - t.Fatalf("could not disable check_function_bodies: %s", err) - } - _, err = tx.Exec(` -CREATE OR REPLACE FUNCTION bad_function() -RETURNS integer --- hack to prevent the function from being inlined -SET check_function_bodies TO TRUE -AS $$ - SELECT text 'bad' -$$ LANGUAGE sql`) - if err != nil { - t.Fatalf("could not create function: %s", err) - } - - err = tx.QueryRow("SELECT * FROM bad_function()").Scan(&a) - if err == nil { - t.Fatalf("expected error") - } - pge, ok = err.(*Error) - if !ok { - t.Fatalf("expected *Error; got: %#v", err) - } - if pge.Code.Name() != "invalid_function_definition" { - t.Fatalf("expected invalid_function_definition; got: %s (%+v)", pge.Code.Name(), err) - } - - err = tx.Rollback() - if err != nil { - t.Fatalf("unexpected error %s in Rollback", err) - } - - // Also test that simpleQuery()'s workaround works when the query fails - // after a row has been received. - rows, err := db.Query(` -select - (select generate_series(1, ss.i)) -from (select gs.i - from generate_series(1, 2) gs(i) - order by gs.i limit 2) ss`) - if err != nil { - t.Fatalf("query failed: %s", err) - } - if !rows.Next() { - t.Fatalf("expected at least one result row; got %s", rows.Err()) - } - var i int - err = rows.Scan(&i) - if err != nil { - t.Fatalf("rows.Scan() failed: %s", err) - } - if i != 1 { - t.Fatalf("unexpected value for i: %d", i) - } - if rows.Next() { - t.Fatalf("unexpected row") - } - pge, ok = rows.Err().(*Error) - if !ok { - t.Fatalf("expected *Error; got: %#v", err) - } - if pge.Code.Name() != "cardinality_violation" { - t.Fatalf("expected cardinality_violation; got: %s (%+v)", pge.Code.Name(), rows.Err()) - } -} - -func TestSimpleQuery(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - r, err := db.Query("select 1") - if err != nil { - t.Fatal(err) - } - defer r.Close() - - if !r.Next() { - t.Fatal("expected row") - } -} - -func TestBindError(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - _, err := db.Exec("create temp table test (i integer)") - if err != nil { - t.Fatal(err) - } - - _, err = db.Query("select * from test where i=$1", "hhh") - if err == nil { - t.Fatal("expected an error") - } - - // Should not get error here - r, err := db.Query("select * from test where i=$1", 1) - if err != nil { - t.Fatal(err) - } - defer r.Close() -} - -func TestParseErrorInExtendedQuery(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - _, err := db.Query("PARSE_ERROR $1", 1) - pqErr, _ := err.(*Error) - // Expecting a syntax error. - if err == nil || pqErr == nil || pqErr.Code != "42601" { - t.Fatalf("expected syntax error, got %s", err) - } - - rows, err := db.Query("SELECT 1") - if err != nil { - t.Fatal(err) - } - rows.Close() -} - -// TestReturning tests that an INSERT query using the RETURNING clause returns a row. -func TestReturning(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - _, err := db.Exec("CREATE TEMP TABLE distributors (did integer default 0, dname text)") - if err != nil { - t.Fatal(err) - } - - rows, err := db.Query("INSERT INTO distributors (did, dname) VALUES (DEFAULT, 'XYZ Widgets') " + - "RETURNING did;") - if err != nil { - t.Fatal(err) - } - if !rows.Next() { - t.Fatal("no rows") - } - var did int - err = rows.Scan(&did) - if err != nil { - t.Fatal(err) - } - if did != 0 { - t.Fatalf("bad value for did: got %d, want %d", did, 0) - } - - if rows.Next() { - t.Fatal("unexpected next row") - } - err = rows.Err() - if err != nil { - t.Fatal(err) - } -} - -func TestIssue186(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - // Exec() a query which returns results - _, err := db.Exec("VALUES (1), (2), (3)") - if err != nil { - t.Fatal(err) - } - - _, err = db.Exec("VALUES ($1), ($2), ($3)", 1, 2, 3) - if err != nil { - t.Fatal(err) - } - - // Query() a query which doesn't return any results - txn, err := db.Begin() - if err != nil { - t.Fatal(err) - } - defer txn.Rollback() - - rows, err := txn.Query("CREATE TEMP TABLE foo(f1 int)") - if err != nil { - t.Fatal(err) - } - if err = rows.Close(); err != nil { - t.Fatal(err) - } - - // small trick to get NoData from a parameterized query - _, err = txn.Exec("CREATE RULE nodata AS ON INSERT TO foo DO INSTEAD NOTHING") - if err != nil { - t.Fatal(err) - } - rows, err = txn.Query("INSERT INTO foo VALUES ($1)", 1) - if err != nil { - t.Fatal(err) - } - if err = rows.Close(); err != nil { - t.Fatal(err) - } -} - -func TestIssue196(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - row := db.QueryRow("SELECT float4 '0.10000122' = $1, float8 '35.03554004971999' = $2", - float32(0.10000122), float64(35.03554004971999)) - - var float4match, float8match bool - err := row.Scan(&float4match, &float8match) - if err != nil { - t.Fatal(err) - } - if !float4match { - t.Errorf("Expected float4 fidelity to be maintained; got no match") - } - if !float8match { - t.Errorf("Expected float8 fidelity to be maintained; got no match") - } -} - -// Test that any CommandComplete messages sent before the query results are -// ignored. -func TestIssue282(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - var searchPath string - err := db.QueryRow(` - SET LOCAL search_path TO pg_catalog; - SET LOCAL search_path TO pg_catalog; - SHOW search_path`).Scan(&searchPath) - if err != nil { - t.Fatal(err) - } - if searchPath != "pg_catalog" { - t.Fatalf("unexpected search_path %s", searchPath) - } -} - -func TestReadFloatPrecision(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - row := db.QueryRow("SELECT float4 '0.10000122', float8 '35.03554004971999'") - var float4val float32 - var float8val float64 - err := row.Scan(&float4val, &float8val) - if err != nil { - t.Fatal(err) - } - if float4val != float32(0.10000122) { - t.Errorf("Expected float4 fidelity to be maintained; got no match") - } - if float8val != float64(35.03554004971999) { - t.Errorf("Expected float8 fidelity to be maintained; got no match") - } -} - -func TestXactMultiStmt(t *testing.T) { - // minified test case based on bug reports from - // pico303@gmail.com and rangelspam@gmail.com - t.Skip("Skipping failing test") - db := openTestConn(t) - defer db.Close() - - tx, err := db.Begin() - if err != nil { - t.Fatal(err) - } - defer tx.Commit() - - rows, err := tx.Query("select 1") - if err != nil { - t.Fatal(err) - } - - if rows.Next() { - var val int32 - if err = rows.Scan(&val); err != nil { - t.Fatal(err) - } - } else { - t.Fatal("Expected at least one row in first query in xact") - } - - rows2, err := tx.Query("select 2") - if err != nil { - t.Fatal(err) - } - - if rows2.Next() { - var val2 int32 - if err := rows2.Scan(&val2); err != nil { - t.Fatal(err) - } - } else { - t.Fatal("Expected at least one row in second query in xact") - } - - if err = rows.Err(); err != nil { - t.Fatal(err) - } - - if err = rows2.Err(); err != nil { - t.Fatal(err) - } - - if err = tx.Commit(); err != nil { - t.Fatal(err) - } -} - -var envParseTests = []struct { - Expected map[string]string - Env []string -}{ - { - Env: []string{"PGDATABASE=hello", "PGUSER=goodbye"}, - Expected: map[string]string{"dbname": "hello", "user": "goodbye"}, - }, - { - Env: []string{"PGDATESTYLE=ISO, MDY"}, - Expected: map[string]string{"datestyle": "ISO, MDY"}, - }, - { - Env: []string{"PGCONNECT_TIMEOUT=30"}, - Expected: map[string]string{"connect_timeout": "30"}, - }, -} - -func TestParseEnviron(t *testing.T) { - for i, tt := range envParseTests { - results := parseEnviron(tt.Env) - if !reflect.DeepEqual(tt.Expected, results) { - t.Errorf("%d: Expected: %#v Got: %#v", i, tt.Expected, results) - } - } -} - -func TestParseComplete(t *testing.T) { - tpc := func(commandTag string, command string, affectedRows int64, shouldFail bool) { - defer func() { - if p := recover(); p != nil { - if !shouldFail { - t.Error(p) - } - } - }() - cn := &conn{} - res, c := cn.parseComplete(commandTag) - if c != command { - t.Errorf("Expected %v, got %v", command, c) - } - n, err := res.RowsAffected() - if err != nil { - t.Fatal(err) - } - if n != affectedRows { - t.Errorf("Expected %d, got %d", affectedRows, n) - } - } - - tpc("ALTER TABLE", "ALTER TABLE", 0, false) - tpc("INSERT 0 1", "INSERT", 1, false) - tpc("UPDATE 100", "UPDATE", 100, false) - tpc("SELECT 100", "SELECT", 100, false) - tpc("FETCH 100", "FETCH", 100, false) - // allow COPY (and others) without row count - tpc("COPY", "COPY", 0, false) - // don't fail on command tags we don't recognize - tpc("UNKNOWNCOMMANDTAG", "UNKNOWNCOMMANDTAG", 0, false) - - // failure cases - tpc("INSERT 1", "", 0, true) // missing oid - tpc("UPDATE 0 1", "", 0, true) // too many numbers - tpc("SELECT foo", "", 0, true) // invalid row count -} - -// Test interface conformance. -var ( - _ driver.ExecerContext = (*conn)(nil) - _ driver.QueryerContext = (*conn)(nil) -) - -func TestNullAfterNonNull(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - r, err := db.Query("SELECT 9::integer UNION SELECT NULL::integer") - if err != nil { - t.Fatal(err) - } - - var n sql.NullInt64 - - if !r.Next() { - if r.Err() != nil { - t.Fatal(err) - } - t.Fatal("expected row") - } - - if err := r.Scan(&n); err != nil { - t.Fatal(err) - } - - if n.Int64 != 9 { - t.Fatalf("expected 2, not %d", n.Int64) - } - - if !r.Next() { - if r.Err() != nil { - t.Fatal(err) - } - t.Fatal("expected row") - } - - if err := r.Scan(&n); err != nil { - t.Fatal(err) - } - - if n.Valid { - t.Fatal("expected n to be invalid") - } - - if n.Int64 != 0 { - t.Fatalf("expected n to 2, not %d", n.Int64) - } -} - -func Test64BitErrorChecking(t *testing.T) { - defer func() { - if err := recover(); err != nil { - t.Fatal("panic due to 0xFFFFFFFF != -1 " + - "when int is 64 bits") - } - }() - - db := openTestConn(t) - defer db.Close() - - r, err := db.Query(`SELECT * -FROM (VALUES (0::integer, NULL::text), (1, 'test string')) AS t;`) - - if err != nil { - t.Fatal(err) - } - - defer r.Close() - - for r.Next() { - } -} - -func TestCommit(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - _, err := db.Exec("CREATE TEMP TABLE temp (a int)") - if err != nil { - t.Fatal(err) - } - sqlInsert := "INSERT INTO temp VALUES (1)" - sqlSelect := "SELECT * FROM temp" - tx, err := db.Begin() - if err != nil { - t.Fatal(err) - } - _, err = tx.Exec(sqlInsert) - if err != nil { - t.Fatal(err) - } - err = tx.Commit() - if err != nil { - t.Fatal(err) - } - var i int - err = db.QueryRow(sqlSelect).Scan(&i) - if err != nil { - t.Fatal(err) - } - if i != 1 { - t.Fatalf("expected 1, got %d", i) - } -} - -func TestErrorClass(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - _, err := db.Query("SELECT int 'notint'") - if err == nil { - t.Fatal("expected error") - } - pge, ok := err.(*Error) - if !ok { - t.Fatalf("expected *pq.Error, got %#+v", err) - } - if pge.Code.Class() != "22" { - t.Fatalf("expected class 28, got %v", pge.Code.Class()) - } - if pge.Code.Class().Name() != "data_exception" { - t.Fatalf("expected data_exception, got %v", pge.Code.Class().Name()) - } -} - -func TestParseOpts(t *testing.T) { - tests := []struct { - in string - expected values - valid bool - }{ - {"dbname=hello user=goodbye", values{"dbname": "hello", "user": "goodbye"}, true}, - {"dbname=hello user=goodbye ", values{"dbname": "hello", "user": "goodbye"}, true}, - {"dbname = hello user=goodbye", values{"dbname": "hello", "user": "goodbye"}, true}, - {"dbname=hello user =goodbye", values{"dbname": "hello", "user": "goodbye"}, true}, - {"dbname=hello user= goodbye", values{"dbname": "hello", "user": "goodbye"}, true}, - {"host=localhost password='correct horse battery staple'", values{"host": "localhost", "password": "correct horse battery staple"}, true}, - {"dbname=データベース password=パスワード", values{"dbname": "データベース", "password": "パスワード"}, true}, - {"dbname=hello user=''", values{"dbname": "hello", "user": ""}, true}, - {"user='' dbname=hello", values{"dbname": "hello", "user": ""}, true}, - // The last option value is an empty string if there's no non-whitespace after its = - {"dbname=hello user= ", values{"dbname": "hello", "user": ""}, true}, - - // The parser ignores spaces after = and interprets the next set of non-whitespace characters as the value. - {"user= password=foo", values{"user": "password=foo"}, true}, - - // Backslash escapes next char - {`user=a\ \'\\b`, values{"user": `a '\b`}, true}, - {`user='a \'b'`, values{"user": `a 'b`}, true}, - - // Incomplete escape - {`user=x\`, values{}, false}, - - // No '=' after the key - {"postgre://marko@internet", values{}, false}, - {"dbname user=goodbye", values{}, false}, - {"user=foo blah", values{}, false}, - {"user=foo blah ", values{}, false}, - - // Unterminated quoted value - {"dbname=hello user='unterminated", values{}, false}, - } - - for _, test := range tests { - o := make(values) - err := parseOpts(test.in, o) - - switch { - case err != nil && test.valid: - t.Errorf("%q got unexpected error: %s", test.in, err) - case err == nil && test.valid && !reflect.DeepEqual(test.expected, o): - t.Errorf("%q got: %#v want: %#v", test.in, o, test.expected) - case err == nil && !test.valid: - t.Errorf("%q expected an error", test.in) - } - } -} - -func TestRuntimeParameters(t *testing.T) { - tests := []struct { - conninfo string - param string - expected string - success bool - }{ - // invalid parameter - {"DOESNOTEXIST=foo", "", "", false}, - // we can only work with a specific value for these two - {"client_encoding=SQL_ASCII", "", "", false}, - {"datestyle='ISO, YDM'", "", "", false}, - // "options" should work exactly as it does in libpq - {"options='-c search_path=pqgotest'", "search_path", "pqgotest", true}, - // pq should override client_encoding in this case - {"options='-c client_encoding=SQL_ASCII'", "client_encoding", "UTF8", true}, - // allow client_encoding to be set explicitly - {"client_encoding=UTF8", "client_encoding", "UTF8", true}, - // test a runtime parameter not supported by libpq - {"work_mem='139kB'", "work_mem", "139kB", true}, - // test fallback_application_name - {"application_name=foo fallback_application_name=bar", "application_name", "foo", true}, - {"application_name='' fallback_application_name=bar", "application_name", "", true}, - {"fallback_application_name=bar", "application_name", "bar", true}, - } - - for _, test := range tests { - db, err := openTestConnConninfo(test.conninfo) - if err != nil { - t.Fatal(err) - } - - // application_name didn't exist before 9.0 - if test.param == "application_name" && getServerVersion(t, db) < 90000 { - db.Close() - continue - } - - tryGetParameterValue := func() (value string, success bool) { - defer db.Close() - row := db.QueryRow("SELECT current_setting($1)", test.param) - err = row.Scan(&value) - if err != nil { - return "", false - } - return value, true - } - - value, success := tryGetParameterValue() - if success != test.success && !test.success { - t.Fatalf("%v: unexpected error: %v", test.conninfo, err) - } - if success != test.success { - t.Fatalf("unexpected outcome %v (was expecting %v) for conninfo \"%s\"", - success, test.success, test.conninfo) - } - if value != test.expected { - t.Fatalf("bad value for %s: got %s, want %s with conninfo \"%s\"", - test.param, value, test.expected, test.conninfo) - } - } -} - -func TestIsUTF8(t *testing.T) { - var cases = []struct { - name string - want bool - }{ - {"unicode", true}, - {"utf-8", true}, - {"utf_8", true}, - {"UTF-8", true}, - {"UTF8", true}, - {"utf8", true}, - {"u n ic_ode", true}, - {"ut_f%8", true}, - {"ubf8", false}, - {"punycode", false}, - } - - for _, test := range cases { - if g := isUTF8(test.name); g != test.want { - t.Errorf("isUTF8(%q) = %v want %v", test.name, g, test.want) - } - } -} - -func TestQuoteIdentifier(t *testing.T) { - var cases = []struct { - input string - want string - }{ - {`foo`, `"foo"`}, - {`foo bar baz`, `"foo bar baz"`}, - {`foo"bar`, `"foo""bar"`}, - {"foo\x00bar", `"foo"`}, - {"\x00foo", `""`}, - } - - for _, test := range cases { - got := QuoteIdentifier(test.input) - if got != test.want { - t.Errorf("QuoteIdentifier(%q) = %v want %v", test.input, got, test.want) - } - } -} - -func TestRowsResultTag(t *testing.T) { - type ResultTag interface { - Result() driver.Result - Tag() string - } - - tests := []struct { - query string - tag string - ra int64 - }{ - { - query: "CREATE TEMP TABLE temp (a int)", - tag: "CREATE TABLE", - }, - { - query: "INSERT INTO temp VALUES (1), (2)", - tag: "INSERT", - ra: 2, - }, - { - query: "SELECT 1", - }, - // A SELECT anywhere should take precedent. - { - query: "SELECT 1; INSERT INTO temp VALUES (1), (2)", - }, - { - query: "INSERT INTO temp VALUES (1), (2); SELECT 1", - }, - // Multiple statements that don't return rows should return the last tag. - { - query: "CREATE TEMP TABLE t (a int); DROP TABLE t", - tag: "DROP TABLE", - }, - // Ensure a rows-returning query in any position among various tags-returing - // statements will prefer the rows. - { - query: "SELECT 1; CREATE TEMP TABLE t (a int); DROP TABLE t", - }, - { - query: "CREATE TEMP TABLE t (a int); SELECT 1; DROP TABLE t", - }, - { - query: "CREATE TEMP TABLE t (a int); DROP TABLE t; SELECT 1", - }, - // Verify that an no-results query doesn't set the tag. - { - query: "CREATE TEMP TABLE t (a int); SELECT 1 WHERE FALSE; DROP TABLE t;", - }, - } - - // If this is the only test run, this will correct the connection string. - openTestConn(t).Close() - - conn, err := Open("") - if err != nil { - t.Fatal(err) - } - defer conn.Close() - q := conn.(driver.QueryerContext) - - for _, test := range tests { - if rows, err := q.QueryContext(context.Background(), test.query, nil); err != nil { - t.Fatalf("%s: %s", test.query, err) - } else { - r := rows.(ResultTag) - if tag := r.Tag(); tag != test.tag { - t.Fatalf("%s: unexpected tag %q", test.query, tag) - } - res := r.Result() - if ra, _ := res.RowsAffected(); ra != test.ra { - t.Fatalf("%s: unexpected rows affected: %d", test.query, ra) - } - rows.Close() - } - } -} - -// TestQuickClose tests that closing a query early allows a subsequent query to work. -func TestQuickClose(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - tx, err := db.Begin() - if err != nil { - t.Fatal(err) - } - rows, err := tx.Query("SELECT 1; SELECT 2;") - if err != nil { - t.Fatal(err) - } - if err := rows.Close(); err != nil { - t.Fatal(err) - } - - var id int - if err := tx.QueryRow("SELECT 3").Scan(&id); err != nil { - t.Fatal(err) - } - if id != 3 { - t.Fatalf("unexpected %d", id) - } - if err := tx.Commit(); err != nil { - t.Fatal(err) - } -} diff --git a/vendor/github.com/lib/pq/connector_example_test.go b/vendor/github.com/lib/pq/connector_example_test.go deleted file mode 100644 index 5b66cf4b..00000000 --- a/vendor/github.com/lib/pq/connector_example_test.go +++ /dev/null @@ -1,33 +0,0 @@ -// +build go1.10 - -package pq_test - -import ( - "database/sql" - "fmt" - - "github.com/lib/pq" -) - -func ExampleNewConnector() { - name := "" - connector, err := pq.NewConnector(name) - if err != nil { - fmt.Println(err) - return - } - db := sql.OpenDB(connector) - if err != nil { - fmt.Println(err) - return - } - defer db.Close() - - // Use the DB - txn, err := db.Begin() - if err != nil { - fmt.Println(err) - return - } - txn.Rollback() -} diff --git a/vendor/github.com/lib/pq/connector_test.go b/vendor/github.com/lib/pq/connector_test.go deleted file mode 100644 index 3d2c67b0..00000000 --- a/vendor/github.com/lib/pq/connector_test.go +++ /dev/null @@ -1,67 +0,0 @@ -// +build go1.10 - -package pq - -import ( - "context" - "database/sql" - "database/sql/driver" - "testing" -) - -func TestNewConnector_WorksWithOpenDB(t *testing.T) { - name := "" - c, err := NewConnector(name) - if err != nil { - t.Fatal(err) - } - db := sql.OpenDB(c) - defer db.Close() - // database/sql might not call our Open at all unless we do something with - // the connection - txn, err := db.Begin() - if err != nil { - t.Fatal(err) - } - txn.Rollback() -} - -func TestNewConnector_Connect(t *testing.T) { - name := "" - c, err := NewConnector(name) - if err != nil { - t.Fatal(err) - } - db, err := c.Connect(context.Background()) - if err != nil { - t.Fatal(err) - } - defer db.Close() - // database/sql might not call our Open at all unless we do something with - // the connection - txn, err := db.(driver.ConnBeginTx).BeginTx(context.Background(), driver.TxOptions{}) - if err != nil { - t.Fatal(err) - } - txn.Rollback() -} - -func TestNewConnector_Driver(t *testing.T) { - name := "" - c, err := NewConnector(name) - if err != nil { - t.Fatal(err) - } - db, err := c.Driver().Open(name) - if err != nil { - t.Fatal(err) - } - defer db.Close() - // database/sql might not call our Open at all unless we do something with - // the connection - txn, err := db.(driver.ConnBeginTx).BeginTx(context.Background(), driver.TxOptions{}) - if err != nil { - t.Fatal(err) - } - txn.Rollback() -} diff --git a/vendor/github.com/lib/pq/copy_test.go b/vendor/github.com/lib/pq/copy_test.go deleted file mode 100644 index a888a894..00000000 --- a/vendor/github.com/lib/pq/copy_test.go +++ /dev/null @@ -1,468 +0,0 @@ -package pq - -import ( - "bytes" - "database/sql" - "database/sql/driver" - "net" - "strings" - "testing" -) - -func TestCopyInStmt(t *testing.T) { - stmt := CopyIn("table name") - if stmt != `COPY "table name" () FROM STDIN` { - t.Fatal(stmt) - } - - stmt = CopyIn("table name", "column 1", "column 2") - if stmt != `COPY "table name" ("column 1", "column 2") FROM STDIN` { - t.Fatal(stmt) - } - - stmt = CopyIn(`table " name """`, `co"lumn""`) - if stmt != `COPY "table "" name """"""" ("co""lumn""""") FROM STDIN` { - t.Fatal(stmt) - } -} - -func TestCopyInSchemaStmt(t *testing.T) { - stmt := CopyInSchema("schema name", "table name") - if stmt != `COPY "schema name"."table name" () FROM STDIN` { - t.Fatal(stmt) - } - - stmt = CopyInSchema("schema name", "table name", "column 1", "column 2") - if stmt != `COPY "schema name"."table name" ("column 1", "column 2") FROM STDIN` { - t.Fatal(stmt) - } - - stmt = CopyInSchema(`schema " name """`, `table " name """`, `co"lumn""`) - if stmt != `COPY "schema "" name """"""".`+ - `"table "" name """"""" ("co""lumn""""") FROM STDIN` { - t.Fatal(stmt) - } -} - -func TestCopyInMultipleValues(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - txn, err := db.Begin() - if err != nil { - t.Fatal(err) - } - defer txn.Rollback() - - _, err = txn.Exec("CREATE TEMP TABLE temp (a int, b varchar)") - if err != nil { - t.Fatal(err) - } - - stmt, err := txn.Prepare(CopyIn("temp", "a", "b")) - if err != nil { - t.Fatal(err) - } - - longString := strings.Repeat("#", 500) - - for i := 0; i < 500; i++ { - _, err = stmt.Exec(int64(i), longString) - if err != nil { - t.Fatal(err) - } - } - - _, err = stmt.Exec() - if err != nil { - t.Fatal(err) - } - - err = stmt.Close() - if err != nil { - t.Fatal(err) - } - - var num int - err = txn.QueryRow("SELECT COUNT(*) FROM temp").Scan(&num) - if err != nil { - t.Fatal(err) - } - - if num != 500 { - t.Fatalf("expected 500 items, not %d", num) - } -} - -func TestCopyInRaiseStmtTrigger(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - if getServerVersion(t, db) < 90000 { - var exists int - err := db.QueryRow("SELECT 1 FROM pg_language WHERE lanname = 'plpgsql'").Scan(&exists) - if err == sql.ErrNoRows { - t.Skip("language PL/PgSQL does not exist; skipping TestCopyInRaiseStmtTrigger") - } else if err != nil { - t.Fatal(err) - } - } - - txn, err := db.Begin() - if err != nil { - t.Fatal(err) - } - defer txn.Rollback() - - _, err = txn.Exec("CREATE TEMP TABLE temp (a int, b varchar)") - if err != nil { - t.Fatal(err) - } - - _, err = txn.Exec(` - CREATE OR REPLACE FUNCTION pg_temp.temptest() - RETURNS trigger AS - $BODY$ begin - raise notice 'Hello world'; - return new; - end $BODY$ - LANGUAGE plpgsql`) - if err != nil { - t.Fatal(err) - } - - _, err = txn.Exec(` - CREATE TRIGGER temptest_trigger - BEFORE INSERT - ON temp - FOR EACH ROW - EXECUTE PROCEDURE pg_temp.temptest()`) - if err != nil { - t.Fatal(err) - } - - stmt, err := txn.Prepare(CopyIn("temp", "a", "b")) - if err != nil { - t.Fatal(err) - } - - longString := strings.Repeat("#", 500) - - _, err = stmt.Exec(int64(1), longString) - if err != nil { - t.Fatal(err) - } - - _, err = stmt.Exec() - if err != nil { - t.Fatal(err) - } - - err = stmt.Close() - if err != nil { - t.Fatal(err) - } - - var num int - err = txn.QueryRow("SELECT COUNT(*) FROM temp").Scan(&num) - if err != nil { - t.Fatal(err) - } - - if num != 1 { - t.Fatalf("expected 1 items, not %d", num) - } -} - -func TestCopyInTypes(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - txn, err := db.Begin() - if err != nil { - t.Fatal(err) - } - defer txn.Rollback() - - _, err = txn.Exec("CREATE TEMP TABLE temp (num INTEGER, text VARCHAR, blob BYTEA, nothing VARCHAR)") - if err != nil { - t.Fatal(err) - } - - stmt, err := txn.Prepare(CopyIn("temp", "num", "text", "blob", "nothing")) - if err != nil { - t.Fatal(err) - } - - _, err = stmt.Exec(int64(1234567890), "Héllö\n ☃!\r\t\\", []byte{0, 255, 9, 10, 13}, nil) - if err != nil { - t.Fatal(err) - } - - _, err = stmt.Exec() - if err != nil { - t.Fatal(err) - } - - err = stmt.Close() - if err != nil { - t.Fatal(err) - } - - var num int - var text string - var blob []byte - var nothing sql.NullString - - err = txn.QueryRow("SELECT * FROM temp").Scan(&num, &text, &blob, ¬hing) - if err != nil { - t.Fatal(err) - } - - if num != 1234567890 { - t.Fatal("unexpected result", num) - } - if text != "Héllö\n ☃!\r\t\\" { - t.Fatal("unexpected result", text) - } - if !bytes.Equal(blob, []byte{0, 255, 9, 10, 13}) { - t.Fatal("unexpected result", blob) - } - if nothing.Valid { - t.Fatal("unexpected result", nothing.String) - } -} - -func TestCopyInWrongType(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - txn, err := db.Begin() - if err != nil { - t.Fatal(err) - } - defer txn.Rollback() - - _, err = txn.Exec("CREATE TEMP TABLE temp (num INTEGER)") - if err != nil { - t.Fatal(err) - } - - stmt, err := txn.Prepare(CopyIn("temp", "num")) - if err != nil { - t.Fatal(err) - } - defer stmt.Close() - - _, err = stmt.Exec("Héllö\n ☃!\r\t\\") - if err != nil { - t.Fatal(err) - } - - _, err = stmt.Exec() - if err == nil { - t.Fatal("expected error") - } - if pge := err.(*Error); pge.Code.Name() != "invalid_text_representation" { - t.Fatalf("expected 'invalid input syntax for integer' error, got %s (%+v)", pge.Code.Name(), pge) - } -} - -func TestCopyOutsideOfTxnError(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - _, err := db.Prepare(CopyIn("temp", "num")) - if err == nil { - t.Fatal("COPY outside of transaction did not return an error") - } - if err != errCopyNotSupportedOutsideTxn { - t.Fatalf("expected %s, got %s", err, err.Error()) - } -} - -func TestCopyInBinaryError(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - txn, err := db.Begin() - if err != nil { - t.Fatal(err) - } - defer txn.Rollback() - - _, err = txn.Exec("CREATE TEMP TABLE temp (num INTEGER)") - if err != nil { - t.Fatal(err) - } - _, err = txn.Prepare("COPY temp (num) FROM STDIN WITH binary") - if err != errBinaryCopyNotSupported { - t.Fatalf("expected %s, got %+v", errBinaryCopyNotSupported, err) - } - // check that the protocol is in a valid state - err = txn.Rollback() - if err != nil { - t.Fatal(err) - } -} - -func TestCopyFromError(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - txn, err := db.Begin() - if err != nil { - t.Fatal(err) - } - defer txn.Rollback() - - _, err = txn.Exec("CREATE TEMP TABLE temp (num INTEGER)") - if err != nil { - t.Fatal(err) - } - _, err = txn.Prepare("COPY temp (num) TO STDOUT") - if err != errCopyToNotSupported { - t.Fatalf("expected %s, got %+v", errCopyToNotSupported, err) - } - // check that the protocol is in a valid state - err = txn.Rollback() - if err != nil { - t.Fatal(err) - } -} - -func TestCopySyntaxError(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - txn, err := db.Begin() - if err != nil { - t.Fatal(err) - } - defer txn.Rollback() - - _, err = txn.Prepare("COPY ") - if err == nil { - t.Fatal("expected error") - } - if pge := err.(*Error); pge.Code.Name() != "syntax_error" { - t.Fatalf("expected syntax error, got %s (%+v)", pge.Code.Name(), pge) - } - // check that the protocol is in a valid state - err = txn.Rollback() - if err != nil { - t.Fatal(err) - } -} - -// Tests for connection errors in copyin.resploop() -func TestCopyRespLoopConnectionError(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - txn, err := db.Begin() - if err != nil { - t.Fatal(err) - } - defer txn.Rollback() - - var pid int - err = txn.QueryRow("SELECT pg_backend_pid()").Scan(&pid) - if err != nil { - t.Fatal(err) - } - - _, err = txn.Exec("CREATE TEMP TABLE temp (a int)") - if err != nil { - t.Fatal(err) - } - - stmt, err := txn.Prepare(CopyIn("temp", "a")) - if err != nil { - t.Fatal(err) - } - defer stmt.Close() - - _, err = db.Exec("SELECT pg_terminate_backend($1)", pid) - if err != nil { - t.Fatal(err) - } - - if getServerVersion(t, db) < 90500 { - // We have to try and send something over, since postgres before - // version 9.5 won't process SIGTERMs while it's waiting for - // CopyData/CopyEnd messages; see tcop/postgres.c. - _, err = stmt.Exec(1) - if err != nil { - t.Fatal(err) - } - } - _, err = stmt.Exec() - if err == nil { - t.Fatalf("expected error") - } - switch pge := err.(type) { - case *Error: - if pge.Code.Name() != "admin_shutdown" { - t.Fatalf("expected admin_shutdown, got %s", pge.Code.Name()) - } - case *net.OpError: - // ignore - default: - if err == driver.ErrBadConn { - // likely an EPIPE - } else { - t.Fatalf("unexpected error, got %+#v", err) - } - } - - _ = stmt.Close() -} - -func BenchmarkCopyIn(b *testing.B) { - db := openTestConn(b) - defer db.Close() - - txn, err := db.Begin() - if err != nil { - b.Fatal(err) - } - defer txn.Rollback() - - _, err = txn.Exec("CREATE TEMP TABLE temp (a int, b varchar)") - if err != nil { - b.Fatal(err) - } - - stmt, err := txn.Prepare(CopyIn("temp", "a", "b")) - if err != nil { - b.Fatal(err) - } - - for i := 0; i < b.N; i++ { - _, err = stmt.Exec(int64(i), "hello world!") - if err != nil { - b.Fatal(err) - } - } - - _, err = stmt.Exec() - if err != nil { - b.Fatal(err) - } - - err = stmt.Close() - if err != nil { - b.Fatal(err) - } - - var num int - err = txn.QueryRow("SELECT COUNT(*) FROM temp").Scan(&num) - if err != nil { - b.Fatal(err) - } - - if num != b.N { - b.Fatalf("expected %d items, not %d", b.N, num) - } -} diff --git a/vendor/github.com/lib/pq/encode_test.go b/vendor/github.com/lib/pq/encode_test.go deleted file mode 100644 index d58798a4..00000000 --- a/vendor/github.com/lib/pq/encode_test.go +++ /dev/null @@ -1,766 +0,0 @@ -package pq - -import ( - "bytes" - "database/sql" - "fmt" - "regexp" - "testing" - "time" - - "github.com/lib/pq/oid" -) - -func TestScanTimestamp(t *testing.T) { - var nt NullTime - tn := time.Now() - nt.Scan(tn) - if !nt.Valid { - t.Errorf("Expected Valid=false") - } - if nt.Time != tn { - t.Errorf("Time value mismatch") - } -} - -func TestScanNilTimestamp(t *testing.T) { - var nt NullTime - nt.Scan(nil) - if nt.Valid { - t.Errorf("Expected Valid=false") - } -} - -var timeTests = []struct { - str string - timeval time.Time -}{ - {"22001-02-03", time.Date(22001, time.February, 3, 0, 0, 0, 0, time.FixedZone("", 0))}, - {"2001-02-03", time.Date(2001, time.February, 3, 0, 0, 0, 0, time.FixedZone("", 0))}, - {"0001-12-31 BC", time.Date(0, time.December, 31, 0, 0, 0, 0, time.FixedZone("", 0))}, - {"2001-02-03 BC", time.Date(-2000, time.February, 3, 0, 0, 0, 0, time.FixedZone("", 0))}, - {"2001-02-03 04:05:06", time.Date(2001, time.February, 3, 4, 5, 6, 0, time.FixedZone("", 0))}, - {"2001-02-03 04:05:06.000001", time.Date(2001, time.February, 3, 4, 5, 6, 1000, time.FixedZone("", 0))}, - {"2001-02-03 04:05:06.00001", time.Date(2001, time.February, 3, 4, 5, 6, 10000, time.FixedZone("", 0))}, - {"2001-02-03 04:05:06.0001", time.Date(2001, time.February, 3, 4, 5, 6, 100000, time.FixedZone("", 0))}, - {"2001-02-03 04:05:06.001", time.Date(2001, time.February, 3, 4, 5, 6, 1000000, time.FixedZone("", 0))}, - {"2001-02-03 04:05:06.01", time.Date(2001, time.February, 3, 4, 5, 6, 10000000, time.FixedZone("", 0))}, - {"2001-02-03 04:05:06.1", time.Date(2001, time.February, 3, 4, 5, 6, 100000000, time.FixedZone("", 0))}, - {"2001-02-03 04:05:06.12", time.Date(2001, time.February, 3, 4, 5, 6, 120000000, time.FixedZone("", 0))}, - {"2001-02-03 04:05:06.123", time.Date(2001, time.February, 3, 4, 5, 6, 123000000, time.FixedZone("", 0))}, - {"2001-02-03 04:05:06.1234", time.Date(2001, time.February, 3, 4, 5, 6, 123400000, time.FixedZone("", 0))}, - {"2001-02-03 04:05:06.12345", time.Date(2001, time.February, 3, 4, 5, 6, 123450000, time.FixedZone("", 0))}, - {"2001-02-03 04:05:06.123456", time.Date(2001, time.February, 3, 4, 5, 6, 123456000, time.FixedZone("", 0))}, - {"2001-02-03 04:05:06.123-07", time.Date(2001, time.February, 3, 4, 5, 6, 123000000, - time.FixedZone("", -7*60*60))}, - {"2001-02-03 04:05:06-07", time.Date(2001, time.February, 3, 4, 5, 6, 0, - time.FixedZone("", -7*60*60))}, - {"2001-02-03 04:05:06-07:42", time.Date(2001, time.February, 3, 4, 5, 6, 0, - time.FixedZone("", -(7*60*60+42*60)))}, - {"2001-02-03 04:05:06-07:30:09", time.Date(2001, time.February, 3, 4, 5, 6, 0, - time.FixedZone("", -(7*60*60+30*60+9)))}, - {"2001-02-03 04:05:06+07", time.Date(2001, time.February, 3, 4, 5, 6, 0, - time.FixedZone("", 7*60*60))}, - {"0011-02-03 04:05:06 BC", time.Date(-10, time.February, 3, 4, 5, 6, 0, time.FixedZone("", 0))}, - {"0011-02-03 04:05:06.123 BC", time.Date(-10, time.February, 3, 4, 5, 6, 123000000, time.FixedZone("", 0))}, - {"0011-02-03 04:05:06.123-07 BC", time.Date(-10, time.February, 3, 4, 5, 6, 123000000, - time.FixedZone("", -7*60*60))}, - {"0001-02-03 04:05:06.123", time.Date(1, time.February, 3, 4, 5, 6, 123000000, time.FixedZone("", 0))}, - {"0001-02-03 04:05:06.123 BC", time.Date(1, time.February, 3, 4, 5, 6, 123000000, time.FixedZone("", 0)).AddDate(-1, 0, 0)}, - {"0001-02-03 04:05:06.123 BC", time.Date(0, time.February, 3, 4, 5, 6, 123000000, time.FixedZone("", 0))}, - {"0002-02-03 04:05:06.123 BC", time.Date(0, time.February, 3, 4, 5, 6, 123000000, time.FixedZone("", 0)).AddDate(-1, 0, 0)}, - {"0002-02-03 04:05:06.123 BC", time.Date(-1, time.February, 3, 4, 5, 6, 123000000, time.FixedZone("", 0))}, - {"12345-02-03 04:05:06.1", time.Date(12345, time.February, 3, 4, 5, 6, 100000000, time.FixedZone("", 0))}, - {"123456-02-03 04:05:06.1", time.Date(123456, time.February, 3, 4, 5, 6, 100000000, time.FixedZone("", 0))}, -} - -// Test that parsing the string results in the expected value. -func TestParseTs(t *testing.T) { - for i, tt := range timeTests { - val, err := ParseTimestamp(nil, tt.str) - if err != nil { - t.Errorf("%d: got error: %v", i, err) - } else if val.String() != tt.timeval.String() { - t.Errorf("%d: expected to parse %q into %q; got %q", - i, tt.str, tt.timeval, val) - } - } -} - -var timeErrorTests = []string{ - "BC", - " BC", - "2001", - "2001-2-03", - "2001-02-3", - "2001-02-03 ", - "2001-02-03 B", - "2001-02-03 04", - "2001-02-03 04:", - "2001-02-03 04:05", - "2001-02-03 04:05 B", - "2001-02-03 04:05 BC", - "2001-02-03 04:05:", - "2001-02-03 04:05:6", - "2001-02-03 04:05:06 B", - "2001-02-03 04:05:06BC", - "2001-02-03 04:05:06.123 B", -} - -// Test that parsing the string results in an error. -func TestParseTsErrors(t *testing.T) { - for i, tt := range timeErrorTests { - _, err := ParseTimestamp(nil, tt) - if err == nil { - t.Errorf("%d: expected an error from parsing: %v", i, tt) - } - } -} - -// Now test that sending the value into the database and parsing it back -// returns the same time.Time value. -func TestEncodeAndParseTs(t *testing.T) { - db, err := openTestConnConninfo("timezone='Etc/UTC'") - if err != nil { - t.Fatal(err) - } - defer db.Close() - - for i, tt := range timeTests { - var dbstr string - err = db.QueryRow("SELECT ($1::timestamptz)::text", tt.timeval).Scan(&dbstr) - if err != nil { - t.Errorf("%d: could not send value %q to the database: %s", i, tt.timeval, err) - continue - } - - val, err := ParseTimestamp(nil, dbstr) - if err != nil { - t.Errorf("%d: could not parse value %q: %s", i, dbstr, err) - continue - } - val = val.In(tt.timeval.Location()) - if val.String() != tt.timeval.String() { - t.Errorf("%d: expected to parse %q into %q; got %q", i, dbstr, tt.timeval, val) - } - } -} - -var formatTimeTests = []struct { - time time.Time - expected string -}{ - {time.Time{}, "0001-01-01 00:00:00Z"}, - {time.Date(2001, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", 0)), "2001-02-03 04:05:06.123456789Z"}, - {time.Date(2001, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", 2*60*60)), "2001-02-03 04:05:06.123456789+02:00"}, - {time.Date(2001, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", -6*60*60)), "2001-02-03 04:05:06.123456789-06:00"}, - {time.Date(2001, time.February, 3, 4, 5, 6, 0, time.FixedZone("", -(7*60*60+30*60+9))), "2001-02-03 04:05:06-07:30:09"}, - - {time.Date(1, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", 0)), "0001-02-03 04:05:06.123456789Z"}, - {time.Date(1, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", 2*60*60)), "0001-02-03 04:05:06.123456789+02:00"}, - {time.Date(1, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", -6*60*60)), "0001-02-03 04:05:06.123456789-06:00"}, - - {time.Date(0, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", 0)), "0001-02-03 04:05:06.123456789Z BC"}, - {time.Date(0, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", 2*60*60)), "0001-02-03 04:05:06.123456789+02:00 BC"}, - {time.Date(0, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", -6*60*60)), "0001-02-03 04:05:06.123456789-06:00 BC"}, - - {time.Date(1, time.February, 3, 4, 5, 6, 0, time.FixedZone("", -(7*60*60+30*60+9))), "0001-02-03 04:05:06-07:30:09"}, - {time.Date(0, time.February, 3, 4, 5, 6, 0, time.FixedZone("", -(7*60*60+30*60+9))), "0001-02-03 04:05:06-07:30:09 BC"}, -} - -func TestFormatTs(t *testing.T) { - for i, tt := range formatTimeTests { - val := string(formatTs(tt.time)) - if val != tt.expected { - t.Errorf("%d: incorrect time format %q, want %q", i, val, tt.expected) - } - } -} - -func TestFormatTsBackend(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - var str string - err := db.QueryRow("SELECT '2001-02-03T04:05:06.007-08:09:10'::time::text").Scan(&str) - if err == nil { - t.Fatalf("PostgreSQL is accepting an ISO timestamp input for time") - } - - for i, tt := range formatTimeTests { - for _, typ := range []string{"date", "time", "timetz", "timestamp", "timestamptz"} { - err = db.QueryRow("SELECT $1::"+typ+"::text", tt.time).Scan(&str) - if err != nil { - t.Errorf("%d: incorrect time format for %v on the backend: %v", i, typ, err) - } - } - } -} - -func TestTimestampWithTimeZone(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - tx, err := db.Begin() - if err != nil { - t.Fatal(err) - } - defer tx.Rollback() - - // try several different locations, all included in Go's zoneinfo.zip - for _, locName := range []string{ - "UTC", - "America/Chicago", - "America/New_York", - "Australia/Darwin", - "Australia/Perth", - } { - loc, err := time.LoadLocation(locName) - if err != nil { - t.Logf("Could not load time zone %s - skipping", locName) - continue - } - - // Postgres timestamps have a resolution of 1 microsecond, so don't - // use the full range of the Nanosecond argument - refTime := time.Date(2012, 11, 6, 10, 23, 42, 123456000, loc) - - for _, pgTimeZone := range []string{"US/Eastern", "Australia/Darwin"} { - // Switch Postgres's timezone to test different output timestamp formats - _, err = tx.Exec(fmt.Sprintf("set time zone '%s'", pgTimeZone)) - if err != nil { - t.Fatal(err) - } - - var gotTime time.Time - row := tx.QueryRow("select $1::timestamp with time zone", refTime) - err = row.Scan(&gotTime) - if err != nil { - t.Fatal(err) - } - - if !refTime.Equal(gotTime) { - t.Errorf("timestamps not equal: %s != %s", refTime, gotTime) - } - - // check that the time zone is set correctly based on TimeZone - pgLoc, err := time.LoadLocation(pgTimeZone) - if err != nil { - t.Logf("Could not load time zone %s - skipping", pgLoc) - continue - } - translated := refTime.In(pgLoc) - if translated.String() != gotTime.String() { - t.Errorf("timestamps not equal: %s != %s", translated, gotTime) - } - } - } -} - -func TestTimestampWithOutTimezone(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - test := func(ts, pgts string) { - r, err := db.Query("SELECT $1::timestamp", pgts) - if err != nil { - t.Fatalf("Could not run query: %v", err) - } - - if !r.Next() { - t.Fatal("Expected at least one row") - } - - var result time.Time - err = r.Scan(&result) - if err != nil { - t.Fatalf("Did not expect error scanning row: %v", err) - } - - expected, err := time.Parse(time.RFC3339, ts) - if err != nil { - t.Fatalf("Could not parse test time literal: %v", err) - } - - if !result.Equal(expected) { - t.Fatalf("Expected time to match %v: got mismatch %v", - expected, result) - } - - if r.Next() { - t.Fatal("Expected only one row") - } - } - - test("2000-01-01T00:00:00Z", "2000-01-01T00:00:00") - - // Test higher precision time - test("2013-01-04T20:14:58.80033Z", "2013-01-04 20:14:58.80033") -} - -func TestInfinityTimestamp(t *testing.T) { - db := openTestConn(t) - defer db.Close() - var err error - var resultT time.Time - - expectedErrorStrRegexp := regexp.MustCompile( - `^sql: Scan error on column index 0(, name "timestamp(tz)?"|): unsupported`) - - type testCases []struct { - Query string - Param string - ExpectedErrorStrRegexp *regexp.Regexp - ExpectedVal interface{} - } - tc := testCases{ - {"SELECT $1::timestamp", "-infinity", expectedErrorStrRegexp, "-infinity"}, - {"SELECT $1::timestamptz", "-infinity", expectedErrorStrRegexp, "-infinity"}, - {"SELECT $1::timestamp", "infinity", expectedErrorStrRegexp, "infinity"}, - {"SELECT $1::timestamptz", "infinity", expectedErrorStrRegexp, "infinity"}, - } - // try to assert []byte to time.Time - for _, q := range tc { - err = db.QueryRow(q.Query, q.Param).Scan(&resultT) - if !q.ExpectedErrorStrRegexp.MatchString(err.Error()) { - t.Errorf("Scanning -/+infinity, expected error to match regexp %q, got %q", - q.ExpectedErrorStrRegexp, err) - } - } - // yield []byte - for _, q := range tc { - var resultI interface{} - err = db.QueryRow(q.Query, q.Param).Scan(&resultI) - if err != nil { - t.Errorf("Scanning -/+infinity, expected no error, got %q", err) - } - result, ok := resultI.([]byte) - if !ok { - t.Errorf("Scanning -/+infinity, expected []byte, got %#v", resultI) - } - if string(result) != q.ExpectedVal { - t.Errorf("Scanning -/+infinity, expected %q, got %q", q.ExpectedVal, result) - } - } - - y1500 := time.Date(1500, time.January, 1, 0, 0, 0, 0, time.UTC) - y2500 := time.Date(2500, time.January, 1, 0, 0, 0, 0, time.UTC) - EnableInfinityTs(y1500, y2500) - - err = db.QueryRow("SELECT $1::timestamp", "infinity").Scan(&resultT) - if err != nil { - t.Errorf("Scanning infinity, expected no error, got %q", err) - } - if !resultT.Equal(y2500) { - t.Errorf("Scanning infinity, expected %q, got %q", y2500, resultT) - } - - err = db.QueryRow("SELECT $1::timestamptz", "infinity").Scan(&resultT) - if err != nil { - t.Errorf("Scanning infinity, expected no error, got %q", err) - } - if !resultT.Equal(y2500) { - t.Errorf("Scanning Infinity, expected time %q, got %q", y2500, resultT.String()) - } - - err = db.QueryRow("SELECT $1::timestamp", "-infinity").Scan(&resultT) - if err != nil { - t.Errorf("Scanning -infinity, expected no error, got %q", err) - } - if !resultT.Equal(y1500) { - t.Errorf("Scanning -infinity, expected time %q, got %q", y1500, resultT.String()) - } - - err = db.QueryRow("SELECT $1::timestamptz", "-infinity").Scan(&resultT) - if err != nil { - t.Errorf("Scanning -infinity, expected no error, got %q", err) - } - if !resultT.Equal(y1500) { - t.Errorf("Scanning -infinity, expected time %q, got %q", y1500, resultT.String()) - } - - ym1500 := time.Date(-1500, time.January, 1, 0, 0, 0, 0, time.UTC) - y11500 := time.Date(11500, time.January, 1, 0, 0, 0, 0, time.UTC) - var s string - err = db.QueryRow("SELECT $1::timestamp::text", ym1500).Scan(&s) - if err != nil { - t.Errorf("Encoding -infinity, expected no error, got %q", err) - } - if s != "-infinity" { - t.Errorf("Encoding -infinity, expected %q, got %q", "-infinity", s) - } - err = db.QueryRow("SELECT $1::timestamptz::text", ym1500).Scan(&s) - if err != nil { - t.Errorf("Encoding -infinity, expected no error, got %q", err) - } - if s != "-infinity" { - t.Errorf("Encoding -infinity, expected %q, got %q", "-infinity", s) - } - - err = db.QueryRow("SELECT $1::timestamp::text", y11500).Scan(&s) - if err != nil { - t.Errorf("Encoding infinity, expected no error, got %q", err) - } - if s != "infinity" { - t.Errorf("Encoding infinity, expected %q, got %q", "infinity", s) - } - err = db.QueryRow("SELECT $1::timestamptz::text", y11500).Scan(&s) - if err != nil { - t.Errorf("Encoding infinity, expected no error, got %q", err) - } - if s != "infinity" { - t.Errorf("Encoding infinity, expected %q, got %q", "infinity", s) - } - - disableInfinityTs() - - var panicErrorString string - func() { - defer func() { - panicErrorString, _ = recover().(string) - }() - EnableInfinityTs(y2500, y1500) - }() - if panicErrorString != infinityTsNegativeMustBeSmaller { - t.Errorf("Expected error, %q, got %q", infinityTsNegativeMustBeSmaller, panicErrorString) - } -} - -func TestStringWithNul(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - hello0world := string("hello\x00world") - _, err := db.Query("SELECT $1::text", &hello0world) - if err == nil { - t.Fatal("Postgres accepts a string with nul in it; " + - "injection attacks may be plausible") - } -} - -func TestByteSliceToText(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - b := []byte("hello world") - row := db.QueryRow("SELECT $1::text", b) - - var result []byte - err := row.Scan(&result) - if err != nil { - t.Fatal(err) - } - - if string(result) != string(b) { - t.Fatalf("expected %v but got %v", b, result) - } -} - -func TestStringToBytea(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - b := "hello world" - row := db.QueryRow("SELECT $1::bytea", b) - - var result []byte - err := row.Scan(&result) - if err != nil { - t.Fatal(err) - } - - if !bytes.Equal(result, []byte(b)) { - t.Fatalf("expected %v but got %v", b, result) - } -} - -func TestTextByteSliceToUUID(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - b := []byte("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11") - row := db.QueryRow("SELECT $1::uuid", b) - - var result string - err := row.Scan(&result) - if forceBinaryParameters() { - pqErr := err.(*Error) - if pqErr == nil { - t.Errorf("Expected to get error") - } else if pqErr.Code != "22P03" { - t.Fatalf("Expected to get invalid binary encoding error (22P03), got %s", pqErr.Code) - } - } else { - if err != nil { - t.Fatal(err) - } - - if result != string(b) { - t.Fatalf("expected %v but got %v", b, result) - } - } -} - -func TestBinaryByteSlicetoUUID(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - b := []byte{'\xa0', '\xee', '\xbc', '\x99', - '\x9c', '\x0b', - '\x4e', '\xf8', - '\xbb', '\x00', '\x6b', - '\xb9', '\xbd', '\x38', '\x0a', '\x11'} - row := db.QueryRow("SELECT $1::uuid", b) - - var result string - err := row.Scan(&result) - if forceBinaryParameters() { - if err != nil { - t.Fatal(err) - } - - if result != string("a0eebc99-9c0b-4ef8-bb00-6bb9bd380a11") { - t.Fatalf("expected %v but got %v", b, result) - } - } else { - pqErr := err.(*Error) - if pqErr == nil { - t.Errorf("Expected to get error") - } else if pqErr.Code != "22021" { - t.Fatalf("Expected to get invalid byte sequence for encoding error (22021), got %s", pqErr.Code) - } - } -} - -func TestStringToUUID(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - s := "a0eebc99-9c0b-4ef8-bb00-6bb9bd380a11" - row := db.QueryRow("SELECT $1::uuid", s) - - var result string - err := row.Scan(&result) - if err != nil { - t.Fatal(err) - } - - if result != s { - t.Fatalf("expected %v but got %v", s, result) - } -} - -func TestTextByteSliceToInt(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - expected := 12345678 - b := []byte(fmt.Sprintf("%d", expected)) - row := db.QueryRow("SELECT $1::int", b) - - var result int - err := row.Scan(&result) - if forceBinaryParameters() { - pqErr := err.(*Error) - if pqErr == nil { - t.Errorf("Expected to get error") - } else if pqErr.Code != "22P03" { - t.Fatalf("Expected to get invalid binary encoding error (22P03), got %s", pqErr.Code) - } - } else { - if err != nil { - t.Fatal(err) - } - if result != expected { - t.Fatalf("expected %v but got %v", expected, result) - } - } -} - -func TestBinaryByteSliceToInt(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - expected := 12345678 - b := []byte{'\x00', '\xbc', '\x61', '\x4e'} - row := db.QueryRow("SELECT $1::int", b) - - var result int - err := row.Scan(&result) - if forceBinaryParameters() { - if err != nil { - t.Fatal(err) - } - if result != expected { - t.Fatalf("expected %v but got %v", expected, result) - } - } else { - pqErr := err.(*Error) - if pqErr == nil { - t.Errorf("Expected to get error") - } else if pqErr.Code != "22021" { - t.Fatalf("Expected to get invalid byte sequence for encoding error (22021), got %s", pqErr.Code) - } - } -} - -func TestTextDecodeIntoString(t *testing.T) { - input := []byte("hello world") - want := string(input) - for _, typ := range []oid.Oid{oid.T_char, oid.T_varchar, oid.T_text} { - got := decode(¶meterStatus{}, input, typ, formatText) - if got != want { - t.Errorf("invalid string decoding output for %T(%+v), got %v but expected %v", typ, typ, got, want) - } - } -} - -func TestByteaOutputFormatEncoding(t *testing.T) { - input := []byte("\\x\x00\x01\x02\xFF\xFEabcdefg0123") - want := []byte("\\x5c78000102fffe6162636465666730313233") - got := encode(¶meterStatus{serverVersion: 90000}, input, oid.T_bytea) - if !bytes.Equal(want, got) { - t.Errorf("invalid hex bytea output, got %v but expected %v", got, want) - } - - want = []byte("\\\\x\\000\\001\\002\\377\\376abcdefg0123") - got = encode(¶meterStatus{serverVersion: 84000}, input, oid.T_bytea) - if !bytes.Equal(want, got) { - t.Errorf("invalid escape bytea output, got %v but expected %v", got, want) - } -} - -func TestByteaOutputFormats(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - if getServerVersion(t, db) < 90000 { - // skip - return - } - - testByteaOutputFormat := func(f string, usePrepared bool) { - expectedData := []byte("\x5c\x78\x00\xff\x61\x62\x63\x01\x08") - sqlQuery := "SELECT decode('5c7800ff6162630108', 'hex')" - - var data []byte - - // use a txn to avoid relying on getting the same connection - txn, err := db.Begin() - if err != nil { - t.Fatal(err) - } - defer txn.Rollback() - - _, err = txn.Exec("SET LOCAL bytea_output TO " + f) - if err != nil { - t.Fatal(err) - } - var rows *sql.Rows - var stmt *sql.Stmt - if usePrepared { - stmt, err = txn.Prepare(sqlQuery) - if err != nil { - t.Fatal(err) - } - rows, err = stmt.Query() - } else { - // use Query; QueryRow would hide the actual error - rows, err = txn.Query(sqlQuery) - } - if err != nil { - t.Fatal(err) - } - if !rows.Next() { - if rows.Err() != nil { - t.Fatal(rows.Err()) - } - t.Fatal("shouldn't happen") - } - err = rows.Scan(&data) - if err != nil { - t.Fatal(err) - } - err = rows.Close() - if err != nil { - t.Fatal(err) - } - if stmt != nil { - err = stmt.Close() - if err != nil { - t.Fatal(err) - } - } - if !bytes.Equal(data, expectedData) { - t.Errorf("unexpected bytea value %v for format %s; expected %v", data, f, expectedData) - } - } - - testByteaOutputFormat("hex", false) - testByteaOutputFormat("escape", false) - testByteaOutputFormat("hex", true) - testByteaOutputFormat("escape", true) -} - -func TestAppendEncodedText(t *testing.T) { - var buf []byte - - buf = appendEncodedText(¶meterStatus{serverVersion: 90000}, buf, int64(10)) - buf = append(buf, '\t') - buf = appendEncodedText(¶meterStatus{serverVersion: 90000}, buf, 42.0000000001) - buf = append(buf, '\t') - buf = appendEncodedText(¶meterStatus{serverVersion: 90000}, buf, "hello\tworld") - buf = append(buf, '\t') - buf = appendEncodedText(¶meterStatus{serverVersion: 90000}, buf, []byte{0, 128, 255}) - - if string(buf) != "10\t42.0000000001\thello\\tworld\t\\\\x0080ff" { - t.Fatal(string(buf)) - } -} - -func TestAppendEscapedText(t *testing.T) { - if esc := appendEscapedText(nil, "hallo\tescape"); string(esc) != "hallo\\tescape" { - t.Fatal(string(esc)) - } - if esc := appendEscapedText(nil, "hallo\\tescape\n"); string(esc) != "hallo\\\\tescape\\n" { - t.Fatal(string(esc)) - } - if esc := appendEscapedText(nil, "\n\r\t\f"); string(esc) != "\\n\\r\\t\f" { - t.Fatal(string(esc)) - } -} - -func TestAppendEscapedTextExistingBuffer(t *testing.T) { - buf := []byte("123\t") - if esc := appendEscapedText(buf, "hallo\tescape"); string(esc) != "123\thallo\\tescape" { - t.Fatal(string(esc)) - } - buf = []byte("123\t") - if esc := appendEscapedText(buf, "hallo\\tescape\n"); string(esc) != "123\thallo\\\\tescape\\n" { - t.Fatal(string(esc)) - } - buf = []byte("123\t") - if esc := appendEscapedText(buf, "\n\r\t\f"); string(esc) != "123\t\\n\\r\\t\f" { - t.Fatal(string(esc)) - } -} - -func BenchmarkAppendEscapedText(b *testing.B) { - longString := "" - for i := 0; i < 100; i++ { - longString += "123456789\n" - } - for i := 0; i < b.N; i++ { - appendEscapedText(nil, longString) - } -} - -func BenchmarkAppendEscapedTextNoEscape(b *testing.B) { - longString := "" - for i := 0; i < 100; i++ { - longString += "1234567890" - } - for i := 0; i < b.N; i++ { - appendEscapedText(nil, longString) - } -} diff --git a/vendor/github.com/lib/pq/go.mod b/vendor/github.com/lib/pq/go.mod deleted file mode 100644 index edf0b343..00000000 --- a/vendor/github.com/lib/pq/go.mod +++ /dev/null @@ -1 +0,0 @@ -module github.com/lib/pq diff --git a/vendor/github.com/lib/pq/go18_test.go b/vendor/github.com/lib/pq/go18_test.go deleted file mode 100644 index 1a88a5b4..00000000 --- a/vendor/github.com/lib/pq/go18_test.go +++ /dev/null @@ -1,321 +0,0 @@ -// +build go1.8 - -package pq - -import ( - "context" - "database/sql" - "runtime" - "strings" - "testing" - "time" -) - -func TestMultipleSimpleQuery(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - rows, err := db.Query("select 1; set time zone default; select 2; select 3") - if err != nil { - t.Fatal(err) - } - defer rows.Close() - - var i int - for rows.Next() { - if err := rows.Scan(&i); err != nil { - t.Fatal(err) - } - if i != 1 { - t.Fatalf("expected 1, got %d", i) - } - } - if !rows.NextResultSet() { - t.Fatal("expected more result sets", rows.Err()) - } - for rows.Next() { - if err := rows.Scan(&i); err != nil { - t.Fatal(err) - } - if i != 2 { - t.Fatalf("expected 2, got %d", i) - } - } - - // Make sure that if we ignore a result we can still query. - - rows, err = db.Query("select 4; select 5") - if err != nil { - t.Fatal(err) - } - defer rows.Close() - - for rows.Next() { - if err := rows.Scan(&i); err != nil { - t.Fatal(err) - } - if i != 4 { - t.Fatalf("expected 4, got %d", i) - } - } - if !rows.NextResultSet() { - t.Fatal("expected more result sets", rows.Err()) - } - for rows.Next() { - if err := rows.Scan(&i); err != nil { - t.Fatal(err) - } - if i != 5 { - t.Fatalf("expected 5, got %d", i) - } - } - if rows.NextResultSet() { - t.Fatal("unexpected result set") - } -} - -const contextRaceIterations = 100 - -func TestContextCancelExec(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - ctx, cancel := context.WithCancel(context.Background()) - - // Delay execution for just a bit until db.ExecContext has begun. - defer time.AfterFunc(time.Millisecond*10, cancel).Stop() - - // Not canceled until after the exec has started. - if _, err := db.ExecContext(ctx, "select pg_sleep(1)"); err == nil { - t.Fatal("expected error") - } else if err.Error() != "pq: canceling statement due to user request" { - t.Fatalf("unexpected error: %s", err) - } - - // Context is already canceled, so error should come before execution. - if _, err := db.ExecContext(ctx, "select pg_sleep(1)"); err == nil { - t.Fatal("expected error") - } else if err.Error() != "context canceled" { - t.Fatalf("unexpected error: %s", err) - } - - for i := 0; i < contextRaceIterations; i++ { - func() { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - if _, err := db.ExecContext(ctx, "select 1"); err != nil { - t.Fatal(err) - } - }() - - if _, err := db.Exec("select 1"); err != nil { - t.Fatal(err) - } - } -} - -func TestContextCancelQuery(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - ctx, cancel := context.WithCancel(context.Background()) - - // Delay execution for just a bit until db.QueryContext has begun. - defer time.AfterFunc(time.Millisecond*10, cancel).Stop() - - // Not canceled until after the exec has started. - if _, err := db.QueryContext(ctx, "select pg_sleep(1)"); err == nil { - t.Fatal("expected error") - } else if err.Error() != "pq: canceling statement due to user request" { - t.Fatalf("unexpected error: %s", err) - } - - // Context is already canceled, so error should come before execution. - if _, err := db.QueryContext(ctx, "select pg_sleep(1)"); err == nil { - t.Fatal("expected error") - } else if err.Error() != "context canceled" { - t.Fatalf("unexpected error: %s", err) - } - - for i := 0; i < contextRaceIterations; i++ { - func() { - ctx, cancel := context.WithCancel(context.Background()) - rows, err := db.QueryContext(ctx, "select 1") - cancel() - if err != nil { - t.Fatal(err) - } else if err := rows.Close(); err != nil { - t.Fatal(err) - } - }() - - if rows, err := db.Query("select 1"); err != nil { - t.Fatal(err) - } else if err := rows.Close(); err != nil { - t.Fatal(err) - } - } -} - -// TestIssue617 tests that a failed query in QueryContext doesn't lead to a -// goroutine leak. -func TestIssue617(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - const N = 10 - - numGoroutineStart := runtime.NumGoroutine() - for i := 0; i < N; i++ { - func() { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - _, err := db.QueryContext(ctx, `SELECT * FROM DOESNOTEXIST`) - pqErr, _ := err.(*Error) - // Expecting "pq: relation \"doesnotexist\" does not exist" error. - if err == nil || pqErr == nil || pqErr.Code != "42P01" { - t.Fatalf("expected undefined table error, got %v", err) - } - }() - } - numGoroutineFinish := runtime.NumGoroutine() - - // We use N/2 and not N because the GC and other actors may increase or - // decrease the number of goroutines. - if numGoroutineFinish-numGoroutineStart >= N/2 { - t.Errorf("goroutine leak detected, was %d, now %d", numGoroutineStart, numGoroutineFinish) - } -} - -func TestContextCancelBegin(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - ctx, cancel := context.WithCancel(context.Background()) - tx, err := db.BeginTx(ctx, nil) - if err != nil { - t.Fatal(err) - } - - // Delay execution for just a bit until tx.Exec has begun. - defer time.AfterFunc(time.Millisecond*10, cancel).Stop() - - // Not canceled until after the exec has started. - if _, err := tx.Exec("select pg_sleep(1)"); err == nil { - t.Fatal("expected error") - } else if err.Error() != "pq: canceling statement due to user request" { - t.Fatalf("unexpected error: %s", err) - } - - // Transaction is canceled, so expect an error. - if _, err := tx.Query("select pg_sleep(1)"); err == nil { - t.Fatal("expected error") - } else if err != sql.ErrTxDone { - t.Fatalf("unexpected error: %s", err) - } - - // Context is canceled, so cannot begin a transaction. - if _, err := db.BeginTx(ctx, nil); err == nil { - t.Fatal("expected error") - } else if err.Error() != "context canceled" { - t.Fatalf("unexpected error: %s", err) - } - - for i := 0; i < contextRaceIterations; i++ { - func() { - ctx, cancel := context.WithCancel(context.Background()) - tx, err := db.BeginTx(ctx, nil) - cancel() - if err != nil { - t.Fatal(err) - } else if err := tx.Rollback(); err != nil && - err.Error() != "pq: canceling statement due to user request" && - err != sql.ErrTxDone { - t.Fatal(err) - } - }() - - if tx, err := db.Begin(); err != nil { - t.Fatal(err) - } else if err := tx.Rollback(); err != nil { - t.Fatal(err) - } - } -} - -func TestTxOptions(t *testing.T) { - db := openTestConn(t) - defer db.Close() - ctx := context.Background() - - tests := []struct { - level sql.IsolationLevel - isolation string - }{ - { - level: sql.LevelDefault, - isolation: "", - }, - { - level: sql.LevelReadUncommitted, - isolation: "read uncommitted", - }, - { - level: sql.LevelReadCommitted, - isolation: "read committed", - }, - { - level: sql.LevelRepeatableRead, - isolation: "repeatable read", - }, - { - level: sql.LevelSerializable, - isolation: "serializable", - }, - } - - for _, test := range tests { - for _, ro := range []bool{true, false} { - tx, err := db.BeginTx(ctx, &sql.TxOptions{ - Isolation: test.level, - ReadOnly: ro, - }) - if err != nil { - t.Fatal(err) - } - - var isolation string - err = tx.QueryRow("select current_setting('transaction_isolation')").Scan(&isolation) - if err != nil { - t.Fatal(err) - } - - if test.isolation != "" && isolation != test.isolation { - t.Errorf("wrong isolation level: %s != %s", isolation, test.isolation) - } - - var isRO string - err = tx.QueryRow("select current_setting('transaction_read_only')").Scan(&isRO) - if err != nil { - t.Fatal(err) - } - - if ro != (isRO == "on") { - t.Errorf("read/[write,only] not set: %t != %s for level %s", - ro, isRO, test.isolation) - } - - tx.Rollback() - } - } - - _, err := db.BeginTx(ctx, &sql.TxOptions{ - Isolation: sql.LevelLinearizable, - }) - if err == nil { - t.Fatal("expected LevelLinearizable to fail") - } - if !strings.Contains(err.Error(), "isolation level not supported") { - t.Errorf("Expected error to mention isolation level, got %q", err) - } -} diff --git a/vendor/github.com/lib/pq/hstore/hstore_test.go b/vendor/github.com/lib/pq/hstore/hstore_test.go deleted file mode 100644 index 1c9f2bd4..00000000 --- a/vendor/github.com/lib/pq/hstore/hstore_test.go +++ /dev/null @@ -1,148 +0,0 @@ -package hstore - -import ( - "database/sql" - "os" - "testing" - - _ "github.com/lib/pq" -) - -type Fatalistic interface { - Fatal(args ...interface{}) -} - -func openTestConn(t Fatalistic) *sql.DB { - datname := os.Getenv("PGDATABASE") - sslmode := os.Getenv("PGSSLMODE") - - if datname == "" { - os.Setenv("PGDATABASE", "pqgotest") - } - - if sslmode == "" { - os.Setenv("PGSSLMODE", "disable") - } - - conn, err := sql.Open("postgres", "") - if err != nil { - t.Fatal(err) - } - - return conn -} - -func TestHstore(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - // quitely create hstore if it doesn't exist - _, err := db.Exec("CREATE EXTENSION IF NOT EXISTS hstore") - if err != nil { - t.Skipf("Skipping hstore tests - hstore extension create failed: %s", err.Error()) - } - - hs := Hstore{} - - // test for null-valued hstores - err = db.QueryRow("SELECT NULL::hstore").Scan(&hs) - if err != nil { - t.Fatal(err) - } - if hs.Map != nil { - t.Fatalf("expected null map") - } - - err = db.QueryRow("SELECT $1::hstore", hs).Scan(&hs) - if err != nil { - t.Fatalf("re-query null map failed: %s", err.Error()) - } - if hs.Map != nil { - t.Fatalf("expected null map") - } - - // test for empty hstores - err = db.QueryRow("SELECT ''::hstore").Scan(&hs) - if err != nil { - t.Fatal(err) - } - if hs.Map == nil { - t.Fatalf("expected empty map, got null map") - } - if len(hs.Map) != 0 { - t.Fatalf("expected empty map, got len(map)=%d", len(hs.Map)) - } - - err = db.QueryRow("SELECT $1::hstore", hs).Scan(&hs) - if err != nil { - t.Fatalf("re-query empty map failed: %s", err.Error()) - } - if hs.Map == nil { - t.Fatalf("expected empty map, got null map") - } - if len(hs.Map) != 0 { - t.Fatalf("expected empty map, got len(map)=%d", len(hs.Map)) - } - - // a few example maps to test out - hsOnePair := Hstore{ - Map: map[string]sql.NullString{ - "key1": {String: "value1", Valid: true}, - }, - } - - hsThreePairs := Hstore{ - Map: map[string]sql.NullString{ - "key1": {String: "value1", Valid: true}, - "key2": {String: "value2", Valid: true}, - "key3": {String: "value3", Valid: true}, - }, - } - - hsSmorgasbord := Hstore{ - Map: map[string]sql.NullString{ - "nullstring": {String: "NULL", Valid: true}, - "actuallynull": {String: "", Valid: false}, - "NULL": {String: "NULL string key", Valid: true}, - "withbracket": {String: "value>42", Valid: true}, - "withequal": {String: "value=42", Valid: true}, - `"withquotes1"`: {String: `this "should" be fine`, Valid: true}, - `"withquotes"2"`: {String: `this "should\" also be fine`, Valid: true}, - "embedded1": {String: "value1=>x1", Valid: true}, - "embedded2": {String: `"value2"=>x2`, Valid: true}, - "withnewlines": {String: "\n\nvalue\t=>2", Valid: true}, - "<>": {String: `this, "should,\" also, => be fine`, Valid: true}, - }, - } - - // test encoding in query params, then decoding during Scan - testBidirectional := func(h Hstore) { - err = db.QueryRow("SELECT $1::hstore", h).Scan(&hs) - if err != nil { - t.Fatalf("re-query %d-pair map failed: %s", len(h.Map), err.Error()) - } - if hs.Map == nil { - t.Fatalf("expected %d-pair map, got null map", len(h.Map)) - } - if len(hs.Map) != len(h.Map) { - t.Fatalf("expected %d-pair map, got len(map)=%d", len(h.Map), len(hs.Map)) - } - - for key, val := range hs.Map { - otherval, found := h.Map[key] - if !found { - t.Fatalf(" key '%v' not found in %d-pair map", key, len(h.Map)) - } - if otherval.Valid != val.Valid { - t.Fatalf(" value %v <> %v in %d-pair map", otherval, val, len(h.Map)) - } - if otherval.String != val.String { - t.Fatalf(" value '%v' <> '%v' in %d-pair map", otherval.String, val.String, len(h.Map)) - } - } - } - - testBidirectional(hsOnePair) - testBidirectional(hsThreePairs) - testBidirectional(hsSmorgasbord) -} diff --git a/vendor/github.com/lib/pq/issues_test.go b/vendor/github.com/lib/pq/issues_test.go deleted file mode 100644 index 3a330a0a..00000000 --- a/vendor/github.com/lib/pq/issues_test.go +++ /dev/null @@ -1,26 +0,0 @@ -package pq - -import "testing" - -func TestIssue494(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - query := `CREATE TEMP TABLE t (i INT PRIMARY KEY)` - if _, err := db.Exec(query); err != nil { - t.Fatal(err) - } - - txn, err := db.Begin() - if err != nil { - t.Fatal(err) - } - - if _, err := txn.Prepare(CopyIn("t", "i")); err != nil { - t.Fatal(err) - } - - if _, err := txn.Query("SELECT 1"); err == nil { - t.Fatal("expected error") - } -} diff --git a/vendor/github.com/lib/pq/notify_test.go b/vendor/github.com/lib/pq/notify_test.go deleted file mode 100644 index 075666dd..00000000 --- a/vendor/github.com/lib/pq/notify_test.go +++ /dev/null @@ -1,570 +0,0 @@ -package pq - -import ( - "errors" - "fmt" - "io" - "os" - "runtime" - "sync" - "testing" - "time" -) - -var errNilNotification = errors.New("nil notification") - -func expectNotification(t *testing.T, ch <-chan *Notification, relname string, extra string) error { - select { - case n := <-ch: - if n == nil { - return errNilNotification - } - if n.Channel != relname || n.Extra != extra { - return fmt.Errorf("unexpected notification %v", n) - } - return nil - case <-time.After(1500 * time.Millisecond): - return fmt.Errorf("timeout") - } -} - -func expectNoNotification(t *testing.T, ch <-chan *Notification) error { - select { - case n := <-ch: - return fmt.Errorf("unexpected notification %v", n) - case <-time.After(100 * time.Millisecond): - return nil - } -} - -func expectEvent(t *testing.T, eventch <-chan ListenerEventType, et ListenerEventType) error { - select { - case e := <-eventch: - if e != et { - return fmt.Errorf("unexpected event %v", e) - } - return nil - case <-time.After(1500 * time.Millisecond): - panic("expectEvent timeout") - } -} - -func expectNoEvent(t *testing.T, eventch <-chan ListenerEventType) error { - select { - case e := <-eventch: - return fmt.Errorf("unexpected event %v", e) - case <-time.After(100 * time.Millisecond): - return nil - } -} - -func newTestListenerConn(t *testing.T) (*ListenerConn, <-chan *Notification) { - datname := os.Getenv("PGDATABASE") - sslmode := os.Getenv("PGSSLMODE") - - if datname == "" { - os.Setenv("PGDATABASE", "pqgotest") - } - - if sslmode == "" { - os.Setenv("PGSSLMODE", "disable") - } - - notificationChan := make(chan *Notification) - l, err := NewListenerConn("", notificationChan) - if err != nil { - t.Fatal(err) - } - - return l, notificationChan -} - -func TestNewListenerConn(t *testing.T) { - l, _ := newTestListenerConn(t) - - defer l.Close() -} - -func TestConnListen(t *testing.T) { - l, channel := newTestListenerConn(t) - - defer l.Close() - - db := openTestConn(t) - defer db.Close() - - ok, err := l.Listen("notify_test") - if !ok || err != nil { - t.Fatal(err) - } - - _, err = db.Exec("NOTIFY notify_test") - if err != nil { - t.Fatal(err) - } - - err = expectNotification(t, channel, "notify_test", "") - if err != nil { - t.Fatal(err) - } -} - -func TestConnUnlisten(t *testing.T) { - l, channel := newTestListenerConn(t) - - defer l.Close() - - db := openTestConn(t) - defer db.Close() - - ok, err := l.Listen("notify_test") - if !ok || err != nil { - t.Fatal(err) - } - - _, err = db.Exec("NOTIFY notify_test") - if err != nil { - t.Fatal(err) - } - - err = expectNotification(t, channel, "notify_test", "") - if err != nil { - t.Fatal(err) - } - - ok, err = l.Unlisten("notify_test") - if !ok || err != nil { - t.Fatal(err) - } - - _, err = db.Exec("NOTIFY notify_test") - if err != nil { - t.Fatal(err) - } - - err = expectNoNotification(t, channel) - if err != nil { - t.Fatal(err) - } -} - -func TestConnUnlistenAll(t *testing.T) { - l, channel := newTestListenerConn(t) - - defer l.Close() - - db := openTestConn(t) - defer db.Close() - - ok, err := l.Listen("notify_test") - if !ok || err != nil { - t.Fatal(err) - } - - _, err = db.Exec("NOTIFY notify_test") - if err != nil { - t.Fatal(err) - } - - err = expectNotification(t, channel, "notify_test", "") - if err != nil { - t.Fatal(err) - } - - ok, err = l.UnlistenAll() - if !ok || err != nil { - t.Fatal(err) - } - - _, err = db.Exec("NOTIFY notify_test") - if err != nil { - t.Fatal(err) - } - - err = expectNoNotification(t, channel) - if err != nil { - t.Fatal(err) - } -} - -func TestConnClose(t *testing.T) { - l, _ := newTestListenerConn(t) - defer l.Close() - - err := l.Close() - if err != nil { - t.Fatal(err) - } - err = l.Close() - if err != errListenerConnClosed { - t.Fatalf("expected errListenerConnClosed; got %v", err) - } -} - -func TestConnPing(t *testing.T) { - l, _ := newTestListenerConn(t) - defer l.Close() - err := l.Ping() - if err != nil { - t.Fatal(err) - } - err = l.Close() - if err != nil { - t.Fatal(err) - } - err = l.Ping() - if err != errListenerConnClosed { - t.Fatalf("expected errListenerConnClosed; got %v", err) - } -} - -// Test for deadlock where a query fails while another one is queued -func TestConnExecDeadlock(t *testing.T) { - l, _ := newTestListenerConn(t) - defer l.Close() - - var wg sync.WaitGroup - wg.Add(2) - - go func() { - l.ExecSimpleQuery("SELECT pg_sleep(60)") - wg.Done() - }() - runtime.Gosched() - go func() { - l.ExecSimpleQuery("SELECT 1") - wg.Done() - }() - // give the two goroutines some time to get into position - runtime.Gosched() - // calls Close on the net.Conn; equivalent to a network failure - l.Close() - - defer time.AfterFunc(10*time.Second, func() { - panic("timed out") - }).Stop() - wg.Wait() -} - -// Test for ListenerConn being closed while a slow query is executing -func TestListenerConnCloseWhileQueryIsExecuting(t *testing.T) { - l, _ := newTestListenerConn(t) - defer l.Close() - - var wg sync.WaitGroup - wg.Add(1) - - go func() { - sent, err := l.ExecSimpleQuery("SELECT pg_sleep(60)") - if sent { - panic("expected sent=false") - } - // could be any of a number of errors - if err == nil { - panic("expected error") - } - wg.Done() - }() - // give the above goroutine some time to get into position - runtime.Gosched() - err := l.Close() - if err != nil { - t.Fatal(err) - } - - defer time.AfterFunc(10*time.Second, func() { - panic("timed out") - }).Stop() - wg.Wait() -} - -func TestNotifyExtra(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - if getServerVersion(t, db) < 90000 { - t.Skip("skipping NOTIFY payload test since the server does not appear to support it") - } - - l, channel := newTestListenerConn(t) - defer l.Close() - - ok, err := l.Listen("notify_test") - if !ok || err != nil { - t.Fatal(err) - } - - _, err = db.Exec("NOTIFY notify_test, 'something'") - if err != nil { - t.Fatal(err) - } - - err = expectNotification(t, channel, "notify_test", "something") - if err != nil { - t.Fatal(err) - } -} - -// create a new test listener and also set the timeouts -func newTestListenerTimeout(t *testing.T, min time.Duration, max time.Duration) (*Listener, <-chan ListenerEventType) { - datname := os.Getenv("PGDATABASE") - sslmode := os.Getenv("PGSSLMODE") - - if datname == "" { - os.Setenv("PGDATABASE", "pqgotest") - } - - if sslmode == "" { - os.Setenv("PGSSLMODE", "disable") - } - - eventch := make(chan ListenerEventType, 16) - l := NewListener("", min, max, func(t ListenerEventType, err error) { eventch <- t }) - err := expectEvent(t, eventch, ListenerEventConnected) - if err != nil { - t.Fatal(err) - } - return l, eventch -} - -func newTestListener(t *testing.T) (*Listener, <-chan ListenerEventType) { - return newTestListenerTimeout(t, time.Hour, time.Hour) -} - -func TestListenerListen(t *testing.T) { - l, _ := newTestListener(t) - defer l.Close() - - db := openTestConn(t) - defer db.Close() - - err := l.Listen("notify_listen_test") - if err != nil { - t.Fatal(err) - } - - _, err = db.Exec("NOTIFY notify_listen_test") - if err != nil { - t.Fatal(err) - } - - err = expectNotification(t, l.Notify, "notify_listen_test", "") - if err != nil { - t.Fatal(err) - } -} - -func TestListenerUnlisten(t *testing.T) { - l, _ := newTestListener(t) - defer l.Close() - - db := openTestConn(t) - defer db.Close() - - err := l.Listen("notify_listen_test") - if err != nil { - t.Fatal(err) - } - - _, err = db.Exec("NOTIFY notify_listen_test") - if err != nil { - t.Fatal(err) - } - - err = l.Unlisten("notify_listen_test") - if err != nil { - t.Fatal(err) - } - - err = expectNotification(t, l.Notify, "notify_listen_test", "") - if err != nil { - t.Fatal(err) - } - - _, err = db.Exec("NOTIFY notify_listen_test") - if err != nil { - t.Fatal(err) - } - - err = expectNoNotification(t, l.Notify) - if err != nil { - t.Fatal(err) - } -} - -func TestListenerUnlistenAll(t *testing.T) { - l, _ := newTestListener(t) - defer l.Close() - - db := openTestConn(t) - defer db.Close() - - err := l.Listen("notify_listen_test") - if err != nil { - t.Fatal(err) - } - - _, err = db.Exec("NOTIFY notify_listen_test") - if err != nil { - t.Fatal(err) - } - - err = l.UnlistenAll() - if err != nil { - t.Fatal(err) - } - - err = expectNotification(t, l.Notify, "notify_listen_test", "") - if err != nil { - t.Fatal(err) - } - - _, err = db.Exec("NOTIFY notify_listen_test") - if err != nil { - t.Fatal(err) - } - - err = expectNoNotification(t, l.Notify) - if err != nil { - t.Fatal(err) - } -} - -func TestListenerFailedQuery(t *testing.T) { - l, eventch := newTestListener(t) - defer l.Close() - - db := openTestConn(t) - defer db.Close() - - err := l.Listen("notify_listen_test") - if err != nil { - t.Fatal(err) - } - - _, err = db.Exec("NOTIFY notify_listen_test") - if err != nil { - t.Fatal(err) - } - - err = expectNotification(t, l.Notify, "notify_listen_test", "") - if err != nil { - t.Fatal(err) - } - - // shouldn't cause a disconnect - ok, err := l.cn.ExecSimpleQuery("SELECT error") - if !ok { - t.Fatalf("could not send query to server: %v", err) - } - _, ok = err.(PGError) - if !ok { - t.Fatalf("unexpected error %v", err) - } - err = expectNoEvent(t, eventch) - if err != nil { - t.Fatal(err) - } - - // should still work - _, err = db.Exec("NOTIFY notify_listen_test") - if err != nil { - t.Fatal(err) - } - - err = expectNotification(t, l.Notify, "notify_listen_test", "") - if err != nil { - t.Fatal(err) - } -} - -func TestListenerReconnect(t *testing.T) { - l, eventch := newTestListenerTimeout(t, 20*time.Millisecond, time.Hour) - defer l.Close() - - db := openTestConn(t) - defer db.Close() - - err := l.Listen("notify_listen_test") - if err != nil { - t.Fatal(err) - } - - _, err = db.Exec("NOTIFY notify_listen_test") - if err != nil { - t.Fatal(err) - } - - err = expectNotification(t, l.Notify, "notify_listen_test", "") - if err != nil { - t.Fatal(err) - } - - // kill the connection and make sure it comes back up - ok, err := l.cn.ExecSimpleQuery("SELECT pg_terminate_backend(pg_backend_pid())") - if ok { - t.Fatalf("could not kill the connection: %v", err) - } - if err != io.EOF { - t.Fatalf("unexpected error %v", err) - } - err = expectEvent(t, eventch, ListenerEventDisconnected) - if err != nil { - t.Fatal(err) - } - err = expectEvent(t, eventch, ListenerEventReconnected) - if err != nil { - t.Fatal(err) - } - - // should still work - _, err = db.Exec("NOTIFY notify_listen_test") - if err != nil { - t.Fatal(err) - } - - // should get nil after Reconnected - err = expectNotification(t, l.Notify, "", "") - if err != errNilNotification { - t.Fatal(err) - } - - err = expectNotification(t, l.Notify, "notify_listen_test", "") - if err != nil { - t.Fatal(err) - } -} - -func TestListenerClose(t *testing.T) { - l, _ := newTestListenerTimeout(t, 20*time.Millisecond, time.Hour) - defer l.Close() - - err := l.Close() - if err != nil { - t.Fatal(err) - } - err = l.Close() - if err != errListenerClosed { - t.Fatalf("expected errListenerClosed; got %v", err) - } -} - -func TestListenerPing(t *testing.T) { - l, _ := newTestListenerTimeout(t, 20*time.Millisecond, time.Hour) - defer l.Close() - - err := l.Ping() - if err != nil { - t.Fatal(err) - } - - err = l.Close() - if err != nil { - t.Fatal(err) - } - - err = l.Ping() - if err != errListenerClosed { - t.Fatalf("expected errListenerClosed; got %v", err) - } -} diff --git a/vendor/github.com/lib/pq/rows_test.go b/vendor/github.com/lib/pq/rows_test.go deleted file mode 100644 index 3033bc01..00000000 --- a/vendor/github.com/lib/pq/rows_test.go +++ /dev/null @@ -1,220 +0,0 @@ -// +build go1.8 - -package pq - -import ( - "math" - "reflect" - "testing" - - "github.com/lib/pq/oid" -) - -func TestDataTypeName(t *testing.T) { - tts := []struct { - typ oid.Oid - name string - }{ - {oid.T_int8, "INT8"}, - {oid.T_int4, "INT4"}, - {oid.T_int2, "INT2"}, - {oid.T_varchar, "VARCHAR"}, - {oid.T_text, "TEXT"}, - {oid.T_bool, "BOOL"}, - {oid.T_numeric, "NUMERIC"}, - {oid.T_date, "DATE"}, - {oid.T_time, "TIME"}, - {oid.T_timetz, "TIMETZ"}, - {oid.T_timestamp, "TIMESTAMP"}, - {oid.T_timestamptz, "TIMESTAMPTZ"}, - {oid.T_bytea, "BYTEA"}, - } - - for i, tt := range tts { - dt := fieldDesc{OID: tt.typ} - if name := dt.Name(); name != tt.name { - t.Errorf("(%d) got: %s want: %s", i, name, tt.name) - } - } -} - -func TestDataType(t *testing.T) { - tts := []struct { - typ oid.Oid - kind reflect.Kind - }{ - {oid.T_int8, reflect.Int64}, - {oid.T_int4, reflect.Int32}, - {oid.T_int2, reflect.Int16}, - {oid.T_varchar, reflect.String}, - {oid.T_text, reflect.String}, - {oid.T_bool, reflect.Bool}, - {oid.T_date, reflect.Struct}, - {oid.T_time, reflect.Struct}, - {oid.T_timetz, reflect.Struct}, - {oid.T_timestamp, reflect.Struct}, - {oid.T_timestamptz, reflect.Struct}, - {oid.T_bytea, reflect.Slice}, - } - - for i, tt := range tts { - dt := fieldDesc{OID: tt.typ} - if kind := dt.Type().Kind(); kind != tt.kind { - t.Errorf("(%d) got: %s want: %s", i, kind, tt.kind) - } - } -} - -func TestDataTypeLength(t *testing.T) { - tts := []struct { - typ oid.Oid - len int - mod int - length int64 - ok bool - }{ - {oid.T_int4, 0, -1, 0, false}, - {oid.T_varchar, 65535, 9, 5, true}, - {oid.T_text, 65535, -1, math.MaxInt64, true}, - {oid.T_bytea, 65535, -1, math.MaxInt64, true}, - } - - for i, tt := range tts { - dt := fieldDesc{OID: tt.typ, Len: tt.len, Mod: tt.mod} - if l, k := dt.Length(); k != tt.ok || l != tt.length { - t.Errorf("(%d) got: %d, %t want: %d, %t", i, l, k, tt.length, tt.ok) - } - } -} - -func TestDataTypePrecisionScale(t *testing.T) { - tts := []struct { - typ oid.Oid - mod int - precision, scale int64 - ok bool - }{ - {oid.T_int4, -1, 0, 0, false}, - {oid.T_numeric, 589830, 9, 2, true}, - {oid.T_text, -1, 0, 0, false}, - } - - for i, tt := range tts { - dt := fieldDesc{OID: tt.typ, Mod: tt.mod} - p, s, k := dt.PrecisionScale() - if k != tt.ok { - t.Errorf("(%d) got: %t want: %t", i, k, tt.ok) - } - if p != tt.precision { - t.Errorf("(%d) wrong precision got: %d want: %d", i, p, tt.precision) - } - if s != tt.scale { - t.Errorf("(%d) wrong scale got: %d want: %d", i, s, tt.scale) - } - } -} - -func TestRowsColumnTypes(t *testing.T) { - columnTypesTests := []struct { - Name string - TypeName string - Length struct { - Len int64 - OK bool - } - DecimalSize struct { - Precision int64 - Scale int64 - OK bool - } - ScanType reflect.Type - }{ - { - Name: "a", - TypeName: "INT4", - Length: struct { - Len int64 - OK bool - }{ - Len: 0, - OK: false, - }, - DecimalSize: struct { - Precision int64 - Scale int64 - OK bool - }{ - Precision: 0, - Scale: 0, - OK: false, - }, - ScanType: reflect.TypeOf(int32(0)), - }, { - Name: "bar", - TypeName: "TEXT", - Length: struct { - Len int64 - OK bool - }{ - Len: math.MaxInt64, - OK: true, - }, - DecimalSize: struct { - Precision int64 - Scale int64 - OK bool - }{ - Precision: 0, - Scale: 0, - OK: false, - }, - ScanType: reflect.TypeOf(""), - }, - } - - db := openTestConn(t) - defer db.Close() - - rows, err := db.Query("SELECT 1 AS a, text 'bar' AS bar, 1.28::numeric(9, 2) AS dec") - if err != nil { - t.Fatal(err) - } - - columns, err := rows.ColumnTypes() - if err != nil { - t.Fatal(err) - } - if len(columns) != 3 { - t.Errorf("expected 3 columns found %d", len(columns)) - } - - for i, tt := range columnTypesTests { - c := columns[i] - if c.Name() != tt.Name { - t.Errorf("(%d) got: %s, want: %s", i, c.Name(), tt.Name) - } - if c.DatabaseTypeName() != tt.TypeName { - t.Errorf("(%d) got: %s, want: %s", i, c.DatabaseTypeName(), tt.TypeName) - } - l, ok := c.Length() - if l != tt.Length.Len { - t.Errorf("(%d) got: %d, want: %d", i, l, tt.Length.Len) - } - if ok != tt.Length.OK { - t.Errorf("(%d) got: %t, want: %t", i, ok, tt.Length.OK) - } - p, s, ok := c.DecimalSize() - if p != tt.DecimalSize.Precision { - t.Errorf("(%d) got: %d, want: %d", i, p, tt.DecimalSize.Precision) - } - if s != tt.DecimalSize.Scale { - t.Errorf("(%d) got: %d, want: %d", i, s, tt.DecimalSize.Scale) - } - if ok != tt.DecimalSize.OK { - t.Errorf("(%d) got: %t, want: %t", i, ok, tt.DecimalSize.OK) - } - if c.ScanType() != tt.ScanType { - t.Errorf("(%d) got: %v, want: %v", i, c.ScanType(), tt.ScanType) - } - } -} diff --git a/vendor/github.com/lib/pq/ssl_test.go b/vendor/github.com/lib/pq/ssl_test.go deleted file mode 100644 index 3eafbfd2..00000000 --- a/vendor/github.com/lib/pq/ssl_test.go +++ /dev/null @@ -1,279 +0,0 @@ -package pq - -// This file contains SSL tests - -import ( - _ "crypto/sha256" - "crypto/x509" - "database/sql" - "os" - "path/filepath" - "testing" -) - -func maybeSkipSSLTests(t *testing.T) { - // Require some special variables for testing certificates - if os.Getenv("PQSSLCERTTEST_PATH") == "" { - t.Skip("PQSSLCERTTEST_PATH not set, skipping SSL tests") - } - - value := os.Getenv("PQGOSSLTESTS") - if value == "" || value == "0" { - t.Skip("PQGOSSLTESTS not enabled, skipping SSL tests") - } else if value != "1" { - t.Fatalf("unexpected value %q for PQGOSSLTESTS", value) - } -} - -func openSSLConn(t *testing.T, conninfo string) (*sql.DB, error) { - db, err := openTestConnConninfo(conninfo) - if err != nil { - // should never fail - t.Fatal(err) - } - // Do something with the connection to see whether it's working or not. - tx, err := db.Begin() - if err == nil { - return db, tx.Rollback() - } - _ = db.Close() - return nil, err -} - -func checkSSLSetup(t *testing.T, conninfo string) { - _, err := openSSLConn(t, conninfo) - if pge, ok := err.(*Error); ok { - if pge.Code.Name() != "invalid_authorization_specification" { - t.Fatalf("unexpected error code '%s'", pge.Code.Name()) - } - } else { - t.Fatalf("expected %T, got %v", (*Error)(nil), err) - } -} - -// Connect over SSL and run a simple query to test the basics -func TestSSLConnection(t *testing.T) { - maybeSkipSSLTests(t) - // Environment sanity check: should fail without SSL - checkSSLSetup(t, "sslmode=disable user=pqgossltest") - - db, err := openSSLConn(t, "sslmode=require user=pqgossltest") - if err != nil { - t.Fatal(err) - } - rows, err := db.Query("SELECT 1") - if err != nil { - t.Fatal(err) - } - rows.Close() -} - -// Test sslmode=verify-full -func TestSSLVerifyFull(t *testing.T) { - maybeSkipSSLTests(t) - // Environment sanity check: should fail without SSL - checkSSLSetup(t, "sslmode=disable user=pqgossltest") - - // Not OK according to the system CA - _, err := openSSLConn(t, "host=postgres sslmode=verify-full user=pqgossltest") - if err == nil { - t.Fatal("expected error") - } - _, ok := err.(x509.UnknownAuthorityError) - if !ok { - t.Fatalf("expected x509.UnknownAuthorityError, got %#+v", err) - } - - rootCertPath := filepath.Join(os.Getenv("PQSSLCERTTEST_PATH"), "root.crt") - rootCert := "sslrootcert=" + rootCertPath + " " - // No match on Common Name - _, err = openSSLConn(t, rootCert+"host=127.0.0.1 sslmode=verify-full user=pqgossltest") - if err == nil { - t.Fatal("expected error") - } - _, ok = err.(x509.HostnameError) - if !ok { - t.Fatalf("expected x509.HostnameError, got %#+v", err) - } - // OK - _, err = openSSLConn(t, rootCert+"host=postgres sslmode=verify-full user=pqgossltest") - if err != nil { - t.Fatal(err) - } -} - -// Test sslmode=require sslrootcert=rootCertPath -func TestSSLRequireWithRootCert(t *testing.T) { - maybeSkipSSLTests(t) - // Environment sanity check: should fail without SSL - checkSSLSetup(t, "sslmode=disable user=pqgossltest") - - bogusRootCertPath := filepath.Join(os.Getenv("PQSSLCERTTEST_PATH"), "bogus_root.crt") - bogusRootCert := "sslrootcert=" + bogusRootCertPath + " " - - // Not OK according to the bogus CA - _, err := openSSLConn(t, bogusRootCert+"host=postgres sslmode=require user=pqgossltest") - if err == nil { - t.Fatal("expected error") - } - _, ok := err.(x509.UnknownAuthorityError) - if !ok { - t.Fatalf("expected x509.UnknownAuthorityError, got %s, %#+v", err, err) - } - - nonExistentCertPath := filepath.Join(os.Getenv("PQSSLCERTTEST_PATH"), "non_existent.crt") - nonExistentCert := "sslrootcert=" + nonExistentCertPath + " " - - // No match on Common Name, but that's OK because we're not validating anything. - _, err = openSSLConn(t, nonExistentCert+"host=127.0.0.1 sslmode=require user=pqgossltest") - if err != nil { - t.Fatal(err) - } - - rootCertPath := filepath.Join(os.Getenv("PQSSLCERTTEST_PATH"), "root.crt") - rootCert := "sslrootcert=" + rootCertPath + " " - - // No match on Common Name, but that's OK because we're not validating the CN. - _, err = openSSLConn(t, rootCert+"host=127.0.0.1 sslmode=require user=pqgossltest") - if err != nil { - t.Fatal(err) - } - // Everything OK - _, err = openSSLConn(t, rootCert+"host=postgres sslmode=require user=pqgossltest") - if err != nil { - t.Fatal(err) - } -} - -// Test sslmode=verify-ca -func TestSSLVerifyCA(t *testing.T) { - maybeSkipSSLTests(t) - // Environment sanity check: should fail without SSL - checkSSLSetup(t, "sslmode=disable user=pqgossltest") - - // Not OK according to the system CA - { - _, err := openSSLConn(t, "host=postgres sslmode=verify-ca user=pqgossltest") - if _, ok := err.(x509.UnknownAuthorityError); !ok { - t.Fatalf("expected %T, got %#+v", x509.UnknownAuthorityError{}, err) - } - } - - // Still not OK according to the system CA; empty sslrootcert is treated as unspecified. - { - _, err := openSSLConn(t, "host=postgres sslmode=verify-ca user=pqgossltest sslrootcert=''") - if _, ok := err.(x509.UnknownAuthorityError); !ok { - t.Fatalf("expected %T, got %#+v", x509.UnknownAuthorityError{}, err) - } - } - - rootCertPath := filepath.Join(os.Getenv("PQSSLCERTTEST_PATH"), "root.crt") - rootCert := "sslrootcert=" + rootCertPath + " " - // No match on Common Name, but that's OK - if _, err := openSSLConn(t, rootCert+"host=127.0.0.1 sslmode=verify-ca user=pqgossltest"); err != nil { - t.Fatal(err) - } - // Everything OK - if _, err := openSSLConn(t, rootCert+"host=postgres sslmode=verify-ca user=pqgossltest"); err != nil { - t.Fatal(err) - } -} - -// Authenticate over SSL using client certificates -func TestSSLClientCertificates(t *testing.T) { - maybeSkipSSLTests(t) - // Environment sanity check: should fail without SSL - checkSSLSetup(t, "sslmode=disable user=pqgossltest") - - const baseinfo = "sslmode=require user=pqgosslcert" - - // Certificate not specified, should fail - { - _, err := openSSLConn(t, baseinfo) - if pge, ok := err.(*Error); ok { - if pge.Code.Name() != "invalid_authorization_specification" { - t.Fatalf("unexpected error code '%s'", pge.Code.Name()) - } - } else { - t.Fatalf("expected %T, got %v", (*Error)(nil), err) - } - } - - // Empty certificate specified, should fail - { - _, err := openSSLConn(t, baseinfo+" sslcert=''") - if pge, ok := err.(*Error); ok { - if pge.Code.Name() != "invalid_authorization_specification" { - t.Fatalf("unexpected error code '%s'", pge.Code.Name()) - } - } else { - t.Fatalf("expected %T, got %v", (*Error)(nil), err) - } - } - - // Non-existent certificate specified, should fail - { - _, err := openSSLConn(t, baseinfo+" sslcert=/tmp/filedoesnotexist") - if pge, ok := err.(*Error); ok { - if pge.Code.Name() != "invalid_authorization_specification" { - t.Fatalf("unexpected error code '%s'", pge.Code.Name()) - } - } else { - t.Fatalf("expected %T, got %v", (*Error)(nil), err) - } - } - - certpath, ok := os.LookupEnv("PQSSLCERTTEST_PATH") - if !ok { - t.Fatalf("PQSSLCERTTEST_PATH not present in environment") - } - - sslcert := filepath.Join(certpath, "postgresql.crt") - - // Cert present, key not specified, should fail - { - _, err := openSSLConn(t, baseinfo+" sslcert="+sslcert) - if _, ok := err.(*os.PathError); !ok { - t.Fatalf("expected %T, got %#+v", (*os.PathError)(nil), err) - } - } - - // Cert present, empty key specified, should fail - { - _, err := openSSLConn(t, baseinfo+" sslcert="+sslcert+" sslkey=''") - if _, ok := err.(*os.PathError); !ok { - t.Fatalf("expected %T, got %#+v", (*os.PathError)(nil), err) - } - } - - // Cert present, non-existent key, should fail - { - _, err := openSSLConn(t, baseinfo+" sslcert="+sslcert+" sslkey=/tmp/filedoesnotexist") - if _, ok := err.(*os.PathError); !ok { - t.Fatalf("expected %T, got %#+v", (*os.PathError)(nil), err) - } - } - - // Key has wrong permissions (passing the cert as the key), should fail - if _, err := openSSLConn(t, baseinfo+" sslcert="+sslcert+" sslkey="+sslcert); err != ErrSSLKeyHasWorldPermissions { - t.Fatalf("expected %s, got %#+v", ErrSSLKeyHasWorldPermissions, err) - } - - sslkey := filepath.Join(certpath, "postgresql.key") - - // Should work - if db, err := openSSLConn(t, baseinfo+" sslcert="+sslcert+" sslkey="+sslkey); err != nil { - t.Fatal(err) - } else { - rows, err := db.Query("SELECT 1") - if err != nil { - t.Fatal(err) - } - if err := rows.Close(); err != nil { - t.Fatal(err) - } - if err := db.Close(); err != nil { - t.Fatal(err) - } - } -} diff --git a/vendor/github.com/lib/pq/url_test.go b/vendor/github.com/lib/pq/url_test.go deleted file mode 100644 index 4ff0ce03..00000000 --- a/vendor/github.com/lib/pq/url_test.go +++ /dev/null @@ -1,66 +0,0 @@ -package pq - -import ( - "testing" -) - -func TestSimpleParseURL(t *testing.T) { - expected := "host=hostname.remote" - str, err := ParseURL("postgres://hostname.remote") - if err != nil { - t.Fatal(err) - } - - if str != expected { - t.Fatalf("unexpected result from ParseURL:\n+ %v\n- %v", str, expected) - } -} - -func TestIPv6LoopbackParseURL(t *testing.T) { - expected := "host=::1 port=1234" - str, err := ParseURL("postgres://[::1]:1234") - if err != nil { - t.Fatal(err) - } - - if str != expected { - t.Fatalf("unexpected result from ParseURL:\n+ %v\n- %v", str, expected) - } -} - -func TestFullParseURL(t *testing.T) { - expected := `dbname=database host=hostname.remote password=top\ secret port=1234 user=username` - str, err := ParseURL("postgres://username:top%20secret@hostname.remote:1234/database") - if err != nil { - t.Fatal(err) - } - - if str != expected { - t.Fatalf("unexpected result from ParseURL:\n+ %s\n- %s", str, expected) - } -} - -func TestInvalidProtocolParseURL(t *testing.T) { - _, err := ParseURL("http://hostname.remote") - switch err { - case nil: - t.Fatal("Expected an error from parsing invalid protocol") - default: - msg := "invalid connection protocol: http" - if err.Error() != msg { - t.Fatalf("Unexpected error message:\n+ %s\n- %s", - err.Error(), msg) - } - } -} - -func TestMinimalURL(t *testing.T) { - cs, err := ParseURL("postgres://") - if err != nil { - t.Fatal(err) - } - - if cs != "" { - t.Fatalf("expected blank connection string, got: %q", cs) - } -} diff --git a/vendor/github.com/lib/pq/uuid_test.go b/vendor/github.com/lib/pq/uuid_test.go deleted file mode 100644 index 8ecee2fd..00000000 --- a/vendor/github.com/lib/pq/uuid_test.go +++ /dev/null @@ -1,46 +0,0 @@ -package pq - -import ( - "reflect" - "strings" - "testing" -) - -func TestDecodeUUIDBinaryError(t *testing.T) { - t.Parallel() - _, err := decodeUUIDBinary([]byte{0x12, 0x34}) - - if err == nil { - t.Fatal("Expected error, got none") - } - if !strings.HasPrefix(err.Error(), "pq:") { - t.Errorf("Expected error to start with %q, got %q", "pq:", err.Error()) - } - if !strings.Contains(err.Error(), "bad length: 2") { - t.Errorf("Expected error to contain length, got %q", err.Error()) - } -} - -func BenchmarkDecodeUUIDBinary(b *testing.B) { - x := []byte{0x03, 0xa3, 0x52, 0x2f, 0x89, 0x28, 0x49, 0x87, 0x84, 0xd6, 0x93, 0x7b, 0x36, 0xec, 0x27, 0x6f} - - for i := 0; i < b.N; i++ { - decodeUUIDBinary(x) - } -} - -func TestDecodeUUIDBackend(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - var s = "a0ecc91d-a13f-4fe4-9fce-7e09777cc70a" - var scanned interface{} - - err := db.QueryRow(`SELECT $1::uuid`, s).Scan(&scanned) - if err != nil { - t.Fatalf("Expected no error, got %v", err) - } - if !reflect.DeepEqual(scanned, []byte(s)) { - t.Errorf("Expected []byte(%q), got %T(%q)", s, scanned, scanned) - } -} diff --git a/vendor/github.com/mattn/go-sqlite3/README.md b/vendor/github.com/mattn/go-sqlite3/README.md deleted file mode 100644 index 207f1cd1..00000000 --- a/vendor/github.com/mattn/go-sqlite3/README.md +++ /dev/null @@ -1,519 +0,0 @@ -go-sqlite3 -========== - -[![GoDoc Reference](https://godoc.org/github.com/mattn/go-sqlite3?status.svg)](http://godoc.org/github.com/mattn/go-sqlite3) -[![Build Status](https://travis-ci.org/mattn/go-sqlite3.svg?branch=master)](https://travis-ci.org/mattn/go-sqlite3) -[![Coverage Status](https://coveralls.io/repos/mattn/go-sqlite3/badge.svg?branch=master)](https://coveralls.io/r/mattn/go-sqlite3?branch=master) -[![Go Report Card](https://goreportcard.com/badge/github.com/mattn/go-sqlite3)](https://goreportcard.com/report/github.com/mattn/go-sqlite3) - -# Description - -sqlite3 driver conforming to the built-in database/sql interface - -Supported Golang version: -- 1.9.x -- 1.10.x - -[This package follows the official Golang Release Policy.](https://golang.org/doc/devel/release.html#policy) - -### Overview - -- [Installation](#installation) -- [API Reference](#api-reference) -- [Connection String](#connection-string) -- [Features](#features) -- [Compilation](#compilation) - - [Android](#android) - - [ARM](#arm) - - [Cross Compile](#cross-compile) - - [Google Cloud Platform](#google-cloud-platform) - - [Linux](#linux) - - [Alpine](#alpine) - - [Fedora](#fedora) - - [Ubuntu](#ubuntu) - - [Mac OSX](#mac-osx) - - [Windows](#windows) - - [Errors](#errors) -- [User Authentication](#user-authentication) - - [Compile](#compile) - - [Usage](#usage) -- [Extensions](#extensions) - - [Spatialite](#spatialite) -- [FAQ](#faq) -- [License](#license) - -# Installation - -This package can be installed with the go get command: - - go get github.com/mattn/go-sqlite3 - -_go-sqlite3_ is *cgo* package. -If you want to build your app using go-sqlite3, you need gcc. -However, after you have built and installed _go-sqlite3_ with `go install github.com/mattn/go-sqlite3` (which requires gcc), you can build your app without relying on gcc in future. - -***Important: because this is a `CGO` enabled package you are required to set the environment variable `CGO_ENABLED=1` and have a `gcc` compile present within your path.*** - -# API Reference - -API documentation can be found here: http://godoc.org/github.com/mattn/go-sqlite3 - -Examples can be found under the [examples](./_example) directory - -# Connection String - -When creating a new SQLite database or connection to an existing one, with the file name additional options can be given. -This is also known as a DSN string. (Data Source Name). - -Options are append after the filename of the SQLite database. -The database filename and options are seperated by an `?` (Question Mark). -Options should be URL-encoded (see [url.QueryEscape](https://golang.org/pkg/net/url/#QueryEscape)). - -This also applies when using an in-memory database instead of a file. - -Options can be given using the following format: `KEYWORD=VALUE` and multiple options can be combined with the `&` ampersand. - -This library supports dsn options of SQLite itself and provides additional options. - -Boolean values can be one of: -* `0` `no` `false` `off` -* `1` `yes` `true` `on` - -| Name | Key | Value(s) | Description | -|------|-----|----------|-------------| -| UA - Create | `_auth` | - | Create User Authentication, for more information see [User Authentication](#user-authentication) | -| UA - Username | `_auth_user` | `string` | Username for User Authentication, for more information see [User Authentication](#user-authentication) | -| UA - Password | `_auth_pass` | `string` | Password for User Authentication, for more information see [User Authentication](#user-authentication) | -| UA - Crypt | `_auth_crypt` |
  • SHA1
  • SSHA1
  • SHA256
  • SSHA256
  • SHA384
  • SSHA384
  • SHA512
  • SSHA512
| Password encoder to use for User Authentication, for more information see [User Authentication](#user-authentication) | -| UA - Salt | `_auth_salt` | `string` | Salt to use if the configure password encoder requires a salt, for User Authentication, for more information see [User Authentication](#user-authentication) | -| Auto Vacuum | `_auto_vacuum` \| `_vacuum` |
  • `0` \| `none`
  • `1` \| `full`
  • `2` \| `incremental`
| For more information see [PRAGMA auto_vacuum](https://www.sqlite.org/pragma.html#pragma_auto_vacuum) | -| Busy Timeout | `_busy_timeout` \| `_timeout` | `int` | Specify value for sqlite3_busy_timeout. For more information see [PRAGMA busy_timeout](https://www.sqlite.org/pragma.html#pragma_busy_timeout) | -| Case Sensitive LIKE | `_case_sensitive_like` \| `_cslike` | `boolean` | For more information see [PRAGMA case_sensitive_like](https://www.sqlite.org/pragma.html#pragma_case_sensitive_like) | -| Defer Foreign Keys | `_defer_foreign_keys` \| `_defer_fk` | `boolean` | For more information see [PRAGMA defer_foreign_keys](https://www.sqlite.org/pragma.html#pragma_defer_foreign_keys) | -| Foreign Keys | `_foreign_keys` \| `_fk` | `boolean` | For more information see [PRAGMA foreign_keys](https://www.sqlite.org/pragma.html#pragma_foreign_keys) | -| Ignore CHECK Constraints | `_ignore_check_constraints` | `boolean` | For more information see [PRAGMA ignore_check_constraints](https://www.sqlite.org/pragma.html#pragma_ignore_check_constraints) | -| Immutable | `immutable` | `boolean` | For more information see [Immutable](https://www.sqlite.org/c3ref/open.html) | -| Journal Mode | `_journal_mode` \| `_journal` |
  • DELETE
  • TRUNCATE
  • PERSIST
  • MEMORY
  • WAL
  • OFF
| For more information see [PRAGMA journal_mode](https://www.sqlite.org/pragma.html#pragma_journal_mode) | -| Locking Mode | `_locking_mode` \| `_locking` |
  • NORMAL
  • EXCLUSIVE
| For more information see [PRAGMA locking_mode](https://www.sqlite.org/pragma.html#pragma_locking_mode) | -| Mode | `mode` |
  • ro
  • rw
  • rwc
  • memory
| Access Mode of the database. For more information see [SQLite Open](https://www.sqlite.org/c3ref/open.html) | -| Mutex Locking | `_mutex` |
  • no
  • full
| Specify mutex mode. | -| Query Only | `_query_only` | `boolean` | For more information see [PRAGMA query_only](https://www.sqlite.org/pragma.html#pragma_query_only) | -| Recursive Triggers | `_recursive_triggers` \| `_rt` | `boolean` | For more information see [PRAGMA recursive_triggers](https://www.sqlite.org/pragma.html#pragma_recursive_triggers) | -| Secure Delete | `_secure_delete` | `boolean` \| `FAST` | For more information see [PRAGMA secure_delete](https://www.sqlite.org/pragma.html#pragma_secure_delete) | -| Shared-Cache Mode | `cache` |
  • shared
  • private
| Set cache mode for more information see [sqlite.org](https://www.sqlite.org/sharedcache.html) | -| Synchronous | `_synchronous` \| `_sync` |
  • 0 \| OFF
  • 1 \| NORMAL
  • 2 \| FULL
  • 3 \| EXTRA
| For more information see [PRAGMA synchronous](https://www.sqlite.org/pragma.html#pragma_synchronous) | -| Time Zone Location | `_loc` | auto | Specify location of time format. | -| Transaction Lock | `_txlock` |
  • immediate
  • deferred
  • exclusive
| Specify locking behavior for transactions. | -| Writable Schema | `_writable_schema` | `Boolean` | When this pragma is on, the SQLITE_MASTER tables in which database can be changed using ordinary UPDATE, INSERT, and DELETE statements. Warning: misuse of this pragma can easily result in a corrupt database file. | - -## DSN Examples - -``` -file:test.db?cache=shared&mode=memory -``` - -# Features - -This package allows additional configuration of features available within SQLite3 to be enabled or disabled by golang build constraints also known as build `tags`. - -[Click here for more information about build tags / constraints.](https://golang.org/pkg/go/build/#hdr-Build_Constraints) - -### Usage - -If you wish to build this library with additional extensions / features. -Use the following command. - -```bash -go build --tags "" -``` - -For available features see the extension list. -When using multiple build tags, all the different tags should be space delimted. - -Example: - -```bash -go build --tags "icu json1 fts5 secure_delete" -``` - -### Feature / Extension List - -| Extension | Build Tag | Description | -|-----------|-----------|-------------| -| Additional Statistics | sqlite_stat4 | This option adds additional logic to the ANALYZE command and to the query planner that can help SQLite to chose a better query plan under certain situations. The ANALYZE command is enhanced to collect histogram data from all columns of every index and store that data in the sqlite_stat4 table.

The query planner will then use the histogram data to help it make better index choices. The downside of this compile-time option is that it violates the query planner stability guarantee making it more difficult to ensure consistent performance in mass-produced applications.

SQLITE_ENABLE_STAT4 is an enhancement of SQLITE_ENABLE_STAT3. STAT3 only recorded histogram data for the left-most column of each index whereas the STAT4 enhancement records histogram data from all columns of each index.

The SQLITE_ENABLE_STAT3 compile-time option is a no-op and is ignored if the SQLITE_ENABLE_STAT4 compile-time option is used | -| Allow URI Authority | sqlite_allow_uri_authority | URI filenames normally throws an error if the authority section is not either empty or "localhost".

However, if SQLite is compiled with the SQLITE_ALLOW_URI_AUTHORITY compile-time option, then the URI is converted into a Uniform Naming Convention (UNC) filename and passed down to the underlying operating system that way | -| App Armor | sqlite_app_armor | When defined, this C-preprocessor macro activates extra code that attempts to detect misuse of the SQLite API, such as passing in NULL pointers to required parameters or using objects after they have been destroyed.

App Armor is not available under `Windows`. | -| Disable Load Extensions | sqlite_omit_load_extension | Loading of external extensions is enabled by default.

To disable extension loading add the build tag `sqlite_omit_load_extension`. | -| Foreign Keys | sqlite_foreign_keys | This macro determines whether enforcement of foreign key constraints is enabled or disabled by default for new database connections.

Each database connection can always turn enforcement of foreign key constraints on and off and run-time using the foreign_keys pragma.

Enforcement of foreign key constraints is normally off by default, but if this compile-time parameter is set to 1, enforcement of foreign key constraints will be on by default | -| Full Auto Vacuum | sqlite_vacuum_full | Set the default auto vacuum to full | -| Incremental Auto Vacuum | sqlite_vacuum_incr | Set the default auto vacuum to incremental | -| Full Text Search Engine | sqlite_fts5 | When this option is defined in the amalgamation, versions 5 of the full-text search engine (fts5) is added to the build automatically | -| International Components for Unicode | sqlite_icu | This option causes the International Components for Unicode or "ICU" extension to SQLite to be added to the build | -| Introspect PRAGMAS | sqlite_introspect | This option adds some extra PRAGMA statements.
  • PRAGMA function_list
  • PRAGMA module_list
  • PRAGMA pragma_list
| -| JSON SQL Functions | sqlite_json | When this option is defined in the amalgamation, the JSON SQL functions are added to the build automatically | -| Secure Delete | sqlite_secure_delete | This compile-time option changes the default setting of the secure_delete pragma.

When this option is not used, secure_delete defaults to off. When this option is present, secure_delete defaults to on.

The secure_delete setting causes deleted content to be overwritten with zeros. There is a small performance penalty since additional I/O must occur.

On the other hand, secure_delete can prevent fragments of sensitive information from lingering in unused parts of the database file after it has been deleted. See the documentation on the secure_delete pragma for additional information | -| Secure Delete (FAST) | sqlite_secure_delete_fast | For more information see [PRAGMA secure_delete](https://www.sqlite.org/pragma.html#pragma_secure_delete) | -| Tracing / Debug | sqlite_trace | Activate trace functions | -| User Authentication | sqlite_userauth | SQLite User Authentication see [User Authentication](#user-authentication) for more information. | - -# Compilation - -This package requires `CGO_ENABLED=1` ennvironment variable if not set by default, and the presence of the `gcc` compiler. - -If you need to add additional CFLAGS or LDFLAGS to the build command, and do not want to modify this package. Then this can be achieved by using the `CGO_CFLAGS` and `CGO_LDFLAGS` environment variables. - -## Android - -This package can be compiled for android. -Compile with: - -```bash -go build --tags "android" -``` - -For more information see [#201](https://github.com/mattn/go-sqlite3/issues/201) - -# ARM - -To compile for `ARM` use the following environment. - -```bash -env CC=arm-linux-gnueabihf-gcc CXX=arm-linux-gnueabihf-g++ \ - CGO_ENABLED=1 GOOS=linux GOARCH=arm GOARM=7 \ - go build -v -``` - -Additional information: -- [#242](https://github.com/mattn/go-sqlite3/issues/242) -- [#504](https://github.com/mattn/go-sqlite3/issues/504) - -# Cross Compile - -This library can be cross-compiled. - -In some cases you are required to the `CC` environment variable with the cross compiler. - -Additional information: -- [#491](https://github.com/mattn/go-sqlite3/issues/491) -- [#560](https://github.com/mattn/go-sqlite3/issues/560) - -# Google Cloud Platform - -Building on GCP is not possible because Google Cloud Platform does not allow `gcc` to be executed. - -Please work only with compiled final binaries. - -## Linux - -To compile this package on Linux you must install the development tools for your linux distribution. - -To compile under linux use the build tag `linux`. - -```bash -go build --tags "linux" -``` - -If you wish to link directly to libsqlite3 then you can use the `libsqlite3` build tag. - -``` -go build --tags "libsqlite3 linux" -``` - -### Alpine - -When building in an `alpine` container run the following command before building. - -``` -apk add --update gcc musl-dev -``` - -### Fedora - -```bash -sudo yum groupinstall "Development Tools" "Development Libraries" -``` - -### Ubuntu - -```bash -sudo apt-get install build-essential -``` - -## Mac OSX - -OSX should have all the tools present to compile this package, if not install XCode this will add all the developers tools. - -Required dependency - -```bash -brew install sqlite3 -``` - -For OSX there is an additional package install which is required if you whish to build the `icu` extension. - -This additional package can be installed with `homebrew`. - -```bash -brew upgrade icu4c -``` - -To compile for Mac OSX. - -```bash -go build --tags "darwin" -``` - -If you wish to link directly to libsqlite3 then you can use the `libsqlite3` build tag. - -``` -go build --tags "libsqlite3 darwin" -``` - -Additional information: -- [#206](https://github.com/mattn/go-sqlite3/issues/206) -- [#404](https://github.com/mattn/go-sqlite3/issues/404) - -## Windows - -To compile this package on Windows OS you must have the `gcc` compiler installed. - -1) Install a Windows `gcc` toolchain. -2) Add the `bin` folders to the Windows path if the installer did not do this by default. -3) Open a terminal for the TDM-GCC toolchain, can be found in the Windows Start menu. -4) Navigate to your project folder and run the `go build ...` command for this package. - -For example the TDM-GCC Toolchain can be found [here](ttps://sourceforge.net/projects/tdm-gcc/). - -## Errors - -- Compile error: `can not be used when making a shared object; recompile with -fPIC` - - When receiving a compile time error referencing recompile with `-FPIC` then you - are probably using a hardend system. - - You can compile the library on a hardend system with the following command. - - ```bash - go build -ldflags '-extldflags=-fno-PIC' - ``` - - More details see [#120](https://github.com/mattn/go-sqlite3/issues/120) - -- Can't build go-sqlite3 on windows 64bit. - - > Probably, you are using go 1.0, go1.0 has a problem when it comes to compiling/linking on windows 64bit. - > See: [#27](https://github.com/mattn/go-sqlite3/issues/27) - -- `go get github.com/mattn/go-sqlite3` throws compilation error. - - `gcc` throws: `internal compiler error` - - Remove the download repository from your disk and try re-install with: - - ```bash - go install github.com/mattn/go-sqlite3 - ``` - -# User Authentication - -This package supports the SQLite User Authentication module. - -## Compile - -To use the User authentication module the package has to be compiled with the tag `sqlite_userauth`. See [Features](#features). - -## Usage - -### Create protected database - -To create a database protected by user authentication provide the following argument to the connection string `_auth`. -This will enable user authentication within the database. This option however requires two additional arguments: - -- `_auth_user` -- `_auth_pass` - -When `_auth` is present on the connection string user authentication will be enabled and the provided user will be created -as an `admin` user. After initial creation, the parameter `_auth` has no effect anymore and can be omitted from the connection string. - -Example connection string: - -Create an user authentication database with user `admin` and password `admin`. - -`file:test.s3db?_auth&_auth_user=admin&_auth_pass=admin` - -Create an user authentication database with user `admin` and password `admin` and use `SHA1` for the password encoding. - -`file:test.s3db?_auth&_auth_user=admin&_auth_pass=admin&_auth_crypt=sha1` - -### Password Encoding - -The passwords within the user authentication module of SQLite are encoded with the SQLite function `sqlite_cryp`. -This function uses a ceasar-cypher which is quite insecure. -This library provides several additional password encoders which can be configured through the connection string. - -The password cypher can be configured with the key `_auth_crypt`. And if the configured password encoder also requires an -salt this can be configured with `_auth_salt`. - -#### Available Encoders - -- SHA1 -- SSHA1 (Salted SHA1) -- SHA256 -- SSHA256 (salted SHA256) -- SHA384 -- SSHA384 (salted SHA384) -- SHA512 -- SSHA512 (salted SHA512) - -### Restrictions - -Operations on the database regarding to user management can only be preformed by an administrator user. - -### Support - -The user authentication supports two kinds of users - -- administrators -- regular users - -### User Management - -User management can be done by directly using the `*SQLiteConn` or by SQL. - -#### SQL - -The following sql functions are available for user management. - -| Function | Arguments | Description | -|----------|-----------|-------------| -| `authenticate` | username `string`, password `string` | Will authenticate an user, this is done by the connection; and should not be used manually. | -| `auth_user_add` | username `string`, password `string`, admin `int` | This function will add an user to the database.
if the database is not protected by user authentication it will enable it. Argument `admin` is an integer identifying if the added user should be an administrator. Only Administrators can add administrators. | -| `auth_user_change` | username `string`, password `string`, admin `int` | Function to modify an user. Users can change their own password, but only an administrator can change the administrator flag. | -| `authUserDelete` | username `string` | Delete an user from the database. Can only be used by an administrator. The current logged in administrator cannot be deleted. This is to make sure their is always an administrator remaining. | - -These functions will return an integer. - -- 0 (SQLITE_OK) -- 23 (SQLITE_AUTH) Failed to perform due to authentication or insufficient privileges - -##### Examples - -```sql -// Autheticate user -// Create Admin User -SELECT auth_user_add('admin2', 'admin2', 1); - -// Change password for user -SELECT auth_user_change('user', 'userpassword', 0); - -// Delete user -SELECT user_delete('user'); -``` - -#### *SQLiteConn - -The following functions are available for User authentication from the `*SQLiteConn`. - -| Function | Description | -|----------|-------------| -| `Authenticate(username, password string) error` | Authenticate user | -| `AuthUserAdd(username, password string, admin bool) error` | Add user | -| `AuthUserChange(username, password string, admin bool) error` | Modify user | -| `AuthUserDelete(username string) error` | Delete user | - -### Attached database - -When using attached databases. SQLite will use the authentication from the `main` database for the attached database(s). - -# Extensions - -If you want your own extension to be listed here or you want to add a reference to an extension; please submit an Issue for this. - -## Spatialite - -Spatialite is available as an extension to SQLite, and can be used in combination with this repository. -For an example see [shaxbee/go-spatialite](https://github.com/shaxbee/go-spatialite). - -# FAQ - -- Getting insert error while query is opened. - - > You can pass some arguments into the connection string, for example, a URI. - > See: [#39](https://github.com/mattn/go-sqlite3/issues/39) - -- Do you want to cross compile? mingw on Linux or Mac? - - > See: [#106](https://github.com/mattn/go-sqlite3/issues/106) - > See also: http://www.limitlessfx.com/cross-compile-golang-app-for-windows-from-linux.html - -- Want to get time.Time with current locale - - Use `_loc=auto` in SQLite3 filename schema like `file:foo.db?_loc=auto`. - -- Can I use this in multiple routines concurrently? - - Yes for readonly. But, No for writable. See [#50](https://github.com/mattn/go-sqlite3/issues/50), [#51](https://github.com/mattn/go-sqlite3/issues/51), [#209](https://github.com/mattn/go-sqlite3/issues/209), [#274](https://github.com/mattn/go-sqlite3/issues/274). - -- Why I'm getting `no such table` error? - - Why is it racy if I use a `sql.Open("sqlite3", ":memory:")` database? - - Each connection to :memory: opens a brand new in-memory sql database, so if - the stdlib's sql engine happens to open another connection and you've only - specified ":memory:", that connection will see a brand new database. A - workaround is to use "file::memory:?mode=memory&cache=shared". Every - connection to this string will point to the same in-memory database. - - For more information see - * [#204](https://github.com/mattn/go-sqlite3/issues/204) - * [#511](https://github.com/mattn/go-sqlite3/issues/511) - -- Reading from database with large amount of goroutines fails on OSX. - - OS X limits OS-wide to not have more than 1000 files open simultaneously by default. - - For more information see [#289](https://github.com/mattn/go-sqlite3/issues/289) - -- Trying to execute a `.` (dot) command throws an error. - - Error: `Error: near ".": syntax error` - Dot command are part of SQLite3 CLI not of this library. - - You need to implement the feature or call the sqlite3 cli. - - More infomation see [#305](https://github.com/mattn/go-sqlite3/issues/305) - -- Error: `database is locked` - - When you get an database is locked. Please use the following options. - - Add to DSN: `cache=shared` - - Example: - ```go - db, err := sql.Open("sqlite3", "file:locked.sqlite?cache=shared") - ``` - - Second please set the database connections of the SQL package to 1. - - ```go - db.SetMaxOpenConn(1) - ``` - - More information see [#209](https://github.com/mattn/go-sqlite3/issues/209) - -# License - -MIT: http://mattn.mit-license.org/2018 - -sqlite3-binding.c, sqlite3-binding.h, sqlite3ext.h - -The -binding suffix was added to avoid build failures under gccgo. - -In this repository, those files are an amalgamation of code that was copied from SQLite3. The license of that code is the same as the license of SQLite3. - -# Author - -Yasuhiro Matsumoto (a.k.a mattn) - -G.J.R. Timmer diff --git a/vendor/github.com/mattn/go-sqlite3/backup_test.go b/vendor/github.com/mattn/go-sqlite3/backup_test.go deleted file mode 100644 index 73c0a4b5..00000000 --- a/vendor/github.com/mattn/go-sqlite3/backup_test.go +++ /dev/null @@ -1,290 +0,0 @@ -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package sqlite3 - -import ( - "database/sql" - "fmt" - "os" - "testing" - "time" -) - -// The number of rows of test data to create in the source database. -// Can be used to control how many pages are available to be backed up. -const testRowCount = 100 - -// The maximum number of seconds after which the page-by-page backup is considered to have taken too long. -const usePagePerStepsTimeoutSeconds = 30 - -// Test the backup functionality. -func testBackup(t *testing.T, testRowCount int, usePerPageSteps bool) { - // This function will be called multiple times. - // It uses sql.Register(), which requires the name parameter value to be unique. - // There does not currently appear to be a way to unregister a registered driver, however. - // So generate a database driver name that will likely be unique. - var driverName = fmt.Sprintf("sqlite3_testBackup_%v_%v_%v", testRowCount, usePerPageSteps, time.Now().UnixNano()) - - // The driver's connection will be needed in order to perform the backup. - driverConns := []*SQLiteConn{} - sql.Register(driverName, &SQLiteDriver{ - ConnectHook: func(conn *SQLiteConn) error { - driverConns = append(driverConns, conn) - return nil - }, - }) - - // Connect to the source database. - srcTempFilename := TempFilename(t) - defer os.Remove(srcTempFilename) - srcDb, err := sql.Open(driverName, srcTempFilename) - if err != nil { - t.Fatal("Failed to open the source database:", err) - } - defer srcDb.Close() - err = srcDb.Ping() - if err != nil { - t.Fatal("Failed to connect to the source database:", err) - } - - // Connect to the destination database. - destTempFilename := TempFilename(t) - defer os.Remove(destTempFilename) - destDb, err := sql.Open(driverName, destTempFilename) - if err != nil { - t.Fatal("Failed to open the destination database:", err) - } - defer destDb.Close() - err = destDb.Ping() - if err != nil { - t.Fatal("Failed to connect to the destination database:", err) - } - - // Check the driver connections. - if len(driverConns) != 2 { - t.Fatalf("Expected 2 driver connections, but found %v.", len(driverConns)) - } - srcDbDriverConn := driverConns[0] - if srcDbDriverConn == nil { - t.Fatal("The source database driver connection is nil.") - } - destDbDriverConn := driverConns[1] - if destDbDriverConn == nil { - t.Fatal("The destination database driver connection is nil.") - } - - // Generate some test data for the given ID. - var generateTestData = func(id int) string { - return fmt.Sprintf("test-%v", id) - } - - // Populate the source database with a test table containing some test data. - tx, err := srcDb.Begin() - if err != nil { - t.Fatal("Failed to begin a transaction when populating the source database:", err) - } - _, err = srcDb.Exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)") - if err != nil { - tx.Rollback() - t.Fatal("Failed to create the source database \"test\" table:", err) - } - for id := 0; id < testRowCount; id++ { - _, err = srcDb.Exec("INSERT INTO test (id, value) VALUES (?, ?)", id, generateTestData(id)) - if err != nil { - tx.Rollback() - t.Fatal("Failed to insert a row into the source database \"test\" table:", err) - } - } - err = tx.Commit() - if err != nil { - t.Fatal("Failed to populate the source database:", err) - } - - // Confirm that the destination database is initially empty. - var destTableCount int - err = destDb.QueryRow("SELECT COUNT(*) FROM sqlite_master WHERE type = 'table'").Scan(&destTableCount) - if err != nil { - t.Fatal("Failed to check the destination table count:", err) - } - if destTableCount != 0 { - t.Fatalf("The destination database is not empty; %v table(s) found.", destTableCount) - } - - // Prepare to perform the backup. - backup, err := destDbDriverConn.Backup("main", srcDbDriverConn, "main") - if err != nil { - t.Fatal("Failed to initialize the backup:", err) - } - - // Allow the initial page count and remaining values to be retrieved. - // According to , the page count and remaining values are "... only updated by sqlite3_backup_step()." - isDone, err := backup.Step(0) - if err != nil { - t.Fatal("Unable to perform an initial 0-page backup step:", err) - } - if isDone { - t.Fatal("Backup is unexpectedly done.") - } - - // Check that the page count and remaining values are reasonable. - initialPageCount := backup.PageCount() - if initialPageCount <= 0 { - t.Fatalf("Unexpected initial page count value: %v", initialPageCount) - } - initialRemaining := backup.Remaining() - if initialRemaining <= 0 { - t.Fatalf("Unexpected initial remaining value: %v", initialRemaining) - } - if initialRemaining != initialPageCount { - t.Fatalf("Initial remaining value differs from the initial page count value; remaining: %v; page count: %v", initialRemaining, initialPageCount) - } - - // Perform the backup. - if usePerPageSteps { - var startTime = time.Now().Unix() - - // Test backing-up using a page-by-page approach. - var latestRemaining = initialRemaining - for { - // Perform the backup step. - isDone, err = backup.Step(1) - if err != nil { - t.Fatal("Failed to perform a backup step:", err) - } - - // The page count should remain unchanged from its initial value. - currentPageCount := backup.PageCount() - if currentPageCount != initialPageCount { - t.Fatalf("Current page count differs from the initial page count; initial page count: %v; current page count: %v", initialPageCount, currentPageCount) - } - - // There should now be one less page remaining. - currentRemaining := backup.Remaining() - expectedRemaining := latestRemaining - 1 - if currentRemaining != expectedRemaining { - t.Fatalf("Unexpected remaining value; expected remaining value: %v; actual remaining value: %v", expectedRemaining, currentRemaining) - } - latestRemaining = currentRemaining - - if isDone { - break - } - - // Limit the runtime of the backup attempt. - if (time.Now().Unix() - startTime) > usePagePerStepsTimeoutSeconds { - t.Fatal("Backup is taking longer than expected.") - } - } - } else { - // Test the copying of all remaining pages. - isDone, err = backup.Step(-1) - if err != nil { - t.Fatal("Failed to perform a backup step:", err) - } - if !isDone { - t.Fatal("Backup is unexpectedly not done.") - } - } - - // Check that the page count and remaining values are reasonable. - finalPageCount := backup.PageCount() - if finalPageCount != initialPageCount { - t.Fatalf("Final page count differs from the initial page count; initial page count: %v; final page count: %v", initialPageCount, finalPageCount) - } - finalRemaining := backup.Remaining() - if finalRemaining != 0 { - t.Fatalf("Unexpected remaining value: %v", finalRemaining) - } - - // Finish the backup. - err = backup.Finish() - if err != nil { - t.Fatal("Failed to finish backup:", err) - } - - // Confirm that the "test" table now exists in the destination database. - var doesTestTableExist bool - err = destDb.QueryRow("SELECT EXISTS (SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'test' LIMIT 1) AS test_table_exists").Scan(&doesTestTableExist) - if err != nil { - t.Fatal("Failed to check if the \"test\" table exists in the destination database:", err) - } - if !doesTestTableExist { - t.Fatal("The \"test\" table could not be found in the destination database.") - } - - // Confirm that the number of rows in the destination database's "test" table matches that of the source table. - var actualTestTableRowCount int - err = destDb.QueryRow("SELECT COUNT(*) FROM test").Scan(&actualTestTableRowCount) - if err != nil { - t.Fatal("Failed to determine the rowcount of the \"test\" table in the destination database:", err) - } - if testRowCount != actualTestTableRowCount { - t.Fatalf("Unexpected destination \"test\" table row count; expected: %v; found: %v", testRowCount, actualTestTableRowCount) - } - - // Check each of the rows in the destination database. - for id := 0; id < testRowCount; id++ { - var checkedValue string - err = destDb.QueryRow("SELECT value FROM test WHERE id = ?", id).Scan(&checkedValue) - if err != nil { - t.Fatal("Failed to query the \"test\" table in the destination database:", err) - } - - var expectedValue = generateTestData(id) - if checkedValue != expectedValue { - t.Fatalf("Unexpected value in the \"test\" table in the destination database; expected value: %v; actual value: %v", expectedValue, checkedValue) - } - } -} - -func TestBackupStepByStep(t *testing.T) { - testBackup(t, testRowCount, true) -} - -func TestBackupAllRemainingPages(t *testing.T) { - testBackup(t, testRowCount, false) -} - -// Test the error reporting when preparing to perform a backup. -func TestBackupError(t *testing.T) { - const driverName = "sqlite3_TestBackupError" - - // The driver's connection will be needed in order to perform the backup. - var dbDriverConn *SQLiteConn - sql.Register(driverName, &SQLiteDriver{ - ConnectHook: func(conn *SQLiteConn) error { - dbDriverConn = conn - return nil - }, - }) - - // Connect to the database. - dbTempFilename := TempFilename(t) - defer os.Remove(dbTempFilename) - db, err := sql.Open(driverName, dbTempFilename) - if err != nil { - t.Fatal("Failed to open the database:", err) - } - defer db.Close() - db.Ping() - - // Need the driver connection in order to perform the backup. - if dbDriverConn == nil { - t.Fatal("Failed to get the driver connection.") - } - - // Prepare to perform the backup. - // Intentionally using the same connection for both the source and destination databases, to trigger an error result. - backup, err := dbDriverConn.Backup("main", dbDriverConn, "main") - if err == nil { - t.Fatal("Failed to get the expected error result.") - } - const expectedError = "source and destination must be distinct" - if err.Error() != expectedError { - t.Fatalf("Unexpected error message; expected value: \"%v\"; actual value: \"%v\"", expectedError, err.Error()) - } - if backup != nil { - t.Fatal("Failed to get the expected nil backup result.") - } -} diff --git a/vendor/github.com/mattn/go-sqlite3/callback_test.go b/vendor/github.com/mattn/go-sqlite3/callback_test.go deleted file mode 100644 index 5c61f443..00000000 --- a/vendor/github.com/mattn/go-sqlite3/callback_test.go +++ /dev/null @@ -1,97 +0,0 @@ -package sqlite3 - -import ( - "errors" - "math" - "reflect" - "testing" -) - -func TestCallbackArgCast(t *testing.T) { - intConv := callbackSyntheticForTests(reflect.ValueOf(int64(math.MaxInt64)), nil) - floatConv := callbackSyntheticForTests(reflect.ValueOf(float64(math.MaxFloat64)), nil) - errConv := callbackSyntheticForTests(reflect.Value{}, errors.New("test")) - - tests := []struct { - f callbackArgConverter - o reflect.Value - }{ - {intConv, reflect.ValueOf(int8(-1))}, - {intConv, reflect.ValueOf(int16(-1))}, - {intConv, reflect.ValueOf(int32(-1))}, - {intConv, reflect.ValueOf(uint8(math.MaxUint8))}, - {intConv, reflect.ValueOf(uint16(math.MaxUint16))}, - {intConv, reflect.ValueOf(uint32(math.MaxUint32))}, - // Special case, int64->uint64 is only 1<<63 - 1, not 1<<64 - 1 - {intConv, reflect.ValueOf(uint64(math.MaxInt64))}, - {floatConv, reflect.ValueOf(float32(math.Inf(1)))}, - } - - for _, test := range tests { - conv := callbackArgCast{test.f, test.o.Type()} - val, err := conv.Run(nil) - if err != nil { - t.Errorf("Couldn't convert to %s: %s", test.o.Type(), err) - } else if !reflect.DeepEqual(val.Interface(), test.o.Interface()) { - t.Errorf("Unexpected result from converting to %s: got %v, want %v", test.o.Type(), val.Interface(), test.o.Interface()) - } - } - - conv := callbackArgCast{errConv, reflect.TypeOf(int8(0))} - _, err := conv.Run(nil) - if err == nil { - t.Errorf("Expected error during callbackArgCast, but got none") - } -} - -func TestCallbackConverters(t *testing.T) { - tests := []struct { - v interface{} - err bool - }{ - // Unfortunately, we can't tell which converter was returned, - // but we can at least check which types can be converted. - {[]byte{0}, false}, - {"text", false}, - {true, false}, - {int8(0), false}, - {int16(0), false}, - {int32(0), false}, - {int64(0), false}, - {uint8(0), false}, - {uint16(0), false}, - {uint32(0), false}, - {uint64(0), false}, - {int(0), false}, - {uint(0), false}, - {float64(0), false}, - {float32(0), false}, - - {func() {}, true}, - {complex64(complex(0, 0)), true}, - {complex128(complex(0, 0)), true}, - {struct{}{}, true}, - {map[string]string{}, true}, - {[]string{}, true}, - {(*int8)(nil), true}, - {make(chan int), true}, - } - - for _, test := range tests { - _, err := callbackArg(reflect.TypeOf(test.v)) - if test.err && err == nil { - t.Errorf("Expected an error when converting %s, got no error", reflect.TypeOf(test.v)) - } else if !test.err && err != nil { - t.Errorf("Expected converter when converting %s, got error: %s", reflect.TypeOf(test.v), err) - } - } - - for _, test := range tests { - _, err := callbackRet(reflect.TypeOf(test.v)) - if test.err && err == nil { - t.Errorf("Expected an error when converting %s, got no error", reflect.TypeOf(test.v)) - } else if !test.err && err != nil { - t.Errorf("Expected converter when converting %s, got error: %s", reflect.TypeOf(test.v), err) - } - } -} diff --git a/vendor/github.com/mattn/go-sqlite3/error_test.go b/vendor/github.com/mattn/go-sqlite3/error_test.go deleted file mode 100644 index 7fccd572..00000000 --- a/vendor/github.com/mattn/go-sqlite3/error_test.go +++ /dev/null @@ -1,242 +0,0 @@ -// Copyright (C) 2014 Yasuhiro Matsumoto . -// -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package sqlite3 - -import ( - "database/sql" - "io/ioutil" - "os" - "path" - "testing" -) - -func TestSimpleError(t *testing.T) { - e := ErrError.Error() - if e != "SQL logic error or missing database" && e != "SQL logic error" { - t.Error("wrong error code: " + e) - } -} - -func TestCorruptDbErrors(t *testing.T) { - dirName, err := ioutil.TempDir("", "sqlite3") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(dirName) - - dbFileName := path.Join(dirName, "test.db") - f, err := os.Create(dbFileName) - if err != nil { - t.Error(err) - } - f.Write([]byte{1, 2, 3, 4, 5}) - f.Close() - - db, err := sql.Open("sqlite3", dbFileName) - if err == nil { - _, err = db.Exec("drop table foo") - } - - sqliteErr := err.(Error) - if sqliteErr.Code != ErrNotADB { - t.Error("wrong error code for corrupted DB") - } - if err.Error() == "" { - t.Error("wrong error string for corrupted DB") - } - db.Close() -} - -func TestSqlLogicErrors(t *testing.T) { - dirName, err := ioutil.TempDir("", "sqlite3") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(dirName) - - dbFileName := path.Join(dirName, "test.db") - db, err := sql.Open("sqlite3", dbFileName) - if err != nil { - t.Error(err) - } - defer db.Close() - - _, err = db.Exec("CREATE TABLE Foo (id INTEGER PRIMARY KEY)") - if err != nil { - t.Error(err) - } - - const expectedErr = "table Foo already exists" - _, err = db.Exec("CREATE TABLE Foo (id INTEGER PRIMARY KEY)") - if err.Error() != expectedErr { - t.Errorf("Unexpected error: %s, expected %s", err.Error(), expectedErr) - } - -} - -func TestExtendedErrorCodes_ForeignKey(t *testing.T) { - dirName, err := ioutil.TempDir("", "sqlite3-err") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(dirName) - - dbFileName := path.Join(dirName, "test.db") - db, err := sql.Open("sqlite3", dbFileName) - if err != nil { - t.Error(err) - } - defer db.Close() - - _, err = db.Exec("PRAGMA foreign_keys=ON;") - if err != nil { - t.Errorf("PRAGMA foreign_keys=ON: %v", err) - } - - _, err = db.Exec(`CREATE TABLE Foo ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - value INTEGER NOT NULL, - ref INTEGER NULL REFERENCES Foo (id), - UNIQUE(value) - );`) - if err != nil { - t.Error(err) - } - - _, err = db.Exec("INSERT INTO Foo (ref, value) VALUES (100, 100);") - if err == nil { - t.Error("No error!") - } else { - sqliteErr := err.(Error) - if sqliteErr.Code != ErrConstraint { - t.Errorf("Wrong basic error code: %d != %d", - sqliteErr.Code, ErrConstraint) - } - if sqliteErr.ExtendedCode != ErrConstraintForeignKey { - t.Errorf("Wrong extended error code: %d != %d", - sqliteErr.ExtendedCode, ErrConstraintForeignKey) - } - } - -} - -func TestExtendedErrorCodes_NotNull(t *testing.T) { - dirName, err := ioutil.TempDir("", "sqlite3-err") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(dirName) - - dbFileName := path.Join(dirName, "test.db") - db, err := sql.Open("sqlite3", dbFileName) - if err != nil { - t.Error(err) - } - defer db.Close() - - _, err = db.Exec("PRAGMA foreign_keys=ON;") - if err != nil { - t.Errorf("PRAGMA foreign_keys=ON: %v", err) - } - - _, err = db.Exec(`CREATE TABLE Foo ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - value INTEGER NOT NULL, - ref INTEGER NULL REFERENCES Foo (id), - UNIQUE(value) - );`) - if err != nil { - t.Error(err) - } - - res, err := db.Exec("INSERT INTO Foo (value) VALUES (100);") - if err != nil { - t.Fatalf("Creating first row: %v", err) - } - - id, err := res.LastInsertId() - if err != nil { - t.Fatalf("Retrieving last insert id: %v", err) - } - - _, err = db.Exec("INSERT INTO Foo (ref) VALUES (?);", id) - if err == nil { - t.Error("No error!") - } else { - sqliteErr := err.(Error) - if sqliteErr.Code != ErrConstraint { - t.Errorf("Wrong basic error code: %d != %d", - sqliteErr.Code, ErrConstraint) - } - if sqliteErr.ExtendedCode != ErrConstraintNotNull { - t.Errorf("Wrong extended error code: %d != %d", - sqliteErr.ExtendedCode, ErrConstraintNotNull) - } - } - -} - -func TestExtendedErrorCodes_Unique(t *testing.T) { - dirName, err := ioutil.TempDir("", "sqlite3-err") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(dirName) - - dbFileName := path.Join(dirName, "test.db") - db, err := sql.Open("sqlite3", dbFileName) - if err != nil { - t.Error(err) - } - defer db.Close() - - _, err = db.Exec("PRAGMA foreign_keys=ON;") - if err != nil { - t.Errorf("PRAGMA foreign_keys=ON: %v", err) - } - - _, err = db.Exec(`CREATE TABLE Foo ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - value INTEGER NOT NULL, - ref INTEGER NULL REFERENCES Foo (id), - UNIQUE(value) - );`) - if err != nil { - t.Error(err) - } - - res, err := db.Exec("INSERT INTO Foo (value) VALUES (100);") - if err != nil { - t.Fatalf("Creating first row: %v", err) - } - - id, err := res.LastInsertId() - if err != nil { - t.Fatalf("Retrieving last insert id: %v", err) - } - - _, err = db.Exec("INSERT INTO Foo (ref, value) VALUES (?, 100);", id) - if err == nil { - t.Error("No error!") - } else { - sqliteErr := err.(Error) - if sqliteErr.Code != ErrConstraint { - t.Errorf("Wrong basic error code: %d != %d", - sqliteErr.Code, ErrConstraint) - } - if sqliteErr.ExtendedCode != ErrConstraintUnique { - t.Errorf("Wrong extended error code: %d != %d", - sqliteErr.ExtendedCode, ErrConstraintUnique) - } - extended := sqliteErr.Code.Extend(3).Error() - expected := "constraint failed" - if extended != expected { - t.Errorf("Wrong basic error code: %q != %q", - extended, expected) - } - } - -} diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_func_crypt_test.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_func_crypt_test.go deleted file mode 100644 index 0329ca86..00000000 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3_func_crypt_test.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (C) 2018 G.J.R. Timmer . -// -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package sqlite3 - -import ( - "fmt" - "strings" - "testing" -) - -// TestCryptEncoders to increase coverage -func TestCryptEncoders(t *testing.T) { - tests := []struct { - enc string - salt string - expected string - }{ - {"sha1", "", "d033e22ae348aeb5660fc2140aec35850c4da997"}, - {"sha256", "", "8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918"}, - {"sha384", "", "9ca694a90285c034432c9550421b7b9dbd5c0f4b6673f05f6dbce58052ba20e4248041956ee8c9a2ec9f10290cdc0782"}, - {"sha512", "", "c7ad44cbad762a5da0a452f9e854fdc1e0e7a52a38015f23f3eab1d80b931dd472634dfac71cd34ebc35d16ab7fb8a90c81f975113d6c7538dc69dd8de9077ec"}, - {"ssha1", "salt", "9bc7aa55f08fdad935c3f8362d3f48bcf70eb280"}, - {"ssha256", "salt", "f9a81477552594c79f2abc3fc099daa896a6e3a3590a55ffa392b6000412e80b"}, - {"ssha384", "salt", "9ed776b477fcfc1b5e584989e8d770f5e17d98a7643546a63c2b07d4ab00f1348f6b8e73103d3a23554f727136e8c215"}, - {"ssha512", "salt", "3c4a79782143337be4492be072abcfe979dd703c00541a8c39a0f3df4bab2029c050cf46fddc47090b5b04ac537b3e78189e3de16e601e859f95c51ac9f6dafb"}, - } - - for _, e := range tests { - var fn func(pass []byte, hash interface{}) []byte - switch e.enc { - case "sha1": - fn = CryptEncoderSHA1 - case "ssha1": - fn = CryptEncoderSSHA1(e.salt) - case "sha256": - fn = CryptEncoderSHA256 - case "ssha256": - fn = CryptEncoderSSHA256(e.salt) - case "sha384": - fn = CryptEncoderSHA384 - case "ssha384": - fn = CryptEncoderSSHA384(e.salt) - case "sha512": - fn = CryptEncoderSHA512 - case "ssha512": - fn = CryptEncoderSSHA512(e.salt) - } - - h := fn([]byte("admin"), nil) - if strings.Compare(fmt.Sprintf("%x", h), e.expected) != 0 { - t.Fatalf("Invalid %s hash: expected: %s; got: %x", strings.ToUpper(e.enc), e.expected, h) - } - } -} diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_go18_test.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_go18_test.go deleted file mode 100644 index 741ed90a..00000000 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3_go18_test.go +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright (C) 2014 Yasuhiro Matsumoto . -// -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -// +build go1.8 - -package sqlite3 - -import ( - "context" - "database/sql" - "fmt" - "math/rand" - "os" - "testing" - "time" -) - -func TestNamedParams(t *testing.T) { - tempFilename := TempFilename(t) - defer os.Remove(tempFilename) - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer db.Close() - - _, err = db.Exec(` - create table foo (id integer, name text, extra text); - `) - if err != nil { - t.Error("Failed to call db.Query:", err) - } - - _, err = db.Exec(`insert into foo(id, name, extra) values(:id, :name, :name)`, sql.Named("name", "foo"), sql.Named("id", 1)) - if err != nil { - t.Error("Failed to call db.Exec:", err) - } - - row := db.QueryRow(`select id, extra from foo where id = :id and extra = :extra`, sql.Named("id", 1), sql.Named("extra", "foo")) - if row == nil { - t.Error("Failed to call db.QueryRow") - } - var id int - var extra string - err = row.Scan(&id, &extra) - if err != nil { - t.Error("Failed to db.Scan:", err) - } - if id != 1 || extra != "foo" { - t.Error("Failed to db.QueryRow: not matched results") - } -} - -var ( - testTableStatements = []string{ - `DROP TABLE IF EXISTS test_table`, - ` -CREATE TABLE IF NOT EXISTS test_table ( - key1 VARCHAR(64) PRIMARY KEY, - key_id VARCHAR(64) NOT NULL, - key2 VARCHAR(64) NOT NULL, - key3 VARCHAR(64) NOT NULL, - key4 VARCHAR(64) NOT NULL, - key5 VARCHAR(64) NOT NULL, - key6 VARCHAR(64) NOT NULL, - data BLOB NOT NULL -);`, - } - letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" -) - -func randStringBytes(n int) string { - b := make([]byte, n) - for i := range b { - b[i] = letterBytes[rand.Intn(len(letterBytes))] - } - return string(b) -} - -func initDatabase(t *testing.T, db *sql.DB, rowCount int64) { - for _, query := range testTableStatements { - _, err := db.Exec(query) - if err != nil { - t.Fatal(err) - } - } - for i := int64(0); i < rowCount; i++ { - query := `INSERT INTO test_table - (key1, key_id, key2, key3, key4, key5, key6, data) - VALUES - (?, ?, ?, ?, ?, ?, ?, ?);` - args := []interface{}{ - randStringBytes(50), - fmt.Sprint(i), - randStringBytes(50), - randStringBytes(50), - randStringBytes(50), - randStringBytes(50), - randStringBytes(50), - randStringBytes(50), - randStringBytes(2048), - } - _, err := db.Exec(query, args...) - if err != nil { - t.Fatal(err) - } - } -} - -func TestShortTimeout(t *testing.T) { - srcTempFilename := TempFilename(t) - defer os.Remove(srcTempFilename) - - db, err := sql.Open("sqlite3", srcTempFilename) - if err != nil { - t.Fatal(err) - } - defer db.Close() - initDatabase(t, db, 100) - - ctx, cancel := context.WithTimeout(context.Background(), 1*time.Microsecond) - defer cancel() - query := `SELECT key1, key_id, key2, key3, key4, key5, key6, data - FROM test_table - ORDER BY key2 ASC` - _, err = db.QueryContext(ctx, query) - if err != nil && err != context.DeadlineExceeded { - t.Fatal(err) - } - if ctx.Err() != nil && ctx.Err() != context.DeadlineExceeded { - t.Fatal(ctx.Err()) - } -} - -func TestExecCancel(t *testing.T) { - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - t.Fatal(err) - } - defer db.Close() - - if _, err = db.Exec("create table foo (id integer primary key)"); err != nil { - t.Fatal(err) - } - - for n := 0; n < 100; n++ { - ctx, cancel := context.WithCancel(context.Background()) - _, err = db.ExecContext(ctx, "insert into foo (id) values (?)", n) - cancel() - if err != nil { - t.Fatal(err) - } - } -} diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_fts3_test.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_fts3_test.go deleted file mode 100644 index e06fc5d1..00000000 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_fts3_test.go +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright (C) 2015 Yasuhiro Matsumoto . -// -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package sqlite3 - -import ( - "database/sql" - "os" - "testing" -) - -func TestFTS3(t *testing.T) { - tempFilename := TempFilename(t) - defer os.Remove(tempFilename) - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer db.Close() - - _, err = db.Exec("DROP TABLE foo") - _, err = db.Exec("CREATE VIRTUAL TABLE foo USING fts3(id INTEGER PRIMARY KEY, value TEXT)") - if err != nil { - t.Fatal("Failed to create table:", err) - } - - _, err = db.Exec("INSERT INTO foo(id, value) VALUES(?, ?)", 1, `今日の 晩御飯は 天麩羅よ`) - if err != nil { - t.Fatal("Failed to insert value:", err) - } - - _, err = db.Exec("INSERT INTO foo(id, value) VALUES(?, ?)", 2, `今日は いい 天気だ`) - if err != nil { - t.Fatal("Failed to insert value:", err) - } - - rows, err := db.Query("SELECT id, value FROM foo WHERE value MATCH '今日* 天*'") - if err != nil { - t.Fatal("Unable to query foo table:", err) - } - defer rows.Close() - - for rows.Next() { - var id int - var value string - - if err := rows.Scan(&id, &value); err != nil { - t.Error("Unable to scan results:", err) - continue - } - - if id == 1 && value != `今日の 晩御飯は 天麩羅よ` { - t.Error("Value for id 1 should be `今日の 晩御飯は 天麩羅よ`, but:", value) - } else if id == 2 && value != `今日は いい 天気だ` { - t.Error("Value for id 2 should be `今日は いい 天気だ`, but:", value) - } - } - - rows, err = db.Query("SELECT value FROM foo WHERE value MATCH '今日* 天麩羅*'") - if err != nil { - t.Fatal("Unable to query foo table:", err) - } - defer rows.Close() - - var value string - if !rows.Next() { - t.Fatal("Result should be only one") - } - - if err := rows.Scan(&value); err != nil { - t.Fatal("Unable to scan results:", err) - } - - if value != `今日の 晩御飯は 天麩羅よ` { - t.Fatal("Value should be `今日の 晩御飯は 天麩羅よ`, but:", value) - } - - if rows.Next() { - t.Fatal("Result should be only one") - } -} - -func TestFTS4(t *testing.T) { - tempFilename := TempFilename(t) - defer os.Remove(tempFilename) - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer db.Close() - - _, err = db.Exec("DROP TABLE foo") - _, err = db.Exec("CREATE VIRTUAL TABLE foo USING fts4(tokenize=unicode61, id INTEGER PRIMARY KEY, value TEXT)") - switch { - case err != nil && err.Error() == "unknown tokenizer: unicode61": - t.Skip("FTS4 not supported") - case err != nil: - t.Fatal("Failed to create table:", err) - } - - _, err = db.Exec("INSERT INTO foo(id, value) VALUES(?, ?)", 1, `février`) - if err != nil { - t.Fatal("Failed to insert value:", err) - } - - rows, err := db.Query("SELECT value FROM foo WHERE value MATCH 'fevrier'") - if err != nil { - t.Fatal("Unable to query foo table:", err) - } - defer rows.Close() - - var value string - if !rows.Next() { - t.Fatal("Result should be only one") - } - - if err := rows.Scan(&value); err != nil { - t.Fatal("Unable to scan results:", err) - } - - if value != `février` { - t.Fatal("Value should be `février`, but:", value) - } - - if rows.Next() { - t.Fatal("Result should be only one") - } -} diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_unlock_notify_test.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_unlock_notify_test.go deleted file mode 100644 index 812c5430..00000000 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_unlock_notify_test.go +++ /dev/null @@ -1,222 +0,0 @@ -// Copyright (C) 2018 Yasuhiro Matsumoto . -// -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -// +build sqlite_unlock_notify - -package sqlite3 - -import ( - "database/sql" - "fmt" - "os" - "sync" - "testing" - "time" -) - -func TestUnlockNotify(t *testing.T) { - tempFilename := TempFilename(t) - defer os.Remove(tempFilename) - dsn := fmt.Sprintf("file:%s?cache=shared&mode=rwc&_busy_timeout=%d", tempFilename, 500) - db, err := sql.Open("sqlite3", dsn) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer db.Close() - - _, err = db.Exec("CREATE TABLE foo(id INTEGER, status INTEGER)") - if err != nil { - t.Fatal("Failed to create table:", err) - } - - tx, err := db.Begin() - if err != nil { - t.Fatal("Failed to begin transaction:", err) - } - - _, err = tx.Exec("INSERT INTO foo(id, status) VALUES(1, 100)") - if err != nil { - t.Fatal("Failed to insert null:", err) - } - - _, err = tx.Exec("UPDATE foo SET status = 200 WHERE id = 1") - if err != nil { - t.Fatal("Failed to update table:", err) - } - - wg := sync.WaitGroup{} - wg.Add(1) - timer := time.NewTimer(500 * time.Millisecond) - go func() { - <-timer.C - err := tx.Commit() - if err != nil { - t.Fatal("Failed to commit transaction:", err) - } - wg.Done() - }() - - rows, err := db.Query("SELECT count(*) from foo") - if err != nil { - t.Fatal("Unable to query foo table:", err) - } - - if rows.Next() { - var count int - if err := rows.Scan(&count); err != nil { - t.Fatal("Failed to Scan rows", err) - } - } - if err := rows.Err(); err != nil { - t.Fatal("Failed at the call to Next:", err) - } - wg.Wait() - -} - -func TestUnlockNotifyMany(t *testing.T) { - tempFilename := TempFilename(t) - defer os.Remove(tempFilename) - dsn := fmt.Sprintf("file:%s?cache=shared&mode=rwc&_busy_timeout=%d", tempFilename, 500) - db, err := sql.Open("sqlite3", dsn) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer db.Close() - - _, err = db.Exec("CREATE TABLE foo(id INTEGER, status INTEGER)") - if err != nil { - t.Fatal("Failed to create table:", err) - } - - tx, err := db.Begin() - if err != nil { - t.Fatal("Failed to begin transaction:", err) - } - - _, err = tx.Exec("INSERT INTO foo(id, status) VALUES(1, 100)") - if err != nil { - t.Fatal("Failed to insert null:", err) - } - - _, err = tx.Exec("UPDATE foo SET status = 200 WHERE id = 1") - if err != nil { - t.Fatal("Failed to update table:", err) - } - - wg := sync.WaitGroup{} - wg.Add(1) - timer := time.NewTimer(500 * time.Millisecond) - go func() { - <-timer.C - err := tx.Commit() - if err != nil { - t.Fatal("Failed to commit transaction:", err) - } - wg.Done() - }() - - const concurrentQueries = 1000 - wg.Add(concurrentQueries) - for i := 0; i < concurrentQueries; i++ { - go func() { - rows, err := db.Query("SELECT count(*) from foo") - if err != nil { - t.Fatal("Unable to query foo table:", err) - } - - if rows.Next() { - var count int - if err := rows.Scan(&count); err != nil { - t.Fatal("Failed to Scan rows", err) - } - } - if err := rows.Err(); err != nil { - t.Fatal("Failed at the call to Next:", err) - } - wg.Done() - }() - } - wg.Wait() -} - -func TestUnlockNotifyDeadlock(t *testing.T) { - tempFilename := TempFilename(t) - defer os.Remove(tempFilename) - dsn := fmt.Sprintf("file:%s?cache=shared&mode=rwc&_busy_timeout=%d", tempFilename, 500) - db, err := sql.Open("sqlite3", dsn) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer db.Close() - - _, err = db.Exec("CREATE TABLE foo(id INTEGER, status INTEGER)") - if err != nil { - t.Fatal("Failed to create table:", err) - } - - tx, err := db.Begin() - if err != nil { - t.Fatal("Failed to begin transaction:", err) - } - - _, err = tx.Exec("INSERT INTO foo(id, status) VALUES(1, 100)") - if err != nil { - t.Fatal("Failed to insert null:", err) - } - - _, err = tx.Exec("UPDATE foo SET status = 200 WHERE id = 1") - if err != nil { - t.Fatal("Failed to update table:", err) - } - - wg := sync.WaitGroup{} - wg.Add(1) - timer := time.NewTimer(500 * time.Millisecond) - go func() { - <-timer.C - err := tx.Commit() - if err != nil { - t.Fatal("Failed to commit transaction:", err) - } - wg.Done() - }() - - wg.Add(1) - go func() { - tx2, err := db.Begin() - if err != nil { - t.Fatal("Failed to begin transaction:", err) - } - defer tx2.Rollback() - - _, err = tx2.Exec("DELETE FROM foo") - if err != nil { - t.Fatal("Failed to delete table:", err) - } - err = tx2.Commit() - if err != nil { - t.Fatal("Failed to commit transaction:", err) - } - wg.Done() - }() - - rows, err := tx.Query("SELECT count(*) from foo") - if err != nil { - t.Fatal("Unable to query foo table:", err) - } - - if rows.Next() { - var count int - if err := rows.Scan(&count); err != nil { - t.Fatal("Failed to Scan rows", err) - } - } - if err := rows.Err(); err != nil { - t.Fatal("Failed at the call to Next:", err) - } - - wg.Wait() -} diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_userauth_test.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_userauth_test.go deleted file mode 100644 index b4ac4a92..00000000 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_userauth_test.go +++ /dev/null @@ -1,619 +0,0 @@ -// Copyright (C) 2018 G.J.R. Timmer . -// -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -// +build sqlite_userauth - -package sqlite3 - -import ( - "database/sql" - "fmt" - "os" - "testing" -) - -var ( - conn *SQLiteConn - create func(t *testing.T, username, password string) (file string, err error) - createWithCrypt func(t *testing.T, username, password, crypt, salt string) (file string, err error) - connect func(t *testing.T, f string, username, password string) (file string, db *sql.DB, c *SQLiteConn, err error) - connectWithCrypt func(t *testing.T, f string, username, password string, crypt string, salt string) (file string, db *sql.DB, c *SQLiteConn, err error) - authEnabled func(db *sql.DB) (exists bool, err error) - addUser func(db *sql.DB, username, password string, admin int) (rv int, err error) - userExists func(db *sql.DB, username string) (rv int, err error) - isAdmin func(db *sql.DB, username string) (rv bool, err error) - modifyUser func(db *sql.DB, username, password string, admin int) (rv int, err error) - deleteUser func(db *sql.DB, username string) (rv int, err error) -) - -func init() { - // Create database connection - sql.Register("sqlite3_with_conn", - &SQLiteDriver{ - ConnectHook: func(c *SQLiteConn) error { - conn = c - return nil - }, - }) - - create = func(t *testing.T, username, password string) (file string, err error) { - var db *sql.DB - file, db, _, err = connect(t, "", username, password) - db.Close() - return - } - - createWithCrypt = func(t *testing.T, username, password, crypt, salt string) (file string, err error) { - var db *sql.DB - file, db, _, err = connectWithCrypt(t, "", "admin", "admin", crypt, salt) - db.Close() - return - } - - connect = func(t *testing.T, f string, username, password string) (file string, db *sql.DB, c *SQLiteConn, err error) { - conn = nil // Clear connection - file = f // Copy provided file (f) => file - if file == "" { - // Create dummy file - file = TempFilename(t) - } - - db, err = sql.Open("sqlite3_with_conn", "file:"+file+fmt.Sprintf("?_auth&_auth_user=%s&_auth_pass=%s", username, password)) - if err != nil { - defer os.Remove(file) - return file, nil, nil, err - } - - // Dummy query to force connection and database creation - // Will return ErrUnauthorized (SQLITE_AUTH) if user authentication fails - if _, err = db.Exec("SELECT 1;"); err != nil { - defer os.Remove(file) - defer db.Close() - return file, nil, nil, err - } - c = conn - - return - } - - connectWithCrypt = func(t *testing.T, f string, username, password string, crypt string, salt string) (file string, db *sql.DB, c *SQLiteConn, err error) { - conn = nil // Clear connection - file = f // Copy provided file (f) => file - if file == "" { - // Create dummy file - file = TempFilename(t) - } - - db, err = sql.Open("sqlite3_with_conn", "file:"+file+fmt.Sprintf("?_auth&_auth_user=%s&_auth_pass=%s&_auth_crypt=%s&_auth_salt=%s", username, password, crypt, salt)) - if err != nil { - defer os.Remove(file) - return file, nil, nil, err - } - - // Dummy query to force connection and database creation - // Will return ErrUnauthorized (SQLITE_AUTH) if user authentication fails - if _, err = db.Exec("SELECT 1;"); err != nil { - defer os.Remove(file) - defer db.Close() - return file, nil, nil, err - } - c = conn - - return - } - - authEnabled = func(db *sql.DB) (exists bool, err error) { - err = db.QueryRow("select count(type) from sqlite_master WHERE type='table' and name='sqlite_user';").Scan(&exists) - return - } - - addUser = func(db *sql.DB, username, password string, admin int) (rv int, err error) { - err = db.QueryRow("select auth_user_add(?, ?, ?);", username, password, admin).Scan(&rv) - return - } - - userExists = func(db *sql.DB, username string) (rv int, err error) { - err = db.QueryRow("select count(uname) from sqlite_user where uname=?", username).Scan(&rv) - return - } - - isAdmin = func(db *sql.DB, username string) (rv bool, err error) { - err = db.QueryRow("select isAdmin from sqlite_user where uname=?", username).Scan(&rv) - return - } - - modifyUser = func(db *sql.DB, username, password string, admin int) (rv int, err error) { - err = db.QueryRow("select auth_user_change(?, ?, ?);", username, password, admin).Scan(&rv) - return - } - - deleteUser = func(db *sql.DB, username string) (rv int, err error) { - err = db.QueryRow("select auth_user_delete(?);", username).Scan(&rv) - return - } -} - -func TestUserAuthCreateDatabase(t *testing.T) { - f, db, c, err := connect(t, "", "admin", "admin") - if err != nil && c == nil && db == nil { - t.Fatal(err) - } - defer db.Close() - defer os.Remove(f) - - enabled, err := authEnabled(db) - if err != nil || !enabled { - t.Fatalf("UserAuth not enabled: %s", err) - } - - e, err := userExists(db, "admin") - if err != nil { - t.Fatal(err) - } - if e != 1 { - t.Fatal("UserAuth: admin does not exists") - } - a, err := isAdmin(db, "admin") - if err != nil { - t.Fatal(err) - } - if !a { - t.Fatal("UserAuth: User is not administrator") - } -} - -func TestUserAuthLogin(t *testing.T) { - f1, err := create(t, "admin", "admin") - if err != nil { - t.Fatal(err) - } - defer os.Remove(f1) - - f2, db2, c2, err := connect(t, f1, "admin", "admin") - if err != nil { - t.Fatal(err) - } - defer db2.Close() - if f1 != f2 { - t.Fatal("UserAuth: Database file mismatch") - } - - // Test lower level authentication - err = c2.Authenticate("admin", "admin") - if err != nil { - t.Fatalf("UserAuth: *SQLiteConn.Authenticate() Failed: %s", err) - } - - // Test Login Failed - _, _, _, err = connect(t, f1, "admin", "invalid") - if err == nil { - t.Fatal("Login successful while expecting to fail") - } - if err != ErrUnauthorized { - t.Fatal(err) - } - err = c2.Authenticate("admin", "invalid") - if err == nil { - t.Fatal("Login successful while expecting to fail") - } - if err != ErrUnauthorized { - t.Fatal(err) - } -} - -func TestUserAuthAddAdmin(t *testing.T) { - f, db, c, err := connect(t, "", "admin", "admin") - if err != nil && c == nil && db == nil { - t.Fatal(err) - } - defer db.Close() - defer os.Remove(f) - - // Add Admin User through SQL call - rv, err := addUser(db, "admin2", "admin2", 1) - if err != nil { - t.Fatal(err) - } - if rv != 0 { - t.Fatal("Failed to add user") - } - - // Check if user was created - exists, err := userExists(db, "admin2") - if err != nil { - t.Fatal(err) - } - if exists != 1 { - t.Fatal("UserAuth: 'admin2' does not exists") - } - - // Check if user was created as an Administrator - admin, err := isAdmin(db, "admin2") - if err != nil { - t.Fatal(err) - } - if !admin { - t.Fatal("UserAuth: 'admin2' is not administrator") - } - - // Test *SQLiteConn - err = c.AuthUserAdd("admin3", "admin3", true) - if err != nil { - t.Fatal(err) - } - - // Check if user was created - exists, err = userExists(db, "admin2") - if err != nil { - t.Fatal(err) - } - if exists != 1 { - t.Fatal("UserAuth: 'admin3' does not exists") - } - - // Check if the user was created as an Administrator - admin, err = isAdmin(db, "admin3") - if err != nil { - t.Fatal(err) - } - if !admin { - t.Fatal("UserAuth: 'admin3' is not administrator") - } -} - -func TestUserAuthAddUser(t *testing.T) { - f1, db1, c, err := connect(t, "", "admin", "admin") - if err != nil && c == nil && db == nil { - t.Fatal(err) - } - defer os.Remove(f1) - - // Add user through SQL call - rv, err := addUser(db1, "user", "user", 0) - if err != nil { - t.Fatal(err) - } - if rv != 0 { - t.Fatal("Failed to add user") - } - - // Check if user was created - exists, err := userExists(db1, "user") - if err != nil { - t.Fatal(err) - } - if exists != 1 { - t.Fatal("UserAuth: 'user' does not exists") - } - - // Check if user was created as an Administrator - admin, err := isAdmin(db1, "user") - if err != nil { - t.Fatal(err) - } - if admin { - t.Fatal("UserAuth: 'user' is administrator") - } - - // Test *SQLiteConn - err = c.AuthUserAdd("user2", "user2", false) - if err != nil { - t.Fatal(err) - } - - // Check if user was created - exists, err = userExists(db1, "user2") - if err != nil { - t.Fatal(err) - } - if exists != 1 { - t.Fatal("UserAuth: 'user2' does not exists") - } - - // Check if the user was created as an Administrator - admin, err = isAdmin(db1, "user2") - if err != nil { - t.Fatal(err) - } - if admin { - t.Fatal("UserAuth: 'user2' is administrator") - } - - // Reconnect as normal user - db1.Close() - _, db2, c2, err := connect(t, f1, "user", "user") - if err != nil { - t.Fatal(err) - } - defer db2.Close() - - // Try to create admin user while logged in as normal user - rv, err = addUser(db2, "admin2", "admin2", 1) - if err != nil { - t.Fatal(err) - } - if rv != SQLITE_AUTH { - t.Fatal("Created admin user while not allowed") - } - - err = c2.AuthUserAdd("admin3", "admin3", true) - if err != ErrAdminRequired { - t.Fatal("Created admin user while not allowed") - } - - // Try to create normal user while logged in as normal user - rv, err = addUser(db2, "user3", "user3", 0) - if err != nil { - t.Fatal(err) - } - if rv != SQLITE_AUTH { - t.Fatal("Created user while not allowed") - } - - err = c2.AuthUserAdd("user4", "user4", false) - if err != ErrAdminRequired { - t.Fatal("Created user while not allowed") - } -} - -func TestUserAuthModifyUser(t *testing.T) { - f1, db1, c1, err := connect(t, "", "admin", "admin") - if err != nil && c1 == nil && db == nil { - t.Fatal(err) - } - defer os.Remove(f1) - - // Modify Password for current logged in admin - // through SQL - rv, err := modifyUser(db1, "admin", "admin2", 1) - if err != nil { - t.Fatal(err) - } - if rv != 0 { - t.Fatal("Failed to modify password for admin") - } - - // Modify password for current logged in admin - // through *SQLiteConn - err = c1.AuthUserChange("admin", "admin3", true) - if err != nil { - t.Fatal(err) - } - - // Modify Administrator Flag - // Because we are current logged in as 'admin' - // Changing our own admin flag should fail. - rv, err = modifyUser(db1, "admin", "admin3", 0) - if err != nil { - t.Fatal(err) - } - if rv != SQLITE_AUTH { - t.Fatal("Successfully changed admin flag while not allowed") - } - - // Modify admin flag through (*SQLiteConn) - // Because we are current logged in as 'admin' - // Changing our own admin flag should fail. - err = c1.AuthUserChange("admin", "admin3", false) - if err != ErrAdminRequired { - t.Fatal("Successfully changed admin flag while not allowed") - } - - // Add normal user - rv, err = addUser(db1, "user", "password", 0) - if err != nil { - t.Fatal(err) - } - if rv != 0 { - t.Fatal("Failed to add user") - } - - rv, err = addUser(db1, "user2", "user2", 0) - if err != nil { - t.Fatal(err) - } - if rv != 0 { - t.Fatal("Failed to add user") - } - - // Modify other user password and flag through SQL - rv, err = modifyUser(db1, "user", "pass", 1) - if err != nil { - t.Fatal(err) - } - if rv != 0 { - t.Fatal("Failed to modify password for user") - } - - // Modify other user password and flag through *SQLiteConn - err = c1.AuthUserChange("user", "newpass", false) - if err != nil { - t.Fatal(err) - } - - // Disconnect database for reconnect - db1.Close() - _, db2, c2, err := connect(t, f1, "user", "newpass") - if err != nil { - t.Fatal(err) - } - defer db2.Close() - - // Modify other user password through SQL - rv, err = modifyUser(db2, "user2", "newpass", 0) - if err != nil { - t.Fatal(err) - } - if rv != SQLITE_AUTH { - t.Fatal("Password change succesful while not allowed") - } - - // Modify other user password and flag through *SQLiteConn - err = c2.AuthUserChange("user2", "invalid", false) - if err != ErrAdminRequired { - t.Fatal("Password change succesful while not allowed") - } -} - -func TestUserAuthDeleteUser(t *testing.T) { - f1, db1, c, err := connect(t, "", "admin", "admin") - if err != nil && c == nil && db == nil { - t.Fatal(err) - } - defer os.Remove(f1) - - // Add Admin User 2 - rv, err := addUser(db1, "admin2", "admin2", 1) - if err != nil { - t.Fatal(err) - } - if rv != 0 { - t.Fatal("Failed to add user") - } - - rv, err = addUser(db1, "admin3", "admin3", 1) - if err != nil { - t.Fatal(err) - } - if rv != 0 { - t.Fatal("Failed to add user") - } - - // Check if user was created - exists, err := userExists(db1, "admin2") - if err != nil { - t.Fatal(err) - } - if exists != 1 { - t.Fatal("UserAuth: 'admin2' does not exists") - } - - exists, err = userExists(db1, "admin3") - if err != nil { - t.Fatal(err) - } - if exists != 1 { - t.Fatal("UserAuth: 'admin2' does not exists") - } - - // Delete user through SQL - rv, err = deleteUser(db1, "admin2") - if err != nil { - t.Fatal(err) - } - if rv != 0 { - t.Fatal("Failed to delete admin2") - } - - // Verify user admin2 deleted - exists, err = userExists(db1, "admin2") - if err != nil { - t.Fatal(err) - } - if exists != 0 { - t.Fatal("UserAuth: 'admin2' still exists") - } - - // Delete user through *SQLiteConn - rv, err = deleteUser(db1, "admin3") - if err != nil { - t.Fatal(err) - } - if rv != 0 { - t.Fatal("Failed to delete admin3") - } - - // Verify user admin3 deleted - exists, err = userExists(db1, "admin3") - if err != nil { - t.Fatal(err) - } - if exists != 0 { - t.Fatal("UserAuth: 'admin3' still exists") - } - - // Add normal user for reconnect and privileges check - rv, err = addUser(db1, "reconnect", "reconnect", 0) - if err != nil { - t.Fatal(err) - } - if rv != 0 { - t.Fatal("Failed to add user") - } - - // Add normal user for deletion through SQL - rv, err = addUser(db1, "user", "user", 0) - if err != nil { - t.Fatal(err) - } - if rv != 0 { - t.Fatal("Failed to add user") - } - - rv, err = addUser(db1, "user2", "user2", 0) - if err != nil { - t.Fatal(err) - } - if rv != 0 { - t.Fatal("Failed to add user") - } - - // Close database for reconnect - db1.Close() - - // Reconnect as normal user - _, db2, c2, err := connect(t, f1, "reconnect", "reconnect") - if err != nil { - t.Fatal(err) - } - defer db2.Close() - - // Delete user while logged in as normal user - // through SQL - rv, err = deleteUser(db2, "user") - if err != nil { - t.Fatal(err) - } - if rv != SQLITE_AUTH { - t.Fatal("Successfully deleted user wthout proper privileges") - } - - // Delete user while logged in as normal user - // through *SQLiteConn - err = c2.AuthUserDelete("user2") - if err != ErrAdminRequired { - t.Fatal("Successfully deleted user wthout proper privileges") - } -} - -func TestUserAuthEncoders(t *testing.T) { - cases := map[string]string{ - "sha1": "", - "ssha1": "salted", - "sha256": "", - "ssha256": "salted", - "sha384": "", - "ssha384": "salted", - "sha512": "", - "ssha512": "salted", - } - - for enc, salt := range cases { - f, err := createWithCrypt(t, "admin", "admin", enc, salt) - if err != nil { - t.Fatal(err) - } - defer os.Remove(f) - - _, db, _, err := connectWithCrypt(t, f, "admin", "admin", enc, salt) - if err != nil { - t.Fatal(err) - } - defer db.Close() - if e, err := authEnabled(db); err != nil && !e { - t.Fatalf("UserAuth (%s) not enabled %s", enc, err) - } - } -} diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vtable_test.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vtable_test.go deleted file mode 100644 index d196c756..00000000 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vtable_test.go +++ /dev/null @@ -1,486 +0,0 @@ -// Copyright (C) 2014 Yasuhiro Matsumoto . -// -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -// +build sqlite_vtable vtable - -package sqlite3 - -import ( - "database/sql" - "errors" - "fmt" - "os" - "reflect" - "strings" - "testing" -) - -type testModule struct { - t *testing.T - intarray []int -} - -type testVTab struct { - intarray []int -} - -type testVTabCursor struct { - vTab *testVTab - index int -} - -func (m testModule) Create(c *SQLiteConn, args []string) (VTab, error) { - if len(args) != 6 { - m.t.Fatal("six arguments expected") - } - if args[0] != "test" { - m.t.Fatal("module name") - } - if args[1] != "main" { - m.t.Fatal("db name") - } - if args[2] != "vtab" { - m.t.Fatal("table name") - } - if args[3] != "'1'" { - m.t.Fatal("first arg") - } - if args[4] != "2" { - m.t.Fatal("second arg") - } - if args[5] != "three" { - m.t.Fatal("third argsecond arg") - } - err := c.DeclareVTab("CREATE TABLE x(test TEXT)") - if err != nil { - return nil, err - } - return &testVTab{m.intarray}, nil -} - -func (m testModule) Connect(c *SQLiteConn, args []string) (VTab, error) { - return m.Create(c, args) -} - -func (m testModule) DestroyModule() {} - -func (v *testVTab) BestIndex(cst []InfoConstraint, ob []InfoOrderBy) (*IndexResult, error) { - used := make([]bool, 0, len(cst)) - for range cst { - used = append(used, false) - } - return &IndexResult{ - Used: used, - IdxNum: 0, - IdxStr: "test-index", - AlreadyOrdered: true, - EstimatedCost: 100, - EstimatedRows: 200, - }, nil -} - -func (v *testVTab) Disconnect() error { - return nil -} - -func (v *testVTab) Destroy() error { - return nil -} - -func (v *testVTab) Open() (VTabCursor, error) { - return &testVTabCursor{v, 0}, nil -} - -func (vc *testVTabCursor) Close() error { - return nil -} - -func (vc *testVTabCursor) Filter(idxNum int, idxStr string, vals []interface{}) error { - vc.index = 0 - return nil -} - -func (vc *testVTabCursor) Next() error { - vc.index++ - return nil -} - -func (vc *testVTabCursor) EOF() bool { - return vc.index >= len(vc.vTab.intarray) -} - -func (vc *testVTabCursor) Column(c *SQLiteContext, col int) error { - if col != 0 { - return fmt.Errorf("column index out of bounds: %d", col) - } - c.ResultInt(vc.vTab.intarray[vc.index]) - return nil -} - -func (vc *testVTabCursor) Rowid() (int64, error) { - return int64(vc.index), nil -} - -func TestCreateModule(t *testing.T) { - tempFilename := TempFilename(t) - defer os.Remove(tempFilename) - intarray := []int{1, 2, 3} - sql.Register("sqlite3_TestCreateModule", &SQLiteDriver{ - ConnectHook: func(conn *SQLiteConn) error { - return conn.CreateModule("test", testModule{t, intarray}) - }, - }) - db, err := sql.Open("sqlite3_TestCreateModule", tempFilename) - if err != nil { - t.Fatalf("could not open db: %v", err) - } - _, err = db.Exec("CREATE VIRTUAL TABLE vtab USING test('1', 2, three)") - if err != nil { - t.Fatalf("could not create vtable: %v", err) - } - - var i, value int - rows, err := db.Query("SELECT rowid, * FROM vtab WHERE test = '3'") - if err != nil { - t.Fatalf("couldn't select from virtual table: %v", err) - } - for rows.Next() { - rows.Scan(&i, &value) - if intarray[i] != value { - t.Fatalf("want %v but %v", intarray[i], value) - } - } - - _, err = db.Exec("DROP TABLE vtab") - if err != nil { - t.Fatalf("couldn't drop virtual table: %v", err) - } -} - -func TestVUpdate(t *testing.T) { - tempFilename := TempFilename(t) - defer os.Remove(tempFilename) - - // create module - updateMod := &vtabUpdateModule{t, make(map[string]*vtabUpdateTable)} - - // register module - sql.Register("sqlite3_TestVUpdate", &SQLiteDriver{ - ConnectHook: func(conn *SQLiteConn) error { - return conn.CreateModule("updatetest", updateMod) - }, - }) - - // connect - db, err := sql.Open("sqlite3_TestVUpdate", tempFilename) - if err != nil { - t.Fatalf("could not open db: %v", err) - } - - // create test table - _, err = db.Exec(`CREATE VIRTUAL TABLE vt USING updatetest(f1 integer, f2 text, f3 text)`) - if err != nil { - t.Fatalf("could not create updatetest vtable vt, got: %v", err) - } - - // check that table is defined properly - if len(updateMod.tables) != 1 { - t.Fatalf("expected exactly 1 table to exist, got: %d", len(updateMod.tables)) - } - if _, ok := updateMod.tables["vt"]; !ok { - t.Fatalf("expected table `vt` to exist in tables") - } - - // check nothing in updatetest - rows, err := db.Query(`select * from vt`) - if err != nil { - t.Fatalf("could not query vt, got: %v", err) - } - i, err := getRowCount(rows) - if err != nil { - t.Fatalf("expected no error, got: %v", err) - } - if i != 0 { - t.Fatalf("expected no rows in vt, got: %d", i) - } - - _, err = db.Exec(`delete from vt where f1 = 'yes'`) - if err != nil { - t.Fatalf("expected error on delete, got nil") - } - - // test bad column name - _, err = db.Exec(`insert into vt (f4) values('a')`) - if err == nil { - t.Fatalf("expected error on insert, got nil") - } - - // insert to vt - res, err := db.Exec(`insert into vt (f1, f2, f3) values (115, 'b', 'c'), (116, 'd', 'e')`) - if err != nil { - t.Fatalf("expected no error on insert, got: %v", err) - } - n, err := res.RowsAffected() - if err != nil { - t.Fatalf("expected no error, got: %v", err) - } - if n != 2 { - t.Fatalf("expected 1 row affected, got: %d", n) - } - - // check vt table - vt := updateMod.tables["vt"] - if len(vt.data) != 2 { - t.Fatalf("expected table vt to have exactly 2 rows, got: %d", len(vt.data)) - } - if !reflect.DeepEqual(vt.data[0], []interface{}{int64(115), "b", "c"}) { - t.Fatalf("expected table vt entry 0 to be [115 b c], instead: %v", vt.data[0]) - } - if !reflect.DeepEqual(vt.data[1], []interface{}{int64(116), "d", "e"}) { - t.Fatalf("expected table vt entry 1 to be [116 d e], instead: %v", vt.data[1]) - } - - // query vt - var f1 int - var f2, f3 string - err = db.QueryRow(`select * from vt where f1 = 115`).Scan(&f1, &f2, &f3) - if err != nil { - t.Fatalf("expected no error on vt query, got: %v", err) - } - - // check column values - if f1 != 115 || f2 != "b" || f3 != "c" { - t.Errorf("expected f1==115, f2==b, f3==c, got: %d, %q, %q", f1, f2, f3) - } - - // update vt - res, err = db.Exec(`update vt set f1=117, f2='f' where f3='e'`) - if err != nil { - t.Fatalf("expected no error, got: %v", err) - } - n, err = res.RowsAffected() - if err != nil { - t.Fatalf("expected no error, got: %v", err) - } - if n != 1 { - t.Fatalf("expected exactly one row updated, got: %d", n) - } - - // check vt table - if len(vt.data) != 2 { - t.Fatalf("expected table vt to have exactly 2 rows, got: %d", len(vt.data)) - } - if !reflect.DeepEqual(vt.data[0], []interface{}{int64(115), "b", "c"}) { - t.Fatalf("expected table vt entry 0 to be [115 b c], instead: %v", vt.data[0]) - } - if !reflect.DeepEqual(vt.data[1], []interface{}{int64(117), "f", "e"}) { - t.Fatalf("expected table vt entry 1 to be [117 f e], instead: %v", vt.data[1]) - } - - // delete from vt - res, err = db.Exec(`delete from vt where f1 = 117`) - if err != nil { - t.Fatalf("expected no error, got: %v", err) - } - n, err = res.RowsAffected() - if err != nil { - t.Fatalf("expected no error, got: %v", err) - } - if n != 1 { - t.Fatalf("expected exactly one row deleted, got: %d", n) - } - - // check vt table - if len(vt.data) != 1 { - t.Fatalf("expected table vt to have exactly 1 row, got: %d", len(vt.data)) - } - if !reflect.DeepEqual(vt.data[0], []interface{}{int64(115), "b", "c"}) { - t.Fatalf("expected table vt entry 0 to be [115 b c], instead: %v", vt.data[0]) - } - - // check updatetest has 1 result - rows, err = db.Query(`select * from vt`) - if err != nil { - t.Fatalf("could not query vt, got: %v", err) - } - i, err = getRowCount(rows) - if err != nil { - t.Fatalf("expected no error, got: %v", err) - } - if i != 1 { - t.Fatalf("expected 1 row in vt, got: %d", i) - } -} - -func getRowCount(rows *sql.Rows) (int, error) { - var i int - for rows.Next() { - i++ - } - return i, nil -} - -type vtabUpdateModule struct { - t *testing.T - tables map[string]*vtabUpdateTable -} - -func (m *vtabUpdateModule) Create(c *SQLiteConn, args []string) (VTab, error) { - if len(args) < 2 { - return nil, errors.New("must declare at least one column") - } - - // get database name, table name, and column declarations ... - dbname, tname, decls := args[1], args[2], args[3:] - - // extract column names + types from parameters declarations - cols, typs := make([]string, len(decls)), make([]string, len(decls)) - for i := 0; i < len(decls); i++ { - n, typ := decls[i], "" - if j := strings.IndexAny(n, " \t\n"); j != -1 { - typ, n = strings.TrimSpace(n[j+1:]), n[:j] - } - cols[i], typs[i] = n, typ - } - - // declare table - err := c.DeclareVTab(fmt.Sprintf(`CREATE TABLE "%s"."%s" (%s)`, dbname, tname, strings.Join(decls, ","))) - if err != nil { - return nil, err - } - - // create table - vtab := &vtabUpdateTable{m.t, dbname, tname, cols, typs, make([][]interface{}, 0)} - m.tables[tname] = vtab - return vtab, nil -} - -func (m *vtabUpdateModule) Connect(c *SQLiteConn, args []string) (VTab, error) { - return m.Create(c, args) -} - -func (m *vtabUpdateModule) DestroyModule() {} - -type vtabUpdateTable struct { - t *testing.T - db string - name string - cols []string - typs []string - data [][]interface{} -} - -func (t *vtabUpdateTable) Open() (VTabCursor, error) { - return &vtabUpdateCursor{t, 0}, nil -} - -func (t *vtabUpdateTable) BestIndex(cst []InfoConstraint, ob []InfoOrderBy) (*IndexResult, error) { - return &IndexResult{Used: make([]bool, len(cst))}, nil -} - -func (t *vtabUpdateTable) Disconnect() error { - return nil -} - -func (t *vtabUpdateTable) Destroy() error { - return nil -} - -func (t *vtabUpdateTable) Insert(id interface{}, vals []interface{}) (int64, error) { - var i int64 - if id == nil { - i, t.data = int64(len(t.data)), append(t.data, vals) - return i, nil - } - - var ok bool - i, ok = id.(int64) - if !ok { - return 0, fmt.Errorf("id is invalid type: %T", id) - } - - t.data[i] = vals - - return i, nil -} - -func (t *vtabUpdateTable) Update(id interface{}, vals []interface{}) error { - i, ok := id.(int64) - if !ok { - return fmt.Errorf("id is invalid type: %T", id) - } - - if int(i) >= len(t.data) || i < 0 { - return fmt.Errorf("invalid row id %d", i) - } - - t.data[int(i)] = vals - - return nil -} - -func (t *vtabUpdateTable) Delete(id interface{}) error { - i, ok := id.(int64) - if !ok { - return fmt.Errorf("id is invalid type: %T", id) - } - - if int(i) >= len(t.data) || i < 0 { - return fmt.Errorf("invalid row id %d", i) - } - - t.data = append(t.data[:i], t.data[i+1:]...) - - return nil -} - -type vtabUpdateCursor struct { - t *vtabUpdateTable - i int -} - -func (c *vtabUpdateCursor) Column(ctxt *SQLiteContext, col int) error { - switch x := c.t.data[c.i][col].(type) { - case []byte: - ctxt.ResultBlob(x) - case bool: - ctxt.ResultBool(x) - case float64: - ctxt.ResultDouble(x) - case int: - ctxt.ResultInt(x) - case int64: - ctxt.ResultInt64(x) - case nil: - ctxt.ResultNull() - case string: - ctxt.ResultText(x) - default: - ctxt.ResultText(fmt.Sprintf("%v", x)) - } - - return nil -} - -func (c *vtabUpdateCursor) Filter(ixNum int, ixName string, vals []interface{}) error { - return nil -} - -func (c *vtabUpdateCursor) Next() error { - c.i++ - return nil -} - -func (c *vtabUpdateCursor) EOF() bool { - return c.i >= len(c.t.data) -} - -func (c *vtabUpdateCursor) Rowid() (int64, error) { - return int64(c.i), nil -} - -func (c *vtabUpdateCursor) Close() error { - return nil -} diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_test.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_test.go deleted file mode 100644 index b295ddd0..00000000 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3_test.go +++ /dev/null @@ -1,2195 +0,0 @@ -// Copyright (C) 2014 Yasuhiro Matsumoto . -// -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package sqlite3 - -import ( - "bytes" - "database/sql" - "database/sql/driver" - "errors" - "fmt" - "io/ioutil" - "math/rand" - "net/url" - "os" - "reflect" - "regexp" - "strconv" - "strings" - "sync" - "testing" - "time" -) - -func TempFilename(t *testing.T) string { - f, err := ioutil.TempFile("", "go-sqlite3-test-") - if err != nil { - t.Fatal(err) - } - f.Close() - return f.Name() -} - -func doTestOpen(t *testing.T, option string) (string, error) { - var url string - tempFilename := TempFilename(t) - defer os.Remove(tempFilename) - if option != "" { - url = tempFilename + option - } else { - url = tempFilename - } - db, err := sql.Open("sqlite3", url) - if err != nil { - return "Failed to open database:", err - } - defer os.Remove(tempFilename) - defer db.Close() - - _, err = db.Exec("drop table foo") - _, err = db.Exec("create table foo (id integer)") - if err != nil { - return "Failed to create table:", err - } - - if stat, err := os.Stat(tempFilename); err != nil || stat.IsDir() { - return "Failed to create ./foo.db", nil - } - - return "", nil -} - -func TestOpen(t *testing.T) { - cases := map[string]bool{ - "": true, - "?_txlock=immediate": true, - "?_txlock=deferred": true, - "?_txlock=exclusive": true, - "?_txlock=bogus": false, - } - for option, expectedPass := range cases { - result, err := doTestOpen(t, option) - if result == "" { - if !expectedPass { - errmsg := fmt.Sprintf("_txlock error not caught at dbOpen with option: %s", option) - t.Fatal(errmsg) - } - } else if expectedPass { - if err == nil { - t.Fatal(result) - } else { - t.Fatal(result, err) - } - } - } -} - -func TestReadonly(t *testing.T) { - tempFilename := TempFilename(t) - defer os.Remove(tempFilename) - - db1, err := sql.Open("sqlite3", "file:"+tempFilename) - if err != nil { - t.Fatal(err) - } - db1.Exec("CREATE TABLE test (x int, y float)") - - db2, err := sql.Open("sqlite3", "file:"+tempFilename+"?mode=ro") - if err != nil { - t.Fatal(err) - } - _ = db2 - _, err = db2.Exec("INSERT INTO test VALUES (1, 3.14)") - if err == nil { - t.Fatal("didn't expect INSERT into read-only database to work") - } -} - -func TestForeignKeys(t *testing.T) { - cases := map[string]bool{ - "?_foreign_keys=1": true, - "?_foreign_keys=0": false, - } - for option, want := range cases { - fname := TempFilename(t) - uri := "file:" + fname + option - db, err := sql.Open("sqlite3", uri) - if err != nil { - os.Remove(fname) - t.Errorf("sql.Open(\"sqlite3\", %q): %v", uri, err) - continue - } - var enabled bool - err = db.QueryRow("PRAGMA foreign_keys;").Scan(&enabled) - db.Close() - os.Remove(fname) - if err != nil { - t.Errorf("query foreign_keys for %s: %v", uri, err) - continue - } - if enabled != want { - t.Errorf("\"PRAGMA foreign_keys;\" for %q = %t; want %t", uri, enabled, want) - continue - } - } -} - -func TestRecursiveTriggers(t *testing.T) { - cases := map[string]bool{ - "?_recursive_triggers=1": true, - "?_recursive_triggers=0": false, - } - for option, want := range cases { - fname := TempFilename(t) - uri := "file:" + fname + option - db, err := sql.Open("sqlite3", uri) - if err != nil { - os.Remove(fname) - t.Errorf("sql.Open(\"sqlite3\", %q): %v", uri, err) - continue - } - var enabled bool - err = db.QueryRow("PRAGMA recursive_triggers;").Scan(&enabled) - db.Close() - os.Remove(fname) - if err != nil { - t.Errorf("query recursive_triggers for %s: %v", uri, err) - continue - } - if enabled != want { - t.Errorf("\"PRAGMA recursive_triggers;\" for %q = %t; want %t", uri, enabled, want) - continue - } - } -} - -func TestClose(t *testing.T) { - tempFilename := TempFilename(t) - defer os.Remove(tempFilename) - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - - _, err = db.Exec("drop table foo") - _, err = db.Exec("create table foo (id integer)") - if err != nil { - t.Fatal("Failed to create table:", err) - } - - stmt, err := db.Prepare("select id from foo where id = ?") - if err != nil { - t.Fatal("Failed to select records:", err) - } - - db.Close() - _, err = stmt.Exec(1) - if err == nil { - t.Fatal("Failed to operate closed statement") - } -} - -func TestInsert(t *testing.T) { - tempFilename := TempFilename(t) - defer os.Remove(tempFilename) - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer db.Close() - - _, err = db.Exec("drop table foo") - _, err = db.Exec("create table foo (id integer)") - if err != nil { - t.Fatal("Failed to create table:", err) - } - - res, err := db.Exec("insert into foo(id) values(123)") - if err != nil { - t.Fatal("Failed to insert record:", err) - } - affected, _ := res.RowsAffected() - if affected != 1 { - t.Fatalf("Expected %d for affected rows, but %d:", 1, affected) - } - - rows, err := db.Query("select id from foo") - if err != nil { - t.Fatal("Failed to select records:", err) - } - defer rows.Close() - - rows.Next() - - var result int - rows.Scan(&result) - if result != 123 { - t.Errorf("Expected %d for fetched result, but %d:", 123, result) - } -} - -func TestUpsert(t *testing.T) { - _, n, _ := Version() - if !(n >= 3024000) { - t.Skip("UPSERT requires sqlite3 => 3.24.0") - } - tempFilename := TempFilename(t) - defer os.Remove(tempFilename) - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer db.Close() - - _, err = db.Exec("drop table foo") - _, err = db.Exec("create table foo (name string primary key, counter integer)") - if err != nil { - t.Fatal("Failed to create table:", err) - } - - for i := 0; i < 10; i++ { - res, err := db.Exec("insert into foo(name, counter) values('key', 1) on conflict (name) do update set counter=counter+1") - if err != nil { - t.Fatal("Failed to upsert record:", err) - } - affected, _ := res.RowsAffected() - if affected != 1 { - t.Fatalf("Expected %d for affected rows, but %d:", 1, affected) - } - } - rows, err := db.Query("select name, counter from foo") - if err != nil { - t.Fatal("Failed to select records:", err) - } - defer rows.Close() - - rows.Next() - - var resultName string - var resultCounter int - rows.Scan(&resultName, &resultCounter) - if resultName != "key" { - t.Errorf("Expected %s for fetched result, but %s:", "key", resultName) - } - if resultCounter != 10 { - t.Errorf("Expected %d for fetched result, but %d:", 10, resultCounter) - } - -} - -func TestUpdate(t *testing.T) { - tempFilename := TempFilename(t) - defer os.Remove(tempFilename) - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer db.Close() - - _, err = db.Exec("drop table foo") - _, err = db.Exec("create table foo (id integer)") - if err != nil { - t.Fatal("Failed to create table:", err) - } - - res, err := db.Exec("insert into foo(id) values(123)") - if err != nil { - t.Fatal("Failed to insert record:", err) - } - expected, err := res.LastInsertId() - if err != nil { - t.Fatal("Failed to get LastInsertId:", err) - } - affected, _ := res.RowsAffected() - if err != nil { - t.Fatal("Failed to get RowsAffected:", err) - } - if affected != 1 { - t.Fatalf("Expected %d for affected rows, but %d:", 1, affected) - } - - res, err = db.Exec("update foo set id = 234") - if err != nil { - t.Fatal("Failed to update record:", err) - } - lastID, err := res.LastInsertId() - if err != nil { - t.Fatal("Failed to get LastInsertId:", err) - } - if expected != lastID { - t.Errorf("Expected %q for last Id, but %q:", expected, lastID) - } - affected, _ = res.RowsAffected() - if err != nil { - t.Fatal("Failed to get RowsAffected:", err) - } - if affected != 1 { - t.Fatalf("Expected %d for affected rows, but %d:", 1, affected) - } - - rows, err := db.Query("select id from foo") - if err != nil { - t.Fatal("Failed to select records:", err) - } - defer rows.Close() - - rows.Next() - - var result int - rows.Scan(&result) - if result != 234 { - t.Errorf("Expected %d for fetched result, but %d:", 234, result) - } -} - -func TestDelete(t *testing.T) { - tempFilename := TempFilename(t) - defer os.Remove(tempFilename) - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer db.Close() - - _, err = db.Exec("drop table foo") - _, err = db.Exec("create table foo (id integer)") - if err != nil { - t.Fatal("Failed to create table:", err) - } - - res, err := db.Exec("insert into foo(id) values(123)") - if err != nil { - t.Fatal("Failed to insert record:", err) - } - expected, err := res.LastInsertId() - if err != nil { - t.Fatal("Failed to get LastInsertId:", err) - } - affected, err := res.RowsAffected() - if err != nil { - t.Fatal("Failed to get RowsAffected:", err) - } - if affected != 1 { - t.Errorf("Expected %d for cout of affected rows, but %q:", 1, affected) - } - - res, err = db.Exec("delete from foo where id = 123") - if err != nil { - t.Fatal("Failed to delete record:", err) - } - lastID, err := res.LastInsertId() - if err != nil { - t.Fatal("Failed to get LastInsertId:", err) - } - if expected != lastID { - t.Errorf("Expected %q for last Id, but %q:", expected, lastID) - } - affected, err = res.RowsAffected() - if err != nil { - t.Fatal("Failed to get RowsAffected:", err) - } - if affected != 1 { - t.Errorf("Expected %d for cout of affected rows, but %q:", 1, affected) - } - - rows, err := db.Query("select id from foo") - if err != nil { - t.Fatal("Failed to select records:", err) - } - defer rows.Close() - - if rows.Next() { - t.Error("Fetched row but expected not rows") - } -} - -func TestBooleanRoundtrip(t *testing.T) { - tempFilename := TempFilename(t) - defer os.Remove(tempFilename) - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer db.Close() - - _, err = db.Exec("DROP TABLE foo") - _, err = db.Exec("CREATE TABLE foo(id INTEGER, value BOOL)") - if err != nil { - t.Fatal("Failed to create table:", err) - } - - _, err = db.Exec("INSERT INTO foo(id, value) VALUES(1, ?)", true) - if err != nil { - t.Fatal("Failed to insert true value:", err) - } - - _, err = db.Exec("INSERT INTO foo(id, value) VALUES(2, ?)", false) - if err != nil { - t.Fatal("Failed to insert false value:", err) - } - - rows, err := db.Query("SELECT id, value FROM foo") - if err != nil { - t.Fatal("Unable to query foo table:", err) - } - defer rows.Close() - - for rows.Next() { - var id int - var value bool - - if err := rows.Scan(&id, &value); err != nil { - t.Error("Unable to scan results:", err) - continue - } - - if id == 1 && !value { - t.Error("Value for id 1 should be true, not false") - - } else if id == 2 && value { - t.Error("Value for id 2 should be false, not true") - } - } -} - -func timezone(t time.Time) string { return t.Format("-07:00") } - -func TestTimestamp(t *testing.T) { - tempFilename := TempFilename(t) - defer os.Remove(tempFilename) - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer db.Close() - - _, err = db.Exec("DROP TABLE foo") - _, err = db.Exec("CREATE TABLE foo(id INTEGER, ts timeSTAMP, dt DATETIME)") - if err != nil { - t.Fatal("Failed to create table:", err) - } - - timestamp1 := time.Date(2012, time.April, 6, 22, 50, 0, 0, time.UTC) - timestamp2 := time.Date(2006, time.January, 2, 15, 4, 5, 123456789, time.UTC) - timestamp3 := time.Date(2012, time.November, 4, 0, 0, 0, 0, time.UTC) - tzTest := time.FixedZone("TEST", -9*3600-13*60) - tests := []struct { - value interface{} - expected time.Time - }{ - {"nonsense", time.Time{}}, - {"0000-00-00 00:00:00", time.Time{}}, - {time.Time{}.Unix(), time.Time{}}, - {timestamp1, timestamp1}, - {timestamp2.Unix(), timestamp2.Truncate(time.Second)}, - {timestamp2.UnixNano() / int64(time.Millisecond), timestamp2.Truncate(time.Millisecond)}, - {timestamp1.In(tzTest), timestamp1.In(tzTest)}, - {timestamp1.Format("2006-01-02 15:04:05.000"), timestamp1}, - {timestamp1.Format("2006-01-02T15:04:05.000"), timestamp1}, - {timestamp1.Format("2006-01-02 15:04:05"), timestamp1}, - {timestamp1.Format("2006-01-02T15:04:05"), timestamp1}, - {timestamp2, timestamp2}, - {"2006-01-02 15:04:05.123456789", timestamp2}, - {"2006-01-02T15:04:05.123456789", timestamp2}, - {"2006-01-02T05:51:05.123456789-09:13", timestamp2.In(tzTest)}, - {"2012-11-04", timestamp3}, - {"2012-11-04 00:00", timestamp3}, - {"2012-11-04 00:00:00", timestamp3}, - {"2012-11-04 00:00:00.000", timestamp3}, - {"2012-11-04T00:00", timestamp3}, - {"2012-11-04T00:00:00", timestamp3}, - {"2012-11-04T00:00:00.000", timestamp3}, - {"2006-01-02T15:04:05.123456789Z", timestamp2}, - {"2012-11-04Z", timestamp3}, - {"2012-11-04 00:00Z", timestamp3}, - {"2012-11-04 00:00:00Z", timestamp3}, - {"2012-11-04 00:00:00.000Z", timestamp3}, - {"2012-11-04T00:00Z", timestamp3}, - {"2012-11-04T00:00:00Z", timestamp3}, - {"2012-11-04T00:00:00.000Z", timestamp3}, - } - for i := range tests { - _, err = db.Exec("INSERT INTO foo(id, ts, dt) VALUES(?, ?, ?)", i, tests[i].value, tests[i].value) - if err != nil { - t.Fatal("Failed to insert timestamp:", err) - } - } - - rows, err := db.Query("SELECT id, ts, dt FROM foo ORDER BY id ASC") - if err != nil { - t.Fatal("Unable to query foo table:", err) - } - defer rows.Close() - - seen := 0 - for rows.Next() { - var id int - var ts, dt time.Time - - if err := rows.Scan(&id, &ts, &dt); err != nil { - t.Error("Unable to scan results:", err) - continue - } - if id < 0 || id >= len(tests) { - t.Error("Bad row id: ", id) - continue - } - seen++ - if !tests[id].expected.Equal(ts) { - t.Errorf("Timestamp value for id %v (%v) should be %v, not %v", id, tests[id].value, tests[id].expected, dt) - } - if !tests[id].expected.Equal(dt) { - t.Errorf("Datetime value for id %v (%v) should be %v, not %v", id, tests[id].value, tests[id].expected, dt) - } - if timezone(tests[id].expected) != timezone(ts) { - t.Errorf("Timezone for id %v (%v) should be %v, not %v", id, tests[id].value, - timezone(tests[id].expected), timezone(ts)) - } - if timezone(tests[id].expected) != timezone(dt) { - t.Errorf("Timezone for id %v (%v) should be %v, not %v", id, tests[id].value, - timezone(tests[id].expected), timezone(dt)) - } - } - - if seen != len(tests) { - t.Errorf("Expected to see %d rows", len(tests)) - } -} - -func TestBoolean(t *testing.T) { - tempFilename := TempFilename(t) - defer os.Remove(tempFilename) - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - - defer db.Close() - - _, err = db.Exec("CREATE TABLE foo(id INTEGER, fbool BOOLEAN)") - if err != nil { - t.Fatal("Failed to create table:", err) - } - - bool1 := true - _, err = db.Exec("INSERT INTO foo(id, fbool) VALUES(1, ?)", bool1) - if err != nil { - t.Fatal("Failed to insert boolean:", err) - } - - bool2 := false - _, err = db.Exec("INSERT INTO foo(id, fbool) VALUES(2, ?)", bool2) - if err != nil { - t.Fatal("Failed to insert boolean:", err) - } - - bool3 := "nonsense" - _, err = db.Exec("INSERT INTO foo(id, fbool) VALUES(3, ?)", bool3) - if err != nil { - t.Fatal("Failed to insert nonsense:", err) - } - - rows, err := db.Query("SELECT id, fbool FROM foo where fbool = ?", bool1) - if err != nil { - t.Fatal("Unable to query foo table:", err) - } - counter := 0 - - var id int - var fbool bool - - for rows.Next() { - if err := rows.Scan(&id, &fbool); err != nil { - t.Fatal("Unable to scan results:", err) - } - counter++ - } - - if counter != 1 { - t.Fatalf("Expected 1 row but %v", counter) - } - - if id != 1 && !fbool { - t.Fatalf("Value for id 1 should be %v, not %v", bool1, fbool) - } - - rows, err = db.Query("SELECT id, fbool FROM foo where fbool = ?", bool2) - if err != nil { - t.Fatal("Unable to query foo table:", err) - } - - counter = 0 - - for rows.Next() { - if err := rows.Scan(&id, &fbool); err != nil { - t.Fatal("Unable to scan results:", err) - } - counter++ - } - - if counter != 1 { - t.Fatalf("Expected 1 row but %v", counter) - } - - if id != 2 && fbool { - t.Fatalf("Value for id 2 should be %v, not %v", bool2, fbool) - } - - // make sure "nonsense" triggered an error - rows, err = db.Query("SELECT id, fbool FROM foo where id=?;", 3) - if err != nil { - t.Fatal("Unable to query foo table:", err) - } - - rows.Next() - err = rows.Scan(&id, &fbool) - if err == nil { - t.Error("Expected error from \"nonsense\" bool") - } -} - -func TestFloat32(t *testing.T) { - tempFilename := TempFilename(t) - defer os.Remove(tempFilename) - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer db.Close() - - _, err = db.Exec("CREATE TABLE foo(id INTEGER)") - if err != nil { - t.Fatal("Failed to create table:", err) - } - - _, err = db.Exec("INSERT INTO foo(id) VALUES(null)") - if err != nil { - t.Fatal("Failed to insert null:", err) - } - - rows, err := db.Query("SELECT id FROM foo") - if err != nil { - t.Fatal("Unable to query foo table:", err) - } - - if !rows.Next() { - t.Fatal("Unable to query results:", err) - } - - var id interface{} - if err := rows.Scan(&id); err != nil { - t.Fatal("Unable to scan results:", err) - } - if id != nil { - t.Error("Expected nil but not") - } -} - -func TestNull(t *testing.T) { - tempFilename := TempFilename(t) - defer os.Remove(tempFilename) - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer db.Close() - - rows, err := db.Query("SELECT 3.141592") - if err != nil { - t.Fatal("Unable to query foo table:", err) - } - - if !rows.Next() { - t.Fatal("Unable to query results:", err) - } - - var v interface{} - if err := rows.Scan(&v); err != nil { - t.Fatal("Unable to scan results:", err) - } - f, ok := v.(float64) - if !ok { - t.Error("Expected float but not") - } - if f != 3.141592 { - t.Error("Expected 3.141592 but not") - } -} - -func TestTransaction(t *testing.T) { - tempFilename := TempFilename(t) - defer os.Remove(tempFilename) - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer db.Close() - - _, err = db.Exec("CREATE TABLE foo(id INTEGER)") - if err != nil { - t.Fatal("Failed to create table:", err) - } - - tx, err := db.Begin() - if err != nil { - t.Fatal("Failed to begin transaction:", err) - } - - _, err = tx.Exec("INSERT INTO foo(id) VALUES(1)") - if err != nil { - t.Fatal("Failed to insert null:", err) - } - - rows, err := tx.Query("SELECT id from foo") - if err != nil { - t.Fatal("Unable to query foo table:", err) - } - - err = tx.Rollback() - if err != nil { - t.Fatal("Failed to rollback transaction:", err) - } - - if rows.Next() { - t.Fatal("Unable to query results:", err) - } - - tx, err = db.Begin() - if err != nil { - t.Fatal("Failed to begin transaction:", err) - } - - _, err = tx.Exec("INSERT INTO foo(id) VALUES(1)") - if err != nil { - t.Fatal("Failed to insert null:", err) - } - - err = tx.Commit() - if err != nil { - t.Fatal("Failed to commit transaction:", err) - } - - rows, err = tx.Query("SELECT id from foo") - if err == nil { - t.Fatal("Expected failure to query") - } -} - -func TestWAL(t *testing.T) { - tempFilename := TempFilename(t) - defer os.Remove(tempFilename) - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer db.Close() - - if _, err = db.Exec("PRAGMA journal_mode=WAL;"); err != nil { - t.Fatal("Failed to Exec PRAGMA journal_mode:", err) - } - if _, err = db.Exec("PRAGMA locking_mode=EXCLUSIVE;"); err != nil { - t.Fatal("Failed to Exec PRAGMA locking_mode:", err) - } - if _, err = db.Exec("CREATE TABLE test (id SERIAL, user TEXT NOT NULL, name TEXT NOT NULL);"); err != nil { - t.Fatal("Failed to Exec CREATE TABLE:", err) - } - if _, err = db.Exec("INSERT INTO test (user, name) VALUES ('user','name');"); err != nil { - t.Fatal("Failed to Exec INSERT:", err) - } - - trans, err := db.Begin() - if err != nil { - t.Fatal("Failed to Begin:", err) - } - s, err := trans.Prepare("INSERT INTO test (user, name) VALUES (?, ?);") - if err != nil { - t.Fatal("Failed to Prepare:", err) - } - - var count int - if err = trans.QueryRow("SELECT count(user) FROM test;").Scan(&count); err != nil { - t.Fatal("Failed to QueryRow:", err) - } - if _, err = s.Exec("bbbb", "aaaa"); err != nil { - t.Fatal("Failed to Exec prepared statement:", err) - } - if err = s.Close(); err != nil { - t.Fatal("Failed to Close prepared statement:", err) - } - if err = trans.Commit(); err != nil { - t.Fatal("Failed to Commit:", err) - } -} - -func TestTimezoneConversion(t *testing.T) { - zones := []string{"UTC", "US/Central", "US/Pacific", "Local"} - for _, tz := range zones { - tempFilename := TempFilename(t) - defer os.Remove(tempFilename) - db, err := sql.Open("sqlite3", tempFilename+"?_loc="+url.QueryEscape(tz)) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer db.Close() - - _, err = db.Exec("DROP TABLE foo") - _, err = db.Exec("CREATE TABLE foo(id INTEGER, ts TIMESTAMP, dt DATETIME)") - if err != nil { - t.Fatal("Failed to create table:", err) - } - - loc, err := time.LoadLocation(tz) - if err != nil { - t.Fatal("Failed to load location:", err) - } - - timestamp1 := time.Date(2012, time.April, 6, 22, 50, 0, 0, time.UTC) - timestamp2 := time.Date(2006, time.January, 2, 15, 4, 5, 123456789, time.UTC) - timestamp3 := time.Date(2012, time.November, 4, 0, 0, 0, 0, time.UTC) - tests := []struct { - value interface{} - expected time.Time - }{ - {"nonsense", time.Time{}.In(loc)}, - {"0000-00-00 00:00:00", time.Time{}.In(loc)}, - {timestamp1, timestamp1.In(loc)}, - {timestamp1.Unix(), timestamp1.In(loc)}, - {timestamp1.In(time.FixedZone("TEST", -7*3600)), timestamp1.In(loc)}, - {timestamp1.Format("2006-01-02 15:04:05.000"), timestamp1.In(loc)}, - {timestamp1.Format("2006-01-02T15:04:05.000"), timestamp1.In(loc)}, - {timestamp1.Format("2006-01-02 15:04:05"), timestamp1.In(loc)}, - {timestamp1.Format("2006-01-02T15:04:05"), timestamp1.In(loc)}, - {timestamp2, timestamp2.In(loc)}, - {"2006-01-02 15:04:05.123456789", timestamp2.In(loc)}, - {"2006-01-02T15:04:05.123456789", timestamp2.In(loc)}, - {"2012-11-04", timestamp3.In(loc)}, - {"2012-11-04 00:00", timestamp3.In(loc)}, - {"2012-11-04 00:00:00", timestamp3.In(loc)}, - {"2012-11-04 00:00:00.000", timestamp3.In(loc)}, - {"2012-11-04T00:00", timestamp3.In(loc)}, - {"2012-11-04T00:00:00", timestamp3.In(loc)}, - {"2012-11-04T00:00:00.000", timestamp3.In(loc)}, - } - for i := range tests { - _, err = db.Exec("INSERT INTO foo(id, ts, dt) VALUES(?, ?, ?)", i, tests[i].value, tests[i].value) - if err != nil { - t.Fatal("Failed to insert timestamp:", err) - } - } - - rows, err := db.Query("SELECT id, ts, dt FROM foo ORDER BY id ASC") - if err != nil { - t.Fatal("Unable to query foo table:", err) - } - defer rows.Close() - - seen := 0 - for rows.Next() { - var id int - var ts, dt time.Time - - if err := rows.Scan(&id, &ts, &dt); err != nil { - t.Error("Unable to scan results:", err) - continue - } - if id < 0 || id >= len(tests) { - t.Error("Bad row id: ", id) - continue - } - seen++ - if !tests[id].expected.Equal(ts) { - t.Errorf("Timestamp value for id %v (%v) should be %v, not %v", id, tests[id].value, tests[id].expected, ts) - } - if !tests[id].expected.Equal(dt) { - t.Errorf("Datetime value for id %v (%v) should be %v, not %v", id, tests[id].value, tests[id].expected, dt) - } - if tests[id].expected.Location().String() != ts.Location().String() { - t.Errorf("Location for id %v (%v) should be %v, not %v", id, tests[id].value, tests[id].expected.Location().String(), ts.Location().String()) - } - if tests[id].expected.Location().String() != dt.Location().String() { - t.Errorf("Location for id %v (%v) should be %v, not %v", id, tests[id].value, tests[id].expected.Location().String(), dt.Location().String()) - } - } - - if seen != len(tests) { - t.Errorf("Expected to see %d rows", len(tests)) - } - } -} - -// TODO: Execer & Queryer currently disabled -// https://github.com/mattn/go-sqlite3/issues/82 -func TestExecer(t *testing.T) { - tempFilename := TempFilename(t) - defer os.Remove(tempFilename) - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer db.Close() - - _, err = db.Exec(` - create table foo (id integer); -- one comment - insert into foo(id) values(?); - insert into foo(id) values(?); - insert into foo(id) values(?); -- another comment - `, 1, 2, 3) - if err != nil { - t.Error("Failed to call db.Exec:", err) - } -} - -func TestQueryer(t *testing.T) { - tempFilename := TempFilename(t) - defer os.Remove(tempFilename) - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer db.Close() - - _, err = db.Exec(` - create table foo (id integer); - `) - if err != nil { - t.Error("Failed to call db.Query:", err) - } - - rows, err := db.Query(` - insert into foo(id) values(?); - insert into foo(id) values(?); - insert into foo(id) values(?); - select id from foo order by id; - `, 3, 2, 1) - if err != nil { - t.Error("Failed to call db.Query:", err) - } - defer rows.Close() - n := 1 - if rows != nil { - for rows.Next() { - var id int - err = rows.Scan(&id) - if err != nil { - t.Error("Failed to db.Query:", err) - } - if id != n { - t.Error("Failed to db.Query: not matched results") - } - } - } -} - -func TestStress(t *testing.T) { - tempFilename := TempFilename(t) - defer os.Remove(tempFilename) - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - db.Exec("CREATE TABLE foo (id int);") - db.Exec("INSERT INTO foo VALUES(1);") - db.Exec("INSERT INTO foo VALUES(2);") - db.Close() - - for i := 0; i < 10000; i++ { - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - - for j := 0; j < 3; j++ { - rows, err := db.Query("select * from foo where id=1;") - if err != nil { - t.Error("Failed to call db.Query:", err) - } - for rows.Next() { - var i int - if err := rows.Scan(&i); err != nil { - t.Errorf("Scan failed: %v\n", err) - } - } - if err := rows.Err(); err != nil { - t.Errorf("Post-scan failed: %v\n", err) - } - rows.Close() - } - db.Close() - } -} - -func TestDateTimeLocal(t *testing.T) { - zone := "Asia/Tokyo" - tempFilename := TempFilename(t) - defer os.Remove(tempFilename) - db, err := sql.Open("sqlite3", tempFilename+"?_loc="+zone) - if err != nil { - t.Fatal("Failed to open database:", err) - } - db.Exec("CREATE TABLE foo (dt datetime);") - db.Exec("INSERT INTO foo VALUES('2015-03-05 15:16:17');") - - row := db.QueryRow("select * from foo") - var d time.Time - err = row.Scan(&d) - if err != nil { - t.Fatal("Failed to scan datetime:", err) - } - if d.Hour() == 15 || !strings.Contains(d.String(), "JST") { - t.Fatal("Result should have timezone", d) - } - db.Close() - - db, err = sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - - row = db.QueryRow("select * from foo") - err = row.Scan(&d) - if err != nil { - t.Fatal("Failed to scan datetime:", err) - } - if d.UTC().Hour() != 15 || !strings.Contains(d.String(), "UTC") { - t.Fatalf("Result should not have timezone %v %v", zone, d.String()) - } - - _, err = db.Exec("DELETE FROM foo") - if err != nil { - t.Fatal("Failed to delete table:", err) - } - dt, err := time.Parse("2006/1/2 15/4/5 -0700 MST", "2015/3/5 15/16/17 +0900 JST") - if err != nil { - t.Fatal("Failed to parse datetime:", err) - } - db.Exec("INSERT INTO foo VALUES(?);", dt) - - db.Close() - db, err = sql.Open("sqlite3", tempFilename+"?_loc="+zone) - if err != nil { - t.Fatal("Failed to open database:", err) - } - - row = db.QueryRow("select * from foo") - err = row.Scan(&d) - if err != nil { - t.Fatal("Failed to scan datetime:", err) - } - if d.Hour() != 15 || !strings.Contains(d.String(), "JST") { - t.Fatalf("Result should have timezone %v %v", zone, d.String()) - } -} - -func TestVersion(t *testing.T) { - s, n, id := Version() - if s == "" || n == 0 || id == "" { - t.Errorf("Version failed %q, %d, %q\n", s, n, id) - } -} - -func TestStringContainingZero(t *testing.T) { - tempFilename := TempFilename(t) - defer os.Remove(tempFilename) - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer db.Close() - - _, err = db.Exec(` - create table foo (id integer, name, extra text); - `) - if err != nil { - t.Error("Failed to call db.Query:", err) - } - - const text = "foo\x00bar" - - _, err = db.Exec(`insert into foo(id, name, extra) values($1, $2, $2)`, 1, text) - if err != nil { - t.Error("Failed to call db.Exec:", err) - } - - row := db.QueryRow(`select id, extra from foo where id = $1 and extra = $2`, 1, text) - if row == nil { - t.Error("Failed to call db.QueryRow") - } - - var id int - var extra string - err = row.Scan(&id, &extra) - if err != nil { - t.Error("Failed to db.Scan:", err) - } - if id != 1 || extra != text { - t.Error("Failed to db.QueryRow: not matched results") - } -} - -const CurrentTimeStamp = "2006-01-02 15:04:05" - -type TimeStamp struct{ *time.Time } - -func (t TimeStamp) Scan(value interface{}) error { - var err error - switch v := value.(type) { - case string: - *t.Time, err = time.Parse(CurrentTimeStamp, v) - case []byte: - *t.Time, err = time.Parse(CurrentTimeStamp, string(v)) - default: - err = errors.New("invalid type for current_timestamp") - } - return err -} - -func (t TimeStamp) Value() (driver.Value, error) { - return t.Time.Format(CurrentTimeStamp), nil -} - -func TestDateTimeNow(t *testing.T) { - tempFilename := TempFilename(t) - defer os.Remove(tempFilename) - db, err := sql.Open("sqlite3", tempFilename) - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer db.Close() - - var d time.Time - err = db.QueryRow("SELECT datetime('now')").Scan(TimeStamp{&d}) - if err != nil { - t.Fatal("Failed to scan datetime:", err) - } -} - -func TestFunctionRegistration(t *testing.T) { - addi8_16_32 := func(a int8, b int16) int32 { return int32(a) + int32(b) } - addi64 := func(a, b int64) int64 { return a + b } - addu8_16_32 := func(a uint8, b uint16) uint32 { return uint32(a) + uint32(b) } - addu64 := func(a, b uint64) uint64 { return a + b } - addiu := func(a int, b uint) int64 { return int64(a) + int64(b) } - addf32_64 := func(a float32, b float64) float64 { return float64(a) + b } - not := func(a bool) bool { return !a } - regex := func(re, s string) (bool, error) { - return regexp.MatchString(re, s) - } - generic := func(a interface{}) int64 { - switch a.(type) { - case int64: - return 1 - case float64: - return 2 - case []byte: - return 3 - case string: - return 4 - default: - panic("unreachable") - } - } - variadic := func(a, b int64, c ...int64) int64 { - ret := a + b - for _, d := range c { - ret += d - } - return ret - } - variadicGeneric := func(a ...interface{}) int64 { - return int64(len(a)) - } - - sql.Register("sqlite3_FunctionRegistration", &SQLiteDriver{ - ConnectHook: func(conn *SQLiteConn) error { - if err := conn.RegisterFunc("addi8_16_32", addi8_16_32, true); err != nil { - return err - } - if err := conn.RegisterFunc("addi64", addi64, true); err != nil { - return err - } - if err := conn.RegisterFunc("addu8_16_32", addu8_16_32, true); err != nil { - return err - } - if err := conn.RegisterFunc("addu64", addu64, true); err != nil { - return err - } - if err := conn.RegisterFunc("addiu", addiu, true); err != nil { - return err - } - if err := conn.RegisterFunc("addf32_64", addf32_64, true); err != nil { - return err - } - if err := conn.RegisterFunc("not", not, true); err != nil { - return err - } - if err := conn.RegisterFunc("regex", regex, true); err != nil { - return err - } - if err := conn.RegisterFunc("generic", generic, true); err != nil { - return err - } - if err := conn.RegisterFunc("variadic", variadic, true); err != nil { - return err - } - if err := conn.RegisterFunc("variadicGeneric", variadicGeneric, true); err != nil { - return err - } - return nil - }, - }) - db, err := sql.Open("sqlite3_FunctionRegistration", ":memory:") - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer db.Close() - - ops := []struct { - query string - expected interface{} - }{ - {"SELECT addi8_16_32(1,2)", int32(3)}, - {"SELECT addi64(1,2)", int64(3)}, - {"SELECT addu8_16_32(1,2)", uint32(3)}, - {"SELECT addu64(1,2)", uint64(3)}, - {"SELECT addiu(1,2)", int64(3)}, - {"SELECT addf32_64(1.5,1.5)", float64(3)}, - {"SELECT not(1)", false}, - {"SELECT not(0)", true}, - {`SELECT regex("^foo.*", "foobar")`, true}, - {`SELECT regex("^foo.*", "barfoobar")`, false}, - {"SELECT generic(1)", int64(1)}, - {"SELECT generic(1.1)", int64(2)}, - {`SELECT generic(NULL)`, int64(3)}, - {`SELECT generic("foo")`, int64(4)}, - {"SELECT variadic(1,2)", int64(3)}, - {"SELECT variadic(1,2,3,4)", int64(10)}, - {"SELECT variadic(1,1,1,1,1,1,1,1,1,1)", int64(10)}, - {`SELECT variadicGeneric(1,"foo",2.3, NULL)`, int64(4)}, - } - - for _, op := range ops { - ret := reflect.New(reflect.TypeOf(op.expected)) - err = db.QueryRow(op.query).Scan(ret.Interface()) - if err != nil { - t.Errorf("Query %q failed: %s", op.query, err) - } else if !reflect.DeepEqual(ret.Elem().Interface(), op.expected) { - t.Errorf("Query %q returned wrong value: got %v (%T), want %v (%T)", op.query, ret.Elem().Interface(), ret.Elem().Interface(), op.expected, op.expected) - } - } -} - -type sumAggregator int64 - -func (s *sumAggregator) Step(x int64) { - *s += sumAggregator(x) -} - -func (s *sumAggregator) Done() int64 { - return int64(*s) -} - -func TestAggregatorRegistration(t *testing.T) { - customSum := func() *sumAggregator { - var ret sumAggregator - return &ret - } - - sql.Register("sqlite3_AggregatorRegistration", &SQLiteDriver{ - ConnectHook: func(conn *SQLiteConn) error { - if err := conn.RegisterAggregator("customSum", customSum, true); err != nil { - return err - } - return nil - }, - }) - db, err := sql.Open("sqlite3_AggregatorRegistration", ":memory:") - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer db.Close() - - _, err = db.Exec("create table foo (department integer, profits integer)") - if err != nil { - // trace feature is not implemented - t.Skip("Failed to create table:", err) - } - - _, err = db.Exec("insert into foo values (1, 10), (1, 20), (2, 42)") - if err != nil { - t.Fatal("Failed to insert records:", err) - } - - tests := []struct { - dept, sum int64 - }{ - {1, 30}, - {2, 42}, - } - - for _, test := range tests { - var ret int64 - err = db.QueryRow("select customSum(profits) from foo where department = $1 group by department", test.dept).Scan(&ret) - if err != nil { - t.Fatal("Query failed:", err) - } - if ret != test.sum { - t.Fatalf("Custom sum returned wrong value, got %d, want %d", ret, test.sum) - } - } -} - -func rot13(r rune) rune { - switch { - case r >= 'A' && r <= 'Z': - return 'A' + (r-'A'+13)%26 - case r >= 'a' && r <= 'z': - return 'a' + (r-'a'+13)%26 - } - return r -} - -func TestCollationRegistration(t *testing.T) { - collateRot13 := func(a, b string) int { - ra, rb := strings.Map(rot13, a), strings.Map(rot13, b) - return strings.Compare(ra, rb) - } - collateRot13Reverse := func(a, b string) int { - return collateRot13(b, a) - } - - sql.Register("sqlite3_CollationRegistration", &SQLiteDriver{ - ConnectHook: func(conn *SQLiteConn) error { - if err := conn.RegisterCollation("rot13", collateRot13); err != nil { - return err - } - if err := conn.RegisterCollation("rot13reverse", collateRot13Reverse); err != nil { - return err - } - return nil - }, - }) - - db, err := sql.Open("sqlite3_CollationRegistration", ":memory:") - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer db.Close() - - populate := []string{ - `CREATE TABLE test (s TEXT)`, - `INSERT INTO test VALUES ("aaaa")`, - `INSERT INTO test VALUES ("ffff")`, - `INSERT INTO test VALUES ("qqqq")`, - `INSERT INTO test VALUES ("tttt")`, - `INSERT INTO test VALUES ("zzzz")`, - } - for _, stmt := range populate { - if _, err := db.Exec(stmt); err != nil { - t.Fatal("Failed to populate test DB:", err) - } - } - - ops := []struct { - query string - want []string - }{ - { - "SELECT * FROM test ORDER BY s COLLATE rot13 ASC", - []string{ - "qqqq", - "tttt", - "zzzz", - "aaaa", - "ffff", - }, - }, - { - "SELECT * FROM test ORDER BY s COLLATE rot13 DESC", - []string{ - "ffff", - "aaaa", - "zzzz", - "tttt", - "qqqq", - }, - }, - { - "SELECT * FROM test ORDER BY s COLLATE rot13reverse ASC", - []string{ - "ffff", - "aaaa", - "zzzz", - "tttt", - "qqqq", - }, - }, - { - "SELECT * FROM test ORDER BY s COLLATE rot13reverse DESC", - []string{ - "qqqq", - "tttt", - "zzzz", - "aaaa", - "ffff", - }, - }, - } - - for _, op := range ops { - rows, err := db.Query(op.query) - if err != nil { - t.Fatalf("Query %q failed: %s", op.query, err) - } - got := []string{} - defer rows.Close() - for rows.Next() { - var s string - if err = rows.Scan(&s); err != nil { - t.Fatalf("Reading row for %q: %s", op.query, err) - } - got = append(got, s) - } - if err = rows.Err(); err != nil { - t.Fatalf("Reading rows for %q: %s", op.query, err) - } - - if !reflect.DeepEqual(got, op.want) { - t.Fatalf("Unexpected output from %q\ngot:\n%s\n\nwant:\n%s", op.query, strings.Join(got, "\n"), strings.Join(op.want, "\n")) - } - } -} - -func TestDeclTypes(t *testing.T) { - - d := SQLiteDriver{} - - conn, err := d.Open(":memory:") - if err != nil { - t.Fatal("Failed to begin transaction:", err) - } - defer conn.Close() - - sqlite3conn := conn.(*SQLiteConn) - - _, err = sqlite3conn.Exec("create table foo (id integer not null primary key, name text)", nil) - if err != nil { - t.Fatal("Failed to create table:", err) - } - - _, err = sqlite3conn.Exec("insert into foo(name) values(\"bar\")", nil) - if err != nil { - t.Fatal("Failed to insert:", err) - } - - rs, err := sqlite3conn.Query("select * from foo", nil) - if err != nil { - t.Fatal("Failed to select:", err) - } - defer rs.Close() - - declTypes := rs.(*SQLiteRows).DeclTypes() - - if !reflect.DeepEqual(declTypes, []string{"integer", "text"}) { - t.Fatal("Unexpected declTypes:", declTypes) - } -} - -func TestPinger(t *testing.T) { - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - t.Fatal(err) - } - err = db.Ping() - if err != nil { - t.Fatal(err) - } - db.Close() - err = db.Ping() - if err == nil { - t.Fatal("Should be closed") - } -} - -func TestUpdateAndTransactionHooks(t *testing.T) { - var events []string - var commitHookReturn = 0 - - sql.Register("sqlite3_UpdateHook", &SQLiteDriver{ - ConnectHook: func(conn *SQLiteConn) error { - conn.RegisterCommitHook(func() int { - events = append(events, "commit") - return commitHookReturn - }) - conn.RegisterRollbackHook(func() { - events = append(events, "rollback") - }) - conn.RegisterUpdateHook(func(op int, db string, table string, rowid int64) { - events = append(events, fmt.Sprintf("update(op=%v db=%v table=%v rowid=%v)", op, db, table, rowid)) - }) - return nil - }, - }) - db, err := sql.Open("sqlite3_UpdateHook", ":memory:") - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer db.Close() - - statements := []string{ - "create table foo (id integer primary key)", - "insert into foo values (9)", - "update foo set id = 99 where id = 9", - "delete from foo where id = 99", - } - for _, statement := range statements { - _, err = db.Exec(statement) - if err != nil { - t.Fatalf("Unable to prepare test data [%v]: %v", statement, err) - } - } - - commitHookReturn = 1 - _, err = db.Exec("insert into foo values (5)") - if err == nil { - t.Error("Commit hook failed to rollback transaction") - } - - var expected = []string{ - "commit", - fmt.Sprintf("update(op=%v db=main table=foo rowid=9)", SQLITE_INSERT), - "commit", - fmt.Sprintf("update(op=%v db=main table=foo rowid=99)", SQLITE_UPDATE), - "commit", - fmt.Sprintf("update(op=%v db=main table=foo rowid=99)", SQLITE_DELETE), - "commit", - fmt.Sprintf("update(op=%v db=main table=foo rowid=5)", SQLITE_INSERT), - "commit", - "rollback", - } - if !reflect.DeepEqual(events, expected) { - t.Errorf("Expected notifications %v but got %v", expected, events) - } -} - -func TestAuthorizer(t *testing.T) { - var authorizerReturn = 0 - - sql.Register("sqlite3_Authorizer", &SQLiteDriver{ - ConnectHook: func(conn *SQLiteConn) error { - conn.RegisterAuthorizer(func(op int, arg1, arg2, arg3 string) int { - return authorizerReturn - }) - return nil - }, - }) - db, err := sql.Open("sqlite3_Authorizer", ":memory:") - if err != nil { - t.Fatal("Failed to open database:", err) - } - defer db.Close() - - statements := []string{ - "create table foo (id integer primary key, name varchar)", - "insert into foo values (9, 'test9')", - "update foo set name = 'test99' where id = 9", - "select * from foo", - } - - authorizerReturn = SQLITE_OK - for _, statement := range statements { - _, err = db.Exec(statement) - if err != nil { - t.Fatalf("No error expected [%v]: %v", statement, err) - } - } - - authorizerReturn = SQLITE_DENY - for _, statement := range statements { - _, err = db.Exec(statement) - if err == nil { - t.Fatalf("Authorizer didn't worked - nil received, but error expected: [%v]", statement) - } - } -} - -func TestNilAndEmptyBytes(t *testing.T) { - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - t.Fatal(err) - } - defer db.Close() - actualNil := []byte("use this to use an actual nil not a reference to nil") - emptyBytes := []byte{} - for tsti, tst := range []struct { - name string - columnType string - insertBytes []byte - expectedBytes []byte - }{ - {"actual nil blob", "blob", actualNil, nil}, - {"referenced nil blob", "blob", nil, nil}, - {"empty blob", "blob", emptyBytes, emptyBytes}, - {"actual nil text", "text", actualNil, nil}, - {"referenced nil text", "text", nil, nil}, - {"empty text", "text", emptyBytes, emptyBytes}, - } { - if _, err = db.Exec(fmt.Sprintf("create table tbl%d (txt %s)", tsti, tst.columnType)); err != nil { - t.Fatal(tst.name, err) - } - if bytes.Equal(tst.insertBytes, actualNil) { - if _, err = db.Exec(fmt.Sprintf("insert into tbl%d (txt) values (?)", tsti), nil); err != nil { - t.Fatal(tst.name, err) - } - } else { - if _, err = db.Exec(fmt.Sprintf("insert into tbl%d (txt) values (?)", tsti), &tst.insertBytes); err != nil { - t.Fatal(tst.name, err) - } - } - rows, err := db.Query(fmt.Sprintf("select txt from tbl%d", tsti)) - if err != nil { - t.Fatal(tst.name, err) - } - if !rows.Next() { - t.Fatal(tst.name, "no rows") - } - var scanBytes []byte - if err = rows.Scan(&scanBytes); err != nil { - t.Fatal(tst.name, err) - } - if err = rows.Err(); err != nil { - t.Fatal(tst.name, err) - } - if tst.expectedBytes == nil && scanBytes != nil { - t.Errorf("%s: %#v != %#v", tst.name, scanBytes, tst.expectedBytes) - } else if !bytes.Equal(scanBytes, tst.expectedBytes) { - t.Errorf("%s: %#v != %#v", tst.name, scanBytes, tst.expectedBytes) - } - } -} - -func TestInsertNilByteSlice(t *testing.T) { - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - t.Fatal(err) - } - defer db.Close() - if _, err := db.Exec("create table blob_not_null (b blob not null)"); err != nil { - t.Fatal(err) - } - var nilSlice []byte - if _, err := db.Exec("insert into blob_not_null (b) values (?)", nilSlice); err == nil { - t.Fatal("didn't expect INSERT to 'not null' column with a nil []byte slice to work") - } - zeroLenSlice := []byte{} - if _, err := db.Exec("insert into blob_not_null (b) values (?)", zeroLenSlice); err != nil { - t.Fatal("failed to insert zero-length slice") - } -} - -var customFunctionOnce sync.Once - -func BenchmarkCustomFunctions(b *testing.B) { - customFunctionOnce.Do(func() { - customAdd := func(a, b int64) int64 { - return a + b - } - - sql.Register("sqlite3_BenchmarkCustomFunctions", &SQLiteDriver{ - ConnectHook: func(conn *SQLiteConn) error { - // Impure function to force sqlite to reexecute it each time. - return conn.RegisterFunc("custom_add", customAdd, false) - }, - }) - }) - - db, err := sql.Open("sqlite3_BenchmarkCustomFunctions", ":memory:") - if err != nil { - b.Fatal("Failed to open database:", err) - } - defer db.Close() - - b.ResetTimer() - for i := 0; i < b.N; i++ { - var i int64 - err = db.QueryRow("SELECT custom_add(1,2)").Scan(&i) - if err != nil { - b.Fatal("Failed to run custom add:", err) - } - } -} - -func TestSuite(t *testing.T) { - tempFilename := TempFilename(t) - defer os.Remove(tempFilename) - d, err := sql.Open("sqlite3", tempFilename+"?_busy_timeout=99999") - if err != nil { - t.Fatal(err) - } - defer d.Close() - - db = &TestDB{t, d, SQLITE, sync.Once{}} - ok := testing.RunTests(func(string, string) (bool, error) { return true, nil }, tests) - if !ok { - t.Fatal("A subtest failed") - } - - if !testing.Short() { - for _, b := range benchmarks { - fmt.Printf("%-20s", b.Name) - r := testing.Benchmark(b.F) - fmt.Printf("%10d %10.0f req/s\n", r.N, float64(r.N)/r.T.Seconds()) - } - } - db.tearDown() -} - -// Dialect is a type of dialect of databases. -type Dialect int - -// Dialects for databases. -const ( - SQLITE Dialect = iota // SQLITE mean SQLite3 dialect - POSTGRESQL // POSTGRESQL mean PostgreSQL dialect - MYSQL // MYSQL mean MySQL dialect -) - -// DB provide context for the tests -type TestDB struct { - *testing.T - *sql.DB - dialect Dialect - once sync.Once -} - -var db *TestDB - -// the following tables will be created and dropped during the test -var testTables = []string{"foo", "bar", "t", "bench"} - -var tests = []testing.InternalTest{ - {Name: "TestResult", F: testResult}, - {Name: "TestBlobs", F: testBlobs}, - {Name: "TestMultiBlobs", F: testMultiBlobs}, - {Name: "TestManyQueryRow", F: testManyQueryRow}, - {Name: "TestTxQuery", F: testTxQuery}, - {Name: "TestPreparedStmt", F: testPreparedStmt}, -} - -var benchmarks = []testing.InternalBenchmark{ - {Name: "BenchmarkExec", F: benchmarkExec}, - {Name: "BenchmarkQuery", F: benchmarkQuery}, - {Name: "BenchmarkParams", F: benchmarkParams}, - {Name: "BenchmarkStmt", F: benchmarkStmt}, - {Name: "BenchmarkRows", F: benchmarkRows}, - {Name: "BenchmarkStmtRows", F: benchmarkStmtRows}, -} - -func (db *TestDB) mustExec(sql string, args ...interface{}) sql.Result { - res, err := db.Exec(sql, args...) - if err != nil { - db.Fatalf("Error running %q: %v", sql, err) - } - return res -} - -func (db *TestDB) tearDown() { - for _, tbl := range testTables { - switch db.dialect { - case SQLITE: - db.mustExec("drop table if exists " + tbl) - case MYSQL, POSTGRESQL: - db.mustExec("drop table if exists " + tbl) - default: - db.Fatal("unknown dialect") - } - } -} - -// q replaces ? parameters if needed -func (db *TestDB) q(sql string) string { - switch db.dialect { - case POSTGRESQL: // replace with $1, $2, .. - qrx := regexp.MustCompile(`\?`) - n := 0 - return qrx.ReplaceAllStringFunc(sql, func(string) string { - n++ - return "$" + strconv.Itoa(n) - }) - } - return sql -} - -func (db *TestDB) blobType(size int) string { - switch db.dialect { - case SQLITE: - return fmt.Sprintf("blob[%d]", size) - case POSTGRESQL: - return "bytea" - case MYSQL: - return fmt.Sprintf("VARBINARY(%d)", size) - } - panic("unknown dialect") -} - -func (db *TestDB) serialPK() string { - switch db.dialect { - case SQLITE: - return "integer primary key autoincrement" - case POSTGRESQL: - return "serial primary key" - case MYSQL: - return "integer primary key auto_increment" - } - panic("unknown dialect") -} - -func (db *TestDB) now() string { - switch db.dialect { - case SQLITE: - return "datetime('now')" - case POSTGRESQL: - return "now()" - case MYSQL: - return "now()" - } - panic("unknown dialect") -} - -func makeBench() { - if _, err := db.Exec("create table bench (n varchar(32), i integer, d double, s varchar(32), t datetime)"); err != nil { - panic(err) - } - st, err := db.Prepare("insert into bench values (?, ?, ?, ?, ?)") - if err != nil { - panic(err) - } - defer st.Close() - for i := 0; i < 100; i++ { - if _, err = st.Exec(nil, i, float64(i), fmt.Sprintf("%d", i), time.Now()); err != nil { - panic(err) - } - } -} - -// testResult is test for result -func testResult(t *testing.T) { - db.tearDown() - db.mustExec("create temporary table test (id " + db.serialPK() + ", name varchar(10))") - - for i := 1; i < 3; i++ { - r := db.mustExec(db.q("insert into test (name) values (?)"), fmt.Sprintf("row %d", i)) - n, err := r.RowsAffected() - if err != nil { - t.Fatal(err) - } - if n != 1 { - t.Errorf("got %v, want %v", n, 1) - } - n, err = r.LastInsertId() - if err != nil { - t.Fatal(err) - } - if n != int64(i) { - t.Errorf("got %v, want %v", n, i) - } - } - if _, err := db.Exec("error!"); err == nil { - t.Fatalf("expected error") - } -} - -// testBlobs is test for blobs -func testBlobs(t *testing.T) { - db.tearDown() - var blob = []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} - db.mustExec("create table foo (id integer primary key, bar " + db.blobType(16) + ")") - db.mustExec(db.q("insert into foo (id, bar) values(?,?)"), 0, blob) - - want := fmt.Sprintf("%x", blob) - - b := make([]byte, 16) - err := db.QueryRow(db.q("select bar from foo where id = ?"), 0).Scan(&b) - got := fmt.Sprintf("%x", b) - if err != nil { - t.Errorf("[]byte scan: %v", err) - } else if got != want { - t.Errorf("for []byte, got %q; want %q", got, want) - } - - err = db.QueryRow(db.q("select bar from foo where id = ?"), 0).Scan(&got) - want = string(blob) - if err != nil { - t.Errorf("string scan: %v", err) - } else if got != want { - t.Errorf("for string, got %q; want %q", got, want) - } -} - -func testMultiBlobs(t *testing.T) { - db.tearDown() - db.mustExec("create table foo (id integer primary key, bar " + db.blobType(16) + ")") - var blob0 = []byte{0, 1, 2, 3, 4, 5, 6, 7} - db.mustExec(db.q("insert into foo (id, bar) values(?,?)"), 0, blob0) - var blob1 = []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} - db.mustExec(db.q("insert into foo (id, bar) values(?,?)"), 1, blob1) - - r, err := db.Query(db.q("select bar from foo order by id")) - if err != nil { - t.Fatal(err) - } - defer r.Close() - if !r.Next() { - if r.Err() != nil { - t.Fatal(err) - } - t.Fatal("expected one rows") - } - - want0 := fmt.Sprintf("%x", blob0) - b0 := make([]byte, 8) - err = r.Scan(&b0) - if err != nil { - t.Fatal(err) - } - got0 := fmt.Sprintf("%x", b0) - - if !r.Next() { - if r.Err() != nil { - t.Fatal(err) - } - t.Fatal("expected one rows") - } - - want1 := fmt.Sprintf("%x", blob1) - b1 := make([]byte, 16) - err = r.Scan(&b1) - if err != nil { - t.Fatal(err) - } - got1 := fmt.Sprintf("%x", b1) - if got0 != want0 { - t.Errorf("for []byte, got %q; want %q", got0, want0) - } - if got1 != want1 { - t.Errorf("for []byte, got %q; want %q", got1, want1) - } -} - -// testManyQueryRow is test for many query row -func testManyQueryRow(t *testing.T) { - if testing.Short() { - t.Log("skipping in short mode") - return - } - db.tearDown() - db.mustExec("create table foo (id integer primary key, name varchar(50))") - db.mustExec(db.q("insert into foo (id, name) values(?,?)"), 1, "bob") - var name string - for i := 0; i < 10000; i++ { - err := db.QueryRow(db.q("select name from foo where id = ?"), 1).Scan(&name) - if err != nil || name != "bob" { - t.Fatalf("on query %d: err=%v, name=%q", i, err, name) - } - } -} - -// testTxQuery is test for transactional query -func testTxQuery(t *testing.T) { - db.tearDown() - tx, err := db.Begin() - if err != nil { - t.Fatal(err) - } - defer tx.Rollback() - - _, err = tx.Exec("create table foo (id integer primary key, name varchar(50))") - if err != nil { - t.Fatal(err) - } - - _, err = tx.Exec(db.q("insert into foo (id, name) values(?,?)"), 1, "bob") - if err != nil { - t.Fatal(err) - } - - r, err := tx.Query(db.q("select name from foo where id = ?"), 1) - if err != nil { - t.Fatal(err) - } - defer r.Close() - - if !r.Next() { - if r.Err() != nil { - t.Fatal(err) - } - t.Fatal("expected one rows") - } - - var name string - err = r.Scan(&name) - if err != nil { - t.Fatal(err) - } -} - -// testPreparedStmt is test for prepared statement -func testPreparedStmt(t *testing.T) { - db.tearDown() - db.mustExec("CREATE TABLE t (count INT)") - sel, err := db.Prepare("SELECT count FROM t ORDER BY count DESC") - if err != nil { - t.Fatalf("prepare 1: %v", err) - } - ins, err := db.Prepare(db.q("INSERT INTO t (count) VALUES (?)")) - if err != nil { - t.Fatalf("prepare 2: %v", err) - } - - for n := 1; n <= 3; n++ { - if _, err := ins.Exec(n); err != nil { - t.Fatalf("insert(%d) = %v", n, err) - } - } - - const nRuns = 10 - var wg sync.WaitGroup - for i := 0; i < nRuns; i++ { - wg.Add(1) - go func() { - defer wg.Done() - for j := 0; j < 10; j++ { - count := 0 - if err := sel.QueryRow().Scan(&count); err != nil && err != sql.ErrNoRows { - t.Errorf("Query: %v", err) - return - } - if _, err := ins.Exec(rand.Intn(100)); err != nil { - t.Errorf("Insert: %v", err) - return - } - } - }() - } - wg.Wait() -} - -// Benchmarks need to use panic() since b.Error errors are lost when -// running via testing.Benchmark() I would like to run these via go -// test -bench but calling Benchmark() from a benchmark test -// currently hangs go. - -// benchmarkExec is benchmark for exec -func benchmarkExec(b *testing.B) { - for i := 0; i < b.N; i++ { - if _, err := db.Exec("select 1"); err != nil { - panic(err) - } - } -} - -// benchmarkQuery is benchmark for query -func benchmarkQuery(b *testing.B) { - for i := 0; i < b.N; i++ { - var n sql.NullString - var i int - var f float64 - var s string - // var t time.Time - if err := db.QueryRow("select null, 1, 1.1, 'foo'").Scan(&n, &i, &f, &s); err != nil { - panic(err) - } - } -} - -// benchmarkParams is benchmark for params -func benchmarkParams(b *testing.B) { - for i := 0; i < b.N; i++ { - var n sql.NullString - var i int - var f float64 - var s string - // var t time.Time - if err := db.QueryRow("select ?, ?, ?, ?", nil, 1, 1.1, "foo").Scan(&n, &i, &f, &s); err != nil { - panic(err) - } - } -} - -// benchmarkStmt is benchmark for statement -func benchmarkStmt(b *testing.B) { - st, err := db.Prepare("select ?, ?, ?, ?") - if err != nil { - panic(err) - } - defer st.Close() - - for n := 0; n < b.N; n++ { - var n sql.NullString - var i int - var f float64 - var s string - // var t time.Time - if err := st.QueryRow(nil, 1, 1.1, "foo").Scan(&n, &i, &f, &s); err != nil { - panic(err) - } - } -} - -// benchmarkRows is benchmark for rows -func benchmarkRows(b *testing.B) { - db.once.Do(makeBench) - - for n := 0; n < b.N; n++ { - var n sql.NullString - var i int - var f float64 - var s string - var t time.Time - r, err := db.Query("select * from bench") - if err != nil { - panic(err) - } - for r.Next() { - if err = r.Scan(&n, &i, &f, &s, &t); err != nil { - panic(err) - } - } - if err = r.Err(); err != nil { - panic(err) - } - } -} - -// benchmarkStmtRows is benchmark for statement rows -func benchmarkStmtRows(b *testing.B) { - db.once.Do(makeBench) - - st, err := db.Prepare("select * from bench") - if err != nil { - panic(err) - } - defer st.Close() - - for n := 0; n < b.N; n++ { - var n sql.NullString - var i int - var f float64 - var s string - var t time.Time - r, err := st.Query() - if err != nil { - panic(err) - } - for r.Next() { - if err = r.Scan(&n, &i, &f, &s, &t); err != nil { - panic(err) - } - } - if err = r.Err(); err != nil { - panic(err) - } - } -} diff --git a/vendor/github.com/msteinert/pam/README.md b/vendor/github.com/msteinert/pam/README.md deleted file mode 100644 index 66b38206..00000000 --- a/vendor/github.com/msteinert/pam/README.md +++ /dev/null @@ -1,30 +0,0 @@ -[![Build Status](https://travis-ci.org/msteinert/pam.svg?branch=master)](https://travis-ci.org/msteinert/pam) -[![GoDoc](https://godoc.org/github.com/msteinert/pam?status.svg)](http://godoc.org/github.com/msteinert/pam) -[![Coverage Status](https://coveralls.io/repos/msteinert/pam/badge.svg?branch=master)](https://coveralls.io/r/msteinert/pam?branch=master) -[![Go Report Card](http://goreportcard.com/badge/msteinert/pam)](http://goreportcard.com/report/msteinert/pam) - -# Go PAM - -This is a Go wrapper for the PAM application API. - -## Testing - -To run the full suite, the tests must be run as the root user. To setup your -system for testing, create a user named "test" with the password "secret". For -example: - -``` -$ sudo useradd test \ - -d /tmp/test \ - -p '$1$Qd8H95T5$RYSZQeoFbEB.gS19zS99A0' \ - -s /bin/false -``` - -Then execute the tests: - -``` -$ sudo GOPATH=$GOPATH $(which go) test -v -``` - -[1]: http://godoc.org/github.com/msteinert/pam -[2]: http://www.linux-pam.org/Linux-PAM-html/Linux-PAM_ADG.html diff --git a/vendor/github.com/msteinert/pam/callback_test.go b/vendor/github.com/msteinert/pam/callback_test.go deleted file mode 100644 index 45a84be7..00000000 --- a/vendor/github.com/msteinert/pam/callback_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package pam - -import ( - "reflect" - "testing" -) - -func TestCallback_001(t *testing.T) { - c := cbAdd(TestCallback_001) - v := cbGet(c) - if reflect.TypeOf(v) != reflect.TypeOf(TestCallback_001) { - t.Error("Received unexpected value") - } - cbDelete(c) -} - -func TestCallback_002(t *testing.T) { - defer func() { - recover() - }() - c := cbAdd(TestCallback_002) - cbGet(c + 1) - t.Error("Expected a panic") -} - -func TestCallback_003(t *testing.T) { - defer func() { - recover() - }() - c := cbAdd(TestCallback_003) - cbDelete(c + 1) - t.Error("Expected a panic") -} diff --git a/vendor/github.com/msteinert/pam/example_test.go b/vendor/github.com/msteinert/pam/example_test.go deleted file mode 100644 index aca24a1a..00000000 --- a/vendor/github.com/msteinert/pam/example_test.go +++ /dev/null @@ -1,53 +0,0 @@ -package pam_test - -import ( - "bufio" - "errors" - "fmt" - "log" - "os" - - "github.com/bgentry/speakeasy" - "github.com/msteinert/pam" -) - -// This example uses whatever default PAM service configuration is available -// on the system, and tries to authenticate any user. This should cause PAM -// to ask its conversation handler for a username and password, in sequence. -// -// This application will handle those requests by displaying the -// PAM-provided prompt and sending back the first line of stdin input -// it can read for each. -// -// Keep in mind that unless run as root (or setuid root), the only -// user's authentication that can succeed is that of the process owner. -func Example_authenticate() { - t, err := pam.StartFunc("", "", func(s pam.Style, msg string) (string, error) { - switch s { - case pam.PromptEchoOff: - return speakeasy.Ask(msg) - case pam.PromptEchoOn: - fmt.Print(msg + " ") - input, err := bufio.NewReader(os.Stdin).ReadString('\n') - if err != nil { - return "", err - } - return input[:len(input)-1], nil - case pam.ErrorMsg: - log.Print(msg) - return "", nil - case pam.TextInfo: - fmt.Println(msg) - return "", nil - } - return "", errors.New("Unrecognized message style") - }) - if err != nil { - log.Fatalf("Start: %s", err.Error()) - } - err = t.Authenticate(0) - if err != nil { - log.Fatalf("Authenticate: %s", err.Error()) - } - fmt.Println("Authentication succeeded!") -} diff --git a/vendor/github.com/msteinert/pam/transaction_test.go b/vendor/github.com/msteinert/pam/transaction_test.go deleted file mode 100644 index 6be678fa..00000000 --- a/vendor/github.com/msteinert/pam/transaction_test.go +++ /dev/null @@ -1,349 +0,0 @@ -package pam - -import ( - "errors" - "os/user" - "runtime" - "testing" -) - -func TestPAM_001(t *testing.T) { - u, _ := user.Current() - if u.Uid != "0" { - t.Skip("run this test as root") - } - p := "secret" - tx, err := StartFunc("", "test", func(s Style, msg string) (string, error) { - return p, nil - }) - if err != nil { - t.Fatalf("start #error: %v", err) - } - err = tx.Authenticate(0) - if err != nil { - t.Fatalf("authenticate #error: %v", err) - } - err = tx.AcctMgmt(Silent) - if err != nil { - t.Fatalf("acct_mgmt #error: %v", err) - } - err = tx.SetCred(Silent | EstablishCred) - if err != nil { - t.Fatalf("setcred #error: %v", err) - } - runtime.GC() -} - -func TestPAM_002(t *testing.T) { - u, _ := user.Current() - if u.Uid != "0" { - t.Skip("run this test as root") - } - tx, err := StartFunc("", "", func(s Style, msg string) (string, error) { - switch s { - case PromptEchoOn: - return "test", nil - case PromptEchoOff: - return "secret", nil - } - return "", errors.New("unexpected") - }) - if err != nil { - t.Fatalf("start #error: %v", err) - } - err = tx.Authenticate(0) - if err != nil { - t.Fatalf("authenticate #error: %v", err) - } - runtime.GC() -} - -type Credentials struct { - User string - Password string -} - -func (c Credentials) RespondPAM(s Style, msg string) (string, error) { - switch s { - case PromptEchoOn: - return c.User, nil - case PromptEchoOff: - return c.Password, nil - } - return "", errors.New("unexpected") -} - -func TestPAM_003(t *testing.T) { - u, _ := user.Current() - if u.Uid != "0" { - t.Skip("run this test as root") - } - c := Credentials{ - User: "test", - Password: "secret", - } - tx, err := Start("", "", c) - if err != nil { - t.Fatalf("start #error: %v", err) - } - err = tx.Authenticate(0) - if err != nil { - t.Fatalf("authenticate #error: %v", err) - } - runtime.GC() -} - -func TestPAM_004(t *testing.T) { - u, _ := user.Current() - if u.Uid != "0" { - t.Skip("run this test as root") - } - c := Credentials{ - Password: "secret", - } - tx, err := Start("", "test", c) - if err != nil { - t.Fatalf("start #error: %v", err) - } - err = tx.Authenticate(0) - if err != nil { - t.Fatalf("authenticate #error: %v", err) - } - runtime.GC() -} - -func TestPAM_005(t *testing.T) { - u, _ := user.Current() - if u.Uid != "0" { - t.Skip("run this test as root") - } - tx, err := StartFunc("passwd", "test", func(s Style, msg string) (string, error) { - return "secret", nil - }) - if err != nil { - t.Fatalf("start #error: %v", err) - } - err = tx.ChangeAuthTok(Silent) - if err != nil { - t.Fatalf("chauthtok #error: %v", err) - } - runtime.GC() -} - -func TestPAM_006(t *testing.T) { - u, _ := user.Current() - if u.Uid != "0" { - t.Skip("run this test as root") - } - tx, err := StartFunc("passwd", u.Username, func(s Style, msg string) (string, error) { - return "secret", nil - }) - if err != nil { - t.Fatalf("start #error: %v", err) - } - err = tx.OpenSession(Silent) - if err != nil { - t.Fatalf("open_session #error: %v", err) - } - err = tx.CloseSession(Silent) - if err != nil { - t.Fatalf("close_session #error: %v", err) - } - runtime.GC() -} - -func TestPAM_007(t *testing.T) { - u, _ := user.Current() - if u.Uid != "0" { - t.Skip("run this test as root") - } - tx, err := StartFunc("", "test", func(s Style, msg string) (string, error) { - return "", errors.New("Sorry, it didn't work") - }) - if err != nil { - t.Fatalf("start #error: %v", err) - } - err = tx.Authenticate(0) - if err == nil { - t.Fatalf("authenticate #expected an error") - } - s := err.Error() - if len(s) == 0 { - t.Fatalf("error #expected an error message") - } - runtime.GC() -} - -func TestItem(t *testing.T) { - tx, err := StartFunc("passwd", "test", func(s Style, msg string) (string, error) { - return "", nil - }) - - s, err := tx.GetItem(Service) - if err != nil { - t.Fatalf("getitem #error: %v", err) - } - if s != "passwd" { - t.Fatalf("getitem #error: expected passwd, got %v", s) - } - - s, err = tx.GetItem(User) - if err != nil { - t.Fatalf("getitem #error: %v", err) - } - if s != "test" { - t.Fatalf("getitem #error: expected test, got %v", s) - } - - err = tx.SetItem(User, "root") - if err != nil { - t.Fatalf("setitem #error: %v", err) - } - s, err = tx.GetItem(User) - if err != nil { - t.Fatalf("getitem #error: %v", err) - } - if s != "root" { - t.Fatalf("getitem #error: expected root, got %v", s) - } - runtime.GC() -} - -func TestEnv(t *testing.T) { - tx, err := StartFunc("", "", func(s Style, msg string) (string, error) { - return "", nil - }) - if err != nil { - t.Fatalf("start #error: %v", err) - } - - m, err := tx.GetEnvList() - if err != nil { - t.Fatalf("getenvlist #error: %v", err) - } - n := len(m) - if n != 0 { - t.Fatalf("putenv #error: expected 0 items, got %v", n) - } - - vals := []string{ - "VAL1=1", - "VAL2=2", - "VAL3=3", - } - for _, s := range vals { - err = tx.PutEnv(s) - if err != nil { - t.Fatalf("putenv #error: %v", err) - } - } - - s := tx.GetEnv("VAL0") - if s != "" { - t.Fatalf("getenv #error: expected \"\", got %v", s) - } - - s = tx.GetEnv("VAL1") - if s != "1" { - t.Fatalf("getenv #error: expected 1, got %v", s) - } - s = tx.GetEnv("VAL2") - if s != "2" { - t.Fatalf("getenv #error: expected 2, got %v", s) - } - s = tx.GetEnv("VAL3") - if s != "3" { - t.Fatalf("getenv #error: expected 3, got %v", s) - } - - m, err = tx.GetEnvList() - if err != nil { - t.Fatalf("getenvlist #error: %v", err) - } - n = len(m) - if n != 3 { - t.Fatalf("getenvlist #error: expected 3 items, got %v", n) - } - if m["VAL1"] != "1" { - t.Fatalf("getenvlist #error: expected 1, got %v", m["VAL1"]) - } - if m["VAL2"] != "2" { - t.Fatalf("getenvlist #error: expected 2, got %v", m["VAL1"]) - } - if m["VAL3"] != "3" { - t.Fatalf("getenvlist #error: expected 3, got %v", m["VAL1"]) - } - runtime.GC() -} - -func TestFailure_001(t *testing.T) { - tx := Transaction{} - _, err := tx.GetEnvList() - if err == nil { - t.Fatalf("getenvlist #expected an error") - } -} - -func TestFailure_002(t *testing.T) { - tx := Transaction{} - err := tx.PutEnv("") - if err == nil { - t.Fatalf("getenvlist #expected an error") - } -} - -func TestFailure_003(t *testing.T) { - tx := Transaction{} - err := tx.CloseSession(0) - if err == nil { - t.Fatalf("getenvlist #expected an error") - } -} - -func TestFailure_004(t *testing.T) { - tx := Transaction{} - err := tx.OpenSession(0) - if err == nil { - t.Fatalf("getenvlist #expected an error") - } -} - -func TestFailure_005(t *testing.T) { - tx := Transaction{} - err := tx.ChangeAuthTok(0) - if err == nil { - t.Fatalf("getenvlist #expected an error") - } -} - -func TestFailure_006(t *testing.T) { - tx := Transaction{} - err := tx.AcctMgmt(0) - if err == nil { - t.Fatalf("getenvlist #expected an error") - } -} - -func TestFailure_007(t *testing.T) { - tx := Transaction{} - err := tx.SetCred(0) - if err == nil { - t.Fatalf("getenvlist #expected an error") - } -} - -func TestFailure_008(t *testing.T) { - tx := Transaction{} - err := tx.SetItem(User, "test") - if err == nil { - t.Fatalf("getenvlist #expected an error") - } -} - -func TestFailure_009(t *testing.T) { - tx := Transaction{} - _, err := tx.GetItem(User) - if err == nil { - t.Fatalf("getenvlist #expected an error") - } -} diff --git a/vendor/go.opencensus.io/CONTRIBUTING.md b/vendor/go.opencensus.io/CONTRIBUTING.md deleted file mode 100644 index 3f3aed39..00000000 --- a/vendor/go.opencensus.io/CONTRIBUTING.md +++ /dev/null @@ -1,56 +0,0 @@ -# How to contribute - -We'd love to accept your patches and contributions to this project. There are -just a few small guidelines you need to follow. - -## Contributor License Agreement - -Contributions to this project must be accompanied by a Contributor License -Agreement. You (or your employer) retain the copyright to your contribution, -this simply gives us permission to use and redistribute your contributions as -part of the project. Head over to to see -your current agreements on file or to sign a new one. - -You generally only need to submit a CLA once, so if you've already submitted one -(even if it was for a different project), you probably don't need to do it -again. - -## Code reviews - -All submissions, including submissions by project members, require review. We -use GitHub pull requests for this purpose. Consult [GitHub Help] for more -information on using pull requests. - -[GitHub Help]: https://help.github.com/articles/about-pull-requests/ - -## Instructions - -Fork the repo, checkout the upstream repo to your GOPATH by: - -``` -$ go get -d go.opencensus.io -``` - -Add your fork as an origin: - -``` -cd $(go env GOPATH)/src/go.opencensus.io -git remote add fork git@github.com:YOUR_GITHUB_USERNAME/opencensus-go.git -``` - -Run tests: - -``` -$ go test ./... -``` - -Checkout a new branch, make modifications and push the branch to your fork: - -``` -$ git checkout -b feature -# edit files -$ git commit -$ git push fork feature -``` - -Open a pull request against the main opencensus-go repo. diff --git a/vendor/go.opencensus.io/Gopkg.lock b/vendor/go.opencensus.io/Gopkg.lock deleted file mode 100644 index 3be12ac8..00000000 --- a/vendor/go.opencensus.io/Gopkg.lock +++ /dev/null @@ -1,231 +0,0 @@ -# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. - - -[[projects]] - branch = "master" - digest = "1:eee9386329f4fcdf8d6c0def0c9771b634bdd5ba460d888aa98c17d59b37a76c" - name = "git.apache.org/thrift.git" - packages = ["lib/go/thrift"] - pruneopts = "UT" - revision = "6e67faa92827ece022380b211c2caaadd6145bf5" - source = "github.com/apache/thrift" - -[[projects]] - branch = "master" - digest = "1:d6afaeed1502aa28e80a4ed0981d570ad91b2579193404256ce672ed0a609e0d" - name = "github.com/beorn7/perks" - packages = ["quantile"] - pruneopts = "UT" - revision = "3a771d992973f24aa725d07868b467d1ddfceafb" - -[[projects]] - digest = "1:4c0989ca0bcd10799064318923b9bc2db6b4d6338dd75f3f2d86c3511aaaf5cf" - name = "github.com/golang/protobuf" - packages = [ - "proto", - "ptypes", - "ptypes/any", - "ptypes/duration", - "ptypes/timestamp", - ] - pruneopts = "UT" - revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5" - version = "v1.2.0" - -[[projects]] - digest = "1:ff5ebae34cfbf047d505ee150de27e60570e8c394b3b8fdbb720ff6ac71985fc" - name = "github.com/matttproud/golang_protobuf_extensions" - packages = ["pbutil"] - pruneopts = "UT" - revision = "c12348ce28de40eed0136aa2b644d0ee0650e56c" - version = "v1.0.1" - -[[projects]] - digest = "1:824c8f3aa4c5f23928fa84ebbd5ed2e9443b3f0cb958a40c1f2fbed5cf5e64b1" - name = "github.com/openzipkin/zipkin-go" - packages = [ - ".", - "idgenerator", - "model", - "propagation", - "reporter", - "reporter/http", - ] - pruneopts = "UT" - revision = "d455a5674050831c1e187644faa4046d653433c2" - version = "v0.1.1" - -[[projects]] - digest = "1:d14a5f4bfecf017cb780bdde1b6483e5deb87e12c332544d2c430eda58734bcb" - name = "github.com/prometheus/client_golang" - packages = [ - "prometheus", - "prometheus/promhttp", - ] - pruneopts = "UT" - revision = "c5b7fccd204277076155f10851dad72b76a49317" - version = "v0.8.0" - -[[projects]] - branch = "master" - digest = "1:2d5cd61daa5565187e1d96bae64dbbc6080dacf741448e9629c64fd93203b0d4" - name = "github.com/prometheus/client_model" - packages = ["go"] - pruneopts = "UT" - revision = "5c3871d89910bfb32f5fcab2aa4b9ec68e65a99f" - -[[projects]] - branch = "master" - digest = "1:63b68062b8968092eb86bedc4e68894bd096ea6b24920faca8b9dcf451f54bb5" - name = "github.com/prometheus/common" - packages = [ - "expfmt", - "internal/bitbucket.org/ww/goautoneg", - "model", - ] - pruneopts = "UT" - revision = "c7de2306084e37d54b8be01f3541a8464345e9a5" - -[[projects]] - branch = "master" - digest = "1:8c49953a1414305f2ff5465147ee576dd705487c35b15918fcd4efdc0cb7a290" - name = "github.com/prometheus/procfs" - packages = [ - ".", - "internal/util", - "nfs", - "xfs", - ] - pruneopts = "UT" - revision = "05ee40e3a273f7245e8777337fc7b46e533a9a92" - -[[projects]] - branch = "master" - digest = "1:deafe4ab271911fec7de5b693d7faae3f38796d9eb8622e2b9e7df42bb3dfea9" - name = "golang.org/x/net" - packages = [ - "context", - "http/httpguts", - "http2", - "http2/hpack", - "idna", - "internal/timeseries", - "trace", - ] - pruneopts = "UT" - revision = "922f4815f713f213882e8ef45e0d315b164d705c" - -[[projects]] - branch = "master" - digest = "1:e0140c0c868c6e0f01c0380865194592c011fe521d6e12d78bfd33e756fe018a" - name = "golang.org/x/sync" - packages = ["semaphore"] - pruneopts = "UT" - revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca" - -[[projects]] - branch = "master" - digest = "1:a3f00ac457c955fe86a41e1495e8f4c54cb5399d609374c5cc26aa7d72e542c8" - name = "golang.org/x/sys" - packages = ["unix"] - pruneopts = "UT" - revision = "3b58ed4ad3395d483fc92d5d14123ce2c3581fec" - -[[projects]] - digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" - name = "golang.org/x/text" - packages = [ - "collate", - "collate/build", - "internal/colltab", - "internal/gen", - "internal/tag", - "internal/triegen", - "internal/ucd", - "language", - "secure/bidirule", - "transform", - "unicode/bidi", - "unicode/cldr", - "unicode/norm", - "unicode/rangetable", - ] - pruneopts = "UT" - revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" - version = "v0.3.0" - -[[projects]] - branch = "master" - digest = "1:c0c17c94fe8bc1ab34e7f586a4a8b788c5e1f4f9f750ff23395b8b2f5a523530" - name = "google.golang.org/api" - packages = ["support/bundler"] - pruneopts = "UT" - revision = "e21acd801f91da814261b938941d193bb036441a" - -[[projects]] - branch = "master" - digest = "1:077c1c599507b3b3e9156d17d36e1e61928ee9b53a5b420f10f28ebd4a0b275c" - name = "google.golang.org/genproto" - packages = ["googleapis/rpc/status"] - pruneopts = "UT" - revision = "c66870c02cf823ceb633bcd05be3c7cda29976f4" - -[[projects]] - digest = "1:3dd7996ce6bf52dec6a2f69fa43e7c4cefea1d4dfa3c8ab7a5f8a9f7434e239d" - name = "google.golang.org/grpc" - packages = [ - ".", - "balancer", - "balancer/base", - "balancer/roundrobin", - "codes", - "connectivity", - "credentials", - "encoding", - "encoding/proto", - "grpclog", - "internal", - "internal/backoff", - "internal/channelz", - "internal/envconfig", - "internal/grpcrand", - "internal/transport", - "keepalive", - "metadata", - "naming", - "peer", - "resolver", - "resolver/dns", - "resolver/passthrough", - "stats", - "status", - "tap", - ] - pruneopts = "UT" - revision = "32fb0ac620c32ba40a4626ddf94d90d12cce3455" - version = "v1.14.0" - -[solve-meta] - analyzer-name = "dep" - analyzer-version = 1 - input-imports = [ - "git.apache.org/thrift.git/lib/go/thrift", - "github.com/golang/protobuf/proto", - "github.com/openzipkin/zipkin-go", - "github.com/openzipkin/zipkin-go/model", - "github.com/openzipkin/zipkin-go/reporter", - "github.com/openzipkin/zipkin-go/reporter/http", - "github.com/prometheus/client_golang/prometheus", - "github.com/prometheus/client_golang/prometheus/promhttp", - "golang.org/x/net/context", - "golang.org/x/net/http2", - "google.golang.org/api/support/bundler", - "google.golang.org/grpc", - "google.golang.org/grpc/codes", - "google.golang.org/grpc/grpclog", - "google.golang.org/grpc/metadata", - "google.golang.org/grpc/stats", - "google.golang.org/grpc/status", - ] - solver-name = "gps-cdcl" - solver-version = 1 diff --git a/vendor/go.opencensus.io/Gopkg.toml b/vendor/go.opencensus.io/Gopkg.toml deleted file mode 100644 index a9f3cd68..00000000 --- a/vendor/go.opencensus.io/Gopkg.toml +++ /dev/null @@ -1,36 +0,0 @@ -# For v0.x.y dependencies, prefer adding a constraints of the form: version=">= 0.x.y" -# to avoid locking to a particular minor version which can cause dep to not be -# able to find a satisfying dependency graph. - -[[constraint]] - branch = "master" - name = "git.apache.org/thrift.git" - source = "github.com/apache/thrift" - -[[constraint]] - name = "github.com/golang/protobuf" - version = "1.0.0" - -[[constraint]] - name = "github.com/openzipkin/zipkin-go" - version = ">=0.1.0" - -[[constraint]] - name = "github.com/prometheus/client_golang" - version = ">=0.8.0" - -[[constraint]] - branch = "master" - name = "golang.org/x/net" - -[[constraint]] - branch = "master" - name = "google.golang.org/api" - -[[constraint]] - name = "google.golang.org/grpc" - version = "1.11.3" - -[prune] - go-tests = true - unused-packages = true diff --git a/vendor/go.opencensus.io/README.md b/vendor/go.opencensus.io/README.md deleted file mode 100644 index 97d66983..00000000 --- a/vendor/go.opencensus.io/README.md +++ /dev/null @@ -1,263 +0,0 @@ -# OpenCensus Libraries for Go - -[![Build Status][travis-image]][travis-url] -[![Windows Build Status][appveyor-image]][appveyor-url] -[![GoDoc][godoc-image]][godoc-url] -[![Gitter chat][gitter-image]][gitter-url] - -OpenCensus Go is a Go implementation of OpenCensus, a toolkit for -collecting application performance and behavior monitoring data. -Currently it consists of three major components: tags, stats and tracing. - -## Installation - -``` -$ go get -u go.opencensus.io -``` - -The API of this project is still evolving, see: [Deprecation Policy](#deprecation-policy). -The use of vendoring or a dependency management tool is recommended. - -## Prerequisites - -OpenCensus Go libraries require Go 1.8 or later. - -## Getting Started - -The easiest way to get started using OpenCensus in your application is to use an existing -integration with your RPC framework: - -* [net/http](https://godoc.org/go.opencensus.io/plugin/ochttp) -* [gRPC](https://godoc.org/go.opencensus.io/plugin/ocgrpc) -* [database/sql](https://godoc.org/github.com/basvanbeek/ocsql) -* [Go kit](https://godoc.org/github.com/go-kit/kit/tracing/opencensus) -* [Groupcache](https://godoc.org/github.com/orijtech/groupcache) -* [Caddy webserver](https://godoc.org/github.com/orijtech/caddy) -* [MongoDB](https://godoc.org/github.com/orijtech/mongo-go-driver) -* [Redis gomodule/redigo](https://godoc.org/github.com/orijtech/redigo) -* [Redis goredis/redis](https://godoc.org/github.com/orijtech/redis) -* [Memcache](https://godoc.org/github.com/orijtech/gomemcache) - -If you're using a framework not listed here, you could either implement your own middleware for your -framework or use [custom stats](#stats) and [spans](#spans) directly in your application. - -## Exporters - -OpenCensus can export instrumentation data to various backends. -OpenCensus has exporter implementations for the following, users -can implement their own exporters by implementing the exporter interfaces -([stats](https://godoc.org/go.opencensus.io/stats/view#Exporter), -[trace](https://godoc.org/go.opencensus.io/trace#Exporter)): - -* [Prometheus][exporter-prom] for stats -* [OpenZipkin][exporter-zipkin] for traces -* [Stackdriver][exporter-stackdriver] Monitoring for stats and Trace for traces -* [Jaeger][exporter-jaeger] for traces -* [AWS X-Ray][exporter-xray] for traces -* [Datadog][exporter-datadog] for stats and traces -* [Graphite][exporter-graphite] for stats -* [Honeycomb][exporter-honeycomb] for traces - -## Overview - -![OpenCensus Overview](https://i.imgur.com/cf4ElHE.jpg) - -In a microservices environment, a user request may go through -multiple services until there is a response. OpenCensus allows -you to instrument your services and collect diagnostics data all -through your services end-to-end. - -## Tags - -Tags represent propagated key-value pairs. They are propagated using `context.Context` -in the same process or can be encoded to be transmitted on the wire. Usually, this will -be handled by an integration plugin, e.g. `ocgrpc.ServerHandler` and `ocgrpc.ClientHandler` -for gRPC. - -Package `tag` allows adding or modifying tags in the current context. - -[embedmd]:# (internal/readme/tags.go new) -```go -ctx, err = tag.New(ctx, - tag.Insert(osKey, "macOS-10.12.5"), - tag.Upsert(userIDKey, "cde36753ed"), -) -if err != nil { - log.Fatal(err) -} -``` - -## Stats - -OpenCensus is a low-overhead framework even if instrumentation is always enabled. -In order to be so, it is optimized to make recording of data points fast -and separate from the data aggregation. - -OpenCensus stats collection happens in two stages: - -* Definition of measures and recording of data points -* Definition of views and aggregation of the recorded data - -### Recording - -Measurements are data points associated with a measure. -Recording implicitly tags the set of Measurements with the tags from the -provided context: - -[embedmd]:# (internal/readme/stats.go record) -```go -stats.Record(ctx, videoSize.M(102478)) -``` - -### Views - -Views are how Measures are aggregated. You can think of them as queries over the -set of recorded data points (measurements). - -Views have two parts: the tags to group by and the aggregation type used. - -Currently three types of aggregations are supported: -* CountAggregation is used to count the number of times a sample was recorded. -* DistributionAggregation is used to provide a histogram of the values of the samples. -* SumAggregation is used to sum up all sample values. - -[embedmd]:# (internal/readme/stats.go aggs) -```go -distAgg := view.Distribution(0, 1<<32, 2<<32, 3<<32) -countAgg := view.Count() -sumAgg := view.Sum() -``` - -Here we create a view with the DistributionAggregation over our measure. - -[embedmd]:# (internal/readme/stats.go view) -```go -if err := view.Register(&view.View{ - Name: "example.com/video_size_distribution", - Description: "distribution of processed video size over time", - Measure: videoSize, - Aggregation: view.Distribution(0, 1<<32, 2<<32, 3<<32), -}); err != nil { - log.Fatalf("Failed to register view: %v", err) -} -``` - -Register begins collecting data for the view. Registered views' data will be -exported via the registered exporters. - -## Traces - -A distributed trace tracks the progression of a single user request as -it is handled by the services and processes that make up an application. -Each step is called a span in the trace. Spans include metadata about the step, -including especially the time spent in the step, called the span’s latency. - -Below you see a trace and several spans underneath it. - -![Traces and spans](https://i.imgur.com/7hZwRVj.png) - -### Spans - -Span is the unit step in a trace. Each span has a name, latency, status and -additional metadata. - -Below we are starting a span for a cache read and ending it -when we are done: - -[embedmd]:# (internal/readme/trace.go startend) -```go -ctx, span := trace.StartSpan(ctx, "cache.Get") -defer span.End() - -// Do work to get from cache. -``` - -### Propagation - -Spans can have parents or can be root spans if they don't have any parents. -The current span is propagated in-process and across the network to allow associating -new child spans with the parent. - -In the same process, `context.Context` is used to propagate spans. -`trace.StartSpan` creates a new span as a root if the current context -doesn't contain a span. Or, it creates a child of the span that is -already in current context. The returned context can be used to keep -propagating the newly created span in the current context. - -[embedmd]:# (internal/readme/trace.go startend) -```go -ctx, span := trace.StartSpan(ctx, "cache.Get") -defer span.End() - -// Do work to get from cache. -``` - -Across the network, OpenCensus provides different propagation -methods for different protocols. - -* gRPC integrations use the OpenCensus' [binary propagation format](https://godoc.org/go.opencensus.io/trace/propagation). -* HTTP integrations use Zipkin's [B3](https://github.com/openzipkin/b3-propagation) - by default but can be configured to use a custom propagation method by setting another - [propagation.HTTPFormat](https://godoc.org/go.opencensus.io/trace/propagation#HTTPFormat). - -## Execution Tracer - -With Go 1.11, OpenCensus Go will support integration with the Go execution tracer. -See [Debugging Latency in Go](https://medium.com/observability/debugging-latency-in-go-1-11-9f97a7910d68) -for an example of their mutual use. - -## Profiles - -OpenCensus tags can be applied as profiler labels -for users who are on Go 1.9 and above. - -[embedmd]:# (internal/readme/tags.go profiler) -```go -ctx, err = tag.New(ctx, - tag.Insert(osKey, "macOS-10.12.5"), - tag.Insert(userIDKey, "fff0989878"), -) -if err != nil { - log.Fatal(err) -} -tag.Do(ctx, func(ctx context.Context) { - // Do work. - // When profiling is on, samples will be - // recorded with the key/values from the tag map. -}) -``` - -A screenshot of the CPU profile from the program above: - -![CPU profile](https://i.imgur.com/jBKjlkw.png) - -## Deprecation Policy - -Before version 1.0.0, the following deprecation policy will be observed: - -No backwards-incompatible changes will be made except for the removal of symbols that have -been marked as *Deprecated* for at least one minor release (e.g. 0.9.0 to 0.10.0). A release -removing the *Deprecated* functionality will be made no sooner than 28 days after the first -release in which the functionality was marked *Deprecated*. - -[travis-image]: https://travis-ci.org/census-instrumentation/opencensus-go.svg?branch=master -[travis-url]: https://travis-ci.org/census-instrumentation/opencensus-go -[appveyor-image]: https://ci.appveyor.com/api/projects/status/vgtt29ps1783ig38?svg=true -[appveyor-url]: https://ci.appveyor.com/project/opencensusgoteam/opencensus-go/branch/master -[godoc-image]: https://godoc.org/go.opencensus.io?status.svg -[godoc-url]: https://godoc.org/go.opencensus.io -[gitter-image]: https://badges.gitter.im/census-instrumentation/lobby.svg -[gitter-url]: https://gitter.im/census-instrumentation/lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge - - -[new-ex]: https://godoc.org/go.opencensus.io/tag#example-NewMap -[new-replace-ex]: https://godoc.org/go.opencensus.io/tag#example-NewMap--Replace - -[exporter-prom]: https://godoc.org/go.opencensus.io/exporter/prometheus -[exporter-stackdriver]: https://godoc.org/contrib.go.opencensus.io/exporter/stackdriver -[exporter-zipkin]: https://godoc.org/go.opencensus.io/exporter/zipkin -[exporter-jaeger]: https://godoc.org/go.opencensus.io/exporter/jaeger -[exporter-xray]: https://github.com/census-ecosystem/opencensus-go-exporter-aws -[exporter-datadog]: https://github.com/DataDog/opencensus-go-exporter-datadog -[exporter-graphite]: https://github.com/census-ecosystem/opencensus-go-exporter-graphite -[exporter-honeycomb]: https://github.com/honeycombio/opencensus-exporter diff --git a/vendor/go.opencensus.io/appveyor.yml b/vendor/go.opencensus.io/appveyor.yml deleted file mode 100644 index 98057888..00000000 --- a/vendor/go.opencensus.io/appveyor.yml +++ /dev/null @@ -1,24 +0,0 @@ -version: "{build}" - -platform: x64 - -clone_folder: c:\gopath\src\go.opencensus.io - -environment: - GOPATH: 'c:\gopath' - GOVERSION: '1.11' - GO111MODULE: 'on' - CGO_ENABLED: '0' # See: https://github.com/appveyor/ci/issues/2613 - -install: - - set PATH=%GOPATH%\bin;c:\go\bin;%PATH% - - go version - - go env - -build: false -deploy: false - -test_script: - - cd %APPVEYOR_BUILD_FOLDER% - - go build -v .\... - - go test -v .\... # No -race because cgo is disabled diff --git a/vendor/go.opencensus.io/go.mod b/vendor/go.opencensus.io/go.mod deleted file mode 100644 index 1236f4c2..00000000 --- a/vendor/go.opencensus.io/go.mod +++ /dev/null @@ -1,25 +0,0 @@ -module go.opencensus.io - -require ( - git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999 - github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 - github.com/ghodss/yaml v1.0.0 // indirect - github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect - github.com/golang/protobuf v1.2.0 - github.com/google/go-cmp v0.2.0 - github.com/grpc-ecosystem/grpc-gateway v1.5.0 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.1 - github.com/openzipkin/zipkin-go v0.1.1 - github.com/prometheus/client_golang v0.8.0 - github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 - github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e - github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273 - golang.org/x/net v0.0.0-20180906233101-161cd47e91fd - golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f - golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e - golang.org/x/text v0.3.0 - google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf - google.golang.org/genproto v0.0.0-20180831171423-11092d34479b - google.golang.org/grpc v1.14.0 - gopkg.in/yaml.v2 v2.2.1 // indirect -) diff --git a/vendor/go.opencensus.io/go.sum b/vendor/go.opencensus.io/go.sum deleted file mode 100644 index 3e0bab88..00000000 --- a/vendor/go.opencensus.io/go.sum +++ /dev/null @@ -1,48 +0,0 @@ -git.apache.org/thrift.git v0.0.0-20180807212849-6e67faa92827/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= -git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999 h1:sihTnRgTOUSCQz0iS0pjZuFQy/z7GXCJgSBg3+rZKHw= -git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/grpc-ecosystem/grpc-gateway v1.5.0 h1:WcmKMm43DR7RdtlkEXQJyo5ws8iTp98CyhCCbOHMvNI= -github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/openzipkin/zipkin-go v0.1.1 h1:A/ADD6HaPnAKj3yS7HjGHRK77qi41Hi0DirOOIQAeIw= -github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= -github.com/prometheus/client_golang v0.8.0 h1:1921Yw9Gc3iSc4VQh3PIoOqgPCZS7G/4xQNVUp8Mda8= -github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e h1:n/3MEhJQjQxrOUCzh1Y3Re6aJUUWRp2M9+Oc3eVn/54= -github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273 h1:agujYaXJSxSo18YNX3jzl+4G6Bstwt+kqv47GS12uL0= -github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -golang.org/x/net v0.0.0-20180821023952-922f4815f713/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180821140842-3b58ed4ad339/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -google.golang.org/api v0.0.0-20180818000503-e21acd801f91/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf h1:rjxqQmxjyqerRKEj+tZW+MCm4LgpFXu18bsEoCMgDsk= -google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20180831171423-11092d34479b h1:lohp5blsw53GBXtLyLNaTXPXS9pJ1tiTw61ZHUoE9Qw= -google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/grpc v1.14.0 h1:ArxJuB1NWfPY6r9Gp9gqwplT0Ge7nqv9msgu03lHLmo= -google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/vendor/go.opencensus.io/internal/sanitize_test.go b/vendor/go.opencensus.io/internal/sanitize_test.go deleted file mode 100644 index 6c02c7da..00000000 --- a/vendor/go.opencensus.io/internal/sanitize_test.go +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2017, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package internal - -import ( - "strings" - "testing" -) - -func TestSanitize(t *testing.T) { - tests := []struct { - name string - input string - want string - }{ - { - name: "trunacate long string", - input: strings.Repeat("a", 101), - want: strings.Repeat("a", 100), - }, - { - name: "replace character", - input: "test/key-1", - want: "test_key_1", - }, - { - name: "add prefix if starting with digit", - input: "0123456789", - want: "key_0123456789", - }, - { - name: "add prefix if starting with _", - input: "_0123456789", - want: "key_0123456789", - }, - { - name: "starts with _ after sanitization", - input: "/0123456789", - want: "key_0123456789", - }, - { - name: "valid input", - input: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0123456789", - want: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0123456789", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got, want := Sanitize(tt.input), tt.want; got != want { - t.Errorf("sanitize() = %q; want %q", got, want) - } - }) - } -} diff --git a/vendor/go.opencensus.io/plugin/ochttp/client_test.go b/vendor/go.opencensus.io/plugin/ochttp/client_test.go deleted file mode 100644 index 97d15ab9..00000000 --- a/vendor/go.opencensus.io/plugin/ochttp/client_test.go +++ /dev/null @@ -1,316 +0,0 @@ -// Copyright 2018, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package ochttp_test - -import ( - "fmt" - "io/ioutil" - "net/http" - "net/http/httptest" - "strings" - "sync" - "testing" - - "go.opencensus.io/plugin/ochttp" - "go.opencensus.io/stats/view" - "go.opencensus.io/trace" -) - -const reqCount = 5 - -func TestClientNew(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { - resp.Write([]byte("Hello, world!")) - })) - defer server.Close() - - if err := view.Register( - ochttp.ClientSentBytesDistribution, - ochttp.ClientReceivedBytesDistribution, - ochttp.ClientRoundtripLatencyDistribution, - ochttp.ClientCompletedCount, - ); err != nil { - t.Fatalf("Failed to register ochttp.DefaultClientViews error: %v", err) - } - - views := []string{ - "opencensus.io/http/client/sent_bytes", - "opencensus.io/http/client/received_bytes", - "opencensus.io/http/client/roundtrip_latency", - "opencensus.io/http/client/completed_count", - } - for _, name := range views { - v := view.Find(name) - if v == nil { - t.Errorf("view not found %q", name) - continue - } - } - - var wg sync.WaitGroup - var tr ochttp.Transport - errs := make(chan error, reqCount) - wg.Add(reqCount) - - for i := 0; i < reqCount; i++ { - go func() { - defer wg.Done() - req, err := http.NewRequest("POST", server.URL, strings.NewReader("req-body")) - if err != nil { - errs <- fmt.Errorf("error creating request: %v", err) - } - resp, err := tr.RoundTrip(req) - if err != nil { - errs <- fmt.Errorf("response error: %v", err) - } - if err := resp.Body.Close(); err != nil { - errs <- fmt.Errorf("error closing response body: %v", err) - } - if got, want := resp.StatusCode, 200; got != want { - errs <- fmt.Errorf("resp.StatusCode=%d; wantCount %d", got, want) - } - }() - } - - go func() { - wg.Wait() - close(errs) - }() - - for err := range errs { - if err != nil { - t.Fatal(err) - } - } - - for _, viewName := range views { - v := view.Find(viewName) - if v == nil { - t.Errorf("view not found %q", viewName) - continue - } - rows, err := view.RetrieveData(v.Name) - if err != nil { - t.Error(err) - continue - } - if got, want := len(rows), 1; got != want { - t.Errorf("len(%q) = %d; want %d", viewName, got, want) - continue - } - data := rows[0].Data - var count int64 - switch data := data.(type) { - case *view.CountData: - count = data.Value - case *view.DistributionData: - count = data.Count - default: - t.Errorf("Unkown data type: %v", data) - continue - } - if got := count; got != reqCount { - t.Fatalf("%s = %d; want %d", viewName, got, reqCount) - } - } -} - -func TestClientOld(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { - resp.Write([]byte("Hello, world!")) - })) - defer server.Close() - - if err := view.Register(ochttp.DefaultClientViews...); err != nil { - t.Fatalf("Failed to register ochttp.DefaultClientViews error: %v", err) - } - - views := []string{ - "opencensus.io/http/client/request_count", - "opencensus.io/http/client/latency", - "opencensus.io/http/client/request_bytes", - "opencensus.io/http/client/response_bytes", - } - for _, name := range views { - v := view.Find(name) - if v == nil { - t.Errorf("view not found %q", name) - continue - } - } - - var wg sync.WaitGroup - var tr ochttp.Transport - errs := make(chan error, reqCount) - wg.Add(reqCount) - - for i := 0; i < reqCount; i++ { - go func() { - defer wg.Done() - req, err := http.NewRequest("POST", server.URL, strings.NewReader("req-body")) - if err != nil { - errs <- fmt.Errorf("error creating request: %v", err) - } - resp, err := tr.RoundTrip(req) - if err != nil { - errs <- fmt.Errorf("response error: %v", err) - } - if err := resp.Body.Close(); err != nil { - errs <- fmt.Errorf("error closing response body: %v", err) - } - if got, want := resp.StatusCode, 200; got != want { - errs <- fmt.Errorf("resp.StatusCode=%d; wantCount %d", got, want) - } - }() - } - - go func() { - wg.Wait() - close(errs) - }() - - for err := range errs { - if err != nil { - t.Fatal(err) - } - } - - for _, viewName := range views { - v := view.Find(viewName) - if v == nil { - t.Errorf("view not found %q", viewName) - continue - } - rows, err := view.RetrieveData(v.Name) - if err != nil { - t.Error(err) - continue - } - if got, want := len(rows), 1; got != want { - t.Errorf("len(%q) = %d; want %d", viewName, got, want) - continue - } - data := rows[0].Data - var count int64 - switch data := data.(type) { - case *view.CountData: - count = data.Value - case *view.DistributionData: - count = data.Count - default: - t.Errorf("Unkown data type: %v", data) - continue - } - if got := count; got != reqCount { - t.Fatalf("%s = %d; want %d", viewName, got, reqCount) - } - } -} - -var noTrace = trace.StartOptions{Sampler: trace.NeverSample()} - -func BenchmarkTransportNoTrace(b *testing.B) { - benchmarkClientServer(b, &ochttp.Transport{StartOptions: noTrace}) -} - -func BenchmarkTransport(b *testing.B) { - benchmarkClientServer(b, &ochttp.Transport{}) -} - -func benchmarkClientServer(b *testing.B, transport *ochttp.Transport) { - b.ReportAllocs() - ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - fmt.Fprintf(rw, "Hello world.\n") - })) - defer ts.Close() - transport.StartOptions.Sampler = trace.AlwaysSample() - var client http.Client - client.Transport = transport - b.ResetTimer() - - for i := 0; i < b.N; i++ { - res, err := client.Get(ts.URL) - if err != nil { - b.Fatalf("Get: %v", err) - } - all, err := ioutil.ReadAll(res.Body) - res.Body.Close() - if err != nil { - b.Fatal("ReadAll:", err) - } - body := string(all) - if body != "Hello world.\n" { - b.Fatal("Got body:", body) - } - } -} - -func BenchmarkTransportParallel64NoTrace(b *testing.B) { - benchmarkClientServerParallel(b, 64, &ochttp.Transport{StartOptions: noTrace}) -} - -func BenchmarkTransportParallel64(b *testing.B) { - benchmarkClientServerParallel(b, 64, &ochttp.Transport{}) -} - -func benchmarkClientServerParallel(b *testing.B, parallelism int, transport *ochttp.Transport) { - b.ReportAllocs() - ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - fmt.Fprintf(rw, "Hello world.\n") - })) - defer ts.Close() - - var c http.Client - transport.Base = &http.Transport{ - MaxIdleConns: parallelism, - MaxIdleConnsPerHost: parallelism, - } - transport.StartOptions.Sampler = trace.AlwaysSample() - c.Transport = transport - - b.ResetTimer() - - // TODO(ramonza): replace with b.RunParallel (it didn't work when I tried) - - var wg sync.WaitGroup - wg.Add(parallelism) - for i := 0; i < parallelism; i++ { - iterations := b.N / parallelism - if i == 0 { - iterations += b.N % parallelism - } - go func() { - defer wg.Done() - for j := 0; j < iterations; j++ { - res, err := c.Get(ts.URL) - if err != nil { - b.Logf("Get: %v", err) - return - } - all, err := ioutil.ReadAll(res.Body) - res.Body.Close() - if err != nil { - b.Logf("ReadAll: %v", err) - return - } - body := string(all) - if body != "Hello world.\n" { - panic("Got body: " + body) - } - } - }() - } - wg.Wait() -} diff --git a/vendor/go.opencensus.io/plugin/ochttp/example_test.go b/vendor/go.opencensus.io/plugin/ochttp/example_test.go deleted file mode 100644 index bb115abb..00000000 --- a/vendor/go.opencensus.io/plugin/ochttp/example_test.go +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2018, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package ochttp_test - -import ( - "log" - "net/http" - - "go.opencensus.io/plugin/ochttp" - "go.opencensus.io/plugin/ochttp/propagation/b3" - "go.opencensus.io/stats/view" - "go.opencensus.io/tag" -) - -func ExampleTransport() { - // import ( - // "go.opencensus.io/plugin/ochttp" - // "go.opencensus.io/stats/view" - // ) - - if err := view.Register( - // Register a few default views. - ochttp.ClientSentBytesDistribution, - ochttp.ClientReceivedBytesDistribution, - ochttp.ClientRoundtripLatencyDistribution, - // Register a custom view. - &view.View{ - Name: "httpclient_latency_by_path", - TagKeys: []tag.Key{ochttp.KeyClientPath}, - Measure: ochttp.ClientRoundtripLatency, - Aggregation: ochttp.DefaultLatencyDistribution, - }, - ); err != nil { - log.Fatal(err) - } - - client := &http.Client{ - Transport: &ochttp.Transport{}, - } - - // Use client to perform requests. - _ = client -} - -var usersHandler http.Handler - -func ExampleHandler() { - // import "go.opencensus.io/plugin/ochttp" - - http.Handle("/users", ochttp.WithRouteTag(usersHandler, "/users")) - - // If no handler is specified, the default mux is used. - log.Fatal(http.ListenAndServe("localhost:8080", &ochttp.Handler{})) -} - -func ExampleHandler_mux() { - // import "go.opencensus.io/plugin/ochttp" - - mux := http.NewServeMux() - mux.Handle("/users", ochttp.WithRouteTag(usersHandler, "/users")) - log.Fatal(http.ListenAndServe("localhost:8080", &ochttp.Handler{ - Handler: mux, - Propagation: &b3.HTTPFormat{}, - })) -} diff --git a/vendor/go.opencensus.io/plugin/ochttp/propagation/b3/b3_test.go b/vendor/go.opencensus.io/plugin/ochttp/propagation/b3/b3_test.go deleted file mode 100644 index 4f7b5db8..00000000 --- a/vendor/go.opencensus.io/plugin/ochttp/propagation/b3/b3_test.go +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright 2018, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package b3 - -import ( - "net/http" - "reflect" - "testing" - - "go.opencensus.io/trace" -) - -func TestHTTPFormat_FromRequest(t *testing.T) { - tests := []struct { - name string - makeReq func() *http.Request - wantSc trace.SpanContext - wantOk bool - }{ - { - name: "128-bit trace ID + 64-bit span ID; sampled=1", - makeReq: func() *http.Request { - req, _ := http.NewRequest("GET", "http://example.com", nil) - req.Header.Set(TraceIDHeader, "463ac35c9f6413ad48485a3953bb6124") - req.Header.Set(SpanIDHeader, "0020000000000001") - req.Header.Set(SampledHeader, "1") - return req - }, - wantSc: trace.SpanContext{ - TraceID: trace.TraceID{70, 58, 195, 92, 159, 100, 19, 173, 72, 72, 90, 57, 83, 187, 97, 36}, - SpanID: trace.SpanID{0, 32, 0, 0, 0, 0, 0, 1}, - TraceOptions: trace.TraceOptions(1), - }, - wantOk: true, - }, - { - name: "short trace ID + short span ID; sampled=1", - makeReq: func() *http.Request { - req, _ := http.NewRequest("GET", "http://example.com", nil) - req.Header.Set(TraceIDHeader, "000102") - req.Header.Set(SpanIDHeader, "000102") - req.Header.Set(SampledHeader, "1") - return req - }, - wantSc: trace.SpanContext{ - TraceID: trace.TraceID{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2}, - SpanID: trace.SpanID{0, 0, 0, 0, 0, 0, 1, 2}, - TraceOptions: trace.TraceOptions(1), - }, - wantOk: true, - }, - { - name: "64-bit trace ID + 64-bit span ID; sampled=0", - makeReq: func() *http.Request { - req, _ := http.NewRequest("GET", "http://example.com", nil) - req.Header.Set(TraceIDHeader, "0020000000000001") - req.Header.Set(SpanIDHeader, "0020000000000001") - req.Header.Set(SampledHeader, "0") - return req - }, - wantSc: trace.SpanContext{ - TraceID: trace.TraceID{0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 1}, - SpanID: trace.SpanID{0, 32, 0, 0, 0, 0, 0, 1}, - TraceOptions: trace.TraceOptions(0), - }, - wantOk: true, - }, - { - name: "128-bit trace ID + 64-bit span ID; no sampling header", - makeReq: func() *http.Request { - req, _ := http.NewRequest("GET", "http://example.com", nil) - req.Header.Set(TraceIDHeader, "463ac35c9f6413ad48485a3953bb6124") - req.Header.Set(SpanIDHeader, "0020000000000001") - return req - }, - wantSc: trace.SpanContext{ - TraceID: trace.TraceID{70, 58, 195, 92, 159, 100, 19, 173, 72, 72, 90, 57, 83, 187, 97, 36}, - SpanID: trace.SpanID{0, 32, 0, 0, 0, 0, 0, 1}, - TraceOptions: trace.TraceOptions(0), - }, - wantOk: true, - }, - { - name: "invalid trace ID + 64-bit span ID; no sampling header", - makeReq: func() *http.Request { - req, _ := http.NewRequest("GET", "http://example.com", nil) - req.Header.Set(TraceIDHeader, "") - req.Header.Set(SpanIDHeader, "0020000000000001") - return req - }, - wantSc: trace.SpanContext{}, - wantOk: false, - }, - { - name: "128-bit trace ID; invalid span ID; no sampling header", - makeReq: func() *http.Request { - req, _ := http.NewRequest("GET", "http://example.com", nil) - req.Header.Set(TraceIDHeader, "463ac35c9f6413ad48485a3953bb6124") - req.Header.Set(SpanIDHeader, "") - return req - }, - wantSc: trace.SpanContext{}, - wantOk: false, - }, - { - name: "128-bit trace ID + 64-bit span ID; sampled=true", - makeReq: func() *http.Request { - req, _ := http.NewRequest("GET", "http://example.com", nil) - req.Header.Set(TraceIDHeader, "463ac35c9f6413ad48485a3953bb6124") - req.Header.Set(SpanIDHeader, "0020000000000001") - req.Header.Set(SampledHeader, "true") - return req - }, - wantSc: trace.SpanContext{ - TraceID: trace.TraceID{70, 58, 195, 92, 159, 100, 19, 173, 72, 72, 90, 57, 83, 187, 97, 36}, - SpanID: trace.SpanID{0, 32, 0, 0, 0, 0, 0, 1}, - TraceOptions: trace.TraceOptions(1), - }, - wantOk: true, - }, - { - name: "128-bit trace ID + 64-bit span ID; sampled=false", - makeReq: func() *http.Request { - req, _ := http.NewRequest("GET", "http://example.com", nil) - req.Header.Set(TraceIDHeader, "463ac35c9f6413ad48485a3953bb6124") - req.Header.Set(SpanIDHeader, "0020000000000001") - req.Header.Set(SampledHeader, "false") - return req - }, - wantSc: trace.SpanContext{ - TraceID: trace.TraceID{70, 58, 195, 92, 159, 100, 19, 173, 72, 72, 90, 57, 83, 187, 97, 36}, - SpanID: trace.SpanID{0, 32, 0, 0, 0, 0, 0, 1}, - TraceOptions: trace.TraceOptions(0), - }, - wantOk: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - f := &HTTPFormat{} - sc, ok := f.SpanContextFromRequest(tt.makeReq()) - if ok != tt.wantOk { - t.Errorf("HTTPFormat.SpanContextFromRequest() got ok = %v, want %v", ok, tt.wantOk) - } - if !reflect.DeepEqual(sc, tt.wantSc) { - t.Errorf("HTTPFormat.SpanContextFromRequest() got span context = %v, want %v", sc, tt.wantSc) - } - }) - } -} - -func TestHTTPFormat_ToRequest(t *testing.T) { - tests := []struct { - name string - sc trace.SpanContext - wantHeaders map[string]string - }{ - { - name: "valid traceID, header ID, sampled=1", - sc: trace.SpanContext{ - TraceID: trace.TraceID{70, 58, 195, 92, 159, 100, 19, 173, 72, 72, 90, 57, 83, 187, 97, 36}, - SpanID: trace.SpanID{0, 32, 0, 0, 0, 0, 0, 1}, - TraceOptions: trace.TraceOptions(1), - }, - wantHeaders: map[string]string{ - "X-B3-TraceId": "463ac35c9f6413ad48485a3953bb6124", - "X-B3-SpanId": "0020000000000001", - "X-B3-Sampled": "1", - }, - }, - { - name: "valid traceID, header ID, sampled=0", - sc: trace.SpanContext{ - TraceID: trace.TraceID{70, 58, 195, 92, 159, 100, 19, 173, 72, 72, 90, 57, 83, 187, 97, 36}, - SpanID: trace.SpanID{0, 32, 0, 0, 0, 0, 0, 1}, - TraceOptions: trace.TraceOptions(0), - }, - wantHeaders: map[string]string{ - "X-B3-TraceId": "463ac35c9f6413ad48485a3953bb6124", - "X-B3-SpanId": "0020000000000001", - "X-B3-Sampled": "0", - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - f := &HTTPFormat{} - req, _ := http.NewRequest("GET", "http://example.com", nil) - f.SpanContextToRequest(tt.sc, req) - - for k, v := range tt.wantHeaders { - if got, want := req.Header.Get(k), v; got != want { - t.Errorf("req.Header.Get(%q) = %q; want %q", k, got, want) - } - } - }) - } -} diff --git a/vendor/go.opencensus.io/plugin/ochttp/propagation/tracecontext/propagation_test.go b/vendor/go.opencensus.io/plugin/ochttp/propagation/tracecontext/propagation_test.go deleted file mode 100644 index 996cfa88..00000000 --- a/vendor/go.opencensus.io/plugin/ochttp/propagation/tracecontext/propagation_test.go +++ /dev/null @@ -1,267 +0,0 @@ -// Copyright 2018, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package tracecontext - -import ( - "fmt" - "net/http" - "reflect" - "strings" - "testing" - - "go.opencensus.io/trace" - "go.opencensus.io/trace/tracestate" -) - -var ( - tpHeader = "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01" - traceID = trace.TraceID{75, 249, 47, 53, 119, 179, 77, 166, 163, 206, 146, 157, 14, 14, 71, 54} - spanID = trace.SpanID{0, 240, 103, 170, 11, 169, 2, 183} - traceOpt = trace.TraceOptions(1) - oversizeValue = strings.Repeat("a", maxTracestateLen/2) - oversizeEntry1 = tracestate.Entry{Key: "foo", Value: oversizeValue} - oversizeEntry2 = tracestate.Entry{Key: "hello", Value: oversizeValue} - entry1 = tracestate.Entry{Key: "foo", Value: "bar"} - entry2 = tracestate.Entry{Key: "hello", Value: "world example"} - oversizeTs, _ = tracestate.New(nil, oversizeEntry1, oversizeEntry2) - defaultTs, _ = tracestate.New(nil, nil...) - nonDefaultTs, _ = tracestate.New(nil, entry1, entry2) -) - -func TestHTTPFormat_FromRequest(t *testing.T) { - tests := []struct { - name string - header string - wantSc trace.SpanContext - wantOk bool - }{ - { - name: "future version", - header: "02-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01", - wantSc: trace.SpanContext{ - TraceID: trace.TraceID{75, 249, 47, 53, 119, 179, 77, 166, 163, 206, 146, 157, 14, 14, 71, 54}, - SpanID: trace.SpanID{0, 240, 103, 170, 11, 169, 2, 183}, - TraceOptions: trace.TraceOptions(1), - }, - wantOk: true, - }, - { - name: "zero trace ID and span ID", - header: "00-00000000000000000000000000000000-0000000000000000-01", - wantSc: trace.SpanContext{}, - wantOk: false, - }, - { - name: "valid header", - header: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01", - wantSc: trace.SpanContext{ - TraceID: trace.TraceID{75, 249, 47, 53, 119, 179, 77, 166, 163, 206, 146, 157, 14, 14, 71, 54}, - SpanID: trace.SpanID{0, 240, 103, 170, 11, 169, 2, 183}, - TraceOptions: trace.TraceOptions(1), - }, - wantOk: true, - }, - { - name: "missing options", - header: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7", - wantSc: trace.SpanContext{}, - wantOk: false, - }, - { - name: "empty options", - header: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-", - wantSc: trace.SpanContext{}, - wantOk: false, - }, - } - - f := &HTTPFormat{} - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - req, _ := http.NewRequest("GET", "http://example.com", nil) - req.Header.Set("traceparent", tt.header) - - gotSc, gotOk := f.SpanContextFromRequest(req) - if !reflect.DeepEqual(gotSc, tt.wantSc) { - t.Errorf("HTTPFormat.FromRequest() gotSc = %v, want %v", gotSc, tt.wantSc) - } - if gotOk != tt.wantOk { - t.Errorf("HTTPFormat.FromRequest() gotOk = %v, want %v", gotOk, tt.wantOk) - } - }) - } -} - -func TestHTTPFormat_ToRequest(t *testing.T) { - tests := []struct { - sc trace.SpanContext - wantHeader string - }{ - { - sc: trace.SpanContext{ - TraceID: trace.TraceID{75, 249, 47, 53, 119, 179, 77, 166, 163, 206, 146, 157, 14, 14, 71, 54}, - SpanID: trace.SpanID{0, 240, 103, 170, 11, 169, 2, 183}, - TraceOptions: trace.TraceOptions(1), - }, - wantHeader: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01", - }, - } - for _, tt := range tests { - t.Run(tt.wantHeader, func(t *testing.T) { - f := &HTTPFormat{} - req, _ := http.NewRequest("GET", "http://example.com", nil) - f.SpanContextToRequest(tt.sc, req) - - h := req.Header.Get("traceparent") - if got, want := h, tt.wantHeader; got != want { - t.Errorf("HTTPFormat.ToRequest() header = %v, want %v", got, want) - } - }) - } -} - -func TestHTTPFormatTracestate_FromRequest(t *testing.T) { - scWithNonDefaultTracestate := trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceOptions: traceOpt, - Tracestate: nonDefaultTs, - } - - scWithDefaultTracestate := trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceOptions: traceOpt, - Tracestate: defaultTs, - } - - tests := []struct { - name string - tpHeader string - tsHeader string - wantSc trace.SpanContext - wantOk bool - }{ - { - name: "tracestate invalid entries delimiter", - tpHeader: tpHeader, - tsHeader: "foo=bar;hello=world", - wantSc: scWithDefaultTracestate, - wantOk: true, - }, - { - name: "tracestate invalid key-value delimiter", - tpHeader: tpHeader, - tsHeader: "foo=bar,hello-world", - wantSc: scWithDefaultTracestate, - wantOk: true, - }, - { - name: "tracestate invalid value character", - tpHeader: tpHeader, - tsHeader: "foo=bar,hello=world example \u00a0 ", - wantSc: scWithDefaultTracestate, - wantOk: true, - }, - { - name: "tracestate blank key-value", - tpHeader: tpHeader, - tsHeader: "foo=bar, ", - wantSc: scWithDefaultTracestate, - wantOk: true, - }, - { - name: "tracestate oversize header", - tpHeader: tpHeader, - tsHeader: fmt.Sprintf("foo=%s,hello=%s", oversizeValue, oversizeValue), - wantSc: scWithDefaultTracestate, - wantOk: true, - }, - { - name: "tracestate valid", - tpHeader: tpHeader, - tsHeader: "foo=bar , hello=world example", - wantSc: scWithNonDefaultTracestate, - wantOk: true, - }, - } - - f := &HTTPFormat{} - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - req, _ := http.NewRequest("GET", "http://example.com", nil) - req.Header.Set("traceparent", tt.tpHeader) - req.Header.Set("tracestate", tt.tsHeader) - - gotSc, gotOk := f.SpanContextFromRequest(req) - if !reflect.DeepEqual(gotSc, tt.wantSc) { - t.Errorf("HTTPFormat.FromRequest() gotTs = %v, want %v", gotSc.Tracestate, tt.wantSc.Tracestate) - } - if gotOk != tt.wantOk { - t.Errorf("HTTPFormat.FromRequest() gotOk = %v, want %v", gotOk, tt.wantOk) - } - }) - } -} - -func TestHTTPFormatTracestate_ToRequest(t *testing.T) { - tests := []struct { - name string - sc trace.SpanContext - wantHeader string - }{ - { - name: "valid span context with default tracestate", - sc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceOptions: traceOpt, - }, - wantHeader: "", - }, - { - name: "valid span context with non default tracestate", - sc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceOptions: traceOpt, - Tracestate: nonDefaultTs, - }, - wantHeader: "foo=bar,hello=world example", - }, - { - name: "valid span context with oversize tracestate", - sc: trace.SpanContext{ - TraceID: traceID, - SpanID: spanID, - TraceOptions: traceOpt, - Tracestate: oversizeTs, - }, - wantHeader: "", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - f := &HTTPFormat{} - req, _ := http.NewRequest("GET", "http://example.com", nil) - f.SpanContextToRequest(tt.sc, req) - - h := req.Header.Get("tracestate") - if got, want := h, tt.wantHeader; got != want { - t.Errorf("HTTPFormat.ToRequest() tracestate header = %v, want %v", got, want) - } - }) - } -} diff --git a/vendor/go.opencensus.io/plugin/ochttp/propagation_test.go b/vendor/go.opencensus.io/plugin/ochttp/propagation_test.go deleted file mode 100644 index 9ebfd89f..00000000 --- a/vendor/go.opencensus.io/plugin/ochttp/propagation_test.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2018, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package ochttp - -import ( - "context" - "fmt" - "io/ioutil" - "net/http" - "net/http/httptest" - "testing" - - "go.opencensus.io/plugin/ochttp/propagation/b3" - "go.opencensus.io/plugin/ochttp/propagation/tracecontext" - "go.opencensus.io/trace" - "go.opencensus.io/trace/propagation" -) - -func TestRoundTripAllFormats(t *testing.T) { - // TODO: test combinations of different formats for chains of calls - formats := []propagation.HTTPFormat{ - &b3.HTTPFormat{}, - &tracecontext.HTTPFormat{}, - } - - ctx := context.Background() - ctx, span := trace.StartSpan(ctx, "test", trace.WithSampler(trace.AlwaysSample())) - sc := span.SpanContext() - wantStr := fmt.Sprintf("trace_id=%x, span_id=%x, options=%d", sc.TraceID, sc.SpanID, sc.TraceOptions) - defer span.End() - - for _, format := range formats { - srv := httptest.NewServer(http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { - sc, ok := format.SpanContextFromRequest(req) - if !ok { - resp.WriteHeader(http.StatusBadRequest) - } - fmt.Fprintf(resp, "trace_id=%x, span_id=%x, options=%d", sc.TraceID, sc.SpanID, sc.TraceOptions) - })) - req, err := http.NewRequest("GET", srv.URL, nil) - if err != nil { - t.Fatal(err) - } - format.SpanContextToRequest(span.SpanContext(), req) - resp, err := http.DefaultClient.Do(req) - if err != nil { - t.Fatal(err) - } - if resp.StatusCode != 200 { - t.Fatal(resp.Status) - } - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - t.Fatal(err) - } - resp.Body.Close() - if got, want := string(body), wantStr; got != want { - t.Errorf("%s; want %s", got, want) - } - srv.Close() - } -} diff --git a/vendor/go.opencensus.io/plugin/ochttp/route_test.go b/vendor/go.opencensus.io/plugin/ochttp/route_test.go deleted file mode 100644 index a9793eb0..00000000 --- a/vendor/go.opencensus.io/plugin/ochttp/route_test.go +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2018, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package ochttp_test - -import ( - "net/http" - "net/http/httptest" - "testing" - - "github.com/google/go-cmp/cmp" - "go.opencensus.io/plugin/ochttp" - "go.opencensus.io/stats/view" - "go.opencensus.io/tag" -) - -func TestWithRouteTag(t *testing.T) { - v := &view.View{ - Name: "request_total", - Measure: ochttp.ServerLatency, - Aggregation: view.Count(), - TagKeys: []tag.Key{ochttp.KeyServerRoute}, - } - view.Register(v) - var e testStatsExporter - view.RegisterExporter(&e) - defer view.UnregisterExporter(&e) - - mux := http.NewServeMux() - handler := ochttp.WithRouteTag(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(204) - }), "/a/") - mux.Handle("/a/", handler) - plugin := ochttp.Handler{Handler: mux} - req, _ := http.NewRequest("GET", "/a/b/c", nil) - rr := httptest.NewRecorder() - plugin.ServeHTTP(rr, req) - if got, want := rr.Code, 204; got != want { - t.Fatalf("Unexpected response, got %d; want %d", got, want) - } - - view.Unregister(v) // trigger exporting - - got := e.rowsForView("request_total") - want := []*view.Row{ - {Data: &view.CountData{Value: 1}, Tags: []tag.Tag{{Key: ochttp.KeyServerRoute, Value: "/a/"}}}, - } - if diff := cmp.Diff(got, want); diff != "" { - t.Errorf("Unexpected view data exported, -got, +want: %s", diff) - } -} - -type testStatsExporter struct { - vd []*view.Data -} - -func (t *testStatsExporter) ExportView(d *view.Data) { - t.vd = append(t.vd, d) -} - -func (t *testStatsExporter) rowsForView(name string) []*view.Row { - var rows []*view.Row - for _, d := range t.vd { - if d.View.Name == name { - rows = append(rows, d.Rows...) - } - } - return rows -} diff --git a/vendor/go.opencensus.io/plugin/ochttp/server_test.go b/vendor/go.opencensus.io/plugin/ochttp/server_test.go deleted file mode 100644 index 29468cbe..00000000 --- a/vendor/go.opencensus.io/plugin/ochttp/server_test.go +++ /dev/null @@ -1,597 +0,0 @@ -package ochttp - -import ( - "bufio" - "bytes" - "context" - "crypto/tls" - "fmt" - "io" - "io/ioutil" - "net" - "net/http" - "net/http/httptest" - "strings" - "sync" - "testing" - "time" - - "golang.org/x/net/http2" - - "go.opencensus.io/stats/view" - "go.opencensus.io/trace" -) - -func httpHandler(statusCode, respSize int) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(statusCode) - body := make([]byte, respSize) - w.Write(body) - }) -} - -func updateMean(mean float64, sample, count int) float64 { - if count == 1 { - return float64(sample) - } - return mean + (float64(sample)-mean)/float64(count) -} - -func TestHandlerStatsCollection(t *testing.T) { - if err := view.Register(DefaultServerViews...); err != nil { - t.Fatalf("Failed to register ochttp.DefaultServerViews error: %v", err) - } - - views := []string{ - "opencensus.io/http/server/request_count", - "opencensus.io/http/server/latency", - "opencensus.io/http/server/request_bytes", - "opencensus.io/http/server/response_bytes", - } - - // TODO: test latency measurements? - tests := []struct { - name, method, target string - count, statusCode, reqSize, respSize int - }{ - {"get 200", "GET", "http://opencensus.io/request/one", 10, 200, 512, 512}, - {"post 503", "POST", "http://opencensus.io/request/two", 5, 503, 1024, 16384}, - {"no body 302", "GET", "http://opencensus.io/request/three", 2, 302, 0, 0}, - } - totalCount, meanReqSize, meanRespSize := 0, 0.0, 0.0 - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - body := bytes.NewBuffer(make([]byte, test.reqSize)) - r := httptest.NewRequest(test.method, test.target, body) - w := httptest.NewRecorder() - mux := http.NewServeMux() - mux.Handle("/request/", httpHandler(test.statusCode, test.respSize)) - h := &Handler{ - Handler: mux, - StartOptions: trace.StartOptions{ - Sampler: trace.NeverSample(), - }, - } - for i := 0; i < test.count; i++ { - h.ServeHTTP(w, r) - totalCount++ - // Distributions do not track sum directly, we must - // mimic their behaviour to avoid rounding failures. - meanReqSize = updateMean(meanReqSize, test.reqSize, totalCount) - meanRespSize = updateMean(meanRespSize, test.respSize, totalCount) - } - }) - } - - for _, viewName := range views { - v := view.Find(viewName) - if v == nil { - t.Errorf("view not found %q", viewName) - continue - } - rows, err := view.RetrieveData(viewName) - if err != nil { - t.Error(err) - continue - } - if got, want := len(rows), 1; got != want { - t.Errorf("len(%q) = %d; want %d", viewName, got, want) - continue - } - data := rows[0].Data - - var count int - var sum float64 - switch data := data.(type) { - case *view.CountData: - count = int(data.Value) - case *view.DistributionData: - count = int(data.Count) - sum = data.Sum() - default: - t.Errorf("Unkown data type: %v", data) - continue - } - - if got, want := count, totalCount; got != want { - t.Fatalf("%s = %d; want %d", viewName, got, want) - } - - // We can only check sum for distribution views. - switch viewName { - case "opencensus.io/http/server/request_bytes": - if got, want := sum, meanReqSize*float64(totalCount); got != want { - t.Fatalf("%s = %g; want %g", viewName, got, want) - } - case "opencensus.io/http/server/response_bytes": - if got, want := sum, meanRespSize*float64(totalCount); got != want { - t.Fatalf("%s = %g; want %g", viewName, got, want) - } - } - } -} - -type testResponseWriterHijacker struct { - httptest.ResponseRecorder -} - -func (trw *testResponseWriterHijacker) Hijack() (net.Conn, *bufio.ReadWriter, error) { - return nil, nil, nil -} - -func TestUnitTestHandlerProxiesHijack(t *testing.T) { - tests := []struct { - w http.ResponseWriter - hasHijack bool - }{ - {httptest.NewRecorder(), false}, - {nil, false}, - {new(testResponseWriterHijacker), true}, - } - - for i, tt := range tests { - tw := &trackingResponseWriter{writer: tt.w} - w := tw.wrappedResponseWriter() - _, ttHijacker := w.(http.Hijacker) - if want, have := tt.hasHijack, ttHijacker; want != have { - t.Errorf("#%d Hijack got %t, want %t", i, have, want) - } - } -} - -// Integration test with net/http to ensure that our Handler proxies to its -// response the call to (http.Hijack).Hijacker() and that that successfully -// passes with HTTP/1.1 connections. See Issue #642 -func TestHandlerProxiesHijack_HTTP1(t *testing.T) { - cst := httptest.NewServer(&Handler{ - Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - var writeMsg func(string) - defer func() { - err := recover() - writeMsg(fmt.Sprintf("Proto=%s\npanic=%v", r.Proto, err != nil)) - }() - conn, _, _ := w.(http.Hijacker).Hijack() - writeMsg = func(msg string) { - fmt.Fprintf(conn, "%s 200\nContentLength: %d", r.Proto, len(msg)) - fmt.Fprintf(conn, "\r\n\r\n%s", msg) - conn.Close() - } - }), - }) - defer cst.Close() - - testCases := []struct { - name string - tr *http.Transport - want string - }{ - { - name: "http1-transport", - tr: new(http.Transport), - want: "Proto=HTTP/1.1\npanic=false", - }, - { - name: "http2-transport", - tr: func() *http.Transport { - tr := new(http.Transport) - http2.ConfigureTransport(tr) - return tr - }(), - want: "Proto=HTTP/1.1\npanic=false", - }, - } - - for _, tc := range testCases { - c := &http.Client{Transport: &Transport{Base: tc.tr}} - res, err := c.Get(cst.URL) - if err != nil { - t.Errorf("(%s) unexpected error %v", tc.name, err) - continue - } - blob, _ := ioutil.ReadAll(res.Body) - res.Body.Close() - if g, w := string(blob), tc.want; g != w { - t.Errorf("(%s) got = %q; want = %q", tc.name, g, w) - } - } -} - -// Integration test with net/http, x/net/http2 to ensure that our Handler proxies -// to its response the call to (http.Hijack).Hijacker() and that that crashes -// since http.Hijacker and HTTP/2.0 connections are incompatible, but the -// detection is only at runtime and ensure that we can stream and flush to the -// connection even after invoking Hijack(). See Issue #642. -func TestHandlerProxiesHijack_HTTP2(t *testing.T) { - cst := httptest.NewUnstartedServer(&Handler{ - Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if _, ok := w.(http.Hijacker); ok { - conn, _, err := w.(http.Hijacker).Hijack() - if conn != nil { - data := fmt.Sprintf("Surprisingly got the Hijacker() Proto: %s", r.Proto) - fmt.Fprintf(conn, "%s 200\nContent-Length:%d\r\n\r\n%s", r.Proto, len(data), data) - conn.Close() - return - } - - switch { - case err == nil: - fmt.Fprintf(w, "Unexpectedly did not encounter an error!") - default: - fmt.Fprintf(w, "Unexpected error: %v", err) - case strings.Contains(err.(error).Error(), "Hijack"): - // Confirmed HTTP/2.0, let's stream to it - for i := 0; i < 5; i++ { - fmt.Fprintf(w, "%d\n", i) - w.(http.Flusher).Flush() - } - } - } else { - // Confirmed HTTP/2.0, let's stream to it - for i := 0; i < 5; i++ { - fmt.Fprintf(w, "%d\n", i) - w.(http.Flusher).Flush() - } - } - }), - }) - cst.TLS = &tls.Config{NextProtos: []string{"h2"}} - cst.StartTLS() - defer cst.Close() - - if wantPrefix := "https://"; !strings.HasPrefix(cst.URL, wantPrefix) { - t.Fatalf("URL got = %q wantPrefix = %q", cst.URL, wantPrefix) - } - - tr := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}} - http2.ConfigureTransport(tr) - c := &http.Client{Transport: tr} - res, err := c.Get(cst.URL) - if err != nil { - t.Fatalf("Unexpected error %v", err) - } - blob, _ := ioutil.ReadAll(res.Body) - res.Body.Close() - if g, w := string(blob), "0\n1\n2\n3\n4\n"; g != w { - t.Errorf("got = %q; want = %q", g, w) - } -} - -func TestEnsureTrackingResponseWriterSetsStatusCode(t *testing.T) { - // Ensure that the trackingResponseWriter always sets the spanStatus on ending the span. - // Because we can only examine the Status after exporting, this test roundtrips a - // couple of requests and then later examines the exported spans. - // See Issue #700. - exporter := &spanExporter{cur: make(chan *trace.SpanData, 1)} - trace.RegisterExporter(exporter) - defer trace.UnregisterExporter(exporter) - - tests := []struct { - res *http.Response - want trace.Status - }{ - {res: &http.Response{StatusCode: 200}, want: trace.Status{Code: trace.StatusCodeOK, Message: `OK`}}, - {res: &http.Response{StatusCode: 500}, want: trace.Status{Code: trace.StatusCodeUnknown, Message: `UNKNOWN`}}, - {res: &http.Response{StatusCode: 403}, want: trace.Status{Code: trace.StatusCodePermissionDenied, Message: `PERMISSION_DENIED`}}, - {res: &http.Response{StatusCode: 401}, want: trace.Status{Code: trace.StatusCodeUnauthenticated, Message: `UNAUTHENTICATED`}}, - {res: &http.Response{StatusCode: 429}, want: trace.Status{Code: trace.StatusCodeResourceExhausted, Message: `RESOURCE_EXHAUSTED`}}, - } - - for _, tt := range tests { - t.Run(tt.want.Message, func(t *testing.T) { - ctx := context.Background() - prc, pwc := io.Pipe() - go func() { - pwc.Write([]byte("Foo")) - pwc.Close() - }() - inRes := tt.res - inRes.Body = prc - tr := &traceTransport{ - base: &testResponseTransport{res: inRes}, - formatSpanName: spanNameFromURL, - startOptions: trace.StartOptions{ - Sampler: trace.AlwaysSample(), - }, - } - req, err := http.NewRequest("POST", "https://example.org", bytes.NewReader([]byte("testing"))) - if err != nil { - t.Fatalf("NewRequest error: %v", err) - } - req = req.WithContext(ctx) - res, err := tr.RoundTrip(req) - if err != nil { - t.Fatalf("RoundTrip error: %v", err) - } - _, _ = ioutil.ReadAll(res.Body) - res.Body.Close() - - cur := <-exporter.cur - if got, want := cur.Status, tt.want; got != want { - t.Fatalf("SpanData:\ngot = (%#v)\nwant = (%#v)", got, want) - } - }) - } -} - -type spanExporter struct { - sync.Mutex - cur chan *trace.SpanData -} - -var _ trace.Exporter = (*spanExporter)(nil) - -func (se *spanExporter) ExportSpan(sd *trace.SpanData) { - se.Lock() - se.cur <- sd - se.Unlock() -} - -type testResponseTransport struct { - res *http.Response -} - -var _ http.RoundTripper = (*testResponseTransport)(nil) - -func (rb *testResponseTransport) RoundTrip(*http.Request) (*http.Response, error) { - return rb.res, nil -} - -func TestHandlerImplementsHTTPPusher(t *testing.T) { - cst := setupAndStartServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - pusher, ok := w.(http.Pusher) - if !ok { - w.Write([]byte("false")) - return - } - err := pusher.Push("/static.css", &http.PushOptions{ - Method: "GET", - Header: http.Header{"Accept-Encoding": r.Header["Accept-Encoding"]}, - }) - if err != nil && false { - // TODO: (@odeke-em) consult with Go stdlib for why trying - // to configure even an HTTP/2 server and HTTP/2 transport - // still return http.ErrNotSupported even without using ochttp.Handler. - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - w.Write([]byte("true")) - }), asHTTP2) - defer cst.Close() - - tests := []struct { - rt http.RoundTripper - wantBody string - }{ - { - rt: h1Transport(), - wantBody: "false", - }, - { - rt: h2Transport(), - wantBody: "true", - }, - { - rt: &Transport{Base: h1Transport()}, - wantBody: "false", - }, - { - rt: &Transport{Base: h2Transport()}, - wantBody: "true", - }, - } - - for i, tt := range tests { - c := &http.Client{Transport: &Transport{Base: tt.rt}} - res, err := c.Get(cst.URL) - if err != nil { - t.Errorf("#%d: Unexpected error %v", i, err) - continue - } - body, _ := ioutil.ReadAll(res.Body) - _ = res.Body.Close() - if g, w := string(body), tt.wantBody; g != w { - t.Errorf("#%d: got = %q; want = %q", i, g, w) - } - } -} - -const ( - isNil = "isNil" - hang = "hang" - ended = "ended" - nonNotifier = "nonNotifier" - - asHTTP1 = false - asHTTP2 = true -) - -func setupAndStartServer(hf func(http.ResponseWriter, *http.Request), isHTTP2 bool) *httptest.Server { - cst := httptest.NewUnstartedServer(&Handler{ - Handler: http.HandlerFunc(hf), - }) - if isHTTP2 { - http2.ConfigureServer(cst.Config, new(http2.Server)) - cst.TLS = cst.Config.TLSConfig - cst.StartTLS() - } else { - cst.Start() - } - - return cst -} - -func insecureTLS() *tls.Config { return &tls.Config{InsecureSkipVerify: true} } -func h1Transport() *http.Transport { return &http.Transport{TLSClientConfig: insecureTLS()} } -func h2Transport() *http.Transport { - tr := &http.Transport{TLSClientConfig: insecureTLS()} - http2.ConfigureTransport(tr) - return tr -} - -type concurrentBuffer struct { - sync.RWMutex - bw *bytes.Buffer -} - -func (cw *concurrentBuffer) Write(b []byte) (int, error) { - cw.Lock() - defer cw.Unlock() - - return cw.bw.Write(b) -} - -func (cw *concurrentBuffer) String() string { - cw.Lock() - defer cw.Unlock() - - return cw.bw.String() -} - -func handleCloseNotify(outLog io.Writer) http.HandlerFunc { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - cn, ok := w.(http.CloseNotifier) - if !ok { - fmt.Fprintln(outLog, nonNotifier) - return - } - ch := cn.CloseNotify() - if ch == nil { - fmt.Fprintln(outLog, isNil) - return - } - - <-ch - fmt.Fprintln(outLog, ended) - }) -} - -func TestHandlerImplementsHTTPCloseNotify(t *testing.T) { - http1Log := &concurrentBuffer{bw: new(bytes.Buffer)} - http1Server := setupAndStartServer(handleCloseNotify(http1Log), asHTTP1) - http2Log := &concurrentBuffer{bw: new(bytes.Buffer)} - http2Server := setupAndStartServer(handleCloseNotify(http2Log), asHTTP2) - - defer http1Server.Close() - defer http2Server.Close() - - tests := []struct { - url string - want string - }{ - {url: http1Server.URL, want: nonNotifier}, - {url: http2Server.URL, want: ended}, - } - - transports := []struct { - name string - rt http.RoundTripper - }{ - {name: "http2+ochttp", rt: &Transport{Base: h2Transport()}}, - {name: "http1+ochttp", rt: &Transport{Base: h1Transport()}}, - {name: "http1-ochttp", rt: h1Transport()}, - {name: "http2-ochttp", rt: h2Transport()}, - } - - // Each transport invokes one of two server types, either HTTP/1 or HTTP/2 - for _, trc := range transports { - // Try out all the transport combinations - for i, tt := range tests { - req, err := http.NewRequest("GET", tt.url, nil) - if err != nil { - t.Errorf("#%d: Unexpected error making request: %v", i, err) - continue - } - - // Using a timeout to ensure that the request is cancelled and the server - // if its handler implements CloseNotify will see this as the client leaving. - ctx, cancel := context.WithTimeout(context.Background(), 80*time.Millisecond) - defer cancel() - req = req.WithContext(ctx) - - client := &http.Client{Transport: trc.rt} - res, err := client.Do(req) - if err != nil && !strings.Contains(err.Error(), "context deadline exceeded") { - t.Errorf("#%d: %sClient Unexpected error %v", i, trc.name, err) - continue - } - if res != nil && res.Body != nil { - io.CopyN(ioutil.Discard, res.Body, 5) - _ = res.Body.Close() - } - } - } - - // Wait for a couple of milliseconds for the GoAway frames to be properly propagated - <-time.After(150 * time.Millisecond) - - wantHTTP1Log := strings.Repeat("ended\n", len(transports)) - wantHTTP2Log := strings.Repeat("ended\n", len(transports)) - if g, w := http1Log.String(), wantHTTP1Log; g != w { - t.Errorf("HTTP1Log got\n\t%q\nwant\n\t%q", g, w) - } - if g, w := http2Log.String(), wantHTTP2Log; g != w { - t.Errorf("HTTP2Log got\n\t%q\nwant\n\t%q", g, w) - } -} - -func TestIgnoreHealthz(t *testing.T) { - var spans int - - ts := httptest.NewServer(&Handler{ - Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - span := trace.FromContext(r.Context()) - if span != nil { - spans++ - } - fmt.Fprint(w, "ok") - }), - StartOptions: trace.StartOptions{ - Sampler: trace.AlwaysSample(), - }, - }) - defer ts.Close() - - client := &http.Client{} - - for _, path := range []string{"/healthz", "/_ah/health"} { - resp, err := client.Get(ts.URL + path) - if err != nil { - t.Fatalf("Cannot GET %q: %v", path, err) - } - - b, err := ioutil.ReadAll(resp.Body) - if err != nil { - t.Fatalf("Cannot read body for %q: %v", path, err) - } - - if got, want := string(b), "ok"; got != want { - t.Fatalf("Body for %q = %q; want %q", path, got, want) - } - resp.Body.Close() - } - - if spans > 0 { - t.Errorf("Got %v spans; want no spans", spans) - } -} diff --git a/vendor/go.opencensus.io/plugin/ochttp/span_annotating_client_trace_test.go b/vendor/go.opencensus.io/plugin/ochttp/span_annotating_client_trace_test.go deleted file mode 100644 index 3336d7ec..00000000 --- a/vendor/go.opencensus.io/plugin/ochttp/span_annotating_client_trace_test.go +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2018, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package ochttp_test - -import ( - "errors" - "net/http" - "net/http/httptest" - "strings" - "sync" - "testing" - - "go.opencensus.io/plugin/ochttp" - "go.opencensus.io/trace" -) - -func TestSpanAnnotatingClientTrace(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { - resp.Write([]byte("Hello, world!")) - })) - defer server.Close() - - recorder := &testExporter{} - - trace.RegisterExporter(recorder) - - tr := ochttp.Transport{ - NewClientTrace: ochttp.NewSpanAnnotatingClientTrace, - StartOptions: trace.StartOptions{ - Sampler: trace.AlwaysSample(), - }, - } - - req, err := http.NewRequest("POST", server.URL, strings.NewReader("req-body")) - if err != nil { - t.Errorf("error creating request: %v", err) - } - - resp, err := tr.RoundTrip(req) - if err != nil { - t.Errorf("response error: %v", err) - } - if err := resp.Body.Close(); err != nil { - t.Errorf("error closing response body: %v", err) - } - if got, want := resp.StatusCode, 200; got != want { - t.Errorf("resp.StatusCode=%d; want=%d", got, want) - } - - if got, want := len(recorder.spans), 1; got != want { - t.Fatalf("span count=%d; want=%d", got, want) - } - - var annotations []string - for _, annotation := range recorder.spans[0].Annotations { - annotations = append(annotations, annotation.Message) - } - - required := []string{ - "GetConn", "GotConn", "GotFirstResponseByte", "ConnectStart", - "ConnectDone", "WroteHeaders", "WroteRequest", - } - - if errs := requiredAnnotations(required, annotations); len(errs) > 0 { - for _, err := range errs { - t.Error(err) - } - } - -} - -type testExporter struct { - mu sync.Mutex - spans []*trace.SpanData -} - -func (t *testExporter) ExportSpan(s *trace.SpanData) { - t.mu.Lock() - t.spans = append(t.spans, s) - t.mu.Unlock() -} - -func requiredAnnotations(required []string, list []string) []error { - var errs []error - for _, item := range required { - var found bool - for _, v := range list { - if v == item { - found = true - } - } - if !found { - errs = append(errs, errors.New("missing expected annotation: "+item)) - } - } - return errs -} diff --git a/vendor/go.opencensus.io/plugin/ochttp/stats_test.go b/vendor/go.opencensus.io/plugin/ochttp/stats_test.go deleted file mode 100644 index ce3621bf..00000000 --- a/vendor/go.opencensus.io/plugin/ochttp/stats_test.go +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2018, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package ochttp - -import ( - "reflect" - "strings" - "testing" - - "go.opencensus.io/stats" - "go.opencensus.io/stats/view" - "go.opencensus.io/tag" -) - -func TestClientViews(t *testing.T) { - for _, v := range []*view.View{ - ClientSentBytesDistribution, - ClientReceivedBytesDistribution, - ClientRoundtripLatencyDistribution, - ClientCompletedCount, - } { - - if v.Measure == nil { - t.Fatalf("nil measure: %v", v) - } - if m := v.Measure.Name(); !strings.HasPrefix(m, "opencensus.io/http/client/") { - t.Errorf("Unexpected measure name prefix: %v", v) - } - if v.Name == "" { - t.Errorf("Empty name: %v", v) - } - if !strings.HasPrefix(v.Name, "opencensus.io/http/client/") { - t.Errorf("Unexpected prefix: %s", v.Name) - } - if v.Description == "" { - t.Errorf("Empty description: %s", v.Name) - } - if !reflect.DeepEqual(v.TagKeys, []tag.Key{KeyClientMethod, KeyClientStatus}) { - t.Errorf("Unexpected tags for client view %s: %v", v.Name, v.TagKeys) - } - if strings.HasSuffix(v.Description, ".") { - t.Errorf("View description should not end with a period: %s", v.Name) - } - } -} - -func TestClientTagKeys(t *testing.T) { - for _, k := range []tag.Key{ - KeyClientStatus, - KeyClientMethod, - KeyClientHost, - KeyClientPath, - } { - if !strings.HasPrefix(k.Name(), "http_client_") { - t.Errorf("Unexpected prefix: %s", k.Name()) - } - } -} - -func TestClientMeasures(t *testing.T) { - for _, m := range []stats.Measure{ - ClientSentBytes, - ClientReceivedBytes, - ClientRoundtripLatency, - } { - if !strings.HasPrefix(m.Name(), "opencensus.io/http/client/") { - t.Errorf("Unexpected prefix: %v", m) - } - if strings.HasSuffix(m.Description(), ".") { - t.Errorf("View description should not end with a period: %s", m.Name()) - } - if len(m.Unit()) == 0 { - t.Errorf("No unit: %s", m.Name()) - } - } -} diff --git a/vendor/go.opencensus.io/plugin/ochttp/trace_test.go b/vendor/go.opencensus.io/plugin/ochttp/trace_test.go deleted file mode 100644 index ea9b77c0..00000000 --- a/vendor/go.opencensus.io/plugin/ochttp/trace_test.go +++ /dev/null @@ -1,543 +0,0 @@ -// Copyright 2018, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package ochttp - -import ( - "bytes" - "context" - "encoding/hex" - "errors" - "fmt" - "io" - "io/ioutil" - "log" - "net/http" - "net/http/httptest" - "reflect" - "strings" - "testing" - "time" - - "go.opencensus.io/plugin/ochttp/propagation/b3" - "go.opencensus.io/plugin/ochttp/propagation/tracecontext" - "go.opencensus.io/trace" -) - -type testExporter struct { - spans []*trace.SpanData -} - -func (t *testExporter) ExportSpan(s *trace.SpanData) { - t.spans = append(t.spans, s) -} - -type testTransport struct { - ch chan *http.Request -} - -func (t *testTransport) RoundTrip(req *http.Request) (*http.Response, error) { - t.ch <- req - return nil, errors.New("noop") -} - -type testPropagator struct{} - -func (t testPropagator) SpanContextFromRequest(req *http.Request) (sc trace.SpanContext, ok bool) { - header := req.Header.Get("trace") - buf, err := hex.DecodeString(header) - if err != nil { - log.Fatalf("Cannot decode trace header: %q", header) - } - r := bytes.NewReader(buf) - r.Read(sc.TraceID[:]) - r.Read(sc.SpanID[:]) - opts, err := r.ReadByte() - if err != nil { - log.Fatalf("Cannot read trace options from trace header: %q", header) - } - sc.TraceOptions = trace.TraceOptions(opts) - return sc, true -} - -func (t testPropagator) SpanContextToRequest(sc trace.SpanContext, req *http.Request) { - var buf bytes.Buffer - buf.Write(sc.TraceID[:]) - buf.Write(sc.SpanID[:]) - buf.WriteByte(byte(sc.TraceOptions)) - req.Header.Set("trace", hex.EncodeToString(buf.Bytes())) -} - -func TestTransport_RoundTrip_Race(t *testing.T) { - // This tests that we don't modify the request in accordance with the - // specification for http.RoundTripper. - // We attempt to trigger a race by reading the request from a separate - // goroutine. If the request is modified by Transport, this should trigger - // the race detector. - - transport := &testTransport{ch: make(chan *http.Request, 1)} - rt := &Transport{ - Propagation: &testPropagator{}, - Base: transport, - } - req, _ := http.NewRequest("GET", "http://foo.com", nil) - go func() { - fmt.Println(*req) - }() - rt.RoundTrip(req) - _ = <-transport.ch -} - -func TestTransport_RoundTrip(t *testing.T) { - ctx := context.Background() - ctx, parent := trace.StartSpan(ctx, "parent") - tests := []struct { - name string - parent *trace.Span - }{ - { - name: "no parent", - parent: nil, - }, - { - name: "parent", - parent: parent, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - transport := &testTransport{ch: make(chan *http.Request, 1)} - - rt := &Transport{ - Propagation: &testPropagator{}, - Base: transport, - } - - req, _ := http.NewRequest("GET", "http://foo.com", nil) - if tt.parent != nil { - req = req.WithContext(trace.NewContext(req.Context(), tt.parent)) - } - rt.RoundTrip(req) - - req = <-transport.ch - span := trace.FromContext(req.Context()) - - if header := req.Header.Get("trace"); header == "" { - t.Fatalf("Trace header = empty; want valid trace header") - } - if span == nil { - t.Fatalf("Got no spans in req context; want one") - } - if tt.parent != nil { - if got, want := span.SpanContext().TraceID, tt.parent.SpanContext().TraceID; got != want { - t.Errorf("span.SpanContext().TraceID=%v; want %v", got, want) - } - } - }) - } -} - -func TestHandler(t *testing.T) { - traceID := [16]byte{16, 84, 69, 170, 120, 67, 188, 139, 242, 6, 177, 32, 0, 16, 0, 0} - tests := []struct { - header string - wantTraceID trace.TraceID - wantTraceOptions trace.TraceOptions - }{ - { - header: "105445aa7843bc8bf206b12000100000000000000000000000", - wantTraceID: traceID, - wantTraceOptions: trace.TraceOptions(0), - }, - { - header: "105445aa7843bc8bf206b12000100000000000000000000001", - wantTraceID: traceID, - wantTraceOptions: trace.TraceOptions(1), - }, - } - - for _, tt := range tests { - t.Run(tt.header, func(t *testing.T) { - handler := &Handler{ - Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - span := trace.FromContext(r.Context()) - sc := span.SpanContext() - if got, want := sc.TraceID, tt.wantTraceID; got != want { - t.Errorf("TraceID = %q; want %q", got, want) - } - if got, want := sc.TraceOptions, tt.wantTraceOptions; got != want { - t.Errorf("TraceOptions = %v; want %v", got, want) - } - }), - StartOptions: trace.StartOptions{Sampler: trace.ProbabilitySampler(0.0)}, - Propagation: &testPropagator{}, - } - req, _ := http.NewRequest("GET", "http://foo.com", nil) - req.Header.Add("trace", tt.header) - handler.ServeHTTP(nil, req) - }) - } -} - -var _ http.RoundTripper = (*traceTransport)(nil) - -type collector []*trace.SpanData - -func (c *collector) ExportSpan(s *trace.SpanData) { - *c = append(*c, s) -} - -func TestEndToEnd(t *testing.T) { - tc := []struct { - name string - handler *Handler - transport *Transport - wantSameTraceID bool - wantLinks bool // expect a link between client and server span - }{ - { - name: "internal default propagation", - handler: &Handler{}, - transport: &Transport{}, - wantSameTraceID: true, - }, - { - name: "external default propagation", - handler: &Handler{IsPublicEndpoint: true}, - transport: &Transport{}, - wantSameTraceID: false, - wantLinks: true, - }, - { - name: "internal TraceContext propagation", - handler: &Handler{Propagation: &tracecontext.HTTPFormat{}}, - transport: &Transport{Propagation: &tracecontext.HTTPFormat{}}, - wantSameTraceID: true, - }, - { - name: "misconfigured propagation", - handler: &Handler{IsPublicEndpoint: true, Propagation: &tracecontext.HTTPFormat{}}, - transport: &Transport{Propagation: &b3.HTTPFormat{}}, - wantSameTraceID: false, - wantLinks: false, - }, - } - - for _, tt := range tc { - t.Run(tt.name, func(t *testing.T) { - var spans collector - trace.RegisterExporter(&spans) - defer trace.UnregisterExporter(&spans) - - // Start the server. - serverDone := make(chan struct{}) - serverReturn := make(chan time.Time) - tt.handler.StartOptions.Sampler = trace.AlwaysSample() - url := serveHTTP(tt.handler, serverDone, serverReturn) - - ctx := context.Background() - // Make the request. - req, err := http.NewRequest( - http.MethodPost, - fmt.Sprintf("%s/example/url/path?qparam=val", url), - strings.NewReader("expected-request-body")) - if err != nil { - t.Fatal(err) - } - req = req.WithContext(ctx) - tt.transport.StartOptions.Sampler = trace.AlwaysSample() - c := &http.Client{ - Transport: tt.transport, - } - resp, err := c.Do(req) - if err != nil { - t.Fatal(err) - } - if resp.StatusCode != http.StatusOK { - t.Fatalf("resp.StatusCode = %d", resp.StatusCode) - } - - // Tell the server to return from request handling. - serverReturn <- time.Now().Add(time.Millisecond) - - respBody, err := ioutil.ReadAll(resp.Body) - if err != nil { - t.Fatal(err) - } - if got, want := string(respBody), "expected-response"; got != want { - t.Fatalf("respBody = %q; want %q", got, want) - } - - resp.Body.Close() - - <-serverDone - trace.UnregisterExporter(&spans) - - if got, want := len(spans), 2; got != want { - t.Fatalf("len(spans) = %d; want %d", got, want) - } - - var client, server *trace.SpanData - for _, sp := range spans { - switch sp.SpanKind { - case trace.SpanKindClient: - client = sp - if got, want := client.Name, "/example/url/path"; got != want { - t.Errorf("Span name: %q; want %q", got, want) - } - case trace.SpanKindServer: - server = sp - if got, want := server.Name, "/example/url/path"; got != want { - t.Errorf("Span name: %q; want %q", got, want) - } - default: - t.Fatalf("server or client span missing; kind = %v", sp.SpanKind) - } - } - - if tt.wantSameTraceID { - if server.TraceID != client.TraceID { - t.Errorf("TraceID does not match: server.TraceID=%q client.TraceID=%q", server.TraceID, client.TraceID) - } - if !server.HasRemoteParent { - t.Errorf("server span should have remote parent") - } - if server.ParentSpanID != client.SpanID { - t.Errorf("server span should have client span as parent") - } - } - if !tt.wantSameTraceID { - if server.TraceID == client.TraceID { - t.Errorf("TraceID should not be trusted") - } - } - if tt.wantLinks { - if got, want := len(server.Links), 1; got != want { - t.Errorf("len(server.Links) = %d; want %d", got, want) - } else { - link := server.Links[0] - if got, want := link.Type, trace.LinkTypeChild; got != want { - t.Errorf("link.Type = %v; want %v", got, want) - } - } - } - if server.StartTime.Before(client.StartTime) { - t.Errorf("server span starts before client span") - } - if server.EndTime.After(client.EndTime) { - t.Errorf("client span ends before server span") - } - }) - } -} - -func serveHTTP(handler *Handler, done chan struct{}, wait chan time.Time) string { - handler.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(200) - w.(http.Flusher).Flush() - - // Simulate a slow-responding server. - sleepUntil := <-wait - for time.Now().Before(sleepUntil) { - time.Sleep(sleepUntil.Sub(time.Now())) - } - - io.WriteString(w, "expected-response") - close(done) - }) - server := httptest.NewServer(handler) - go func() { - <-done - server.Close() - }() - return server.URL -} - -func TestSpanNameFromURL(t *testing.T) { - tests := []struct { - u string - want string - }{ - { - u: "http://localhost:80/hello?q=a", - want: "/hello", - }, - { - u: "/a/b?q=c", - want: "/a/b", - }, - } - for _, tt := range tests { - t.Run(tt.u, func(t *testing.T) { - req, err := http.NewRequest("GET", tt.u, nil) - if err != nil { - t.Errorf("url issue = %v", err) - } - if got := spanNameFromURL(req); got != tt.want { - t.Errorf("spanNameFromURL() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestFormatSpanName(t *testing.T) { - formatSpanName := func(r *http.Request) string { - return r.Method + " " + r.URL.Path - } - - handler := &Handler{ - Handler: http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { - resp.Write([]byte("Hello, world!")) - }), - FormatSpanName: formatSpanName, - } - - server := httptest.NewServer(handler) - defer server.Close() - - client := &http.Client{ - Transport: &Transport{ - FormatSpanName: formatSpanName, - StartOptions: trace.StartOptions{ - Sampler: trace.AlwaysSample(), - }, - }, - } - - tests := []struct { - u string - want string - }{ - { - u: "/hello?q=a", - want: "GET /hello", - }, - { - u: "/a/b?q=c", - want: "GET /a/b", - }, - } - - for _, tt := range tests { - t.Run(tt.u, func(t *testing.T) { - var te testExporter - trace.RegisterExporter(&te) - res, err := client.Get(server.URL + tt.u) - if err != nil { - t.Fatalf("error creating request: %v", err) - } - res.Body.Close() - trace.UnregisterExporter(&te) - if want, got := 2, len(te.spans); want != got { - t.Fatalf("got exported spans %#v, wanted two spans", te.spans) - } - if got := te.spans[0].Name; got != tt.want { - t.Errorf("spanNameFromURL() = %v, want %v", got, tt.want) - } - if got := te.spans[1].Name; got != tt.want { - t.Errorf("spanNameFromURL() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestRequestAttributes(t *testing.T) { - tests := []struct { - name string - makeReq func() *http.Request - wantAttrs []trace.Attribute - }{ - { - name: "GET example.com/hello", - makeReq: func() *http.Request { - req, _ := http.NewRequest("GET", "http://example.com:779/hello", nil) - req.Header.Add("User-Agent", "ua") - return req - }, - wantAttrs: []trace.Attribute{ - trace.StringAttribute("http.path", "/hello"), - trace.StringAttribute("http.host", "example.com:779"), - trace.StringAttribute("http.method", "GET"), - trace.StringAttribute("http.user_agent", "ua"), - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - req := tt.makeReq() - attrs := requestAttrs(req) - - if got, want := attrs, tt.wantAttrs; !reflect.DeepEqual(got, want) { - t.Errorf("Request attributes = %#v; want %#v", got, want) - } - }) - } -} - -func TestResponseAttributes(t *testing.T) { - tests := []struct { - name string - resp *http.Response - wantAttrs []trace.Attribute - }{ - { - name: "non-zero HTTP 200 response", - resp: &http.Response{StatusCode: 200}, - wantAttrs: []trace.Attribute{ - trace.Int64Attribute("http.status_code", 200), - }, - }, - { - name: "zero HTTP 500 response", - resp: &http.Response{StatusCode: 500}, - wantAttrs: []trace.Attribute{ - trace.Int64Attribute("http.status_code", 500), - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - attrs := responseAttrs(tt.resp) - if got, want := attrs, tt.wantAttrs; !reflect.DeepEqual(got, want) { - t.Errorf("Response attributes = %#v; want %#v", got, want) - } - }) - } -} - -func TestStatusUnitTest(t *testing.T) { - tests := []struct { - in int - want trace.Status - }{ - {200, trace.Status{Code: trace.StatusCodeOK, Message: `OK`}}, - {204, trace.Status{Code: trace.StatusCodeOK, Message: `OK`}}, - {100, trace.Status{Code: trace.StatusCodeUnknown, Message: `UNKNOWN`}}, - {500, trace.Status{Code: trace.StatusCodeUnknown, Message: `UNKNOWN`}}, - {404, trace.Status{Code: trace.StatusCodeNotFound, Message: `NOT_FOUND`}}, - {600, trace.Status{Code: trace.StatusCodeUnknown, Message: `UNKNOWN`}}, - {401, trace.Status{Code: trace.StatusCodeUnauthenticated, Message: `UNAUTHENTICATED`}}, - {403, trace.Status{Code: trace.StatusCodePermissionDenied, Message: `PERMISSION_DENIED`}}, - {301, trace.Status{Code: trace.StatusCodeOK, Message: `OK`}}, - {501, trace.Status{Code: trace.StatusCodeUnimplemented, Message: `UNIMPLEMENTED`}}, - } - - for _, tt := range tests { - got, want := TraceStatus(tt.in, ""), tt.want - if got != want { - t.Errorf("status(%d) got = (%#v) want = (%#v)", tt.in, got, want) - } - } -} diff --git a/vendor/go.opencensus.io/stats/benchmark_test.go b/vendor/go.opencensus.io/stats/benchmark_test.go deleted file mode 100644 index 3e0264fa..00000000 --- a/vendor/go.opencensus.io/stats/benchmark_test.go +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2017, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package stats_test - -import ( - "context" - "testing" - - "go.opencensus.io/stats" - _ "go.opencensus.io/stats/view" // enable collection - "go.opencensus.io/tag" -) - -var m = makeMeasure() - -func BenchmarkRecord0(b *testing.B) { - ctx := context.Background() - b.ResetTimer() - - for i := 0; i < b.N; i++ { - stats.Record(ctx) - } -} - -func BenchmarkRecord1(b *testing.B) { - ctx := context.Background() - b.ResetTimer() - - for i := 0; i < b.N; i++ { - stats.Record(ctx, m.M(1)) - } -} - -func BenchmarkRecord8(b *testing.B) { - ctx := context.Background() - b.ResetTimer() - - for i := 0; i < b.N; i++ { - stats.Record(ctx, m.M(1), m.M(1), m.M(1), m.M(1), m.M(1), m.M(1), m.M(1), m.M(1)) - } -} - -func BenchmarkRecord8_Parallel(b *testing.B) { - ctx := context.Background() - b.ResetTimer() - - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - stats.Record(ctx, m.M(1), m.M(1), m.M(1), m.M(1), m.M(1), m.M(1), m.M(1), m.M(1)) - } - }) -} - -func BenchmarkRecord8_8Tags(b *testing.B) { - ctx := context.Background() - key1, _ := tag.NewKey("key1") - key2, _ := tag.NewKey("key2") - key3, _ := tag.NewKey("key3") - key4, _ := tag.NewKey("key4") - key5, _ := tag.NewKey("key5") - key6, _ := tag.NewKey("key6") - key7, _ := tag.NewKey("key7") - key8, _ := tag.NewKey("key8") - - tag.New(ctx, - tag.Insert(key1, "value"), - tag.Insert(key2, "value"), - tag.Insert(key3, "value"), - tag.Insert(key4, "value"), - tag.Insert(key5, "value"), - tag.Insert(key6, "value"), - tag.Insert(key7, "value"), - tag.Insert(key8, "value"), - ) - b.ResetTimer() - - for i := 0; i < b.N; i++ { - stats.Record(ctx, m.M(1), m.M(1), m.M(1), m.M(1), m.M(1), m.M(1), m.M(1), m.M(1)) - } -} - -func makeMeasure() *stats.Int64Measure { - return stats.Int64("m", "test measure", "") -} diff --git a/vendor/go.opencensus.io/stats/example_test.go b/vendor/go.opencensus.io/stats/example_test.go deleted file mode 100644 index 5520eac8..00000000 --- a/vendor/go.opencensus.io/stats/example_test.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2017, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package stats_test - -import ( - "context" - - "go.opencensus.io/stats" -) - -func ExampleRecord() { - ctx := context.Background() - - // Measures are usually declared as package-private global variables. - openConns := stats.Int64("example.com/measure/openconns", "open connections", stats.UnitDimensionless) - - // Instrumented packages call stats.Record() to record measuremens. - stats.Record(ctx, openConns.M(124)) // Record 124 open connections. - - // Without any views or exporters registered, this statement has no observable effects. -} diff --git a/vendor/go.opencensus.io/stats/view/aggregation_data_test.go b/vendor/go.opencensus.io/stats/view/aggregation_data_test.go deleted file mode 100644 index 9b12b853..00000000 --- a/vendor/go.opencensus.io/stats/view/aggregation_data_test.go +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright 2018, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -package view - -import ( - "reflect" - "testing" - "time" - - "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" - "go.opencensus.io/exemplar" -) - -func TestDataClone(t *testing.T) { - dist := newDistributionData([]float64{1, 2, 3, 4}) - dist.Count = 7 - dist.Max = 11 - dist.Min = 1 - dist.CountPerBucket = []int64{0, 2, 3, 2} - dist.Mean = 4 - dist.SumOfSquaredDev = 1.2 - - tests := []struct { - name string - src AggregationData - }{ - { - name: "count data", - src: &CountData{Value: 5}, - }, - { - name: "distribution data", - src: dist, - }, - { - name: "sum data", - src: &SumData{Value: 65.7}, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got := tt.src.clone() - if !reflect.DeepEqual(got, tt.src) { - t.Errorf("AggregationData.clone() = %v, want %v", got, tt.src) - } - // TODO(jbd): Make sure that data is deep copied. - if got == tt.src { - t.Errorf("AggregationData.clone() returned the same pointer") - } - }) - } -} - -func TestDistributionData_addSample(t *testing.T) { - dd := newDistributionData([]float64{0, 1, 2}) - t1, _ := time.Parse("Mon Jan 2 15:04:05 -0700 MST 2006", "Mon Jan 2 15:04:05 -0700 MST 2006") - e1 := &exemplar.Exemplar{ - Attachments: exemplar.Attachments{ - "tag:X": "Y", - "tag:A": "B", - }, - Timestamp: t1, - Value: 0.5, - } - dd.addSample(e1) - - want := &DistributionData{ - Count: 1, - CountPerBucket: []int64{0, 1, 0, 0}, - ExemplarsPerBucket: []*exemplar.Exemplar{nil, e1, nil, nil}, - Max: 0.5, - Min: 0.5, - Mean: 0.5, - SumOfSquaredDev: 0, - } - if diff := cmpDD(dd, want); diff != "" { - t.Fatalf("Unexpected DistributionData -got +want: %s", diff) - } - - t2 := t1.Add(time.Microsecond) - e2 := &exemplar.Exemplar{ - Attachments: exemplar.Attachments{ - "tag:X": "Y", - }, - Timestamp: t2, - Value: 0.7, - } - dd.addSample(e2) - - // Previous exemplar should be preserved, since it has more annotations. - want = &DistributionData{ - Count: 2, - CountPerBucket: []int64{0, 2, 0, 0}, - ExemplarsPerBucket: []*exemplar.Exemplar{nil, e1, nil, nil}, - Max: 0.7, - Min: 0.5, - Mean: 0.6, - SumOfSquaredDev: 0, - } - if diff := cmpDD(dd, want); diff != "" { - t.Fatalf("Unexpected DistributionData -got +want: %s", diff) - } - - t3 := t2.Add(time.Microsecond) - e3 := &exemplar.Exemplar{ - Attachments: exemplar.Attachments{ - exemplar.KeyTraceID: "abcd", - }, - Timestamp: t3, - Value: 0.2, - } - dd.addSample(e3) - - // Exemplar should be replaced since it has a trace_id. - want = &DistributionData{ - Count: 3, - CountPerBucket: []int64{0, 3, 0, 0}, - ExemplarsPerBucket: []*exemplar.Exemplar{nil, e3, nil, nil}, - Max: 0.7, - Min: 0.2, - Mean: 0.4666666666666667, - SumOfSquaredDev: 0, - } - if diff := cmpDD(dd, want); diff != "" { - t.Fatalf("Unexpected DistributionData -got +want: %s", diff) - } -} - -func cmpDD(got, want *DistributionData) string { - return cmp.Diff(got, want, cmpopts.IgnoreFields(DistributionData{}, "SumOfSquaredDev"), cmpopts.IgnoreUnexported(DistributionData{})) -} diff --git a/vendor/go.opencensus.io/stats/view/benchmark_test.go b/vendor/go.opencensus.io/stats/view/benchmark_test.go deleted file mode 100644 index 0f195d43..00000000 --- a/vendor/go.opencensus.io/stats/view/benchmark_test.go +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2018, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -package view - -import ( - "context" - "fmt" - "testing" - "time" - - "go.opencensus.io/stats" - "go.opencensus.io/tag" -) - -var ( - m = stats.Float64("m", "", "") - k1, _ = tag.NewKey("k1") - k2, _ = tag.NewKey("k2") - k3, _ = tag.NewKey("k3") - k4, _ = tag.NewKey("k4") - k5, _ = tag.NewKey("k5") - k6, _ = tag.NewKey("k6") - k7, _ = tag.NewKey("k7") - k8, _ = tag.NewKey("k8") - view = &View{ - Measure: m, - Aggregation: Distribution(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), - TagKeys: []tag.Key{k1, k2}, - } -) - -// BenchmarkRecordReqCommand benchmarks calling the internal recording machinery -// directly. -func BenchmarkRecordReqCommand(b *testing.B) { - w := newWorker() - - register := ®isterViewReq{views: []*View{view}, err: make(chan error, 1)} - register.handleCommand(w) - if err := <-register.err; err != nil { - b.Fatal(err) - } - - const tagCount = 10 - ctxs := make([]context.Context, 0, tagCount) - for i := 0; i < tagCount; i++ { - ctx, _ := tag.New(context.Background(), - tag.Upsert(k1, fmt.Sprintf("v%d", i)), - tag.Upsert(k2, fmt.Sprintf("v%d", i)), - tag.Upsert(k3, fmt.Sprintf("v%d", i)), - tag.Upsert(k4, fmt.Sprintf("v%d", i)), - tag.Upsert(k5, fmt.Sprintf("v%d", i)), - tag.Upsert(k6, fmt.Sprintf("v%d", i)), - tag.Upsert(k7, fmt.Sprintf("v%d", i)), - tag.Upsert(k8, fmt.Sprintf("v%d", i)), - ) - ctxs = append(ctxs, ctx) - } - - b.ReportAllocs() - b.ResetTimer() - - for i := 0; i < b.N; i++ { - record := &recordReq{ - ms: []stats.Measurement{ - m.M(1), - m.M(1), - m.M(1), - m.M(1), - m.M(1), - m.M(1), - m.M(1), - m.M(1), - }, - tm: tag.FromContext(ctxs[i%len(ctxs)]), - t: time.Now(), - } - record.handleCommand(w) - } -} diff --git a/vendor/go.opencensus.io/stats/view/collector_test.go b/vendor/go.opencensus.io/stats/view/collector_test.go deleted file mode 100644 index 57720c10..00000000 --- a/vendor/go.opencensus.io/stats/view/collector_test.go +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2017, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package view - -import ( - "context" - "testing" - - "go.opencensus.io/tag" -) - -func TestEncodeDecodeTags(t *testing.T) { - ctx := context.Background() - type testData struct { - m *tag.Map - keys []tag.Key - want map[tag.Key][]byte - } - - k1, err := tag.NewKey("/encodedecodetest/k1") - if err != nil { - t.Fatal(err) - } - k2, err := tag.NewKey("/encodedecodetest/k2") - if err != nil { - t.Fatal(err) - } - k3, err := tag.NewKey("/encodedecodetest/k3") - if err != nil { - t.Fatal(err) - } - - ctx1, _ := tag.New(ctx) - ctx2, _ := tag.New(ctx, tag.Insert(k2, "v2")) - ctx3, _ := tag.New(ctx, tag.Insert(k1, "v1"), tag.Insert(k2, "v2")) - ctx4, _ := tag.New(ctx, tag.Insert(k1, "v1"), tag.Insert(k2, "v2"), tag.Insert(k3, "v3")) - - m1 := tag.FromContext(ctx1) - m2 := tag.FromContext(ctx2) - m3 := tag.FromContext(ctx3) - m4 := tag.FromContext(ctx4) - - tests := []testData{ - { - m1, - []tag.Key{k1}, - nil, - }, - { - m2, - []tag.Key{}, - nil, - }, - { - m2, - []tag.Key{k1}, - nil, - }, - { - m2, - []tag.Key{k2}, - map[tag.Key][]byte{ - k2: []byte("v2"), - }, - }, - { - m3, - []tag.Key{k1}, - map[tag.Key][]byte{ - k1: []byte("v1"), - }, - }, - { - m3, - []tag.Key{k1, k2}, - map[tag.Key][]byte{ - k1: []byte("v1"), - k2: []byte("v2"), - }, - }, - { - m4, - []tag.Key{k3, k1}, - map[tag.Key][]byte{ - k1: []byte("v1"), - k3: []byte("v3"), - }, - }, - } - - for label, tt := range tests { - tags := decodeTags(encodeWithKeys(tt.m, tt.keys), tt.keys) - if got, want := len(tags), len(tt.want); got != want { - t.Fatalf("%d: len(decoded) = %v; not %v", label, got, want) - } - - for _, tag := range tags { - if _, ok := tt.want[tag.Key]; !ok { - t.Errorf("%d: missing key %v", label, tag.Key) - } - if got, want := tag.Value, string(tt.want[tag.Key]); got != want { - t.Errorf("%d: got value %q; want %q", label, got, want) - } - } - } -} diff --git a/vendor/go.opencensus.io/stats/view/example_test.go b/vendor/go.opencensus.io/stats/view/example_test.go deleted file mode 100644 index 78556a31..00000000 --- a/vendor/go.opencensus.io/stats/view/example_test.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2018, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package view_test - -import ( - "log" - - "go.opencensus.io/stats" - "go.opencensus.io/stats/view" -) - -func Example() { - // Measures are usually declared and used by instrumented packages. - m := stats.Int64("example.com/measure/openconns", "open connections", stats.UnitDimensionless) - - // Views are usually registered in your application main function. - if err := view.Register(&view.View{ - Name: "example.com/views/openconns", - Description: "open connections", - Measure: m, - Aggregation: view.Distribution(0, 1000, 2000), - }); err != nil { - log.Fatal(err) - } - - // Use view.RegisterExporter to export collected data. -} diff --git a/vendor/go.opencensus.io/stats/view/view_measure_test.go b/vendor/go.opencensus.io/stats/view/view_measure_test.go deleted file mode 100644 index 6ee8413d..00000000 --- a/vendor/go.opencensus.io/stats/view/view_measure_test.go +++ /dev/null @@ -1,50 +0,0 @@ -package view - -import ( - "context" - "testing" - - "go.opencensus.io/stats" -) - -func TestMeasureFloat64AndInt64(t *testing.T) { - // Recording through both a Float64Measure and Int64Measure with the - // same name should work. - - im := stats.Int64("TestMeasureFloat64AndInt64", "", stats.UnitDimensionless) - fm := stats.Float64("TestMeasureFloat64AndInt64", "", stats.UnitDimensionless) - - if im == nil || fm == nil { - t.Fatal("Error creating Measures") - } - - v1 := &View{ - Name: "TestMeasureFloat64AndInt64/v1", - Measure: im, - Aggregation: Sum(), - } - v2 := &View{ - Name: "TestMeasureFloat64AndInt64/v2", - Measure: fm, - Aggregation: Sum(), - } - Register(v1, v2) - - stats.Record(context.Background(), im.M(5)) - stats.Record(context.Background(), fm.M(2.2)) - - d1, _ := RetrieveData(v1.Name) - d2, _ := RetrieveData(v2.Name) - - sum1 := d1[0].Data.(*SumData) - sum2 := d2[0].Data.(*SumData) - - // We expect both views to return 7.2, as though we recorded on a single measure. - - if got, want := sum1.Value, 7.2; got != want { - t.Errorf("sum1 = %v; want %v", got, want) - } - if got, want := sum2.Value, 7.2; got != want { - t.Errorf("sum2 = %v; want %v", got, want) - } -} diff --git a/vendor/go.opencensus.io/stats/view/view_test.go b/vendor/go.opencensus.io/stats/view/view_test.go deleted file mode 100644 index 445e56a1..00000000 --- a/vendor/go.opencensus.io/stats/view/view_test.go +++ /dev/null @@ -1,446 +0,0 @@ -// Copyright 2017, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -package view - -import ( - "context" - "testing" - - "go.opencensus.io/exemplar" - - "go.opencensus.io/stats" - "go.opencensus.io/tag" -) - -func Test_View_MeasureFloat64_AggregationDistribution(t *testing.T) { - k1, _ := tag.NewKey("k1") - k2, _ := tag.NewKey("k2") - k3, _ := tag.NewKey("k3") - agg1 := Distribution(2) - m := stats.Int64("Test_View_MeasureFloat64_AggregationDistribution/m1", "", stats.UnitDimensionless) - view1 := &View{ - TagKeys: []tag.Key{k1, k2}, - Measure: m, - Aggregation: agg1, - } - view, err := newViewInternal(view1) - if err != nil { - t.Fatal(err) - } - - type tagString struct { - k tag.Key - v string - } - type record struct { - f float64 - tags []tagString - } - - type testCase struct { - label string - records []record - wantRows []*Row - } - - tcs := []testCase{ - { - "1", - []record{ - {1, []tagString{{k1, "v1"}}}, - {5, []tagString{{k1, "v1"}}}, - }, - []*Row{ - { - []tag.Tag{{Key: k1, Value: "v1"}}, - &DistributionData{ - Count: 2, Min: 1, Max: 5, Mean: 3, SumOfSquaredDev: 8, CountPerBucket: []int64{1, 1}, bounds: []float64{2}, ExemplarsPerBucket: []*exemplar.Exemplar{nil, nil}, - }, - }, - }, - }, - { - "2", - []record{ - {1, []tagString{{k1, "v1"}}}, - {5, []tagString{{k2, "v2"}}}, - }, - []*Row{ - { - []tag.Tag{{Key: k1, Value: "v1"}}, - &DistributionData{ - Count: 1, Min: 1, Max: 1, Mean: 1, CountPerBucket: []int64{1, 0}, bounds: []float64{2}, ExemplarsPerBucket: []*exemplar.Exemplar{nil, nil}, - }, - }, - { - []tag.Tag{{Key: k2, Value: "v2"}}, - &DistributionData{ - Count: 1, Min: 5, Max: 5, Mean: 5, CountPerBucket: []int64{0, 1}, bounds: []float64{2}, ExemplarsPerBucket: []*exemplar.Exemplar{nil, nil}, - }, - }, - }, - }, - { - "3", - []record{ - {1, []tagString{{k1, "v1"}}}, - {5, []tagString{{k1, "v1"}, {k3, "v3"}}}, - {1, []tagString{{k1, "v1 other"}}}, - {5, []tagString{{k2, "v2"}}}, - {5, []tagString{{k1, "v1"}, {k2, "v2"}}}, - }, - []*Row{ - { - []tag.Tag{{Key: k1, Value: "v1"}}, - &DistributionData{ - Count: 2, Min: 1, Max: 5, Mean: 3, SumOfSquaredDev: 8, CountPerBucket: []int64{1, 1}, bounds: []float64{2}, ExemplarsPerBucket: []*exemplar.Exemplar{nil, nil}, - }, - }, - { - []tag.Tag{{Key: k1, Value: "v1 other"}}, - &DistributionData{ - Count: 1, Min: 1, Max: 1, Mean: 1, CountPerBucket: []int64{1, 0}, bounds: []float64{2}, ExemplarsPerBucket: []*exemplar.Exemplar{nil, nil}, - }, - }, - { - []tag.Tag{{Key: k2, Value: "v2"}}, - &DistributionData{ - Count: 1, Min: 5, Max: 5, Mean: 5, CountPerBucket: []int64{0, 1}, bounds: []float64{2}, ExemplarsPerBucket: []*exemplar.Exemplar{nil, nil}, - }, - }, - { - []tag.Tag{{Key: k1, Value: "v1"}, {Key: k2, Value: "v2"}}, - &DistributionData{ - Count: 1, Min: 5, Max: 5, Mean: 5, CountPerBucket: []int64{0, 1}, bounds: []float64{2}, ExemplarsPerBucket: []*exemplar.Exemplar{nil, nil}, - }, - }, - }, - }, - { - "4", - []record{ - {1, []tagString{{k1, "v1 is a very long value key"}}}, - {5, []tagString{{k1, "v1 is a very long value key"}, {k3, "v3"}}}, - {1, []tagString{{k1, "v1 is another very long value key"}}}, - {1, []tagString{{k1, "v1 is a very long value key"}, {k2, "v2 is a very long value key"}}}, - {5, []tagString{{k1, "v1 is a very long value key"}, {k2, "v2 is a very long value key"}}}, - {3, []tagString{{k1, "v1 is a very long value key"}, {k2, "v2 is a very long value key"}}}, - {3, []tagString{{k1, "v1 is a very long value key"}, {k2, "v2 is a very long value key"}}}, - }, - []*Row{ - { - []tag.Tag{{Key: k1, Value: "v1 is a very long value key"}}, - &DistributionData{ - Count: 2, Min: 1, Max: 5, Mean: 3, SumOfSquaredDev: 8, CountPerBucket: []int64{1, 1}, bounds: []float64{2}, ExemplarsPerBucket: []*exemplar.Exemplar{nil, nil}, - }, - }, - { - []tag.Tag{{Key: k1, Value: "v1 is another very long value key"}}, - &DistributionData{ - Count: 1, Min: 1, Max: 1, Mean: 1, CountPerBucket: []int64{1, 0}, bounds: []float64{2}, ExemplarsPerBucket: []*exemplar.Exemplar{nil, nil}, - }, - }, - { - []tag.Tag{{Key: k1, Value: "v1 is a very long value key"}, {Key: k2, Value: "v2 is a very long value key"}}, - &DistributionData{ - Count: 4, Min: 1, Max: 5, Mean: 3, SumOfSquaredDev: 2.66666666666667 * 3, CountPerBucket: []int64{1, 3}, bounds: []float64{2}, ExemplarsPerBucket: []*exemplar.Exemplar{nil, nil}, - }, - }, - }, - }, - } - - for _, tc := range tcs { - view.clearRows() - view.subscribe() - for _, r := range tc.records { - mods := []tag.Mutator{} - for _, t := range r.tags { - mods = append(mods, tag.Insert(t.k, t.v)) - } - ctx, err := tag.New(context.Background(), mods...) - if err != nil { - t.Errorf("%v: New = %v", tc.label, err) - } - e := &exemplar.Exemplar{ - Value: r.f, - Attachments: exemplar.AttachmentsFromContext(ctx), - } - view.addSample(tag.FromContext(ctx), e) - } - - gotRows := view.collectedRows() - for i, got := range gotRows { - if !containsRow(tc.wantRows, got) { - t.Errorf("%v-%d: got row %v; want none", tc.label, i, got) - break - } - } - - for i, want := range tc.wantRows { - if !containsRow(gotRows, want) { - t.Errorf("%v-%d: got none; want row %v", tc.label, i, want) - break - } - } - } -} - -func Test_View_MeasureFloat64_AggregationSum(t *testing.T) { - k1, _ := tag.NewKey("k1") - k2, _ := tag.NewKey("k2") - k3, _ := tag.NewKey("k3") - m := stats.Int64("Test_View_MeasureFloat64_AggregationSum/m1", "", stats.UnitDimensionless) - view, err := newViewInternal(&View{TagKeys: []tag.Key{k1, k2}, Measure: m, Aggregation: Sum()}) - if err != nil { - t.Fatal(err) - } - - type tagString struct { - k tag.Key - v string - } - type record struct { - f float64 - tags []tagString - } - - tcs := []struct { - label string - records []record - wantRows []*Row - }{ - { - "1", - []record{ - {1, []tagString{{k1, "v1"}}}, - {5, []tagString{{k1, "v1"}}}, - }, - []*Row{ - { - []tag.Tag{{Key: k1, Value: "v1"}}, - &SumData{Value: 6}, - }, - }, - }, - { - "2", - []record{ - {1, []tagString{{k1, "v1"}}}, - {5, []tagString{{k2, "v2"}}}, - }, - []*Row{ - { - []tag.Tag{{Key: k1, Value: "v1"}}, - &SumData{Value: 1}, - }, - { - []tag.Tag{{Key: k2, Value: "v2"}}, - &SumData{Value: 5}, - }, - }, - }, - { - "3", - []record{ - {1, []tagString{{k1, "v1"}}}, - {5, []tagString{{k1, "v1"}, {k3, "v3"}}}, - {1, []tagString{{k1, "v1 other"}}}, - {5, []tagString{{k2, "v2"}}}, - {5, []tagString{{k1, "v1"}, {k2, "v2"}}}, - }, - []*Row{ - { - []tag.Tag{{Key: k1, Value: "v1"}}, - &SumData{Value: 6}, - }, - { - []tag.Tag{{Key: k1, Value: "v1 other"}}, - &SumData{Value: 1}, - }, - { - []tag.Tag{{Key: k2, Value: "v2"}}, - &SumData{Value: 5}, - }, - { - []tag.Tag{{Key: k1, Value: "v1"}, {Key: k2, Value: "v2"}}, - &SumData{Value: 5}, - }, - }, - }, - } - - for _, tt := range tcs { - view.clearRows() - view.subscribe() - for _, r := range tt.records { - mods := []tag.Mutator{} - for _, t := range r.tags { - mods = append(mods, tag.Insert(t.k, t.v)) - } - ctx, err := tag.New(context.Background(), mods...) - if err != nil { - t.Errorf("%v: New = %v", tt.label, err) - } - e := &exemplar.Exemplar{ - Value: r.f, - } - view.addSample(tag.FromContext(ctx), e) - } - - gotRows := view.collectedRows() - for i, got := range gotRows { - if !containsRow(tt.wantRows, got) { - t.Errorf("%v-%d: got row %v; want none", tt.label, i, got) - break - } - } - - for i, want := range tt.wantRows { - if !containsRow(gotRows, want) { - t.Errorf("%v-%d: got none; want row %v", tt.label, i, want) - break - } - } - } -} - -func TestCanonicalize(t *testing.T) { - k1, _ := tag.NewKey("k1") - k2, _ := tag.NewKey("k2") - m := stats.Int64("TestCanonicalize/m1", "desc desc", stats.UnitDimensionless) - v := &View{TagKeys: []tag.Key{k2, k1}, Measure: m, Aggregation: Sum()} - err := v.canonicalize() - if err != nil { - t.Fatal(err) - } - if got, want := v.Name, "TestCanonicalize/m1"; got != want { - t.Errorf("vc.Name = %q; want %q", got, want) - } - if got, want := v.Description, "desc desc"; got != want { - t.Errorf("vc.Description = %q; want %q", got, want) - } - if got, want := len(v.TagKeys), 2; got != want { - t.Errorf("len(vc.TagKeys) = %d; want %d", got, want) - } - if got, want := v.TagKeys[0].Name(), "k1"; got != want { - t.Errorf("vc.TagKeys[0].Name() = %q; want %q", got, want) - } -} - -func TestViewSortedKeys(t *testing.T) { - k1, _ := tag.NewKey("a") - k2, _ := tag.NewKey("b") - k3, _ := tag.NewKey("c") - ks := []tag.Key{k1, k3, k2} - - m := stats.Int64("TestViewSortedKeys/m1", "", stats.UnitDimensionless) - Register(&View{ - Name: "sort_keys", - Description: "desc sort_keys", - TagKeys: ks, - Measure: m, - Aggregation: Sum(), - }) - // Register normalizes the view by sorting the tag keys, retrieve the normalized view - v := Find("sort_keys") - - want := []string{"a", "b", "c"} - vks := v.TagKeys - if len(vks) != len(want) { - t.Errorf("Keys = %+v; want %+v", vks, want) - } - - for i, v := range want { - if got, want := v, vks[i].Name(); got != want { - t.Errorf("View name = %q; want %q", got, want) - } - } -} - -// containsRow returns true if rows contain r. -func containsRow(rows []*Row, r *Row) bool { - for _, x := range rows { - if r.Equal(x) { - return true - } - } - return false -} - -func TestRegisterUnregisterParity(t *testing.T) { - measures := []stats.Measure{ - stats.Int64("ifoo", "iFOO", "iBar"), - stats.Float64("ffoo", "fFOO", "fBar"), - } - aggregations := []*Aggregation{ - Count(), - Sum(), - Distribution(1, 2.0, 4.0, 8.0, 16.0), - } - - for i := 0; i < 10; i++ { - for _, m := range measures { - for _, agg := range aggregations { - v := &View{ - Aggregation: agg, - Name: "Lookup here", - Measure: m, - } - if err := Register(v); err != nil { - t.Errorf("Iteration #%d:\nMeasure: (%#v)\nAggregation (%#v)\nError: %v", i, m, agg, err) - } - Unregister(v) - } - } - } -} - -func TestRegisterAfterMeasurement(t *testing.T) { - // Tests that we can register views after measurements are created and - // they still take effect. - - m := stats.Int64(t.Name(), "", stats.UnitDimensionless) - mm := m.M(1) - ctx := context.Background() - - stats.Record(ctx, mm) - v := &View{ - Measure: m, - Aggregation: Count(), - } - if err := Register(v); err != nil { - t.Fatal(err) - } - - rows, err := RetrieveData(v.Name) - if err != nil { - t.Fatal(err) - } - if len(rows) > 0 { - t.Error("View should not have data") - } - - stats.Record(ctx, mm) - - rows, err = RetrieveData(v.Name) - if err != nil { - t.Fatal(err) - } - if len(rows) == 0 { - t.Error("View should have data") - } -} diff --git a/vendor/go.opencensus.io/stats/view/worker_test.go b/vendor/go.opencensus.io/stats/view/worker_test.go deleted file mode 100644 index d4301464..00000000 --- a/vendor/go.opencensus.io/stats/view/worker_test.go +++ /dev/null @@ -1,435 +0,0 @@ -// Copyright 2017, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -package view - -import ( - "context" - "errors" - "sync" - "testing" - "time" - - "go.opencensus.io/stats" - "go.opencensus.io/tag" -) - -func Test_Worker_ViewRegistration(t *testing.T) { - someError := errors.New("some error") - - sc1 := make(chan *Data) - - type registration struct { - c chan *Data - vID string - err error - } - type testCase struct { - label string - registrations []registration - } - tcs := []testCase{ - { - "register v1ID", - []registration{ - { - sc1, - "v1ID", - nil, - }, - }, - }, - { - "register v1ID+v2ID", - []registration{ - { - sc1, - "v1ID", - nil, - }, - }, - }, - { - "register to v1ID; ??? to v1ID and view with same ID", - []registration{ - { - sc1, - "v1ID", - nil, - }, - { - sc1, - "v1SameNameID", - someError, - }, - }, - }, - } - - mf1 := stats.Float64("MF1/Test_Worker_ViewSubscription", "desc MF1", "unit") - mf2 := stats.Float64("MF2/Test_Worker_ViewSubscription", "desc MF2", "unit") - - for _, tc := range tcs { - t.Run(tc.label, func(t *testing.T) { - restart() - - views := map[string]*View{ - "v1ID": { - Name: "VF1", - Measure: mf1, - Aggregation: Count(), - }, - "v1SameNameID": { - Name: "VF1", - Description: "desc duplicate name VF1", - Measure: mf1, - Aggregation: Sum(), - }, - "v2ID": { - Name: "VF2", - Measure: mf2, - Aggregation: Count(), - }, - "vNilID": nil, - } - - for _, r := range tc.registrations { - v := views[r.vID] - err := Register(v) - if (err != nil) != (r.err != nil) { - t.Errorf("%v: Register() = %v, want %v", tc.label, err, r.err) - } - } - }) - } -} - -func Test_Worker_RecordFloat64(t *testing.T) { - restart() - - someError := errors.New("some error") - m := stats.Float64("Test_Worker_RecordFloat64/MF1", "desc MF1", "unit") - - k1, _ := tag.NewKey("k1") - k2, _ := tag.NewKey("k2") - ctx, err := tag.New(context.Background(), - tag.Insert(k1, "v1"), - tag.Insert(k2, "v2"), - ) - if err != nil { - t.Fatal(err) - } - - v1 := &View{"VF1", "desc VF1", []tag.Key{k1, k2}, m, Count()} - v2 := &View{"VF2", "desc VF2", []tag.Key{k1, k2}, m, Count()} - - type want struct { - v *View - rows []*Row - err error - } - type testCase struct { - label string - registrations []*View - records []float64 - wants []want - } - - tcs := []testCase{ - { - label: "0", - registrations: []*View{}, - records: []float64{1, 1}, - wants: []want{{v1, nil, someError}, {v2, nil, someError}}, - }, - { - label: "1", - registrations: []*View{v1}, - records: []float64{1, 1}, - wants: []want{ - { - v1, - []*Row{ - { - []tag.Tag{{Key: k1, Value: "v1"}, {Key: k2, Value: "v2"}}, - &CountData{Value: 2}, - }, - }, - nil, - }, - {v2, nil, someError}, - }, - }, - { - label: "2", - registrations: []*View{v1, v2}, - records: []float64{1, 1}, - wants: []want{ - { - v1, - []*Row{ - { - []tag.Tag{{Key: k1, Value: "v1"}, {Key: k2, Value: "v2"}}, - &CountData{Value: 2}, - }, - }, - nil, - }, - { - v2, - []*Row{ - { - []tag.Tag{{Key: k1, Value: "v1"}, {Key: k2, Value: "v2"}}, - &CountData{Value: 2}, - }, - }, - nil, - }, - }, - }, - } - - for _, tc := range tcs { - for _, v := range tc.registrations { - if err := Register(v); err != nil { - t.Fatalf("%v: Register(%v) = %v; want no errors", tc.label, v.Name, err) - } - } - - for _, value := range tc.records { - stats.Record(ctx, m.M(value)) - } - - for _, w := range tc.wants { - gotRows, err := RetrieveData(w.v.Name) - if (err != nil) != (w.err != nil) { - t.Fatalf("%s: RetrieveData(%v) = %v; want error = %v", tc.label, w.v.Name, err, w.err) - } - for _, got := range gotRows { - if !containsRow(w.rows, got) { - t.Errorf("%s: got row %#v; want none", tc.label, got) - break - } - } - for _, want := range w.rows { - if !containsRow(gotRows, want) { - t.Errorf("%s: got none; want %#v'", tc.label, want) - break - } - } - } - - // Cleaning up. - Unregister(tc.registrations...) - } -} - -func TestReportUsage(t *testing.T) { - ctx := context.Background() - - m := stats.Int64("measure", "desc", "unit") - - tests := []struct { - name string - view *View - wantMaxCount int64 - }{ - { - name: "cum", - view: &View{Name: "cum1", Measure: m, Aggregation: Count()}, - wantMaxCount: 8, - }, - { - name: "cum2", - view: &View{Name: "cum1", Measure: m, Aggregation: Count()}, - wantMaxCount: 8, - }, - } - - for _, tt := range tests { - restart() - SetReportingPeriod(25 * time.Millisecond) - - if err := Register(tt.view); err != nil { - t.Fatalf("%v: cannot register: %v", tt.name, err) - } - - e := &countExporter{} - RegisterExporter(e) - - stats.Record(ctx, m.M(1)) - stats.Record(ctx, m.M(1)) - stats.Record(ctx, m.M(1)) - stats.Record(ctx, m.M(1)) - - time.Sleep(50 * time.Millisecond) - - stats.Record(ctx, m.M(1)) - stats.Record(ctx, m.M(1)) - stats.Record(ctx, m.M(1)) - stats.Record(ctx, m.M(1)) - - time.Sleep(50 * time.Millisecond) - - e.Lock() - count := e.count - e.Unlock() - if got, want := count, tt.wantMaxCount; got > want { - t.Errorf("%v: got count data = %v; want at most %v", tt.name, got, want) - } - } - -} - -func Test_SetReportingPeriodReqNeverBlocks(t *testing.T) { - t.Parallel() - - worker := newWorker() - durations := []time.Duration{-1, 0, 10, 100 * time.Millisecond} - for i, duration := range durations { - ackChan := make(chan bool, 1) - cmd := &setReportingPeriodReq{c: ackChan, d: duration} - cmd.handleCommand(worker) - - select { - case <-ackChan: - case <-time.After(500 * time.Millisecond): // Arbitrarily using 500ms as the timeout duration. - t.Errorf("#%d: duration %v blocks", i, duration) - } - } -} - -func TestWorkerStarttime(t *testing.T) { - restart() - - ctx := context.Background() - m := stats.Int64("measure/TestWorkerStarttime", "desc", "unit") - v := &View{ - Name: "testview", - Measure: m, - Aggregation: Count(), - } - - SetReportingPeriod(25 * time.Millisecond) - if err := Register(v); err != nil { - t.Fatalf("cannot register to %v: %v", v.Name, err) - } - - e := &vdExporter{} - RegisterExporter(e) - defer UnregisterExporter(e) - - stats.Record(ctx, m.M(1)) - stats.Record(ctx, m.M(1)) - stats.Record(ctx, m.M(1)) - stats.Record(ctx, m.M(1)) - - time.Sleep(50 * time.Millisecond) - - stats.Record(ctx, m.M(1)) - stats.Record(ctx, m.M(1)) - stats.Record(ctx, m.M(1)) - stats.Record(ctx, m.M(1)) - - time.Sleep(50 * time.Millisecond) - - e.Lock() - if len(e.vds) == 0 { - t.Fatal("Got no view data; want at least one") - } - - var start time.Time - for _, vd := range e.vds { - if start.IsZero() { - start = vd.Start - } - if !vd.Start.Equal(start) { - t.Errorf("Cumulative view data start time = %v; want %v", vd.Start, start) - } - } - e.Unlock() -} - -func TestUnregisterReportsUsage(t *testing.T) { - restart() - ctx := context.Background() - - m1 := stats.Int64("measure", "desc", "unit") - view1 := &View{Name: "count", Measure: m1, Aggregation: Count()} - m2 := stats.Int64("measure2", "desc", "unit") - view2 := &View{Name: "count2", Measure: m2, Aggregation: Count()} - - SetReportingPeriod(time.Hour) - - if err := Register(view1, view2); err != nil { - t.Fatalf("cannot register: %v", err) - } - - e := &countExporter{} - RegisterExporter(e) - - stats.Record(ctx, m1.M(1)) - stats.Record(ctx, m2.M(1)) - stats.Record(ctx, m2.M(1)) - - Unregister(view2) - - // Unregister should only flush view2, so expect the count of 2. - want := int64(2) - - e.Lock() - got := e.totalCount - e.Unlock() - if got != want { - t.Errorf("got count data = %v; want %v", got, want) - } -} - -type countExporter struct { - sync.Mutex - count int64 - totalCount int64 -} - -func (e *countExporter) ExportView(vd *Data) { - if len(vd.Rows) == 0 { - return - } - d := vd.Rows[0].Data.(*CountData) - - e.Lock() - defer e.Unlock() - e.count = d.Value - e.totalCount += d.Value -} - -type vdExporter struct { - sync.Mutex - vds []*Data -} - -func (e *vdExporter) ExportView(vd *Data) { - e.Lock() - defer e.Unlock() - - e.vds = append(e.vds, vd) -} - -// restart stops the current processors and creates a new one. -func restart() { - defaultWorker.stop() - defaultWorker = newWorker() - go defaultWorker.start() -} diff --git a/vendor/go.opencensus.io/tag/context_test.go b/vendor/go.opencensus.io/tag/context_test.go deleted file mode 100644 index e85b1c40..00000000 --- a/vendor/go.opencensus.io/tag/context_test.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2018, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -package tag - -import ( - "context" - "testing" -) - -func TestExtractTagsAttachment(t *testing.T) { - // We can't depend on the stats of view package without creating a - // dependency cycle. - - var m map[string]string - ctx := context.Background() - - res := extractTagsAttachments(ctx, m) - if res != nil { - t.Fatalf("res = %v; want nil", res) - } - - k, _ := NewKey("test") - ctx, _ = New(ctx, Insert(k, "test123")) - res = extractTagsAttachments(ctx, m) - if res == nil { - t.Fatal("res = nil") - } - if got, want := res["tag:test"], "test123"; got != want { - t.Fatalf("res[Tags:test] = %v; want %v", got, want) - } -} diff --git a/vendor/go.opencensus.io/tag/example_test.go b/vendor/go.opencensus.io/tag/example_test.go deleted file mode 100644 index fe0c5d9e..00000000 --- a/vendor/go.opencensus.io/tag/example_test.go +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2017, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -package tag_test - -import ( - "context" - "log" - - "go.opencensus.io/tag" -) - -var ( - tagMap *tag.Map - ctx context.Context - key tag.Key -) - -func ExampleNewKey() { - // Get a key to represent user OS. - key, err := tag.NewKey("example.com/keys/user-os") - if err != nil { - log.Fatal(err) - } - _ = key // use key -} - -func ExampleNew() { - osKey, err := tag.NewKey("example.com/keys/user-os") - if err != nil { - log.Fatal(err) - } - userIDKey, err := tag.NewKey("example.com/keys/user-id") - if err != nil { - log.Fatal(err) - } - - ctx, err := tag.New(ctx, - tag.Insert(osKey, "macOS-10.12.5"), - tag.Upsert(userIDKey, "cde36753ed"), - ) - if err != nil { - log.Fatal(err) - } - - _ = ctx // use context -} - -func ExampleNew_replace() { - ctx, err := tag.New(ctx, - tag.Insert(key, "macOS-10.12.5"), - tag.Upsert(key, "macOS-10.12.7"), - ) - if err != nil { - log.Fatal(err) - } - - _ = ctx // use context -} - -func ExampleNewContext() { - // Propagate the tag map in the current context. - ctx := tag.NewContext(context.Background(), tagMap) - - _ = ctx // use context -} - -func ExampleFromContext() { - tagMap := tag.FromContext(ctx) - - _ = tagMap // use the tag map -} - -func ExampleDo() { - ctx, err := tag.New(ctx, - tag.Insert(key, "macOS-10.12.5"), - tag.Upsert(key, "macOS-10.12.7"), - ) - if err != nil { - log.Fatal(err) - } - tag.Do(ctx, func(ctx context.Context) { - _ = ctx // use context - }) -} diff --git a/vendor/go.opencensus.io/tag/map_codec_test.go b/vendor/go.opencensus.io/tag/map_codec_test.go deleted file mode 100644 index a5605e69..00000000 --- a/vendor/go.opencensus.io/tag/map_codec_test.go +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright 2017, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -package tag - -import ( - "context" - "reflect" - "sort" - "testing" -) - -func TestEncodeDecode(t *testing.T) { - k1, _ := NewKey("k1") - k2, _ := NewKey("k2") - k3, _ := NewKey("k3 is very weird <>.,?/'\";:`~!@#$%^&*()_-+={[}]|\\") - k4, _ := NewKey("k4") - - type keyValue struct { - k Key - v string - } - - testCases := []struct { - label string - pairs []keyValue - }{ - { - "0", - []keyValue{}, - }, - { - "1", - []keyValue{ - {k1, "v1"}, - }, - }, - { - "2", - []keyValue{ - {k1, "v1"}, - {k2, "v2"}, - }, - }, - { - "3", - []keyValue{ - {k1, "v1"}, - {k2, "v2"}, - {k3, "v3"}, - }, - }, - { - "4", - []keyValue{ - {k1, "v1"}, - {k2, "v2"}, - {k3, "v3"}, - {k4, "v4 is very weird <>.,?/'\";:`~!@#$%^&*()_-+={[}]|\\"}, - }, - }, - } - - for _, tc := range testCases { - mods := make([]Mutator, len(tc.pairs)) - for i, pair := range tc.pairs { - mods[i] = Upsert(pair.k, pair.v) - } - ctx, err := New(context.Background(), mods...) - if err != nil { - t.Errorf("%v: New = %v", tc.label, err) - } - - encoded := Encode(FromContext(ctx)) - decoded, err := Decode(encoded) - if err != nil { - t.Errorf("%v: decoding encoded tag map failed: %v", tc.label, err) - } - - got := make([]keyValue, 0) - for k, v := range decoded.m { - got = append(got, keyValue{k, string(v)}) - } - want := tc.pairs - - sort.Slice(got, func(i, j int) bool { return got[i].k.name < got[j].k.name }) - sort.Slice(want, func(i, j int) bool { return got[i].k.name < got[j].k.name }) - - if !reflect.DeepEqual(got, tc.pairs) { - t.Errorf("%v: decoded tag map = %#v; want %#v", tc.label, got, want) - } - } -} - -func TestDecode(t *testing.T) { - k1, _ := NewKey("k1") - ctx, _ := New(context.Background(), Insert(k1, "v1")) - - tests := []struct { - name string - bytes []byte - want *Map - wantErr bool - }{ - { - name: "valid", - bytes: []byte{0, 0, 2, 107, 49, 2, 118, 49}, - want: FromContext(ctx), - wantErr: false, - }, - { - name: "non-ascii key", - bytes: []byte{0, 0, 2, 107, 49, 2, 118, 49, 0, 2, 107, 25, 2, 118, 49}, - want: nil, - wantErr: true, - }, - { - name: "non-ascii value", - bytes: []byte{0, 0, 2, 107, 49, 2, 118, 49, 0, 2, 107, 50, 2, 118, 25}, - want: nil, - wantErr: true, - }, - { - name: "long value", - bytes: []byte{0, 0, 2, 107, 49, 2, 118, 49, 0, 2, 107, 50, 172, 2, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97}, - want: nil, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := Decode(tt.bytes) - if (err != nil) != tt.wantErr { - t.Errorf("Decode() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("Decode() = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/vendor/go.opencensus.io/tag/map_test.go b/vendor/go.opencensus.io/tag/map_test.go deleted file mode 100644 index 855b747a..00000000 --- a/vendor/go.opencensus.io/tag/map_test.go +++ /dev/null @@ -1,222 +0,0 @@ -// Copyright 2017, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -package tag - -import ( - "context" - "fmt" - "reflect" - "strings" - "testing" -) - -func TestContext(t *testing.T) { - k1, _ := NewKey("k1") - k2, _ := NewKey("k2") - - ctx := context.Background() - ctx, _ = New(ctx, - Insert(k1, "v1"), - Insert(k2, "v2"), - ) - got := FromContext(ctx) - want := newMap() - want.insert(k1, "v1") - want.insert(k2, "v2") - - if !reflect.DeepEqual(got, want) { - t.Errorf("Map = %#v; want %#v", got, want) - } -} - -func TestDo(t *testing.T) { - k1, _ := NewKey("k1") - k2, _ := NewKey("k2") - ctx := context.Background() - ctx, _ = New(ctx, - Insert(k1, "v1"), - Insert(k2, "v2"), - ) - got := FromContext(ctx) - want := newMap() - want.insert(k1, "v1") - want.insert(k2, "v2") - Do(ctx, func(ctx context.Context) { - got = FromContext(ctx) - }) - if !reflect.DeepEqual(got, want) { - t.Errorf("Map = %#v; want %#v", got, want) - } -} - -func TestNewMap(t *testing.T) { - k1, _ := NewKey("k1") - k2, _ := NewKey("k2") - k3, _ := NewKey("k3") - k4, _ := NewKey("k4") - k5, _ := NewKey("k5") - - initial := makeTestTagMap(5) - - tests := []struct { - name string - initial *Map - mods []Mutator - want *Map - }{ - { - name: "from empty; insert", - initial: nil, - mods: []Mutator{ - Insert(k5, "v5"), - }, - want: makeTestTagMap(2, 4, 5), - }, - { - name: "from empty; insert existing", - initial: nil, - mods: []Mutator{ - Insert(k1, "v1"), - }, - want: makeTestTagMap(1, 2, 4), - }, - { - name: "from empty; update", - initial: nil, - mods: []Mutator{ - Update(k1, "v1"), - }, - want: makeTestTagMap(2, 4), - }, - { - name: "from empty; update unexisting", - initial: nil, - mods: []Mutator{ - Update(k5, "v5"), - }, - want: makeTestTagMap(2, 4), - }, - { - name: "from existing; upsert", - initial: initial, - mods: []Mutator{ - Upsert(k5, "v5"), - }, - want: makeTestTagMap(2, 4, 5), - }, - { - name: "from existing; delete", - initial: initial, - mods: []Mutator{ - Delete(k2), - }, - want: makeTestTagMap(4, 5), - }, - { - name: "from empty; invalid", - initial: nil, - mods: []Mutator{ - Insert(k5, "v\x19"), - Upsert(k5, "v\x19"), - Update(k5, "v\x19"), - }, - want: nil, - }, - { - name: "from empty; no partial", - initial: nil, - mods: []Mutator{ - Insert(k5, "v1"), - Update(k5, "v\x19"), - }, - want: nil, - }, - } - - for _, tt := range tests { - mods := []Mutator{ - Insert(k1, "v1"), - Insert(k2, "v2"), - Update(k3, "v3"), - Upsert(k4, "v4"), - Insert(k2, "v2"), - Delete(k1), - } - mods = append(mods, tt.mods...) - ctx := NewContext(context.Background(), tt.initial) - ctx, err := New(ctx, mods...) - if tt.want != nil && err != nil { - t.Errorf("%v: New = %v", tt.name, err) - } - - if got, want := FromContext(ctx), tt.want; !reflect.DeepEqual(got, want) { - t.Errorf("%v: got %v; want %v", tt.name, got, want) - } - } -} - -func TestNewValidation(t *testing.T) { - tests := []struct { - err string - seed *Map - }{ - // Key name validation in seed - {err: "invalid key", seed: &Map{m: map[Key]string{{name: ""}: "foo"}}}, - {err: "", seed: &Map{m: map[Key]string{{name: "key"}: "foo"}}}, - {err: "", seed: &Map{m: map[Key]string{{name: strings.Repeat("a", 255)}: "census"}}}, - {err: "invalid key", seed: &Map{m: map[Key]string{{name: strings.Repeat("a", 256)}: "census"}}}, - {err: "invalid key", seed: &Map{m: map[Key]string{{name: "Приве́т"}: "census"}}}, - - // Value validation - {err: "", seed: &Map{m: map[Key]string{{name: "key"}: ""}}}, - {err: "", seed: &Map{m: map[Key]string{{name: "key"}: strings.Repeat("a", 255)}}}, - {err: "invalid value", seed: &Map{m: map[Key]string{{name: "key"}: "Приве́т"}}}, - {err: "invalid value", seed: &Map{m: map[Key]string{{name: "key"}: strings.Repeat("a", 256)}}}, - } - - for i, tt := range tests { - ctx := NewContext(context.Background(), tt.seed) - ctx, err := New(ctx) - - if tt.err != "" { - if err == nil { - t.Errorf("#%d: got nil error; want %q", i, tt.err) - continue - } else if s, substr := err.Error(), tt.err; !strings.Contains(s, substr) { - t.Errorf("#%d:\ngot %q\nwant %q", i, s, substr) - } - continue - } - if err != nil { - t.Errorf("#%d: got %q want nil", i, err) - continue - } - m := FromContext(ctx) - if m == nil { - t.Errorf("#%d: got nil map", i) - continue - } - } -} - -func makeTestTagMap(ids ...int) *Map { - m := newMap() - for _, v := range ids { - k, _ := NewKey(fmt.Sprintf("k%d", v)) - m.m[k] = fmt.Sprintf("v%d", v) - } - return m -} diff --git a/vendor/go.opencensus.io/tag/validate_test.go b/vendor/go.opencensus.io/tag/validate_test.go deleted file mode 100644 index 371a775c..00000000 --- a/vendor/go.opencensus.io/tag/validate_test.go +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2017, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package tag - -import ( - "strings" - "testing" -) - -func TestCheckKeyName(t *testing.T) { - tests := []struct { - name string - key string - wantOK bool - }{ - { - name: "valid", - key: "k1", - wantOK: true, - }, - { - name: "invalid i", - key: "k\x19", - wantOK: false, - }, - { - name: "invalid ii", - key: "k\x7f", - wantOK: false, - }, - { - name: "empty", - key: "", - wantOK: false, - }, - { - name: "whitespace", - key: " k ", - wantOK: true, - }, - { - name: "long", - key: strings.Repeat("a", 256), - wantOK: false, - }, - } - for _, tt := range tests { - ok := checkKeyName(tt.key) - if ok != tt.wantOK { - t.Errorf("%v: got %v; want %v", tt.name, ok, tt.wantOK) - } - } -} - -func TestCheckValue(t *testing.T) { - tests := []struct { - name string - value string - wantOK bool - }{ - { - name: "valid", - value: "v1", - wantOK: true, - }, - { - name: "invalid i", - value: "k\x19", - wantOK: false, - }, - { - name: "invalid ii", - value: "k\x7f", - wantOK: false, - }, - { - name: "empty", - value: "", - wantOK: true, - }, - { - name: "whitespace", - value: " v ", - wantOK: true, - }, - { - name: "long", - value: strings.Repeat("a", 256), - wantOK: false, - }, - } - for _, tt := range tests { - ok := checkValue(tt.value) - if ok != tt.wantOK { - t.Errorf("%v: got %v; want %v", tt.name, ok, tt.wantOK) - } - } -} diff --git a/vendor/go.opencensus.io/trace/benchmark_test.go b/vendor/go.opencensus.io/trace/benchmark_test.go deleted file mode 100644 index 7e86d64d..00000000 --- a/vendor/go.opencensus.io/trace/benchmark_test.go +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2018, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package trace - -import ( - "context" - "testing" -) - -func BenchmarkStartEndSpan(b *testing.B) { - traceBenchmark(b, func(b *testing.B) { - ctx := context.Background() - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, span := StartSpan(ctx, "/foo") - span.End() - } - }) -} - -func BenchmarkSpanWithAnnotations_3(b *testing.B) { - traceBenchmark(b, func(b *testing.B) { - ctx := context.Background() - b.ResetTimer() - - for i := 0; i < b.N; i++ { - _, span := StartSpan(ctx, "/foo") - span.AddAttributes( - BoolAttribute("key1", false), - StringAttribute("key2", "hello"), - Int64Attribute("key3", 123), - ) - span.End() - } - }) -} - -func BenchmarkSpanWithAnnotations_6(b *testing.B) { - traceBenchmark(b, func(b *testing.B) { - ctx := context.Background() - b.ResetTimer() - - for i := 0; i < b.N; i++ { - _, span := StartSpan(ctx, "/foo") - span.AddAttributes( - BoolAttribute("key1", false), - BoolAttribute("key2", true), - StringAttribute("key3", "hello"), - StringAttribute("key4", "hello"), - Int64Attribute("key5", 123), - Int64Attribute("key6", 456), - ) - span.End() - } - }) -} - -func BenchmarkTraceID_DotString(b *testing.B) { - traceBenchmark(b, func(b *testing.B) { - t := TraceID{0x0D, 0x0E, 0x0A, 0x0D, 0x0B, 0x0E, 0x0E, 0x0F, 0x0F, 0x0E, 0x0E, 0x0B, 0x0D, 0x0A, 0x0E, 0x0D} - want := "0d0e0a0d0b0e0e0f0f0e0e0b0d0a0e0d" - for i := 0; i < b.N; i++ { - if got := t.String(); got != want { - b.Fatalf("got = %q want = %q", got, want) - } - } - }) -} - -func BenchmarkSpanID_DotString(b *testing.B) { - traceBenchmark(b, func(b *testing.B) { - s := SpanID{0x0D, 0x0E, 0x0A, 0x0D, 0x0B, 0x0E, 0x0E, 0x0F} - want := "0d0e0a0d0b0e0e0f" - for i := 0; i < b.N; i++ { - if got := s.String(); got != want { - b.Fatalf("got = %q want = %q", got, want) - } - } - }) -} - -func traceBenchmark(b *testing.B, fn func(*testing.B)) { - b.Run("AlwaysSample", func(b *testing.B) { - b.ReportAllocs() - ApplyConfig(Config{DefaultSampler: AlwaysSample()}) - fn(b) - }) - b.Run("NeverSample", func(b *testing.B) { - b.ReportAllocs() - ApplyConfig(Config{DefaultSampler: NeverSample()}) - fn(b) - }) -} diff --git a/vendor/go.opencensus.io/trace/config_test.go b/vendor/go.opencensus.io/trace/config_test.go deleted file mode 100644 index 8495d813..00000000 --- a/vendor/go.opencensus.io/trace/config_test.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2018, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package trace - -import ( - "reflect" - "testing" -) - -func TestApplyZeroConfig(t *testing.T) { - cfg := config.Load().(*Config) - ApplyConfig(Config{}) - currentCfg := config.Load().(*Config) - - if got, want := reflect.ValueOf(currentCfg.DefaultSampler).Pointer(), reflect.ValueOf(cfg.DefaultSampler).Pointer(); got != want { - t.Fatalf("config.DefaultSampler = %#v; want %#v", got, want) - } - if got, want := currentCfg.IDGenerator, cfg.IDGenerator; got != want { - t.Fatalf("config.IDGenerator = %#v; want %#v", got, want) - } -} diff --git a/vendor/go.opencensus.io/trace/examples_test.go b/vendor/go.opencensus.io/trace/examples_test.go deleted file mode 100644 index 41925d6c..00000000 --- a/vendor/go.opencensus.io/trace/examples_test.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2017, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package trace_test - -import ( - "fmt" - - "go.opencensus.io/trace" - "golang.org/x/net/context" -) - -// This example shows how to use StartSpan and (*Span).End to capture -// a function execution in a Span. It assumes that the function -// has a context.Context argument. -func ExampleStartSpan() { - printEvens := func(ctx context.Context) { - ctx, span := trace.StartSpan(ctx, "my/package.Function") - defer span.End() - - for i := 0; i < 10; i++ { - if i%2 == 0 { - fmt.Printf("Even!\n") - } - } - } - - ctx := context.Background() - printEvens(ctx) -} diff --git a/vendor/go.opencensus.io/trace/exemplar_test.go b/vendor/go.opencensus.io/trace/exemplar_test.go deleted file mode 100644 index de27631f..00000000 --- a/vendor/go.opencensus.io/trace/exemplar_test.go +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2018, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package trace_test - -import ( - "context" - "testing" - - "go.opencensus.io/stats" - "go.opencensus.io/stats/view" - "go.opencensus.io/trace" -) - -func TestTraceExemplar(t *testing.T) { - m := stats.Float64("measure."+t.Name(), "", stats.UnitDimensionless) - v := &view.View{ - Measure: m, - Aggregation: view.Distribution(0, 1, 2, 3), - } - view.Register(v) - ctx := context.Background() - ctx, span := trace.StartSpan(ctx, t.Name(), trace.WithSampler(trace.AlwaysSample())) - stats.Record(ctx, m.M(1.5)) - span.End() - - rows, err := view.RetrieveData(v.Name) - if err != nil { - t.Fatal(err) - } - if len(rows) == 0 { - t.Fatal("len(rows) = 0; want > 0") - } - dd := rows[0].Data.(*view.DistributionData) - if got := len(dd.ExemplarsPerBucket); got < 3 { - t.Fatalf("len(dd.ExemplarsPerBucket) = %d; want >= 2", got) - } - exemplar := dd.ExemplarsPerBucket[2] - if exemplar == nil { - t.Fatal("Expected exemplar") - } - if got, want := exemplar.Value, 1.5; got != want { - t.Fatalf("exemplar.Value = %v; got %v", got, want) - } - if _, ok := exemplar.Attachments["trace_id"]; !ok { - t.Fatalf("exemplar.Attachments = %v; want trace_id key", exemplar.Attachments) - } - if _, ok := exemplar.Attachments["span_id"]; !ok { - t.Fatalf("exemplar.Attachments = %v; want span_id key", exemplar.Attachments) - } -} - -func TestTraceExemplar_notSampled(t *testing.T) { - m := stats.Float64("measure."+t.Name(), "", stats.UnitDimensionless) - v := &view.View{ - Measure: m, - Aggregation: view.Distribution(0, 1, 2, 3), - } - view.Register(v) - ctx := context.Background() - ctx, span := trace.StartSpan(ctx, t.Name(), trace.WithSampler(trace.NeverSample())) - stats.Record(ctx, m.M(1.5)) - span.End() - - rows, err := view.RetrieveData(v.Name) - if err != nil { - t.Fatal(err) - } - if len(rows) == 0 { - t.Fatal("len(rows) = 0; want > 0") - } - dd := rows[0].Data.(*view.DistributionData) - if got := len(dd.ExemplarsPerBucket); got < 3 { - t.Fatalf("len(buckets) = %d; want >= 2", got) - } - exemplar := dd.ExemplarsPerBucket[2] - if exemplar == nil { - t.Fatal("Expected exemplar") - } - if got, want := exemplar.Value, 1.5; got != want { - t.Fatalf("exemplar.Value = %v; got %v", got, want) - } - if _, ok := exemplar.Attachments["trace_id"]; ok { - t.Fatalf("exemplar.Attachments = %v; want no trace_id", exemplar.Attachments) - } - if _, ok := exemplar.Attachments["span_id"]; ok { - t.Fatalf("exemplar.Attachments = %v; want span_id key", exemplar.Attachments) - } -} diff --git a/vendor/go.opencensus.io/trace/propagation/propagation_test.go b/vendor/go.opencensus.io/trace/propagation/propagation_test.go deleted file mode 100644 index d7e14aaa..00000000 --- a/vendor/go.opencensus.io/trace/propagation/propagation_test.go +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2017, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package propagation - -import ( - "bytes" - "fmt" - "testing" - - . "go.opencensus.io/trace" -) - -func TestBinary(t *testing.T) { - tid := TraceID{0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f} - sid := SpanID{0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68} - b := []byte{ - 0, 0, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 1, 97, 98, 99, 100, - 101, 102, 103, 104, 2, 1, - } - if b2 := Binary(SpanContext{ - TraceID: tid, - SpanID: sid, - TraceOptions: 1, - }); !bytes.Equal(b2, b) { - t.Errorf("Binary: got serialization %02x want %02x", b2, b) - } - - sc, ok := FromBinary(b) - if !ok { - t.Errorf("FromBinary: got ok==%t, want true", ok) - } - if got := sc.TraceID; got != tid { - t.Errorf("FromBinary: got trace ID %s want %s", got, tid) - } - if got := sc.SpanID; got != sid { - t.Errorf("FromBinary: got span ID %s want %s", got, sid) - } - - b[0] = 1 - sc, ok = FromBinary(b) - if ok { - t.Errorf("FromBinary: decoding bytes containing an unsupported version: got ok==%t want false", ok) - } - - b = []byte{0, 1, 97, 98, 99, 100, 101, 102, 103, 104, 2, 1} - sc, ok = FromBinary(b) - if ok { - t.Errorf("FromBinary: decoding bytes without a TraceID: got ok==%t want false", ok) - } - - if b := Binary(SpanContext{}); b != nil { - t.Errorf("Binary(SpanContext{}): got serialization %02x want nil", b) - } -} - -func TestFromBinary(t *testing.T) { - validData := []byte{0, 0, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 1, 97, 98, 99, 100, 101, 102, 103, 104, 2, 1} - tests := []struct { - name string - data []byte - wantTraceID TraceID - wantSpanID SpanID - wantOpts TraceOptions - wantOk bool - }{ - { - name: "nil data", - data: nil, - wantOk: false, - }, - { - name: "short data", - data: []byte{0, 0, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77}, - wantOk: false, - }, - { - name: "wrong field number", - data: []byte{0, 1, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77}, - wantOk: false, - }, - { - name: "valid data", - data: validData, - wantTraceID: TraceID{64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79}, - wantSpanID: SpanID{97, 98, 99, 100, 101, 102, 103, 104}, - wantOpts: 1, - wantOk: true, - }, - } - for _, tt := range tests { - sc, gotOk := FromBinary(tt.data) - gotTraceID, gotSpanID, gotOpts := sc.TraceID, sc.SpanID, sc.TraceOptions - if gotTraceID != tt.wantTraceID { - t.Errorf("%s: Decode() gotTraceID = %v, want %v", tt.name, gotTraceID, tt.wantTraceID) - } - if gotSpanID != tt.wantSpanID { - t.Errorf("%s: Decode() gotSpanID = %v, want %v", tt.name, gotSpanID, tt.wantSpanID) - } - if gotOpts != tt.wantOpts { - t.Errorf("%s: Decode() gotOpts = %v, want %v", tt.name, gotOpts, tt.wantOpts) - } - if gotOk != tt.wantOk { - t.Errorf("%s: Decode() gotOk = %v, want %v", tt.name, gotOk, tt.wantOk) - } - } -} - -func BenchmarkBinary(b *testing.B) { - tid := TraceID{0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f} - sid := SpanID{0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68} - sc := SpanContext{ - TraceID: tid, - SpanID: sid, - } - var x byte - for i := 0; i < b.N; i++ { - bin := Binary(sc) - x += bin[0] - } - if x == 1 { - fmt.Println(x) // try to prevent optimizing-out - } -} - -func BenchmarkFromBinary(b *testing.B) { - bin := []byte{ - 0, 0, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 1, 97, 98, 99, 100, - 101, 102, 103, 104, 2, 1, - } - var x byte - for i := 0; i < b.N; i++ { - sc, _ := FromBinary(bin) - x += sc.TraceID[0] - } - if x == 1 { - fmt.Println(x) // try to prevent optimizing-out - } -} diff --git a/vendor/go.opencensus.io/trace/trace_test.go b/vendor/go.opencensus.io/trace/trace_test.go deleted file mode 100644 index 0c25cc7f..00000000 --- a/vendor/go.opencensus.io/trace/trace_test.go +++ /dev/null @@ -1,714 +0,0 @@ -// Copyright 2017, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package trace - -import ( - "context" - "fmt" - "reflect" - "sync/atomic" - "testing" - "time" - - "go.opencensus.io/trace/tracestate" -) - -var ( - tid = TraceID{1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 4, 8, 16, 32, 64, 128} - sid = SpanID{1, 2, 4, 8, 16, 32, 64, 128} - testTracestate, _ = tracestate.New(nil, tracestate.Entry{Key: "foo", Value: "bar"}) -) - -func init() { - // no random sampling, but sample children of sampled spans. - ApplyConfig(Config{DefaultSampler: ProbabilitySampler(0)}) -} - -func TestStrings(t *testing.T) { - if got, want := tid.String(), "01020304050607080102040810204080"; got != want { - t.Errorf("TraceID.String: got %q want %q", got, want) - } - if got, want := sid.String(), "0102040810204080"; got != want { - t.Errorf("SpanID.String: got %q want %q", got, want) - } -} - -func TestFromContext(t *testing.T) { - want := &Span{} - ctx := NewContext(context.Background(), want) - got := FromContext(ctx) - if got != want { - t.Errorf("got Span pointer %p want %p", got, want) - } -} - -type foo int - -func (f foo) String() string { - return "foo" -} - -// checkChild tests that c has fields set appropriately, given that it is a child span of p. -func checkChild(p SpanContext, c *Span) error { - if c == nil { - return fmt.Errorf("got nil child span, want non-nil") - } - if got, want := c.spanContext.TraceID, p.TraceID; got != want { - return fmt.Errorf("got child trace ID %s, want %s", got, want) - } - if childID, parentID := c.spanContext.SpanID, p.SpanID; childID == parentID { - return fmt.Errorf("got child span ID %s, parent span ID %s; want unequal IDs", childID, parentID) - } - if got, want := c.spanContext.TraceOptions, p.TraceOptions; got != want { - return fmt.Errorf("got child trace options %d, want %d", got, want) - } - if got, want := c.spanContext.Tracestate, p.Tracestate; got != want { - return fmt.Errorf("got child tracestate %v, want %v", got, want) - } - return nil -} - -func TestStartSpan(t *testing.T) { - ctx, _ := StartSpan(context.Background(), "StartSpan") - if FromContext(ctx).data != nil { - t.Error("StartSpan: new span is recording events") - } -} - -func TestSampling(t *testing.T) { - for _, test := range []struct { - remoteParent bool - localParent bool - parentTraceOptions TraceOptions - sampler Sampler - wantTraceOptions TraceOptions - }{ - {true, false, 0, nil, 0}, - {true, false, 1, nil, 1}, - {true, false, 0, NeverSample(), 0}, - {true, false, 1, NeverSample(), 0}, - {true, false, 0, AlwaysSample(), 1}, - {true, false, 1, AlwaysSample(), 1}, - {false, true, 0, NeverSample(), 0}, - {false, true, 1, NeverSample(), 0}, - {false, true, 0, AlwaysSample(), 1}, - {false, true, 1, AlwaysSample(), 1}, - {false, false, 0, nil, 0}, - {false, false, 0, NeverSample(), 0}, - {false, false, 0, AlwaysSample(), 1}, - } { - var ctx context.Context - if test.remoteParent { - sc := SpanContext{ - TraceID: tid, - SpanID: sid, - TraceOptions: test.parentTraceOptions, - } - ctx, _ = StartSpanWithRemoteParent(context.Background(), "foo", sc, WithSampler(test.sampler)) - } else if test.localParent { - sampler := NeverSample() - if test.parentTraceOptions == 1 { - sampler = AlwaysSample() - } - ctx2, _ := StartSpan(context.Background(), "foo", WithSampler(sampler)) - ctx, _ = StartSpan(ctx2, "foo", WithSampler(test.sampler)) - } else { - ctx, _ = StartSpan(context.Background(), "foo", WithSampler(test.sampler)) - } - sc := FromContext(ctx).SpanContext() - if (sc == SpanContext{}) { - t.Errorf("case %#v: starting new span: no span in context", test) - continue - } - if sc.SpanID == (SpanID{}) { - t.Errorf("case %#v: starting new span: got zero SpanID, want nonzero", test) - } - if sc.TraceOptions != test.wantTraceOptions { - t.Errorf("case %#v: starting new span: got TraceOptions %x, want %x", test, sc.TraceOptions, test.wantTraceOptions) - } - } - - // Test that for children of local spans, the default sampler has no effect. - for _, test := range []struct { - parentTraceOptions TraceOptions - wantTraceOptions TraceOptions - }{ - {0, 0}, - {0, 0}, - {1, 1}, - {1, 1}, - } { - for _, defaultSampler := range []Sampler{ - NeverSample(), - AlwaysSample(), - ProbabilitySampler(0), - } { - ApplyConfig(Config{DefaultSampler: defaultSampler}) - sampler := NeverSample() - if test.parentTraceOptions == 1 { - sampler = AlwaysSample() - } - ctx2, _ := StartSpan(context.Background(), "foo", WithSampler(sampler)) - ctx, _ := StartSpan(ctx2, "foo") - sc := FromContext(ctx).SpanContext() - if (sc == SpanContext{}) { - t.Errorf("case %#v: starting new child of local span: no span in context", test) - continue - } - if sc.SpanID == (SpanID{}) { - t.Errorf("case %#v: starting new child of local span: got zero SpanID, want nonzero", test) - } - if sc.TraceOptions != test.wantTraceOptions { - t.Errorf("case %#v: starting new child of local span: got TraceOptions %x, want %x", test, sc.TraceOptions, test.wantTraceOptions) - } - } - } - ApplyConfig(Config{DefaultSampler: ProbabilitySampler(0)}) // reset the default sampler. -} - -func TestProbabilitySampler(t *testing.T) { - exported := 0 - for i := 0; i < 1000; i++ { - _, span := StartSpan(context.Background(), "foo", WithSampler(ProbabilitySampler(0.3))) - if span.SpanContext().IsSampled() { - exported++ - } - } - if exported < 200 || exported > 400 { - t.Errorf("got %f%% exported spans, want approximately 30%%", float64(exported)*0.1) - } -} - -func TestStartSpanWithRemoteParent(t *testing.T) { - sc := SpanContext{ - TraceID: tid, - SpanID: sid, - TraceOptions: 0x0, - } - ctx, _ := StartSpanWithRemoteParent(context.Background(), "startSpanWithRemoteParent", sc) - if err := checkChild(sc, FromContext(ctx)); err != nil { - t.Error(err) - } - - ctx, _ = StartSpanWithRemoteParent(context.Background(), "startSpanWithRemoteParent", sc) - if err := checkChild(sc, FromContext(ctx)); err != nil { - t.Error(err) - } - - sc = SpanContext{ - TraceID: tid, - SpanID: sid, - TraceOptions: 0x1, - Tracestate: testTracestate, - } - ctx, _ = StartSpanWithRemoteParent(context.Background(), "startSpanWithRemoteParent", sc) - if err := checkChild(sc, FromContext(ctx)); err != nil { - t.Error(err) - } - - ctx, _ = StartSpanWithRemoteParent(context.Background(), "startSpanWithRemoteParent", sc) - if err := checkChild(sc, FromContext(ctx)); err != nil { - t.Error(err) - } - - ctx2, _ := StartSpan(ctx, "StartSpan") - parent := FromContext(ctx).SpanContext() - if err := checkChild(parent, FromContext(ctx2)); err != nil { - t.Error(err) - } -} - -// startSpan returns a context with a new Span that is recording events and will be exported. -func startSpan(o StartOptions) *Span { - _, span := StartSpanWithRemoteParent(context.Background(), "span0", - SpanContext{ - TraceID: tid, - SpanID: sid, - TraceOptions: 1, - }, - WithSampler(o.Sampler), - WithSpanKind(o.SpanKind), - ) - return span -} - -type testExporter struct { - spans []*SpanData -} - -func (t *testExporter) ExportSpan(s *SpanData) { - t.spans = append(t.spans, s) -} - -// endSpan ends the Span in the context and returns the exported SpanData. -// -// It also does some tests on the Span, and tests and clears some fields in the SpanData. -func endSpan(span *Span) (*SpanData, error) { - - if !span.IsRecordingEvents() { - return nil, fmt.Errorf("IsRecordingEvents: got false, want true") - } - if !span.SpanContext().IsSampled() { - return nil, fmt.Errorf("IsSampled: got false, want true") - } - var te testExporter - RegisterExporter(&te) - span.End() - UnregisterExporter(&te) - if len(te.spans) != 1 { - return nil, fmt.Errorf("got exported spans %#v, want one span", te.spans) - } - got := te.spans[0] - if got.SpanContext.SpanID == (SpanID{}) { - return nil, fmt.Errorf("exporting span: expected nonzero SpanID") - } - got.SpanContext.SpanID = SpanID{} - if !checkTime(&got.StartTime) { - return nil, fmt.Errorf("exporting span: expected nonzero StartTime") - } - if !checkTime(&got.EndTime) { - return nil, fmt.Errorf("exporting span: expected nonzero EndTime") - } - return got, nil -} - -// checkTime checks that a nonzero time was set in x, then clears it. -func checkTime(x *time.Time) bool { - if x.IsZero() { - return false - } - *x = time.Time{} - return true -} - -func TestSpanKind(t *testing.T) { - tests := []struct { - name string - startOptions StartOptions - want *SpanData - }{ - { - name: "zero StartOptions", - startOptions: StartOptions{}, - want: &SpanData{ - SpanContext: SpanContext{ - TraceID: tid, - SpanID: SpanID{}, - TraceOptions: 0x1, - }, - ParentSpanID: sid, - Name: "span0", - SpanKind: SpanKindUnspecified, - HasRemoteParent: true, - }, - }, - { - name: "client span", - startOptions: StartOptions{ - SpanKind: SpanKindClient, - }, - want: &SpanData{ - SpanContext: SpanContext{ - TraceID: tid, - SpanID: SpanID{}, - TraceOptions: 0x1, - }, - ParentSpanID: sid, - Name: "span0", - SpanKind: SpanKindClient, - HasRemoteParent: true, - }, - }, - { - name: "server span", - startOptions: StartOptions{ - SpanKind: SpanKindServer, - }, - want: &SpanData{ - SpanContext: SpanContext{ - TraceID: tid, - SpanID: SpanID{}, - TraceOptions: 0x1, - }, - ParentSpanID: sid, - Name: "span0", - SpanKind: SpanKindServer, - HasRemoteParent: true, - }, - }, - } - - for _, tt := range tests { - span := startSpan(tt.startOptions) - got, err := endSpan(span) - if err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("exporting span: got %#v want %#v", got, tt.want) - } - } -} - -func TestSetSpanAttributes(t *testing.T) { - span := startSpan(StartOptions{}) - span.AddAttributes(StringAttribute("key1", "value1")) - got, err := endSpan(span) - if err != nil { - t.Fatal(err) - } - - want := &SpanData{ - SpanContext: SpanContext{ - TraceID: tid, - SpanID: SpanID{}, - TraceOptions: 0x1, - }, - ParentSpanID: sid, - Name: "span0", - Attributes: map[string]interface{}{"key1": "value1"}, - HasRemoteParent: true, - } - if !reflect.DeepEqual(got, want) { - t.Errorf("exporting span: got %#v want %#v", got, want) - } -} - -func TestAnnotations(t *testing.T) { - span := startSpan(StartOptions{}) - span.Annotatef([]Attribute{StringAttribute("key1", "value1")}, "%f", 1.5) - span.Annotate([]Attribute{StringAttribute("key2", "value2")}, "Annotate") - got, err := endSpan(span) - if err != nil { - t.Fatal(err) - } - - for i := range got.Annotations { - if !checkTime(&got.Annotations[i].Time) { - t.Error("exporting span: expected nonzero Annotation Time") - } - } - - want := &SpanData{ - SpanContext: SpanContext{ - TraceID: tid, - SpanID: SpanID{}, - TraceOptions: 0x1, - }, - ParentSpanID: sid, - Name: "span0", - Annotations: []Annotation{ - {Message: "1.500000", Attributes: map[string]interface{}{"key1": "value1"}}, - {Message: "Annotate", Attributes: map[string]interface{}{"key2": "value2"}}, - }, - HasRemoteParent: true, - } - if !reflect.DeepEqual(got, want) { - t.Errorf("exporting span: got %#v want %#v", got, want) - } -} - -func TestMessageEvents(t *testing.T) { - span := startSpan(StartOptions{}) - span.AddMessageReceiveEvent(3, 400, 300) - span.AddMessageSendEvent(1, 200, 100) - got, err := endSpan(span) - if err != nil { - t.Fatal(err) - } - - for i := range got.MessageEvents { - if !checkTime(&got.MessageEvents[i].Time) { - t.Error("exporting span: expected nonzero MessageEvent Time") - } - } - - want := &SpanData{ - SpanContext: SpanContext{ - TraceID: tid, - SpanID: SpanID{}, - TraceOptions: 0x1, - }, - ParentSpanID: sid, - Name: "span0", - MessageEvents: []MessageEvent{ - {EventType: 2, MessageID: 0x3, UncompressedByteSize: 0x190, CompressedByteSize: 0x12c}, - {EventType: 1, MessageID: 0x1, UncompressedByteSize: 0xc8, CompressedByteSize: 0x64}, - }, - HasRemoteParent: true, - } - if !reflect.DeepEqual(got, want) { - t.Errorf("exporting span: got %#v want %#v", got, want) - } -} - -func TestSetSpanName(t *testing.T) { - want := "SpanName-1" - span := startSpan(StartOptions{}) - span.SetName(want) - got, err := endSpan(span) - if err != nil { - t.Fatal(err) - } - - if got.Name != want { - t.Errorf("span.Name=%q; want %q", got.Name, want) - } -} - -func TestSetSpanNameUnsampledSpan(t *testing.T) { - var nilSpanData *SpanData - span := startSpan(StartOptions{Sampler: NeverSample()}) - span.SetName("NoopName") - - if want, got := nilSpanData, span.data; want != got { - t.Errorf("span.data=%+v; want %+v", got, want) - } -} - -func TestSetSpanNameAfterSpanEnd(t *testing.T) { - want := "SpanName-2" - span := startSpan(StartOptions{}) - span.SetName(want) - got, err := endSpan(span) - if err != nil { - t.Fatal(err) - } - - // updating name after span.End - span.SetName("NoopName") - - // exported span should not be updated by previous call to SetName - if got.Name != want { - t.Errorf("span.Name=%q; want %q", got.Name, want) - } - - // span should not be exported again - var te testExporter - RegisterExporter(&te) - span.End() - UnregisterExporter(&te) - if len(te.spans) != 0 { - t.Errorf("got exported spans %#v, wanted no spans", te.spans) - } -} - -func TestSetSpanStatus(t *testing.T) { - span := startSpan(StartOptions{}) - span.SetStatus(Status{Code: int32(1), Message: "request failed"}) - got, err := endSpan(span) - if err != nil { - t.Fatal(err) - } - - want := &SpanData{ - SpanContext: SpanContext{ - TraceID: tid, - SpanID: SpanID{}, - TraceOptions: 0x1, - }, - ParentSpanID: sid, - Name: "span0", - Status: Status{Code: 1, Message: "request failed"}, - HasRemoteParent: true, - } - if !reflect.DeepEqual(got, want) { - t.Errorf("exporting span: got %#v want %#v", got, want) - } -} - -func TestAddLink(t *testing.T) { - span := startSpan(StartOptions{}) - span.AddLink(Link{ - TraceID: tid, - SpanID: sid, - Type: LinkTypeParent, - Attributes: map[string]interface{}{"key5": "value5"}, - }) - got, err := endSpan(span) - if err != nil { - t.Fatal(err) - } - - want := &SpanData{ - SpanContext: SpanContext{ - TraceID: tid, - SpanID: SpanID{}, - TraceOptions: 0x1, - }, - ParentSpanID: sid, - Name: "span0", - Links: []Link{{ - TraceID: tid, - SpanID: sid, - Type: 2, - Attributes: map[string]interface{}{"key5": "value5"}, - }}, - HasRemoteParent: true, - } - if !reflect.DeepEqual(got, want) { - t.Errorf("exporting span: got %#v want %#v", got, want) - } -} - -func TestUnregisterExporter(t *testing.T) { - var te testExporter - RegisterExporter(&te) - UnregisterExporter(&te) - - ctx := startSpan(StartOptions{}) - endSpan(ctx) - if len(te.spans) != 0 { - t.Error("unregistered Exporter was called") - } -} - -func TestBucket(t *testing.T) { - // make a bucket of size 5 and add 10 spans - b := makeBucket(5) - for i := 1; i <= 10; i++ { - b.nextTime = time.Time{} // reset the time so that the next span is accepted. - // add a span, with i stored in the TraceID so we can test for it later. - b.add(&SpanData{SpanContext: SpanContext{TraceID: TraceID{byte(i)}}, EndTime: time.Now()}) - if i <= 5 { - if b.size() != i { - t.Fatalf("got bucket size %d, want %d %#v\n", b.size(), i, b) - } - for j := 0; j < i; j++ { - if b.span(j).TraceID[0] != byte(j+1) { - t.Errorf("got span index %d, want %d\n", b.span(j).TraceID[0], j+1) - } - } - } else { - if b.size() != 5 { - t.Fatalf("got bucket size %d, want 5\n", b.size()) - } - for j := 0; j < 5; j++ { - want := i - 4 + j - if b.span(j).TraceID[0] != byte(want) { - t.Errorf("got span index %d, want %d\n", b.span(j).TraceID[0], want) - } - } - } - } - // expand the bucket - b.resize(20) - if b.size() != 5 { - t.Fatalf("after resizing upwards: got bucket size %d, want 5\n", b.size()) - } - for i := 0; i < 5; i++ { - want := 6 + i - if b.span(i).TraceID[0] != byte(want) { - t.Errorf("after resizing upwards: got span index %d, want %d\n", b.span(i).TraceID[0], want) - } - } - // shrink the bucket - b.resize(3) - if b.size() != 3 { - t.Fatalf("after resizing downwards: got bucket size %d, want 3\n", b.size()) - } - for i := 0; i < 3; i++ { - want := 8 + i - if b.span(i).TraceID[0] != byte(want) { - t.Errorf("after resizing downwards: got span index %d, want %d\n", b.span(i).TraceID[0], want) - } - } -} - -type exporter map[string]*SpanData - -func (e exporter) ExportSpan(s *SpanData) { - e[s.Name] = s -} - -func Test_Issue328_EndSpanTwice(t *testing.T) { - spans := make(exporter) - RegisterExporter(&spans) - defer UnregisterExporter(&spans) - ctx := context.Background() - ctx, span := StartSpan(ctx, "span-1", WithSampler(AlwaysSample())) - span.End() - span.End() - UnregisterExporter(&spans) - if len(spans) != 1 { - t.Fatalf("expected only a single span, got %#v", spans) - } -} - -func TestStartSpanAfterEnd(t *testing.T) { - spans := make(exporter) - RegisterExporter(&spans) - defer UnregisterExporter(&spans) - ctx, span0 := StartSpan(context.Background(), "parent", WithSampler(AlwaysSample())) - ctx1, span1 := StartSpan(ctx, "span-1", WithSampler(AlwaysSample())) - span1.End() - // Start a new span with the context containing span-1 - // even though span-1 is ended, we still add this as a new child of span-1 - _, span2 := StartSpan(ctx1, "span-2", WithSampler(AlwaysSample())) - span2.End() - span0.End() - UnregisterExporter(&spans) - if got, want := len(spans), 3; got != want { - t.Fatalf("len(%#v) = %d; want %d", spans, got, want) - } - if got, want := spans["span-1"].TraceID, spans["parent"].TraceID; got != want { - t.Errorf("span-1.TraceID=%q; want %q", got, want) - } - if got, want := spans["span-2"].TraceID, spans["parent"].TraceID; got != want { - t.Errorf("span-2.TraceID=%q; want %q", got, want) - } - if got, want := spans["span-1"].ParentSpanID, spans["parent"].SpanID; got != want { - t.Errorf("span-1.ParentSpanID=%q; want %q (parent.SpanID)", got, want) - } - if got, want := spans["span-2"].ParentSpanID, spans["span-1"].SpanID; got != want { - t.Errorf("span-2.ParentSpanID=%q; want %q (span1.SpanID)", got, want) - } -} - -func TestNilSpanEnd(t *testing.T) { - var span *Span - span.End() -} - -func TestExecutionTracerTaskEnd(t *testing.T) { - var n uint64 - executionTracerTaskEnd := func() { - atomic.AddUint64(&n, 1) - } - - var spans []*Span - _, span := StartSpan(context.Background(), "foo", WithSampler(NeverSample())) - span.executionTracerTaskEnd = executionTracerTaskEnd - spans = append(spans, span) // never sample - - _, span = StartSpanWithRemoteParent(context.Background(), "foo", SpanContext{ - TraceID: TraceID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - SpanID: SpanID{0, 1, 2, 3, 4, 5, 6, 7}, - TraceOptions: 0, - }) - span.executionTracerTaskEnd = executionTracerTaskEnd - spans = append(spans, span) // parent not sampled - - _, span = StartSpan(context.Background(), "foo", WithSampler(AlwaysSample())) - span.executionTracerTaskEnd = executionTracerTaskEnd - spans = append(spans, span) // always sample - - for _, span := range spans { - span.End() - } - if got, want := n, uint64(len(spans)); got != want { - t.Fatalf("Execution tracer task ended for %v spans; want %v", got, want) - } -} diff --git a/vendor/go.opencensus.io/trace/tracestate/tracestate_test.go b/vendor/go.opencensus.io/trace/tracestate/tracestate_test.go deleted file mode 100644 index db76d9c3..00000000 --- a/vendor/go.opencensus.io/trace/tracestate/tracestate_test.go +++ /dev/null @@ -1,313 +0,0 @@ -// Copyright 2018, OpenCensus Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package tracestate - -import ( - "fmt" - "testing" -) - -func checkFront(t *testing.T, tracestate *Tracestate, wantKey, testname string) { - gotKey := tracestate.entries[0].Key - if gotKey != wantKey { - t.Errorf("test:%s: first entry in the list: got %q want %q", testname, gotKey, wantKey) - } -} - -func checkBack(t *testing.T, tracestate *Tracestate, wantKey, testname string) { - gotKey := tracestate.entries[len(tracestate.entries)-1].Key - if gotKey != wantKey { - t.Errorf("test:%s: last entry in the list: got %q want %q", testname, gotKey, wantKey) - } -} - -func checkSize(t *testing.T, tracestate *Tracestate, wantSize int, testname string) { - if gotSize := len(tracestate.entries); gotSize != wantSize { - t.Errorf("test:%s: size of the list: got %q want %q", testname, gotSize, wantSize) - } -} - -func (ts *Tracestate) get(key string) (string, bool) { - if ts == nil { - return "", false - } - for _, entry := range ts.entries { - if entry.Key == key { - return entry.Value, true - } - } - return "", false -} - -func checkKeyValue(t *testing.T, tracestate *Tracestate, key, wantValue, testname string) { - wantOk := true - if wantValue == "" { - wantOk = false - } - gotValue, gotOk := tracestate.get(key) - if wantOk != gotOk || gotValue != wantValue { - t.Errorf("test:%s: get value for key=%s failed: got %q want %q", testname, key, gotValue, wantValue) - } -} - -func checkError(t *testing.T, tracestate *Tracestate, err error, testname, msg string) { - if err != nil { - t.Errorf("test:%s: %s: tracestate=%v, error= %v", testname, msg, tracestate, err) - } -} - -func wantError(t *testing.T, tracestate *Tracestate, err error, testname, msg string) { - if err == nil { - t.Errorf("test:%s: %s: tracestate=%v, error=%v", testname, msg, tracestate, err) - } -} - -func TestCreateWithNullParent(t *testing.T) { - key1, value1 := "hello", "world" - testname := "TestCreateWithNullParent" - - entry := Entry{key1, value1} - tracestate, err := New(nil, entry) - checkError(t, tracestate, err, testname, "create failed from null parent") - checkKeyValue(t, tracestate, key1, value1, testname) -} - -func TestCreateFromParentWithSingleKey(t *testing.T) { - key1, value1, key2, value2 := "hello", "world", "foo", "bar" - testname := "TestCreateFromParentWithSingleKey" - - entry1 := Entry{key1, value1} - entry2 := Entry{key2, value2} - parent, _ := New(nil, entry1) - tracestate, err := New(parent, entry2) - - checkError(t, tracestate, err, testname, "create failed from parent with single key") - checkKeyValue(t, tracestate, key2, value2, testname) - checkFront(t, tracestate, key2, testname) - checkBack(t, tracestate, key1, testname) -} - -func TestCreateFromParentWithDoubleKeys(t *testing.T) { - key1, value1, key2, value2, key3, value3 := "hello", "world", "foo", "bar", "bar", "baz" - testname := "TestCreateFromParentWithDoubleKeys" - - entry1 := Entry{key1, value1} - entry2 := Entry{key2, value2} - entry3 := Entry{key3, value3} - parent, _ := New(nil, entry2, entry1) - tracestate, err := New(parent, entry3) - - checkError(t, tracestate, err, testname, "create failed from parent with double keys") - checkKeyValue(t, tracestate, key3, value3, testname) - checkFront(t, tracestate, key3, testname) - checkBack(t, tracestate, key1, testname) -} - -func TestCreateFromParentWithExistingKey(t *testing.T) { - key1, value1, key2, value2, key3, value3 := "hello", "world", "foo", "bar", "hello", "baz" - testname := "TestCreateFromParentWithExistingKey" - - entry1 := Entry{key1, value1} - entry2 := Entry{key2, value2} - entry3 := Entry{key3, value3} - parent, _ := New(nil, entry2, entry1) - tracestate, err := New(parent, entry3) - - checkError(t, tracestate, err, testname, "create failed with an existing key") - checkKeyValue(t, tracestate, key3, value3, testname) - checkFront(t, tracestate, key3, testname) - checkBack(t, tracestate, key2, testname) - checkSize(t, tracestate, 2, testname) -} - -func TestImplicitImmutableTracestate(t *testing.T) { - key1, value1, key2, value2, key3, value3 := "hello", "world", "hello", "bar", "foo", "baz" - testname := "TestImplicitImmutableTracestate" - - entry1 := Entry{key1, value1} - entry2 := Entry{key2, value2} - parent, _ := New(nil, entry1) - tracestate, err := New(parent, entry2) - - checkError(t, tracestate, err, testname, "create failed") - checkKeyValue(t, tracestate, key2, value2, testname) - checkKeyValue(t, parent, key2, value1, testname) - - // Get and update entries. - entries := tracestate.Entries() - entry := Entry{key3, value3} - entries = append(entries, entry) - - // Check Tracestate does not have key3. - checkKeyValue(t, tracestate, key3, "", testname) -} - -func TestKeyWithValidChar(t *testing.T) { - testname := "TestKeyWithValidChar" - - arrayRune := []rune("") - for c := 'a'; c <= 'z'; c++ { - arrayRune = append(arrayRune, c) - } - for c := '0'; c <= '9'; c++ { - arrayRune = append(arrayRune, c) - } - arrayRune = append(arrayRune, '_') - arrayRune = append(arrayRune, '-') - arrayRune = append(arrayRune, '*') - arrayRune = append(arrayRune, '/') - key := string(arrayRune) - entry := Entry{key, "world"} - tracestate, err := New(nil, entry) - - checkError(t, tracestate, err, testname, "create failed when the key contains all valid characters") -} - -func TestKeyWithInvalidChar(t *testing.T) { - testname := "TestKeyWithInvalidChar" - - keys := []string{"1ab", "1ab2", "Abc", " abc", "a=b"} - - for _, key := range keys { - entry := Entry{key, "world"} - tracestate, err := New(nil, entry) - wantError(t, tracestate, err, testname, fmt.Sprintf( - "create did not err with invalid key=%q", key)) - } -} - -func TestNilKey(t *testing.T) { - testname := "TestNilKey" - - entry := Entry{"", "world"} - tracestate, err := New(nil, entry) - wantError(t, tracestate, err, testname, "create did not err when the key is nil (\"\")") -} - -func TestValueWithInvalidChar(t *testing.T) { - testname := "TestValueWithInvalidChar" - - keys := []string{"A=B", "A,B", "AB "} - - for _, value := range keys { - entry := Entry{"hello", value} - tracestate, err := New(nil, entry) - wantError(t, tracestate, err, testname, - fmt.Sprintf("create did not err when the value is invalid (%q)", value)) - } -} - -func TestNilValue(t *testing.T) { - testname := "TestNilValue" - - tracestate, err := New(nil, Entry{"hello", ""}) - wantError(t, tracestate, err, testname, "create did not err when the value is nil (\"\")") -} - -func TestInvalidKeyLen(t *testing.T) { - testname := "TestInvalidKeyLen" - - arrayRune := []rune("") - for i := 0; i <= keyMaxSize+1; i++ { - arrayRune = append(arrayRune, 'a') - } - key := string(arrayRune) - tracestate, err := New(nil, Entry{key, "world"}) - - wantError(t, tracestate, err, testname, - fmt.Sprintf("create did not err when the length (%d) of the key is larger than max (%d)", - len(key), keyMaxSize)) -} - -func TestInvalidValueLen(t *testing.T) { - testname := "TestInvalidValueLen" - - arrayRune := []rune("") - for i := 0; i <= valueMaxSize+1; i++ { - arrayRune = append(arrayRune, 'a') - } - value := string(arrayRune) - tracestate, err := New(nil, Entry{"hello", value}) - - wantError(t, tracestate, err, testname, - fmt.Sprintf("create did not err when the length (%d) of the value is larger than max (%d)", - len(value), valueMaxSize)) -} - -func TestCreateFromArrayWithOverLimitKVPairs(t *testing.T) { - testname := "TestCreateFromArrayWithOverLimitKVPairs" - - entries := []Entry{} - for i := 0; i <= maxKeyValuePairs; i++ { - key := fmt.Sprintf("a%db", i) - entry := Entry{key, "world"} - entries = append(entries, entry) - } - tracestate, err := New(nil, entries...) - wantError(t, tracestate, err, testname, - fmt.Sprintf("create did not err when the number (%d) of key-value pairs is larger than max (%d)", - len(entries), maxKeyValuePairs)) -} - -func TestCreateFromEmptyArray(t *testing.T) { - testname := "TestCreateFromEmptyArray" - - tracestate, err := New(nil, nil...) - checkError(t, tracestate, err, testname, - "failed to create nil tracestate") -} - -func TestCreateFromParentWithOverLimitKVPairs(t *testing.T) { - testname := "TestCreateFromParentWithOverLimitKVPairs" - - entries := []Entry{} - for i := 0; i < maxKeyValuePairs; i++ { - key := fmt.Sprintf("a%db", i) - entry := Entry{key, "world"} - entries = append(entries, entry) - } - parent, err := New(nil, entries...) - - checkError(t, parent, err, testname, fmt.Sprintf("create failed to add %d key-value pair", maxKeyValuePairs)) - - // Add one more to go over the limit - key := fmt.Sprintf("a%d", maxKeyValuePairs) - tracestate, err := New(parent, Entry{key, "world"}) - wantError(t, tracestate, err, testname, - fmt.Sprintf("create did not err when attempted to exceed the key-value pair limit of %d", maxKeyValuePairs)) -} - -func TestCreateFromArrayWithDuplicateKeys(t *testing.T) { - key1, value1, key2, value2, key3, value3 := "hello", "world", "foo", "bar", "hello", "baz" - testname := "TestCreateFromArrayWithDuplicateKeys" - - entry1 := Entry{key1, value1} - entry2 := Entry{key2, value2} - entry3 := Entry{key3, value3} - tracestate, err := New(nil, entry1, entry2, entry3) - - wantError(t, tracestate, err, testname, - "create did not err when entries contained duplicate keys") -} - -func TestEntriesWithNil(t *testing.T) { - ts, err := New(nil) - if err != nil { - t.Fatal(err) - } - if got, want := len(ts.Entries()), 0; got != want { - t.Errorf("zero value should have no entries, got %v; want %v", got, want) - } -} diff --git a/vendor/golang.org/x/crypto/CONTRIBUTING.md b/vendor/golang.org/x/crypto/CONTRIBUTING.md deleted file mode 100644 index d0485e88..00000000 --- a/vendor/golang.org/x/crypto/CONTRIBUTING.md +++ /dev/null @@ -1,26 +0,0 @@ -# Contributing to Go - -Go is an open source project. - -It is the work of hundreds of contributors. We appreciate your help! - -## Filing issues - -When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions: - -1. What version of Go are you using (`go version`)? -2. What operating system and processor architecture are you using? -3. What did you do? -4. What did you expect to see? -5. What did you see instead? - -General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker. -The gophers there will answer or ask you to file an issue if you've tripped over a bug. - -## Contributing code - -Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html) -before sending patches. - -Unless otherwise noted, the Go source files are distributed under -the BSD-style license found in the LICENSE file. diff --git a/vendor/golang.org/x/crypto/README.md b/vendor/golang.org/x/crypto/README.md deleted file mode 100644 index c9d6fecd..00000000 --- a/vendor/golang.org/x/crypto/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# Go Cryptography - -This repository holds supplementary Go cryptography libraries. - -## Download/Install - -The easiest way to install is to run `go get -u golang.org/x/crypto/...`. You -can also manually git clone the repository to `$GOPATH/src/golang.org/x/crypto`. - -## Report Issues / Send Patches - -This repository uses Gerrit for code changes. To learn how to submit changes to -this repository, see https://golang.org/doc/contribute.html. - -The main issue tracker for the crypto repository is located at -https://github.com/golang/go/issues. Prefix your issue with "x/crypto:" in the -subject line, so it is easy to find. - -Note that contributions to the cryptography package receive additional scrutiny -due to their sensitive nature. Patches may take longer than normal to receive -feedback. diff --git a/vendor/golang.org/x/crypto/codereview.cfg b/vendor/golang.org/x/crypto/codereview.cfg deleted file mode 100644 index 3f8b14b6..00000000 --- a/vendor/golang.org/x/crypto/codereview.cfg +++ /dev/null @@ -1 +0,0 @@ -issuerepo: golang/go diff --git a/vendor/golang.org/x/crypto/curve25519/curve25519_test.go b/vendor/golang.org/x/crypto/curve25519/curve25519_test.go deleted file mode 100644 index 051a8301..00000000 --- a/vendor/golang.org/x/crypto/curve25519/curve25519_test.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package curve25519 - -import ( - "fmt" - "testing" -) - -const expectedHex = "89161fde887b2b53de549af483940106ecc114d6982daa98256de23bdf77661a" - -func TestBaseScalarMult(t *testing.T) { - var a, b [32]byte - in := &a - out := &b - a[0] = 1 - - for i := 0; i < 200; i++ { - ScalarBaseMult(out, in) - in, out = out, in - } - - result := fmt.Sprintf("%x", in[:]) - if result != expectedHex { - t.Errorf("incorrect result: got %s, want %s", result, expectedHex) - } -} - -func BenchmarkScalarBaseMult(b *testing.B) { - var in, out [32]byte - in[0] = 1 - - b.SetBytes(32) - for i := 0; i < b.N; i++ { - ScalarBaseMult(&out, &in) - } -} diff --git a/vendor/golang.org/x/crypto/ed25519/ed25519_test.go b/vendor/golang.org/x/crypto/ed25519/ed25519_test.go deleted file mode 100644 index 80946036..00000000 --- a/vendor/golang.org/x/crypto/ed25519/ed25519_test.go +++ /dev/null @@ -1,220 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ed25519 - -import ( - "bufio" - "bytes" - "compress/gzip" - "crypto" - "crypto/rand" - "encoding/hex" - "os" - "strings" - "testing" - - "golang.org/x/crypto/ed25519/internal/edwards25519" -) - -type zeroReader struct{} - -func (zeroReader) Read(buf []byte) (int, error) { - for i := range buf { - buf[i] = 0 - } - return len(buf), nil -} - -func TestUnmarshalMarshal(t *testing.T) { - pub, _, _ := GenerateKey(rand.Reader) - - var A edwards25519.ExtendedGroupElement - var pubBytes [32]byte - copy(pubBytes[:], pub) - if !A.FromBytes(&pubBytes) { - t.Fatalf("ExtendedGroupElement.FromBytes failed") - } - - var pub2 [32]byte - A.ToBytes(&pub2) - - if pubBytes != pub2 { - t.Errorf("FromBytes(%v)->ToBytes does not round-trip, got %x\n", pubBytes, pub2) - } -} - -func TestSignVerify(t *testing.T) { - var zero zeroReader - public, private, _ := GenerateKey(zero) - - message := []byte("test message") - sig := Sign(private, message) - if !Verify(public, message, sig) { - t.Errorf("valid signature rejected") - } - - wrongMessage := []byte("wrong message") - if Verify(public, wrongMessage, sig) { - t.Errorf("signature of different message accepted") - } -} - -func TestCryptoSigner(t *testing.T) { - var zero zeroReader - public, private, _ := GenerateKey(zero) - - signer := crypto.Signer(private) - - publicInterface := signer.Public() - public2, ok := publicInterface.(PublicKey) - if !ok { - t.Fatalf("expected PublicKey from Public() but got %T", publicInterface) - } - - if !bytes.Equal(public, public2) { - t.Errorf("public keys do not match: original:%x vs Public():%x", public, public2) - } - - message := []byte("message") - var noHash crypto.Hash - signature, err := signer.Sign(zero, message, noHash) - if err != nil { - t.Fatalf("error from Sign(): %s", err) - } - - if !Verify(public, message, signature) { - t.Errorf("Verify failed on signature from Sign()") - } -} - -func TestGolden(t *testing.T) { - // sign.input.gz is a selection of test cases from - // https://ed25519.cr.yp.to/python/sign.input - testDataZ, err := os.Open("testdata/sign.input.gz") - if err != nil { - t.Fatal(err) - } - defer testDataZ.Close() - testData, err := gzip.NewReader(testDataZ) - if err != nil { - t.Fatal(err) - } - defer testData.Close() - - scanner := bufio.NewScanner(testData) - lineNo := 0 - - for scanner.Scan() { - lineNo++ - - line := scanner.Text() - parts := strings.Split(line, ":") - if len(parts) != 5 { - t.Fatalf("bad number of parts on line %d", lineNo) - } - - privBytes, _ := hex.DecodeString(parts[0]) - pubKey, _ := hex.DecodeString(parts[1]) - msg, _ := hex.DecodeString(parts[2]) - sig, _ := hex.DecodeString(parts[3]) - // The signatures in the test vectors also include the message - // at the end, but we just want R and S. - sig = sig[:SignatureSize] - - if l := len(pubKey); l != PublicKeySize { - t.Fatalf("bad public key length on line %d: got %d bytes", lineNo, l) - } - - var priv [PrivateKeySize]byte - copy(priv[:], privBytes) - copy(priv[32:], pubKey) - - sig2 := Sign(priv[:], msg) - if !bytes.Equal(sig, sig2[:]) { - t.Errorf("different signature result on line %d: %x vs %x", lineNo, sig, sig2) - } - - if !Verify(pubKey, msg, sig2) { - t.Errorf("signature failed to verify on line %d", lineNo) - } - - priv2 := NewKeyFromSeed(priv[:32]) - if !bytes.Equal(priv[:], priv2) { - t.Errorf("recreating key pair gave different private key on line %d: %x vs %x", lineNo, priv[:], priv2) - } - - if pubKey2 := priv2.Public().(PublicKey); !bytes.Equal(pubKey, pubKey2) { - t.Errorf("recreating key pair gave different public key on line %d: %x vs %x", lineNo, pubKey, pubKey2) - } - - if seed := priv2.Seed(); !bytes.Equal(priv[:32], seed) { - t.Errorf("recreating key pair gave different seed on line %d: %x vs %x", lineNo, priv[:32], seed) - } - } - - if err := scanner.Err(); err != nil { - t.Fatalf("error reading test data: %s", err) - } -} - -func TestMalleability(t *testing.T) { - // https://tools.ietf.org/html/rfc8032#section-5.1.7 adds an additional test - // that s be in [0, order). This prevents someone from adding a multiple of - // order to s and obtaining a second valid signature for the same message. - msg := []byte{0x54, 0x65, 0x73, 0x74} - sig := []byte{ - 0x7c, 0x38, 0xe0, 0x26, 0xf2, 0x9e, 0x14, 0xaa, 0xbd, 0x05, 0x9a, - 0x0f, 0x2d, 0xb8, 0xb0, 0xcd, 0x78, 0x30, 0x40, 0x60, 0x9a, 0x8b, - 0xe6, 0x84, 0xdb, 0x12, 0xf8, 0x2a, 0x27, 0x77, 0x4a, 0xb0, 0x67, - 0x65, 0x4b, 0xce, 0x38, 0x32, 0xc2, 0xd7, 0x6f, 0x8f, 0x6f, 0x5d, - 0xaf, 0xc0, 0x8d, 0x93, 0x39, 0xd4, 0xee, 0xf6, 0x76, 0x57, 0x33, - 0x36, 0xa5, 0xc5, 0x1e, 0xb6, 0xf9, 0x46, 0xb3, 0x1d, - } - publicKey := []byte{ - 0x7d, 0x4d, 0x0e, 0x7f, 0x61, 0x53, 0xa6, 0x9b, 0x62, 0x42, 0xb5, - 0x22, 0xab, 0xbe, 0xe6, 0x85, 0xfd, 0xa4, 0x42, 0x0f, 0x88, 0x34, - 0xb1, 0x08, 0xc3, 0xbd, 0xae, 0x36, 0x9e, 0xf5, 0x49, 0xfa, - } - - if Verify(publicKey, msg, sig) { - t.Fatal("non-canonical signature accepted") - } -} - -func BenchmarkKeyGeneration(b *testing.B) { - var zero zeroReader - for i := 0; i < b.N; i++ { - if _, _, err := GenerateKey(zero); err != nil { - b.Fatal(err) - } - } -} - -func BenchmarkSigning(b *testing.B) { - var zero zeroReader - _, priv, err := GenerateKey(zero) - if err != nil { - b.Fatal(err) - } - message := []byte("Hello, world!") - b.ResetTimer() - for i := 0; i < b.N; i++ { - Sign(priv, message) - } -} - -func BenchmarkVerification(b *testing.B) { - var zero zeroReader - pub, priv, err := GenerateKey(zero) - if err != nil { - b.Fatal(err) - } - message := []byte("Hello, world!") - signature := Sign(priv, message) - b.ResetTimer() - for i := 0; i < b.N; i++ { - Verify(pub, message, signature) - } -} diff --git a/vendor/golang.org/x/crypto/internal/chacha20/chacha_test.go b/vendor/golang.org/x/crypto/internal/chacha20/chacha_test.go deleted file mode 100644 index 9a7a0994..00000000 --- a/vendor/golang.org/x/crypto/internal/chacha20/chacha_test.go +++ /dev/null @@ -1,225 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package chacha20 - -import ( - "encoding/binary" - "encoding/hex" - "fmt" - "math/rand" - "testing" -) - -func TestCore(t *testing.T) { - // This is just a smoke test that checks the example from - // https://tools.ietf.org/html/rfc7539#section-2.3.2. The - // chacha20poly1305 package contains much more extensive tests of this - // code. - var key [32]byte - for i := range key { - key[i] = byte(i) - } - - var input [16]byte - input[0] = 1 - input[7] = 9 - input[11] = 0x4a - - var out [64]byte - XORKeyStream(out[:], out[:], &input, &key) - const expected = "10f1e7e4d13b5915500fdd1fa32071c4c7d1f4c733c068030422aa9ac3d46c4ed2826446079faa0914c2d705d98b02a2b5129cd1de164eb9cbd083e8a2503c4e" - if result := hex.EncodeToString(out[:]); result != expected { - t.Errorf("wanted %x but got %x", expected, result) - } -} - -// Run the test cases with the input and output in different buffers. -func TestNoOverlap(t *testing.T) { - for _, c := range testVectors { - s := New(c.key, c.nonce) - input, err := hex.DecodeString(c.input) - if err != nil { - t.Fatalf("cannot decode input %#v: %v", c.input, err) - } - output := make([]byte, c.length) - s.XORKeyStream(output, input) - got := hex.EncodeToString(output) - if got != c.output { - t.Errorf("length=%v: got %#v, want %#v", c.length, got, c.output) - } - } -} - -// Run the test cases with the input and output overlapping entirely. -func TestOverlap(t *testing.T) { - for _, c := range testVectors { - s := New(c.key, c.nonce) - data, err := hex.DecodeString(c.input) - if err != nil { - t.Fatalf("cannot decode input %#v: %v", c.input, err) - } - s.XORKeyStream(data, data) - got := hex.EncodeToString(data) - if got != c.output { - t.Errorf("length=%v: got %#v, want %#v", c.length, got, c.output) - } - } -} - -// Run the test cases with various source and destination offsets. -func TestUnaligned(t *testing.T) { - const max = 8 // max offset (+1) to test - for _, c := range testVectors { - input := make([]byte, c.length+max) - output := make([]byte, c.length+max) - for i := 0; i < max; i++ { // input offsets - for j := 0; j < max; j++ { // output offsets - s := New(c.key, c.nonce) - - input := input[i : i+c.length] - output := output[j : j+c.length] - - data, err := hex.DecodeString(c.input) - if err != nil { - t.Fatalf("cannot decode input %#v: %v", c.input, err) - } - copy(input, data) - s.XORKeyStream(output, input) - got := hex.EncodeToString(output) - if got != c.output { - t.Errorf("length=%v: got %#v, want %#v", c.length, got, c.output) - } - } - } - } -} - -// Run the test cases by calling XORKeyStream multiple times. -func TestStep(t *testing.T) { - // wide range of step sizes to try and hit edge cases - steps := [...]int{1, 3, 4, 7, 8, 17, 24, 30, 64, 256} - rnd := rand.New(rand.NewSource(123)) - for _, c := range testVectors { - s := New(c.key, c.nonce) - input, err := hex.DecodeString(c.input) - if err != nil { - t.Fatalf("cannot decode input %#v: %v", c.input, err) - } - output := make([]byte, c.length) - - // step through the buffers - i, step := 0, steps[rnd.Intn(len(steps))] - for i+step < c.length { - s.XORKeyStream(output[i:i+step], input[i:i+step]) - if i+step < c.length && output[i+step] != 0 { - t.Errorf("length=%v, i=%v, step=%v: output overwritten", c.length, i, step) - } - i += step - step = steps[rnd.Intn(len(steps))] - } - // finish the encryption - s.XORKeyStream(output[i:], input[i:]) - - got := hex.EncodeToString(output) - if got != c.output { - t.Errorf("length=%v: got %#v, want %#v", c.length, got, c.output) - } - } -} - -// Test that Advance() discards bytes until a block boundary is hit. -func TestAdvance(t *testing.T) { - for _, c := range testVectors { - for i := 0; i < 63; i++ { - s := New(c.key, c.nonce) - z := New(c.key, c.nonce) - input, err := hex.DecodeString(c.input) - if err != nil { - t.Fatalf("cannot decode input %#v: %v", c.input, err) - } - zeros, discard := make([]byte, 64), make([]byte, 64) - so, zo := make([]byte, c.length), make([]byte, c.length) - for j := 0; j < c.length; j += 64 { - lim := j + i - if lim > c.length { - lim = c.length - } - s.XORKeyStream(so[j:lim], input[j:lim]) - // calling s.Advance() multiple times should have no effect - for k := 0; k < i%3+1; k++ { - s.Advance() - } - z.XORKeyStream(zo[j:lim], input[j:lim]) - if lim < c.length { - end := 64 - i - if c.length-lim < end { - end = c.length - lim - } - z.XORKeyStream(discard[:], zeros[:end]) - } - } - - got := hex.EncodeToString(so) - want := hex.EncodeToString(zo) - if got != want { - t.Errorf("length=%v: got %#v, want %#v", c.length, got, want) - } - } - } -} - -func BenchmarkChaCha20(b *testing.B) { - sizes := []int{32, 63, 64, 256, 1024, 1350, 65536} - for _, size := range sizes { - s := size - b.Run(fmt.Sprint(s), func(b *testing.B) { - k := [32]byte{} - c := [16]byte{} - src := make([]byte, s) - dst := make([]byte, s) - b.SetBytes(int64(s)) - b.ResetTimer() - for i := 0; i < b.N; i++ { - XORKeyStream(dst, src, &c, &k) - } - }) - } -} - -func TestHChaCha20(t *testing.T) { - // See draft-paragon-paseto-rfc-00 §7.2.1. - key := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f} - nonce := []byte{0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4a, - 0x00, 0x00, 0x00, 0x00, 0x31, 0x41, 0x59, 0x27} - expected := []byte{0x82, 0x41, 0x3b, 0x42, 0x27, 0xb2, 0x7b, 0xfe, - 0xd3, 0x0e, 0x42, 0x50, 0x8a, 0x87, 0x7d, 0x73, - 0xa0, 0xf9, 0xe4, 0xd5, 0x8a, 0x74, 0xa8, 0x53, - 0xc1, 0x2e, 0xc4, 0x13, 0x26, 0xd3, 0xec, 0xdc, - } - result := HChaCha20(&[8]uint32{ - binary.LittleEndian.Uint32(key[0:4]), - binary.LittleEndian.Uint32(key[4:8]), - binary.LittleEndian.Uint32(key[8:12]), - binary.LittleEndian.Uint32(key[12:16]), - binary.LittleEndian.Uint32(key[16:20]), - binary.LittleEndian.Uint32(key[20:24]), - binary.LittleEndian.Uint32(key[24:28]), - binary.LittleEndian.Uint32(key[28:32]), - }, &[4]uint32{ - binary.LittleEndian.Uint32(nonce[0:4]), - binary.LittleEndian.Uint32(nonce[4:8]), - binary.LittleEndian.Uint32(nonce[8:12]), - binary.LittleEndian.Uint32(nonce[12:16]), - }) - for i := 0; i < 8; i++ { - want := binary.LittleEndian.Uint32(expected[i*4 : (i+1)*4]) - if got := result[i]; got != want { - t.Errorf("word %d incorrect: want 0x%x, got 0x%x", i, want, got) - } - } -} diff --git a/vendor/golang.org/x/crypto/internal/chacha20/vectors_test.go b/vendor/golang.org/x/crypto/internal/chacha20/vectors_test.go deleted file mode 100644 index b441fbd1..00000000 --- a/vendor/golang.org/x/crypto/internal/chacha20/vectors_test.go +++ /dev/null @@ -1,578 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package chacha20 - -// Test vectors for ChaCha20 implementations. - -type testCase struct { - length int - nonce [3]uint32 - key [8]uint32 - input string - output string -} - -var testVectors = [...]testCase{ - { - length: 0, - nonce: [3]uint32{0x94d13317, 0x6b6a2b3, 0x3ffe0036}, - key: [8]uint32{0x9da8a3b6, 0x3abf4ae6, 0xa2f19cae, 0x1068c707, 0x72e4801e, 0xce165d92, 0x61e7028f, 0x82ac3d57}, - input: "", - output: "", - }, - { - length: 5, - nonce: [3]uint32{0x469fadd, 0xee3fcc1e, 0x45cf77b0}, - key: [8]uint32{0x3477e02b, 0x45bf809f, 0x27f4a1fa, 0xdb901de8, 0xd8a190dc, 0x1d2c21d4, 0x87bdf2ac, 0xdfbf0000}, - input: "23dbad0780", - output: "415a3e498d", - }, - { - length: 9, - nonce: [3]uint32{0x512a6b49, 0x8df9af6d, 0x5336a2a5}, - key: [8]uint32{0xe9124c25, 0x4fd1a373, 0x7945f7bb, 0xeed5f064, 0x29c4185d, 0x3c9acf13, 0x4c94a367, 0x7c2c2c53}, - input: "f518831fab69c054a6", - output: "cfe40f63f81391484b", - }, - { - length: 12, - nonce: [3]uint32{0xca697a9e, 0x6b2f6717, 0xb7859220}, - key: [8]uint32{0xfc825020, 0x5ca4410b, 0x7d5285d0, 0x160a1c9d, 0x15470b41, 0x3634742a, 0xe64aa7fa, 0xca0be67a}, - input: "805fad1d62951537aeed9859", - output: "47bd303f93c3ce04bce44710", - }, - { - length: 14, - nonce: [3]uint32{0xcded3db3, 0x35770a7f, 0x6aede9b}, - key: [8]uint32{0x44632def, 0xa5e420a7, 0xfc12a8f, 0x63b79a15, 0x337de314, 0xb82fbf16, 0x3104bc57, 0x677c9227}, - input: "f4e8a7577affb841cf48392cf5df", - output: "f445c0fb7e3d5bfdab47090ddee6", - }, - { - length: 15, - nonce: [3]uint32{0x348a50b1, 0x4acc9280, 0x8d6014ce}, - key: [8]uint32{0x34bd31a8, 0x2808f47e, 0x9d8b19f9, 0x4df59683, 0x31584348, 0x34a74a45, 0xde174a2, 0x29d4c7dc}, - input: "1179b71ec4dc34bd812f742b5a0b27", - output: "cc7f80f333c647d6e592e4f7ecc834", - }, - { - length: 20, - nonce: [3]uint32{0xc8754703, 0x9188c521, 0xac8ce8a6}, - key: [8]uint32{0xe93c79ed, 0xce89162b, 0x116a8366, 0xecdc657f, 0x5bc81d98, 0xff5d2f52, 0x171f3ebb, 0x50773f2f}, - input: "7bd94943d55392d0311c413ac755ce0347872ba3", - output: "c43665de15136af232675d9d5dbbeca77f3c542a", - }, - { - length: 21, - nonce: [3]uint32{0x9a8655cb, 0x6e9d6ea5, 0x5dad705e}, - key: [8]uint32{0x3542d5b3, 0x1f7bfd8f, 0x1038abf8, 0x7214e8ec, 0xedd05693, 0x60e663bd, 0xe8e5d506, 0xeea923a2}, - input: "1505f669acc5ad9aaa0e993ba8c24e744d13655e1f", - output: "26cad1ccf4cf4c49b267ab7be10bc2ffa3ba66bc86", - }, - { - length: 25, - nonce: [3]uint32{0x3f202ca4, 0x63fc86, 0x7260a10e}, - key: [8]uint32{0xe28ab1d6, 0xe83b3d47, 0x671271ca, 0xb977bcff, 0xa2f64476, 0x311d79b4, 0x180d91d0, 0xec1a6e0c}, - input: "20070523ddb4ebf0d5f20fd95aacf47fb269ebadda6879638a", - output: "5ce972624cb2b7e7c28f5b865ba08c887911b4f5e361830a4b", - }, - { - length: 31, - nonce: [3]uint32{0xcf8671ea, 0x8d72df2f, 0x8b5a538a}, - key: [8]uint32{0xe46ca2bb, 0xd06ab5ef, 0xb0e2966b, 0x54dd0c2d, 0x8815d89a, 0x426c30a9, 0x15b0f1e, 0x254bae75}, - input: "d10f8050c1186f92e26f351db36490d82ea677498562d8d4f487a0a4058adf", - output: "f30c11bc553b2baf6870760d735680897c9fee168f976b2a33ef395fdbd4fc", - }, - { - length: 34, - nonce: [3]uint32{0xd1be983a, 0xf5aa389, 0xfa26c7e1}, - key: [8]uint32{0x795c6da7, 0x8cb1aadc, 0xa042359a, 0x95ea2e27, 0x128253c4, 0xaabc592f, 0x391e810, 0xf641d971}, - input: "e88dc380b7d45a4a762c34f310199587867516fac4a2634022b96a9f862e17714d17", - output: "aac98ba3821399e55a5eab5862f7f1bfc63637d700125878c2b17151f306c9aec80e", - }, - { - length: 34, - nonce: [3]uint32{0x98f5f4b8, 0x3f181d73, 0x5bf4572e}, - key: [8]uint32{0xa86f8cf7, 0x8db41a2b, 0xe0e03156, 0x3dad8a59, 0xb3e4d1ba, 0x75f6fb38, 0xdb94709d, 0xc3db34f3}, - input: "b0fcf0a731e2902787309697db2384e1cda07b60002c95355a4e261fb601f034b2b3", - output: "b6c8c40ddda029a70a21c25f724cc90c43f6edc407055683572a9f5e9690a1d571bb", - }, - { - length: 40, - nonce: [3]uint32{0x7289ae18, 0x7ebe7e50, 0x7d819176}, - key: [8]uint32{0x336c07a0, 0x4a2ea22b, 0xa8872f46, 0xa47b5e28, 0xbe645e3f, 0x371c6591, 0xd2dc237a, 0x92c59580}, - input: "cf9ec6fa3f0a67488adb5598a48ed916729a1e416d206f9675dfa9fd6585793f274f363bbca348b3", - output: "bb7ed8a199aa329dcd18736ce705804ffae8c3e2ba341ae907f94f4672d57175df25d28e16962fd6", - }, - { - length: 47, - nonce: [3]uint32{0xfd3181de, 0x8b193e26, 0xbebc799}, - key: [8]uint32{0x781a4c2e, 0x27ab55e2, 0x814aaf43, 0xa0bab01, 0x9de62ce0, 0x472b03d2, 0xdfee18e8, 0x8b855b93}, - input: "be9a8211d68642310724eda3dd02f63fcc03a101d9564b0ecee6f4ecececcb0099bb26aabee46b1a2c0416b4ac269e", - output: "3152f317cf3626e26d02cff9392619ea02e22115b6d43d6dd2e1177c6bb3cb71c4a90c3d13b63c43e03605ec98d9a1", - }, - { - length: 51, - nonce: [3]uint32{0x27b02ff6, 0xa510613e, 0x218b22d8}, - key: [8]uint32{0x62fc7732, 0xcef06cf4, 0xa4f45ed5, 0x2f96654f, 0x9f2b956e, 0x42b572f4, 0x5bb59c86, 0x35e4784f}, - input: "495343a257250f8970f791f493b89d10edba89806b88aaaeb3b5aefd078ba7b765746164bce653f5e6c096dd8499fb76d97d77", - output: "62c01f426581551b5b16e8b1a3a23c86bcdd189ab695dbea4bf811a14741e6ebbb0261ef8ae47778a6be7e0ef11697b891412c", - }, - { - length: 52, - nonce: [3]uint32{0x9db97a63, 0xff50248, 0xf2b6df56}, - key: [8]uint32{0x2b657a8f, 0xfe67575d, 0xaa56d261, 0x30179a97, 0xaefcfff1, 0x9b8eb698, 0x1efe3756, 0xb4ea450c}, - input: "e37fbbd3fe37ce5a99d18e5dcb0dafe7adf8b596528708f7d310569ab44c251377f7363a390c653965e0cb8dd217464b3d8f79c1", - output: "b07d4c56fb83a49e8d9fc992e1230bb5086fecbd828cdbc7353f61b1a3cec0baf9c5bf67c9da06b49469a999ba3b37916ec125be", - }, - { - length: 56, - nonce: [3]uint32{0xc1dfec38, 0x7d7503d3, 0x9a3e3c66}, - key: [8]uint32{0x8614d8e7, 0xde9b0413, 0x2a48b4fa, 0xcbbde744, 0xad5ddc5e, 0x9144d83e, 0x74d9d617, 0x230bdb45}, - input: "9efab614388a7d99102bcc901e3623d31fd9dd9d3c3338d086f69c13e7aa8653f9ce76e722e5a6a8cbbbee067a6cb9c59aa9b4b4c518bbed", - output: "829d9fe74b7a4b3aeb04580b41d38a156ffbebba5d49ad55d1b0370f25abcd41221304941ad8e0d5095e15fbd839295bf1e7a509a807c005", - }, - { - length: 63, - nonce: [3]uint32{0xc7e2521c, 0x795499b4, 0xc7946cd7}, - key: [8]uint32{0x53fce774, 0x9a4b53bf, 0x5f614134, 0xa3c39414, 0xa8a07c72, 0x93242311, 0x43aeec99, 0x216deb5a}, - input: "03b5d7ab4bd8c9a4f47ec122cbeb595bd1a0d58de3bb3dcc66c4e288f29622d6863e846fdfb27a90740feb03a4761c6017250bc0f129cc65d19680ab9d6970", - output: "83db55d9eb441a909268311da67d432c732ad6bda0a0dae710d1bce040b91269deb558a68ced4aa5760ca0b9c5efc84e725f297bdbdadbc368bea4e20261c5", - }, - { - length: 66, - nonce: [3]uint32{0x1d41f0a1, 0x7c3b7778, 0x6991eea5}, - key: [8]uint32{0x1f213e39, 0x56261d14, 0x15fc7c2c, 0x21feccc5, 0xa95684c5, 0x26600506, 0xdadcc06b, 0xf2c810b0}, - input: "2f4da518578a2a82c8c855155645838ca431cdf35d9f8562f256746150580ca1c74f79b3e9ae78224573da8b47a4b3cc63fbed8d4e831a6b4d796c124d87c78a66e5", - output: "6fc086ded3d1d5566577ccd9971e713c1126ec52d3894f09ab701116c7b5abda959cbb207f4468eb7b6a6b7e1b6d2bc6047f337499d63522f256ee751b91f84f70b6", - }, - { - length: 72, - nonce: [3]uint32{0x749f022c, 0xa021dab0, 0x648c2252}, - key: [8]uint32{0xa1ace7b0, 0x567a0ea1, 0x52af13b9, 0xcba30c08, 0xe07a6d74, 0x5c3bca39, 0x85b2ac07, 0x3b5afc0}, - input: "55739a1738b4a4028021b21549e2661b050e3d830ad9a56f57bfcaca3e0f72051b9ca92411840061083e5e45124d8425061ab26c632ac7852118411ac80026da946357c630f27225", - output: "8051bf98f8f2617e159ba205a9342ab700973dd045e09321805eed89e419f37f3211c5aa82666b9a097270babc26d3bfe0c990fe245ae982a31f23cfbf6156b5c8cfb77f340e2bf5", - }, - { - length: 74, - nonce: [3]uint32{0x23c16ba8, 0x9fd1cd4e, 0xcb224ecb}, - key: [8]uint32{0xb694404a, 0x86b5f198, 0x10fd1bff, 0x13a84e54, 0xab21e509, 0x7443d764, 0x931b3f1, 0x686e87f2}, - input: "7ffd8d5970fdee613eeae531d1c673fd379d64b0b6bfedd010433b080b561038f7f266fa7e15d7d8e10d23f21b9d7724bb200b0f58b9250483e784f4a6555d09c234e8d1c549ebb76a8e", - output: "c173617e36ea20ce04c490803b2098bd4f1ff4b31fdca1c51c6475ade83892c5f12731652d5774631d55ae2938617a5e9462bb6083328a23a4fba52de50ca9075586f2efc22aae56e3a8", - }, - { - length: 81, - nonce: [3]uint32{0xd65f6f29, 0xf3f76219, 0x9a033c9e}, - key: [8]uint32{0xeba017c4, 0x69e0421a, 0x449e2317, 0x29858a11, 0xd0c8523a, 0xa8b0c9a2, 0xab2ca84, 0xaf011a45}, - input: "7a5766097562361cfaeac5b8a6175e1ceeeda30aec5e354df4302e7700ea48c505da9fdc57874da879480ecfea9c6c8904f330cbac5e27f296b33b667fea483348f031bef761d0b8e318a8132caa7a5943", - output: "5e9fbf427c4f0fcf44db3180ea47d923f52bee933a985543622eff70e2b3f5c673be8e05cd7acbcadd8593da454c60d5f19131e61730a73b9c0f87e3921ee5a591a086446b2a0fadd8a4bc7b49a8e83764", - }, - { - length: 88, - nonce: [3]uint32{0xc70ee56e, 0xe58ec41, 0xafd96f61}, - key: [8]uint32{0x172af2bb, 0x9085d27c, 0x8ca2c44d, 0x8aa148da, 0x290c88b0, 0x88187439, 0x18d54781, 0x633f2cce}, - input: "0777c02a2900052d9b79f38387d2c234108a2ad066cbf7df6ea6acc5a3f86b3d6156abb5b18ad4ecf79e171383a1897e64a95ecdbba6aa3f1c7c12fe31283629ff547cb113a826cb348a7c10507cc645fa2eb97b5f22e44d", - output: "368c90db3464ba488340b1960e9f75d2c3b5b392bdd5622ff70e85e6d00b1e6a996ba3978ce64f8f2b5a9a90576c8f32b908233e15d2f443cccc98af87745c93c8056603407a3fb37ce0c1f8ab6384cc37c69c98bfecf337", - }, - { - length: 92, - nonce: [3]uint32{0x3006da79, 0x2748051d, 0x72c17cdc}, - key: [8]uint32{0x60cdb7e8, 0xcecbe928, 0xe19b7ab9, 0x30d61537, 0xa0fbc199, 0x897738bf, 0xdd7705a9, 0x3e5c1763}, - input: "cf2dccbcfd781c030376f9019d841ca701cb54a1791f50f50bee0c2bf178182603a4712b5916eebd5001595c3f48283f1ba097ce2e7bf94f2b7fa957ce776e14a7a570093be2de386ececbd6525e72c5970c3e7d35974b8f0b831fbc", - output: "7c92b8c75e6eb8675229660cedcb10334965a7737cde7336512d9eff846c670d1fa8f8a427ea4f43e66be609466711fd241ccff7d3f049bda3a2394e5aa2108abc80e859611dbd3c7ba2d044a3ececa4980dd65e823dd110fea7a548", - }, - { - length: 96, - nonce: [3]uint32{0xfc0fb1ee, 0x414cc60a, 0x4144bd67}, - key: [8]uint32{0x103291c6, 0x822b03b6, 0xd29ab548, 0xc88f3efe, 0x6936056a, 0x28aaa61f, 0xa0df7858, 0xdaa23519}, - input: "e08a8949a1bfd6a8c1186b431b6ad59b106ae5552821db69b66dc03fbc4a2b970dcf9c7da4f5082572bc978f8ee27c554c8884b5a450b36d70453348cd6cac9b80c9900cf98a4088803f564bb1281d24507b2f61ba737c8145c71b50eb0f6dfc", - output: "73d043acf9dcd758c7299bd1fd1f4100d61ff77d339e279bfbe6f9233b0d9afa24992a9c1c7a19545d469fdfb369c201322f6fe8c633fcdcffef31032bfb41b9fb55506e301d049fd447d61f974a713debeaed886f486a98efd3d6c3f25fbb30", - }, - { - length: 103, - nonce: [3]uint32{0xc2030c57, 0x1e3b59e1, 0x607ede1a}, - key: [8]uint32{0xd1bac2b5, 0x56a94583, 0x628b479b, 0x3056a51e, 0x69bf8f8f, 0x2df1e03d, 0x4b9d48d2, 0x7df5c379}, - input: "a0c302120111f00c99cff7d839cdf43207a7e2f73d5dd888daa00d84254db0e621a72493480420c9c61ce1cfc54188ff525bb7a0e6c1cd298f598973a1de9fd2d79a21401588775b0adbe261ba4e4f79a894d1bd5835b5924d09ba32ef03cb4bc0bd6eb4ee4274", - output: "bc714bd7d8399beedc238f7ddeb0b99d94ad6bf8bf54548a3e4b90a76aa5673c91db6482591e8ff9126e1412bce56d52a4c2d89f22c29858e24482f177abacef428d0ae1779f0ae0778c44f9f02fe474da93c35c615b5fad29eca697978891f426714441317f2b", - }, - { - length: 109, - nonce: [3]uint32{0xf44dc81f, 0xcf6e03e7, 0xf4966796}, - key: [8]uint32{0xd7b12f4, 0x683f4789, 0xc7828fb4, 0x820fc6a0, 0xc51231eb, 0xe46716d7, 0x4036ef93, 0x26afb96c}, - input: "ebce290c03c7cb65d053918ba2da0256dc700b337b8c124c43d5da4746888ca78387feea1a3a72c5e249d3d93a1907977dd4009699a15be5da2ca89c60e971c8df5d4553b61b710d92d3453dea595a0e45ae1e093f02ea70608b7b32f9c6aadc661a052f9b14c03ea0117a3192", - output: "cbb8c4ec827a1123c1141327c594d4a8b0b4a74b0008115bb9ec4275db3a8e5529a4f145551af29c473764cbaa0794b2d1eb1066f32a07fd39f5f3fe51498c46fba5310ae7c3664571d6a851e673ded3badc25e426f9c6038724779aa6d2d8ec3f54865f7df612e25575635ab5", - }, - { - length: 115, - nonce: [3]uint32{0x8d3e461b, 0x7e05c360, 0x3bbbafdd}, - key: [8]uint32{0xf9b917c9, 0x9af89bf7, 0x7decbbc9, 0xe7e5ea7b, 0x9b4aab55, 0x90eff6be, 0xa19b6d90, 0xb9f69b1a}, - input: "275c97de985aa265332065ccce437770b110737a77dea62137a5d6cb62e9cb8b504d34334a58a71aba153d9b86f21377467b2fafaf54829331bf2ce0009acb37842b7a4b5f152aab650a393153f1ed479abc21f7a6fe205b9852ff2f7f3a0e3bfe76ca9770efada4e29e06db0569a99d08648e", - output: "b225aa01d5c438d572deaea51ac12c0c694e0f9dc0ed2884a98e5e2943d52bb4692d7d8f12486de12d0559087e8c09e4f2d5b74e350838aa2bd36023032ccbcae56be75c6a17c59583d81a1fd60e305af5053ac89f753c9347f3040e48405232dc8428c49dcb3d9b899145f5b3bc955f34dbbe", - }, - { - length: 119, - nonce: [3]uint32{0x871f33f5, 0xe4fee3ba, 0xcb8c1e93}, - key: [8]uint32{0x33124903, 0x7e0287e5, 0xe9d6988f, 0x1962405f, 0x5f21c1b5, 0x2ac695e6, 0x46b200c9, 0x9fda98ba}, - input: "ceda15cfffd53ccebe31b5886facd863f6166e02ec65f46f54148860a5c2702e34fd204d881af6055952690cd1ffa8ba4d0e297cc165d981b371932adb935398c987baff335108c5e77f2e5dd5e1ca9a017bc376cbdbe3c0f45e079c212e8986b438444e79cd37927c1479f45c9e75b0076cc9f8679011", - output: "a3f1c3f885583b999c85cd118e2ababfa5a2de0c8eb28aacc161b1efee89d8de36ddeb584174c0e92011b8d667cb64009049976082072e6262933dbf7b14839805e1face375b7cbb54f9828ba1ed8aa55634ec5d72b6351feff4d77a3a22b34203b02e096f5e5f9ae9ad6a9dd16c57ce6d94dcc8873d18", - }, - { - length: 120, - nonce: [3]uint32{0xef553ce8, 0xdfe120ea, 0x9a047e3a}, - key: [8]uint32{0xbef479c1, 0x59554f8b, 0xbf97f089, 0x52316f1e, 0x141e428, 0xff26dc04, 0xe10c8f57, 0xa7568a59}, - input: "799bb2d634406753416b3a2b67513293a0b3496ef5b2d019758dedaaac2edd72502fc4a375b3f0d4237bc16b0e3d47e7ddc315c6aef3a23fcae2eb3a6083bc7ac4fd1b5bf0025cc1cb266b40234b77db762c747d3a7b27956cf3a4cf72320fb60c0d0713fa60b37a6cb5b21a599e79d0f06a5b7201aeb5d2", - output: "e84dfb3dbaac364085497aeabd197db852d3140c0c07f5f10e5c144c1fe26a50a9877649e88c6fe04283f4b7590a8d0d042ef577693f76f706e31c4979437590fe0ab03d89afb089d1be50ae173ea5458810372838eceac53bf4bac792735d8149e548efb432e236da92bf3168bbcf36f644c23efb478a4e", - }, - { - length: 123, - nonce: [3]uint32{0xd98124a0, 0x78cd80aa, 0x3dc55cfc}, - key: [8]uint32{0x2286e41, 0xf13e38e3, 0xf735476b, 0x33c44bfc, 0xd7978797, 0x4a9c4595, 0x6080413, 0x1299fdd8}, - input: "b2d060bd173955f44ee01b8bfcf0a6fad017c3517e4e8c8da728379f6d54471c955615e2b1effe4ce3d0139df225223c361be1cac416ade10a749c5da324563696dae8272577e44e8588cd5306bff0bfbdb32af3ac7cbc78be24b51baf4d5e47cf8f1d6b0a63ed9359da45c3e7297b2314028848f5816feab885e2", - output: "ffa4aa66dd5d39694ae64696bfa96f771accef68f195456ad815751e25c47ed4f27b436f1b3e3fcaa3e0d04133b53559c100cd633ced3d4321fc56225c85d2443727bce40434455aa4c1f3e6768c0fe58ad88b3a928313d41a7629f1ce874d2c8bcf822ebdaebfd9d95a31bb62daab5385eb8eefe026e8cbf1ff7a", - }, - { - length: 127, - nonce: [3]uint32{0x53106b0f, 0xdf11fd81, 0x69d1b6f3}, - key: [8]uint32{0x736b138, 0x55cde194, 0xf8273c1, 0xf7c268e6, 0x61362bd5, 0xbb3cb455, 0x44d3c9fc, 0x7d56d3fd}, - input: "4f0171d7309493a349530940feece3c6200693f9cff38924114d53f723d090fffa3c80731b5ca989d3e924d1fa14266632cb9ab879e1a36df22dc9f8d1dadea229db72fded0c42187c38b9fa263c20e5fb5b4aa80eb90e8616e36d9b8c613b371c402343823184ecad3532058a46cf9e7ea5a9ecad043ac3028cbcc3f36d32", - output: "88c773ff34b23e691e14018ba1b2bd48a4a6979b377eb0d68336ce6192dcd5177e6b4f1c4bea2df90af56b35fe2a1d6279d253c0194dcbca9bf136f92d69165b216e4c9d1ce6b3fbe40c71e32c3f4088de352732d0e2bad9c16fd0bb9bde3d6c30257ce063432d09f19da79d49aa7641124a6c9e3f09449e911edbae11a053", - }, - { - length: 130, - nonce: [3]uint32{0x5e90ffbd, 0xa898f173, 0x269f9a88}, - key: [8]uint32{0x5244e05f, 0xf9adbe9b, 0x9e9f54ac, 0x23460046, 0x6782cdea, 0xba982c96, 0xc721506b, 0xed10f7e3}, - input: "8f8d9e18d3212bd20b96d75c06d1a63622fd83d13f79d542e45996135368772ea81511302a0d87e246dd346314cfe019bae8a5c97f567f12d82aca98dfea397c6a47dd0c419f1c609d9c52dcfcbe7eee68b2635954206ed592b7081442ce9ce3187d10ccd41cc856fb924b011f817c676c9419f52a2938c7af5f76755a75eb065411", - output: "4e130c5df384b9c3c84aa38a744260735e93783da0337ade99f777e692c5ea276ac4cc65880b4ae9c3b96888760fdddb74bc2e2694bedf1ee6f14619c8015f951ba81b274b466e318d09defe80bdbed57bc213ac4631d2eb14c8e348181d60f6295ceee1e9231ae047830ef4778ff66146621b76974773b5d11c8e17a476450f46ef", - }, - { - length: 130, - nonce: [3]uint32{0x308e39e8, 0x9aa4f14f, 0xf511db96}, - key: [8]uint32{0x833b5219, 0x4b82e588, 0x4b2d652c, 0x7c8f6ed7, 0xfe4be863, 0x9d3a50e5, 0xb888099b, 0x9f8d1968}, - input: "30d2379dd3ceae612182576f9acf6de505ab5a9445fe1a86ae75c5c29429e11c50fd9ec657b29b173a3763b1e171b5a7da1803ba5d64fccb2d32cb7788be194dbca00c3c91774c4c4c8ede48c1027d7cc8b387101a4fe5e44a1d9693b2f627626025072806083aadbced91c9711a0171f52ffb8ed5596cf34130022398c8a1da99c7", - output: "b1e8da34ad0189038ee24673979b405ef73fdbdd6f376f800031d64005a4ebed51a37f2180571223848decbea6dd22b198ab9560d7edc047c5d69183dc69b5fca346911d25cb2a1a9f830dc6382ad0024e8c3eef3aa2d155abcfe43bff01956a5e20a862fbed5c5e8df8eed0601a120caac634b068314e221f175baa11ae29002bb9", - }, - { - length: 135, - nonce: [3]uint32{0xa5feca5a, 0x753ac1b4, 0xc5a46609}, - key: [8]uint32{0xabbf4859, 0x828d9bf6, 0xf7f7aa6d, 0x25208ca2, 0xd7a4c0ad, 0x2fdd3282, 0x2bfcb8c2, 0x8389d84b}, - input: "d9404ccdcc8ef128a1b1ace4f9f1669d274ec82aa914cac34b83ac00b236478fd6167e96ec658850c6c139eb0f6fc0dd7191ba9a39828032008f7f37eb9a8df9d6cdd54240e600efe7fc49a674000c5030d825b2c5c96d0f19b8ecdbf4eeb86d3e569c5e3131abc7d6359dd4255284ccacf150d42e7a899536d51ee6db329654a4581c5ac6e419", - output: "c5534b5fb40b4834300e9577a9d87440c5272263d06e6aee84aa92cdf5d1b033145d336f26e5fe55c09a7e75753af93d0786dfc1cb435e86c67bd3ec8e766d0801b99e68691e2c3c3ffec539cf62e68285ea9027daa2716cd6f97e8eb7b9e266357a25eb2d4839a829508a6b7228f2832b3cd998f77597ae530430e6e4ecb53eb9efe456863a04", - }, - { - length: 135, - nonce: [3]uint32{0x12aa5846, 0x88604f6c, 0xc10d9585}, - key: [8]uint32{0x1491ccd6, 0x602f559d, 0xd4080c06, 0x202fabd, 0xffd3f4f8, 0xbf144c17, 0x88bf3f3c, 0x8083375}, - input: "231765f832927461f338aceb0f4cf51fd8469348c69c549c1dec7333d4aa4968c1ed58b65ab3fe3d0562600a2b076d56fd9ef91f589752e0455dd1d2e614cacfc0d757a11a4a2264bd38f23d3cca108632201b4f6c3b06477467726dde0c2f3aee01d66d788247663f1d0e66b044da9393ede27b9905b44115b067914961bdade85a2eca2844e1", - output: "1dd35f3f774f66d88cb7c2b23820ee078a093d0d85f86c4f103d869f93e2dbdd8a7cb8f101084fe1d7281a71754ec9aac5eb4fca8c365b24ed80e695caace1a8781a5a225938b50b8be96d0499752fdabd4f50d0b6ce396c6e2ca45308d1f2cc5a2a2361a8ca7a334e6ee62d466d74a1b0bf5b352f4ef6d8f8c589b733748bd3d7cda593243fab", - }, - { - length: 140, - nonce: [3]uint32{0x1c9d70f0, 0xa088a367, 0x4ec24d2b}, - key: [8]uint32{0x494e9775, 0xd07a852, 0xaf8af24a, 0xc65b825c, 0xc5e06780, 0x17fbbace, 0x651d71b5, 0xf548d8ef}, - input: "e46841f12d98aeb7710b9162d342895a971b0e3a499886bbb6aa74dc744a28d89a54542b628acdc2f693cb7c03f73fc3b74069bc3f2d000a145fb8a806cdc7d6fa971da09a33b92851cc3d1f6f5646d7fa2b1d564876feefeb63b6e66dba1c0b86ca345235bb822e0f93132346840d2a3d6eb1b541178ea51affc7b31f8da02732cc4e5bcb5d8683ae0a91c9", - output: "1dcbfd0bb2b905656c52bd7b1bcdad9b4d434ae9ac221a0d3a316115cdd4a463fa9b3444d2612a4e277d0dcd881fa6e80e59e5a54e35e1a14747aed31edf4ac24214f9d9c329ebe2157620b64efaded9976549bc4aa100d5c15be3f85f700f8a21dfe77590dfee2de9a23cc1ed1e44f32ebf68ca289b097bc13b42802dc7c75309c4afc25b5741839f7db3d5", - }, - { - length: 144, - nonce: [3]uint32{0x23067b8b, 0x5b276c6d, 0xaeca6c60}, - key: [8]uint32{0x29d64488, 0x893a2973, 0x32e3b4ef, 0x2af3d5d4, 0x95ec01b, 0xc805b64c, 0x884e8b7d, 0x798d7062}, - input: "e98e4a9550bdd29e4106f0cc8669dcc646a69438408e9a72c7cdb9b9d437b5f7a13fcb197629541c55bca1f8972a80cd1c1f591a0e24f977cdeb84763eab2648e42286e6473ea95e3a6a43b07a32b6a6cd80fe007ba0cf7f5ac7e651431f5e72690ec52a7134f9757daf0d8eff6b831a229db4ab8288f6bbf81e16fedebe621fd1737c8792cfd15fb3040f4f6a4cbc1e", - output: "5c69cf522c058790a3bc38979e172b60e71f7896d362d754edc1668d4f388b3fc0acdf40786d2f34886e107a142b1e724b9b9b171cb0e38fd78b35f8ac5269d74296c39c9f8628d848f57af9d8525a33f19021db2b9c64ba113171ebb3882075019ec7e77b51ce80b063ed41d48dad481d9536c030002a75d15c1c10ce0ec3ff17bc483f8416055a99b53035f4b6ea60", - }, - { - length: 148, - nonce: [3]uint32{0x2b079658, 0xbdf5da85, 0x8a75450d}, - key: [8]uint32{0x49c9eaa3, 0x62048819, 0x9baacfa5, 0x3870addc, 0x5c682e1, 0xf4f9fff3, 0xa3848e4b, 0xac1ebc1}, - input: "ce0f0d900dd0d31749d08631ec59f216a1391f66a73bae81d3b0e2919a461bc9a14d6a01b827e3bcb55bbccf27c1ed574157e6becd5cf47181a73c9d3e865ab48a20551027e560e965876b0e1a256bfa5cb5179bf54bd8ec65e5570e374b853b37bf4b3ef1ec612d288ebc19275fa88da9419e012f957f9b6a7e375b3377db0eb3619c731aebfeb0930772b4020d3a3e90723e72", - output: "b06981b57fe184091ef9f8ccf522a5bcdb59bf9a68a3ddb817fdd999a6ecf81053a602141cf1b17017bae592b6b6e64756631a2b29a9e1b4f877c8b2ae30f71bc921e4f34b6f9cd8e587c57a30245f80e95005d0f18f5114400785140e6743da352d921fb4a74632a9c40115ad7706263ac9b41a11609fa0c42fc00f8d60931976162598df63ebad9496dd8943d25a03fa47475c", - }, - { - length: 148, - nonce: [3]uint32{0x98e8ab8, 0x84d8e77b, 0xbb305841}, - key: [8]uint32{0x46b5f93c, 0xc8b2778d, 0x2cc5278f, 0xd2a3904c, 0x6ce5d4f, 0xc4459e8, 0x4a35c30, 0x2feadc02}, - input: "eccfd66bdc691478f354b8423d6a3f20932a1f591d8e6cefa734975fb8ee6881b6dc92c0d1d5ed54fd1999efd7f11ac697a1f130587dd895eb498c9a8fc7d1714c385ec156ecae3bdea2a3462834245e724531d0fedda2b77693a53ed7354b758e875b23cfc83219a091fb2076e7a88cd77f779ed96f8d81ffa3fe5059303ac706086494b9f2982f4f88a0c6fadc3748625004db", - output: "925529047d4177b72bf50905ba77e47608815522c1829b24046e439d5451901257903a5409fb910373167e8b7f4fdfa543a477608ddfc11bbd1efc138366961463b9915b302a346b795dd593f6fcf4fa73529b6fe83079552aabbe99474a72806f59688d826675fa7f6649b9f5307e5028853c9821b8c4a1a0fc4bfdc7c8c78b25aeaba2b5821d17b36317381a3bd578917d2504", - }, - { - length: 152, - nonce: [3]uint32{0x2e2a6e4a, 0x9a6d488a, 0xf9966cb6}, - key: [8]uint32{0x58903bff, 0xc2be173f, 0xe26128b5, 0xb6b6af53, 0x92f8eeb, 0x38cf3336, 0x7fdf90fb, 0x7ae24b37}, - input: "f0c7139c69413869bca980d7f192b2bc3f57e34ca4f26164e1a54a234e84e1aa285cc02cfbaef3dfba2dbb52a555ec1f6ef0e89d0b2f0bd1846e65b74444b5f003a7308965e67bed558689be2668ca10ca368fac072e0e4535a031af23b3c37c561e185872b86c9bceddb5c1199e43fb5f735384766d33710460b541b52d3f5b6c108c08e76724bcac7ad2d866a8bbeeea92a3d867660d2e", - output: "d2c16c7a242b493038203daec65960de384c030eb698ef6a53c36eabb7556cbfa4770eaa8bc0a2b385ad97495eeb1c03ff4e6efcb804aefa81c177dc62700a9eefe6e8dd10cff5d43a2f47463cab5eb1ee260c3826cac9bfa070f1e0435541a89ebd224d13cc43f8fff12f38091c2b3f2102d5c20d8b1c3ae4f129364bbe9f9ce2147dcf0639668ddb90dffe6a50f939f53fa7ba358e913f", - }, - { - length: 155, - nonce: [3]uint32{0x243e0198, 0x884448c, 0x9a31e760}, - key: [8]uint32{0x37e017bc, 0x9b1e2e90, 0x15679daa, 0xf94a23ee, 0xda86dfe, 0xc3eea84c, 0xdd199799, 0x6eeffb92}, - input: "7024974ebf3f66e25631c0699bcc057be0af06bc60d81a7131acaa620a998e15f385c4eaf51ff1e0a81ae5c6a7442d28a3cdc8aeb9701055e75d39ecac35f1e0ac9f9affb6f9197c0066bf39338a2286316e9d1bb7464398e411da1507c470d64f88d11d86d09e6958fa856583ace697f4ee4edc82618662cb3c5380cb4ce7f01c770aab3467d6367c409a83e447c36768a92fc78f9cbe5698c11e", - output: "ff56a3a6e3867588c753260b320c301ce80de8c406545fdd69025abc21ce7430cba6b4f4a08ad3d95dc09be50e67beeff20d1983a98b9cb544b91165f9a0a5b803a66c4e21bd3a10b463b7c1f565e66064f7019362290c77238d72b0ea1e264c0939d76799843439b9f09e220982eb1dc075d449412f838709428a6b8975db25163c58f40bf320514abf7a685150d37a98bac8b34ccb5245edb551", - }, - { - length: 160, - nonce: [3]uint32{0xd24e866d, 0xc59d25d8, 0xfcf623f1}, - key: [8]uint32{0x5f32cca0, 0x4167cac5, 0xc04943ee, 0x507fa1ec, 0xad8fdfc0, 0x6266fa2d, 0x22f05341, 0x8074143e}, - input: "8d79329cf647e966fde65a57fc959223c745801c55312046b791671773cca0af4cd48ead1f316eba0da44aa5d18025eced0c9ed97abaabb24570d89b5b00c179dca15dbae89c0b12bb9e67028e3ae4d6065041b76e508706bec36517a135554d8e6ef7cf3b613cbf894bec65d4dc4e8cb5ca8734ad397238e1e5f528fa11181a57dc71cc3d8c29f3aba45f746b1e8c7faace119c9ba23a05fffd9022c6c85260", - output: "60aea840869f7be6fcc5584b87f43d7ba91ed2d246a8f0a58e82c5153772a9561bdf08e31a0a974f8a057b04a238feb014403cd5ffe9cf231db292199198271f9793c9202387f0835a1e1dc24f85dd86cb34608923783fd38226244a2dd745071b27d49cbffebea80d9dacad1578c09852406aa15250de58d6d09cf50c3fcfff3313fac92c8dad5cb0a61ccc02c91cecee3f628e30c666698edecf81831e55ec", - }, - { - length: 167, - nonce: [3]uint32{0x30b61047, 0x810cf901, 0x4d681524}, - key: [8]uint32{0xe51476d0, 0xdf98008d, 0x59dfe69e, 0xdb39166, 0x6c1e4a4a, 0xfb76165e, 0x5180f185, 0x7359fb35}, - input: "85484293a843d2d80b72924b7972dfa97cbe5b8c6bcc096f4d5b38956eb3f13f47b02b0f759ea37014ecdecfb55f2707ef6d7e81fd4973c92b0043eac160aaf90a4f32b83067b708a08b48db7c5900d87e4f2f62b932cf0981de72b4feea50a5eb00e39429c374698cbe5b86cf3e1fc313a6156a1559f73c5bac146ceaaaf3ccf81917c3fdd0b639d57cf19ab5bc98295fff3c779242f8be486ba348bd757ba920ca6579be2156", - output: "bb1650260ef2e86d96d39170f355411b6561082dcc763df0e018fdea8f10e9dc48489fb7a075f7f84260aecc10abcfadbc6e1cd26924b25dedb1cc887ada49bb4e3e02006bdd39098ef404c1c320fb3b294ded3e82b3920c8798727badfb0d63853138c29cf1ebf1759423a1457b3d2c252acf0d1cde8165f01c0b2266297e688ff03756d1b06cb79a2cc3ba649d161b8d9ef1f8fb792bd823c4eabb7fb799393f4106ab324d98", - }, - { - length: 172, - nonce: [3]uint32{0x42020cbe, 0xad62af90, 0x29e53cd}, - key: [8]uint32{0xabad2095, 0x601ec477, 0x3bc923a1, 0x1edede1a, 0x33612355, 0x285b4858, 0xd3fd6714, 0xe0f4bcc3}, - input: "a2fc6e1b5281a4e0330eecd1ab4c41670570423173255979953142b78733b2910fa5540e8294208df6ae4f18672d5ac65acf851bcd394e1932db13c81b21e6f165e5538aff862e46126c650bbe055e54b31c78f2f0221d2631d66ef6d3f4c5ae25eada043b74d8770e2c29799c0954d8ccbd17766b79e6e94e88f478db3566a20cb890846917591a07738328d5c05f7ed4695a82607660f1239661faa9af0368aeb89726f13c2aaecf0deaf7", - output: "d8fe402a641c388522842385de98be60f87d922c318215947d4b7562d4ca1e2dbc7ee86494e65fb0bfddfdebdb2ae6469312f95b32c722b2720d64bb8d7cc3dd82f9055b1d89f05b77984f91f94ba4ac79c5129cd7c91cc751b0defc3f2799518e372d27aa683f1e7bbd4f55414c48fe8a3a37ac1f179a1a329cda775aec0d31d75a5a38addb1de67c06bddbedf4c8d87abc18c9f9dd072d457ea29ad4dfb109ce7e99a4a82fbe330b0afbb5", - }, - { - length: 176, - nonce: [3]uint32{0xa8021c8f, 0x667a02c4, 0x7a68b693}, - key: [8]uint32{0xece401c8, 0xfa805a47, 0x6d572fca, 0x9c1c780c, 0x647545e5, 0xd7ef4c11, 0x91dc1e46, 0xba2a694e}, - input: "480387bc6d2bbc9e4ced2448d9ec39a4f27abe8cfb46752d773552ad7808a794058962b49e005fef4e403e6a391d1d3f59025eeb5fb8fbbe920f5361862c205d430eac613cd66108f2f2f0bd4d95a8f6ca7bd1f917eaeb388be87d8b7084a2eb98c575034578edf1b3dafff051a59313873a7be78908599e7e1c442d883d3fd3d26787eb7467eed3a3fb2d40046a4460d5d14215565606bcf8b6270af8500e3504d6d27dacf45bace32214472d525fdc", - output: "ab81a9c28358dfe12e35a21e96f5f4190afb59214f3cf310c092ab273c63cd73a783d080c7d4db2faccd70d1180b954cd700c0a56b086691e2c2cd735c88e765e2266cd9ebe1830d63df4b34e2611a8abeeca9c8c4fac71135dafb1cb3569540ed1362ddeb744ed62f6fd21de87b836ec2980f165c02506e0c316ae3cf3d18a862954d9781f726ecc1723af4a730ccc6d6de82553450a52499acb58fb2008969401c45b2f20e12b58f308db1d199b4ff", - }, - { - length: 176, - nonce: [3]uint32{0x414e687c, 0xc6fc69c2, 0xd3ca12d3}, - key: [8]uint32{0x1b51cca, 0xbc8455af, 0x3f904842, 0x6042b452, 0xcd4dd164, 0xda83f3f0, 0xff04b972, 0xf972dd0e}, - input: "b274e61059f3215173ae226e30a92ee4b4f8a3da95f2e768e3fac2e54ddac92c200c525f190403a6ef9d13c0661c6a7e52ed14c73b821c9680f1f29711f28a6f3163cf762742ed9474dbea51ff94503a5a404adbbdfbf4c6041e57cb14ea90945dc6cb095a52a1c57c69c5f62ac1a91cd8784b925666335bbfee331820b5f7470bc566f8bbb303366aafe75d77c4df5de2649ed55b2e5e514c3cb9f632b567594a0cf02ec6089a950dbe00554ee4dfb9", - output: "a0969730d48ee881792a3927b2f5d279aba9f2ed01e6b31b92d0e1fb8ba7f35a236d838e0ce5f8654957167de864f324c870864b4e7450a6050cd4950aa35e5a1a34a595e88dd6f6396300aff285de369691b6e0e894106dc5b31525e4539c1e56df3ceedbbab1e85da8c0914e816270a4bae3af294b04a3ea6e9ef7e2aab4da5f5370df2706b5e3f000d88179ac756deaa652a1cc85e80ad9622f1bf91a2776262eb7289846d44f7f8192e763cb37aa", - }, - { - length: 183, - nonce: [3]uint32{0xdd315c1d, 0x2335da98, 0xe0a0da0f}, - key: [8]uint32{0x6419c7d6, 0xd340f42, 0x7af2f4b8, 0x3536cf42, 0x2f68c6fb, 0xac9d855f, 0x7c4d490, 0x9711b1b1}, - input: "ee849039c6cd972dc943d2a4468844d130c0150276f4e0889047e2300c3ecc6792c4527bfe9437dad877eb986e6b1aa9b867d1798c9d314243f0a87ec9ee5b601c2554876c87cbf50df3334a077c4152f8b8fef4a2d301ddbfa90c887ece757c3eb6c4fc1e0212d6b5a8bb038acaec28cba064c9b34f5364cb7f0fc2ac4ef2c7ddde0f5ba17014459eaa78f08a46a01882ebf7c6e409dadda250bb899dc8b3b70e160bbcb4412a9963b174d0fc6bc16383a46ffaacb6e0", - output: "3e272ded9c0a5cebe7cf17ac03f69eb20f62996e047501b6cc3c8691ddb2780ea72c21a81888bfea96e4373a412c55ca95648390de740102d661143043baec3976230e024477d134b8504a223c36a215b34164c9e9e1fa99a49fdc56f2f04ea525a6b82997d9bbc95c4b5baeab4dec50061efb7c1a757887acb8b47b142e0a2e61885a2c14c4642d83d718a0546b90699adc545a48129603862a1c89d8e665cde54b3ba487754db6d6f5acf6a4b95693cc569577a2dc48", - }, - { - length: 185, - nonce: [3]uint32{0xebb44f7c, 0xaf14c7dd, 0x4543cd7a}, - key: [8]uint32{0xce71977, 0x99790e86, 0x6510d6dc, 0x37968ae7, 0x2917fb9a, 0x19ef25f, 0xd282d085, 0x6128d043}, - input: "0992396a6f29b861dd0bc256e1d1b7dce88435733506a6aa20c62e43afa542d1c46e28b2e6d8e2eacb7c08db05e356fe404684b0e3a9849596db82eb788aa09258c28eb19e9838f757425b4edef12deeca56e30cf030272e325d4246d6e083219b2f965124963ca91f066d47bf5a8282a011a78b0155aa70038259a4a59135f241fd2f88c908b9f4eef7b7df0f3a1c16a52c009b522f89dabd52601bbf6e3ce68732e1a6d444469480f06da218786cf6c9666362e7a7f7be12", - output: "545c05a84b5a4fffd1dd623c8f2b11443818560bdb0c26dadd3b694d4790d294b99059f4127b7cca122c4000954d745af96094ff4623f60db33e994bb6903263d775f48d7047427b3a498c2ecde65bd37bcb8ee7e240a1e08c884c0079cab518f4e1c38ba5ea547f4da83b7c6036e4259bee91c42e8fae895df07781cc166f1d50e1550a88ee0244bb2950070714dd80a891aa8a9f0580a67a35cb44609b82a5cc7235f16deea2c4f3667f2c2b33e8eeef944e1abdc25e48fa", - }, - { - length: 187, - nonce: [3]uint32{0x35cb7190, 0x212e9a86, 0xbc423ce4}, - key: [8]uint32{0xfa19cede, 0x576ae8f2, 0x58055dab, 0x91b3355d, 0x69d2501a, 0x736323c2, 0x266c1385, 0x134f4557}, - input: "3b9efcbbb607fad5e9f1263dad014cc5c2617d439fcd980408f4f9a93acb1a33d1c3a22f38c037e4603dfbbfb5571bc08c4a1958cbbf510e3e4dd19007fe15fad7808369149a9c4db7ca0496f7a600a6f2454ee1cffd5a68d45c270e4b53ac9b77f33a1ffbb1804244f57d2b05b8036fe2cda9efead3d4eff074ea5c07128e0b354a4a11ffa179163933bc6bd10d200804cc93b64575746e94e975f990bddcc8a4335e99e2459fbe9bc0e004ffcd6cac52f48ef55cc0637a75c1dc", - output: "631ba7301e33236da2477506ea98d3b732447389e849b68e1f09bd5fd814f40dc3247a1012fa654f08e3dda0c104ee2dff12ecf5cb018644de50d70dfb6c8cc1f5f552e5f1e50466bbb538ad6b98fd37f33fe615c326efc9cc97899b829b007f91569fa9b28ce0076c53daedf9cc0f838e22cf1125b86a6a2c2eb4a45dadea45ad00fb4f054e7d6b09c13ab1dd5328debfbf4f1b70af2b8a5b1d02df8a87d7661473e0c180ba4c815f14db87c5bdc15f11a29d8e0ce3d747d5dcd4", - }, - { - length: 191, - nonce: [3]uint32{0xccc941ac, 0xdba45b02, 0xab0d7ad6}, - key: [8]uint32{0x9b750752, 0xa627090a, 0x967c95f0, 0xf8ff2c3f, 0x69beb97e, 0xa30b99c1, 0xadddc83, 0x443f9baf}, - input: "f28a71efd95e963e5e0bc0fcf04d8768ce93cb55dc73c32e6496022e214596314b7f843f5c7b136a371c2776a0bfbdd534dccbe7f55e9d3d3b5e938f2d7e74393e4caf6c38fa4b05c948e31dc6a9126817fa3d7892c478f75ab9f6ab85c0e12091bd06e89c7d3ca8d9dcdd4c21fead3d769a253919c2c72dd068474ea322b7e71cafa31684e05a63e179e6432fb70661792cc626a5060cec9e506b35d9286f15dc53cc220b1826314eec337dd8e7af688e5950b2316c30516620569ea65aab", - output: "1bcea54b1bf4e6e17f87e0d16388abe49b988b9c785b31f67f49f2ca4011ecd2ad5283d52ef707dd3b803e73a17663b5bfa9027710e045a0da4237f77a725cf92792b178575456de731b2971718937dd0e9ea12558c3fa06e80bbf769e9799f7470db5b91476d6175f1a6d8e974fd505854c1230b252bb892a318e6d0c24dcc9ecb4861769cd746abab58805bc41c6086a6d22b951fba57b00c5b78f6dcb2831715b9d4d788b11c06086f1d6e6279cd130bc752218d7836abc77d255a9e7a1", - }, - { - length: 198, - nonce: [3]uint32{0x987e7c58, 0xcc839a94, 0x30952e60}, - key: [8]uint32{0xe34a286f, 0x4adcd996, 0x97168712, 0xa82dde8, 0x14249e5, 0x5e82810b, 0xb4a445e8, 0x9579adb0}, - input: "c1d1ede73bd89b7c3d4ea43b7d49c065a99f789c57452670d1f92f04f2e26f4f5325c825f545016c854f2db2b3448f3dc00afe37c547d0740223515de57fd7a0861b00acfb39931dc9b1681035d69702183e4b9c6559fb8196acbf80b45e8cc5348b638c6d12cea11f6ef3cc370073c5467d0e077d2fb75e6bf89cea9e93e5cf9612862219ca743ef1696783140d833cd2147d8821a33310e3a49360cb26e393b3fee6dba08fcda38d1b7e2310ec1f715e3d8fa0c6b5e291eea07c25afd5c82759a834a89cc5", - output: "11a8493cdc495c179f0d29c2b4672997205a9080f596ee3c80d79b55162b1c875ac18eb94bf2a9e05b08024f524a1e9665912394a330c593d23260e6bdf87620c10a48f678693196fb744c49054182fba667c601e7b7ebf0f068e8d69ba004b804fda616a4a0d5350e1a3bd424b8266462be282308219c578569aefc1ccd09ecdf5da283356c9e524e14e69d25b0e19643dab26f54373a7272b43755c3f1ddaee6c5fb9e8e093110c41697e95f73a68c75454e050239197c9fbd8cec76698bd11894ebf6e2b2", - }, - { - length: 204, - nonce: [3]uint32{0x851f025a, 0xe6f3c800, 0x85ae7530}, - key: [8]uint32{0x2d0dbe47, 0xda05e465, 0x42f6b3b2, 0x7026e79e, 0x9e446680, 0x691df976, 0xf7b23da2, 0xbb3421fa}, - input: "37b2dc4b6a5203d3a753d2aeffcdaed5a7c1741ed04d755dd6325902128f63b6981f93c8cc540f678987f0ddb13aae6965abb975a565f0769528e2bc8c6c19d66b8934f2a39f1234f5a5e16f8f0e47789cd3042ca24d7e1d4ddb9f69d6a96e4fd648673a3a7e988a0730229512382caaded327b6bbbbd00a35df681aca21b186bc7ac3356d50889bbf891839a22bb85db4c00bfa43717b26699c485892eb5e16d1034b08d3afa61f3b5f798af502bba33d7281f2f1942b18fb733ca983244e57963615a43b64184f00a5e220", - output: "b68c7a2a1c8d8c8a03fc33495199c432726b9a1500bc5b0f8034ce32c3e3a78c42c1078e087665bd93c72a41df6bfa4e5beb63e3d3226aeeba686128229a584fab0c8c074a65cef417ad06ab1565675a41cf06bb0fb38f51204eccccb75edd724cdd16b1d65a272f939c01508f0385ca55ac68a0e145806317cc12e6848b1124943a6b2d99a8c92083fc5f31ab2e7354db3f8f2d783dbf1cfec9c54f8bfcb93d6f28ef66f18f19b0fab8836458e9b09bee742ba936cb2b747dd9dcf97ca7f6c82bf0af6f1b433592d65143fe", - }, - { - length: 210, - nonce: [3]uint32{0xaebfd97f, 0xf583442d, 0x15ab2f1f}, - key: [8]uint32{0xd3d1cf9b, 0xe43187e6, 0x5071a757, 0x412a83b4, 0x3f27716f, 0x17fdc488, 0x271f77ed, 0x6c4bb056}, - input: "68c2c5612912b5f994172720130dff092ee85a2c1395111efa64d5a281ca864d3db9600e685854d81c6de7e8747b92fb7c4c2efa829d3d4c0c9fc9d689e2e5c84c9eae8ba4ab536fb6c7523124b9e9f2997f0b36e05fb16163d6952eee066dd22fb7585925ffded0204cc76818bcead0d1f8095ca2cf9cd1ddcd0361b9c9451940e14332dac4e870e8b2af57f8c55996447e2a8c9d548255fe3ed6c08aedaf05bb599743ecb0df8655152bbb162a52e3f21bea51cb8bf29f6df8525eb1aa9f2dd73cd3d99f4cca31f90c05316a146aab2b5b", - output: "d0ae327fa3c4d6270a2750b1125145bdeef8ab5d0a11662c25372e56f368c82c6f5fc99115a06a5968f22ffe1e4c3034c231614dd6304e6853090c5940b4d1f7905ef4588356d16d903199186167fec57e3d5ce72c900fe1330a389200ed61eec0bdc3672554f1588ec342961bf4be874139b95df66431178d1d10b178e11fcbd26963ff589d5d5faf301b7774a56bbfa836112a6ea9c3026ebdd051085f9131132c2700674bef6e6c2c5b96aace94eb2ba6c0e0aef0eefa88995e742ca51ac50af83683b801b7c2c5af4880e2b344cc5564", - }, - { - length: 216, - nonce: [3]uint32{0xf9e973b8, 0x2485a6a7, 0x2ea7dee6}, - key: [8]uint32{0x96edef11, 0x8cf57f26, 0xb6e3a83c, 0x9ef434c6, 0x4607ea48, 0xace87e4d, 0xa0d87475, 0x3a9c9458}, - input: "fed3d1efa309c8b50cb9da02b95167f3b77c76e0f213490a404f049270a9c105158160357b7922e6be78bc014053360534add61c2052265d9d1985022af6c2327cf2d565e9cef25a13202577948c01edc22337dc4c45defe6adbfb36385b2766e4fa7e9059b23754b1bad52e42fce76c87782918c5911f57a9394a565620d4b2d46716aa6b2ba73e9c4001298c77bfdca6e9f7df8c20807fa71278bd11d6c318ed323584978ad345c9d383b9186db3bd9cec6d128f43ff89998f315dd07fa56e2230c89d803c1c000a1b749107a3159a54398dac37487d9a", - output: "6a95fba06be8147a269599bccda0ce8f5c693398a83738512e972808ec2f25bc72402d4bcd1bc808cc7772b6e863b0e49d1d70c58fcf4fcaa442215eeb3a4648ade085177b4e7a0b0e2198f0acf5465c97bd63f93781db3f0b9a0a184c3e06a76c4793a13923f83b2242b62511c2edff00b5304584cbe317c538de23785d2504fae8faabee81c5315298186ce3dcbf63370d1ccd9efec718cbc90b3d2e0b0b6aefb3a9b31e4311f8f518be22fdc2b0f00e79a283701c53f6936dd63734ecb24480d5365d1a81392498faf9a1ddee577007acc5f8c87895be", - }, - { - length: 217, - nonce: [3]uint32{0xe3bd4c44, 0xa3b75a31, 0xfe92010f}, - key: [8]uint32{0xdd05ab8b, 0x5ac7cd1, 0xb8113720, 0x53524706, 0x8e0ceea1, 0x52eb23e7, 0x1c85730b, 0xb33914d5}, - input: "d776bee5625d29a2ebf6fec4df94d2b9ac62e8e7c56704fd38a87ee932b787cbc555621535e76ea30183cb0ee30604f485b541f45feb8c01b9750d37fded5cdffbbc34fb90fdc9c7c7ddf949a1d50b796f1ea5db437238c7fb83c4b22c9e491f75b33d84746f1cd10bfda56851b8514ff0ded0adfd5092a66a85202d06bd967485d06a2c56011110da74bf40b6e59f61b0273164744da02ce2b285d5c3f03aee79eea4d4503e517177692ed3bb035071d77fc1b95c97a4d6cc0d41462ae4a357edf478d457c4805fa586515614697e647e19271091d5734d90", - output: "60e9b2dd15da511770162345251edfb15cea929fb79285a42f6c616dfde6befc77f252e653b2d7902a403032fc4ce4934620931a2ec952a8d0f14bf1c0b65cc287b23c2300999ed993446eb416749bf0c9c7dfe60181903e5d78a92d85e7a46b5e1f824c6004d851810b0875ec7b4083e7d861aabdd251b255b3f1fd1ee64619a17d97fde45c5704ab1ef28242d607d9501709a3ac28ee7d91a3aac00cd7f27eb9e7feaf7279962b9d3468bb4367e8e725ecf168a2e1af0b0dc5ca3f5a205b8a7a2aae6534edd224efa2cf1a9cd113b372577decaaf83c1afd", - }, - { - length: 218, - nonce: [3]uint32{0xcdabfd50, 0xd10d5b99, 0x9e160a85}, - key: [8]uint32{0x8231a4e9, 0x89f33c8b, 0xf96b11b, 0x853cae9d, 0xf6624a33, 0xee9523ee, 0x28bb7853, 0x688ac6f8}, - input: "4f57848ff5398e61bcafd4d4609bcd616ef109c0f5aa826c84f0e5055d475c6a3a90f978a38d0bd773df153179465ab6402b2c03a4bf43de1f7516eb8626d057ae1ab455316dd87f7636b15762a9e46a332645648b707b139e609b377165207bb501b8bccfa05f1bf0084631c648279afdf51c26798899777812de520f6a6f0d3c7f3ef866982f5d57f9c8d81c9a4eabb036651e8055a43c23a7f558b893dd66d8534bf8d179d8aa7d9e8987cfdaaa7b5a9381ba9c79d5c1161b1bdbd30defdd304ee07f19b7ba829a0d5b40a04b42edd6407b68399caac69069", - output: "e096cc68956ed16d2dea1154a259e01647913eeea488be0b54bd1816c781a35e161772ae1f7a26b82e864ade297a51cc9be518641b2e5f195b557ec6fc183e4e5c1fc01d84fe6ca75e5b073af8339427569b1b8ee7fcff0ffa5e7e6237987c40deec0abf091c06a3b28469c8f955fc72e4f3727557f78e8606123e0639dff782e954d55e236448f4223ff6301accda9f8fa6cd43a8d6381e5dde61851a5aec0f23aeca7262659bc793ce71fa7992f80e44611ae080b7d36066e5c75c30851306f0af514591d4d5034ecdf0d6c704bfdf85473f86141c9eb59377", - }, - { - length: 219, - nonce: [3]uint32{0x67de323f, 0xa0442ac9, 0x9d77b1d9}, - key: [8]uint32{0xca8d33d4, 0x834349d9, 0x5e68d581, 0x99a7c30e, 0xdc7f6038, 0x697e8b63, 0x284c2ece, 0xee3e3bfa}, - input: "046a61c0f09dcbf3e3af52fab8bbcded365092fad817b66ed8ca6603b649780ed812af0150adbc8b988c43a6ada564a70df677661aff7b9f380d62977d8180d2506c63637c0585dcef6fe3f7a2cf3bbb7b3d0df7769f04bf0f2e3af9439ab7615c304b32055aea0fc060890beb34fa9f90084814b6ed7363b400dfc52ee87925c5b4a14a98e3b50c7f65adc48c89ddd6414626c5e0bdefabab85c4a0e012243e682d4931be413af62fd7123ab7e7774fcae7e423bf1d3a31d036195437e9ea8f38aa40182daa9aacf3c9f3d90cc0050977c6065c9a46bcca6ba745", - output: "cd5a6a263e3ee50dda0e34c614b94c3ec1b14b99a2f4095a6b5715fdfc3449fcdf8a09d1ae02d4c52e5e638f1ee87a4a629f99f15a23dd06718792f24285f5a415e40f698752c697ee81f2f9248da1506ce04a7f489f8e2b02e6834671a2da79acc1cdfb78ea01822d09a1c4a87ffa44e56c4f85f97507044cf946ccb6a2e06e2917bac013f608d75ee78fa422a5efc9c569226bf7068d4705fde3a9fad2030256db0acf9a1d12666e0acf9f5346ad62e5af4c01a008d67ab1224b3e98278d073116ff966cdc779fb3aff985ec9411a3eefa042d71dd4ae5b15d5e", - }, - { - length: 221, - nonce: [3]uint32{0xa36a3d5a, 0x1747a05f, 0x5440eb4}, - key: [8]uint32{0x2d701ee6, 0x143d5a1a, 0xbb67b9ab, 0xabc88ccc, 0x20baad8f, 0x6507e48b, 0xdb1e1b39, 0x9e521d80}, - input: "af516216f74a6344cbe458cbba820f7e25c0b10aa84b790da2ee6317e059171076d7246c2878be83fc00c200d546c007f849e4c163d52c7b0da31beff4abff481be3266b92e668cf4dd1c84d9d7b3e5191dcd6ddb51d17d337621046e83e9ac035fccfb239648bc3c6fd340fbb50707e5a33b3ef439d292192d0e4bc727690c61450e5a28789e5ea50e746bc66d039493e080fb70e9ae06d89004cb71de8178941c422f1e9862492fc9149a4864ff52b1277b9f5a63c2f16e9adb5263cf65a034a62ebb0f1a385d2681c87a35f1c45670b4edef1c68fe9544fcf411d95", - output: "b22ffd8f0e549bd3e0206d7f01ff222f92d39b41cf995a331d5ef0cf5c24bcc3ddb36e64d351b5755400246fe4989b5f912e18daa46cdd33e52dafbd2872f16e94220b56315d72c1dbb1525fd34831d7202970c11711ff36de3fc479407c34fef0aea86e172f9beb0f393194355b9dd59625639f4a6bf72ba571c229f2fb053c1114e82793deb2dfe8232f1a327949689d2fb2820662dcd2a39a2546c7df12b3ff7e87e58c74badf568cddebd3c558f0f7874c834c4b8aa988653f138ec79620f5e3ed737690928a30f981dca9f2920ac7307607063b40f87c204de47c", - }, - { - length: 223, - nonce: [3]uint32{0xb92be022, 0x1e1257c7, 0xad7c01e}, - key: [8]uint32{0xca1dbb9c, 0xaadb9504, 0x77b8a95c, 0xc50deb5e, 0x2dbc0fb8, 0x9e654bc2, 0x94d8925a, 0xfe9cfb66}, - input: "a3d70bdb509f10bb28a8caab96db61652467cf4d8e608ee365699d6148d4e84d5d93bdabe29aa4f0bc8ee155f0b1fb73293c5293929eaacdd070e770c7cccfb2de120b0c3811abeeddaf77b7214a375ca67d618a5d169bb274a477421d71a651cfb9370bcf7e0d38f913754c11002089cf6cd6a8de1c8a937fb216591d57b37efdf3797f280773950f7eddeb9c3385c8315ff5ff581c64610a86ada7ff6a1657e262df94892dff9fdfb6e958d101f4c26296470c138dc4e1ca4bb565b3ff877a7f78b3d11d64b7c24e27ba6f6b06f6e368f5ac218cd5d11b815ab0987678eb", - output: "646314264896a6e25601e536f6e783d465b2ead1e0be4422bc9cc8eacabae4a749ad533eb28091be8397328dcfb34c92006bbda930ab070ed7b806095bb1c8f476350e7b08ffbd4d7d6055c8defaa8deff9d54f5215c2d7db27ce09e08f5d87a859145ea3126e2a01882921c3fddef3985bd451bca44063258390aec8ec725b07d064314fe43a9c83e9287b47616dfefbf539b82da209aa08a6d3176b7e3b4be4a17d44e581280a684e4a64414649bfcea82b541729f8178b580e8b972a89f5b8c4f9b68205e9396d8ae5e81873b61da074080fd44c52d50fb0880ee9c35da", - }, - { - length: 224, - nonce: [3]uint32{0x5091927, 0x661c75ba, 0xc23dad}, - key: [8]uint32{0x2e00499d, 0xafdc63db, 0xc3c62efb, 0xb4157a19, 0x84ce8b13, 0x85326279, 0x2ee71e9d, 0x318721e4}, - input: "f48b5ae62f9968baa9ba0754276cd8e9dcfa8a88e4571856d483ee857b1e7bc98b4732e81f1b4421a3bf05ab9020d56c573474b2a2ac4a2daf0a7e0c3a692a097e746d12507ba6c47bec1d91d4c7cfc8993c6700c65a0e5f11b1ccd07a04eac41f59b15b085c1e2a38b7d3be9eb7d08984782753ae23acdafbd01ae0065ab9c6d2a2d157c1fc9c49c2444f2e5f9b0f0bbfb055cc04e29b2658b85d414b448a5b62d32af9a1e115d3d396387d4bb97ba656a9202f868b32353cc05f15ae46cbe983d47b78ba73d2578a94d149e2c64a48d0c1a04fc68baf34c24b641ea0b7a800", - output: "b9af1016275eaff9905356292944168c3fe5fdffd9e4494eb33d539b34546680936c664420769204e91ead32c2bb33a8b4868b563174d1a46108b9dfe6d9ac6cc1e975f9662c8473b14950cbc9bc2c08de19d5d0653bb460bea37b4c20a9ab118a9550bfeb1b4892a3ff774e8efe3656adcdf48239f96e844d242525ee9f9559f6a469e920dcb3eaa283a0f31f5dfac3c4fac7befa586ac31bd17f8406f5c4379ba8c3e03a6992a1915afa526d5ed8cc7d5a2605423ece9f4a44f0c41d6dc35a5d2085916ca8cabd85ac257421eb78d73451f69aaedeb4ec57840231436654ce", - }, - { - length: 227, - nonce: [3]uint32{0x5d6d997c, 0x9d623987, 0x5742de36}, - key: [8]uint32{0x57b2a5ea, 0xc5bdd68b, 0x99c7b0c6, 0x26aea960, 0xba5c75f1, 0xa904cf6b, 0x685031de, 0xa0f0e99}, - input: "b39101601efa2ecdf41878b0fd920a3005ce709e4ec2970abb76e32c232ea21069f81b246eda75aace7555ce8ae203455d3723e684bd671389300e353eec0d2f499d10654fafda2e7a69bfca7198eb172249167ca8864b5d5f58d28723090ec86e251a1bac0346d52fd81f06e0c05429e0b2b895588290b7d00878a4da3378eb6c7e61487de2b318fedf68fa7ad7c88ee746827c1f60d98c7716f3f9695c5ffd4670f71a0fa78a1fb554ba482c5de83feaed7c65fc71acc9f541342eb8f7622b12bb2cfa222fa2ddd8b3ed210ce442275afa3132c8a0e17dd504ecbc92525c118952be", - output: "50eb5b21c179a03b9a822f0075906a3ce4acc32486139f92635c7d834f69071d5a6dc0e15ed06a5cee37147071d59641d140a82ad5815b954e7f28e080c3dbbeaf13943d7b7c66d49d51ba1132eeadd4cb7a7e7d726d08d95f1578d55519f267f753f3e16ff39504a87b2286d8bfba0fe6bc28887b466bf276453a82cdd0abbbbf08db0e1c26c317d50ad9b8dc09cd621bc566d362024e8404739df6468869d2125c58b25d70e392f5e75924c4341be81c263915bb514ad436fb24c2c67450e84f6d1b72d1a02a3310c07a7814d930264fdbbf5ddca7067e18e8a44faa87169b7f2e35", - }, - { - length: 233, - nonce: [3]uint32{0x75bca707, 0x89f6d1f4, 0x2a6f657a}, - key: [8]uint32{0x949f42cc, 0x2b5d3c48, 0xfe0be473, 0x17ac92aa, 0xbdc9d9dd, 0x74f9df26, 0x26487508, 0x7c7b41a2}, - input: "0a42f63b975ad0e12a1e32615813dfd6f79e53ce011e2a2f0534dd054689f8df73a8326fecfd517ff7fe530d78081af66c3a8c7c189eb9d9efed1e5577b5512d42ef1fe273f670ce380c64bc62e217a7e410a8ed89998344e29301e4e053a3a3cf7e71587fd056a6bd976f16e157476a06997dfaaff32172dd84190570621f2221420c0a0ea607ea756e9792c8c0e7157c95b89c9490e20b750ee85e4c27c9b8f409e848ec90afcad33342010bb9808358afbcb3d9b094127c38c243a204e76899677079758e7cbada9a5c18363449eebc07bab516a16372722403a046df85c7dd2ffc804c54d38aab", - output: "87a47bcaa1c1eb8e55151011c4f39af4b9e108a55a7124cdcf66d0dee727306e6971f783b038bd6b215f530cdbb53e17975742ec304fdb3792a88b674504396978c6a5e4a9c87a7c3ca430d61165c1a3f6162eeaf38c93e18b6ccb6a595ad428cdc98efef8f84463eed757a72ffd827b71c0579fcc1f4baa11812be2bc5a2a95df8e41d04b33343df09ce628c367d1f88488f7a2787f013c8e76f0b9257cee777ec4adc6df8c5790e41ea02da85142b777a0d4e7c7157a48118046935f8888b5352d1750bf00b92843027a349cf5685e8a2a2efde16dcf5e1c1ed8c779bb38cabfb42ec4dd87d58273", - }, - { - length: 234, - nonce: [3]uint32{0x5003a4f7, 0x40bd8cde, 0xfe35fb25}, - key: [8]uint32{0x576e49d9, 0xe84e9df, 0x9f227a3, 0x437c9de0, 0xc46ac8de, 0x1a6a2d2b, 0x42ab7684, 0x4253fbb6}, - input: "abeff48fa082dfe78cac33636c421991b0d94c3bc9e5bd6d22763601a55201fa47b09ce60cb959ba107020213c28ae31d54923d1e74ab1d9ddc2762b2d23d8c6961d81068230884a39682fa4b30676ffec19319362c075df0b879a0f083a67b23597bf95c4bb997fae4736479cb8a9c00520ba2f6e5962d54c313c576180d17779ff239ad60f1f1373627770d50a1c49718b2b2e536846299e052f8c1a5d3079e91cb1b8eac4661daac32d73b3b99e2051f8f694a61d1e9d3935f802921a4d979b6ade453cf30d73a4a498a6a2c5395c60fcf271d50b4967ac12b0d7bf818c2679d552e9b3b963f9f789", - output: "a0d11e732984ad575570ed51031b8ac2d7b4c536f7e85f6fce9ef5d2b946cefe2ee009227d6747c7d133ba69609f4a1e2253d0eb59d1f930611e0c26a7c0cf2d2ce7ccea6e079eadf2eb1acf0463d90fb4b3269faae3febfc88cb9fb0873d8b74894506199394c8e44a96e6b479bd3e045749cce1c3f57243abdb37e67084eb573cd820c6cee424227019592a027e9da8f7b8997bfb292627a986f83c8fb8d156a91a12a8b52659cf9272924631745ed3a2453a4c2d87a167faa9104e799c715ed597bcb66949ab15dae29a86ba147507e8d8af66e96c09c53caa053ad3b79d9ed3c0c6c00169eaec3a3", - }, - { - length: 237, - nonce: [3]uint32{0xc6ae48ce, 0x26f0906f, 0xfd8ab8bf}, - key: [8]uint32{0x42b82c50, 0x7f519e0d, 0xcbb95098, 0x6f75e532, 0xe2c9f61b, 0x5a4af942, 0x2679777b, 0x6a8e1c9c}, - input: "a77b7a5870335b9145fd2e08ec898ba2f158fda16e8a2661a7a416857b6ba6937b4843ecaa79d3635d28383af80290842de9ca0bb621ee22b7fd6bf379922741e812b1739c33dd6923d0607826fc84d46bbdbd1fe9d1255f56a167779a560a6eed1b9c9579b8f771147df467e67a070d9e9ce8ad92dc0543d1c28216c1dec82614ac5e853ed49b6abac7eb3426ef0c749febce2ca4e589d06ccfc8f9f622ede388282d69ceb2fd5122ba024b7a194da9dffc7acb481eabfcd127e9b854be1da727483452a83d1ca14238a496db89958afd7140dd057773ea9a1eee412875b552d464ba0fab31239c752d7dd3d9", - output: "b330c33a511d9809436ab0c4b84253eeda63b095d5e8dc74803de5f070444a0256d21d6c1cf82054a231b43648c3547aa37919b32cfd9893e265b55545be6d7cd11d3f238ef66c3c278fcccb7dd0dc59f57750562cb28da05d86ee30265ff6a3991a466ba7e6208c56fc8862e19ac332e5fb3cbcc84e83a6205dee61a71acd363a3c9de96d54070a69860c152d4ceb9c4b4cc3b878547b6116699885654b11f888dc3c23483a4b24fbe27c52545c06dd80ab7223d4578ab89bff5f9cbf5d55b19611a5251031df5da5060a1f198226c638ab5e8ec5db459e9cd8210f64b2521a2329d79228cc484c5065ef8a1d", - }, - { - length: 244, - nonce: [3]uint32{0xea38678b, 0xc41eada, 0x3381147b}, - key: [8]uint32{0x268fc2ac, 0x21297e86, 0xdf9ef8cf, 0xd4b45234, 0x2a95c4f2, 0xcec36ce3, 0xd5fa38c9, 0x7dc43790}, - input: "322d634bc180458123e10d0509870b54e0f0a3a72a2bd9e9cf44324c7a1ca37dd6adf9db1fcc8dadabd881f91d47d93b58382802b42ee936802fac8612ea4dd9eca5f215935ea9ba6233b9c8bddba3385861de669d95c888c8977851cb305db577a4eb2360f362fa459d61ffc8fcaa1502905b073bd8e9567ac7cff8e5fb1002c55641a3af5fc47ac0131fae372f073e19721ffcce9821e0241d7fa67bfc499c8f100e050d39bd4d7cae4557d208629603ec4a007852762ec1905d0e81b873510fd334dedcd9c288eb8415db505913af06bea94d197ab627d58f6a9944f6c56247595fc54ae3f8604aa37c3466f74561131e11dc", - output: "edbfb1090987762f75eba2439d746cdbefe8605b8ebad59e075d28b54edfe48813ccae891f6ed655c5ab5211ba896fff0c8e09bd1554aad987dc53f355d0822e9b0f524a99a79c68a9f3b4e30506cd725b07be135e4540078be88dac64fc545c433837b96a924452f6b844291c4c3fb5f8cc94f06d9f19dad7fc945f093020e82ed19f9eb3ddff68b813629991d1a460e5455e1cb41cf23bb3d96fdb6b96581c3bf9ef72814406329bbbba5b835e7724c728cebe88efcd996dea71d0fd5c53e081c21ce8b3764738d693e390fbf8e0137a716760fc9cd2014cd9bf3fd706bc3464d1f15803606976e96b1077cda0a62921ff7c32", - }, - { - length: 250, - nonce: [3]uint32{0x883ac584, 0x8fb8e7d5, 0xdf07de66}, - key: [8]uint32{0xc7747e47, 0x853d88c6, 0xbf9aa631, 0x78f16480, 0x7c248080, 0x15ff973b, 0x31528a40, 0x629686e5}, - input: "e6b8a9012cdfd2041ab2b65b4e4f1442794fdf1c3685e6622ce70f80b9c2252ba6d9e6384d474a7622053d35df946a3b19408b3e1712da00525070279ce381359b542a9ad7c07750e393e0834593777352c1f7dbc84cc1a2b1eba787377d2cb1d08a7d20e1393d44022107acac5d765be37f9075af02e4bbf8e60ceb262aa34e2b870cc7adcf54329a667249cb4958393bff4f4333338cae45cbca419d59e605aa0cecb1241080339198b9b283e4201afc07360b8ae2a57b0b9b97167c315f03fd7a87a00ae73f91ca560a1505f3cdf04576b9aee5ea775f719916f1e1942ad5311c7f87153f8e62855ace3f34afb08d4d7c7f4fd2bf83e42f76", - output: "fc2673c80812d101bca7a2e0e105fa449550e695a016596f5c3cde11fb7dc518b94fdb74058e634546a726c37896110e1d1f9cdeccba1c89958041061ded8e8bc2751ec6dad76a305e70c57f9c81a5a65b5116390af4f7bf7053a03ec13f5d60a58cc5ba61f8c46ef6d2d291de490082dcfdf294aeb3a9414d64e4bd6497d4625acfa591627bfd98f0aec7e7def71515c09942db6911d73b96b4bd2d6df03bb729e945d71549d40e4bc401e1f73baf263a74280537692240638619f92645a5ade1eb8151191c7ff8bd715b3c1cd667e69745b806e16d46d9aa680a7367b8fb45a1598631cf3d44c1f5cfcd95bc8dafdb65a2083905a6937fcf21", - }, - { - length: 256, - nonce: [3]uint32{0x79cd7a62, 0xae619be, 0x7d96d236}, - key: [8]uint32{0x7dec8e64, 0x9f12b14, 0x6c70df2a, 0xeae0aa0d, 0x27b1ac14, 0x7a00d833, 0xe63c0aca, 0x189438e2}, - input: "0cfd93b195e37dd15dfae83132c24ed5bfce7fe6fad4064b213b2c31a39e39ddad2f977e904c9c5b055ed03db46fcdd845bbb6ff0ab5a8c92e89295b6801f36ae63eba61fba24a3858aeb36f2da226b23b24d7b2c7d2670f23a9a1b60db85c0ecee584bef1b00e42d10ca17432a74bbb220d88356d82c850da4c09dd5baf413caf8f9479e02a330065fb865489c0f59605d56146ec8434182345de2d15e2a1dceeeee2fe94871d41913f6788738947ed9849ca0ae985e3e19a97bee82b96feeddceb196c9b6012264661945981c279f43db9599a4ef01116f592478619690daa64387290484d21e8d2444751194e1f361fb37f04014a3c7e4b409e5c828d8990", - output: "0502848571d1472ff10bec06c1299fad23a2cb824d88bf91b5447c5139500bd837a2fddc629e4a964e84907c1e6740263f1fef4f5ed41062982c150d9e77a1047b7d86c0e191945e8db00ca3845a39560857fc9e0e4a394eea4ba80a689cb5714c4bab7124ffdbfa8bbb91c3eb3caa1621f49dba1eea3ebf1d547ee337f9085638a12317b86c11aa1525813445107038942fc519eebdc1b98d313ad822bf0b94a054259aa8cf1be4b3a68f974269729941747f9a23fa5d83453071b431dac62274c24f6a32248b0785ff90aad5840fadc89af0aef7553d9352cfb00d3999ffbe28cd9fde7854e95710f4532b8bf5011e518c93361e58d22a2302182e00e8bccd", - }, - { - length: 268, - nonce: [3]uint32{0xb7581e00, 0x9a1bba92, 0x64356674}, - key: [8]uint32{0xdc2c9fcd, 0x5e50de1a, 0x8546466b, 0xc1b49b21, 0x36a670cd, 0x2887f367, 0x2fbf4300, 0xf90a0374}, - input: "0d8d864010ce8df1c0179cf0236dce1c100f9c115eaa5294c24a2e1afa27f9d57ebc18f00482be0218d44262bd4db73002ff53c6388f5e333470aced2a42a73b376686c8d02e05ece27cdd8b1e3f675c715981f8b656d68d0e16227b529cf881d2433e4371fbcd933eaa72346e77e688ac80ee95324512c66a4c16338cf38c941b72c21c3d01e005a07c0eb436014fb1ee61806de7e96842ca3217ab8c7607d609dd2f637f9fda8a85cb0549f262c9e4a955c384319a6ad2b696e2593d7d174f5ddb98e2a8d5d12558c18ab67571e9a0202e91ce26d720cbe41a3a6a4f309296ca4d9d9a59a9043dd2e5a707ed7d5034023d5ea06ab14b39b7852e5c984848d5670c6f2f0b189c2a8a4a4bca", - output: "d2a5693c9d503a8821751d085a0837579233e65b691366e4a7464481d22800e786939349f721a815f28b4e47c8889f0814fb95d592d1185e45d6dbcac14ffa4f1d6c79194f2f7eb7323439d9607edf80f01e3a968b483eb93c01d9cb9d3625d21d66927e7aeedc1d9bd589560ed2b61cbed5ad0e0310c8ebe140c64c67d4909c010902d5386efa359ab60a9573493d3e5d8761cfd4023eba23de48372032d4673b5f6ad66cd0dfab02a73aa81f269ae88fcabb3ae9cb09f6bf60fd3575a3046bc6843f444e1e9fb9ff9b991620344fb99da68df09496b40f8b9dfc34e830a87f65710940603ebab554d36e8b4c9228bc9c26c07b828f34cdfdd40b161717236ba325e8c20bd018b324345e09", - }, - { - length: 305, - nonce: [3]uint32{0x2c641fcb, 0x5170c7e2, 0x62a23688}, - key: [8]uint32{0x5aed5915, 0xc5c4cc18, 0xf0e51574, 0x75d894c6, 0x1b7082d1, 0x5d2ea1db, 0x709fd24, 0xf5f69898}, - input: "07c50a69e168e388caf6f91471cf436886a3de58ef2c44795d94fba6538add8d414d84f3ef0ac9377fd5bed6aa6805a695f3a711025550bb6f014893c664e09bd05f4d3b850771991fc02f41c7353cd062156243b67fce9c1f0c21eb73087a5de0db0578923eb49bf87a583351e8441c7b121645bcb64ef5960fdca85af863dca7ebb56662e9707d541513bc91bf9b301431423b552e2c148e66ecfd48045ecb3a940dd65694d7fc8bf511e691b9cfd7547fe7bca6465b72ff9f1748723c4eb14f8bc1efb2fbc6726115c597a3881e0d5019335daf2e5ea8796c2a8b893ca798c4ef2639465505c4bd492bf7e934bb35be9b66c9f35730736c65fa4c1a2485378b9d71912cb924634a8e0db2802b75728818dc00fc28effdf1d8a05e4de4608bb6a78bb19c377d5ec77dca1b5ad38fded7", - output: "3dff5fde2ca24bf419e13cb7d12368e70449d41f2aa22e4b567f5cbdbcf3257975e44097deb180f2621ec36acf375dad3b7a19234b9856dc6c7842a7f86be00304b41a8c1662a02e8390346cbd0ff6be7bc1ceb821dbd805ab5c93c9c6ea5093249b5dc52081cbbbe1b326e831ef3c6c42fb791790086d1586f7daf031e70a71b54e9134f942e9ce229fc77980eb80c985ee0c5965eaba375d156f9b423b0615f4ca6fd77de28e28f35aba327e4f1b75725730155b7b4d6c5c264bf3d9dc9a16e7ededcc261add8c666278bac5cf0b3275d6d6678060eae30bbf2ce5f63e6a53a450b65aa0adbd1c90cf045f5ddd9700c2a99c80586c5244cf4c08035b6ff630c82cec3a4fcc83860e987898b42fe746939f8b37c814f8dab65de276e9784fb90f0751d3ba0826889e1e7e4fdbf8a90942", - }, - { - length: 430, - nonce: [3]uint32{0x99b172cc, 0x91056d0, 0x48057533}, - key: [8]uint32{0xe6cf398e, 0xc3c56066, 0xc5ff194c, 0xf6d2d8c4, 0x6d1d8908, 0x63e62065, 0xcca485cb, 0x1eb03dd6}, - input: "3ddcd3c00014747903c95e49f64258615455a0b26c5070a9532382a9bbd18eeb19c9fe1a902f5c6baf544c5938fc256d310a9332223dc3c54a6eb79a4b4091c3b01c798d2800418863f2865c1cd8add760e445588576d4a6c945e1d6d50dc913674daa4737ac94d84eb0ff57cda95df915989c75adc97c4e3c1c837c798a432ba4803a246bb274b032db77e5c1bb554a5342ef2e5d3ff7f102adb5d4e282ad800ccae83f68c4bfd3b6046786a8cfaa2b63c62d64c938189b1039ae1a81ce5c91530772cca0f4a3470ba68e4e0548a221eb4addf91554e603155a4592dc5c338aa0f75a8cc2822b318fbfba4a8f73fa08512132705dae792eed6b809c251d35cca60c476406d964187b63cd59333771e37367671d0ccb393f5b8bde77bebc133485ec5c66bdd631d98cdbee78a3cf435d2f824fa2f9e91e89af28b2e155df4fb04bbe4ce0b6162dcd8e81ee8d5922ebf9c957b26c343a0396d91f6287a4af9e11b7fbb5a5a5c1fcdb186365a20617d4ff5037b0bfa97b6213a6ebcf0b78b81c65737378787b255cba03d715fed4addc2c70c1fb4d3ab16f2bff287186c26a164dae2fe9dbe3c4a2e1617f01cae79f", - output: "ecea5fc18dc4aed23359cacb8f79a457512e0a27d9816f353e315519d2b2faf74d14ae8ae5e227b203823998a47a050c363a807f45f610942fed4518b8091b88dff8b2af8fb6552eb654c85d2b6a918bcf56fb898392941d983b1afd867ef840e12313059ed3e4d217498dd511563a939c3c536fbbf8e019deed29262f0a655fc680b15939475e0cee0ce2e8bab5834f7354b93e2e0958a5bc608fab369b6aee3c9d73a6898e402484eac7300150517bbd137bf55762897696a3dc4be74b0c141755ac8f2f6e59f707b1690c451a774c46bbe195d826a6784f8d807b78f8ebc343ecacf37cb9b1b2fdbff6a1237b5098853d783e77515c419894c2628f8b5117042294ee2ed58a33746f9e79b13fdfaa25a75fc95340a89076e786e0ecad7de437a9a3fb3092146d255005b22895310b1252a3e34572cf74665b97f4adc30dd0f34e3216c7757953a4b618a775bbe68f9e0922d75afc80a1379aaf1745f2263afb6f0b37553d9c984f1ef781ea75b1980c559c77565c83f3e0bd7a3cd7cdb594658beb7e5eb940633dbc6ae2f50383beea676cb6c814b17b1d73dd133f544da88ab371415889ead21803c1ffe3f2", - }, - { - length: 449, - nonce: [3]uint32{0x2adb4a6d, 0x33d00c1c, 0x10a0193c}, - key: [8]uint32{0x8bd707df, 0x70212019, 0xdb685581, 0x9cdbd1a3, 0x7db9ff1a, 0x1af119ee, 0xb1d8c0ff, 0x3c4a22cb}, - input: "93ce72a518ae892e00c271a08ead720cc4a32b676016612b5bf2b45d9ae9a27da52e664dbbdf709d9a69ba0506e2c988bb5a587400bca8ae4773bf1f315a8f383826741bfd36afeae5219796f5ce34b229cac71c066988dbcae2cbcfcdbb49efcf335380519669aaf3058e9df7f364bfd66c84703d3faaf8747442bdd35ac98acdc719011d27beba39f62eab8656060df02fab7039223f2a96caac8649bc34da45f6f224f928d69c18b281a9b3065f376858c9fd10f26658ae21f5166a50fe9a0d20739402eec84f5240ee05e61268f34408089e264e7006a59bb63eeaa629ba72603e65718d48e94e244e7b39d21d85848d5f6f417631f3876f51b76b6c264356d7d7b1b27bbac78316c5167b689eff236078cf9e2e4626a4ae8bedeecbcaf6883e2e6e9304969b4fc7a4280dcdc5196267e9bb980e225fcbf7a9b2f7098f7f5c9edd06f50c8791edaf387ff3e85ff7bee1f61e4660fddd4eaf5ab0320508e3ccaa9823ae5a71faa86bd76e16d862d83ed57bf6a13de046a3095a74a10c4da952b3c9b8fbde36048537f76eef631a83d55d3a13096e48f02b96a5a8da74c287a9164ce03ddf2f868e9ca3119ec41f0233792e64086c903eb9247dbae80e923eae", - output: "bcf49d62dcd1cff9dc37d7096df0c39031e64ccaeea3830fa485edb71b7fcf2ec709a4b327ef9c7d4ea2b35f113a8485d4c236e06b3baccee30e79c6c08739fe5fbed59db30479b56dfbe584a5d79b169b200430ed27072137e940a34170606b31f22095f2151b4d9b901f6337f991a23e4c8997a1ebf5105361fdade1c889b8dc9565e3b33e0bd608c39d725becbb60da8a797186fe0986736112da3d09906442364d6e253e5b27fd5ad72e877c120ea7a11d42b19948f0df5ddabf9cf661c5ce14b81adc2a95b6b0009ece48922b6a2b6efffdf961be8f8ec1b51ad7cfc5c1bca371f42cdac2389cbddcdc5373b6507cdf3ffc7bfb7e81487a778fcf380b934f7326b131cb568bbaa14c8f427920aa78cc0b323d6ea65260022113e2febfb93dcfce791ab6a18489e9b38de281169f1cd3b35eee0a57ed30533d7411a7e50641a78d2e80db1f872398e4ae49938b8d5aa930c0c0da2182bd176e3df56ab90af3e46cdb862cfc12070bc3bd62d6b0387e4eee66d90c50972427b34acaf2baff9d8a76002a20f43c22ac93686defc68b98b7b707d78d0e7265aabadde32507a67f425cbd16c22a426d56b9892bac3a73dd2d2c03efdb22ecc6483f8d1ca67fc7d5", - }, - { - length: 487, - nonce: [3]uint32{0xecf15215, 0x45e31add, 0x56499d31}, - key: [8]uint32{0xf5988496, 0x49bcc2df, 0x7b4ba3c3, 0x5d5138be, 0xd6cb466b, 0xe98c82f8, 0x147d3f27, 0xc82389f0}, - input: "f72bec13b0f0b6f2317118f14c2a0d8e963b1bd49ae7584e710dbde75bb1e30c79281847cb822a5f3ae4fa56825e511212f17f0d293cfe80f872e6992d304e9283d08ce65ceeacb003b36a862c91282a22536e0b9c19953512a1bf9e20d3e7a8f1a2dff45dec0b9b04c592e88a7814540cf636a024d10008463d0b3aafbc4c9359889149433ef173124866aa6f53526ef3b3f2c630860ecdd08ffd9fc050e95da512cc87f812f9391085cdec5cc87258b8560806a52336d612da7ab05e0f60566b950904aa27c975a48c7d78455728c87f9b53aa4978374ab9592e12c22d9a760e26eb527133534ac5bbf969596b71cde8b4ef3587fa7ffa7116834348c275ad4dce68ab3397521ddc8e54380129cc81b981f9b32db20dddb0ecaa0f1ff7b06495a42b4a800a207b8e9ca38794e2fa9f40546e0e3aef7b5236d7fdadd72b1158714a5ad8d6264df1e75120088e449b9e911eddac59f1f19a795205ab7532783a93159876133b3fe3a518475a545fbe8dd2ac143f33c35d98e3ee13b63606b1e671917ac3ff9412773a3ac47b8c6627b8ba9dde6820f4f16c2ed9cb7d7086cfbb0cf2d7533eff253d14f634ab2aad3fb4289b9a0bb667a6fdd0acd5949185d53f1dd2b96ff060bb44f872a67259100669e6eaf1a7e2b11dd5fc35792db0c44a1127765934a068bf", - output: "bb618ae6b7739a4dedde1dbacf864b0892b93dea3007237d2f6f23be0718bdd29321e6b0fcb6a44dacf0f5c53d91e16165997e2302ae7ebc2dbd02c0fd8e8606a4ad13e409a4e807f331cf4174171c5fff23ca232192906b4eefdf2ffb4c65af78be01b0ba7d15b4341dd5a2edd49b17db2812358c8af0a4a9724e0169f50d1d331936bc2400012a60849876c3ead52cc9fe60173c9992f83f3e41ebd24fe3961835109612994c7620280539d483f91ef9a64c16032a35612a119589efe6357fa35b19531274576e304be75bc7e91d58015792095bb00ce4de251a52b946554366ea7ed9ce9317020ec155ae0071e022af36ad10eda5d671e5090c136e381cecdb8bc179474fabc7dab2d8a134772976cf0791b6cebe2333d34b4b8e2b6b2eab2b5dc7c6a08a583d091df64328cbcde36bc1b81095d82c741a1503c55d833d551a855e098166c5efffb8e4146e32e54abcaa85076ca6660abdfca9e82824217b5d3f23f7ff3455872bc76751480c1a8e3e725365c82fc135cd3713cc0f1ea733754142f8c37716a2a4fa8a6b898215c287565325774c2510df6b49e78cb986853ac5ca532c9a7e2bceb7c0157f60433f29fe29009343d6035d7b5892c77f821b644590615dc505604501dd218dcab789e6f0525387919cf25c7c6d62a8979e39d346decbed2657", - }, - { - length: 511, - nonce: [3]uint32{0xba68c47, 0xbc020097, 0xbf7d14a7}, - key: [8]uint32{0x3bbeedde, 0x6e8f4d6c, 0x6e27cd72, 0x140ff360, 0xc891efa0, 0x4aaa227f, 0x733cfef2, 0x2b51f1f3}, - input: "96eb94e1adbcc0646440c8824a2fc0f2c4b17d9cbddbb8ba8d9dbd6482fbf7201c74eb923153e0138b2f6f182f9c3d5656ee40bb7c26a01740b5c7d125261d4e4197614800aa152b402ba581bfbf4288e73c9ef7e7e37491212b921420eaaff880eeb458e3d0aa108b01b53492c97e328e9d10e3220b924351d583c00e76aee9325d6b89b1f162ffa30b386b37b5eaf4dfc25d22987dde4496158818c4d8f19ea300fe140be921d3f1abdaf9ab8946833a57cda5f41f995ff80e98b0f10f7afd736dd33438dfd395547f11563056078ff8f7c202aac262955f0ca5dae2365472de40f069028104ac552ea5a45ff2773335e5d3242f1e62e0e98003333dc51a3c8abbaf368f284536672e55d005b24b7aeba8e4cef23289adc12db2213aa037c797e7e753ae985568199cfe14cf1704fbca443e6036bdd05859e3583897cbefe7a0cf268b75d554b2da6e503ee04b126fbf74eaac0ebca37e84ab9c726973af780fe2bc9869fe67b7d9e4a04062ee535b2c1740d1347224e211b5cd37ee14c3325f40abee930eb6a1634986e756b3a1f86a3d7ee7184d95ea948506d8ab8b23f92ecf3eb0586f7a8b1bc227e08a0e32ca75ca4eeffc5c0a2a623547788bca66f3dc2c48671e462544d52a87d34307a7f111aeacb7da50262deab33d9f29dd6b47c3bb555be598d619cc66be8c4b74b01772725268a43d467f39bc565e5efcd0", - output: "590965d18ebdf1a89689662cfae1b8c8a73db8b26941313006b9b9bd6afa6a57149d09a27390b8883069e4fc2dfcf75035def1f8b865e24c21b1a1ed3e9f220d7b48046577b661bc92d9888a912984ad415ea2fc92c9e37da0bef5c7dab11495c612c27b5babe6eee28fd26482272fce69ca7f11bac95251735ad808365ac587830ec04105304f8e440a4da47d30e788718da4282941c9c76f18de4f954b8be750b54cb1145489edf273625a0df9a694a23fe7bfea12579b53c3b2a3de85705568cd7e603f3b8beba9a14cad9979ea283a8a291d3e1105b7f890e2a569804d9b7dd4c7e50bd0dcd11223fd7247af77f04212ece1b98c238d2fa0386a994bc502f83dcdd2e5a0d45b185155e1a395d91726d383c2c198fff1590e983c65ee041638510787c8c59c2e96f31678226a033e027bb40c416b73c3dbef31affc93a659c8ec7ffeca313fd5283a80533b2d63941c8f245d22b160c5fe57c5fa4b759c407b9acd6d9c4f80f244360b9acd11e2b43d4af757e16a6ef9d6756df39ca3a8a235e74351f50b2ebf54df633c8c400fd80b41b07117676d486377095660f2f20f62c034563b4560b473a8f4d6a740306d2a822fd8bd98012a840ba9b1709df9a0d61ecc305f7180fd764e334045d9a8ca23cb8036c05616a8b21fc488429ba4168c59dfa231f0ffa668a3be7b16583df1a55bb9c15d51660ddeca730d66f7a9", - }, - { - length: 607, - nonce: [3]uint32{0x9419df54, 0x4593f2a, 0x71c06dd6}, - key: [8]uint32{0x7b517740, 0x41e86353, 0xed629408, 0x5fe32cea, 0xb06bc5df, 0xaec9b350, 0xc00c2a6f, 0xb3aaf44f}, - input: "be3f309c6e7b89e1ec4a855cf161156d09f8a04d5630534ee19e9e071e3f4603f23f0c59a7b7f8a32c4c203ec8c129a268faba09abde7b61135c6c37fd091e2d695f0e242488098ebed30c7d321f4dcef0bdd23fa85a53569868cf2008bf4d2ee7a12a6673298c7e797321b9f4559748223b590e6fcf17aa72251586b01181cefcd32c6a1a20a0fc27143426f6572b1aab0e7301e390cb857f912d78d5153906c698ee140b36cdc72693cc019cb7add747ca3a07b2b82a2332bfa76c962b186ad94209fcf590ed0f6a73b08a771a58eb9649f2f1da4f7c385da83d50c939231f745514d14b0920deedd9c4dc6d2e547f83643d13541870875e52c610372b14b602e7a47f0b3721cfca60ec68e2eee91f40ceba2d0fdb4ebe19cb1d1ab170726c9e600030454ef355f9a40033672be520e528937f38e7a862a5ae50cd94f667cd015a72ee3f91b1a09031bf4c207e0c516b2e7a4baedf373f1ee71843e560741ed3a3094d2b513e2248caf27ce135716f6887d9f1fe5b11e02c12c989d29054ab183a3f55d9b40d78e12ff56edf936ab966c7c3130bea472b71fd69e70165a76afbf720e2c1587a77943b35acfd81b2ab6f39476623edf3663024fb84da8057ed3a361e9533caf9fc58a5e4897e4bf84f58ed063b5c353bdca3792952eec0a1404149ebeb5b17cd6350ab3e27e44e40fbcb00780d001a48d0365d534ff830553409919608881e665f83bb5cf0736d728c41cc4e985c377f89ee1186303d0d76bc634875ab3ebd87059969f24b0464ae11967bcc47f300a34e3b917b1affceea716c5ad9abf1aa3a1106e2f4d006514dc62cfd2a52426968f2f3991c9f9d8fcd", - output: "e4032c01bcece73fde73961ed216820dcb44ce20134678c98afb674bb03afec2f4aacbade7f87a32fff57ae9213eaf0509e9d9db1313b06fd1df53561f85896ba627cccd2d0e2ae4f24f5579bf02f6599f5e63412ba084cf53a5bc9a8061b5c029b755329fcd73f629fadd3bcf6cb4c572fea86466cb5159d19eaaf0f44c3471d0323bc7206bb514ed8117a61c6d98d44faff6a83716657531d965ba3efbcf067c452e0d2807db3423958d9a4421886fe132d7c47e82086db9507616b67f0051dffc1a49ecce3ca8e4d5f5af15684cd8837a471430ddd333ea0b6ee603b7d9e702692f857fab060ccf26f2a8e61dfd3b12923acca78b83a6004e4ff09113becf6bdd0bec3a449a195559dfeafd4e2a79ead5ae3c993a15ad9b1a2ce818e18edb010b7fece9aa437d85ba9841d89026d6aac1a3a6ab6dad932a26d7db6f3664b06d51584cf4d22a75c06e2840db7292798306e4d39379af85a6bc8dcaebb5246e07fadd5e336f122de0ecb99ca24a971701a1f43bd69933beef6e52d299b132e7510caf27b99739e32bd272afc36755ea80cc7ed3957d91325584b338d15b19fe554ee70bee903babe21d0cbecd49235c70a3a4f516ce16761d1cfcd70bb4b9c7c73c359f3fdd0753d6c1ac1a1463142f18266b6a9c84675f247d56563646fb2c8c3b6b81944c2ba2b76b685ba5ea40cf539bcf3850a8af3e0a69c0b38164de520a3bea82b91f67d36bbd87877b5be7f06c2d26b2dc747a26a51f51fe293197db0e91e6ac617c71ddc6edfeb7db8f067ac2012268deb7e5f00a640c1bbec5c4c71f10f921071308cadededad5c90e72d744d0bf790b043fd35729570889ebe5", - }, - { - length: 682, - nonce: [3]uint32{0x17cebe90, 0xeffe259b, 0xbdf9d4ca}, - key: [8]uint32{0x172d51e8, 0x5b80f5c6, 0xb9c9e438, 0xa56119c0, 0x62212323, 0xf5386589, 0xde7079a3, 0x669e643}, - input: "0aa4fbce7e1774f0607e7ea01fc0e6d210bb283964ae75e180a9f6ff3d2c4d50914bfc32bca6d243eb33551521d54d66f377fdc1d31974ece79b157905ff7e7a9b064f349727ce37c83c15ae13df635c3e6b4baf994d9aa0bb90b06c6cda51deefda72c97a2993448e654b746b216d2b949bff1af5238558205cfc3162f1d7a020a919db4d4eb44bcf7b269d4df57e24133d1e540694b9148444cee16e64035ef006a6079dff449949c1b342991f2a27f21c8bd74ccf4bc944284a46e9fd9f9bfd4b95f80c05553950fabbf5e5aed6babb8427832266aa4d175114de9127ff6ee848534d6dd5aa6d2dc361319863cdf32cfb1b074faed17d368964393352df01fe8d86af0e994bc9dac315f7d9efa7bef47a16676cdf17a535ae71d399c4c11a3a3ba0491e8d41f419685258a4ec7d1ae588b3ca341719c0827ce5f5a653959a8671844f2d0293c09bc7d35497ed18c160fc7b6d073a311b621a7a37f7ded1df3d73dcba1821278c9e17a191997fa4dab0802e1ee1b468e91e4272c4569a17dc0b2805b980bde798640aa328a3605abea1865083d7446e960c27f69d32882a2a2295efc9c440dc203872373411925f8839715e9441d31dd9cc14bab09a3e03b4a63e14db3039d58725796326ea6327f189beecd63955f1409467c81f4691ecfe9f0ac5234f23dfb84e3199e415ee7b4f67189e8857ff6cb3f64c2ac1b554bfbd679a6ea8491cfd69d96d08ee2744d9103e0b044212560ff707974b1a9043e1f2c3592828fde8ab5e993652c00e2b3fdb19082611b67866ece6c4a2635f87e04d2136d679f632416b03ece4d7e9406f3437163f4fe0c8cc7b87d487f6de3b3022665bcafa847c2b9199e1ba9af7deb0e29b66ad41688d03a8369416dfbee6d03526adb3ebc4b4f8531d73589499a3010b5309e9d9d2f5a9cf347983a92722dbf6c4f0bae8aba57b37d322", - output: "a31f9a532f35f20ba604a9ab9989260e5a4ed04e6ecfa1cb9e0e1d16943906acbbb4e761a2bebc86cad0ce8b3f26d98b455e4b0835eb8b43791cea29fe8fa6e5187b60198142059bbce98917aa2957ae2555bee70e6e9e21ff6197a51ac2ca2952c413efec4d9903a2f6883e88aebe7ca8316831f6a8f2cd0e486319b58dc8db862779adff98b7f35c33faa53d56acd7a81e0feffc286b728f3a11afab7cace4c30b1a45780276b1f0ab89242410d07cb1191c7b9da5d09db7c9a729d91ac3ed82f4350f2871a12d125ba672861d1b0af7219c360a0e023a8b7c23fb9d72631c72e032c097118d90e5db0576586d8224165a8376fe8d04de93516848e7c2653cb4f7d24a971ccf4f16c527ea5b4153fad5fd5bf473b15806671854507bf1a6d9e5fe4a6f6ec977197d21d69a041dd955e199031f895adefd850c8b0ae327ba0c18ca1783560e1ff0feb2f659137e34a91e9e9ff04fe3375b7db6e4326986e6265e5fef00297f6ae627c7563846e531762748fe8d0b6baff17acf1e6c5cfefa35a95ef634ff96f83f16342a6c62311fc653d314f8a6de109356ab7801316e69a48834cb6325816b1f66d5c67d6e9c9cbc8e1a0521fd6e4bf77a7d2609f99c9579e143f530677b99d198a97620d087f058edf35eb7271701ecebb8bfde5671641ed21aeee9e7db06b932e0def91be93cf2955159e9666c770cdffa03886eb6e98dfca8f91ff5cef1927c0f82b9226d65c68d011416cbef802c264e34244ead7a6ebbe28a510a37e1276f4f3cf27a3944a08aaa23bd321092761627dae20dc269b6150545c75e995cfee0a9bcedb1ad8b364beb8839fd5c9f7984fa0a08a1a354aebe18f62acf6d6664978fcfda2ce6fc16eaa2cda5b835339001b3b98d3a407a3e18e0ec2da6ee3d1448c1ece2ed67c3f51f01e76ed59f0e61102b103a3c65aea94275e8d1f0d331538efe", - }, - { - length: 768, - nonce: [3]uint32{0xb1c9bd09, 0xdbe6497d, 0x16c73b95}, - key: [8]uint32{0xbf9d9e5, 0x2eede668, 0x631dca95, 0x4233e36d, 0xd83fe644, 0x99b11f89, 0xef055717, 0x1ae9695f}, - input: "e097b1e8dea40f63714e63ab3ad9bdd518ac3e188926d1086a9850a5580affb592f6e421abc617c103479ba39a3924eea1c0bbbb051614c4b5003bbd5fcbb8093864fc1c130748194d6b560e203b889b98b574a98ec3e0e07cb2d9f271ba7794e5419123b4f2ebc7e0d65cd404104868905ff2c38d30c967fe9d77ebdd4b8fa836c3b0ad15e3e70e9a28236d5593e761e694b047f63bc62c7b0d493c3e2528c8af78f56725172ac9416ec2bdc54de92b92a63f9ccb61e686f9249c7cc337d99b2160400bb5535eb8f8eb1e3cafcbceaa821c1088edbacb3b01b5bed977e702de747ad00268ffe72e3d877dd75816db65b5459607cd1b963fe43bf2405ec223ddc0de514d59cde74f7522dc72285caa3eeb7eae527a7723b33d21ce91c91c8d26bf36eeb1dcdfc1e9e475c1565ed9c7e64ef601874a4f277280a5ceec26717e9385aee8b159379e3feed7952b87240c942970d63351259aa7a286ddb4a2620fa67565c92f592902e49422f1eecea2f44d1c0bbbf54a9e5612b86a9549aa3e6639a924c7bbe2d3c1b5669da73c0e2c6f6f6084f54a912ad2635d0141c2f5ac925414dce0da09ab8f86eae2a7b7e48741253189e5fd554d5c04d9807ac6ffd8a4f8229a3e8ab75ca5c778bd7ec5a5c02085faba9792cbc47f9e9311f3444e6544359769e1b3eb4d42ac8923ec94536e1a44497766b5da523f5763749dbc2738dfa8e13c191dfeac56c7614a96bd3ae23e4e6e5ac00be851ac9831108989b491eaade62113c531385ef3e964ce817c8ed0857adca946467682c2f4387fab2f31ce71b58370853171720268459588d5d216faca58d0bebbd7cd83a78445d9b49e83ec2cdb59b5d760880bf60532178d60372752b47d52562b316c7de5c74af9cd588643002d66bc6260595a540d2f82cf2c07fa64e0cdd1f79877b6a25b0608c735a7d35ca10852da441fcfb31061fd7e482a0989866f9eea8b0b39c3d519715c1c2766c3ad99f041143cdb36557ed647403458155dccbb80c3a365f0a85b1135695648ab67ac76b3d219c7b77e49d735c72ac947b1d7eeb279beb9d2602aba7b36ca", - output: "7b6e07e6415660affba56047b988f4548b308e7a642c76791f5c3742cc4cb744cde48fc30e50d458084e06c6dd29a52cb4c306a69a493a17c0838d14b107d07b81c983a2dbad09b80f087ba48465a8beaae5b16e8093e17cfb9e84ea3bdb9af00889268a5c01ddf25af434de56f65882322432aa275fac8519e317ef4d89478f29182143f97350983050f5d37c4b518611da6fa2aed7bb73e614231a194fe17c9073e377fc6ea0aa491e15ca54808e0536c8c3f1bf657283f807ebfc89b55049ac8fb86f89f17974fcf0afc1a2c690c0442842d0f4af9ee29dd960e499d1077bfdad4c0c9189a6e83799bb585acdb853c1e99da7ce9c7eeb9bf431f8d364d0ea80b0a95a7807f196c6ee69fe90e6d1f5d23e5cb256e37e65826d7a111f2272884d6319f968580b3164b2697ea6556816cea3ca316651fe2fd68dfa905d080c28622606f7d24da216289fa2c54c6f42dc244ecb047512ace62f0801f2dfad8f0218f45e2b3bbac97c2176c842398b16dfa1fdfc9a68b7b5a1e785d2a0cc592bc491f5a69c81127b758ee02c66b81674d3135c5882d1dc89dadcffa06f4b0644df5c7fd65c72611d79be7ad637edd6fc38b39946aa2a2c6d08ca9d3ff9a8ffe2e7989546489539b1a623fa937c468e59e0978602526b4367de277526895aa222fbaeae2084f418c5745d8ee844da0baa47f592970c14cf710f49539c12104a62baddb3382f5773dd18c83ecb238ae2e749a51584a38e394ebadd175bf5c3cec787907abb1d94af70ae63d3b7d8d5ff254da90b78ec8fe2ea95dfbc6e3e69ecad856c9e54906df8fe39859f2014b74dc3ca0ee2a957001939d37a6c0b489bd3f1658b835a57b24aa282c23e875c9e67e6eb8b32fe44e7d7d8e285d85da0ce1b53990f9fdb5e2e74728e433ed2c1044df9e89cb9bb316c39fc6fc8bcc74a382093926a288170e857d6b7f47858a4c2d05c74263dc9e8199332d0179687f4a4cdfc80ee6737300cefba75905b22d21e897f887b67aa3051877fff11d98bf96ca5091bb225bddd5eae697f3dfb0efcdb788ebf6694b5b39dbb0d4bf9427382a3a58f0b", - }, - { - length: 828, - nonce: [3]uint32{0xc7e503e, 0xf8110ddf, 0x83316c8c}, - key: [8]uint32{0xfa2d1cd, 0x4fe7f905, 0x2b9e4c1b, 0x115bc881, 0x2922bcc5, 0x3f60aa25, 0x13c26d31, 0x2096af63}, - input: "0a1064714f20d9e47fe53250ecfec759f4137e60afaf65755f4709a483504c3855833b6dcaf7aa0180fd735fa9a73d46697f6c45004adf12452ea4c04a720fd7c20b9783b74b8b3ea0c8b1563d5a85f44af8afd7d91ca6298ca22642a684f66e365edd6f6bdb2dd32dfa13c62dc497fb341b86f65d40655931171416e23e3b2623c0b4a67d448877b6e3d4e0fe284034a10162b2b5e21639047036874f4bcde22b145b5f18aa8ff32dec81e6a5ac68b3c30c24bd8fd3b8e098a1cf202e2ab2a3bb66a9393222b9f7384653cda7707f00bc3c81e9591fd040a07d3629410c2db78781a4c9db3df5f9d648162f1b087974f56a89db07aa21ba827e3864a1618945b2fba06853a13c35da2909f5013feb313bae09870b8eab904024adab0d6ac46c1a1499791b47413139dee59db676949b9e9ab8d3d6abaa954ec2a9fc83953c91b483c3b6bd6700b96484850734e72e3710a1b379c0d0698aeaf68f13a0d317bfd689471e3299288e7a383a58522f0daaff210cc4917fa05f0b8ceefc2afc46148a05a100d30787accfb4da094e61ea6b58f132692aedcabae928e53c2594b01507b8fc2d0a85a1d111d1f4de0b95258281ae01873a72606753b6f878ecd8c4f613fb3477710d260f0bca0d4c06f675ab7113eded395f88755a98a0ad22b4a002cfe9447c4e39eda13738f4eccb9c13367ebc2878257c4647d31b67e5e32b6a77f23e9593658d19c0a40e8a7228767afba1cf23072b013b2d76ee66e42b57bec2797ce3619c695a661004c8129cb5c5d6a2836be22483f3b7e40bf8ac5535bf6cd065c4821a87829948c88163cfe3c0f60cea4e7ff59df4cdbf80064b2d664b39487413039999b5e86f1d467b12682d0cd355e9f7cd980e87d584ddbda89f68632d3b8fd6bc3b80205d7feb97a46842b093f74aa14bb21accda7474247b5e39ac76ef75e9b5b52b6a829a7e2297ab88fb0eb690d54ab1af2d7437149a6202035ce15f1e6c6267458d62677c263d83d3f8119af191b7d766582620e0f08b411c996c25ba6a32c2d73f592e789ed662e94103329bfa5e6573f1116ec04438997f3e4ad91b4123b570743455020d914bde2d8417fb24671e6db261732fb89dda1a36614b095529e4f97374c9bc0e55aa577bfffa663c816ca9fae3472e0a", - output: "b00a7caf5359c5bcebe590e6bab9aa03370050c55cbd45a257f4869937e922a15f2d38121b1493d6b5dd4a8a47d7b4e5cb049d396ad84ed421df774b0408b6939f18ebf5cf83f48c540affcc2a885967bf4bd222c42904b8a73c4185bde3f97e874fad25b46714235e60c9ff53ed2975c9c85ebad0752249e4b627ffa41555eb9074f63a5f7d61d207d2ce11b2a9fa23a13a0832eccb91efa2afd8d9acfee94ac78a733fa156bfea5006da1d0127c32aadbb75c015b68c627903e1c85bf3a1a9f99c6cfbdbb5c871f7f9661b78cf5e16d819f53e9930e201d4f58e69bcdce77ec5b9b1d2cf206a71f744342273c26b9abc71303c20df3d51f52222893d803fc8e0e0afcd99ee1c7f95b48680403566f7f9e296d7ccc0ec348b6ad515af58d11fd82c628ea29ee6a5d67aaeabd8823addc01a078b04313af73105d4ce4abef8e6ee8ce649640a19678292d4f1017d121549fd2c19ba6cdc0b613e512bc9551d759c6d38aea7e35c0847a142e273a16bb1495e652f9668b97801ba3f6d9931c0a1efaa4452e15732dca1ca9cb45ed289e0fd08d1cee1cdcc9dfba8d0b2562b0b1a180f4ee69d63573222c8d4789bf0d63d2a201a70c7b27c84e620e33e8a863cf49b784269a51ead3d4ad26f044d5859988d5485a11533ea805f5a8f6313caa6b421071a34f57170fdd8e4663e9a4cdcdcc1ddaa9f6e651fb365cf827667b018ae7d028c7f96295b2b4f9eeb4b361b48af86463a79f50b107ab0935e3cec3f4f203cea801ff95fb870d2c2f0e315dc8a6a547dd3c390a1f5403917315164bd2d40362489b389a54e8dc0ddb83e6a43a26c65923e6f76ee0ee0e3a33b0a9066620a01f0319e20b9f1beb3910ad962a3000e6aacb0ae57f3f6c5e0315be5de93edcf0e45e0e47332f9daf7f33e6e8bf1929910b78b8f88ca12bf5519a3217b7554c8c8350cc314561d580bf67a3878e3979430d070121a5e070a3458742e8549bda972f603222e2b30eb8a49a955805307e6e02f8c60a08188f69340e116422458d4a8841f46a78c833b1a822e3f6c9c97422c918f17c36175ca4b3d1c081ee4b175b4b07bf101c3836eb5b9e3cbd08a89b4a1c50edcb41ea8ea6ceb1532f5b842715d50dc21e2499e08c373d3dedb96bb477c8802ab7aa957e0b5810f38", - }, - { - length: 859, - nonce: [3]uint32{0xeb02dac9, 0xa7cba06c, 0xc24764c}, - key: [8]uint32{0xe9414a57, 0xd5e29546, 0x1a5e2f4c, 0x806e4c46, 0x48098d1f, 0x4351ca1a, 0x53ed97c, 0xa6a495ca}, - input: "00fa3b13b5cfa9b5d65a41cc2d3c420518802c22c4582873f1ad52a22032d2cef7c975078b199787e852fb1f914529f60d1cc854e5d6d547216dce043e0fc94866bb2193343c3a07fde60e668266d1cee3067c6f2ce0f9f63456ad08094b6c7f515f7ca90caa96494e2a6835ba1f3f166012ad1ff6af6b5f8455d5c26e72402966af9066ca70ad027eed23b0eb02c751195064a62283975efeb29bc5993f83360d012a2f5275ac758a9e8fe458fc7cc0673e6b9e338678f0faff60a67fff3784c3054dcbd95d1b00ed4c6156b3831cc42a2ccdeee55541f228b88e6c318e2d797c6fc035ae12868c4a4e3843b5b25a530b1477dec3f5ac27644476b5766e0ee132d833f9a63200eb0980bf72c3666150e567e01e3e1f469cf36beea65946fce714a3f354983e54ca4315b57ea35c5f48bd5eada05f49db1004cbb39888ebab3afad62f6509abad77ca8c4ff28731c7ae545e6876c8f4a80b6cc26928ee05001a9764694b52edd605e182d5a3a5fd192bff58aba90f57e4debe612d02cf6f08af33a78ebf8823bb3eb46d4da25b7dfa15ad436c380633d3db3d0dc4dfec6c2324d105e7090e65342b554854e777b40b5dab8125a58e8b212364ff88459a8466ff5ae661034abc8286a78ad5aa582e2dabbcd7a0b0cedcb9fd5f0bb8c3bef9117f2ca6520a72b94e528c1a4a464398e654995d5f4c77cbabf2b204b96a058cf1b38284b34e41ac37b05a003ed51be9602050f21c6b9326714bc425c1e22833da95a6e77571691d4dcab4ef9056c4c7f85d5b445b902eb375b5164c6bdf629ccfd4127a6c024bb6c4da0b6b08350432e58f8229e04e2e76f704be17d36e0c04fcc7a98f721d4572aa7f66ae8e9664300a189bc3862da47b60c8b33424f6d577cc10f4755f36c2a6decc30ba81bf48f96616ccfcfb74965d6bdcab82728bb224c560d1cfd7a175413ad1c14c734746be3b062b4e7514e9075c688103515e32e3335dbd272a315024d56f4ecd354264da9bc712080657b2b51b06dc7c4c441d9858935a4c3e6b207bde38ea83bba4c6854b2bcf914d758e0a174c0528e0e385c7cff355c38db1c22440369141e91266824c59f1ed23e7d4b99d31b0baa7bed4526e24259dbef5c9ae275e97267b756645f804c274d65ac7ab0f7683435bc2e4f24075cd1b790aa2b53fbf044e8f2092bdf0dbe88a582ff8f8de291e8220", - output: "bea32587095caac661c3ac49e65654b282192b2addf5b9a403aea6c8bd0096291a0a66ca4062acf1da91fb5749952096ec63ab652ecf94c29807f0aaac939b6896edcd6f0cd8dd8d208b906ef4d7a8766831fecd6ce98f4ea0c34fa9a5114dbeb23c2cd6d3aa962e39b18cb343c24e65d49fad0a0fb50736f8d2b24b011108932484399f4c4510ac9a5e6bc78ff0b450e67f87b49f253b99d95d6294e15a9934fc8b89a5913c08f75d3516766fb0f60f82e2b2647b4619991c78adbcf548c07c0dda30c629349d84f298313c3e629e03760b1cf860264205a950d6fd86732a6513827f72c0dff5aff96f7203464f60849c1065beb70f282cca1334f6f6c767dfff94f063361f592e85597de5d313eaed17bd533db24818d9ba9aea2afa797721fbd19eea7b8d46bbc4b9dc0164636d2e754f5e9e8c04e2a381096331731c645ea1f613a37bfa9a6fb2c6307e9bacacbeab7f5672163ff9742a8115049bce0269d7d5f6f35787be031dbee1535b0516ec0b46d12f5833cde5f2cc569edcdd20993e9776aacf48ace7bfadf79065f2803fba6b2b27aa622abb7ae023ff2b27b727f509f313f92026392485a5ed4fd53b2e22b2d2dc1538ce158d34921214638be30ae054a0f5f1d4f9c590a2d215ac2a5b23ed33871ab26c8bb6db7fe9d6f51e527c9547248a4e9734c64658b22893f4f6867a35f18e2bbfd7d62142025955cb51af8e40b6fcb91c7e959cea2c92022c87c29dae107a306f41b00e73c7bceef8cb070e8f9e830caeee463170e919cba6eee63092a5a7ee33b74db09cdd022fdafbcd5d524253a29a103ba6f4d668d31d18f867557871c0e0258221c3050d57c18bdae4cc4ff8da0daddb5c08619be127ee76a317b59a9d8e67808603a1bfce6b4e0d070082b283bf9c0e6ef8256208e482f3e2d1a40d30807f60a868e2279dfbc3586d44ee25fdca3505cd39fd469c2cd03bc2f921d22a8346750f346c919e7247301c1c8a4a3ddb8eabc6e80d85cd2459afe1cbb4851ea2c86b8075e0fef3177cb074894410ecf681242fac62b5fa4ed3a10ddaa595427851d376cf69e350207b667f7aa26d003f1ec739a8792532ebd93f3cafb1fea40d227bcadda2fb6da794cea3371240f257f80b1b8a857ea453b46938397c1f4b303a46257750003a60666a11d03bf2afb5c71e059933d617288891733b63784bd9c662234f", - }, - { - length: 985, - nonce: [3]uint32{0x3c2b47a4, 0xf614c813, 0xa26f7014}, - key: [8]uint32{0x39bd3d18, 0xc9aacd67, 0xcb5485b5, 0x20536a22, 0xbb22ac87, 0x1c9da580, 0x7d996b2e, 0x456fe461}, - input: "01847d8a97d56e55e12f89adb13c8c0f9dea5555e8dc61171fbb8e181f6cf846a4dd68b2c75335c0896fa215bf7f9eb7e398e4520aaaf33461ecfb61051f43d43569fb75fabd79d319bf39469f951e4da7932a74624c46d8d26a9499c701c00d3dea57a6f65b4c0f33b568d13989340294d17cd005b26d89cf6fa1c88e7b6ef4d074291fa8c117ae05d7c785459ef4561c45af63a811e9aa1c31b69a5bdac2356d955a0f579791247a757a691b3de447a53619878397cd82a74053f06da3574045bc856500ec01fd2afbc64d8dd283ac876a50e9396f78c424ab157f481316fd9c90cd899f5aca46dad32c68f1d64ea7f1c4bdb994ad847072609bd89adc2fa8382a5d573b680533640b8321b6adf27926274660b2cbaf04fbc9a4fb17ce8957c38c7bab1aafd5bf7263171e47d2e1ae5cf0494815642209d303dba561754479c24ea01a573c9083b68acc49907b1748924d3c6a82feb9417ca932578c123f9db35521c0d992565f7396f0c23e436289c1720e4e7c6e285c04a8159f93e06801334e523b18fe188355cc6a155febe64ba053e6b5d1cc87787fd5ae68fa86d8c51868b9f6a9664cf0d56aa6cb8463362bb671e6b8423bcbefe2a1a0acba3f135496736b5cec5e329494af46aba322bf5d1cc108c98298459558773a316e09b0bb960a26f4b0bfbaa493b5f98a0e522b6203c471b10e662abe9b9e60de2a1517843933add02017fadd62608383ad53796159f3d21b2c8ed7295802ca79ea65d550114ca2bcc7f7c3b4c6709fffc3c2de00da06e83d8f0cf04b8c8edd21c0fc11a0b2aa7f6adad255fef25e5c0a9d59546e97446e1fbf6a51a8ea6cad54cabfdd19cd10d7d33ff0549b710557e3931821dd8809ab0a9d3aaa761a01ae0f2e378906672924d6a1b12fb1cca7bed41f31974b9917a05de60c32796f502e7035a2c01cb49bc8e1734b9fa138b81b4dfe19d37f5942dd1b42f03e1e5a6a046ecd457174150e17dd148e4bfea44b72da35ef42a7251244700e59e702033677d42611168fd246e1b18b9a464b6c20fc7fcf6360cd00466ece059a69d7d54a4f5565d08799f85dd3c849a08ba43415077c1c0e5dbdba52bb3167ee99a11db551f0260493be1dde58d2072e8c02251f4f574b6e115cbb6136dc2c3fbce75fdcefe812d9c07a91a89088985a52cb1fb9f6cef80fa30364706414175e42c75e8e37f6e7cd028c99f59caa88c49db5b46e8d6301bc39034013718a9eeef5506415016fb21d70e46a03b4c5ba72f91dd9321ff5e210e5e5f7b0723a3bc4bb02b5a74c1f4a63aa5a993a31f79a768fe8033c9abfeb4deb536af1054be02d8d1c4a6a0fa75f3eb787d57a03b7ae994fb1b54b2c43b230ce32e6245d944b3cea4fa6", - output: "785dbea5d1e50af4743ed5fd2209e441fc7c50bc7f6fd9cc7f24654c619e2606178dcbbd81a1f94c1b3176837024098bd31326145be326b32fd9277a55a6fb38780c8dc8b471a3184379d90da4aa87d80b889b1f4d8d0755c1704a526b99ac829b8ad157ca54b2b05ff8b2917e27b0c147ab54add9a89fdcad7b93ba1fe2d5be9de88b68a5324f1b42943e45ee31c4ef783ec9e2337b3f2834b10cf452b313fafdf0c03719140f64060da0a565e185cb8e544e1c185ca230ff2321739a285abe8be4be0ce76678a7b0902a77a645194de49fef8ff64cc464ea25e1f1d72c775e450f08ddd7680d27a4142879787b198583d93b84cd87fd5b4063d92d13d9c9cb580c01fac0174686a18f64e6fa0b3589624cfae04aad74950559bdf92b2b199c60cb04013aa0ef56d1f9ec5b7e968f6a83756ecc9cee7dd8b433f64649f948df5474a64549e71e46fd8bb16568d21f5fb67f5ed555f2b8aec4709383e8cbc45b9fe47c0434178ad4c6d0d42606d6eef0e21d0370898d1d5d646830a88d5f024094fe9c7a2003ca13d20ab7cd748dc11a22f578ddab416f3500eff3d89fc177b46436108e2e2c7973910cb8454a01c9e9b98f966848325444b2ac205b1ed6919fa76aaf63717574761b7f62b10649357df49f85a845a30b6acd57fa202fe58673930ec59399f537e9682b1f5f6f409988789a8e0c1f803478dded14b40d3b6eb3109758efeb6a7fe21f41c4dcc8027258da27ad74010839dbfdf8fe55050511f85c321e653f76e55f22248f46da529a380c6b1a16a19ce73af9715545c2cae098dc42dd61248dbcf7b295f4dc6b8930b41baeef677156c534869be65e723e1aa0336e8be8a3b138f840c9cd63bab6d9d61f239a47d8cf56258544e6ef65edca27069f7a57f087a7cc021fa1294b75c0c0f1093c025e426e4f041ed5187f358402676d5da5fb6ceba76a178f65c8c3046f258531c165b8808bdd221c59ff56e3e06247576e144aac01ea96a07f1be15d7a2b0b3b6c259a9133f8a50b56154ecf9f61022f470027247e6e70e6eaf7ece5e324ec8f95667ffed10337652b119e7cb8d197e306e81ea251340b9fb2c33aa230c0a16e1ca783f9344b3acbf413acd96616e6d477dba90e39326089934bc5ca6620855cdc442e25bf8b8debf335e16e7e25cceb68659cc81b13a507fbd9f30b347126beeb57016bd348fe3df592d4778011664a218227e70d7360d139480500b7f6f84153e61ca4dea105875e19ce3d11a3dfd0ad0074035ff6a9fac0ece91afd8be74c168da20c8baafcc14632eb0e774db758a3d90709cddf0266c27963788c35a842beea8ba2d916234431efde4bb32fd7e1cef51dcf580f4697206bbc3f991f4046360aea6e88ec", - }, -} diff --git a/vendor/golang.org/x/crypto/internal/subtle/aliasing_test.go b/vendor/golang.org/x/crypto/internal/subtle/aliasing_test.go deleted file mode 100644 index a5b62ff7..00000000 --- a/vendor/golang.org/x/crypto/internal/subtle/aliasing_test.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package subtle_test - -import ( - "testing" - - "golang.org/x/crypto/internal/subtle" -) - -var a, b [100]byte - -var aliasingTests = []struct { - x, y []byte - anyOverlap, inexactOverlap bool -}{ - {a[:], b[:], false, false}, - {a[:], b[:0], false, false}, - {a[:], b[:50], false, false}, - {a[40:50], a[50:60], false, false}, - {a[40:50], a[60:70], false, false}, - {a[:51], a[50:], true, true}, - {a[:], a[:], true, false}, - {a[:50], a[:60], true, false}, - {a[:], nil, false, false}, - {nil, nil, false, false}, - {a[:], a[:0], false, false}, - {a[:10], a[:10:20], true, false}, - {a[:10], a[5:10:20], true, true}, -} - -func testAliasing(t *testing.T, i int, x, y []byte, anyOverlap, inexactOverlap bool) { - any := subtle.AnyOverlap(x, y) - if any != anyOverlap { - t.Errorf("%d: wrong AnyOverlap result, expected %v, got %v", i, anyOverlap, any) - } - inexact := subtle.InexactOverlap(x, y) - if inexact != inexactOverlap { - t.Errorf("%d: wrong InexactOverlap result, expected %v, got %v", i, inexactOverlap, any) - } -} - -func TestAliasing(t *testing.T) { - for i, tt := range aliasingTests { - testAliasing(t, i, tt.x, tt.y, tt.anyOverlap, tt.inexactOverlap) - testAliasing(t, i, tt.y, tt.x, tt.anyOverlap, tt.inexactOverlap) - } -} diff --git a/vendor/golang.org/x/crypto/md4/example_test.go b/vendor/golang.org/x/crypto/md4/example_test.go deleted file mode 100644 index db3f59b1..00000000 --- a/vendor/golang.org/x/crypto/md4/example_test.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package md4_test - -import ( - "fmt" - "io" - - "golang.org/x/crypto/md4" -) - -func ExampleNew() { - h := md4.New() - data := "These pretzels are making me thirsty." - io.WriteString(h, data) - fmt.Printf("%x", h.Sum(nil)) - // Output: 48c4e365090b30a32f084c4888deceaa -} diff --git a/vendor/golang.org/x/crypto/md4/md4_test.go b/vendor/golang.org/x/crypto/md4/md4_test.go deleted file mode 100644 index b56edd78..00000000 --- a/vendor/golang.org/x/crypto/md4/md4_test.go +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package md4 - -import ( - "fmt" - "io" - "testing" -) - -type md4Test struct { - out string - in string -} - -var golden = []md4Test{ - {"31d6cfe0d16ae931b73c59d7e0c089c0", ""}, - {"bde52cb31de33e46245e05fbdbd6fb24", "a"}, - {"ec388dd78999dfc7cf4632465693b6bf", "ab"}, - {"a448017aaf21d8525fc10ae87aa6729d", "abc"}, - {"41decd8f579255c5200f86a4bb3ba740", "abcd"}, - {"9803f4a34e8eb14f96adba49064a0c41", "abcde"}, - {"804e7f1c2586e50b49ac65db5b645131", "abcdef"}, - {"752f4adfe53d1da0241b5bc216d098fc", "abcdefg"}, - {"ad9daf8d49d81988590a6f0e745d15dd", "abcdefgh"}, - {"1e4e28b05464316b56402b3815ed2dfd", "abcdefghi"}, - {"dc959c6f5d6f9e04e4380777cc964b3d", "abcdefghij"}, - {"1b5701e265778898ef7de5623bbe7cc0", "Discard medicine more than two years old."}, - {"d7f087e090fe7ad4a01cb59dacc9a572", "He who has a shady past knows that nice guys finish last."}, - {"a6f8fd6df617c72837592fc3570595c9", "I wouldn't marry him with a ten foot pole."}, - {"c92a84a9526da8abc240c05d6b1a1ce0", "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave"}, - {"f6013160c4dcb00847069fee3bb09803", "The days of the digital watch are numbered. -Tom Stoppard"}, - {"2c3bb64f50b9107ed57640fe94bec09f", "Nepal premier won't resign."}, - {"45b7d8a32c7806f2f7f897332774d6e4", "For every action there is an equal and opposite government program."}, - {"b5b4f9026b175c62d7654bdc3a1cd438", "His money is twice tainted: 'taint yours and 'taint mine."}, - {"caf44e80f2c20ce19b5ba1cab766e7bd", "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977"}, - {"191fae6707f496aa54a6bce9f2ecf74d", "It's a tiny change to the code and not completely disgusting. - Bob Manchek"}, - {"9ddc753e7a4ccee6081cd1b45b23a834", "size: a.out: bad magic"}, - {"8d050f55b1cadb9323474564be08a521", "The major problem is with sendmail. -Mark Horton"}, - {"ad6e2587f74c3e3cc19146f6127fa2e3", "Give me a rock, paper and scissors and I will move the world. CCFestoon"}, - {"1d616d60a5fabe85589c3f1566ca7fca", "If the enemy is within range, then so are you."}, - {"aec3326a4f496a2ced65a1963f84577f", "It's well we cannot hear the screams/That we create in others' dreams."}, - {"77b4fd762d6b9245e61c50bf6ebf118b", "You remind me of a TV show, but that's all right: I watch it anyway."}, - {"e8f48c726bae5e516f6ddb1a4fe62438", "C is as portable as Stonehedge!!"}, - {"a3a84366e7219e887423b01f9be7166e", "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley"}, - {"a6b7aa35157e984ef5d9b7f32e5fbb52", "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction. Lewis-Randall Rule"}, - {"75661f0545955f8f9abeeb17845f3fd6", "How can you write a big system without C++? -Paul Glick"}, -} - -func TestGolden(t *testing.T) { - for i := 0; i < len(golden); i++ { - g := golden[i] - c := New() - for j := 0; j < 3; j++ { - if j < 2 { - io.WriteString(c, g.in) - } else { - io.WriteString(c, g.in[0:len(g.in)/2]) - c.Sum(nil) - io.WriteString(c, g.in[len(g.in)/2:]) - } - s := fmt.Sprintf("%x", c.Sum(nil)) - if s != g.out { - t.Fatalf("md4[%d](%s) = %s want %s", j, g.in, s, g.out) - } - c.Reset() - } - } -} diff --git a/vendor/golang.org/x/crypto/poly1305/poly1305_test.go b/vendor/golang.org/x/crypto/poly1305/poly1305_test.go deleted file mode 100644 index 256bdbba..00000000 --- a/vendor/golang.org/x/crypto/poly1305/poly1305_test.go +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package poly1305 - -import ( - "encoding/hex" - "flag" - "testing" - "unsafe" -) - -var stressFlag = flag.Bool("stress", false, "run slow stress tests") - -type test struct { - in string - key string - tag string -} - -func (t *test) Input() []byte { - in, err := hex.DecodeString(t.in) - if err != nil { - panic(err) - } - return in -} - -func (t *test) Key() [32]byte { - buf, err := hex.DecodeString(t.key) - if err != nil { - panic(err) - } - var key [32]byte - copy(key[:], buf[:32]) - return key -} - -func (t *test) Tag() [16]byte { - buf, err := hex.DecodeString(t.tag) - if err != nil { - panic(err) - } - var tag [16]byte - copy(tag[:], buf[:16]) - return tag -} - -func testSum(t *testing.T, unaligned bool, sumImpl func(tag *[TagSize]byte, msg []byte, key *[32]byte)) { - var tag [16]byte - for i, v := range testData { - in := v.Input() - if unaligned { - in = unalignBytes(in) - } - key := v.Key() - sumImpl(&tag, in, &key) - if tag != v.Tag() { - t.Errorf("%d: expected %x, got %x", i, v.Tag(), tag[:]) - } - } -} - -func TestBurnin(t *testing.T) { - // This test can be used to sanity-check significant changes. It can - // take about many minutes to run, even on fast machines. It's disabled - // by default. - if !*stressFlag { - t.Skip("skipping without -stress") - } - - var key [32]byte - var input [25]byte - var output [16]byte - - for i := range key { - key[i] = 1 - } - for i := range input { - input[i] = 2 - } - - for i := uint64(0); i < 1e10; i++ { - Sum(&output, input[:], &key) - copy(key[0:], output[:]) - copy(key[16:], output[:]) - copy(input[:], output[:]) - copy(input[16:], output[:]) - } - - const expected = "5e3b866aea0b636d240c83c428f84bfa" - if got := hex.EncodeToString(output[:]); got != expected { - t.Errorf("expected %s, got %s", expected, got) - } -} - -func TestSum(t *testing.T) { testSum(t, false, Sum) } -func TestSumUnaligned(t *testing.T) { testSum(t, true, Sum) } -func TestSumGeneric(t *testing.T) { testSum(t, false, sumGeneric) } -func TestSumGenericUnaligned(t *testing.T) { testSum(t, true, sumGeneric) } - -func benchmark(b *testing.B, size int, unaligned bool) { - var out [16]byte - var key [32]byte - in := make([]byte, size) - if unaligned { - in = unalignBytes(in) - } - b.SetBytes(int64(len(in))) - b.ResetTimer() - for i := 0; i < b.N; i++ { - Sum(&out, in, &key) - } -} - -func Benchmark64(b *testing.B) { benchmark(b, 64, false) } -func Benchmark1K(b *testing.B) { benchmark(b, 1024, false) } -func Benchmark64Unaligned(b *testing.B) { benchmark(b, 64, true) } -func Benchmark1KUnaligned(b *testing.B) { benchmark(b, 1024, true) } -func Benchmark2M(b *testing.B) { benchmark(b, 2097152, true) } - -func unalignBytes(in []byte) []byte { - out := make([]byte, len(in)+1) - if uintptr(unsafe.Pointer(&out[0]))&(unsafe.Alignof(uint32(0))-1) == 0 { - out = out[1:] - } else { - out = out[:len(in)] - } - copy(out, in) - return out -} diff --git a/vendor/golang.org/x/crypto/poly1305/vectors_test.go b/vendor/golang.org/x/crypto/poly1305/vectors_test.go deleted file mode 100644 index 18d7ff8e..00000000 --- a/vendor/golang.org/x/crypto/poly1305/vectors_test.go +++ /dev/null @@ -1,2943 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package poly1305 - -var testData = [...]test{ - // edge cases - { - // see https://go-review.googlesource.com/#/c/30101/ - key: "3b3a29e93b213a5c5c3b3b053a3a8c0d00000000000000000000000000000000", - tag: "6dc18b8c344cd79927118bbe84b7f314", - in: "81d8b2e46a25213b58fee4213a2a28e921c12a9632516d3b73272727becf2129", - }, - { - key: "0100000000000000000000000000000000000000000000000000000000000000", - tag: "04000000000000000000000000000000", // (2¹³⁰-1) % (2¹³⁰-5) - in: "ffffffffffffffffffffffffffffffff" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000", - }, - { - key: "0100000000000000000000000000000000000000000000000000000000000000", - tag: "faffffffffffffffffffffffffffffff", // (2¹³⁰-6) % (2¹³⁰-5) - in: "faffffffffffffffffffffffffffffff" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000", - }, - { - key: "0100000000000000000000000000000000000000000000000000000000000000", - tag: "00000000000000000000000000000000", // (2¹³⁰-5) % (2¹³⁰-5) - in: "fbffffffffffffffffffffffffffffff" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000", - }, - { - key: "0100000000000000000000000000000000000000000000000000000000000000", - tag: "f9ffffffffffffffffffffffffffffff", // (2*(2¹³⁰-6)) % (2¹³⁰-5) - in: "faffffffffffffffffffffffffffffff" + - "faffffffffffffffffffffffffffffff" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000", - }, - { - key: "0100000000000000000000000000000000000000000000000000000000000000", - tag: "00000000000000000000000000000000", // (2*(2¹³⁰-5)) % (2¹³⁰-5) - in: "fbffffffffffffffffffffffffffffff" + - "fbffffffffffffffffffffffffffffff" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000", - }, - { - key: "0100000000000000000000000000000000000000000000000000000000000000", - tag: "f8ffffffffffffffffffffffffffffff", // (3*(2¹³⁰-6)) % (2¹³⁰-5) - in: "faffffffffffffffffffffffffffffff" + - "faffffffffffffffffffffffffffffff" + - "faffffffffffffffffffffffffffffff" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000", - }, - { - key: "0100000000000000000000000000000000000000000000000000000000000000", - tag: "00000000000000000000000000000000", // (3*(2¹³⁰-5)) % (2¹³⁰-5) - in: "fbffffffffffffffffffffffffffffff" + - "fbffffffffffffffffffffffffffffff" + - "fbffffffffffffffffffffffffffffff" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000", - }, - { - key: "0100000000000000000000000000000000000000000000000000000000000000", - tag: "f7ffffffffffffffffffffffffffffff", // (4*(2¹³⁰-6)) % (2¹³⁰-5) - in: "faffffffffffffffffffffffffffffff" + - "faffffffffffffffffffffffffffffff" + - "faffffffffffffffffffffffffffffff" + - "faffffffffffffffffffffffffffffff" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000", - }, - { - key: "0100000000000000000000000000000000000000000000000000000000000000", - tag: "00000000000000000000000000000000", // (4*(2¹³⁰-5)) % (2¹³⁰-5) - in: "fbffffffffffffffffffffffffffffff" + - "fbffffffffffffffffffffffffffffff" + - "fbffffffffffffffffffffffffffffff" + - "fbffffffffffffffffffffffffffffff" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000", - }, - { - key: "0100000000000000000000000000000000000000000000000000000000000000", - tag: "f3ffffffffffffffffffffffffffffff", // (8*(2¹³⁰-6)) % (2¹³⁰-5) - in: "faffffffffffffffffffffffffffffff" + - "faffffffffffffffffffffffffffffff" + - "faffffffffffffffffffffffffffffff" + - "faffffffffffffffffffffffffffffff" + - "faffffffffffffffffffffffffffffff" + - "faffffffffffffffffffffffffffffff" + - "faffffffffffffffffffffffffffffff" + - "faffffffffffffffffffffffffffffff" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000", - }, - { - key: "0100000000000000000000000000000000000000000000000000000000000000", - tag: "00000000000000000000000000000000", // (8*(2¹³⁰-5)) % (2¹³⁰-5) - in: "fbffffffffffffffffffffffffffffff" + - "fbffffffffffffffffffffffffffffff" + - "fbffffffffffffffffffffffffffffff" + - "fbffffffffffffffffffffffffffffff" + - "fbffffffffffffffffffffffffffffff" + - "fbffffffffffffffffffffffffffffff" + - "fbffffffffffffffffffffffffffffff" + - "fbffffffffffffffffffffffffffffff" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000", - }, - { - key: "0100000000000000000000000000000000000000000000000000000000000000", - tag: "ebffffffffffffffffffffffffffffff", // (16*(2¹³⁰-6)) % (2¹³⁰-5) - in: "faffffffffffffffffffffffffffffff" + - "faffffffffffffffffffffffffffffff" + - "faffffffffffffffffffffffffffffff" + - "faffffffffffffffffffffffffffffff" + - "faffffffffffffffffffffffffffffff" + - "faffffffffffffffffffffffffffffff" + - "faffffffffffffffffffffffffffffff" + - "faffffffffffffffffffffffffffffff" + - "faffffffffffffffffffffffffffffff" + - "faffffffffffffffffffffffffffffff" + - "faffffffffffffffffffffffffffffff" + - "faffffffffffffffffffffffffffffff" + - "faffffffffffffffffffffffffffffff" + - "faffffffffffffffffffffffffffffff" + - "faffffffffffffffffffffffffffffff" + - "faffffffffffffffffffffffffffffff" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000", - }, - { - key: "0100000000000000000000000000000000000000000000000000000000000000", - tag: "00000000000000000000000000000000", // (16*(2¹³⁰-5)) % (2¹³⁰-5) - in: "fbffffffffffffffffffffffffffffff" + - "fbffffffffffffffffffffffffffffff" + - "fbffffffffffffffffffffffffffffff" + - "fbffffffffffffffffffffffffffffff" + - "fbffffffffffffffffffffffffffffff" + - "fbffffffffffffffffffffffffffffff" + - "fbffffffffffffffffffffffffffffff" + - "fbffffffffffffffffffffffffffffff" + - "fbffffffffffffffffffffffffffffff" + - "fbffffffffffffffffffffffffffffff" + - "fbffffffffffffffffffffffffffffff" + - "fbffffffffffffffffffffffffffffff" + - "fbffffffffffffffffffffffffffffff" + - "fbffffffffffffffffffffffffffffff" + - "fbffffffffffffffffffffffffffffff" + - "fbffffffffffffffffffffffffffffff" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000" + - "00000000000000000000000000000000", - }, - // original smoke tests - { - key: "746869732069732033322d62797465206b657920666f7220506f6c7931333035", - tag: "a6f745008f81c916a20dcc74eef2b2f0", - in: "48656c6c6f20776f726c6421", - }, - { - key: "746869732069732033322d62797465206b657920666f7220506f6c7931333035", - tag: "49ec78090e481ec6c26b33b91ccc0307", - in: "0000000000000000000000000000000000000000000000000000000000000000", - }, - { - key: "746869732069732033322d62797465206b657920666f7220506f6c7931333035", - tag: "da84bcab02676c38cdb015604274c2aa", - in: "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000", - }, - { - key: "0000000000000000000000000000000000000000000000000000000000000000", - tag: "00000000000000000000000000000000", - in: "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000", - }, - // randomly generated - { - key: "52fdfc072182654f163f5f0f9a621d729566c74d10037c4d7bbb0407d1e2c649", - tag: "9566c74d10037c4d7bbb0407d1e2c649", - in: "", - }, - { - key: "81855ad8681d0d86d1e91e00167939cb6694d2c422acd208a0072939487f6999", - tag: "eaa270caaa12faa39b797374a4b8a420", - in: "eb", - }, - { - key: "9d18a44784045d87f3c67cf22746e995af5a25367951baa2ff6cd471c483f15f", - tag: "dbea66e1da48a8f822887c6162c2acf1", - in: "b90b", - }, - { - key: "adb37c5821b6d95526a41a9504680b4e7c8b763a1b1d49d4955c848621632525", - tag: "6ac09aaa88c32ee95a7198376f16abdb", - in: "3fec73", - }, - { - key: "8dd7a9e28bf921119c160f0702448615bbda08313f6a8eb668d20bf505987592", - tag: "b1443487f97fe340b04a74719ed4de68", - in: "1e668a5b", - }, - { - key: "df2c7fc4844592d2572bcd0668d2d6c52f5054e2d0836bf84c7174cb7476364c", - tag: "7463be0f9d99a5348039e4afcbf4019c", - in: "c3dbd968b0", - }, - { - key: "f7172ed85794bb358b0c3b525da1786f9fff094279db1944ebd7a19d0f7bbacb", - tag: "2edaee3bcf303fd05609e131716f8157", - in: "e0255aa5b7d4", - }, - { - key: "4bec40f84c892b9bffd43629b0223beea5f4f74391f445d15afd4294040374f6", - tag: "965f18767420c1d94a4ef657e8d15e1e", - in: "924b98cbf8713f", - }, - { - key: "8d962d7c8d019192c24224e2cafccae3a61fb586b14323a6bc8f9e7df1d92933", - tag: "2bf4a33287dd6d87e1ed4282f7342b6a", - in: "3ff993933bea6f5b", - }, - { - key: "3af6de0374366c4719e43a1b067d89bc7f01f1f573981659a44ff17a4c7215a3", - tag: "c5e987b60373a48893c5af30acf2471f", - in: "b539eb1e5849c6077d", - }, - { - key: "bb5722f5717a289a266f97647981998ebea89c0b4b373970115e82ed6f4125c8", - tag: "19f0f640b309d168ea1b480e6a4faee5", - in: "fa7311e4d7defa922daa", - }, - { - key: "e7786667f7e936cd4f24abf7df866baa56038367ad6145de1ee8f4a8b0993ebd", - tag: "de75e5565d97834b9fa84ad568d31359", - in: "f8883a0ad8be9c3978b048", - }, - { - key: "83e56a156a8de563afa467d49dec6a40e9a1d007f033c2823061bdd0eaa59f8e", - tag: "de184a5a9b826aa203c5c017986d6690", - in: "4da6430105220d0b29688b73", - }, - { - key: "4b8ea0f3ca9936e8461f10d77c96ea80a7a665f606f6a63b7f3dfd2567c18979", - tag: "7478f18d9684905aa5d1a34ee67e4c84", - in: "e4d60f26686d9bf2fb26c901ff", - }, - { - key: "354cde1607ee294b39f32b7c7822ba64f84ab43ca0c6e6b91c1fd3be89904341", - tag: "3b2008a9c52b5308f5538b789ab5506f", - in: "79d3af4491a369012db92d184fc3", - }, - { - key: "9d1734ff5716428953bb6865fcf92b0c3a17c9028be9914eb7649c6c93478009", - tag: "71c8e76a67a505b7370b562ba15ba032", - in: "79d1830356f2a54c3deab2a4b4475d", - }, - { - key: "63afbe8fb56987c77f5818526f1814be823350eab13935f31d84484517e924ae", - tag: "1dc895f74f866bdb3edf6c4430829c1c", - in: "f78ae151c00755925836b7075885650c", - }, - { - key: "30ec29a3703934bf50a28da102975deda77e758579ea3dfe4136abf752b3b827", - tag: "afca2b3ba7b0e1a928001966883e9b16", - in: "1d03e944b3c9db366b75045f8efd69d22ae5411947cb553d7694267aef4e" + - "bcea406b32d6108bd68584f57e37caac6e33feaa3263a399437024ba9c9b" + - "14678a274f01a910ae295f6efbfe5f5abf44ccde263b5606633e2bf0006f" + - "28295d7d39069f01a239c4365854c3af7f6b41d631f92b9a8d12f4125732" + - "5fff332f7576b0620556304a3e3eae14c28d0cea39d2901a52720da85ca1" + - "e4b38eaf3f", - }, - { - key: "44c6c6ef8362f2f54fc00e09d6fc25640854c15dfcacaa8a2cecce5a3aba53ab", - tag: "6f2a09aa76c9b76774e31ec02dcf7991", - in: "705b18db94b4d338a5143e63408d8724b0cf3fae17a3f79be1072fb63c35" + - "d6042c4160f38ee9e2a9f3fb4ffb0019b454d522b5ffa17604193fb89667" + - "10a7960732ca52cf53c3f520c889b79bf504cfb57c7601232d589baccea9" + - "d6e263e25c27741d3f6c62cbbb15d9afbcbf7f7da41ab0408e3969c2e2cd" + - "cf233438bf1774ace7709a4f091e9a83fdeae0ec55eb233a9b5394cb3c78" + - "56b546d313c8a3b4c1c0e05447f4ba370eb36dbcfdec90b302dcdc3b9ef5" + - "22e2a6f1ed0afec1f8e20faabedf6b162e717d3a748a58677a0c56348f89" + - "21a266b11d0f334c62fe52ba53af19779cb2948b6570ffa0b773963c130a" + - "d797ddea", - }, - { - key: "fe4e3ad29b5125210f0ef1c314090f07c79a6f571c246f3e9ac0b7413ef110bd", - tag: "27381e3fc2a356103fb796f107d826e7", - in: "58b00ce73bff706f7ff4b6f44090a32711f3208e4e4b89cb5165ce64002c" + - "bd9c2887aa113df2468928d5a23b9ca740f80c9382d9c6034ad2960c7965" + - "03e1ce221725f50caf1fbfe831b10b7bf5b15c47a53dbf8e7dcafc9e1386" + - "47a4b44ed4bce964ed47f74aa594468ced323cb76f0d3fac476c9fb03fc9" + - "228fbae88fd580663a0454b68312207f0a3b584c62316492b49753b5d502" + - "7ce15a4f0a58250d8fb50e77f2bf4f0152e5d49435807f9d4b97be6fb779" + - "70466a5626fe33408cf9e88e2c797408a32d29416baf206a329cfffd4a75" + - "e498320982c85aad70384859c05a4b13a1d5b2f5bfef5a6ed92da482caa9" + - "568e5b6fe9d8a9ddd9eb09277b92cef9046efa18500944cbe800a0b1527e" + - "a6", - }, - { - key: "4729a861d2f6497a3235c37f4192779ec1d96b3b1c5424fce0b727b03072e641", - tag: "0173965669fb9de88d38a827a0271271", - in: "5a761f03abaa40abc9448fddeb2191d945c04767af847afd0edb5d8857b7" + - "99acb18e4affabe3037ffe7fa68aa8af5e39cc416e734d373c5ebebc9cdc" + - "c595bcce3c7bd3d8df93fab7e125ddebafe65a31bd5d41e2d2ce9c2b1789" + - "2f0fea1931a290220777a93143dfdcbfa68406e877073ff08834e197a403" + - "4aa48afa3f85b8a62708caebbac880b5b89b93da53810164402104e648b6" + - "226a1b78021851f5d9ac0f313a89ddfc454c5f8f72ac89b38b19f53784c1" + - "9e9beac03c875a27db029de37ae37a42318813487685929359ca8c5eb94e" + - "152dc1af42ea3d1676c1bdd19ab8e2925c6daee4de5ef9f9dcf08dfcbd02" + - "b80809398585928a0f7de50be1a6dc1d5768e8537988fddce562e9b948c9" + - "18bba3e933e5c400cde5e60c5ead6fc7ae77ba1d259b188a4b21c86fbc23" + - "d728b45347eada650af24c56d0800a8691332088a805bd55c446e25eb075" + - "90bafcccbec6177536401d9a2b7f512b54bfc9d00532adf5aaa7c3a96bc5" + - "9b489f77d9042c5bce26b163defde5ee6a0fbb3e9346cef81f0ae9515ef3" + - "0fa47a364e75aea9e111d596e685a591121966e031650d510354aa845580" + - "ff560760fd36514ca197c875f1d02d9216eba7627e2398322eb5cf43d72b" + - "d2e5b887d4630fb8d4747ead6eb82acd1c5b078143ee26a586ad23139d50" + - "41723470bf24a865837c", - }, - { - key: "9123461c41f5ff99aa99ce24eb4d788576e3336e65491622558fdf297b9fa007", - tag: "1eb0cdad9237905250d30a24fe172a34", - in: "864bafd7cd4ca1b2fb5766ab431a032b72b9a7e937ed648d0801f29055d3" + - "090d2463718254f9442483c7b98b938045da519843854b0ed3f7ba951a49" + - "3f321f0966603022c1dfc579b99ed9d20d573ad53171c8fef7f1f4e4613b" + - "b365b2ebb44f0ffb6907136385cdc838f0bdd4c812f042577410aca008c2" + - "afbc4c79c62572e20f8ed94ee62b4de7aa1cc84c887e1f7c31e927dfe52a" + - "5f8f46627eb5d3a4fe16fafce23623e196c9dfff7fbaff4ffe94f4589733" + - "e563e19d3045aad3e226488ac02cca4291aed169dce5039d6ab00e40f67a" + - "ab29332de1448b35507c7c8a09c4db07105dc31003620405da3b2169f5a9" + - "10c9d0096e5e3ef1b570680746acd0cc7760331b663138d6d342b051b5df" + - "410637cf7aee9b0c8c10a8f9980630f34ce001c0ab7ac65e502d39b216cb" + - "c50e73a32eaf936401e2506bd8b82c30d346bc4b2fa319f245a8657ec122" + - "eaf4ad5425c249ee160e17b95541c2aee5df820ac85de3f8e784870fd87a" + - "36cc0d163833df636613a9cc947437b6592835b9f6f4f8c0e70dbeebae7b" + - "14cdb9bc41033aa5baf40d45e24d72eac4a28e3ca030c9937ab8409a7cbf" + - "05ae21f97425254543d94d115900b90ae703b97d9856d2441d14ba49a677" + - "de8b18cb454b99ddd9daa7ccbb7500dae4e2e5df8cf3859ebddada6745fb" + - "a6a04c5c37c7ca35036f11732ce8bc27b48868611fc73c82a491bfabd7a1" + - "9df50fdc78a55dbbc2fd37f9296566557fab885b039f30e706f0cd5961e1" + - "9b642221db44a69497b8ad99408fe1e037c68bf7c5e5de1d2c68192348ec" + - "1189fb2e36973cef09ff14be23922801f6eaee41409158b45f2dec82d17c" + - "aaba160cd6", - }, - { - key: "40ff73495fe4a05ce1202ca7287ed3235b95e69f571fa5e656aaa51fae1ebdd7", - tag: "2e619d8ea81b77484e4fddeb29844e4b", - in: "aa6269c2ec7f4057b33593bc84888c970fd528d4a99a1eab9d2420134537" + - "cd6d02282e0981e140232a4a87383a21d1845c408ad757043813032a0bd5" + - "a30dcca6e3aa2df04715d879279a96879a4f3690ac2025a60c7db15e0501" + - "ebc34b734355fe4a059bd3899d920e95f1c46d432f9b08e64d7f9b38965d" + - "5a77a7ac183c3833e1a3425ead69d4f975012fd1a49ed832f69e6e9c63b4" + - "53ec049c9e7a5cf944232d10353f64434abae060f6506ad3fdb1f4415b0a" + - "f9ce8c208bc20ee526741539fa3203c77ecba410fd6718f227e0b430f9bc" + - "b049a3d38540dc222969120ce80f2007cd42a708a721aa29987b45d4e428" + - "811984ecad349cc35dd93515cefe0b002cee5e71c47935e281ebfc4b8b65" + - "2b69ccb092e55a20f1b9f97d046296124621928739a86671cc180152b953" + - "e3bf9d19f825c3dd54ae1688e49efb5efe65dcdad34bc860010e7c8c997c" + - "d5f9e320ca7d39d4ba801a175b1c76f057832f3f36d7d893e216e4c7bbdb" + - "548d0ba48449330027368b34f9c69776b4591532da1c5be68ef4eebe8cb8" + - "fa7dc5483fb70c2c896334cb1f9cb5dfe044fa086197ff5dfd02f2ba3884" + - "c53dd718c8560da743a8e9d4aeae20ccef002d82ca352592b8d8f2a8df3b" + - "0c35f15b9b370dca80d4ca8e9a133eb52094f2dd5c08731f52315d828846" + - "e37df68fd10658b480f2ac84233633957e688e924ffe3713b52c76fd8a56" + - "da8bb07daa8eb4eb8f7334f99256e2766a4109150eed424f0f743543cdea" + - "66e5baaa03edc918e8305bb19fc0c6b4ddb4aa3886cb5090940fc6d4cabe" + - "2153809e4ed60a0e2af07f1b2a6bb5a6017a578a27cbdc20a1759f76b088" + - "9a83ce25ce3ca91a4eb5c2f8580819da04d02c41770c01746de44f3db6e3" + - "402e7873db7635516e87b33e4b412ba3df68544920f5ea27ec097710954f" + - "42158bdba66d4814c064b4112538676095467c89ba98e6a543758d7093a4" + - "94df", - }, - { - key: "5cc36d09c7a6472a41f29c380a987b1ecdcf84765f4e5d3ceefc1c02181f570f", - tag: "0d57b8cbea8090df0541354673dcb4e0", - in: "44fcd629f08dc1ef53c9ae0d8869fe67fdc7a2c67b425f13c5be8d9f630c" + - "1d063c02fd75cf64c1aec9d2e2ef6e6431d5f5ad0489078dc61f46494dcc" + - "f403dad7f094170d2c3e29c198b0f341e284c4be8fa60c1a478d6bd55dd2" + - "c04dad86d2053d5d25b014e3d8b64322cdcb5004faa46cfa2d6ad2ff933b" + - "c3bd9a5a74660af3d048a9a43634c0250427d9a6219197a3f3633f841753" + - "ba7c27f3619f387b6b1a6cb9c1dc227674aa020724d137da2cb87b1615d5" + - "12974fa4747dd1e17d02c9462a44fec150ca3a8f99cc1e4953365e429956" + - "5e108535b1f62e1d4ba18e17a52164418bfd1a933f7fb3a126c860830a87" + - "293d9271da736e4398c1e37fb75c4bf02786e1faf4b610cd1377fbb9ae18" + - "0655a0abefbad700c09473469f1eca5a66d53fa3dc7cd3e7c3b0411d7e14" + - "5f96eb9654ab94913dda503a50f9e773842f4d2a5faa60869bf365830511" + - "f2ededd03e0a73000edb60c9a29a5f5e194cf3b5667a694690384599d116" + - "f8d2fd93b2aed55b7d44b5b054f3f38e788e4fdf36e591568c41d1052cad" + - "0fcb68ca4c4bf5090d57df9db6f0d91dd8b11b804f331adb7efb087a5604" + - "e9e22b4d54db40bcbc6e272ff5eaddfc1471459e59f0554c58251342134a" + - "8daaef1498069ba581ef1da2510be92843487a4eb8111c79a6f0195fc38a" + - "d6aee93c1df2b5897eaa38ad8f47ab2fe0e3aa3e6accbfd4c16d46843318" + - "5fc61c861b96ca65e34d31f24d6f56ee85092314a4d7656205c15322f1c9" + - "7613c079eae292ba966e10d1e700164e518b243f424c46f9ea63db1c2c34" + - "b512c403c128ee19030a6226517b805a072512a5e4cd274b7fd1fa23f830" + - "058208ff1a063b41039c74036b5b3da8b1a0b93135a710352da0f6c31203" + - "a09d1f2329651bb3ab3984ab591f2247e71cd44835e7a1a1b66d8595f7ae" + - "f9bf39d1417d2d31ea3599d405ff4b5999a86f52f3259b452909b57937d8" + - "5364d6c23deb4f14e0d9fcee9184df5994fdc11f045c025c8d561adb0e7d" + - "fd4748fd4b20f84e53322471a410cdb3fd88e48b2e7eb7ae5dae994cb5ea" + - "e3eaf21cf9005db560d6d22e4d9b97d7e9e488751afcd72aa176c0fcde93" + - "16f676fd527d9c42105b851639f09ea70533d26fc60cbeb4b76ed554fc99" + - "177620b28ca6f56a716f8cb384", - }, - { - key: "811c3e356e7c793acf114c624dc86ace38e67bff2a60e5b2a6c20723c1b9f003", - tag: "c6e59044cefc43ee681c3eed872d02b3", - in: "e115b304c023792448794546a2474f04294d7a616215e5dd6c40a65bb6ed" + - "b508c3680b14c176c327fdfb1ee21962c0006b7deb4e5de87db21989d13c" + - "3ab0462d5d2a52ef4ca0d366ae06a314f50e3a21d9247f814037798cc5e1" + - "0a63de027477decdeb8a8e0c279299272490106ddf8683126f60d35772c6" + - "dfc744b0adbfd5dcf118c4f2b06cfaf077881d733a5e643b7c46976647d1" + - "c1d3f8f6237c6218fa86fb47080b1f7966137667bd6661660c43b75b6339" + - "0b514bbe491aa46b524bde1c5b7456255fb214c3f74907b7ce1cba94210b" + - "78b5e68f049fcb002b96a5d38d59df6e977d587abb42d0972d5f3ffc898b" + - "3cbec26f104255761aee1b8a232d703585dd276ee1f43c8cd7e92a993eb1" + - "5107d02f59ba75f8dd1442ee37786ddb902deb88dd0ebdbf229fb25a9dca" + - "86d0ce46a278a45f5517bff2c049cc959a227dcdd3aca677e96ce84390e9" + - "b9a28e0988777331847a59f1225b027a66c1421422683dd6081af95e16f2" + - "48ab03da494112449ce7bdace6c988292f95699bb5e4d9c8d250aa28a6df" + - "44c0c265156deb27e9476a0a4af44f34bdf631b4af1146afe34ea988fc95" + - "3e71fc21ce60b3962313000fe46d757109281f6e55bc950200d0834ceb5c" + - "41553afd12576f3fbb9a8e05883ccc51c9a1269b6d8e9d27123dce5d0bd6" + - "db649c6fea06b4e4e9dea8d2d17709dc50ae8aa38231fd409e9580e255fe" + - "2bf59e6e1b6e310610ea4881206262be76120d6c97db969e003947f08bad" + - "8fa731f149397c47d2c964e84f090e77e19046277e18cd8917c48a776c9d" + - "e627b6656203b522c60e97cc61914621c564243913ae643f1c9c9e0ad00a" + - "14f66eaa45844229ecc35abb2637317ae5d5e338c68691bea8fa1fd469b7" + - "b54d0fccd730c1284ec7e6fccdec800b8fa67e6e55ac574f1e53a65ab976" + - "4c218a404184793cc9892308e296b334c85f7097edc16927c2451c4cd7e5" + - "3f239aa4f4c83241bde178f692898b1ece2dbcb19a97e64c4710326528f2" + - "4b099d0b674bd614fad307d9b9440adab32117f0f15b1450277b00eb366e" + - "0260fca84c1d27e50a1116d2ce16c8f5eb212c77c1a84425744ea3195edb" + - "b54c970b77e090b644942d43fe8c4546a158bad7620217a40e34b9bb84d1" + - "89eff32b20ef3f015714dbb1f150015d6eeb84cbccbd3fffa63bde89", - }, - { - key: "f33691f5db2dea41e1e608af3ff39f3a6988dba204ce1b09214475ae0ea864b8", - tag: "6e50e70411201378c8d67857d7b631d2", - in: "439bc9ea10db4d2b08c7fcf2e8bd89fa9844f8061d462e28f174489e7514" + - "0f84e842040141cc59ce38f9551850cfbdfac2d75337d155090d70d0d930" + - "04340bdfe60062f17c53f3c9005b9995a0feb49f6bef8eaff80f4feb7ef3" + - "f2181733a4b43b6ac43a5130a73a9b3c2cbc93bd296cd5f48c9df022b6c8" + - "2bb752bc21e3d8379be31328aa32edc11efc8a4b4b3f370ee8c870cd281d" + - "614e6bc2c0a5ca303bc48696a3bd574ee34738de4c4c29910f8feb7557bf" + - "ffcfe7428b4703144bd6d7fe5b3f5de748918553df5453b3c6001696f3de" + - "0137e454aadf30cedfb6be36b0b908a38409f1a2dc202fc285610765e4c8" + - "6414692bf4bde20ed899e97727b7ea1d95d7c621717c560f1d260ab3624e" + - "d6168d77c483dd5ce0d234049017795f2e5a7569d7ad323c50a5b1170337" + - "4174a9977026c20cd52c10b72f14e0569a684a3dcf2ccbc148fd3db506e2" + - "8d24f6c55544cb3980a36e86747adc89ebad78d1630618d113fa445f8625" + - "b583cd7be33913c30c419d047cf3baf40fd05219a1fcec717b87a65fa022" + - "1a3aa8143062d77588168019454240ae3d37640996f2967810459bc658df" + - "e556de4d07263dc3d9158ec242008226d1c6aea7f0846e12ce2d316e80da" + - "522343264ec9451ec23aaaa367d640faad4af3d44d6d86544ade34c93518" + - "2843f6b4d1c934996778affa9ee962e7dfef5e70d933d4309f0f343e9606" + - "1b91b11ac380a9675e17a96099fe411bedc28a298cd78d5496e28fbbd4f5" + - "b0a27735d1144348e22be5b75724d8f125e99c4cb4e9c3a1f0b4e9da5146" + - "e6afaa33d02fda74bf58a8badee2b634b989c01755afa6ab20ee494c6ae4" + - "c2c6f17af6b53b61d2947d83a18eb3b8a1612aad5d3ea7e8e35f325c9168" + - "ac490f22cb713ddb61fbd96011c5849ac8e2fcd42db820349bdf9157dcc0" + - "0d9f9ed9c099b10c7194d48b623b0df43759734b2a2e5f8a35e7192bf9a0" + - "03dcb9d16a54bd84d922f85b6021b28aacc5264fe9e83deb48f18f864cbd" + - "367eb163d39c45b0eb907311a2a4b09fb26109088df782ce031b02f3caff" + - "d2dbe25b1cbde9f35ba7c47292a4fd49e7def7a28824f3dfda259a86c3de" + - "59257c255c712686ee47d128a55c7b9e8c546035eab7e2da420f32ed5c94" + - "bc12a34dc68eb99257a7ea03b69d6c760b0681fa24e4ca97b7c377182ab5" + - "fee30a278b08c44c988a8f925af2997883111c750d176b432735868208f4" + - "0de7137331b544f2d28040a3581d195e82811c945c3f9fde68fc21b36a44" + - "e1cfa2d8eb625f3102461539b3f13c660936a5ddb29a0ae791fbf52c2f69" + - "7bd334653f3605b362d91cd78569b41dbd09b2a5892440b5097fa08d0b4b" + - "291fc5b934585dd8d5adc80d573fdd194b2eae26dfc49f5e51c1f1607d7e" + - "87740702f244bf39ca1d52423e0ae84891dfdf4f43ef984c7a5f293a2007" + - "a1e00e39c757f064518953f55621f955986f63", - }, - { - key: "d115b6ac998a65b48b3dae5977abaf985258d3d1cfe1616cec3d6a77f7a75785", - tag: "b431c9318ec2769fc8ee8f5fc3c079c3", - in: "7e7eb43839a6d7616b8a7b1fb7144817904342a9bd34167051162941a6b1" + - "b85db5e587f76e4a53211755d5ab29c11822d7711a97b3f1ff5b21f2485d" + - "9c86241fb56cdd6796245d3112df11ad9a7344db44d09934c4efb280ed65" + - "80cfcafb5c97a32993cbbf4917183e0b7bb38f2ce2479c28e1d39f673962" + - "17a7010448dfd39a4e7f406c8bd2d804f993bb410fffa4eb57518a531ecf" + - "259a8af068230acb826d9ffc20ee0fc43885221a321e3928971bb28615f0" + - "d9f099f5b68a80503a910fdba0bc643c60b64837900be38770b6b30c362c" + - "4580722b5dbb1b9c8cd02a18fd7b5661d2c4d28aa941c50af6655c826690" + - "37312fbf9f1cf4adb0b9400532755011b40e8252bd0e3c7a22efb0ef9122" + - "1e04b4aa8316d4a4ffeaa11909d38cc264650e7ca416835ded0953f39e29" + - "b01d3a33bba454760fb0a96d9fe50b3e42c95271e57840380d1fd39a375b" + - "3e5513a31a4b80a2dad8731d4fd1ced5ff61e1fbe8ff3ff90a277e6b5631" + - "f99f046c4c3c66158554f61af2ede73aede97e94b1d1f129aaadf9b53548" + - "553cc2304103e245b77701f134d94d2a3658f2b41108c5a519c2c8f450db" + - "027824f1c0ab94010589a4139ff521938b4f0c7bf0986585f535b6e292e5" + - "b3ded23bf81cec17c8420fe67a449e508864e4cbb7eaf335975668f013e9" + - "da70b33bd52a72094a8f03762ea7440ce9fcd10e251837cfc9ccc1a8cc47" + - "0c67379f6a32f16cf70ea8c19d1a67779a9b2d2b379665e0e908a88b26e7" + - "8c9f94f17acefa6d5feb70a7095e0297c53e091cf98df132a23a5ce5aa72" + - "59f1154b92e079f0b6f95d2a38aa5d62a2fd97c12ee7b085e57cc4652863" + - "8defacc1e70c3aceab82a9fa04e6aa70f5fbfd19de075bee4e3aac4a87d0" + - "ad0226a463a554816f1ebac08f30f4c3a93fa85d79b92f0da06348b4f008" + - "880fac2df0f768d8f9d082f5a747afb0f62eb29c89d926de9fc491921474" + - "1d8647c67d57ac55f94751389ee466bbd44dbe186f2f38abbc61a0425613" + - "e9b6a64e6bcb45a2e2bb783b9103483643d5610a7e2dcdb10b5d78423285" + - "506b42a99b00a4fb7b619b4526bb4ec78299dd01ad894fde2f053e18c55b" + - "6047f86333f2690c2cb8e87d9834ab8a5e339aa346e4d9952ed62dc083e3" + - "b11a823a67f23fec099a033f127ebe8626a89fa1a5a6b3520aa0d215a8e7" + - "dea3af37907686c16521739a95d6c532cc259c497bf397fceaea49cd46b9" + - "ad5c1b39a36fdd2f0d2225fef1b6ca2bb73fe604646c10ba4c572ab13a26" + - "559ededc98f5a34c874cc25621e65ba4852529b5a4e9c1b2bf8e1a8f8ff0" + - "5a31095b84696c6381eb9ad37ac0db184fe5fccf3554e514946a33cabe6f" + - "4d617b549d28ad1cc4642dac96e0215ee1596481600d3619e8f45e2c9ae1" + - "da834d44aca216bba0efef6254503ca90339f2d7ca508b2722d50c08def8" + - "a736590fa44855cd9eb9979c743783aa26e633696739f2ae25ff7b72ceb2" + - "4dff4455b85bbd675c8cb71ad18386dc58c371bdf37b4b3875b98a9423ff" + - "3becfc0d0ba2aacab3ee7683cb3b345095fefcaca5751ca793da63c89428", - }, - { - key: "f3717306b9729be998cdb2c9d856306c5ae3d89da2cdcef12f86f6110c98d873", - tag: "907dba0f4849c7cf4570b5128b5f31d5", - in: "079572187d4559f24d8e48dc366441acf226a4db79e214ec3ee288acc349" + - "887e2e377419bcafa377d0151497b52e4d9cf2a02b0fc91ad9516482bdf6" + - "eccd1497954b53241bfb0bc5c04cc45045c6251f23a510060fee32721872" + - "bbc95cd8d400dff00bcac2ecce6229c7d73d8f85ed5a87afdccf6dedd299" + - "2d5c7b5b8090c47c737ded036ff0e9aedf02a2242fd9820be618b9601e73" + - "d3ba5d8f1ae9805cfd2306251704bc74e3546997f109f1dfae20c03ff31f" + - "17564769aa49f01233c9c4b79f90fa3d1433d18cdc497914046ad77d2792" + - "2588a7d0e61d4258d7d80cdab8503e3111ddca22cf7f39c1f80f1e16a68d" + - "9e21db8b53dd316dfa4233cb453a39a90101c60efc08514a3057db007e96" + - "507745bd4a0764ed8717a250bffb5fd1ea58474bdfb5b869681939693926" + - "40d832a3387ed4ac9cdab0d2af8fcb51b86e4d927097f1e79b5af96574ec" + - "d59d0dd150a0208978c41de28ad6cadf72a49279cffd6dc281c640f2e294" + - "4cde49a13ed390da1dd92e3011ce0f4a0863375a9db3f67fca1e3b8288a0" + - "78611161d7cb668ecdb932e1ff3733982c8c460eeeff2bca46c96e8a02cf" + - "b55d770940de556373a4dd676e3a0dd66f1280c8cb77a85136b3f003fab4" + - "887dad548de7bfe6488ae55e7a71da4097db03900d4b94e776a939530328" + - "83492da900b2a6c3e73d7a6f12ee30c9dd06cc34e5a3893976eb1de5864d" + - "32e792ac02e68d052d9d0cfc7cfb40b77728422f6c26cf68987c6b40fcfe" + - "9d660abc657360eb129de11bd70af5eb8fe350af2c27a6ece2cdf81b94c8" + - "0e68e8c51106497cfa5171236efe2d71d76b5dff3352af9b407dc5aab60f" + - "46b5683646f5b28732b7c750d351a08a507243d8e437cc4bef13a3edaa20" + - "5fc4e9968b4e563fa0dc965ba20b8e48bc188a321b16d3213bed69647512" + - "7a20afc1a3680ef261df6d37b017dee05cfc3a42e4130216e5540cf715c4" + - "e638d7d615c50bef576eeb19b3b15b2c2b454dfcef2b18161a143ddf52fc" + - "8e88fa71cbe34c92cd4b5a0adc81e5c33e11d2721bc1b95a9e693ac3cabc" + - "490889a8a42bf7e22375b679e8598c8faef22a006ed2da8ab1c08aaed2f5" + - "6d6f26649036335c0881bfec1e3a5346335c3b3707ee92173f1a7a3305c2" + - "933f78e995da8f1df64daf12b81ce23c8813c27fd4551103dc33561c2e80" + - "45b6b6770fa03498fd359a104884699d628020173edbcc4398b977e456e4" + - "885964840466176a490e7c513ba5d66090277c1ab1632a995a54f555a452" + - "1170a000507865b6650730aa6d6050a55959102836fff3d37e4773340e59" + - "2e56951ff9652519de4421d9c5b63edbeb30a3852a1ea110a9a29721aee3" + - "23d5a306de1624cecc87badc47aa87f489635d2fb60bff62ba67f5257999" + - "6af0a1f1a6fbcd8704e119196fcc289a6db6a4170a2cae31a1d30744b702" + - "2536d1526d41659c2dcc8b39c26aecfc0f8a707136d81b2827a158fd7386" + - "a537514471c213a8c859016748e0264cf3fbde10f40c620840ec4df99432" + - "e2b9e1e368e33f126ec40c572e841c2618d49d4eb098b9533b1f4ae00b46" + - "8d15de8c8ab6d0b650e599576f2bd90a124c9c6a0f911fd1bd8253bac272" + - "942cbdf8864f3747ff7f09d8a5a9d8599be7ee1744e5f1faf3e526cd2a06" + - "b157527272af9d38565957c9ce663c295766c0e0e464971c6282b70d4c0c" + - "1fb3b69856b34c089ad2b2c745f5a033cee1429c5b855581ee285278893c" + - "43a5968d9c28384b7abe8d072ba69089c938685cb1eab461f05314ad6d06" + - "eaa58512f8738bde35b7b15ef359dd2e8753cb1ed6", - }, - { - key: "9772c1a4b74cbf53586e5df04369b35f1fdca390565872251bc6844bc81bda88", - tag: "68eb7fc459ecc3be819485001ab438dc", - in: "e115cc2f33e367cb85c01a914b3a512404ad6a98b5b0c3a211d4bffd5802" + - "ee43b3fb07451c74524ec8b4eddbb41ca33dd6e49791875d716a44bec97b" + - "7c2d4546616939ffa3b1ab9b8ba1d1a637e7c985cc922606caa0453085e3" + - "5f2fe0bd2de129d1d1856ade975a3281a62965927d8bb695e54514e69558" + - "89361a2a00a1b24e62bda78d0b71a0d40147016fcdaf1a702331dda8e678" + - "d8f476dcc91698da1688c610ec0cb1d9b8fbcd45dfde6d1503ba60a01337" + - "ae5b2f5c854a82c3087779babd2e522dd92f4718cd9f8c649ac226745ca2" + - "fa1696442764758f67cd926369578ae87612790dc56ed9cda935281a490e" + - "5c984950ec7a4e930520d273a69da4ed3a330e532508e26f942961fed0e3" + - "efeed52a7b96250d723155aa39a8ae85131c255c32bf406b647de1a37fba" + - "dc61e302bb5b70adec4505ee66b3a1d1b7bfe9c58b11e53ad556d56e5807" + - "017bb30b71be94e8f86aaf1496e8b8d6db75ec0afbe1cd336c23963c745d" + - "7b4ba1787ceb30728f1762b46f6eaad5064c8029d29b86266b87f93142a2" + - "74f519f3281d8c1cb43c23eb184ae41f3f625cf624b05a48d73cd7783fdf" + - "14954a03ec1a930e9a954424eff030e3f15357de4c19983f484619a0e9e2" + - "b67221cf965e9aa8d8926595c793adfe0181050df8b845ce648a66df532f" + - "78b10c83ecc86374a4f8abf8edcc303654bafd3dcc7de9c77a0a9d1d98fb" + - "121534b47d16f75b55fdc2a5e2e6799f8a2f8000d4292282e56863ae422a" + - "5779900ad6881b78946e750d7777f33f2f013a75c19615632c0e40b98338" + - "1e9b8d35a26abe30242c45662eebb157e6d7a8a5519de60268ac289b8295" + - "5d4feb47b9eef6da65031c6f52c2c4f5baa36fce3618b6a331f1e8bdd621" + - "48954fcf0846afeeb0a6cadb495c909a7fe671b021d5b0b4669961052187" + - "d01b67d44218471bfb04c1a3d82bf7b776208013fc8adabaefb11719f7a7" + - "e6cb0b92d4cc39b403ceb56bd806cbdcc9ee75362ab4aaeb760e170fdc6a" + - "23c038d45f465d8ec8519af8b0aad2eb5fae2972c603ed35ff8e46644803" + - "fc042ff8044540280766e35d8aaddcaa81e7c0c7eba28674f710492924c6" + - "1743da4d241e12b0c519910d4e31de332c2672ea77c9a3d5c60cd78a35d7" + - "924fda105b6f0a7cc11523157982418405be0bacf554b6398aeb9a1a3b12" + - "fe411c09e9bfb66416a47dd51cbd29abf8fbbd264dd57ba21a388c7e19e8" + - "12e66768b2584ad8471bef36245881fc04a22d9900a246668592ca35cfc3" + - "a8faf77da494df65f7d5c3daa129b7c98cef57e0826dee394eb927b3d6b3" + - "a3c42fa2576dcc6efd1259b6819da9544c82728276b324a36121a519aee5" + - "ae850738a44349cdec1220a6a933808aee44ba48ce46ec8fb7d897bd9e6b" + - "c4c325a27d1b457eb6be5c1806cd301c5d874d2e863fb0a01cbd3e1f5b0f" + - "8e0c771fca0c0b14042a7b0f3ae6264294a82212119b73821dcfbbfd85bb" + - "625b6f75e4dc0ee0292ab4f17daf1d507e6c97364260480d406bd43b7d8e" + - "8c2f26672a916321b482d5fa7166e282bfeed9b3598c8f8c19d2f8c8b98d" + - "f24c2500c8ad41cd6ed3f2835737916d846f1a6406cda1125ed7740fe301" + - "d1144559b7c95fa407599ae40a795226513153f86c9b8abe7d8aa6963c99" + - "5646ec586cbf20a03a698cc0681b7bd333402d00fa8e15cb32300b5a24ea" + - "316c5e1df67de78891846cb9183a4b112c3bcc17bcaa5fecd6c1dbbf6ef8" + - "272d9269e7f0ba9f17050a6aa5f11cb28874360396ab647941f2c9a85cb0" + - "6a969919b16997b0827af8f909c614545f1ad638ebb23109f6bab6b49b22" + - "b2285cabbb998b3e1bf42771b4d4e52330b224e5a1d63169ec85fe1c7dd2" + - "46dbafa6138448420f463d547a41c2b26026d4621b854bc7786ab3a0a93a" + - "e5390dd840f2454028b7c3bb87680f04f084089bbc8786ee42cf06904d01" + - "7e405144d2fae141599e2babe71abfbe7644fb25ec8a8a44a8928ff77a59" + - "a3e235de6bd7c7b803cf3cf60435e473e3315f02d7292b1c3f5a19c93646" + - "3cc4ccd6b24961083756f86ffa107322c5c7dd8d2e4ca0466f6725e8a35b" + - "574f0439f34ca52a393b2f017d2503ba2018fb4a0991fddc1949832d370a" + - "27c42e", - }, - { - key: "d18a328b63a1d0f34e987682fe6ca3d48b4834b4312a17e99b3d88827b8d2238", - tag: "938b43b80cb3935e39b21dd8ba133cf8", - in: "bc2b0baf92580ee6c5efe640f2a029a791a3c77bec459be74cbc30931508" + - "d9f312c3a0944212831cbe4fc92e8f107f2f750c91bcc09f7624fa9a09b4" + - "9b7712cf5d619ea9da100fc23068ae2f4e353047e3956b215884bdb12235" + - "3f06b8ee98f36c3212493d61ae9ce151cd0453f3075b18a12d7d73da3de7" + - "dc2d98376cfb420069ca8148c511ca6bbae57572394a3c615a6fefb30c5f" + - "d727f964b4065ac9ee252bdd2bcae3e70162fe0e8069974e073f0a093d45" + - "be52d7de16a8f5f65c548aa6525822ffb00dc642530fedf355f7188ef017" + - "56384760c80afb61ad903d10119a7d615ec4fbdc79c490160bdeaf200915" + - "e405f2a921a2380c0ab9d2ac1e4fdc8ec4b907368c004458598efac13dc7" + - "2751e7faded538e3dc8b16590cac9b7ec294da0ad53e22cb9c05d8ef494f" + - "a04f6ab7c843c867fbe3cf1b4eb146d65339b0b03392259f12627a8e98e8" + - "0f4896c30b8ecd210acb2365539a872541921dcd8e1e54caf4936dfc7e1f" + - "68f3bbce61d325b447a8cce7f0fcad28494f2e47dae46b136594b5dfca7a" + - "bdafd6856f91496c05b21079aa55aa8c41628220a2cf0cdd755893375b7b" + - "b13d914c9a1d1db4a18f8fa36c55e52d0342352052032fb62d32fcd51cb1" + - "ac46f44b06e682db5d96d583cda03b966c650c03ae53542e8da1066b6884" + - "4a7e2280c664415e413f270b1fdcfbb40b9daa6131d071ee7eb1553dc5b1" + - "a50677971223dc316d2d326d57cbd529c88698facdca425e2d5c6b10d7ae" + - "cae28b8890aa44ede9b9193dbe8d1d8aa1fa580ca384b57eadcbefc96dd8" + - "bfccbe3b855a96f1fd4913035f817b75954ef1827c7718aab24d353e41cb" + - "a73748e14e0c2750d5b6a9752125708cc7ee7a498c7fbadf4186e7f8fa93" + - "bfdf281a49400f877621651b8ba87edda5231e80b758564e75139b61b1a9" + - "9fb9ec694f928ab1f47c6c4287bd4182d1b2be053380616e98da06f3ef57" + - "b570ade17c51da1d602b6ebc5a638ebde30d99bf4f91d0e01557c7dcd8f7" + - "9e5120143c935fc699eb5616ccd3cac56b5f8a53ed9e6c47ba896bfefe71" + - "2004ad908c12cf6d954b83bec8fb0e641cc261ff8f542b86e62d90e227f2" + - "a5bd59c9d390c0dd857f6da2b7624787a0bb31908bae84896890b283da61" + - "d8ec4f56eea38b22b438d6374b42243f9c1d94288874e53ab90c554cc1f1" + - "d736acde67aff55007fd4b3becc4d0f3ddd96f10dc75255cb0327aa47076" + - "2b3a3a656e33c87b02a682658b6cd2a75d9c0462803c9bbffa51441501a0" + - "3a2fbb2344aa13d27ffb9e98704ea6720b6a9992e53449688cd74d0648fa" + - "e8e776b0ea6bf048b2ec05341e5948cab0af015328b284ae7bd89a5f763c" + - "eaf5ca3e647a9f5bff7197e4d357e4359fa5fe30709545453149be510e3b" + - "ff86beeba5110c79c0215fbe9ac9339a8ac7d41f7488588ab14ac657aaf7" + - "d5c03a353932bbb2b261f0e83f3526c5e8e0c2348a10ab4eed6ecdcf9014" + - "7550abcb0a722f257e01d38bad47cdd5a64eef43ef4e741bf50da275720a" + - "0aee47adfc5cd2534b911dc269197c3c396820b303f6941e3fd85b5ed21d" + - "6d8136745c3eeb9f36b1f226434e334dc94be8a5606079cb7643136aacd2" + - "da9c38b2eb7e2b898bd8632003767bf0c87d00a3c2fcee48bbbcdd949af3" + - "3455128216709df25879b0ce894ac4f121dfca6b8c7865002b828696641d" + - "14ffc59924fbda50866fded0afaea545c8008c564a3a0b023f519a9980ea" + - "d541d91d1c07a739fd02286ea5660e473f80494236a68e84ea31aad71348" + - "e45055ded69c39941e31d51df257a4d0b0d8f025dbedee093f2b91795bc1" + - "533dc472020769a157a187abd6d8d52e1693e2ef56b2212759d0c0120e54" + - "c425d0084fdb3925e296dd6cdd8e677043a90674904057d88ebdea5998aa" + - "03562a790adecc4399352df43e5179cf8c584d95ef8e4b37295946b1d37f" + - "faf4b3b7b98869184e42ea8b304fe1059f180ff83d14a0861ca7c0682c34" + - "b48a70df8653bd8d9a26f9489e1271fa44e41b392e648d0e619ecdad2c53" + - "952094802eeb70ade4ffe096e3049867de93a824217e31364b18204e9681" + - "dd8e84ae2678aad155b238f59dd9bf9ce07e97183a690b2a46a8f3624843" + - "5b2f713e7d8dcda4dea1e3c4cf9692dda082322c51f7bb1f63d92aa987ec" + - "cf1355a043e21a7b8d60a2b97f18487f6fff4c77df92dbfdc9837540c518" + - "9fd9585731bc6e726a34ca21154b0499522c9d1016953dd0fa2eb6a92b6d" + - "14d6e3da5c12fabe92bd639e253983fc91041091791643", - }, - { - key: "46e8eb27acfdc8f4be622d8741c7bc414464c149e21da97ab4afbf3e07b98b0e", - tag: "56b5f49be824c7a19b19faabf0787a87", - in: "ced52b76c057872a60107194b432cf04b7be05e65209045d2952ea0284d8" + - "3e2ed5a15cfdc58071204573c18ab03765b4d5e63a601419e039c42075b2" + - "7ebb2827de9c6233d6632e6d3db9140bdb4a9291d53f33734c2dc8e24df9" + - "0764dc10e0d321d20fdf659bfa2a81bc9e04fd0f83448143276647c08bfa" + - "dcfe3bc23898eda655c9353693ed7b022f43eefa23c21db7660c5029ca64" + - "a6085d93029ea6c43197356f56b7624d4819f5008d053357d981ffbe7f40" + - "96d6c55d8417002d36189b04bbb2c637339d90f4910a400833a8d422d88d" + - "c816c1636e8d9f7f926c244a28d9e0a956cec11e81d0fd81d4b2b5d4904a" + - "d1a5f55b5ec078dcb5c2bc1112bbfd5efc8c2577fe6d9872a985ee129e5b" + - "953e9cebf28cf23c6f9c6a5e09cb09ab586c6a50e4389cd3110777591d7f" + - "0608a3fd95b99f6ba03984fb0e13c6bbbde3668c59f2f2b69d7caadffa94" + - "6f67e725d56280e59e66dca025a18d4616e81abd9801835bd94485bb2025" + - "dee81fba440005b181ee81dc1d7796cbec92e4ec1c9016c8e8073cf281ce" + - "f749993f09a618a4671d58b476feffa454600f82955c591882715148a826" + - "586f68bb50059914dce1c1c85e5e3951647c9964ec9316005209a58baeb5" + - "2c6d01e6b4c275c0050a7e2bdc52133e433b050a700b556d4314e5c041d1" + - "93ee47f47adc971aed1b63259dd5cd4f95854a71a947eae3d3d12d0d7b52" + - "c6cd2fef2d2e892607a9681d73ac3236fad21ee30a4f857010bc95c00d5f" + - "6f0c6b3fe50cd6452be6eec4f5f01542dc2cb5e2db1f52224f11348fe2a0" + - "5d1e5885f1317f2d06ce2813dc4c723008e836a2ee95d0aac66855fe4c3b" + - "1b2e02ba0700be759b1ef1c2a3123ee4ccf9200d8d4de5e0d503f04c2053" + - "66393d1e91b648392ca28389d976aa618b4796acbfe8aa356ecdce1f7786" + - "bf09af226bb9402317b6fa319bbb9248d8ce00b1f49f066c69d4df93266b" + - "938342cd7fd4b07c320c2409ef72d8a57c21d0c6d6d493f7ca94d01b9852" + - "e4fca6a9291e9060154bc38af6c86932645f53914709fc90e11db56ec471" + - "6d600ee6452041248ea8244f79534f793bfc1f2020855d817cb4ca3c48ea" + - "7f6441ce9af9bda61936c226d810086c04a35e8654fdc30d4b35701adccc" + - "016d5895b2121ba4066e44d694f6371d97911786edb73dc3020ba186a01f" + - "ee3dd6036c0e205a8d05979bad228fd12c0fd2fded6c7f1e4c11354d266e" + - "d9c2f706269c43cd90504997d93a17b39b10dab0ff083ab3bd06540ce612" + - "d08f46ce75a16ef330525737410a0d98fb3d484968f9c12edcaf50103fdc" + - "c14128ea4ad6c30b56247eab28197fe617e5f88afa5cbe003c63d423647a" + - "d3042626fafd2084a0582ff1b1efdb5baa162662048019546234e2f6b6a1" + - "d8bb971114aae41df7795b4f3598f2af9e8921a9aadc7fab6c780aaa32a3" + - "84865a4ccb02351dbc55ec92a3152d1e66ec9d478be5dca17b4a131b4a0d" + - "3d4420fc6123fef80fd56ca266407d58a7880d6b7e5ce2b6bdc9a3721071" + - "7feec573d83c83a2e3f7d4023f2f68e785cde728fdbf5054060e4c89faa6" + - "1c9dd10524a08811d15c627b3b4ada549a3fa1d8dd77c005daaf2addeb10" + - "0abf694da8dd692f113965cd6366a5a7b0c17e1f2a320243e2c90b01418e" + - "22426d0401a2c8fd02cb3129a14fdfa6cbcaa1f1c2f17706e9ac374a3458" + - "777761e986ee4c358d26f8e420d33230d198fd86704e77298dd4c40c5205" + - "7566ac0cd92993b21937c3a3b4a8b89110a97cf38c781ad758bdc28f3565" + - "60cf3acbedfa8e05b396d226ef619746e8e4fa84c8e00a7f0e6d652808c8" + - "9c9b123d9bd802624cfa949eb68af85ca459b9aa85b81dbc0b630856cb9d" + - "7e18cdc96b3c069a006dd5b716e218a5ed1f580be3e3ccf0083017607902" + - "a7967a02d0a439e7c54b3b7ca4cc9d94a7754efba0bb5e192e8d1a6e7c79" + - "4aa59e410869b21009d9443204213f7bceb880ccf1f61edb6a67c395a361" + - "ff14144262b4d90c0e715dbefce92339ff704cc4065d56118624a7e429e4" + - "cadf0b9d2e7ffc4eb31c6078474a5265beba0774209c79bf81a930b302bd" + - "0f142534a6ae402da6d355a010d8c82dc379ea16d49b9d859a7de4db6e62" + - "40f6976ae0f47bc583b327df7ec88f5bd68f713b5d53796e72e28c29e843" + - "6c64cd411d335623ff4f5d167f3c7b8cba411e82f03714662425c8e1bc1e" + - "fbf435d28df541a914a55317de0ded8c744a1c3a6e047590244b207bcdcb" + - "f4bd1f9f81210deddd629192c58e6fd73e83812f084ef52f21c67bea98ee" + - "17554437d9642e2e", - }, - { - key: "b41210e5ef845bd5a8128455c4e67b533e3e2b19dffc1fb754caa528c234d6a0", - tag: "72c9534aec8c1d883eef899f04e1c65e", - in: "7eeca180bb20d99635e36b9208221b2b8ef073fbf5a57f5190e19cb86c49" + - "89b0e8150d22ec3aaf56f6ed9cb6720284d13a4b0a34cd3d7f7fc7089326" + - "6d1893fa4185269fb806677ff490aec8f889896fca50d6c80d295875b1d5" + - "4a779b6d49305360b31011b48537157d0f323ff4e865d46fba6bd23a06c1" + - "46878cf9404360d325432312ff08ce495edca63a3c93c44d79c050e3f1de" + - "4b6ca5fedbbd43dbdef9ceb26d440a59c7e0be3a8e461c4f15b6b1e1dc36" + - "a71fc723ad593fb903e83d0804ce497fc49bfc6b6a602b9dc6e9891010b1" + - "4ca066cb1c68044c1ad837c638076dd3708078509cba49fdc54922cdf5d7" + - "715fb43e9b5a5942cb8950eade143577bc9dcedde58d51deddc70075e452" + - "bbceab1e95b5d003eb96bea69687faa6d50d9c605769cb4287b5d9924dd6" + - "8881c699abaa6f93e41dac7639cdbbbd0259099a3ed096f482a1fa322b15" + - "ffc379812c74e09e95f1bd3706347eac421fe56895e738a47fcd3e118773" + - "c3a7e7e264cc7ff5a53a80e436df058265dab9756fdf6913786a47e98bbc" + - "411052d58ffec9ee948e28cbaadaae471c5d828eaf3b3c87d3bfd495477b" + - "403da54f1418a15ace0d4d0df68f6a8f2b0457b127d5eae1f45ae055afa1" + - "8f058d5dd7eea559de3ae9378ca53f7d6dc9a9465ea1f945295f16ee0404" + - "7fc9dd3deda8ee32631d7af70c20edc1e12c5f8abd2e78f43dbd4cd6407f" + - "038efab144a24ea8a090a7ba3e6499345a60106220c2959a388e1a73d070" + - "1d854bfaaa86165a5aee934b615ac7f45da7c43a1e8f74613917ed10dcd2" + - "27e4b070414412e77851db5bc053e5f502bb4e2b2645bca074c18643e814" + - "4caeccb58be49ea9a552913c0616382c899635eea79a166988c206b9aaa0" + - "977c7ced89c4c7aaeaa8fb89b38030c44530a97187fda592b088198b63a5" + - "2dfad59a0a4c1aadf812bdf1881924e8b51b8fd4dbca8e73b2986b3ab484" + - "171e9d0cbb08be40ae60de8818bd7f400191b42c7b3200c27643f06720a7" + - "e0a17441f34131629388ac43955b78c31ea6602a70dd665f872e7669e865" + - "f6f40e634e8772d747608cd3a570e1726eb1ddca64f08582b022bb026eda" + - "6a913dc83f174ce3c18b9fc0503d3ac74e2fe45691d6dfb4af8c86d752a1" + - "6d6664fab4de08afe8858392fcc35cb9ea82fc42c42d48c0c0556267ea0d" + - "cc19b10f05e0318c4488ffe704b5036908f5cb938eebd3163503acaa874f" + - "592d945448fbeb93a877a26a72306a36e181745ba300afdc30cb7986919f" + - "3dbdc5c47ef1fa052a9e4aeeda3955f61ce2f30a0593a81dbaffebac5a49" + - "e5a8d1308352701d1ca9e620a67a89abdf5f0f8b1a0acfde5819981d4b77" + - "58799c0fe41030b86754837712af821c315301aa8dd50d1387b9fb92ee63" + - "10777e08229edd54e5e86b086ac281bd321082ef46ce298a6211aaa3aa4f" + - "6e55b5a4641220ec94cca73087760da1b1ac3e0da3f438214e691aa184b0" + - "535950b715a64d11485940dcaa3f72e0aa521002b1443f5e7880e2a85b83" + - "40d32db0fc4c4702e10f0fa24a35da9307850e945f608ad34d6cfdf6f2b9" + - "ff4f6b8e9eb5a883546578e2ff3cc5787322e4384640f42dc5bd05f432d9" + - "610dcf7c06cdf34762dd2a5e805e24aee8cebb3b4db9e4d1471da995bba9" + - "a72cf59ea8a040671b1d8ce24a3dce4fc86d2df85c8ab5e1eb2b0567c186" + - "4fb464f48c3ca72c7df2749542ed4d4be51b63769012ce3d06356856b2a4" + - "24995a2429a156ad93bc79c705e7b163149ce53a42c34a19680dfe4fd0f7" + - "fce38c30dffe9da9bc941d131f435c1398f8284a230e9d6e3992710074c3" + - "881d03aa309a9edd0fde7a39c33f6455dfcc5ae3fa20ea0e0d6549a43536" + - "b4cd8a2991a135b7d7a4265fb840318813091274414108f13fe191db7774" + - "6a5f4270f6d51a29ff523954f84cb76131d4abee79161dcbd97dc1ef24cf" + - "db1fade057dddee00a1e0de0db1afaeed1b535f7bb402afa3b297551fd14" + - "8c8f3e05f1351d3a8ee2948daaf14e7fc448c4670c906ae076eac5a7c656" + - "fd5f9cd937b91e26c9e5adb43c138f8d65e447b0022a524e059f879c6e27" + - "4ff7e671f75717233aae70853d5bd7bbb41b43c47bb08d6dc2f54f9ec606" + - "9487d1267add72403d01552a3d138abab9ca8a0d2dc32439759aa5695f70" + - "1a17d28dfb85850fdb55fddadcdde4d220e4b05821e5736d346e7dc9c945" + - "72743366488b1de8975184771361894b6520e3407c5c2e38473430969e35" + - "b106024da8618665d58c9d084824a28991a33658d6ec702139e01b65b7d0" + - "cc537a644caeee880657803d95f5f67816948d5ab362922f8ffbd531473e" + - "b0ff8fde2afc37a4abfa28dbed0be1b3d4ed48a1d02358e8403905d33b12" + - "3066e7a9fe2491ee9eb24fc9de7dbd322c8ddbc5ebcd0d92cd102ebac96b" + - "90e2fd784fd6d4b699304df23b17d963080a013794322690456be525c071" + - "b78fcd2d1148026e44ff14c4d0f942cd44d2b3263f4a93b79ec7a618b4b0" + - "d77ae7a1f6e6c7c7e2f498b825bf1954df348bae45ae1d7c87b6787f1212" + - "60c9a724429a4a2491ef989f65acfdc72fa717486dcf1984905218e11cc3" + - "970a09d71061e6df751f100abfbf", - }, - { - key: "d9b0dc303188756312c12d08488c29f43a72e78714560fe476703c1d9d3e20c1", - tag: "6b9782f2a09b59653aa448348a49291b", - in: "dbde1820035997dc8a8ff3015b4e0674e7ce7bf0c2d994b7977f2d91b49b" + - "f200995040daeb1218a0f4307b6b8211913992b070d321bdb947b4ba5017" + - "a0885e7e5502710a75cbbcb56d49e1bdc2bc2afa5a0e83851162dec41340" + - "bafc41c5e11fcbf4ea2ac45bc57def4742281bbf734777f83c9ae1ea3d5e" + - "d42380230570f59c40d5dd9a2d89b75fa3c92664f12a274d965ed8de79a8" + - "b37f3763939ad21d1703ad794f617c8b32b20cc4dd7c1b7f969a65e1bafa" + - "f6c43f30c9eba256f10201910e2cc31a9b13a46ad29257024ef8f2ee29b2" + - "ee63cc5b6230ab9f87cd5cb534f4b0bb08a790466e0d57b849fffa1ed21b" + - "fb0b27804e3ff9df7bebf14e100cf91691a493e53870abfad6321f6711c5" + - "0fbcf1f0b2c1e5231d6c0a08e710525176355f6f82bedc1f787f0d3cb41f" + - "a11e91ebf9f4cbae46035a371232d63ef0d8bda0355af8cd0a2f7d1327d8" + - "0ab769ea0f1da0f76ec99cc737b5ce84675fa8a9ac0c98342bb82b5848bf" + - "656d35327ea01a1b09d84ab974c307511af68a30cd6978b529a8f58c68a5" + - "9d476062ace8897ec0d1a90d5d167e29ebaa6f46d93d697760c8771417ce" + - "94c0f3698985a98702833d1b68641b811840ca3d935386dbd4600fbc81c8" + - "728c4fd0e4588be739a048f03bd4ac651ceecd7e2fb120fe7190011f957f" + - "cbbfdc025f1ca0b356208db8cad87fcd53c5d3a30a7c2a48140ccd4cdb49" + - "f3961cef742caedd1e848bf3cacafb0da030416bf3177877aa0bc5f9d1cc" + - "41fafcb829d5e3ace9394028683d712552579e024084a6b855830ad9f567" + - "ff58f05d3ec263eddd6f56adec378f167e8dabbeaf7d0a9e65c71660314d" + - "6c8d54beeca2711113fbc32a2ff8c0daa8373278d10085d2a0660ad53f4e" + - "1ade74a483be180180acf9e9ad3ea5bdd9162ccd69599163a451c6837d5e" + - "a5e115bd9a560f395128ea002ee739009a44fa46078b18959933fb6e866f" + - "eb4612a56ce93b1affcb95fccaa18d71a148582ba1412a5daa07404fcb39" + - "c3cb4a2519cc506c1172c6c326016ae2e5410f6a438569f35a50d45cbf3c" + - "c46188651aa22c257858f60649cee8c05c75953ce49358dfe5980445fce9" + - "614ccd16d333ad236e29d204691ca0bf46f29da954bcaae52e41016556d2" + - "f4cae1d37565bcbe84de1b49f344d0200478a38187da29c155cc98184d9d" + - "33dca088d70054e0fce321f7a90c48a14963d0ace2b4e7a24b21c14a5e67" + - "1994fe1f7d22d1135d4df9268dd18d323fde3603288735626a5449582d35" + - "30e2c2225414e05a8c7b987c873a82e272a5d83e59b90f3d7264631d6ad0" + - "4a0cf3b5e96596a66ed5bfbc24ab6e4870aeec0acbad2cc5affaee06de32" + - "dca06f175bf763cf8e7fdf95941a177e934f0078be7dbaa4c9b6f5c16b4a" + - "5607bab5d56144a6ba3c7d9a084b8d1f4b24b6f9754ed207b230d3a2cc26" + - "259ccc725e1f8a44c4df8143e13edb5ebf073e2c9d2da5f1562df4feece2" + - "f6480987f093f642eb7afa3aa92dce2a8b60bb925cd2d11cf6c2ae7d2153" + - "1a9c8f068d71d0e682023932fe64e956a49347aed22b21084c4a84480491" + - "244ac6b337b6d12d5551ad5684766c68bacca62bdcafab6603c81bdbd8e6" + - "80d9d8b3825eaea4df023142e840f98ee251466a0422d810a54726a9f03a" + - "7e0afeb0043e60e2ba4908f951d2e87fcbc372096f2a9f4f2a95ad5faede" + - "3796b11ecf4401c3ee3d268bd8c46476c61e0ffc5c43c0f3c58c79e20f75" + - "520c102aa3c260972a870fc50f8841fa0553a9e30bf37ad282fb51b34adc" + - "7a933ca1691a8a706605ce0b906fdccbe954f8e5f2f63c42599a483c4be7" + - "3a041ef90ad930fe60e7e6d44bab29eebde5abb111e433447825c8a46ef7" + - "070d1f65862b30418efd93bfea9c2b601a994354a2ff1fc11c383e7bc555" + - "9e7546b8bf8d44358b1ce8cb63978dd194260e00a88a8fd17df06373aa80" + - "04a89172a6051bd5b8cea41bdaf3f23fc0612197f5573f3f72bce39c9f89" + - "faf3fb48d8ca918586d4feaea7e0f2a0d7a6afca096a081af462ea5318cc" + - "898a9cc09e8258a837559570cbd5eb901e8c0e04ee88ba31c81a76b000b8" + - "0e544feba576b3eb5272b53e46e96a0b35b9c759caadcec61444f8ec47c3" + - "45a1d2304e2708eeddfbfa75a98eab3493889047d690e84431d445407fdd" + - "99560c0bdd287e0944116f8ac62ab992ed3f1e2b415aea784b03c6904795" + - "f4326ff60bc839615f2894570dc9c27cf928ef192047528a1a19ec990978" + - "3b0d1a13dd4baf4a19e49bf798975abe2ad167dd574b32b3d0c22aa4d9b5" + - "2761e8f56cf2100fe5a39fceae3d865f3724d4f299d07ff899fed6baf7fc" + - "eb7189357bf56cf94a6493e61301b43e3ed158cb9c7a0e615fd9888c2db0" + - "7f7689762f62ef6b3ad4125e06b07a422f5040c3aa8b8f205d68356c9225" + - "56fc4c976165fed9599daeb297498ecf744bf6c7dc5e30604c461ad99402" + - "2eea0fb6fe33f82a97b5c272fd24162a94b761ec7e52173e7bb42e88b343" + - "64f5fa2c141ed04a86b8d00fd9c25bf77a8dc3e63f5543331405be6bf421" + - "6a891089b316aa4f887cb4aff0dfb4e80c2ccd65ddd9daa74b17b4411c0f" + - "c849dc748d9b138279dcd9ebfc6e6759a53f5c28a41bb82107d71cc161fa" + - "81291a8290", - }, - { - key: "fb70ae7ec12264ff9f51124da188e5b11dbf53cae2671363f6054b575b1ddcc1", - tag: "d9ab81fab28b3be96fa3331714e78c9a", - in: "c62edf20b1d53962b42386eb570b10378f9764421ecbd7c4802853332747" + - "19ff4c89c06005050fa9ba6579a844060eb7ece6c43bab520e683e0f36ba" + - "49cba259edc6ae35d41e0d7812a7d5edbe4d90cd5e0504d16f4c3f70d01f" + - "5a0313de55934b661ce1ec317968c2c4de60f45c66cded8c10565a1ca6d2" + - "3a84bf182df2fcb05956ed4d46b49fc0fe3bd23961d9466fde070341ce41" + - "bc6e148449360a31634fe10e91082d82def90d9da2c250ea72c58add2058" + - "d046b4392b78bc3af5b3936ed568733e8ad5672dabbfa3130a6a535ec73b" + - "da8e7223535f49f96cd35d56ed4792c5cb7076720d5461d96a2692b2ada5" + - "2be08fb7bad15d15a0108143790024f0f15f5adc275e783aa56b70844061" + - "e30952a040e4cb9650f2a010417812790105d8f58bd25d99b0db3cb16229" + - "3f6322e86cd5b0bb1505a7b998fb0f81d1e1915faca3c2c8ddea39115507" + - "80339430a7955521839deff5b301f3fad54edd5ebd2ac4ec9b1795cb4dc0" + - "e2eb62ebca8e886c3f1e507d10a0228c3027b472a7104b815f5ec8dae55e" + - "0783ff7ae9a3e6b99e381ad788206b135520cb870ba0cdbe876feea843b8" + - "5a82adc95a6d71c555f798da92b82daf0abfcdbc82ec30b1f12d78490b06" + - "7315735017a94ac150b44dfaace151896f873923310ffcd41e91bac04de6" + - "d70ea71565948c907ab21c4a23703fbbd2a8de6d3095f3d8f901538968e3" + - "60e7bfddb9d22036b1c23f4f5f1b2ee22623426a2d5de68c1e1a38e38e08" + - "e2b5670aac1edff69e9c73c2ca56cb69c709009ef1d541aff1fdb2b40c92" + - "9b87f162f394b76cdbba1f5605993e4dd9c312321d59b0aa5c6e33be1b10" + - "bfd00b92d4c02db064d0e4a98f2913c89051b0f0ead163deb5087b6466d9" + - "84f57553b0fa53850eaa142e072fd91802eb9f0d2eb7318dd620555e6ce1" + - "86706b866d41cf6ba81f100342faa14d801dc6f3d522db38fab17a879fcb" + - "b6acfe922163505bd23a6842f6ef6397ae5fb6e6016421998bd43b0142b0" + - "3ca3b16d6ccb7a47891c75c687d791a930b26aaa2e3412e7aa16e2cf1501" + - "7bf6df6d2e1c289af0d7ce03954a60c1dfcee5e4b3da51eb43ddd14faf59" + - "082005d0c8b104561f66c002ff426be60be769282fc5685cfd1968df1941" + - "73667e48e9ad681d35757f1199f1d93377bbad093c8cc3efa2bcb6ecb703" + - "694422772d15aaa58cab9e9ab277ed510f684114cc4a44ccadb3eb1c9a76" + - "d8619a9b7743106df6fb6f927ac49b22ae5bb9a9a4d231e340a2cd0e3282" + - "53f6d75df694826f60e4b3e758398793eaf73ef5d4b56cd1471e16400f40" + - "4a947e9737f4f874fe09a29ad799f4525156e3abbf0585c3c3c0a3744c86" + - "5d56db3d2ecba6bcbb1adcc8bf5f3b2a2d46d3eba18cda55201598a8112f" + - "d8f14e205f0e615f081b8ff6c5aa6669da776bfc7c34d5af4d0b26d0d819" + - "f6aacc53cf3c6653138b9a962acee9d6ea01d280c35bb1f05d1509238ccf" + - "004c5013167f804d1780d9f4ef9d45742fccac346b0472bde24ff5db9ae0" + - "16455a3c02256358fcd8e6a9aae94f8a37a1a3da58a889bbe3d295e16544" + - "2e580f59bdd31c92ffcab40c49c1cdbb4db1dd4882b66edc10fcb1704203" + - "c518c1d8d4c268588ce13fc38e0210aeb47d11d2603d4b3de5c6ff5e969b" + - "9d5904abb282b699bd04a6e9f1cb323679e30400d725aab128a032745dc0" + - "be05a46b02b34b93bff02523cd8498c021fc35a488f164a70ef1ceb873d9" + - "14a681d3a3a34cc76bfd5a547e2630d7741a284511bae5897d9f7a197fc2" + - "456af5c6cd7e1a93d3388c7a990b5feacd7749cf39fdecdc20adfdd540c6" + - "9d330195db7cc0d4555ea5f5356a3647e2265399f153c34ed1e217c5dafd" + - "c2c5dd3d566c332c7ddacb0d76ecd3a0ad505a4165443aa81b0f43cabfb4" + - "62942fe74a77c22b8f68a8b1a6d712d1e9b86e6a750005a3796ba1545396" + - "13170906d228dabf572ab969c762f8b296054f23d5d4a37bff64bf9cc46f" + - "43b491b41101256018376d487fe8097f1653a7a9e99e1ef2492600598fb0" + - "bbb7df8270be8b9106126d6f491f8b342a96ab95df6133e883d3db4c6a99" + - "402aeb58d371263a32dcf76d33c8904395b9cf0016fdfc15608eb43e20b0" + - "99cbe7455f7a76f69bba058ef96f83ae752587485657f89c7f26fde7fbeb" + - "a82ede581ee92821dc13b8202930aa58bd4f1c86f68926baca0d06fee642" + - "ea8c652d226af91a9638a0244f1a03c7ce56969b87cd5c1f86110d192e0b" + - "98dd979d74acca6c1956b1127d9a1f456053d17974081ed8ced0faa4293a" + - "319e5b25ba285c1151214f52c283e39c35af51c4572c8e395b7856697bfe" + - "dfc4145ab4ed0bdbe43ba509c06a196ae6bf30d7582550cb546c63b51833" + - "cb0dfff7196d83f6a1c6d6d712cce2ec1989fd9ff5a0a22ac5022b49d566" + - "58f196703e4809e7624fe7cfa6c13b378f5aac7e66e657ed7eaa942d1a00" + - "544a947199f24d736b8976ec2cfb563433c49ba131bd08b63636854219d4" + - "c45100c98e3092773ef492dd9210bfd8f54cfe2cddafcf5c05468d90e620" + - "0c2ef99d17fa6992cc45eff3072b7cfd51cabb07ea3019582c245b3ff758" + - "0302e88edc2c13fc43646ba34de37338568baa66ecff3accfebad88d143a" + - "fd1c3b09ae39c501e3f116af33b0b720d6c2baf5acd7f31220788b2f9017" + - "3ed7a51f400054e174d3b692273fcab263eb87bc38b1f486e707d399fe8d" + - "5a3f0a7ed4f5e443d477d1ab30bc0b312b7d85754cb886e9", - }, - { - key: "f7e7affceb80a0127d9ce2f27693f447be80efc695d2e3ee9ca37c3f1b4120f4", - tag: "41c32ced08a16bb35ac8c23868f58ac9", - in: "5a3607fb98eaea52e4d642e98aa35719bfce5b7d7902950995f4a87c3dc6" + - "ad6238aadc71b7884318c2b93cd24139eed13d68773f901307a90189e272" + - "6471e4bf9e786b2e4cf144764f33c3ac3e66521f845f6f0688f09eaa227f" + - "e71033b0f74295f6ddb91fe741323f2b54f420cb9b774d4291b06219f1fb" + - "4410b55900425c5e6fcabec76a5c2424d637a1641db6f0f6cad564a36a91" + - "0f49894bfd598e91f38ceea65e8253c1284f210cf7b50a96e664e562f3cc" + - "01c4fc490fa6d4679fd63fbb3ed8995a8a05166b573e92d22ef4370c6aac" + - "74ae94c94177e5f71143c6f340efceefda679ae76f6ed7f26eaa4848a8de" + - "8c40894316efbb06400f9695b18ba279e8947c032a84a40ca647d9ace457" + - "6dd0082494d6bd7be4e7928e749c78110af8774a5d43e9c9479964e2fddc" + - "ee51146460eac734311225d08c60706e40f298a7cb97f369ef599be097ac" + - "3bf1c275497bbd68968a235fdf8a61bc7cfeef0fe451bb04e662ca39f34e" + - "a8e3acdd0befe9762f9eeb275c0cdd43c80fc91131d1e0e790020975ab65" + - "afbea81f303ebd86760821efb4cad7cc01fd6d6fd194ac5ffe7703d890d0" + - "169e21b444cdbaf691fc741a5d99bd47357c37785755fa72582ca4754a03" + - "b4def86ded39aa6d9eb3f38801077e6d17e3cee3fb57ae83f30c79c3cf29" + - "0e2739c6b7323612cec3a561ebeadb4faa642f150323aaa9d270658c907c" + - "4c1610a5e1834730c08be3379cf1abc50c30e2bf01ce903927c27d85e135" + - "3db9e216dda8860c45925e2bb791abe5c8281ee6d16607bdca87f60662dc" + - "bd6e20224e7f009a86db66fadd8e37e0a59559328385090c6953cd20bb61" + - "f28a734fb056714f5159977f18e5c5f11de75f7a00ba807e47a29e4da32d" + - "5c67ec76ce4d7b669b5e6ee17e1df7c673dd8a7c87fce665cda8adb9547d" + - "1dccbdbe7be44846b4b121b0bfa65e4ed530789510d79bc4477e50178060" + - "f2668ac8956f39ef422ecb0e4cf90b8ce508552eedeeefa6c7d1bccc077e" + - "8088bd7e0e6aaf0bda9f11c412c270ee2ad6912f9808f9344a4bb137bdac" + - "b5b9372b00b0de026a8f5d1fb13972e1290b5005689f7636c43aee2fd443" + - "93d390371ae573f0e064b2d7df552b9adf04bf173d71c621795b9fb503dc" + - "5e918536c6ad25ce4a76f70e6b752b6d44be321187269a19bcf33ec899ca" + - "40e88b4eb23217095a85057bf95d8a54812cae4a7d32e0c2966a21376110" + - "74c6c8c3dd45a553c43c675d23308709f91be0b235d0222aa5e1e1ce08f9" + - "c6b45ceb5b47bcd7d7b2d4380bcdbd6eced452d93e6d8cbe18123277889c" + - "7f86b15fb991364a501fbf5d8244f2e3332ea0ab49e833c6f765017a4006" + - "cc7cd1a0365945a8d8873cb21832b210c83e451c01ac949de2fb0f7a420e" + - "405bf64eb251c6f022181595d68174b91e503187d3b3f49b60c23e44ea40" + - "ca20311305b413047bb22e89672758b74d6bd1a06decf09e9556421087a4" + - "0c1d2c44c5fb13d4d9625581ac4ccef1a1b5eeb5689aac5c0291aebda276" + - "50daf9d4396a64d02c6d58bcbd609d9a0017880ae0cbaf02ad0f1fc8d1b3" + - "ec987ffe13102d77352690c9b761bf13ea0b3a8ebad4a0823817fcaab4d0" + - "9b0bf03486620761dc77a6ba007ba07153b17425c4026597473e78863cbf" + - "430c0e5e9b04a83ad11506b61b8d9be3aeb06b5114e0d53d4724863eba12" + - "4f3b974bdb0d02743520409910621cd730c97ca984fe2921c38055f83ee8" + - "c4611db92e52d8ea51d89203e89df7586c574df15f3a96ed5a10bf04cb27" + - "f9656b5b11cf35fd21360b029ab26e9a741c6b3e6357aa1a41de2cac6e85" + - "f9a49e3441e60a60e74f434e1b8cd4454b11962e5507ebf904e9d6c52a7d" + - "9722300517c434758fbd6191f4550108b143eb16c0b60094fdc29327492c" + - "18a3f36737e506fda2ae48cd48691533f525acfffb619d356bf8347a8bbb" + - "4babdc2ac866e497f192e65a694d620687cfb4f631fbd6ae5d20ac2e3a12" + - "4d85f9391a240b616d829ac2adceedf8f3451ee77e4835639b13c622ef8c" + - "48a181fc7598eacb419fa438d4046aa971942c86b36eb8e16eab67105783" + - "d27fc56f5b66f35451b2a407d4648a87ae70807e45bccf14983b3abcb198" + - "d661d562dfcb00ffc569ca967171746e4e36f839946bc7d2ea9a0eda85b5" + - "a5594f6a9c1b179f7230eaa7797a6aaf8628d67fd538050cf47aa654778c" + - "11dbdc149458c1ec2233c7ca5cb172356424eb79479b6a3eed1deb9f3278" + - "5282a1034ba165032b0d30733912e7cd775cdb7e0f2616b05d521dc407a2" + - "ae7dfcf46fbae30547b56f14dbb0ead11b3666666c45d345cd5dbfa200ae" + - "24d5d0b747cdc29dfe7d9029a3e8c94d205c0b78b56d5e18613b3169bd44" + - "1b3c31513528fe102f9bac588c400f29c515d59bbcb0725a62c2e5bfb32b" + - "5cf291d737e67f923080f52d8a79f2324e45a3bd051bd51bac2816c501af" + - "873b27f253ef9b92ba4d7a422e2fb26a35c1e99eca605acc10d2a60369d0" + - "1f52bca5850299a522b3aa126f470675fa2ec84793a31e9ac0d11beab08e" + - "2c66d989a1e1b89db8d11439ad0d0e79617eafe0160e88384f936c15eb15" + - "ece4ff00e1ba80b0f9fb7a7d6138bdf0bf48d5d2ad494deae0ccf448c4bd" + - "60f0788d3f2b76de8ad1456f7572bd0ffd27bc2836d704d95e9c0df34571" + - "9dab267dd805577fafda03b834dd225ad9714d2bd182b4103faa5975180f" + - "90d5d6cac1825a19b9d4c87cc825512ae9dbeb33d2759c990905050f960c" + - "db3eb364c15b593524c882902b2a1d7fe40ea3f54fb0202fd8821463c7e3" + - "4b02a1209ba0048a9805f0468a13e03d18009318ecd92042959be263a51a" + - "407f1e660632c4247419659a4e073a8e9cd4a226763a7daea464d5427270" + - "7efd053cb4efc0504602c4f63e7d247b55db2ce1c07138f585d16cec97a3" + - "0731d5aec2166cb4de41695feb76280cbae1af8a2e67c2d5a3ac5487ffe8" + - "640f308ace6137e83576b79d586b663122221c20aba7a6bf60f73958f436" + - "59f087f850ba6e2d7fd862249c5fa6b20e3e43d4f2aa10d4c9cebfcbdf02" + - "6b8d103e4f89b93dd8af172f421001c8b162bd6d0b847a58ac108b6d6cc4" + - "9c7a9ba069deee", - }, - { - key: "e3d21f9674f72ae65661aebe726a8a6496dd3cc4b3319f797e75ccbc98125caa", - tag: "3c95668130de728d24f7bca0c91588bc", - in: "baaea2b4b4cbe9dbc4fa193c376271f40a9e216836dc35ac8012476e9abd" + - "43dac6b9ce67dc6815904e6c84a5730cea0f9b4c6900a04ae2f7344fd846" + - "58a99513ffb268c6899dfe98d605c11e7dc77de77b0d30986f3051754503" + - "7c26be7b719aa9ca1140cfdf4c586b7fe726a8bc403249396a11cfee0a6a" + - "f6c5e72259785cfd13c2897384fe527100170001ea19106aed38f7d5d9a7" + - "ad43f0b41451e19989192a46b4f9734a774b6304cb74feb7d83822044a24" + - "2e51d55c0b8318e0439493bd1a57cc13f6079166cabc46877d003dcd39b2" + - "c0b90f6b32fc77acf04a6c125e11b35d91e2b18401cd53df4aff804e3c67" + - "a8bb3894b27c6e9b0070b53a85aafab0c0a253f9cfd4d3cd3be52428385b" + - "24a3f9f71660ca2c38474d14a0309e2f400e2c21af6e379099283ff241d7" + - "51da5a96a8dcbfdc43b913b29cc8cf8020eebb4a67f5bed31f2e383f8656" + - "8c815ff172382b425e95902e80f5fc219eccb51b656d37b56660f749e5b1" + - "4976a23648680a472d02ba71476e0afb29a0e084984f4eac3befbf8dd802" + - "2b7dca4dadd18bbe58e49c49ce48a06a71557a9a620c51e2623f818e4d62" + - "c2564c7ba04595cc109685869b183faeff2ac7a65049fc57cb10fb01951e" + - "a525332782d691f9759ec2ecd68bebb9c7aece5d522a08ce7830be520db4" + - "c9d60a2e490eaa0c91e37b256a97f84b39fe3c77953748c3b86fd84e9547" + - "a298c049cb28b8c85d59548b8dce635d59487c9de615802d16a8adc4c0e7" + - "80f35b9f10588a431b39b499dca929ab9d225f26e5721820627fe62427fe" + - "06d5773a50878b6effe840dc55bd3ea0c35168f6b6a972d57e8f88c5993d" + - "1ae33e0b7e9459c123753b518c184de7aaf429df078c9a18a29af77c727b" + - "796f5c1a501fa8105ee873c4e78c907142eb19690638a182fddb413adb06" + - "d66db19c7f6f46dac582bd72a6347b4427a576eb769d233febaf7be8f768" + - "337273c12253924f15653f9f3602b783703a81454a1dd7a8772a9ab1eeb8" + - "51be33e0c6c0708f3cc2012cabe8e2f0c38e35372abe27bc148fc4e1054d" + - "9d151f80aec0232a3a92dd77928a3678ebd7d09ba7b4e1d83227257292c0" + - "b8bc4a76de36bff6c9deb383029afaf4f37d5b935dc080a18665545e4acc" + - "195da0b9545d8902408886204b64f8548b32d012e0cdc520c17d9fb3be97" + - "800c2e2b945cb09a75a0a49e5d4d81c4194d91e839333b2b9b9e34d588e4" + - "e20cc1e911ca0a1429fa70ff063f0090fd842f89dfc5cc44affcce4e1e1b" + - "8b11c612f66b074c03ac2a055fd8f51ac9ed4f2e624589ff5730721d077a" + - "fb4c19e43abf8cf3ffa698362be8be51e92c2c91a4a56be64d9ac6d3fbaf" + - "5536a24c7fd0adaf74ca84c508e5e8c8bf7d4254e0c44158bd26acdf3f64" + - "e78438b3aaff89ac9986cef1e3a88d5bf2016340367a1cacd01ec167ec6d" + - "185d93a2a220d718b43ce1d429d2cb598605660b030e51e8d75fdbdd5b8f" + - "8677675e196a40a88285b18b24c5d2d594bab3d457e6f9e503e38cd470a6" + - "9ff8037c9a0a0f110a434335d954fa856a3721e0edcfb14287c3dd9639ba" + - "4db32b7da0670dd0a872e468e3819741d0d4ecf0a4f7a011bbae1493c01e" + - "642757491189f8664be3ec6437c4f3c76abfb0276e44a4d28871d3487c2c" + - "ce2f230452cb06184bb8620919659a7ba0a3d5c12ec25678b03403715ee4" + - "acb6a53d281036d8f3a085143cf5ecc3a0c6c92129caa7ac1f645c7bb95e" + - "4f63da38dc319e2ccff4a9006f9b9b1a38c4c39f6dc686bb82d43fb9fce4" + - "0c767d3ff22f52c5f9900130c65bb6a9cc7408a777d49b70946665f4a733" + - "5099376b276a43dc9a6382bb2d40425f6481b1846148434c672b84dd7a20" + - "33deb5140d43ba39e04ffe83659b6deb48629e1abf51e68748deffb756a3" + - "ed9e0807506b248a024cd509f539f4161366547c62c72933584e851599b6" + - "82ec16f1d79e9c6a01cff6f51ba7f46b67cdca09f3ab8496322b990a6116" + - "8d7574854a1cb1cb8f30a303dbd13a095df56dbb940dd16ce79879cd2d73" + - "80a419842fa1b34da668286de4c1ff5917b7aaa64713c349dc8f855d04ae" + - "de9a3a4d0739dfc36510b1e7bb1695418164285c44631b4b1a7c5798ecb2" + - "d976c1a3679a827bf0e8c662567e402bcc1354222036ad5959a6f0b8508c" + - "6a8c7d4a63e7dde154d778fc80a011592771d55801c7e1297b00b77f80d6" + - "314ebd1f5b3057398d1943599897cfabb65e7568d8fbdfcbecfd4b8a83ca" + - "0a7bed08ab9a656424831e0d7718c15727af7c83b2ef5eb5684aa044eca2" + - "ba896811246766248b20a325094a4b4159f9cde1ee349be6dc3c9a190453" + - "0349212a9537f65ae333c288753cd2bef6c5beb2f4164168d965a2c0fb9c" + - "c8c73d9e776e23d53ddcfb83bb7dfe2a1b8c781280f449d6f310faf8b53e" + - "89e6a611d6d3f42f2aaed5259730d149b3e7dabdc9f865bc1555374738c8" + - "456abe112e9628fb31efc2ecdc972da05987aafce728ccaed246cfcdf518" + - "3fe5dae528bbfb99d33194167e0f84d462d3d0da83e92227cf57922c7956" + - "4fe44648d87c69ad708e797972c44c4a5183fd5d1150a1182e3d39c3cd16" + - "3920f1d7ed83992bc4116d9351ae1c6c4827d1374242e374310409f32d5f" + - "0f38c78b6489c568b791c70394d29ea2516dcb10e51bdad862ce3339d5e6" + - "14fe14f150961809c36e0a2c8eb872e9f7a1c0956fbc9194cb63ff9993e5" + - "d0dcf62c0f49e81dbe99f3656c4dea57b766ae9a11254f9970618f1b33c8" + - "f339f440de240170f7a21f03ff2da42102b323ce2b9b7d0de5aae324d1ba" + - "c87b1e4c5279a566bf659778f8b03882aded57377a0f1b063af2897060e4" + - "23be7cefd4aa9a28479c16773944d254fc21d3e1acdf508b7972372b5991" + - "3b8b088e93471a7d54c6ae4c52ba465ef07f19f269677fc2f64d3fb3d7f1" + - "9069d6c7001d4b002ed6683c59bd5651a450503b68a4a00820b8c17e3263" + - "18f32c21dfbcb2a02a104edaeff67ec09533aaf3d1a7fb41aa5d506ccdbb" + - "e6e35fa0a263c0aad3acc91182addf8c5bdfbd0626702694b8d652a63c65" + - "8d6b2b7c75d015630de508195e1fca9573b61bc549ca017c4bd888194d44" + - "3e031f36170215a301f922736a819f3ffda69117170d1933300366c5f2ae" + - "1052446ef7c3b82c5868be158a881597132f51c91c80c24ebf621393dc45" + - "05fe057364a76ae67494a8a5f67acb551cfe89f447df272ed9c1509fc330" + - "2c3e16541452d4d68438f26858724012ad3b72c094b9f166c6bedb8336a3" + - "41e032988f39cf53535789b320b5424d07b6bf5f8792e3aceb0e868765b8" + - "611d7905089949e0c273e2410c72a146cd63981f420405bd883e5390e985" + - "8214a8db714e8400a21d0636d7e5d9671a3582ab9ff032170b8dd6b9d5a2" + - "144d065228fa54aea9a22654df67f3f62c5fc59d68914d8b219829b536cd" + - "2ae937ecccdb6031d94cb3", - }, - { - key: "84373472e362a356bd5c9b50f55c588d067b939009944f02564f136c62dac36b", - tag: "12dd5297cfcec53deae1dd5f9325d894", - in: "860d9b2954c3daf18fd67eb8bd9e6e3de2e4988ad9b04b1987219204dee2" + - "388db1c59a935de27bce29e7cd3ebdf038785efb35eabd4c3785a62b1d9c" + - "3ffa25e2273cfe5eb10b4ec6152cd8f21dea415421b452efc7cc4ea6bf1a" + - "b85fa6614e7f6d650125424865386ff8ab53247a63ff023b2d0753a9e5bd" + - "458d6ab0156fd3cf2d5002f902f927a847e8c4a8426b0a5191f5e237d590" + - "2659ce9be9024750d1d618a6b8dd57efb6c2bbac2930858f1132639391aa" + - "9e8a620a2a7d64bb7e943c77753401b5b619d95ef857df25a52b4eb97372" + - "a05416706b2644e2687bf1d42c0cf06e5eef8a1fc7e178440bfebb85c44a" + - "4837f69e43a1789728a999c5e04291576e757510f22bca11583a4e93688b" + - "442f2b2dab8d5ea9441ff09b8287862ca538ad979297cc75510a3d9ef36a" + - "662b4b7c373f184202befa5bf3f315642e6210763d033b7e2c59731cb356" + - "045e9470bf2f83cd62f11b3e904b0c0b1be99bcb805150ba7ef12b8df3ca" + - "bfc5055640687d710ab88e0fa8034b26112ebfd044a4b290b1c6f6d18c31" + - "ba9880b1cf2d81b5d02f00d6d351da5dbf47b6a5cb7b53eaf6de52c8a68d" + - "053602ccffa37ccb44a7683ab4f8a58c4bbc9e140e4e6f3cc10a5c07ebd6" + - "070818db983f9f415168606011efab6b8d7b4e61e8eadd8bfd8d028b89bf" + - "b0a16996252d7b4ee4f9ab50fc9d6e482ecf99beeabc38d70efbb9a0d4b7" + - "9a1c5d2835adf8e25111352eabd24d562644efc97637f695e4792f2049c6" + - "00f4d889ceb951cfe289adf159865d013046985d7fe2598014bf2dbbc528" + - "b4166fc2180e724ded8e7ea1c8d66338ec50d955d5594a0a7b4655338b70" + - "e8978485a722df814fdc6fd2436dbc060121fcb575672b2a5e454c1209bc" + - "2bb21a99d39dcb3c697306dbc2104d60fd8051c43ea2fce268987d0ec249" + - "a5c02f91d3b0dfee181b3cf8ef1ba9665daf7ea1f1d3b216e378943b78b6" + - "bb41e5dba095748bc776f8df6383033a1f5504955da3f42153b1c7ea83e2" + - "f90b990ea0c5bd3906b5c4060b19f447ec7762916b8766e5a23bc4d39cdf" + - "8e27752df8129b60ccee1731e47383b589d4fcad865eed4041a186df206e" + - "9fb69ab6ea092e36f186a6fea8d77bd7f3ab0fa0e29404d617317c75c832" + - "854427848237cfc18486c95f7213b9d53f324da036e8d298133b5003984a" + - "b9d71836f9f1b059db90005a9067c261bd85aaeed4d623df2220eb52b73d" + - "d683abcdee5cebd411996f853752f638bd28df6d78bec2ed3e00d7beea06" + - "2b81c19682ffb2f6abe3a3623a2e0570650c1384f1818d76fbefe3a7ef3f" + - "46138160ef897f9934e00e066e215230e719c23905dc60d7fa4d666fa52f" + - "e7737db15126d3262c3a4c385cdb23ff3b56c131e43b241f4a6062a1a248" + - "de9f13eb82c11f7b6a22c28904a1eb6513cdb11179067b13c7b5f83a58c1" + - "4f2753f19fdb356f124f52923249d6e4a2c8dadc8bb0fc91e360155a14c5" + - "c194334b9f0a566d51fad98592b59c1cc4b40eeddb34e64f337f83874884" + - "0583f853398c343dabc29b9444be1e316309fb8d81304d654b3d4bc4cff3" + - "55fc31278fe22e649324ef10acd247c0b72397edf96a1c16bbbef0640296" + - "4d219575fd23c36efc1fb8f8a34b510ba9bdfb3b478e236777ef7c6c47f5" + - "5a2bd0383d8eed3759456ffcffb15e61985b08c022658a5ffc875821bdf8" + - "83f69f096dcc72a96888c3af76db57a54be701759670bf05cc9015f5bf1a" + - "745cf755a25b1403a870875701427f820c4b29eccc260f30113629ba03e2" + - "785014bdcbf34d0c67aa6aca20d2dece811788686d5a45820d2980bf7d69" + - "d5c820a09bad7bd95166f63dcfbe8652565c285e60e2704955d69b3037d8" + - "7f5e6567d95b8891276d5cf7c59047d10a02ae4a28794405e2524ec2d595" + - "1b36ad1b9d5265fa098a033b88aa66cd9eaf01eea49c7dc4cc51c486f624" + - "507a2be23f152f43709b2cfecee44945ca506950e90e70164b77e12e1c13" + - "0b4d1021c2afa20038f190096276cd22e89b6e7dd10fd58fa033c9d42536" + - "98de3f4908203be8dbf259112f840c76726d982b4a837cae7139e27182b6" + - "1b4dfbcc50e42d5ab8532edfbd30f668879824e9ebc34b63ff1526cda81a" + - "e38352a774d79f73219500e57f0159a32326195d8895d965071834876a45" + - "c1a3c0bc4b1638535f7d40011cd5b23343fc27fa318c1aa3f9d8c43351c6" + - "6148dc2175e0e620813266da3000954dfa22048f305244629d512e852376" + - "6248a897a3ec3e2983aaa8a0f025f18feea57a5153a59b02604ebfcc7a9f" + - "b03e62443df88ead9dee955e23bcf6528c278a353f254c9484a67a7b263d" + - "a301923a4efb6866aeaaafd428e6da48781365bc49e90cd16b2388220d08" + - "bb9f79d14012b5a8299a651917b6a829488753b6ca449a14e8dd8c5fd5ef" + - "657d627b8e7773475b802655dc033694f24376e3b01e519d1aa8365d0e55" + - "92d0a4adbf555639b6d75d7ee59a7d12c6c11317b7927f11bbe75ed90508" + - "b0698420e231206704d22dd1f1740edbdcaf19a47d66ace4eecbcefb77b0" + - "85cfcfaced4d2d6048ce76434eb79990f0898adb4af2c377b581ebab3f3a" + - "150f40dcae002d4caa60050591c0de4ba83bfd59a08670beaa4641aa9829" + - "bdbb720d6eb8b2f3e864a98676a67271a82cffdca2b3590a0b5f97efa5d4" + - "ba062b4798707159782bedc75e5363d5f5d55ec2bef70db22955adf401fa" + - "c3b7af937816eb25d54d9f2a92e5a2a04bd8b8d7568204fd289f5ed2e033" + - "a76209d288e11e8a4dbb06b9029e90cb186446746853f02d738e06bba538" + - "894e03e2658ab3d7f9ac861d2cffdf12396004d1cd15f18812d3803ab9e0" + - "6f41c9b374d6a0678bb82ce06d9e3b9dbc8d2e90b8f64d0d040f3fa8a3fa" + - "8be71d2b3183cceae1bcbfa2353689d842f7d7052e5699dcc70ab2b58761" + - "7041e5aa1e2f41911d525505f061d3ca45152f5a7a1fab50c674e4597a52" + - "b46aafb4ba57413879cad1308321843abb7c39696fc2f2e225878bb1191e" + - "e151cc76f1a1b8d491c1672fecbf710db82dcd32554361967fc839c8e5d4" + - "e488856e1b9382eb3fc3bdc3b6886a3cd79761b02bafa080a745ef6afa26" + - "822f1d10d5e8eefb842837d82c9986e78fc3390caa142b7643de8f613e5a" + - "890a57f5883409549537f8139534f4ca1b60f33e42be25433f1d82add530" + - "6a4cfce258c0d4f1f3c9148ffb5c4b626d51f78ac20bff0393b7fdb4b9cd" + - "70fee7f69892c8a9ee089c6c5c7bee0a1b825e5b9517f2c82d6c149735fe" + - "45a8839812c2deb2a355b6230697053092eca450b7b0d3242b2689efe364" + - "09e820d91fa4932034d96495d9dd3baa4b385da815a7cb69438ff648b326" + - "e7efe8d688e88570ba59df7c439faf72c95317a10c984c5ec0043407e9fc" + - "9b46487810eac19d2bb40e0a654935f76e7d8861480c5f48419eb33084d4" + - "0e1070e5ad542c94f58b49e67dd05b6637a2c67d41451b7e00ba30eff221" + - "755d6d427ec634a2b95980d274a89579feccf1c7df3787a9435e588f2496" + - "06a93b7ac41c8aaa84b91c95cad9463d4881de7353d95b13bbde4c9da90b" + - "f1fe96257309a416407c64368b5564f022c4a493f2a39df1696f45801e42" + - "a5", - }, - { - key: "2d0035a30d19b9cbc7a27561f3ab474c01115c4499b4adec660ea06ebaa1a14c", - tag: "a2c77b55cb0c076d8ea83cfe0e64f293", - in: "4e667580ba4f38f64e5cb5566bffb486dcae10cd17acb3754251e837767f" + - "16429bba2b832f29ba538f97f3556548d163be25e69f88fff0743150623b" + - "e0a1d82af9384ca335927a0e9cacc3dadbdf1e24fa5c81f2602d109e1400" + - "33929e409b9a0fa4f2653944edcb8b3ef963ba7f8806196c73bff0ded670" + - "c6def5d240c5f3daa121f8d5bec9b2a0b0f1d62d54b013dc742d6bd46325" + - "460f692b76d4991f0796820ddebf150c7d33829795784dd2759b334d2706" + - "70a7264941be5d99d460d078a9eedc3660cb3176ad302f9365f0bd698e46" + - "9f3e63511abc81109995dba17be1abe8bcd28407c7fc8d02c14794bb033e" + - "178a94f6dc73719d5bc235f980a16eccb4121ca83b13c4e165931ae4f192" + - "4292f8cfdf1c3ed40feb71e13d919b48fa296dddb4d23114a3d86ec10f16" + - "f314de4cef813ed24b49f4c7bc44cb8424df1f70e8d77366161c7cdd709e" + - "97610aca3a24fb2202ffe15eaaa25d711cb5179212a2c6497a13e5d7c365" + - "7bc502b3d2ebde2e57b714dd9bc21e73795f3d35d620613918c4c9aa0e89" + - "031481c97a5a4c15ec6abe42d40498c33d71c823bf1d5bb5fee457e2fff0" + - "bf777c80c6e3336ab3ce793440e74b336a8f7034f6ea2e4ff5ea4ea7c350" + - "65cf2ccd2da1d6df29bde10f4cc0202b5e4cf7ed097da49b970a6db41e5e" + - "98f3845b42f46663b1d1ff01da71389a8737ba8f51eac1ef357ba5ac9a80" + - "dd2c7f9476111dcd651fc33f4c86dc8658656f3f02a8878bc38ff0d0a1af" + - "2e31fb92eaef08c50195490818661feaf90e8b6f5daa1ebedb2cdbc8d5dc" + - "16db3505f9611ac46bc37931e02c1fd6aad6e4b7e187d5e6f990fddc9563" + - "2b33f55bf68b0db3890b11113ecc839a4fa4de25160e574289aabe4d8fb7" + - "9cecf9d2fa75ac8d0195beefbdfe0815f8d7d9751c1280a29b547149ec7c" + - "2295f5afa53cfb516158086bf203357eec2a5db71143f996c81555a47f92" + - "209719a71570a5553f1ff9b4b41827dd74657b463f36623565f0c9f4d2ee" + - "8735d6af56ceb3b3d0ec516b22f0ddafbc24647481f61ab169e2616c91c0" + - "e1f6a35436598ed801670e1dba76226cbd0544959ebe70f836c8a7df575c" + - "b907d780ed5aa0d6e4e8e0d2f457efe89a777374aa49d4961db96dbb787f" + - "021d99231001360d532a70ee1fb94bd6f26524dd4b7556c6d40e08723d7f" + - "9905aca66c4743f2bf8b34493bdabcfca617809a867bfe0a4f94c756a6a3" + - "dcd04ffc0a3ac671a0afefe0d5d447efcec48c6368998760db6a572676d4" + - "29b6d3d6e0c815650447748c4b27541c5447acfb8f7261b6378f3fc0fdd7" + - "375eb9d458648c7fe9cd96344f11aca912cc5098e9ee39e0b6794cc1dc2d" + - "f1b10f927102705efa20e667b63a91f935c17764650b287f5289d5790766" + - "555f31985c5aad94c652ba41fa9c0195d15405f1fcce9e23054a42c8a252" + - "da83bf6268782ba44edec5d8f94a20b1830cd1c5894cc6b9b52ad0b12a5e" + - "cf3195a32a0b02483ae3b954ac6f3af1e0f334221279d03a72138f3a2cb2" + - "1e706427c4d604674dab88d429f28a67be7a996126e077a1dcf8989d90d0" + - "8b08f4abb9a546b3c64ecaa287bf3468c59add86365b885f52afe13ed8d2" + - "69ea61832a7ecbb96ff3336f58a1eeaa6dde3611f3ff7c2cc8c9b745b0e8" + - "b5919914245a49ac192cd77d10deb9a249623f696065a532c20eef9e9b0f" + - "e706579566a9eeb14d4e8251a7750e29eaa60f034c1a7a1d51aa03a45fff" + - "89acf41080deec5506128b06f003fa46bc4021a82fad6a8052a49744ed69" + - "45bd9331b5ae80d873cd042bff079b2b9d8af8065a22c449c32a56dbbe7a" + - "80d0f3e30b9167532506915883dce0aa9cb749e4368c595c5bd33b57e36d" + - "98cc9bf91cbfa47331d69b5cbe9c92bc66c0fc9ca8717bfc108e1f710333" + - "14dba02a28b9aa05890cb01ae9175806c3c4215bd446f6cc96ec5d08982b" + - "4f83cd1646160e1d306b3cdec02d251f0901b03e8c3c35464eaa5082586b" + - "b55482db97599d513ed8d7a82e32fae302684b7ede058474c1fac7893444" + - "16fec93fb982accd162dd956ba2f31a894e9366eca00e6e997fbbf9a2980" + - "8b83a139f6432147a717381bb8baa2205715f735c1e0db273cdda6897c9f" + - "39bf0d7eb7caf93f657ef4d3fecea28baf69cf36d3cf347081df3114455e" + - "b4fe3e49ad3c3f14435e0b39b6c0d16db0fbcfd7ba8da8760d5952c03667" + - "251e7a4c3008cfb0904225e55c23b884bb09d26631650460c4240bd5a165" + - "b531ee76ba5749b3bc60adad35de519321c1672b47bc35fb59f7792a3495" + - "11b2bb3504ba4a28717823a27a1f99ce6970290b26efcf1e7a0399b10eb1" + - "0c1299c09b80f4520d00e7908d004d5b6a72a411759cfa9523f6b2912234" + - "481b1d8fe4c2365961c0528bd593d42bebb398b5836ae6ca013fe440adbb" + - "0090e8ea274f4d8bcae483e3663051a328f7c12870b40e4973a9797a2336" + - "3d3c53e1b0d1a9159bfb26158f44734b3c34b571be641bba2db937d4ae1e" + - "edc807b95b1c2a7d44804885536316ad38aedf0d83b1519661f2bb5283cb" + - "9c50dd61c3753433e988189f26962d1f4befd444257d0b6d5b819d5fd572" + - "22c9fdff032e07a4d8686d451e71de4748965309c0a2d7c422ab7cf3d96a" + - "8c0a1b0afb229debd1c9421cb828b9f2be96bb9d6b5be7ef8134bd9ccf81" + - "51620937d720d83dbdddbfaba8ecd2eab6f1974090efde0ca963e9fdd691" + - "ed0cc5e074c5780779222552fa46ddcd951763a32aa3a044ff4a73cbab41" + - "dabb3c2c03fcda68303477f0dc26f35bdb5c9bde721fba1a2db732a89629" + - "a8de3cfebc3918df1a9d5053d09da5b7316e3285bf62156ca28cb64d343e" + - "72445fd66757bf4ab374fe7932a65f3d7fb6e42cb12e5b67ddf8530383a4" + - "6c1ee7ec8883e454a467df1aa7e468a6e7035515f473901efca5d46ff358" + - "70e0cc2575bbd7f8866c8e73cb157903a1694ff3051424f28de826984dcd" + - "065dc3658df144ae3a6d37b88c367e3cf7c58169dfdedda4a2821ce22188" + - "40472ff72f0dd1a6b0100555ff188b80f835259a634405e3dad61fc299f9" + - "307e27503b2cb7714bf3b636cc64b61d2e374119c8ef8adb21f1516c7fe2" + - "38c807818065bf312003c12e02525d69d9629a99e4ac66ad2e792f302cd2" + - "a6f5f702dd28040738a084a7052f2c3ed0924c33b7a5d357b7c9a29cebd8" + - "621a4bfb7bb34676ff210d59f7f9d4eafb7c5c490c9ea48402af5bb072c4" + - "731bdebcbed4e8e08a67931b6d7342d4ef7bc4a75ca1dfbd32ed6027d8fc" + - "b71e3f55565c02e06daa8c579b69774889181291c470576a99e11f2c5acf" + - "77e091ef65ed243d4287176f7f6ac7aba6908c9ff1fa43b894a499b642ad" + - "c01b2fa1c4b58801411941bb448f1f7a04794d2cfe5db1be61f7b86d6eca" + - "c547ee51d4c9050f9e9f318dae958c150acc21c878f0c7df6065294eb1d9" + - "a278c920838a0db752b080a32e67ac312fa76b589a385f31847196076ed8" + - "1021fcc375bfcc8e1361878e2693860eb21ff0595e4eaaf7897f2b79367f" + - "7c4f711279bf0c93a97dcb1cd8d87e444ad5f4cb5c1de44e37868c6743f1" + - "cd72cec376726f26c8bd4836f9a9f9c68042f95ca6f9d7cde493e531c553" + - "8bf7ace6dd768db69ac7b41ce93e8ca27ff20a83ff2148ec5b89e05d8b8f" + - "5d78d0fe16b96f6eb8d3b20126a186085c6825df81aa16b3dbf57eabc360" + - "71299ccdda60e250c652408d9cd1da94d73c728440ae08fddb901aec0fac" + - "1050a778b10f94f84883bee158bc53b1c001807c43a3151fbf581b18dda2" + - "527430872834e5c380575c54b7aa50f817cf3249fb943d46933cad32092e" + - "bfc575bd31cc744b7405580a5f2eabe27a02eec31e0d7306750adbbb9f08" + - "c78cb2d4c738b2274c7310cbf8dd0e59138b6a91b8253ae9512fe3d7367e" + - "a965ac44d54a7ed664e5e5c3c6c2d942eac388cd32beffb38f", - }, - { - key: "2f29d71d73f7af98f96b34e939e1a21e2789ec6271b878bbebd14d7942d30080", - tag: "ec02f4953a9a63ab6f2bfc3501e4fab8", - in: "0e0950987f3508239063e26a13727fefcdfd2cea6a903615c64bf12d9ed3" + - "887f9b2cf7ccaa196ccc7756b09471475b9daefd4261e69abd23b9faf9c5" + - "1fd5d5788bb39d3c068fa6807d30f6201d3f6dfd31715d08b1733440cde1" + - "049608d23c4e45c5ed61f863350232f85827e7c292dc5f1eced1cbc912e3" + - "f5c420bd945911d3881ede5153d3b2cc85371fff98d2caf97cad6ef59001" + - "4017f9690cab08989851c2647e77e81401714a93ed9f938b79f8f54e3133" + - "fc2cdef259df2ba0d48f37bf9e43792e3a777214cf4aab6dde6deeb543a8" + - "813b71b5974136c1220d6218a252881f0f5677ff5b6aba127f19a5f3c5aa" + - "c988543d7839a90a3f947c4e4d5c6ae1ab48dbd40456d1aa65339a4c15eb" + - "520e8ff9f965ac4c37735937cf09942e7958f8a6cddee41707423f715903" + - "ffe0d15af8c3140d3a736d23be7485fceb9f07c6509f2c506eda4ec9d30c" + - "cc133708f48d8828e332808c84a745d337296d871b9794de1c5d06534aaf" + - "65587526a84e2521f8b332645e0e72564bb308ecf99b7bc69608474389d1" + - "686ffab8c49b7f04dadc28d2ecdd0f508dad2135843304e378b3bc7a4f25" + - "7fa4316be956e0a021edb8045f39fa9f002087f067199bd6001acaadd261" + - "4bf6aefd3f098f92a959685f24bb2206c347359d9c6adc6847117bb434ac" + - "6c40ec618f6ae8b75a5e2e4d44c332b7b06c8b4d521493b9b0bde8894209" + - "717a24b320214297b62dec741cea018ea681c9b56702068528b3726953e8" + - "c5e4ccd5029e4183e772d9834a56a88d45bf87603dfda40e03f7e894766a" + - "7623ab4dcc0dfc3086d17566945069173935916f772e2a5f8e1547348f28" + - "782400fc069ac0e2b94242e9e0f1ba2d0e76898f9b986540e61ea64d7f69" + - "1006b86ce61565da75eb16a8b4c5865ca4eebdde2190e354734bda94fe7e" + - "12ff47dcb5d5e6ad93cfadcc491cb350b09ffe391a157e14b65e3a211b5d" + - "4e447c3ff95571dbab33a83126d68dfddf9383b4359d4103ca64af1e6963" + - "d09e17eb944aa71e76711dca33168586bfc44ebe9fdc55497d83f238c66d" + - "bcb16063bc85635f0f1a6280563bca49ef971db96a41b6ac5e0642643262" + - "61eb4662f3d6ad4cac826db895de22c9b8aa35e6464a7f44e1ae7238e355" + - "068d68754ffcca76c50b7ce7ef9bfebac9eeab32c87d059cc7ef2adb5d57" + - "c7419adb394eef48441952253e8391e555730e29789d6293c3696f441449" + - "0aebe2bbe541e191a6652ffbec1192f0f9395b7ea370aefc1f1cc8438035" + - "d7681f12f1e11d6e334da188b10c302fc0f4bcf1de448090510a8f1d5683" + - "0c943a3c388b33a038c26741a4cf3487313f755fe7a28e25e44b5383c5f4" + - "cd6ef34d7dd73462226281899dc3f2e69809a0150f694673f31addc89888" + - "072a7d4ecd63d6b90540f9522ec05829a7f17d48728345ad808fb0203883" + - "3cbd018d612992a88df944b8e34a70920b3f26cda2e8bb16c3aa38b12b33" + - "b395c9ba5e809f60ff05f087112151af1b5987403cff8bb2dce79093f431" + - "2c744f911a6f3091e4f9ef9375c4dce4c241d2f6024a1797321851ca316c" + - "4e460fc060e7839deaff8ab5e8bf682c0f21ab6952eb793cffe690db911f" + - "50b11f56ea352942c43bfff51d4360882754faeb7cf28b6b32bf7fc9ca71" + - "fbfe1d72be05b8bac9ba513d731e2c9d13d6f2f10eb926edaaf0e3996656" + - "da8718a8e103c59326529e91ebac6ed52657c9690ccbf81028cd9fb189ec" + - "4de94fc0771e53302c8d9082835a68780cccd772660a110a1b40c57bef3a" + - "c1d69428aea549ed17663a96895a66a3bb5ff6ff61dc64908df49b760caf" + - "a5aff05e2766a418dbaa1e7d189a9edd55a04fee8c9d6e506d299abc36a9" + - "d67be035fea5d220f41d081af67615fe627c4dd04bd8659c7fa4f57f35d0" + - "db40d9684aa178d7483ed5d86f04eaea412e0ea05a4698377dbff4fc3a39" + - "1f6ce0cb833d3118d6c69319b511cce65fdc74928e270da0c537f8201eff" + - "77416155d4a39c7ad38c22cdbf7d2b7ff7d85383c178a835ec604c3f9ee3" + - "7399f7dd826e34f1a35ab75da44ba56f86097ddc0f3658ef5bd65a24f4de" + - "4255d0b03411a9d7f0ddc29e33cb865da23393471aa94e6c9e72e789206d" + - "3ba118aecd39727068f528f01b25fae2280d70033e4ee46b41b864bb922e" + - "001d8bf46d6fbaa5a594e926f45eb3a4d2f074506d7834b606f43c89699a" + - "6db00b374658d9333700894d440a712a1f25f5538f9e7c8ee57ae7e612df" + - "13292c8ba9dbede4fb77cc6c8944aaef59ea6ad3b36db398f4bb0f82d40b" + - "44879835f224d6e05992b1b8a68dd58c3dbda2fd73786492ee48c7a25f87" + - "264b766930fe9427487504fad17f8d230934f044e49ba219f26ead728856" + - "cb30eecc33a3946d3b1b781061f2458c7c46f6d96f3e06f369f97be91835" + - "f23b38347d1e381ad5be4419275772c2abd549522a0203c1ee9c96faefe1" + - "df413c4b7b2624417890e0716854b7092b3b3b368cb674035d3e6bab2357" + - "e7c262b606f7141b6dad2f6145ebc1deb7597814719784f3c17848a90ffb" + - "cb0289e2f3cc7da12442b837c4e47f468bca3eb4e944a31c48562c2f144e" + - "9e920ab5e4cf90a14ccadbae29af13db38cda911e3c8f6f525e6722809b5" + - "31a4de1926ab12f643d25af87eb8610df59eded6ec278242247dc69a4213" + - "13f7c2b26ae7a917c1bdaf66c56876e9104d40b59e6ca1431ddb77fc89f3" + - "14b46a154cf127688564a4f9e120d7b5816cd24a6e095dc8ab8b43bc3639" + - "329719f0e0f723e2f5136d82638e2249e648ebca67cf0306741e9e8d45cb" + - "903bca85485c4007397c88a1ce07266f4f611b96b7e0ace3074247a7dfb1" + - "cdbbdd66e25e172fd2bda74abde7f3b4cb5cc7ee7859f053b2f04f9de03b" + - "a8e96264117f502087c3ddbee8d850bf3618b4de90f7b3e562dfa57e4426" + - "5357236e35e71d1669226d63bca50b1b944ac07a1f794e73e80985689b25" + - "f18fc709367d63b8639d71865cee667536040be827145c08cf3e57a66678" + - "4c81115706a146eccadc7aa1a9f074b47e95bcba7db8108a13279077bef2" + - "64699fb87e5abf5b05ff3879d7c7c5169c7cae817c13f0859d4e9c05db0f" + - "74c045ecc30a51e515feea627da387ff780719395b5b9ad93179b16fad10" + - "5856049169dcebd43a7f39c549762405f807378e854b1654a1179d895ef0" + - "85aafc72c7fe1e0e1cd3abf8e20935e331145bbcece4f17ad24ebb6c64ea" + - "73bd98a7494c134859206c9422f7c4a057db0ae0770c4bcb08c1a6b9ca4b" + - "7dd8c1cdb3e4977c7ce6c1e79b9d6ad98e27d2759b53cee73ec037a8b686" + - "f1ff78eb8421f41c74ce9c62a90d38b75159ec925f232e0db71362f31e29" + - "4336f5580a34b26c5a01ee3454cba227c7f400f6889a319d7121dcea27b9" + - "584f33ac796d48a9a24cc5b6799ee12f10725fbc10d7cf83e4b87d9c444b" + - "f43e2f5ee49d8f3b531ebb58fed4234cb8bcab1b8b18bf50956506baae8b" + - "c1b7492250f3adf64294310387f1d4bcac12652895d4f2dce26f380733ce" + - "0b5820e9fcd8512a1585a49940a32fc8875ac3c9542a4270602e5e97e720" + - "90ed71b51badb775340429fdbe45b887fb9ee61cf9e091c06092cf0a2129" + - "b26572574c46910cb458bca7c63eddd29d89753d57e568323e380065794d" + - "3fa1ffb874543f5b0ddc702b087e91e22604d9600d37fa0dd90d7acb2458" + - "4cd408a4e66bb781dde5f39efda6a8fc26be0d08ffdf851e422ab1500c28" + - "bf6b4c85bdfa94e8aef5cda22870c39ad49c3c6acdbb3b0d58cd05424c65" + - "20740b5c2bce4336545eda12716317df58e6fb764fcb3004f5248c5ccd84" + - "f63abdc0dd2a64e447c0de4da4a1082a729d8ebe14810d396933085cde18" + - "318278481fdb9a748b637cacb491f5234bfe16b53a35da6677336baeedb7" + - "4a28c19a412e7812dace251446d40ec07afd63854c3dffbd5c0f6a9a3cac" + - "ee3bab07fba94800fd1fa0fe44f5f2ecb2b4a188cd02b8a2df0728347c50" + - "7d0cc58fcd5d54dffdbda11dd1bcc59758396ed8db77498fbe13238d3d8a" + - "0040194dfe66811542ddaa658094a9580d4e4b4e29", - }, - { - key: "1285f117bd90b70ef078ae62f37d2218419e894b7d334759ddb2d88833b287b5", - tag: "429b2b39195a10357043c9601590a277", - in: "00ef065a1adb4ce7108b497813ccc748933fa8442689a7cb8dc7c1ffdbf6" + - "c09adfe05ca2cc5ec3acb7493f3497ee8f9cd9bb8a4b332c18e33f78114a" + - "c8f9a72ddb9f13494e934ad711818909831013ba195b53f5e9e5b4689399" + - "6d0b669f3860958a32b85a21009d47fddbc8697b7c9b92dc75d5060eb4fb" + - "40aed7a1dbe69dbbeb6296f5467ea2426cd17d323671fa408855bc53e5c2" + - "d111203ae38cecac7719c0bd7f21f6bd6a1588187b3b513983627b80ac0b" + - "300b7fa038af1cc8512403ac2cea6e406595202ec3e74014d94cf8780ed0" + - "33c570e887ca7fb35ee4768202aa52427d02c24e63f7f2cede95ca9909e9" + - "dfa86246a27db757750667c198c9aff4ce348f7ac51864b36ef5695df713" + - "d17b8f561a972d0136bd9ee9aa16079c2ab5d29ac9ab472255ade05dc49c" + - "b966e0c1c04258ef9ec59ded01f402d9fdcd9a2020a2038a8c78892ca218" + - "30136069485527069132959dab2b81c73ca590fde2a7ecff761d95a54d63" + - "a2664aa5a6deec163e46b5225bc98976a4f363063b0f42e29f792d138af8" + - "eae68d3854b5c1985d5cd1c9f49f529b0b4d2c936887b5b92cdebacef992" + - "c35e0b7bbd52114aff8c6b261852e28e451b02099814f809b0289cba0586" + - "04a363e3f969aad3d982f645ec4c549f943fb360fb8fa0d5a597bf89842f" + - "8ced6014a5b2590ef71524a7ad50fe0ef0e2f81b6e26b99f9ebbc8036549" + - "f7eacbf6ab884710c6406ff59788e03ede35c30d4781ad5af171e0623e8f" + - "cf5344d71165f0475e256e9159040f702b359a2963116ed135dd6c1d111d" + - "2a1e33e15c178ca4f02c5fb15593c50cf9a8a492f01e04778dbb81d26c99" + - "0c58cf50a9bcf4fe38fbfc0fc0685d8bd422a773c7bce649f7a86c59118e" + - "f5f857b2c72508cd1ef05e1a0c0b7ab4687fdd57437092eb49bf41a9ae8b" + - "bd98272ea2f8ee2515ff267fa6ae892c266a7effe61ed54984924aefc461" + - "6cf483dec024ad666bc797beaa429a742d1b8806f67d451b6d3a85b4d474" + - "003cfe9e9dd906df47da5559c41f15afabecc3e6af279cca0f2a200eb2e8" + - "31437e034d457fc880f60f5ae635690bce82bf6d1ad6b4f5344ec042bf25" + - "7d010273c861e3ac516e9ee2bab3a255f570baa32298467bf704bf6d9076" + - "a4c0b08a528a05cd1fcbdf51f3885fbaba7891a144fc058919903b269b4a" + - "29f43926eda32c38853b814a7d528156c223748d674d8f7f5448350f011b" + - "bfab1511001b8014e20fee37ccd4a0456f638c197c86dc116b34f955c0b7" + - "dee10bac5ea0c2fec8a780ac05098b51b902ca6afff4db3c6fb4f761df79" + - "b2039dc5f16d9402442a6fcf6c4297769e6c36824d908beba8e584ea0b3a" + - "91b9017baeefac651d0307bd89f517789236c0693c65a5a20f244d39684c" + - "eb810cd2ffd3c78fe9285d2eb9f55d133b86113efb8dffcbc6d258e84c38" + - "2dd8f4d7d63b65672516d9bfcc3310a79ce244b60d380128d529487f99b7" + - "d532d5f5c28fad8b9a071fd2fab8fd98f6d7ed9dadbd2fc4396476eba6e2" + - "1a1b1cc594a31fbd3418d98e4aa736cab285a2786fbbd4650e49f9b080ed" + - "3fda34941c28d25545395e1408fc3e60730d0696061f821a4d24123cadf2" + - "3af3d37ba7ce1ba3cde1368d468f136df82c02f9be9210022192aa02117a" + - "ef5ff70bcfeffd47bc37b920826a4d3db001f956939abc0df520f3ec1613" + - "ba1c4b3385cad97e42bfd15a3150711fe86ba4562f17780cee1cdf198615" + - "ca06270db84986f33e1d53d552b0da82397c496a23c7a78ca7641a908e71" + - "89249cc657c0431f1e09ae0213f28a27e6267e9d17b5bba0ea4f3c21f266" + - "fe538e215ec62f85517ae6bd87799ac5ce68453f09cbbc50d6e2a168f0cf" + - "7166ad50cb65b6c76406c326573c00e04a3186251c6181933828c58f4198" + - "f8208c4484805639b0d428fd05b57e4356239638f458a84000c7a7a8de62" + - "ec25b54d1e39d2579ec9c512fec475f243576f35efc02a1cd6b0478e2dc8" + - "be5f17aa4e3849cd42e76fbffe6e7d6f912d6edf80f718f94a7e48e1fc10" + - "6cac29627d9d4b82f05a30cd7c739f7f3ef7ea368d22612f189da450e274" + - "de7b61c6361521e684d639be5af4cb11fefa5fce6f8a5065c90873e504c1" + - "2c940571ea7bd7e9221129b83039d2edb069e8b5bb68567d8fcae34c6ee0" + - "cb94474d8b056cc3c7403873f2fe6db3b567a44e702e4f4813b2a264231b" + - "0a998207b41916715ef94e5eec281589d0a711f8e74be32bc60f43d693de" + - "77f21d5f7eef892abe87725f3d2b01d9ddb6dee15f40735a8fb67766dbcd" + - "020a93b8eef4361dc3a891d521551f65dbe6e3f68c60819b0a540b0991c6" + - "4449d207cf5b1c198c17ad6caf3adc628d09fa0baae7a696d84e1879577c" + - "ffe9b3f62669d4ea5ebab6364f08c66d170ee4a94d61fb77d60b33dd6b60" + - "650f034c5c9879243d5c16f853dd7a89885a9047a341b076912d47872b3b" + - "3de49edf7451b435698ac4e182d16c339be83e18531a34aebad36c5c7c93" + - "aaf121cf99ff92d3844d40740fe001eeca9ee71300d826bc3cfc87a29d39" + - "ea108a3cf259657ec4b967fbb534e7513ef3a96bffb35abc5ce0e890696e" + - "54fab515af3d2c0be6e003747504e486c0ec6e30fa4ca79d6596ae0425f3" + - "396e40fd37432e52c74f812250dad603b3502f97ada48a26e39fd4d44584" + - "6591bfa5ffb3770d95d3dbd49e9c3a38c6305796b8f7d79bd0845170925d" + - "575774445299bdf9d3f8ad3dc2dc5cfd3ef0293b84d6e11370851af05ebf" + - "b3510a22edd930797dcb76b759a9b5a77ed8dd5130e79ff5ac44b01901bb" + - "79603cecf674202bc5d84076ff41b3c806454ce80cb9e5fa9db77294d20e" + - "6d3008ae3017aba712862ecd4b32daafef1b8cc8b19ee8f8bc3835e2372b" + - "5cec66222ad5ea9df753c033508ec43c8b5995e88c36c13ea3465c8bc462" + - "ae0a659d9767db34499e9d01fb1588410257d6f588b3fdb766a66bce28b5" + - "e0880f8cf988a2e5eb5bf80cd7d83192b7392fbb2e3a07d51aea2b6bfac0" + - "d74d304f56d5af3598a0712cb09c04c5dc14194eca8e1b9b29f88344c0ea" + - "55638c0f8ebb70b6242b797fe2525fa1bde76293dbc0a66ab4715e6f9b11" + - "f7ecd8f35a20ee4ff3552caf01bb307e257ec0576023d624d6094d43d25a" + - "aadfce939a6808f8baacb2109c3de50a1cfada9e384cdba3e97d2c9025a3" + - "2377bb195fce68c5569d2d1267e1bc68fcd925ddb4acf567fb29ea80517a" + - "7e4056fb014cdee597333ac2408157ff60cfa1afdc363a11fd4883308cab" + - "d9a8fe56c2b41c95eaef854f20bf5941ed23156d86de3bd413465a3bc74d" + - "5acffcd15722879849c261c1bbe987f89a1f00b3069453841b7da667d566" + - "e41fd894d94de44c23fed08d9bdffb723aa8449bf236261240d865efd7b1" + - "74a4460e5004ff77f4196d1d421227dff7c78f1726df7b5eebddb4bb5f57" + - "5ade25296dda2e71ab87ea2b44ef2ce8742a7ad5c1e7a40e097eb336561e" + - "865515f7ee0efbe01d5a928f208f7c9f2f58974d1c11af0e737c673dc446" + - "1795da9757010cefc6e7f2784658717938735ed8cbcbd7981a1bb8f31cab" + - "b901c87a3218dd1195c59f64d0bc3ce8b72580fe38e6dbf1181e0090e5c6" + - "d162df9f31cc52fa6a8ac61897e9b4b3cb0ca2bfb38a38d9b78e46d775d5" + - "7645d2d6da16bda8edd8675e2ba121f7f85400cf7cacb9ffcdfae583fb93" + - "753d07985a00afc3a4e26c9939a5116d9b61196502f5d774ab4c7fb6cfa6" + - "01bcfddcfabfcd28055e858d7d3c19feb6bd7c02565add3a3af61bfba8b6" + - "f4b52c072a8613e878368318383143059a98a85ba521f781a8983c2486ba" + - "b83f5b91fce02acee0be8d0dda7489975f0506c8f363b5adc48ba971adeb" + - "4e1c830b5f264ed42da36d2b5ce2fdab1e63333b1061ec5a44ec1b6e99da" + - "0f25e7f7250e788fe3f1b8e64467d3d709aeb7360720f854afe38e190cc0" + - "925c6cbd77fbfccc07d8beeb0ce68e47442fadaf13b53c30a03ce317cf79" + - "dc9155ddf96814583695f15c970fd0b6cea0b04b1825eb26e65ea9351bf2" + - "f7a841ddaa8c9f8e885b7c30b9985bac23d3ce777b", - }, - { - key: "491ebd0dddefc9f0117176772f9bab61b92a1f1de13796176091c56d1e53dfbe", - tag: "fbd3f884a3dc2a8be06ce03883282e1e", - in: "953b9a40789b206fb507ec2c5e9c88ca1baf25ad24c11a62f664db1da8bf" + - "dbe9b54f8e93b0bfb4adb12f8873096b8960fd91eb92a8ddb53232ac9141" + - "57caced33424cff943a8db129049af7e7b733afbec6637d8ee4f39d063e2" + - "be241cca6a339e48d72372efabceac57220692c40856532d95529adfae87" + - "a71c72f30244126d01a875375ad8836ef8db929bc81027935042a05c346f" + - "bc94dcc057db015e55c56064d2b11154596b813ee64b73bcac05d2688bf6" + - "f1fbb0cf3f8307b3df44c3e2dd1d226a4d0e9dc5f7482bada9611970f887" + - "f656dcb19ce1f8c5c86f4cbd1e4f49b18f170ecfd184028e769e79d7424f" + - "d01cb315897c21111f53f4d41c3b71402eea695272cb5b4e5f33abb9df50" + - "cbdaa55ed629d3ed7d93b43e550295502db1f2ed884afc320518e88be4c6" + - "b62a13f8d3636ba091d07dbc6c20c7e7fda016c05b2fadcfc9ea32f4ee2c" + - "4893de78ad8a1771aacf6efdbd8fb1f6ee9b0572ced3edc6313185b5d398" + - "88ce77950aa4c5201a256e3ae3e74f05b70faada14124b35b105a70e7769" + - "7184576b69708eaabd36e0ba885fc6bafd5738a67307a1181792333cddfd" + - "a4ef19c88497c82fccff05a8f9f732fc7505f0467a14e135288ee018aef3" + - "d0412f6b0760573d8ee4ab455d2789b4d22a42eebdf60616fe403627cfca" + - "fea672bd0a49e8e7b80e7b7b8feebce3381f2fc16819a8996a99ea230c3a" + - "84b510cf2e0d914610d646a2f45a14268ec1d6fca03d0aea5c9ae1c8d519" + - "b0e8b0f6fb8ad176b5d6aa620b253cc492b5e5645353fbd9b6c02bea48f0" + - "286e2c669782b5ffefa4d8f3f1037151026d9cca78e7808dfbe61df29e82" + - "951d7154f3c97606cd1e99300012578ea6a776dcef0811338b56606b51a6" + - "9893fe68f762af6c9c26066b1d503e64877d8cd988b443af66a36af8bdfa" + - "41b4dfb3721d1d81895884755b9c52527030afdfaecd66d4638fab1d1786" + - "3d5517ef7ee7d081b5555d24991810f1edde30930fd392f817cfe632b4ca" + - "6fb0460c36bde4a5620b9c369bf51c7d870c43998b8171a553d2f643fe8a" + - "58aabfce8cf7363ea978ff4d53f58284db822ca95b80306ec02a64d26a29" + - "c98520f1924c70d161682c54d08a2c48f54bb72980a8cf5babd0aaf0fd72" + - "7d5b1b9d9b731dc49bad228fe83f7347750e277a4fbd526983c206e075d6" + - "a03d68957b3e925a71bc1ea7304c77660d112a5d19fd21a785d4a8d7f2eb" + - "dc4183376d8125341eb28b2df5be0b4e04bbf95c47d2fe2aed939619cb97" + - "79548b752f57b723cf8295dfce69c9b7486b75a4e900f91926636f3fc78f" + - "7b7720a5151abdf5868fecf1e1a1d830cd6a4c5e3cd739da4432cf1fe2af" + - "a1090d6a1eeb32e7236ecfddb9d07b97220ab8e23edcc93d91abc11b0c30" + - "460d2027869d1c2487070cf60b85ad0b8bc5df566f6fdb0e58fd044da530" + - "6d277e564ca6cbfa820ca73fb6201b240a5a94c4ecd11d466cdc44046a66" + - "32478221bfa69b3a2cebd16baa302a573c90895d7f4cab453b11e3a4d8bb" + - "b5a9bf264781ce5b9796e3c47d0fa57f46b923889af4d073270a360dae8d" + - "51d85ea916f14787c6500d2d906ccaaa92d20d93edd09139f79bfeb5fcd9" + - "8c1cdbcbe9f2587e9c9094e3c4a32ab9ba56f400b929e80c0551f953896b" + - "e8eda6ecf22e6d4a541957dec21d6a9cf388ff0ba58169ab934902892a58" + - "86e1126b16118e965a271495ffa339c49466209ed3875b568a4290b7b949" + - "69d0465744a3c2a75c599c3a04ab1a3fd09125fe8f45724b2f48c7822b9f" + - "ef95af4b758ae66a8b6646df7a0a1aabe2a24c052fd6d30561cae0389263" + - "e3388c4c1effe431a04356c334aac64f36593544885c4b7295b57dc39638" + - "b665b22dcbf7dd6da867615de38c6a575cc66391135d47f8e1f0c73c6129" + - "17ada4099723933a758d83311b384364263cad5fe14bdd7c825d9601c400" + - "3537a5aca7f9da4710c132ce8b0f1464cee625633ef57f507739a0ab1cd2" + - "21ae634d4d0b3ff07e9ecb1baaef0a82a97279d46543a0464855cd62c07d" + - "5e890265612906a9eac88bec07b1dea5f67054c31ae40f8c673296cc5df7" + - "f0dd8cc9e643b44fd90dc2d1e870ad8acdbe165237642fd04c00965837cf" + - "bd2344ae830887a5719a3c16dc8ec08bd9131d055bfb959b64ff4cb638a1" + - "002a4fe02e369871cc4e3ffda17dd85343e679fab43e11970e60198b424b" + - "676ab17fb0dee10cc9c2e92b32b68d5b05b7a559176f822850c0557ed98b" + - "7454916e32af549a0027db95f02b88cfc5e7e05f28f53757dd97cc0f0594" + - "212f8801e58043cb17b040413c226dfce2104a172d218caa4353890de17d" + - "be1f53af6ceda24b8781801516cc51de9ca459e469b3c322be13d8c9541f" + - "755c518ca41a0ed42e44b9f87faa2a968b0292216e9f3d3e8987282103e5" + - "016fe9f7681496e1e8d663eb2d8bc30b41d735465527f19e336a98d2dc54" + - "d7c020bfab30fe6c62cbae7d09f84af69bc2c51a1839ffba15015d381ba0" + - "a44a3758771c4f18d13827f518f30bb74f4bff29a87d4b9e949f1063f63f" + - "662721cfd64ffe1dab3761852387f78fa83fb48ae2c75fc567475b673da6" + - "fa8f53770b6e5a3c9fad951ec099c6bc1e72d1c489e1ae620e7f12ddc29f" + - "ed65f29c65cef75014b999d739e2e6e015f928a30f2fee3f2e59bf65b54d" + - "89948bf2bfde98b076e5460643952befd02fc1b0f472a8b75195c53ea296" + - "6403b9028db529cd04b97231bac3068855fa211f4d976a88bc27a0088f04" + - "576e2487ac0467992066ef7667ca8429faee92db38003728e5c219c751f6" + - "6f011b5d679fdd957f4575a0cfb6b54693a9624f2c7e66c578f5f0367005" + - "c66addd1e3ab7ea1ac404e357cbdab9438b9b4f80b3a6761b864b006f1df" + - "689ae4c0434b06b686d5353d3e421b57381ea24fdcf6199195ccdb3d5cf4" + - "623a6bb1f9eba9b22fa15395f65f8093b5f90455061c1cbf8128b44a31e3" + - "910862a59e187aa7f4d22e0317ae6c177cef24eebc44171f70c25efac73b" + - "38ada0cba0b74f72d1c171277a734819c1111ebe46d5db20a6ff20e2c1a9" + - "a57edae95a3c1f80ddf2b12c86d3df0078a7bf68695b16ccf92053c727a4" + - "80586b8d87d0d1772e456fde0c20a7927f351a641bff5f22f9ee2217b6a2" + - "d0983c8102d7d5356dea60a19e105ce366b9d000987c8c33396569f97c56" + - "2d0fc0bc5859779aa10efd1f8df0909c307a9110083cc6d9748456c9bddf" + - "16dccee52b7974867cec718bb0b76b3353379a621257094277a30148ac38" + - "e5cf67ed7cc9c1bae12dbdeb99d7d880ce98e17f0dc93c5330d1824a3c9e" + - "ffd86f89e15b59a4bee5a48d4f674766896e187abaa39917b83f8d2f3265" + - "bbe7aac44c9f8d92f775fe6493e85ab44e6e28f79f28eff156c21e1abdae" + - "d10a291b88c4020b1ae8be001080870847a852d073e82bfc751028ac62d5" + - "6aeac1b18f2cff1c0c7d336bf08f8cd5099d9d3b28f9e16077e9caabab49" + - "f2d234616a7522a6bde1a3b3c608df4cc74a6c633d4c8068138abda8d26b" + - "4ca70f95d152888fb32bdee5dfad8ff4a5b002a0a327c873656db8d6fdd8" + - "ed882e47ce8e47c729e1292db9122ce2e9fa275f9bb986eb7e0a1dccb7cf" + - "abd0449c92fd35e2aedc4aa89caf53bcd28170cae85e93f93988e723a896" + - "10cefb4edb6fa545835fba3107e21dceb272c5a32da26fa77df070f41d7c" + - "ad1d68b836199ff0f1221e36b9b976b5e69bed54b5bfec67fe9cbb383484" + - "696265204797634594bc335150daea92dbc1004f613b4c27bf5c699debf9" + - "4365041b5a894701da68a93bcb61f4e546c553fe61f14ab0322b45915da6" + - "ecacaa093b0071f2516ca8c3fef2f1e3c403993d734403c47bfe5f4379e9" + - "cb5b613fde3c0d880cecef4101aad8b8b1c60a92ac5185f6c243fdf1711b" + - "0b56f0fd8e5ed6cc0f99da888e4f156455a0f0eb365b8964347eedd15d80" + - "2f297977af667ed1376dfcc610f5152421b97afaaf16f9db57a435328595" + - "b9aa00b5ed9ff106c66970fafef379f4d2f98f2c5984ea05aad64651fbf7" + - "7968c8cbc4e959859b85302a88a3c2faed37765f3f6ced59d8feb6c72e71" + - "f9d4497d98bccf95fcb650f29131e1df1bf06a5443f8af844aa1a7b5a68e" + - "bb250c7de3a65ae9b1086cf83f832050e55030d0f67c6a54ea2a1dbe18e2" + - "8a96c9e0dea2966997bfc5c5afd4244e3c8477c4f5e8bee8fc8ca9a5cde4" + - "d9c5a2c7f3d2e811b1de7ce4279229319e432674c609b4c8b70dc6172e9e" + - "653fe1969bbc2cb3685e64fd81d96d33", - }, - { - key: "b41db44465a0f0d70093f0303bbd7776017bca8461c92116595ae89f1da1e95f", - tag: "d8a111a09db22b841fa28367ce35438b", - in: "b074b0984fb83749586881e8ec2c5ce9e086cfb2aad17b42b2429d4cf43a" + - "0400fd15352d182e6c51e9338da892f886f460d40bd178d81c52e9ab9c1c" + - "bdd812594e6fe7a9bb7fb729c11328d3288604097600a0c151fa3d9e4268" + - "de75866558e9f47d8dd331994bf69f826fd4a6cb475ae5e18365f59a477a" + - "dde7fbcf7e40b4e3dee020a115830b86f0faae561751e9b596c07491c42d" + - "e02fc979e69071113953729d7b99f1867116d058a90f1b8c0f9ba12c6322" + - "4ebd1b563a87734f5d6e2d4e6715d5f0213e33316500cc4b23784f78a9bf" + - "13fdf99bfe149cf47aeaaeb9df1cee140c3c1264fe89bcde8acda6bde16c" + - "e3d770ba51950b67ad2c5232ae0cff048ddfda8540cf18e673582dc96987" + - "4b127f655e7d4e08859f2c6b95403cd5b4e2c21f72bb872e49e592306286" + - "48ba1b16fc9637709636b198f9a297aec364d4c3bc869dcad32b1830e434" + - "b556b429136f0012a0a0b6fb3797bc8668014b010ea51674ef8865348dcc" + - "197672047fcf72e6b6910a0e32a4f110d85e28db0e338d9cfdec715a8800" + - "b4f007a7951d09e41620815848c89f8768344c50bd522c46f64ac6c98e53" + - "92176651961c7a70b62f3d1819bfda674e2ecd3167415edc4b97419e8ae4" + - "9974b56cd8d52e1d05b82610b59606a750b34844ca33bfc9b21fb970738d" + - "b66f48928df79cf67730a30b0b612f8c15c22892120548ab460a6b9bb3ac" + - "e30554c86c9681c797821a1b1ce91d0e87fe90ad4097c974cfbdfd5c4c24" + - "a5f808f388e1b1473e858f48a387614501c8c39d6973ded69b1764663cd5" + - "166be02b596a49e392d637e3d8afc91323f7450318b79d5488c040e346cf" + - "0cee512044514b570aa66bb98d639a9ee23a7cebe28474592623d082873b" + - "73efb3eaa4721fc4761e15a390497cb13cce181107e8b1a0186b9e47a5a4" + - "b67a5be3cd88a43d341ef63f10af6970aaf56035db938655020809033a92" + - "8d4fe6d2f5424fbde2fe82adfd991d388edf293cb4e3eb68d876f225a5f1" + - "58208bcb1aaefcbc28d6763d267406aa8d6ecb413d18cff7a318ba031ba6" + - "0ac4560748c248de64eec56dd4540124b38581604f502d94a2004f9eb1d6" + - "edb009e16af6c6d3ccbea79b10743da98aee7ace407a90c6cfdde694f36b" + - "e0271e722618a457be68619b980754795f4ac95ebf4f1820b85ca8e3fbff" + - "a2430f8e01ab422d7140751f7741f2c921400dac404b04e049736738a87b" + - "6f49bd54b1b447b922c473831a65f224ab84fc96e4551a0333bc6187e15c" + - "c0f0ad628068bcd7c043bd1e3036ec01e7fdc3d157476149917baafaced0" + - "15d09fafb92181a0ec65b00c9c13631e65de184377416e04d3d93b847e0e" + - "286c1d88245d4d550d30d4fbfcb416ff26a39a94275631c2deafc7cb6780" + - "f149e4d0e9c4515b708fcd62be5252485407a6ceeb9247de34e0266ef384" + - "976f6d31284c97468b3b03e951d87a5a00836ea303a266147a79ff3431b4" + - "b382e86c74d92661e0f65e266b7d569c03994b667a8137f3080eda2ff542" + - "0f0b52b427558dc26932a22a615c9e6b1834a251c6b68fdfc0bbe0e8781e" + - "36adf669f2d78bd23509ef7e086634e526258e8d11a1e0be0a678ac09c7b" + - "b4e3c5758504011e701dc85997fe2a3e40c7af83f032bdbe7adc10ef1e4a" + - "666946c2bf31dd8e3a383211c9684d5302f89dafcf77976d5a02c14e2462" + - "09d2d99918e82402cb0eacaa12032ad8316315af1b3d3bd5058f7c935d35" + - "ef0d4e71373958fd5e4140a9a586d89c53e4144c00148a4706a524896eb0" + - "5b1479a0de5d3f57be46b3f5fa4e49bffe027c81a33e37abc01a4cafe08b" + - "8e21fa86b42be52d75d6407e6cdf399de7aedb9b61a6917b2677b211c979" + - "33536664c637a57ce2234e3319fe8b4a77d7285ae6347464dfd0aab3e6f1" + - "178e0029686770d3b0dd541490b097f001e95f27efe8eb16e4747937d643" + - "cdefd49e586ecad541270cedc3064bdb7c79f086bf1fa8c666304d977a15" + - "54ae268881e17d8bc3fe51fa9969f7e560e3d3e050424febec0998b35f2a" + - "7378b2c3e384cbfc80c4987734d76c78224cb81cc5376f88f0ceda28aa50" + - "44e956537c3ee209071d84a66173384e0aa466d989759fb1f2f17fe627a0" + - "ffeaae7c5a3884b237f5151278a07117c2e833f1815c7e0e0b1611f25058" + - "ca338d21deb1a571faf1d0486667cb7c58e2814c3722d24fb77ce1b7e018" + - "2ae5746442b5ad00208b17c0a68bab4df8a8f36edead4fbe79b4c9220dd6" + - "acea6d23c7caaf6ce7cabeeca677a1c764d610ea6c7e994d6a9c88f57fda" + - "ef160b251e7595578ea2cc1441d480c14b8b6945e76a001891b1f214979b" + - "c52ec15e9480d706a40cb6e3b259ee99a9e84e63a738f1b52cf71c8ecb04" + - "fc833c2c680bfed587aa1541e5ffe8bbd7b21302bbf745011e559f94f952" + - "8b7fad8a37f6d855306a5be22725859cc950bcc334179d49564af3b9c78c" + - "e1de59a9cb45086a33856ba7195c17cef573950155bea73ed16645768bf0" + - "a5cefce78ba3ff98a54a8e8afc5dfcb0d422bd811ba9b7770a663b081dbb" + - "40aefffbeabca955a9638830f0c5d70663cbf5b26067cd061c4a3f5cf8fa" + - "4b6678d82d9a2aa33f8538b7499a3466f6b0ae2a1daf280ab91a6c220684" + - "12705245f353b4b83db50bedd3bf99d42bde6363fd6212cb745467acb007" + - "b678128f6580629a06171f7f3af272f8900b801af3bf47439167871e7b0c" + - "33f198333992a6c52c32be46071738cfbf245937d48f816ebb88ff0e726a" + - "dc41de4c771ff0bd320a4c0b1fcccd9fd6c42ec9c5185943c70e9a4b7c26" + - "a980afe104bb1f99576671a254704c7d4233eaf9915e1d56c103ba9f6e8a" + - "46aff466933bf58c9842796ae9cd21f7ac6aa96ef42ca54e390203bac354" + - "b7c1de7d1887c48255201335f819020e2782a2ee8af92ceb206b651ae92b" + - "3f4fdefed05e08974aee0a353d104b1be9a5e75c7f958f1981271b0a6928" + - "05a7a2f28a0448d86102b4fadf9ab4ec2f98e31e64fcfdf2b524780b3342" + - "7a2a3100c2032fc93199f3ea7a9e8063fe73282dcb1fafaa9496c7da868f" + - "dcf33bbb761df0bfc6fef30fadd2b6efef4fd3216a8aee48a2ef28102491" + - "cf7278b567c272d1064a277eb193b3f6f01df641ddb729f72454943cbd3b" + - "671ec077f9e3548f5f57d063c653ebee4f228a78f8a128d26f7f4b44160a" + - "07e942bab87b2d043c77ecdf10c1a419e0a1c4162a99c21d4abae0558b8f" + - "4dc0b7f1ca3892a6babf71f2f70aaca26bb813ac884ee5d71abd273ff1c4" + - "add230a771b678afbb12a1ca7fbcb2c0f5589c9ce67fe8f78a8db87825b3" + - "09ca34f48ac35aa7ac69c2fb2423807650fcf47ee5529e9d79dd2628718e" + - "230ffe5b83f9d5bdfd9c5d211282e71cbcacf972995bf1b13d21419f7fa2" + - "8829ed1dcc459da35883b9269a474f7fceff01d44ab78caf1ef7d8117f50" + - "cc83eb624062b149a6ed06ddd1cd1feafccdee7122353e7b3eb82978ca69" + - "247fde52d2d6cfe7324f04af5259e1b5c2460889da4541b431ba342a1c25" + - "3a1b1b65fce7120829e5466e7ad2fe4e0f773c7c13954a9c92d906c91aa1" + - "de211f40916596bfa8245344e257e5907a2c49ebcc864cfbe28663e700d8" + - "472c50355313d5cf088e9e8a19cdd85bcfc483520498c6386050e53a3ff8" + - "1e2b77b55b116a853d71f60d621265166cd7e95ff5cb4466226d7cef68ff" + - "d0a35b61e76a43cdcfa8da7fff9558e2f89b981ec6be632b126303ca1fe8" + - "53d5c628d967d39317b60ac904d6a882beb0746f6925a86693aff4deaac2" + - "e5b64b611de86767d55a6e11221605508b1c5cc828251539b1b6f65c2c04" + - "8e65be5422c1b11194eb687d906c559068c0a810713b23b30d8b17f10df7" + - "0962c5e7e782aff7bb95adfe4cba9d90b0ebc975fa56822025100b5cb8b3" + - "8bdc8928c1a2a8034dd66e2a763696d7ce6cef4dd586b83f7d01749d37fc" + - "4fe8d7abd324d4ff1efdbdbfeb0a2fbb8b266fc2bce8e5e5b95d0089e7c5" + - "d7de4db837d1822ac8db8198889d6bfe778d0b19e842f12b5afd740aaecd" + - "e36e2cefc2cf0b082aa0c4f75684d024b8d828d8f2911fe1aae270251f62" + - "4f49584e40bb193577c9d8e04eb16c094653cdf9a15fe9210f724c7a7c73" + - "74cfd1a74abb5ceae88ea54f7e7569f8eb674529cbec965ed05bb62f1968" + - "8fdaa97297268bfeefd06eb21f700cc56f9bf7f6cecbbbe7278ada8399fb" + - "960371a2d5cdb852b11c9fa17650e614c5297bf46cb7889d52bcf49d2560" + - "720852822b75bb16524d88273cb366b84b88282da91875562e5a1fe73973" + - "afe90e5cdd3f5381612d3ba7bfa058d023a9326e403ec474d8938313fb32" + - "bdb5bf899b900c3818c43c8a0af6a061bd26e847ed75983402ee8a9cf4ef" + - "85bba5545a0d329ba81495157eda0286f1917de512fe448251697dea406d" + - "a510adcb05", - }, - { - key: "b78d5b3019688e6ef5980c17d28d7f543ca5b8f9f360f805ee459717ca0d85a1", - tag: "f01babc4901e957d0c2032a7279321e1", - in: "ba7d35b2ef8af1118bce1e78018c9314b0c8c320591e103d23f715acb05e" + - "dc98fbc618de06627661df5842dbba9f604c2d20d664e5db06e949b11d49" + - "665088dbafdb0d39d20beaca7d723f8dcdc57e9c5583d303b6cdfdbecf95" + - "7d8daf2f1c72b2a6fa27e3d18841f4841abafd334c110cd2b74efb6191db" + - "ab9b8fc8427ee17664082f31db98d30bf15dda967e20730a9ef525abe9f3" + - "f620e559ed22bf74d347c9869f0311f33da7f1a3dc858b3a8aa73a35989d" + - "b055a4a2c269c95e352259c57de8b94d8de48984ecde426d3ef60ec1c7b4" + - "41cc950f7764f55bd0cf52d069b9ad446d1f765f35d02ec104ffcc00bf1e" + - "dc1b951ef953acd19984ff1b41041bea0e9f5326a7c9ed97e6aab42174ee" + - "971ea1dbe2fd1c1f67f977ab215962b0195417170f6b7748fd57262424d6" + - "cf7c235b34425f4047191232722932213b3eb73904cadd6a2e9c7571d7c6" + - "6c2f705b5039ff75e5e71c5aa738bf4177653e6eb0b49303a4bc0e641e91" + - "2691f217296a3325431d578d615afddf47784e4618a2ca40ccecb05d621d" + - "a52f272b8cf84f7fd8177c83af1580d25a764cc06436d67171cb5d1e3b39" + - "367b46d9a59d849d87ab6bfcf3fb9bac2b1ebfcd1cef4459e74b0e1b7080" + - "dabd2dea79f75581a55de63c4b23ff67d986ad060102933fc6cce8d614c9" + - "c86dc84068828dd9e21ffc5665c809d83b09432fd315dfce5d7a4ebd8143" + - "181953e3f8716e47b0b30cc1f753e31a7d509f2dbd4177b6da310cf3cd02" + - "5db270adf98e96259a5ae1b81f5be4d5c76f502a612ca73c76b91e0ca695" + - "aa921f9489948619482c2956205ae71fffc3aba4476ff754e4878e36c763" + - "2c935c076857c5b90cd63ea4764efbcee53e2ddc9bdce54b1cbbcf0e7544" + - "d023e7c2b79419ad92221a1f76abe31a8236e370d38e2493cc9ca2aaa811" + - "30fc713d11f500fd071d6eba6861e8b0859b372e62fe60b627a96c377f66" + - "236aedf307e1d148a61bdad072b93d7d2a73367c595b1e048f7023e72729" + - "1ec508326f5424a5bbf4e010d0240b71fa9137e6642ab40c5e4fff79877d" + - "b3253c663a221b49b3e77ea307c7b9f3f72a0f3a54d0112c45c64a0c0034" + - "baf2b55ae36ea6f811bbb480cee663136474dacac174c73b1e8be817916c" + - "fd4eb1876582bb3a36cfbabad91776aa676305ddf568a86e3a5eb687fa81" + - "67771fca7b5ca00e974b3cc3e322b4bd9bcee2a87d0ae7976da5e04fa18c" + - "219fa988d4f6fce62f194b05c26ed3ae1b066cd9751a2d916d53426a454d" + - "58f9c3b2fb49374e5791b412fdee1b6029144f1ca787f56fece4f64f4fac" + - "bfe4cfd8ba7c807a83cf44008fe5126a283ab2631a87acd8e2a3bd10979c" + - "4b07a84a49b0687a45a4798ded0b5e9b2acce30e714d78395bfa8f33ca91" + - "e68b2138bd67d8a694cd87c88dcefcd101a3b408d7a9095cc6a4b38898ec" + - "c8b375f5a67deaaf73eb7e99b10314ca6bba824658bee85dd731d9a1475f" + - "976b7c0aed4b67b088f0db5ca5091273217f724969dff6cf184181377c45" + - "5722beb23fd9d097a82ea2d8d527ba6284acc20cb30f2e52af28800c61fd" + - "1faf9f4f619550e0162a1a63758e202533889b27420fe7d0eac9a47a6e11" + - "1d80054412340e0426cdddbb3c7b9b823b8db3ef58230fad7a3ac21a7805" + - "d30878d4ea78dda95c951b7a5dc552e9434c35e03e1dd88652d3714f8fbe" + - "a39936cc0717c2e0335371f2a751204f5d9386baaec853f019325edfd1b0" + - "719d1fdac3fbd774a64bf957fc54039501f66df94b5b9b82c2076c597065" + - "dfcfe58b2e215a3734066aeb685ef97759c704b5f32dd672ba59b74806cf" + - "ad5daeeb98d16f7332ff0ca713d541c84e4aef0750bab7477ea707e2e497" + - "e12882dbc0765106070ec6a722d08fe5c84a677817b28fa3a41a6117f2f5" + - "465c2a2f0eb2b8be4f36e676b4115008bade3573c86cfb1370c03b6b0dc4" + - "bbbb0ada4dedac10a593655068a26febc2bf10d869cac84e046c9c846ce7" + - "927431f606f07b92abdfd81260199ae05ed01dfa07088c56a6a8de9c6d51" + - "d61d6a6d3f9904c216ea8329467a006a3d2495a768a39ef99a21827d2def" + - "909bb743fed7209f7fe59ff1c1e710095b05f166c6173deef5c6ec4105c5" + - "fc3b87c8269c786bebd999af4acbf12d20453b125f338aee87e9509ee405" + - "9c9e568e336304d7be9ffe81d1700555b0800242d9b7450d7256f2b17f6e" + - "d46a39f67bb2980572ce73169e352070dbafd4c7fa5a6be78cf9b72981c0" + - "a01f1e1e30ee3736c59828b791d2373799854497a28a44bbe0e074925723" + - "4986696fbb06ef9ea83fbd49c45a583ce12ff10258ba06127c67b0f66dd1" + - "09f1366d8036853973d8884f93de54fb2a12949eefc020717eff47898cef" + - "306b5de068411f1e113ffdfe2556e0faedc3e27d95a45b8afc15ba0eeeff" + - "eb86da7b4324e20af80c62bf0ceb4aee1515f5912f71c6bf2febf20123e3" + - "dd3a82dc1e58a108f1039942dcdacdeb1f0ad0b2ef34488d98d6a52311ae" + - "acbd03c12f6e775e375d5979c7c295bb049f2cfd3580e3da3841ddd8e6af" + - "4de5e6512ca79cebcab9280554524881da37984d340e8f0163fe10a02ed0" + - "88682560bc6d3c4dbcf1a542ffb3dcc2ed16a2eb96896e8269697ffeb50b" + - "73f2cc354092e782a0072fc12e1eaff117c2cc8a5a1ad8b47802ac9e23fb" + - "91a0cef9e4027595e0885464e61563093ee2b1dc5f22dfd04af7de6a70d5" + - "977d3751a4b3cc0c71a71c59c0534cb1f8c0eeddcf1c0e1b3e5ad0d083b6" + - "6e8b998ddf9ae9d3b365c851d42e995b9afdf8d66b2ac40bf514ce32e456" + - "0880afd38c42c08926067eb243c4b1184e667ba756c14ace5f525eb48df7" + - "ebb429d0a23d159664f8021d27dc7167081de331c7114c9c6456e1ffdb42" + - "2172a81c06d8deca995e158c48df27261a83f83e0127f5e056a139be9b76" + - "e25dadf534d3d1ed6ebc0b5d77d51e5b90ff86f30d4023066115bc11b33c" + - "c827b1103098826d0bf8777176b2da6f1e5b580e407ccf7e614fdf4f5b53" + - "3ef6d30b20c1bee61eab90e983b1a97173a62720ffd27abb8976a948d532" + - "d06596c23b0ef31c79831bead8f8e99ad209af3658cac0cb3c3f9c88379b" + - "9bc871d8e84171d53400902da1243f664afeaff60bd96ba2639a7644676c" + - "a79f43130af12ba2c877d67f7ec030a4217a72f5368af7c9f24e643db6ac" + - "97a04adaf57dbc53762d8dfa1afd49667c4041adcb5ec303e191b786273b" + - "bb065cd9f16a3a4a399c6a7aab9c1a6604998264e8b3dbd13d8f2228b13b" + - "2c2b9fec5055d8e9f2df1d9a25e4bfe2029776389877bbef7e2c7621f06b" + - "c0b7fc0786e2b2d042483ccd4a59d2872a6c5ac73e217123e5c8401580a8" + - "d967e0895aaa28f4d25ce68c90b4394d8113bc423e9fae46ac47bc2ac191" + - "fb97b80b5a85feb2bb54f84c493235c1408662fe253c6786fcf6fdb8be87" + - "dc66a72cc847f94dfb5214af5905b7039a7363a1b23a07853daa26862783" + - "ba08a80846fbb93ce98700a4f9961115128dd67bd7d19e0c588fdf6196c1" + - "1cb0154002ae862f11421f5dc3a57b6c0870b452272be556a1d14eab1af0" + - "a91ff5b89de6bbeed6e03bc64f5efddf9e54da71c594bc5ef78e0192cfde" + - "da36e4ad1a6b0b51110c1b24d20dea1f19e18cb1184d80189f842d4f07ac" + - "834744dd009aa3771b1e5502fe4b65a403a4bb319e1880ff6ba852e90a8f" + - "4fcb52cf374c88408428cdb1255291b04ed58c992310955198d61fa1fd9d" + - "762d48f2f65a287773efc67d549981c291b427889d3e3dfc0cc6cd68415c" + - "dbed81b516786dacf431472a7dfc99688d15bb6c1b85b1a2015a106e5de8" + - "cb9eec4c80b17d00fdcf4a9c64de4643a95dade8fa9f1bc5c839037d86c1" + - "3800a244188e3b18561a74912ed72f99f2365f0126732d037dd54a3ab77f" + - "9a9f6a1c1469ea92eb707482066bd4990dec4d7614ccb4ea6dd4deb8bee2" + - "2c4dc0b9b4d4cc70a500d2c8a5ac3ef88a38439b7dc254a6d920cfd317a8" + - "4d7747148c65b6730709e43369d4c995b03c58b9df444f77f216944e70f6" + - "6446554d8d513b8f7f28ef0a2d7ad5ca2f6110304196953247a7ac184f68" + - "61fba896c2d5a59007ec2b2c8e263957e54cdc1f3b4a145228823fdf0960" + - "c33a28f59b03ee4be21001d2f56fd49ed14db33b2c4eec2c3f41b250a624" + - "99a9b6602c1e838526a54cdcd058af1c252d56009d4c7769deace53bdb66" + - "543f5a081cdde775e61efa70956fe2a7a6019a164c6e413ded314bc928b4" + - "aebccb946ffdf3eb33e187bf421febe26112b3262a526de65678cd1fa03b" + - "83513705108fe0bb87aa99aceb28af3641c46a2c4427cc1063de01aedaea" + - "fba68155d4de494a27ff6b7fcc8f5c5c3f7d3a115c397a1a295bc55aec8f" + - "7f150cbce2a8aa4706d54ec863877bb966ad441c57e612a1b5d438b98d9e" + - "fcdfe6d4f66e885f96407e038015cf974ae5a3540692b054d2ddfde59b28" + - "ede7e2f581eeb56c5b88e2779aea60c1d8ca6107b0cdda1ac93e6c7520da" + - "edc66afeed12f980e20e1e1c327d15ade4bb90de30b011a9cb33855ca3ca" + - "e2", - }, - { - key: "2b0b0fd3347e73c2fa3a9234e2787e690a11aec97a1c6d555ff7b4047b36f372", - tag: "81b1a6633f849ab0aa7baafa58a5d9b8", - in: "427f3a7a5f1142ffa68e83df5f917e07b2bc454f3adce068a8ae9e0908e1" + - "3e0099aaa9074697593c6d8c2528fedddeca05e3888be1a0a201c389a72d" + - "20cb661017544d95a431e70e7c6580d8fb46ea4495bc59db6ae2cd69510a" + - "02426c50de1b6110120f759960605aca718d4d0a497e003e1ea2b8ae9a53" + - "df3c1eb4f704eb32f8f05eb08cecba0fd4a94f0daa3b0984c30a38f94b7a" + - "10cde723182d30588bc40f1f9d38a3bab4800fdd5148e34e396144763696" + - "c9b3e9b8adfdb337123d54237c7413f98bb2056152b256e37a27bb947c67" + - "240fa3ce8da62ab367db540bcdd9eb873d6c71c75a08fe99b5c11ec8e6af" + - "f926d2adfcf073479de394d4aac5fdc6241824d944b8773db604c59afc01" + - "495ee755905e5616f256c8a64321d743a1c9368d46418826d99b762e2f6b" + - "f998d37a995969cdc1de85f0ce3987c6550459f5e5bfd9173bfcb9e0112a" + - "d91f092de446beba14fb3b8ce3fb2f9c941815b2cb5a3b406e2d887b7912" + - "bba07c8dc7caab9836827da93ca71fa5ada810da1e5e9b09738524564d8c" + - "923746d19c78dc9107b9f20f653e05d7f2eb6bd90cf5eb30fdd7b587eb46" + - "74a1064c70ef0af2e75373044d32b78d96eb1db3112342d38dca0e47b96e" + - "9307fcdd711b1c66355186369a28481cb47ef6bf6651c2ff7ee4665247cb" + - "12b573933d3b626d1c6264c88bd77873c2e73e73ee649216bf0b6d6615ab" + - "245c43569d0b8096596f25ceca8667661de1cd60dd575697370ebd63f7e9" + - "5333e8a2cdb829b75ea83d72cd246d50358f7c094c8a515805fda03165d5" + - "21391617c9f9a2ea562b419632df611a67912d2b369e5e505dbd5c719253" + - "16d66cd608cc4a9583a8eaa4661b7279870345fac3031631c1a220551527" + - "5be7d8d89b71960e687aace3a0e8f206e475053d6fbf97717b154c75406f" + - "2caa97d1ab66048f1c99281c188a2f37b8bfc736c25840a9130ef2031c05" + - "6acd9dc10592eddf94f5bac85319b10ae46cc136a0738aa803837287ed7e" + - "dafe08d1fcf31d5e63763e39a5e1f4d7d0edab368d44e63fdb33c28905ff" + - "d6be406a024c017081b4f2d70860776e9d2556cd008fa5017b58733da13c" + - "634938407a118827a80baa28d4e605db59430f65862b90cd8356baa287b8" + - "4e6d9199fd80abb9fa697e2c2c4c760128e4ec0438388cf407e2a2fe0f57" + - "908187ed8efd4c5cb83cc91dbe6a11444eede85099149ca82921bc28bdd6" + - "b9999594a41d97307f8854b1bf77b697e8cdd4daead2aa49fbc571aa44c0" + - "bc84a57cb5fd85f06847ad897ceaf449eec45bddd4e4eb1e1e119d15d5e7" + - "90957e686acbdda1bbe47ea935ebc4b8c2e3cf9b7157cc6dc03bcb19508d" + - "a9e19cb76d166da55559ec7e0995d9b50c6c45932d5b46eee400c56d9dee" + - "618977dcf6f76e3e86bc5207493afbc2aae9f569ec9277f33d9f61c03d59" + - "dd6d8250ee8cb3e54e5e941afb74f0735c41d52ef967610c9f55b2b52868" + - "4b549a99ae3392a7237bb52ff5f8d97327e2837268e767bed0bea51f76bf" + - "88bf0286bf22b881f93f1d54fab5cd4e3c148c96c39e7aeef375de249df0" + - "4d89d1bd97a7afb2be0cbfd3380cb861d31e4ad1ea8627721e4518b9db3c" + - "cda20273ec23549c4adc3c027e3ac9558de2010a0263c1225a77dac8be60" + - "d498b913f91391d8b2656ffddb06e748cb454dc2b7226745f11030a6b9ae" + - "09ac8ac428d9c6500801fb540650c94610ab70465b1210c6db2064dc84dd" + - "7f52573f8f40c281470e85176c85ec6de3c718663d30ad6b3dfc1a3a9606" + - "1936744357ca62fb8bb066aa1fcac6d7a2adf0a635cd546bef39fbd3ee0a" + - "8802ab0466ec9b049b5892a9befa4377cd199a887c34569b6f90852139a7" + - "86babc0049ee2b527aa96b988237a52eae8b4b49d2ee15ee5294118cee62" + - "3c3e11cecb836b21af88555f10be2eff8379beb615b7b3d6c01d545cacf6" + - "61be8ebbf7a3c58ac5e0e7b17997659a2bf15f2b2e3d680d142fd29d23a7" + - "aea9890f3ff7c337fce49ecedaf38573edfae07810ba9806723e576d687e" + - "a11700b8ccb96a6559259c367cef4e3999a05a373ab00a5672ce8b3d1dec" + - "a414187f383e449d10021b73c1f7e39ce01516b7af96193f9993036049fc" + - "72ac059ef36b2bcfbe13acf140d41592880fb8294ebffb98eb428ce9e65e" + - "1094521bcf8ecd71b84c7064539a7a1aac1ad2a8a22558fb3febe8a44b87" + - "72fc00c735773d4ce2868a0b478ee574b4f2e2ceb189221d36780b66212c" + - "dd8fd3627cf2faaa23a3d0b3cd7779b4d2b7f5b01eb8f1d78f5b6549c32a" + - "cc27945b5209f2dc82979324aebb5a80ab8a3b02129d358a7a98003e701c" + - "788a64de89726da470010eda8fdcf3da58b020fadc8970fafb08a29bef20" + - "2bd0707e994015258b08958fc2af4c86c3a570443fe6e1d786d7617b0c66" + - "29a6d9a97740c487622b5b8186c529d7f8af04d9f0a9f883043f08103ca4" + - "d70057ee76639f3b1046d86928d54cd79fb5bb7b46defdf15d2f8578568f" + - "1d7b73e475e798ec6812586700e038ed4791b23ac9439d679a1a4bc04cea" + - "e328330c24b065c9cdcdcedfbaf58e5299779e6f48783d29ec3b1643bc8f" + - "1095c724dea75770583b15797fc666f787510d91e65a8e2090cc1ed2013f" + - "e63ab17bc7640ee817487f4eac8326e9c4698cb4df05d01bae8c0d00fc00" + - "08919484d5e386c8f60b8ac097c93c025d74faa56e8cb688d1f0c554fc95" + - "aae30873e09aae39b2b53b1fd330b8546e82d9e09bbb80132d794c46263f" + - "4fd7b45fda61f86576dec52c49f2373e4dca31f276d033e155bbcdda82af" + - "8f823948498f4949bf23a08f4c8ca5fcc8598b89c7691a13e5aba3299ee0" + - "0b479b031463a11b97a9d0ed3189d60a6b6c2390fa5c27ce27e28384e4fb" + - "04291b476f01689292ace4db14abcb22a1a37556675c3497ac08098dfd94" + - "d682401cabec239377dff592c91aca7eb86634e9d5a2848161dc9f8c0c3a" + - "f7b6a728371fac9be057107b32634478476a34cbc8b95f83e5b7c08d28f6" + - "fb793e557513ca4c5342b124ad7808c7de9ecd2ac22d35d6d3c9ce2f8418" + - "7f16103879ed1f4827d1537f7a92b5bbd7cd12d1ecc13b91b2257ad073b7" + - "a9b1ea8f56b781bea1bddf19b3d7b5973f1065fb72105bb4aeecca5b7513" + - "ffd44d62bf41751e58490f171eb9e9eb6d57ffebedd4f77dd32f4016b769" + - "fed08dd96929e8efb39774d3c694b0d30c58610541dcfab3c1cd34970195" + - "7bf50204acd498da7e83947815e40f42338204392563a7b9039c8583a4dc" + - "faba5eaf2d0c27ada3b357b4fccd1595b9de09c607ebf20c537eb5b214b8" + - "e358cd97992fa5487bc1572c8459c583116a71e87c45c0ba2ca801931a47" + - "a18ef0785ebbe420790a30278d2d0d42a0225d211900618438d1a0b2d5be" + - "d14f8b4be850dc8cb08d775a011683a69ee1970bb114d8d5017de492f672" + - "09062d9ba3616e256d24078536f30489e4dacd6429ed37aab9b73c53fdd8" + - "a8a7aff1b914b9d82d75a46d0ccf85f48d3ce9a8d3f959b596ae9994ac3e" + - "3b4af137d0c8e07ece1b21fd8aa05522ba98f85a7ab24ed8c1e265fadf4e" + - "9a18c5ab5684d8ba8d3382ad53b415c73ebfaba35abeebaf973b6f18e0d8" + - "7f019420eb34e09bbb12afc5b149f1e9e9b6ae36ebde429d437ada1a2d52" + - "b998f7c75ef731132aafc3bb106a2ad3ae11223a355804d4869ebaa47166" + - "2df261d95d48ac6eb17c1781e81c0027ccf8f05c39e1eda7793cb16622be" + - "ce7a1ad5d2f72f8bf4bdb2f4f4dcadac3db3bf727f0d447adddad4500360" + - "09ee011bf4155e5e46c74b00d72e8e6a88de9a81a5a4685651b90e874dfe" + - "eba41698c98370fd9e99619ce59ebb8342417d03fc724f9c910ae36ac5e5" + - "b46c424141073199aaac34232a8e17ebbfdd80eb75e82290de92968f3893" + - "0ab53dc83ac433833576e86fbabfb9d7cd792c7e062811f4cb017710f841" + - "1e0fb65ea4b3cd68b0af132cb08330aa13579196ec632091476f268b44ba" + - "8f2e64b482427dfc535d40d3f58b4dee99053b35a3fed1cb245c711fa16f" + - "c141974c8db04f4c525205dad6ca23ccaebde585cd3bc91f5874452ed473" + - "08de95cb6164102744f90b3007e511e091653c97d364fe0cbd7f4cd3249c" + - "1f5c452becd722ccc8c6b4e371e2631337dff78efd903a8fc195a90ca5a2" + - "aa4513bc63cd43794ff06c5337329055c43d4fb547e63d6e4d14fbe37b52" + - "1411caf2f1b0df51a68f677db59aa227c725cf494ccb7f8cacc5a06ac5bd" + - "f135a2603175a5fd5e5af615fd2e7cea61934e6d938b9e672290aaccd99a" + - "7e26dc55efe928e56ae6354168264e61668a61f842a581cd0c4b39e0e429" + - "04631c01320857b4d7e260a39c7fbed0593875b495a76aa782b51fee4f88" + - "84ca8ddb8dda560b695323cdde78f82dd85757cadea12ef7cf205138c7ba" + - "db6a7361a8d7868c7aefa7aaf15f212f5f5ab090fd40113e5e3ad1ab04f9" + - "b7f68a12ad0c6db642d4efb3d9f54070cc80d05842272991bcdae54cd484" + - "9a017d2879fd2f6d6ebce27469dda28ad5c345c7f3c9738038667cc9a5bf" + - "97f8f3bc", - }, - { - key: "aa3a83a6843cec16ab9a02db3725654cb177e55ec9c0c4abd03ada0fbafca99a", - tag: "719dbe5a028d634398ce98e6702a164b", - in: "643883153c215352a4ff2bb2d6c857bafa6444f910653cacd2bbdb50ffdb" + - "cae23cc297a66e3afefbd85ab885e8ccf8d8f4930e403662fb4db5121aca" + - "82dfcc3069bd5f90be4f5bfd3c10f8038272021f155e5de0a381d1716abe" + - "0b64b6d0f73c30baf6ddfe0e6a700483cad0fa14f637afb2f72361e84915" + - "78ba117e1c03f01fd61aa8f31da6464f3d0c529524d12dc53b68f4d4b326" + - "db7fc45c63f75244002b8f9a185556f8aab85948647818f1486d32c73614" + - "b8c4763e2645bdb457721ff3901327588da01622a37ccbbd0374fec6fd1b" + - "cce62157e64c4cde22c3a5f14c54cd6db63db0bd77e14579989f1dd46461" + - "4c8691ef26406984b3f794bb7b612e8b160374be11586ec91e3dbb3d2ccc" + - "dbfd9c4b52f0069df27f04853e7cc8b2e382323345b82ce19473c30296cc" + - "453f479af9a09ec759597337221e37e395b5ef958d91767eeb2df37069a4" + - "f3a530399961b6bf01a88ce9dfcc21c573e899b7951723d76d3993666b7e" + - "24dc2570afe738cbe215272ccedb9d752e1a2da00d76adb4bc0bd05b52c3" + - "fa08445671c7c99981a1b535582e9b3228ce61662a1d90a9c79afbdcfcd4" + - "74def2b7880cac6533ba0a73fa0ba595e81fd9a72ec26965acc0f4159ba5" + - "08cd42553c23540bc582e6e9ac996a95a63309f3fa012eac14128818a377" + - "4d39936338827bbaafad7316e500a89ed0df7af81be99e2f6aae6bb62568" + - "1dfa7e100ebca5c8d70f67be3c1e534f25446738d990ee821c195c98d19c" + - "fd901e7722b4e388da90b95ac0b5b5dc5d052ad6b54f6ea34a824bcf0cd8" + - "7f1fc9a07e8f5b8aa0793e3c9c1022109a7c7ae97ee2a2867fd0cf0f8971" + - "34b3d150d3b24fcf8323de929b73cca01244df02510393f0b3905caa0268" + - "7fe35f64391e7d4b30be1cc98319716528ca4f35bb75d7e55cf7749968c5" + - "37136eddb149a9f91c456fde51937c0f35e7e524647311077e6fbe7f3c12" + - "37b9584fcf3b0f78744c7b2d3b452823aca06d144e4463eb5b01014201cc" + - "bfed1adf3414427072135d48e705b1b36ab602cae69428e7c19d39cbb4e0" + - "ca26a871d607ed4daa158b5c58a0a9f4aa935c18a66bdeff42f3dc44166b" + - "a299d71a2141877f23213b11c52d068b5afadc1fad76387cf1e76571e334" + - "0b066ade8da02fe3b0bdc575b1d9ec5d5f5a5f78599f14b62db0bef7ccc6" + - "1711482dfa4787957d42a58fdc2f99525c32962b06492229399980601bd2" + - "ee252306b1464914424de9aa414a0a6e5dadf8ffbf789e6d18a761035d3e" + - "f2ff0753becbd2dd19fc1c28f9acebec86f934f20b608a9ef735ac91f6b7" + - "83d9327cce7f4870d39bbbfb0100838dee83e6baf2b40cfc98415dd174ed" + - "72e393ad0459e8035dce7eb18eb3af2f39d2712846b9e1852cd61d06dfc3" + - "5e34fb761b67e2a711ceb4a82557371ed32ca8db2e4cd7fea0b6bd026177" + - "4057b9abc45dae6869cab1097459473a389a80a4523e5de696554f8b0bec" + - "0ca605e6acfaa00386fb5a48e0f5893860a29f35e680be979cf3bf81ee7e" + - "ed88262dc80af042b8cfe6359cf8b475560bb704728034e2bd67e590bd76" + - "1632e516e3292b564c7265d7a6dc15c75ba6f6a447b1c98c25315ac7de59" + - "9edc4993e4dc7d1dbfcea7e50ebd0b226e096500216c42de3abe352e5b09" + - "a3c9754aa35d00883906599c90a80284d172a90abbeaf7e156fe2166ada1" + - "794420fe55b1a166d752d0eb7f04e822d021c615e84777101e7c9f9dd12e" + - "565b7d093fe978f85e6142c1ca26798b45f4b8d23ecff6be836e810e314f" + - "ebd2ea66f2ac95bad84b39b7a6bac41448f237b45e9ec579235ba2bf5fa1" + - "f00286379ec107c743f06ae0d11b57a2f5b32e3bc5f1697aae812d7ca303" + - "b196a8a43259257f7697bae67adc7f121be561b2d0725982532ffc06cb22" + - "839d9066dce0e4d683d9348899089f6732de62751ca77f1c439e43054468" + - "2c531b9c61977bc221b66030f7571dfb3ddfb91d9838529dbc99612f650a" + - "d72bb78de061192068941a81d6ac341101aeb745b61bd7a87a35a2714d50" + - "c3eb2c3ea148fb9ebed948307f8b491aec277ac01903ba36e6ad54f89fe4" + - "280a17f8e7ae639e75aec16d56576f03c2a1efe4af995eb825ccaa6efe0f" + - "d6d878299a351591d791c286cac5cb049834580d47a9bb7720d0603e3141" + - "ad7c1ec2dd23d3002e15d73c1828a7f08062848b1b6fcf816bd954743547" + - "6f0d6f882125bd03095eb1b1a846d535730e258fc279f7095de7c2d3fcca" + - "a4640a2e2d5ce0974c1e073c60bb78171c1c88ae62c7213a95d36ea9ab17" + - "59093813b85d17ff106e69100bd739ede9656388bf47cc52730766a8a186" + - "9dcc623e09e43cfba1f83ae1d9f16789064ec73504c29686760ea02c6634" + - "a929ca10c6d334b1751494c6d143671ce8e1e7dcc9bcda25af895a193032" + - "ce27c1016ccc4d85507fd2265ebf280d3419f54f66ba2a161c068491578f" + - "be056f02f97be745db443e25ed2647c5348f278f4ad8bf5b2a2c2d56e795" + - "532e25585984a3a94f435ef2742a0413abed7230ff2e9724187c91f73a7a" + - "726ebf36bc8d0d959418dd586452664990889358c56720c1001c004ff768" + - "54b9850890ce1b31735fd9f4a3640622ef0b25c659e8a937daa0df7a21f1" + - "77be13dfdb8f729da1f48e39a05f592d8c98da416b022fd8edab8e6132eb" + - "a80c00501f5cc1e0243b6b096c8dbe7f8c6ffa2f8bcc7f309fb80b489b92" + - "c4878fabad42d91876e10ee64ccd415124461cdc7d86c7bb6bcd9133f3c0" + - "dfa8f629ddb43ab914c0ac5ecddf4398052229876fd838b9ae72523946cb" + - "bba0906a6b3ef26672c78cb24cbf691a5ec869d9fc912009d840772b7da0" + - "c7f47856037c7608705cd533918c207a744f75fdfac618a6981778e09332" + - "5c7d22170da85bdc61044b4c397919d601a30746cefefa798c58f02cb827" + - "0d130c813cbeb67b77fe67da37a1b04bf3f1e9ee95b104939220fb8a0394" + - "86ab8954b2a1468016f546406d1946d531966eadce8af3e02a1f59043ff6" + - "e1efc237dbf4dfd482c876531d131c9b120af8b8fd9662cef1a47a32da40" + - "da96c57dc4efad707a4e86d0b84262d850b451bda48e630c482ef7ede5bd" + - "c55147f69e2ff8d49262d9fe66368d1e38ecdb5c1d4e4042effff0670e69" + - "04e47d7d3047a971d65372126ff5d0426d82b12b253bb4b55005e7a22de5" + - "6fa54f1dfcce30b1e4b4f12b1e3c0de27cea30ce79b08c8c1aceb1ffa285" + - "c317d203a9f2e01d542874fc8035b7670f3648eec79561d6ff2fc20d114f" + - "ba4fbed462f1cd975ee78763c41663849b44cb2827ee875e500b445193e1" + - "4556bcccfaba833bb4ea331d24a6a3bd8ec09906c7b75598b44ce1820a49" + - "fca4a0c1501e6c67515d4fa7f88f6aa3cd7fbc6802131a7b14b219e154db" + - "9ed241133e10ace40e4d963f904dd9f3bdaaade99f19de1ddfe8af2b3cc4" + - "0a48374dd8eb559782bea5410f8f9a1cd128523c0157b6baad9ea331c273" + - "311492fa65c032d0d3b513d23b13b86201840d51759021e4133f873f2781" + - "8f54f34ba73b4f33107d49c8de1533856ec37bb440f3c67d42148765610c" + - "3296bce932c839fd866bec3762a38406ac2b39d0d93730d0c88cb8f765dc" + - "d8ee71263fc96068b538da06fc49e25dbeaa10a5111a9af8e8f8d78e6ed1" + - "3752ad021d9f2c6b5ff18a859fee9651d23a7237bd5a5c29029db3882c47" + - "0470de59fd19fb3bfbd25d116f2f13ef5c534bf3a84284ae03e3cf9cf01d" + - "9e984af9a2e63de54e030857b1a071267cc33d22843b28b64b66e4e02803" + - "c6ab5635291aefa69cfeb3958c09d0b37176842b902da26caae3f0d305e7" + - "c6ab550414e862e1d13d9bb9dc6122cb90ddb1a7bc6d31c55f146659baa9" + - "6cca4ea283e5e1639967889543ecb6849e355b6c0227572097221dd46c1d" + - "f8600b230e9644ba611ba45cd83fa4ac7df647b3be57387b6db12682018a" + - "de9be50a8ea7d5f7c743bf0c6382964bb385b3c207c0cdd63279c16130b3" + - "73ba974125291673344b35c8ef9a33be5a8a394e28dc1448f54d46af675a" + - "edc88ce85a11ad7e50058df4f3f2364abd243683d58a2b13fcb0dc0eed21" + - "380b666eb87f4be75e7f2842bae916c15af3e9658c55408537b2301faa6e" + - "42af4d94e3eda6a41d6d302be281e2a9299e9d0fb1f20cf4ca978e66bdd7" + - "4c8bea0f15c84d6513cdea787dacbd4bb529ed03528284cb12f6ecd841d3" + - "c58c3a57c6bc19b65d6d10692f4e1ad63b091137c8acacc6bc1496953f81" + - "2972bf6362cf883bb75a2d10614029596bf9f35e92addbb50315b30161b7" + - "de8867a1393d9583887a292cadceb54078c9c846ec30882e6ff987494060" + - "721d3c761940b91a126e8d1e0118617bdae01a7f9c1aa96bdd6c78ca06f2" + - "6c8d85664a8705334f4997c724ef98fe265985593d5a9c30798714e6de1e" + - "bd04b648be47a6b5d986a3103e738a5cd114b19b7ba99d2e2eec6181bf3d" + - "ff0fec8c54ae6118be8702c3e775d493a6fafb509712a43ee66c3f4b75b0" + - "194c88937cffa5fa17b284d2556f2b0eebf876e05f92c065515198bd5e83" + - "00d0db432cb256a4a0f9963a05694ffce3ecbd182209e0b7bb50120f6be4" + - "eeb9d268b17790ee14a2c887dc5753e0086630b3123734053aa37595aa8f" + - "31968ddae4991af4ab970c1e3cfa1146a2efd9dc42abd6af14777b8a0455" + - "3865691cbac4b4417b3fa13c154d581b498f3b8cb77adf0e42dc2f2fb521" + - "732447de97271e542c6cf8cad3ba0148cc3ba1f2983ead836a25a2c022d0" + - "43ba18fcd009d518d07b53344a5bc4d626b3b38405a114471f75dc70e015" + - "d11e8f6f57d087fa72909785573008b1", - }, - { - key: "1793bfda9c8666f0839b4b983776735a927bdaa3da99b13c9f3d1cc57d4d6b03", - tag: "bc89cfec34ab2f4f2d5308b8c1a5e70a", - in: "a09f661aa125471417d88912f0a4a14115df9a3a19c1de184878291acb0e" + - "89ee1f9d8213f62df442f8969a9a5a7c402fea09bdbe236fb832544e1f93" + - "9cdd4873802b2bb8fc35ba06b7ff96da6dc7efddfeeda84116bc525a7fc5" + - "2d84d2e63cbac00b122dc64f2d15b36595259d81a1d2a09f204c54072751" + - "dd812259df1104bb2d2ee58baee917c5d0aa2649c8a1503114501e6ed6fe" + - "239847d3d88dccd63d5f842426b600079c6bf06e80a2813b2208181163b8" + - "61dca07fa4d88254e84dac1c78c38397a016b5ad55a6b58878f99036db56" + - "89871ab3c321f6ed5895f218f8fd976c348b3f1269fcdf4d38c9492b4721" + - "6c45f499f5705830b33114d721f9731acf6c69fca681b74c2d82c92e145b" + - "7bab77110821d3a12cc818d7595a5c60c4b5e5219376c38a4dd52d435d41" + - "562802ff65ba2bba5c331c333d5adf194d29b2cd9ebb55927bb4ec17681a" + - "3f5574ad34fb4e964f2c756f6dbbb7a6876a21579a515263444de7a30a33" + - "15005458bc137ccfdff18a3892fc9f58f1de10d4de20bbcf860f5f036d8e" + - "8a188f18e5cf7ea3cd260710e7491befcb131d49a28dfb1ef688fd021a1e" + - "e4420d32fbfb03b47f5e85c37d91e49a1b0db85d966eb5434c4197433eb4" + - "9d56f2ff999c9a72230447032dc949202468261b48b6ac212e3f651d6c63" + - "03a06c90bb2d3a755ed91ba73bcdc28e1c5b0936e51e0a9f69c3ebabd3db" + - "add7abab6d8f6a44daeb3126429a01815f57444fb7022a4a510f8b564ae2" + - "dd9779b3a273fef15859a33e233724846c30d89fb78a595b6ff6c834812c" + - "00a991e405806aafd0c26a788895ad00a5e43c5426197aa8247207077548" + - "ee67db4cd6f878431a2e36e952d84b5fb89d681f553198e2c066310ea6ac" + - "3a31f5b1792620616f6c41d486fb844eeacc7fd36971abf416e8d6d50985" + - "c83cc92ea46ac37da8f0026aba30c945d8bb15080d2d95e4081bad626199" + - "3f95f57ed3252822a7caa035ae22a36c35e280cbbc82d729346cacdb1794" + - "ae9a9bb2793fd1d5c47121b135c2836063367339c5151b4e35278e97f62a" + - "fdd2f231d4b47812d083a829ebb9c374ff2ae8479cc4b76d55f9cef3ec6c" + - "4894f53e8caaeb0d8cd072960cedaf758e48e3640590d4f728626e0a08ee" + - "ebf719c96bf8ed4d0c283be09c0ae67b609e22d3b9aa6b03642854909de0" + - "5ed52b39673867bf586a632ab8072de15c637cc212cba8387515c9c9c433" + - "abd7ba6b02abd09da06a34694ad34f88515b65c0c9c247fdf9819fb05a1a" + - "ea4728c1182f8a08a64b7581cd0fb2131265edcb3d4874b009aede0e87ed" + - "463a2e4392aefd55e008eb7ba931788262f56e53193122a3555d4c08133b" + - "66020154b15643fa7f4f5e9f17621d350ede3dc70be02c59e40fea74dbbd" + - "7919d1a8d4e22ef07c916fa65e7d4b89fb11a7c24ddc4ca5f43344c753b6" + - "1331c3fa4558738ba7832b5b2a275bc9b7989b6e6888865793329806cd3b" + - "f0ba57c941d4428623e062f4ac05e7cd79ad5446f8838f2b247b66bddadf" + - "540845a1bb304a04b7edbbff579c8d37e2f6718f8690abd5231822c7e565" + - "69365ce532449a41ae963ec23a2a75e88307dc6b59cbb3fab913e43ed74d" + - "841ca9f6e4ef96dfd9f04e29e89361aece439c0b2e1943b30410a63d495c" + - "522ac3ec1b04ec4cb345f7f86969957ad750e5bd7dbf1d6a22eed02f70b8" + - "1cb5b2b020c0694d7f63044f9de0c3de1ede52009c858992d01ebb92ff19" + - "a9e0fbea18942fbafb77746c8e9e687dd58ccc569e767528bde43b62c7c1" + - "270a5721f1212de2b29a7aae2d6ba6cd173d7fbc78aec4356ce2e8ba9164" + - "d97dec061dd0c3a0e3c520a7611ac99739049dd5825537c70b7ef660046c" + - "1785546cd99aa400da848eb7c3c91247415c8e245d0f14c30d482c5849ae" + - "aaeab2568288229b08267818dae8f76fc674c684c99eb5faf88a0783813d" + - "f7298e0b50cb233f78471e5ca9cc3b04927c26a3871cf253798cc49aa717" + - "d8f18a1ddcbdc26497d188f15f86ec494dcf8f942c3e07e572385c6fa0ef" + - "40c0b625f1737543074a747a369482a0b342a08b3eccac9f9209be31aefe" + - "5a7794974f71ac0bc9a58026397ea3dd4f5e40511d58d2a3b45925c194ef" + - "13987037d736dd48b509d003a86471d5f161e0e5dd168b4f1ce32f703b89" + - "15004d8dfc708a5bb02b2e6fb67424b2cbcb31ddaa0114c4016b0917382d" + - "aad11815ff5b6e37d5af48daa5ef67cee3439283712bc51b5adf2356cb2a" + - "5181b8941fd78945c7c9d61497683e44fee456ad345e12b4258f15945d45" + - "b6ca4369ee792d849112d583fdb39cd4d333ee057355f0abc8d1eea4640c" + - "128cc1617982db0394233dbd416102eec1874081247d2982bbf9fed1b1b3" + - "8f4da923d68c8975c698f189a4d7840fd7aca9dceb7d91c076f85e1c546f" + - "4d5de4f60c91348455aaea30cac134c844dad93d583c139dd52b3be6346c" + - "4d2e6864125c5a2d0aed8f67930e1ebf8700ca88aacc914ea76ff17148f0" + - "777738cc126e75a2c81110faf02fefc47c91edbab7814599000ce55fe20e" + - "f313566e9b62457acf2f22e1141e220bd9d4747417d03e703d4e39282803" + - "386327fc65dd597f723ee28185c78d9195fc70a75706c36287ab9c6e00e8" + - "5cecbbd6043c6af8d30df6cdd8777be0686853b7c8a55a5b1e03e4431d39" + - "1725ff99875a85cae6926998723b36d13ad458220712209bfc5e8d2ca5d4" + - "4ea044d5ba846b4035e7ac7e9885f55d3f85c0c1b3d09fe929a74450f5d2" + - "9c9672e42d3f59be4ca9d864a4322cc454c2578493bd498a51bbe960e657" + - "3e5dd02c4a3a386d4f29e4578a39e9184024cd28d0e86ecac893b8e271bf" + - "ce3f944d130817378c74d471bd20a4086f2429ed66c5c99969fd8da358ff" + - "5c3be72bf356ae49a385aa0a631b588ddb63628fd162673e915cfc4de56e" + - "ae6ff7101df3b33125c9bab95928f6e61c60039b6cc07a66f9c733251447" + - "ef9c1ffefa2158a8ddf89dc08686a4cf9b86ea09914e79842d72a3236afc" + - "98a3afa0a1cac5590ab6a923e35a2ab8db6410a9d33cb84d1c48a054377e" + - "549774b25f50fbb343ecd5db095155cce9fb0c77d09752f62d4bbf16a770" + - "30452a75f6bdf73f7807d8f3a6bae16ad06b22175fee60549c22548de9c1" + - "3df35ef4e7bf7b66491a62b93c2c3fb0c5edc51f60f5704b56af30f1079d" + - "7c385b99f958ef8209e030e381d1ee8d67d3cb84f32e030e8ea2c1d0c77f" + - "d6b242a9f48707557c8682a08e1127f51221a55c733ab1edd00a9c2912cb" + - "36dde85f73b524e1a4f4da6414c5e4c18d9537722b2becc8a91bcc63f2b0" + - "9f32409c53c2beee0de6726dabcd6bf33118a5c23fb9c5c1810476efe658" + - "4bb6109c516b45e16b2f79f96755680374d82b91f2c519639a1815fd485b" + - "a3c00b46fbefeafcf25554ec5a6a5ae2da07c85b8a0f9fcde50263d9ed85" + - "038b2f7aadb9de765655bd201235218bfc74bcad6a9ddf4506167a649afa" + - "df400b85752d68a92b7a97f26b334dd77fce824862046b286a7c8e0adc36" + - "f713a252a673d4d995b268badf4bec8b8eefe85c25b823b6728582d35c4a" + - "60041114dab72b0623b99e2758f6a1e97365279bfba0eb1fc8952ca4f2c6" + - "fbffd9f5fd7dcad1125b18a796981b5ead0b6431141315898ace96f0d38f" + - "865698df8822ca7b65644b6b1f0a0f0d2e5850d4c93ec48ca3eba1b919e2" + - "4413a46d595ffa427715e499db3b7b9ab53c64abec7302bc737a5bd124bc" + - "da756abbca132f7f67e6989e09bfb23b497da31bf156bb9c69ae54588df1" + - "7420e8fe989f0472c8893b2bfe57cdae265a8cc7aeb39624167a567a6fbe" + - "bb1aa30c3dcfd14f2808a070994085e6e1fa79021e77c399f90ab1f995a7" + - "baff672cb693bd39b798b4c890b7d0a57978d6b9bcdc5bf3f4d205f8f24b" + - "2b43d3ae300a96971c9182be297618b9adceebedba1ab0f324b01d23d7e6" + - "35f009db3dbbc643c2d787567594bc639bfd78c4f3e6d948caf06f013423" + - "eb3c764666b58f886d5d28137c053c2a28535efcea400147e92ac6753574" + - "3b47f9cb48852abed1d057647d5b1c6f334eab1a813401fccd3dae332738" + - "776bb223e359f3c459b5c573ba64fa945bdd66c5ac0fcbd53b67032a7b80" + - "25f551e8d1fd2a4291bdb7941cbabe3a09765dc263e2bbb6db7077cc8fe6" + - "790d4bed5e36bd976d1e37dfdba36aafcdaa10c5f3ed51ba973379bcb8fd" + - "203d8b7282abbd271ecf947e54486e8653b7712c9df996a8ad035f41f29c" + - "ab81509f922c67dacb03f25f8f120cb1365ab3c1c286849c2722448ba9bc" + - "ff42a6b8a7a52f2c79b2bfcbdd22ef8a5651c18879a9575dac35f57d8107" + - "d6bece37b15d7dfff480c01f4461ef11f22228792accda4f7936d29d4c56" + - "cbba103b6d3e6db86e39e5f1bb9e9fd955df65b8a6e44a148620f02b5b90" + - "b2be9e5bb526d0ec75b1e723e94da933a356d7ca42d0ce8349699f730b8e" + - "59bac24a6b633759c88041d29399ce60a2ca2261c7eec1acb9a56e0e65bd" + - "e37653ce2cf7eb83a4d019c755bdc5d685b6394ecddb9006823182dd8138" + - "a1bf79a32d07a8e5e8ab221995c714e571b40bb255b79e328ab883542c16" + - "4899fffa16eb3296f310e302512352a864fd809beaab4169113027c6ccca" + - "99a92c6ce35c30f9449a3add70f10db1ed08078e8e6cbaafef630aab7e9f" + - "c8adb09c18e33fe1af3620d1e4d069ac11325e23cc18e5519a1ed249caf8" + - "ddba871c701f1287cc160019766988f63e089bd9bf1af7e6f5b9002e3b6c" + - "264d69a8bac16914ab55c418d3a8e974677cdcbea36c912e90386a839a37" + - "77b878e680c07c7cc99f42a7dd71924babf7fb0627d1f2cc60d9d390d1e1" + - "50d47386be6eefec9ddbb83b28fa7e2fd28cc3867cbe42d13b00545af8a0" + - "48cc07016ec79808b180e0b258c564739185da754f2e", - }, - { - key: "0d41cb4ac25217feb20e86fc2490e8d2ea2e8225c051252a9395cc4f56e1ae5a", - tag: "42df9f9a59d6dc05c98fd9e9577f7176", - in: "01caba7a19cdb09dc0ec6c522c61c628eacf17ef15485aa5710fed723875" + - "2e4e8e93dd4bbc414e4c5620bab596876dfbea33987e568ddabf7814b318" + - "8210a5f8d70041351e4d8410840642a29cc8d901c25fa67cc8f9664ea5e1" + - "9e433eaff7c722d0258ae112b7aca47120aa8af4420d4412a10732551db2" + - "cd3e0af6e5855d5eea61035af15a4d0d898d04033809e995706eba750a7c" + - "ac07aaa0dc71477d3020f778d0347f1a8e37c18540deb9ae967e734c0264" + - "df0e1f52b0b5334805579ea744c8784c3ae0c3ff8217cd3f53cb747f6996" + - "f3d2147699799e649061b205f97f7992e147fb20f21ff862c6c512e95534" + - "f03075e8e52f162e0d70d7a259e3618474427f400f44f75198edebae6e40" + - "a2173257d114e1bb5a13cf419c821eb124d90e89a938d91f4d2e70dfd1ab" + - "60446f1b602614930a329e98a0c30f107d342281db25b8f8259933e14d20" + - "8bbd991e42969e8b0600272f9bd408483cddfc4cb8dfe7bc19be1989c7fa" + - "129d38e1078d094b82e0a845040ddd69f220dc4aa2b236c44101d7da7779" + - "9827a7b037561b51e50fa033a045571c7267af93b96192df3bf6180c9a30" + - "7e8c8f2b1d6b9391767369625015da02730ad6070df4595eb8099bd8e484" + - "59214310cb62c3a91a4fa8ac3b3d7b2017d4254fb465f0a248e1bf45819b" + - "4f0360f37c9a79d405e2bb72e5c25a1b4df192cfd524d61e1e8b274f2fe0" + - "634c73f0653c7c9e9062c9d081f22a8b0327897eed7c6e870f2815bbac8f" + - "585c1bd868759a98dcb5c3db2f6c53244b9cc494a56f28a9ba673167cea8" + - "b799f37049ee7b0772972b3a6603f0b80eddb58ef03f916106814d72f000" + - "250b3573c97c5c105910d79b2f85ad9d56002a76a1f43d9d1c244ef56d3e" + - "032a9bab95fe3bd5dd830ad7d7e341f28b58c0440658f7fc2ca98f157708" + - "1c647e91432cb0739d9acdbf973ceb9b0047634d695279e8837b04dc5357" + - "f013fde3c55c9c53bf1d817ec59a1b18ed0ac0081ed9bbb3bcd1a5d3634f" + - "50f7506f79dc6a4ebfa640bf65682fe9aeca68088e276937669250064de1" + - "c19ad6d5c697f862114d0f81d2cc52be831ed20d3aab1e41fe6f476b5392" + - "af4799392464c51394c2d1a8325ee2e84f1635d295ee663490e538eb338c" + - "7126a8e731ad5c0becf144c7a9cae5c6493350b589385de29e1a0ad6716c" + - "346ec4f0a31ca5ea35c59ab6b099f65d7f0b3d00925a1da1b5777c029aea" + - "9679e895d7100645dc83f81d82a6174beab2357f7888ea640900cf3ee67a" + - "e0724a123919d78e70e05288f67e5e69ffa6f345be8a96e58bbe260184b5" + - "ec5c0c1354cfd516ebdb8d420029137d41b029641959cc07fa7b4e16b39d" + - "17f36b2367057410a42e0550e9ec1dcd2df4604d52d4f9dd1140d57af08d" + - "50e1527dad793b6d649324de799754f755818bf10e6d1ab614958dbb24ac" + - "8e2c01270a90ec3df4379c3f509b5ef721b0fd4f91a1bdb8127ae4dc74d0" + - "75f6cd8bb28319d6f8e8d8ff64fb4a42d646e9365156c6bc72cc46e9cd1c" + - "f9e735549e3df9a8e6b5fe541948b126190117db71fd1d61ad84be0f725f" + - "20b99eb141b240326d399976c4f2ce5823d94649a9580e1e8820bf49184d" + - "fc34378a60bea89b12aca69cb996c17847b7fb517cf2d51f16d78e3875ce" + - "aa33be15f6a154004f0e1134c6652c815c705efc34bcf35bd7743d28f0a2" + - "77d82dea4709dab41fbfb4e0cbc118c17aa00808872f0edc6437c357cd31" + - "74a02aee61890464e03e9458853189431bf5df6a0ad5d69951e24be7f266" + - "5bb3c904aa03f799fe7edc7bc6779d621cab7e520b5994f81505d0f01e55" + - "96e14b4c1efdf3e8aadee866c5337c1e50066b3acc039c84567b29b7d957" + - "683cadfb04fb35402acaba631e46ca83dbdd8adf28e377ec147e4d555a21" + - "e6d779d7c5a3078ab72702234d36ca65f68bd01221c9411f68f32e16ef04" + - "99a20c2d945fa31b79d9965853d38ada9d48eead9084d868c6bad974b0f4" + - "0956aa0fcbce6dac905858e46c4b62c0ee576b8db7d484a524e951f4c179" + - "decfc7d6f619e86dee808f246dd71c7e0b51d28bc958110d122fa2717148" + - "77823242711632f6e1c7c15248655ced8e451a107707cec8c84929beece4" + - "efe5503d3c1763d0ab7f139f043e26027d5e52a00d5414dd98a324a8fc2a" + - "06a1345cbde747f41099c3377b86bbdc5a17c8f6e5b773a761f78573832e" + - "4359b143810361dedc79142fffc49ddc0b32f225d50d360ceec3920fb0ba" + - "0693b644ee07fbd1ce829e223a02794b197614061c4bfa46112d105c2b7b" + - "4efea448501d146dece44f6640d674d5749db498b32969de6e165e705a18" + - "2aa1f3d8e16892b0120337640d52c9bee35e5b4b17f03eaeb31205c8ecbe" + - "1ae1b110023016e40ee87370a65c5c20bfb00f100d3c6c1de6e4a1c90162" + - "f25bddbf300ed637330206788a4ff96903f971c9618493ad074412af625c" + - "ff9e0f8f183bbd5e96c1f28307e6cae8b50cc0eb1a3a8154e44e9de947af" + - "002e4d1098d6b0ee3f2e71a10d03eb444729c42461283f37be8af2ce81ba" + - "bac246a05c2c94efacc43f0cf9ff3df38ab6fc1648c796ae7026ea95752e" + - "b70873a6da59da10d8b5316126431c4a17289466e95dc739c061d7a4b13a" + - "450809479eef421bddcdade77a6df133410328c754af8999a09b1a5c056b" + - "ecbb6fc2c339586ab92100f46d2fa1fa689994b36aa70703d76bf7738adc" + - "f0589fdfa6bd215339ad69ed983f62efce0add5a63fe7dfe4bfa006ff16e" + - "0cc06d39199ad60adcae12b75ca98d764502a783373da3a41281e03c2037" + - "e1b3ca7f7eb60e2b67427e97ec72d36670db7662c6daa505701fd279f116" + - "ac0ef569471f204e1531c25a4ac3ce19b6f68a8994b6f89b5abf034a6507" + - "32c7fad4206eb4eaa7cd9a710d866bf3c3f13c16faa268ae0cf4f69be909" + - "bb9b79aab80dd25101d4cc813a48d3f38d870f10ac0b6768005aa0e69e87" + - "dfc0424deef06414c9ba6f498c93c41c692a7a6221fb5595b390a32c70e0" + - "2cd64471c797ee8a143725849c1e054ee2043dcfc0b4cb1c00be21a14be9" + - "2d9a07f1b4e975d4c86b8a5c1387e6c42bf393e078fe86d24612d497e14b" + - "874485a3cc922b5b6d91295d7b79ab8bfa1c7f64b51e761d19bb9da82a5a" + - "a34aa469699036b6b2c55e2b84f84942f10585027ab07e2e0e562e0fc3dd" + - "36047850ded84be4416e22aa41c7a2f7d4a4d8e3dd420d746a1d8d56d87e" + - "5133a1b4380bd9a89500fd6d7e68a1ec02eb9e79e4a13edfdde1273466e4" + - "6b0e6a75f59ff6175716629da52463ad21de27f40fa2e25a566eec4b2696" + - "4af3a717dfb0170a73144c0bd9b00bed67ad8c0a146eb5a055812d071209" + - "c9d530cd4f50a41488c2238898dea8bb36b0f1496d3ea8c4ff8e263b367f" + - "64977679e697d88e5295bd97ac16a0420850d1ead9621e25a3f58925c266" + - "ef5246488b1c15a8fe0d8ec4291864faa5a67b2388b7786f47b6d27e8fe8" + - "46f85f85163e54155ef95cea4901e712a44404a4d3f27f28dd961ce36b84" + - "f3856770f07f20a2ebd34d77405beab04ddfc09770167d7d6340f494dc6b" + - "7e4c3df896bd974730193b1e862b58d4a5938e6e4ae8897dba8812924379" + - "e54f51a71364d39f76e24fdf2c6c704479ce85b456558ca6947b8fd76f03" + - "78273f0a7bcd1d860ef1defe4eea8fdb81c73eda028d82fdcb2248582ac4" + - "59eb7698a811e6c5823be886410f6b8577ff2e8252343b6ea890016ae846" + - "01c5894cfb988121059fd9c8fbc1596da470a149404fc67baa15383d38cb" + - "d17ac107b4ff3c1ca4c76b7930de02b240e7547d39f4978e0cc1fa37f8c1" + - "012b677f07bb4df4486196e9b0beb823a3827585475b878e3f6f0a2d3836" + - "2c7d34f9f3c91ed46c39cec95c2a0b6f0279a03a00ed5035b0725c393849" + - "cdb1ed3c0ecbcf3c2ce108017f468e1c3d469c03e8231d4195344ced70cf" + - "daa667252cc1554dce8d0c54eb4cf4da62367d77d7dcc02f81e788ce9f8d" + - "d306ba1b48192359cfe92bdbea9980f87ea0677d7d2082205a436cf514e6" + - "fde5eadd21b13dc836ce33b5dfb6118bcac79ae00fbb16d61f00a923b145" + - "f9caa9f3a2c7f0104f8b052e390987e57c8dc80cd5f0358afb0111af1fc4" + - "e31f92bd832ad35fd2e0bdf768272de52ce0b152f74d43a8973ad516b3ea" + - "f5937ec8a236ebc86adeba610de0cf7168453111f3c983b64df07678cae0" + - "a75466ae15adfb127328e716448cdbd2c1b73424cc29d93df11a765441e0" + - "0eeed72228e1099bd20569d9d0e9e5a0b3c11d0002e2896631186483db61" + - "c1a0cb407951f9b1ea6d3ebc79b37afb5a7037e957985e4955979b91fb85" + - "61ca7d5e8b9cdd5b7ce0130a880d9241027b011fea7696b0c695d4949ca2" + - "d0cf22d44b9fee073ecaef66d4981e172e03ea71a6edc7144393bfea5071" + - "2afac137f091bae2f5700bfb073a6d57fddcba674a899d7349044a10aadb" + - "2e7f547887dd2f765f394de5dc9ef5dbf1eab4d869be8cb68aad8e2614ac" + - "37bbf21ccd5a832ee09fdd07ce50a580a2af36256b1046e646fe3dff6d20" + - "0c5110f1ad1311bc39b8114cd11ecdb87f94df43d4f6468932fc0ed892d0" + - "3d8f3db3f8323ebb29776ab7d260493a36700bcda668abd62126a8189e91" + - "df2d2970ef688d4e8172fc942e69ba63941a36b79ac546fff38f5f7d1176" + - "57612a662ea38134e1090c3e903c9adacdeefd3ac2a0467e9f5125058c19" + - "7b2260d2afad2b0e627a9ae52cd579ee27168065658089e1b83a2d8cdb47" + - "e08966e4ec0018e78c4d267f9575b8fea2a42de5c2d25356fe4b8c9cb1ac" + - "daf0d1af4bf58b9704cd4bc08471e3b9a0e45a5693433ede2eb1374bce44" + - "1f1811cdc7612d7bb61f4f34aea0a44757bbcc12a55c1ba41a7901eb004e" + - "689587a38e5b4df4574ddcc7b2eda97f6e480d7d39f45247ea3b03c90a93" + - "0dd168b65d52a59ce9c2cb4e860cc6aaa0ee02a58d0c8ba990194bce80fe" + - "8c34ba5693fb0943ec2cbfc919e534cc47c04f502b6c217c2f860d1d482a" + - "a016aa02adfc2bea3171fc4e27e2a262fd37b824099aa227fccca508f778" + - "b8c6ec7aaff1d15f6497753f439daa9e52060fd6e9e056e6843d770fb057" + - "6d9e2e782db4843c0c2c7f408a17376719a3c5cf9fa08f04f8a779885a16" + - "5cf93ce404be", - }, - { - key: "ddbd5d6c5ebd61fa72b453dd849dc302c98a0f3e300f4768bf1dc698a3827dd2", - tag: "af608b71a353e63c64911558baa122f3", - in: "c67e2524b0de16483158a0232078fadcf611e4fbdb9e642e397b21222423" + - "cc2ed42ed34ffcb178448919ee337eff9d7d691f622e70fd3317cfd271df" + - "fe6a9d9b7e07db0d20813e2331164a654386db2ab06ae2983bf2460eaaa6" + - "3aa0171fb87afb82e85b40d95c8993b2039d32e9d38473dd13f41fb1ff1e" + - "261752ab004b221a4472b9b1a0e139f0c999f826a26a7e7df362b0611aac" + - "fa83c55cca2f7c0138d2c30313c2f6eb357278328ea6ebd6a5077947e18a" + - "a97c34b9dde3b6f2de4b83778ffcebc8c9cb58756691d5e2a3d15a759a2e" + - "5050b6da937a6f5551aec069a08027d60dd870d175d2a5b5f0b4f3143904" + - "7445c368a5c866370e9426abbc1a1c5a272b96731c4128aedeee93e8e00b" + - "b450601a6d31ea279b9450e738b4a47c0dc22d2d8ed5d44257f6318e0c59" + - "b951fb6b57746062ab95cd73c23ef0a5c000a7d14c18bfff172e59b6f6de" + - "aa61b81009e803eb05e24fb0b706870e18889a9180ac16a042d12dfff9d9" + - "1b88130f045d2342fd5ddc5f443681c31090459f262d1a65654c55251fc7" + - "d5a67bd2e62940ccd606f3e50700e4d1e992a3fdf0388b9ce3df9de6dda1" + - "5c1cd6b70622ac062dcb7ed7058872c00ff3df94032853927126cf6fa4cd" + - "c468d91c9b52dcbc272fd7ba920dcd3ea1e048af9c3286dba74d988ce9ce" + - "77174e25a87935352721dc23b60a9549322fadbe6a00dd1197dfa25b33fd" + - "9e5713afcfd0fae6dbcf27147fa58d995580d7e0a903c895752fe9819f5b" + - "b002ed752719552d0f3575312f2e618173a8ae7c147ca64a709053e5d2e1" + - "2f4d1ea337afa9ac4f9ba62760046ec1e48f4ed8f6df66786c9fd9f5bc7f" + - "9ca2526e1327b042f4657c405757690e190c91f260dee2dd3d2e6616b721" + - "e489c7c3cb828478a3d953b88f09904e7927cdf6dbd6a5419eeeb83c0be2" + - "51934a80dfe61e09442f0761aa2d013e10aeec3a32df204571ce8984a430" + - "9bbe30ccc91977790bf0305d2651ee450b749c3e7761534e45970e70a0a8" + - "473cadbc88f096970c275f188c9d2644e237fd50c2e24c1eabbf7578e80e" + - "6500762ac513fcd68cf6f8bb7a9d9eedadca059d9ecec07fe6fe7792b468" + - "9311861728dd482f087c28374cf9c5ea20b2c8630029e8485fa6fe518c74" + - "ef77d44eb7526ca764e50b5f34ed0f253a91fb2af6e59338e2af6e041e01" + - "084e1efade1aebb7d1b698ccdb8b4248ac89cd40d9517d840960c08f5e86" + - "88d8ba2b54889c1870d315498b70e0e9720f2c8c53a3377a8c0bd2d6a1c6" + - "f17c6ff847eb14def6855dc3886b99039e528b421ccbf6064e39263f8f3d" + - "340d5d20b1b14c264ac2310b5f3a0c6f0c1006d0d4f1a69af68d28ab447f" + - "cd17387e1fc98f164982a6d05dd32d6b4f0f1b04e40c6c6e0fb4467dd6b1" + - "0c5a9c92cc8c2bc97ef669b6d55cdd0aa8a15c46af954359165949012713" + - "4ea9f74181d54a300d3172c9f01db73288ef6a709c763a4891666d0baf88" + - "8531dcc77f0911412d096aef9033fa36b5c1ed283b8b5c109e45b5cde911" + - "6f3da2533fa0ab81929bd5783271d5501a9e4fce2aff9eb5a70a4215b253" + - "46885d7e4225fe34bb55b309a114a312693d60ccc61267359a8c2dd28141" + - "226e7cfd99f0f12c69df57d75dd790dbabfe3145f7fd1a24fa58e03bc2e2" + - "6ea19288af4929e5acc517d8f52a074745ff4644d94179eae6ba7d267292" + - "bbd2053167a0da9be5e4b6cd0a4200fcac5182d9957dffbefa857e662b82" + - "fc3a7cc32506e78030ed5c5d448d7f1b4fd854a735a0c50016bb85e6e716" + - "0f87527bca0de235f4b7dacb75be84919c15a5b8cf6bec035795cb67061b" + - "7855c2134c1b1bfa6affe04b7db239f73af6ea9c02bc9f7972b7f6400b6b" + - "838f4653aefc42179c21765e3ca7a5e96b4402ff544d4bc2332756a23500" + - "11241dc42ec6848afe127c00b9c333e69bb5a54ea5c7193e59ea22bd6d32" + - "af4f56b1bd2d5982ef7d9c1b02d7668525e4e81b68a400f7afc2653f0f41" + - "a03e11c7a02bd094830093481afbab96397245b9f37a568ea1c4ae248cdf" + - "afc87f88b1fb5dc300d8e9039af4e6e701b458ed3f32d693f2e869b76bb5" + - "1358cbbe5b5089013bf452734388a176cccfc1ae9b7cff603631ca48e129" + - "b5c9573d4e379547272cce8aeeeb407d3fc57f782a0eb5fcbd41e6fb13be" + - "7e4f1067cd407b42a6121b2969c384916ba2b32563e659f52aae09c8ce2e" + - "3c500fbb7e58be74cc1592dcfacd9f0d4cea1a90a18658147c81cccf6fb3" + - "078ed27f369e7646f551386a74e1b07074d93e0c1f298c761af46cdaae9f" + - "f4be86808b66d0e228016d27a3a77c843365cb847fddccb0bbcfb3b9008a" + - "1bacac59ffb0aa759a0568c72c556caf0ac1091431b574687c5fc7bd486e" + - "963e0fc3bdc828d988734a21070747c955cf8dba2df1c3a0ba8146cd58b5" + - "91b6d54712db67a9851b1607c8445bc97406eeb7488f5f85e547850d619c" + - "407f97632ca1801f52c09c2b314b4ab0f8e7fb5851fd60852f4666913ca6" + - "bc840c1ec8f8f06caefdbfbf02ce00f20b87b14ba9e651c80f40a31d0306" + - "403f541776075fbf23733a6b19e3b44d04b455b29ef8effa70cce0c59331" + - "7119abc07aa8c8d0246a760b0b36a3d87b244e83bae8a745b8277a531298" + - "f5d0283498a509c89898ddf0f7a7455be1f8a6889c46d323f1dd18c3babe" + - "1751a05f871f0639f50967afa46c19cb93d9c2a79c81e2436a7a62f225bc" + - "37c90698640f5b43673e1dc276de05ff1e29acdb4ace5121659db5f23c49" + - "57aae22f53e6f2cc935824fbd07c2ac87672eeeab895c3f06e09e178560e" + - "2fcfa7097f10201dfb8b1ebac08ca806c1b3ba3aff9284846a1a3beada53" + - "e9f7ade12eb89b5591f462b2543bb4090e081fee9fb53bbf821dc92d6b16" + - "fe820ab2ee4b1f6c0b6a6f19edb0bf6479e257fc73bcd60dc2261d0a4752" + - "e23a0be18abf355f3065177d8c3c14e21edc178d0abd1b39f703e6335131" + - "ec90cba3d9846cee7354a06c320a3f61b8a269abc7138831614f57ca6c19" + - "a4a621142889cd924bf4ffb82b57f871b854f3157e8874c22d43a5726900" + - "bafbb8f2260a1eba3a462e23d4def2ccf68ebaae8e52739a1ce67c039eaf" + - "9a6c3232fbb5a91d1e59a8dcd3798ba71345fbf83d09b83b41cc49d5ff5f" + - "2e809d2b1d5fbc1e7001ea76b9b2d8f896eb6609e2e1c5c562d2a6e74960" + - "2d67a0f6b43a201d5087509b8dc7b0440144e308c18ff8b96b607de2f20c" + - "6ee99bb05367a8b25947011889f724965a2b5c52c9db1e0622df9343c548" + - "d054699badeb15fc41055af0d79a2bfc1a5b4574634fa0dd9dd10a6213ed" + - "b6991187dc560facdc27440456a0a209fd7f5ee4fb350ae71f869723e5eb" + - "5338e3d1448bc993afca6957f4cc7b047a2c7c9593b7234725e66cc0eb23" + - "3824eb4cb905701cc522ec210950b871397c6c0bb3d0b839f2eb1a120f70" + - "36107246df4dfb2c24891bef0bd1dc131f2c9d7c295ee967e3184d963037" + - "fcc9e0b8c7011c8e04b4e70038150d34caab4f8c0230418cd2d8a91146e4" + - "4e11cf6707452ddc03d9b4e6380658135dfb48f62c0690ebad75167f4dd1" + - "c0df3ed555b5081a7b82616d9e501757c83c2193d0f640236d59f9c97a4a" + - "5c8bf532aea2cf5964ed2dbd8a70c01ca5c7677224cf2a37f3b24d8fe4ba" + - "91cd3b5033715de227de51deed15afb8eda9d2b9615d197b8f98322d7096" + - "79c5131eed48050fbe0145a9284e236605c25a4876e2adba42f4e35a8949" + - "3d59bbf44b3338d9d2e65a7d7ec6c863cd47cae9e23181b07298078a5e9b" + - "06a5c7e1059f474eb1a4247e8f02cdd4efdca67d22035b12abecf9b15982" + - "de4932a28e797bc4de38442cff2cba263eeddba0ab14fc706dbca04eaca1" + - "b4cc13000a10e35b32461424809b299798e4d8e66c92aa3181c5df16ab65" + - "9611cb625e895a8021af8c60960227d6f2ebeacb17b13536a5ff139734ef" + - "37cb67018ef9a410b856e6f6eddbe3f59b088d538c50a8f3f0912d06e47b" + - "88d773069aa759cc614e1f53cf6e572c127123d1ab56b79ee753a921cb22" + - "a60e4e6cae768c9966de4e2625484f2e990154da7fca84b6e6c0b59201e7" + - "fb8a729cb20b4c774381e84f1bd6e304543d952dc76ef741b72f3a4ca7a6" + - "ea7958b8b6337994ed82dcf988eb70f509610b9a279ab4d0f28cc2b2dd99" + - "3b8637a6be0cb4b5f67c79654c6b15e1b61120374ba9b974a628c547f11e" + - "52d72d39f8f9c5dbfc23a89f22d38984dd8d5c3ca72cd54e6adfe2b3d163" + - "86afdb50967846a4c311351a51e5fd322757bdb061d44c8796a61fa4db36" + - "793bc11984eac83bbcefb40d0bc7bab0ca81e7df3a7f58c6fe800396716d" + - "832acaddff6d72c8e19dc9ea838294ead800deadb6bc18d3e399fa76c46c" + - "5d88ee72a86a87399423b0578eb6e27d78156ea2abf6f08b5cbf747f2f74" + - "5301b694bfba84bfe3c5527acd50660eea5105a2644c1aa92f954a604fb6" + - "a1b3b2d0331497deafc3aaadc7040b9188a36cf607ee85a0655ae963fd32" + - "91dd58f8bb50b4e46dcf7c2957639bffa6b12d895660dc0323b7a092f999" + - "813380b820e1873c60d3e3038129c66d507862100a5d5842150869e7873d" + - "6bb6ad022350ffa3813aca26c80ccae72692bed9c77c9d4da23178c57153" + - "90b5f4505240a796ec9d10a7f280bd60a570b1b693453807707651fc0464" + - "03e4768965a6f42f112152942134f0a38c84137c7a6e086ef1ab9ad20d24" + - "3b93356b305c0996ab7d02c02c44cbaf8f7e60b8c0b8c9fece3f189b099d" + - "dbd126b7357c1c4ea1c8bc1ad93db91ea9bf043a4320acb60b502bec37b8" + - "6b2a5004b8225e549e613c6f83b97b7e4aeda1b013e0a442d7ce2f14e78e" + - "a94bab700c9ac0abba945e28f39fdadff223c4498cb204f01ddfcb450a41" + - "f32ae47f99a49114c6646a5cb103e9cd75f9d81dba417e48c4053e3b0295" + - "2267cd30589b0f5d993a5485a6ead1ffab9f2f4294c5853ba76383a326a6" + - "a42fb8b78948aa49f0f1f614bd0a3fbd2a58a3197daf2094605bd838285a" + - "1260f1265dca74aadd95652632335fd17cafcb73b202c3f0e5da836c2dcf" + - "2934f005935dca80154af43fa34c8ba440d1581b74ff17dfaca369dc9aa6" + - "734c03916d78e1b952691cef918fe033d33f7f4323cf724ffb8cd6c219bd" + - "046e9f268eb0601098e93daa59dde370e46269dd7c54891f71bee2829a53" + - "df86a2c7fb1046cd7c98fa21cd83597be554997a70acebe0b6e60f1f7098" + - "6f65adcae24385cb7102bdd3e01300ffd15d00f9764b3a5c51e35e5c9cdd" + - "da84f4b656fe514ec4ff8dcd774373f8a9103cf36abefe875f7084b9bbd9" + - "42e0c997ec2d860a4b622ff1a39a628582fd81f237d3d8f6843d26ac77cf" + - "bd48003e8e8c591ff813a9a897e3149ff0297ff476299d717e54d885cdd4" + - "4c3ba6ebf54bc7a1", - }, - { - key: "b15578da1020f662ada0ad4f33a180d9f8ad4991b3720bc42a22b52625c7414a", - tag: "b0e4ad4a010afd6dd41ed82868cda555", - in: "6d2afb7a9154064341bdbb533f11990d4987e7c90fbfc0167c1e58d6efff" + - "6010f7ed569dac62ad37183b0d384519ebed0bf9c6e05a070b4858e6b846" + - "547ab5e45619c866f83cce83dcdab6a8a6c36b115ac832de1c6d433b94fa" + - "35803fa1a36f1ee114f8632402a027a74ac110394f32ec4006beb0057f09" + - "a94dada8bd0d1ca9a14b1f2efb8f526d79d6438bbbaac0ca1a43935627e5" + - "d129d52c06bf6413af07513bc579447eccc3a9406645c94dae59dab98d6a" + - "f92fa90fd4efaaa4bec466806ed401d2083cda587139ad7e9ee2adbb1dfe" + - "a88b59dd788b954a0f52c3854a3fffecb4bea83debbb2f5f8883e6415d3b" + - "ac1b872df1afe185468adc59364c173082f1dd6da9d348f5f5ba2d216243" + - "23de1f623eeec875bf31d12acec40dc0c1b9562826f3105cdad4c43cf45d" + - "829aa8b14012c47847aef7a2a6e3935fd972235f5d3a7ce4ad3582785393" + - "602e2e27329914021eff38ed2926c88acec1551f17a1b818fc1c3ed4b3b6" + - "6825d55bea269d710123b52e12ca9520a069d9c6a21df3a0253b3a4a6a8c" + - "dc226d667541548834da6bdbbdc165f39e40047d4b647c507d981be17b3a" + - "836063436241a8bb46b11a2867b621413c42d838e4578b72cc1982e34bde" + - "c303b5575ef4b8dd9fea8ed5bf69539413909d03461d3853b5fbf714a61c" + - "769569f42b38fac4b849104e2f2ac1dad0e388646278789f83e0b0511571" + - "019d3bfc5b03ca4cb5564e4e75e103ea1b6000be6588e27105d7cdc2d2f1" + - "f680ad34ef823ac4bd4068146e9997834665aec7dcc7a82ff28d85d52dd6" + - "9c18dd35f326bcf709f74df5981bb90ca8e765fef9f0698a19e12220b287" + - "24a6d9e4f4c7ce93f8ca9a126689ad1df820072557ce3db246cdf41599dd" + - "44ca841bece6c7869358005536e1189aa86b764e890ef90970d6e3831def" + - "fa890bf8692381123924e7d9df804fd770a0a30ee97d5dcdca302833efe8" + - "1d4b2505b17382f0b3429b38c41269ac95e36e9f5a1dbc6e6c8963741917" + - "02a23198decb4efe6809fcbeb5d0c9098a4c300155dc841610e55c8a6e27" + - "2a38a39de3d8ebf38a750af25836ffb1bb7822bb98886280f0cab6838c01" + - "cec57961bdc2e1bf158248309ff9294adcb962252b1c24646d132a3be2c9" + - "1ff82e8e101facbdb807826cc9d1840a90874ba08692e808c336c9d280ee" + - "f36a43a75c746fb864f85711e802546ab5cc3f8f117904ba1a85d6e4b729" + - "85122c5041891e16d55b93d6fc1b7fcfdc80ed3d72d55d64b8895bbf2f8e" + - "d188684e7e89afdc1e6a7ab9bd1d3da95d68698df2cdcbb2e1a4ae70e2fd" + - "dd4760f9e5cf4255eeb1e9e8009ab507395bacb8b2177e7c5757ad02baa9" + - "a96db967d20a150d2dd7f3081d90675fe0c82f94aa3cfdf6ac5585583901" + - "7a8e122170cc817f327a3c8ef44acd6e4fa81b73bcd0bcb5792eed470481" + - "152e87f7a20c3f7c69d5a8199bf9bb7c7269b450dc37a9b22102acaa8438" + - "134d6d733d231cee9522f7d02fbb37b5818ad3ca72df4752230ee11392ef" + - "8f8219be55202bc3d476f5a9078b32fb63d42bed4cda5ef90cc62467bf5e" + - "418ecd9d5d0cf1a33eb9a930e652ce96057fef40b65588aac67621d651a0" + - "9003dbc3925912e385296cd3b2b386a44113308ddf2af52ca390487eb20c" + - "716b76d78ad45129e7c285d918de7107ea8c3b0cfd9e73933b87c0b2b505" + - "cb4c95794f2ee6d6d43e2e76026923a0bbfbc3bb22df9ad729452283ce62" + - "dc9b26684fd45e07650581afd73713a708869a069c58b599ab478974f206" + - "dbd3e4e563e346ff1881723c5fd440bdf9f70f761c6f746113397d7c04b6" + - "b341d7e44de7de0aae79badaaef5ed372ef629dffd52926110683ab2d4da" + - "a4be83eb86c8700703a660edd5a5029f66f1581da96fe1feefc970ab4086" + - "a83ae02e959821967bd27b3b629652f5bc3db2b7f1af674f9f3fb3a788f7" + - "88e6dc1722382971831a7ed72502f85b25888c1534d81c0a4f7351ecc40f" + - "4e0412e05718403fae5746d313a78c80ac297f1391ad389070410e1330a1" + - "b07d683d1c795bda74bde947f2cf0dc9638b5d0851cda27df030403816dd" + - "3b70f042888c9c192656cc4b9fea10b81b5347900d9199c8f0f47d42f2ee" + - "482b68acfa5ff47d9950c950a926a497d94c6a796e0b715416520bd6c59f" + - "30217718d5f1d7bf7c24039f6467214ac8783cf011b25c37c67dfddde426" + - "40afe97f94879f4586954737b86701b32d560f08caec3fc45184bc719c7c" + - "5bf699074fde814acae32c189158c737665a8f94637068322f0c23ff8860" + - "f1b1c1bd766440afee290aa6f7150c7adefa6d72a738cd2268da7c94788e" + - "bb39002e9a328a51f3a92dc5c7cd9e4faed5702d3592ad16217c4978f84e" + - "af0fd2c9e4c6f4dcdd9112c781eb41a9aacb0f7935bb5c92d41e67cfff6b" + - "991ccefbd667ffeded1de325da50c33e28e2eef2f636c9726dc5bfe753ee" + - "c7bb6e1f080c89451f81bc8c29dc9067ce83deed02769714fa9bb477aca5" + - "c09089934674a0cc8e4b2c3136b2e4af8040cc601b90a4dec898dc922ca4" + - "976ab5ae4ac5af93fa5b1854a76ac3bcc2090bdeaa49ec4f319cf7c7b674" + - "6d8e617abb3361b28b27983dd1b139ec4f5af7e116439d7ecb16534817bf" + - "264dbd8f59e80b443be12c17fa013c7f4d029504c9bb62b296c2326f4f49" + - "cc3201b70ac3f62abb683c630179594a6d4cf30fd55b163bf8d01986bb6b" + - "cb7050fd527f095c45661920268e56f760fee80a29c9d37b7fc23f608710" + - "1e723038e64ee1b91c4849d69bd95fc9bc24fc4a234f4855f2a203e3f699" + - "c32698585c83781677739f2c48697c93b3388dcc64aa61f01118495ded33" + - "21ef9a1c949481f96005f8d5b277a7d6a0d906ec304cf4292df172e72d20" + - "29ecdeb65f06267a605f376804bf7bc5b82d5c8facfe7e41dc10806d27e0" + - "bcc5a341d80b3c1532407f75088716d732632cd88b0037f0d829bf385fec" + - "b52a202956489f61f16b0f4781bf59068b33d7330571d0b4a6ed91830258" + - "e1220b308784fa155be9bc821f5c0009a33802fa66dd66d1dde997dddd97" + - "873ddf65927dc1be979af2b5f110eee627dc1e210326ac20544a757ac168" + - "1823f3dd04b1ddc4bf96677a0a87633994e7af2ec99b7d5dfe44c6192be6" + - "a6e69d17b074256da3947808fbf68c7506a7e2c99e6b64d1ffadbd6285d8" + - "e7e032e24d42dde0594bf03fd550be05e5d66c91a660cd1ab7cb1f43fa9d" + - "69885203a7aee35a28f117427d7ac02b742f53d13b818f8631081b1730d1" + - "5b4e1e283cc8e5c4fc3b4652fce05fd8db821f99fcf93e6842816a549791" + - "7f6c49cc53d733788b2fe3c687de58bfe6153c70d99380df1fd566a7c758" + - "8052c62e73340d6a9eccd2ed26b763d518f3a0c4d6362212fbecebb4ffb7" + - "dc94d29944fcc4ab37725b105aa7571f364146782356d8ef056a0be93a55" + - "0c890df8fecc178776fe40703ad1bd2443d92c420be4306d99686592c030" + - "fd3e2230c0b48d8db79002e8a832ef27edb53a45532955f1171203d38414" + - "b4692e901e9f40f918528fc494430f86cf967452f456b01846ac6a383fc0" + - "de2243c7d804e8643aabcb78e2653b145f400a999670217c8da43bbb9c11" + - "e074176424be0c116c304a420120138e901eca4b12ce68fec460b23bc0c7" + - "765a74fc66cbda0e503e7b1baf5883744e468c97c5f1c4b0acc4b87de9f1" + - "4b537405dfb28195439d1ff848d9cd28a8d375038ebb540a9075b7b5074b" + - "ebc18418a370f1d3ac5d68f5d239513002ad11bfc2b7ff53e2e41ccffc4b" + - "0503acc4967c93ae8590a43439b5e7987d10cb8d1957bd9ef717ee3d12df" + - "5d6736c1d8bd8da102337a94b7d14f830f6c403cbaf7925a8a2a7af1311c" + - "57224967a38f6ca374013a9819c55fd2e2a5fac4f2490be5b059f4cd9c60" + - "2d62f80789eb8d9ab893c7f44a4945e41886af218179dfa754bbb59aab68" + - "13b71d2202eb8fc8a425625d21176a28a620e21bb0dad820c0b7051ce8d1" + - "3a33f3af0958bb6cd89f9d6414ab00ddd1d2f9fdece9183d0c05fcdfd117" + - "10d250e4b2029e6992a88293d0457e73e5b1b6a1aae182c69b9cb664992f" + - "073595ef68117026ad7ea579a4043cda318931eee7b2946a34cdc7c9755f" + - "80cc79a2bfe3ed9c79dc52faa5126b824868c965eeb37e9e4e6a49600f3a" + - "cce93c0853b546edb310dcd16a5755f15b1098b2f59dbd2d90e2ea8360ba" + - "f12108236e854465456598ae2f7bc380f008f2e3cd7c98c87643cafd7c36" + - "d40e2597236428d46aa5b260f84b4212d5e26804086adcf00363ce4becb4" + - "9b57eb2847b2f18ec82c99714ad4ddfe4ff3bcac1d0fcaa32660a1dccc68" + - "5bed83254c8e2ea0ae3632a70cfbcbeadef922d78a006d43ac7ab1f8a609" + - "c6e0ebc3ca6bb8430f1a562f41010db74b9febf931ca794fa08d1bc17780" + - "532ae76f25c4ee679d788835dfa4e70ca154c9e2865c3750ffe7b837eed1" + - "972be058fdf2bdb3eb301867bb132306c7aa237f6771d60bbc56cf31cb30" + - "32a87204d454542de747418470025ab84935d3eaaca01dbbdae9ef6b5d3a" + - "ca62ce9f871a3e1272b2b671582c096a349c00f32d742ddb17993994d8ae" + - "fc178cbcf9abc03114ff2bf7db8f757c63d6898faccd822f5c2e9a7570fb" + - "9cfff148570888be24ae42644c1a5bebb6f6287147a4bcc01c7675be9e4a" + - "897519dd3132a7cc2e778f8c90d23dc8073f6fa108d7ef82d561794bd9d5" + - "f1faa306334f338ac3ba99c853f79c24f7048fa906fde87d1ed28a7b11c0" + - "66a3bb98f8d21055aaafdf7e069b77b60b3d5cbe7c5e4379c7651af955cd" + - "82a19a09caf36becb6cd3fe9e12f40379941542709991066df21b7b12dfb" + - "2416d83fcdc33bb583e3b42f24f53edf8dc7c579ad3be831c99f72bf9fb7" + - "a35b6562e824e039e6bf1adc8f5ca53846de7bae11c4317e696d887df33c" + - "525f0a9c01fc29f2c26c90b85fe82ed8bd50954cd4e9ac7c85c7f3efec75" + - "da1da4ed173cb695cee295190527edb3cb06c5dbdabe0228cc60b6455153" + - "76244f27aa56da2db10f2659090137ffb82c57233c833e0bbf22d6f647fb" + - "97b3652d2888b3ab08010b8e8a6967d560b747757806736dc98b78226634" + - "f1eecaa4a2e23ba36591acb5737d735c5bc7a2e36f1a46946927e061fdf7" + - "7a3b68ef582c26b01f5aa9a438ecc26c6941221d1590c838072f9e471fe7" + - "fd59dacb0d092d40d76ea2f7c6e954a132a015bd4cb31147f3ebe4518322" + - "916438a62836ac85a4cf4492190a85bcc8edb37e38b99ea552d749c30f74" + - "ca20c298165e8ed02d4671e0b41cac3a32a345b9349ad22c2a4bb2c16a4c" + - "e0613ca0f0518759f7d2b33cfad2fae764f410d4d9ff8a76ae02a8107e7e" + - "01d9cd0552676b85ba002f19c01ad5f416d1d08bb84fec7c3555b098dbce" + - "48e1a5d847895e54db9c5b80cc22d5b87cd41a1a94be102bdd45a3cda5d1" + - "181e10446d213d6b3fdc350d486d2011d705c5f16ccf7519065c47bad7d6" + - "89c71e5fdf9d04bfb91eb1f07fa0f001009c1d4b1f6a116a570823a8580b", - }, - { - key: "392468efccff36dade31fc1c62eb38bb61394fe448def9d9d9beec2413ddb418", - tag: "e1122e7c8e6965b90addbd46d8a548d6", - in: "6a13d37f0ec933194c227351f4a19b507d93465b1f3e88dcb5f1ed1262fa" + - "58ea99ff31e6fc85c39c04129fa69195b71b2060122fe618dd9430a63f97" + - "54b52a80b3cd099f248f91a468bae211a27bdb47ba005d29881ea5143a82" + - "967c4c30c9a4f0dba1a4975e6407fe296d40023a00efa06be763f2d73d46" + - "a2901ae28b3d8ce18009a462e223b71476d7b954c138e177d15a390847de" + - "96a7f7fd0598748e86b0f08e64d915e67c7e3cf936f3dcd60edebd36e2a1" + - "d65b6ac29530c48ab3bd52d45b4f938a19b9b31e2911105a8561600d5377" + - "905a67112ec28025aa680350ff85b808c5b4c98b7b9567d03f5ed3911ec9" + - "365a8de4b15ca62adaa69e5ba710eb1756a346016c67a297d8624f9f1ab5" + - "b3fbce98b141049f0ce26c85d2f8a9cc6ca8ab6c6e148be968931430dcc6" + - "2bf58ea9698ef52a5d271cf48e6748ac9e04bc7ae7da205a1a7535478322" + - "d820eca146cedf4b2f9aa9fcfd77ab56a7276977401dcc1f96baa1b607e0" + - "256bd04ec324ec67a4313e2d5a53d3a3fb5332927929b20c63bde805f637" + - "eb1050fee2a152a0405634f55c48a59fe370d54b2ab1671dae2c7fd92243" + - "10627808e553127c74f724362b4a6ee49b697daae7df3ddc5d2ed9d6befd" + - "77fb9f68fe3041f6ef13f46f34ab682ab8563e8996344f82b2ef006a8d54" + - "3dd9c1db4979d7da97bda45e722065f8a238f0873217b783a9a629a12b3a" + - "4de437445039997bd243efbf5e3b6059b9459d395290efb9081c632fb694" + - "81000dc74c395cb507422df181aba20f776ce3fd8765ac485021992c98b1" + - "67c68805662cb4356a0ee7ba6bdae51ac10cd06bb5b2f3a72841c714c8ed" + - "bc56998fe2fefb9bf69e172fdf54b2ab138ae59372c52a67e93882a3000f" + - "d966992aa2250c6ff93e9cac89645d70625d79332ade5dab7eb1adbe7dce" + - "5a013fb65ad32fe22ed16fb9bb35eca1f37a0433c320e8752f8fc4b7618c" + - "5e4df2efece832e259ad98b895c474e47d0e3fc488bea8f717a17de0dcf7" + - "597fb8fe12e62246296f9a887dcc3a700820c190a55a4931a7d44bd3bb2e" + - "ab6c8a8126f1be93790cebabc1d69e01796e6cc80e7c16bbc82fb333fb21" + - "c774ab7db843242838e82d8e1cb8ccab385e67a4271fe7031d74b6e8edcc" + - "8ed585d1c05a365c7665899c1dbc561151d3b44bceace77c4f53c0e0f6f7" + - "74d42f9ad3e56f1c2a8d53879d695f895690afb4698472a3d52d67159313" + - "133c87823fe0500eb68fe286f8b9a2f59f12785d026dc97bdbf793c7d1eb" + - "155f1f136aae66c256583e987f718afbe733e0a5ce30d021493fb84e2242" + - "5b18754d126235ef80335004fa84f88361a584753df409360cd8bd45bace" + - "8f48156bec66577bf2c685089f5ac7e7ec76c0df068fbaa47661f8517f92" + - "e14723b3b278f151816537a7212c96bd340a00c15c9c9bc9a2a5d163655d" + - "84b38073e2be9217cad97d362d89d4baf3ce0a8d8562f19a8c97a9aaf5e7" + - "77d60456360ffb77b30f177d2809052020d141697ecf9cb65f42b9190caf" + - "6540b2c82f6e5a8482934a6a1a5711a8c24546cd8ba432068404eae5a827" + - "2e09efc3c6037af4feaac0a46329229b010ecac6b9f077a9b076bb6d9ce1" + - "38401eb38d124baa11507a994185295020bf9b754fcf78430db9253f5929" + - "87c46c0f8589c4e463b15a3840b1cea795e24cf6b20f29a630136e0589b3" + - "8dd7fbe5ea21da72c88bd8e56473586822aa3765660a45a988df9b8eb8e8" + - "141939d3e4cc637c5d788064d40a9f7c734e43fdf8d7189a5d76700d9743" + - "fe0122944663afdb88c5201318ca782f6848b742ddebe7463fd4a32280ac" + - "1cf8311e9137d319de05ce9cd85abab24c5364041c14d3b4ce650400498e" + - "122166eccc12784b7ac3b262ac0b198ffc26eeed9a5da5374f7a2a53c87a" + - "78c217ea1fbf8d38f62511657b73109f31691aef14d82ce6e1010eae9e6f" + - "a419e5c1c16c0cc70651eb3374c03549a1bc7d3ed42d60f886102c798dbc" + - "ba56f0a2b3b9b412530c35f5f7ed06311ee14571f9c26ed9c81ef38ff000" + - "2f5ef3aab7351e32049a6ef8f48a43da1d84402d229df513dfaf1b2e4043" + - "6ce68c70ebeddd7477c9164f0dce45a6fc5de050f52ec269659d5854bcae" + - "f7762ed7400713c27a4d523eaf8c136c4a1ca00b9e9e55902daf6cdf8528" + - "c22ca1f2fa7ce87902d75a6850e1a5a4592497be1bb401878f18b189b0e2" + - "c59d10705bfabde3cd2da01eb452006b294108d5d42e88e9e15424d8cd0b" + - "8ab43a6c546b3dbf52e47b59cde6a3e417b0395220b6d63736d429da3458" + - "9a2524f1629320206fa7f1d8a041e17222c4a5814561937e1030e6375c77" + - "9dc988bb928bbdbe2c2eb20111639725d82b5d7192cd3e4acc27581f0ba7" + - "286cff41f97aa5a52ea0083de5057fd2ba985aa738e4d03fcf11ebab1d97" + - "e2ac77d1c2beb8799150a421a07b3777d0b850f24194b8309135b13da6c7" + - "e38653a711e407a1811290fbb7bc15d8b12efc6916e97ead41e042a44721" + - "e9cde3388073d921595bcddcac758dc675173f38242e65e4a284aaa7e8fa" + - "6adddaf00bc46428ab2d8601205b8895bcedfc80ca0aa4619ed6bb082ddf" + - "33ec04fa5d417f33fcdd238c6b11320c5a08f800e0f350b75d81e3bcbd15" + - "58a1eab87a3c8c2ffd7ba1d7e754e607cf98ba22a3fc766c45bd6f2569b4" + - "84639e6611714119d188a24a5e963089a16ed34e20b9f154cad8ac6031dd" + - "7a3a885afc2ae5e003ae8d4e4aabdb3e51dfc423b8cf4ed9ae2010072cbb" + - "b1108c7da1ff075e54ed827a0963ac5523ecdf3fc5eee7b4d1a6773764ec" + - "5c30f41690523fd70d895edb7ca6a1806d54240c4c7b43410da73503a323" + - "90d9070ed30da3a2fb5eccd40d083be7cf8bf40b4279f819cf795b6f075b" + - "5a67a10a06a6076d0d83c72efea05f244901c4b5fd9eb380432519311baf" + - "8c81f6325df4d37ff4d30d318f904ebb837ec76b341dd00a8f247cf0bbe9" + - "6f3784dc8f5feb344958fdf1a9ececb105f8770826db1f17a5281e997951" + - "d3c60cc28fc3e66ffeb5dbac315f98f6d240208043f28dee963d843e68ab" + - "57d847f76ae2f96ce6e37f377ef5dfef2176ecd7440ce4dadcec2231b606" + - "e4a80420fb3ed135640e1f05d6bd58b8dce062dd7d36b885d424f6318e5e" + - "a0753efbb33bbc7360d2b5dfab3ae0d5e000b8d31f2ba0f5fd8b34f96b55" + - "28fff35e769461d0f03cf3bfdf0b801dcbbf2838180cb9b108e06c353e3f" + - "0b9ef61678cfed1ea37ae76bccb5ef5957ac2c8e8f4794c8145a15f1cc88" + - "bfb0881080326c481b373c3bc9b07a9b60a0c8bd5fa4f6f90145590a5227" + - "6fcc0ccc2375d0ccb571d414d1b0c38b4e02c39db4d701c5e25e90785ef4" + - "d26f35edd8c4b96455bdca7245cfefd9cfbd2f319615e5fdf07bb9564fa0" + - "44bb35a58391d02e3927780b4076bc0893dfcb4b63a32cd7a541a4a8c253" + - "0349c6e96e378dbeb66dedf87d813d0b744452c1c4088507dca722193827" + - "9e2dfa24e4a409de494acf654f44262db9206a7717fa434ac4fdc6a6eb5b" + - "1fd5a193b6043bc4327c8c09fd6822eaa9df37bbcac1077754a295621601" + - "267b68733b62dadc2563f1700af180141f29899e2689dbbe9745ba8477f4" + - "352921900b403a01c9dd042a8c1b0e0489959fb0b0a8431c97b41e202204" + - "212ebfa00c593399dbd14d7aec07b8292d2e40b48f05fcd54a15da4a24d7" + - "2759e409f4c7b5b98fce4abac6c30e4872d92efa1f96479ec30f21699825" + - "50fa60584f5a09051a00f8e7dbb3853e66ca3f05fbfe43bef9b120a25a01" + - "eb436ba8ecda715201eda72e517d628f883386c1503aa8b8e75610f7155e" + - "9f916335ab6d6f0f9589b6220cd2b81c2c937dc065d3d14a7df8cc916cd0" + - "0ce1bb53fd9c8974298d3bd316f3658aa8cc6904f073a1472149e4b08c64" + - "5e11abe0428ccb6174df2103edd735965d6454b543d3f01410f77053f65e" + - "c1d1aee56fdd3af23bcd4e1a7fcc4e600c4831007c33fe5f0c8300f686eb" + - "9b4d1e4f08fe4ddc8a90be14dc3a5a88ff96716509341d5db24c0d016863" + - "998b1859c5021df815a6f1ca9845f1a8e99dbad132b406227c5897a1bdf3" + - "e698962f799133ff4429decbef6ce036296facf38e4812fec102b76c6d30" + - "beba1b70722254fafbc471096153478c971db7d96263660209265cb10f13" + - "b34b5fd55c4abe818a5f9715d8a85094e2946b7a001b47f629e26c636d86" + - "4968ad2ab616dfe28840bd60b4b9855c8dbe1cb873fcbc4577b5fefeb8bb" + - "4832039867dc35db9c036c83bc204396e3474ddfe806c77c65c936f488b6" + - "7c1028739562d7bb055d21441af29ae2921290e548dccf8a56021385422b" + - "15da6b232b24151309a75a00296d11aa1952a1513110b0faa93d1d8cd9ae" + - "fa9f1c59377ec9165b2c9e07cbde40db7b81bca6d58fc28bae8f473cd0e9" + - "a2420e0b943a83d284108626c24ac570b1d6c1ab971e71f43fbd6c00e171" + - "238141a6dc987a60385c3a04dd147a2f8e80dfe727b104c0fdd80b326f59" + - "0b9f86fd7b2fd1122a390979889eabd803ab57159c8509a1443eb6789382" + - "090a770ae4eba03306f96e50e19a7d44c584ccc230d104548946efca4520" + - "d61de5f473e2f4eada6c8ce9c7ee975eb4f63c0483cb775ed7d3cf690a61" + - "7d6656d683a8512707d81ca5ba176a42bcffcfa692129f292607d2a47536" + - "ccaeb464c9272d6f3816074b712af602470088b253deba18771e5f67734b" + - "587707cdd06f35264b2262fd253c25b5d38ee7db287610e5398062b7a34e" + - "6e4cf7447d00873b930ad148fd96f0ab18771bc468b874bb109924101c84" + - "c4e239ecc7687d875e4d94a1a973620ca61e35a872c2e2e61a502169f1bb" + - "4e5ff5fa2bff657be6195b3e2c7151a52fc0096d98e7f08f5a98f570aee1" + - "7b4275f1356e87e080ce0e1b9bbabe7dea48b5903bc390ce23472ad64a89" + - "41c3247bfd23ea90b2dee09085571bad85568040105e098f993bb37e43c3" + - "e6d511171c77cfc450570dfb9fc6a3930ef43c03f8213f6203d545d791c7" + - "d3fa42d5dde1655038d35c5dfacc12e9dee24fe833977549eda68ae8b508" + - "be277e743921b584f9dfa0eefbd8bf3c23f51efdef7f7487001d29e8097b" + - "ba63289cfca743023d1668555a46fe6d5b7421377414df1e9ef135480622" + - "22e2e9a7baa618d88f407517f6317b6a0ba3384ace16d68631d59ea169d5" + - "092d20afc1a481b82be5e734bb092953a0a94702bae1a0f48d2a22b9a05f" + - "f64493b7b2e984f27582b1eb937fddf8512c49830435d146dcc291a4118d" + - "5dc638b99cdcbcc5860de7a92c5b13cbd1e01e051f01af40afe124346320" + - "d3626bf9d8f7850744e032a993c276fd388718237740c6caf260fca60b8d" + - "d846102e3262b6e05ceca00c6affe938fac1847350865fc858d3ddd1d130" + - "71d1221ce7c5d575587fcba580e544b74d877ed5ca92763ef0ca0d7bfa08" + - "d57a0216b2a01a2b9ec74b8430051e0074862b7be25b6766ab520f2eb75d" + - "eeb979c28f03795f6f1e4b8410beab19a20febc91985b8a7c298534a6598" + - "f2c5b0dc5de9f5e55a97791507bc6373db26", - }, -} diff --git a/vendor/golang.org/x/crypto/ssh/benchmark_test.go b/vendor/golang.org/x/crypto/ssh/benchmark_test.go deleted file mode 100644 index 20c33077..00000000 --- a/vendor/golang.org/x/crypto/ssh/benchmark_test.go +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ssh - -import ( - "errors" - "io" - "net" - "testing" -) - -type server struct { - *ServerConn - chans <-chan NewChannel -} - -func newServer(c net.Conn, conf *ServerConfig) (*server, error) { - sconn, chans, reqs, err := NewServerConn(c, conf) - if err != nil { - return nil, err - } - go DiscardRequests(reqs) - return &server{sconn, chans}, nil -} - -func (s *server) Accept() (NewChannel, error) { - n, ok := <-s.chans - if !ok { - return nil, io.EOF - } - return n, nil -} - -func sshPipe() (Conn, *server, error) { - c1, c2, err := netPipe() - if err != nil { - return nil, nil, err - } - - clientConf := ClientConfig{ - User: "user", - HostKeyCallback: InsecureIgnoreHostKey(), - } - serverConf := ServerConfig{ - NoClientAuth: true, - } - serverConf.AddHostKey(testSigners["ecdsa"]) - done := make(chan *server, 1) - go func() { - server, err := newServer(c2, &serverConf) - if err != nil { - done <- nil - } - done <- server - }() - - client, _, reqs, err := NewClientConn(c1, "", &clientConf) - if err != nil { - return nil, nil, err - } - - server := <-done - if server == nil { - return nil, nil, errors.New("server handshake failed.") - } - go DiscardRequests(reqs) - - return client, server, nil -} - -func BenchmarkEndToEnd(b *testing.B) { - b.StopTimer() - - client, server, err := sshPipe() - if err != nil { - b.Fatalf("sshPipe: %v", err) - } - - defer client.Close() - defer server.Close() - - size := (1 << 20) - input := make([]byte, size) - output := make([]byte, size) - b.SetBytes(int64(size)) - done := make(chan int, 1) - - go func() { - newCh, err := server.Accept() - if err != nil { - b.Fatalf("Client: %v", err) - } - ch, incoming, err := newCh.Accept() - go DiscardRequests(incoming) - for i := 0; i < b.N; i++ { - if _, err := io.ReadFull(ch, output); err != nil { - b.Fatalf("ReadFull: %v", err) - } - } - ch.Close() - done <- 1 - }() - - ch, in, err := client.OpenChannel("speed", nil) - if err != nil { - b.Fatalf("OpenChannel: %v", err) - } - go DiscardRequests(in) - - b.ResetTimer() - b.StartTimer() - for i := 0; i < b.N; i++ { - if _, err := ch.Write(input); err != nil { - b.Fatalf("WriteFull: %v", err) - } - } - ch.Close() - b.StopTimer() - - <-done -} diff --git a/vendor/golang.org/x/crypto/ssh/buffer_test.go b/vendor/golang.org/x/crypto/ssh/buffer_test.go deleted file mode 100644 index d5781cb3..00000000 --- a/vendor/golang.org/x/crypto/ssh/buffer_test.go +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ssh - -import ( - "io" - "testing" -) - -var alphabet = []byte("abcdefghijklmnopqrstuvwxyz") - -func TestBufferReadwrite(t *testing.T) { - b := newBuffer() - b.write(alphabet[:10]) - r, _ := b.Read(make([]byte, 10)) - if r != 10 { - t.Fatalf("Expected written == read == 10, written: 10, read %d", r) - } - - b = newBuffer() - b.write(alphabet[:5]) - r, _ = b.Read(make([]byte, 10)) - if r != 5 { - t.Fatalf("Expected written == read == 5, written: 5, read %d", r) - } - - b = newBuffer() - b.write(alphabet[:10]) - r, _ = b.Read(make([]byte, 5)) - if r != 5 { - t.Fatalf("Expected written == 10, read == 5, written: 10, read %d", r) - } - - b = newBuffer() - b.write(alphabet[:5]) - b.write(alphabet[5:15]) - r, _ = b.Read(make([]byte, 10)) - r2, _ := b.Read(make([]byte, 10)) - if r != 10 || r2 != 5 || 15 != r+r2 { - t.Fatal("Expected written == read == 15") - } -} - -func TestBufferClose(t *testing.T) { - b := newBuffer() - b.write(alphabet[:10]) - b.eof() - _, err := b.Read(make([]byte, 5)) - if err != nil { - t.Fatal("expected read of 5 to not return EOF") - } - b = newBuffer() - b.write(alphabet[:10]) - b.eof() - r, err := b.Read(make([]byte, 5)) - r2, err2 := b.Read(make([]byte, 10)) - if r != 5 || r2 != 5 || err != nil || err2 != nil { - t.Fatal("expected reads of 5 and 5") - } - - b = newBuffer() - b.write(alphabet[:10]) - b.eof() - r, err = b.Read(make([]byte, 5)) - r2, err2 = b.Read(make([]byte, 10)) - r3, err3 := b.Read(make([]byte, 10)) - if r != 5 || r2 != 5 || r3 != 0 || err != nil || err2 != nil || err3 != io.EOF { - t.Fatal("expected reads of 5 and 5 and 0, with EOF") - } - - b = newBuffer() - b.write(make([]byte, 5)) - b.write(make([]byte, 10)) - b.eof() - r, err = b.Read(make([]byte, 9)) - r2, err2 = b.Read(make([]byte, 3)) - r3, err3 = b.Read(make([]byte, 3)) - r4, err4 := b.Read(make([]byte, 10)) - if err != nil || err2 != nil || err3 != nil || err4 != io.EOF { - t.Fatalf("Expected EOF on forth read only, err=%v, err2=%v, err3=%v, err4=%v", err, err2, err3, err4) - } - if r != 9 || r2 != 3 || r3 != 3 || r4 != 0 { - t.Fatal("Expected written == read == 15", r, r2, r3, r4) - } -} diff --git a/vendor/golang.org/x/crypto/ssh/certs_test.go b/vendor/golang.org/x/crypto/ssh/certs_test.go deleted file mode 100644 index c8e7cf58..00000000 --- a/vendor/golang.org/x/crypto/ssh/certs_test.go +++ /dev/null @@ -1,335 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ssh - -import ( - "bytes" - "crypto/ecdsa" - "crypto/elliptic" - "crypto/rand" - "net" - "reflect" - "testing" - "time" - - "golang.org/x/crypto/ssh/testdata" -) - -// Cert generated by ssh-keygen 6.0p1 Debian-4. -// % ssh-keygen -s ca-key -I test user-key -const exampleSSHCert = `ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgb1srW/W3ZDjYAO45xLYAwzHBDLsJ4Ux6ICFIkTjb1LEAAAADAQABAAAAYQCkoR51poH0wE8w72cqSB8Sszx+vAhzcMdCO0wqHTj7UNENHWEXGrU0E0UQekD7U+yhkhtoyjbPOVIP7hNa6aRk/ezdh/iUnCIt4Jt1v3Z1h1P+hA4QuYFMHNB+rmjPwAcAAAAAAAAAAAAAAAEAAAAEdGVzdAAAAAAAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAAHcAAAAHc3NoLXJzYQAAAAMBAAEAAABhANFS2kaktpSGc+CcmEKPyw9mJC4nZKxHKTgLVZeaGbFZOvJTNzBspQHdy7Q1uKSfktxpgjZnksiu/tFF9ngyY2KFoc+U88ya95IZUycBGCUbBQ8+bhDtw/icdDGQD5WnUwAAAG8AAAAHc3NoLXJzYQAAAGC8Y9Z2LQKhIhxf52773XaWrXdxP0t3GBVo4A10vUWiYoAGepr6rQIoGGXFxT4B9Gp+nEBJjOwKDXPrAevow0T9ca8gZN+0ykbhSrXLE5Ao48rqr3zP4O1/9P7e6gp0gw8=` - -func TestParseCert(t *testing.T) { - authKeyBytes := []byte(exampleSSHCert) - - key, _, _, rest, err := ParseAuthorizedKey(authKeyBytes) - if err != nil { - t.Fatalf("ParseAuthorizedKey: %v", err) - } - if len(rest) > 0 { - t.Errorf("rest: got %q, want empty", rest) - } - - if _, ok := key.(*Certificate); !ok { - t.Fatalf("got %v (%T), want *Certificate", key, key) - } - - marshaled := MarshalAuthorizedKey(key) - // Before comparison, remove the trailing newline that - // MarshalAuthorizedKey adds. - marshaled = marshaled[:len(marshaled)-1] - if !bytes.Equal(authKeyBytes, marshaled) { - t.Errorf("marshaled certificate does not match original: got %q, want %q", marshaled, authKeyBytes) - } -} - -// Cert generated by ssh-keygen OpenSSH_6.8p1 OS X 10.10.3 -// % ssh-keygen -s ca -I testcert -O source-address=192.168.1.0/24 -O force-command=/bin/sleep user.pub -// user.pub key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDACh1rt2DXfV3hk6fszSQcQ/rueMId0kVD9U7nl8cfEnFxqOCrNT92g4laQIGl2mn8lsGZfTLg8ksHq3gkvgO3oo/0wHy4v32JeBOHTsN5AL4gfHNEhWeWb50ev47hnTsRIt9P4dxogeUo/hTu7j9+s9lLpEQXCvq6xocXQt0j8MV9qZBBXFLXVT3cWIkSqOdwt/5ZBg+1GSrc7WfCXVWgTk4a20uPMuJPxU4RQwZW6X3+O8Pqo8C3cW0OzZRFP6gUYUKUsTI5WntlS+LAxgw1mZNsozFGdbiOPRnEryE3SRldh9vjDR3tin1fGpA5P7+CEB/bqaXtG3V+F2OkqaMN -// Critical Options: -// force-command /bin/sleep -// source-address 192.168.1.0/24 -// Extensions: -// permit-X11-forwarding -// permit-agent-forwarding -// permit-port-forwarding -// permit-pty -// permit-user-rc -const exampleSSHCertWithOptions = `ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgDyysCJY0XrO1n03EeRRoITnTPdjENFmWDs9X58PP3VUAAAADAQABAAABAQDACh1rt2DXfV3hk6fszSQcQ/rueMId0kVD9U7nl8cfEnFxqOCrNT92g4laQIGl2mn8lsGZfTLg8ksHq3gkvgO3oo/0wHy4v32JeBOHTsN5AL4gfHNEhWeWb50ev47hnTsRIt9P4dxogeUo/hTu7j9+s9lLpEQXCvq6xocXQt0j8MV9qZBBXFLXVT3cWIkSqOdwt/5ZBg+1GSrc7WfCXVWgTk4a20uPMuJPxU4RQwZW6X3+O8Pqo8C3cW0OzZRFP6gUYUKUsTI5WntlS+LAxgw1mZNsozFGdbiOPRnEryE3SRldh9vjDR3tin1fGpA5P7+CEB/bqaXtG3V+F2OkqaMNAAAAAAAAAAAAAAABAAAACHRlc3RjZXJ0AAAAAAAAAAAAAAAA//////////8AAABLAAAADWZvcmNlLWNvbW1hbmQAAAAOAAAACi9iaW4vc2xlZXAAAAAOc291cmNlLWFkZHJlc3MAAAASAAAADjE5Mi4xNjguMS4wLzI0AAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAABFwAAAAdzc2gtcnNhAAAAAwEAAQAAAQEAwU+c5ui5A8+J/CFpjW8wCa52bEODA808WWQDCSuTG/eMXNf59v9Y8Pk0F1E9dGCosSNyVcB/hacUrc6He+i97+HJCyKavBsE6GDxrjRyxYqAlfcOXi/IVmaUGiO8OQ39d4GHrjToInKvExSUeleQyH4Y4/e27T/pILAqPFL3fyrvMLT5qU9QyIt6zIpa7GBP5+urouNavMprV3zsfIqNBbWypinOQAw823a5wN+zwXnhZrgQiHZ/USG09Y6k98y1dTVz8YHlQVR4D3lpTAsKDKJ5hCH9WU4fdf+lU8OyNGaJ/vz0XNqxcToe1l4numLTnaoSuH89pHryjqurB7lJKwAAAQ8AAAAHc3NoLXJzYQAAAQCaHvUIoPL1zWUHIXLvu96/HU1s/i4CAW2IIEuGgxCUCiFj6vyTyYtgxQxcmbfZf6eaITlS6XJZa7Qq4iaFZh75C1DXTX8labXhRSD4E2t//AIP9MC1rtQC5xo6FmbQ+BoKcDskr+mNACcbRSxs3IL3bwCfWDnIw2WbVox9ZdcthJKk4UoCW4ix4QwdHw7zlddlz++fGEEVhmTbll1SUkycGApPFBsAYRTMupUJcYPIeReBI/m8XfkoMk99bV8ZJQTAd7OekHY2/48Ff53jLmyDjP7kNw1F8OaPtkFs6dGJXta4krmaekPy87j+35In5hFj7yoOqvSbmYUkeX70/GGQ` - -func TestParseCertWithOptions(t *testing.T) { - opts := map[string]string{ - "source-address": "192.168.1.0/24", - "force-command": "/bin/sleep", - } - exts := map[string]string{ - "permit-X11-forwarding": "", - "permit-agent-forwarding": "", - "permit-port-forwarding": "", - "permit-pty": "", - "permit-user-rc": "", - } - authKeyBytes := []byte(exampleSSHCertWithOptions) - - key, _, _, rest, err := ParseAuthorizedKey(authKeyBytes) - if err != nil { - t.Fatalf("ParseAuthorizedKey: %v", err) - } - if len(rest) > 0 { - t.Errorf("rest: got %q, want empty", rest) - } - cert, ok := key.(*Certificate) - if !ok { - t.Fatalf("got %v (%T), want *Certificate", key, key) - } - if !reflect.DeepEqual(cert.CriticalOptions, opts) { - t.Errorf("unexpected critical options - got %v, want %v", cert.CriticalOptions, opts) - } - if !reflect.DeepEqual(cert.Extensions, exts) { - t.Errorf("unexpected Extensions - got %v, want %v", cert.Extensions, exts) - } - marshaled := MarshalAuthorizedKey(key) - // Before comparison, remove the trailing newline that - // MarshalAuthorizedKey adds. - marshaled = marshaled[:len(marshaled)-1] - if !bytes.Equal(authKeyBytes, marshaled) { - t.Errorf("marshaled certificate does not match original: got %q, want %q", marshaled, authKeyBytes) - } -} - -func TestValidateCert(t *testing.T) { - key, _, _, _, err := ParseAuthorizedKey([]byte(exampleSSHCert)) - if err != nil { - t.Fatalf("ParseAuthorizedKey: %v", err) - } - validCert, ok := key.(*Certificate) - if !ok { - t.Fatalf("got %v (%T), want *Certificate", key, key) - } - checker := CertChecker{} - checker.IsUserAuthority = func(k PublicKey) bool { - return bytes.Equal(k.Marshal(), validCert.SignatureKey.Marshal()) - } - - if err := checker.CheckCert("user", validCert); err != nil { - t.Errorf("Unable to validate certificate: %v", err) - } - invalidCert := &Certificate{ - Key: testPublicKeys["rsa"], - SignatureKey: testPublicKeys["ecdsa"], - ValidBefore: CertTimeInfinity, - Signature: &Signature{}, - } - if err := checker.CheckCert("user", invalidCert); err == nil { - t.Error("Invalid cert signature passed validation") - } -} - -func TestValidateCertTime(t *testing.T) { - cert := Certificate{ - ValidPrincipals: []string{"user"}, - Key: testPublicKeys["rsa"], - ValidAfter: 50, - ValidBefore: 100, - } - - cert.SignCert(rand.Reader, testSigners["ecdsa"]) - - for ts, ok := range map[int64]bool{ - 25: false, - 50: true, - 99: true, - 100: false, - 125: false, - } { - checker := CertChecker{ - Clock: func() time.Time { return time.Unix(ts, 0) }, - } - checker.IsUserAuthority = func(k PublicKey) bool { - return bytes.Equal(k.Marshal(), - testPublicKeys["ecdsa"].Marshal()) - } - - if v := checker.CheckCert("user", &cert); (v == nil) != ok { - t.Errorf("Authenticate(%d): %v", ts, v) - } - } -} - -// TODO(hanwen): tests for -// -// host keys: -// * fallbacks - -func TestHostKeyCert(t *testing.T) { - cert := &Certificate{ - ValidPrincipals: []string{"hostname", "hostname.domain", "otherhost"}, - Key: testPublicKeys["rsa"], - ValidBefore: CertTimeInfinity, - CertType: HostCert, - } - cert.SignCert(rand.Reader, testSigners["ecdsa"]) - - checker := &CertChecker{ - IsHostAuthority: func(p PublicKey, addr string) bool { - return addr == "hostname:22" && bytes.Equal(testPublicKeys["ecdsa"].Marshal(), p.Marshal()) - }, - } - - certSigner, err := NewCertSigner(cert, testSigners["rsa"]) - if err != nil { - t.Errorf("NewCertSigner: %v", err) - } - - for _, test := range []struct { - addr string - succeed bool - }{ - {addr: "hostname:22", succeed: true}, - {addr: "otherhost:22", succeed: false}, // The certificate is valid for 'otherhost' as hostname, but we only recognize the authority of the signer for the address 'hostname:22' - {addr: "lasthost:22", succeed: false}, - } { - c1, c2, err := netPipe() - if err != nil { - t.Fatalf("netPipe: %v", err) - } - defer c1.Close() - defer c2.Close() - - errc := make(chan error) - - go func() { - conf := ServerConfig{ - NoClientAuth: true, - } - conf.AddHostKey(certSigner) - _, _, _, err := NewServerConn(c1, &conf) - errc <- err - }() - - config := &ClientConfig{ - User: "user", - HostKeyCallback: checker.CheckHostKey, - } - _, _, _, err = NewClientConn(c2, test.addr, config) - - if (err == nil) != test.succeed { - t.Fatalf("NewClientConn(%q): %v", test.addr, err) - } - - err = <-errc - if (err == nil) != test.succeed { - t.Fatalf("NewServerConn(%q): %v", test.addr, err) - } - } -} - -func TestCertTypes(t *testing.T) { - var testVars = []struct { - name string - keys func() Signer - }{ - { - name: CertAlgoECDSA256v01, - keys: func() Signer { - s, _ := ParsePrivateKey(testdata.PEMBytes["ecdsap256"]) - return s - }, - }, - { - name: CertAlgoECDSA384v01, - keys: func() Signer { - s, _ := ParsePrivateKey(testdata.PEMBytes["ecdsap384"]) - return s - }, - }, - { - name: CertAlgoECDSA521v01, - keys: func() Signer { - s, _ := ParsePrivateKey(testdata.PEMBytes["ecdsap521"]) - return s - }, - }, - { - name: CertAlgoED25519v01, - keys: func() Signer { - s, _ := ParsePrivateKey(testdata.PEMBytes["ed25519"]) - return s - }, - }, - { - name: CertAlgoRSAv01, - keys: func() Signer { - s, _ := ParsePrivateKey(testdata.PEMBytes["rsa"]) - return s - }, - }, - { - name: CertAlgoDSAv01, - keys: func() Signer { - s, _ := ParsePrivateKey(testdata.PEMBytes["dsa"]) - return s - }, - }, - } - - k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - if err != nil { - t.Fatalf("error generating host key: %v", err) - } - - signer, err := NewSignerFromKey(k) - if err != nil { - t.Fatalf("error generating signer for ssh listener: %v", err) - } - - conf := &ServerConfig{ - PublicKeyCallback: func(c ConnMetadata, k PublicKey) (*Permissions, error) { - return new(Permissions), nil - }, - } - conf.AddHostKey(signer) - - for _, m := range testVars { - t.Run(m.name, func(t *testing.T) { - - c1, c2, err := netPipe() - if err != nil { - t.Fatalf("netPipe: %v", err) - } - defer c1.Close() - defer c2.Close() - - go NewServerConn(c1, conf) - - priv := m.keys() - if err != nil { - t.Fatalf("error generating ssh pubkey: %v", err) - } - - cert := &Certificate{ - CertType: UserCert, - Key: priv.PublicKey(), - } - cert.SignCert(rand.Reader, priv) - - certSigner, err := NewCertSigner(cert, priv) - if err != nil { - t.Fatalf("error generating cert signer: %v", err) - } - - config := &ClientConfig{ - User: "user", - HostKeyCallback: func(h string, r net.Addr, k PublicKey) error { return nil }, - Auth: []AuthMethod{PublicKeys(certSigner)}, - } - - _, _, _, err = NewClientConn(c2, "", config) - if err != nil { - t.Fatalf("error connecting: %v", err) - } - }) - } -} diff --git a/vendor/golang.org/x/crypto/ssh/cipher_test.go b/vendor/golang.org/x/crypto/ssh/cipher_test.go deleted file mode 100644 index a52d6e48..00000000 --- a/vendor/golang.org/x/crypto/ssh/cipher_test.go +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ssh - -import ( - "bytes" - "crypto" - "crypto/rand" - "testing" -) - -func TestDefaultCiphersExist(t *testing.T) { - for _, cipherAlgo := range supportedCiphers { - if _, ok := cipherModes[cipherAlgo]; !ok { - t.Errorf("supported cipher %q is unknown", cipherAlgo) - } - } - for _, cipherAlgo := range preferredCiphers { - if _, ok := cipherModes[cipherAlgo]; !ok { - t.Errorf("preferred cipher %q is unknown", cipherAlgo) - } - } -} - -func TestPacketCiphers(t *testing.T) { - defaultMac := "hmac-sha2-256" - defaultCipher := "aes128-ctr" - for cipher := range cipherModes { - t.Run("cipher="+cipher, - func(t *testing.T) { testPacketCipher(t, cipher, defaultMac) }) - } - for mac := range macModes { - t.Run("mac="+mac, - func(t *testing.T) { testPacketCipher(t, defaultCipher, mac) }) - } -} - -func testPacketCipher(t *testing.T, cipher, mac string) { - kr := &kexResult{Hash: crypto.SHA1} - algs := directionAlgorithms{ - Cipher: cipher, - MAC: mac, - Compression: "none", - } - client, err := newPacketCipher(clientKeys, algs, kr) - if err != nil { - t.Fatalf("newPacketCipher(client, %q, %q): %v", cipher, mac, err) - } - server, err := newPacketCipher(clientKeys, algs, kr) - if err != nil { - t.Fatalf("newPacketCipher(client, %q, %q): %v", cipher, mac, err) - } - - want := "bla bla" - input := []byte(want) - buf := &bytes.Buffer{} - if err := client.writePacket(0, buf, rand.Reader, input); err != nil { - t.Fatalf("writePacket(%q, %q): %v", cipher, mac, err) - } - - packet, err := server.readPacket(0, buf) - if err != nil { - t.Fatalf("readPacket(%q, %q): %v", cipher, mac, err) - } - - if string(packet) != want { - t.Errorf("roundtrip(%q, %q): got %q, want %q", cipher, mac, packet, want) - } -} - -func TestCBCOracleCounterMeasure(t *testing.T) { - kr := &kexResult{Hash: crypto.SHA1} - algs := directionAlgorithms{ - Cipher: aes128cbcID, - MAC: "hmac-sha1", - Compression: "none", - } - client, err := newPacketCipher(clientKeys, algs, kr) - if err != nil { - t.Fatalf("newPacketCipher(client): %v", err) - } - - want := "bla bla" - input := []byte(want) - buf := &bytes.Buffer{} - if err := client.writePacket(0, buf, rand.Reader, input); err != nil { - t.Errorf("writePacket: %v", err) - } - - packetSize := buf.Len() - buf.Write(make([]byte, 2*maxPacket)) - - // We corrupt each byte, but this usually will only test the - // 'packet too large' or 'MAC failure' cases. - lastRead := -1 - for i := 0; i < packetSize; i++ { - server, err := newPacketCipher(clientKeys, algs, kr) - if err != nil { - t.Fatalf("newPacketCipher(client): %v", err) - } - - fresh := &bytes.Buffer{} - fresh.Write(buf.Bytes()) - fresh.Bytes()[i] ^= 0x01 - - before := fresh.Len() - _, err = server.readPacket(0, fresh) - if err == nil { - t.Errorf("corrupt byte %d: readPacket succeeded ", i) - continue - } - if _, ok := err.(cbcError); !ok { - t.Errorf("corrupt byte %d: got %v (%T), want cbcError", i, err, err) - continue - } - - after := fresh.Len() - bytesRead := before - after - if bytesRead < maxPacket { - t.Errorf("corrupt byte %d: read %d bytes, want more than %d", i, bytesRead, maxPacket) - continue - } - - if i > 0 && bytesRead != lastRead { - t.Errorf("corrupt byte %d: read %d bytes, want %d bytes read", i, bytesRead, lastRead) - } - lastRead = bytesRead - } -} diff --git a/vendor/golang.org/x/crypto/ssh/client_auth_test.go b/vendor/golang.org/x/crypto/ssh/client_auth_test.go deleted file mode 100644 index 026d137e..00000000 --- a/vendor/golang.org/x/crypto/ssh/client_auth_test.go +++ /dev/null @@ -1,678 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ssh - -import ( - "bytes" - "crypto/rand" - "errors" - "fmt" - "io" - "os" - "strings" - "testing" -) - -type keyboardInteractive map[string]string - -func (cr keyboardInteractive) Challenge(user string, instruction string, questions []string, echos []bool) ([]string, error) { - var answers []string - for _, q := range questions { - answers = append(answers, cr[q]) - } - return answers, nil -} - -// reused internally by tests -var clientPassword = "tiger" - -// tryAuth runs a handshake with a given config against an SSH server -// with config serverConfig. Returns both client and server side errors. -func tryAuth(t *testing.T, config *ClientConfig) error { - err, _ := tryAuthBothSides(t, config) - return err -} - -// tryAuthBothSides runs the handshake and returns the resulting errors from both sides of the connection. -func tryAuthBothSides(t *testing.T, config *ClientConfig) (clientError error, serverAuthErrors []error) { - c1, c2, err := netPipe() - if err != nil { - t.Fatalf("netPipe: %v", err) - } - defer c1.Close() - defer c2.Close() - - certChecker := CertChecker{ - IsUserAuthority: func(k PublicKey) bool { - return bytes.Equal(k.Marshal(), testPublicKeys["ecdsa"].Marshal()) - }, - UserKeyFallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) { - if conn.User() == "testuser" && bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) { - return nil, nil - } - - return nil, fmt.Errorf("pubkey for %q not acceptable", conn.User()) - }, - IsRevoked: func(c *Certificate) bool { - return c.Serial == 666 - }, - } - - serverConfig := &ServerConfig{ - PasswordCallback: func(conn ConnMetadata, pass []byte) (*Permissions, error) { - if conn.User() == "testuser" && string(pass) == clientPassword { - return nil, nil - } - return nil, errors.New("password auth failed") - }, - PublicKeyCallback: certChecker.Authenticate, - KeyboardInteractiveCallback: func(conn ConnMetadata, challenge KeyboardInteractiveChallenge) (*Permissions, error) { - ans, err := challenge("user", - "instruction", - []string{"question1", "question2"}, - []bool{true, true}) - if err != nil { - return nil, err - } - ok := conn.User() == "testuser" && ans[0] == "answer1" && ans[1] == "answer2" - if ok { - challenge("user", "motd", nil, nil) - return nil, nil - } - return nil, errors.New("keyboard-interactive failed") - }, - } - serverConfig.AddHostKey(testSigners["rsa"]) - - serverConfig.AuthLogCallback = func(conn ConnMetadata, method string, err error) { - serverAuthErrors = append(serverAuthErrors, err) - } - - go newServer(c1, serverConfig) - _, _, _, err = NewClientConn(c2, "", config) - return err, serverAuthErrors -} - -func TestClientAuthPublicKey(t *testing.T) { - config := &ClientConfig{ - User: "testuser", - Auth: []AuthMethod{ - PublicKeys(testSigners["rsa"]), - }, - HostKeyCallback: InsecureIgnoreHostKey(), - } - if err := tryAuth(t, config); err != nil { - t.Fatalf("unable to dial remote side: %s", err) - } -} - -func TestAuthMethodPassword(t *testing.T) { - config := &ClientConfig{ - User: "testuser", - Auth: []AuthMethod{ - Password(clientPassword), - }, - HostKeyCallback: InsecureIgnoreHostKey(), - } - - if err := tryAuth(t, config); err != nil { - t.Fatalf("unable to dial remote side: %s", err) - } -} - -func TestAuthMethodFallback(t *testing.T) { - var passwordCalled bool - config := &ClientConfig{ - User: "testuser", - Auth: []AuthMethod{ - PublicKeys(testSigners["rsa"]), - PasswordCallback( - func() (string, error) { - passwordCalled = true - return "WRONG", nil - }), - }, - HostKeyCallback: InsecureIgnoreHostKey(), - } - - if err := tryAuth(t, config); err != nil { - t.Fatalf("unable to dial remote side: %s", err) - } - - if passwordCalled { - t.Errorf("password auth tried before public-key auth.") - } -} - -func TestAuthMethodWrongPassword(t *testing.T) { - config := &ClientConfig{ - User: "testuser", - Auth: []AuthMethod{ - Password("wrong"), - PublicKeys(testSigners["rsa"]), - }, - HostKeyCallback: InsecureIgnoreHostKey(), - } - - if err := tryAuth(t, config); err != nil { - t.Fatalf("unable to dial remote side: %s", err) - } -} - -func TestAuthMethodKeyboardInteractive(t *testing.T) { - answers := keyboardInteractive(map[string]string{ - "question1": "answer1", - "question2": "answer2", - }) - config := &ClientConfig{ - User: "testuser", - Auth: []AuthMethod{ - KeyboardInteractive(answers.Challenge), - }, - HostKeyCallback: InsecureIgnoreHostKey(), - } - - if err := tryAuth(t, config); err != nil { - t.Fatalf("unable to dial remote side: %s", err) - } -} - -func TestAuthMethodWrongKeyboardInteractive(t *testing.T) { - answers := keyboardInteractive(map[string]string{ - "question1": "answer1", - "question2": "WRONG", - }) - config := &ClientConfig{ - User: "testuser", - Auth: []AuthMethod{ - KeyboardInteractive(answers.Challenge), - }, - } - - if err := tryAuth(t, config); err == nil { - t.Fatalf("wrong answers should not have authenticated with KeyboardInteractive") - } -} - -// the mock server will only authenticate ssh-rsa keys -func TestAuthMethodInvalidPublicKey(t *testing.T) { - config := &ClientConfig{ - User: "testuser", - Auth: []AuthMethod{ - PublicKeys(testSigners["dsa"]), - }, - } - - if err := tryAuth(t, config); err == nil { - t.Fatalf("dsa private key should not have authenticated with rsa public key") - } -} - -// the client should authenticate with the second key -func TestAuthMethodRSAandDSA(t *testing.T) { - config := &ClientConfig{ - User: "testuser", - Auth: []AuthMethod{ - PublicKeys(testSigners["dsa"], testSigners["rsa"]), - }, - HostKeyCallback: InsecureIgnoreHostKey(), - } - if err := tryAuth(t, config); err != nil { - t.Fatalf("client could not authenticate with rsa key: %v", err) - } -} - -type invalidAlgSigner struct { - Signer -} - -func (s *invalidAlgSigner) Sign(rand io.Reader, data []byte) (*Signature, error) { - sig, err := s.Signer.Sign(rand, data) - if sig != nil { - sig.Format = "invalid" - } - return sig, err -} - -func TestMethodInvalidAlgorithm(t *testing.T) { - config := &ClientConfig{ - User: "testuser", - Auth: []AuthMethod{ - PublicKeys(&invalidAlgSigner{testSigners["rsa"]}), - }, - HostKeyCallback: InsecureIgnoreHostKey(), - } - - err, serverErrors := tryAuthBothSides(t, config) - if err == nil { - t.Fatalf("login succeeded") - } - - found := false - want := "algorithm \"invalid\"" - - var errStrings []string - for _, err := range serverErrors { - found = found || (err != nil && strings.Contains(err.Error(), want)) - errStrings = append(errStrings, err.Error()) - } - if !found { - t.Errorf("server got error %q, want substring %q", errStrings, want) - } -} - -func TestClientHMAC(t *testing.T) { - for _, mac := range supportedMACs { - config := &ClientConfig{ - User: "testuser", - Auth: []AuthMethod{ - PublicKeys(testSigners["rsa"]), - }, - Config: Config{ - MACs: []string{mac}, - }, - HostKeyCallback: InsecureIgnoreHostKey(), - } - if err := tryAuth(t, config); err != nil { - t.Fatalf("client could not authenticate with mac algo %s: %v", mac, err) - } - } -} - -// issue 4285. -func TestClientUnsupportedCipher(t *testing.T) { - config := &ClientConfig{ - User: "testuser", - Auth: []AuthMethod{ - PublicKeys(), - }, - Config: Config{ - Ciphers: []string{"aes128-cbc"}, // not currently supported - }, - } - if err := tryAuth(t, config); err == nil { - t.Errorf("expected no ciphers in common") - } -} - -func TestClientUnsupportedKex(t *testing.T) { - if os.Getenv("GO_BUILDER_NAME") != "" { - t.Skip("skipping known-flaky test on the Go build dashboard; see golang.org/issue/15198") - } - config := &ClientConfig{ - User: "testuser", - Auth: []AuthMethod{ - PublicKeys(), - }, - Config: Config{ - KeyExchanges: []string{"diffie-hellman-group-exchange-sha256"}, // not currently supported - }, - HostKeyCallback: InsecureIgnoreHostKey(), - } - if err := tryAuth(t, config); err == nil || !strings.Contains(err.Error(), "common algorithm") { - t.Errorf("got %v, expected 'common algorithm'", err) - } -} - -func TestClientLoginCert(t *testing.T) { - cert := &Certificate{ - Key: testPublicKeys["rsa"], - ValidBefore: CertTimeInfinity, - CertType: UserCert, - } - cert.SignCert(rand.Reader, testSigners["ecdsa"]) - certSigner, err := NewCertSigner(cert, testSigners["rsa"]) - if err != nil { - t.Fatalf("NewCertSigner: %v", err) - } - - clientConfig := &ClientConfig{ - User: "user", - HostKeyCallback: InsecureIgnoreHostKey(), - } - clientConfig.Auth = append(clientConfig.Auth, PublicKeys(certSigner)) - - // should succeed - if err := tryAuth(t, clientConfig); err != nil { - t.Errorf("cert login failed: %v", err) - } - - // corrupted signature - cert.Signature.Blob[0]++ - if err := tryAuth(t, clientConfig); err == nil { - t.Errorf("cert login passed with corrupted sig") - } - - // revoked - cert.Serial = 666 - cert.SignCert(rand.Reader, testSigners["ecdsa"]) - if err := tryAuth(t, clientConfig); err == nil { - t.Errorf("revoked cert login succeeded") - } - cert.Serial = 1 - - // sign with wrong key - cert.SignCert(rand.Reader, testSigners["dsa"]) - if err := tryAuth(t, clientConfig); err == nil { - t.Errorf("cert login passed with non-authoritative key") - } - - // host cert - cert.CertType = HostCert - cert.SignCert(rand.Reader, testSigners["ecdsa"]) - if err := tryAuth(t, clientConfig); err == nil { - t.Errorf("cert login passed with wrong type") - } - cert.CertType = UserCert - - // principal specified - cert.ValidPrincipals = []string{"user"} - cert.SignCert(rand.Reader, testSigners["ecdsa"]) - if err := tryAuth(t, clientConfig); err != nil { - t.Errorf("cert login failed: %v", err) - } - - // wrong principal specified - cert.ValidPrincipals = []string{"fred"} - cert.SignCert(rand.Reader, testSigners["ecdsa"]) - if err := tryAuth(t, clientConfig); err == nil { - t.Errorf("cert login passed with wrong principal") - } - cert.ValidPrincipals = nil - - // added critical option - cert.CriticalOptions = map[string]string{"root-access": "yes"} - cert.SignCert(rand.Reader, testSigners["ecdsa"]) - if err := tryAuth(t, clientConfig); err == nil { - t.Errorf("cert login passed with unrecognized critical option") - } - - // allowed source address - cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42/24,::42/120"} - cert.SignCert(rand.Reader, testSigners["ecdsa"]) - if err := tryAuth(t, clientConfig); err != nil { - t.Errorf("cert login with source-address failed: %v", err) - } - - // disallowed source address - cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42,::42"} - cert.SignCert(rand.Reader, testSigners["ecdsa"]) - if err := tryAuth(t, clientConfig); err == nil { - t.Errorf("cert login with source-address succeeded") - } -} - -func testPermissionsPassing(withPermissions bool, t *testing.T) { - serverConfig := &ServerConfig{ - PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) { - if conn.User() == "nopermissions" { - return nil, nil - } - return &Permissions{}, nil - }, - } - serverConfig.AddHostKey(testSigners["rsa"]) - - clientConfig := &ClientConfig{ - Auth: []AuthMethod{ - PublicKeys(testSigners["rsa"]), - }, - HostKeyCallback: InsecureIgnoreHostKey(), - } - if withPermissions { - clientConfig.User = "permissions" - } else { - clientConfig.User = "nopermissions" - } - - c1, c2, err := netPipe() - if err != nil { - t.Fatalf("netPipe: %v", err) - } - defer c1.Close() - defer c2.Close() - - go NewClientConn(c2, "", clientConfig) - serverConn, err := newServer(c1, serverConfig) - if err != nil { - t.Fatal(err) - } - if p := serverConn.Permissions; (p != nil) != withPermissions { - t.Fatalf("withPermissions is %t, but Permissions object is %#v", withPermissions, p) - } -} - -func TestPermissionsPassing(t *testing.T) { - testPermissionsPassing(true, t) -} - -func TestNoPermissionsPassing(t *testing.T) { - testPermissionsPassing(false, t) -} - -func TestRetryableAuth(t *testing.T) { - n := 0 - passwords := []string{"WRONG1", "WRONG2"} - - config := &ClientConfig{ - User: "testuser", - Auth: []AuthMethod{ - RetryableAuthMethod(PasswordCallback(func() (string, error) { - p := passwords[n] - n++ - return p, nil - }), 2), - PublicKeys(testSigners["rsa"]), - }, - HostKeyCallback: InsecureIgnoreHostKey(), - } - - if err := tryAuth(t, config); err != nil { - t.Fatalf("unable to dial remote side: %s", err) - } - if n != 2 { - t.Fatalf("Did not try all passwords") - } -} - -func ExampleRetryableAuthMethod(t *testing.T) { - user := "testuser" - NumberOfPrompts := 3 - - // Normally this would be a callback that prompts the user to answer the - // provided questions - Cb := func(user, instruction string, questions []string, echos []bool) (answers []string, err error) { - return []string{"answer1", "answer2"}, nil - } - - config := &ClientConfig{ - HostKeyCallback: InsecureIgnoreHostKey(), - User: user, - Auth: []AuthMethod{ - RetryableAuthMethod(KeyboardInteractiveChallenge(Cb), NumberOfPrompts), - }, - } - - if err := tryAuth(t, config); err != nil { - t.Fatalf("unable to dial remote side: %s", err) - } -} - -// Test if username is received on server side when NoClientAuth is used -func TestClientAuthNone(t *testing.T) { - user := "testuser" - serverConfig := &ServerConfig{ - NoClientAuth: true, - } - serverConfig.AddHostKey(testSigners["rsa"]) - - clientConfig := &ClientConfig{ - User: user, - HostKeyCallback: InsecureIgnoreHostKey(), - } - - c1, c2, err := netPipe() - if err != nil { - t.Fatalf("netPipe: %v", err) - } - defer c1.Close() - defer c2.Close() - - go NewClientConn(c2, "", clientConfig) - serverConn, err := newServer(c1, serverConfig) - if err != nil { - t.Fatalf("newServer: %v", err) - } - if serverConn.User() != user { - t.Fatalf("server: got %q, want %q", serverConn.User(), user) - } -} - -// Test if authentication attempts are limited on server when MaxAuthTries is set -func TestClientAuthMaxAuthTries(t *testing.T) { - user := "testuser" - - serverConfig := &ServerConfig{ - MaxAuthTries: 2, - PasswordCallback: func(conn ConnMetadata, pass []byte) (*Permissions, error) { - if conn.User() == "testuser" && string(pass) == "right" { - return nil, nil - } - return nil, errors.New("password auth failed") - }, - } - serverConfig.AddHostKey(testSigners["rsa"]) - - expectedErr := fmt.Errorf("ssh: handshake failed: %v", &disconnectMsg{ - Reason: 2, - Message: "too many authentication failures", - }) - - for tries := 2; tries < 4; tries++ { - n := tries - clientConfig := &ClientConfig{ - User: user, - Auth: []AuthMethod{ - RetryableAuthMethod(PasswordCallback(func() (string, error) { - n-- - if n == 0 { - return "right", nil - } - return "wrong", nil - }), tries), - }, - HostKeyCallback: InsecureIgnoreHostKey(), - } - - c1, c2, err := netPipe() - if err != nil { - t.Fatalf("netPipe: %v", err) - } - defer c1.Close() - defer c2.Close() - - go newServer(c1, serverConfig) - _, _, _, err = NewClientConn(c2, "", clientConfig) - if tries > 2 { - if err == nil { - t.Fatalf("client: got no error, want %s", expectedErr) - } else if err.Error() != expectedErr.Error() { - t.Fatalf("client: got %s, want %s", err, expectedErr) - } - } else { - if err != nil { - t.Fatalf("client: got %s, want no error", err) - } - } - } -} - -// Test if authentication attempts are correctly limited on server -// when more public keys are provided then MaxAuthTries -func TestClientAuthMaxAuthTriesPublicKey(t *testing.T) { - signers := []Signer{} - for i := 0; i < 6; i++ { - signers = append(signers, testSigners["dsa"]) - } - - validConfig := &ClientConfig{ - User: "testuser", - Auth: []AuthMethod{ - PublicKeys(append([]Signer{testSigners["rsa"]}, signers...)...), - }, - HostKeyCallback: InsecureIgnoreHostKey(), - } - if err := tryAuth(t, validConfig); err != nil { - t.Fatalf("unable to dial remote side: %s", err) - } - - expectedErr := fmt.Errorf("ssh: handshake failed: %v", &disconnectMsg{ - Reason: 2, - Message: "too many authentication failures", - }) - invalidConfig := &ClientConfig{ - User: "testuser", - Auth: []AuthMethod{ - PublicKeys(append(signers, testSigners["rsa"])...), - }, - HostKeyCallback: InsecureIgnoreHostKey(), - } - if err := tryAuth(t, invalidConfig); err == nil { - t.Fatalf("client: got no error, want %s", expectedErr) - } else if err.Error() != expectedErr.Error() { - t.Fatalf("client: got %s, want %s", err, expectedErr) - } -} - -// Test whether authentication errors are being properly logged if all -// authentication methods have been exhausted -func TestClientAuthErrorList(t *testing.T) { - publicKeyErr := errors.New("This is an error from PublicKeyCallback") - - clientConfig := &ClientConfig{ - Auth: []AuthMethod{ - PublicKeys(testSigners["rsa"]), - }, - HostKeyCallback: InsecureIgnoreHostKey(), - } - serverConfig := &ServerConfig{ - PublicKeyCallback: func(_ ConnMetadata, _ PublicKey) (*Permissions, error) { - return nil, publicKeyErr - }, - } - serverConfig.AddHostKey(testSigners["rsa"]) - - c1, c2, err := netPipe() - if err != nil { - t.Fatalf("netPipe: %v", err) - } - defer c1.Close() - defer c2.Close() - - go NewClientConn(c2, "", clientConfig) - _, err = newServer(c1, serverConfig) - if err == nil { - t.Fatal("newServer: got nil, expected errors") - } - - authErrs, ok := err.(*ServerAuthError) - if !ok { - t.Fatalf("errors: got %T, want *ssh.ServerAuthError", err) - } - for i, e := range authErrs.Errors { - switch i { - case 0: - if e != ErrNoAuth { - t.Fatalf("errors: got error %v, want ErrNoAuth", e) - } - case 1: - if e != publicKeyErr { - t.Fatalf("errors: got %v, want %v", e, publicKeyErr) - } - default: - t.Fatalf("errors: got %v, expected 2 errors", authErrs.Errors) - } - } -} diff --git a/vendor/golang.org/x/crypto/ssh/client_test.go b/vendor/golang.org/x/crypto/ssh/client_test.go deleted file mode 100644 index 81f9599e..00000000 --- a/vendor/golang.org/x/crypto/ssh/client_test.go +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ssh - -import ( - "strings" - "testing" -) - -func TestClientVersion(t *testing.T) { - for _, tt := range []struct { - name string - version string - multiLine string - wantErr bool - }{ - { - name: "default version", - version: packageVersion, - }, - { - name: "custom version", - version: "SSH-2.0-CustomClientVersionString", - }, - { - name: "good multi line version", - version: packageVersion, - multiLine: strings.Repeat("ignored\r\n", 20), - }, - { - name: "bad multi line version", - version: packageVersion, - multiLine: "bad multi line version", - wantErr: true, - }, - { - name: "long multi line version", - version: packageVersion, - multiLine: strings.Repeat("long multi line version\r\n", 50)[:256], - wantErr: true, - }, - } { - t.Run(tt.name, func(t *testing.T) { - c1, c2, err := netPipe() - if err != nil { - t.Fatalf("netPipe: %v", err) - } - defer c1.Close() - defer c2.Close() - go func() { - if tt.multiLine != "" { - c1.Write([]byte(tt.multiLine)) - } - NewClientConn(c1, "", &ClientConfig{ - ClientVersion: tt.version, - HostKeyCallback: InsecureIgnoreHostKey(), - }) - c1.Close() - }() - conf := &ServerConfig{NoClientAuth: true} - conf.AddHostKey(testSigners["rsa"]) - conn, _, _, err := NewServerConn(c2, conf) - if err == nil == tt.wantErr { - t.Fatalf("got err %v; wantErr %t", err, tt.wantErr) - } - if tt.wantErr { - // Don't verify the version on an expected error. - return - } - if got := string(conn.ClientVersion()); got != tt.version { - t.Fatalf("got %q; want %q", got, tt.version) - } - }) - } -} - -func TestHostKeyCheck(t *testing.T) { - for _, tt := range []struct { - name string - wantError string - key PublicKey - }{ - {"no callback", "must specify HostKeyCallback", nil}, - {"correct key", "", testSigners["rsa"].PublicKey()}, - {"mismatch", "mismatch", testSigners["ecdsa"].PublicKey()}, - } { - c1, c2, err := netPipe() - if err != nil { - t.Fatalf("netPipe: %v", err) - } - defer c1.Close() - defer c2.Close() - serverConf := &ServerConfig{ - NoClientAuth: true, - } - serverConf.AddHostKey(testSigners["rsa"]) - - go NewServerConn(c1, serverConf) - clientConf := ClientConfig{ - User: "user", - } - if tt.key != nil { - clientConf.HostKeyCallback = FixedHostKey(tt.key) - } - - _, _, _, err = NewClientConn(c2, "", &clientConf) - if err != nil { - if tt.wantError == "" || !strings.Contains(err.Error(), tt.wantError) { - t.Errorf("%s: got error %q, missing %q", tt.name, err.Error(), tt.wantError) - } - } else if tt.wantError != "" { - t.Errorf("%s: succeeded, but want error string %q", tt.name, tt.wantError) - } - } -} - -func TestBannerCallback(t *testing.T) { - c1, c2, err := netPipe() - if err != nil { - t.Fatalf("netPipe: %v", err) - } - defer c1.Close() - defer c2.Close() - - serverConf := &ServerConfig{ - PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { - return &Permissions{}, nil - }, - BannerCallback: func(conn ConnMetadata) string { - return "Hello World" - }, - } - serverConf.AddHostKey(testSigners["rsa"]) - go NewServerConn(c1, serverConf) - - var receivedBanner string - var bannerCount int - clientConf := ClientConfig{ - Auth: []AuthMethod{ - Password("123"), - }, - User: "user", - HostKeyCallback: InsecureIgnoreHostKey(), - BannerCallback: func(message string) error { - bannerCount++ - receivedBanner = message - return nil - }, - } - - _, _, _, err = NewClientConn(c2, "", &clientConf) - if err != nil { - t.Fatal(err) - } - - if bannerCount != 1 { - t.Errorf("got %d banners; want 1", bannerCount) - } - - expected := "Hello World" - if receivedBanner != expected { - t.Fatalf("got %s; want %s", receivedBanner, expected) - } -} diff --git a/vendor/golang.org/x/crypto/ssh/example_test.go b/vendor/golang.org/x/crypto/ssh/example_test.go deleted file mode 100644 index b910c7bf..00000000 --- a/vendor/golang.org/x/crypto/ssh/example_test.go +++ /dev/null @@ -1,320 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ssh_test - -import ( - "bufio" - "bytes" - "fmt" - "io/ioutil" - "log" - "net" - "net/http" - "os" - "path/filepath" - "strings" - - "golang.org/x/crypto/ssh" - "golang.org/x/crypto/ssh/terminal" -) - -func ExampleNewServerConn() { - // Public key authentication is done by comparing - // the public key of a received connection - // with the entries in the authorized_keys file. - authorizedKeysBytes, err := ioutil.ReadFile("authorized_keys") - if err != nil { - log.Fatalf("Failed to load authorized_keys, err: %v", err) - } - - authorizedKeysMap := map[string]bool{} - for len(authorizedKeysBytes) > 0 { - pubKey, _, _, rest, err := ssh.ParseAuthorizedKey(authorizedKeysBytes) - if err != nil { - log.Fatal(err) - } - - authorizedKeysMap[string(pubKey.Marshal())] = true - authorizedKeysBytes = rest - } - - // An SSH server is represented by a ServerConfig, which holds - // certificate details and handles authentication of ServerConns. - config := &ssh.ServerConfig{ - // Remove to disable password auth. - PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) { - // Should use constant-time compare (or better, salt+hash) in - // a production setting. - if c.User() == "testuser" && string(pass) == "tiger" { - return nil, nil - } - return nil, fmt.Errorf("password rejected for %q", c.User()) - }, - - // Remove to disable public key auth. - PublicKeyCallback: func(c ssh.ConnMetadata, pubKey ssh.PublicKey) (*ssh.Permissions, error) { - if authorizedKeysMap[string(pubKey.Marshal())] { - return &ssh.Permissions{ - // Record the public key used for authentication. - Extensions: map[string]string{ - "pubkey-fp": ssh.FingerprintSHA256(pubKey), - }, - }, nil - } - return nil, fmt.Errorf("unknown public key for %q", c.User()) - }, - } - - privateBytes, err := ioutil.ReadFile("id_rsa") - if err != nil { - log.Fatal("Failed to load private key: ", err) - } - - private, err := ssh.ParsePrivateKey(privateBytes) - if err != nil { - log.Fatal("Failed to parse private key: ", err) - } - - config.AddHostKey(private) - - // Once a ServerConfig has been configured, connections can be - // accepted. - listener, err := net.Listen("tcp", "0.0.0.0:2022") - if err != nil { - log.Fatal("failed to listen for connection: ", err) - } - nConn, err := listener.Accept() - if err != nil { - log.Fatal("failed to accept incoming connection: ", err) - } - - // Before use, a handshake must be performed on the incoming - // net.Conn. - conn, chans, reqs, err := ssh.NewServerConn(nConn, config) - if err != nil { - log.Fatal("failed to handshake: ", err) - } - log.Printf("logged in with key %s", conn.Permissions.Extensions["pubkey-fp"]) - - // The incoming Request channel must be serviced. - go ssh.DiscardRequests(reqs) - - // Service the incoming Channel channel. - for newChannel := range chans { - // Channels have a type, depending on the application level - // protocol intended. In the case of a shell, the type is - // "session" and ServerShell may be used to present a simple - // terminal interface. - if newChannel.ChannelType() != "session" { - newChannel.Reject(ssh.UnknownChannelType, "unknown channel type") - continue - } - channel, requests, err := newChannel.Accept() - if err != nil { - log.Fatalf("Could not accept channel: %v", err) - } - - // Sessions have out-of-band requests such as "shell", - // "pty-req" and "env". Here we handle only the - // "shell" request. - go func(in <-chan *ssh.Request) { - for req := range in { - req.Reply(req.Type == "shell", nil) - } - }(requests) - - term := terminal.NewTerminal(channel, "> ") - - go func() { - defer channel.Close() - for { - line, err := term.ReadLine() - if err != nil { - break - } - fmt.Println(line) - } - }() - } -} - -func ExampleHostKeyCheck() { - // Every client must provide a host key check. Here is a - // simple-minded parse of OpenSSH's known_hosts file - host := "hostname" - file, err := os.Open(filepath.Join(os.Getenv("HOME"), ".ssh", "known_hosts")) - if err != nil { - log.Fatal(err) - } - defer file.Close() - - scanner := bufio.NewScanner(file) - var hostKey ssh.PublicKey - for scanner.Scan() { - fields := strings.Split(scanner.Text(), " ") - if len(fields) != 3 { - continue - } - if strings.Contains(fields[0], host) { - var err error - hostKey, _, _, _, err = ssh.ParseAuthorizedKey(scanner.Bytes()) - if err != nil { - log.Fatalf("error parsing %q: %v", fields[2], err) - } - break - } - } - - if hostKey == nil { - log.Fatalf("no hostkey for %s", host) - } - - config := ssh.ClientConfig{ - User: os.Getenv("USER"), - HostKeyCallback: ssh.FixedHostKey(hostKey), - } - - _, err = ssh.Dial("tcp", host+":22", &config) - log.Println(err) -} - -func ExampleDial() { - var hostKey ssh.PublicKey - // An SSH client is represented with a ClientConn. - // - // To authenticate with the remote server you must pass at least one - // implementation of AuthMethod via the Auth field in ClientConfig, - // and provide a HostKeyCallback. - config := &ssh.ClientConfig{ - User: "username", - Auth: []ssh.AuthMethod{ - ssh.Password("yourpassword"), - }, - HostKeyCallback: ssh.FixedHostKey(hostKey), - } - client, err := ssh.Dial("tcp", "yourserver.com:22", config) - if err != nil { - log.Fatal("Failed to dial: ", err) - } - - // Each ClientConn can support multiple interactive sessions, - // represented by a Session. - session, err := client.NewSession() - if err != nil { - log.Fatal("Failed to create session: ", err) - } - defer session.Close() - - // Once a Session is created, you can execute a single command on - // the remote side using the Run method. - var b bytes.Buffer - session.Stdout = &b - if err := session.Run("/usr/bin/whoami"); err != nil { - log.Fatal("Failed to run: " + err.Error()) - } - fmt.Println(b.String()) -} - -func ExamplePublicKeys() { - var hostKey ssh.PublicKey - // A public key may be used to authenticate against the remote - // server by using an unencrypted PEM-encoded private key file. - // - // If you have an encrypted private key, the crypto/x509 package - // can be used to decrypt it. - key, err := ioutil.ReadFile("/home/user/.ssh/id_rsa") - if err != nil { - log.Fatalf("unable to read private key: %v", err) - } - - // Create the Signer for this private key. - signer, err := ssh.ParsePrivateKey(key) - if err != nil { - log.Fatalf("unable to parse private key: %v", err) - } - - config := &ssh.ClientConfig{ - User: "user", - Auth: []ssh.AuthMethod{ - // Use the PublicKeys method for remote authentication. - ssh.PublicKeys(signer), - }, - HostKeyCallback: ssh.FixedHostKey(hostKey), - } - - // Connect to the remote server and perform the SSH handshake. - client, err := ssh.Dial("tcp", "host.com:22", config) - if err != nil { - log.Fatalf("unable to connect: %v", err) - } - defer client.Close() -} - -func ExampleClient_Listen() { - var hostKey ssh.PublicKey - config := &ssh.ClientConfig{ - User: "username", - Auth: []ssh.AuthMethod{ - ssh.Password("password"), - }, - HostKeyCallback: ssh.FixedHostKey(hostKey), - } - // Dial your ssh server. - conn, err := ssh.Dial("tcp", "localhost:22", config) - if err != nil { - log.Fatal("unable to connect: ", err) - } - defer conn.Close() - - // Request the remote side to open port 8080 on all interfaces. - l, err := conn.Listen("tcp", "0.0.0.0:8080") - if err != nil { - log.Fatal("unable to register tcp forward: ", err) - } - defer l.Close() - - // Serve HTTP with your SSH server acting as a reverse proxy. - http.Serve(l, http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { - fmt.Fprintf(resp, "Hello world!\n") - })) -} - -func ExampleSession_RequestPty() { - var hostKey ssh.PublicKey - // Create client config - config := &ssh.ClientConfig{ - User: "username", - Auth: []ssh.AuthMethod{ - ssh.Password("password"), - }, - HostKeyCallback: ssh.FixedHostKey(hostKey), - } - // Connect to ssh server - conn, err := ssh.Dial("tcp", "localhost:22", config) - if err != nil { - log.Fatal("unable to connect: ", err) - } - defer conn.Close() - // Create a session - session, err := conn.NewSession() - if err != nil { - log.Fatal("unable to create session: ", err) - } - defer session.Close() - // Set up terminal modes - modes := ssh.TerminalModes{ - ssh.ECHO: 0, // disable echoing - ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud - ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud - } - // Request pseudo terminal - if err := session.RequestPty("xterm", 40, 80, modes); err != nil { - log.Fatal("request for pseudo terminal failed: ", err) - } - // Start remote shell - if err := session.Shell(); err != nil { - log.Fatal("failed to start shell: ", err) - } -} diff --git a/vendor/golang.org/x/crypto/ssh/handshake_test.go b/vendor/golang.org/x/crypto/ssh/handshake_test.go deleted file mode 100644 index 91d49356..00000000 --- a/vendor/golang.org/x/crypto/ssh/handshake_test.go +++ /dev/null @@ -1,559 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ssh - -import ( - "bytes" - "crypto/rand" - "errors" - "fmt" - "io" - "net" - "reflect" - "runtime" - "strings" - "sync" - "testing" -) - -type testChecker struct { - calls []string -} - -func (t *testChecker) Check(dialAddr string, addr net.Addr, key PublicKey) error { - if dialAddr == "bad" { - return fmt.Errorf("dialAddr is bad") - } - - if tcpAddr, ok := addr.(*net.TCPAddr); !ok || tcpAddr == nil { - return fmt.Errorf("testChecker: got %T want *net.TCPAddr", addr) - } - - t.calls = append(t.calls, fmt.Sprintf("%s %v %s %x", dialAddr, addr, key.Type(), key.Marshal())) - - return nil -} - -// netPipe is analogous to net.Pipe, but it uses a real net.Conn, and -// therefore is buffered (net.Pipe deadlocks if both sides start with -// a write.) -func netPipe() (net.Conn, net.Conn, error) { - listener, err := net.Listen("tcp", "127.0.0.1:0") - if err != nil { - listener, err = net.Listen("tcp", "[::1]:0") - if err != nil { - return nil, nil, err - } - } - defer listener.Close() - c1, err := net.Dial("tcp", listener.Addr().String()) - if err != nil { - return nil, nil, err - } - - c2, err := listener.Accept() - if err != nil { - c1.Close() - return nil, nil, err - } - - return c1, c2, nil -} - -// noiseTransport inserts ignore messages to check that the read loop -// and the key exchange filters out these messages. -type noiseTransport struct { - keyingTransport -} - -func (t *noiseTransport) writePacket(p []byte) error { - ignore := []byte{msgIgnore} - if err := t.keyingTransport.writePacket(ignore); err != nil { - return err - } - debug := []byte{msgDebug, 1, 2, 3} - if err := t.keyingTransport.writePacket(debug); err != nil { - return err - } - - return t.keyingTransport.writePacket(p) -} - -func addNoiseTransport(t keyingTransport) keyingTransport { - return &noiseTransport{t} -} - -// handshakePair creates two handshakeTransports connected with each -// other. If the noise argument is true, both transports will try to -// confuse the other side by sending ignore and debug messages. -func handshakePair(clientConf *ClientConfig, addr string, noise bool) (client *handshakeTransport, server *handshakeTransport, err error) { - a, b, err := netPipe() - if err != nil { - return nil, nil, err - } - - var trC, trS keyingTransport - - trC = newTransport(a, rand.Reader, true) - trS = newTransport(b, rand.Reader, false) - if noise { - trC = addNoiseTransport(trC) - trS = addNoiseTransport(trS) - } - clientConf.SetDefaults() - - v := []byte("version") - client = newClientTransport(trC, v, v, clientConf, addr, a.RemoteAddr()) - - serverConf := &ServerConfig{} - serverConf.AddHostKey(testSigners["ecdsa"]) - serverConf.AddHostKey(testSigners["rsa"]) - serverConf.SetDefaults() - server = newServerTransport(trS, v, v, serverConf) - - if err := server.waitSession(); err != nil { - return nil, nil, fmt.Errorf("server.waitSession: %v", err) - } - if err := client.waitSession(); err != nil { - return nil, nil, fmt.Errorf("client.waitSession: %v", err) - } - - return client, server, nil -} - -func TestHandshakeBasic(t *testing.T) { - if runtime.GOOS == "plan9" { - t.Skip("see golang.org/issue/7237") - } - - checker := &syncChecker{ - waitCall: make(chan int, 10), - called: make(chan int, 10), - } - - checker.waitCall <- 1 - trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr", false) - if err != nil { - t.Fatalf("handshakePair: %v", err) - } - - defer trC.Close() - defer trS.Close() - - // Let first kex complete normally. - <-checker.called - - clientDone := make(chan int, 0) - gotHalf := make(chan int, 0) - const N = 20 - - go func() { - defer close(clientDone) - // Client writes a bunch of stuff, and does a key - // change in the middle. This should not confuse the - // handshake in progress. We do this twice, so we test - // that the packet buffer is reset correctly. - for i := 0; i < N; i++ { - p := []byte{msgRequestSuccess, byte(i)} - if err := trC.writePacket(p); err != nil { - t.Fatalf("sendPacket: %v", err) - } - if (i % 10) == 5 { - <-gotHalf - // halfway through, we request a key change. - trC.requestKeyExchange() - - // Wait until we can be sure the key - // change has really started before we - // write more. - <-checker.called - } - if (i % 10) == 7 { - // write some packets until the kex - // completes, to test buffering of - // packets. - checker.waitCall <- 1 - } - } - }() - - // Server checks that client messages come in cleanly - i := 0 - err = nil - for ; i < N; i++ { - var p []byte - p, err = trS.readPacket() - if err != nil { - break - } - if (i % 10) == 5 { - gotHalf <- 1 - } - - want := []byte{msgRequestSuccess, byte(i)} - if bytes.Compare(p, want) != 0 { - t.Errorf("message %d: got %v, want %v", i, p, want) - } - } - <-clientDone - if err != nil && err != io.EOF { - t.Fatalf("server error: %v", err) - } - if i != N { - t.Errorf("received %d messages, want 10.", i) - } - - close(checker.called) - if _, ok := <-checker.called; ok { - // If all went well, we registered exactly 2 key changes: one - // that establishes the session, and one that we requested - // additionally. - t.Fatalf("got another host key checks after 2 handshakes") - } -} - -func TestForceFirstKex(t *testing.T) { - // like handshakePair, but must access the keyingTransport. - checker := &testChecker{} - clientConf := &ClientConfig{HostKeyCallback: checker.Check} - a, b, err := netPipe() - if err != nil { - t.Fatalf("netPipe: %v", err) - } - - var trC, trS keyingTransport - - trC = newTransport(a, rand.Reader, true) - - // This is the disallowed packet: - trC.writePacket(Marshal(&serviceRequestMsg{serviceUserAuth})) - - // Rest of the setup. - trS = newTransport(b, rand.Reader, false) - clientConf.SetDefaults() - - v := []byte("version") - client := newClientTransport(trC, v, v, clientConf, "addr", a.RemoteAddr()) - - serverConf := &ServerConfig{} - serverConf.AddHostKey(testSigners["ecdsa"]) - serverConf.AddHostKey(testSigners["rsa"]) - serverConf.SetDefaults() - server := newServerTransport(trS, v, v, serverConf) - - defer client.Close() - defer server.Close() - - // We setup the initial key exchange, but the remote side - // tries to send serviceRequestMsg in cleartext, which is - // disallowed. - - if err := server.waitSession(); err == nil { - t.Errorf("server first kex init should reject unexpected packet") - } -} - -func TestHandshakeAutoRekeyWrite(t *testing.T) { - checker := &syncChecker{ - called: make(chan int, 10), - waitCall: nil, - } - clientConf := &ClientConfig{HostKeyCallback: checker.Check} - clientConf.RekeyThreshold = 500 - trC, trS, err := handshakePair(clientConf, "addr", false) - if err != nil { - t.Fatalf("handshakePair: %v", err) - } - defer trC.Close() - defer trS.Close() - - input := make([]byte, 251) - input[0] = msgRequestSuccess - - done := make(chan int, 1) - const numPacket = 5 - go func() { - defer close(done) - j := 0 - for ; j < numPacket; j++ { - if p, err := trS.readPacket(); err != nil { - break - } else if !bytes.Equal(input, p) { - t.Errorf("got packet type %d, want %d", p[0], input[0]) - } - } - - if j != numPacket { - t.Errorf("got %d, want 5 messages", j) - } - }() - - <-checker.called - - for i := 0; i < numPacket; i++ { - p := make([]byte, len(input)) - copy(p, input) - if err := trC.writePacket(p); err != nil { - t.Errorf("writePacket: %v", err) - } - if i == 2 { - // Make sure the kex is in progress. - <-checker.called - } - - } - <-done -} - -type syncChecker struct { - waitCall chan int - called chan int -} - -func (c *syncChecker) Check(dialAddr string, addr net.Addr, key PublicKey) error { - c.called <- 1 - if c.waitCall != nil { - <-c.waitCall - } - return nil -} - -func TestHandshakeAutoRekeyRead(t *testing.T) { - sync := &syncChecker{ - called: make(chan int, 2), - waitCall: nil, - } - clientConf := &ClientConfig{ - HostKeyCallback: sync.Check, - } - clientConf.RekeyThreshold = 500 - - trC, trS, err := handshakePair(clientConf, "addr", false) - if err != nil { - t.Fatalf("handshakePair: %v", err) - } - defer trC.Close() - defer trS.Close() - - packet := make([]byte, 501) - packet[0] = msgRequestSuccess - if err := trS.writePacket(packet); err != nil { - t.Fatalf("writePacket: %v", err) - } - - // While we read out the packet, a key change will be - // initiated. - done := make(chan int, 1) - go func() { - defer close(done) - if _, err := trC.readPacket(); err != nil { - t.Fatalf("readPacket(client): %v", err) - } - - }() - - <-done - <-sync.called -} - -// errorKeyingTransport generates errors after a given number of -// read/write operations. -type errorKeyingTransport struct { - packetConn - readLeft, writeLeft int -} - -func (n *errorKeyingTransport) prepareKeyChange(*algorithms, *kexResult) error { - return nil -} - -func (n *errorKeyingTransport) getSessionID() []byte { - return nil -} - -func (n *errorKeyingTransport) writePacket(packet []byte) error { - if n.writeLeft == 0 { - n.Close() - return errors.New("barf") - } - - n.writeLeft-- - return n.packetConn.writePacket(packet) -} - -func (n *errorKeyingTransport) readPacket() ([]byte, error) { - if n.readLeft == 0 { - n.Close() - return nil, errors.New("barf") - } - - n.readLeft-- - return n.packetConn.readPacket() -} - -func TestHandshakeErrorHandlingRead(t *testing.T) { - for i := 0; i < 20; i++ { - testHandshakeErrorHandlingN(t, i, -1, false) - } -} - -func TestHandshakeErrorHandlingWrite(t *testing.T) { - for i := 0; i < 20; i++ { - testHandshakeErrorHandlingN(t, -1, i, false) - } -} - -func TestHandshakeErrorHandlingReadCoupled(t *testing.T) { - for i := 0; i < 20; i++ { - testHandshakeErrorHandlingN(t, i, -1, true) - } -} - -func TestHandshakeErrorHandlingWriteCoupled(t *testing.T) { - for i := 0; i < 20; i++ { - testHandshakeErrorHandlingN(t, -1, i, true) - } -} - -// testHandshakeErrorHandlingN runs handshakes, injecting errors. If -// handshakeTransport deadlocks, the go runtime will detect it and -// panic. -func testHandshakeErrorHandlingN(t *testing.T, readLimit, writeLimit int, coupled bool) { - msg := Marshal(&serviceRequestMsg{strings.Repeat("x", int(minRekeyThreshold)/4)}) - - a, b := memPipe() - defer a.Close() - defer b.Close() - - key := testSigners["ecdsa"] - serverConf := Config{RekeyThreshold: minRekeyThreshold} - serverConf.SetDefaults() - serverConn := newHandshakeTransport(&errorKeyingTransport{a, readLimit, writeLimit}, &serverConf, []byte{'a'}, []byte{'b'}) - serverConn.hostKeys = []Signer{key} - go serverConn.readLoop() - go serverConn.kexLoop() - - clientConf := Config{RekeyThreshold: 10 * minRekeyThreshold} - clientConf.SetDefaults() - clientConn := newHandshakeTransport(&errorKeyingTransport{b, -1, -1}, &clientConf, []byte{'a'}, []byte{'b'}) - clientConn.hostKeyAlgorithms = []string{key.PublicKey().Type()} - clientConn.hostKeyCallback = InsecureIgnoreHostKey() - go clientConn.readLoop() - go clientConn.kexLoop() - - var wg sync.WaitGroup - - for _, hs := range []packetConn{serverConn, clientConn} { - if !coupled { - wg.Add(2) - go func(c packetConn) { - for i := 0; ; i++ { - str := fmt.Sprintf("%08x", i) + strings.Repeat("x", int(minRekeyThreshold)/4-8) - err := c.writePacket(Marshal(&serviceRequestMsg{str})) - if err != nil { - break - } - } - wg.Done() - c.Close() - }(hs) - go func(c packetConn) { - for { - _, err := c.readPacket() - if err != nil { - break - } - } - wg.Done() - }(hs) - } else { - wg.Add(1) - go func(c packetConn) { - for { - _, err := c.readPacket() - if err != nil { - break - } - if err := c.writePacket(msg); err != nil { - break - } - - } - wg.Done() - }(hs) - } - } - wg.Wait() -} - -func TestDisconnect(t *testing.T) { - if runtime.GOOS == "plan9" { - t.Skip("see golang.org/issue/7237") - } - checker := &testChecker{} - trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr", false) - if err != nil { - t.Fatalf("handshakePair: %v", err) - } - - defer trC.Close() - defer trS.Close() - - trC.writePacket([]byte{msgRequestSuccess, 0, 0}) - errMsg := &disconnectMsg{ - Reason: 42, - Message: "such is life", - } - trC.writePacket(Marshal(errMsg)) - trC.writePacket([]byte{msgRequestSuccess, 0, 0}) - - packet, err := trS.readPacket() - if err != nil { - t.Fatalf("readPacket 1: %v", err) - } - if packet[0] != msgRequestSuccess { - t.Errorf("got packet %v, want packet type %d", packet, msgRequestSuccess) - } - - _, err = trS.readPacket() - if err == nil { - t.Errorf("readPacket 2 succeeded") - } else if !reflect.DeepEqual(err, errMsg) { - t.Errorf("got error %#v, want %#v", err, errMsg) - } - - _, err = trS.readPacket() - if err == nil { - t.Errorf("readPacket 3 succeeded") - } -} - -func TestHandshakeRekeyDefault(t *testing.T) { - clientConf := &ClientConfig{ - Config: Config{ - Ciphers: []string{"aes128-ctr"}, - }, - HostKeyCallback: InsecureIgnoreHostKey(), - } - trC, trS, err := handshakePair(clientConf, "addr", false) - if err != nil { - t.Fatalf("handshakePair: %v", err) - } - defer trC.Close() - defer trS.Close() - - trC.writePacket([]byte{msgRequestSuccess, 0, 0}) - trC.Close() - - rgb := (1024 + trC.readBytesLeft) >> 30 - wgb := (1024 + trC.writeBytesLeft) >> 30 - - if rgb != 64 { - t.Errorf("got rekey after %dG read, want 64G", rgb) - } - if wgb != 64 { - t.Errorf("got rekey after %dG write, want 64G", wgb) - } -} diff --git a/vendor/golang.org/x/crypto/ssh/kex_test.go b/vendor/golang.org/x/crypto/ssh/kex_test.go deleted file mode 100644 index 12ca0acd..00000000 --- a/vendor/golang.org/x/crypto/ssh/kex_test.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ssh - -// Key exchange tests. - -import ( - "crypto/rand" - "reflect" - "testing" -) - -func TestKexes(t *testing.T) { - type kexResultErr struct { - result *kexResult - err error - } - - for name, kex := range kexAlgoMap { - a, b := memPipe() - - s := make(chan kexResultErr, 1) - c := make(chan kexResultErr, 1) - var magics handshakeMagics - go func() { - r, e := kex.Client(a, rand.Reader, &magics) - a.Close() - c <- kexResultErr{r, e} - }() - go func() { - r, e := kex.Server(b, rand.Reader, &magics, testSigners["ecdsa"]) - b.Close() - s <- kexResultErr{r, e} - }() - - clientRes := <-c - serverRes := <-s - if clientRes.err != nil { - t.Errorf("client: %v", clientRes.err) - } - if serverRes.err != nil { - t.Errorf("server: %v", serverRes.err) - } - if !reflect.DeepEqual(clientRes.result, serverRes.result) { - t.Errorf("kex %q: mismatch %#v, %#v", name, clientRes.result, serverRes.result) - } - } -} diff --git a/vendor/golang.org/x/crypto/ssh/keys_test.go b/vendor/golang.org/x/crypto/ssh/keys_test.go deleted file mode 100644 index 3847b3bf..00000000 --- a/vendor/golang.org/x/crypto/ssh/keys_test.go +++ /dev/null @@ -1,574 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ssh - -import ( - "bytes" - "crypto/dsa" - "crypto/ecdsa" - "crypto/elliptic" - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "encoding/base64" - "encoding/pem" - "fmt" - "io" - "reflect" - "strings" - "testing" - - "golang.org/x/crypto/ed25519" - "golang.org/x/crypto/ssh/testdata" -) - -func rawKey(pub PublicKey) interface{} { - switch k := pub.(type) { - case *rsaPublicKey: - return (*rsa.PublicKey)(k) - case *dsaPublicKey: - return (*dsa.PublicKey)(k) - case *ecdsaPublicKey: - return (*ecdsa.PublicKey)(k) - case ed25519PublicKey: - return (ed25519.PublicKey)(k) - case *Certificate: - return k - } - panic("unknown key type") -} - -func TestKeyMarshalParse(t *testing.T) { - for _, priv := range testSigners { - pub := priv.PublicKey() - roundtrip, err := ParsePublicKey(pub.Marshal()) - if err != nil { - t.Errorf("ParsePublicKey(%T): %v", pub, err) - } - - k1 := rawKey(pub) - k2 := rawKey(roundtrip) - - if !reflect.DeepEqual(k1, k2) { - t.Errorf("got %#v in roundtrip, want %#v", k2, k1) - } - } -} - -func TestUnsupportedCurves(t *testing.T) { - raw, err := ecdsa.GenerateKey(elliptic.P224(), rand.Reader) - if err != nil { - t.Fatalf("GenerateKey: %v", err) - } - - if _, err = NewSignerFromKey(raw); err == nil || !strings.Contains(err.Error(), "only P-256") { - t.Fatalf("NewPrivateKey should not succeed with P-224, got: %v", err) - } - - if _, err = NewPublicKey(&raw.PublicKey); err == nil || !strings.Contains(err.Error(), "only P-256") { - t.Fatalf("NewPublicKey should not succeed with P-224, got: %v", err) - } -} - -func TestNewPublicKey(t *testing.T) { - for _, k := range testSigners { - raw := rawKey(k.PublicKey()) - // Skip certificates, as NewPublicKey does not support them. - if _, ok := raw.(*Certificate); ok { - continue - } - pub, err := NewPublicKey(raw) - if err != nil { - t.Errorf("NewPublicKey(%#v): %v", raw, err) - } - if !reflect.DeepEqual(k.PublicKey(), pub) { - t.Errorf("NewPublicKey(%#v) = %#v, want %#v", raw, pub, k.PublicKey()) - } - } -} - -func TestKeySignVerify(t *testing.T) { - for _, priv := range testSigners { - pub := priv.PublicKey() - - data := []byte("sign me") - sig, err := priv.Sign(rand.Reader, data) - if err != nil { - t.Fatalf("Sign(%T): %v", priv, err) - } - - if err := pub.Verify(data, sig); err != nil { - t.Errorf("publicKey.Verify(%T): %v", priv, err) - } - sig.Blob[5]++ - if err := pub.Verify(data, sig); err == nil { - t.Errorf("publicKey.Verify on broken sig did not fail") - } - } -} - -func TestKeySignWithAlgorithmVerify(t *testing.T) { - for _, priv := range testSigners { - if algorithmSigner, ok := priv.(AlgorithmSigner); !ok { - t.Errorf("Signers constructed by ssh package should always implement the AlgorithmSigner interface: %T", priv) - } else { - pub := priv.PublicKey() - data := []byte("sign me") - - signWithAlgTestCase := func(algorithm string, expectedAlg string) { - sig, err := algorithmSigner.SignWithAlgorithm(rand.Reader, data, algorithm) - if err != nil { - t.Fatalf("Sign(%T): %v", priv, err) - } - if sig.Format != expectedAlg { - t.Errorf("signature format did not match requested signature algorithm: %s != %s", sig.Format, expectedAlg) - } - - if err := pub.Verify(data, sig); err != nil { - t.Errorf("publicKey.Verify(%T): %v", priv, err) - } - sig.Blob[5]++ - if err := pub.Verify(data, sig); err == nil { - t.Errorf("publicKey.Verify on broken sig did not fail") - } - } - - // Using the empty string as the algorithm name should result in the same signature format as the algorithm-free Sign method. - defaultSig, err := priv.Sign(rand.Reader, data) - if err != nil { - t.Fatalf("Sign(%T): %v", priv, err) - } - signWithAlgTestCase("", defaultSig.Format) - - // RSA keys are the only ones which currently support more than one signing algorithm - if pub.Type() == KeyAlgoRSA { - for _, algorithm := range []string{SigAlgoRSA, SigAlgoRSASHA2256, SigAlgoRSASHA2512} { - signWithAlgTestCase(algorithm, algorithm) - } - } - } - } -} - -func TestParseRSAPrivateKey(t *testing.T) { - key := testPrivateKeys["rsa"] - - rsa, ok := key.(*rsa.PrivateKey) - if !ok { - t.Fatalf("got %T, want *rsa.PrivateKey", rsa) - } - - if err := rsa.Validate(); err != nil { - t.Errorf("Validate: %v", err) - } -} - -func TestParseECPrivateKey(t *testing.T) { - key := testPrivateKeys["ecdsa"] - - ecKey, ok := key.(*ecdsa.PrivateKey) - if !ok { - t.Fatalf("got %T, want *ecdsa.PrivateKey", ecKey) - } - - if !validateECPublicKey(ecKey.Curve, ecKey.X, ecKey.Y) { - t.Fatalf("public key does not validate.") - } -} - -// See Issue https://github.com/golang/go/issues/6650. -func TestParseEncryptedPrivateKeysFails(t *testing.T) { - const wantSubstring = "encrypted" - for i, tt := range testdata.PEMEncryptedKeys { - _, err := ParsePrivateKey(tt.PEMBytes) - if err == nil { - t.Errorf("#%d key %s: ParsePrivateKey successfully parsed, expected an error", i, tt.Name) - continue - } - - if !strings.Contains(err.Error(), wantSubstring) { - t.Errorf("#%d key %s: got error %q, want substring %q", i, tt.Name, err, wantSubstring) - } - } -} - -// Parse encrypted private keys with passphrase -func TestParseEncryptedPrivateKeysWithPassphrase(t *testing.T) { - data := []byte("sign me") - for _, tt := range testdata.PEMEncryptedKeys { - s, err := ParsePrivateKeyWithPassphrase(tt.PEMBytes, []byte(tt.EncryptionKey)) - if err != nil { - t.Fatalf("ParsePrivateKeyWithPassphrase returned error: %s", err) - continue - } - sig, err := s.Sign(rand.Reader, data) - if err != nil { - t.Fatalf("dsa.Sign: %v", err) - } - if err := s.PublicKey().Verify(data, sig); err != nil { - t.Errorf("Verify failed: %v", err) - } - } - - tt := testdata.PEMEncryptedKeys[0] - _, err := ParsePrivateKeyWithPassphrase(tt.PEMBytes, []byte("incorrect")) - if err != x509.IncorrectPasswordError { - t.Fatalf("got %v want IncorrectPasswordError", err) - } -} - -func TestParseDSA(t *testing.T) { - // We actually exercise the ParsePrivateKey codepath here, as opposed to - // using the ParseRawPrivateKey+NewSignerFromKey path that testdata_test.go - // uses. - s, err := ParsePrivateKey(testdata.PEMBytes["dsa"]) - if err != nil { - t.Fatalf("ParsePrivateKey returned error: %s", err) - } - - data := []byte("sign me") - sig, err := s.Sign(rand.Reader, data) - if err != nil { - t.Fatalf("dsa.Sign: %v", err) - } - - if err := s.PublicKey().Verify(data, sig); err != nil { - t.Errorf("Verify failed: %v", err) - } -} - -// Tests for authorized_keys parsing. - -// getTestKey returns a public key, and its base64 encoding. -func getTestKey() (PublicKey, string) { - k := testPublicKeys["rsa"] - - b := &bytes.Buffer{} - e := base64.NewEncoder(base64.StdEncoding, b) - e.Write(k.Marshal()) - e.Close() - - return k, b.String() -} - -func TestMarshalParsePublicKey(t *testing.T) { - pub, pubSerialized := getTestKey() - line := fmt.Sprintf("%s %s user@host", pub.Type(), pubSerialized) - - authKeys := MarshalAuthorizedKey(pub) - actualFields := strings.Fields(string(authKeys)) - if len(actualFields) == 0 { - t.Fatalf("failed authKeys: %v", authKeys) - } - - // drop the comment - expectedFields := strings.Fields(line)[0:2] - - if !reflect.DeepEqual(actualFields, expectedFields) { - t.Errorf("got %v, expected %v", actualFields, expectedFields) - } - - actPub, _, _, _, err := ParseAuthorizedKey([]byte(line)) - if err != nil { - t.Fatalf("cannot parse %v: %v", line, err) - } - if !reflect.DeepEqual(actPub, pub) { - t.Errorf("got %v, expected %v", actPub, pub) - } -} - -type testAuthResult struct { - pubKey PublicKey - options []string - comments string - rest string - ok bool -} - -func testAuthorizedKeys(t *testing.T, authKeys []byte, expected []testAuthResult) { - rest := authKeys - var values []testAuthResult - for len(rest) > 0 { - var r testAuthResult - var err error - r.pubKey, r.comments, r.options, rest, err = ParseAuthorizedKey(rest) - r.ok = (err == nil) - t.Log(err) - r.rest = string(rest) - values = append(values, r) - } - - if !reflect.DeepEqual(values, expected) { - t.Errorf("got %#v, expected %#v", values, expected) - } -} - -func TestAuthorizedKeyBasic(t *testing.T) { - pub, pubSerialized := getTestKey() - line := "ssh-rsa " + pubSerialized + " user@host" - testAuthorizedKeys(t, []byte(line), - []testAuthResult{ - {pub, nil, "user@host", "", true}, - }) -} - -func TestAuth(t *testing.T) { - pub, pubSerialized := getTestKey() - authWithOptions := []string{ - `# comments to ignore before any keys...`, - ``, - `env="HOME=/home/root",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`, - `# comments to ignore, along with a blank line`, - ``, - `env="HOME=/home/root2" ssh-rsa ` + pubSerialized + ` user2@host2`, - ``, - `# more comments, plus a invalid entry`, - `ssh-rsa data-that-will-not-parse user@host3`, - } - for _, eol := range []string{"\n", "\r\n"} { - authOptions := strings.Join(authWithOptions, eol) - rest2 := strings.Join(authWithOptions[3:], eol) - rest3 := strings.Join(authWithOptions[6:], eol) - testAuthorizedKeys(t, []byte(authOptions), []testAuthResult{ - {pub, []string{`env="HOME=/home/root"`, "no-port-forwarding"}, "user@host", rest2, true}, - {pub, []string{`env="HOME=/home/root2"`}, "user2@host2", rest3, true}, - {nil, nil, "", "", false}, - }) - } -} - -func TestAuthWithQuotedSpaceInEnv(t *testing.T) { - pub, pubSerialized := getTestKey() - authWithQuotedSpaceInEnv := []byte(`env="HOME=/home/root dir",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`) - testAuthorizedKeys(t, []byte(authWithQuotedSpaceInEnv), []testAuthResult{ - {pub, []string{`env="HOME=/home/root dir"`, "no-port-forwarding"}, "user@host", "", true}, - }) -} - -func TestAuthWithQuotedCommaInEnv(t *testing.T) { - pub, pubSerialized := getTestKey() - authWithQuotedCommaInEnv := []byte(`env="HOME=/home/root,dir",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`) - testAuthorizedKeys(t, []byte(authWithQuotedCommaInEnv), []testAuthResult{ - {pub, []string{`env="HOME=/home/root,dir"`, "no-port-forwarding"}, "user@host", "", true}, - }) -} - -func TestAuthWithQuotedQuoteInEnv(t *testing.T) { - pub, pubSerialized := getTestKey() - authWithQuotedQuoteInEnv := []byte(`env="HOME=/home/\"root dir",no-port-forwarding` + "\t" + `ssh-rsa` + "\t" + pubSerialized + ` user@host`) - authWithDoubleQuotedQuote := []byte(`no-port-forwarding,env="HOME=/home/ \"root dir\"" ssh-rsa ` + pubSerialized + "\t" + `user@host`) - testAuthorizedKeys(t, []byte(authWithQuotedQuoteInEnv), []testAuthResult{ - {pub, []string{`env="HOME=/home/\"root dir"`, "no-port-forwarding"}, "user@host", "", true}, - }) - - testAuthorizedKeys(t, []byte(authWithDoubleQuotedQuote), []testAuthResult{ - {pub, []string{"no-port-forwarding", `env="HOME=/home/ \"root dir\""`}, "user@host", "", true}, - }) -} - -func TestAuthWithInvalidSpace(t *testing.T) { - _, pubSerialized := getTestKey() - authWithInvalidSpace := []byte(`env="HOME=/home/root dir", no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host -#more to follow but still no valid keys`) - testAuthorizedKeys(t, []byte(authWithInvalidSpace), []testAuthResult{ - {nil, nil, "", "", false}, - }) -} - -func TestAuthWithMissingQuote(t *testing.T) { - pub, pubSerialized := getTestKey() - authWithMissingQuote := []byte(`env="HOME=/home/root,no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host -env="HOME=/home/root",shared-control ssh-rsa ` + pubSerialized + ` user@host`) - - testAuthorizedKeys(t, []byte(authWithMissingQuote), []testAuthResult{ - {pub, []string{`env="HOME=/home/root"`, `shared-control`}, "user@host", "", true}, - }) -} - -func TestInvalidEntry(t *testing.T) { - authInvalid := []byte(`ssh-rsa`) - _, _, _, _, err := ParseAuthorizedKey(authInvalid) - if err == nil { - t.Errorf("got valid entry for %q", authInvalid) - } -} - -var knownHostsParseTests = []struct { - input string - err string - - marker string - comment string - hosts []string - rest string -}{ - { - "", - "EOF", - - "", "", nil, "", - }, - { - "# Just a comment", - "EOF", - - "", "", nil, "", - }, - { - " \t ", - "EOF", - - "", "", nil, "", - }, - { - "localhost ssh-rsa {RSAPUB}", - "", - - "", "", []string{"localhost"}, "", - }, - { - "localhost\tssh-rsa {RSAPUB}", - "", - - "", "", []string{"localhost"}, "", - }, - { - "localhost\tssh-rsa {RSAPUB}\tcomment comment", - "", - - "", "comment comment", []string{"localhost"}, "", - }, - { - "localhost\tssh-rsa {RSAPUB}\tcomment comment\n", - "", - - "", "comment comment", []string{"localhost"}, "", - }, - { - "localhost\tssh-rsa {RSAPUB}\tcomment comment\r\n", - "", - - "", "comment comment", []string{"localhost"}, "", - }, - { - "localhost\tssh-rsa {RSAPUB}\tcomment comment\r\nnext line", - "", - - "", "comment comment", []string{"localhost"}, "next line", - }, - { - "localhost,[host2:123]\tssh-rsa {RSAPUB}\tcomment comment", - "", - - "", "comment comment", []string{"localhost", "[host2:123]"}, "", - }, - { - "@marker \tlocalhost,[host2:123]\tssh-rsa {RSAPUB}", - "", - - "marker", "", []string{"localhost", "[host2:123]"}, "", - }, - { - "@marker \tlocalhost,[host2:123]\tssh-rsa aabbccdd", - "short read", - - "", "", nil, "", - }, -} - -func TestKnownHostsParsing(t *testing.T) { - rsaPub, rsaPubSerialized := getTestKey() - - for i, test := range knownHostsParseTests { - var expectedKey PublicKey - const rsaKeyToken = "{RSAPUB}" - - input := test.input - if strings.Contains(input, rsaKeyToken) { - expectedKey = rsaPub - input = strings.Replace(test.input, rsaKeyToken, rsaPubSerialized, -1) - } - - marker, hosts, pubKey, comment, rest, err := ParseKnownHosts([]byte(input)) - if err != nil { - if len(test.err) == 0 { - t.Errorf("#%d: unexpectedly failed with %q", i, err) - } else if !strings.Contains(err.Error(), test.err) { - t.Errorf("#%d: expected error containing %q, but got %q", i, test.err, err) - } - continue - } else if len(test.err) != 0 { - t.Errorf("#%d: succeeded but expected error including %q", i, test.err) - continue - } - - if !reflect.DeepEqual(expectedKey, pubKey) { - t.Errorf("#%d: expected key %#v, but got %#v", i, expectedKey, pubKey) - } - - if marker != test.marker { - t.Errorf("#%d: expected marker %q, but got %q", i, test.marker, marker) - } - - if comment != test.comment { - t.Errorf("#%d: expected comment %q, but got %q", i, test.comment, comment) - } - - if !reflect.DeepEqual(test.hosts, hosts) { - t.Errorf("#%d: expected hosts %#v, but got %#v", i, test.hosts, hosts) - } - - if rest := string(rest); rest != test.rest { - t.Errorf("#%d: expected remaining input to be %q, but got %q", i, test.rest, rest) - } - } -} - -func TestFingerprintLegacyMD5(t *testing.T) { - pub, _ := getTestKey() - fingerprint := FingerprintLegacyMD5(pub) - want := "fb:61:6d:1a:e3:f0:95:45:3c:a0:79:be:4a:93:63:66" // ssh-keygen -lf -E md5 rsa - if fingerprint != want { - t.Errorf("got fingerprint %q want %q", fingerprint, want) - } -} - -func TestFingerprintSHA256(t *testing.T) { - pub, _ := getTestKey() - fingerprint := FingerprintSHA256(pub) - want := "SHA256:Anr3LjZK8YVpjrxu79myrW9Hrb/wpcMNpVvTq/RcBm8" // ssh-keygen -lf rsa - if fingerprint != want { - t.Errorf("got fingerprint %q want %q", fingerprint, want) - } -} - -func TestInvalidKeys(t *testing.T) { - keyTypes := []string{ - "RSA PRIVATE KEY", - "PRIVATE KEY", - "EC PRIVATE KEY", - "DSA PRIVATE KEY", - "OPENSSH PRIVATE KEY", - } - - for _, keyType := range keyTypes { - for _, dataLen := range []int{0, 1, 2, 5, 10, 20} { - data := make([]byte, dataLen) - if _, err := io.ReadFull(rand.Reader, data); err != nil { - t.Fatal(err) - } - - var buf bytes.Buffer - pem.Encode(&buf, &pem.Block{ - Type: keyType, - Bytes: data, - }) - - // This test is just to ensure that the function - // doesn't panic so the return value is ignored. - ParseRawPrivateKey(buf.Bytes()) - } - } -} diff --git a/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts_test.go b/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts_test.go deleted file mode 100644 index 464dd592..00000000 --- a/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts_test.go +++ /dev/null @@ -1,356 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package knownhosts - -import ( - "bytes" - "fmt" - "net" - "reflect" - "testing" - - "golang.org/x/crypto/ssh" -) - -const edKeyStr = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGBAarftlLeoyf+v+nVchEZII/vna2PCV8FaX4vsF5BX" -const alternateEdKeyStr = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIXffBYeYL+WVzVru8npl5JHt2cjlr4ornFTWzoij9sx" -const ecKeyStr = "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNLCu01+wpXe3xB5olXCN4SqU2rQu0qjSRKJO4Bg+JRCPU+ENcgdA5srTU8xYDz/GEa4dzK5ldPw4J/gZgSXCMs=" - -var ecKey, alternateEdKey, edKey ssh.PublicKey -var testAddr = &net.TCPAddr{ - IP: net.IP{198, 41, 30, 196}, - Port: 22, -} - -var testAddr6 = &net.TCPAddr{ - IP: net.IP{198, 41, 30, 196, - 1, 2, 3, 4, - 1, 2, 3, 4, - 1, 2, 3, 4, - }, - Port: 22, -} - -func init() { - var err error - ecKey, _, _, _, err = ssh.ParseAuthorizedKey([]byte(ecKeyStr)) - if err != nil { - panic(err) - } - edKey, _, _, _, err = ssh.ParseAuthorizedKey([]byte(edKeyStr)) - if err != nil { - panic(err) - } - alternateEdKey, _, _, _, err = ssh.ParseAuthorizedKey([]byte(alternateEdKeyStr)) - if err != nil { - panic(err) - } -} - -func testDB(t *testing.T, s string) *hostKeyDB { - db := newHostKeyDB() - if err := db.Read(bytes.NewBufferString(s), "testdb"); err != nil { - t.Fatalf("Read: %v", err) - } - - return db -} - -func TestRevoked(t *testing.T) { - db := testDB(t, "\n\n@revoked * "+edKeyStr+"\n") - want := &RevokedError{ - Revoked: KnownKey{ - Key: edKey, - Filename: "testdb", - Line: 3, - }, - } - if err := db.check("", &net.TCPAddr{ - Port: 42, - }, edKey); err == nil { - t.Fatal("no error for revoked key") - } else if !reflect.DeepEqual(want, err) { - t.Fatalf("got %#v, want %#v", want, err) - } -} - -func TestHostAuthority(t *testing.T) { - for _, m := range []struct { - authorityFor string - address string - - good bool - }{ - {authorityFor: "localhost", address: "localhost:22", good: true}, - {authorityFor: "localhost", address: "localhost", good: false}, - {authorityFor: "localhost", address: "localhost:1234", good: false}, - {authorityFor: "[localhost]:1234", address: "localhost:1234", good: true}, - {authorityFor: "[localhost]:1234", address: "localhost:22", good: false}, - {authorityFor: "[localhost]:1234", address: "localhost", good: false}, - } { - db := testDB(t, `@cert-authority `+m.authorityFor+` `+edKeyStr) - if ok := db.IsHostAuthority(db.lines[0].knownKey.Key, m.address); ok != m.good { - t.Errorf("IsHostAuthority: authority %s, address %s, wanted good = %v, got good = %v", - m.authorityFor, m.address, m.good, ok) - } - } -} - -func TestBracket(t *testing.T) { - db := testDB(t, `[git.eclipse.org]:29418,[198.41.30.196]:29418 `+edKeyStr) - - if err := db.check("git.eclipse.org:29418", &net.TCPAddr{ - IP: net.IP{198, 41, 30, 196}, - Port: 29418, - }, edKey); err != nil { - t.Errorf("got error %v, want none", err) - } - - if err := db.check("git.eclipse.org:29419", &net.TCPAddr{ - Port: 42, - }, edKey); err == nil { - t.Fatalf("no error for unknown address") - } else if ke, ok := err.(*KeyError); !ok { - t.Fatalf("got type %T, want *KeyError", err) - } else if len(ke.Want) > 0 { - t.Fatalf("got Want %v, want []", ke.Want) - } -} - -func TestNewKeyType(t *testing.T) { - str := fmt.Sprintf("%s %s", testAddr, edKeyStr) - db := testDB(t, str) - if err := db.check("", testAddr, ecKey); err == nil { - t.Fatalf("no error for unknown address") - } else if ke, ok := err.(*KeyError); !ok { - t.Fatalf("got type %T, want *KeyError", err) - } else if len(ke.Want) == 0 { - t.Fatalf("got empty KeyError.Want") - } -} - -func TestSameKeyType(t *testing.T) { - str := fmt.Sprintf("%s %s", testAddr, edKeyStr) - db := testDB(t, str) - if err := db.check("", testAddr, alternateEdKey); err == nil { - t.Fatalf("no error for unknown address") - } else if ke, ok := err.(*KeyError); !ok { - t.Fatalf("got type %T, want *KeyError", err) - } else if len(ke.Want) == 0 { - t.Fatalf("got empty KeyError.Want") - } else if got, want := ke.Want[0].Key.Marshal(), edKey.Marshal(); !bytes.Equal(got, want) { - t.Fatalf("got key %q, want %q", got, want) - } -} - -func TestIPAddress(t *testing.T) { - str := fmt.Sprintf("%s %s", testAddr, edKeyStr) - db := testDB(t, str) - if err := db.check("", testAddr, edKey); err != nil { - t.Errorf("got error %q, want none", err) - } -} - -func TestIPv6Address(t *testing.T) { - str := fmt.Sprintf("%s %s", testAddr6, edKeyStr) - db := testDB(t, str) - - if err := db.check("", testAddr6, edKey); err != nil { - t.Errorf("got error %q, want none", err) - } -} - -func TestBasic(t *testing.T) { - str := fmt.Sprintf("#comment\n\nserver.org,%s %s\notherhost %s", testAddr, edKeyStr, ecKeyStr) - db := testDB(t, str) - if err := db.check("server.org:22", testAddr, edKey); err != nil { - t.Errorf("got error %v, want none", err) - } - - want := KnownKey{ - Key: edKey, - Filename: "testdb", - Line: 3, - } - if err := db.check("server.org:22", testAddr, ecKey); err == nil { - t.Errorf("succeeded, want KeyError") - } else if ke, ok := err.(*KeyError); !ok { - t.Errorf("got %T, want *KeyError", err) - } else if len(ke.Want) != 1 { - t.Errorf("got %v, want 1 entry", ke) - } else if !reflect.DeepEqual(ke.Want[0], want) { - t.Errorf("got %v, want %v", ke.Want[0], want) - } -} - -func TestHostNamePrecedence(t *testing.T) { - var evilAddr = &net.TCPAddr{ - IP: net.IP{66, 66, 66, 66}, - Port: 22, - } - - str := fmt.Sprintf("server.org,%s %s\nevil.org,%s %s", testAddr, edKeyStr, evilAddr, ecKeyStr) - db := testDB(t, str) - - if err := db.check("server.org:22", evilAddr, ecKey); err == nil { - t.Errorf("check succeeded") - } else if _, ok := err.(*KeyError); !ok { - t.Errorf("got %T, want *KeyError", err) - } -} - -func TestDBOrderingPrecedenceKeyType(t *testing.T) { - str := fmt.Sprintf("server.org,%s %s\nserver.org,%s %s", testAddr, edKeyStr, testAddr, alternateEdKeyStr) - db := testDB(t, str) - - if err := db.check("server.org:22", testAddr, alternateEdKey); err == nil { - t.Errorf("check succeeded") - } else if _, ok := err.(*KeyError); !ok { - t.Errorf("got %T, want *KeyError", err) - } -} - -func TestNegate(t *testing.T) { - str := fmt.Sprintf("%s,!server.org %s", testAddr, edKeyStr) - db := testDB(t, str) - if err := db.check("server.org:22", testAddr, ecKey); err == nil { - t.Errorf("succeeded") - } else if ke, ok := err.(*KeyError); !ok { - t.Errorf("got error type %T, want *KeyError", err) - } else if len(ke.Want) != 0 { - t.Errorf("got expected keys %d (first of type %s), want []", len(ke.Want), ke.Want[0].Key.Type()) - } -} - -func TestWildcard(t *testing.T) { - str := fmt.Sprintf("server*.domain %s", edKeyStr) - db := testDB(t, str) - - want := &KeyError{ - Want: []KnownKey{{ - Filename: "testdb", - Line: 1, - Key: edKey, - }}, - } - - got := db.check("server.domain:22", &net.TCPAddr{}, ecKey) - if !reflect.DeepEqual(got, want) { - t.Errorf("got %s, want %s", got, want) - } -} - -func TestLine(t *testing.T) { - for in, want := range map[string]string{ - "server.org": "server.org " + edKeyStr, - "server.org:22": "server.org " + edKeyStr, - "server.org:23": "[server.org]:23 " + edKeyStr, - "[c629:1ec4:102:304:102:304:102:304]:22": "[c629:1ec4:102:304:102:304:102:304] " + edKeyStr, - "[c629:1ec4:102:304:102:304:102:304]:23": "[c629:1ec4:102:304:102:304:102:304]:23 " + edKeyStr, - } { - if got := Line([]string{in}, edKey); got != want { - t.Errorf("Line(%q) = %q, want %q", in, got, want) - } - } -} - -func TestWildcardMatch(t *testing.T) { - for _, c := range []struct { - pat, str string - want bool - }{ - {"a?b", "abb", true}, - {"ab", "abc", false}, - {"abc", "ab", false}, - {"a*b", "axxxb", true}, - {"a*b", "axbxb", true}, - {"a*b", "axbxbc", false}, - {"a*?", "axbxc", true}, - {"a*b*", "axxbxxxxxx", true}, - {"a*b*c", "axxbxxxxxxc", true}, - {"a*b*?", "axxbxxxxxxc", true}, - {"a*b*z", "axxbxxbxxxz", true}, - {"a*b*z", "axxbxxzxxxz", true}, - {"a*b*z", "axxbxxzxxx", false}, - } { - got := wildcardMatch([]byte(c.pat), []byte(c.str)) - if got != c.want { - t.Errorf("wildcardMatch(%q, %q) = %v, want %v", c.pat, c.str, got, c.want) - } - - } -} - -// TODO(hanwen): test coverage for certificates. - -const testHostname = "hostname" - -// generated with keygen -H -f -const encodedTestHostnameHash = "|1|IHXZvQMvTcZTUU29+2vXFgx8Frs=|UGccIWfRVDwilMBnA3WJoRAC75Y=" - -func TestHostHash(t *testing.T) { - testHostHash(t, testHostname, encodedTestHostnameHash) -} - -func TestHashList(t *testing.T) { - encoded := HashHostname(testHostname) - testHostHash(t, testHostname, encoded) -} - -func testHostHash(t *testing.T, hostname, encoded string) { - typ, salt, hash, err := decodeHash(encoded) - if err != nil { - t.Fatalf("decodeHash: %v", err) - } - - if got := encodeHash(typ, salt, hash); got != encoded { - t.Errorf("got encoding %s want %s", got, encoded) - } - - if typ != sha1HashType { - t.Fatalf("got hash type %q, want %q", typ, sha1HashType) - } - - got := hashHost(hostname, salt) - if !bytes.Equal(got, hash) { - t.Errorf("got hash %x want %x", got, hash) - } -} - -func TestNormalize(t *testing.T) { - for in, want := range map[string]string{ - "127.0.0.1:22": "127.0.0.1", - "[127.0.0.1]:22": "127.0.0.1", - "[127.0.0.1]:23": "[127.0.0.1]:23", - "127.0.0.1:23": "[127.0.0.1]:23", - "[a.b.c]:22": "a.b.c", - "[abcd:abcd:abcd:abcd]": "[abcd:abcd:abcd:abcd]", - "[abcd:abcd:abcd:abcd]:22": "[abcd:abcd:abcd:abcd]", - "[abcd:abcd:abcd:abcd]:23": "[abcd:abcd:abcd:abcd]:23", - } { - got := Normalize(in) - if got != want { - t.Errorf("Normalize(%q) = %q, want %q", in, got, want) - } - } -} - -func TestHashedHostkeyCheck(t *testing.T) { - str := fmt.Sprintf("%s %s", HashHostname(testHostname), edKeyStr) - db := testDB(t, str) - if err := db.check(testHostname+":22", testAddr, edKey); err != nil { - t.Errorf("check(%s): %v", testHostname, err) - } - want := &KeyError{ - Want: []KnownKey{{ - Filename: "testdb", - Line: 1, - Key: edKey, - }}, - } - if got := db.check(testHostname+":22", testAddr, alternateEdKey); !reflect.DeepEqual(got, want) { - t.Errorf("got error %v, want %v", got, want) - } -} diff --git a/vendor/golang.org/x/crypto/ssh/mempipe_test.go b/vendor/golang.org/x/crypto/ssh/mempipe_test.go deleted file mode 100644 index 8697cd61..00000000 --- a/vendor/golang.org/x/crypto/ssh/mempipe_test.go +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ssh - -import ( - "io" - "sync" - "testing" -) - -// An in-memory packetConn. It is safe to call Close and writePacket -// from different goroutines. -type memTransport struct { - eof bool - pending [][]byte - write *memTransport - sync.Mutex - *sync.Cond -} - -func (t *memTransport) readPacket() ([]byte, error) { - t.Lock() - defer t.Unlock() - for { - if len(t.pending) > 0 { - r := t.pending[0] - t.pending = t.pending[1:] - return r, nil - } - if t.eof { - return nil, io.EOF - } - t.Cond.Wait() - } -} - -func (t *memTransport) closeSelf() error { - t.Lock() - defer t.Unlock() - if t.eof { - return io.EOF - } - t.eof = true - t.Cond.Broadcast() - return nil -} - -func (t *memTransport) Close() error { - err := t.write.closeSelf() - t.closeSelf() - return err -} - -func (t *memTransport) writePacket(p []byte) error { - t.write.Lock() - defer t.write.Unlock() - if t.write.eof { - return io.EOF - } - c := make([]byte, len(p)) - copy(c, p) - t.write.pending = append(t.write.pending, c) - t.write.Cond.Signal() - return nil -} - -func memPipe() (a, b packetConn) { - t1 := memTransport{} - t2 := memTransport{} - t1.write = &t2 - t2.write = &t1 - t1.Cond = sync.NewCond(&t1.Mutex) - t2.Cond = sync.NewCond(&t2.Mutex) - return &t1, &t2 -} - -func TestMemPipe(t *testing.T) { - a, b := memPipe() - if err := a.writePacket([]byte{42}); err != nil { - t.Fatalf("writePacket: %v", err) - } - if err := a.Close(); err != nil { - t.Fatal("Close: ", err) - } - p, err := b.readPacket() - if err != nil { - t.Fatal("readPacket: ", err) - } - if len(p) != 1 || p[0] != 42 { - t.Fatalf("got %v, want {42}", p) - } - p, err = b.readPacket() - if err != io.EOF { - t.Fatalf("got %v, %v, want EOF", p, err) - } -} - -func TestDoubleClose(t *testing.T) { - a, _ := memPipe() - err := a.Close() - if err != nil { - t.Errorf("Close: %v", err) - } - err = a.Close() - if err != io.EOF { - t.Errorf("expect EOF on double close.") - } -} diff --git a/vendor/golang.org/x/crypto/ssh/messages_test.go b/vendor/golang.org/x/crypto/ssh/messages_test.go deleted file mode 100644 index e7907641..00000000 --- a/vendor/golang.org/x/crypto/ssh/messages_test.go +++ /dev/null @@ -1,288 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ssh - -import ( - "bytes" - "math/big" - "math/rand" - "reflect" - "testing" - "testing/quick" -) - -var intLengthTests = []struct { - val, length int -}{ - {0, 4 + 0}, - {1, 4 + 1}, - {127, 4 + 1}, - {128, 4 + 2}, - {-1, 4 + 1}, -} - -func TestIntLength(t *testing.T) { - for _, test := range intLengthTests { - v := new(big.Int).SetInt64(int64(test.val)) - length := intLength(v) - if length != test.length { - t.Errorf("For %d, got length %d but expected %d", test.val, length, test.length) - } - } -} - -type msgAllTypes struct { - Bool bool `sshtype:"21"` - Array [16]byte - Uint64 uint64 - Uint32 uint32 - Uint8 uint8 - String string - Strings []string - Bytes []byte - Int *big.Int - Rest []byte `ssh:"rest"` -} - -func (t *msgAllTypes) Generate(rand *rand.Rand, size int) reflect.Value { - m := &msgAllTypes{} - m.Bool = rand.Intn(2) == 1 - randomBytes(m.Array[:], rand) - m.Uint64 = uint64(rand.Int63n(1<<63 - 1)) - m.Uint32 = uint32(rand.Intn((1 << 31) - 1)) - m.Uint8 = uint8(rand.Intn(1 << 8)) - m.String = string(m.Array[:]) - m.Strings = randomNameList(rand) - m.Bytes = m.Array[:] - m.Int = randomInt(rand) - m.Rest = m.Array[:] - return reflect.ValueOf(m) -} - -func TestMarshalUnmarshal(t *testing.T) { - rand := rand.New(rand.NewSource(0)) - iface := &msgAllTypes{} - ty := reflect.ValueOf(iface).Type() - - n := 100 - if testing.Short() { - n = 5 - } - for j := 0; j < n; j++ { - v, ok := quick.Value(ty, rand) - if !ok { - t.Errorf("failed to create value") - break - } - - m1 := v.Elem().Interface() - m2 := iface - - marshaled := Marshal(m1) - if err := Unmarshal(marshaled, m2); err != nil { - t.Errorf("Unmarshal %#v: %s", m1, err) - break - } - - if !reflect.DeepEqual(v.Interface(), m2) { - t.Errorf("got: %#v\nwant:%#v\n%x", m2, m1, marshaled) - break - } - } -} - -func TestUnmarshalEmptyPacket(t *testing.T) { - var b []byte - var m channelRequestSuccessMsg - if err := Unmarshal(b, &m); err == nil { - t.Fatalf("unmarshal of empty slice succeeded") - } -} - -func TestUnmarshalUnexpectedPacket(t *testing.T) { - type S struct { - I uint32 `sshtype:"43"` - S string - B bool - } - - s := S{11, "hello", true} - packet := Marshal(s) - packet[0] = 42 - roundtrip := S{} - err := Unmarshal(packet, &roundtrip) - if err == nil { - t.Fatal("expected error, not nil") - } -} - -func TestMarshalPtr(t *testing.T) { - s := struct { - S string - }{"hello"} - - m1 := Marshal(s) - m2 := Marshal(&s) - if !bytes.Equal(m1, m2) { - t.Errorf("got %q, want %q for marshaled pointer", m2, m1) - } -} - -func TestBareMarshalUnmarshal(t *testing.T) { - type S struct { - I uint32 - S string - B bool - } - - s := S{42, "hello", true} - packet := Marshal(s) - roundtrip := S{} - Unmarshal(packet, &roundtrip) - - if !reflect.DeepEqual(s, roundtrip) { - t.Errorf("got %#v, want %#v", roundtrip, s) - } -} - -func TestBareMarshal(t *testing.T) { - type S2 struct { - I uint32 - } - s := S2{42} - packet := Marshal(s) - i, rest, ok := parseUint32(packet) - if len(rest) > 0 || !ok { - t.Errorf("parseInt(%q): parse error", packet) - } - if i != s.I { - t.Errorf("got %d, want %d", i, s.I) - } -} - -func TestUnmarshalShortKexInitPacket(t *testing.T) { - // This used to panic. - // Issue 11348 - packet := []byte{0x14, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xff, 0xff, 0xff, 0xff} - kim := &kexInitMsg{} - if err := Unmarshal(packet, kim); err == nil { - t.Error("truncated packet unmarshaled without error") - } -} - -func TestMarshalMultiTag(t *testing.T) { - var res struct { - A uint32 `sshtype:"1|2"` - } - - good1 := struct { - A uint32 `sshtype:"1"` - }{ - 1, - } - good2 := struct { - A uint32 `sshtype:"2"` - }{ - 1, - } - - if e := Unmarshal(Marshal(good1), &res); e != nil { - t.Errorf("error unmarshaling multipart tag: %v", e) - } - - if e := Unmarshal(Marshal(good2), &res); e != nil { - t.Errorf("error unmarshaling multipart tag: %v", e) - } - - bad1 := struct { - A uint32 `sshtype:"3"` - }{ - 1, - } - if e := Unmarshal(Marshal(bad1), &res); e == nil { - t.Errorf("bad struct unmarshaled without error") - } -} - -func randomBytes(out []byte, rand *rand.Rand) { - for i := 0; i < len(out); i++ { - out[i] = byte(rand.Int31()) - } -} - -func randomNameList(rand *rand.Rand) []string { - ret := make([]string, rand.Int31()&15) - for i := range ret { - s := make([]byte, 1+(rand.Int31()&15)) - for j := range s { - s[j] = 'a' + uint8(rand.Int31()&15) - } - ret[i] = string(s) - } - return ret -} - -func randomInt(rand *rand.Rand) *big.Int { - return new(big.Int).SetInt64(int64(int32(rand.Uint32()))) -} - -func (*kexInitMsg) Generate(rand *rand.Rand, size int) reflect.Value { - ki := &kexInitMsg{} - randomBytes(ki.Cookie[:], rand) - ki.KexAlgos = randomNameList(rand) - ki.ServerHostKeyAlgos = randomNameList(rand) - ki.CiphersClientServer = randomNameList(rand) - ki.CiphersServerClient = randomNameList(rand) - ki.MACsClientServer = randomNameList(rand) - ki.MACsServerClient = randomNameList(rand) - ki.CompressionClientServer = randomNameList(rand) - ki.CompressionServerClient = randomNameList(rand) - ki.LanguagesClientServer = randomNameList(rand) - ki.LanguagesServerClient = randomNameList(rand) - if rand.Int31()&1 == 1 { - ki.FirstKexFollows = true - } - return reflect.ValueOf(ki) -} - -func (*kexDHInitMsg) Generate(rand *rand.Rand, size int) reflect.Value { - dhi := &kexDHInitMsg{} - dhi.X = randomInt(rand) - return reflect.ValueOf(dhi) -} - -var ( - _kexInitMsg = new(kexInitMsg).Generate(rand.New(rand.NewSource(0)), 10).Elem().Interface() - _kexDHInitMsg = new(kexDHInitMsg).Generate(rand.New(rand.NewSource(0)), 10).Elem().Interface() - - _kexInit = Marshal(_kexInitMsg) - _kexDHInit = Marshal(_kexDHInitMsg) -) - -func BenchmarkMarshalKexInitMsg(b *testing.B) { - for i := 0; i < b.N; i++ { - Marshal(_kexInitMsg) - } -} - -func BenchmarkUnmarshalKexInitMsg(b *testing.B) { - m := new(kexInitMsg) - for i := 0; i < b.N; i++ { - Unmarshal(_kexInit, m) - } -} - -func BenchmarkMarshalKexDHInitMsg(b *testing.B) { - for i := 0; i < b.N; i++ { - Marshal(_kexDHInitMsg) - } -} - -func BenchmarkUnmarshalKexDHInitMsg(b *testing.B) { - m := new(kexDHInitMsg) - for i := 0; i < b.N; i++ { - Unmarshal(_kexDHInit, m) - } -} diff --git a/vendor/golang.org/x/crypto/ssh/mux_test.go b/vendor/golang.org/x/crypto/ssh/mux_test.go deleted file mode 100644 index 94596ec2..00000000 --- a/vendor/golang.org/x/crypto/ssh/mux_test.go +++ /dev/null @@ -1,501 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ssh - -import ( - "io" - "io/ioutil" - "sync" - "testing" -) - -func muxPair() (*mux, *mux) { - a, b := memPipe() - - s := newMux(a) - c := newMux(b) - - return s, c -} - -// Returns both ends of a channel, and the mux for the 2nd -// channel. -func channelPair(t *testing.T) (*channel, *channel, *mux) { - c, s := muxPair() - - res := make(chan *channel, 1) - go func() { - newCh, ok := <-s.incomingChannels - if !ok { - t.Fatalf("No incoming channel") - } - if newCh.ChannelType() != "chan" { - t.Fatalf("got type %q want chan", newCh.ChannelType()) - } - ch, _, err := newCh.Accept() - if err != nil { - t.Fatalf("Accept %v", err) - } - res <- ch.(*channel) - }() - - ch, err := c.openChannel("chan", nil) - if err != nil { - t.Fatalf("OpenChannel: %v", err) - } - - return <-res, ch, c -} - -// Test that stderr and stdout can be addressed from different -// goroutines. This is intended for use with the race detector. -func TestMuxChannelExtendedThreadSafety(t *testing.T) { - writer, reader, mux := channelPair(t) - defer writer.Close() - defer reader.Close() - defer mux.Close() - - var wr, rd sync.WaitGroup - magic := "hello world" - - wr.Add(2) - go func() { - io.WriteString(writer, magic) - wr.Done() - }() - go func() { - io.WriteString(writer.Stderr(), magic) - wr.Done() - }() - - rd.Add(2) - go func() { - c, err := ioutil.ReadAll(reader) - if string(c) != magic { - t.Fatalf("stdout read got %q, want %q (error %s)", c, magic, err) - } - rd.Done() - }() - go func() { - c, err := ioutil.ReadAll(reader.Stderr()) - if string(c) != magic { - t.Fatalf("stderr read got %q, want %q (error %s)", c, magic, err) - } - rd.Done() - }() - - wr.Wait() - writer.CloseWrite() - rd.Wait() -} - -func TestMuxReadWrite(t *testing.T) { - s, c, mux := channelPair(t) - defer s.Close() - defer c.Close() - defer mux.Close() - - magic := "hello world" - magicExt := "hello stderr" - go func() { - _, err := s.Write([]byte(magic)) - if err != nil { - t.Fatalf("Write: %v", err) - } - _, err = s.Extended(1).Write([]byte(magicExt)) - if err != nil { - t.Fatalf("Write: %v", err) - } - }() - - var buf [1024]byte - n, err := c.Read(buf[:]) - if err != nil { - t.Fatalf("server Read: %v", err) - } - got := string(buf[:n]) - if got != magic { - t.Fatalf("server: got %q want %q", got, magic) - } - - n, err = c.Extended(1).Read(buf[:]) - if err != nil { - t.Fatalf("server Read: %v", err) - } - - got = string(buf[:n]) - if got != magicExt { - t.Fatalf("server: got %q want %q", got, magic) - } -} - -func TestMuxChannelOverflow(t *testing.T) { - reader, writer, mux := channelPair(t) - defer reader.Close() - defer writer.Close() - defer mux.Close() - - wDone := make(chan int, 1) - go func() { - if _, err := writer.Write(make([]byte, channelWindowSize)); err != nil { - t.Errorf("could not fill window: %v", err) - } - writer.Write(make([]byte, 1)) - wDone <- 1 - }() - writer.remoteWin.waitWriterBlocked() - - // Send 1 byte. - packet := make([]byte, 1+4+4+1) - packet[0] = msgChannelData - marshalUint32(packet[1:], writer.remoteId) - marshalUint32(packet[5:], uint32(1)) - packet[9] = 42 - - if err := writer.mux.conn.writePacket(packet); err != nil { - t.Errorf("could not send packet") - } - if _, err := reader.SendRequest("hello", true, nil); err == nil { - t.Errorf("SendRequest succeeded.") - } - <-wDone -} - -func TestMuxChannelCloseWriteUnblock(t *testing.T) { - reader, writer, mux := channelPair(t) - defer reader.Close() - defer writer.Close() - defer mux.Close() - - wDone := make(chan int, 1) - go func() { - if _, err := writer.Write(make([]byte, channelWindowSize)); err != nil { - t.Errorf("could not fill window: %v", err) - } - if _, err := writer.Write(make([]byte, 1)); err != io.EOF { - t.Errorf("got %v, want EOF for unblock write", err) - } - wDone <- 1 - }() - - writer.remoteWin.waitWriterBlocked() - reader.Close() - <-wDone -} - -func TestMuxConnectionCloseWriteUnblock(t *testing.T) { - reader, writer, mux := channelPair(t) - defer reader.Close() - defer writer.Close() - defer mux.Close() - - wDone := make(chan int, 1) - go func() { - if _, err := writer.Write(make([]byte, channelWindowSize)); err != nil { - t.Errorf("could not fill window: %v", err) - } - if _, err := writer.Write(make([]byte, 1)); err != io.EOF { - t.Errorf("got %v, want EOF for unblock write", err) - } - wDone <- 1 - }() - - writer.remoteWin.waitWriterBlocked() - mux.Close() - <-wDone -} - -func TestMuxReject(t *testing.T) { - client, server := muxPair() - defer server.Close() - defer client.Close() - - go func() { - ch, ok := <-server.incomingChannels - if !ok { - t.Fatalf("Accept") - } - if ch.ChannelType() != "ch" || string(ch.ExtraData()) != "extra" { - t.Fatalf("unexpected channel: %q, %q", ch.ChannelType(), ch.ExtraData()) - } - ch.Reject(RejectionReason(42), "message") - }() - - ch, err := client.openChannel("ch", []byte("extra")) - if ch != nil { - t.Fatal("openChannel not rejected") - } - - ocf, ok := err.(*OpenChannelError) - if !ok { - t.Errorf("got %#v want *OpenChannelError", err) - } else if ocf.Reason != 42 || ocf.Message != "message" { - t.Errorf("got %#v, want {Reason: 42, Message: %q}", ocf, "message") - } - - want := "ssh: rejected: unknown reason 42 (message)" - if err.Error() != want { - t.Errorf("got %q, want %q", err.Error(), want) - } -} - -func TestMuxChannelRequest(t *testing.T) { - client, server, mux := channelPair(t) - defer server.Close() - defer client.Close() - defer mux.Close() - - var received int - var wg sync.WaitGroup - wg.Add(1) - go func() { - for r := range server.incomingRequests { - received++ - r.Reply(r.Type == "yes", nil) - } - wg.Done() - }() - _, err := client.SendRequest("yes", false, nil) - if err != nil { - t.Fatalf("SendRequest: %v", err) - } - ok, err := client.SendRequest("yes", true, nil) - if err != nil { - t.Fatalf("SendRequest: %v", err) - } - - if !ok { - t.Errorf("SendRequest(yes): %v", ok) - - } - - ok, err = client.SendRequest("no", true, nil) - if err != nil { - t.Fatalf("SendRequest: %v", err) - } - if ok { - t.Errorf("SendRequest(no): %v", ok) - - } - - client.Close() - wg.Wait() - - if received != 3 { - t.Errorf("got %d requests, want %d", received, 3) - } -} - -func TestMuxGlobalRequest(t *testing.T) { - clientMux, serverMux := muxPair() - defer serverMux.Close() - defer clientMux.Close() - - var seen bool - go func() { - for r := range serverMux.incomingRequests { - seen = seen || r.Type == "peek" - if r.WantReply { - err := r.Reply(r.Type == "yes", - append([]byte(r.Type), r.Payload...)) - if err != nil { - t.Errorf("AckRequest: %v", err) - } - } - } - }() - - _, _, err := clientMux.SendRequest("peek", false, nil) - if err != nil { - t.Errorf("SendRequest: %v", err) - } - - ok, data, err := clientMux.SendRequest("yes", true, []byte("a")) - if !ok || string(data) != "yesa" || err != nil { - t.Errorf("SendRequest(\"yes\", true, \"a\"): %v %v %v", - ok, data, err) - } - if ok, data, err := clientMux.SendRequest("yes", true, []byte("a")); !ok || string(data) != "yesa" || err != nil { - t.Errorf("SendRequest(\"yes\", true, \"a\"): %v %v %v", - ok, data, err) - } - - if ok, data, err := clientMux.SendRequest("no", true, []byte("a")); ok || string(data) != "noa" || err != nil { - t.Errorf("SendRequest(\"no\", true, \"a\"): %v %v %v", - ok, data, err) - } - - if !seen { - t.Errorf("never saw 'peek' request") - } -} - -func TestMuxGlobalRequestUnblock(t *testing.T) { - clientMux, serverMux := muxPair() - defer serverMux.Close() - defer clientMux.Close() - - result := make(chan error, 1) - go func() { - _, _, err := clientMux.SendRequest("hello", true, nil) - result <- err - }() - - <-serverMux.incomingRequests - serverMux.conn.Close() - err := <-result - - if err != io.EOF { - t.Errorf("want EOF, got %v", io.EOF) - } -} - -func TestMuxChannelRequestUnblock(t *testing.T) { - a, b, connB := channelPair(t) - defer a.Close() - defer b.Close() - defer connB.Close() - - result := make(chan error, 1) - go func() { - _, err := a.SendRequest("hello", true, nil) - result <- err - }() - - <-b.incomingRequests - connB.conn.Close() - err := <-result - - if err != io.EOF { - t.Errorf("want EOF, got %v", err) - } -} - -func TestMuxCloseChannel(t *testing.T) { - r, w, mux := channelPair(t) - defer mux.Close() - defer r.Close() - defer w.Close() - - result := make(chan error, 1) - go func() { - var b [1024]byte - _, err := r.Read(b[:]) - result <- err - }() - if err := w.Close(); err != nil { - t.Errorf("w.Close: %v", err) - } - - if _, err := w.Write([]byte("hello")); err != io.EOF { - t.Errorf("got err %v, want io.EOF after Close", err) - } - - if err := <-result; err != io.EOF { - t.Errorf("got %v (%T), want io.EOF", err, err) - } -} - -func TestMuxCloseWriteChannel(t *testing.T) { - r, w, mux := channelPair(t) - defer mux.Close() - - result := make(chan error, 1) - go func() { - var b [1024]byte - _, err := r.Read(b[:]) - result <- err - }() - if err := w.CloseWrite(); err != nil { - t.Errorf("w.CloseWrite: %v", err) - } - - if _, err := w.Write([]byte("hello")); err != io.EOF { - t.Errorf("got err %v, want io.EOF after CloseWrite", err) - } - - if err := <-result; err != io.EOF { - t.Errorf("got %v (%T), want io.EOF", err, err) - } -} - -func TestMuxInvalidRecord(t *testing.T) { - a, b := muxPair() - defer a.Close() - defer b.Close() - - packet := make([]byte, 1+4+4+1) - packet[0] = msgChannelData - marshalUint32(packet[1:], 29348723 /* invalid channel id */) - marshalUint32(packet[5:], 1) - packet[9] = 42 - - a.conn.writePacket(packet) - go a.SendRequest("hello", false, nil) - // 'a' wrote an invalid packet, so 'b' has exited. - req, ok := <-b.incomingRequests - if ok { - t.Errorf("got request %#v after receiving invalid packet", req) - } -} - -func TestZeroWindowAdjust(t *testing.T) { - a, b, mux := channelPair(t) - defer a.Close() - defer b.Close() - defer mux.Close() - - go func() { - io.WriteString(a, "hello") - // bogus adjust. - a.sendMessage(windowAdjustMsg{}) - io.WriteString(a, "world") - a.Close() - }() - - want := "helloworld" - c, _ := ioutil.ReadAll(b) - if string(c) != want { - t.Errorf("got %q want %q", c, want) - } -} - -func TestMuxMaxPacketSize(t *testing.T) { - a, b, mux := channelPair(t) - defer a.Close() - defer b.Close() - defer mux.Close() - - large := make([]byte, a.maxRemotePayload+1) - packet := make([]byte, 1+4+4+1+len(large)) - packet[0] = msgChannelData - marshalUint32(packet[1:], a.remoteId) - marshalUint32(packet[5:], uint32(len(large))) - packet[9] = 42 - - if err := a.mux.conn.writePacket(packet); err != nil { - t.Errorf("could not send packet") - } - - go a.SendRequest("hello", false, nil) - - _, ok := <-b.incomingRequests - if ok { - t.Errorf("connection still alive after receiving large packet.") - } -} - -// Don't ship code with debug=true. -func TestDebug(t *testing.T) { - if debugMux { - t.Error("mux debug switched on") - } - if debugHandshake { - t.Error("handshake debug switched on") - } - if debugTransport { - t.Error("transport debug switched on") - } -} diff --git a/vendor/golang.org/x/crypto/ssh/session_test.go b/vendor/golang.org/x/crypto/ssh/session_test.go deleted file mode 100644 index 7dce6dd6..00000000 --- a/vendor/golang.org/x/crypto/ssh/session_test.go +++ /dev/null @@ -1,774 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ssh - -// Session tests. - -import ( - "bytes" - crypto_rand "crypto/rand" - "errors" - "io" - "io/ioutil" - "math/rand" - "net" - "testing" - - "golang.org/x/crypto/ssh/terminal" -) - -type serverType func(Channel, <-chan *Request, *testing.T) - -// dial constructs a new test server and returns a *ClientConn. -func dial(handler serverType, t *testing.T) *Client { - c1, c2, err := netPipe() - if err != nil { - t.Fatalf("netPipe: %v", err) - } - - go func() { - defer c1.Close() - conf := ServerConfig{ - NoClientAuth: true, - } - conf.AddHostKey(testSigners["rsa"]) - - _, chans, reqs, err := NewServerConn(c1, &conf) - if err != nil { - t.Fatalf("Unable to handshake: %v", err) - } - go DiscardRequests(reqs) - - for newCh := range chans { - if newCh.ChannelType() != "session" { - newCh.Reject(UnknownChannelType, "unknown channel type") - continue - } - - ch, inReqs, err := newCh.Accept() - if err != nil { - t.Errorf("Accept: %v", err) - continue - } - go func() { - handler(ch, inReqs, t) - }() - } - }() - - config := &ClientConfig{ - User: "testuser", - HostKeyCallback: InsecureIgnoreHostKey(), - } - - conn, chans, reqs, err := NewClientConn(c2, "", config) - if err != nil { - t.Fatalf("unable to dial remote side: %v", err) - } - - return NewClient(conn, chans, reqs) -} - -// Test a simple string is returned to session.Stdout. -func TestSessionShell(t *testing.T) { - conn := dial(shellHandler, t) - defer conn.Close() - session, err := conn.NewSession() - if err != nil { - t.Fatalf("Unable to request new session: %v", err) - } - defer session.Close() - stdout := new(bytes.Buffer) - session.Stdout = stdout - if err := session.Shell(); err != nil { - t.Fatalf("Unable to execute command: %s", err) - } - if err := session.Wait(); err != nil { - t.Fatalf("Remote command did not exit cleanly: %v", err) - } - actual := stdout.String() - if actual != "golang" { - t.Fatalf("Remote shell did not return expected string: expected=golang, actual=%s", actual) - } -} - -// TODO(dfc) add support for Std{in,err}Pipe when the Server supports it. - -// Test a simple string is returned via StdoutPipe. -func TestSessionStdoutPipe(t *testing.T) { - conn := dial(shellHandler, t) - defer conn.Close() - session, err := conn.NewSession() - if err != nil { - t.Fatalf("Unable to request new session: %v", err) - } - defer session.Close() - stdout, err := session.StdoutPipe() - if err != nil { - t.Fatalf("Unable to request StdoutPipe(): %v", err) - } - var buf bytes.Buffer - if err := session.Shell(); err != nil { - t.Fatalf("Unable to execute command: %v", err) - } - done := make(chan bool, 1) - go func() { - if _, err := io.Copy(&buf, stdout); err != nil { - t.Errorf("Copy of stdout failed: %v", err) - } - done <- true - }() - if err := session.Wait(); err != nil { - t.Fatalf("Remote command did not exit cleanly: %v", err) - } - <-done - actual := buf.String() - if actual != "golang" { - t.Fatalf("Remote shell did not return expected string: expected=golang, actual=%s", actual) - } -} - -// Test that a simple string is returned via the Output helper, -// and that stderr is discarded. -func TestSessionOutput(t *testing.T) { - conn := dial(fixedOutputHandler, t) - defer conn.Close() - session, err := conn.NewSession() - if err != nil { - t.Fatalf("Unable to request new session: %v", err) - } - defer session.Close() - - buf, err := session.Output("") // cmd is ignored by fixedOutputHandler - if err != nil { - t.Error("Remote command did not exit cleanly:", err) - } - w := "this-is-stdout." - g := string(buf) - if g != w { - t.Error("Remote command did not return expected string:") - t.Logf("want %q", w) - t.Logf("got %q", g) - } -} - -// Test that both stdout and stderr are returned -// via the CombinedOutput helper. -func TestSessionCombinedOutput(t *testing.T) { - conn := dial(fixedOutputHandler, t) - defer conn.Close() - session, err := conn.NewSession() - if err != nil { - t.Fatalf("Unable to request new session: %v", err) - } - defer session.Close() - - buf, err := session.CombinedOutput("") // cmd is ignored by fixedOutputHandler - if err != nil { - t.Error("Remote command did not exit cleanly:", err) - } - const stdout = "this-is-stdout." - const stderr = "this-is-stderr." - g := string(buf) - if g != stdout+stderr && g != stderr+stdout { - t.Error("Remote command did not return expected string:") - t.Logf("want %q, or %q", stdout+stderr, stderr+stdout) - t.Logf("got %q", g) - } -} - -// Test non-0 exit status is returned correctly. -func TestExitStatusNonZero(t *testing.T) { - conn := dial(exitStatusNonZeroHandler, t) - defer conn.Close() - session, err := conn.NewSession() - if err != nil { - t.Fatalf("Unable to request new session: %v", err) - } - defer session.Close() - if err := session.Shell(); err != nil { - t.Fatalf("Unable to execute command: %v", err) - } - err = session.Wait() - if err == nil { - t.Fatalf("expected command to fail but it didn't") - } - e, ok := err.(*ExitError) - if !ok { - t.Fatalf("expected *ExitError but got %T", err) - } - if e.ExitStatus() != 15 { - t.Fatalf("expected command to exit with 15 but got %v", e.ExitStatus()) - } -} - -// Test 0 exit status is returned correctly. -func TestExitStatusZero(t *testing.T) { - conn := dial(exitStatusZeroHandler, t) - defer conn.Close() - session, err := conn.NewSession() - if err != nil { - t.Fatalf("Unable to request new session: %v", err) - } - defer session.Close() - - if err := session.Shell(); err != nil { - t.Fatalf("Unable to execute command: %v", err) - } - err = session.Wait() - if err != nil { - t.Fatalf("expected nil but got %v", err) - } -} - -// Test exit signal and status are both returned correctly. -func TestExitSignalAndStatus(t *testing.T) { - conn := dial(exitSignalAndStatusHandler, t) - defer conn.Close() - session, err := conn.NewSession() - if err != nil { - t.Fatalf("Unable to request new session: %v", err) - } - defer session.Close() - if err := session.Shell(); err != nil { - t.Fatalf("Unable to execute command: %v", err) - } - err = session.Wait() - if err == nil { - t.Fatalf("expected command to fail but it didn't") - } - e, ok := err.(*ExitError) - if !ok { - t.Fatalf("expected *ExitError but got %T", err) - } - if e.Signal() != "TERM" || e.ExitStatus() != 15 { - t.Fatalf("expected command to exit with signal TERM and status 15 but got signal %s and status %v", e.Signal(), e.ExitStatus()) - } -} - -// Test exit signal and status are both returned correctly. -func TestKnownExitSignalOnly(t *testing.T) { - conn := dial(exitSignalHandler, t) - defer conn.Close() - session, err := conn.NewSession() - if err != nil { - t.Fatalf("Unable to request new session: %v", err) - } - defer session.Close() - if err := session.Shell(); err != nil { - t.Fatalf("Unable to execute command: %v", err) - } - err = session.Wait() - if err == nil { - t.Fatalf("expected command to fail but it didn't") - } - e, ok := err.(*ExitError) - if !ok { - t.Fatalf("expected *ExitError but got %T", err) - } - if e.Signal() != "TERM" || e.ExitStatus() != 143 { - t.Fatalf("expected command to exit with signal TERM and status 143 but got signal %s and status %v", e.Signal(), e.ExitStatus()) - } -} - -// Test exit signal and status are both returned correctly. -func TestUnknownExitSignal(t *testing.T) { - conn := dial(exitSignalUnknownHandler, t) - defer conn.Close() - session, err := conn.NewSession() - if err != nil { - t.Fatalf("Unable to request new session: %v", err) - } - defer session.Close() - if err := session.Shell(); err != nil { - t.Fatalf("Unable to execute command: %v", err) - } - err = session.Wait() - if err == nil { - t.Fatalf("expected command to fail but it didn't") - } - e, ok := err.(*ExitError) - if !ok { - t.Fatalf("expected *ExitError but got %T", err) - } - if e.Signal() != "SYS" || e.ExitStatus() != 128 { - t.Fatalf("expected command to exit with signal SYS and status 128 but got signal %s and status %v", e.Signal(), e.ExitStatus()) - } -} - -func TestExitWithoutStatusOrSignal(t *testing.T) { - conn := dial(exitWithoutSignalOrStatus, t) - defer conn.Close() - session, err := conn.NewSession() - if err != nil { - t.Fatalf("Unable to request new session: %v", err) - } - defer session.Close() - if err := session.Shell(); err != nil { - t.Fatalf("Unable to execute command: %v", err) - } - err = session.Wait() - if err == nil { - t.Fatalf("expected command to fail but it didn't") - } - if _, ok := err.(*ExitMissingError); !ok { - t.Fatalf("got %T want *ExitMissingError", err) - } -} - -// windowTestBytes is the number of bytes that we'll send to the SSH server. -const windowTestBytes = 16000 * 200 - -// TestServerWindow writes random data to the server. The server is expected to echo -// the same data back, which is compared against the original. -func TestServerWindow(t *testing.T) { - origBuf := bytes.NewBuffer(make([]byte, 0, windowTestBytes)) - io.CopyN(origBuf, crypto_rand.Reader, windowTestBytes) - origBytes := origBuf.Bytes() - - conn := dial(echoHandler, t) - defer conn.Close() - session, err := conn.NewSession() - if err != nil { - t.Fatal(err) - } - defer session.Close() - result := make(chan []byte) - - go func() { - defer close(result) - echoedBuf := bytes.NewBuffer(make([]byte, 0, windowTestBytes)) - serverStdout, err := session.StdoutPipe() - if err != nil { - t.Errorf("StdoutPipe failed: %v", err) - return - } - n, err := copyNRandomly("stdout", echoedBuf, serverStdout, windowTestBytes) - if err != nil && err != io.EOF { - t.Errorf("Read only %d bytes from server, expected %d: %v", n, windowTestBytes, err) - } - result <- echoedBuf.Bytes() - }() - - serverStdin, err := session.StdinPipe() - if err != nil { - t.Fatalf("StdinPipe failed: %v", err) - } - written, err := copyNRandomly("stdin", serverStdin, origBuf, windowTestBytes) - if err != nil { - t.Fatalf("failed to copy origBuf to serverStdin: %v", err) - } - if written != windowTestBytes { - t.Fatalf("Wrote only %d of %d bytes to server", written, windowTestBytes) - } - - echoedBytes := <-result - - if !bytes.Equal(origBytes, echoedBytes) { - t.Fatalf("Echoed buffer differed from original, orig %d, echoed %d", len(origBytes), len(echoedBytes)) - } -} - -// Verify the client can handle a keepalive packet from the server. -func TestClientHandlesKeepalives(t *testing.T) { - conn := dial(channelKeepaliveSender, t) - defer conn.Close() - session, err := conn.NewSession() - if err != nil { - t.Fatal(err) - } - defer session.Close() - if err := session.Shell(); err != nil { - t.Fatalf("Unable to execute command: %v", err) - } - err = session.Wait() - if err != nil { - t.Fatalf("expected nil but got: %v", err) - } -} - -type exitStatusMsg struct { - Status uint32 -} - -type exitSignalMsg struct { - Signal string - CoreDumped bool - Errmsg string - Lang string -} - -func handleTerminalRequests(in <-chan *Request) { - for req := range in { - ok := false - switch req.Type { - case "shell": - ok = true - if len(req.Payload) > 0 { - // We don't accept any commands, only the default shell. - ok = false - } - case "env": - ok = true - } - req.Reply(ok, nil) - } -} - -func newServerShell(ch Channel, in <-chan *Request, prompt string) *terminal.Terminal { - term := terminal.NewTerminal(ch, prompt) - go handleTerminalRequests(in) - return term -} - -func exitStatusZeroHandler(ch Channel, in <-chan *Request, t *testing.T) { - defer ch.Close() - // this string is returned to stdout - shell := newServerShell(ch, in, "> ") - readLine(shell, t) - sendStatus(0, ch, t) -} - -func exitStatusNonZeroHandler(ch Channel, in <-chan *Request, t *testing.T) { - defer ch.Close() - shell := newServerShell(ch, in, "> ") - readLine(shell, t) - sendStatus(15, ch, t) -} - -func exitSignalAndStatusHandler(ch Channel, in <-chan *Request, t *testing.T) { - defer ch.Close() - shell := newServerShell(ch, in, "> ") - readLine(shell, t) - sendStatus(15, ch, t) - sendSignal("TERM", ch, t) -} - -func exitSignalHandler(ch Channel, in <-chan *Request, t *testing.T) { - defer ch.Close() - shell := newServerShell(ch, in, "> ") - readLine(shell, t) - sendSignal("TERM", ch, t) -} - -func exitSignalUnknownHandler(ch Channel, in <-chan *Request, t *testing.T) { - defer ch.Close() - shell := newServerShell(ch, in, "> ") - readLine(shell, t) - sendSignal("SYS", ch, t) -} - -func exitWithoutSignalOrStatus(ch Channel, in <-chan *Request, t *testing.T) { - defer ch.Close() - shell := newServerShell(ch, in, "> ") - readLine(shell, t) -} - -func shellHandler(ch Channel, in <-chan *Request, t *testing.T) { - defer ch.Close() - // this string is returned to stdout - shell := newServerShell(ch, in, "golang") - readLine(shell, t) - sendStatus(0, ch, t) -} - -// Ignores the command, writes fixed strings to stderr and stdout. -// Strings are "this-is-stdout." and "this-is-stderr.". -func fixedOutputHandler(ch Channel, in <-chan *Request, t *testing.T) { - defer ch.Close() - _, err := ch.Read(nil) - - req, ok := <-in - if !ok { - t.Fatalf("error: expected channel request, got: %#v", err) - return - } - - // ignore request, always send some text - req.Reply(true, nil) - - _, err = io.WriteString(ch, "this-is-stdout.") - if err != nil { - t.Fatalf("error writing on server: %v", err) - } - _, err = io.WriteString(ch.Stderr(), "this-is-stderr.") - if err != nil { - t.Fatalf("error writing on server: %v", err) - } - sendStatus(0, ch, t) -} - -func readLine(shell *terminal.Terminal, t *testing.T) { - if _, err := shell.ReadLine(); err != nil && err != io.EOF { - t.Errorf("unable to read line: %v", err) - } -} - -func sendStatus(status uint32, ch Channel, t *testing.T) { - msg := exitStatusMsg{ - Status: status, - } - if _, err := ch.SendRequest("exit-status", false, Marshal(&msg)); err != nil { - t.Errorf("unable to send status: %v", err) - } -} - -func sendSignal(signal string, ch Channel, t *testing.T) { - sig := exitSignalMsg{ - Signal: signal, - CoreDumped: false, - Errmsg: "Process terminated", - Lang: "en-GB-oed", - } - if _, err := ch.SendRequest("exit-signal", false, Marshal(&sig)); err != nil { - t.Errorf("unable to send signal: %v", err) - } -} - -func discardHandler(ch Channel, t *testing.T) { - defer ch.Close() - io.Copy(ioutil.Discard, ch) -} - -func echoHandler(ch Channel, in <-chan *Request, t *testing.T) { - defer ch.Close() - if n, err := copyNRandomly("echohandler", ch, ch, windowTestBytes); err != nil { - t.Errorf("short write, wrote %d, expected %d: %v ", n, windowTestBytes, err) - } -} - -// copyNRandomly copies n bytes from src to dst. It uses a variable, and random, -// buffer size to exercise more code paths. -func copyNRandomly(title string, dst io.Writer, src io.Reader, n int) (int, error) { - var ( - buf = make([]byte, 32*1024) - written int - remaining = n - ) - for remaining > 0 { - l := rand.Intn(1 << 15) - if remaining < l { - l = remaining - } - nr, er := src.Read(buf[:l]) - nw, ew := dst.Write(buf[:nr]) - remaining -= nw - written += nw - if ew != nil { - return written, ew - } - if nr != nw { - return written, io.ErrShortWrite - } - if er != nil && er != io.EOF { - return written, er - } - } - return written, nil -} - -func channelKeepaliveSender(ch Channel, in <-chan *Request, t *testing.T) { - defer ch.Close() - shell := newServerShell(ch, in, "> ") - readLine(shell, t) - if _, err := ch.SendRequest("keepalive@openssh.com", true, nil); err != nil { - t.Errorf("unable to send channel keepalive request: %v", err) - } - sendStatus(0, ch, t) -} - -func TestClientWriteEOF(t *testing.T) { - conn := dial(simpleEchoHandler, t) - defer conn.Close() - - session, err := conn.NewSession() - if err != nil { - t.Fatal(err) - } - defer session.Close() - stdin, err := session.StdinPipe() - if err != nil { - t.Fatalf("StdinPipe failed: %v", err) - } - stdout, err := session.StdoutPipe() - if err != nil { - t.Fatalf("StdoutPipe failed: %v", err) - } - - data := []byte(`0000`) - _, err = stdin.Write(data) - if err != nil { - t.Fatalf("Write failed: %v", err) - } - stdin.Close() - - res, err := ioutil.ReadAll(stdout) - if err != nil { - t.Fatalf("Read failed: %v", err) - } - - if !bytes.Equal(data, res) { - t.Fatalf("Read differed from write, wrote: %v, read: %v", data, res) - } -} - -func simpleEchoHandler(ch Channel, in <-chan *Request, t *testing.T) { - defer ch.Close() - data, err := ioutil.ReadAll(ch) - if err != nil { - t.Errorf("handler read error: %v", err) - } - _, err = ch.Write(data) - if err != nil { - t.Errorf("handler write error: %v", err) - } -} - -func TestSessionID(t *testing.T) { - c1, c2, err := netPipe() - if err != nil { - t.Fatalf("netPipe: %v", err) - } - defer c1.Close() - defer c2.Close() - - serverID := make(chan []byte, 1) - clientID := make(chan []byte, 1) - - serverConf := &ServerConfig{ - NoClientAuth: true, - } - serverConf.AddHostKey(testSigners["ecdsa"]) - clientConf := &ClientConfig{ - HostKeyCallback: InsecureIgnoreHostKey(), - User: "user", - } - - go func() { - conn, chans, reqs, err := NewServerConn(c1, serverConf) - if err != nil { - t.Fatalf("server handshake: %v", err) - } - serverID <- conn.SessionID() - go DiscardRequests(reqs) - for ch := range chans { - ch.Reject(Prohibited, "") - } - }() - - go func() { - conn, chans, reqs, err := NewClientConn(c2, "", clientConf) - if err != nil { - t.Fatalf("client handshake: %v", err) - } - clientID <- conn.SessionID() - go DiscardRequests(reqs) - for ch := range chans { - ch.Reject(Prohibited, "") - } - }() - - s := <-serverID - c := <-clientID - if bytes.Compare(s, c) != 0 { - t.Errorf("server session ID (%x) != client session ID (%x)", s, c) - } else if len(s) == 0 { - t.Errorf("client and server SessionID were empty.") - } -} - -type noReadConn struct { - readSeen bool - net.Conn -} - -func (c *noReadConn) Close() error { - return nil -} - -func (c *noReadConn) Read(b []byte) (int, error) { - c.readSeen = true - return 0, errors.New("noReadConn error") -} - -func TestInvalidServerConfiguration(t *testing.T) { - c1, c2, err := netPipe() - if err != nil { - t.Fatalf("netPipe: %v", err) - } - defer c1.Close() - defer c2.Close() - - serveConn := noReadConn{Conn: c1} - serverConf := &ServerConfig{} - - NewServerConn(&serveConn, serverConf) - if serveConn.readSeen { - t.Fatalf("NewServerConn attempted to Read() from Conn while configuration is missing host key") - } - - serverConf.AddHostKey(testSigners["ecdsa"]) - - NewServerConn(&serveConn, serverConf) - if serveConn.readSeen { - t.Fatalf("NewServerConn attempted to Read() from Conn while configuration is missing authentication method") - } -} - -func TestHostKeyAlgorithms(t *testing.T) { - serverConf := &ServerConfig{ - NoClientAuth: true, - } - serverConf.AddHostKey(testSigners["rsa"]) - serverConf.AddHostKey(testSigners["ecdsa"]) - - connect := func(clientConf *ClientConfig, want string) { - var alg string - clientConf.HostKeyCallback = func(h string, a net.Addr, key PublicKey) error { - alg = key.Type() - return nil - } - c1, c2, err := netPipe() - if err != nil { - t.Fatalf("netPipe: %v", err) - } - defer c1.Close() - defer c2.Close() - - go NewServerConn(c1, serverConf) - _, _, _, err = NewClientConn(c2, "", clientConf) - if err != nil { - t.Fatalf("NewClientConn: %v", err) - } - if alg != want { - t.Errorf("selected key algorithm %s, want %s", alg, want) - } - } - - // By default, we get the preferred algorithm, which is ECDSA 256. - - clientConf := &ClientConfig{ - HostKeyCallback: InsecureIgnoreHostKey(), - } - connect(clientConf, KeyAlgoECDSA256) - - // Client asks for RSA explicitly. - clientConf.HostKeyAlgorithms = []string{KeyAlgoRSA} - connect(clientConf, KeyAlgoRSA) - - c1, c2, err := netPipe() - if err != nil { - t.Fatalf("netPipe: %v", err) - } - defer c1.Close() - defer c2.Close() - - go NewServerConn(c1, serverConf) - clientConf.HostKeyAlgorithms = []string{"nonexistent-hostkey-algo"} - _, _, _, err = NewClientConn(c2, "", clientConf) - if err == nil { - t.Fatal("succeeded connecting with unknown hostkey algorithm") - } -} diff --git a/vendor/golang.org/x/crypto/ssh/sshpiper_test.go b/vendor/golang.org/x/crypto/ssh/sshpiper_test.go deleted file mode 100644 index 23d6ada8..00000000 --- a/vendor/golang.org/x/crypto/ssh/sshpiper_test.go +++ /dev/null @@ -1,800 +0,0 @@ -// Copyright 2014, 2015 tgic. All rights reserved. -// this file is governed by MIT-license -// -// https://github.com/tg123/sshpiper - -package ssh - -import ( - "bytes" - "fmt" - "io/ioutil" - "net" - "testing" -) - -// {{{ Example NewSSHPiperConn - -func ExampleNewSSHPiperConn() { - - // upstream addr - const serverAddr = "127.0.0.1:22" - - piper := &PiperConfig{ - // return conn dial to serverAddr - FindUpstream: func(conn ConnMetadata, challengeCtx AdditionalChallengeContext) (net.Conn, *AuthPipe, error) { - c, err := net.Dial("tcp", serverAddr) - if err != nil { - return nil, nil, err - } - - // change upstream username to root - return c, &AuthPipe{ - User: "root", - UpstreamHostKeyCallback: InsecureIgnoreHostKey(), - }, nil - }, - } - - // add private key - privateBytes, err := ioutil.ReadFile("id_rsa") - if err != nil { - panic("Failed to load private key") - } - - private, err := ParsePrivateKey(privateBytes) - if err != nil { - panic("Failed to parse private key") - } - - piper.AddHostKey(private) - - // serve at a address - listener, err := net.Listen("tcp", "0.0.0.0:2022") - if err != nil { - panic("failed to listen for connection") - } - nConn, err := listener.Accept() - if err != nil { - panic("failed to accept incoming connection") - } - - // accept nConn and build a SSHPipe - p, err := NewSSHPiperConn(nConn, piper) - if err != nil { - panic("failed to establish piped connection") - } - - // wait util either side shutdown - p.Wait() -} - -// }}} - -func dialPiper(piper *PiperConfig, afterConn func(*PiperConn), t *testing.T) (net.Conn, error) { - c, s, err := netPipe() - if err != nil { - return nil, err - } - - piper.AddHostKey(testSigners["rsa"]) - - go func() { - defer c.Close() - defer s.Close() - - p, err := NewSSHPiperConn(s, piper) - - if err != nil { - t.Errorf("failed to create piper conn %v", err) - return - } - - if afterConn != nil { - afterConn(p) - } - - p.Wait() - }() - - return c, nil -} - -func TestPiperFindUpstreamCallback(t *testing.T) { - - const username = "testuser" - - var called bool - - c, err := dialPiper(&PiperConfig{ - FindUpstream: func(conn ConnMetadata, challengeCtx AdditionalChallengeContext) (net.Conn, *AuthPipe, error) { - if username != conn.User() { - t.Errorf("different username") - } - - s, err := dialUpstream(simpleEchoHandler, &ServerConfig{ - PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { - called = true - - if conn.User() != username { - t.Errorf("default username changed") - } - - if string(password) != "password" { - t.Errorf("password not equal") - } - - return nil, nil - }, - }, t) - - return s, &AuthPipe{ - UpstreamHostKeyCallback: InsecureIgnoreHostKey(), - }, err - }, - }, nil, t) - - if err != nil { - t.Fatalf("connect dial to piper: %v", err) - } - - NewClientConn(c, "", &ClientConfig{ - User: username, - Auth: []AuthMethod{Password("password")}, - HostKeyCallback: InsecureIgnoreHostKey(), - }) - - if !called { - t.Fatalf("FindUpstream not called") - - } -} - -// TODO clean up duplicate code -func TestPiperFindUpstreamWithUserCallback(t *testing.T) { - const username = "testuser" - const mappedname = "mappedname" - - var called bool - - c, err := dialPiper(&PiperConfig{ - FindUpstream: func(conn ConnMetadata, challengeCtx AdditionalChallengeContext) (net.Conn, *AuthPipe, error) { - - s, err := dialUpstream(simpleEchoHandler, &ServerConfig{ - PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { - called = true - - if conn.User() != mappedname { - t.Errorf("bad mapped username") - } - - return nil, nil - }, - }, t) - - return s, &AuthPipe{ - User: mappedname, - UpstreamHostKeyCallback: InsecureIgnoreHostKey(), - }, err - }, - }, nil, t) - - if err != nil { - t.Fatalf("connect dial to piper: %v", err) - } - - NewClientConn(c, "", &ClientConfig{ - User: username, - Auth: []AuthMethod{Password("password")}, - HostKeyCallback: InsecureIgnoreHostKey(), - }) - - if !called { - t.Fatalf("FindUpstream not called") - } -} - -func TestPiperMapPublicKey(t *testing.T) { - - certChecker := CertChecker{ - IsUserAuthority: func(k PublicKey) bool { - return bytes.Equal(k.Marshal(), testPublicKeys["ecdsa"].Marshal()) - }, - UserKeyFallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) { - if bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) { - return nil, nil - } - - return nil, fmt.Errorf("pubkey for %q not acceptable", conn.User()) - }, - IsRevoked: func(c *Certificate) bool { - return c.Serial == 666 - }, - } - - c, err := dialPiper(&PiperConfig{ - FindUpstream: func(conn ConnMetadata, challengeCtx AdditionalChallengeContext) (net.Conn, *AuthPipe, error) { - s, err := dialUpstream(simpleEchoHandler, &ServerConfig{ - PublicKeyCallback: certChecker.Authenticate, - }, t) - return s, &AuthPipe{ - - PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (AuthPipeType, AuthMethod, error) { - return AuthPipeTypeMap, PublicKeys(testSigners["rsa"]), nil - }, - - UpstreamHostKeyCallback: InsecureIgnoreHostKey(), - }, err - }, - }, nil, t) - - if err != nil { - t.Fatalf("connect dial to piper: %v", err) - } - - _, _, _, err = NewClientConn(c, "", &ClientConfig{ - User: "testuser", - Auth: []AuthMethod{ - PublicKeys(testSigners["rsa"]), - }, - HostKeyCallback: InsecureIgnoreHostKey(), - }) - - if err != nil { - t.Fatalf("can connect to piper %v", err) - } -} - -func TestPiperMapPublicKeyToPassword(t *testing.T) { - certChecker := CertChecker{ - IsUserAuthority: func(k PublicKey) bool { - return bytes.Equal(k.Marshal(), testPublicKeys["ecdsa"].Marshal()) - }, - UserKeyFallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) { - if bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) { - return nil, nil - } - - return nil, fmt.Errorf("pubkey for %q not acceptable", conn.User()) - }, - IsRevoked: func(c *Certificate) bool { - return c.Serial == 666 - }, - } - - var called bool - - c, err := dialPiper(&PiperConfig{ - FindUpstream: func(conn ConnMetadata, challengeCtx AdditionalChallengeContext) (net.Conn, *AuthPipe, error) { - s, err := dialUpstream(simpleEchoHandler, &ServerConfig{ - PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { - t.Errorf("PasswordCallback should not be called") - return nil, nil - }, - PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) { - - called = true - return certChecker.Authenticate(conn, key) - }, - }, t) - return s, &AuthPipe{ - PasswordCallback: func(conn ConnMetadata, password []byte) (AuthPipeType, AuthMethod, error) { - if string(password) != "mypassword" { - t.Errorf("password not equal") - } - - return AuthPipeTypeMap, PublicKeys(testSigners["rsa"]), nil - }, - - UpstreamHostKeyCallback: InsecureIgnoreHostKey(), - }, err - }, - }, nil, t) - - if err != nil { - t.Fatalf("connect dial to piper: %v", err) - } - - _, _, _, err = NewClientConn(c, "", &ClientConfig{ - User: "testuser", - Auth: []AuthMethod{ - Password("mypassword"), - }, - HostKeyCallback: InsecureIgnoreHostKey(), - }) - - if err != nil { - t.Fatalf("can connect to piper %v", err) - } - - if !called { - t.Fatalf("PublicKeyCallback not called") - } -} - -func TestPiperPasswordToMapPublicKey(t *testing.T) { - var called bool - - c, err := dialPiper(&PiperConfig{ - FindUpstream: func(conn ConnMetadata, challengeCtx AdditionalChallengeContext) (net.Conn, *AuthPipe, error) { - s, err := dialUpstream(simpleEchoHandler, &ServerConfig{ - PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { - called = true - - if string(password) != "mypassword" { - t.Errorf("password not equal") - } - - return nil, nil - }, - PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) { - - t.Errorf("PublicKeyCallback should not be called") - return nil, nil - }, - }, t) - return s, &AuthPipe{ - - PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (AuthPipeType, AuthMethod, error) { - return AuthPipeTypeMap, Password("mypassword"), nil - }, - - UpstreamHostKeyCallback: InsecureIgnoreHostKey(), - }, err - }, - }, nil, t) - - if err != nil { - t.Fatalf("connect dial to piper: %v", err) - } - - _, _, _, err = NewClientConn(c, "", &ClientConfig{ - User: "testuser", - Auth: []AuthMethod{ - PublicKeys(testSigners["rsa"]), - }, - HostKeyCallback: InsecureIgnoreHostKey(), - }) - - if err != nil { - t.Fatalf("can connect to piper %v", err) - } - - if !called { - t.Fatalf("PasswordCallback not called") - } -} - -func TestPiperServerWithBanner(t *testing.T) { - - const username = "testuser" - const mappedname = "mappedname" - - var called bool - - c, err := dialPiper(&PiperConfig{ - FindUpstream: func(conn ConnMetadata, challengeCtx AdditionalChallengeContext) (net.Conn, *AuthPipe, error) { - if username != conn.User() { - t.Errorf("different username") - } - - s, err := dialUpstream(simpleEchoHandler, &ServerConfig{ - PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { - if mappedname != conn.User() { - t.Errorf("username changed after banner") - } - called = true - return nil, nil - }, - BannerCallback: func(conn ConnMetadata) string { - return "banner" - }, - }, t) - - return s, &AuthPipe{ - User: mappedname, - UpstreamHostKeyCallback: InsecureIgnoreHostKey(), - }, err - }, - }, nil, t) - - if err != nil { - t.Fatalf("connect dial to piper: %v", err) - } - - NewClientConn(c, "", &ClientConfig{ - User: username, - Auth: []AuthMethod{Password("password")}, - HostKeyCallback: InsecureIgnoreHostKey(), - BannerCallback: func(message string) error { - if message != "banner" { - t.Errorf("bad banner string") - } - - return nil - }, - }) - - if !called { - t.Fatalf("FindUpstream not called") - } -} - -func TestPiperUsernameNotChangedWithinSession(t *testing.T) { - const mappedname = "mappedname" - - callcount := 0 - - certChecker := CertChecker{ - IsUserAuthority: func(k PublicKey) bool { - return bytes.Equal(k.Marshal(), testPublicKeys["ecdsa"].Marshal()) - }, - UserKeyFallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) { - if bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) { - return nil, nil - } - - return nil, fmt.Errorf("pubkey for %q not acceptable", conn.User()) - }, - IsRevoked: func(c *Certificate) bool { - return c.Serial == 666 - }, - } - - c, err := dialPiper(&PiperConfig{ - FindUpstream: func(conn ConnMetadata, challengeCtx AdditionalChallengeContext) (net.Conn, *AuthPipe, error) { - s, err := dialUpstream(simpleEchoHandler, &ServerConfig{ - PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { - if conn.User() != mappedname { - t.Errorf("bad mapped username") - } - - return nil, fmt.Errorf("access denied") - }, - PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) { - if conn.User() != mappedname { - t.Errorf("bad mapped username") - } - - return certChecker.Authenticate(conn, key) - }, - AuthLogCallback: func(conn ConnMetadata, method string, err error) { - if conn.User() != mappedname { - t.Errorf("bad mapped username") - } - - callcount++ - }, - }, t) - return s, &AuthPipe{ - User: mappedname, - - PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (AuthPipeType, AuthMethod, error) { - return AuthPipeTypeMap, PublicKeys(testSigners["rsa"]), nil - }, - - UpstreamHostKeyCallback: InsecureIgnoreHostKey(), - }, err - }, - }, nil, t) - - if err != nil { - t.Fatalf("connect dial to piper: %v", err) - } - - _, _, _, err = NewClientConn(c, "", &ClientConfig{ - User: "testuser", - Auth: []AuthMethod{ - AuthMethod(new(noneAuth)), - Password("badpassword"), - PublicKeys(testSigners["rsa"]), - }, - HostKeyCallback: InsecureIgnoreHostKey(), - }) - - if err != nil { - t.Fatalf("can connect to piper %v", err) - } - - if callcount != 3 { - t.Fatalf("some auth not called") - } -} - -type fakeChallengerContext string - -func (fakeChallengerContext) ChallengerName() string { return "" } -func (fakeChallengerContext) Meta() interface{} { return nil } -func (c fakeChallengerContext) ChallengedUsername() string { return string(c) } - -func TestPiperAdditionalChallenge(t *testing.T) { - - c, err := dialPiper(&PiperConfig{ - AdditionalChallenge: func(conn ConnMetadata, challenge KeyboardInteractiveChallenge) (AdditionalChallengeContext, error) { - ans, err := challenge("user", - "instruction", - []string{"question1", "question2"}, - []bool{true, true}) - - if err != nil { - return nil, err - } - - ok := conn.User() == "testuser" && ans[0] == "answer1" && ans[1] == "answer2" - if ok { - challenge("user", "motd", nil, nil) - return fakeChallengerContext("chal"), nil - } - return nil, fmt.Errorf("keyboard-interactive failed") - }, - FindUpstream: func(conn ConnMetadata, challengeCtx AdditionalChallengeContext) (net.Conn, *AuthPipe, error) { - - if challengeCtx.ChallengedUsername() != "chal" { - t.Fatalf("challengeCtx.ChallengedUsername changed") - } - - s, err := dialUpstream(simpleEchoHandler, &ServerConfig{NoClientAuth: true}, t) - return s, &AuthPipe{ - UpstreamHostKeyCallback: InsecureIgnoreHostKey(), - }, err - }, - }, nil, t) - - if err != nil { - t.Fatalf("connect dial to piper: %v", err) - } - - answers := keyboardInteractive(map[string]string{ - "question1": "answer1", - // TODO "question2": "WRONG", - "question2": "answer2", - }) - - _, _, _, err = NewClientConn(c, "", &ClientConfig{ - User: "testuser", - Auth: []AuthMethod{ - KeyboardInteractive(answers.Challenge), - }, - HostKeyCallback: InsecureIgnoreHostKey(), - }) - - if err != nil { - t.Fatalf("can connect to piper %v", err) - } - -} - -func fakeUpstreamServer(s net.Conn, upstream *ServerConfig, handler serverType, t *testing.T) { - defer s.Close() - - upstream.AddHostKey(testSigners["rsa"]) - - _, chans, reqs, err := NewServerConn(s, upstream) - if err != nil { - t.Errorf("cannot start upstream %v", err) - } - - go DiscardRequests(reqs) - - for newCh := range chans { - if newCh.ChannelType() != "session" { - newCh.Reject(UnknownChannelType, "unknown channel type") - continue - } - - ch, inReqs, err := newCh.Accept() - if err != nil { - t.Errorf("Accept: %v", err) - continue - } - go func() { - handler(ch, inReqs, t) - }() - } -} - -func dialUpstream(handler serverType, upstream *ServerConfig, t *testing.T) (net.Conn, error) { - c, s, err := netPipe() - if err != nil { - t.Errorf("netPipe piper->upstream: %v", err) - return nil, err - } - - go fakeUpstreamServer(s, upstream, handler, t) - return c, nil -} - -func TestPiperConnMeta(t *testing.T) { - - wait := make(chan int) - - c, err := dialPiper(&PiperConfig{ - FindUpstream: func(conn ConnMetadata, challengeCtx AdditionalChallengeContext) (net.Conn, *AuthPipe, error) { - s, err := dialUpstream(simpleEchoHandler, &ServerConfig{NoClientAuth: true}, t) - return s, &AuthPipe{ - User: "up", - UpstreamHostKeyCallback: InsecureIgnoreHostKey(), - }, err - }, - }, func(p *PiperConn) { - - if p.DownstreamConnMeta().User() != "down" { - t.Errorf("different downstream user") - } - - if p.UpstreamConnMeta().User() != "up" { - t.Errorf("different upstream user") - } - - wait <- 0 - }, t) - - _, _, _, err = NewClientConn(c, "", &ClientConfig{ - User: "down", - Auth: []AuthMethod{new(noneAuth)}, - HostKeyCallback: InsecureIgnoreHostKey(), - }) - - if err != nil { - t.Fatalf("can connect to piper %v", err) - } - - <-wait -} - -func TestPiperConnMsgHook(t *testing.T) { - - wait := make(chan int) - - c, err := dialPiper(&PiperConfig{ - FindUpstream: func(conn ConnMetadata, challengeCtx AdditionalChallengeContext) (net.Conn, *AuthPipe, error) { - s, err := dialUpstream(simpleEchoHandler, &ServerConfig{NoClientAuth: true}, t) - return s, &AuthPipe{ - UpstreamHostKeyCallback: InsecureIgnoreHostKey(), - }, err - }, - }, func(p *PiperConn) { - - p.HookDownstreamMsg = func(conn ConnMetadata, msg []byte) ([]byte, error) { - if msg[0] == msgChannelData { - m := channelDataMsg{} - Unmarshal(msg, &m) - if string(m.Rest) != "123456" { - t.Errorf("msg not equal") - } - - m.Length = 3 - m.Rest = []byte("654") - - return Marshal(m), nil - } - - return msg, nil - } - - p.HookUpstreamMsg = func(conn ConnMetadata, msg []byte) ([]byte, error) { - if msg[0] == msgChannelData { - m := channelDataMsg{} - Unmarshal(msg, &m) - if string(m.Rest) != "654" { - t.Errorf("msg not equal") - } - - m.Length = 7 - m.Rest = []byte("abcdefg") - - return Marshal(m), nil - } - - return msg, nil - } - - wait <- 0 - }, t) - - sshc, chans, reqs, err := NewClientConn(c, "", &ClientConfig{ - User: "test", - Auth: []AuthMethod{new(noneAuth)}, - HostKeyCallback: InsecureIgnoreHostKey(), - }) - - if err != nil { - t.Fatalf("can connect to piper %v", err) - } - <-wait - - conn := NewClient(sshc, chans, reqs) - defer conn.Close() - - session, err := conn.NewSession() - if err != nil { - t.Fatal(err) - } - defer session.Close() - - stdin, err := session.StdinPipe() - if err != nil { - t.Fatalf("StdinPipe failed: %v", err) - } - stdout, err := session.StdoutPipe() - if err != nil { - t.Fatalf("StdoutPipe failed: %v", err) - } - - data := []byte(`123456`) - _, err = stdin.Write(data) - if err != nil { - t.Fatalf("Write failed: %v", err) - } - stdin.Close() - - res, err := ioutil.ReadAll(stdout) - if err != nil { - t.Fatalf("Read failed: %v", err) - } - - if !bytes.Equal([]byte(`abcdefg`), res) { - t.Fatalf("Read differed from write, wrote: %v, read: %v", data, res) - } - -} - -func TestPiperPipeData(t *testing.T) { - - c, err := dialPiper(&PiperConfig{ - FindUpstream: func(conn ConnMetadata, challengeCtx AdditionalChallengeContext) (net.Conn, *AuthPipe, error) { - s, err := dialUpstream(simpleEchoHandler, &ServerConfig{NoClientAuth: true}, t) - return s, &AuthPipe{ - UpstreamHostKeyCallback: InsecureIgnoreHostKey(), - }, err - }, - }, nil, t) - - if err != nil { - t.Fatalf("connect dial to piper: %v", err) - } - - // {{{ copy from session_test.go TestClientWriteEOF(t *testing.T) - sshc, chans, reqs, err := NewClientConn(c, "", &ClientConfig{ - User: "testuser", - HostKeyCallback: InsecureIgnoreHostKey(), - }) - if err != nil { - t.Fatalf("error create client %v", err) - } - - conn := NewClient(sshc, chans, reqs) - defer conn.Close() - - session, err := conn.NewSession() - if err != nil { - t.Fatal(err) - } - defer session.Close() - - stdin, err := session.StdinPipe() - if err != nil { - t.Fatalf("StdinPipe failed: %v", err) - } - stdout, err := session.StdoutPipe() - if err != nil { - t.Fatalf("StdoutPipe failed: %v", err) - } - - data := []byte(`0000`) - _, err = stdin.Write(data) - if err != nil { - t.Fatalf("Write failed: %v", err) - } - stdin.Close() - - res, err := ioutil.ReadAll(stdout) - if err != nil { - t.Fatalf("Read failed: %v", err) - } - - if !bytes.Equal(data, res) { - t.Fatalf("Read differed from write, wrote: %v, read: %v", data, res) - } - // }}} -} diff --git a/vendor/golang.org/x/crypto/ssh/tcpip_test.go b/vendor/golang.org/x/crypto/ssh/tcpip_test.go deleted file mode 100644 index f1265cb4..00000000 --- a/vendor/golang.org/x/crypto/ssh/tcpip_test.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ssh - -import ( - "testing" -) - -func TestAutoPortListenBroken(t *testing.T) { - broken := "SSH-2.0-OpenSSH_5.9hh11" - works := "SSH-2.0-OpenSSH_6.1" - if !isBrokenOpenSSHVersion(broken) { - t.Errorf("version %q not marked as broken", broken) - } - if isBrokenOpenSSHVersion(works) { - t.Errorf("version %q marked as broken", works) - } -} diff --git a/vendor/golang.org/x/crypto/ssh/test/agent_unix_test.go b/vendor/golang.org/x/crypto/ssh/test/agent_unix_test.go deleted file mode 100644 index f481253c..00000000 --- a/vendor/golang.org/x/crypto/ssh/test/agent_unix_test.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build darwin dragonfly freebsd linux netbsd openbsd - -package test - -import ( - "bytes" - "testing" - - "golang.org/x/crypto/ssh" - "golang.org/x/crypto/ssh/agent" -) - -func TestAgentForward(t *testing.T) { - server := newServer(t) - defer server.Shutdown() - conn := server.Dial(clientConfig()) - defer conn.Close() - - keyring := agent.NewKeyring() - if err := keyring.Add(agent.AddedKey{PrivateKey: testPrivateKeys["dsa"]}); err != nil { - t.Fatalf("Error adding key: %s", err) - } - if err := keyring.Add(agent.AddedKey{ - PrivateKey: testPrivateKeys["dsa"], - ConfirmBeforeUse: true, - LifetimeSecs: 3600, - }); err != nil { - t.Fatalf("Error adding key with constraints: %s", err) - } - pub := testPublicKeys["dsa"] - - sess, err := conn.NewSession() - if err != nil { - t.Fatalf("NewSession: %v", err) - } - if err := agent.RequestAgentForwarding(sess); err != nil { - t.Fatalf("RequestAgentForwarding: %v", err) - } - - if err := agent.ForwardToAgent(conn, keyring); err != nil { - t.Fatalf("SetupForwardKeyring: %v", err) - } - out, err := sess.CombinedOutput("ssh-add -L") - if err != nil { - t.Fatalf("running ssh-add: %v, out %s", err, out) - } - key, _, _, _, err := ssh.ParseAuthorizedKey(out) - if err != nil { - t.Fatalf("ParseAuthorizedKey(%q): %v", out, err) - } - - if !bytes.Equal(key.Marshal(), pub.Marshal()) { - t.Fatalf("got key %s, want %s", ssh.MarshalAuthorizedKey(key), ssh.MarshalAuthorizedKey(pub)) - } -} diff --git a/vendor/golang.org/x/crypto/ssh/test/banner_test.go b/vendor/golang.org/x/crypto/ssh/test/banner_test.go deleted file mode 100644 index d3b21ac7..00000000 --- a/vendor/golang.org/x/crypto/ssh/test/banner_test.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build darwin dragonfly freebsd linux netbsd openbsd - -package test - -import ( - "testing" -) - -func TestBannerCallbackAgainstOpenSSH(t *testing.T) { - server := newServer(t) - defer server.Shutdown() - - clientConf := clientConfig() - - var receivedBanner string - clientConf.BannerCallback = func(message string) error { - receivedBanner = message - return nil - } - - conn := server.Dial(clientConf) - defer conn.Close() - - expected := "Server Banner" - if receivedBanner != expected { - t.Fatalf("got %v; want %v", receivedBanner, expected) - } -} diff --git a/vendor/golang.org/x/crypto/ssh/test/cert_test.go b/vendor/golang.org/x/crypto/ssh/test/cert_test.go deleted file mode 100644 index b231dd80..00000000 --- a/vendor/golang.org/x/crypto/ssh/test/cert_test.go +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build darwin dragonfly freebsd linux netbsd openbsd - -package test - -import ( - "bytes" - "crypto/rand" - "testing" - - "golang.org/x/crypto/ssh" -) - -// Test both logging in with a cert, and also that the certificate presented by an OpenSSH host can be validated correctly -func TestCertLogin(t *testing.T) { - s := newServer(t) - defer s.Shutdown() - - // Use a key different from the default. - clientKey := testSigners["dsa"] - caAuthKey := testSigners["ecdsa"] - cert := &ssh.Certificate{ - Key: clientKey.PublicKey(), - ValidPrincipals: []string{username()}, - CertType: ssh.UserCert, - ValidBefore: ssh.CertTimeInfinity, - } - if err := cert.SignCert(rand.Reader, caAuthKey); err != nil { - t.Fatalf("SetSignature: %v", err) - } - - certSigner, err := ssh.NewCertSigner(cert, clientKey) - if err != nil { - t.Fatalf("NewCertSigner: %v", err) - } - - conf := &ssh.ClientConfig{ - User: username(), - HostKeyCallback: (&ssh.CertChecker{ - IsHostAuthority: func(pk ssh.PublicKey, addr string) bool { - return bytes.Equal(pk.Marshal(), testPublicKeys["ca"].Marshal()) - }, - }).CheckHostKey, - } - conf.Auth = append(conf.Auth, ssh.PublicKeys(certSigner)) - - for _, test := range []struct { - addr string - succeed bool - }{ - {addr: "host.example.com:22", succeed: true}, - {addr: "host.example.com:10000", succeed: true}, // non-standard port must be OK - {addr: "host.example.com", succeed: false}, // port must be specified - {addr: "host.ex4mple.com:22", succeed: false}, // wrong host - } { - client, err := s.TryDialWithAddr(conf, test.addr) - - // Always close client if opened successfully - if err == nil { - client.Close() - } - - // Now evaluate whether the test failed or passed - if test.succeed { - if err != nil { - t.Fatalf("TryDialWithAddr: %v", err) - } - } else { - if err == nil { - t.Fatalf("TryDialWithAddr, unexpected success") - } - } - } -} diff --git a/vendor/golang.org/x/crypto/ssh/test/dial_unix_test.go b/vendor/golang.org/x/crypto/ssh/test/dial_unix_test.go deleted file mode 100644 index 091e48cc..00000000 --- a/vendor/golang.org/x/crypto/ssh/test/dial_unix_test.go +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !windows - -package test - -// direct-tcpip and direct-streamlocal functional tests - -import ( - "fmt" - "io" - "io/ioutil" - "net" - "strings" - "testing" -) - -type dialTester interface { - TestServerConn(t *testing.T, c net.Conn) - TestClientConn(t *testing.T, c net.Conn) -} - -func testDial(t *testing.T, n, listenAddr string, x dialTester) { - server := newServer(t) - defer server.Shutdown() - sshConn := server.Dial(clientConfig()) - defer sshConn.Close() - - l, err := net.Listen(n, listenAddr) - if err != nil { - t.Fatalf("Listen: %v", err) - } - defer l.Close() - - testData := fmt.Sprintf("hello from %s, %s", n, listenAddr) - go func() { - for { - c, err := l.Accept() - if err != nil { - break - } - x.TestServerConn(t, c) - - io.WriteString(c, testData) - c.Close() - } - }() - - conn, err := sshConn.Dial(n, l.Addr().String()) - if err != nil { - t.Fatalf("Dial: %v", err) - } - x.TestClientConn(t, conn) - defer conn.Close() - b, err := ioutil.ReadAll(conn) - if err != nil { - t.Fatalf("ReadAll: %v", err) - } - t.Logf("got %q", string(b)) - if string(b) != testData { - t.Fatalf("expected %q, got %q", testData, string(b)) - } -} - -type tcpDialTester struct { - listenAddr string -} - -func (x *tcpDialTester) TestServerConn(t *testing.T, c net.Conn) { - host := strings.Split(x.listenAddr, ":")[0] - prefix := host + ":" - if !strings.HasPrefix(c.LocalAddr().String(), prefix) { - t.Fatalf("expected to start with %q, got %q", prefix, c.LocalAddr().String()) - } - if !strings.HasPrefix(c.RemoteAddr().String(), prefix) { - t.Fatalf("expected to start with %q, got %q", prefix, c.RemoteAddr().String()) - } -} - -func (x *tcpDialTester) TestClientConn(t *testing.T, c net.Conn) { - // we use zero addresses. see *Client.Dial. - if c.LocalAddr().String() != "0.0.0.0:0" { - t.Fatalf("expected \"0.0.0.0:0\", got %q", c.LocalAddr().String()) - } - if c.RemoteAddr().String() != "0.0.0.0:0" { - t.Fatalf("expected \"0.0.0.0:0\", got %q", c.RemoteAddr().String()) - } -} - -func TestDialTCP(t *testing.T) { - x := &tcpDialTester{ - listenAddr: "127.0.0.1:0", - } - testDial(t, "tcp", x.listenAddr, x) -} - -type unixDialTester struct { - listenAddr string -} - -func (x *unixDialTester) TestServerConn(t *testing.T, c net.Conn) { - if c.LocalAddr().String() != x.listenAddr { - t.Fatalf("expected %q, got %q", x.listenAddr, c.LocalAddr().String()) - } - if c.RemoteAddr().String() != "@" { - t.Fatalf("expected \"@\", got %q", c.RemoteAddr().String()) - } -} - -func (x *unixDialTester) TestClientConn(t *testing.T, c net.Conn) { - if c.RemoteAddr().String() != x.listenAddr { - t.Fatalf("expected %q, got %q", x.listenAddr, c.RemoteAddr().String()) - } - if c.LocalAddr().String() != "@" { - t.Fatalf("expected \"@\", got %q", c.LocalAddr().String()) - } -} - -func TestDialUnix(t *testing.T) { - addr, cleanup := newTempSocket(t) - defer cleanup() - x := &unixDialTester{ - listenAddr: addr, - } - testDial(t, "unix", x.listenAddr, x) -} diff --git a/vendor/golang.org/x/crypto/ssh/test/doc.go b/vendor/golang.org/x/crypto/ssh/test/doc.go deleted file mode 100644 index 198f0ca1..00000000 --- a/vendor/golang.org/x/crypto/ssh/test/doc.go +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package test contains integration tests for the -// golang.org/x/crypto/ssh package. -package test // import "golang.org/x/crypto/ssh/test" diff --git a/vendor/golang.org/x/crypto/ssh/test/forward_unix_test.go b/vendor/golang.org/x/crypto/ssh/test/forward_unix_test.go deleted file mode 100644 index ea819378..00000000 --- a/vendor/golang.org/x/crypto/ssh/test/forward_unix_test.go +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build darwin dragonfly freebsd linux netbsd openbsd - -package test - -import ( - "bytes" - "io" - "io/ioutil" - "math/rand" - "net" - "testing" - "time" -) - -type closeWriter interface { - CloseWrite() error -} - -func testPortForward(t *testing.T, n, listenAddr string) { - server := newServer(t) - defer server.Shutdown() - conn := server.Dial(clientConfig()) - defer conn.Close() - - sshListener, err := conn.Listen(n, listenAddr) - if err != nil { - t.Fatal(err) - } - - go func() { - sshConn, err := sshListener.Accept() - if err != nil { - t.Fatalf("listen.Accept failed: %v", err) - } - - _, err = io.Copy(sshConn, sshConn) - if err != nil && err != io.EOF { - t.Fatalf("ssh client copy: %v", err) - } - sshConn.Close() - }() - - forwardedAddr := sshListener.Addr().String() - netConn, err := net.Dial(n, forwardedAddr) - if err != nil { - t.Fatalf("net dial failed: %v", err) - } - - readChan := make(chan []byte) - go func() { - data, _ := ioutil.ReadAll(netConn) - readChan <- data - }() - - // Invent some data. - data := make([]byte, 100*1000) - for i := range data { - data[i] = byte(i % 255) - } - - var sent []byte - for len(sent) < 1000*1000 { - // Send random sized chunks - m := rand.Intn(len(data)) - n, err := netConn.Write(data[:m]) - if err != nil { - break - } - sent = append(sent, data[:n]...) - } - if err := netConn.(closeWriter).CloseWrite(); err != nil { - t.Errorf("netConn.CloseWrite: %v", err) - } - - read := <-readChan - - if len(sent) != len(read) { - t.Fatalf("got %d bytes, want %d", len(read), len(sent)) - } - if bytes.Compare(sent, read) != 0 { - t.Fatalf("read back data does not match") - } - - if err := sshListener.Close(); err != nil { - t.Fatalf("sshListener.Close: %v", err) - } - - // Check that the forward disappeared. - netConn, err = net.Dial(n, forwardedAddr) - if err == nil { - netConn.Close() - t.Errorf("still listening to %s after closing", forwardedAddr) - } -} - -func TestPortForwardTCP(t *testing.T) { - testPortForward(t, "tcp", "localhost:0") -} - -func TestPortForwardUnix(t *testing.T) { - addr, cleanup := newTempSocket(t) - defer cleanup() - testPortForward(t, "unix", addr) -} - -func testAcceptClose(t *testing.T, n, listenAddr string) { - server := newServer(t) - defer server.Shutdown() - conn := server.Dial(clientConfig()) - - sshListener, err := conn.Listen(n, listenAddr) - if err != nil { - t.Fatal(err) - } - - quit := make(chan error, 1) - go func() { - for { - c, err := sshListener.Accept() - if err != nil { - quit <- err - break - } - c.Close() - } - }() - sshListener.Close() - - select { - case <-time.After(1 * time.Second): - t.Errorf("timeout: listener did not close.") - case err := <-quit: - t.Logf("quit as expected (error %v)", err) - } -} - -func TestAcceptCloseTCP(t *testing.T) { - testAcceptClose(t, "tcp", "localhost:0") -} - -func TestAcceptCloseUnix(t *testing.T) { - addr, cleanup := newTempSocket(t) - defer cleanup() - testAcceptClose(t, "unix", addr) -} - -// Check that listeners exit if the underlying client transport dies. -func testPortForwardConnectionClose(t *testing.T, n, listenAddr string) { - server := newServer(t) - defer server.Shutdown() - conn := server.Dial(clientConfig()) - - sshListener, err := conn.Listen(n, listenAddr) - if err != nil { - t.Fatal(err) - } - - quit := make(chan error, 1) - go func() { - for { - c, err := sshListener.Accept() - if err != nil { - quit <- err - break - } - c.Close() - } - }() - - // It would be even nicer if we closed the server side, but it - // is more involved as the fd for that side is dup()ed. - server.clientConn.Close() - - select { - case <-time.After(1 * time.Second): - t.Errorf("timeout: listener did not close.") - case err := <-quit: - t.Logf("quit as expected (error %v)", err) - } -} - -func TestPortForwardConnectionCloseTCP(t *testing.T) { - testPortForwardConnectionClose(t, "tcp", "localhost:0") -} - -func TestPortForwardConnectionCloseUnix(t *testing.T) { - addr, cleanup := newTempSocket(t) - defer cleanup() - testPortForwardConnectionClose(t, "unix", addr) -} diff --git a/vendor/golang.org/x/crypto/ssh/test/multi_auth_test.go b/vendor/golang.org/x/crypto/ssh/test/multi_auth_test.go deleted file mode 100644 index f594d36e..00000000 --- a/vendor/golang.org/x/crypto/ssh/test/multi_auth_test.go +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Tests for ssh client multi-auth -// -// These tests run a simple go ssh client against OpenSSH server -// over unix domain sockets. The tests use multiple combinations -// of password, keyboard-interactive and publickey authentication -// methods. -// -// A wrapper library for making sshd PAM authentication use test -// passwords is required in ./sshd_test_pw.so. If the library does -// not exist these tests will be skipped. See compile instructions -// (for linux) in file ./sshd_test_pw.c. - -// +build linux - -package test - -import ( - "fmt" - "strings" - "testing" - - "golang.org/x/crypto/ssh" -) - -// test cases -type multiAuthTestCase struct { - authMethods []string - expectedPasswordCbs int - expectedKbdIntCbs int -} - -// test context -type multiAuthTestCtx struct { - password string - numPasswordCbs int - numKbdIntCbs int -} - -// create test context -func newMultiAuthTestCtx(t *testing.T) *multiAuthTestCtx { - password, err := randomPassword() - if err != nil { - t.Fatalf("Failed to generate random test password: %s", err.Error()) - } - - return &multiAuthTestCtx{ - password: password, - } -} - -// password callback -func (ctx *multiAuthTestCtx) passwordCb() (secret string, err error) { - ctx.numPasswordCbs++ - return ctx.password, nil -} - -// keyboard-interactive callback -func (ctx *multiAuthTestCtx) kbdIntCb(user, instruction string, questions []string, echos []bool) (answers []string, err error) { - if len(questions) == 0 { - return nil, nil - } - - ctx.numKbdIntCbs++ - if len(questions) == 1 { - return []string{ctx.password}, nil - } - - return nil, fmt.Errorf("unsupported keyboard-interactive flow") -} - -// TestMultiAuth runs several subtests for different combinations of password, keyboard-interactive and publickey authentication methods -func TestMultiAuth(t *testing.T) { - testCases := []multiAuthTestCase{ - // Test password,publickey authentication, assert that password callback is called 1 time - multiAuthTestCase{ - authMethods: []string{"password", "publickey"}, - expectedPasswordCbs: 1, - }, - // Test keyboard-interactive,publickey authentication, assert that keyboard-interactive callback is called 1 time - multiAuthTestCase{ - authMethods: []string{"keyboard-interactive", "publickey"}, - expectedKbdIntCbs: 1, - }, - // Test publickey,password authentication, assert that password callback is called 1 time - multiAuthTestCase{ - authMethods: []string{"publickey", "password"}, - expectedPasswordCbs: 1, - }, - // Test publickey,keyboard-interactive authentication, assert that keyboard-interactive callback is called 1 time - multiAuthTestCase{ - authMethods: []string{"publickey", "keyboard-interactive"}, - expectedKbdIntCbs: 1, - }, - // Test password,password authentication, assert that password callback is called 2 times - multiAuthTestCase{ - authMethods: []string{"password", "password"}, - expectedPasswordCbs: 2, - }, - } - - for _, testCase := range testCases { - t.Run(strings.Join(testCase.authMethods, ","), func(t *testing.T) { - ctx := newMultiAuthTestCtx(t) - - server := newServerForConfig(t, "MultiAuth", map[string]string{"AuthMethods": strings.Join(testCase.authMethods, ",")}) - defer server.Shutdown() - - clientConfig := clientConfig() - server.setTestPassword(clientConfig.User, ctx.password) - - publicKeyAuthMethod := clientConfig.Auth[0] - clientConfig.Auth = nil - for _, authMethod := range testCase.authMethods { - switch authMethod { - case "publickey": - clientConfig.Auth = append(clientConfig.Auth, publicKeyAuthMethod) - case "password": - clientConfig.Auth = append(clientConfig.Auth, - ssh.RetryableAuthMethod(ssh.PasswordCallback(ctx.passwordCb), 5)) - case "keyboard-interactive": - clientConfig.Auth = append(clientConfig.Auth, - ssh.RetryableAuthMethod(ssh.KeyboardInteractive(ctx.kbdIntCb), 5)) - default: - t.Fatalf("Unknown authentication method %s", authMethod) - } - } - - conn := server.Dial(clientConfig) - defer conn.Close() - - if ctx.numPasswordCbs != testCase.expectedPasswordCbs { - t.Fatalf("passwordCallback was called %d times, expected %d times", ctx.numPasswordCbs, testCase.expectedPasswordCbs) - } - - if ctx.numKbdIntCbs != testCase.expectedKbdIntCbs { - t.Fatalf("keyboardInteractiveCallback was called %d times, expected %d times", ctx.numKbdIntCbs, testCase.expectedKbdIntCbs) - } - }) - } -} diff --git a/vendor/golang.org/x/crypto/ssh/test/session_test.go b/vendor/golang.org/x/crypto/ssh/test/session_test.go deleted file mode 100644 index 4eb7afde..00000000 --- a/vendor/golang.org/x/crypto/ssh/test/session_test.go +++ /dev/null @@ -1,443 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !windows - -package test - -// Session functional tests. - -import ( - "bytes" - "errors" - "fmt" - "io" - "strings" - "testing" - - "golang.org/x/crypto/ssh" -) - -func TestRunCommandSuccess(t *testing.T) { - server := newServer(t) - defer server.Shutdown() - conn := server.Dial(clientConfig()) - defer conn.Close() - - session, err := conn.NewSession() - if err != nil { - t.Fatalf("session failed: %v", err) - } - defer session.Close() - err = session.Run("true") - if err != nil { - t.Fatalf("session failed: %v", err) - } -} - -func TestHostKeyCheck(t *testing.T) { - server := newServer(t) - defer server.Shutdown() - - conf := clientConfig() - hostDB := hostKeyDB() - conf.HostKeyCallback = hostDB.Check - - // change the keys. - hostDB.keys[ssh.KeyAlgoRSA][25]++ - hostDB.keys[ssh.KeyAlgoDSA][25]++ - hostDB.keys[ssh.KeyAlgoECDSA256][25]++ - - conn, err := server.TryDial(conf) - if err == nil { - conn.Close() - t.Fatalf("dial should have failed.") - } else if !strings.Contains(err.Error(), "host key mismatch") { - t.Fatalf("'host key mismatch' not found in %v", err) - } -} - -func TestRunCommandStdin(t *testing.T) { - server := newServer(t) - defer server.Shutdown() - conn := server.Dial(clientConfig()) - defer conn.Close() - - session, err := conn.NewSession() - if err != nil { - t.Fatalf("session failed: %v", err) - } - defer session.Close() - - r, w := io.Pipe() - defer r.Close() - defer w.Close() - session.Stdin = r - - err = session.Run("true") - if err != nil { - t.Fatalf("session failed: %v", err) - } -} - -func TestRunCommandStdinError(t *testing.T) { - server := newServer(t) - defer server.Shutdown() - conn := server.Dial(clientConfig()) - defer conn.Close() - - session, err := conn.NewSession() - if err != nil { - t.Fatalf("session failed: %v", err) - } - defer session.Close() - - r, w := io.Pipe() - defer r.Close() - session.Stdin = r - pipeErr := errors.New("closing write end of pipe") - w.CloseWithError(pipeErr) - - err = session.Run("true") - if err != pipeErr { - t.Fatalf("expected %v, found %v", pipeErr, err) - } -} - -func TestRunCommandFailed(t *testing.T) { - server := newServer(t) - defer server.Shutdown() - conn := server.Dial(clientConfig()) - defer conn.Close() - - session, err := conn.NewSession() - if err != nil { - t.Fatalf("session failed: %v", err) - } - defer session.Close() - err = session.Run(`bash -c "kill -9 $$"`) - if err == nil { - t.Fatalf("session succeeded: %v", err) - } -} - -func TestRunCommandWeClosed(t *testing.T) { - server := newServer(t) - defer server.Shutdown() - conn := server.Dial(clientConfig()) - defer conn.Close() - - session, err := conn.NewSession() - if err != nil { - t.Fatalf("session failed: %v", err) - } - err = session.Shell() - if err != nil { - t.Fatalf("shell failed: %v", err) - } - err = session.Close() - if err != nil { - t.Fatalf("shell failed: %v", err) - } -} - -func TestFuncLargeRead(t *testing.T) { - server := newServer(t) - defer server.Shutdown() - conn := server.Dial(clientConfig()) - defer conn.Close() - - session, err := conn.NewSession() - if err != nil { - t.Fatalf("unable to create new session: %s", err) - } - - stdout, err := session.StdoutPipe() - if err != nil { - t.Fatalf("unable to acquire stdout pipe: %s", err) - } - - err = session.Start("dd if=/dev/urandom bs=2048 count=1024") - if err != nil { - t.Fatalf("unable to execute remote command: %s", err) - } - - buf := new(bytes.Buffer) - n, err := io.Copy(buf, stdout) - if err != nil { - t.Fatalf("error reading from remote stdout: %s", err) - } - - if n != 2048*1024 { - t.Fatalf("Expected %d bytes but read only %d from remote command", 2048, n) - } -} - -func TestKeyChange(t *testing.T) { - server := newServer(t) - defer server.Shutdown() - conf := clientConfig() - hostDB := hostKeyDB() - conf.HostKeyCallback = hostDB.Check - conf.RekeyThreshold = 1024 - conn := server.Dial(conf) - defer conn.Close() - - for i := 0; i < 4; i++ { - session, err := conn.NewSession() - if err != nil { - t.Fatalf("unable to create new session: %s", err) - } - - stdout, err := session.StdoutPipe() - if err != nil { - t.Fatalf("unable to acquire stdout pipe: %s", err) - } - - err = session.Start("dd if=/dev/urandom bs=1024 count=1") - if err != nil { - t.Fatalf("unable to execute remote command: %s", err) - } - buf := new(bytes.Buffer) - n, err := io.Copy(buf, stdout) - if err != nil { - t.Fatalf("error reading from remote stdout: %s", err) - } - - want := int64(1024) - if n != want { - t.Fatalf("Expected %d bytes but read only %d from remote command", want, n) - } - } - - if changes := hostDB.checkCount; changes < 4 { - t.Errorf("got %d key changes, want 4", changes) - } -} - -func TestInvalidTerminalMode(t *testing.T) { - server := newServer(t) - defer server.Shutdown() - conn := server.Dial(clientConfig()) - defer conn.Close() - - session, err := conn.NewSession() - if err != nil { - t.Fatalf("session failed: %v", err) - } - defer session.Close() - - if err = session.RequestPty("vt100", 80, 40, ssh.TerminalModes{255: 1984}); err == nil { - t.Fatalf("req-pty failed: successful request with invalid mode") - } -} - -func TestValidTerminalMode(t *testing.T) { - server := newServer(t) - defer server.Shutdown() - conn := server.Dial(clientConfig()) - defer conn.Close() - - session, err := conn.NewSession() - if err != nil { - t.Fatalf("session failed: %v", err) - } - defer session.Close() - - stdout, err := session.StdoutPipe() - if err != nil { - t.Fatalf("unable to acquire stdout pipe: %s", err) - } - - stdin, err := session.StdinPipe() - if err != nil { - t.Fatalf("unable to acquire stdin pipe: %s", err) - } - - tm := ssh.TerminalModes{ssh.ECHO: 0} - if err = session.RequestPty("xterm", 80, 40, tm); err != nil { - t.Fatalf("req-pty failed: %s", err) - } - - err = session.Shell() - if err != nil { - t.Fatalf("session failed: %s", err) - } - - stdin.Write([]byte("stty -a && exit\n")) - - var buf bytes.Buffer - if _, err := io.Copy(&buf, stdout); err != nil { - t.Fatalf("reading failed: %s", err) - } - - if sttyOutput := buf.String(); !strings.Contains(sttyOutput, "-echo ") { - t.Fatalf("terminal mode failure: expected -echo in stty output, got %s", sttyOutput) - } -} - -func TestWindowChange(t *testing.T) { - server := newServer(t) - defer server.Shutdown() - conn := server.Dial(clientConfig()) - defer conn.Close() - - session, err := conn.NewSession() - if err != nil { - t.Fatalf("session failed: %v", err) - } - defer session.Close() - - stdout, err := session.StdoutPipe() - if err != nil { - t.Fatalf("unable to acquire stdout pipe: %s", err) - } - - stdin, err := session.StdinPipe() - if err != nil { - t.Fatalf("unable to acquire stdin pipe: %s", err) - } - - tm := ssh.TerminalModes{ssh.ECHO: 0} - if err = session.RequestPty("xterm", 80, 40, tm); err != nil { - t.Fatalf("req-pty failed: %s", err) - } - - if err := session.WindowChange(100, 100); err != nil { - t.Fatalf("window-change failed: %s", err) - } - - err = session.Shell() - if err != nil { - t.Fatalf("session failed: %s", err) - } - - stdin.Write([]byte("stty size && exit\n")) - - var buf bytes.Buffer - if _, err := io.Copy(&buf, stdout); err != nil { - t.Fatalf("reading failed: %s", err) - } - - if sttyOutput := buf.String(); !strings.Contains(sttyOutput, "100 100") { - t.Fatalf("terminal WindowChange failure: expected \"100 100\" stty output, got %s", sttyOutput) - } -} - -func testOneCipher(t *testing.T, cipher string, cipherOrder []string) { - server := newServer(t) - defer server.Shutdown() - conf := clientConfig() - conf.Ciphers = []string{cipher} - // Don't fail if sshd doesn't have the cipher. - conf.Ciphers = append(conf.Ciphers, cipherOrder...) - conn, err := server.TryDial(conf) - if err != nil { - t.Fatalf("TryDial: %v", err) - } - defer conn.Close() - - numBytes := 4096 - - // Exercise sending data to the server - if _, _, err := conn.Conn.SendRequest("drop-me", false, make([]byte, numBytes)); err != nil { - t.Fatalf("SendRequest: %v", err) - } - - // Exercise receiving data from the server - session, err := conn.NewSession() - if err != nil { - t.Fatalf("NewSession: %v", err) - } - - out, err := session.Output(fmt.Sprintf("dd if=/dev/zero of=/dev/stdout bs=%d count=1", numBytes)) - if err != nil { - t.Fatalf("Output: %v", err) - } - - if len(out) != numBytes { - t.Fatalf("got %d bytes, want %d bytes", len(out), numBytes) - } -} - -var deprecatedCiphers = []string{ - "aes128-cbc", "3des-cbc", - "arcfour128", "arcfour256", -} - -func TestCiphers(t *testing.T) { - var config ssh.Config - config.SetDefaults() - cipherOrder := append(config.Ciphers, deprecatedCiphers...) - - for _, ciph := range cipherOrder { - t.Run(ciph, func(t *testing.T) { - testOneCipher(t, ciph, cipherOrder) - }) - } -} - -func TestMACs(t *testing.T) { - var config ssh.Config - config.SetDefaults() - macOrder := config.MACs - - for _, mac := range macOrder { - server := newServer(t) - defer server.Shutdown() - conf := clientConfig() - conf.MACs = []string{mac} - // Don't fail if sshd doesn't have the MAC. - conf.MACs = append(conf.MACs, macOrder...) - if conn, err := server.TryDial(conf); err == nil { - conn.Close() - } else { - t.Fatalf("failed for MAC %q", mac) - } - } -} - -func TestKeyExchanges(t *testing.T) { - var config ssh.Config - config.SetDefaults() - kexOrder := config.KeyExchanges - for _, kex := range kexOrder { - server := newServer(t) - defer server.Shutdown() - conf := clientConfig() - // Don't fail if sshd doesn't have the kex. - conf.KeyExchanges = append([]string{kex}, kexOrder...) - conn, err := server.TryDial(conf) - if err == nil { - conn.Close() - } else { - t.Errorf("failed for kex %q", kex) - } - } -} - -func TestClientAuthAlgorithms(t *testing.T) { - for _, key := range []string{ - "rsa", - "dsa", - "ecdsa", - "ed25519", - } { - server := newServer(t) - conf := clientConfig() - conf.SetDefaults() - conf.Auth = []ssh.AuthMethod{ - ssh.PublicKeys(testSigners[key]), - } - - conn, err := server.TryDial(conf) - if err == nil { - conn.Close() - } else { - t.Errorf("failed for key %q", key) - } - - server.Shutdown() - } -} diff --git a/vendor/golang.org/x/crypto/ssh/test/sshd_test_pw.c b/vendor/golang.org/x/crypto/ssh/test/sshd_test_pw.c deleted file mode 100644 index 2794a563..00000000 --- a/vendor/golang.org/x/crypto/ssh/test/sshd_test_pw.c +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// sshd_test_pw.c -// Wrapper to inject test password data for sshd PAM authentication -// -// This wrapper implements custom versions of getpwnam, getpwnam_r, -// getspnam and getspnam_r. These functions first call their real -// libc versions, then check if the requested user matches test user -// specified in env variable TEST_USER and if so replace the password -// with crypted() value of TEST_PASSWD env variable. -// -// Compile: -// gcc -Wall -shared -o sshd_test_pw.so -fPIC sshd_test_pw.c -// -// Compile with debug: -// gcc -DVERBOSE -Wall -shared -o sshd_test_pw.so -fPIC sshd_test_pw.c -// -// Run sshd: -// LD_PRELOAD="sshd_test_pw.so" TEST_USER="..." TEST_PASSWD="..." sshd ... - -// +build ignore - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include - -#ifdef VERBOSE -#define DEBUG(X...) fprintf(stderr, X) -#else -#define DEBUG(X...) while (0) { } -#endif - -/* crypt() password */ -static char * -pwhash(char *passwd) { - return strdup(crypt(passwd, "$6$")); -} - -/* Pointers to real functions in libc */ -static struct passwd * (*real_getpwnam)(const char *) = NULL; -static int (*real_getpwnam_r)(const char *, struct passwd *, char *, size_t, struct passwd **) = NULL; -static struct spwd * (*real_getspnam)(const char *) = NULL; -static int (*real_getspnam_r)(const char *, struct spwd *, char *, size_t, struct spwd **) = NULL; - -/* Cached test user and test password */ -static char *test_user = NULL; -static char *test_passwd_hash = NULL; - -static void -init(void) { - /* Fetch real libc function pointers */ - real_getpwnam = dlsym(RTLD_NEXT, "getpwnam"); - real_getpwnam_r = dlsym(RTLD_NEXT, "getpwnam_r"); - real_getspnam = dlsym(RTLD_NEXT, "getspnam"); - real_getspnam_r = dlsym(RTLD_NEXT, "getspnam_r"); - - /* abort if env variables are not defined */ - if (getenv("TEST_USER") == NULL || getenv("TEST_PASSWD") == NULL) { - fprintf(stderr, "env variables TEST_USER and TEST_PASSWD are missing\n"); - abort(); - } - - /* Fetch test user and test password from env */ - test_user = strdup(getenv("TEST_USER")); - test_passwd_hash = pwhash(getenv("TEST_PASSWD")); - - DEBUG("sshd_test_pw init():\n"); - DEBUG("\treal_getpwnam: %p\n", real_getpwnam); - DEBUG("\treal_getpwnam_r: %p\n", real_getpwnam_r); - DEBUG("\treal_getspnam: %p\n", real_getspnam); - DEBUG("\treal_getspnam_r: %p\n", real_getspnam_r); - DEBUG("\tTEST_USER: '%s'\n", test_user); - DEBUG("\tTEST_PASSWD: '%s'\n", getenv("TEST_PASSWD")); - DEBUG("\tTEST_PASSWD_HASH: '%s'\n", test_passwd_hash); -} - -static int -is_test_user(const char *name) { - if (test_user != NULL && strcmp(test_user, name) == 0) - return 1; - return 0; -} - -/* getpwnam */ - -struct passwd * -getpwnam(const char *name) { - struct passwd *pw; - - DEBUG("sshd_test_pw getpwnam(%s)\n", name); - - if (real_getpwnam == NULL) - init(); - if ((pw = real_getpwnam(name)) == NULL) - return NULL; - - if (is_test_user(name)) - pw->pw_passwd = strdup(test_passwd_hash); - - return pw; -} - -/* getpwnam_r */ - -int -getpwnam_r(const char *name, - struct passwd *pwd, - char *buf, - size_t buflen, - struct passwd **result) { - int r; - - DEBUG("sshd_test_pw getpwnam_r(%s)\n", name); - - if (real_getpwnam_r == NULL) - init(); - if ((r = real_getpwnam_r(name, pwd, buf, buflen, result)) != 0 || *result == NULL) - return r; - - if (is_test_user(name)) - pwd->pw_passwd = strdup(test_passwd_hash); - - return 0; -} - -/* getspnam */ - -struct spwd * -getspnam(const char *name) { - struct spwd *sp; - - DEBUG("sshd_test_pw getspnam(%s)\n", name); - - if (real_getspnam == NULL) - init(); - if ((sp = real_getspnam(name)) == NULL) - return NULL; - - if (is_test_user(name)) - sp->sp_pwdp = strdup(test_passwd_hash); - - return sp; -} - -/* getspnam_r */ - -int -getspnam_r(const char *name, - struct spwd *spbuf, - char *buf, - size_t buflen, - struct spwd **spbufp) { - int r; - - DEBUG("sshd_test_pw getspnam_r(%s)\n", name); - - if (real_getspnam_r == NULL) - init(); - if ((r = real_getspnam_r(name, spbuf, buf, buflen, spbufp)) != 0) - return r; - - if (is_test_user(name)) - spbuf->sp_pwdp = strdup(test_passwd_hash); - - return r; -} diff --git a/vendor/golang.org/x/crypto/ssh/test/test_unix_test.go b/vendor/golang.org/x/crypto/ssh/test/test_unix_test.go deleted file mode 100644 index 2fbe880a..00000000 --- a/vendor/golang.org/x/crypto/ssh/test/test_unix_test.go +++ /dev/null @@ -1,368 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build darwin dragonfly freebsd linux netbsd openbsd plan9 - -package test - -// functional test harness for unix. - -import ( - "bytes" - "crypto/rand" - "encoding/base64" - "fmt" - "io/ioutil" - "log" - "net" - "os" - "os/exec" - "os/user" - "path/filepath" - "testing" - "text/template" - - "golang.org/x/crypto/ssh" - "golang.org/x/crypto/ssh/testdata" -) - -const ( - defaultSshdConfig = ` -Protocol 2 -Banner {{.Dir}}/banner -HostKey {{.Dir}}/id_rsa -HostKey {{.Dir}}/id_dsa -HostKey {{.Dir}}/id_ecdsa -HostCertificate {{.Dir}}/id_rsa-cert.pub -Pidfile {{.Dir}}/sshd.pid -#UsePrivilegeSeparation no -KeyRegenerationInterval 3600 -ServerKeyBits 768 -SyslogFacility AUTH -LogLevel DEBUG2 -LoginGraceTime 120 -PermitRootLogin no -StrictModes no -RSAAuthentication yes -PubkeyAuthentication yes -AuthorizedKeysFile {{.Dir}}/authorized_keys -TrustedUserCAKeys {{.Dir}}/id_ecdsa.pub -IgnoreRhosts yes -RhostsRSAAuthentication no -HostbasedAuthentication no -PubkeyAcceptedKeyTypes=* -` - multiAuthSshdConfigTail = ` -UsePAM yes -PasswordAuthentication yes -ChallengeResponseAuthentication yes -AuthenticationMethods {{.AuthMethods}} -` -) - -var configTmpl = map[string]*template.Template{ - "default": template.Must(template.New("").Parse(defaultSshdConfig)), - "MultiAuth": template.Must(template.New("").Parse(defaultSshdConfig + multiAuthSshdConfigTail))} - -type server struct { - t *testing.T - cleanup func() // executed during Shutdown - configfile string - cmd *exec.Cmd - output bytes.Buffer // holds stderr from sshd process - - testUser string // test username for sshd - testPasswd string // test password for sshd - sshdTestPwSo string // dynamic library to inject a custom password into sshd - - // Client half of the network connection. - clientConn net.Conn -} - -func username() string { - var username string - if user, err := user.Current(); err == nil { - username = user.Username - } else { - // user.Current() currently requires cgo. If an error is - // returned attempt to get the username from the environment. - log.Printf("user.Current: %v; falling back on $USER", err) - username = os.Getenv("USER") - } - if username == "" { - panic("Unable to get username") - } - return username -} - -type storedHostKey struct { - // keys map from an algorithm string to binary key data. - keys map[string][]byte - - // checkCount counts the Check calls. Used for testing - // rekeying. - checkCount int -} - -func (k *storedHostKey) Add(key ssh.PublicKey) { - if k.keys == nil { - k.keys = map[string][]byte{} - } - k.keys[key.Type()] = key.Marshal() -} - -func (k *storedHostKey) Check(addr string, remote net.Addr, key ssh.PublicKey) error { - k.checkCount++ - algo := key.Type() - - if k.keys == nil || bytes.Compare(key.Marshal(), k.keys[algo]) != 0 { - return fmt.Errorf("host key mismatch. Got %q, want %q", key, k.keys[algo]) - } - return nil -} - -func hostKeyDB() *storedHostKey { - keyChecker := &storedHostKey{} - keyChecker.Add(testPublicKeys["ecdsa"]) - keyChecker.Add(testPublicKeys["rsa"]) - keyChecker.Add(testPublicKeys["dsa"]) - return keyChecker -} - -func clientConfig() *ssh.ClientConfig { - config := &ssh.ClientConfig{ - User: username(), - Auth: []ssh.AuthMethod{ - ssh.PublicKeys(testSigners["user"]), - }, - HostKeyCallback: hostKeyDB().Check, - HostKeyAlgorithms: []string{ // by default, don't allow certs as this affects the hostKeyDB checker - ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521, - ssh.KeyAlgoRSA, ssh.KeyAlgoDSA, - ssh.KeyAlgoED25519, - }, - } - return config -} - -// unixConnection creates two halves of a connected net.UnixConn. It -// is used for connecting the Go SSH client with sshd without opening -// ports. -func unixConnection() (*net.UnixConn, *net.UnixConn, error) { - dir, err := ioutil.TempDir("", "unixConnection") - if err != nil { - return nil, nil, err - } - defer os.Remove(dir) - - addr := filepath.Join(dir, "ssh") - listener, err := net.Listen("unix", addr) - if err != nil { - return nil, nil, err - } - defer listener.Close() - c1, err := net.Dial("unix", addr) - if err != nil { - return nil, nil, err - } - - c2, err := listener.Accept() - if err != nil { - c1.Close() - return nil, nil, err - } - - return c1.(*net.UnixConn), c2.(*net.UnixConn), nil -} - -func (s *server) TryDial(config *ssh.ClientConfig) (*ssh.Client, error) { - return s.TryDialWithAddr(config, "") -} - -// addr is the user specified host:port. While we don't actually dial it, -// we need to know this for host key matching -func (s *server) TryDialWithAddr(config *ssh.ClientConfig, addr string) (*ssh.Client, error) { - sshd, err := exec.LookPath("sshd") - if err != nil { - s.t.Skipf("skipping test: %v", err) - } - - c1, c2, err := unixConnection() - if err != nil { - s.t.Fatalf("unixConnection: %v", err) - } - - s.cmd = exec.Command(sshd, "-f", s.configfile, "-i", "-e") - f, err := c2.File() - if err != nil { - s.t.Fatalf("UnixConn.File: %v", err) - } - defer f.Close() - s.cmd.Stdin = f - s.cmd.Stdout = f - s.cmd.Stderr = &s.output - - if s.sshdTestPwSo != "" { - if s.testUser == "" { - s.t.Fatal("user missing from sshd_test_pw.so config") - } - if s.testPasswd == "" { - s.t.Fatal("password missing from sshd_test_pw.so config") - } - s.cmd.Env = append(os.Environ(), - fmt.Sprintf("LD_PRELOAD=%s", s.sshdTestPwSo), - fmt.Sprintf("TEST_USER=%s", s.testUser), - fmt.Sprintf("TEST_PASSWD=%s", s.testPasswd)) - } - - if err := s.cmd.Start(); err != nil { - s.t.Fail() - s.Shutdown() - s.t.Fatalf("s.cmd.Start: %v", err) - } - s.clientConn = c1 - conn, chans, reqs, err := ssh.NewClientConn(c1, addr, config) - if err != nil { - return nil, err - } - return ssh.NewClient(conn, chans, reqs), nil -} - -func (s *server) Dial(config *ssh.ClientConfig) *ssh.Client { - conn, err := s.TryDial(config) - if err != nil { - s.t.Fail() - s.Shutdown() - s.t.Fatalf("ssh.Client: %v", err) - } - return conn -} - -func (s *server) Shutdown() { - if s.cmd != nil && s.cmd.Process != nil { - // Don't check for errors; if it fails it's most - // likely "os: process already finished", and we don't - // care about that. Use os.Interrupt, so child - // processes are killed too. - s.cmd.Process.Signal(os.Interrupt) - s.cmd.Wait() - } - if s.t.Failed() { - // log any output from sshd process - s.t.Logf("sshd: %s", s.output.String()) - } - s.cleanup() -} - -func writeFile(path string, contents []byte) { - f, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0600) - if err != nil { - panic(err) - } - defer f.Close() - if _, err := f.Write(contents); err != nil { - panic(err) - } -} - -// generate random password -func randomPassword() (string, error) { - b := make([]byte, 12) - _, err := rand.Read(b) - if err != nil { - return "", err - } - return base64.RawURLEncoding.EncodeToString(b), nil -} - -// setTestPassword is used for setting user and password data for sshd_test_pw.so -// This function also checks that ./sshd_test_pw.so exists and if not calls s.t.Skip() -func (s *server) setTestPassword(user, passwd string) error { - wd, _ := os.Getwd() - wrapper := filepath.Join(wd, "sshd_test_pw.so") - if _, err := os.Stat(wrapper); err != nil { - s.t.Skip(fmt.Errorf("sshd_test_pw.so is not available")) - return err - } - - s.sshdTestPwSo = wrapper - s.testUser = user - s.testPasswd = passwd - return nil -} - -// newServer returns a new mock ssh server. -func newServer(t *testing.T) *server { - return newServerForConfig(t, "default", map[string]string{}) -} - -// newServerForConfig returns a new mock ssh server. -func newServerForConfig(t *testing.T, config string, configVars map[string]string) *server { - if testing.Short() { - t.Skip("skipping test due to -short") - } - u, err := user.Current() - if err != nil { - t.Fatalf("user.Current: %v", err) - } - if u.Name == "root" { - t.Skip("skipping test because current user is root") - } - dir, err := ioutil.TempDir("", "sshtest") - if err != nil { - t.Fatal(err) - } - f, err := os.Create(filepath.Join(dir, "sshd_config")) - if err != nil { - t.Fatal(err) - } - if _, ok := configTmpl[config]; ok == false { - t.Fatal(fmt.Errorf("Invalid server config '%s'", config)) - } - configVars["Dir"] = dir - err = configTmpl[config].Execute(f, configVars) - if err != nil { - t.Fatal(err) - } - f.Close() - - writeFile(filepath.Join(dir, "banner"), []byte("Server Banner")) - - for k, v := range testdata.PEMBytes { - filename := "id_" + k - writeFile(filepath.Join(dir, filename), v) - writeFile(filepath.Join(dir, filename+".pub"), ssh.MarshalAuthorizedKey(testPublicKeys[k])) - } - - for k, v := range testdata.SSHCertificates { - filename := "id_" + k + "-cert.pub" - writeFile(filepath.Join(dir, filename), v) - } - - var authkeys bytes.Buffer - for k := range testdata.PEMBytes { - authkeys.Write(ssh.MarshalAuthorizedKey(testPublicKeys[k])) - } - writeFile(filepath.Join(dir, "authorized_keys"), authkeys.Bytes()) - - return &server{ - t: t, - configfile: f.Name(), - cleanup: func() { - if err := os.RemoveAll(dir); err != nil { - t.Error(err) - } - }, - } -} - -func newTempSocket(t *testing.T) (string, func()) { - dir, err := ioutil.TempDir("", "socket") - if err != nil { - t.Fatal(err) - } - deferFunc := func() { os.RemoveAll(dir) } - addr := filepath.Join(dir, "sock") - return addr, deferFunc -} diff --git a/vendor/golang.org/x/crypto/ssh/test/testdata_test.go b/vendor/golang.org/x/crypto/ssh/test/testdata_test.go deleted file mode 100644 index a053f67e..00000000 --- a/vendor/golang.org/x/crypto/ssh/test/testdata_test.go +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// IMPLEMENTATION NOTE: To avoid a package loop, this file is in three places: -// ssh/, ssh/agent, and ssh/test/. It should be kept in sync across all three -// instances. - -package test - -import ( - "crypto/rand" - "fmt" - - "golang.org/x/crypto/ssh" - "golang.org/x/crypto/ssh/testdata" -) - -var ( - testPrivateKeys map[string]interface{} - testSigners map[string]ssh.Signer - testPublicKeys map[string]ssh.PublicKey -) - -func init() { - var err error - - n := len(testdata.PEMBytes) - testPrivateKeys = make(map[string]interface{}, n) - testSigners = make(map[string]ssh.Signer, n) - testPublicKeys = make(map[string]ssh.PublicKey, n) - for t, k := range testdata.PEMBytes { - testPrivateKeys[t], err = ssh.ParseRawPrivateKey(k) - if err != nil { - panic(fmt.Sprintf("Unable to parse test key %s: %v", t, err)) - } - testSigners[t], err = ssh.NewSignerFromKey(testPrivateKeys[t]) - if err != nil { - panic(fmt.Sprintf("Unable to create signer for test key %s: %v", t, err)) - } - testPublicKeys[t] = testSigners[t].PublicKey() - } - - // Create a cert and sign it for use in tests. - testCert := &ssh.Certificate{ - Nonce: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil - ValidPrincipals: []string{"gopher1", "gopher2"}, // increases test coverage - ValidAfter: 0, // unix epoch - ValidBefore: ssh.CertTimeInfinity, // The end of currently representable time. - Reserved: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil - Key: testPublicKeys["ecdsa"], - SignatureKey: testPublicKeys["rsa"], - Permissions: ssh.Permissions{ - CriticalOptions: map[string]string{}, - Extensions: map[string]string{}, - }, - } - testCert.SignCert(rand.Reader, testSigners["rsa"]) - testPrivateKeys["cert"] = testPrivateKeys["ecdsa"] - testSigners["cert"], err = ssh.NewCertSigner(testCert, testSigners["ecdsa"]) - if err != nil { - panic(fmt.Sprintf("Unable to create certificate signer: %v", err)) - } -} diff --git a/vendor/golang.org/x/crypto/ssh/testdata_test.go b/vendor/golang.org/x/crypto/ssh/testdata_test.go deleted file mode 100644 index 2da8c79d..00000000 --- a/vendor/golang.org/x/crypto/ssh/testdata_test.go +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// IMPLEMENTATION NOTE: To avoid a package loop, this file is in three places: -// ssh/, ssh/agent, and ssh/test/. It should be kept in sync across all three -// instances. - -package ssh - -import ( - "crypto/rand" - "fmt" - - "golang.org/x/crypto/ssh/testdata" -) - -var ( - testPrivateKeys map[string]interface{} - testSigners map[string]Signer - testPublicKeys map[string]PublicKey -) - -func init() { - var err error - - n := len(testdata.PEMBytes) - testPrivateKeys = make(map[string]interface{}, n) - testSigners = make(map[string]Signer, n) - testPublicKeys = make(map[string]PublicKey, n) - for t, k := range testdata.PEMBytes { - testPrivateKeys[t], err = ParseRawPrivateKey(k) - if err != nil { - panic(fmt.Sprintf("Unable to parse test key %s: %v", t, err)) - } - testSigners[t], err = NewSignerFromKey(testPrivateKeys[t]) - if err != nil { - panic(fmt.Sprintf("Unable to create signer for test key %s: %v", t, err)) - } - testPublicKeys[t] = testSigners[t].PublicKey() - } - - // Create a cert and sign it for use in tests. - testCert := &Certificate{ - Nonce: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil - ValidPrincipals: []string{"gopher1", "gopher2"}, // increases test coverage - ValidAfter: 0, // unix epoch - ValidBefore: CertTimeInfinity, // The end of currently representable time. - Reserved: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil - Key: testPublicKeys["ecdsa"], - SignatureKey: testPublicKeys["rsa"], - Permissions: Permissions{ - CriticalOptions: map[string]string{}, - Extensions: map[string]string{}, - }, - } - testCert.SignCert(rand.Reader, testSigners["rsa"]) - testPrivateKeys["cert"] = testPrivateKeys["ecdsa"] - testSigners["cert"], err = NewCertSigner(testCert, testSigners["ecdsa"]) - if err != nil { - panic(fmt.Sprintf("Unable to create certificate signer: %v", err)) - } -} diff --git a/vendor/golang.org/x/crypto/ssh/transport_test.go b/vendor/golang.org/x/crypto/ssh/transport_test.go deleted file mode 100644 index 8445e1e5..00000000 --- a/vendor/golang.org/x/crypto/ssh/transport_test.go +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ssh - -import ( - "bytes" - "crypto/rand" - "encoding/binary" - "strings" - "testing" -) - -func TestReadVersion(t *testing.T) { - longVersion := strings.Repeat("SSH-2.0-bla", 50)[:253] - multiLineVersion := strings.Repeat("ignored\r\n", 20) + "SSH-2.0-bla\r\n" - cases := map[string]string{ - "SSH-2.0-bla\r\n": "SSH-2.0-bla", - "SSH-2.0-bla\n": "SSH-2.0-bla", - multiLineVersion: "SSH-2.0-bla", - longVersion + "\r\n": longVersion, - } - - for in, want := range cases { - result, err := readVersion(bytes.NewBufferString(in)) - if err != nil { - t.Errorf("readVersion(%q): %s", in, err) - } - got := string(result) - if got != want { - t.Errorf("got %q, want %q", got, want) - } - } -} - -func TestReadVersionError(t *testing.T) { - longVersion := strings.Repeat("SSH-2.0-bla", 50)[:253] - multiLineVersion := strings.Repeat("ignored\r\n", 50) + "SSH-2.0-bla\r\n" - cases := []string{ - longVersion + "too-long\r\n", - multiLineVersion, - } - for _, in := range cases { - if _, err := readVersion(bytes.NewBufferString(in)); err == nil { - t.Errorf("readVersion(%q) should have failed", in) - } - } -} - -func TestExchangeVersionsBasic(t *testing.T) { - v := "SSH-2.0-bla" - buf := bytes.NewBufferString(v + "\r\n") - them, err := exchangeVersions(buf, []byte("xyz")) - if err != nil { - t.Errorf("exchangeVersions: %v", err) - } - - if want := "SSH-2.0-bla"; string(them) != want { - t.Errorf("got %q want %q for our version", them, want) - } -} - -func TestExchangeVersions(t *testing.T) { - cases := []string{ - "not\x000allowed", - "not allowed\x01\r\n", - } - for _, c := range cases { - buf := bytes.NewBufferString("SSH-2.0-bla\r\n") - if _, err := exchangeVersions(buf, []byte(c)); err == nil { - t.Errorf("exchangeVersions(%q): should have failed", c) - } - } -} - -type closerBuffer struct { - bytes.Buffer -} - -func (b *closerBuffer) Close() error { - return nil -} - -func TestTransportMaxPacketWrite(t *testing.T) { - buf := &closerBuffer{} - tr := newTransport(buf, rand.Reader, true) - huge := make([]byte, maxPacket+1) - err := tr.writePacket(huge) - if err == nil { - t.Errorf("transport accepted write for a huge packet.") - } -} - -func TestTransportMaxPacketReader(t *testing.T) { - var header [5]byte - huge := make([]byte, maxPacket+128) - binary.BigEndian.PutUint32(header[0:], uint32(len(huge))) - // padding. - header[4] = 0 - - buf := &closerBuffer{} - buf.Write(header[:]) - buf.Write(huge) - - tr := newTransport(buf, rand.Reader, true) - _, err := tr.readPacket() - if err == nil { - t.Errorf("transport succeeded reading huge packet.") - } else if !strings.Contains(err.Error(), "large") { - t.Errorf("got %q, should mention %q", err.Error(), "large") - } -} diff --git a/vendor/golang.org/x/net/CONTRIBUTING.md b/vendor/golang.org/x/net/CONTRIBUTING.md deleted file mode 100644 index d0485e88..00000000 --- a/vendor/golang.org/x/net/CONTRIBUTING.md +++ /dev/null @@ -1,26 +0,0 @@ -# Contributing to Go - -Go is an open source project. - -It is the work of hundreds of contributors. We appreciate your help! - -## Filing issues - -When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions: - -1. What version of Go are you using (`go version`)? -2. What operating system and processor architecture are you using? -3. What did you do? -4. What did you expect to see? -5. What did you see instead? - -General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker. -The gophers there will answer or ask you to file an issue if you've tripped over a bug. - -## Contributing code - -Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html) -before sending patches. - -Unless otherwise noted, the Go source files are distributed under -the BSD-style license found in the LICENSE file. diff --git a/vendor/golang.org/x/net/README.md b/vendor/golang.org/x/net/README.md deleted file mode 100644 index 00a9b6eb..00000000 --- a/vendor/golang.org/x/net/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# Go Networking - -This repository holds supplementary Go networking libraries. - -## Download/Install - -The easiest way to install is to run `go get -u golang.org/x/net`. You can -also manually git clone the repository to `$GOPATH/src/golang.org/x/net`. - -## Report Issues / Send Patches - -This repository uses Gerrit for code changes. To learn how to submit -changes to this repository, see https://golang.org/doc/contribute.html. -The main issue tracker for the net repository is located at -https://github.com/golang/go/issues. Prefix your issue with "x/net:" in the -subject line, so it is easy to find. diff --git a/vendor/golang.org/x/net/codereview.cfg b/vendor/golang.org/x/net/codereview.cfg deleted file mode 100644 index 3f8b14b6..00000000 --- a/vendor/golang.org/x/net/codereview.cfg +++ /dev/null @@ -1 +0,0 @@ -issuerepo: golang/go diff --git a/vendor/golang.org/x/net/context/context_test.go b/vendor/golang.org/x/net/context/context_test.go deleted file mode 100644 index 62844131..00000000 --- a/vendor/golang.org/x/net/context/context_test.go +++ /dev/null @@ -1,583 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !go1.7 - -package context - -import ( - "fmt" - "math/rand" - "runtime" - "strings" - "sync" - "testing" - "time" -) - -// otherContext is a Context that's not one of the types defined in context.go. -// This lets us test code paths that differ based on the underlying type of the -// Context. -type otherContext struct { - Context -} - -func TestBackground(t *testing.T) { - c := Background() - if c == nil { - t.Fatalf("Background returned nil") - } - select { - case x := <-c.Done(): - t.Errorf("<-c.Done() == %v want nothing (it should block)", x) - default: - } - if got, want := fmt.Sprint(c), "context.Background"; got != want { - t.Errorf("Background().String() = %q want %q", got, want) - } -} - -func TestTODO(t *testing.T) { - c := TODO() - if c == nil { - t.Fatalf("TODO returned nil") - } - select { - case x := <-c.Done(): - t.Errorf("<-c.Done() == %v want nothing (it should block)", x) - default: - } - if got, want := fmt.Sprint(c), "context.TODO"; got != want { - t.Errorf("TODO().String() = %q want %q", got, want) - } -} - -func TestWithCancel(t *testing.T) { - c1, cancel := WithCancel(Background()) - - if got, want := fmt.Sprint(c1), "context.Background.WithCancel"; got != want { - t.Errorf("c1.String() = %q want %q", got, want) - } - - o := otherContext{c1} - c2, _ := WithCancel(o) - contexts := []Context{c1, o, c2} - - for i, c := range contexts { - if d := c.Done(); d == nil { - t.Errorf("c[%d].Done() == %v want non-nil", i, d) - } - if e := c.Err(); e != nil { - t.Errorf("c[%d].Err() == %v want nil", i, e) - } - - select { - case x := <-c.Done(): - t.Errorf("<-c.Done() == %v want nothing (it should block)", x) - default: - } - } - - cancel() - time.Sleep(100 * time.Millisecond) // let cancelation propagate - - for i, c := range contexts { - select { - case <-c.Done(): - default: - t.Errorf("<-c[%d].Done() blocked, but shouldn't have", i) - } - if e := c.Err(); e != Canceled { - t.Errorf("c[%d].Err() == %v want %v", i, e, Canceled) - } - } -} - -func TestParentFinishesChild(t *testing.T) { - // Context tree: - // parent -> cancelChild - // parent -> valueChild -> timerChild - parent, cancel := WithCancel(Background()) - cancelChild, stop := WithCancel(parent) - defer stop() - valueChild := WithValue(parent, "key", "value") - timerChild, stop := WithTimeout(valueChild, 10000*time.Hour) - defer stop() - - select { - case x := <-parent.Done(): - t.Errorf("<-parent.Done() == %v want nothing (it should block)", x) - case x := <-cancelChild.Done(): - t.Errorf("<-cancelChild.Done() == %v want nothing (it should block)", x) - case x := <-timerChild.Done(): - t.Errorf("<-timerChild.Done() == %v want nothing (it should block)", x) - case x := <-valueChild.Done(): - t.Errorf("<-valueChild.Done() == %v want nothing (it should block)", x) - default: - } - - // The parent's children should contain the two cancelable children. - pc := parent.(*cancelCtx) - cc := cancelChild.(*cancelCtx) - tc := timerChild.(*timerCtx) - pc.mu.Lock() - if len(pc.children) != 2 || !pc.children[cc] || !pc.children[tc] { - t.Errorf("bad linkage: pc.children = %v, want %v and %v", - pc.children, cc, tc) - } - pc.mu.Unlock() - - if p, ok := parentCancelCtx(cc.Context); !ok || p != pc { - t.Errorf("bad linkage: parentCancelCtx(cancelChild.Context) = %v, %v want %v, true", p, ok, pc) - } - if p, ok := parentCancelCtx(tc.Context); !ok || p != pc { - t.Errorf("bad linkage: parentCancelCtx(timerChild.Context) = %v, %v want %v, true", p, ok, pc) - } - - cancel() - - pc.mu.Lock() - if len(pc.children) != 0 { - t.Errorf("pc.cancel didn't clear pc.children = %v", pc.children) - } - pc.mu.Unlock() - - // parent and children should all be finished. - check := func(ctx Context, name string) { - select { - case <-ctx.Done(): - default: - t.Errorf("<-%s.Done() blocked, but shouldn't have", name) - } - if e := ctx.Err(); e != Canceled { - t.Errorf("%s.Err() == %v want %v", name, e, Canceled) - } - } - check(parent, "parent") - check(cancelChild, "cancelChild") - check(valueChild, "valueChild") - check(timerChild, "timerChild") - - // WithCancel should return a canceled context on a canceled parent. - precanceledChild := WithValue(parent, "key", "value") - select { - case <-precanceledChild.Done(): - default: - t.Errorf("<-precanceledChild.Done() blocked, but shouldn't have") - } - if e := precanceledChild.Err(); e != Canceled { - t.Errorf("precanceledChild.Err() == %v want %v", e, Canceled) - } -} - -func TestChildFinishesFirst(t *testing.T) { - cancelable, stop := WithCancel(Background()) - defer stop() - for _, parent := range []Context{Background(), cancelable} { - child, cancel := WithCancel(parent) - - select { - case x := <-parent.Done(): - t.Errorf("<-parent.Done() == %v want nothing (it should block)", x) - case x := <-child.Done(): - t.Errorf("<-child.Done() == %v want nothing (it should block)", x) - default: - } - - cc := child.(*cancelCtx) - pc, pcok := parent.(*cancelCtx) // pcok == false when parent == Background() - if p, ok := parentCancelCtx(cc.Context); ok != pcok || (ok && pc != p) { - t.Errorf("bad linkage: parentCancelCtx(cc.Context) = %v, %v want %v, %v", p, ok, pc, pcok) - } - - if pcok { - pc.mu.Lock() - if len(pc.children) != 1 || !pc.children[cc] { - t.Errorf("bad linkage: pc.children = %v, cc = %v", pc.children, cc) - } - pc.mu.Unlock() - } - - cancel() - - if pcok { - pc.mu.Lock() - if len(pc.children) != 0 { - t.Errorf("child's cancel didn't remove self from pc.children = %v", pc.children) - } - pc.mu.Unlock() - } - - // child should be finished. - select { - case <-child.Done(): - default: - t.Errorf("<-child.Done() blocked, but shouldn't have") - } - if e := child.Err(); e != Canceled { - t.Errorf("child.Err() == %v want %v", e, Canceled) - } - - // parent should not be finished. - select { - case x := <-parent.Done(): - t.Errorf("<-parent.Done() == %v want nothing (it should block)", x) - default: - } - if e := parent.Err(); e != nil { - t.Errorf("parent.Err() == %v want nil", e) - } - } -} - -func testDeadline(c Context, wait time.Duration, t *testing.T) { - select { - case <-time.After(wait): - t.Fatalf("context should have timed out") - case <-c.Done(): - } - if e := c.Err(); e != DeadlineExceeded { - t.Errorf("c.Err() == %v want %v", e, DeadlineExceeded) - } -} - -func TestDeadline(t *testing.T) { - t.Parallel() - const timeUnit = 500 * time.Millisecond - c, _ := WithDeadline(Background(), time.Now().Add(1*timeUnit)) - if got, prefix := fmt.Sprint(c), "context.Background.WithDeadline("; !strings.HasPrefix(got, prefix) { - t.Errorf("c.String() = %q want prefix %q", got, prefix) - } - testDeadline(c, 2*timeUnit, t) - - c, _ = WithDeadline(Background(), time.Now().Add(1*timeUnit)) - o := otherContext{c} - testDeadline(o, 2*timeUnit, t) - - c, _ = WithDeadline(Background(), time.Now().Add(1*timeUnit)) - o = otherContext{c} - c, _ = WithDeadline(o, time.Now().Add(3*timeUnit)) - testDeadline(c, 2*timeUnit, t) -} - -func TestTimeout(t *testing.T) { - t.Parallel() - const timeUnit = 500 * time.Millisecond - c, _ := WithTimeout(Background(), 1*timeUnit) - if got, prefix := fmt.Sprint(c), "context.Background.WithDeadline("; !strings.HasPrefix(got, prefix) { - t.Errorf("c.String() = %q want prefix %q", got, prefix) - } - testDeadline(c, 2*timeUnit, t) - - c, _ = WithTimeout(Background(), 1*timeUnit) - o := otherContext{c} - testDeadline(o, 2*timeUnit, t) - - c, _ = WithTimeout(Background(), 1*timeUnit) - o = otherContext{c} - c, _ = WithTimeout(o, 3*timeUnit) - testDeadline(c, 2*timeUnit, t) -} - -func TestCanceledTimeout(t *testing.T) { - t.Parallel() - const timeUnit = 500 * time.Millisecond - c, _ := WithTimeout(Background(), 2*timeUnit) - o := otherContext{c} - c, cancel := WithTimeout(o, 4*timeUnit) - cancel() - time.Sleep(1 * timeUnit) // let cancelation propagate - select { - case <-c.Done(): - default: - t.Errorf("<-c.Done() blocked, but shouldn't have") - } - if e := c.Err(); e != Canceled { - t.Errorf("c.Err() == %v want %v", e, Canceled) - } -} - -type key1 int -type key2 int - -var k1 = key1(1) -var k2 = key2(1) // same int as k1, different type -var k3 = key2(3) // same type as k2, different int - -func TestValues(t *testing.T) { - check := func(c Context, nm, v1, v2, v3 string) { - if v, ok := c.Value(k1).(string); ok == (len(v1) == 0) || v != v1 { - t.Errorf(`%s.Value(k1).(string) = %q, %t want %q, %t`, nm, v, ok, v1, len(v1) != 0) - } - if v, ok := c.Value(k2).(string); ok == (len(v2) == 0) || v != v2 { - t.Errorf(`%s.Value(k2).(string) = %q, %t want %q, %t`, nm, v, ok, v2, len(v2) != 0) - } - if v, ok := c.Value(k3).(string); ok == (len(v3) == 0) || v != v3 { - t.Errorf(`%s.Value(k3).(string) = %q, %t want %q, %t`, nm, v, ok, v3, len(v3) != 0) - } - } - - c0 := Background() - check(c0, "c0", "", "", "") - - c1 := WithValue(Background(), k1, "c1k1") - check(c1, "c1", "c1k1", "", "") - - if got, want := fmt.Sprint(c1), `context.Background.WithValue(1, "c1k1")`; got != want { - t.Errorf("c.String() = %q want %q", got, want) - } - - c2 := WithValue(c1, k2, "c2k2") - check(c2, "c2", "c1k1", "c2k2", "") - - c3 := WithValue(c2, k3, "c3k3") - check(c3, "c2", "c1k1", "c2k2", "c3k3") - - c4 := WithValue(c3, k1, nil) - check(c4, "c4", "", "c2k2", "c3k3") - - o0 := otherContext{Background()} - check(o0, "o0", "", "", "") - - o1 := otherContext{WithValue(Background(), k1, "c1k1")} - check(o1, "o1", "c1k1", "", "") - - o2 := WithValue(o1, k2, "o2k2") - check(o2, "o2", "c1k1", "o2k2", "") - - o3 := otherContext{c4} - check(o3, "o3", "", "c2k2", "c3k3") - - o4 := WithValue(o3, k3, nil) - check(o4, "o4", "", "c2k2", "") -} - -func TestAllocs(t *testing.T) { - bg := Background() - for _, test := range []struct { - desc string - f func() - limit float64 - gccgoLimit float64 - }{ - { - desc: "Background()", - f: func() { Background() }, - limit: 0, - gccgoLimit: 0, - }, - { - desc: fmt.Sprintf("WithValue(bg, %v, nil)", k1), - f: func() { - c := WithValue(bg, k1, nil) - c.Value(k1) - }, - limit: 3, - gccgoLimit: 3, - }, - { - desc: "WithTimeout(bg, 15*time.Millisecond)", - f: func() { - c, _ := WithTimeout(bg, 15*time.Millisecond) - <-c.Done() - }, - limit: 8, - gccgoLimit: 16, - }, - { - desc: "WithCancel(bg)", - f: func() { - c, cancel := WithCancel(bg) - cancel() - <-c.Done() - }, - limit: 5, - gccgoLimit: 8, - }, - { - desc: "WithTimeout(bg, 100*time.Millisecond)", - f: func() { - c, cancel := WithTimeout(bg, 100*time.Millisecond) - cancel() - <-c.Done() - }, - limit: 8, - gccgoLimit: 25, - }, - } { - limit := test.limit - if runtime.Compiler == "gccgo" { - // gccgo does not yet do escape analysis. - // TODO(iant): Remove this when gccgo does do escape analysis. - limit = test.gccgoLimit - } - if n := testing.AllocsPerRun(100, test.f); n > limit { - t.Errorf("%s allocs = %f want %d", test.desc, n, int(limit)) - } - } -} - -func TestSimultaneousCancels(t *testing.T) { - root, cancel := WithCancel(Background()) - m := map[Context]CancelFunc{root: cancel} - q := []Context{root} - // Create a tree of contexts. - for len(q) != 0 && len(m) < 100 { - parent := q[0] - q = q[1:] - for i := 0; i < 4; i++ { - ctx, cancel := WithCancel(parent) - m[ctx] = cancel - q = append(q, ctx) - } - } - // Start all the cancels in a random order. - var wg sync.WaitGroup - wg.Add(len(m)) - for _, cancel := range m { - go func(cancel CancelFunc) { - cancel() - wg.Done() - }(cancel) - } - // Wait on all the contexts in a random order. - for ctx := range m { - select { - case <-ctx.Done(): - case <-time.After(1 * time.Second): - buf := make([]byte, 10<<10) - n := runtime.Stack(buf, true) - t.Fatalf("timed out waiting for <-ctx.Done(); stacks:\n%s", buf[:n]) - } - } - // Wait for all the cancel functions to return. - done := make(chan struct{}) - go func() { - wg.Wait() - close(done) - }() - select { - case <-done: - case <-time.After(1 * time.Second): - buf := make([]byte, 10<<10) - n := runtime.Stack(buf, true) - t.Fatalf("timed out waiting for cancel functions; stacks:\n%s", buf[:n]) - } -} - -func TestInterlockedCancels(t *testing.T) { - parent, cancelParent := WithCancel(Background()) - child, cancelChild := WithCancel(parent) - go func() { - parent.Done() - cancelChild() - }() - cancelParent() - select { - case <-child.Done(): - case <-time.After(1 * time.Second): - buf := make([]byte, 10<<10) - n := runtime.Stack(buf, true) - t.Fatalf("timed out waiting for child.Done(); stacks:\n%s", buf[:n]) - } -} - -func TestLayersCancel(t *testing.T) { - testLayers(t, time.Now().UnixNano(), false) -} - -func TestLayersTimeout(t *testing.T) { - testLayers(t, time.Now().UnixNano(), true) -} - -func testLayers(t *testing.T, seed int64, testTimeout bool) { - rand.Seed(seed) - errorf := func(format string, a ...interface{}) { - t.Errorf(fmt.Sprintf("seed=%d: %s", seed, format), a...) - } - const ( - timeout = 200 * time.Millisecond - minLayers = 30 - ) - type value int - var ( - vals []*value - cancels []CancelFunc - numTimers int - ctx = Background() - ) - for i := 0; i < minLayers || numTimers == 0 || len(cancels) == 0 || len(vals) == 0; i++ { - switch rand.Intn(3) { - case 0: - v := new(value) - ctx = WithValue(ctx, v, v) - vals = append(vals, v) - case 1: - var cancel CancelFunc - ctx, cancel = WithCancel(ctx) - cancels = append(cancels, cancel) - case 2: - var cancel CancelFunc - ctx, cancel = WithTimeout(ctx, timeout) - cancels = append(cancels, cancel) - numTimers++ - } - } - checkValues := func(when string) { - for _, key := range vals { - if val := ctx.Value(key).(*value); key != val { - errorf("%s: ctx.Value(%p) = %p want %p", when, key, val, key) - } - } - } - select { - case <-ctx.Done(): - errorf("ctx should not be canceled yet") - default: - } - if s, prefix := fmt.Sprint(ctx), "context.Background."; !strings.HasPrefix(s, prefix) { - t.Errorf("ctx.String() = %q want prefix %q", s, prefix) - } - t.Log(ctx) - checkValues("before cancel") - if testTimeout { - select { - case <-ctx.Done(): - case <-time.After(timeout + 100*time.Millisecond): - errorf("ctx should have timed out") - } - checkValues("after timeout") - } else { - cancel := cancels[rand.Intn(len(cancels))] - cancel() - select { - case <-ctx.Done(): - default: - errorf("ctx should be canceled") - } - checkValues("after cancel") - } -} - -func TestCancelRemoves(t *testing.T) { - checkChildren := func(when string, ctx Context, want int) { - if got := len(ctx.(*cancelCtx).children); got != want { - t.Errorf("%s: context has %d children, want %d", when, got, want) - } - } - - ctx, _ := WithCancel(Background()) - checkChildren("after creation", ctx, 0) - _, cancel := WithCancel(ctx) - checkChildren("with WithCancel child ", ctx, 1) - cancel() - checkChildren("after cancelling WithCancel child", ctx, 0) - - ctx, _ = WithCancel(Background()) - checkChildren("after creation", ctx, 0) - _, cancel = WithTimeout(ctx, 60*time.Minute) - checkChildren("with WithTimeout child ", ctx, 1) - cancel() - checkChildren("after cancelling WithTimeout child", ctx, 0) -} diff --git a/vendor/golang.org/x/net/context/withtimeout_test.go b/vendor/golang.org/x/net/context/withtimeout_test.go deleted file mode 100644 index e6f56691..00000000 --- a/vendor/golang.org/x/net/context/withtimeout_test.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package context_test - -import ( - "fmt" - "time" - - "golang.org/x/net/context" -) - -// This example passes a context with a timeout to tell a blocking function that -// it should abandon its work after the timeout elapses. -func ExampleWithTimeout() { - // Pass a context with a timeout to tell a blocking function that it - // should abandon its work after the timeout elapses. - ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond) - defer cancel() - - select { - case <-time.After(1 * time.Second): - fmt.Println("overslept") - case <-ctx.Done(): - fmt.Println(ctx.Err()) // prints "context deadline exceeded" - } - - // Output: - // context deadline exceeded -} diff --git a/vendor/golang.org/x/net/http/httpguts/httplex_test.go b/vendor/golang.org/x/net/http/httpguts/httplex_test.go deleted file mode 100644 index a2c57f39..00000000 --- a/vendor/golang.org/x/net/http/httpguts/httplex_test.go +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package httpguts - -import ( - "testing" -) - -func isChar(c rune) bool { return c <= 127 } - -func isCtl(c rune) bool { return c <= 31 || c == 127 } - -func isSeparator(c rune) bool { - switch c { - case '(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '{', '}', ' ', '\t': - return true - } - return false -} - -func TestIsToken(t *testing.T) { - for i := 0; i <= 130; i++ { - r := rune(i) - expected := isChar(r) && !isCtl(r) && !isSeparator(r) - if IsTokenRune(r) != expected { - t.Errorf("isToken(0x%x) = %v", r, !expected) - } - } -} - -func TestHeaderValuesContainsToken(t *testing.T) { - tests := []struct { - vals []string - token string - want bool - }{ - { - vals: []string{"foo"}, - token: "foo", - want: true, - }, - { - vals: []string{"bar", "foo"}, - token: "foo", - want: true, - }, - { - vals: []string{"foo"}, - token: "FOO", - want: true, - }, - { - vals: []string{"foo"}, - token: "bar", - want: false, - }, - { - vals: []string{" foo "}, - token: "FOO", - want: true, - }, - { - vals: []string{"foo,bar"}, - token: "FOO", - want: true, - }, - { - vals: []string{"bar,foo,bar"}, - token: "FOO", - want: true, - }, - { - vals: []string{"bar , foo"}, - token: "FOO", - want: true, - }, - { - vals: []string{"foo ,bar "}, - token: "FOO", - want: true, - }, - { - vals: []string{"bar, foo ,bar"}, - token: "FOO", - want: true, - }, - { - vals: []string{"bar , foo"}, - token: "FOO", - want: true, - }, - } - for _, tt := range tests { - got := HeaderValuesContainsToken(tt.vals, tt.token) - if got != tt.want { - t.Errorf("headerValuesContainsToken(%q, %q) = %v; want %v", tt.vals, tt.token, got, tt.want) - } - } -} - -func TestPunycodeHostPort(t *testing.T) { - tests := []struct { - in, want string - }{ - {"www.google.com", "www.google.com"}, - {"гофер.рф", "xn--c1ae0ajs.xn--p1ai"}, - {"bücher.de", "xn--bcher-kva.de"}, - {"bücher.de:8080", "xn--bcher-kva.de:8080"}, - {"[1::6]:8080", "[1::6]:8080"}, - } - for _, tt := range tests { - got, err := PunycodeHostPort(tt.in) - if tt.want != got || err != nil { - t.Errorf("PunycodeHostPort(%q) = %q, %v, want %q, nil", tt.in, got, err, tt.want) - } - } -} diff --git a/vendor/golang.org/x/net/http2/Dockerfile b/vendor/golang.org/x/net/http2/Dockerfile deleted file mode 100644 index 53fc5257..00000000 --- a/vendor/golang.org/x/net/http2/Dockerfile +++ /dev/null @@ -1,51 +0,0 @@ -# -# This Dockerfile builds a recent curl with HTTP/2 client support, using -# a recent nghttp2 build. -# -# See the Makefile for how to tag it. If Docker and that image is found, the -# Go tests use this curl binary for integration tests. -# - -FROM ubuntu:trusty - -RUN apt-get update && \ - apt-get upgrade -y && \ - apt-get install -y git-core build-essential wget - -RUN apt-get install -y --no-install-recommends \ - autotools-dev libtool pkg-config zlib1g-dev \ - libcunit1-dev libssl-dev libxml2-dev libevent-dev \ - automake autoconf - -# The list of packages nghttp2 recommends for h2load: -RUN apt-get install -y --no-install-recommends make binutils \ - autoconf automake autotools-dev \ - libtool pkg-config zlib1g-dev libcunit1-dev libssl-dev libxml2-dev \ - libev-dev libevent-dev libjansson-dev libjemalloc-dev \ - cython python3.4-dev python-setuptools - -# Note: setting NGHTTP2_VER before the git clone, so an old git clone isn't cached: -ENV NGHTTP2_VER 895da9a -RUN cd /root && git clone https://github.com/tatsuhiro-t/nghttp2.git - -WORKDIR /root/nghttp2 -RUN git reset --hard $NGHTTP2_VER -RUN autoreconf -i -RUN automake -RUN autoconf -RUN ./configure -RUN make -RUN make install - -WORKDIR /root -RUN wget http://curl.haxx.se/download/curl-7.45.0.tar.gz -RUN tar -zxvf curl-7.45.0.tar.gz -WORKDIR /root/curl-7.45.0 -RUN ./configure --with-ssl --with-nghttp2=/usr/local -RUN make -RUN make install -RUN ldconfig - -CMD ["-h"] -ENTRYPOINT ["/usr/local/bin/curl"] - diff --git a/vendor/golang.org/x/net/http2/Makefile b/vendor/golang.org/x/net/http2/Makefile deleted file mode 100644 index 55fd826f..00000000 --- a/vendor/golang.org/x/net/http2/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -curlimage: - docker build -t gohttp2/curl . - diff --git a/vendor/golang.org/x/net/http2/README b/vendor/golang.org/x/net/http2/README deleted file mode 100644 index 360d5aa3..00000000 --- a/vendor/golang.org/x/net/http2/README +++ /dev/null @@ -1,20 +0,0 @@ -This is a work-in-progress HTTP/2 implementation for Go. - -It will eventually live in the Go standard library and won't require -any changes to your code to use. It will just be automatic. - -Status: - -* The server support is pretty good. A few things are missing - but are being worked on. -* The client work has just started but shares a lot of code - is coming along much quicker. - -Docs are at https://godoc.org/golang.org/x/net/http2 - -Demo test server at https://http2.golang.org/ - -Help & bug reports welcome! - -Contributing: https://golang.org/doc/contribute.html -Bugs: https://golang.org/issue/new?title=x/net/http2:+ diff --git a/vendor/golang.org/x/net/http2/ciphers_test.go b/vendor/golang.org/x/net/http2/ciphers_test.go deleted file mode 100644 index 764bbc8c..00000000 --- a/vendor/golang.org/x/net/http2/ciphers_test.go +++ /dev/null @@ -1,309 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package http2 - -import "testing" - -func TestIsBadCipherBad(t *testing.T) { - for _, c := range badCiphers { - if !isBadCipher(c) { - t.Errorf("Wrong result for isBadCipher(%d), want true", c) - } - } -} - -// verify we don't give false positives on ciphers not on blacklist -func TestIsBadCipherGood(t *testing.T) { - goodCiphers := map[uint16]string{ - cipher_TLS_DHE_RSA_WITH_AES_256_CCM: "cipher_TLS_DHE_RSA_WITH_AES_256_CCM", - cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CCM: "cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CCM", - cipher_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256: "cipher_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256", - } - for c, name := range goodCiphers { - if isBadCipher(c) { - t.Errorf("Wrong result for isBadCipher(%d) %s, want false", c, name) - } - } -} - -// copied from https://http2.github.io/http2-spec/#BadCipherSuites, -var badCiphers = []uint16{ - cipher_TLS_NULL_WITH_NULL_NULL, - cipher_TLS_RSA_WITH_NULL_MD5, - cipher_TLS_RSA_WITH_NULL_SHA, - cipher_TLS_RSA_EXPORT_WITH_RC4_40_MD5, - cipher_TLS_RSA_WITH_RC4_128_MD5, - cipher_TLS_RSA_WITH_RC4_128_SHA, - cipher_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5, - cipher_TLS_RSA_WITH_IDEA_CBC_SHA, - cipher_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA, - cipher_TLS_RSA_WITH_DES_CBC_SHA, - cipher_TLS_RSA_WITH_3DES_EDE_CBC_SHA, - cipher_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA, - cipher_TLS_DH_DSS_WITH_DES_CBC_SHA, - cipher_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA, - cipher_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA, - cipher_TLS_DH_RSA_WITH_DES_CBC_SHA, - cipher_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA, - cipher_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, - cipher_TLS_DHE_DSS_WITH_DES_CBC_SHA, - cipher_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, - cipher_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, - cipher_TLS_DHE_RSA_WITH_DES_CBC_SHA, - cipher_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, - cipher_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5, - cipher_TLS_DH_anon_WITH_RC4_128_MD5, - cipher_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA, - cipher_TLS_DH_anon_WITH_DES_CBC_SHA, - cipher_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA, - cipher_TLS_KRB5_WITH_DES_CBC_SHA, - cipher_TLS_KRB5_WITH_3DES_EDE_CBC_SHA, - cipher_TLS_KRB5_WITH_RC4_128_SHA, - cipher_TLS_KRB5_WITH_IDEA_CBC_SHA, - cipher_TLS_KRB5_WITH_DES_CBC_MD5, - cipher_TLS_KRB5_WITH_3DES_EDE_CBC_MD5, - cipher_TLS_KRB5_WITH_RC4_128_MD5, - cipher_TLS_KRB5_WITH_IDEA_CBC_MD5, - cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA, - cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA, - cipher_TLS_KRB5_EXPORT_WITH_RC4_40_SHA, - cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5, - cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5, - cipher_TLS_KRB5_EXPORT_WITH_RC4_40_MD5, - cipher_TLS_PSK_WITH_NULL_SHA, - cipher_TLS_DHE_PSK_WITH_NULL_SHA, - cipher_TLS_RSA_PSK_WITH_NULL_SHA, - cipher_TLS_RSA_WITH_AES_128_CBC_SHA, - cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA, - cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA, - cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA, - cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, - cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA, - cipher_TLS_RSA_WITH_AES_256_CBC_SHA, - cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA, - cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA, - cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA, - cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, - cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA, - cipher_TLS_RSA_WITH_NULL_SHA256, - cipher_TLS_RSA_WITH_AES_128_CBC_SHA256, - cipher_TLS_RSA_WITH_AES_256_CBC_SHA256, - cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA256, - cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA256, - cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, - cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, - cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA, - cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA, - cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA, - cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, - cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA, - cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, - cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA256, - cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA256, - cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, - cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, - cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA256, - cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA256, - cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, - cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA, - cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA, - cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA, - cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, - cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA, - cipher_TLS_PSK_WITH_RC4_128_SHA, - cipher_TLS_PSK_WITH_3DES_EDE_CBC_SHA, - cipher_TLS_PSK_WITH_AES_128_CBC_SHA, - cipher_TLS_PSK_WITH_AES_256_CBC_SHA, - cipher_TLS_DHE_PSK_WITH_RC4_128_SHA, - cipher_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, - cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, - cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, - cipher_TLS_RSA_PSK_WITH_RC4_128_SHA, - cipher_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, - cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, - cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, - cipher_TLS_RSA_WITH_SEED_CBC_SHA, - cipher_TLS_DH_DSS_WITH_SEED_CBC_SHA, - cipher_TLS_DH_RSA_WITH_SEED_CBC_SHA, - cipher_TLS_DHE_DSS_WITH_SEED_CBC_SHA, - cipher_TLS_DHE_RSA_WITH_SEED_CBC_SHA, - cipher_TLS_DH_anon_WITH_SEED_CBC_SHA, - cipher_TLS_RSA_WITH_AES_128_GCM_SHA256, - cipher_TLS_RSA_WITH_AES_256_GCM_SHA384, - cipher_TLS_DH_RSA_WITH_AES_128_GCM_SHA256, - cipher_TLS_DH_RSA_WITH_AES_256_GCM_SHA384, - cipher_TLS_DH_DSS_WITH_AES_128_GCM_SHA256, - cipher_TLS_DH_DSS_WITH_AES_256_GCM_SHA384, - cipher_TLS_DH_anon_WITH_AES_128_GCM_SHA256, - cipher_TLS_DH_anon_WITH_AES_256_GCM_SHA384, - cipher_TLS_PSK_WITH_AES_128_GCM_SHA256, - cipher_TLS_PSK_WITH_AES_256_GCM_SHA384, - cipher_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, - cipher_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, - cipher_TLS_PSK_WITH_AES_128_CBC_SHA256, - cipher_TLS_PSK_WITH_AES_256_CBC_SHA384, - cipher_TLS_PSK_WITH_NULL_SHA256, - cipher_TLS_PSK_WITH_NULL_SHA384, - cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, - cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, - cipher_TLS_DHE_PSK_WITH_NULL_SHA256, - cipher_TLS_DHE_PSK_WITH_NULL_SHA384, - cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, - cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, - cipher_TLS_RSA_PSK_WITH_NULL_SHA256, - cipher_TLS_RSA_PSK_WITH_NULL_SHA384, - cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, - cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256, - cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256, - cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256, - cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, - cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256, - cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, - cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256, - cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256, - cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256, - cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, - cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256, - cipher_TLS_EMPTY_RENEGOTIATION_INFO_SCSV, - cipher_TLS_ECDH_ECDSA_WITH_NULL_SHA, - cipher_TLS_ECDH_ECDSA_WITH_RC4_128_SHA, - cipher_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, - cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, - cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, - cipher_TLS_ECDHE_ECDSA_WITH_NULL_SHA, - cipher_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, - cipher_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, - cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, - cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, - cipher_TLS_ECDH_RSA_WITH_NULL_SHA, - cipher_TLS_ECDH_RSA_WITH_RC4_128_SHA, - cipher_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, - cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, - cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, - cipher_TLS_ECDHE_RSA_WITH_NULL_SHA, - cipher_TLS_ECDHE_RSA_WITH_RC4_128_SHA, - cipher_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, - cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, - cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, - cipher_TLS_ECDH_anon_WITH_NULL_SHA, - cipher_TLS_ECDH_anon_WITH_RC4_128_SHA, - cipher_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA, - cipher_TLS_ECDH_anon_WITH_AES_128_CBC_SHA, - cipher_TLS_ECDH_anon_WITH_AES_256_CBC_SHA, - cipher_TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA, - cipher_TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA, - cipher_TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA, - cipher_TLS_SRP_SHA_WITH_AES_128_CBC_SHA, - cipher_TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA, - cipher_TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA, - cipher_TLS_SRP_SHA_WITH_AES_256_CBC_SHA, - cipher_TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA, - cipher_TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA, - cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, - cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, - cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, - cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, - cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, - cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, - cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, - cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, - cipher_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, - cipher_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, - cipher_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, - cipher_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, - cipher_TLS_ECDHE_PSK_WITH_RC4_128_SHA, - cipher_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, - cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, - cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, - cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, - cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, - cipher_TLS_ECDHE_PSK_WITH_NULL_SHA, - cipher_TLS_ECDHE_PSK_WITH_NULL_SHA256, - cipher_TLS_ECDHE_PSK_WITH_NULL_SHA384, - cipher_TLS_RSA_WITH_ARIA_128_CBC_SHA256, - cipher_TLS_RSA_WITH_ARIA_256_CBC_SHA384, - cipher_TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256, - cipher_TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384, - cipher_TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256, - cipher_TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384, - cipher_TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256, - cipher_TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384, - cipher_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256, - cipher_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384, - cipher_TLS_DH_anon_WITH_ARIA_128_CBC_SHA256, - cipher_TLS_DH_anon_WITH_ARIA_256_CBC_SHA384, - cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256, - cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384, - cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256, - cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384, - cipher_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256, - cipher_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384, - cipher_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256, - cipher_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384, - cipher_TLS_RSA_WITH_ARIA_128_GCM_SHA256, - cipher_TLS_RSA_WITH_ARIA_256_GCM_SHA384, - cipher_TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256, - cipher_TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384, - cipher_TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256, - cipher_TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384, - cipher_TLS_DH_anon_WITH_ARIA_128_GCM_SHA256, - cipher_TLS_DH_anon_WITH_ARIA_256_GCM_SHA384, - cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256, - cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384, - cipher_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256, - cipher_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384, - cipher_TLS_PSK_WITH_ARIA_128_CBC_SHA256, - cipher_TLS_PSK_WITH_ARIA_256_CBC_SHA384, - cipher_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256, - cipher_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384, - cipher_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256, - cipher_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384, - cipher_TLS_PSK_WITH_ARIA_128_GCM_SHA256, - cipher_TLS_PSK_WITH_ARIA_256_GCM_SHA384, - cipher_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256, - cipher_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384, - cipher_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256, - cipher_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384, - cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, - cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, - cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, - cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, - cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, - cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, - cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, - cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, - cipher_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, - cipher_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, - cipher_TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256, - cipher_TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384, - cipher_TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256, - cipher_TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384, - cipher_TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256, - cipher_TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384, - cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, - cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, - cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, - cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, - cipher_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, - cipher_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, - cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, - cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, - cipher_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, - cipher_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, - cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, - cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, - cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, - cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, - cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, - cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, - cipher_TLS_RSA_WITH_AES_128_CCM, - cipher_TLS_RSA_WITH_AES_256_CCM, - cipher_TLS_RSA_WITH_AES_128_CCM_8, - cipher_TLS_RSA_WITH_AES_256_CCM_8, - cipher_TLS_PSK_WITH_AES_128_CCM, - cipher_TLS_PSK_WITH_AES_256_CCM, - cipher_TLS_PSK_WITH_AES_128_CCM_8, - cipher_TLS_PSK_WITH_AES_256_CCM_8, -} diff --git a/vendor/golang.org/x/net/http2/databuffer_test.go b/vendor/golang.org/x/net/http2/databuffer_test.go deleted file mode 100644 index 32cd5f38..00000000 --- a/vendor/golang.org/x/net/http2/databuffer_test.go +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package http2 - -import ( - "bytes" - "fmt" - "reflect" - "testing" -) - -func fmtDataChunk(chunk []byte) string { - out := "" - var last byte - var count int - for _, c := range chunk { - if c != last { - if count > 0 { - out += fmt.Sprintf(" x %d ", count) - count = 0 - } - out += string([]byte{c}) - last = c - } - count++ - } - if count > 0 { - out += fmt.Sprintf(" x %d", count) - } - return out -} - -func fmtDataChunks(chunks [][]byte) string { - var out string - for _, chunk := range chunks { - out += fmt.Sprintf("{%q}", fmtDataChunk(chunk)) - } - return out -} - -func testDataBuffer(t *testing.T, wantBytes []byte, setup func(t *testing.T) *dataBuffer) { - // Run setup, then read the remaining bytes from the dataBuffer and check - // that they match wantBytes. We use different read sizes to check corner - // cases in Read. - for _, readSize := range []int{1, 2, 1 * 1024, 32 * 1024} { - t.Run(fmt.Sprintf("ReadSize=%d", readSize), func(t *testing.T) { - b := setup(t) - buf := make([]byte, readSize) - var gotRead bytes.Buffer - for { - n, err := b.Read(buf) - gotRead.Write(buf[:n]) - if err == errReadEmpty { - break - } - if err != nil { - t.Fatalf("error after %v bytes: %v", gotRead.Len(), err) - } - } - if got, want := gotRead.Bytes(), wantBytes; !bytes.Equal(got, want) { - t.Errorf("FinalRead=%q, want %q", fmtDataChunk(got), fmtDataChunk(want)) - } - }) - } -} - -func TestDataBufferAllocation(t *testing.T) { - writes := [][]byte{ - bytes.Repeat([]byte("a"), 1*1024-1), - []byte("a"), - bytes.Repeat([]byte("b"), 4*1024-1), - []byte("b"), - bytes.Repeat([]byte("c"), 8*1024-1), - []byte("c"), - bytes.Repeat([]byte("d"), 16*1024-1), - []byte("d"), - bytes.Repeat([]byte("e"), 32*1024), - } - var wantRead bytes.Buffer - for _, p := range writes { - wantRead.Write(p) - } - - testDataBuffer(t, wantRead.Bytes(), func(t *testing.T) *dataBuffer { - b := &dataBuffer{} - for _, p := range writes { - if n, err := b.Write(p); n != len(p) || err != nil { - t.Fatalf("Write(%q x %d)=%v,%v want %v,nil", p[:1], len(p), n, err, len(p)) - } - } - want := [][]byte{ - bytes.Repeat([]byte("a"), 1*1024), - bytes.Repeat([]byte("b"), 4*1024), - bytes.Repeat([]byte("c"), 8*1024), - bytes.Repeat([]byte("d"), 16*1024), - bytes.Repeat([]byte("e"), 16*1024), - bytes.Repeat([]byte("e"), 16*1024), - } - if !reflect.DeepEqual(b.chunks, want) { - t.Errorf("dataBuffer.chunks\ngot: %s\nwant: %s", fmtDataChunks(b.chunks), fmtDataChunks(want)) - } - return b - }) -} - -func TestDataBufferAllocationWithExpected(t *testing.T) { - writes := [][]byte{ - bytes.Repeat([]byte("a"), 1*1024), // allocates 16KB - bytes.Repeat([]byte("b"), 14*1024), - bytes.Repeat([]byte("c"), 15*1024), // allocates 16KB more - bytes.Repeat([]byte("d"), 2*1024), - bytes.Repeat([]byte("e"), 1*1024), // overflows 32KB expectation, allocates just 1KB - } - var wantRead bytes.Buffer - for _, p := range writes { - wantRead.Write(p) - } - - testDataBuffer(t, wantRead.Bytes(), func(t *testing.T) *dataBuffer { - b := &dataBuffer{expected: 32 * 1024} - for _, p := range writes { - if n, err := b.Write(p); n != len(p) || err != nil { - t.Fatalf("Write(%q x %d)=%v,%v want %v,nil", p[:1], len(p), n, err, len(p)) - } - } - want := [][]byte{ - append(bytes.Repeat([]byte("a"), 1*1024), append(bytes.Repeat([]byte("b"), 14*1024), bytes.Repeat([]byte("c"), 1*1024)...)...), - append(bytes.Repeat([]byte("c"), 14*1024), bytes.Repeat([]byte("d"), 2*1024)...), - bytes.Repeat([]byte("e"), 1*1024), - } - if !reflect.DeepEqual(b.chunks, want) { - t.Errorf("dataBuffer.chunks\ngot: %s\nwant: %s", fmtDataChunks(b.chunks), fmtDataChunks(want)) - } - return b - }) -} - -func TestDataBufferWriteAfterPartialRead(t *testing.T) { - testDataBuffer(t, []byte("cdxyz"), func(t *testing.T) *dataBuffer { - b := &dataBuffer{} - if n, err := b.Write([]byte("abcd")); n != 4 || err != nil { - t.Fatalf("Write(\"abcd\")=%v,%v want 4,nil", n, err) - } - p := make([]byte, 2) - if n, err := b.Read(p); n != 2 || err != nil || !bytes.Equal(p, []byte("ab")) { - t.Fatalf("Read()=%q,%v,%v want \"ab\",2,nil", p, n, err) - } - if n, err := b.Write([]byte("xyz")); n != 3 || err != nil { - t.Fatalf("Write(\"xyz\")=%v,%v want 3,nil", n, err) - } - return b - }) -} diff --git a/vendor/golang.org/x/net/http2/errors_test.go b/vendor/golang.org/x/net/http2/errors_test.go deleted file mode 100644 index da5c58c3..00000000 --- a/vendor/golang.org/x/net/http2/errors_test.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package http2 - -import "testing" - -func TestErrCodeString(t *testing.T) { - tests := []struct { - err ErrCode - want string - }{ - {ErrCodeProtocol, "PROTOCOL_ERROR"}, - {0xd, "HTTP_1_1_REQUIRED"}, - {0xf, "unknown error code 0xf"}, - } - for i, tt := range tests { - got := tt.err.String() - if got != tt.want { - t.Errorf("%d. Error = %q; want %q", i, got, tt.want) - } - } -} diff --git a/vendor/golang.org/x/net/http2/flow_test.go b/vendor/golang.org/x/net/http2/flow_test.go deleted file mode 100644 index 7ae82c78..00000000 --- a/vendor/golang.org/x/net/http2/flow_test.go +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package http2 - -import "testing" - -func TestFlow(t *testing.T) { - var st flow - var conn flow - st.add(3) - conn.add(2) - - if got, want := st.available(), int32(3); got != want { - t.Errorf("available = %d; want %d", got, want) - } - st.setConnFlow(&conn) - if got, want := st.available(), int32(2); got != want { - t.Errorf("after parent setup, available = %d; want %d", got, want) - } - - st.take(2) - if got, want := conn.available(), int32(0); got != want { - t.Errorf("after taking 2, conn = %d; want %d", got, want) - } - if got, want := st.available(), int32(0); got != want { - t.Errorf("after taking 2, stream = %d; want %d", got, want) - } -} - -func TestFlowAdd(t *testing.T) { - var f flow - if !f.add(1) { - t.Fatal("failed to add 1") - } - if !f.add(-1) { - t.Fatal("failed to add -1") - } - if got, want := f.available(), int32(0); got != want { - t.Fatalf("size = %d; want %d", got, want) - } - if !f.add(1<<31 - 1) { - t.Fatal("failed to add 2^31-1") - } - if got, want := f.available(), int32(1<<31-1); got != want { - t.Fatalf("size = %d; want %d", got, want) - } - if f.add(1) { - t.Fatal("adding 1 to max shouldn't be allowed") - } -} - -func TestFlowAddOverflow(t *testing.T) { - var f flow - if !f.add(0) { - t.Fatal("failed to add 0") - } - if !f.add(-1) { - t.Fatal("failed to add -1") - } - if !f.add(0) { - t.Fatal("failed to add 0") - } - if !f.add(1) { - t.Fatal("failed to add 1") - } - if !f.add(1) { - t.Fatal("failed to add 1") - } - if !f.add(0) { - t.Fatal("failed to add 0") - } - if !f.add(-3) { - t.Fatal("failed to add -3") - } - if got, want := f.available(), int32(-2); got != want { - t.Fatalf("size = %d; want %d", got, want) - } - if !f.add(1<<31 - 1) { - t.Fatal("failed to add 2^31-1") - } - if got, want := f.available(), int32(1+-3+(1<<31-1)); got != want { - t.Fatalf("size = %d; want %d", got, want) - } - -} diff --git a/vendor/golang.org/x/net/http2/frame_test.go b/vendor/golang.org/x/net/http2/frame_test.go deleted file mode 100644 index 3c107b95..00000000 --- a/vendor/golang.org/x/net/http2/frame_test.go +++ /dev/null @@ -1,1235 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package http2 - -import ( - "bytes" - "fmt" - "io" - "reflect" - "strings" - "testing" - "unsafe" - - "golang.org/x/net/http2/hpack" -) - -func testFramer() (*Framer, *bytes.Buffer) { - buf := new(bytes.Buffer) - return NewFramer(buf, buf), buf -} - -func TestFrameSizes(t *testing.T) { - // Catch people rearranging the FrameHeader fields. - if got, want := int(unsafe.Sizeof(FrameHeader{})), 12; got != want { - t.Errorf("FrameHeader size = %d; want %d", got, want) - } -} - -func TestFrameTypeString(t *testing.T) { - tests := []struct { - ft FrameType - want string - }{ - {FrameData, "DATA"}, - {FramePing, "PING"}, - {FrameGoAway, "GOAWAY"}, - {0xf, "UNKNOWN_FRAME_TYPE_15"}, - } - - for i, tt := range tests { - got := tt.ft.String() - if got != tt.want { - t.Errorf("%d. String(FrameType %d) = %q; want %q", i, int(tt.ft), got, tt.want) - } - } -} - -func TestWriteRST(t *testing.T) { - fr, buf := testFramer() - var streamID uint32 = 1<<24 + 2<<16 + 3<<8 + 4 - var errCode uint32 = 7<<24 + 6<<16 + 5<<8 + 4 - fr.WriteRSTStream(streamID, ErrCode(errCode)) - const wantEnc = "\x00\x00\x04\x03\x00\x01\x02\x03\x04\x07\x06\x05\x04" - if buf.String() != wantEnc { - t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc) - } - f, err := fr.ReadFrame() - if err != nil { - t.Fatal(err) - } - want := &RSTStreamFrame{ - FrameHeader: FrameHeader{ - valid: true, - Type: 0x3, - Flags: 0x0, - Length: 0x4, - StreamID: 0x1020304, - }, - ErrCode: 0x7060504, - } - if !reflect.DeepEqual(f, want) { - t.Errorf("parsed back %#v; want %#v", f, want) - } -} - -func TestWriteData(t *testing.T) { - fr, buf := testFramer() - var streamID uint32 = 1<<24 + 2<<16 + 3<<8 + 4 - data := []byte("ABC") - fr.WriteData(streamID, true, data) - const wantEnc = "\x00\x00\x03\x00\x01\x01\x02\x03\x04ABC" - if buf.String() != wantEnc { - t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc) - } - f, err := fr.ReadFrame() - if err != nil { - t.Fatal(err) - } - df, ok := f.(*DataFrame) - if !ok { - t.Fatalf("got %T; want *DataFrame", f) - } - if !bytes.Equal(df.Data(), data) { - t.Errorf("got %q; want %q", df.Data(), data) - } - if f.Header().Flags&1 == 0 { - t.Errorf("didn't see END_STREAM flag") - } -} - -func TestWriteDataPadded(t *testing.T) { - tests := [...]struct { - streamID uint32 - endStream bool - data []byte - pad []byte - wantHeader FrameHeader - }{ - // Unpadded: - 0: { - streamID: 1, - endStream: true, - data: []byte("foo"), - pad: nil, - wantHeader: FrameHeader{ - Type: FrameData, - Flags: FlagDataEndStream, - Length: 3, - StreamID: 1, - }, - }, - - // Padded bit set, but no padding: - 1: { - streamID: 1, - endStream: true, - data: []byte("foo"), - pad: []byte{}, - wantHeader: FrameHeader{ - Type: FrameData, - Flags: FlagDataEndStream | FlagDataPadded, - Length: 4, - StreamID: 1, - }, - }, - - // Padded bit set, with padding: - 2: { - streamID: 1, - endStream: false, - data: []byte("foo"), - pad: []byte{0, 0, 0}, - wantHeader: FrameHeader{ - Type: FrameData, - Flags: FlagDataPadded, - Length: 7, - StreamID: 1, - }, - }, - } - for i, tt := range tests { - fr, _ := testFramer() - fr.WriteDataPadded(tt.streamID, tt.endStream, tt.data, tt.pad) - f, err := fr.ReadFrame() - if err != nil { - t.Errorf("%d. ReadFrame: %v", i, err) - continue - } - got := f.Header() - tt.wantHeader.valid = true - if got != tt.wantHeader { - t.Errorf("%d. read %+v; want %+v", i, got, tt.wantHeader) - continue - } - df := f.(*DataFrame) - if !bytes.Equal(df.Data(), tt.data) { - t.Errorf("%d. got %q; want %q", i, df.Data(), tt.data) - } - } -} - -func TestWriteHeaders(t *testing.T) { - tests := []struct { - name string - p HeadersFrameParam - wantEnc string - wantFrame *HeadersFrame - }{ - { - "basic", - HeadersFrameParam{ - StreamID: 42, - BlockFragment: []byte("abc"), - Priority: PriorityParam{}, - }, - "\x00\x00\x03\x01\x00\x00\x00\x00*abc", - &HeadersFrame{ - FrameHeader: FrameHeader{ - valid: true, - StreamID: 42, - Type: FrameHeaders, - Length: uint32(len("abc")), - }, - Priority: PriorityParam{}, - headerFragBuf: []byte("abc"), - }, - }, - { - "basic + end flags", - HeadersFrameParam{ - StreamID: 42, - BlockFragment: []byte("abc"), - EndStream: true, - EndHeaders: true, - Priority: PriorityParam{}, - }, - "\x00\x00\x03\x01\x05\x00\x00\x00*abc", - &HeadersFrame{ - FrameHeader: FrameHeader{ - valid: true, - StreamID: 42, - Type: FrameHeaders, - Flags: FlagHeadersEndStream | FlagHeadersEndHeaders, - Length: uint32(len("abc")), - }, - Priority: PriorityParam{}, - headerFragBuf: []byte("abc"), - }, - }, - { - "with padding", - HeadersFrameParam{ - StreamID: 42, - BlockFragment: []byte("abc"), - EndStream: true, - EndHeaders: true, - PadLength: 5, - Priority: PriorityParam{}, - }, - "\x00\x00\t\x01\r\x00\x00\x00*\x05abc\x00\x00\x00\x00\x00", - &HeadersFrame{ - FrameHeader: FrameHeader{ - valid: true, - StreamID: 42, - Type: FrameHeaders, - Flags: FlagHeadersEndStream | FlagHeadersEndHeaders | FlagHeadersPadded, - Length: uint32(1 + len("abc") + 5), // pad length + contents + padding - }, - Priority: PriorityParam{}, - headerFragBuf: []byte("abc"), - }, - }, - { - "with priority", - HeadersFrameParam{ - StreamID: 42, - BlockFragment: []byte("abc"), - EndStream: true, - EndHeaders: true, - PadLength: 2, - Priority: PriorityParam{ - StreamDep: 15, - Exclusive: true, - Weight: 127, - }, - }, - "\x00\x00\v\x01-\x00\x00\x00*\x02\x80\x00\x00\x0f\u007fabc\x00\x00", - &HeadersFrame{ - FrameHeader: FrameHeader{ - valid: true, - StreamID: 42, - Type: FrameHeaders, - Flags: FlagHeadersEndStream | FlagHeadersEndHeaders | FlagHeadersPadded | FlagHeadersPriority, - Length: uint32(1 + 5 + len("abc") + 2), // pad length + priority + contents + padding - }, - Priority: PriorityParam{ - StreamDep: 15, - Exclusive: true, - Weight: 127, - }, - headerFragBuf: []byte("abc"), - }, - }, - { - "with priority stream dep zero", // golang.org/issue/15444 - HeadersFrameParam{ - StreamID: 42, - BlockFragment: []byte("abc"), - EndStream: true, - EndHeaders: true, - PadLength: 2, - Priority: PriorityParam{ - StreamDep: 0, - Exclusive: true, - Weight: 127, - }, - }, - "\x00\x00\v\x01-\x00\x00\x00*\x02\x80\x00\x00\x00\u007fabc\x00\x00", - &HeadersFrame{ - FrameHeader: FrameHeader{ - valid: true, - StreamID: 42, - Type: FrameHeaders, - Flags: FlagHeadersEndStream | FlagHeadersEndHeaders | FlagHeadersPadded | FlagHeadersPriority, - Length: uint32(1 + 5 + len("abc") + 2), // pad length + priority + contents + padding - }, - Priority: PriorityParam{ - StreamDep: 0, - Exclusive: true, - Weight: 127, - }, - headerFragBuf: []byte("abc"), - }, - }, - } - for _, tt := range tests { - fr, buf := testFramer() - if err := fr.WriteHeaders(tt.p); err != nil { - t.Errorf("test %q: %v", tt.name, err) - continue - } - if buf.String() != tt.wantEnc { - t.Errorf("test %q: encoded %q; want %q", tt.name, buf.Bytes(), tt.wantEnc) - } - f, err := fr.ReadFrame() - if err != nil { - t.Errorf("test %q: failed to read the frame back: %v", tt.name, err) - continue - } - if !reflect.DeepEqual(f, tt.wantFrame) { - t.Errorf("test %q: mismatch.\n got: %#v\nwant: %#v\n", tt.name, f, tt.wantFrame) - } - } -} - -func TestWriteInvalidStreamDep(t *testing.T) { - fr, _ := testFramer() - err := fr.WriteHeaders(HeadersFrameParam{ - StreamID: 42, - Priority: PriorityParam{ - StreamDep: 1 << 31, - }, - }) - if err != errDepStreamID { - t.Errorf("header error = %v; want %q", err, errDepStreamID) - } - - err = fr.WritePriority(2, PriorityParam{StreamDep: 1 << 31}) - if err != errDepStreamID { - t.Errorf("priority error = %v; want %q", err, errDepStreamID) - } -} - -func TestWriteContinuation(t *testing.T) { - const streamID = 42 - tests := []struct { - name string - end bool - frag []byte - - wantFrame *ContinuationFrame - }{ - { - "not end", - false, - []byte("abc"), - &ContinuationFrame{ - FrameHeader: FrameHeader{ - valid: true, - StreamID: streamID, - Type: FrameContinuation, - Length: uint32(len("abc")), - }, - headerFragBuf: []byte("abc"), - }, - }, - { - "end", - true, - []byte("def"), - &ContinuationFrame{ - FrameHeader: FrameHeader{ - valid: true, - StreamID: streamID, - Type: FrameContinuation, - Flags: FlagContinuationEndHeaders, - Length: uint32(len("def")), - }, - headerFragBuf: []byte("def"), - }, - }, - } - for _, tt := range tests { - fr, _ := testFramer() - if err := fr.WriteContinuation(streamID, tt.end, tt.frag); err != nil { - t.Errorf("test %q: %v", tt.name, err) - continue - } - fr.AllowIllegalReads = true - f, err := fr.ReadFrame() - if err != nil { - t.Errorf("test %q: failed to read the frame back: %v", tt.name, err) - continue - } - if !reflect.DeepEqual(f, tt.wantFrame) { - t.Errorf("test %q: mismatch.\n got: %#v\nwant: %#v\n", tt.name, f, tt.wantFrame) - } - } -} - -func TestWritePriority(t *testing.T) { - const streamID = 42 - tests := []struct { - name string - priority PriorityParam - wantFrame *PriorityFrame - }{ - { - "not exclusive", - PriorityParam{ - StreamDep: 2, - Exclusive: false, - Weight: 127, - }, - &PriorityFrame{ - FrameHeader{ - valid: true, - StreamID: streamID, - Type: FramePriority, - Length: 5, - }, - PriorityParam{ - StreamDep: 2, - Exclusive: false, - Weight: 127, - }, - }, - }, - - { - "exclusive", - PriorityParam{ - StreamDep: 3, - Exclusive: true, - Weight: 77, - }, - &PriorityFrame{ - FrameHeader{ - valid: true, - StreamID: streamID, - Type: FramePriority, - Length: 5, - }, - PriorityParam{ - StreamDep: 3, - Exclusive: true, - Weight: 77, - }, - }, - }, - } - for _, tt := range tests { - fr, _ := testFramer() - if err := fr.WritePriority(streamID, tt.priority); err != nil { - t.Errorf("test %q: %v", tt.name, err) - continue - } - f, err := fr.ReadFrame() - if err != nil { - t.Errorf("test %q: failed to read the frame back: %v", tt.name, err) - continue - } - if !reflect.DeepEqual(f, tt.wantFrame) { - t.Errorf("test %q: mismatch.\n got: %#v\nwant: %#v\n", tt.name, f, tt.wantFrame) - } - } -} - -func TestWriteSettings(t *testing.T) { - fr, buf := testFramer() - settings := []Setting{{1, 2}, {3, 4}} - fr.WriteSettings(settings...) - const wantEnc = "\x00\x00\f\x04\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x03\x00\x00\x00\x04" - if buf.String() != wantEnc { - t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc) - } - f, err := fr.ReadFrame() - if err != nil { - t.Fatal(err) - } - sf, ok := f.(*SettingsFrame) - if !ok { - t.Fatalf("Got a %T; want a SettingsFrame", f) - } - var got []Setting - sf.ForeachSetting(func(s Setting) error { - got = append(got, s) - valBack, ok := sf.Value(s.ID) - if !ok || valBack != s.Val { - t.Errorf("Value(%d) = %v, %v; want %v, true", s.ID, valBack, ok, s.Val) - } - return nil - }) - if !reflect.DeepEqual(settings, got) { - t.Errorf("Read settings %+v != written settings %+v", got, settings) - } -} - -func TestWriteSettingsAck(t *testing.T) { - fr, buf := testFramer() - fr.WriteSettingsAck() - const wantEnc = "\x00\x00\x00\x04\x01\x00\x00\x00\x00" - if buf.String() != wantEnc { - t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc) - } -} - -func TestWriteWindowUpdate(t *testing.T) { - fr, buf := testFramer() - const streamID = 1<<24 + 2<<16 + 3<<8 + 4 - const incr = 7<<24 + 6<<16 + 5<<8 + 4 - if err := fr.WriteWindowUpdate(streamID, incr); err != nil { - t.Fatal(err) - } - const wantEnc = "\x00\x00\x04\x08\x00\x01\x02\x03\x04\x07\x06\x05\x04" - if buf.String() != wantEnc { - t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc) - } - f, err := fr.ReadFrame() - if err != nil { - t.Fatal(err) - } - want := &WindowUpdateFrame{ - FrameHeader: FrameHeader{ - valid: true, - Type: 0x8, - Flags: 0x0, - Length: 0x4, - StreamID: 0x1020304, - }, - Increment: 0x7060504, - } - if !reflect.DeepEqual(f, want) { - t.Errorf("parsed back %#v; want %#v", f, want) - } -} - -func TestWritePing(t *testing.T) { testWritePing(t, false) } -func TestWritePingAck(t *testing.T) { testWritePing(t, true) } - -func testWritePing(t *testing.T, ack bool) { - fr, buf := testFramer() - if err := fr.WritePing(ack, [8]byte{1, 2, 3, 4, 5, 6, 7, 8}); err != nil { - t.Fatal(err) - } - var wantFlags Flags - if ack { - wantFlags = FlagPingAck - } - var wantEnc = "\x00\x00\x08\x06" + string(wantFlags) + "\x00\x00\x00\x00" + "\x01\x02\x03\x04\x05\x06\x07\x08" - if buf.String() != wantEnc { - t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc) - } - - f, err := fr.ReadFrame() - if err != nil { - t.Fatal(err) - } - want := &PingFrame{ - FrameHeader: FrameHeader{ - valid: true, - Type: 0x6, - Flags: wantFlags, - Length: 0x8, - StreamID: 0, - }, - Data: [8]byte{1, 2, 3, 4, 5, 6, 7, 8}, - } - if !reflect.DeepEqual(f, want) { - t.Errorf("parsed back %#v; want %#v", f, want) - } -} - -func TestReadFrameHeader(t *testing.T) { - tests := []struct { - in string - want FrameHeader - }{ - {in: "\x00\x00\x00" + "\x00" + "\x00" + "\x00\x00\x00\x00", want: FrameHeader{}}, - {in: "\x01\x02\x03" + "\x04" + "\x05" + "\x06\x07\x08\x09", want: FrameHeader{ - Length: 66051, Type: 4, Flags: 5, StreamID: 101124105, - }}, - // Ignore high bit: - {in: "\xff\xff\xff" + "\xff" + "\xff" + "\xff\xff\xff\xff", want: FrameHeader{ - Length: 16777215, Type: 255, Flags: 255, StreamID: 2147483647}}, - {in: "\xff\xff\xff" + "\xff" + "\xff" + "\x7f\xff\xff\xff", want: FrameHeader{ - Length: 16777215, Type: 255, Flags: 255, StreamID: 2147483647}}, - } - for i, tt := range tests { - got, err := readFrameHeader(make([]byte, 9), strings.NewReader(tt.in)) - if err != nil { - t.Errorf("%d. readFrameHeader(%q) = %v", i, tt.in, err) - continue - } - tt.want.valid = true - if got != tt.want { - t.Errorf("%d. readFrameHeader(%q) = %+v; want %+v", i, tt.in, got, tt.want) - } - } -} - -func TestReadWriteFrameHeader(t *testing.T) { - tests := []struct { - len uint32 - typ FrameType - flags Flags - streamID uint32 - }{ - {len: 0, typ: 255, flags: 1, streamID: 0}, - {len: 0, typ: 255, flags: 1, streamID: 1}, - {len: 0, typ: 255, flags: 1, streamID: 255}, - {len: 0, typ: 255, flags: 1, streamID: 256}, - {len: 0, typ: 255, flags: 1, streamID: 65535}, - {len: 0, typ: 255, flags: 1, streamID: 65536}, - - {len: 0, typ: 1, flags: 255, streamID: 1}, - {len: 255, typ: 1, flags: 255, streamID: 1}, - {len: 256, typ: 1, flags: 255, streamID: 1}, - {len: 65535, typ: 1, flags: 255, streamID: 1}, - {len: 65536, typ: 1, flags: 255, streamID: 1}, - {len: 16777215, typ: 1, flags: 255, streamID: 1}, - } - for _, tt := range tests { - fr, buf := testFramer() - fr.startWrite(tt.typ, tt.flags, tt.streamID) - fr.writeBytes(make([]byte, tt.len)) - fr.endWrite() - fh, err := ReadFrameHeader(buf) - if err != nil { - t.Errorf("ReadFrameHeader(%+v) = %v", tt, err) - continue - } - if fh.Type != tt.typ || fh.Flags != tt.flags || fh.Length != tt.len || fh.StreamID != tt.streamID { - t.Errorf("ReadFrameHeader(%+v) = %+v; mismatch", tt, fh) - } - } - -} - -func TestWriteTooLargeFrame(t *testing.T) { - fr, _ := testFramer() - fr.startWrite(0, 1, 1) - fr.writeBytes(make([]byte, 1<<24)) - err := fr.endWrite() - if err != ErrFrameTooLarge { - t.Errorf("endWrite = %v; want errFrameTooLarge", err) - } -} - -func TestWriteGoAway(t *testing.T) { - const debug = "foo" - fr, buf := testFramer() - if err := fr.WriteGoAway(0x01020304, 0x05060708, []byte(debug)); err != nil { - t.Fatal(err) - } - const wantEnc = "\x00\x00\v\a\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08" + debug - if buf.String() != wantEnc { - t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc) - } - f, err := fr.ReadFrame() - if err != nil { - t.Fatal(err) - } - want := &GoAwayFrame{ - FrameHeader: FrameHeader{ - valid: true, - Type: 0x7, - Flags: 0, - Length: uint32(4 + 4 + len(debug)), - StreamID: 0, - }, - LastStreamID: 0x01020304, - ErrCode: 0x05060708, - debugData: []byte(debug), - } - if !reflect.DeepEqual(f, want) { - t.Fatalf("parsed back:\n%#v\nwant:\n%#v", f, want) - } - if got := string(f.(*GoAwayFrame).DebugData()); got != debug { - t.Errorf("debug data = %q; want %q", got, debug) - } -} - -func TestWritePushPromise(t *testing.T) { - pp := PushPromiseParam{ - StreamID: 42, - PromiseID: 42, - BlockFragment: []byte("abc"), - } - fr, buf := testFramer() - if err := fr.WritePushPromise(pp); err != nil { - t.Fatal(err) - } - const wantEnc = "\x00\x00\x07\x05\x00\x00\x00\x00*\x00\x00\x00*abc" - if buf.String() != wantEnc { - t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc) - } - f, err := fr.ReadFrame() - if err != nil { - t.Fatal(err) - } - _, ok := f.(*PushPromiseFrame) - if !ok { - t.Fatalf("got %T; want *PushPromiseFrame", f) - } - want := &PushPromiseFrame{ - FrameHeader: FrameHeader{ - valid: true, - Type: 0x5, - Flags: 0x0, - Length: 0x7, - StreamID: 42, - }, - PromiseID: 42, - headerFragBuf: []byte("abc"), - } - if !reflect.DeepEqual(f, want) { - t.Fatalf("parsed back:\n%#v\nwant:\n%#v", f, want) - } -} - -// test checkFrameOrder and that HEADERS and CONTINUATION frames can't be intermingled. -func TestReadFrameOrder(t *testing.T) { - head := func(f *Framer, id uint32, end bool) { - f.WriteHeaders(HeadersFrameParam{ - StreamID: id, - BlockFragment: []byte("foo"), // unused, but non-empty - EndHeaders: end, - }) - } - cont := func(f *Framer, id uint32, end bool) { - f.WriteContinuation(id, end, []byte("foo")) - } - - tests := [...]struct { - name string - w func(*Framer) - atLeast int - wantErr string - }{ - 0: { - w: func(f *Framer) { - head(f, 1, true) - }, - }, - 1: { - w: func(f *Framer) { - head(f, 1, true) - head(f, 2, true) - }, - }, - 2: { - wantErr: "got HEADERS for stream 2; expected CONTINUATION following HEADERS for stream 1", - w: func(f *Framer) { - head(f, 1, false) - head(f, 2, true) - }, - }, - 3: { - wantErr: "got DATA for stream 1; expected CONTINUATION following HEADERS for stream 1", - w: func(f *Framer) { - head(f, 1, false) - }, - }, - 4: { - w: func(f *Framer) { - head(f, 1, false) - cont(f, 1, true) - head(f, 2, true) - }, - }, - 5: { - wantErr: "got CONTINUATION for stream 2; expected stream 1", - w: func(f *Framer) { - head(f, 1, false) - cont(f, 2, true) - head(f, 2, true) - }, - }, - 6: { - wantErr: "unexpected CONTINUATION for stream 1", - w: func(f *Framer) { - cont(f, 1, true) - }, - }, - 7: { - wantErr: "unexpected CONTINUATION for stream 1", - w: func(f *Framer) { - cont(f, 1, false) - }, - }, - 8: { - wantErr: "HEADERS frame with stream ID 0", - w: func(f *Framer) { - head(f, 0, true) - }, - }, - 9: { - wantErr: "CONTINUATION frame with stream ID 0", - w: func(f *Framer) { - cont(f, 0, true) - }, - }, - 10: { - wantErr: "unexpected CONTINUATION for stream 1", - atLeast: 5, - w: func(f *Framer) { - head(f, 1, false) - cont(f, 1, false) - cont(f, 1, false) - cont(f, 1, false) - cont(f, 1, true) - cont(f, 1, false) - }, - }, - } - for i, tt := range tests { - buf := new(bytes.Buffer) - f := NewFramer(buf, buf) - f.AllowIllegalWrites = true - tt.w(f) - f.WriteData(1, true, nil) // to test transition away from last step - - var err error - n := 0 - var log bytes.Buffer - for { - var got Frame - got, err = f.ReadFrame() - fmt.Fprintf(&log, " read %v, %v\n", got, err) - if err != nil { - break - } - n++ - } - if err == io.EOF { - err = nil - } - ok := tt.wantErr == "" - if ok && err != nil { - t.Errorf("%d. after %d good frames, ReadFrame = %v; want success\n%s", i, n, err, log.Bytes()) - continue - } - if !ok && err != ConnectionError(ErrCodeProtocol) { - t.Errorf("%d. after %d good frames, ReadFrame = %v; want ConnectionError(ErrCodeProtocol)\n%s", i, n, err, log.Bytes()) - continue - } - if !((f.errDetail == nil && tt.wantErr == "") || (fmt.Sprint(f.errDetail) == tt.wantErr)) { - t.Errorf("%d. framer eror = %q; want %q\n%s", i, f.errDetail, tt.wantErr, log.Bytes()) - } - if n < tt.atLeast { - t.Errorf("%d. framer only read %d frames; want at least %d\n%s", i, n, tt.atLeast, log.Bytes()) - } - } -} - -func TestMetaFrameHeader(t *testing.T) { - write := func(f *Framer, frags ...[]byte) { - for i, frag := range frags { - end := (i == len(frags)-1) - if i == 0 { - f.WriteHeaders(HeadersFrameParam{ - StreamID: 1, - BlockFragment: frag, - EndHeaders: end, - }) - } else { - f.WriteContinuation(1, end, frag) - } - } - } - - want := func(flags Flags, length uint32, pairs ...string) *MetaHeadersFrame { - mh := &MetaHeadersFrame{ - HeadersFrame: &HeadersFrame{ - FrameHeader: FrameHeader{ - Type: FrameHeaders, - Flags: flags, - Length: length, - StreamID: 1, - }, - }, - Fields: []hpack.HeaderField(nil), - } - for len(pairs) > 0 { - mh.Fields = append(mh.Fields, hpack.HeaderField{ - Name: pairs[0], - Value: pairs[1], - }) - pairs = pairs[2:] - } - return mh - } - truncated := func(mh *MetaHeadersFrame) *MetaHeadersFrame { - mh.Truncated = true - return mh - } - - const noFlags Flags = 0 - - oneKBString := strings.Repeat("a", 1<<10) - - tests := [...]struct { - name string - w func(*Framer) - want interface{} // *MetaHeaderFrame or error - wantErrReason string - maxHeaderListSize uint32 - }{ - 0: { - name: "single_headers", - w: func(f *Framer) { - var he hpackEncoder - all := he.encodeHeaderRaw(t, ":method", "GET", ":path", "/") - write(f, all) - }, - want: want(FlagHeadersEndHeaders, 2, ":method", "GET", ":path", "/"), - }, - 1: { - name: "with_continuation", - w: func(f *Framer) { - var he hpackEncoder - all := he.encodeHeaderRaw(t, ":method", "GET", ":path", "/", "foo", "bar") - write(f, all[:1], all[1:]) - }, - want: want(noFlags, 1, ":method", "GET", ":path", "/", "foo", "bar"), - }, - 2: { - name: "with_two_continuation", - w: func(f *Framer) { - var he hpackEncoder - all := he.encodeHeaderRaw(t, ":method", "GET", ":path", "/", "foo", "bar") - write(f, all[:2], all[2:4], all[4:]) - }, - want: want(noFlags, 2, ":method", "GET", ":path", "/", "foo", "bar"), - }, - 3: { - name: "big_string_okay", - w: func(f *Framer) { - var he hpackEncoder - all := he.encodeHeaderRaw(t, ":method", "GET", ":path", "/", "foo", oneKBString) - write(f, all[:2], all[2:]) - }, - want: want(noFlags, 2, ":method", "GET", ":path", "/", "foo", oneKBString), - }, - 4: { - name: "big_string_error", - w: func(f *Framer) { - var he hpackEncoder - all := he.encodeHeaderRaw(t, ":method", "GET", ":path", "/", "foo", oneKBString) - write(f, all[:2], all[2:]) - }, - maxHeaderListSize: (1 << 10) / 2, - want: ConnectionError(ErrCodeCompression), - }, - 5: { - name: "max_header_list_truncated", - w: func(f *Framer) { - var he hpackEncoder - var pairs = []string{":method", "GET", ":path", "/"} - for i := 0; i < 100; i++ { - pairs = append(pairs, "foo", "bar") - } - all := he.encodeHeaderRaw(t, pairs...) - write(f, all[:2], all[2:]) - }, - maxHeaderListSize: (1 << 10) / 2, - want: truncated(want(noFlags, 2, - ":method", "GET", - ":path", "/", - "foo", "bar", - "foo", "bar", - "foo", "bar", - "foo", "bar", - "foo", "bar", - "foo", "bar", - "foo", "bar", - "foo", "bar", - "foo", "bar", - "foo", "bar", - "foo", "bar", // 11 - )), - }, - 6: { - name: "pseudo_order", - w: func(f *Framer) { - write(f, encodeHeaderRaw(t, - ":method", "GET", - "foo", "bar", - ":path", "/", // bogus - )) - }, - want: streamError(1, ErrCodeProtocol), - wantErrReason: "pseudo header field after regular", - }, - 7: { - name: "pseudo_unknown", - w: func(f *Framer) { - write(f, encodeHeaderRaw(t, - ":unknown", "foo", // bogus - "foo", "bar", - )) - }, - want: streamError(1, ErrCodeProtocol), - wantErrReason: "invalid pseudo-header \":unknown\"", - }, - 8: { - name: "pseudo_mix_request_response", - w: func(f *Framer) { - write(f, encodeHeaderRaw(t, - ":method", "GET", - ":status", "100", - )) - }, - want: streamError(1, ErrCodeProtocol), - wantErrReason: "mix of request and response pseudo headers", - }, - 9: { - name: "pseudo_dup", - w: func(f *Framer) { - write(f, encodeHeaderRaw(t, - ":method", "GET", - ":method", "POST", - )) - }, - want: streamError(1, ErrCodeProtocol), - wantErrReason: "duplicate pseudo-header \":method\"", - }, - 10: { - name: "trailer_okay_no_pseudo", - w: func(f *Framer) { write(f, encodeHeaderRaw(t, "foo", "bar")) }, - want: want(FlagHeadersEndHeaders, 8, "foo", "bar"), - }, - 11: { - name: "invalid_field_name", - w: func(f *Framer) { write(f, encodeHeaderRaw(t, "CapitalBad", "x")) }, - want: streamError(1, ErrCodeProtocol), - wantErrReason: "invalid header field name \"CapitalBad\"", - }, - 12: { - name: "invalid_field_value", - w: func(f *Framer) { write(f, encodeHeaderRaw(t, "key", "bad_null\x00")) }, - want: streamError(1, ErrCodeProtocol), - wantErrReason: "invalid header field value \"bad_null\\x00\"", - }, - } - for i, tt := range tests { - buf := new(bytes.Buffer) - f := NewFramer(buf, buf) - f.ReadMetaHeaders = hpack.NewDecoder(initialHeaderTableSize, nil) - f.MaxHeaderListSize = tt.maxHeaderListSize - tt.w(f) - - name := tt.name - if name == "" { - name = fmt.Sprintf("test index %d", i) - } - - var got interface{} - var err error - got, err = f.ReadFrame() - if err != nil { - got = err - - // Ignore the StreamError.Cause field, if it matches the wantErrReason. - // The test table above predates the Cause field. - if se, ok := err.(StreamError); ok && se.Cause != nil && se.Cause.Error() == tt.wantErrReason { - se.Cause = nil - got = se - } - } - if !reflect.DeepEqual(got, tt.want) { - if mhg, ok := got.(*MetaHeadersFrame); ok { - if mhw, ok := tt.want.(*MetaHeadersFrame); ok { - hg := mhg.HeadersFrame - hw := mhw.HeadersFrame - if hg != nil && hw != nil && !reflect.DeepEqual(*hg, *hw) { - t.Errorf("%s: headers differ:\n got: %+v\nwant: %+v\n", name, *hg, *hw) - } - } - } - str := func(v interface{}) string { - if _, ok := v.(error); ok { - return fmt.Sprintf("error %v", v) - } else { - return fmt.Sprintf("value %#v", v) - } - } - t.Errorf("%s:\n got: %v\nwant: %s", name, str(got), str(tt.want)) - } - if tt.wantErrReason != "" && tt.wantErrReason != fmt.Sprint(f.errDetail) { - t.Errorf("%s: got error reason %q; want %q", name, f.errDetail, tt.wantErrReason) - } - } -} - -func TestSetReuseFrames(t *testing.T) { - fr, buf := testFramer() - fr.SetReuseFrames() - - // Check that DataFrames are reused. Note that - // SetReuseFrames only currently implements reuse of DataFrames. - firstDf := readAndVerifyDataFrame("ABC", 3, fr, buf, t) - - for i := 0; i < 10; i++ { - df := readAndVerifyDataFrame("XYZ", 3, fr, buf, t) - if df != firstDf { - t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf) - } - } - - for i := 0; i < 10; i++ { - df := readAndVerifyDataFrame("", 0, fr, buf, t) - if df != firstDf { - t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf) - } - } - - for i := 0; i < 10; i++ { - df := readAndVerifyDataFrame("HHH", 3, fr, buf, t) - if df != firstDf { - t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf) - } - } -} - -func TestSetReuseFramesMoreThanOnce(t *testing.T) { - fr, buf := testFramer() - fr.SetReuseFrames() - - firstDf := readAndVerifyDataFrame("ABC", 3, fr, buf, t) - fr.SetReuseFrames() - - for i := 0; i < 10; i++ { - df := readAndVerifyDataFrame("XYZ", 3, fr, buf, t) - // SetReuseFrames should be idempotent - fr.SetReuseFrames() - if df != firstDf { - t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf) - } - } -} - -func TestNoSetReuseFrames(t *testing.T) { - fr, buf := testFramer() - const numNewDataFrames = 10 - dfSoFar := make([]interface{}, numNewDataFrames) - - // Check that DataFrames are not reused if SetReuseFrames wasn't called. - // SetReuseFrames only currently implements reuse of DataFrames. - for i := 0; i < numNewDataFrames; i++ { - df := readAndVerifyDataFrame("XYZ", 3, fr, buf, t) - for _, item := range dfSoFar { - if df == item { - t.Errorf("Expected Framer to return new DataFrames since SetNoReuseFrames not set.") - } - } - dfSoFar[i] = df - } -} - -func readAndVerifyDataFrame(data string, length byte, fr *Framer, buf *bytes.Buffer, t *testing.T) *DataFrame { - var streamID uint32 = 1<<24 + 2<<16 + 3<<8 + 4 - fr.WriteData(streamID, true, []byte(data)) - wantEnc := "\x00\x00" + string(length) + "\x00\x01\x01\x02\x03\x04" + data - if buf.String() != wantEnc { - t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc) - } - f, err := fr.ReadFrame() - if err != nil { - t.Fatal(err) - } - df, ok := f.(*DataFrame) - if !ok { - t.Fatalf("got %T; want *DataFrame", f) - } - if !bytes.Equal(df.Data(), []byte(data)) { - t.Errorf("got %q; want %q", df.Data(), []byte(data)) - } - if f.Header().Flags&1 == 0 { - t.Errorf("didn't see END_STREAM flag") - } - return df -} - -func encodeHeaderRaw(t *testing.T, pairs ...string) []byte { - var he hpackEncoder - return he.encodeHeaderRaw(t, pairs...) -} - -func TestSettingsDuplicates(t *testing.T) { - tests := []struct { - settings []Setting - want bool - }{ - {nil, false}, - {[]Setting{{ID: 1}}, false}, - {[]Setting{{ID: 1}, {ID: 2}}, false}, - {[]Setting{{ID: 1}, {ID: 2}}, false}, - {[]Setting{{ID: 1}, {ID: 2}, {ID: 3}}, false}, - {[]Setting{{ID: 1}, {ID: 2}, {ID: 3}}, false}, - {[]Setting{{ID: 1}, {ID: 2}, {ID: 3}, {ID: 4}}, false}, - - {[]Setting{{ID: 1}, {ID: 2}, {ID: 3}, {ID: 2}}, true}, - {[]Setting{{ID: 4}, {ID: 2}, {ID: 3}, {ID: 4}}, true}, - - {[]Setting{ - {ID: 1}, {ID: 2}, {ID: 3}, {ID: 4}, - {ID: 5}, {ID: 6}, {ID: 7}, {ID: 8}, - {ID: 9}, {ID: 10}, {ID: 11}, {ID: 12}, - }, false}, - - {[]Setting{ - {ID: 1}, {ID: 2}, {ID: 3}, {ID: 4}, - {ID: 5}, {ID: 6}, {ID: 7}, {ID: 8}, - {ID: 9}, {ID: 10}, {ID: 11}, {ID: 11}, - }, true}, - } - for i, tt := range tests { - fr, _ := testFramer() - fr.WriteSettings(tt.settings...) - f, err := fr.ReadFrame() - if err != nil { - t.Fatalf("%d. ReadFrame: %v", i, err) - } - sf := f.(*SettingsFrame) - got := sf.HasDuplicates() - if got != tt.want { - t.Errorf("%d. HasDuplicates = %v; want %v", i, got, tt.want) - } - } - -} diff --git a/vendor/golang.org/x/net/http2/gotrack_test.go b/vendor/golang.org/x/net/http2/gotrack_test.go deleted file mode 100644 index 06db6123..00000000 --- a/vendor/golang.org/x/net/http2/gotrack_test.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package http2 - -import ( - "fmt" - "strings" - "testing" -) - -func TestGoroutineLock(t *testing.T) { - oldDebug := DebugGoroutines - DebugGoroutines = true - defer func() { DebugGoroutines = oldDebug }() - - g := newGoroutineLock() - g.check() - - sawPanic := make(chan interface{}) - go func() { - defer func() { sawPanic <- recover() }() - g.check() // should panic - }() - e := <-sawPanic - if e == nil { - t.Fatal("did not see panic from check in other goroutine") - } - if !strings.Contains(fmt.Sprint(e), "wrong goroutine") { - t.Errorf("expected on see panic about running on the wrong goroutine; got %v", e) - } -} diff --git a/vendor/golang.org/x/net/http2/hpack/encode_test.go b/vendor/golang.org/x/net/http2/hpack/encode_test.go deleted file mode 100644 index 05f12db9..00000000 --- a/vendor/golang.org/x/net/http2/hpack/encode_test.go +++ /dev/null @@ -1,386 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package hpack - -import ( - "bytes" - "encoding/hex" - "fmt" - "math/rand" - "reflect" - "strings" - "testing" -) - -func TestEncoderTableSizeUpdate(t *testing.T) { - tests := []struct { - size1, size2 uint32 - wantHex string - }{ - // Should emit 2 table size updates (2048 and 4096) - {2048, 4096, "3fe10f 3fe11f 82"}, - - // Should emit 1 table size update (2048) - {16384, 2048, "3fe10f 82"}, - } - for _, tt := range tests { - var buf bytes.Buffer - e := NewEncoder(&buf) - e.SetMaxDynamicTableSize(tt.size1) - e.SetMaxDynamicTableSize(tt.size2) - if err := e.WriteField(pair(":method", "GET")); err != nil { - t.Fatal(err) - } - want := removeSpace(tt.wantHex) - if got := hex.EncodeToString(buf.Bytes()); got != want { - t.Errorf("e.SetDynamicTableSize %v, %v = %q; want %q", tt.size1, tt.size2, got, want) - } - } -} - -func TestEncoderWriteField(t *testing.T) { - var buf bytes.Buffer - e := NewEncoder(&buf) - var got []HeaderField - d := NewDecoder(4<<10, func(f HeaderField) { - got = append(got, f) - }) - - tests := []struct { - hdrs []HeaderField - }{ - {[]HeaderField{ - pair(":method", "GET"), - pair(":scheme", "http"), - pair(":path", "/"), - pair(":authority", "www.example.com"), - }}, - {[]HeaderField{ - pair(":method", "GET"), - pair(":scheme", "http"), - pair(":path", "/"), - pair(":authority", "www.example.com"), - pair("cache-control", "no-cache"), - }}, - {[]HeaderField{ - pair(":method", "GET"), - pair(":scheme", "https"), - pair(":path", "/index.html"), - pair(":authority", "www.example.com"), - pair("custom-key", "custom-value"), - }}, - } - for i, tt := range tests { - buf.Reset() - got = got[:0] - for _, hf := range tt.hdrs { - if err := e.WriteField(hf); err != nil { - t.Fatal(err) - } - } - _, err := d.Write(buf.Bytes()) - if err != nil { - t.Errorf("%d. Decoder Write = %v", i, err) - } - if !reflect.DeepEqual(got, tt.hdrs) { - t.Errorf("%d. Decoded %+v; want %+v", i, got, tt.hdrs) - } - } -} - -func TestEncoderSearchTable(t *testing.T) { - e := NewEncoder(nil) - - e.dynTab.add(pair("foo", "bar")) - e.dynTab.add(pair("blake", "miz")) - e.dynTab.add(pair(":method", "GET")) - - tests := []struct { - hf HeaderField - wantI uint64 - wantMatch bool - }{ - // Name and Value match - {pair("foo", "bar"), uint64(staticTable.len()) + 3, true}, - {pair("blake", "miz"), uint64(staticTable.len()) + 2, true}, - {pair(":method", "GET"), 2, true}, - - // Only name match because Sensitive == true. This is allowed to match - // any ":method" entry. The current implementation uses the last entry - // added in newStaticTable. - {HeaderField{":method", "GET", true}, 3, false}, - - // Only Name matches - {pair("foo", "..."), uint64(staticTable.len()) + 3, false}, - {pair("blake", "..."), uint64(staticTable.len()) + 2, false}, - // As before, this is allowed to match any ":method" entry. - {pair(":method", "..."), 3, false}, - - // None match - {pair("foo-", "bar"), 0, false}, - } - for _, tt := range tests { - if gotI, gotMatch := e.searchTable(tt.hf); gotI != tt.wantI || gotMatch != tt.wantMatch { - t.Errorf("d.search(%+v) = %v, %v; want %v, %v", tt.hf, gotI, gotMatch, tt.wantI, tt.wantMatch) - } - } -} - -func TestAppendVarInt(t *testing.T) { - tests := []struct { - n byte - i uint64 - want []byte - }{ - // Fits in a byte: - {1, 0, []byte{0}}, - {2, 2, []byte{2}}, - {3, 6, []byte{6}}, - {4, 14, []byte{14}}, - {5, 30, []byte{30}}, - {6, 62, []byte{62}}, - {7, 126, []byte{126}}, - {8, 254, []byte{254}}, - - // Multiple bytes: - {5, 1337, []byte{31, 154, 10}}, - } - for _, tt := range tests { - got := appendVarInt(nil, tt.n, tt.i) - if !bytes.Equal(got, tt.want) { - t.Errorf("appendVarInt(nil, %v, %v) = %v; want %v", tt.n, tt.i, got, tt.want) - } - } -} - -func TestAppendHpackString(t *testing.T) { - tests := []struct { - s, wantHex string - }{ - // Huffman encoded - {"www.example.com", "8c f1e3 c2e5 f23a 6ba0 ab90 f4ff"}, - - // Not Huffman encoded - {"a", "01 61"}, - - // zero length - {"", "00"}, - } - for _, tt := range tests { - want := removeSpace(tt.wantHex) - buf := appendHpackString(nil, tt.s) - if got := hex.EncodeToString(buf); want != got { - t.Errorf("appendHpackString(nil, %q) = %q; want %q", tt.s, got, want) - } - } -} - -func TestAppendIndexed(t *testing.T) { - tests := []struct { - i uint64 - wantHex string - }{ - // 1 byte - {1, "81"}, - {126, "fe"}, - - // 2 bytes - {127, "ff00"}, - {128, "ff01"}, - } - for _, tt := range tests { - want := removeSpace(tt.wantHex) - buf := appendIndexed(nil, tt.i) - if got := hex.EncodeToString(buf); want != got { - t.Errorf("appendIndex(nil, %v) = %q; want %q", tt.i, got, want) - } - } -} - -func TestAppendNewName(t *testing.T) { - tests := []struct { - f HeaderField - indexing bool - wantHex string - }{ - // Incremental indexing - {HeaderField{"custom-key", "custom-value", false}, true, "40 88 25a8 49e9 5ba9 7d7f 89 25a8 49e9 5bb8 e8b4 bf"}, - - // Without indexing - {HeaderField{"custom-key", "custom-value", false}, false, "00 88 25a8 49e9 5ba9 7d7f 89 25a8 49e9 5bb8 e8b4 bf"}, - - // Never indexed - {HeaderField{"custom-key", "custom-value", true}, true, "10 88 25a8 49e9 5ba9 7d7f 89 25a8 49e9 5bb8 e8b4 bf"}, - {HeaderField{"custom-key", "custom-value", true}, false, "10 88 25a8 49e9 5ba9 7d7f 89 25a8 49e9 5bb8 e8b4 bf"}, - } - for _, tt := range tests { - want := removeSpace(tt.wantHex) - buf := appendNewName(nil, tt.f, tt.indexing) - if got := hex.EncodeToString(buf); want != got { - t.Errorf("appendNewName(nil, %+v, %v) = %q; want %q", tt.f, tt.indexing, got, want) - } - } -} - -func TestAppendIndexedName(t *testing.T) { - tests := []struct { - f HeaderField - i uint64 - indexing bool - wantHex string - }{ - // Incremental indexing - {HeaderField{":status", "302", false}, 8, true, "48 82 6402"}, - - // Without indexing - {HeaderField{":status", "302", false}, 8, false, "08 82 6402"}, - - // Never indexed - {HeaderField{":status", "302", true}, 8, true, "18 82 6402"}, - {HeaderField{":status", "302", true}, 8, false, "18 82 6402"}, - } - for _, tt := range tests { - want := removeSpace(tt.wantHex) - buf := appendIndexedName(nil, tt.f, tt.i, tt.indexing) - if got := hex.EncodeToString(buf); want != got { - t.Errorf("appendIndexedName(nil, %+v, %v) = %q; want %q", tt.f, tt.indexing, got, want) - } - } -} - -func TestAppendTableSize(t *testing.T) { - tests := []struct { - i uint32 - wantHex string - }{ - // Fits into 1 byte - {30, "3e"}, - - // Extra byte - {31, "3f00"}, - {32, "3f01"}, - } - for _, tt := range tests { - want := removeSpace(tt.wantHex) - buf := appendTableSize(nil, tt.i) - if got := hex.EncodeToString(buf); want != got { - t.Errorf("appendTableSize(nil, %v) = %q; want %q", tt.i, got, want) - } - } -} - -func TestEncoderSetMaxDynamicTableSize(t *testing.T) { - var buf bytes.Buffer - e := NewEncoder(&buf) - tests := []struct { - v uint32 - wantUpdate bool - wantMinSize uint32 - wantMaxSize uint32 - }{ - // Set new table size to 2048 - {2048, true, 2048, 2048}, - - // Set new table size to 16384, but still limited to - // 4096 - {16384, true, 2048, 4096}, - } - for _, tt := range tests { - e.SetMaxDynamicTableSize(tt.v) - if got := e.tableSizeUpdate; tt.wantUpdate != got { - t.Errorf("e.tableSizeUpdate = %v; want %v", got, tt.wantUpdate) - } - if got := e.minSize; tt.wantMinSize != got { - t.Errorf("e.minSize = %v; want %v", got, tt.wantMinSize) - } - if got := e.dynTab.maxSize; tt.wantMaxSize != got { - t.Errorf("e.maxSize = %v; want %v", got, tt.wantMaxSize) - } - } -} - -func TestEncoderSetMaxDynamicTableSizeLimit(t *testing.T) { - e := NewEncoder(nil) - // 4095 < initialHeaderTableSize means maxSize is truncated to - // 4095. - e.SetMaxDynamicTableSizeLimit(4095) - if got, want := e.dynTab.maxSize, uint32(4095); got != want { - t.Errorf("e.dynTab.maxSize = %v; want %v", got, want) - } - if got, want := e.maxSizeLimit, uint32(4095); got != want { - t.Errorf("e.maxSizeLimit = %v; want %v", got, want) - } - if got, want := e.tableSizeUpdate, true; got != want { - t.Errorf("e.tableSizeUpdate = %v; want %v", got, want) - } - // maxSize will be truncated to maxSizeLimit - e.SetMaxDynamicTableSize(16384) - if got, want := e.dynTab.maxSize, uint32(4095); got != want { - t.Errorf("e.dynTab.maxSize = %v; want %v", got, want) - } - // 8192 > current maxSizeLimit, so maxSize does not change. - e.SetMaxDynamicTableSizeLimit(8192) - if got, want := e.dynTab.maxSize, uint32(4095); got != want { - t.Errorf("e.dynTab.maxSize = %v; want %v", got, want) - } - if got, want := e.maxSizeLimit, uint32(8192); got != want { - t.Errorf("e.maxSizeLimit = %v; want %v", got, want) - } -} - -func removeSpace(s string) string { - return strings.Replace(s, " ", "", -1) -} - -func BenchmarkEncoderSearchTable(b *testing.B) { - e := NewEncoder(nil) - - // A sample of possible header fields. - // This is not based on any actual data from HTTP/2 traces. - var possible []HeaderField - for _, f := range staticTable.ents { - if f.Value == "" { - possible = append(possible, f) - continue - } - // Generate 5 random values, except for cookie and set-cookie, - // which we know can have many values in practice. - num := 5 - if f.Name == "cookie" || f.Name == "set-cookie" { - num = 25 - } - for i := 0; i < num; i++ { - f.Value = fmt.Sprintf("%s-%d", f.Name, i) - possible = append(possible, f) - } - } - for k := 0; k < 10; k++ { - f := HeaderField{ - Name: fmt.Sprintf("x-header-%d", k), - Sensitive: rand.Int()%2 == 0, - } - for i := 0; i < 5; i++ { - f.Value = fmt.Sprintf("%s-%d", f.Name, i) - possible = append(possible, f) - } - } - - // Add a random sample to the dynamic table. This very loosely simulates - // a history of 100 requests with 20 header fields per request. - for r := 0; r < 100*20; r++ { - f := possible[rand.Int31n(int32(len(possible)))] - // Skip if this is in the staticTable verbatim. - if _, has := staticTable.search(f); !has { - e.dynTab.add(f) - } - } - - b.ResetTimer() - for n := 0; n < b.N; n++ { - for _, f := range possible { - e.searchTable(f) - } - } -} diff --git a/vendor/golang.org/x/net/http2/hpack/hpack_test.go b/vendor/golang.org/x/net/http2/hpack/hpack_test.go deleted file mode 100644 index a361a2a7..00000000 --- a/vendor/golang.org/x/net/http2/hpack/hpack_test.go +++ /dev/null @@ -1,770 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package hpack - -import ( - "bytes" - "encoding/hex" - "fmt" - "math/rand" - "reflect" - "strings" - "testing" - "time" -) - -func (d *Decoder) mustAt(idx int) HeaderField { - if hf, ok := d.at(uint64(idx)); !ok { - panic(fmt.Sprintf("bogus index %d", idx)) - } else { - return hf - } -} - -func TestDynamicTableAt(t *testing.T) { - d := NewDecoder(4096, nil) - at := d.mustAt - if got, want := at(2), (pair(":method", "GET")); got != want { - t.Errorf("at(2) = %v; want %v", got, want) - } - d.dynTab.add(pair("foo", "bar")) - d.dynTab.add(pair("blake", "miz")) - if got, want := at(staticTable.len()+1), (pair("blake", "miz")); got != want { - t.Errorf("at(dyn 1) = %v; want %v", got, want) - } - if got, want := at(staticTable.len()+2), (pair("foo", "bar")); got != want { - t.Errorf("at(dyn 2) = %v; want %v", got, want) - } - if got, want := at(3), (pair(":method", "POST")); got != want { - t.Errorf("at(3) = %v; want %v", got, want) - } -} - -func TestDynamicTableSizeEvict(t *testing.T) { - d := NewDecoder(4096, nil) - if want := uint32(0); d.dynTab.size != want { - t.Fatalf("size = %d; want %d", d.dynTab.size, want) - } - add := d.dynTab.add - add(pair("blake", "eats pizza")) - if want := uint32(15 + 32); d.dynTab.size != want { - t.Fatalf("after pizza, size = %d; want %d", d.dynTab.size, want) - } - add(pair("foo", "bar")) - if want := uint32(15 + 32 + 6 + 32); d.dynTab.size != want { - t.Fatalf("after foo bar, size = %d; want %d", d.dynTab.size, want) - } - d.dynTab.setMaxSize(15 + 32 + 1 /* slop */) - if want := uint32(6 + 32); d.dynTab.size != want { - t.Fatalf("after setMaxSize, size = %d; want %d", d.dynTab.size, want) - } - if got, want := d.mustAt(staticTable.len()+1), (pair("foo", "bar")); got != want { - t.Errorf("at(dyn 1) = %v; want %v", got, want) - } - add(pair("long", strings.Repeat("x", 500))) - if want := uint32(0); d.dynTab.size != want { - t.Fatalf("after big one, size = %d; want %d", d.dynTab.size, want) - } -} - -func TestDecoderDecode(t *testing.T) { - tests := []struct { - name string - in []byte - want []HeaderField - wantDynTab []HeaderField // newest entry first - }{ - // C.2.1 Literal Header Field with Indexing - // http://http2.github.io/http2-spec/compression.html#rfc.section.C.2.1 - {"C.2.1", dehex("400a 6375 7374 6f6d 2d6b 6579 0d63 7573 746f 6d2d 6865 6164 6572"), - []HeaderField{pair("custom-key", "custom-header")}, - []HeaderField{pair("custom-key", "custom-header")}, - }, - - // C.2.2 Literal Header Field without Indexing - // http://http2.github.io/http2-spec/compression.html#rfc.section.C.2.2 - {"C.2.2", dehex("040c 2f73 616d 706c 652f 7061 7468"), - []HeaderField{pair(":path", "/sample/path")}, - []HeaderField{}}, - - // C.2.3 Literal Header Field never Indexed - // http://http2.github.io/http2-spec/compression.html#rfc.section.C.2.3 - {"C.2.3", dehex("1008 7061 7373 776f 7264 0673 6563 7265 74"), - []HeaderField{{"password", "secret", true}}, - []HeaderField{}}, - - // C.2.4 Indexed Header Field - // http://http2.github.io/http2-spec/compression.html#rfc.section.C.2.4 - {"C.2.4", []byte("\x82"), - []HeaderField{pair(":method", "GET")}, - []HeaderField{}}, - } - for _, tt := range tests { - d := NewDecoder(4096, nil) - hf, err := d.DecodeFull(tt.in) - if err != nil { - t.Errorf("%s: %v", tt.name, err) - continue - } - if !reflect.DeepEqual(hf, tt.want) { - t.Errorf("%s: Got %v; want %v", tt.name, hf, tt.want) - } - gotDynTab := d.dynTab.reverseCopy() - if !reflect.DeepEqual(gotDynTab, tt.wantDynTab) { - t.Errorf("%s: dynamic table after = %v; want %v", tt.name, gotDynTab, tt.wantDynTab) - } - } -} - -func (dt *dynamicTable) reverseCopy() (hf []HeaderField) { - hf = make([]HeaderField, len(dt.table.ents)) - for i := range hf { - hf[i] = dt.table.ents[len(dt.table.ents)-1-i] - } - return -} - -type encAndWant struct { - enc []byte - want []HeaderField - wantDynTab []HeaderField - wantDynSize uint32 -} - -// C.3 Request Examples without Huffman Coding -// http://http2.github.io/http2-spec/compression.html#rfc.section.C.3 -func TestDecodeC3_NoHuffman(t *testing.T) { - testDecodeSeries(t, 4096, []encAndWant{ - {dehex("8286 8441 0f77 7777 2e65 7861 6d70 6c65 2e63 6f6d"), - []HeaderField{ - pair(":method", "GET"), - pair(":scheme", "http"), - pair(":path", "/"), - pair(":authority", "www.example.com"), - }, - []HeaderField{ - pair(":authority", "www.example.com"), - }, - 57, - }, - {dehex("8286 84be 5808 6e6f 2d63 6163 6865"), - []HeaderField{ - pair(":method", "GET"), - pair(":scheme", "http"), - pair(":path", "/"), - pair(":authority", "www.example.com"), - pair("cache-control", "no-cache"), - }, - []HeaderField{ - pair("cache-control", "no-cache"), - pair(":authority", "www.example.com"), - }, - 110, - }, - {dehex("8287 85bf 400a 6375 7374 6f6d 2d6b 6579 0c63 7573 746f 6d2d 7661 6c75 65"), - []HeaderField{ - pair(":method", "GET"), - pair(":scheme", "https"), - pair(":path", "/index.html"), - pair(":authority", "www.example.com"), - pair("custom-key", "custom-value"), - }, - []HeaderField{ - pair("custom-key", "custom-value"), - pair("cache-control", "no-cache"), - pair(":authority", "www.example.com"), - }, - 164, - }, - }) -} - -// C.4 Request Examples with Huffman Coding -// http://http2.github.io/http2-spec/compression.html#rfc.section.C.4 -func TestDecodeC4_Huffman(t *testing.T) { - testDecodeSeries(t, 4096, []encAndWant{ - {dehex("8286 8441 8cf1 e3c2 e5f2 3a6b a0ab 90f4 ff"), - []HeaderField{ - pair(":method", "GET"), - pair(":scheme", "http"), - pair(":path", "/"), - pair(":authority", "www.example.com"), - }, - []HeaderField{ - pair(":authority", "www.example.com"), - }, - 57, - }, - {dehex("8286 84be 5886 a8eb 1064 9cbf"), - []HeaderField{ - pair(":method", "GET"), - pair(":scheme", "http"), - pair(":path", "/"), - pair(":authority", "www.example.com"), - pair("cache-control", "no-cache"), - }, - []HeaderField{ - pair("cache-control", "no-cache"), - pair(":authority", "www.example.com"), - }, - 110, - }, - {dehex("8287 85bf 4088 25a8 49e9 5ba9 7d7f 8925 a849 e95b b8e8 b4bf"), - []HeaderField{ - pair(":method", "GET"), - pair(":scheme", "https"), - pair(":path", "/index.html"), - pair(":authority", "www.example.com"), - pair("custom-key", "custom-value"), - }, - []HeaderField{ - pair("custom-key", "custom-value"), - pair("cache-control", "no-cache"), - pair(":authority", "www.example.com"), - }, - 164, - }, - }) -} - -// http://http2.github.io/http2-spec/compression.html#rfc.section.C.5 -// "This section shows several consecutive header lists, corresponding -// to HTTP responses, on the same connection. The HTTP/2 setting -// parameter SETTINGS_HEADER_TABLE_SIZE is set to the value of 256 -// octets, causing some evictions to occur." -func TestDecodeC5_ResponsesNoHuff(t *testing.T) { - testDecodeSeries(t, 256, []encAndWant{ - {dehex(` -4803 3330 3258 0770 7269 7661 7465 611d -4d6f 6e2c 2032 3120 4f63 7420 3230 3133 -2032 303a 3133 3a32 3120 474d 546e 1768 -7474 7073 3a2f 2f77 7777 2e65 7861 6d70 -6c65 2e63 6f6d -`), - []HeaderField{ - pair(":status", "302"), - pair("cache-control", "private"), - pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"), - pair("location", "https://www.example.com"), - }, - []HeaderField{ - pair("location", "https://www.example.com"), - pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"), - pair("cache-control", "private"), - pair(":status", "302"), - }, - 222, - }, - {dehex("4803 3330 37c1 c0bf"), - []HeaderField{ - pair(":status", "307"), - pair("cache-control", "private"), - pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"), - pair("location", "https://www.example.com"), - }, - []HeaderField{ - pair(":status", "307"), - pair("location", "https://www.example.com"), - pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"), - pair("cache-control", "private"), - }, - 222, - }, - {dehex(` -88c1 611d 4d6f 6e2c 2032 3120 4f63 7420 -3230 3133 2032 303a 3133 3a32 3220 474d -54c0 5a04 677a 6970 7738 666f 6f3d 4153 -444a 4b48 514b 425a 584f 5157 454f 5049 -5541 5851 5745 4f49 553b 206d 6178 2d61 -6765 3d33 3630 303b 2076 6572 7369 6f6e -3d31 -`), - []HeaderField{ - pair(":status", "200"), - pair("cache-control", "private"), - pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"), - pair("location", "https://www.example.com"), - pair("content-encoding", "gzip"), - pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"), - }, - []HeaderField{ - pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"), - pair("content-encoding", "gzip"), - pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"), - }, - 215, - }, - }) -} - -// http://http2.github.io/http2-spec/compression.html#rfc.section.C.6 -// "This section shows the same examples as the previous section, but -// using Huffman encoding for the literal values. The HTTP/2 setting -// parameter SETTINGS_HEADER_TABLE_SIZE is set to the value of 256 -// octets, causing some evictions to occur. The eviction mechanism -// uses the length of the decoded literal values, so the same -// evictions occurs as in the previous section." -func TestDecodeC6_ResponsesHuffman(t *testing.T) { - testDecodeSeries(t, 256, []encAndWant{ - {dehex(` -4882 6402 5885 aec3 771a 4b61 96d0 7abe -9410 54d4 44a8 2005 9504 0b81 66e0 82a6 -2d1b ff6e 919d 29ad 1718 63c7 8f0b 97c8 -e9ae 82ae 43d3 -`), - []HeaderField{ - pair(":status", "302"), - pair("cache-control", "private"), - pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"), - pair("location", "https://www.example.com"), - }, - []HeaderField{ - pair("location", "https://www.example.com"), - pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"), - pair("cache-control", "private"), - pair(":status", "302"), - }, - 222, - }, - {dehex("4883 640e ffc1 c0bf"), - []HeaderField{ - pair(":status", "307"), - pair("cache-control", "private"), - pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"), - pair("location", "https://www.example.com"), - }, - []HeaderField{ - pair(":status", "307"), - pair("location", "https://www.example.com"), - pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"), - pair("cache-control", "private"), - }, - 222, - }, - {dehex(` -88c1 6196 d07a be94 1054 d444 a820 0595 -040b 8166 e084 a62d 1bff c05a 839b d9ab -77ad 94e7 821d d7f2 e6c7 b335 dfdf cd5b -3960 d5af 2708 7f36 72c1 ab27 0fb5 291f -9587 3160 65c0 03ed 4ee5 b106 3d50 07 -`), - []HeaderField{ - pair(":status", "200"), - pair("cache-control", "private"), - pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"), - pair("location", "https://www.example.com"), - pair("content-encoding", "gzip"), - pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"), - }, - []HeaderField{ - pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"), - pair("content-encoding", "gzip"), - pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"), - }, - 215, - }, - }) -} - -func testDecodeSeries(t *testing.T, size uint32, steps []encAndWant) { - d := NewDecoder(size, nil) - for i, step := range steps { - hf, err := d.DecodeFull(step.enc) - if err != nil { - t.Fatalf("Error at step index %d: %v", i, err) - } - if !reflect.DeepEqual(hf, step.want) { - t.Fatalf("At step index %d: Got headers %v; want %v", i, hf, step.want) - } - gotDynTab := d.dynTab.reverseCopy() - if !reflect.DeepEqual(gotDynTab, step.wantDynTab) { - t.Errorf("After step index %d, dynamic table = %v; want %v", i, gotDynTab, step.wantDynTab) - } - if d.dynTab.size != step.wantDynSize { - t.Errorf("After step index %d, dynamic table size = %v; want %v", i, d.dynTab.size, step.wantDynSize) - } - } -} - -func TestHuffmanDecodeExcessPadding(t *testing.T) { - tests := [][]byte{ - {0xff}, // Padding Exceeds 7 bits - {0x1f, 0xff}, // {"a", 1 byte excess padding} - {0x1f, 0xff, 0xff}, // {"a", 2 byte excess padding} - {0x1f, 0xff, 0xff, 0xff}, // {"a", 3 byte excess padding} - {0xff, 0x9f, 0xff, 0xff, 0xff}, // {"a", 29 bit excess padding} - {'R', 0xbc, '0', 0xff, 0xff, 0xff, 0xff}, // Padding ends on partial symbol. - } - for i, in := range tests { - var buf bytes.Buffer - if _, err := HuffmanDecode(&buf, in); err != ErrInvalidHuffman { - t.Errorf("test-%d: decode(%q) = %v; want ErrInvalidHuffman", i, in, err) - } - } -} - -func TestHuffmanDecodeEOS(t *testing.T) { - in := []byte{0xff, 0xff, 0xff, 0xff, 0xfc} // {EOS, "?"} - var buf bytes.Buffer - if _, err := HuffmanDecode(&buf, in); err != ErrInvalidHuffman { - t.Errorf("error = %v; want ErrInvalidHuffman", err) - } -} - -func TestHuffmanDecodeMaxLengthOnTrailingByte(t *testing.T) { - in := []byte{0x00, 0x01} // {"0", "0", "0"} - var buf bytes.Buffer - if err := huffmanDecode(&buf, 2, in); err != ErrStringLength { - t.Errorf("error = %v; want ErrStringLength", err) - } -} - -func TestHuffmanDecodeCorruptPadding(t *testing.T) { - in := []byte{0x00} - var buf bytes.Buffer - if _, err := HuffmanDecode(&buf, in); err != ErrInvalidHuffman { - t.Errorf("error = %v; want ErrInvalidHuffman", err) - } -} - -func TestHuffmanDecode(t *testing.T) { - tests := []struct { - inHex, want string - }{ - {"f1e3 c2e5 f23a 6ba0 ab90 f4ff", "www.example.com"}, - {"a8eb 1064 9cbf", "no-cache"}, - {"25a8 49e9 5ba9 7d7f", "custom-key"}, - {"25a8 49e9 5bb8 e8b4 bf", "custom-value"}, - {"6402", "302"}, - {"aec3 771a 4b", "private"}, - {"d07a be94 1054 d444 a820 0595 040b 8166 e082 a62d 1bff", "Mon, 21 Oct 2013 20:13:21 GMT"}, - {"9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 d3", "https://www.example.com"}, - {"9bd9 ab", "gzip"}, - {"94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 3160 65c0 03ed 4ee5 b106 3d50 07", - "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"}, - } - for i, tt := range tests { - var buf bytes.Buffer - in, err := hex.DecodeString(strings.Replace(tt.inHex, " ", "", -1)) - if err != nil { - t.Errorf("%d. hex input error: %v", i, err) - continue - } - if _, err := HuffmanDecode(&buf, in); err != nil { - t.Errorf("%d. decode error: %v", i, err) - continue - } - if got := buf.String(); tt.want != got { - t.Errorf("%d. decode = %q; want %q", i, got, tt.want) - } - } -} - -func BenchmarkHuffmanDecode(b *testing.B) { - b.StopTimer() - enc, err := hex.DecodeString(strings.Replace("94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 3160 65c0 03ed 4ee5 b106 3d50 07", - " ", "", -1)) - if err != nil { - b.Fatal(err) - } - b.ReportAllocs() - b.StartTimer() - var buf bytes.Buffer - for i := 0; i < b.N; i++ { - buf.Reset() - if _, err := HuffmanDecode(&buf, enc); err != nil { - b.Fatalf("decode error: %v", err) - } - if string(buf.Bytes()) != "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1" { - b.Fatalf("bogus output %q", buf.Bytes()) - } - } -} - -func TestAppendHuffmanString(t *testing.T) { - tests := []struct { - in, want string - }{ - {"www.example.com", "f1e3 c2e5 f23a 6ba0 ab90 f4ff"}, - {"no-cache", "a8eb 1064 9cbf"}, - {"custom-key", "25a8 49e9 5ba9 7d7f"}, - {"custom-value", "25a8 49e9 5bb8 e8b4 bf"}, - {"302", "6402"}, - {"private", "aec3 771a 4b"}, - {"Mon, 21 Oct 2013 20:13:21 GMT", "d07a be94 1054 d444 a820 0595 040b 8166 e082 a62d 1bff"}, - {"https://www.example.com", "9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 d3"}, - {"gzip", "9bd9 ab"}, - {"foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1", - "94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 3160 65c0 03ed 4ee5 b106 3d50 07"}, - } - for i, tt := range tests { - buf := []byte{} - want := strings.Replace(tt.want, " ", "", -1) - buf = AppendHuffmanString(buf, tt.in) - if got := hex.EncodeToString(buf); want != got { - t.Errorf("%d. encode = %q; want %q", i, got, want) - } - } -} - -func TestHuffmanMaxStrLen(t *testing.T) { - const msg = "Some string" - huff := AppendHuffmanString(nil, msg) - - testGood := func(max int) { - var out bytes.Buffer - if err := huffmanDecode(&out, max, huff); err != nil { - t.Errorf("For maxLen=%d, unexpected error: %v", max, err) - } - if out.String() != msg { - t.Errorf("For maxLen=%d, out = %q; want %q", max, out.String(), msg) - } - } - testGood(0) - testGood(len(msg)) - testGood(len(msg) + 1) - - var out bytes.Buffer - if err := huffmanDecode(&out, len(msg)-1, huff); err != ErrStringLength { - t.Errorf("err = %v; want ErrStringLength", err) - } -} - -func TestHuffmanRoundtripStress(t *testing.T) { - const Len = 50 // of uncompressed string - input := make([]byte, Len) - var output bytes.Buffer - var huff []byte - - n := 5000 - if testing.Short() { - n = 100 - } - seed := time.Now().UnixNano() - t.Logf("Seed = %v", seed) - src := rand.New(rand.NewSource(seed)) - var encSize int64 - for i := 0; i < n; i++ { - for l := range input { - input[l] = byte(src.Intn(256)) - } - huff = AppendHuffmanString(huff[:0], string(input)) - encSize += int64(len(huff)) - output.Reset() - if err := huffmanDecode(&output, 0, huff); err != nil { - t.Errorf("Failed to decode %q -> %q -> error %v", input, huff, err) - continue - } - if !bytes.Equal(output.Bytes(), input) { - t.Errorf("Roundtrip failure on %q -> %q -> %q", input, huff, output.Bytes()) - } - } - t.Logf("Compressed size of original: %0.02f%% (%v -> %v)", 100*(float64(encSize)/(Len*float64(n))), Len*n, encSize) -} - -func TestHuffmanDecodeFuzz(t *testing.T) { - const Len = 50 // of compressed - var buf, zbuf bytes.Buffer - - n := 5000 - if testing.Short() { - n = 100 - } - seed := time.Now().UnixNano() - t.Logf("Seed = %v", seed) - src := rand.New(rand.NewSource(seed)) - numFail := 0 - for i := 0; i < n; i++ { - zbuf.Reset() - if i == 0 { - // Start with at least one invalid one. - zbuf.WriteString("00\x91\xff\xff\xff\xff\xc8") - } else { - for l := 0; l < Len; l++ { - zbuf.WriteByte(byte(src.Intn(256))) - } - } - - buf.Reset() - if err := huffmanDecode(&buf, 0, zbuf.Bytes()); err != nil { - if err == ErrInvalidHuffman { - numFail++ - continue - } - t.Errorf("Failed to decode %q: %v", zbuf.Bytes(), err) - continue - } - } - t.Logf("%0.02f%% are invalid (%d / %d)", 100*float64(numFail)/float64(n), numFail, n) - if numFail < 1 { - t.Error("expected at least one invalid huffman encoding (test starts with one)") - } -} - -func TestReadVarInt(t *testing.T) { - type res struct { - i uint64 - consumed int - err error - } - tests := []struct { - n byte - p []byte - want res - }{ - // Fits in a byte: - {1, []byte{0}, res{0, 1, nil}}, - {2, []byte{2}, res{2, 1, nil}}, - {3, []byte{6}, res{6, 1, nil}}, - {4, []byte{14}, res{14, 1, nil}}, - {5, []byte{30}, res{30, 1, nil}}, - {6, []byte{62}, res{62, 1, nil}}, - {7, []byte{126}, res{126, 1, nil}}, - {8, []byte{254}, res{254, 1, nil}}, - - // Doesn't fit in a byte: - {1, []byte{1}, res{0, 0, errNeedMore}}, - {2, []byte{3}, res{0, 0, errNeedMore}}, - {3, []byte{7}, res{0, 0, errNeedMore}}, - {4, []byte{15}, res{0, 0, errNeedMore}}, - {5, []byte{31}, res{0, 0, errNeedMore}}, - {6, []byte{63}, res{0, 0, errNeedMore}}, - {7, []byte{127}, res{0, 0, errNeedMore}}, - {8, []byte{255}, res{0, 0, errNeedMore}}, - - // Ignoring top bits: - {5, []byte{255, 154, 10}, res{1337, 3, nil}}, // high dummy three bits: 111 - {5, []byte{159, 154, 10}, res{1337, 3, nil}}, // high dummy three bits: 100 - {5, []byte{191, 154, 10}, res{1337, 3, nil}}, // high dummy three bits: 101 - - // Extra byte: - {5, []byte{191, 154, 10, 2}, res{1337, 3, nil}}, // extra byte - - // Short a byte: - {5, []byte{191, 154}, res{0, 0, errNeedMore}}, - - // integer overflow: - {1, []byte{255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128}, res{0, 0, errVarintOverflow}}, - } - for _, tt := range tests { - i, remain, err := readVarInt(tt.n, tt.p) - consumed := len(tt.p) - len(remain) - got := res{i, consumed, err} - if got != tt.want { - t.Errorf("readVarInt(%d, %v ~ %x) = %+v; want %+v", tt.n, tt.p, tt.p, got, tt.want) - } - } -} - -// Fuzz crash, originally reported at https://github.com/bradfitz/http2/issues/56 -func TestHuffmanFuzzCrash(t *testing.T) { - got, err := HuffmanDecodeToString([]byte("00\x91\xff\xff\xff\xff\xc8")) - if got != "" { - t.Errorf("Got %q; want empty string", got) - } - if err != ErrInvalidHuffman { - t.Errorf("Err = %v; want ErrInvalidHuffman", err) - } -} - -func pair(name, value string) HeaderField { - return HeaderField{Name: name, Value: value} -} - -func dehex(s string) []byte { - s = strings.Replace(s, " ", "", -1) - s = strings.Replace(s, "\n", "", -1) - b, err := hex.DecodeString(s) - if err != nil { - panic(err) - } - return b -} - -func TestEmitEnabled(t *testing.T) { - var buf bytes.Buffer - enc := NewEncoder(&buf) - enc.WriteField(HeaderField{Name: "foo", Value: "bar"}) - enc.WriteField(HeaderField{Name: "foo", Value: "bar"}) - - numCallback := 0 - var dec *Decoder - dec = NewDecoder(8<<20, func(HeaderField) { - numCallback++ - dec.SetEmitEnabled(false) - }) - if !dec.EmitEnabled() { - t.Errorf("initial emit enabled = false; want true") - } - if _, err := dec.Write(buf.Bytes()); err != nil { - t.Error(err) - } - if numCallback != 1 { - t.Errorf("num callbacks = %d; want 1", numCallback) - } - if dec.EmitEnabled() { - t.Errorf("emit enabled = true; want false") - } -} - -func TestSaveBufLimit(t *testing.T) { - const maxStr = 1 << 10 - var got []HeaderField - dec := NewDecoder(initialHeaderTableSize, func(hf HeaderField) { - got = append(got, hf) - }) - dec.SetMaxStringLength(maxStr) - var frag []byte - frag = append(frag[:0], encodeTypeByte(false, false)) - frag = appendVarInt(frag, 7, 3) - frag = append(frag, "foo"...) - frag = appendVarInt(frag, 7, 3) - frag = append(frag, "bar"...) - - if _, err := dec.Write(frag); err != nil { - t.Fatal(err) - } - - want := []HeaderField{{Name: "foo", Value: "bar"}} - if !reflect.DeepEqual(got, want) { - t.Errorf("After small writes, got %v; want %v", got, want) - } - - frag = append(frag[:0], encodeTypeByte(false, false)) - frag = appendVarInt(frag, 7, maxStr*3) - frag = append(frag, make([]byte, maxStr*3)...) - - _, err := dec.Write(frag) - if err != ErrStringLength { - t.Fatalf("Write error = %v; want ErrStringLength", err) - } -} - -func TestDynamicSizeUpdate(t *testing.T) { - var buf bytes.Buffer - enc := NewEncoder(&buf) - enc.SetMaxDynamicTableSize(255) - enc.WriteField(HeaderField{Name: "foo", Value: "bar"}) - - d := NewDecoder(4096, func(_ HeaderField) {}) - _, err := d.Write(buf.Bytes()) - if err != nil { - t.Fatalf("unexpected error: got = %v", err) - } - - d.Close() - - // Start a new header - _, err = d.Write(buf.Bytes()) - if err != nil { - t.Fatalf("unexpected error: got = %v", err) - } - - // must fail since the dynamic table update must be at the beginning - _, err = d.Write(buf.Bytes()) - if err == nil { - t.Fatalf("dynamic table size update not at the beginning of a header block") - } -} diff --git a/vendor/golang.org/x/net/http2/hpack/tables_test.go b/vendor/golang.org/x/net/http2/hpack/tables_test.go deleted file mode 100644 index d963f363..00000000 --- a/vendor/golang.org/x/net/http2/hpack/tables_test.go +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package hpack - -import ( - "bufio" - "regexp" - "strconv" - "strings" - "testing" -) - -func TestHeaderFieldTable(t *testing.T) { - table := &headerFieldTable{} - table.init() - table.addEntry(pair("key1", "value1-1")) - table.addEntry(pair("key2", "value2-1")) - table.addEntry(pair("key1", "value1-2")) - table.addEntry(pair("key3", "value3-1")) - table.addEntry(pair("key4", "value4-1")) - table.addEntry(pair("key2", "value2-2")) - - // Tests will be run twice: once before evicting anything, and - // again after evicting the three oldest entries. - tests := []struct { - f HeaderField - beforeWantStaticI uint64 - beforeWantMatch bool - afterWantStaticI uint64 - afterWantMatch bool - }{ - {HeaderField{"key1", "value1-1", false}, 1, true, 0, false}, - {HeaderField{"key1", "value1-2", false}, 3, true, 0, false}, - {HeaderField{"key1", "value1-3", false}, 3, false, 0, false}, - {HeaderField{"key2", "value2-1", false}, 2, true, 3, false}, - {HeaderField{"key2", "value2-2", false}, 6, true, 3, true}, - {HeaderField{"key2", "value2-3", false}, 6, false, 3, false}, - {HeaderField{"key4", "value4-1", false}, 5, true, 2, true}, - // Name match only, because sensitive. - {HeaderField{"key4", "value4-1", true}, 5, false, 2, false}, - // Key not found. - {HeaderField{"key5", "value5-x", false}, 0, false, 0, false}, - } - - staticToDynamic := func(i uint64) uint64 { - if i == 0 { - return 0 - } - return uint64(table.len()) - i + 1 // dynamic is the reversed table - } - - searchStatic := func(f HeaderField) (uint64, bool) { - old := staticTable - staticTable = table - defer func() { staticTable = old }() - return staticTable.search(f) - } - - searchDynamic := func(f HeaderField) (uint64, bool) { - return table.search(f) - } - - for _, test := range tests { - gotI, gotMatch := searchStatic(test.f) - if wantI, wantMatch := test.beforeWantStaticI, test.beforeWantMatch; gotI != wantI || gotMatch != wantMatch { - t.Errorf("before evictions: searchStatic(%+v)=%v,%v want %v,%v", test.f, gotI, gotMatch, wantI, wantMatch) - } - gotI, gotMatch = searchDynamic(test.f) - wantDynamicI := staticToDynamic(test.beforeWantStaticI) - if wantI, wantMatch := wantDynamicI, test.beforeWantMatch; gotI != wantI || gotMatch != wantMatch { - t.Errorf("before evictions: searchDynamic(%+v)=%v,%v want %v,%v", test.f, gotI, gotMatch, wantI, wantMatch) - } - } - - table.evictOldest(3) - - for _, test := range tests { - gotI, gotMatch := searchStatic(test.f) - if wantI, wantMatch := test.afterWantStaticI, test.afterWantMatch; gotI != wantI || gotMatch != wantMatch { - t.Errorf("after evictions: searchStatic(%+v)=%v,%v want %v,%v", test.f, gotI, gotMatch, wantI, wantMatch) - } - gotI, gotMatch = searchDynamic(test.f) - wantDynamicI := staticToDynamic(test.afterWantStaticI) - if wantI, wantMatch := wantDynamicI, test.afterWantMatch; gotI != wantI || gotMatch != wantMatch { - t.Errorf("after evictions: searchDynamic(%+v)=%v,%v want %v,%v", test.f, gotI, gotMatch, wantI, wantMatch) - } - } -} - -func TestHeaderFieldTable_LookupMapEviction(t *testing.T) { - table := &headerFieldTable{} - table.init() - table.addEntry(pair("key1", "value1-1")) - table.addEntry(pair("key2", "value2-1")) - table.addEntry(pair("key1", "value1-2")) - table.addEntry(pair("key3", "value3-1")) - table.addEntry(pair("key4", "value4-1")) - table.addEntry(pair("key2", "value2-2")) - - // evict all pairs - table.evictOldest(table.len()) - - if l := table.len(); l > 0 { - t.Errorf("table.len() = %d, want 0", l) - } - - if l := len(table.byName); l > 0 { - t.Errorf("len(table.byName) = %d, want 0", l) - } - - if l := len(table.byNameValue); l > 0 { - t.Errorf("len(table.byNameValue) = %d, want 0", l) - } -} - -func TestStaticTable(t *testing.T) { - fromSpec := ` - +-------+-----------------------------+---------------+ - | 1 | :authority | | - | 2 | :method | GET | - | 3 | :method | POST | - | 4 | :path | / | - | 5 | :path | /index.html | - | 6 | :scheme | http | - | 7 | :scheme | https | - | 8 | :status | 200 | - | 9 | :status | 204 | - | 10 | :status | 206 | - | 11 | :status | 304 | - | 12 | :status | 400 | - | 13 | :status | 404 | - | 14 | :status | 500 | - | 15 | accept-charset | | - | 16 | accept-encoding | gzip, deflate | - | 17 | accept-language | | - | 18 | accept-ranges | | - | 19 | accept | | - | 20 | access-control-allow-origin | | - | 21 | age | | - | 22 | allow | | - | 23 | authorization | | - | 24 | cache-control | | - | 25 | content-disposition | | - | 26 | content-encoding | | - | 27 | content-language | | - | 28 | content-length | | - | 29 | content-location | | - | 30 | content-range | | - | 31 | content-type | | - | 32 | cookie | | - | 33 | date | | - | 34 | etag | | - | 35 | expect | | - | 36 | expires | | - | 37 | from | | - | 38 | host | | - | 39 | if-match | | - | 40 | if-modified-since | | - | 41 | if-none-match | | - | 42 | if-range | | - | 43 | if-unmodified-since | | - | 44 | last-modified | | - | 45 | link | | - | 46 | location | | - | 47 | max-forwards | | - | 48 | proxy-authenticate | | - | 49 | proxy-authorization | | - | 50 | range | | - | 51 | referer | | - | 52 | refresh | | - | 53 | retry-after | | - | 54 | server | | - | 55 | set-cookie | | - | 56 | strict-transport-security | | - | 57 | transfer-encoding | | - | 58 | user-agent | | - | 59 | vary | | - | 60 | via | | - | 61 | www-authenticate | | - +-------+-----------------------------+---------------+ -` - bs := bufio.NewScanner(strings.NewReader(fromSpec)) - re := regexp.MustCompile(`\| (\d+)\s+\| (\S+)\s*\| (\S(.*\S)?)?\s+\|`) - for bs.Scan() { - l := bs.Text() - if !strings.Contains(l, "|") { - continue - } - m := re.FindStringSubmatch(l) - if m == nil { - continue - } - i, err := strconv.Atoi(m[1]) - if err != nil { - t.Errorf("Bogus integer on line %q", l) - continue - } - if i < 1 || i > staticTable.len() { - t.Errorf("Bogus index %d on line %q", i, l) - continue - } - if got, want := staticTable.ents[i-1].Name, m[2]; got != want { - t.Errorf("header index %d name = %q; want %q", i, got, want) - } - if got, want := staticTable.ents[i-1].Value, m[3]; got != want { - t.Errorf("header index %d value = %q; want %q", i, got, want) - } - } - if err := bs.Err(); err != nil { - t.Error(err) - } -} diff --git a/vendor/golang.org/x/net/http2/http2_test.go b/vendor/golang.org/x/net/http2/http2_test.go deleted file mode 100644 index dda67439..00000000 --- a/vendor/golang.org/x/net/http2/http2_test.go +++ /dev/null @@ -1,280 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package http2 - -import ( - "bytes" - "errors" - "flag" - "fmt" - "net/http" - "os/exec" - "strconv" - "strings" - "testing" - "time" - - "golang.org/x/net/http2/hpack" -) - -var knownFailing = flag.Bool("known_failing", false, "Run known-failing tests.") - -func condSkipFailingTest(t *testing.T) { - if !*knownFailing { - t.Skip("Skipping known-failing test without --known_failing") - } -} - -func init() { - inTests = true - DebugGoroutines = true - flag.BoolVar(&VerboseLogs, "verboseh2", VerboseLogs, "Verbose HTTP/2 debug logging") -} - -func TestSettingString(t *testing.T) { - tests := []struct { - s Setting - want string - }{ - {Setting{SettingMaxFrameSize, 123}, "[MAX_FRAME_SIZE = 123]"}, - {Setting{1<<16 - 1, 123}, "[UNKNOWN_SETTING_65535 = 123]"}, - } - for i, tt := range tests { - got := fmt.Sprint(tt.s) - if got != tt.want { - t.Errorf("%d. for %#v, string = %q; want %q", i, tt.s, got, tt.want) - } - } -} - -type twriter struct { - t testing.TB - st *serverTester // optional -} - -func (w twriter) Write(p []byte) (n int, err error) { - if w.st != nil { - ps := string(p) - for _, phrase := range w.st.logFilter { - if strings.Contains(ps, phrase) { - return len(p), nil // no logging - } - } - } - w.t.Logf("%s", p) - return len(p), nil -} - -// like encodeHeader, but don't add implicit pseudo headers. -func encodeHeaderNoImplicit(t *testing.T, headers ...string) []byte { - var buf bytes.Buffer - enc := hpack.NewEncoder(&buf) - for len(headers) > 0 { - k, v := headers[0], headers[1] - headers = headers[2:] - if err := enc.WriteField(hpack.HeaderField{Name: k, Value: v}); err != nil { - t.Fatalf("HPACK encoding error for %q/%q: %v", k, v, err) - } - } - return buf.Bytes() -} - -// Verify that curl has http2. -func requireCurl(t *testing.T) { - out, err := dockerLogs(curl(t, "--version")) - if err != nil { - t.Skipf("failed to determine curl features; skipping test") - } - if !strings.Contains(string(out), "HTTP2") { - t.Skip("curl doesn't support HTTP2; skipping test") - } -} - -func curl(t *testing.T, args ...string) (container string) { - out, err := exec.Command("docker", append([]string{"run", "-d", "--net=host", "gohttp2/curl"}, args...)...).Output() - if err != nil { - t.Skipf("Failed to run curl in docker: %v, %s", err, out) - } - return strings.TrimSpace(string(out)) -} - -// Verify that h2load exists. -func requireH2load(t *testing.T) { - out, err := dockerLogs(h2load(t, "--version")) - if err != nil { - t.Skipf("failed to probe h2load; skipping test: %s", out) - } - if !strings.Contains(string(out), "h2load nghttp2/") { - t.Skipf("h2load not present; skipping test. (Output=%q)", out) - } -} - -func h2load(t *testing.T, args ...string) (container string) { - out, err := exec.Command("docker", append([]string{"run", "-d", "--net=host", "--entrypoint=/usr/local/bin/h2load", "gohttp2/curl"}, args...)...).Output() - if err != nil { - t.Skipf("Failed to run h2load in docker: %v, %s", err, out) - } - return strings.TrimSpace(string(out)) -} - -type puppetCommand struct { - fn func(w http.ResponseWriter, r *http.Request) - done chan<- bool -} - -type handlerPuppet struct { - ch chan puppetCommand -} - -func newHandlerPuppet() *handlerPuppet { - return &handlerPuppet{ - ch: make(chan puppetCommand), - } -} - -func (p *handlerPuppet) act(w http.ResponseWriter, r *http.Request) { - for cmd := range p.ch { - cmd.fn(w, r) - cmd.done <- true - } -} - -func (p *handlerPuppet) done() { close(p.ch) } -func (p *handlerPuppet) do(fn func(http.ResponseWriter, *http.Request)) { - done := make(chan bool) - p.ch <- puppetCommand{fn, done} - <-done -} -func dockerLogs(container string) ([]byte, error) { - out, err := exec.Command("docker", "wait", container).CombinedOutput() - if err != nil { - return out, err - } - exitStatus, err := strconv.Atoi(strings.TrimSpace(string(out))) - if err != nil { - return out, errors.New("unexpected exit status from docker wait") - } - out, err = exec.Command("docker", "logs", container).CombinedOutput() - exec.Command("docker", "rm", container).Run() - if err == nil && exitStatus != 0 { - err = fmt.Errorf("exit status %d: %s", exitStatus, out) - } - return out, err -} - -func kill(container string) { - exec.Command("docker", "kill", container).Run() - exec.Command("docker", "rm", container).Run() -} - -func cleanDate(res *http.Response) { - if d := res.Header["Date"]; len(d) == 1 { - d[0] = "XXX" - } -} - -func TestSorterPoolAllocs(t *testing.T) { - ss := []string{"a", "b", "c"} - h := http.Header{ - "a": nil, - "b": nil, - "c": nil, - } - sorter := new(sorter) - - if allocs := testing.AllocsPerRun(100, func() { - sorter.SortStrings(ss) - }); allocs >= 1 { - t.Logf("SortStrings allocs = %v; want <1", allocs) - } - - if allocs := testing.AllocsPerRun(5, func() { - if len(sorter.Keys(h)) != 3 { - t.Fatal("wrong result") - } - }); allocs > 0 { - t.Logf("Keys allocs = %v; want <1", allocs) - } -} - -// waitCondition reports whether fn eventually returned true, -// checking immediately and then every checkEvery amount, -// until waitFor has elapsed, at which point it returns false. -func waitCondition(waitFor, checkEvery time.Duration, fn func() bool) bool { - deadline := time.Now().Add(waitFor) - for time.Now().Before(deadline) { - if fn() { - return true - } - time.Sleep(checkEvery) - } - return false -} - -// waitErrCondition is like waitCondition but with errors instead of bools. -func waitErrCondition(waitFor, checkEvery time.Duration, fn func() error) error { - deadline := time.Now().Add(waitFor) - var err error - for time.Now().Before(deadline) { - if err = fn(); err == nil { - return nil - } - time.Sleep(checkEvery) - } - return err -} - -// Tests that http2.Server.IdleTimeout is initialized from -// http.Server.{Idle,Read}Timeout. http.Server.IdleTimeout was -// added in Go 1.8. -func TestConfigureServerIdleTimeout_Go18(t *testing.T) { - const timeout = 5 * time.Second - const notThisOne = 1 * time.Second - - // With a zero http2.Server, verify that it copies IdleTimeout: - { - s1 := &http.Server{ - IdleTimeout: timeout, - ReadTimeout: notThisOne, - } - s2 := &Server{} - if err := ConfigureServer(s1, s2); err != nil { - t.Fatal(err) - } - if s2.IdleTimeout != timeout { - t.Errorf("s2.IdleTimeout = %v; want %v", s2.IdleTimeout, timeout) - } - } - - // And that it falls back to ReadTimeout: - { - s1 := &http.Server{ - ReadTimeout: timeout, - } - s2 := &Server{} - if err := ConfigureServer(s1, s2); err != nil { - t.Fatal(err) - } - if s2.IdleTimeout != timeout { - t.Errorf("s2.IdleTimeout = %v; want %v", s2.IdleTimeout, timeout) - } - } - - // Verify that s1's IdleTimeout doesn't overwrite an existing setting: - { - s1 := &http.Server{ - IdleTimeout: notThisOne, - } - s2 := &Server{ - IdleTimeout: timeout, - } - if err := ConfigureServer(s1, s2); err != nil { - t.Fatal(err) - } - if s2.IdleTimeout != timeout { - t.Errorf("s2.IdleTimeout = %v; want %v", s2.IdleTimeout, timeout) - } - } -} diff --git a/vendor/golang.org/x/net/http2/pipe_test.go b/vendor/golang.org/x/net/http2/pipe_test.go deleted file mode 100644 index 1bf351ff..00000000 --- a/vendor/golang.org/x/net/http2/pipe_test.go +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package http2 - -import ( - "bytes" - "errors" - "io" - "io/ioutil" - "testing" -) - -func TestPipeClose(t *testing.T) { - var p pipe - p.b = new(bytes.Buffer) - a := errors.New("a") - b := errors.New("b") - p.CloseWithError(a) - p.CloseWithError(b) - _, err := p.Read(make([]byte, 1)) - if err != a { - t.Errorf("err = %v want %v", err, a) - } -} - -func TestPipeDoneChan(t *testing.T) { - var p pipe - done := p.Done() - select { - case <-done: - t.Fatal("done too soon") - default: - } - p.CloseWithError(io.EOF) - select { - case <-done: - default: - t.Fatal("should be done") - } -} - -func TestPipeDoneChan_ErrFirst(t *testing.T) { - var p pipe - p.CloseWithError(io.EOF) - done := p.Done() - select { - case <-done: - default: - t.Fatal("should be done") - } -} - -func TestPipeDoneChan_Break(t *testing.T) { - var p pipe - done := p.Done() - select { - case <-done: - t.Fatal("done too soon") - default: - } - p.BreakWithError(io.EOF) - select { - case <-done: - default: - t.Fatal("should be done") - } -} - -func TestPipeDoneChan_Break_ErrFirst(t *testing.T) { - var p pipe - p.BreakWithError(io.EOF) - done := p.Done() - select { - case <-done: - default: - t.Fatal("should be done") - } -} - -func TestPipeCloseWithError(t *testing.T) { - p := &pipe{b: new(bytes.Buffer)} - const body = "foo" - io.WriteString(p, body) - a := errors.New("test error") - p.CloseWithError(a) - all, err := ioutil.ReadAll(p) - if string(all) != body { - t.Errorf("read bytes = %q; want %q", all, body) - } - if err != a { - t.Logf("read error = %v, %v", err, a) - } - // Read and Write should fail. - if n, err := p.Write([]byte("abc")); err != errClosedPipeWrite || n != 0 { - t.Errorf("Write(abc) after close\ngot %v, %v\nwant 0, %v", n, err, errClosedPipeWrite) - } - if n, err := p.Read(make([]byte, 1)); err == nil || n != 0 { - t.Errorf("Read() after close\ngot %v, nil\nwant 0, %v", n, errClosedPipeWrite) - } -} - -func TestPipeBreakWithError(t *testing.T) { - p := &pipe{b: new(bytes.Buffer)} - io.WriteString(p, "foo") - a := errors.New("test err") - p.BreakWithError(a) - all, err := ioutil.ReadAll(p) - if string(all) != "" { - t.Errorf("read bytes = %q; want empty string", all) - } - if err != a { - t.Logf("read error = %v, %v", err, a) - } - if p.b != nil { - t.Errorf("buffer should be nil after BreakWithError") - } - // Write should succeed silently. - if n, err := p.Write([]byte("abc")); err != nil || n != 3 { - t.Errorf("Write(abc) after break\ngot %v, %v\nwant 0, nil", n, err) - } - if p.b != nil { - t.Errorf("buffer should be nil after Write") - } - // Read should fail. - if n, err := p.Read(make([]byte, 1)); err == nil || n != 0 { - t.Errorf("Read() after close\ngot %v, nil\nwant 0, not nil", n) - } -} diff --git a/vendor/golang.org/x/net/http2/server_push_test.go b/vendor/golang.org/x/net/http2/server_push_test.go deleted file mode 100644 index 6e57de0b..00000000 --- a/vendor/golang.org/x/net/http2/server_push_test.go +++ /dev/null @@ -1,519 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package http2 - -import ( - "errors" - "fmt" - "io" - "io/ioutil" - "net/http" - "reflect" - "strconv" - "sync" - "testing" - "time" -) - -func TestServer_Push_Success(t *testing.T) { - const ( - mainBody = "index page" - pushedBody = "pushed page" - userAgent = "testagent" - cookie = "testcookie" - ) - - var stURL string - checkPromisedReq := func(r *http.Request, wantMethod string, wantH http.Header) error { - if got, want := r.Method, wantMethod; got != want { - return fmt.Errorf("promised Req.Method=%q, want %q", got, want) - } - if got, want := r.Header, wantH; !reflect.DeepEqual(got, want) { - return fmt.Errorf("promised Req.Header=%q, want %q", got, want) - } - if got, want := "https://"+r.Host, stURL; got != want { - return fmt.Errorf("promised Req.Host=%q, want %q", got, want) - } - if r.Body == nil { - return fmt.Errorf("nil Body") - } - if buf, err := ioutil.ReadAll(r.Body); err != nil || len(buf) != 0 { - return fmt.Errorf("ReadAll(Body)=%q,%v, want '',nil", buf, err) - } - return nil - } - - errc := make(chan error, 3) - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - switch r.URL.RequestURI() { - case "/": - // Push "/pushed?get" as a GET request, using an absolute URL. - opt := &http.PushOptions{ - Header: http.Header{ - "User-Agent": {userAgent}, - }, - } - if err := w.(http.Pusher).Push(stURL+"/pushed?get", opt); err != nil { - errc <- fmt.Errorf("error pushing /pushed?get: %v", err) - return - } - // Push "/pushed?head" as a HEAD request, using a path. - opt = &http.PushOptions{ - Method: "HEAD", - Header: http.Header{ - "User-Agent": {userAgent}, - "Cookie": {cookie}, - }, - } - if err := w.(http.Pusher).Push("/pushed?head", opt); err != nil { - errc <- fmt.Errorf("error pushing /pushed?head: %v", err) - return - } - w.Header().Set("Content-Type", "text/html") - w.Header().Set("Content-Length", strconv.Itoa(len(mainBody))) - w.WriteHeader(200) - io.WriteString(w, mainBody) - errc <- nil - - case "/pushed?get": - wantH := http.Header{} - wantH.Set("User-Agent", userAgent) - if err := checkPromisedReq(r, "GET", wantH); err != nil { - errc <- fmt.Errorf("/pushed?get: %v", err) - return - } - w.Header().Set("Content-Type", "text/html") - w.Header().Set("Content-Length", strconv.Itoa(len(pushedBody))) - w.WriteHeader(200) - io.WriteString(w, pushedBody) - errc <- nil - - case "/pushed?head": - wantH := http.Header{} - wantH.Set("User-Agent", userAgent) - wantH.Set("Cookie", cookie) - if err := checkPromisedReq(r, "HEAD", wantH); err != nil { - errc <- fmt.Errorf("/pushed?head: %v", err) - return - } - w.WriteHeader(204) - errc <- nil - - default: - errc <- fmt.Errorf("unknown RequestURL %q", r.URL.RequestURI()) - } - }) - stURL = st.ts.URL - - // Send one request, which should push two responses. - st.greet() - getSlash(st) - for k := 0; k < 3; k++ { - select { - case <-time.After(2 * time.Second): - t.Errorf("timeout waiting for handler %d to finish", k) - case err := <-errc: - if err != nil { - t.Fatal(err) - } - } - } - - checkPushPromise := func(f Frame, promiseID uint32, wantH [][2]string) error { - pp, ok := f.(*PushPromiseFrame) - if !ok { - return fmt.Errorf("got a %T; want *PushPromiseFrame", f) - } - if !pp.HeadersEnded() { - return fmt.Errorf("want END_HEADERS flag in PushPromiseFrame") - } - if got, want := pp.PromiseID, promiseID; got != want { - return fmt.Errorf("got PromiseID %v; want %v", got, want) - } - gotH := st.decodeHeader(pp.HeaderBlockFragment()) - if !reflect.DeepEqual(gotH, wantH) { - return fmt.Errorf("got promised headers %v; want %v", gotH, wantH) - } - return nil - } - checkHeaders := func(f Frame, wantH [][2]string) error { - hf, ok := f.(*HeadersFrame) - if !ok { - return fmt.Errorf("got a %T; want *HeadersFrame", f) - } - gotH := st.decodeHeader(hf.HeaderBlockFragment()) - if !reflect.DeepEqual(gotH, wantH) { - return fmt.Errorf("got response headers %v; want %v", gotH, wantH) - } - return nil - } - checkData := func(f Frame, wantData string) error { - df, ok := f.(*DataFrame) - if !ok { - return fmt.Errorf("got a %T; want *DataFrame", f) - } - if gotData := string(df.Data()); gotData != wantData { - return fmt.Errorf("got response data %q; want %q", gotData, wantData) - } - return nil - } - - // Stream 1 has 2 PUSH_PROMISE + HEADERS + DATA - // Stream 2 has HEADERS + DATA - // Stream 4 has HEADERS - expected := map[uint32][]func(Frame) error{ - 1: { - func(f Frame) error { - return checkPushPromise(f, 2, [][2]string{ - {":method", "GET"}, - {":scheme", "https"}, - {":authority", st.ts.Listener.Addr().String()}, - {":path", "/pushed?get"}, - {"user-agent", userAgent}, - }) - }, - func(f Frame) error { - return checkPushPromise(f, 4, [][2]string{ - {":method", "HEAD"}, - {":scheme", "https"}, - {":authority", st.ts.Listener.Addr().String()}, - {":path", "/pushed?head"}, - {"cookie", cookie}, - {"user-agent", userAgent}, - }) - }, - func(f Frame) error { - return checkHeaders(f, [][2]string{ - {":status", "200"}, - {"content-type", "text/html"}, - {"content-length", strconv.Itoa(len(mainBody))}, - }) - }, - func(f Frame) error { - return checkData(f, mainBody) - }, - }, - 2: { - func(f Frame) error { - return checkHeaders(f, [][2]string{ - {":status", "200"}, - {"content-type", "text/html"}, - {"content-length", strconv.Itoa(len(pushedBody))}, - }) - }, - func(f Frame) error { - return checkData(f, pushedBody) - }, - }, - 4: { - func(f Frame) error { - return checkHeaders(f, [][2]string{ - {":status", "204"}, - }) - }, - }, - } - - consumed := map[uint32]int{} - for k := 0; len(expected) > 0; k++ { - f, err := st.readFrame() - if err != nil { - for id, left := range expected { - t.Errorf("stream %d: missing %d frames", id, len(left)) - } - t.Fatalf("readFrame %d: %v", k, err) - } - id := f.Header().StreamID - label := fmt.Sprintf("stream %d, frame %d", id, consumed[id]) - if len(expected[id]) == 0 { - t.Fatalf("%s: unexpected frame %#+v", label, f) - } - check := expected[id][0] - expected[id] = expected[id][1:] - if len(expected[id]) == 0 { - delete(expected, id) - } - if err := check(f); err != nil { - t.Fatalf("%s: %v", label, err) - } - consumed[id]++ - } -} - -func TestServer_Push_SuccessNoRace(t *testing.T) { - // Regression test for issue #18326. Ensure the request handler can mutate - // pushed request headers without racing with the PUSH_PROMISE write. - errc := make(chan error, 2) - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - switch r.URL.RequestURI() { - case "/": - opt := &http.PushOptions{ - Header: http.Header{"User-Agent": {"testagent"}}, - } - if err := w.(http.Pusher).Push("/pushed", opt); err != nil { - errc <- fmt.Errorf("error pushing: %v", err) - return - } - w.WriteHeader(200) - errc <- nil - - case "/pushed": - // Update request header, ensure there is no race. - r.Header.Set("User-Agent", "newagent") - r.Header.Set("Cookie", "cookie") - w.WriteHeader(200) - errc <- nil - - default: - errc <- fmt.Errorf("unknown RequestURL %q", r.URL.RequestURI()) - } - }) - - // Send one request, which should push one response. - st.greet() - getSlash(st) - for k := 0; k < 2; k++ { - select { - case <-time.After(2 * time.Second): - t.Errorf("timeout waiting for handler %d to finish", k) - case err := <-errc: - if err != nil { - t.Fatal(err) - } - } - } -} - -func TestServer_Push_RejectRecursivePush(t *testing.T) { - // Expect two requests, but might get three if there's a bug and the second push succeeds. - errc := make(chan error, 3) - handler := func(w http.ResponseWriter, r *http.Request) error { - baseURL := "https://" + r.Host - switch r.URL.Path { - case "/": - if err := w.(http.Pusher).Push(baseURL+"/push1", nil); err != nil { - return fmt.Errorf("first Push()=%v, want nil", err) - } - return nil - - case "/push1": - if got, want := w.(http.Pusher).Push(baseURL+"/push2", nil), ErrRecursivePush; got != want { - return fmt.Errorf("Push()=%v, want %v", got, want) - } - return nil - - default: - return fmt.Errorf("unexpected path: %q", r.URL.Path) - } - } - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - errc <- handler(w, r) - }) - defer st.Close() - st.greet() - getSlash(st) - if err := <-errc; err != nil { - t.Errorf("First request failed: %v", err) - } - if err := <-errc; err != nil { - t.Errorf("Second request failed: %v", err) - } -} - -func testServer_Push_RejectSingleRequest(t *testing.T, doPush func(http.Pusher, *http.Request) error, settings ...Setting) { - // Expect one request, but might get two if there's a bug and the push succeeds. - errc := make(chan error, 2) - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - errc <- doPush(w.(http.Pusher), r) - }) - defer st.Close() - st.greet() - if err := st.fr.WriteSettings(settings...); err != nil { - st.t.Fatalf("WriteSettings: %v", err) - } - st.wantSettingsAck() - getSlash(st) - if err := <-errc; err != nil { - t.Error(err) - } - // Should not get a PUSH_PROMISE frame. - hf := st.wantHeaders() - if !hf.StreamEnded() { - t.Error("stream should end after headers") - } -} - -func TestServer_Push_RejectIfDisabled(t *testing.T) { - testServer_Push_RejectSingleRequest(t, - func(p http.Pusher, r *http.Request) error { - if got, want := p.Push("https://"+r.Host+"/pushed", nil), http.ErrNotSupported; got != want { - return fmt.Errorf("Push()=%v, want %v", got, want) - } - return nil - }, - Setting{SettingEnablePush, 0}) -} - -func TestServer_Push_RejectWhenNoConcurrentStreams(t *testing.T) { - testServer_Push_RejectSingleRequest(t, - func(p http.Pusher, r *http.Request) error { - if got, want := p.Push("https://"+r.Host+"/pushed", nil), ErrPushLimitReached; got != want { - return fmt.Errorf("Push()=%v, want %v", got, want) - } - return nil - }, - Setting{SettingMaxConcurrentStreams, 0}) -} - -func TestServer_Push_RejectWrongScheme(t *testing.T) { - testServer_Push_RejectSingleRequest(t, - func(p http.Pusher, r *http.Request) error { - if err := p.Push("http://"+r.Host+"/pushed", nil); err == nil { - return errors.New("Push() should have failed (push target URL is http)") - } - return nil - }) -} - -func TestServer_Push_RejectMissingHost(t *testing.T) { - testServer_Push_RejectSingleRequest(t, - func(p http.Pusher, r *http.Request) error { - if err := p.Push("https:pushed", nil); err == nil { - return errors.New("Push() should have failed (push target URL missing host)") - } - return nil - }) -} - -func TestServer_Push_RejectRelativePath(t *testing.T) { - testServer_Push_RejectSingleRequest(t, - func(p http.Pusher, r *http.Request) error { - if err := p.Push("../test", nil); err == nil { - return errors.New("Push() should have failed (push target is a relative path)") - } - return nil - }) -} - -func TestServer_Push_RejectForbiddenMethod(t *testing.T) { - testServer_Push_RejectSingleRequest(t, - func(p http.Pusher, r *http.Request) error { - if err := p.Push("https://"+r.Host+"/pushed", &http.PushOptions{Method: "POST"}); err == nil { - return errors.New("Push() should have failed (cannot promise a POST)") - } - return nil - }) -} - -func TestServer_Push_RejectForbiddenHeader(t *testing.T) { - testServer_Push_RejectSingleRequest(t, - func(p http.Pusher, r *http.Request) error { - header := http.Header{ - "Content-Length": {"10"}, - "Content-Encoding": {"gzip"}, - "Trailer": {"Foo"}, - "Te": {"trailers"}, - "Host": {"test.com"}, - ":authority": {"test.com"}, - } - if err := p.Push("https://"+r.Host+"/pushed", &http.PushOptions{Header: header}); err == nil { - return errors.New("Push() should have failed (forbidden headers)") - } - return nil - }) -} - -func TestServer_Push_StateTransitions(t *testing.T) { - const body = "foo" - - gotPromise := make(chan bool) - finishedPush := make(chan bool) - - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - switch r.URL.RequestURI() { - case "/": - if err := w.(http.Pusher).Push("/pushed", nil); err != nil { - t.Errorf("Push error: %v", err) - } - // Don't finish this request until the push finishes so we don't - // nondeterministically interleave output frames with the push. - <-finishedPush - case "/pushed": - <-gotPromise - } - w.Header().Set("Content-Type", "text/html") - w.Header().Set("Content-Length", strconv.Itoa(len(body))) - w.WriteHeader(200) - io.WriteString(w, body) - }) - defer st.Close() - - st.greet() - if st.stream(2) != nil { - t.Fatal("stream 2 should be empty") - } - if got, want := st.streamState(2), stateIdle; got != want { - t.Fatalf("streamState(2)=%v, want %v", got, want) - } - getSlash(st) - // After the PUSH_PROMISE is sent, the stream should be stateHalfClosedRemote. - st.wantPushPromise() - if got, want := st.streamState(2), stateHalfClosedRemote; got != want { - t.Fatalf("streamState(2)=%v, want %v", got, want) - } - // We stall the HTTP handler for "/pushed" until the above check. If we don't - // stall the handler, then the handler might write HEADERS and DATA and finish - // the stream before we check st.streamState(2) -- should that happen, we'll - // see stateClosed and fail the above check. - close(gotPromise) - st.wantHeaders() - if df := st.wantData(); !df.StreamEnded() { - t.Fatal("expected END_STREAM flag on DATA") - } - if got, want := st.streamState(2), stateClosed; got != want { - t.Fatalf("streamState(2)=%v, want %v", got, want) - } - close(finishedPush) -} - -func TestServer_Push_RejectAfterGoAway(t *testing.T) { - var readyOnce sync.Once - ready := make(chan struct{}) - errc := make(chan error, 2) - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - select { - case <-ready: - case <-time.After(5 * time.Second): - errc <- fmt.Errorf("timeout waiting for GOAWAY to be processed") - } - if got, want := w.(http.Pusher).Push("https://"+r.Host+"/pushed", nil), http.ErrNotSupported; got != want { - errc <- fmt.Errorf("Push()=%v, want %v", got, want) - } - errc <- nil - }) - defer st.Close() - st.greet() - getSlash(st) - - // Send GOAWAY and wait for it to be processed. - st.fr.WriteGoAway(1, ErrCodeNo, nil) - go func() { - for { - select { - case <-ready: - return - default: - } - st.sc.serveMsgCh <- func(loopNum int) { - if !st.sc.pushEnabled { - readyOnce.Do(func() { close(ready) }) - } - } - } - }() - if err := <-errc; err != nil { - t.Error(err) - } -} diff --git a/vendor/golang.org/x/net/http2/server_test.go b/vendor/golang.org/x/net/http2/server_test.go deleted file mode 100644 index f26e910f..00000000 --- a/vendor/golang.org/x/net/http2/server_test.go +++ /dev/null @@ -1,3899 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package http2 - -import ( - "bytes" - "context" - "crypto/tls" - "errors" - "flag" - "fmt" - "io" - "io/ioutil" - "log" - "net" - "net/http" - "net/http/httptest" - "os" - "os/exec" - "reflect" - "runtime" - "strconv" - "strings" - "sync" - "sync/atomic" - "testing" - "time" - - "golang.org/x/net/http2/hpack" -) - -var stderrVerbose = flag.Bool("stderr_verbose", false, "Mirror verbosity to stderr, unbuffered") - -func stderrv() io.Writer { - if *stderrVerbose { - return os.Stderr - } - - return ioutil.Discard -} - -type serverTester struct { - cc net.Conn // client conn - t testing.TB - ts *httptest.Server - fr *Framer - serverLogBuf bytes.Buffer // logger for httptest.Server - logFilter []string // substrings to filter out - scMu sync.Mutex // guards sc - sc *serverConn - hpackDec *hpack.Decoder - decodedHeaders [][2]string - - // If http2debug!=2, then we capture Frame debug logs that will be written - // to t.Log after a test fails. The read and write logs use separate locks - // and buffers so we don't accidentally introduce synchronization between - // the read and write goroutines, which may hide data races. - frameReadLogMu sync.Mutex - frameReadLogBuf bytes.Buffer - frameWriteLogMu sync.Mutex - frameWriteLogBuf bytes.Buffer - - // writing headers: - headerBuf bytes.Buffer - hpackEnc *hpack.Encoder -} - -func init() { - testHookOnPanicMu = new(sync.Mutex) - goAwayTimeout = 25 * time.Millisecond -} - -func resetHooks() { - testHookOnPanicMu.Lock() - testHookOnPanic = nil - testHookOnPanicMu.Unlock() -} - -type serverTesterOpt string - -var optOnlyServer = serverTesterOpt("only_server") -var optQuiet = serverTesterOpt("quiet_logging") -var optFramerReuseFrames = serverTesterOpt("frame_reuse_frames") - -func newServerTester(t testing.TB, handler http.HandlerFunc, opts ...interface{}) *serverTester { - resetHooks() - - ts := httptest.NewUnstartedServer(handler) - - tlsConfig := &tls.Config{ - InsecureSkipVerify: true, - NextProtos: []string{NextProtoTLS}, - } - - var onlyServer, quiet, framerReuseFrames bool - h2server := new(Server) - for _, opt := range opts { - switch v := opt.(type) { - case func(*tls.Config): - v(tlsConfig) - case func(*httptest.Server): - v(ts) - case func(*Server): - v(h2server) - case serverTesterOpt: - switch v { - case optOnlyServer: - onlyServer = true - case optQuiet: - quiet = true - case optFramerReuseFrames: - framerReuseFrames = true - } - case func(net.Conn, http.ConnState): - ts.Config.ConnState = v - default: - t.Fatalf("unknown newServerTester option type %T", v) - } - } - - ConfigureServer(ts.Config, h2server) - - st := &serverTester{ - t: t, - ts: ts, - } - st.hpackEnc = hpack.NewEncoder(&st.headerBuf) - st.hpackDec = hpack.NewDecoder(initialHeaderTableSize, st.onHeaderField) - - ts.TLS = ts.Config.TLSConfig // the httptest.Server has its own copy of this TLS config - if quiet { - ts.Config.ErrorLog = log.New(ioutil.Discard, "", 0) - } else { - ts.Config.ErrorLog = log.New(io.MultiWriter(stderrv(), twriter{t: t, st: st}, &st.serverLogBuf), "", log.LstdFlags) - } - ts.StartTLS() - - if VerboseLogs { - t.Logf("Running test server at: %s", ts.URL) - } - testHookGetServerConn = func(v *serverConn) { - st.scMu.Lock() - defer st.scMu.Unlock() - st.sc = v - } - log.SetOutput(io.MultiWriter(stderrv(), twriter{t: t, st: st})) - if !onlyServer { - cc, err := tls.Dial("tcp", ts.Listener.Addr().String(), tlsConfig) - if err != nil { - t.Fatal(err) - } - st.cc = cc - st.fr = NewFramer(cc, cc) - if framerReuseFrames { - st.fr.SetReuseFrames() - } - if !logFrameReads && !logFrameWrites { - st.fr.debugReadLoggerf = func(m string, v ...interface{}) { - m = time.Now().Format("2006-01-02 15:04:05.999999999 ") + strings.TrimPrefix(m, "http2: ") + "\n" - st.frameReadLogMu.Lock() - fmt.Fprintf(&st.frameReadLogBuf, m, v...) - st.frameReadLogMu.Unlock() - } - st.fr.debugWriteLoggerf = func(m string, v ...interface{}) { - m = time.Now().Format("2006-01-02 15:04:05.999999999 ") + strings.TrimPrefix(m, "http2: ") + "\n" - st.frameWriteLogMu.Lock() - fmt.Fprintf(&st.frameWriteLogBuf, m, v...) - st.frameWriteLogMu.Unlock() - } - st.fr.logReads = true - st.fr.logWrites = true - } - } - return st -} - -func (st *serverTester) closeConn() { - st.scMu.Lock() - defer st.scMu.Unlock() - st.sc.conn.Close() -} - -func (st *serverTester) addLogFilter(phrase string) { - st.logFilter = append(st.logFilter, phrase) -} - -func (st *serverTester) stream(id uint32) *stream { - ch := make(chan *stream, 1) - st.sc.serveMsgCh <- func(int) { - ch <- st.sc.streams[id] - } - return <-ch -} - -func (st *serverTester) streamState(id uint32) streamState { - ch := make(chan streamState, 1) - st.sc.serveMsgCh <- func(int) { - state, _ := st.sc.state(id) - ch <- state - } - return <-ch -} - -// loopNum reports how many times this conn's select loop has gone around. -func (st *serverTester) loopNum() int { - lastc := make(chan int, 1) - st.sc.serveMsgCh <- func(loopNum int) { - lastc <- loopNum - } - return <-lastc -} - -// awaitIdle heuristically awaits for the server conn's select loop to be idle. -// The heuristic is that the server connection's serve loop must schedule -// 50 times in a row without any channel sends or receives occurring. -func (st *serverTester) awaitIdle() { - remain := 50 - last := st.loopNum() - for remain > 0 { - n := st.loopNum() - if n == last+1 { - remain-- - } else { - remain = 50 - } - last = n - } -} - -func (st *serverTester) Close() { - if st.t.Failed() { - st.frameReadLogMu.Lock() - if st.frameReadLogBuf.Len() > 0 { - st.t.Logf("Framer read log:\n%s", st.frameReadLogBuf.String()) - } - st.frameReadLogMu.Unlock() - - st.frameWriteLogMu.Lock() - if st.frameWriteLogBuf.Len() > 0 { - st.t.Logf("Framer write log:\n%s", st.frameWriteLogBuf.String()) - } - st.frameWriteLogMu.Unlock() - - // If we failed already (and are likely in a Fatal, - // unwindowing), force close the connection, so the - // httptest.Server doesn't wait forever for the conn - // to close. - if st.cc != nil { - st.cc.Close() - } - } - st.ts.Close() - if st.cc != nil { - st.cc.Close() - } - log.SetOutput(os.Stderr) -} - -// greet initiates the client's HTTP/2 connection into a state where -// frames may be sent. -func (st *serverTester) greet() { - st.greetAndCheckSettings(func(Setting) error { return nil }) -} - -func (st *serverTester) greetAndCheckSettings(checkSetting func(s Setting) error) { - st.writePreface() - st.writeInitialSettings() - st.wantSettings().ForeachSetting(checkSetting) - st.writeSettingsAck() - - // The initial WINDOW_UPDATE and SETTINGS ACK can come in any order. - var gotSettingsAck bool - var gotWindowUpdate bool - - for i := 0; i < 2; i++ { - f, err := st.readFrame() - if err != nil { - st.t.Fatal(err) - } - switch f := f.(type) { - case *SettingsFrame: - if !f.Header().Flags.Has(FlagSettingsAck) { - st.t.Fatal("Settings Frame didn't have ACK set") - } - gotSettingsAck = true - - case *WindowUpdateFrame: - if f.FrameHeader.StreamID != 0 { - st.t.Fatalf("WindowUpdate StreamID = %d; want 0", f.FrameHeader.StreamID) - } - incr := uint32((&Server{}).initialConnRecvWindowSize() - initialWindowSize) - if f.Increment != incr { - st.t.Fatalf("WindowUpdate increment = %d; want %d", f.Increment, incr) - } - gotWindowUpdate = true - - default: - st.t.Fatalf("Wanting a settings ACK or window update, received a %T", f) - } - } - - if !gotSettingsAck { - st.t.Fatalf("Didn't get a settings ACK") - } - if !gotWindowUpdate { - st.t.Fatalf("Didn't get a window update") - } -} - -func (st *serverTester) writePreface() { - n, err := st.cc.Write(clientPreface) - if err != nil { - st.t.Fatalf("Error writing client preface: %v", err) - } - if n != len(clientPreface) { - st.t.Fatalf("Writing client preface, wrote %d bytes; want %d", n, len(clientPreface)) - } -} - -func (st *serverTester) writeInitialSettings() { - if err := st.fr.WriteSettings(); err != nil { - st.t.Fatalf("Error writing initial SETTINGS frame from client to server: %v", err) - } -} - -func (st *serverTester) writeSettingsAck() { - if err := st.fr.WriteSettingsAck(); err != nil { - st.t.Fatalf("Error writing ACK of server's SETTINGS: %v", err) - } -} - -func (st *serverTester) writeHeaders(p HeadersFrameParam) { - if err := st.fr.WriteHeaders(p); err != nil { - st.t.Fatalf("Error writing HEADERS: %v", err) - } -} - -func (st *serverTester) writePriority(id uint32, p PriorityParam) { - if err := st.fr.WritePriority(id, p); err != nil { - st.t.Fatalf("Error writing PRIORITY: %v", err) - } -} - -func (st *serverTester) encodeHeaderField(k, v string) { - err := st.hpackEnc.WriteField(hpack.HeaderField{Name: k, Value: v}) - if err != nil { - st.t.Fatalf("HPACK encoding error for %q/%q: %v", k, v, err) - } -} - -// encodeHeaderRaw is the magic-free version of encodeHeader. -// It takes 0 or more (k, v) pairs and encodes them. -func (st *serverTester) encodeHeaderRaw(headers ...string) []byte { - if len(headers)%2 == 1 { - panic("odd number of kv args") - } - st.headerBuf.Reset() - for len(headers) > 0 { - k, v := headers[0], headers[1] - st.encodeHeaderField(k, v) - headers = headers[2:] - } - return st.headerBuf.Bytes() -} - -// encodeHeader encodes headers and returns their HPACK bytes. headers -// must contain an even number of key/value pairs. There may be -// multiple pairs for keys (e.g. "cookie"). The :method, :path, and -// :scheme headers default to GET, / and https. The :authority header -// defaults to st.ts.Listener.Addr(). -func (st *serverTester) encodeHeader(headers ...string) []byte { - if len(headers)%2 == 1 { - panic("odd number of kv args") - } - - st.headerBuf.Reset() - defaultAuthority := st.ts.Listener.Addr().String() - - if len(headers) == 0 { - // Fast path, mostly for benchmarks, so test code doesn't pollute - // profiles when we're looking to improve server allocations. - st.encodeHeaderField(":method", "GET") - st.encodeHeaderField(":scheme", "https") - st.encodeHeaderField(":authority", defaultAuthority) - st.encodeHeaderField(":path", "/") - return st.headerBuf.Bytes() - } - - if len(headers) == 2 && headers[0] == ":method" { - // Another fast path for benchmarks. - st.encodeHeaderField(":method", headers[1]) - st.encodeHeaderField(":scheme", "https") - st.encodeHeaderField(":authority", defaultAuthority) - st.encodeHeaderField(":path", "/") - return st.headerBuf.Bytes() - } - - pseudoCount := map[string]int{} - keys := []string{":method", ":scheme", ":authority", ":path"} - vals := map[string][]string{ - ":method": {"GET"}, - ":scheme": {"https"}, - ":authority": {defaultAuthority}, - ":path": {"/"}, - } - for len(headers) > 0 { - k, v := headers[0], headers[1] - headers = headers[2:] - if _, ok := vals[k]; !ok { - keys = append(keys, k) - } - if strings.HasPrefix(k, ":") { - pseudoCount[k]++ - if pseudoCount[k] == 1 { - vals[k] = []string{v} - } else { - // Allows testing of invalid headers w/ dup pseudo fields. - vals[k] = append(vals[k], v) - } - } else { - vals[k] = append(vals[k], v) - } - } - for _, k := range keys { - for _, v := range vals[k] { - st.encodeHeaderField(k, v) - } - } - return st.headerBuf.Bytes() -} - -// bodylessReq1 writes a HEADERS frames with StreamID 1 and EndStream and EndHeaders set. -func (st *serverTester) bodylessReq1(headers ...string) { - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, // clients send odd numbers - BlockFragment: st.encodeHeader(headers...), - EndStream: true, - EndHeaders: true, - }) -} - -func (st *serverTester) writeData(streamID uint32, endStream bool, data []byte) { - if err := st.fr.WriteData(streamID, endStream, data); err != nil { - st.t.Fatalf("Error writing DATA: %v", err) - } -} - -func (st *serverTester) writeDataPadded(streamID uint32, endStream bool, data, pad []byte) { - if err := st.fr.WriteDataPadded(streamID, endStream, data, pad); err != nil { - st.t.Fatalf("Error writing DATA: %v", err) - } -} - -func readFrameTimeout(fr *Framer, wait time.Duration) (Frame, error) { - ch := make(chan interface{}, 1) - go func() { - fr, err := fr.ReadFrame() - if err != nil { - ch <- err - } else { - ch <- fr - } - }() - t := time.NewTimer(wait) - select { - case v := <-ch: - t.Stop() - if fr, ok := v.(Frame); ok { - return fr, nil - } - return nil, v.(error) - case <-t.C: - return nil, errors.New("timeout waiting for frame") - } -} - -func (st *serverTester) readFrame() (Frame, error) { - return readFrameTimeout(st.fr, 2*time.Second) -} - -func (st *serverTester) wantHeaders() *HeadersFrame { - f, err := st.readFrame() - if err != nil { - st.t.Fatalf("Error while expecting a HEADERS frame: %v", err) - } - hf, ok := f.(*HeadersFrame) - if !ok { - st.t.Fatalf("got a %T; want *HeadersFrame", f) - } - return hf -} - -func (st *serverTester) wantContinuation() *ContinuationFrame { - f, err := st.readFrame() - if err != nil { - st.t.Fatalf("Error while expecting a CONTINUATION frame: %v", err) - } - cf, ok := f.(*ContinuationFrame) - if !ok { - st.t.Fatalf("got a %T; want *ContinuationFrame", f) - } - return cf -} - -func (st *serverTester) wantData() *DataFrame { - f, err := st.readFrame() - if err != nil { - st.t.Fatalf("Error while expecting a DATA frame: %v", err) - } - df, ok := f.(*DataFrame) - if !ok { - st.t.Fatalf("got a %T; want *DataFrame", f) - } - return df -} - -func (st *serverTester) wantSettings() *SettingsFrame { - f, err := st.readFrame() - if err != nil { - st.t.Fatalf("Error while expecting a SETTINGS frame: %v", err) - } - sf, ok := f.(*SettingsFrame) - if !ok { - st.t.Fatalf("got a %T; want *SettingsFrame", f) - } - return sf -} - -func (st *serverTester) wantPing() *PingFrame { - f, err := st.readFrame() - if err != nil { - st.t.Fatalf("Error while expecting a PING frame: %v", err) - } - pf, ok := f.(*PingFrame) - if !ok { - st.t.Fatalf("got a %T; want *PingFrame", f) - } - return pf -} - -func (st *serverTester) wantGoAway() *GoAwayFrame { - f, err := st.readFrame() - if err != nil { - st.t.Fatalf("Error while expecting a GOAWAY frame: %v", err) - } - gf, ok := f.(*GoAwayFrame) - if !ok { - st.t.Fatalf("got a %T; want *GoAwayFrame", f) - } - return gf -} - -func (st *serverTester) wantRSTStream(streamID uint32, errCode ErrCode) { - f, err := st.readFrame() - if err != nil { - st.t.Fatalf("Error while expecting an RSTStream frame: %v", err) - } - rs, ok := f.(*RSTStreamFrame) - if !ok { - st.t.Fatalf("got a %T; want *RSTStreamFrame", f) - } - if rs.FrameHeader.StreamID != streamID { - st.t.Fatalf("RSTStream StreamID = %d; want %d", rs.FrameHeader.StreamID, streamID) - } - if rs.ErrCode != errCode { - st.t.Fatalf("RSTStream ErrCode = %d (%s); want %d (%s)", rs.ErrCode, rs.ErrCode, errCode, errCode) - } -} - -func (st *serverTester) wantWindowUpdate(streamID, incr uint32) { - f, err := st.readFrame() - if err != nil { - st.t.Fatalf("Error while expecting a WINDOW_UPDATE frame: %v", err) - } - wu, ok := f.(*WindowUpdateFrame) - if !ok { - st.t.Fatalf("got a %T; want *WindowUpdateFrame", f) - } - if wu.FrameHeader.StreamID != streamID { - st.t.Fatalf("WindowUpdate StreamID = %d; want %d", wu.FrameHeader.StreamID, streamID) - } - if wu.Increment != incr { - st.t.Fatalf("WindowUpdate increment = %d; want %d", wu.Increment, incr) - } -} - -func (st *serverTester) wantSettingsAck() { - f, err := st.readFrame() - if err != nil { - st.t.Fatal(err) - } - sf, ok := f.(*SettingsFrame) - if !ok { - st.t.Fatalf("Wanting a settings ACK, received a %T", f) - } - if !sf.Header().Flags.Has(FlagSettingsAck) { - st.t.Fatal("Settings Frame didn't have ACK set") - } -} - -func (st *serverTester) wantPushPromise() *PushPromiseFrame { - f, err := st.readFrame() - if err != nil { - st.t.Fatal(err) - } - ppf, ok := f.(*PushPromiseFrame) - if !ok { - st.t.Fatalf("Wanted PushPromise, received %T", ppf) - } - return ppf -} - -func TestServer(t *testing.T) { - gotReq := make(chan bool, 1) - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Foo", "Bar") - gotReq <- true - }) - defer st.Close() - - covers("3.5", ` - The server connection preface consists of a potentially empty - SETTINGS frame ([SETTINGS]) that MUST be the first frame the - server sends in the HTTP/2 connection. - `) - - st.greet() - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, // clients send odd numbers - BlockFragment: st.encodeHeader(), - EndStream: true, // no DATA frames - EndHeaders: true, - }) - - select { - case <-gotReq: - case <-time.After(2 * time.Second): - t.Error("timeout waiting for request") - } -} - -func TestServer_Request_Get(t *testing.T) { - testServerRequest(t, func(st *serverTester) { - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, // clients send odd numbers - BlockFragment: st.encodeHeader("foo-bar", "some-value"), - EndStream: true, // no DATA frames - EndHeaders: true, - }) - }, func(r *http.Request) { - if r.Method != "GET" { - t.Errorf("Method = %q; want GET", r.Method) - } - if r.URL.Path != "/" { - t.Errorf("URL.Path = %q; want /", r.URL.Path) - } - if r.ContentLength != 0 { - t.Errorf("ContentLength = %v; want 0", r.ContentLength) - } - if r.Close { - t.Error("Close = true; want false") - } - if !strings.Contains(r.RemoteAddr, ":") { - t.Errorf("RemoteAddr = %q; want something with a colon", r.RemoteAddr) - } - if r.Proto != "HTTP/2.0" || r.ProtoMajor != 2 || r.ProtoMinor != 0 { - t.Errorf("Proto = %q Major=%v,Minor=%v; want HTTP/2.0", r.Proto, r.ProtoMajor, r.ProtoMinor) - } - wantHeader := http.Header{ - "Foo-Bar": []string{"some-value"}, - } - if !reflect.DeepEqual(r.Header, wantHeader) { - t.Errorf("Header = %#v; want %#v", r.Header, wantHeader) - } - if n, err := r.Body.Read([]byte(" ")); err != io.EOF || n != 0 { - t.Errorf("Read = %d, %v; want 0, EOF", n, err) - } - }) -} - -func TestServer_Request_Get_PathSlashes(t *testing.T) { - testServerRequest(t, func(st *serverTester) { - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, // clients send odd numbers - BlockFragment: st.encodeHeader(":path", "/%2f/"), - EndStream: true, // no DATA frames - EndHeaders: true, - }) - }, func(r *http.Request) { - if r.RequestURI != "/%2f/" { - t.Errorf("RequestURI = %q; want /%%2f/", r.RequestURI) - } - if r.URL.Path != "///" { - t.Errorf("URL.Path = %q; want ///", r.URL.Path) - } - }) -} - -// TODO: add a test with EndStream=true on the HEADERS but setting a -// Content-Length anyway. Should we just omit it and force it to -// zero? - -func TestServer_Request_Post_NoContentLength_EndStream(t *testing.T) { - testServerRequest(t, func(st *serverTester) { - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, // clients send odd numbers - BlockFragment: st.encodeHeader(":method", "POST"), - EndStream: true, - EndHeaders: true, - }) - }, func(r *http.Request) { - if r.Method != "POST" { - t.Errorf("Method = %q; want POST", r.Method) - } - if r.ContentLength != 0 { - t.Errorf("ContentLength = %v; want 0", r.ContentLength) - } - if n, err := r.Body.Read([]byte(" ")); err != io.EOF || n != 0 { - t.Errorf("Read = %d, %v; want 0, EOF", n, err) - } - }) -} - -func TestServer_Request_Post_Body_ImmediateEOF(t *testing.T) { - testBodyContents(t, -1, "", func(st *serverTester) { - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, // clients send odd numbers - BlockFragment: st.encodeHeader(":method", "POST"), - EndStream: false, // to say DATA frames are coming - EndHeaders: true, - }) - st.writeData(1, true, nil) // just kidding. empty body. - }) -} - -func TestServer_Request_Post_Body_OneData(t *testing.T) { - const content = "Some content" - testBodyContents(t, -1, content, func(st *serverTester) { - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, // clients send odd numbers - BlockFragment: st.encodeHeader(":method", "POST"), - EndStream: false, // to say DATA frames are coming - EndHeaders: true, - }) - st.writeData(1, true, []byte(content)) - }) -} - -func TestServer_Request_Post_Body_TwoData(t *testing.T) { - const content = "Some content" - testBodyContents(t, -1, content, func(st *serverTester) { - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, // clients send odd numbers - BlockFragment: st.encodeHeader(":method", "POST"), - EndStream: false, // to say DATA frames are coming - EndHeaders: true, - }) - st.writeData(1, false, []byte(content[:5])) - st.writeData(1, true, []byte(content[5:])) - }) -} - -func TestServer_Request_Post_Body_ContentLength_Correct(t *testing.T) { - const content = "Some content" - testBodyContents(t, int64(len(content)), content, func(st *serverTester) { - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, // clients send odd numbers - BlockFragment: st.encodeHeader( - ":method", "POST", - "content-length", strconv.Itoa(len(content)), - ), - EndStream: false, // to say DATA frames are coming - EndHeaders: true, - }) - st.writeData(1, true, []byte(content)) - }) -} - -func TestServer_Request_Post_Body_ContentLength_TooLarge(t *testing.T) { - testBodyContentsFail(t, 3, "request declared a Content-Length of 3 but only wrote 2 bytes", - func(st *serverTester) { - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, // clients send odd numbers - BlockFragment: st.encodeHeader( - ":method", "POST", - "content-length", "3", - ), - EndStream: false, // to say DATA frames are coming - EndHeaders: true, - }) - st.writeData(1, true, []byte("12")) - }) -} - -func TestServer_Request_Post_Body_ContentLength_TooSmall(t *testing.T) { - testBodyContentsFail(t, 4, "sender tried to send more than declared Content-Length of 4 bytes", - func(st *serverTester) { - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, // clients send odd numbers - BlockFragment: st.encodeHeader( - ":method", "POST", - "content-length", "4", - ), - EndStream: false, // to say DATA frames are coming - EndHeaders: true, - }) - st.writeData(1, true, []byte("12345")) - }) -} - -func testBodyContents(t *testing.T, wantContentLength int64, wantBody string, write func(st *serverTester)) { - testServerRequest(t, write, func(r *http.Request) { - if r.Method != "POST" { - t.Errorf("Method = %q; want POST", r.Method) - } - if r.ContentLength != wantContentLength { - t.Errorf("ContentLength = %v; want %d", r.ContentLength, wantContentLength) - } - all, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatal(err) - } - if string(all) != wantBody { - t.Errorf("Read = %q; want %q", all, wantBody) - } - if err := r.Body.Close(); err != nil { - t.Fatalf("Close: %v", err) - } - }) -} - -func testBodyContentsFail(t *testing.T, wantContentLength int64, wantReadError string, write func(st *serverTester)) { - testServerRequest(t, write, func(r *http.Request) { - if r.Method != "POST" { - t.Errorf("Method = %q; want POST", r.Method) - } - if r.ContentLength != wantContentLength { - t.Errorf("ContentLength = %v; want %d", r.ContentLength, wantContentLength) - } - all, err := ioutil.ReadAll(r.Body) - if err == nil { - t.Fatalf("expected an error (%q) reading from the body. Successfully read %q instead.", - wantReadError, all) - } - if !strings.Contains(err.Error(), wantReadError) { - t.Fatalf("Body.Read = %v; want substring %q", err, wantReadError) - } - if err := r.Body.Close(); err != nil { - t.Fatalf("Close: %v", err) - } - }) -} - -// Using a Host header, instead of :authority -func TestServer_Request_Get_Host(t *testing.T) { - const host = "example.com" - testServerRequest(t, func(st *serverTester) { - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, // clients send odd numbers - BlockFragment: st.encodeHeader(":authority", "", "host", host), - EndStream: true, - EndHeaders: true, - }) - }, func(r *http.Request) { - if r.Host != host { - t.Errorf("Host = %q; want %q", r.Host, host) - } - }) -} - -// Using an :authority pseudo-header, instead of Host -func TestServer_Request_Get_Authority(t *testing.T) { - const host = "example.com" - testServerRequest(t, func(st *serverTester) { - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, // clients send odd numbers - BlockFragment: st.encodeHeader(":authority", host), - EndStream: true, - EndHeaders: true, - }) - }, func(r *http.Request) { - if r.Host != host { - t.Errorf("Host = %q; want %q", r.Host, host) - } - }) -} - -func TestServer_Request_WithContinuation(t *testing.T) { - wantHeader := http.Header{ - "Foo-One": []string{"value-one"}, - "Foo-Two": []string{"value-two"}, - "Foo-Three": []string{"value-three"}, - } - testServerRequest(t, func(st *serverTester) { - fullHeaders := st.encodeHeader( - "foo-one", "value-one", - "foo-two", "value-two", - "foo-three", "value-three", - ) - remain := fullHeaders - chunks := 0 - for len(remain) > 0 { - const maxChunkSize = 5 - chunk := remain - if len(chunk) > maxChunkSize { - chunk = chunk[:maxChunkSize] - } - remain = remain[len(chunk):] - - if chunks == 0 { - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, // clients send odd numbers - BlockFragment: chunk, - EndStream: true, // no DATA frames - EndHeaders: false, // we'll have continuation frames - }) - } else { - err := st.fr.WriteContinuation(1, len(remain) == 0, chunk) - if err != nil { - t.Fatal(err) - } - } - chunks++ - } - if chunks < 2 { - t.Fatal("too few chunks") - } - }, func(r *http.Request) { - if !reflect.DeepEqual(r.Header, wantHeader) { - t.Errorf("Header = %#v; want %#v", r.Header, wantHeader) - } - }) -} - -// Concatenated cookie headers. ("8.1.2.5 Compressing the Cookie Header Field") -func TestServer_Request_CookieConcat(t *testing.T) { - const host = "example.com" - testServerRequest(t, func(st *serverTester) { - st.bodylessReq1( - ":authority", host, - "cookie", "a=b", - "cookie", "c=d", - "cookie", "e=f", - ) - }, func(r *http.Request) { - const want = "a=b; c=d; e=f" - if got := r.Header.Get("Cookie"); got != want { - t.Errorf("Cookie = %q; want %q", got, want) - } - }) -} - -func TestServer_Request_Reject_CapitalHeader(t *testing.T) { - testRejectRequest(t, func(st *serverTester) { st.bodylessReq1("UPPER", "v") }) -} - -func TestServer_Request_Reject_HeaderFieldNameColon(t *testing.T) { - testRejectRequest(t, func(st *serverTester) { st.bodylessReq1("has:colon", "v") }) -} - -func TestServer_Request_Reject_HeaderFieldNameNULL(t *testing.T) { - testRejectRequest(t, func(st *serverTester) { st.bodylessReq1("has\x00null", "v") }) -} - -func TestServer_Request_Reject_HeaderFieldNameEmpty(t *testing.T) { - testRejectRequest(t, func(st *serverTester) { st.bodylessReq1("", "v") }) -} - -func TestServer_Request_Reject_HeaderFieldValueNewline(t *testing.T) { - testRejectRequest(t, func(st *serverTester) { st.bodylessReq1("foo", "has\nnewline") }) -} - -func TestServer_Request_Reject_HeaderFieldValueCR(t *testing.T) { - testRejectRequest(t, func(st *serverTester) { st.bodylessReq1("foo", "has\rcarriage") }) -} - -func TestServer_Request_Reject_HeaderFieldValueDEL(t *testing.T) { - testRejectRequest(t, func(st *serverTester) { st.bodylessReq1("foo", "has\x7fdel") }) -} - -func TestServer_Request_Reject_Pseudo_Missing_method(t *testing.T) { - testRejectRequest(t, func(st *serverTester) { st.bodylessReq1(":method", "") }) -} - -func TestServer_Request_Reject_Pseudo_ExactlyOne(t *testing.T) { - // 8.1.2.3 Request Pseudo-Header Fields - // "All HTTP/2 requests MUST include exactly one valid value" ... - testRejectRequest(t, func(st *serverTester) { - st.addLogFilter("duplicate pseudo-header") - st.bodylessReq1(":method", "GET", ":method", "POST") - }) -} - -func TestServer_Request_Reject_Pseudo_AfterRegular(t *testing.T) { - // 8.1.2.3 Request Pseudo-Header Fields - // "All pseudo-header fields MUST appear in the header block - // before regular header fields. Any request or response that - // contains a pseudo-header field that appears in a header - // block after a regular header field MUST be treated as - // malformed (Section 8.1.2.6)." - testRejectRequest(t, func(st *serverTester) { - st.addLogFilter("pseudo-header after regular header") - var buf bytes.Buffer - enc := hpack.NewEncoder(&buf) - enc.WriteField(hpack.HeaderField{Name: ":method", Value: "GET"}) - enc.WriteField(hpack.HeaderField{Name: "regular", Value: "foobar"}) - enc.WriteField(hpack.HeaderField{Name: ":path", Value: "/"}) - enc.WriteField(hpack.HeaderField{Name: ":scheme", Value: "https"}) - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, // clients send odd numbers - BlockFragment: buf.Bytes(), - EndStream: true, - EndHeaders: true, - }) - }) -} - -func TestServer_Request_Reject_Pseudo_Missing_path(t *testing.T) { - testRejectRequest(t, func(st *serverTester) { st.bodylessReq1(":path", "") }) -} - -func TestServer_Request_Reject_Pseudo_Missing_scheme(t *testing.T) { - testRejectRequest(t, func(st *serverTester) { st.bodylessReq1(":scheme", "") }) -} - -func TestServer_Request_Reject_Pseudo_scheme_invalid(t *testing.T) { - testRejectRequest(t, func(st *serverTester) { st.bodylessReq1(":scheme", "bogus") }) -} - -func TestServer_Request_Reject_Pseudo_Unknown(t *testing.T) { - testRejectRequest(t, func(st *serverTester) { - st.addLogFilter(`invalid pseudo-header ":unknown_thing"`) - st.bodylessReq1(":unknown_thing", "") - }) -} - -func testRejectRequest(t *testing.T, send func(*serverTester)) { - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - t.Error("server request made it to handler; should've been rejected") - }) - defer st.Close() - - st.greet() - send(st) - st.wantRSTStream(1, ErrCodeProtocol) -} - -func testRejectRequestWithProtocolError(t *testing.T, send func(*serverTester)) { - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - t.Error("server request made it to handler; should've been rejected") - }, optQuiet) - defer st.Close() - - st.greet() - send(st) - gf := st.wantGoAway() - if gf.ErrCode != ErrCodeProtocol { - t.Errorf("err code = %v; want %v", gf.ErrCode, ErrCodeProtocol) - } -} - -// Section 5.1, on idle connections: "Receiving any frame other than -// HEADERS or PRIORITY on a stream in this state MUST be treated as a -// connection error (Section 5.4.1) of type PROTOCOL_ERROR." -func TestRejectFrameOnIdle_WindowUpdate(t *testing.T) { - testRejectRequestWithProtocolError(t, func(st *serverTester) { - st.fr.WriteWindowUpdate(123, 456) - }) -} -func TestRejectFrameOnIdle_Data(t *testing.T) { - testRejectRequestWithProtocolError(t, func(st *serverTester) { - st.fr.WriteData(123, true, nil) - }) -} -func TestRejectFrameOnIdle_RSTStream(t *testing.T) { - testRejectRequestWithProtocolError(t, func(st *serverTester) { - st.fr.WriteRSTStream(123, ErrCodeCancel) - }) -} - -func TestServer_Request_Connect(t *testing.T) { - testServerRequest(t, func(st *serverTester) { - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, - BlockFragment: st.encodeHeaderRaw( - ":method", "CONNECT", - ":authority", "example.com:123", - ), - EndStream: true, - EndHeaders: true, - }) - }, func(r *http.Request) { - if g, w := r.Method, "CONNECT"; g != w { - t.Errorf("Method = %q; want %q", g, w) - } - if g, w := r.RequestURI, "example.com:123"; g != w { - t.Errorf("RequestURI = %q; want %q", g, w) - } - if g, w := r.URL.Host, "example.com:123"; g != w { - t.Errorf("URL.Host = %q; want %q", g, w) - } - }) -} - -func TestServer_Request_Connect_InvalidPath(t *testing.T) { - testServerRejectsStream(t, ErrCodeProtocol, func(st *serverTester) { - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, - BlockFragment: st.encodeHeaderRaw( - ":method", "CONNECT", - ":authority", "example.com:123", - ":path", "/bogus", - ), - EndStream: true, - EndHeaders: true, - }) - }) -} - -func TestServer_Request_Connect_InvalidScheme(t *testing.T) { - testServerRejectsStream(t, ErrCodeProtocol, func(st *serverTester) { - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, - BlockFragment: st.encodeHeaderRaw( - ":method", "CONNECT", - ":authority", "example.com:123", - ":scheme", "https", - ), - EndStream: true, - EndHeaders: true, - }) - }) -} - -func TestServer_Ping(t *testing.T) { - st := newServerTester(t, nil) - defer st.Close() - st.greet() - - // Server should ignore this one, since it has ACK set. - ackPingData := [8]byte{1, 2, 4, 8, 16, 32, 64, 128} - if err := st.fr.WritePing(true, ackPingData); err != nil { - t.Fatal(err) - } - - // But the server should reply to this one, since ACK is false. - pingData := [8]byte{1, 2, 3, 4, 5, 6, 7, 8} - if err := st.fr.WritePing(false, pingData); err != nil { - t.Fatal(err) - } - - pf := st.wantPing() - if !pf.Flags.Has(FlagPingAck) { - t.Error("response ping doesn't have ACK set") - } - if pf.Data != pingData { - t.Errorf("response ping has data %q; want %q", pf.Data, pingData) - } -} - -func TestServer_RejectsLargeFrames(t *testing.T) { - if runtime.GOOS == "windows" { - t.Skip("see golang.org/issue/13434") - } - - st := newServerTester(t, nil) - defer st.Close() - st.greet() - - // Write too large of a frame (too large by one byte) - // We ignore the return value because it's expected that the server - // will only read the first 9 bytes (the headre) and then disconnect. - st.fr.WriteRawFrame(0xff, 0, 0, make([]byte, defaultMaxReadFrameSize+1)) - - gf := st.wantGoAway() - if gf.ErrCode != ErrCodeFrameSize { - t.Errorf("GOAWAY err = %v; want %v", gf.ErrCode, ErrCodeFrameSize) - } - if st.serverLogBuf.Len() != 0 { - // Previously we spun here for a bit until the GOAWAY disconnect - // timer fired, logging while we fired. - t.Errorf("unexpected server output: %.500s\n", st.serverLogBuf.Bytes()) - } -} - -func TestServer_Handler_Sends_WindowUpdate(t *testing.T) { - puppet := newHandlerPuppet() - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - puppet.act(w, r) - }) - defer st.Close() - defer puppet.done() - - st.greet() - - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, // clients send odd numbers - BlockFragment: st.encodeHeader(":method", "POST"), - EndStream: false, // data coming - EndHeaders: true, - }) - st.writeData(1, false, []byte("abcdef")) - puppet.do(readBodyHandler(t, "abc")) - st.wantWindowUpdate(0, 3) - st.wantWindowUpdate(1, 3) - - puppet.do(readBodyHandler(t, "def")) - st.wantWindowUpdate(0, 3) - st.wantWindowUpdate(1, 3) - - st.writeData(1, true, []byte("ghijkl")) // END_STREAM here - puppet.do(readBodyHandler(t, "ghi")) - puppet.do(readBodyHandler(t, "jkl")) - st.wantWindowUpdate(0, 3) - st.wantWindowUpdate(0, 3) // no more stream-level, since END_STREAM -} - -// the version of the TestServer_Handler_Sends_WindowUpdate with padding. -// See golang.org/issue/16556 -func TestServer_Handler_Sends_WindowUpdate_Padding(t *testing.T) { - puppet := newHandlerPuppet() - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - puppet.act(w, r) - }) - defer st.Close() - defer puppet.done() - - st.greet() - - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, - BlockFragment: st.encodeHeader(":method", "POST"), - EndStream: false, - EndHeaders: true, - }) - st.writeDataPadded(1, false, []byte("abcdef"), []byte{0, 0, 0, 0}) - - // Expect to immediately get our 5 bytes of padding back for - // both the connection and stream (4 bytes of padding + 1 byte of length) - st.wantWindowUpdate(0, 5) - st.wantWindowUpdate(1, 5) - - puppet.do(readBodyHandler(t, "abc")) - st.wantWindowUpdate(0, 3) - st.wantWindowUpdate(1, 3) - - puppet.do(readBodyHandler(t, "def")) - st.wantWindowUpdate(0, 3) - st.wantWindowUpdate(1, 3) -} - -func TestServer_Send_GoAway_After_Bogus_WindowUpdate(t *testing.T) { - st := newServerTester(t, nil) - defer st.Close() - st.greet() - if err := st.fr.WriteWindowUpdate(0, 1<<31-1); err != nil { - t.Fatal(err) - } - gf := st.wantGoAway() - if gf.ErrCode != ErrCodeFlowControl { - t.Errorf("GOAWAY err = %v; want %v", gf.ErrCode, ErrCodeFlowControl) - } - if gf.LastStreamID != 0 { - t.Errorf("GOAWAY last stream ID = %v; want %v", gf.LastStreamID, 0) - } -} - -func TestServer_Send_RstStream_After_Bogus_WindowUpdate(t *testing.T) { - inHandler := make(chan bool) - blockHandler := make(chan bool) - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - inHandler <- true - <-blockHandler - }) - defer st.Close() - defer close(blockHandler) - st.greet() - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, - BlockFragment: st.encodeHeader(":method", "POST"), - EndStream: false, // keep it open - EndHeaders: true, - }) - <-inHandler - // Send a bogus window update: - if err := st.fr.WriteWindowUpdate(1, 1<<31-1); err != nil { - t.Fatal(err) - } - st.wantRSTStream(1, ErrCodeFlowControl) -} - -// testServerPostUnblock sends a hanging POST with unsent data to handler, -// then runs fn once in the handler, and verifies that the error returned from -// handler is acceptable. It fails if takes over 5 seconds for handler to exit. -func testServerPostUnblock(t *testing.T, - handler func(http.ResponseWriter, *http.Request) error, - fn func(*serverTester), - checkErr func(error), - otherHeaders ...string) { - inHandler := make(chan bool) - errc := make(chan error, 1) - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - inHandler <- true - errc <- handler(w, r) - }) - defer st.Close() - st.greet() - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, - BlockFragment: st.encodeHeader(append([]string{":method", "POST"}, otherHeaders...)...), - EndStream: false, // keep it open - EndHeaders: true, - }) - <-inHandler - fn(st) - select { - case err := <-errc: - if checkErr != nil { - checkErr(err) - } - case <-time.After(5 * time.Second): - t.Fatal("timeout waiting for Handler to return") - } -} - -func TestServer_RSTStream_Unblocks_Read(t *testing.T) { - testServerPostUnblock(t, - func(w http.ResponseWriter, r *http.Request) (err error) { - _, err = r.Body.Read(make([]byte, 1)) - return - }, - func(st *serverTester) { - if err := st.fr.WriteRSTStream(1, ErrCodeCancel); err != nil { - t.Fatal(err) - } - }, - func(err error) { - want := StreamError{StreamID: 0x1, Code: 0x8} - if !reflect.DeepEqual(err, want) { - t.Errorf("Read error = %v; want %v", err, want) - } - }, - ) -} - -func TestServer_RSTStream_Unblocks_Header_Write(t *testing.T) { - // Run this test a bunch, because it doesn't always - // deadlock. But with a bunch, it did. - n := 50 - if testing.Short() { - n = 5 - } - for i := 0; i < n; i++ { - testServer_RSTStream_Unblocks_Header_Write(t) - } -} - -func testServer_RSTStream_Unblocks_Header_Write(t *testing.T) { - inHandler := make(chan bool, 1) - unblockHandler := make(chan bool, 1) - headerWritten := make(chan bool, 1) - wroteRST := make(chan bool, 1) - - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - inHandler <- true - <-wroteRST - w.Header().Set("foo", "bar") - w.WriteHeader(200) - w.(http.Flusher).Flush() - headerWritten <- true - <-unblockHandler - }) - defer st.Close() - - st.greet() - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, - BlockFragment: st.encodeHeader(":method", "POST"), - EndStream: false, // keep it open - EndHeaders: true, - }) - <-inHandler - if err := st.fr.WriteRSTStream(1, ErrCodeCancel); err != nil { - t.Fatal(err) - } - wroteRST <- true - st.awaitIdle() - select { - case <-headerWritten: - case <-time.After(2 * time.Second): - t.Error("timeout waiting for header write") - } - unblockHandler <- true -} - -func TestServer_DeadConn_Unblocks_Read(t *testing.T) { - testServerPostUnblock(t, - func(w http.ResponseWriter, r *http.Request) (err error) { - _, err = r.Body.Read(make([]byte, 1)) - return - }, - func(st *serverTester) { st.cc.Close() }, - func(err error) { - if err == nil { - t.Error("unexpected nil error from Request.Body.Read") - } - }, - ) -} - -var blockUntilClosed = func(w http.ResponseWriter, r *http.Request) error { - <-w.(http.CloseNotifier).CloseNotify() - return nil -} - -func TestServer_CloseNotify_After_RSTStream(t *testing.T) { - testServerPostUnblock(t, blockUntilClosed, func(st *serverTester) { - if err := st.fr.WriteRSTStream(1, ErrCodeCancel); err != nil { - t.Fatal(err) - } - }, nil) -} - -func TestServer_CloseNotify_After_ConnClose(t *testing.T) { - testServerPostUnblock(t, blockUntilClosed, func(st *serverTester) { st.cc.Close() }, nil) -} - -// that CloseNotify unblocks after a stream error due to the client's -// problem that's unrelated to them explicitly canceling it (which is -// TestServer_CloseNotify_After_RSTStream above) -func TestServer_CloseNotify_After_StreamError(t *testing.T) { - testServerPostUnblock(t, blockUntilClosed, func(st *serverTester) { - // data longer than declared Content-Length => stream error - st.writeData(1, true, []byte("1234")) - }, nil, "content-length", "3") -} - -func TestServer_StateTransitions(t *testing.T) { - var st *serverTester - inHandler := make(chan bool) - writeData := make(chan bool) - leaveHandler := make(chan bool) - st = newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - inHandler <- true - if st.stream(1) == nil { - t.Errorf("nil stream 1 in handler") - } - if got, want := st.streamState(1), stateOpen; got != want { - t.Errorf("in handler, state is %v; want %v", got, want) - } - writeData <- true - if n, err := r.Body.Read(make([]byte, 1)); n != 0 || err != io.EOF { - t.Errorf("body read = %d, %v; want 0, EOF", n, err) - } - if got, want := st.streamState(1), stateHalfClosedRemote; got != want { - t.Errorf("in handler, state is %v; want %v", got, want) - } - - <-leaveHandler - }) - st.greet() - if st.stream(1) != nil { - t.Fatal("stream 1 should be empty") - } - if got := st.streamState(1); got != stateIdle { - t.Fatalf("stream 1 should be idle; got %v", got) - } - - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, - BlockFragment: st.encodeHeader(":method", "POST"), - EndStream: false, // keep it open - EndHeaders: true, - }) - <-inHandler - <-writeData - st.writeData(1, true, nil) - - leaveHandler <- true - hf := st.wantHeaders() - if !hf.StreamEnded() { - t.Fatal("expected END_STREAM flag") - } - - if got, want := st.streamState(1), stateClosed; got != want { - t.Errorf("at end, state is %v; want %v", got, want) - } - if st.stream(1) != nil { - t.Fatal("at end, stream 1 should be gone") - } -} - -// test HEADERS w/o EndHeaders + another HEADERS (should get rejected) -func TestServer_Rejects_HeadersNoEnd_Then_Headers(t *testing.T) { - testServerRejectsConn(t, func(st *serverTester) { - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, - BlockFragment: st.encodeHeader(), - EndStream: true, - EndHeaders: false, - }) - st.writeHeaders(HeadersFrameParam{ // Not a continuation. - StreamID: 3, // different stream. - BlockFragment: st.encodeHeader(), - EndStream: true, - EndHeaders: true, - }) - }) -} - -// test HEADERS w/o EndHeaders + PING (should get rejected) -func TestServer_Rejects_HeadersNoEnd_Then_Ping(t *testing.T) { - testServerRejectsConn(t, func(st *serverTester) { - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, - BlockFragment: st.encodeHeader(), - EndStream: true, - EndHeaders: false, - }) - if err := st.fr.WritePing(false, [8]byte{}); err != nil { - t.Fatal(err) - } - }) -} - -// test HEADERS w/ EndHeaders + a continuation HEADERS (should get rejected) -func TestServer_Rejects_HeadersEnd_Then_Continuation(t *testing.T) { - testServerRejectsConn(t, func(st *serverTester) { - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, - BlockFragment: st.encodeHeader(), - EndStream: true, - EndHeaders: true, - }) - st.wantHeaders() - if err := st.fr.WriteContinuation(1, true, encodeHeaderNoImplicit(t, "foo", "bar")); err != nil { - t.Fatal(err) - } - }) -} - -// test HEADERS w/o EndHeaders + a continuation HEADERS on wrong stream ID -func TestServer_Rejects_HeadersNoEnd_Then_ContinuationWrongStream(t *testing.T) { - testServerRejectsConn(t, func(st *serverTester) { - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, - BlockFragment: st.encodeHeader(), - EndStream: true, - EndHeaders: false, - }) - if err := st.fr.WriteContinuation(3, true, encodeHeaderNoImplicit(t, "foo", "bar")); err != nil { - t.Fatal(err) - } - }) -} - -// No HEADERS on stream 0. -func TestServer_Rejects_Headers0(t *testing.T) { - testServerRejectsConn(t, func(st *serverTester) { - st.fr.AllowIllegalWrites = true - st.writeHeaders(HeadersFrameParam{ - StreamID: 0, - BlockFragment: st.encodeHeader(), - EndStream: true, - EndHeaders: true, - }) - }) -} - -// No CONTINUATION on stream 0. -func TestServer_Rejects_Continuation0(t *testing.T) { - testServerRejectsConn(t, func(st *serverTester) { - st.fr.AllowIllegalWrites = true - if err := st.fr.WriteContinuation(0, true, st.encodeHeader()); err != nil { - t.Fatal(err) - } - }) -} - -// No PRIORITY on stream 0. -func TestServer_Rejects_Priority0(t *testing.T) { - testServerRejectsConn(t, func(st *serverTester) { - st.fr.AllowIllegalWrites = true - st.writePriority(0, PriorityParam{StreamDep: 1}) - }) -} - -// No HEADERS frame with a self-dependence. -func TestServer_Rejects_HeadersSelfDependence(t *testing.T) { - testServerRejectsStream(t, ErrCodeProtocol, func(st *serverTester) { - st.fr.AllowIllegalWrites = true - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, - BlockFragment: st.encodeHeader(), - EndStream: true, - EndHeaders: true, - Priority: PriorityParam{StreamDep: 1}, - }) - }) -} - -// No PRIORTY frame with a self-dependence. -func TestServer_Rejects_PrioritySelfDependence(t *testing.T) { - testServerRejectsStream(t, ErrCodeProtocol, func(st *serverTester) { - st.fr.AllowIllegalWrites = true - st.writePriority(1, PriorityParam{StreamDep: 1}) - }) -} - -func TestServer_Rejects_PushPromise(t *testing.T) { - testServerRejectsConn(t, func(st *serverTester) { - pp := PushPromiseParam{ - StreamID: 1, - PromiseID: 3, - } - if err := st.fr.WritePushPromise(pp); err != nil { - t.Fatal(err) - } - }) -} - -// testServerRejectsConn tests that the server hangs up with a GOAWAY -// frame and a server close after the client does something -// deserving a CONNECTION_ERROR. -func testServerRejectsConn(t *testing.T, writeReq func(*serverTester)) { - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {}) - st.addLogFilter("connection error: PROTOCOL_ERROR") - defer st.Close() - st.greet() - writeReq(st) - - st.wantGoAway() - errc := make(chan error, 1) - go func() { - fr, err := st.fr.ReadFrame() - if err == nil { - err = fmt.Errorf("got frame of type %T", fr) - } - errc <- err - }() - select { - case err := <-errc: - if err != io.EOF { - t.Errorf("ReadFrame = %v; want io.EOF", err) - } - case <-time.After(2 * time.Second): - t.Error("timeout waiting for disconnect") - } -} - -// testServerRejectsStream tests that the server sends a RST_STREAM with the provided -// error code after a client sends a bogus request. -func testServerRejectsStream(t *testing.T, code ErrCode, writeReq func(*serverTester)) { - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {}) - defer st.Close() - st.greet() - writeReq(st) - st.wantRSTStream(1, code) -} - -// testServerRequest sets up an idle HTTP/2 connection and lets you -// write a single request with writeReq, and then verify that the -// *http.Request is built correctly in checkReq. -func testServerRequest(t *testing.T, writeReq func(*serverTester), checkReq func(*http.Request)) { - gotReq := make(chan bool, 1) - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - if r.Body == nil { - t.Fatal("nil Body") - } - checkReq(r) - gotReq <- true - }) - defer st.Close() - - st.greet() - writeReq(st) - - select { - case <-gotReq: - case <-time.After(2 * time.Second): - t.Error("timeout waiting for request") - } -} - -func getSlash(st *serverTester) { st.bodylessReq1() } - -func TestServer_Response_NoData(t *testing.T) { - testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error { - // Nothing. - return nil - }, func(st *serverTester) { - getSlash(st) - hf := st.wantHeaders() - if !hf.StreamEnded() { - t.Fatal("want END_STREAM flag") - } - if !hf.HeadersEnded() { - t.Fatal("want END_HEADERS flag") - } - }) -} - -func TestServer_Response_NoData_Header_FooBar(t *testing.T) { - testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error { - w.Header().Set("Foo-Bar", "some-value") - return nil - }, func(st *serverTester) { - getSlash(st) - hf := st.wantHeaders() - if !hf.StreamEnded() { - t.Fatal("want END_STREAM flag") - } - if !hf.HeadersEnded() { - t.Fatal("want END_HEADERS flag") - } - goth := st.decodeHeader(hf.HeaderBlockFragment()) - wanth := [][2]string{ - {":status", "200"}, - {"foo-bar", "some-value"}, - {"content-length", "0"}, - } - if !reflect.DeepEqual(goth, wanth) { - t.Errorf("Got headers %v; want %v", goth, wanth) - } - }) -} - -func TestServer_Response_Data_Sniff_DoesntOverride(t *testing.T) { - const msg = "this is HTML." - testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error { - w.Header().Set("Content-Type", "foo/bar") - io.WriteString(w, msg) - return nil - }, func(st *serverTester) { - getSlash(st) - hf := st.wantHeaders() - if hf.StreamEnded() { - t.Fatal("don't want END_STREAM, expecting data") - } - if !hf.HeadersEnded() { - t.Fatal("want END_HEADERS flag") - } - goth := st.decodeHeader(hf.HeaderBlockFragment()) - wanth := [][2]string{ - {":status", "200"}, - {"content-type", "foo/bar"}, - {"content-length", strconv.Itoa(len(msg))}, - } - if !reflect.DeepEqual(goth, wanth) { - t.Errorf("Got headers %v; want %v", goth, wanth) - } - df := st.wantData() - if !df.StreamEnded() { - t.Error("expected DATA to have END_STREAM flag") - } - if got := string(df.Data()); got != msg { - t.Errorf("got DATA %q; want %q", got, msg) - } - }) -} - -func TestServer_Response_TransferEncoding_chunked(t *testing.T) { - const msg = "hi" - testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error { - w.Header().Set("Transfer-Encoding", "chunked") // should be stripped - io.WriteString(w, msg) - return nil - }, func(st *serverTester) { - getSlash(st) - hf := st.wantHeaders() - goth := st.decodeHeader(hf.HeaderBlockFragment()) - wanth := [][2]string{ - {":status", "200"}, - {"content-type", "text/plain; charset=utf-8"}, - {"content-length", strconv.Itoa(len(msg))}, - } - if !reflect.DeepEqual(goth, wanth) { - t.Errorf("Got headers %v; want %v", goth, wanth) - } - }) -} - -// Header accessed only after the initial write. -func TestServer_Response_Data_IgnoreHeaderAfterWrite_After(t *testing.T) { - const msg = "this is HTML." - testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error { - io.WriteString(w, msg) - w.Header().Set("foo", "should be ignored") - return nil - }, func(st *serverTester) { - getSlash(st) - hf := st.wantHeaders() - if hf.StreamEnded() { - t.Fatal("unexpected END_STREAM") - } - if !hf.HeadersEnded() { - t.Fatal("want END_HEADERS flag") - } - goth := st.decodeHeader(hf.HeaderBlockFragment()) - wanth := [][2]string{ - {":status", "200"}, - {"content-type", "text/html; charset=utf-8"}, - {"content-length", strconv.Itoa(len(msg))}, - } - if !reflect.DeepEqual(goth, wanth) { - t.Errorf("Got headers %v; want %v", goth, wanth) - } - }) -} - -// Header accessed before the initial write and later mutated. -func TestServer_Response_Data_IgnoreHeaderAfterWrite_Overwrite(t *testing.T) { - const msg = "this is HTML." - testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error { - w.Header().Set("foo", "proper value") - io.WriteString(w, msg) - w.Header().Set("foo", "should be ignored") - return nil - }, func(st *serverTester) { - getSlash(st) - hf := st.wantHeaders() - if hf.StreamEnded() { - t.Fatal("unexpected END_STREAM") - } - if !hf.HeadersEnded() { - t.Fatal("want END_HEADERS flag") - } - goth := st.decodeHeader(hf.HeaderBlockFragment()) - wanth := [][2]string{ - {":status", "200"}, - {"foo", "proper value"}, - {"content-type", "text/html; charset=utf-8"}, - {"content-length", strconv.Itoa(len(msg))}, - } - if !reflect.DeepEqual(goth, wanth) { - t.Errorf("Got headers %v; want %v", goth, wanth) - } - }) -} - -func TestServer_Response_Data_SniffLenType(t *testing.T) { - const msg = "this is HTML." - testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error { - io.WriteString(w, msg) - return nil - }, func(st *serverTester) { - getSlash(st) - hf := st.wantHeaders() - if hf.StreamEnded() { - t.Fatal("don't want END_STREAM, expecting data") - } - if !hf.HeadersEnded() { - t.Fatal("want END_HEADERS flag") - } - goth := st.decodeHeader(hf.HeaderBlockFragment()) - wanth := [][2]string{ - {":status", "200"}, - {"content-type", "text/html; charset=utf-8"}, - {"content-length", strconv.Itoa(len(msg))}, - } - if !reflect.DeepEqual(goth, wanth) { - t.Errorf("Got headers %v; want %v", goth, wanth) - } - df := st.wantData() - if !df.StreamEnded() { - t.Error("expected DATA to have END_STREAM flag") - } - if got := string(df.Data()); got != msg { - t.Errorf("got DATA %q; want %q", got, msg) - } - }) -} - -func TestServer_Response_Header_Flush_MidWrite(t *testing.T) { - const msg = "this is HTML" - const msg2 = ", and this is the next chunk" - testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error { - io.WriteString(w, msg) - w.(http.Flusher).Flush() - io.WriteString(w, msg2) - return nil - }, func(st *serverTester) { - getSlash(st) - hf := st.wantHeaders() - if hf.StreamEnded() { - t.Fatal("unexpected END_STREAM flag") - } - if !hf.HeadersEnded() { - t.Fatal("want END_HEADERS flag") - } - goth := st.decodeHeader(hf.HeaderBlockFragment()) - wanth := [][2]string{ - {":status", "200"}, - {"content-type", "text/html; charset=utf-8"}, // sniffed - // and no content-length - } - if !reflect.DeepEqual(goth, wanth) { - t.Errorf("Got headers %v; want %v", goth, wanth) - } - { - df := st.wantData() - if df.StreamEnded() { - t.Error("unexpected END_STREAM flag") - } - if got := string(df.Data()); got != msg { - t.Errorf("got DATA %q; want %q", got, msg) - } - } - { - df := st.wantData() - if !df.StreamEnded() { - t.Error("wanted END_STREAM flag on last data chunk") - } - if got := string(df.Data()); got != msg2 { - t.Errorf("got DATA %q; want %q", got, msg2) - } - } - }) -} - -func TestServer_Response_LargeWrite(t *testing.T) { - const size = 1 << 20 - const maxFrameSize = 16 << 10 - testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error { - n, err := w.Write(bytes.Repeat([]byte("a"), size)) - if err != nil { - return fmt.Errorf("Write error: %v", err) - } - if n != size { - return fmt.Errorf("wrong size %d from Write", n) - } - return nil - }, func(st *serverTester) { - if err := st.fr.WriteSettings( - Setting{SettingInitialWindowSize, 0}, - Setting{SettingMaxFrameSize, maxFrameSize}, - ); err != nil { - t.Fatal(err) - } - st.wantSettingsAck() - - getSlash(st) // make the single request - - // Give the handler quota to write: - if err := st.fr.WriteWindowUpdate(1, size); err != nil { - t.Fatal(err) - } - // Give the handler quota to write to connection-level - // window as well - if err := st.fr.WriteWindowUpdate(0, size); err != nil { - t.Fatal(err) - } - hf := st.wantHeaders() - if hf.StreamEnded() { - t.Fatal("unexpected END_STREAM flag") - } - if !hf.HeadersEnded() { - t.Fatal("want END_HEADERS flag") - } - goth := st.decodeHeader(hf.HeaderBlockFragment()) - wanth := [][2]string{ - {":status", "200"}, - {"content-type", "text/plain; charset=utf-8"}, // sniffed - // and no content-length - } - if !reflect.DeepEqual(goth, wanth) { - t.Errorf("Got headers %v; want %v", goth, wanth) - } - var bytes, frames int - for { - df := st.wantData() - bytes += len(df.Data()) - frames++ - for _, b := range df.Data() { - if b != 'a' { - t.Fatal("non-'a' byte seen in DATA") - } - } - if df.StreamEnded() { - break - } - } - if bytes != size { - t.Errorf("Got %d bytes; want %d", bytes, size) - } - if want := int(size / maxFrameSize); frames < want || frames > want*2 { - t.Errorf("Got %d frames; want %d", frames, size) - } - }) -} - -// Test that the handler can't write more than the client allows -func TestServer_Response_LargeWrite_FlowControlled(t *testing.T) { - // Make these reads. Before each read, the client adds exactly enough - // flow-control to satisfy the read. Numbers chosen arbitrarily. - reads := []int{123, 1, 13, 127} - size := 0 - for _, n := range reads { - size += n - } - - testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error { - w.(http.Flusher).Flush() - n, err := w.Write(bytes.Repeat([]byte("a"), size)) - if err != nil { - return fmt.Errorf("Write error: %v", err) - } - if n != size { - return fmt.Errorf("wrong size %d from Write", n) - } - return nil - }, func(st *serverTester) { - // Set the window size to something explicit for this test. - // It's also how much initial data we expect. - if err := st.fr.WriteSettings(Setting{SettingInitialWindowSize, uint32(reads[0])}); err != nil { - t.Fatal(err) - } - st.wantSettingsAck() - - getSlash(st) // make the single request - - hf := st.wantHeaders() - if hf.StreamEnded() { - t.Fatal("unexpected END_STREAM flag") - } - if !hf.HeadersEnded() { - t.Fatal("want END_HEADERS flag") - } - - df := st.wantData() - if got := len(df.Data()); got != reads[0] { - t.Fatalf("Initial window size = %d but got DATA with %d bytes", reads[0], got) - } - - for _, quota := range reads[1:] { - if err := st.fr.WriteWindowUpdate(1, uint32(quota)); err != nil { - t.Fatal(err) - } - df := st.wantData() - if int(quota) != len(df.Data()) { - t.Fatalf("read %d bytes after giving %d quota", len(df.Data()), quota) - } - } - }) -} - -// Test that the handler blocked in a Write is unblocked if the server sends a RST_STREAM. -func TestServer_Response_RST_Unblocks_LargeWrite(t *testing.T) { - const size = 1 << 20 - const maxFrameSize = 16 << 10 - testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error { - w.(http.Flusher).Flush() - errc := make(chan error, 1) - go func() { - _, err := w.Write(bytes.Repeat([]byte("a"), size)) - errc <- err - }() - select { - case err := <-errc: - if err == nil { - return errors.New("unexpected nil error from Write in handler") - } - return nil - case <-time.After(2 * time.Second): - return errors.New("timeout waiting for Write in handler") - } - }, func(st *serverTester) { - if err := st.fr.WriteSettings( - Setting{SettingInitialWindowSize, 0}, - Setting{SettingMaxFrameSize, maxFrameSize}, - ); err != nil { - t.Fatal(err) - } - st.wantSettingsAck() - - getSlash(st) // make the single request - - hf := st.wantHeaders() - if hf.StreamEnded() { - t.Fatal("unexpected END_STREAM flag") - } - if !hf.HeadersEnded() { - t.Fatal("want END_HEADERS flag") - } - - if err := st.fr.WriteRSTStream(1, ErrCodeCancel); err != nil { - t.Fatal(err) - } - }) -} - -func TestServer_Response_Empty_Data_Not_FlowControlled(t *testing.T) { - testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error { - w.(http.Flusher).Flush() - // Nothing; send empty DATA - return nil - }, func(st *serverTester) { - // Handler gets no data quota: - if err := st.fr.WriteSettings(Setting{SettingInitialWindowSize, 0}); err != nil { - t.Fatal(err) - } - st.wantSettingsAck() - - getSlash(st) // make the single request - - hf := st.wantHeaders() - if hf.StreamEnded() { - t.Fatal("unexpected END_STREAM flag") - } - if !hf.HeadersEnded() { - t.Fatal("want END_HEADERS flag") - } - - df := st.wantData() - if got := len(df.Data()); got != 0 { - t.Fatalf("unexpected %d DATA bytes; want 0", got) - } - if !df.StreamEnded() { - t.Fatal("DATA didn't have END_STREAM") - } - }) -} - -func TestServer_Response_Automatic100Continue(t *testing.T) { - const msg = "foo" - const reply = "bar" - testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error { - if v := r.Header.Get("Expect"); v != "" { - t.Errorf("Expect header = %q; want empty", v) - } - buf := make([]byte, len(msg)) - // This read should trigger the 100-continue being sent. - if n, err := io.ReadFull(r.Body, buf); err != nil || n != len(msg) || string(buf) != msg { - return fmt.Errorf("ReadFull = %q, %v; want %q, nil", buf[:n], err, msg) - } - _, err := io.WriteString(w, reply) - return err - }, func(st *serverTester) { - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, // clients send odd numbers - BlockFragment: st.encodeHeader(":method", "POST", "expect", "100-continue"), - EndStream: false, - EndHeaders: true, - }) - hf := st.wantHeaders() - if hf.StreamEnded() { - t.Fatal("unexpected END_STREAM flag") - } - if !hf.HeadersEnded() { - t.Fatal("want END_HEADERS flag") - } - goth := st.decodeHeader(hf.HeaderBlockFragment()) - wanth := [][2]string{ - {":status", "100"}, - } - if !reflect.DeepEqual(goth, wanth) { - t.Fatalf("Got headers %v; want %v", goth, wanth) - } - - // Okay, they sent status 100, so we can send our - // gigantic and/or sensitive "foo" payload now. - st.writeData(1, true, []byte(msg)) - - st.wantWindowUpdate(0, uint32(len(msg))) - - hf = st.wantHeaders() - if hf.StreamEnded() { - t.Fatal("expected data to follow") - } - if !hf.HeadersEnded() { - t.Fatal("want END_HEADERS flag") - } - goth = st.decodeHeader(hf.HeaderBlockFragment()) - wanth = [][2]string{ - {":status", "200"}, - {"content-type", "text/plain; charset=utf-8"}, - {"content-length", strconv.Itoa(len(reply))}, - } - if !reflect.DeepEqual(goth, wanth) { - t.Errorf("Got headers %v; want %v", goth, wanth) - } - - df := st.wantData() - if string(df.Data()) != reply { - t.Errorf("Client read %q; want %q", df.Data(), reply) - } - if !df.StreamEnded() { - t.Errorf("expect data stream end") - } - }) -} - -func TestServer_HandlerWriteErrorOnDisconnect(t *testing.T) { - errc := make(chan error, 1) - testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error { - p := []byte("some data.\n") - for { - _, err := w.Write(p) - if err != nil { - errc <- err - return nil - } - } - }, func(st *serverTester) { - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, - BlockFragment: st.encodeHeader(), - EndStream: false, - EndHeaders: true, - }) - hf := st.wantHeaders() - if hf.StreamEnded() { - t.Fatal("unexpected END_STREAM flag") - } - if !hf.HeadersEnded() { - t.Fatal("want END_HEADERS flag") - } - // Close the connection and wait for the handler to (hopefully) notice. - st.cc.Close() - select { - case <-errc: - case <-time.After(5 * time.Second): - t.Error("timeout") - } - }) -} - -func TestServer_Rejects_Too_Many_Streams(t *testing.T) { - const testPath = "/some/path" - - inHandler := make(chan uint32) - leaveHandler := make(chan bool) - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - id := w.(*responseWriter).rws.stream.id - inHandler <- id - if id == 1+(defaultMaxStreams+1)*2 && r.URL.Path != testPath { - t.Errorf("decoded final path as %q; want %q", r.URL.Path, testPath) - } - <-leaveHandler - }) - defer st.Close() - st.greet() - nextStreamID := uint32(1) - streamID := func() uint32 { - defer func() { nextStreamID += 2 }() - return nextStreamID - } - sendReq := func(id uint32, headers ...string) { - st.writeHeaders(HeadersFrameParam{ - StreamID: id, - BlockFragment: st.encodeHeader(headers...), - EndStream: true, - EndHeaders: true, - }) - } - for i := 0; i < defaultMaxStreams; i++ { - sendReq(streamID()) - <-inHandler - } - defer func() { - for i := 0; i < defaultMaxStreams; i++ { - leaveHandler <- true - } - }() - - // And this one should cross the limit: - // (It's also sent as a CONTINUATION, to verify we still track the decoder context, - // even if we're rejecting it) - rejectID := streamID() - headerBlock := st.encodeHeader(":path", testPath) - frag1, frag2 := headerBlock[:3], headerBlock[3:] - st.writeHeaders(HeadersFrameParam{ - StreamID: rejectID, - BlockFragment: frag1, - EndStream: true, - EndHeaders: false, // CONTINUATION coming - }) - if err := st.fr.WriteContinuation(rejectID, true, frag2); err != nil { - t.Fatal(err) - } - st.wantRSTStream(rejectID, ErrCodeProtocol) - - // But let a handler finish: - leaveHandler <- true - st.wantHeaders() - - // And now another stream should be able to start: - goodID := streamID() - sendReq(goodID, ":path", testPath) - select { - case got := <-inHandler: - if got != goodID { - t.Errorf("Got stream %d; want %d", got, goodID) - } - case <-time.After(3 * time.Second): - t.Error("timeout waiting for handler") - } -} - -// So many response headers that the server needs to use CONTINUATION frames: -func TestServer_Response_ManyHeaders_With_Continuation(t *testing.T) { - testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error { - h := w.Header() - for i := 0; i < 5000; i++ { - h.Set(fmt.Sprintf("x-header-%d", i), fmt.Sprintf("x-value-%d", i)) - } - return nil - }, func(st *serverTester) { - getSlash(st) - hf := st.wantHeaders() - if hf.HeadersEnded() { - t.Fatal("got unwanted END_HEADERS flag") - } - n := 0 - for { - n++ - cf := st.wantContinuation() - if cf.HeadersEnded() { - break - } - } - if n < 5 { - t.Errorf("Only got %d CONTINUATION frames; expected 5+ (currently 6)", n) - } - }) -} - -// This previously crashed (reported by Mathieu Lonjaret as observed -// while using Camlistore) because we got a DATA frame from the client -// after the handler exited and our logic at the time was wrong, -// keeping a stream in the map in stateClosed, which tickled an -// invariant check later when we tried to remove that stream (via -// defer sc.closeAllStreamsOnConnClose) when the serverConn serve loop -// ended. -func TestServer_NoCrash_HandlerClose_Then_ClientClose(t *testing.T) { - testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error { - // nothing - return nil - }, func(st *serverTester) { - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, - BlockFragment: st.encodeHeader(), - EndStream: false, // DATA is coming - EndHeaders: true, - }) - hf := st.wantHeaders() - if !hf.HeadersEnded() || !hf.StreamEnded() { - t.Fatalf("want END_HEADERS+END_STREAM, got %v", hf) - } - - // Sent when the a Handler closes while a client has - // indicated it's still sending DATA: - st.wantRSTStream(1, ErrCodeNo) - - // Now the handler has ended, so it's ended its - // stream, but the client hasn't closed its side - // (stateClosedLocal). So send more data and verify - // it doesn't crash with an internal invariant panic, like - // it did before. - st.writeData(1, true, []byte("foo")) - - // Sent after a peer sends data anyway (admittedly the - // previous RST_STREAM might've still been in-flight), - // but they'll get the more friendly 'cancel' code - // first. - st.wantRSTStream(1, ErrCodeStreamClosed) - - // Set up a bunch of machinery to record the panic we saw - // previously. - var ( - panMu sync.Mutex - panicVal interface{} - ) - - testHookOnPanicMu.Lock() - testHookOnPanic = func(sc *serverConn, pv interface{}) bool { - panMu.Lock() - panicVal = pv - panMu.Unlock() - return true - } - testHookOnPanicMu.Unlock() - - // Now force the serve loop to end, via closing the connection. - st.cc.Close() - select { - case <-st.sc.doneServing: - // Loop has exited. - panMu.Lock() - got := panicVal - panMu.Unlock() - if got != nil { - t.Errorf("Got panic: %v", got) - } - case <-time.After(5 * time.Second): - t.Error("timeout") - } - }) -} - -func TestServer_Rejects_TLS10(t *testing.T) { testRejectTLS(t, tls.VersionTLS10) } -func TestServer_Rejects_TLS11(t *testing.T) { testRejectTLS(t, tls.VersionTLS11) } - -func testRejectTLS(t *testing.T, max uint16) { - st := newServerTester(t, nil, func(c *tls.Config) { - c.MaxVersion = max - }) - defer st.Close() - gf := st.wantGoAway() - if got, want := gf.ErrCode, ErrCodeInadequateSecurity; got != want { - t.Errorf("Got error code %v; want %v", got, want) - } -} - -func TestServer_Rejects_TLSBadCipher(t *testing.T) { - st := newServerTester(t, nil, func(c *tls.Config) { - // All TLS 1.3 ciphers are good. Test with TLS 1.2. - c.MaxVersion = tls.VersionTLS12 - // Only list bad ones: - c.CipherSuites = []uint16{ - tls.TLS_RSA_WITH_RC4_128_SHA, - tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA, - tls.TLS_RSA_WITH_AES_128_CBC_SHA, - tls.TLS_RSA_WITH_AES_256_CBC_SHA, - tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, - tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, - tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, - tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA, - tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, - tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, - tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, - cipher_TLS_RSA_WITH_AES_128_CBC_SHA256, - } - }) - defer st.Close() - gf := st.wantGoAway() - if got, want := gf.ErrCode, ErrCodeInadequateSecurity; got != want { - t.Errorf("Got error code %v; want %v", got, want) - } -} - -func TestServer_Advertises_Common_Cipher(t *testing.T) { - const requiredSuite = tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - st := newServerTester(t, nil, func(c *tls.Config) { - // Have the client only support the one required by the spec. - c.CipherSuites = []uint16{requiredSuite} - }, func(ts *httptest.Server) { - var srv *http.Server = ts.Config - // Have the server configured with no specific cipher suites. - // This tests that Go's defaults include the required one. - srv.TLSConfig = nil - }) - defer st.Close() - st.greet() -} - -func (st *serverTester) onHeaderField(f hpack.HeaderField) { - if f.Name == "date" { - return - } - st.decodedHeaders = append(st.decodedHeaders, [2]string{f.Name, f.Value}) -} - -func (st *serverTester) decodeHeader(headerBlock []byte) (pairs [][2]string) { - st.decodedHeaders = nil - if _, err := st.hpackDec.Write(headerBlock); err != nil { - st.t.Fatalf("hpack decoding error: %v", err) - } - if err := st.hpackDec.Close(); err != nil { - st.t.Fatalf("hpack decoding error: %v", err) - } - return st.decodedHeaders -} - -// testServerResponse sets up an idle HTTP/2 connection. The client function should -// write a single request that must be handled by the handler. This waits up to 5s -// for client to return, then up to an additional 2s for the handler to return. -func testServerResponse(t testing.TB, - handler func(http.ResponseWriter, *http.Request) error, - client func(*serverTester), -) { - errc := make(chan error, 1) - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - if r.Body == nil { - t.Fatal("nil Body") - } - errc <- handler(w, r) - }) - defer st.Close() - - donec := make(chan bool) - go func() { - defer close(donec) - st.greet() - client(st) - }() - - select { - case <-donec: - case <-time.After(5 * time.Second): - t.Fatal("timeout in client") - } - - select { - case err := <-errc: - if err != nil { - t.Fatalf("Error in handler: %v", err) - } - case <-time.After(2 * time.Second): - t.Fatal("timeout in handler") - } -} - -// readBodyHandler returns an http Handler func that reads len(want) -// bytes from r.Body and fails t if the contents read were not -// the value of want. -func readBodyHandler(t *testing.T, want string) func(w http.ResponseWriter, r *http.Request) { - return func(w http.ResponseWriter, r *http.Request) { - buf := make([]byte, len(want)) - _, err := io.ReadFull(r.Body, buf) - if err != nil { - t.Error(err) - return - } - if string(buf) != want { - t.Errorf("read %q; want %q", buf, want) - } - } -} - -// TestServerWithCurl currently fails, hence the LenientCipherSuites test. See: -// https://github.com/tatsuhiro-t/nghttp2/issues/140 & -// http://sourceforge.net/p/curl/bugs/1472/ -func TestServerWithCurl(t *testing.T) { testServerWithCurl(t, false) } -func TestServerWithCurl_LenientCipherSuites(t *testing.T) { testServerWithCurl(t, true) } - -func testServerWithCurl(t *testing.T, permitProhibitedCipherSuites bool) { - if runtime.GOOS != "linux" { - t.Skip("skipping Docker test when not on Linux; requires --net which won't work with boot2docker anyway") - } - if testing.Short() { - t.Skip("skipping curl test in short mode") - } - requireCurl(t) - var gotConn int32 - testHookOnConn = func() { atomic.StoreInt32(&gotConn, 1) } - - const msg = "Hello from curl!\n" - ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Foo", "Bar") - w.Header().Set("Client-Proto", r.Proto) - io.WriteString(w, msg) - })) - ConfigureServer(ts.Config, &Server{ - PermitProhibitedCipherSuites: permitProhibitedCipherSuites, - }) - ts.TLS = ts.Config.TLSConfig // the httptest.Server has its own copy of this TLS config - ts.StartTLS() - defer ts.Close() - - t.Logf("Running test server for curl to hit at: %s", ts.URL) - container := curl(t, "--silent", "--http2", "--insecure", "-v", ts.URL) - defer kill(container) - resc := make(chan interface{}, 1) - go func() { - res, err := dockerLogs(container) - if err != nil { - resc <- err - } else { - resc <- res - } - }() - select { - case res := <-resc: - if err, ok := res.(error); ok { - t.Fatal(err) - } - body := string(res.([]byte)) - // Search for both "key: value" and "key:value", since curl changed their format - // Our Dockerfile contains the latest version (no space), but just in case people - // didn't rebuild, check both. - if !strings.Contains(body, "foo: Bar") && !strings.Contains(body, "foo:Bar") { - t.Errorf("didn't see foo: Bar header") - t.Logf("Got: %s", body) - } - if !strings.Contains(body, "client-proto: HTTP/2") && !strings.Contains(body, "client-proto:HTTP/2") { - t.Errorf("didn't see client-proto: HTTP/2 header") - t.Logf("Got: %s", res) - } - if !strings.Contains(string(res.([]byte)), msg) { - t.Errorf("didn't see %q content", msg) - t.Logf("Got: %s", res) - } - case <-time.After(3 * time.Second): - t.Errorf("timeout waiting for curl") - } - - if atomic.LoadInt32(&gotConn) == 0 { - t.Error("never saw an http2 connection") - } -} - -var doh2load = flag.Bool("h2load", false, "Run h2load test") - -func TestServerWithH2Load(t *testing.T) { - if !*doh2load { - t.Skip("Skipping without --h2load flag.") - } - if runtime.GOOS != "linux" { - t.Skip("skipping Docker test when not on Linux; requires --net which won't work with boot2docker anyway") - } - requireH2load(t) - - msg := strings.Repeat("Hello, h2load!\n", 5000) - ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - io.WriteString(w, msg) - w.(http.Flusher).Flush() - io.WriteString(w, msg) - })) - ts.StartTLS() - defer ts.Close() - - cmd := exec.Command("docker", "run", "--net=host", "--entrypoint=/usr/local/bin/h2load", "gohttp2/curl", - "-n100000", "-c100", "-m100", ts.URL) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - if err := cmd.Run(); err != nil { - t.Fatal(err) - } -} - -// Issue 12843 -func TestServerDoS_MaxHeaderListSize(t *testing.T) { - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {}) - defer st.Close() - - // shake hands - frameSize := defaultMaxReadFrameSize - var advHeaderListSize *uint32 - st.greetAndCheckSettings(func(s Setting) error { - switch s.ID { - case SettingMaxFrameSize: - if s.Val < minMaxFrameSize { - frameSize = minMaxFrameSize - } else if s.Val > maxFrameSize { - frameSize = maxFrameSize - } else { - frameSize = int(s.Val) - } - case SettingMaxHeaderListSize: - advHeaderListSize = &s.Val - } - return nil - }) - - if advHeaderListSize == nil { - t.Errorf("server didn't advertise a max header list size") - } else if *advHeaderListSize == 0 { - t.Errorf("server advertised a max header list size of 0") - } - - st.encodeHeaderField(":method", "GET") - st.encodeHeaderField(":path", "/") - st.encodeHeaderField(":scheme", "https") - cookie := strings.Repeat("*", 4058) - st.encodeHeaderField("cookie", cookie) - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, - BlockFragment: st.headerBuf.Bytes(), - EndStream: true, - EndHeaders: false, - }) - - // Capture the short encoding of a duplicate ~4K cookie, now - // that we've already sent it once. - st.headerBuf.Reset() - st.encodeHeaderField("cookie", cookie) - - // Now send 1MB of it. - const size = 1 << 20 - b := bytes.Repeat(st.headerBuf.Bytes(), size/st.headerBuf.Len()) - for len(b) > 0 { - chunk := b - if len(chunk) > frameSize { - chunk = chunk[:frameSize] - } - b = b[len(chunk):] - st.fr.WriteContinuation(1, len(b) == 0, chunk) - } - - h := st.wantHeaders() - if !h.HeadersEnded() { - t.Fatalf("Got HEADERS without END_HEADERS set: %v", h) - } - headers := st.decodeHeader(h.HeaderBlockFragment()) - want := [][2]string{ - {":status", "431"}, - {"content-type", "text/html; charset=utf-8"}, - {"content-length", "63"}, - } - if !reflect.DeepEqual(headers, want) { - t.Errorf("Headers mismatch.\n got: %q\nwant: %q\n", headers, want) - } -} - -func TestCompressionErrorOnWrite(t *testing.T) { - const maxStrLen = 8 << 10 - var serverConfig *http.Server - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - // No response body. - }, func(ts *httptest.Server) { - serverConfig = ts.Config - serverConfig.MaxHeaderBytes = maxStrLen - }) - st.addLogFilter("connection error: COMPRESSION_ERROR") - defer st.Close() - st.greet() - - maxAllowed := st.sc.framer.maxHeaderStringLen() - - // Crank this up, now that we have a conn connected with the - // hpack.Decoder's max string length set has been initialized - // from the earlier low ~8K value. We want this higher so don't - // hit the max header list size. We only want to test hitting - // the max string size. - serverConfig.MaxHeaderBytes = 1 << 20 - - // First a request with a header that's exactly the max allowed size - // for the hpack compression. It's still too long for the header list - // size, so we'll get the 431 error, but that keeps the compression - // context still valid. - hbf := st.encodeHeader("foo", strings.Repeat("a", maxAllowed)) - - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, - BlockFragment: hbf, - EndStream: true, - EndHeaders: true, - }) - h := st.wantHeaders() - if !h.HeadersEnded() { - t.Fatalf("Got HEADERS without END_HEADERS set: %v", h) - } - headers := st.decodeHeader(h.HeaderBlockFragment()) - want := [][2]string{ - {":status", "431"}, - {"content-type", "text/html; charset=utf-8"}, - {"content-length", "63"}, - } - if !reflect.DeepEqual(headers, want) { - t.Errorf("Headers mismatch.\n got: %q\nwant: %q\n", headers, want) - } - df := st.wantData() - if !strings.Contains(string(df.Data()), "HTTP Error 431") { - t.Errorf("Unexpected data body: %q", df.Data()) - } - if !df.StreamEnded() { - t.Fatalf("expect data stream end") - } - - // And now send one that's just one byte too big. - hbf = st.encodeHeader("bar", strings.Repeat("b", maxAllowed+1)) - st.writeHeaders(HeadersFrameParam{ - StreamID: 3, - BlockFragment: hbf, - EndStream: true, - EndHeaders: true, - }) - ga := st.wantGoAway() - if ga.ErrCode != ErrCodeCompression { - t.Errorf("GOAWAY err = %v; want ErrCodeCompression", ga.ErrCode) - } -} - -func TestCompressionErrorOnClose(t *testing.T) { - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - // No response body. - }) - st.addLogFilter("connection error: COMPRESSION_ERROR") - defer st.Close() - st.greet() - - hbf := st.encodeHeader("foo", "bar") - hbf = hbf[:len(hbf)-1] // truncate one byte from the end, so hpack.Decoder.Close fails. - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, - BlockFragment: hbf, - EndStream: true, - EndHeaders: true, - }) - ga := st.wantGoAway() - if ga.ErrCode != ErrCodeCompression { - t.Errorf("GOAWAY err = %v; want ErrCodeCompression", ga.ErrCode) - } -} - -// test that a server handler can read trailers from a client -func TestServerReadsTrailers(t *testing.T) { - const testBody = "some test body" - writeReq := func(st *serverTester) { - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, // clients send odd numbers - BlockFragment: st.encodeHeader("trailer", "Foo, Bar", "trailer", "Baz"), - EndStream: false, - EndHeaders: true, - }) - st.writeData(1, false, []byte(testBody)) - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, // clients send odd numbers - BlockFragment: st.encodeHeaderRaw( - "foo", "foov", - "bar", "barv", - "baz", "bazv", - "surprise", "wasn't declared; shouldn't show up", - ), - EndStream: true, - EndHeaders: true, - }) - } - checkReq := func(r *http.Request) { - wantTrailer := http.Header{ - "Foo": nil, - "Bar": nil, - "Baz": nil, - } - if !reflect.DeepEqual(r.Trailer, wantTrailer) { - t.Errorf("initial Trailer = %v; want %v", r.Trailer, wantTrailer) - } - slurp, err := ioutil.ReadAll(r.Body) - if string(slurp) != testBody { - t.Errorf("read body %q; want %q", slurp, testBody) - } - if err != nil { - t.Fatalf("Body slurp: %v", err) - } - wantTrailerAfter := http.Header{ - "Foo": {"foov"}, - "Bar": {"barv"}, - "Baz": {"bazv"}, - } - if !reflect.DeepEqual(r.Trailer, wantTrailerAfter) { - t.Errorf("final Trailer = %v; want %v", r.Trailer, wantTrailerAfter) - } - } - testServerRequest(t, writeReq, checkReq) -} - -// test that a server handler can send trailers -func TestServerWritesTrailers_WithFlush(t *testing.T) { testServerWritesTrailers(t, true) } -func TestServerWritesTrailers_WithoutFlush(t *testing.T) { testServerWritesTrailers(t, false) } - -func testServerWritesTrailers(t *testing.T, withFlush bool) { - // See https://httpwg.github.io/specs/rfc7540.html#rfc.section.8.1.3 - testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error { - w.Header().Set("Trailer", "Server-Trailer-A, Server-Trailer-B") - w.Header().Add("Trailer", "Server-Trailer-C") - w.Header().Add("Trailer", "Transfer-Encoding, Content-Length, Trailer") // filtered - - // Regular headers: - w.Header().Set("Foo", "Bar") - w.Header().Set("Content-Length", "5") // len("Hello") - - io.WriteString(w, "Hello") - if withFlush { - w.(http.Flusher).Flush() - } - w.Header().Set("Server-Trailer-A", "valuea") - w.Header().Set("Server-Trailer-C", "valuec") // skipping B - // After a flush, random keys like Server-Surprise shouldn't show up: - w.Header().Set("Server-Surpise", "surprise! this isn't predeclared!") - // But we do permit promoting keys to trailers after a - // flush if they start with the magic - // otherwise-invalid "Trailer:" prefix: - w.Header().Set("Trailer:Post-Header-Trailer", "hi1") - w.Header().Set("Trailer:post-header-trailer2", "hi2") - w.Header().Set("Trailer:Range", "invalid") - w.Header().Set("Trailer:Foo\x01Bogus", "invalid") - w.Header().Set("Transfer-Encoding", "should not be included; Forbidden by RFC 7230 4.1.2") - w.Header().Set("Content-Length", "should not be included; Forbidden by RFC 7230 4.1.2") - w.Header().Set("Trailer", "should not be included; Forbidden by RFC 7230 4.1.2") - return nil - }, func(st *serverTester) { - getSlash(st) - hf := st.wantHeaders() - if hf.StreamEnded() { - t.Fatal("response HEADERS had END_STREAM") - } - if !hf.HeadersEnded() { - t.Fatal("response HEADERS didn't have END_HEADERS") - } - goth := st.decodeHeader(hf.HeaderBlockFragment()) - wanth := [][2]string{ - {":status", "200"}, - {"foo", "Bar"}, - {"trailer", "Server-Trailer-A, Server-Trailer-B"}, - {"trailer", "Server-Trailer-C"}, - {"trailer", "Transfer-Encoding, Content-Length, Trailer"}, - {"content-type", "text/plain; charset=utf-8"}, - {"content-length", "5"}, - } - if !reflect.DeepEqual(goth, wanth) { - t.Errorf("Header mismatch.\n got: %v\nwant: %v", goth, wanth) - } - df := st.wantData() - if string(df.Data()) != "Hello" { - t.Fatalf("Client read %q; want Hello", df.Data()) - } - if df.StreamEnded() { - t.Fatalf("data frame had STREAM_ENDED") - } - tf := st.wantHeaders() // for the trailers - if !tf.StreamEnded() { - t.Fatalf("trailers HEADERS lacked END_STREAM") - } - if !tf.HeadersEnded() { - t.Fatalf("trailers HEADERS lacked END_HEADERS") - } - wanth = [][2]string{ - {"post-header-trailer", "hi1"}, - {"post-header-trailer2", "hi2"}, - {"server-trailer-a", "valuea"}, - {"server-trailer-c", "valuec"}, - } - goth = st.decodeHeader(tf.HeaderBlockFragment()) - if !reflect.DeepEqual(goth, wanth) { - t.Errorf("Header mismatch.\n got: %v\nwant: %v", goth, wanth) - } - }) -} - -// validate transmitted header field names & values -// golang.org/issue/14048 -func TestServerDoesntWriteInvalidHeaders(t *testing.T) { - testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error { - w.Header().Add("OK1", "x") - w.Header().Add("Bad:Colon", "x") // colon (non-token byte) in key - w.Header().Add("Bad1\x00", "x") // null in key - w.Header().Add("Bad2", "x\x00y") // null in value - return nil - }, func(st *serverTester) { - getSlash(st) - hf := st.wantHeaders() - if !hf.StreamEnded() { - t.Error("response HEADERS lacked END_STREAM") - } - if !hf.HeadersEnded() { - t.Fatal("response HEADERS didn't have END_HEADERS") - } - goth := st.decodeHeader(hf.HeaderBlockFragment()) - wanth := [][2]string{ - {":status", "200"}, - {"ok1", "x"}, - {"content-length", "0"}, - } - if !reflect.DeepEqual(goth, wanth) { - t.Errorf("Header mismatch.\n got: %v\nwant: %v", goth, wanth) - } - }) -} - -func BenchmarkServerGets(b *testing.B) { - defer disableGoroutineTracking()() - b.ReportAllocs() - - const msg = "Hello, world" - st := newServerTester(b, func(w http.ResponseWriter, r *http.Request) { - io.WriteString(w, msg) - }) - defer st.Close() - st.greet() - - // Give the server quota to reply. (plus it has the 64KB) - if err := st.fr.WriteWindowUpdate(0, uint32(b.N*len(msg))); err != nil { - b.Fatal(err) - } - - for i := 0; i < b.N; i++ { - id := 1 + uint32(i)*2 - st.writeHeaders(HeadersFrameParam{ - StreamID: id, - BlockFragment: st.encodeHeader(), - EndStream: true, - EndHeaders: true, - }) - st.wantHeaders() - df := st.wantData() - if !df.StreamEnded() { - b.Fatalf("DATA didn't have END_STREAM; got %v", df) - } - } -} - -func BenchmarkServerPosts(b *testing.B) { - defer disableGoroutineTracking()() - b.ReportAllocs() - - const msg = "Hello, world" - st := newServerTester(b, func(w http.ResponseWriter, r *http.Request) { - // Consume the (empty) body from th peer before replying, otherwise - // the server will sometimes (depending on scheduling) send the peer a - // a RST_STREAM with the CANCEL error code. - if n, err := io.Copy(ioutil.Discard, r.Body); n != 0 || err != nil { - b.Errorf("Copy error; got %v, %v; want 0, nil", n, err) - } - io.WriteString(w, msg) - }) - defer st.Close() - st.greet() - - // Give the server quota to reply. (plus it has the 64KB) - if err := st.fr.WriteWindowUpdate(0, uint32(b.N*len(msg))); err != nil { - b.Fatal(err) - } - - for i := 0; i < b.N; i++ { - id := 1 + uint32(i)*2 - st.writeHeaders(HeadersFrameParam{ - StreamID: id, - BlockFragment: st.encodeHeader(":method", "POST"), - EndStream: false, - EndHeaders: true, - }) - st.writeData(id, true, nil) - st.wantHeaders() - df := st.wantData() - if !df.StreamEnded() { - b.Fatalf("DATA didn't have END_STREAM; got %v", df) - } - } -} - -// Send a stream of messages from server to client in separate data frames. -// Brings up performance issues seen in long streams. -// Created to show problem in go issue #18502 -func BenchmarkServerToClientStreamDefaultOptions(b *testing.B) { - benchmarkServerToClientStream(b) -} - -// Justification for Change-Id: Iad93420ef6c3918f54249d867098f1dadfa324d8 -// Expect to see memory/alloc reduction by opting in to Frame reuse with the Framer. -func BenchmarkServerToClientStreamReuseFrames(b *testing.B) { - benchmarkServerToClientStream(b, optFramerReuseFrames) -} - -func benchmarkServerToClientStream(b *testing.B, newServerOpts ...interface{}) { - defer disableGoroutineTracking()() - b.ReportAllocs() - const msgLen = 1 - // default window size - const windowSize = 1<<16 - 1 - - // next message to send from the server and for the client to expect - nextMsg := func(i int) []byte { - msg := make([]byte, msgLen) - msg[0] = byte(i) - if len(msg) != msgLen { - panic("invalid test setup msg length") - } - return msg - } - - st := newServerTester(b, func(w http.ResponseWriter, r *http.Request) { - // Consume the (empty) body from th peer before replying, otherwise - // the server will sometimes (depending on scheduling) send the peer a - // a RST_STREAM with the CANCEL error code. - if n, err := io.Copy(ioutil.Discard, r.Body); n != 0 || err != nil { - b.Errorf("Copy error; got %v, %v; want 0, nil", n, err) - } - for i := 0; i < b.N; i += 1 { - w.Write(nextMsg(i)) - w.(http.Flusher).Flush() - } - }, newServerOpts...) - defer st.Close() - st.greet() - - const id = uint32(1) - - st.writeHeaders(HeadersFrameParam{ - StreamID: id, - BlockFragment: st.encodeHeader(":method", "POST"), - EndStream: false, - EndHeaders: true, - }) - - st.writeData(id, true, nil) - st.wantHeaders() - - var pendingWindowUpdate = uint32(0) - - for i := 0; i < b.N; i += 1 { - expected := nextMsg(i) - df := st.wantData() - if bytes.Compare(expected, df.data) != 0 { - b.Fatalf("Bad message received; want %v; got %v", expected, df.data) - } - // try to send infrequent but large window updates so they don't overwhelm the test - pendingWindowUpdate += uint32(len(df.data)) - if pendingWindowUpdate >= windowSize/2 { - if err := st.fr.WriteWindowUpdate(0, pendingWindowUpdate); err != nil { - b.Fatal(err) - } - if err := st.fr.WriteWindowUpdate(id, pendingWindowUpdate); err != nil { - b.Fatal(err) - } - pendingWindowUpdate = 0 - } - } - df := st.wantData() - if !df.StreamEnded() { - b.Fatalf("DATA didn't have END_STREAM; got %v", df) - } -} - -// go-fuzz bug, originally reported at https://github.com/bradfitz/http2/issues/53 -// Verify we don't hang. -func TestIssue53(t *testing.T) { - const data = "PRI * HTTP/2.0\r\n\r\nSM" + - "\r\n\r\n\x00\x00\x00\x01\ainfinfin\ad" - s := &http.Server{ - ErrorLog: log.New(io.MultiWriter(stderrv(), twriter{t: t}), "", log.LstdFlags), - Handler: http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - w.Write([]byte("hello")) - }), - } - s2 := &Server{ - MaxReadFrameSize: 1 << 16, - PermitProhibitedCipherSuites: true, - } - c := &issue53Conn{[]byte(data), false, false} - s2.ServeConn(c, &ServeConnOpts{BaseConfig: s}) - if !c.closed { - t.Fatal("connection is not closed") - } -} - -type issue53Conn struct { - data []byte - closed bool - written bool -} - -func (c *issue53Conn) Read(b []byte) (n int, err error) { - if len(c.data) == 0 { - return 0, io.EOF - } - n = copy(b, c.data) - c.data = c.data[n:] - return -} - -func (c *issue53Conn) Write(b []byte) (n int, err error) { - c.written = true - return len(b), nil -} - -func (c *issue53Conn) Close() error { - c.closed = true - return nil -} - -func (c *issue53Conn) LocalAddr() net.Addr { - return &net.TCPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 49706} -} -func (c *issue53Conn) RemoteAddr() net.Addr { - return &net.TCPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 49706} -} -func (c *issue53Conn) SetDeadline(t time.Time) error { return nil } -func (c *issue53Conn) SetReadDeadline(t time.Time) error { return nil } -func (c *issue53Conn) SetWriteDeadline(t time.Time) error { return nil } - -// golang.org/issue/12895 -func TestConfigureServer(t *testing.T) { - tests := []struct { - name string - tlsConfig *tls.Config - wantErr string - }{ - { - name: "empty server", - }, - { - name: "just the required cipher suite", - tlsConfig: &tls.Config{ - CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, - }, - }, - { - name: "just the alternative required cipher suite", - tlsConfig: &tls.Config{ - CipherSuites: []uint16{tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, - }, - }, - { - name: "missing required cipher suite", - tlsConfig: &tls.Config{ - CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384}, - }, - wantErr: "is missing an HTTP/2-required AES_128_GCM_SHA256 cipher.", - }, - { - name: "required after bad", - tlsConfig: &tls.Config{ - CipherSuites: []uint16{tls.TLS_RSA_WITH_RC4_128_SHA, tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, - }, - wantErr: "contains an HTTP/2-approved cipher suite (0xc02f), but it comes after", - }, - { - name: "bad after required", - tlsConfig: &tls.Config{ - CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_RSA_WITH_RC4_128_SHA}, - }, - }, - } - for _, tt := range tests { - srv := &http.Server{TLSConfig: tt.tlsConfig} - err := ConfigureServer(srv, nil) - if (err != nil) != (tt.wantErr != "") { - if tt.wantErr != "" { - t.Errorf("%s: success, but want error", tt.name) - } else { - t.Errorf("%s: unexpected error: %v", tt.name, err) - } - } - if err != nil && tt.wantErr != "" && !strings.Contains(err.Error(), tt.wantErr) { - t.Errorf("%s: err = %v; want substring %q", tt.name, err, tt.wantErr) - } - if err == nil && !srv.TLSConfig.PreferServerCipherSuites { - t.Errorf("%s: PreferServerCipherSuite is false; want true", tt.name) - } - } -} - -func TestServerRejectHeadWithBody(t *testing.T) { - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - // No response body. - }) - defer st.Close() - st.greet() - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, // clients send odd numbers - BlockFragment: st.encodeHeader(":method", "HEAD"), - EndStream: false, // what we're testing, a bogus HEAD request with body - EndHeaders: true, - }) - st.wantRSTStream(1, ErrCodeProtocol) -} - -func TestServerNoAutoContentLengthOnHead(t *testing.T) { - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - // No response body. (or smaller than one frame) - }) - defer st.Close() - st.greet() - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, // clients send odd numbers - BlockFragment: st.encodeHeader(":method", "HEAD"), - EndStream: true, - EndHeaders: true, - }) - h := st.wantHeaders() - headers := st.decodeHeader(h.HeaderBlockFragment()) - want := [][2]string{ - {":status", "200"}, - } - if !reflect.DeepEqual(headers, want) { - t.Errorf("Headers mismatch.\n got: %q\nwant: %q\n", headers, want) - } -} - -// golang.org/issue/13495 -func TestServerNoDuplicateContentType(t *testing.T) { - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - w.Header()["Content-Type"] = []string{""} - fmt.Fprintf(w, "hi") - }) - defer st.Close() - st.greet() - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, - BlockFragment: st.encodeHeader(), - EndStream: true, - EndHeaders: true, - }) - h := st.wantHeaders() - headers := st.decodeHeader(h.HeaderBlockFragment()) - want := [][2]string{ - {":status", "200"}, - {"content-type", ""}, - {"content-length", "41"}, - } - if !reflect.DeepEqual(headers, want) { - t.Errorf("Headers mismatch.\n got: %q\nwant: %q\n", headers, want) - } -} - -func disableGoroutineTracking() (restore func()) { - old := DebugGoroutines - DebugGoroutines = false - return func() { DebugGoroutines = old } -} - -func BenchmarkServer_GetRequest(b *testing.B) { - defer disableGoroutineTracking()() - b.ReportAllocs() - const msg = "Hello, world." - st := newServerTester(b, func(w http.ResponseWriter, r *http.Request) { - n, err := io.Copy(ioutil.Discard, r.Body) - if err != nil || n > 0 { - b.Errorf("Read %d bytes, error %v; want 0 bytes.", n, err) - } - io.WriteString(w, msg) - }) - defer st.Close() - - st.greet() - // Give the server quota to reply. (plus it has the 64KB) - if err := st.fr.WriteWindowUpdate(0, uint32(b.N*len(msg))); err != nil { - b.Fatal(err) - } - hbf := st.encodeHeader(":method", "GET") - for i := 0; i < b.N; i++ { - streamID := uint32(1 + 2*i) - st.writeHeaders(HeadersFrameParam{ - StreamID: streamID, - BlockFragment: hbf, - EndStream: true, - EndHeaders: true, - }) - st.wantHeaders() - st.wantData() - } -} - -func BenchmarkServer_PostRequest(b *testing.B) { - defer disableGoroutineTracking()() - b.ReportAllocs() - const msg = "Hello, world." - st := newServerTester(b, func(w http.ResponseWriter, r *http.Request) { - n, err := io.Copy(ioutil.Discard, r.Body) - if err != nil || n > 0 { - b.Errorf("Read %d bytes, error %v; want 0 bytes.", n, err) - } - io.WriteString(w, msg) - }) - defer st.Close() - st.greet() - // Give the server quota to reply. (plus it has the 64KB) - if err := st.fr.WriteWindowUpdate(0, uint32(b.N*len(msg))); err != nil { - b.Fatal(err) - } - hbf := st.encodeHeader(":method", "POST") - for i := 0; i < b.N; i++ { - streamID := uint32(1 + 2*i) - st.writeHeaders(HeadersFrameParam{ - StreamID: streamID, - BlockFragment: hbf, - EndStream: false, - EndHeaders: true, - }) - st.writeData(streamID, true, nil) - st.wantHeaders() - st.wantData() - } -} - -type connStateConn struct { - net.Conn - cs tls.ConnectionState -} - -func (c connStateConn) ConnectionState() tls.ConnectionState { return c.cs } - -// golang.org/issue/12737 -- handle any net.Conn, not just -// *tls.Conn. -func TestServerHandleCustomConn(t *testing.T) { - var s Server - c1, c2 := net.Pipe() - clientDone := make(chan struct{}) - handlerDone := make(chan struct{}) - var req *http.Request - go func() { - defer close(clientDone) - defer c2.Close() - fr := NewFramer(c2, c2) - io.WriteString(c2, ClientPreface) - fr.WriteSettings() - fr.WriteSettingsAck() - f, err := fr.ReadFrame() - if err != nil { - t.Error(err) - return - } - if sf, ok := f.(*SettingsFrame); !ok || sf.IsAck() { - t.Errorf("Got %v; want non-ACK SettingsFrame", summarizeFrame(f)) - return - } - f, err = fr.ReadFrame() - if err != nil { - t.Error(err) - return - } - if sf, ok := f.(*SettingsFrame); !ok || !sf.IsAck() { - t.Errorf("Got %v; want ACK SettingsFrame", summarizeFrame(f)) - return - } - var henc hpackEncoder - fr.WriteHeaders(HeadersFrameParam{ - StreamID: 1, - BlockFragment: henc.encodeHeaderRaw(t, ":method", "GET", ":path", "/", ":scheme", "https", ":authority", "foo.com"), - EndStream: true, - EndHeaders: true, - }) - go io.Copy(ioutil.Discard, c2) - <-handlerDone - }() - const testString = "my custom ConnectionState" - fakeConnState := tls.ConnectionState{ - ServerName: testString, - Version: tls.VersionTLS12, - CipherSuite: cipher_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - } - go s.ServeConn(connStateConn{c1, fakeConnState}, &ServeConnOpts{ - BaseConfig: &http.Server{ - Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - defer close(handlerDone) - req = r - }), - }}) - select { - case <-clientDone: - case <-time.After(5 * time.Second): - t.Fatal("timeout waiting for handler") - } - if req.TLS == nil { - t.Fatalf("Request.TLS is nil. Got: %#v", req) - } - if req.TLS.ServerName != testString { - t.Fatalf("Request.TLS = %+v; want ServerName of %q", req.TLS, testString) - } -} - -// golang.org/issue/14214 -func TestServer_Rejects_ConnHeaders(t *testing.T) { - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - t.Error("should not get to Handler") - }) - defer st.Close() - st.greet() - st.bodylessReq1("connection", "foo") - hf := st.wantHeaders() - goth := st.decodeHeader(hf.HeaderBlockFragment()) - wanth := [][2]string{ - {":status", "400"}, - {"content-type", "text/plain; charset=utf-8"}, - {"x-content-type-options", "nosniff"}, - {"content-length", "51"}, - } - if !reflect.DeepEqual(goth, wanth) { - t.Errorf("Got headers %v; want %v", goth, wanth) - } -} - -type hpackEncoder struct { - enc *hpack.Encoder - buf bytes.Buffer -} - -func (he *hpackEncoder) encodeHeaderRaw(t *testing.T, headers ...string) []byte { - if len(headers)%2 == 1 { - panic("odd number of kv args") - } - he.buf.Reset() - if he.enc == nil { - he.enc = hpack.NewEncoder(&he.buf) - } - for len(headers) > 0 { - k, v := headers[0], headers[1] - err := he.enc.WriteField(hpack.HeaderField{Name: k, Value: v}) - if err != nil { - t.Fatalf("HPACK encoding error for %q/%q: %v", k, v, err) - } - headers = headers[2:] - } - return he.buf.Bytes() -} - -func TestCheckValidHTTP2Request(t *testing.T) { - tests := []struct { - h http.Header - want error - }{ - { - h: http.Header{"Te": {"trailers"}}, - want: nil, - }, - { - h: http.Header{"Te": {"trailers", "bogus"}}, - want: errors.New(`request header "TE" may only be "trailers" in HTTP/2`), - }, - { - h: http.Header{"Foo": {""}}, - want: nil, - }, - { - h: http.Header{"Connection": {""}}, - want: errors.New(`request header "Connection" is not valid in HTTP/2`), - }, - { - h: http.Header{"Proxy-Connection": {""}}, - want: errors.New(`request header "Proxy-Connection" is not valid in HTTP/2`), - }, - { - h: http.Header{"Keep-Alive": {""}}, - want: errors.New(`request header "Keep-Alive" is not valid in HTTP/2`), - }, - { - h: http.Header{"Upgrade": {""}}, - want: errors.New(`request header "Upgrade" is not valid in HTTP/2`), - }, - } - for i, tt := range tests { - got := checkValidHTTP2RequestHeaders(tt.h) - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("%d. checkValidHTTP2Request = %v; want %v", i, got, tt.want) - } - } -} - -// golang.org/issue/14030 -func TestExpect100ContinueAfterHandlerWrites(t *testing.T) { - const msg = "Hello" - const msg2 = "World" - - doRead := make(chan bool, 1) - defer close(doRead) // fallback cleanup - - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - io.WriteString(w, msg) - w.(http.Flusher).Flush() - - // Do a read, which might force a 100-continue status to be sent. - <-doRead - r.Body.Read(make([]byte, 10)) - - io.WriteString(w, msg2) - - }, optOnlyServer) - defer st.Close() - - tr := &Transport{TLSClientConfig: tlsConfigInsecure} - defer tr.CloseIdleConnections() - - req, _ := http.NewRequest("POST", st.ts.URL, io.LimitReader(neverEnding('A'), 2<<20)) - req.Header.Set("Expect", "100-continue") - - res, err := tr.RoundTrip(req) - if err != nil { - t.Fatal(err) - } - defer res.Body.Close() - - buf := make([]byte, len(msg)) - if _, err := io.ReadFull(res.Body, buf); err != nil { - t.Fatal(err) - } - if string(buf) != msg { - t.Fatalf("msg = %q; want %q", buf, msg) - } - - doRead <- true - - if _, err := io.ReadFull(res.Body, buf); err != nil { - t.Fatal(err) - } - if string(buf) != msg2 { - t.Fatalf("second msg = %q; want %q", buf, msg2) - } -} - -type funcReader func([]byte) (n int, err error) - -func (f funcReader) Read(p []byte) (n int, err error) { return f(p) } - -// golang.org/issue/16481 -- return flow control when streams close with unread data. -// (The Server version of the bug. See also TestUnreadFlowControlReturned_Transport) -func TestUnreadFlowControlReturned_Server(t *testing.T) { - unblock := make(chan bool, 1) - defer close(unblock) - - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - // Don't read the 16KB request body. Wait until the client's - // done sending it and then return. This should cause the Server - // to then return those 16KB of flow control to the client. - <-unblock - }, optOnlyServer) - defer st.Close() - - tr := &Transport{TLSClientConfig: tlsConfigInsecure} - defer tr.CloseIdleConnections() - - // This previously hung on the 4th iteration. - for i := 0; i < 6; i++ { - body := io.MultiReader( - io.LimitReader(neverEnding('A'), 16<<10), - funcReader(func([]byte) (n int, err error) { - unblock <- true - return 0, io.EOF - }), - ) - req, _ := http.NewRequest("POST", st.ts.URL, body) - res, err := tr.RoundTrip(req) - if err != nil { - t.Fatal(err) - } - res.Body.Close() - } - -} - -func TestServerIdleTimeout(t *testing.T) { - if testing.Short() { - t.Skip("skipping in short mode") - } - - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - }, func(h2s *Server) { - h2s.IdleTimeout = 500 * time.Millisecond - }) - defer st.Close() - - st.greet() - ga := st.wantGoAway() - if ga.ErrCode != ErrCodeNo { - t.Errorf("GOAWAY error = %v; want ErrCodeNo", ga.ErrCode) - } -} - -func TestServerIdleTimeout_AfterRequest(t *testing.T) { - if testing.Short() { - t.Skip("skipping in short mode") - } - const timeout = 250 * time.Millisecond - - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - time.Sleep(timeout * 2) - }, func(h2s *Server) { - h2s.IdleTimeout = timeout - }) - defer st.Close() - - st.greet() - - // Send a request which takes twice the timeout. Verifies the - // idle timeout doesn't fire while we're in a request: - st.bodylessReq1() - st.wantHeaders() - - // But the idle timeout should be rearmed after the request - // is done: - ga := st.wantGoAway() - if ga.ErrCode != ErrCodeNo { - t.Errorf("GOAWAY error = %v; want ErrCodeNo", ga.ErrCode) - } -} - -// grpc-go closes the Request.Body currently with a Read. -// Verify that it doesn't race. -// See https://github.com/grpc/grpc-go/pull/938 -func TestRequestBodyReadCloseRace(t *testing.T) { - for i := 0; i < 100; i++ { - body := &requestBody{ - pipe: &pipe{ - b: new(bytes.Buffer), - }, - } - body.pipe.CloseWithError(io.EOF) - - done := make(chan bool, 1) - buf := make([]byte, 10) - go func() { - time.Sleep(1 * time.Millisecond) - body.Close() - done <- true - }() - body.Read(buf) - <-done - } -} - -func TestIssue20704Race(t *testing.T) { - if testing.Short() && os.Getenv("GO_BUILDER_NAME") == "" { - t.Skip("skipping in short mode") - } - const ( - itemSize = 1 << 10 - itemCount = 100 - ) - - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - for i := 0; i < itemCount; i++ { - _, err := w.Write(make([]byte, itemSize)) - if err != nil { - return - } - } - }, optOnlyServer) - defer st.Close() - - tr := &Transport{TLSClientConfig: tlsConfigInsecure} - defer tr.CloseIdleConnections() - cl := &http.Client{Transport: tr} - - for i := 0; i < 1000; i++ { - resp, err := cl.Get(st.ts.URL) - if err != nil { - t.Fatal(err) - } - // Force a RST stream to the server by closing without - // reading the body: - resp.Body.Close() - } -} - -func TestServer_Rejects_TooSmall(t *testing.T) { - testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error { - ioutil.ReadAll(r.Body) - return nil - }, func(st *serverTester) { - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, // clients send odd numbers - BlockFragment: st.encodeHeader( - ":method", "POST", - "content-length", "4", - ), - EndStream: false, // to say DATA frames are coming - EndHeaders: true, - }) - st.writeData(1, true, []byte("12345")) - - st.wantRSTStream(1, ErrCodeProtocol) - }) -} - -// Tests that a handler setting "Connection: close" results in a GOAWAY being sent, -// and the connection still completing. -func TestServerHandlerConnectionClose(t *testing.T) { - unblockHandler := make(chan bool, 1) - defer close(unblockHandler) // backup; in case of errors - testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error { - w.Header().Set("Connection", "close") - w.Header().Set("Foo", "bar") - w.(http.Flusher).Flush() - <-unblockHandler - return nil - }, func(st *serverTester) { - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, - BlockFragment: st.encodeHeader(), - EndStream: true, - EndHeaders: true, - }) - var sawGoAway bool - var sawRes bool - for { - f, err := st.readFrame() - if err == io.EOF { - break - } - if err != nil { - t.Fatal(err) - } - switch f := f.(type) { - case *GoAwayFrame: - sawGoAway = true - unblockHandler <- true - if f.LastStreamID != 1 || f.ErrCode != ErrCodeNo { - t.Errorf("unexpected GOAWAY frame: %v", summarizeFrame(f)) - } - case *HeadersFrame: - goth := st.decodeHeader(f.HeaderBlockFragment()) - wanth := [][2]string{ - {":status", "200"}, - {"foo", "bar"}, - } - if !reflect.DeepEqual(goth, wanth) { - t.Errorf("got headers %v; want %v", goth, wanth) - } - sawRes = true - case *DataFrame: - if f.StreamID != 1 || !f.StreamEnded() || len(f.Data()) != 0 { - t.Errorf("unexpected DATA frame: %v", summarizeFrame(f)) - } - default: - t.Logf("unexpected frame: %v", summarizeFrame(f)) - } - } - if !sawGoAway { - t.Errorf("didn't see GOAWAY") - } - if !sawRes { - t.Errorf("didn't see response") - } - }) -} - -func TestServer_Headers_HalfCloseRemote(t *testing.T) { - var st *serverTester - writeData := make(chan bool) - writeHeaders := make(chan bool) - leaveHandler := make(chan bool) - st = newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - if st.stream(1) == nil { - t.Errorf("nil stream 1 in handler") - } - if got, want := st.streamState(1), stateOpen; got != want { - t.Errorf("in handler, state is %v; want %v", got, want) - } - writeData <- true - if n, err := r.Body.Read(make([]byte, 1)); n != 0 || err != io.EOF { - t.Errorf("body read = %d, %v; want 0, EOF", n, err) - } - if got, want := st.streamState(1), stateHalfClosedRemote; got != want { - t.Errorf("in handler, state is %v; want %v", got, want) - } - writeHeaders <- true - - <-leaveHandler - }) - st.greet() - - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, - BlockFragment: st.encodeHeader(), - EndStream: false, // keep it open - EndHeaders: true, - }) - <-writeData - st.writeData(1, true, nil) - - <-writeHeaders - - st.writeHeaders(HeadersFrameParam{ - StreamID: 1, - BlockFragment: st.encodeHeader(), - EndStream: false, // keep it open - EndHeaders: true, - }) - - defer close(leaveHandler) - - st.wantRSTStream(1, ErrCodeStreamClosed) -} - -func TestServerGracefulShutdown(t *testing.T) { - var st *serverTester - handlerDone := make(chan struct{}) - st = newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - defer close(handlerDone) - go st.ts.Config.Shutdown(context.Background()) - - ga := st.wantGoAway() - if ga.ErrCode != ErrCodeNo { - t.Errorf("GOAWAY error = %v; want ErrCodeNo", ga.ErrCode) - } - if ga.LastStreamID != 1 { - t.Errorf("GOAWAY LastStreamID = %v; want 1", ga.LastStreamID) - } - - w.Header().Set("x-foo", "bar") - }) - defer st.Close() - - st.greet() - st.bodylessReq1() - - select { - case <-handlerDone: - case <-time.After(5 * time.Second): - t.Fatalf("server did not shutdown?") - } - hf := st.wantHeaders() - goth := st.decodeHeader(hf.HeaderBlockFragment()) - wanth := [][2]string{ - {":status", "200"}, - {"x-foo", "bar"}, - {"content-length", "0"}, - } - if !reflect.DeepEqual(goth, wanth) { - t.Errorf("Got headers %v; want %v", goth, wanth) - } - - n, err := st.cc.Read([]byte{0}) - if n != 0 || err == nil { - t.Errorf("Read = %v, %v; want 0, non-nil", n, err) - } -} diff --git a/vendor/golang.org/x/net/http2/transport_test.go b/vendor/golang.org/x/net/http2/transport_test.go deleted file mode 100644 index f771f457..00000000 --- a/vendor/golang.org/x/net/http2/transport_test.go +++ /dev/null @@ -1,4281 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package http2 - -import ( - "bufio" - "bytes" - "context" - "crypto/tls" - "errors" - "flag" - "fmt" - "io" - "io/ioutil" - "log" - "math/rand" - "net" - "net/http" - "net/http/httptest" - "net/textproto" - "net/url" - "os" - "reflect" - "runtime" - "sort" - "strconv" - "strings" - "sync" - "sync/atomic" - "testing" - "time" - - "golang.org/x/net/http2/hpack" -) - -var ( - extNet = flag.Bool("extnet", false, "do external network tests") - transportHost = flag.String("transporthost", "http2.golang.org", "hostname to use for TestTransport") - insecure = flag.Bool("insecure", false, "insecure TLS dials") // TODO: dead code. remove? -) - -var tlsConfigInsecure = &tls.Config{InsecureSkipVerify: true} - -var canceledCtx context.Context - -func init() { - ctx, cancel := context.WithCancel(context.Background()) - cancel() - canceledCtx = ctx -} - -func TestTransportExternal(t *testing.T) { - if !*extNet { - t.Skip("skipping external network test") - } - req, _ := http.NewRequest("GET", "https://"+*transportHost+"/", nil) - rt := &Transport{TLSClientConfig: tlsConfigInsecure} - res, err := rt.RoundTrip(req) - if err != nil { - t.Fatalf("%v", err) - } - res.Write(os.Stdout) -} - -type fakeTLSConn struct { - net.Conn -} - -func (c *fakeTLSConn) ConnectionState() tls.ConnectionState { - return tls.ConnectionState{ - Version: tls.VersionTLS12, - CipherSuite: cipher_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - } -} - -func startH2cServer(t *testing.T) net.Listener { - h2Server := &Server{} - l := newLocalListener(t) - go func() { - conn, err := l.Accept() - if err != nil { - t.Error(err) - return - } - h2Server.ServeConn(&fakeTLSConn{conn}, &ServeConnOpts{Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - fmt.Fprintf(w, "Hello, %v, http: %v", r.URL.Path, r.TLS == nil) - })}) - }() - return l -} - -func TestTransportH2c(t *testing.T) { - l := startH2cServer(t) - defer l.Close() - req, err := http.NewRequest("GET", "http://"+l.Addr().String()+"/foobar", nil) - if err != nil { - t.Fatal(err) - } - tr := &Transport{ - AllowHTTP: true, - DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) { - return net.Dial(network, addr) - }, - } - res, err := tr.RoundTrip(req) - if err != nil { - t.Fatal(err) - } - if res.ProtoMajor != 2 { - t.Fatal("proto not h2c") - } - body, err := ioutil.ReadAll(res.Body) - if err != nil { - t.Fatal(err) - } - if got, want := string(body), "Hello, /foobar, http: true"; got != want { - t.Fatalf("response got %v, want %v", got, want) - } -} - -func TestTransport(t *testing.T) { - const body = "sup" - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - io.WriteString(w, body) - }, optOnlyServer) - defer st.Close() - - tr := &Transport{TLSClientConfig: tlsConfigInsecure} - defer tr.CloseIdleConnections() - - req, err := http.NewRequest("GET", st.ts.URL, nil) - if err != nil { - t.Fatal(err) - } - res, err := tr.RoundTrip(req) - if err != nil { - t.Fatal(err) - } - defer res.Body.Close() - - t.Logf("Got res: %+v", res) - if g, w := res.StatusCode, 200; g != w { - t.Errorf("StatusCode = %v; want %v", g, w) - } - if g, w := res.Status, "200 OK"; g != w { - t.Errorf("Status = %q; want %q", g, w) - } - wantHeader := http.Header{ - "Content-Length": []string{"3"}, - "Content-Type": []string{"text/plain; charset=utf-8"}, - "Date": []string{"XXX"}, // see cleanDate - } - cleanDate(res) - if !reflect.DeepEqual(res.Header, wantHeader) { - t.Errorf("res Header = %v; want %v", res.Header, wantHeader) - } - if res.Request != req { - t.Errorf("Response.Request = %p; want %p", res.Request, req) - } - if res.TLS == nil { - t.Error("Response.TLS = nil; want non-nil") - } - slurp, err := ioutil.ReadAll(res.Body) - if err != nil { - t.Errorf("Body read: %v", err) - } else if string(slurp) != body { - t.Errorf("Body = %q; want %q", slurp, body) - } -} - -func onSameConn(t *testing.T, modReq func(*http.Request)) bool { - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - io.WriteString(w, r.RemoteAddr) - }, optOnlyServer, func(c net.Conn, st http.ConnState) { - t.Logf("conn %v is now state %v", c.RemoteAddr(), st) - }) - defer st.Close() - tr := &Transport{TLSClientConfig: tlsConfigInsecure} - defer tr.CloseIdleConnections() - get := func() string { - req, err := http.NewRequest("GET", st.ts.URL, nil) - if err != nil { - t.Fatal(err) - } - modReq(req) - res, err := tr.RoundTrip(req) - if err != nil { - t.Fatal(err) - } - defer res.Body.Close() - slurp, err := ioutil.ReadAll(res.Body) - if err != nil { - t.Fatalf("Body read: %v", err) - } - addr := strings.TrimSpace(string(slurp)) - if addr == "" { - t.Fatalf("didn't get an addr in response") - } - return addr - } - first := get() - second := get() - return first == second -} - -func TestTransportReusesConns(t *testing.T) { - if !onSameConn(t, func(*http.Request) {}) { - t.Errorf("first and second responses were on different connections") - } -} - -func TestTransportReusesConn_RequestClose(t *testing.T) { - if onSameConn(t, func(r *http.Request) { r.Close = true }) { - t.Errorf("first and second responses were not on different connections") - } -} - -func TestTransportReusesConn_ConnClose(t *testing.T) { - if onSameConn(t, func(r *http.Request) { r.Header.Set("Connection", "close") }) { - t.Errorf("first and second responses were not on different connections") - } -} - -// Tests that the Transport only keeps one pending dial open per destination address. -// https://golang.org/issue/13397 -func TestTransportGroupsPendingDials(t *testing.T) { - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - io.WriteString(w, r.RemoteAddr) - }, optOnlyServer) - defer st.Close() - tr := &Transport{ - TLSClientConfig: tlsConfigInsecure, - } - defer tr.CloseIdleConnections() - var ( - mu sync.Mutex - dials = map[string]int{} - ) - var wg sync.WaitGroup - for i := 0; i < 10; i++ { - wg.Add(1) - go func() { - defer wg.Done() - req, err := http.NewRequest("GET", st.ts.URL, nil) - if err != nil { - t.Error(err) - return - } - res, err := tr.RoundTrip(req) - if err != nil { - t.Error(err) - return - } - defer res.Body.Close() - slurp, err := ioutil.ReadAll(res.Body) - if err != nil { - t.Errorf("Body read: %v", err) - } - addr := strings.TrimSpace(string(slurp)) - if addr == "" { - t.Errorf("didn't get an addr in response") - } - mu.Lock() - dials[addr]++ - mu.Unlock() - }() - } - wg.Wait() - if len(dials) != 1 { - t.Errorf("saw %d dials; want 1: %v", len(dials), dials) - } - tr.CloseIdleConnections() - if err := retry(50, 10*time.Millisecond, func() error { - cp, ok := tr.connPool().(*clientConnPool) - if !ok { - return fmt.Errorf("Conn pool is %T; want *clientConnPool", tr.connPool()) - } - cp.mu.Lock() - defer cp.mu.Unlock() - if len(cp.dialing) != 0 { - return fmt.Errorf("dialing map = %v; want empty", cp.dialing) - } - if len(cp.conns) != 0 { - return fmt.Errorf("conns = %v; want empty", cp.conns) - } - if len(cp.keys) != 0 { - return fmt.Errorf("keys = %v; want empty", cp.keys) - } - return nil - }); err != nil { - t.Errorf("State of pool after CloseIdleConnections: %v", err) - } -} - -func retry(tries int, delay time.Duration, fn func() error) error { - var err error - for i := 0; i < tries; i++ { - err = fn() - if err == nil { - return nil - } - time.Sleep(delay) - } - return err -} - -func TestTransportAbortClosesPipes(t *testing.T) { - shutdown := make(chan struct{}) - st := newServerTester(t, - func(w http.ResponseWriter, r *http.Request) { - w.(http.Flusher).Flush() - <-shutdown - }, - optOnlyServer, - ) - defer st.Close() - defer close(shutdown) // we must shutdown before st.Close() to avoid hanging - - done := make(chan struct{}) - requestMade := make(chan struct{}) - go func() { - defer close(done) - tr := &Transport{TLSClientConfig: tlsConfigInsecure} - req, err := http.NewRequest("GET", st.ts.URL, nil) - if err != nil { - t.Fatal(err) - } - res, err := tr.RoundTrip(req) - if err != nil { - t.Fatal(err) - } - defer res.Body.Close() - close(requestMade) - _, err = ioutil.ReadAll(res.Body) - if err == nil { - t.Error("expected error from res.Body.Read") - } - }() - - <-requestMade - // Now force the serve loop to end, via closing the connection. - st.closeConn() - // deadlock? that's a bug. - select { - case <-done: - case <-time.After(3 * time.Second): - t.Fatal("timeout") - } -} - -// TODO: merge this with TestTransportBody to make TestTransportRequest? This -// could be a table-driven test with extra goodies. -func TestTransportPath(t *testing.T) { - gotc := make(chan *url.URL, 1) - st := newServerTester(t, - func(w http.ResponseWriter, r *http.Request) { - gotc <- r.URL - }, - optOnlyServer, - ) - defer st.Close() - - tr := &Transport{TLSClientConfig: tlsConfigInsecure} - defer tr.CloseIdleConnections() - const ( - path = "/testpath" - query = "q=1" - ) - surl := st.ts.URL + path + "?" + query - req, err := http.NewRequest("POST", surl, nil) - if err != nil { - t.Fatal(err) - } - c := &http.Client{Transport: tr} - res, err := c.Do(req) - if err != nil { - t.Fatal(err) - } - defer res.Body.Close() - got := <-gotc - if got.Path != path { - t.Errorf("Read Path = %q; want %q", got.Path, path) - } - if got.RawQuery != query { - t.Errorf("Read RawQuery = %q; want %q", got.RawQuery, query) - } -} - -func randString(n int) string { - rnd := rand.New(rand.NewSource(int64(n))) - b := make([]byte, n) - for i := range b { - b[i] = byte(rnd.Intn(256)) - } - return string(b) -} - -type panicReader struct{} - -func (panicReader) Read([]byte) (int, error) { panic("unexpected Read") } -func (panicReader) Close() error { panic("unexpected Close") } - -func TestActualContentLength(t *testing.T) { - tests := []struct { - req *http.Request - want int64 - }{ - // Verify we don't read from Body: - 0: { - req: &http.Request{Body: panicReader{}}, - want: -1, - }, - // nil Body means 0, regardless of ContentLength: - 1: { - req: &http.Request{Body: nil, ContentLength: 5}, - want: 0, - }, - // ContentLength is used if set. - 2: { - req: &http.Request{Body: panicReader{}, ContentLength: 5}, - want: 5, - }, - // http.NoBody means 0, not -1. - 3: { - req: &http.Request{Body: http.NoBody}, - want: 0, - }, - } - for i, tt := range tests { - got := actualContentLength(tt.req) - if got != tt.want { - t.Errorf("test[%d]: got %d; want %d", i, got, tt.want) - } - } -} - -func TestTransportBody(t *testing.T) { - bodyTests := []struct { - body string - noContentLen bool - }{ - {body: "some message"}, - {body: "some message", noContentLen: true}, - {body: strings.Repeat("a", 1<<20), noContentLen: true}, - {body: strings.Repeat("a", 1<<20)}, - {body: randString(16<<10 - 1)}, - {body: randString(16 << 10)}, - {body: randString(16<<10 + 1)}, - {body: randString(512<<10 - 1)}, - {body: randString(512 << 10)}, - {body: randString(512<<10 + 1)}, - {body: randString(1<<20 - 1)}, - {body: randString(1 << 20)}, - {body: randString(1<<20 + 2)}, - } - - type reqInfo struct { - req *http.Request - slurp []byte - err error - } - gotc := make(chan reqInfo, 1) - st := newServerTester(t, - func(w http.ResponseWriter, r *http.Request) { - slurp, err := ioutil.ReadAll(r.Body) - if err != nil { - gotc <- reqInfo{err: err} - } else { - gotc <- reqInfo{req: r, slurp: slurp} - } - }, - optOnlyServer, - ) - defer st.Close() - - for i, tt := range bodyTests { - tr := &Transport{TLSClientConfig: tlsConfigInsecure} - defer tr.CloseIdleConnections() - - var body io.Reader = strings.NewReader(tt.body) - if tt.noContentLen { - body = struct{ io.Reader }{body} // just a Reader, hiding concrete type and other methods - } - req, err := http.NewRequest("POST", st.ts.URL, body) - if err != nil { - t.Fatalf("#%d: %v", i, err) - } - c := &http.Client{Transport: tr} - res, err := c.Do(req) - if err != nil { - t.Fatalf("#%d: %v", i, err) - } - defer res.Body.Close() - ri := <-gotc - if ri.err != nil { - t.Errorf("#%d: read error: %v", i, ri.err) - continue - } - if got := string(ri.slurp); got != tt.body { - t.Errorf("#%d: Read body mismatch.\n got: %q (len %d)\nwant: %q (len %d)", i, shortString(got), len(got), shortString(tt.body), len(tt.body)) - } - wantLen := int64(len(tt.body)) - if tt.noContentLen && tt.body != "" { - wantLen = -1 - } - if ri.req.ContentLength != wantLen { - t.Errorf("#%d. handler got ContentLength = %v; want %v", i, ri.req.ContentLength, wantLen) - } - } -} - -func shortString(v string) string { - const maxLen = 100 - if len(v) <= maxLen { - return v - } - return fmt.Sprintf("%v[...%d bytes omitted...]%v", v[:maxLen/2], len(v)-maxLen, v[len(v)-maxLen/2:]) -} - -func TestTransportDialTLS(t *testing.T) { - var mu sync.Mutex // guards following - var gotReq, didDial bool - - ts := newServerTester(t, - func(w http.ResponseWriter, r *http.Request) { - mu.Lock() - gotReq = true - mu.Unlock() - }, - optOnlyServer, - ) - defer ts.Close() - tr := &Transport{ - DialTLS: func(netw, addr string, cfg *tls.Config) (net.Conn, error) { - mu.Lock() - didDial = true - mu.Unlock() - cfg.InsecureSkipVerify = true - c, err := tls.Dial(netw, addr, cfg) - if err != nil { - return nil, err - } - return c, c.Handshake() - }, - } - defer tr.CloseIdleConnections() - client := &http.Client{Transport: tr} - res, err := client.Get(ts.ts.URL) - if err != nil { - t.Fatal(err) - } - res.Body.Close() - mu.Lock() - if !gotReq { - t.Error("didn't get request") - } - if !didDial { - t.Error("didn't use dial hook") - } -} - -func TestConfigureTransport(t *testing.T) { - t1 := &http.Transport{} - err := ConfigureTransport(t1) - if err != nil { - t.Fatal(err) - } - if got := fmt.Sprintf("%#v", t1); !strings.Contains(got, `"h2"`) { - // Laziness, to avoid buildtags. - t.Errorf("stringification of HTTP/1 transport didn't contain \"h2\": %v", got) - } - wantNextProtos := []string{"h2", "http/1.1"} - if t1.TLSClientConfig == nil { - t.Errorf("nil t1.TLSClientConfig") - } else if !reflect.DeepEqual(t1.TLSClientConfig.NextProtos, wantNextProtos) { - t.Errorf("TLSClientConfig.NextProtos = %q; want %q", t1.TLSClientConfig.NextProtos, wantNextProtos) - } - if err := ConfigureTransport(t1); err == nil { - t.Error("unexpected success on second call to ConfigureTransport") - } - - // And does it work? - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - io.WriteString(w, r.Proto) - }, optOnlyServer) - defer st.Close() - - t1.TLSClientConfig.InsecureSkipVerify = true - c := &http.Client{Transport: t1} - res, err := c.Get(st.ts.URL) - if err != nil { - t.Fatal(err) - } - slurp, err := ioutil.ReadAll(res.Body) - if err != nil { - t.Fatal(err) - } - if got, want := string(slurp), "HTTP/2.0"; got != want { - t.Errorf("body = %q; want %q", got, want) - } -} - -type capitalizeReader struct { - r io.Reader -} - -func (cr capitalizeReader) Read(p []byte) (n int, err error) { - n, err = cr.r.Read(p) - for i, b := range p[:n] { - if b >= 'a' && b <= 'z' { - p[i] = b - ('a' - 'A') - } - } - return -} - -type flushWriter struct { - w io.Writer -} - -func (fw flushWriter) Write(p []byte) (n int, err error) { - n, err = fw.w.Write(p) - if f, ok := fw.w.(http.Flusher); ok { - f.Flush() - } - return -} - -type clientTester struct { - t *testing.T - tr *Transport - sc, cc net.Conn // server and client conn - fr *Framer // server's framer - client func() error - server func() error -} - -func newClientTester(t *testing.T) *clientTester { - var dialOnce struct { - sync.Mutex - dialed bool - } - ct := &clientTester{ - t: t, - } - ct.tr = &Transport{ - TLSClientConfig: tlsConfigInsecure, - DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) { - dialOnce.Lock() - defer dialOnce.Unlock() - if dialOnce.dialed { - return nil, errors.New("only one dial allowed in test mode") - } - dialOnce.dialed = true - return ct.cc, nil - }, - } - - ln := newLocalListener(t) - cc, err := net.Dial("tcp", ln.Addr().String()) - if err != nil { - t.Fatal(err) - - } - sc, err := ln.Accept() - if err != nil { - t.Fatal(err) - } - ln.Close() - ct.cc = cc - ct.sc = sc - ct.fr = NewFramer(sc, sc) - return ct -} - -func newLocalListener(t *testing.T) net.Listener { - ln, err := net.Listen("tcp4", "127.0.0.1:0") - if err == nil { - return ln - } - ln, err = net.Listen("tcp6", "[::1]:0") - if err != nil { - t.Fatal(err) - } - return ln -} - -func (ct *clientTester) greet(settings ...Setting) { - buf := make([]byte, len(ClientPreface)) - _, err := io.ReadFull(ct.sc, buf) - if err != nil { - ct.t.Fatalf("reading client preface: %v", err) - } - f, err := ct.fr.ReadFrame() - if err != nil { - ct.t.Fatalf("Reading client settings frame: %v", err) - } - if sf, ok := f.(*SettingsFrame); !ok { - ct.t.Fatalf("Wanted client settings frame; got %v", f) - _ = sf // stash it away? - } - if err := ct.fr.WriteSettings(settings...); err != nil { - ct.t.Fatal(err) - } - if err := ct.fr.WriteSettingsAck(); err != nil { - ct.t.Fatal(err) - } -} - -func (ct *clientTester) readNonSettingsFrame() (Frame, error) { - for { - f, err := ct.fr.ReadFrame() - if err != nil { - return nil, err - } - if _, ok := f.(*SettingsFrame); ok { - continue - } - return f, nil - } -} - -func (ct *clientTester) cleanup() { - ct.tr.CloseIdleConnections() -} - -func (ct *clientTester) run() { - errc := make(chan error, 2) - ct.start("client", errc, ct.client) - ct.start("server", errc, ct.server) - defer ct.cleanup() - for i := 0; i < 2; i++ { - if err := <-errc; err != nil { - ct.t.Error(err) - return - } - } -} - -func (ct *clientTester) start(which string, errc chan<- error, fn func() error) { - go func() { - finished := false - var err error - defer func() { - if !finished { - err = fmt.Errorf("%s goroutine didn't finish.", which) - } else if err != nil { - err = fmt.Errorf("%s: %v", which, err) - } - errc <- err - }() - err = fn() - finished = true - }() -} - -func (ct *clientTester) readFrame() (Frame, error) { - return readFrameTimeout(ct.fr, 2*time.Second) -} - -func (ct *clientTester) firstHeaders() (*HeadersFrame, error) { - for { - f, err := ct.readFrame() - if err != nil { - return nil, fmt.Errorf("ReadFrame while waiting for Headers: %v", err) - } - switch f.(type) { - case *WindowUpdateFrame, *SettingsFrame: - continue - } - hf, ok := f.(*HeadersFrame) - if !ok { - return nil, fmt.Errorf("Got %T; want HeadersFrame", f) - } - return hf, nil - } -} - -type countingReader struct { - n *int64 -} - -func (r countingReader) Read(p []byte) (n int, err error) { - for i := range p { - p[i] = byte(i) - } - atomic.AddInt64(r.n, int64(len(p))) - return len(p), err -} - -func TestTransportReqBodyAfterResponse_200(t *testing.T) { testTransportReqBodyAfterResponse(t, 200) } -func TestTransportReqBodyAfterResponse_403(t *testing.T) { testTransportReqBodyAfterResponse(t, 403) } - -func testTransportReqBodyAfterResponse(t *testing.T, status int) { - const bodySize = 10 << 20 - clientDone := make(chan struct{}) - ct := newClientTester(t) - ct.client = func() error { - defer ct.cc.(*net.TCPConn).CloseWrite() - defer close(clientDone) - - var n int64 // atomic - req, err := http.NewRequest("PUT", "https://dummy.tld/", io.LimitReader(countingReader{&n}, bodySize)) - if err != nil { - return err - } - res, err := ct.tr.RoundTrip(req) - if err != nil { - return fmt.Errorf("RoundTrip: %v", err) - } - defer res.Body.Close() - if res.StatusCode != status { - return fmt.Errorf("status code = %v; want %v", res.StatusCode, status) - } - slurp, err := ioutil.ReadAll(res.Body) - if err != nil { - return fmt.Errorf("Slurp: %v", err) - } - if len(slurp) > 0 { - return fmt.Errorf("unexpected body: %q", slurp) - } - if status == 200 { - if got := atomic.LoadInt64(&n); got != bodySize { - return fmt.Errorf("For 200 response, Transport wrote %d bytes; want %d", got, bodySize) - } - } else { - if got := atomic.LoadInt64(&n); got == 0 || got >= bodySize { - return fmt.Errorf("For %d response, Transport wrote %d bytes; want (0,%d) exclusive", status, got, bodySize) - } - } - return nil - } - ct.server = func() error { - ct.greet() - var buf bytes.Buffer - enc := hpack.NewEncoder(&buf) - var dataRecv int64 - var closed bool - for { - f, err := ct.fr.ReadFrame() - if err != nil { - select { - case <-clientDone: - // If the client's done, it - // will have reported any - // errors on its side. - return nil - default: - return err - } - } - //println(fmt.Sprintf("server got frame: %v", f)) - switch f := f.(type) { - case *WindowUpdateFrame, *SettingsFrame: - case *HeadersFrame: - if !f.HeadersEnded() { - return fmt.Errorf("headers should have END_HEADERS be ended: %v", f) - } - if f.StreamEnded() { - return fmt.Errorf("headers contains END_STREAM unexpectedly: %v", f) - } - case *DataFrame: - dataLen := len(f.Data()) - if dataLen > 0 { - if dataRecv == 0 { - enc.WriteField(hpack.HeaderField{Name: ":status", Value: strconv.Itoa(status)}) - ct.fr.WriteHeaders(HeadersFrameParam{ - StreamID: f.StreamID, - EndHeaders: true, - EndStream: false, - BlockFragment: buf.Bytes(), - }) - } - if err := ct.fr.WriteWindowUpdate(0, uint32(dataLen)); err != nil { - return err - } - if err := ct.fr.WriteWindowUpdate(f.StreamID, uint32(dataLen)); err != nil { - return err - } - } - dataRecv += int64(dataLen) - - if !closed && ((status != 200 && dataRecv > 0) || - (status == 200 && dataRecv == bodySize)) { - closed = true - if err := ct.fr.WriteData(f.StreamID, true, nil); err != nil { - return err - } - } - default: - return fmt.Errorf("Unexpected client frame %v", f) - } - } - } - ct.run() -} - -// See golang.org/issue/13444 -func TestTransportFullDuplex(t *testing.T) { - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(200) // redundant but for clarity - w.(http.Flusher).Flush() - io.Copy(flushWriter{w}, capitalizeReader{r.Body}) - fmt.Fprintf(w, "bye.\n") - }, optOnlyServer) - defer st.Close() - - tr := &Transport{TLSClientConfig: tlsConfigInsecure} - defer tr.CloseIdleConnections() - c := &http.Client{Transport: tr} - - pr, pw := io.Pipe() - req, err := http.NewRequest("PUT", st.ts.URL, ioutil.NopCloser(pr)) - if err != nil { - t.Fatal(err) - } - req.ContentLength = -1 - res, err := c.Do(req) - if err != nil { - t.Fatal(err) - } - defer res.Body.Close() - if res.StatusCode != 200 { - t.Fatalf("StatusCode = %v; want %v", res.StatusCode, 200) - } - bs := bufio.NewScanner(res.Body) - want := func(v string) { - if !bs.Scan() { - t.Fatalf("wanted to read %q but Scan() = false, err = %v", v, bs.Err()) - } - } - write := func(v string) { - _, err := io.WriteString(pw, v) - if err != nil { - t.Fatalf("pipe write: %v", err) - } - } - write("foo\n") - want("FOO") - write("bar\n") - want("BAR") - pw.Close() - want("bye.") - if err := bs.Err(); err != nil { - t.Fatal(err) - } -} - -func TestTransportConnectRequest(t *testing.T) { - gotc := make(chan *http.Request, 1) - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - gotc <- r - }, optOnlyServer) - defer st.Close() - - u, err := url.Parse(st.ts.URL) - if err != nil { - t.Fatal(err) - } - - tr := &Transport{TLSClientConfig: tlsConfigInsecure} - defer tr.CloseIdleConnections() - c := &http.Client{Transport: tr} - - tests := []struct { - req *http.Request - want string - }{ - { - req: &http.Request{ - Method: "CONNECT", - Header: http.Header{}, - URL: u, - }, - want: u.Host, - }, - { - req: &http.Request{ - Method: "CONNECT", - Header: http.Header{}, - URL: u, - Host: "example.com:123", - }, - want: "example.com:123", - }, - } - - for i, tt := range tests { - res, err := c.Do(tt.req) - if err != nil { - t.Errorf("%d. RoundTrip = %v", i, err) - continue - } - res.Body.Close() - req := <-gotc - if req.Method != "CONNECT" { - t.Errorf("method = %q; want CONNECT", req.Method) - } - if req.Host != tt.want { - t.Errorf("Host = %q; want %q", req.Host, tt.want) - } - if req.URL.Host != tt.want { - t.Errorf("URL.Host = %q; want %q", req.URL.Host, tt.want) - } - } -} - -type headerType int - -const ( - noHeader headerType = iota // omitted - oneHeader - splitHeader // broken into continuation on purpose -) - -const ( - f0 = noHeader - f1 = oneHeader - f2 = splitHeader - d0 = false - d1 = true -) - -// Test all 36 combinations of response frame orders: -// (3 ways of 100-continue) * (2 ways of headers) * (2 ways of data) * (3 ways of trailers):func TestTransportResponsePattern_00f0(t *testing.T) { testTransportResponsePattern(h0, h1, false, h0) } -// Generated by http://play.golang.org/p/SScqYKJYXd -func TestTransportResPattern_c0h1d0t0(t *testing.T) { testTransportResPattern(t, f0, f1, d0, f0) } -func TestTransportResPattern_c0h1d0t1(t *testing.T) { testTransportResPattern(t, f0, f1, d0, f1) } -func TestTransportResPattern_c0h1d0t2(t *testing.T) { testTransportResPattern(t, f0, f1, d0, f2) } -func TestTransportResPattern_c0h1d1t0(t *testing.T) { testTransportResPattern(t, f0, f1, d1, f0) } -func TestTransportResPattern_c0h1d1t1(t *testing.T) { testTransportResPattern(t, f0, f1, d1, f1) } -func TestTransportResPattern_c0h1d1t2(t *testing.T) { testTransportResPattern(t, f0, f1, d1, f2) } -func TestTransportResPattern_c0h2d0t0(t *testing.T) { testTransportResPattern(t, f0, f2, d0, f0) } -func TestTransportResPattern_c0h2d0t1(t *testing.T) { testTransportResPattern(t, f0, f2, d0, f1) } -func TestTransportResPattern_c0h2d0t2(t *testing.T) { testTransportResPattern(t, f0, f2, d0, f2) } -func TestTransportResPattern_c0h2d1t0(t *testing.T) { testTransportResPattern(t, f0, f2, d1, f0) } -func TestTransportResPattern_c0h2d1t1(t *testing.T) { testTransportResPattern(t, f0, f2, d1, f1) } -func TestTransportResPattern_c0h2d1t2(t *testing.T) { testTransportResPattern(t, f0, f2, d1, f2) } -func TestTransportResPattern_c1h1d0t0(t *testing.T) { testTransportResPattern(t, f1, f1, d0, f0) } -func TestTransportResPattern_c1h1d0t1(t *testing.T) { testTransportResPattern(t, f1, f1, d0, f1) } -func TestTransportResPattern_c1h1d0t2(t *testing.T) { testTransportResPattern(t, f1, f1, d0, f2) } -func TestTransportResPattern_c1h1d1t0(t *testing.T) { testTransportResPattern(t, f1, f1, d1, f0) } -func TestTransportResPattern_c1h1d1t1(t *testing.T) { testTransportResPattern(t, f1, f1, d1, f1) } -func TestTransportResPattern_c1h1d1t2(t *testing.T) { testTransportResPattern(t, f1, f1, d1, f2) } -func TestTransportResPattern_c1h2d0t0(t *testing.T) { testTransportResPattern(t, f1, f2, d0, f0) } -func TestTransportResPattern_c1h2d0t1(t *testing.T) { testTransportResPattern(t, f1, f2, d0, f1) } -func TestTransportResPattern_c1h2d0t2(t *testing.T) { testTransportResPattern(t, f1, f2, d0, f2) } -func TestTransportResPattern_c1h2d1t0(t *testing.T) { testTransportResPattern(t, f1, f2, d1, f0) } -func TestTransportResPattern_c1h2d1t1(t *testing.T) { testTransportResPattern(t, f1, f2, d1, f1) } -func TestTransportResPattern_c1h2d1t2(t *testing.T) { testTransportResPattern(t, f1, f2, d1, f2) } -func TestTransportResPattern_c2h1d0t0(t *testing.T) { testTransportResPattern(t, f2, f1, d0, f0) } -func TestTransportResPattern_c2h1d0t1(t *testing.T) { testTransportResPattern(t, f2, f1, d0, f1) } -func TestTransportResPattern_c2h1d0t2(t *testing.T) { testTransportResPattern(t, f2, f1, d0, f2) } -func TestTransportResPattern_c2h1d1t0(t *testing.T) { testTransportResPattern(t, f2, f1, d1, f0) } -func TestTransportResPattern_c2h1d1t1(t *testing.T) { testTransportResPattern(t, f2, f1, d1, f1) } -func TestTransportResPattern_c2h1d1t2(t *testing.T) { testTransportResPattern(t, f2, f1, d1, f2) } -func TestTransportResPattern_c2h2d0t0(t *testing.T) { testTransportResPattern(t, f2, f2, d0, f0) } -func TestTransportResPattern_c2h2d0t1(t *testing.T) { testTransportResPattern(t, f2, f2, d0, f1) } -func TestTransportResPattern_c2h2d0t2(t *testing.T) { testTransportResPattern(t, f2, f2, d0, f2) } -func TestTransportResPattern_c2h2d1t0(t *testing.T) { testTransportResPattern(t, f2, f2, d1, f0) } -func TestTransportResPattern_c2h2d1t1(t *testing.T) { testTransportResPattern(t, f2, f2, d1, f1) } -func TestTransportResPattern_c2h2d1t2(t *testing.T) { testTransportResPattern(t, f2, f2, d1, f2) } - -func testTransportResPattern(t *testing.T, expect100Continue, resHeader headerType, withData bool, trailers headerType) { - const reqBody = "some request body" - const resBody = "some response body" - - if resHeader == noHeader { - // TODO: test 100-continue followed by immediate - // server stream reset, without headers in the middle? - panic("invalid combination") - } - - ct := newClientTester(t) - ct.client = func() error { - req, _ := http.NewRequest("POST", "https://dummy.tld/", strings.NewReader(reqBody)) - if expect100Continue != noHeader { - req.Header.Set("Expect", "100-continue") - } - res, err := ct.tr.RoundTrip(req) - if err != nil { - return fmt.Errorf("RoundTrip: %v", err) - } - defer res.Body.Close() - if res.StatusCode != 200 { - return fmt.Errorf("status code = %v; want 200", res.StatusCode) - } - slurp, err := ioutil.ReadAll(res.Body) - if err != nil { - return fmt.Errorf("Slurp: %v", err) - } - wantBody := resBody - if !withData { - wantBody = "" - } - if string(slurp) != wantBody { - return fmt.Errorf("body = %q; want %q", slurp, wantBody) - } - if trailers == noHeader { - if len(res.Trailer) > 0 { - t.Errorf("Trailer = %v; want none", res.Trailer) - } - } else { - want := http.Header{"Some-Trailer": {"some-value"}} - if !reflect.DeepEqual(res.Trailer, want) { - t.Errorf("Trailer = %v; want %v", res.Trailer, want) - } - } - return nil - } - ct.server = func() error { - ct.greet() - var buf bytes.Buffer - enc := hpack.NewEncoder(&buf) - - for { - f, err := ct.fr.ReadFrame() - if err != nil { - return err - } - endStream := false - send := func(mode headerType) { - hbf := buf.Bytes() - switch mode { - case oneHeader: - ct.fr.WriteHeaders(HeadersFrameParam{ - StreamID: f.Header().StreamID, - EndHeaders: true, - EndStream: endStream, - BlockFragment: hbf, - }) - case splitHeader: - if len(hbf) < 2 { - panic("too small") - } - ct.fr.WriteHeaders(HeadersFrameParam{ - StreamID: f.Header().StreamID, - EndHeaders: false, - EndStream: endStream, - BlockFragment: hbf[:1], - }) - ct.fr.WriteContinuation(f.Header().StreamID, true, hbf[1:]) - default: - panic("bogus mode") - } - } - switch f := f.(type) { - case *WindowUpdateFrame, *SettingsFrame: - case *DataFrame: - if !f.StreamEnded() { - // No need to send flow control tokens. The test request body is tiny. - continue - } - // Response headers (1+ frames; 1 or 2 in this test, but never 0) - { - buf.Reset() - enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) - enc.WriteField(hpack.HeaderField{Name: "x-foo", Value: "blah"}) - enc.WriteField(hpack.HeaderField{Name: "x-bar", Value: "more"}) - if trailers != noHeader { - enc.WriteField(hpack.HeaderField{Name: "trailer", Value: "some-trailer"}) - } - endStream = withData == false && trailers == noHeader - send(resHeader) - } - if withData { - endStream = trailers == noHeader - ct.fr.WriteData(f.StreamID, endStream, []byte(resBody)) - } - if trailers != noHeader { - endStream = true - buf.Reset() - enc.WriteField(hpack.HeaderField{Name: "some-trailer", Value: "some-value"}) - send(trailers) - } - if endStream { - return nil - } - case *HeadersFrame: - if expect100Continue != noHeader { - buf.Reset() - enc.WriteField(hpack.HeaderField{Name: ":status", Value: "100"}) - send(expect100Continue) - } - } - } - } - ct.run() -} - -// Issue 26189, Issue 17739: ignore unknown 1xx responses -func TestTransportUnknown1xx(t *testing.T) { - var buf bytes.Buffer - defer func() { got1xxFuncForTests = nil }() - got1xxFuncForTests = func(code int, header textproto.MIMEHeader) error { - fmt.Fprintf(&buf, "code=%d header=%v\n", code, header) - return nil - } - - ct := newClientTester(t) - ct.client = func() error { - req, _ := http.NewRequest("GET", "https://dummy.tld/", nil) - res, err := ct.tr.RoundTrip(req) - if err != nil { - return fmt.Errorf("RoundTrip: %v", err) - } - defer res.Body.Close() - if res.StatusCode != 204 { - return fmt.Errorf("status code = %v; want 204", res.StatusCode) - } - want := `code=110 header=map[Foo-Bar:[110]] -code=111 header=map[Foo-Bar:[111]] -code=112 header=map[Foo-Bar:[112]] -code=113 header=map[Foo-Bar:[113]] -code=114 header=map[Foo-Bar:[114]] -` - if got := buf.String(); got != want { - t.Errorf("Got trace:\n%s\nWant:\n%s", got, want) - } - return nil - } - ct.server = func() error { - ct.greet() - var buf bytes.Buffer - enc := hpack.NewEncoder(&buf) - - for { - f, err := ct.fr.ReadFrame() - if err != nil { - return err - } - switch f := f.(type) { - case *WindowUpdateFrame, *SettingsFrame: - case *HeadersFrame: - for i := 110; i <= 114; i++ { - buf.Reset() - enc.WriteField(hpack.HeaderField{Name: ":status", Value: fmt.Sprint(i)}) - enc.WriteField(hpack.HeaderField{Name: "foo-bar", Value: fmt.Sprint(i)}) - ct.fr.WriteHeaders(HeadersFrameParam{ - StreamID: f.StreamID, - EndHeaders: true, - EndStream: false, - BlockFragment: buf.Bytes(), - }) - } - buf.Reset() - enc.WriteField(hpack.HeaderField{Name: ":status", Value: "204"}) - ct.fr.WriteHeaders(HeadersFrameParam{ - StreamID: f.StreamID, - EndHeaders: true, - EndStream: false, - BlockFragment: buf.Bytes(), - }) - return nil - } - } - } - ct.run() - -} - -func TestTransportReceiveUndeclaredTrailer(t *testing.T) { - ct := newClientTester(t) - ct.client = func() error { - req, _ := http.NewRequest("GET", "https://dummy.tld/", nil) - res, err := ct.tr.RoundTrip(req) - if err != nil { - return fmt.Errorf("RoundTrip: %v", err) - } - defer res.Body.Close() - if res.StatusCode != 200 { - return fmt.Errorf("status code = %v; want 200", res.StatusCode) - } - slurp, err := ioutil.ReadAll(res.Body) - if err != nil { - return fmt.Errorf("res.Body ReadAll error = %q, %v; want %v", slurp, err, nil) - } - if len(slurp) > 0 { - return fmt.Errorf("body = %q; want nothing", slurp) - } - if _, ok := res.Trailer["Some-Trailer"]; !ok { - return fmt.Errorf("expected Some-Trailer") - } - return nil - } - ct.server = func() error { - ct.greet() - - var n int - var hf *HeadersFrame - for hf == nil && n < 10 { - f, err := ct.fr.ReadFrame() - if err != nil { - return err - } - hf, _ = f.(*HeadersFrame) - n++ - } - - var buf bytes.Buffer - enc := hpack.NewEncoder(&buf) - - // send headers without Trailer header - enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) - ct.fr.WriteHeaders(HeadersFrameParam{ - StreamID: hf.StreamID, - EndHeaders: true, - EndStream: false, - BlockFragment: buf.Bytes(), - }) - - // send trailers - buf.Reset() - enc.WriteField(hpack.HeaderField{Name: "some-trailer", Value: "I'm an undeclared Trailer!"}) - ct.fr.WriteHeaders(HeadersFrameParam{ - StreamID: hf.StreamID, - EndHeaders: true, - EndStream: true, - BlockFragment: buf.Bytes(), - }) - return nil - } - ct.run() -} - -func TestTransportInvalidTrailer_Pseudo1(t *testing.T) { - testTransportInvalidTrailer_Pseudo(t, oneHeader) -} -func TestTransportInvalidTrailer_Pseudo2(t *testing.T) { - testTransportInvalidTrailer_Pseudo(t, splitHeader) -} -func testTransportInvalidTrailer_Pseudo(t *testing.T, trailers headerType) { - testInvalidTrailer(t, trailers, pseudoHeaderError(":colon"), func(enc *hpack.Encoder) { - enc.WriteField(hpack.HeaderField{Name: ":colon", Value: "foo"}) - enc.WriteField(hpack.HeaderField{Name: "foo", Value: "bar"}) - }) -} - -func TestTransportInvalidTrailer_Capital1(t *testing.T) { - testTransportInvalidTrailer_Capital(t, oneHeader) -} -func TestTransportInvalidTrailer_Capital2(t *testing.T) { - testTransportInvalidTrailer_Capital(t, splitHeader) -} -func testTransportInvalidTrailer_Capital(t *testing.T, trailers headerType) { - testInvalidTrailer(t, trailers, headerFieldNameError("Capital"), func(enc *hpack.Encoder) { - enc.WriteField(hpack.HeaderField{Name: "foo", Value: "bar"}) - enc.WriteField(hpack.HeaderField{Name: "Capital", Value: "bad"}) - }) -} -func TestTransportInvalidTrailer_EmptyFieldName(t *testing.T) { - testInvalidTrailer(t, oneHeader, headerFieldNameError(""), func(enc *hpack.Encoder) { - enc.WriteField(hpack.HeaderField{Name: "", Value: "bad"}) - }) -} -func TestTransportInvalidTrailer_BinaryFieldValue(t *testing.T) { - testInvalidTrailer(t, oneHeader, headerFieldValueError("has\nnewline"), func(enc *hpack.Encoder) { - enc.WriteField(hpack.HeaderField{Name: "x", Value: "has\nnewline"}) - }) -} - -func testInvalidTrailer(t *testing.T, trailers headerType, wantErr error, writeTrailer func(*hpack.Encoder)) { - ct := newClientTester(t) - ct.client = func() error { - req, _ := http.NewRequest("GET", "https://dummy.tld/", nil) - res, err := ct.tr.RoundTrip(req) - if err != nil { - return fmt.Errorf("RoundTrip: %v", err) - } - defer res.Body.Close() - if res.StatusCode != 200 { - return fmt.Errorf("status code = %v; want 200", res.StatusCode) - } - slurp, err := ioutil.ReadAll(res.Body) - se, ok := err.(StreamError) - if !ok || se.Cause != wantErr { - return fmt.Errorf("res.Body ReadAll error = %q, %#v; want StreamError with cause %T, %#v", slurp, err, wantErr, wantErr) - } - if len(slurp) > 0 { - return fmt.Errorf("body = %q; want nothing", slurp) - } - return nil - } - ct.server = func() error { - ct.greet() - var buf bytes.Buffer - enc := hpack.NewEncoder(&buf) - - for { - f, err := ct.fr.ReadFrame() - if err != nil { - return err - } - switch f := f.(type) { - case *HeadersFrame: - var endStream bool - send := func(mode headerType) { - hbf := buf.Bytes() - switch mode { - case oneHeader: - ct.fr.WriteHeaders(HeadersFrameParam{ - StreamID: f.StreamID, - EndHeaders: true, - EndStream: endStream, - BlockFragment: hbf, - }) - case splitHeader: - if len(hbf) < 2 { - panic("too small") - } - ct.fr.WriteHeaders(HeadersFrameParam{ - StreamID: f.StreamID, - EndHeaders: false, - EndStream: endStream, - BlockFragment: hbf[:1], - }) - ct.fr.WriteContinuation(f.StreamID, true, hbf[1:]) - default: - panic("bogus mode") - } - } - // Response headers (1+ frames; 1 or 2 in this test, but never 0) - { - buf.Reset() - enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) - enc.WriteField(hpack.HeaderField{Name: "trailer", Value: "declared"}) - endStream = false - send(oneHeader) - } - // Trailers: - { - endStream = true - buf.Reset() - writeTrailer(enc) - send(trailers) - } - return nil - } - } - } - ct.run() -} - -// headerListSize returns the HTTP2 header list size of h. -// http://httpwg.org/specs/rfc7540.html#SETTINGS_MAX_HEADER_LIST_SIZE -// http://httpwg.org/specs/rfc7540.html#MaxHeaderBlock -func headerListSize(h http.Header) (size uint32) { - for k, vv := range h { - for _, v := range vv { - hf := hpack.HeaderField{Name: k, Value: v} - size += hf.Size() - } - } - return size -} - -// padHeaders adds data to an http.Header until headerListSize(h) == -// limit. Due to the way header list sizes are calculated, padHeaders -// cannot add fewer than len("Pad-Headers") + 32 bytes to h, and will -// call t.Fatal if asked to do so. PadHeaders first reserves enough -// space for an empty "Pad-Headers" key, then adds as many copies of -// filler as possible. Any remaining bytes necessary to push the -// header list size up to limit are added to h["Pad-Headers"]. -func padHeaders(t *testing.T, h http.Header, limit uint64, filler string) { - if limit > 0xffffffff { - t.Fatalf("padHeaders: refusing to pad to more than 2^32-1 bytes. limit = %v", limit) - } - hf := hpack.HeaderField{Name: "Pad-Headers", Value: ""} - minPadding := uint64(hf.Size()) - size := uint64(headerListSize(h)) - - minlimit := size + minPadding - if limit < minlimit { - t.Fatalf("padHeaders: limit %v < %v", limit, minlimit) - } - - // Use a fixed-width format for name so that fieldSize - // remains constant. - nameFmt := "Pad-Headers-%06d" - hf = hpack.HeaderField{Name: fmt.Sprintf(nameFmt, 1), Value: filler} - fieldSize := uint64(hf.Size()) - - // Add as many complete filler values as possible, leaving - // room for at least one empty "Pad-Headers" key. - limit = limit - minPadding - for i := 0; size+fieldSize < limit; i++ { - name := fmt.Sprintf(nameFmt, i) - h.Add(name, filler) - size += fieldSize - } - - // Add enough bytes to reach limit. - remain := limit - size - lastValue := strings.Repeat("*", int(remain)) - h.Add("Pad-Headers", lastValue) -} - -func TestPadHeaders(t *testing.T) { - check := func(h http.Header, limit uint32, fillerLen int) { - if h == nil { - h = make(http.Header) - } - filler := strings.Repeat("f", fillerLen) - padHeaders(t, h, uint64(limit), filler) - gotSize := headerListSize(h) - if gotSize != limit { - t.Errorf("Got size = %v; want %v", gotSize, limit) - } - } - // Try all possible combinations for small fillerLen and limit. - hf := hpack.HeaderField{Name: "Pad-Headers", Value: ""} - minLimit := hf.Size() - for limit := minLimit; limit <= 128; limit++ { - for fillerLen := 0; uint32(fillerLen) <= limit; fillerLen++ { - check(nil, limit, fillerLen) - } - } - - // Try a few tests with larger limits, plus cumulative - // tests. Since these tests are cumulative, tests[i+1].limit - // must be >= tests[i].limit + minLimit. See the comment on - // padHeaders for more info on why the limit arg has this - // restriction. - tests := []struct { - fillerLen int - limit uint32 - }{ - { - fillerLen: 64, - limit: 1024, - }, - { - fillerLen: 1024, - limit: 1286, - }, - { - fillerLen: 256, - limit: 2048, - }, - { - fillerLen: 1024, - limit: 10 * 1024, - }, - { - fillerLen: 1023, - limit: 11 * 1024, - }, - } - h := make(http.Header) - for _, tc := range tests { - check(nil, tc.limit, tc.fillerLen) - check(h, tc.limit, tc.fillerLen) - } -} - -func TestTransportChecksRequestHeaderListSize(t *testing.T) { - st := newServerTester(t, - func(w http.ResponseWriter, r *http.Request) { - // Consume body & force client to send - // trailers before writing response. - // ioutil.ReadAll returns non-nil err for - // requests that attempt to send greater than - // maxHeaderListSize bytes of trailers, since - // those requests generate a stream reset. - ioutil.ReadAll(r.Body) - r.Body.Close() - }, - func(ts *httptest.Server) { - ts.Config.MaxHeaderBytes = 16 << 10 - }, - optOnlyServer, - optQuiet, - ) - defer st.Close() - - tr := &Transport{TLSClientConfig: tlsConfigInsecure} - defer tr.CloseIdleConnections() - - checkRoundTrip := func(req *http.Request, wantErr error, desc string) { - res, err := tr.RoundTrip(req) - if err != wantErr { - if res != nil { - res.Body.Close() - } - t.Errorf("%v: RoundTrip err = %v; want %v", desc, err, wantErr) - return - } - if err == nil { - if res == nil { - t.Errorf("%v: response nil; want non-nil.", desc) - return - } - defer res.Body.Close() - if res.StatusCode != http.StatusOK { - t.Errorf("%v: response status = %v; want %v", desc, res.StatusCode, http.StatusOK) - } - return - } - if res != nil { - t.Errorf("%v: RoundTrip err = %v but response non-nil", desc, err) - } - } - headerListSizeForRequest := func(req *http.Request) (size uint64) { - contentLen := actualContentLength(req) - trailers, err := commaSeparatedTrailers(req) - if err != nil { - t.Fatalf("headerListSizeForRequest: %v", err) - } - cc := &ClientConn{peerMaxHeaderListSize: 0xffffffffffffffff} - cc.henc = hpack.NewEncoder(&cc.hbuf) - cc.mu.Lock() - hdrs, err := cc.encodeHeaders(req, true, trailers, contentLen) - cc.mu.Unlock() - if err != nil { - t.Fatalf("headerListSizeForRequest: %v", err) - } - hpackDec := hpack.NewDecoder(initialHeaderTableSize, func(hf hpack.HeaderField) { - size += uint64(hf.Size()) - }) - if len(hdrs) > 0 { - if _, err := hpackDec.Write(hdrs); err != nil { - t.Fatalf("headerListSizeForRequest: %v", err) - } - } - return size - } - // Create a new Request for each test, rather than reusing the - // same Request, to avoid a race when modifying req.Headers. - // See https://github.com/golang/go/issues/21316 - newRequest := func() *http.Request { - // Body must be non-nil to enable writing trailers. - body := strings.NewReader("hello") - req, err := http.NewRequest("POST", st.ts.URL, body) - if err != nil { - t.Fatalf("newRequest: NewRequest: %v", err) - } - return req - } - - // Make an arbitrary request to ensure we get the server's - // settings frame and initialize peerMaxHeaderListSize. - req := newRequest() - checkRoundTrip(req, nil, "Initial request") - - // Get the ClientConn associated with the request and validate - // peerMaxHeaderListSize. - addr := authorityAddr(req.URL.Scheme, req.URL.Host) - cc, err := tr.connPool().GetClientConn(req, addr) - if err != nil { - t.Fatalf("GetClientConn: %v", err) - } - cc.mu.Lock() - peerSize := cc.peerMaxHeaderListSize - cc.mu.Unlock() - st.scMu.Lock() - wantSize := uint64(st.sc.maxHeaderListSize()) - st.scMu.Unlock() - if peerSize != wantSize { - t.Errorf("peerMaxHeaderListSize = %v; want %v", peerSize, wantSize) - } - - // Sanity check peerSize. (*serverConn) maxHeaderListSize adds - // 320 bytes of padding. - wantHeaderBytes := uint64(st.ts.Config.MaxHeaderBytes) + 320 - if peerSize != wantHeaderBytes { - t.Errorf("peerMaxHeaderListSize = %v; want %v.", peerSize, wantHeaderBytes) - } - - // Pad headers & trailers, but stay under peerSize. - req = newRequest() - req.Header = make(http.Header) - req.Trailer = make(http.Header) - filler := strings.Repeat("*", 1024) - padHeaders(t, req.Trailer, peerSize, filler) - // cc.encodeHeaders adds some default headers to the request, - // so we need to leave room for those. - defaultBytes := headerListSizeForRequest(req) - padHeaders(t, req.Header, peerSize-defaultBytes, filler) - checkRoundTrip(req, nil, "Headers & Trailers under limit") - - // Add enough header bytes to push us over peerSize. - req = newRequest() - req.Header = make(http.Header) - padHeaders(t, req.Header, peerSize, filler) - checkRoundTrip(req, errRequestHeaderListSize, "Headers over limit") - - // Push trailers over the limit. - req = newRequest() - req.Trailer = make(http.Header) - padHeaders(t, req.Trailer, peerSize+1, filler) - checkRoundTrip(req, errRequestHeaderListSize, "Trailers over limit") - - // Send headers with a single large value. - req = newRequest() - filler = strings.Repeat("*", int(peerSize)) - req.Header = make(http.Header) - req.Header.Set("Big", filler) - checkRoundTrip(req, errRequestHeaderListSize, "Single large header") - - // Send trailers with a single large value. - req = newRequest() - req.Trailer = make(http.Header) - req.Trailer.Set("Big", filler) - checkRoundTrip(req, errRequestHeaderListSize, "Single large trailer") -} - -func TestTransportChecksResponseHeaderListSize(t *testing.T) { - ct := newClientTester(t) - ct.client = func() error { - req, _ := http.NewRequest("GET", "https://dummy.tld/", nil) - res, err := ct.tr.RoundTrip(req) - if err != errResponseHeaderListSize { - if res != nil { - res.Body.Close() - } - size := int64(0) - for k, vv := range res.Header { - for _, v := range vv { - size += int64(len(k)) + int64(len(v)) + 32 - } - } - return fmt.Errorf("RoundTrip Error = %v (and %d bytes of response headers); want errResponseHeaderListSize", err, size) - } - return nil - } - ct.server = func() error { - ct.greet() - var buf bytes.Buffer - enc := hpack.NewEncoder(&buf) - - for { - f, err := ct.fr.ReadFrame() - if err != nil { - return err - } - switch f := f.(type) { - case *HeadersFrame: - enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) - large := strings.Repeat("a", 1<<10) - for i := 0; i < 5042; i++ { - enc.WriteField(hpack.HeaderField{Name: large, Value: large}) - } - if size, want := buf.Len(), 6329; size != want { - // Note: this number might change if - // our hpack implementation - // changes. That's fine. This is - // just a sanity check that our - // response can fit in a single - // header block fragment frame. - return fmt.Errorf("encoding over 10MB of duplicate keypairs took %d bytes; expected %d", size, want) - } - ct.fr.WriteHeaders(HeadersFrameParam{ - StreamID: f.StreamID, - EndHeaders: true, - EndStream: true, - BlockFragment: buf.Bytes(), - }) - return nil - } - } - } - ct.run() -} - -// Test that the Transport returns a typed error from Response.Body.Read calls -// when the server sends an error. (here we use a panic, since that should generate -// a stream error, but others like cancel should be similar) -func TestTransportBodyReadErrorType(t *testing.T) { - doPanic := make(chan bool, 1) - st := newServerTester(t, - func(w http.ResponseWriter, r *http.Request) { - w.(http.Flusher).Flush() // force headers out - <-doPanic - panic("boom") - }, - optOnlyServer, - optQuiet, - ) - defer st.Close() - - tr := &Transport{TLSClientConfig: tlsConfigInsecure} - defer tr.CloseIdleConnections() - c := &http.Client{Transport: tr} - - res, err := c.Get(st.ts.URL) - if err != nil { - t.Fatal(err) - } - defer res.Body.Close() - doPanic <- true - buf := make([]byte, 100) - n, err := res.Body.Read(buf) - want := StreamError{StreamID: 0x1, Code: 0x2} - if !reflect.DeepEqual(want, err) { - t.Errorf("Read = %v, %#v; want error %#v", n, err, want) - } -} - -// golang.org/issue/13924 -// This used to fail after many iterations, especially with -race: -// go test -v -run=TestTransportDoubleCloseOnWriteError -count=500 -race -func TestTransportDoubleCloseOnWriteError(t *testing.T) { - var ( - mu sync.Mutex - conn net.Conn // to close if set - ) - - st := newServerTester(t, - func(w http.ResponseWriter, r *http.Request) { - mu.Lock() - defer mu.Unlock() - if conn != nil { - conn.Close() - } - }, - optOnlyServer, - ) - defer st.Close() - - tr := &Transport{ - TLSClientConfig: tlsConfigInsecure, - DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) { - tc, err := tls.Dial(network, addr, cfg) - if err != nil { - return nil, err - } - mu.Lock() - defer mu.Unlock() - conn = tc - return tc, nil - }, - } - defer tr.CloseIdleConnections() - c := &http.Client{Transport: tr} - c.Get(st.ts.URL) -} - -// Test that the http1 Transport.DisableKeepAlives option is respected -// and connections are closed as soon as idle. -// See golang.org/issue/14008 -func TestTransportDisableKeepAlives(t *testing.T) { - st := newServerTester(t, - func(w http.ResponseWriter, r *http.Request) { - io.WriteString(w, "hi") - }, - optOnlyServer, - ) - defer st.Close() - - connClosed := make(chan struct{}) // closed on tls.Conn.Close - tr := &Transport{ - t1: &http.Transport{ - DisableKeepAlives: true, - }, - TLSClientConfig: tlsConfigInsecure, - DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) { - tc, err := tls.Dial(network, addr, cfg) - if err != nil { - return nil, err - } - return ¬eCloseConn{Conn: tc, closefn: func() { close(connClosed) }}, nil - }, - } - c := &http.Client{Transport: tr} - res, err := c.Get(st.ts.URL) - if err != nil { - t.Fatal(err) - } - if _, err := ioutil.ReadAll(res.Body); err != nil { - t.Fatal(err) - } - defer res.Body.Close() - - select { - case <-connClosed: - case <-time.After(1 * time.Second): - t.Errorf("timeout") - } - -} - -// Test concurrent requests with Transport.DisableKeepAlives. We can share connections, -// but when things are totally idle, it still needs to close. -func TestTransportDisableKeepAlives_Concurrency(t *testing.T) { - const D = 25 * time.Millisecond - st := newServerTester(t, - func(w http.ResponseWriter, r *http.Request) { - time.Sleep(D) - io.WriteString(w, "hi") - }, - optOnlyServer, - ) - defer st.Close() - - var dials int32 - var conns sync.WaitGroup - tr := &Transport{ - t1: &http.Transport{ - DisableKeepAlives: true, - }, - TLSClientConfig: tlsConfigInsecure, - DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) { - tc, err := tls.Dial(network, addr, cfg) - if err != nil { - return nil, err - } - atomic.AddInt32(&dials, 1) - conns.Add(1) - return ¬eCloseConn{Conn: tc, closefn: func() { conns.Done() }}, nil - }, - } - c := &http.Client{Transport: tr} - var reqs sync.WaitGroup - const N = 20 - for i := 0; i < N; i++ { - reqs.Add(1) - if i == N-1 { - // For the final request, try to make all the - // others close. This isn't verified in the - // count, other than the Log statement, since - // it's so timing dependent. This test is - // really to make sure we don't interrupt a - // valid request. - time.Sleep(D * 2) - } - go func() { - defer reqs.Done() - res, err := c.Get(st.ts.URL) - if err != nil { - t.Error(err) - return - } - if _, err := ioutil.ReadAll(res.Body); err != nil { - t.Error(err) - return - } - res.Body.Close() - }() - } - reqs.Wait() - conns.Wait() - t.Logf("did %d dials, %d requests", atomic.LoadInt32(&dials), N) -} - -type noteCloseConn struct { - net.Conn - onceClose sync.Once - closefn func() -} - -func (c *noteCloseConn) Close() error { - c.onceClose.Do(c.closefn) - return c.Conn.Close() -} - -func isTimeout(err error) bool { - switch err := err.(type) { - case nil: - return false - case *url.Error: - return isTimeout(err.Err) - case net.Error: - return err.Timeout() - } - return false -} - -// Test that the http1 Transport.ResponseHeaderTimeout option and cancel is sent. -func TestTransportResponseHeaderTimeout_NoBody(t *testing.T) { - testTransportResponseHeaderTimeout(t, false) -} -func TestTransportResponseHeaderTimeout_Body(t *testing.T) { - testTransportResponseHeaderTimeout(t, true) -} - -func testTransportResponseHeaderTimeout(t *testing.T, body bool) { - ct := newClientTester(t) - ct.tr.t1 = &http.Transport{ - ResponseHeaderTimeout: 5 * time.Millisecond, - } - ct.client = func() error { - c := &http.Client{Transport: ct.tr} - var err error - var n int64 - const bodySize = 4 << 20 - if body { - _, err = c.Post("https://dummy.tld/", "text/foo", io.LimitReader(countingReader{&n}, bodySize)) - } else { - _, err = c.Get("https://dummy.tld/") - } - if !isTimeout(err) { - t.Errorf("client expected timeout error; got %#v", err) - } - if body && n != bodySize { - t.Errorf("only read %d bytes of body; want %d", n, bodySize) - } - return nil - } - ct.server = func() error { - ct.greet() - for { - f, err := ct.fr.ReadFrame() - if err != nil { - t.Logf("ReadFrame: %v", err) - return nil - } - switch f := f.(type) { - case *DataFrame: - dataLen := len(f.Data()) - if dataLen > 0 { - if err := ct.fr.WriteWindowUpdate(0, uint32(dataLen)); err != nil { - return err - } - if err := ct.fr.WriteWindowUpdate(f.StreamID, uint32(dataLen)); err != nil { - return err - } - } - case *RSTStreamFrame: - if f.StreamID == 1 && f.ErrCode == ErrCodeCancel { - return nil - } - } - } - } - ct.run() -} - -func TestTransportDisableCompression(t *testing.T) { - const body = "sup" - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - want := http.Header{ - "User-Agent": []string{"Go-http-client/2.0"}, - } - if !reflect.DeepEqual(r.Header, want) { - t.Errorf("request headers = %v; want %v", r.Header, want) - } - }, optOnlyServer) - defer st.Close() - - tr := &Transport{ - TLSClientConfig: tlsConfigInsecure, - t1: &http.Transport{ - DisableCompression: true, - }, - } - defer tr.CloseIdleConnections() - - req, err := http.NewRequest("GET", st.ts.URL, nil) - if err != nil { - t.Fatal(err) - } - res, err := tr.RoundTrip(req) - if err != nil { - t.Fatal(err) - } - defer res.Body.Close() -} - -// RFC 7540 section 8.1.2.2 -func TestTransportRejectsConnHeaders(t *testing.T) { - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - var got []string - for k := range r.Header { - got = append(got, k) - } - sort.Strings(got) - w.Header().Set("Got-Header", strings.Join(got, ",")) - }, optOnlyServer) - defer st.Close() - - tr := &Transport{TLSClientConfig: tlsConfigInsecure} - defer tr.CloseIdleConnections() - - tests := []struct { - key string - value []string - want string - }{ - { - key: "Upgrade", - value: []string{"anything"}, - want: "ERROR: http2: invalid Upgrade request header: [\"anything\"]", - }, - { - key: "Connection", - value: []string{"foo"}, - want: "ERROR: http2: invalid Connection request header: [\"foo\"]", - }, - { - key: "Connection", - value: []string{"close"}, - want: "Accept-Encoding,User-Agent", - }, - { - key: "Connection", - value: []string{"CLoSe"}, - want: "Accept-Encoding,User-Agent", - }, - { - key: "Connection", - value: []string{"close", "something-else"}, - want: "ERROR: http2: invalid Connection request header: [\"close\" \"something-else\"]", - }, - { - key: "Connection", - value: []string{"keep-alive"}, - want: "Accept-Encoding,User-Agent", - }, - { - key: "Connection", - value: []string{"Keep-ALIVE"}, - want: "Accept-Encoding,User-Agent", - }, - { - key: "Proxy-Connection", // just deleted and ignored - value: []string{"keep-alive"}, - want: "Accept-Encoding,User-Agent", - }, - { - key: "Transfer-Encoding", - value: []string{""}, - want: "Accept-Encoding,User-Agent", - }, - { - key: "Transfer-Encoding", - value: []string{"foo"}, - want: "ERROR: http2: invalid Transfer-Encoding request header: [\"foo\"]", - }, - { - key: "Transfer-Encoding", - value: []string{"chunked"}, - want: "Accept-Encoding,User-Agent", - }, - { - key: "Transfer-Encoding", - value: []string{"chunked", "other"}, - want: "ERROR: http2: invalid Transfer-Encoding request header: [\"chunked\" \"other\"]", - }, - { - key: "Content-Length", - value: []string{"123"}, - want: "Accept-Encoding,User-Agent", - }, - { - key: "Keep-Alive", - value: []string{"doop"}, - want: "Accept-Encoding,User-Agent", - }, - } - - for _, tt := range tests { - req, _ := http.NewRequest("GET", st.ts.URL, nil) - req.Header[tt.key] = tt.value - res, err := tr.RoundTrip(req) - var got string - if err != nil { - got = fmt.Sprintf("ERROR: %v", err) - } else { - got = res.Header.Get("Got-Header") - res.Body.Close() - } - if got != tt.want { - t.Errorf("For key %q, value %q, got = %q; want %q", tt.key, tt.value, got, tt.want) - } - } -} - -// golang.org/issue/14048 -func TestTransportFailsOnInvalidHeaders(t *testing.T) { - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - var got []string - for k := range r.Header { - got = append(got, k) - } - sort.Strings(got) - w.Header().Set("Got-Header", strings.Join(got, ",")) - }, optOnlyServer) - defer st.Close() - - tests := [...]struct { - h http.Header - wantErr string - }{ - 0: { - h: http.Header{"with space": {"foo"}}, - wantErr: `invalid HTTP header name "with space"`, - }, - 1: { - h: http.Header{"name": {"Брэд"}}, - wantErr: "", // okay - }, - 2: { - h: http.Header{"имя": {"Brad"}}, - wantErr: `invalid HTTP header name "имя"`, - }, - 3: { - h: http.Header{"foo": {"foo\x01bar"}}, - wantErr: `invalid HTTP header value "foo\x01bar" for header "foo"`, - }, - } - - tr := &Transport{TLSClientConfig: tlsConfigInsecure} - defer tr.CloseIdleConnections() - - for i, tt := range tests { - req, _ := http.NewRequest("GET", st.ts.URL, nil) - req.Header = tt.h - res, err := tr.RoundTrip(req) - var bad bool - if tt.wantErr == "" { - if err != nil { - bad = true - t.Errorf("case %d: error = %v; want no error", i, err) - } - } else { - if !strings.Contains(fmt.Sprint(err), tt.wantErr) { - bad = true - t.Errorf("case %d: error = %v; want error %q", i, err, tt.wantErr) - } - } - if err == nil { - if bad { - t.Logf("case %d: server got headers %q", i, res.Header.Get("Got-Header")) - } - res.Body.Close() - } - } -} - -// Tests that gzipReader doesn't crash on a second Read call following -// the first Read call's gzip.NewReader returning an error. -func TestGzipReader_DoubleReadCrash(t *testing.T) { - gz := &gzipReader{ - body: ioutil.NopCloser(strings.NewReader("0123456789")), - } - var buf [1]byte - n, err1 := gz.Read(buf[:]) - if n != 0 || !strings.Contains(fmt.Sprint(err1), "invalid header") { - t.Fatalf("Read = %v, %v; want 0, invalid header", n, err1) - } - n, err2 := gz.Read(buf[:]) - if n != 0 || err2 != err1 { - t.Fatalf("second Read = %v, %v; want 0, %v", n, err2, err1) - } -} - -func TestTransportNewTLSConfig(t *testing.T) { - tests := [...]struct { - conf *tls.Config - host string - want *tls.Config - }{ - // Normal case. - 0: { - conf: nil, - host: "foo.com", - want: &tls.Config{ - ServerName: "foo.com", - NextProtos: []string{NextProtoTLS}, - }, - }, - - // User-provided name (bar.com) takes precedence: - 1: { - conf: &tls.Config{ - ServerName: "bar.com", - }, - host: "foo.com", - want: &tls.Config{ - ServerName: "bar.com", - NextProtos: []string{NextProtoTLS}, - }, - }, - - // NextProto is prepended: - 2: { - conf: &tls.Config{ - NextProtos: []string{"foo", "bar"}, - }, - host: "example.com", - want: &tls.Config{ - ServerName: "example.com", - NextProtos: []string{NextProtoTLS, "foo", "bar"}, - }, - }, - - // NextProto is not duplicated: - 3: { - conf: &tls.Config{ - NextProtos: []string{"foo", "bar", NextProtoTLS}, - }, - host: "example.com", - want: &tls.Config{ - ServerName: "example.com", - NextProtos: []string{"foo", "bar", NextProtoTLS}, - }, - }, - } - for i, tt := range tests { - // Ignore the session ticket keys part, which ends up populating - // unexported fields in the Config: - if tt.conf != nil { - tt.conf.SessionTicketsDisabled = true - } - - tr := &Transport{TLSClientConfig: tt.conf} - got := tr.newTLSConfig(tt.host) - - got.SessionTicketsDisabled = false - - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("%d. got %#v; want %#v", i, got, tt.want) - } - } -} - -// The Google GFE responds to HEAD requests with a HEADERS frame -// without END_STREAM, followed by a 0-length DATA frame with -// END_STREAM. Make sure we don't get confused by that. (We did.) -func TestTransportReadHeadResponse(t *testing.T) { - ct := newClientTester(t) - clientDone := make(chan struct{}) - ct.client = func() error { - defer close(clientDone) - req, _ := http.NewRequest("HEAD", "https://dummy.tld/", nil) - res, err := ct.tr.RoundTrip(req) - if err != nil { - return err - } - if res.ContentLength != 123 { - return fmt.Errorf("Content-Length = %d; want 123", res.ContentLength) - } - slurp, err := ioutil.ReadAll(res.Body) - if err != nil { - return fmt.Errorf("ReadAll: %v", err) - } - if len(slurp) > 0 { - return fmt.Errorf("Unexpected non-empty ReadAll body: %q", slurp) - } - return nil - } - ct.server = func() error { - ct.greet() - for { - f, err := ct.fr.ReadFrame() - if err != nil { - t.Logf("ReadFrame: %v", err) - return nil - } - hf, ok := f.(*HeadersFrame) - if !ok { - continue - } - var buf bytes.Buffer - enc := hpack.NewEncoder(&buf) - enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) - enc.WriteField(hpack.HeaderField{Name: "content-length", Value: "123"}) - ct.fr.WriteHeaders(HeadersFrameParam{ - StreamID: hf.StreamID, - EndHeaders: true, - EndStream: false, // as the GFE does - BlockFragment: buf.Bytes(), - }) - ct.fr.WriteData(hf.StreamID, true, nil) - - <-clientDone - return nil - } - } - ct.run() -} - -func TestTransportReadHeadResponseWithBody(t *testing.T) { - // This test use not valid response format. - // Discarding logger output to not spam tests output. - log.SetOutput(ioutil.Discard) - defer log.SetOutput(os.Stderr) - - response := "redirecting to /elsewhere" - ct := newClientTester(t) - clientDone := make(chan struct{}) - ct.client = func() error { - defer close(clientDone) - req, _ := http.NewRequest("HEAD", "https://dummy.tld/", nil) - res, err := ct.tr.RoundTrip(req) - if err != nil { - return err - } - if res.ContentLength != int64(len(response)) { - return fmt.Errorf("Content-Length = %d; want %d", res.ContentLength, len(response)) - } - slurp, err := ioutil.ReadAll(res.Body) - if err != nil { - return fmt.Errorf("ReadAll: %v", err) - } - if len(slurp) > 0 { - return fmt.Errorf("Unexpected non-empty ReadAll body: %q", slurp) - } - return nil - } - ct.server = func() error { - ct.greet() - for { - f, err := ct.fr.ReadFrame() - if err != nil { - t.Logf("ReadFrame: %v", err) - return nil - } - hf, ok := f.(*HeadersFrame) - if !ok { - continue - } - var buf bytes.Buffer - enc := hpack.NewEncoder(&buf) - enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) - enc.WriteField(hpack.HeaderField{Name: "content-length", Value: strconv.Itoa(len(response))}) - ct.fr.WriteHeaders(HeadersFrameParam{ - StreamID: hf.StreamID, - EndHeaders: true, - EndStream: false, - BlockFragment: buf.Bytes(), - }) - ct.fr.WriteData(hf.StreamID, true, []byte(response)) - - <-clientDone - return nil - } - } - ct.run() -} - -type neverEnding byte - -func (b neverEnding) Read(p []byte) (int, error) { - for i := range p { - p[i] = byte(b) - } - return len(p), nil -} - -// golang.org/issue/15425: test that a handler closing the request -// body doesn't terminate the stream to the peer. (It just stops -// readability from the handler's side, and eventually the client -// runs out of flow control tokens) -func TestTransportHandlerBodyClose(t *testing.T) { - const bodySize = 10 << 20 - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - r.Body.Close() - io.Copy(w, io.LimitReader(neverEnding('A'), bodySize)) - }, optOnlyServer) - defer st.Close() - - tr := &Transport{TLSClientConfig: tlsConfigInsecure} - defer tr.CloseIdleConnections() - - g0 := runtime.NumGoroutine() - - const numReq = 10 - for i := 0; i < numReq; i++ { - req, err := http.NewRequest("POST", st.ts.URL, struct{ io.Reader }{io.LimitReader(neverEnding('A'), bodySize)}) - if err != nil { - t.Fatal(err) - } - res, err := tr.RoundTrip(req) - if err != nil { - t.Fatal(err) - } - n, err := io.Copy(ioutil.Discard, res.Body) - res.Body.Close() - if n != bodySize || err != nil { - t.Fatalf("req#%d: Copy = %d, %v; want %d, nil", i, n, err, bodySize) - } - } - tr.CloseIdleConnections() - - if !waitCondition(5*time.Second, 100*time.Millisecond, func() bool { - gd := runtime.NumGoroutine() - g0 - return gd < numReq/2 - }) { - t.Errorf("appeared to leak goroutines") - } -} - -// https://golang.org/issue/15930 -func TestTransportFlowControl(t *testing.T) { - const bufLen = 64 << 10 - var total int64 = 100 << 20 // 100MB - if testing.Short() { - total = 10 << 20 - } - - var wrote int64 // updated atomically - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - b := make([]byte, bufLen) - for wrote < total { - n, err := w.Write(b) - atomic.AddInt64(&wrote, int64(n)) - if err != nil { - t.Errorf("ResponseWriter.Write error: %v", err) - break - } - w.(http.Flusher).Flush() - } - }, optOnlyServer) - - tr := &Transport{TLSClientConfig: tlsConfigInsecure} - defer tr.CloseIdleConnections() - req, err := http.NewRequest("GET", st.ts.URL, nil) - if err != nil { - t.Fatal("NewRequest error:", err) - } - resp, err := tr.RoundTrip(req) - if err != nil { - t.Fatal("RoundTrip error:", err) - } - defer resp.Body.Close() - - var read int64 - b := make([]byte, bufLen) - for { - n, err := resp.Body.Read(b) - if err == io.EOF { - break - } - if err != nil { - t.Fatal("Read error:", err) - } - read += int64(n) - - const max = transportDefaultStreamFlow - if w := atomic.LoadInt64(&wrote); -max > read-w || read-w > max { - t.Fatalf("Too much data inflight: server wrote %v bytes but client only received %v", w, read) - } - - // Let the server get ahead of the client. - time.Sleep(1 * time.Millisecond) - } -} - -// golang.org/issue/14627 -- if the server sends a GOAWAY frame, make -// the Transport remember it and return it back to users (via -// RoundTrip or request body reads) if needed (e.g. if the server -// proceeds to close the TCP connection before the client gets its -// response) -func TestTransportUsesGoAwayDebugError_RoundTrip(t *testing.T) { - testTransportUsesGoAwayDebugError(t, false) -} - -func TestTransportUsesGoAwayDebugError_Body(t *testing.T) { - testTransportUsesGoAwayDebugError(t, true) -} - -func testTransportUsesGoAwayDebugError(t *testing.T, failMidBody bool) { - ct := newClientTester(t) - clientDone := make(chan struct{}) - - const goAwayErrCode = ErrCodeHTTP11Required // arbitrary - const goAwayDebugData = "some debug data" - - ct.client = func() error { - defer close(clientDone) - req, _ := http.NewRequest("GET", "https://dummy.tld/", nil) - res, err := ct.tr.RoundTrip(req) - if failMidBody { - if err != nil { - return fmt.Errorf("unexpected client RoundTrip error: %v", err) - } - _, err = io.Copy(ioutil.Discard, res.Body) - res.Body.Close() - } - want := GoAwayError{ - LastStreamID: 5, - ErrCode: goAwayErrCode, - DebugData: goAwayDebugData, - } - if !reflect.DeepEqual(err, want) { - t.Errorf("RoundTrip error = %T: %#v, want %T (%#v)", err, err, want, want) - } - return nil - } - ct.server = func() error { - ct.greet() - for { - f, err := ct.fr.ReadFrame() - if err != nil { - t.Logf("ReadFrame: %v", err) - return nil - } - hf, ok := f.(*HeadersFrame) - if !ok { - continue - } - if failMidBody { - var buf bytes.Buffer - enc := hpack.NewEncoder(&buf) - enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) - enc.WriteField(hpack.HeaderField{Name: "content-length", Value: "123"}) - ct.fr.WriteHeaders(HeadersFrameParam{ - StreamID: hf.StreamID, - EndHeaders: true, - EndStream: false, - BlockFragment: buf.Bytes(), - }) - } - // Write two GOAWAY frames, to test that the Transport takes - // the interesting parts of both. - ct.fr.WriteGoAway(5, ErrCodeNo, []byte(goAwayDebugData)) - ct.fr.WriteGoAway(5, goAwayErrCode, nil) - ct.sc.(*net.TCPConn).CloseWrite() - <-clientDone - return nil - } - } - ct.run() -} - -func testTransportReturnsUnusedFlowControl(t *testing.T, oneDataFrame bool) { - ct := newClientTester(t) - - clientClosed := make(chan struct{}) - serverWroteFirstByte := make(chan struct{}) - - ct.client = func() error { - req, _ := http.NewRequest("GET", "https://dummy.tld/", nil) - res, err := ct.tr.RoundTrip(req) - if err != nil { - return err - } - <-serverWroteFirstByte - - if n, err := res.Body.Read(make([]byte, 1)); err != nil || n != 1 { - return fmt.Errorf("body read = %v, %v; want 1, nil", n, err) - } - res.Body.Close() // leaving 4999 bytes unread - close(clientClosed) - - return nil - } - ct.server = func() error { - ct.greet() - - var hf *HeadersFrame - for { - f, err := ct.fr.ReadFrame() - if err != nil { - return fmt.Errorf("ReadFrame while waiting for Headers: %v", err) - } - switch f.(type) { - case *WindowUpdateFrame, *SettingsFrame: - continue - } - var ok bool - hf, ok = f.(*HeadersFrame) - if !ok { - return fmt.Errorf("Got %T; want HeadersFrame", f) - } - break - } - - var buf bytes.Buffer - enc := hpack.NewEncoder(&buf) - enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) - enc.WriteField(hpack.HeaderField{Name: "content-length", Value: "5000"}) - ct.fr.WriteHeaders(HeadersFrameParam{ - StreamID: hf.StreamID, - EndHeaders: true, - EndStream: false, - BlockFragment: buf.Bytes(), - }) - - // Two cases: - // - Send one DATA frame with 5000 bytes. - // - Send two DATA frames with 1 and 4999 bytes each. - // - // In both cases, the client should consume one byte of data, - // refund that byte, then refund the following 4999 bytes. - // - // In the second case, the server waits for the client connection to - // close before seconding the second DATA frame. This tests the case - // where the client receives a DATA frame after it has reset the stream. - if oneDataFrame { - ct.fr.WriteData(hf.StreamID, false /* don't end stream */, make([]byte, 5000)) - close(serverWroteFirstByte) - <-clientClosed - } else { - ct.fr.WriteData(hf.StreamID, false /* don't end stream */, make([]byte, 1)) - close(serverWroteFirstByte) - <-clientClosed - ct.fr.WriteData(hf.StreamID, false /* don't end stream */, make([]byte, 4999)) - } - - waitingFor := "RSTStreamFrame" - for { - f, err := ct.fr.ReadFrame() - if err != nil { - return fmt.Errorf("ReadFrame while waiting for %s: %v", waitingFor, err) - } - if _, ok := f.(*SettingsFrame); ok { - continue - } - switch waitingFor { - case "RSTStreamFrame": - if rf, ok := f.(*RSTStreamFrame); !ok || rf.ErrCode != ErrCodeCancel { - return fmt.Errorf("Expected a RSTStreamFrame with code cancel; got %v", summarizeFrame(f)) - } - waitingFor = "WindowUpdateFrame" - case "WindowUpdateFrame": - if wuf, ok := f.(*WindowUpdateFrame); !ok || wuf.Increment != 4999 { - return fmt.Errorf("Expected WindowUpdateFrame for 4999 bytes; got %v", summarizeFrame(f)) - } - return nil - } - } - } - ct.run() -} - -// See golang.org/issue/16481 -func TestTransportReturnsUnusedFlowControlSingleWrite(t *testing.T) { - testTransportReturnsUnusedFlowControl(t, true) -} - -// See golang.org/issue/20469 -func TestTransportReturnsUnusedFlowControlMultipleWrites(t *testing.T) { - testTransportReturnsUnusedFlowControl(t, false) -} - -// Issue 16612: adjust flow control on open streams when transport -// receives SETTINGS with INITIAL_WINDOW_SIZE from server. -func TestTransportAdjustsFlowControl(t *testing.T) { - ct := newClientTester(t) - clientDone := make(chan struct{}) - - const bodySize = 1 << 20 - - ct.client = func() error { - defer ct.cc.(*net.TCPConn).CloseWrite() - defer close(clientDone) - - req, _ := http.NewRequest("POST", "https://dummy.tld/", struct{ io.Reader }{io.LimitReader(neverEnding('A'), bodySize)}) - res, err := ct.tr.RoundTrip(req) - if err != nil { - return err - } - res.Body.Close() - return nil - } - ct.server = func() error { - _, err := io.ReadFull(ct.sc, make([]byte, len(ClientPreface))) - if err != nil { - return fmt.Errorf("reading client preface: %v", err) - } - - var gotBytes int64 - var sentSettings bool - for { - f, err := ct.fr.ReadFrame() - if err != nil { - select { - case <-clientDone: - return nil - default: - return fmt.Errorf("ReadFrame while waiting for Headers: %v", err) - } - } - switch f := f.(type) { - case *DataFrame: - gotBytes += int64(len(f.Data())) - // After we've got half the client's - // initial flow control window's worth - // of request body data, give it just - // enough flow control to finish. - if gotBytes >= initialWindowSize/2 && !sentSettings { - sentSettings = true - - ct.fr.WriteSettings(Setting{ID: SettingInitialWindowSize, Val: bodySize}) - ct.fr.WriteWindowUpdate(0, bodySize) - ct.fr.WriteSettingsAck() - } - - if f.StreamEnded() { - var buf bytes.Buffer - enc := hpack.NewEncoder(&buf) - enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) - ct.fr.WriteHeaders(HeadersFrameParam{ - StreamID: f.StreamID, - EndHeaders: true, - EndStream: true, - BlockFragment: buf.Bytes(), - }) - } - } - } - } - ct.run() -} - -// See golang.org/issue/16556 -func TestTransportReturnsDataPaddingFlowControl(t *testing.T) { - ct := newClientTester(t) - - unblockClient := make(chan bool, 1) - - ct.client = func() error { - req, _ := http.NewRequest("GET", "https://dummy.tld/", nil) - res, err := ct.tr.RoundTrip(req) - if err != nil { - return err - } - defer res.Body.Close() - <-unblockClient - return nil - } - ct.server = func() error { - ct.greet() - - var hf *HeadersFrame - for { - f, err := ct.fr.ReadFrame() - if err != nil { - return fmt.Errorf("ReadFrame while waiting for Headers: %v", err) - } - switch f.(type) { - case *WindowUpdateFrame, *SettingsFrame: - continue - } - var ok bool - hf, ok = f.(*HeadersFrame) - if !ok { - return fmt.Errorf("Got %T; want HeadersFrame", f) - } - break - } - - var buf bytes.Buffer - enc := hpack.NewEncoder(&buf) - enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) - enc.WriteField(hpack.HeaderField{Name: "content-length", Value: "5000"}) - ct.fr.WriteHeaders(HeadersFrameParam{ - StreamID: hf.StreamID, - EndHeaders: true, - EndStream: false, - BlockFragment: buf.Bytes(), - }) - pad := make([]byte, 5) - ct.fr.WriteDataPadded(hf.StreamID, false, make([]byte, 5000), pad) // without ending stream - - f, err := ct.readNonSettingsFrame() - if err != nil { - return fmt.Errorf("ReadFrame while waiting for first WindowUpdateFrame: %v", err) - } - wantBack := uint32(len(pad)) + 1 // one byte for the length of the padding - if wuf, ok := f.(*WindowUpdateFrame); !ok || wuf.Increment != wantBack || wuf.StreamID != 0 { - return fmt.Errorf("Expected conn WindowUpdateFrame for %d bytes; got %v", wantBack, summarizeFrame(f)) - } - - f, err = ct.readNonSettingsFrame() - if err != nil { - return fmt.Errorf("ReadFrame while waiting for second WindowUpdateFrame: %v", err) - } - if wuf, ok := f.(*WindowUpdateFrame); !ok || wuf.Increment != wantBack || wuf.StreamID == 0 { - return fmt.Errorf("Expected stream WindowUpdateFrame for %d bytes; got %v", wantBack, summarizeFrame(f)) - } - unblockClient <- true - return nil - } - ct.run() -} - -// golang.org/issue/16572 -- RoundTrip shouldn't hang when it gets a -// StreamError as a result of the response HEADERS -func TestTransportReturnsErrorOnBadResponseHeaders(t *testing.T) { - ct := newClientTester(t) - - ct.client = func() error { - req, _ := http.NewRequest("GET", "https://dummy.tld/", nil) - res, err := ct.tr.RoundTrip(req) - if err == nil { - res.Body.Close() - return errors.New("unexpected successful GET") - } - want := StreamError{1, ErrCodeProtocol, headerFieldNameError(" content-type")} - if !reflect.DeepEqual(want, err) { - t.Errorf("RoundTrip error = %#v; want %#v", err, want) - } - return nil - } - ct.server = func() error { - ct.greet() - - hf, err := ct.firstHeaders() - if err != nil { - return err - } - - var buf bytes.Buffer - enc := hpack.NewEncoder(&buf) - enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) - enc.WriteField(hpack.HeaderField{Name: " content-type", Value: "bogus"}) // bogus spaces - ct.fr.WriteHeaders(HeadersFrameParam{ - StreamID: hf.StreamID, - EndHeaders: true, - EndStream: false, - BlockFragment: buf.Bytes(), - }) - - for { - fr, err := ct.readFrame() - if err != nil { - return fmt.Errorf("error waiting for RST_STREAM from client: %v", err) - } - if _, ok := fr.(*SettingsFrame); ok { - continue - } - if rst, ok := fr.(*RSTStreamFrame); !ok || rst.StreamID != 1 || rst.ErrCode != ErrCodeProtocol { - t.Errorf("Frame = %v; want RST_STREAM for stream 1 with ErrCodeProtocol", summarizeFrame(fr)) - } - break - } - - return nil - } - ct.run() -} - -// byteAndEOFReader returns is in an io.Reader which reads one byte -// (the underlying byte) and io.EOF at once in its Read call. -type byteAndEOFReader byte - -func (b byteAndEOFReader) Read(p []byte) (n int, err error) { - if len(p) == 0 { - panic("unexpected useless call") - } - p[0] = byte(b) - return 1, io.EOF -} - -// Issue 16788: the Transport had a regression where it started -// sending a spurious DATA frame with a duplicate END_STREAM bit after -// the request body writer goroutine had already read an EOF from the -// Request.Body and included the END_STREAM on a data-carrying DATA -// frame. -// -// Notably, to trigger this, the requests need to use a Request.Body -// which returns (non-0, io.EOF) and also needs to set the ContentLength -// explicitly. -func TestTransportBodyDoubleEndStream(t *testing.T) { - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - // Nothing. - }, optOnlyServer) - defer st.Close() - - tr := &Transport{TLSClientConfig: tlsConfigInsecure} - defer tr.CloseIdleConnections() - - for i := 0; i < 2; i++ { - req, _ := http.NewRequest("POST", st.ts.URL, byteAndEOFReader('a')) - req.ContentLength = 1 - res, err := tr.RoundTrip(req) - if err != nil { - t.Fatalf("failure on req %d: %v", i+1, err) - } - defer res.Body.Close() - } -} - -// golang.org/issue/16847, golang.org/issue/19103 -func TestTransportRequestPathPseudo(t *testing.T) { - type result struct { - path string - err string - } - tests := []struct { - req *http.Request - want result - }{ - 0: { - req: &http.Request{ - Method: "GET", - URL: &url.URL{ - Host: "foo.com", - Path: "/foo", - }, - }, - want: result{path: "/foo"}, - }, - // In Go 1.7, we accepted paths of "//foo". - // In Go 1.8, we rejected it (issue 16847). - // In Go 1.9, we accepted it again (issue 19103). - 1: { - req: &http.Request{ - Method: "GET", - URL: &url.URL{ - Host: "foo.com", - Path: "//foo", - }, - }, - want: result{path: "//foo"}, - }, - - // Opaque with //$Matching_Hostname/path - 2: { - req: &http.Request{ - Method: "GET", - URL: &url.URL{ - Scheme: "https", - Opaque: "//foo.com/path", - Host: "foo.com", - Path: "/ignored", - }, - }, - want: result{path: "/path"}, - }, - - // Opaque with some other Request.Host instead: - 3: { - req: &http.Request{ - Method: "GET", - Host: "bar.com", - URL: &url.URL{ - Scheme: "https", - Opaque: "//bar.com/path", - Host: "foo.com", - Path: "/ignored", - }, - }, - want: result{path: "/path"}, - }, - - // Opaque without the leading "//": - 4: { - req: &http.Request{ - Method: "GET", - URL: &url.URL{ - Opaque: "/path", - Host: "foo.com", - Path: "/ignored", - }, - }, - want: result{path: "/path"}, - }, - - // Opaque we can't handle: - 5: { - req: &http.Request{ - Method: "GET", - URL: &url.URL{ - Scheme: "https", - Opaque: "//unknown_host/path", - Host: "foo.com", - Path: "/ignored", - }, - }, - want: result{err: `invalid request :path "https://unknown_host/path" from URL.Opaque = "//unknown_host/path"`}, - }, - - // A CONNECT request: - 6: { - req: &http.Request{ - Method: "CONNECT", - URL: &url.URL{ - Host: "foo.com", - }, - }, - want: result{}, - }, - } - for i, tt := range tests { - cc := &ClientConn{peerMaxHeaderListSize: 0xffffffffffffffff} - cc.henc = hpack.NewEncoder(&cc.hbuf) - cc.mu.Lock() - hdrs, err := cc.encodeHeaders(tt.req, false, "", -1) - cc.mu.Unlock() - var got result - hpackDec := hpack.NewDecoder(initialHeaderTableSize, func(f hpack.HeaderField) { - if f.Name == ":path" { - got.path = f.Value - } - }) - if err != nil { - got.err = err.Error() - } else if len(hdrs) > 0 { - if _, err := hpackDec.Write(hdrs); err != nil { - t.Errorf("%d. bogus hpack: %v", i, err) - continue - } - } - if got != tt.want { - t.Errorf("%d. got %+v; want %+v", i, got, tt.want) - } - - } - -} - -// golang.org/issue/17071 -- don't sniff the first byte of the request body -// before we've determined that the ClientConn is usable. -func TestRoundTripDoesntConsumeRequestBodyEarly(t *testing.T) { - const body = "foo" - req, _ := http.NewRequest("POST", "http://foo.com/", ioutil.NopCloser(strings.NewReader(body))) - cc := &ClientConn{ - closed: true, - } - _, err := cc.RoundTrip(req) - if err != errClientConnUnusable { - t.Fatalf("RoundTrip = %v; want errClientConnUnusable", err) - } - slurp, err := ioutil.ReadAll(req.Body) - if err != nil { - t.Errorf("ReadAll = %v", err) - } - if string(slurp) != body { - t.Errorf("Body = %q; want %q", slurp, body) - } -} - -func TestClientConnPing(t *testing.T) { - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {}, optOnlyServer) - defer st.Close() - tr := &Transport{TLSClientConfig: tlsConfigInsecure} - defer tr.CloseIdleConnections() - cc, err := tr.dialClientConn(st.ts.Listener.Addr().String(), false) - if err != nil { - t.Fatal(err) - } - if err = cc.Ping(context.Background()); err != nil { - t.Fatal(err) - } -} - -// Issue 16974: if the server sent a DATA frame after the user -// canceled the Transport's Request, the Transport previously wrote to a -// closed pipe, got an error, and ended up closing the whole TCP -// connection. -func TestTransportCancelDataResponseRace(t *testing.T) { - cancel := make(chan struct{}) - clientGotError := make(chan bool, 1) - - const msg = "Hello." - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - if strings.Contains(r.URL.Path, "/hello") { - time.Sleep(50 * time.Millisecond) - io.WriteString(w, msg) - return - } - for i := 0; i < 50; i++ { - io.WriteString(w, "Some data.") - w.(http.Flusher).Flush() - if i == 2 { - close(cancel) - <-clientGotError - } - time.Sleep(10 * time.Millisecond) - } - }, optOnlyServer) - defer st.Close() - - tr := &Transport{TLSClientConfig: tlsConfigInsecure} - defer tr.CloseIdleConnections() - - c := &http.Client{Transport: tr} - req, _ := http.NewRequest("GET", st.ts.URL, nil) - req.Cancel = cancel - res, err := c.Do(req) - if err != nil { - t.Fatal(err) - } - if _, err = io.Copy(ioutil.Discard, res.Body); err == nil { - t.Fatal("unexpected success") - } - clientGotError <- true - - res, err = c.Get(st.ts.URL + "/hello") - if err != nil { - t.Fatal(err) - } - slurp, err := ioutil.ReadAll(res.Body) - if err != nil { - t.Fatal(err) - } - if string(slurp) != msg { - t.Errorf("Got = %q; want %q", slurp, msg) - } -} - -// Issue 21316: It should be safe to reuse an http.Request after the -// request has completed. -func TestTransportNoRaceOnRequestObjectAfterRequestComplete(t *testing.T) { - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(200) - io.WriteString(w, "body") - }, optOnlyServer) - defer st.Close() - - tr := &Transport{TLSClientConfig: tlsConfigInsecure} - defer tr.CloseIdleConnections() - - req, _ := http.NewRequest("GET", st.ts.URL, nil) - resp, err := tr.RoundTrip(req) - if err != nil { - t.Fatal(err) - } - if _, err = io.Copy(ioutil.Discard, resp.Body); err != nil { - t.Fatalf("error reading response body: %v", err) - } - if err := resp.Body.Close(); err != nil { - t.Fatalf("error closing response body: %v", err) - } - - // This access of req.Header should not race with code in the transport. - req.Header = http.Header{} -} - -func TestTransportRetryAfterGOAWAY(t *testing.T) { - var dialer struct { - sync.Mutex - count int - } - ct1 := make(chan *clientTester) - ct2 := make(chan *clientTester) - - ln := newLocalListener(t) - defer ln.Close() - - tr := &Transport{ - TLSClientConfig: tlsConfigInsecure, - } - tr.DialTLS = func(network, addr string, cfg *tls.Config) (net.Conn, error) { - dialer.Lock() - defer dialer.Unlock() - dialer.count++ - if dialer.count == 3 { - return nil, errors.New("unexpected number of dials") - } - cc, err := net.Dial("tcp", ln.Addr().String()) - if err != nil { - return nil, fmt.Errorf("dial error: %v", err) - } - sc, err := ln.Accept() - if err != nil { - return nil, fmt.Errorf("accept error: %v", err) - } - ct := &clientTester{ - t: t, - tr: tr, - cc: cc, - sc: sc, - fr: NewFramer(sc, sc), - } - switch dialer.count { - case 1: - ct1 <- ct - case 2: - ct2 <- ct - } - return cc, nil - } - - errs := make(chan error, 3) - done := make(chan struct{}) - defer close(done) - - // Client. - go func() { - req, _ := http.NewRequest("GET", "https://dummy.tld/", nil) - res, err := tr.RoundTrip(req) - if res != nil { - res.Body.Close() - if got := res.Header.Get("Foo"); got != "bar" { - err = fmt.Errorf("foo header = %q; want bar", got) - } - } - if err != nil { - err = fmt.Errorf("RoundTrip: %v", err) - } - errs <- err - }() - - connToClose := make(chan io.Closer, 2) - - // Server for the first request. - go func() { - var ct *clientTester - select { - case ct = <-ct1: - case <-done: - return - } - - connToClose <- ct.cc - ct.greet() - hf, err := ct.firstHeaders() - if err != nil { - errs <- fmt.Errorf("server1 failed reading HEADERS: %v", err) - return - } - t.Logf("server1 got %v", hf) - if err := ct.fr.WriteGoAway(0 /*max id*/, ErrCodeNo, nil); err != nil { - errs <- fmt.Errorf("server1 failed writing GOAWAY: %v", err) - return - } - errs <- nil - }() - - // Server for the second request. - go func() { - var ct *clientTester - select { - case ct = <-ct2: - case <-done: - return - } - - connToClose <- ct.cc - ct.greet() - hf, err := ct.firstHeaders() - if err != nil { - errs <- fmt.Errorf("server2 failed reading HEADERS: %v", err) - return - } - t.Logf("server2 got %v", hf) - - var buf bytes.Buffer - enc := hpack.NewEncoder(&buf) - enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) - enc.WriteField(hpack.HeaderField{Name: "foo", Value: "bar"}) - err = ct.fr.WriteHeaders(HeadersFrameParam{ - StreamID: hf.StreamID, - EndHeaders: true, - EndStream: false, - BlockFragment: buf.Bytes(), - }) - if err != nil { - errs <- fmt.Errorf("server2 failed writing response HEADERS: %v", err) - } else { - errs <- nil - } - }() - - for k := 0; k < 3; k++ { - select { - case err := <-errs: - if err != nil { - t.Error(err) - } - case <-time.After(1 * time.Second): - t.Errorf("timed out") - } - } - - for { - select { - case c := <-connToClose: - c.Close() - default: - return - } - } -} - -func TestTransportRetryAfterRefusedStream(t *testing.T) { - clientDone := make(chan struct{}) - ct := newClientTester(t) - ct.client = func() error { - defer ct.cc.(*net.TCPConn).CloseWrite() - defer close(clientDone) - req, _ := http.NewRequest("GET", "https://dummy.tld/", nil) - resp, err := ct.tr.RoundTrip(req) - if err != nil { - return fmt.Errorf("RoundTrip: %v", err) - } - resp.Body.Close() - if resp.StatusCode != 204 { - return fmt.Errorf("Status = %v; want 204", resp.StatusCode) - } - return nil - } - ct.server = func() error { - ct.greet() - var buf bytes.Buffer - enc := hpack.NewEncoder(&buf) - nreq := 0 - - for { - f, err := ct.fr.ReadFrame() - if err != nil { - select { - case <-clientDone: - // If the client's done, it - // will have reported any - // errors on its side. - return nil - default: - return err - } - } - switch f := f.(type) { - case *WindowUpdateFrame, *SettingsFrame: - case *HeadersFrame: - if !f.HeadersEnded() { - return fmt.Errorf("headers should have END_HEADERS be ended: %v", f) - } - nreq++ - if nreq == 1 { - ct.fr.WriteRSTStream(f.StreamID, ErrCodeRefusedStream) - } else { - enc.WriteField(hpack.HeaderField{Name: ":status", Value: "204"}) - ct.fr.WriteHeaders(HeadersFrameParam{ - StreamID: f.StreamID, - EndHeaders: true, - EndStream: true, - BlockFragment: buf.Bytes(), - }) - } - default: - return fmt.Errorf("Unexpected client frame %v", f) - } - } - } - ct.run() -} - -func TestTransportRetryHasLimit(t *testing.T) { - // Skip in short mode because the total expected delay is 1s+2s+4s+8s+16s=29s. - if testing.Short() { - t.Skip("skipping long test in short mode") - } - clientDone := make(chan struct{}) - ct := newClientTester(t) - ct.client = func() error { - defer ct.cc.(*net.TCPConn).CloseWrite() - defer close(clientDone) - req, _ := http.NewRequest("GET", "https://dummy.tld/", nil) - resp, err := ct.tr.RoundTrip(req) - if err == nil { - return fmt.Errorf("RoundTrip expected error, got response: %+v", resp) - } - t.Logf("expected error, got: %v", err) - return nil - } - ct.server = func() error { - ct.greet() - for { - f, err := ct.fr.ReadFrame() - if err != nil { - select { - case <-clientDone: - // If the client's done, it - // will have reported any - // errors on its side. - return nil - default: - return err - } - } - switch f := f.(type) { - case *WindowUpdateFrame, *SettingsFrame: - case *HeadersFrame: - if !f.HeadersEnded() { - return fmt.Errorf("headers should have END_HEADERS be ended: %v", f) - } - ct.fr.WriteRSTStream(f.StreamID, ErrCodeRefusedStream) - default: - return fmt.Errorf("Unexpected client frame %v", f) - } - } - } - ct.run() -} - -func TestTransportResponseDataBeforeHeaders(t *testing.T) { - // This test use not valid response format. - // Discarding logger output to not spam tests output. - log.SetOutput(ioutil.Discard) - defer log.SetOutput(os.Stderr) - - ct := newClientTester(t) - ct.client = func() error { - defer ct.cc.(*net.TCPConn).CloseWrite() - req := httptest.NewRequest("GET", "https://dummy.tld/", nil) - // First request is normal to ensure the check is per stream and not per connection. - _, err := ct.tr.RoundTrip(req) - if err != nil { - return fmt.Errorf("RoundTrip expected no error, got: %v", err) - } - // Second request returns a DATA frame with no HEADERS. - resp, err := ct.tr.RoundTrip(req) - if err == nil { - return fmt.Errorf("RoundTrip expected error, got response: %+v", resp) - } - if err, ok := err.(StreamError); !ok || err.Code != ErrCodeProtocol { - return fmt.Errorf("expected stream PROTOCOL_ERROR, got: %v", err) - } - return nil - } - ct.server = func() error { - ct.greet() - for { - f, err := ct.fr.ReadFrame() - if err == io.EOF { - return nil - } else if err != nil { - return err - } - switch f := f.(type) { - case *WindowUpdateFrame, *SettingsFrame: - case *HeadersFrame: - switch f.StreamID { - case 1: - // Send a valid response to first request. - var buf bytes.Buffer - enc := hpack.NewEncoder(&buf) - enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) - ct.fr.WriteHeaders(HeadersFrameParam{ - StreamID: f.StreamID, - EndHeaders: true, - EndStream: true, - BlockFragment: buf.Bytes(), - }) - case 3: - ct.fr.WriteData(f.StreamID, true, []byte("payload")) - } - default: - return fmt.Errorf("Unexpected client frame %v", f) - } - } - } - ct.run() -} - -// tests Transport.StrictMaxConcurrentStreams -func TestTransportRequestsStallAtServerLimit(t *testing.T) { - const maxConcurrent = 2 - - greet := make(chan struct{}) // server sends initial SETTINGS frame - gotRequest := make(chan struct{}) // server received a request - clientDone := make(chan struct{}) - - // Collect errors from goroutines. - var wg sync.WaitGroup - errs := make(chan error, 100) - defer func() { - wg.Wait() - close(errs) - for err := range errs { - t.Error(err) - } - }() - - // We will send maxConcurrent+2 requests. This checker goroutine waits for the - // following stages: - // 1. The first maxConcurrent requests are received by the server. - // 2. The client will cancel the next request - // 3. The server is unblocked so it can service the first maxConcurrent requests - // 4. The client will send the final request - wg.Add(1) - unblockClient := make(chan struct{}) - clientRequestCancelled := make(chan struct{}) - unblockServer := make(chan struct{}) - go func() { - defer wg.Done() - // Stage 1. - for k := 0; k < maxConcurrent; k++ { - <-gotRequest - } - // Stage 2. - close(unblockClient) - <-clientRequestCancelled - // Stage 3: give some time for the final RoundTrip call to be scheduled and - // verify that the final request is not sent. - time.Sleep(50 * time.Millisecond) - select { - case <-gotRequest: - errs <- errors.New("last request did not stall") - close(unblockServer) - return - default: - } - close(unblockServer) - // Stage 4. - <-gotRequest - }() - - ct := newClientTester(t) - ct.tr.StrictMaxConcurrentStreams = true - ct.client = func() error { - var wg sync.WaitGroup - defer func() { - wg.Wait() - close(clientDone) - ct.cc.(*net.TCPConn).CloseWrite() - }() - for k := 0; k < maxConcurrent+2; k++ { - wg.Add(1) - go func(k int) { - defer wg.Done() - // Don't send the second request until after receiving SETTINGS from the server - // to avoid a race where we use the default SettingMaxConcurrentStreams, which - // is much larger than maxConcurrent. We have to send the first request before - // waiting because the first request triggers the dial and greet. - if k > 0 { - <-greet - } - // Block until maxConcurrent requests are sent before sending any more. - if k >= maxConcurrent { - <-unblockClient - } - req, _ := http.NewRequest("GET", fmt.Sprintf("https://dummy.tld/%d", k), nil) - if k == maxConcurrent { - // This request will be canceled. - cancel := make(chan struct{}) - req.Cancel = cancel - close(cancel) - _, err := ct.tr.RoundTrip(req) - close(clientRequestCancelled) - if err == nil { - errs <- fmt.Errorf("RoundTrip(%d) should have failed due to cancel", k) - return - } - } else { - resp, err := ct.tr.RoundTrip(req) - if err != nil { - errs <- fmt.Errorf("RoundTrip(%d): %v", k, err) - return - } - ioutil.ReadAll(resp.Body) - resp.Body.Close() - if resp.StatusCode != 204 { - errs <- fmt.Errorf("Status = %v; want 204", resp.StatusCode) - return - } - } - }(k) - } - return nil - } - - ct.server = func() error { - var wg sync.WaitGroup - defer wg.Wait() - - ct.greet(Setting{SettingMaxConcurrentStreams, maxConcurrent}) - - // Server write loop. - var buf bytes.Buffer - enc := hpack.NewEncoder(&buf) - writeResp := make(chan uint32, maxConcurrent+1) - - wg.Add(1) - go func() { - defer wg.Done() - <-unblockServer - for id := range writeResp { - buf.Reset() - enc.WriteField(hpack.HeaderField{Name: ":status", Value: "204"}) - ct.fr.WriteHeaders(HeadersFrameParam{ - StreamID: id, - EndHeaders: true, - EndStream: true, - BlockFragment: buf.Bytes(), - }) - } - }() - - // Server read loop. - var nreq int - for { - f, err := ct.fr.ReadFrame() - if err != nil { - select { - case <-clientDone: - // If the client's done, it will have reported any errors on its side. - return nil - default: - return err - } - } - switch f := f.(type) { - case *WindowUpdateFrame: - case *SettingsFrame: - // Wait for the client SETTINGS ack until ending the greet. - close(greet) - case *HeadersFrame: - if !f.HeadersEnded() { - return fmt.Errorf("headers should have END_HEADERS be ended: %v", f) - } - gotRequest <- struct{}{} - nreq++ - writeResp <- f.StreamID - if nreq == maxConcurrent+1 { - close(writeResp) - } - default: - return fmt.Errorf("Unexpected client frame %v", f) - } - } - } - - ct.run() -} - -func TestAuthorityAddr(t *testing.T) { - tests := []struct { - scheme, authority string - want string - }{ - {"http", "foo.com", "foo.com:80"}, - {"https", "foo.com", "foo.com:443"}, - {"https", "foo.com:1234", "foo.com:1234"}, - {"https", "1.2.3.4:1234", "1.2.3.4:1234"}, - {"https", "1.2.3.4", "1.2.3.4:443"}, - {"https", "[::1]:1234", "[::1]:1234"}, - {"https", "[::1]", "[::1]:443"}, - } - for _, tt := range tests { - got := authorityAddr(tt.scheme, tt.authority) - if got != tt.want { - t.Errorf("authorityAddr(%q, %q) = %q; want %q", tt.scheme, tt.authority, got, tt.want) - } - } -} - -// Issue 20448: stop allocating for DATA frames' payload after -// Response.Body.Close is called. -func TestTransportAllocationsAfterResponseBodyClose(t *testing.T) { - megabyteZero := make([]byte, 1<<20) - - writeErr := make(chan error, 1) - - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - w.(http.Flusher).Flush() - var sum int64 - for i := 0; i < 100; i++ { - n, err := w.Write(megabyteZero) - sum += int64(n) - if err != nil { - writeErr <- err - return - } - } - t.Logf("wrote all %d bytes", sum) - writeErr <- nil - }, optOnlyServer) - defer st.Close() - - tr := &Transport{TLSClientConfig: tlsConfigInsecure} - defer tr.CloseIdleConnections() - c := &http.Client{Transport: tr} - res, err := c.Get(st.ts.URL) - if err != nil { - t.Fatal(err) - } - var buf [1]byte - if _, err := res.Body.Read(buf[:]); err != nil { - t.Error(err) - } - if err := res.Body.Close(); err != nil { - t.Error(err) - } - - trb, ok := res.Body.(transportResponseBody) - if !ok { - t.Fatalf("res.Body = %T; want transportResponseBody", res.Body) - } - if trb.cs.bufPipe.b != nil { - t.Errorf("response body pipe is still open") - } - - gotErr := <-writeErr - if gotErr == nil { - t.Errorf("Handler unexpectedly managed to write its entire response without getting an error") - } else if gotErr != errStreamClosed { - t.Errorf("Handler Write err = %v; want errStreamClosed", gotErr) - } -} - -// Issue 18891: make sure Request.Body == NoBody means no DATA frame -// is ever sent, even if empty. -func TestTransportNoBodyMeansNoDATA(t *testing.T) { - ct := newClientTester(t) - - unblockClient := make(chan bool) - - ct.client = func() error { - req, _ := http.NewRequest("GET", "https://dummy.tld/", http.NoBody) - ct.tr.RoundTrip(req) - <-unblockClient - return nil - } - ct.server = func() error { - defer close(unblockClient) - defer ct.cc.(*net.TCPConn).Close() - ct.greet() - - for { - f, err := ct.fr.ReadFrame() - if err != nil { - return fmt.Errorf("ReadFrame while waiting for Headers: %v", err) - } - switch f := f.(type) { - default: - return fmt.Errorf("Got %T; want HeadersFrame", f) - case *WindowUpdateFrame, *SettingsFrame: - continue - case *HeadersFrame: - if !f.StreamEnded() { - return fmt.Errorf("got headers frame without END_STREAM") - } - return nil - } - } - } - ct.run() -} - -func benchSimpleRoundTrip(b *testing.B, nHeaders int) { - defer disableGoroutineTracking()() - b.ReportAllocs() - st := newServerTester(b, - func(w http.ResponseWriter, r *http.Request) { - }, - optOnlyServer, - optQuiet, - ) - defer st.Close() - - tr := &Transport{TLSClientConfig: tlsConfigInsecure} - defer tr.CloseIdleConnections() - - req, err := http.NewRequest("GET", st.ts.URL, nil) - if err != nil { - b.Fatal(err) - } - - for i := 0; i < nHeaders; i++ { - name := fmt.Sprint("A-", i) - req.Header.Set(name, "*") - } - - b.ResetTimer() - - for i := 0; i < b.N; i++ { - res, err := tr.RoundTrip(req) - if err != nil { - if res != nil { - res.Body.Close() - } - b.Fatalf("RoundTrip err = %v; want nil", err) - } - res.Body.Close() - if res.StatusCode != http.StatusOK { - b.Fatalf("Response code = %v; want %v", res.StatusCode, http.StatusOK) - } - } -} - -type infiniteReader struct{} - -func (r infiniteReader) Read(b []byte) (int, error) { - return len(b), nil -} - -// Issue 20521: it is not an error to receive a response and end stream -// from the server without the body being consumed. -func TestTransportResponseAndResetWithoutConsumingBodyRace(t *testing.T) { - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) - }, optOnlyServer) - defer st.Close() - - tr := &Transport{TLSClientConfig: tlsConfigInsecure} - defer tr.CloseIdleConnections() - - // The request body needs to be big enough to trigger flow control. - req, _ := http.NewRequest("PUT", st.ts.URL, infiniteReader{}) - res, err := tr.RoundTrip(req) - if err != nil { - t.Fatal(err) - } - if res.StatusCode != http.StatusOK { - t.Fatalf("Response code = %v; want %v", res.StatusCode, http.StatusOK) - } -} - -// Verify transport doesn't crash when receiving bogus response lacking a :status header. -// Issue 22880. -func TestTransportHandlesInvalidStatuslessResponse(t *testing.T) { - ct := newClientTester(t) - ct.client = func() error { - req, _ := http.NewRequest("GET", "https://dummy.tld/", nil) - _, err := ct.tr.RoundTrip(req) - const substr = "malformed response from server: missing status pseudo header" - if !strings.Contains(fmt.Sprint(err), substr) { - return fmt.Errorf("RoundTrip error = %v; want substring %q", err, substr) - } - return nil - } - ct.server = func() error { - ct.greet() - var buf bytes.Buffer - enc := hpack.NewEncoder(&buf) - - for { - f, err := ct.fr.ReadFrame() - if err != nil { - return err - } - switch f := f.(type) { - case *HeadersFrame: - enc.WriteField(hpack.HeaderField{Name: "content-type", Value: "text/html"}) // no :status header - ct.fr.WriteHeaders(HeadersFrameParam{ - StreamID: f.StreamID, - EndHeaders: true, - EndStream: false, // we'll send some DATA to try to crash the transport - BlockFragment: buf.Bytes(), - }) - ct.fr.WriteData(f.StreamID, true, []byte("payload")) - return nil - } - } - } - ct.run() -} - -func BenchmarkClientRequestHeaders(b *testing.B) { - b.Run(" 0 Headers", func(b *testing.B) { benchSimpleRoundTrip(b, 0) }) - b.Run(" 10 Headers", func(b *testing.B) { benchSimpleRoundTrip(b, 10) }) - b.Run(" 100 Headers", func(b *testing.B) { benchSimpleRoundTrip(b, 100) }) - b.Run("1000 Headers", func(b *testing.B) { benchSimpleRoundTrip(b, 1000) }) -} - -func activeStreams(cc *ClientConn) int { - cc.mu.Lock() - defer cc.mu.Unlock() - return len(cc.streams) -} - -type closeMode int - -const ( - closeAtHeaders closeMode = iota - closeAtBody - shutdown - shutdownCancel -) - -// See golang.org/issue/17292 -func testClientConnClose(t *testing.T, closeMode closeMode) { - clientDone := make(chan struct{}) - defer close(clientDone) - handlerDone := make(chan struct{}) - closeDone := make(chan struct{}) - beforeHeader := func() {} - bodyWrite := func(w http.ResponseWriter) {} - st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { - defer close(handlerDone) - beforeHeader() - w.WriteHeader(http.StatusOK) - w.(http.Flusher).Flush() - bodyWrite(w) - select { - case <-w.(http.CloseNotifier).CloseNotify(): - // client closed connection before completion - if closeMode == shutdown || closeMode == shutdownCancel { - t.Error("expected request to complete") - } - case <-clientDone: - if closeMode == closeAtHeaders || closeMode == closeAtBody { - t.Error("expected connection closed by client") - } - } - }, optOnlyServer) - defer st.Close() - tr := &Transport{TLSClientConfig: tlsConfigInsecure} - defer tr.CloseIdleConnections() - cc, err := tr.dialClientConn(st.ts.Listener.Addr().String(), false) - req, err := http.NewRequest("GET", st.ts.URL, nil) - if err != nil { - t.Fatal(err) - } - if closeMode == closeAtHeaders { - beforeHeader = func() { - if err := cc.Close(); err != nil { - t.Error(err) - } - close(closeDone) - } - } - var sendBody chan struct{} - if closeMode == closeAtBody { - sendBody = make(chan struct{}) - bodyWrite = func(w http.ResponseWriter) { - <-sendBody - b := make([]byte, 32) - w.Write(b) - w.(http.Flusher).Flush() - if err := cc.Close(); err != nil { - t.Errorf("unexpected ClientConn close error: %v", err) - } - close(closeDone) - w.Write(b) - w.(http.Flusher).Flush() - } - } - res, err := cc.RoundTrip(req) - if res != nil { - defer res.Body.Close() - } - if closeMode == closeAtHeaders { - got := fmt.Sprint(err) - want := "http2: client connection force closed via ClientConn.Close" - if got != want { - t.Fatalf("RoundTrip error = %v, want %v", got, want) - } - } else { - if err != nil { - t.Fatalf("RoundTrip: %v", err) - } - if got, want := activeStreams(cc), 1; got != want { - t.Errorf("got %d active streams, want %d", got, want) - } - } - switch closeMode { - case shutdownCancel: - if err = cc.Shutdown(canceledCtx); err != context.Canceled { - t.Errorf("got %v, want %v", err, context.Canceled) - } - if cc.closing == false { - t.Error("expected closing to be true") - } - if cc.CanTakeNewRequest() == true { - t.Error("CanTakeNewRequest to return false") - } - if v, want := len(cc.streams), 1; v != want { - t.Errorf("expected %d active streams, got %d", want, v) - } - clientDone <- struct{}{} - <-handlerDone - case shutdown: - wait := make(chan struct{}) - shutdownEnterWaitStateHook = func() { - close(wait) - shutdownEnterWaitStateHook = func() {} - } - defer func() { shutdownEnterWaitStateHook = func() {} }() - shutdown := make(chan struct{}, 1) - go func() { - if err = cc.Shutdown(context.Background()); err != nil { - t.Error(err) - } - close(shutdown) - }() - // Let the shutdown to enter wait state - <-wait - cc.mu.Lock() - if cc.closing == false { - t.Error("expected closing to be true") - } - cc.mu.Unlock() - if cc.CanTakeNewRequest() == true { - t.Error("CanTakeNewRequest to return false") - } - if got, want := activeStreams(cc), 1; got != want { - t.Errorf("got %d active streams, want %d", got, want) - } - // Let the active request finish - clientDone <- struct{}{} - // Wait for the shutdown to end - select { - case <-shutdown: - case <-time.After(2 * time.Second): - t.Fatal("expected server connection to close") - } - case closeAtHeaders, closeAtBody: - if closeMode == closeAtBody { - go close(sendBody) - if _, err := io.Copy(ioutil.Discard, res.Body); err == nil { - t.Error("expected a Copy error, got nil") - } - } - <-closeDone - if got, want := activeStreams(cc), 0; got != want { - t.Errorf("got %d active streams, want %d", got, want) - } - // wait for server to get the connection close notice - select { - case <-handlerDone: - case <-time.After(2 * time.Second): - t.Fatal("expected server connection to close") - } - } -} - -// The client closes the connection just after the server got the client's HEADERS -// frame, but before the server sends its HEADERS response back. The expected -// result is an error on RoundTrip explaining the client closed the connection. -func TestClientConnCloseAtHeaders(t *testing.T) { - testClientConnClose(t, closeAtHeaders) -} - -// The client closes the connection between two server's response DATA frames. -// The expected behavior is a response body io read error on the client. -func TestClientConnCloseAtBody(t *testing.T) { - testClientConnClose(t, closeAtBody) -} - -// The client sends a GOAWAY frame before the server finished processing a request. -// We expect the connection not to close until the request is completed. -func TestClientConnShutdown(t *testing.T) { - testClientConnClose(t, shutdown) -} - -// The client sends a GOAWAY frame before the server finishes processing a request, -// but cancels the passed context before the request is completed. The expected -// behavior is the client closing the connection after the context is canceled. -func TestClientConnShutdownCancel(t *testing.T) { - testClientConnClose(t, shutdownCancel) -} - -// Issue 25009: use Request.GetBody if present, even if it seems like -// we might not need it. Apparently something else can still read from -// the original request body. Data race? In any case, rewinding -// unconditionally on retry is a nicer model anyway and should -// simplify code in the future (after the Go 1.11 freeze) -func TestTransportUsesGetBodyWhenPresent(t *testing.T) { - calls := 0 - someBody := func() io.ReadCloser { - return struct{ io.ReadCloser }{ioutil.NopCloser(bytes.NewReader(nil))} - } - req := &http.Request{ - Body: someBody(), - GetBody: func() (io.ReadCloser, error) { - calls++ - return someBody(), nil - }, - } - - afterBodyWrite := false // pretend we haven't read+written the body yet - req2, err := shouldRetryRequest(req, errClientConnUnusable, afterBodyWrite) - if err != nil { - t.Fatal(err) - } - if calls != 1 { - t.Errorf("Calls = %d; want 1", calls) - } - if req2 == req { - t.Error("req2 changed") - } - if req2 == nil { - t.Fatal("req2 is nil") - } - if req2.Body == nil { - t.Fatal("req2.Body is nil") - } - if req2.GetBody == nil { - t.Fatal("req2.GetBody is nil") - } - if req2.Body == req.Body { - t.Error("req2.Body unchanged") - } -} - -// Issue 22891: verify that the "https" altproto we register with net/http -// is a certain type: a struct with one field with our *http2.Transport in it. -func TestNoDialH2RoundTripperType(t *testing.T) { - t1 := new(http.Transport) - t2 := new(Transport) - rt := noDialH2RoundTripper{t2} - if err := registerHTTPSProtocol(t1, rt); err != nil { - t.Fatal(err) - } - rv := reflect.ValueOf(rt) - if rv.Type().Kind() != reflect.Struct { - t.Fatalf("kind = %v; net/http expects struct", rv.Type().Kind()) - } - if n := rv.Type().NumField(); n != 1 { - t.Fatalf("fields = %d; net/http expects 1", n) - } - v := rv.Field(0) - if _, ok := v.Interface().(*Transport); !ok { - t.Fatalf("wrong kind %T; want *Transport", v.Interface()) - } -} - -type errReader struct { - body []byte - err error -} - -func (r *errReader) Read(p []byte) (int, error) { - if len(r.body) > 0 { - n := copy(p, r.body) - r.body = r.body[n:] - return n, nil - } - return 0, r.err -} - -func testTransportBodyReadError(t *testing.T, body []byte) { - clientDone := make(chan struct{}) - ct := newClientTester(t) - ct.client = func() error { - defer ct.cc.(*net.TCPConn).CloseWrite() - defer close(clientDone) - - checkNoStreams := func() error { - cp, ok := ct.tr.connPool().(*clientConnPool) - if !ok { - return fmt.Errorf("conn pool is %T; want *clientConnPool", ct.tr.connPool()) - } - cp.mu.Lock() - defer cp.mu.Unlock() - conns, ok := cp.conns["dummy.tld:443"] - if !ok { - return fmt.Errorf("missing connection") - } - if len(conns) != 1 { - return fmt.Errorf("conn pool size: %v; expect 1", len(conns)) - } - if activeStreams(conns[0]) != 0 { - return fmt.Errorf("active streams count: %v; want 0", activeStreams(conns[0])) - } - return nil - } - bodyReadError := errors.New("body read error") - body := &errReader{body, bodyReadError} - req, err := http.NewRequest("PUT", "https://dummy.tld/", body) - if err != nil { - return err - } - _, err = ct.tr.RoundTrip(req) - if err != bodyReadError { - return fmt.Errorf("err = %v; want %v", err, bodyReadError) - } - if err = checkNoStreams(); err != nil { - return err - } - return nil - } - ct.server = func() error { - ct.greet() - var receivedBody []byte - var resetCount int - for { - f, err := ct.fr.ReadFrame() - if err != nil { - select { - case <-clientDone: - // If the client's done, it - // will have reported any - // errors on its side. - if bytes.Compare(receivedBody, body) != 0 { - return fmt.Errorf("body: %v; expected %v", receivedBody, body) - } - if resetCount != 1 { - return fmt.Errorf("stream reset count: %v; expected: 1", resetCount) - } - return nil - default: - return err - } - } - switch f := f.(type) { - case *WindowUpdateFrame, *SettingsFrame: - case *HeadersFrame: - case *DataFrame: - receivedBody = append(receivedBody, f.Data()...) - case *RSTStreamFrame: - resetCount++ - default: - return fmt.Errorf("Unexpected client frame %v", f) - } - } - } - ct.run() -} - -func TestTransportBodyReadError_Immediately(t *testing.T) { testTransportBodyReadError(t, nil) } -func TestTransportBodyReadError_Some(t *testing.T) { testTransportBodyReadError(t, []byte("123")) } diff --git a/vendor/golang.org/x/net/http2/writesched_priority_test.go b/vendor/golang.org/x/net/http2/writesched_priority_test.go deleted file mode 100644 index f2b535a2..00000000 --- a/vendor/golang.org/x/net/http2/writesched_priority_test.go +++ /dev/null @@ -1,541 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package http2 - -import ( - "bytes" - "fmt" - "sort" - "testing" -) - -func defaultPriorityWriteScheduler() *priorityWriteScheduler { - return NewPriorityWriteScheduler(nil).(*priorityWriteScheduler) -} - -func checkPriorityWellFormed(ws *priorityWriteScheduler) error { - for id, n := range ws.nodes { - if id != n.id { - return fmt.Errorf("bad ws.nodes: ws.nodes[%d] = %d", id, n.id) - } - if n.parent == nil { - if n.next != nil || n.prev != nil { - return fmt.Errorf("bad node %d: nil parent but prev/next not nil", id) - } - continue - } - found := false - for k := n.parent.kids; k != nil; k = k.next { - if k.id == id { - found = true - break - } - } - if !found { - return fmt.Errorf("bad node %d: not found in parent %d kids list", id, n.parent.id) - } - } - return nil -} - -func fmtTree(ws *priorityWriteScheduler, fmtNode func(*priorityNode) string) string { - var ids []int - for _, n := range ws.nodes { - ids = append(ids, int(n.id)) - } - sort.Ints(ids) - - var buf bytes.Buffer - for _, id := range ids { - if buf.Len() != 0 { - buf.WriteString(" ") - } - if id == 0 { - buf.WriteString(fmtNode(&ws.root)) - } else { - buf.WriteString(fmtNode(ws.nodes[uint32(id)])) - } - } - return buf.String() -} - -func fmtNodeParentSkipRoot(n *priorityNode) string { - switch { - case n.id == 0: - return "" - case n.parent == nil: - return fmt.Sprintf("%d{parent:nil}", n.id) - default: - return fmt.Sprintf("%d{parent:%d}", n.id, n.parent.id) - } -} - -func fmtNodeWeightParentSkipRoot(n *priorityNode) string { - switch { - case n.id == 0: - return "" - case n.parent == nil: - return fmt.Sprintf("%d{weight:%d,parent:nil}", n.id, n.weight) - default: - return fmt.Sprintf("%d{weight:%d,parent:%d}", n.id, n.weight, n.parent.id) - } -} - -func TestPriorityTwoStreams(t *testing.T) { - ws := defaultPriorityWriteScheduler() - ws.OpenStream(1, OpenStreamOptions{}) - ws.OpenStream(2, OpenStreamOptions{}) - - want := "1{weight:15,parent:0} 2{weight:15,parent:0}" - if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want { - t.Errorf("After open\ngot %q\nwant %q", got, want) - } - - // Move 1's parent to 2. - ws.AdjustStream(1, PriorityParam{ - StreamDep: 2, - Weight: 32, - Exclusive: false, - }) - want = "1{weight:32,parent:2} 2{weight:15,parent:0}" - if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want { - t.Errorf("After adjust\ngot %q\nwant %q", got, want) - } - - if err := checkPriorityWellFormed(ws); err != nil { - t.Error(err) - } -} - -func TestPriorityAdjustExclusiveZero(t *testing.T) { - // 1, 2, and 3 are all children of the 0 stream. - // Exclusive reprioritization to any of the streams should bring - // the rest of the streams under the reprioritized stream. - ws := defaultPriorityWriteScheduler() - ws.OpenStream(1, OpenStreamOptions{}) - ws.OpenStream(2, OpenStreamOptions{}) - ws.OpenStream(3, OpenStreamOptions{}) - - want := "1{weight:15,parent:0} 2{weight:15,parent:0} 3{weight:15,parent:0}" - if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want { - t.Errorf("After open\ngot %q\nwant %q", got, want) - } - - ws.AdjustStream(2, PriorityParam{ - StreamDep: 0, - Weight: 20, - Exclusive: true, - }) - want = "1{weight:15,parent:2} 2{weight:20,parent:0} 3{weight:15,parent:2}" - if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want { - t.Errorf("After adjust\ngot %q\nwant %q", got, want) - } - - if err := checkPriorityWellFormed(ws); err != nil { - t.Error(err) - } -} - -func TestPriorityAdjustOwnParent(t *testing.T) { - // Assigning a node as its own parent should have no effect. - ws := defaultPriorityWriteScheduler() - ws.OpenStream(1, OpenStreamOptions{}) - ws.OpenStream(2, OpenStreamOptions{}) - ws.AdjustStream(2, PriorityParam{ - StreamDep: 2, - Weight: 20, - Exclusive: true, - }) - want := "1{weight:15,parent:0} 2{weight:15,parent:0}" - if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want { - t.Errorf("After adjust\ngot %q\nwant %q", got, want) - } - if err := checkPriorityWellFormed(ws); err != nil { - t.Error(err) - } -} - -func TestPriorityClosedStreams(t *testing.T) { - ws := NewPriorityWriteScheduler(&PriorityWriteSchedulerConfig{MaxClosedNodesInTree: 2}).(*priorityWriteScheduler) - ws.OpenStream(1, OpenStreamOptions{}) - ws.OpenStream(2, OpenStreamOptions{PusherID: 1}) - ws.OpenStream(3, OpenStreamOptions{PusherID: 2}) - ws.OpenStream(4, OpenStreamOptions{PusherID: 3}) - - // Close the first three streams. We lose 1, but keep 2 and 3. - ws.CloseStream(1) - ws.CloseStream(2) - ws.CloseStream(3) - - want := "2{weight:15,parent:0} 3{weight:15,parent:2} 4{weight:15,parent:3}" - if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want { - t.Errorf("After close\ngot %q\nwant %q", got, want) - } - if err := checkPriorityWellFormed(ws); err != nil { - t.Error(err) - } - - // Adding a stream as an exclusive child of 1 gives it default - // priorities, since 1 is gone. - ws.OpenStream(5, OpenStreamOptions{}) - ws.AdjustStream(5, PriorityParam{StreamDep: 1, Weight: 15, Exclusive: true}) - - // Adding a stream as an exclusive child of 2 should work, since 2 is not gone. - ws.OpenStream(6, OpenStreamOptions{}) - ws.AdjustStream(6, PriorityParam{StreamDep: 2, Weight: 15, Exclusive: true}) - - want = "2{weight:15,parent:0} 3{weight:15,parent:6} 4{weight:15,parent:3} 5{weight:15,parent:0} 6{weight:15,parent:2}" - if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want { - t.Errorf("After add streams\ngot %q\nwant %q", got, want) - } - if err := checkPriorityWellFormed(ws); err != nil { - t.Error(err) - } -} - -func TestPriorityClosedStreamsDisabled(t *testing.T) { - ws := NewPriorityWriteScheduler(&PriorityWriteSchedulerConfig{}).(*priorityWriteScheduler) - ws.OpenStream(1, OpenStreamOptions{}) - ws.OpenStream(2, OpenStreamOptions{PusherID: 1}) - ws.OpenStream(3, OpenStreamOptions{PusherID: 2}) - - // Close the first two streams. We keep only 3. - ws.CloseStream(1) - ws.CloseStream(2) - - want := "3{weight:15,parent:0}" - if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want { - t.Errorf("After close\ngot %q\nwant %q", got, want) - } - if err := checkPriorityWellFormed(ws); err != nil { - t.Error(err) - } -} - -func TestPriorityIdleStreams(t *testing.T) { - ws := NewPriorityWriteScheduler(&PriorityWriteSchedulerConfig{MaxIdleNodesInTree: 2}).(*priorityWriteScheduler) - ws.AdjustStream(1, PriorityParam{StreamDep: 0, Weight: 15}) // idle - ws.AdjustStream(2, PriorityParam{StreamDep: 0, Weight: 15}) // idle - ws.AdjustStream(3, PriorityParam{StreamDep: 2, Weight: 20}) // idle - ws.OpenStream(4, OpenStreamOptions{}) - ws.OpenStream(5, OpenStreamOptions{}) - ws.OpenStream(6, OpenStreamOptions{}) - ws.AdjustStream(4, PriorityParam{StreamDep: 1, Weight: 15}) - ws.AdjustStream(5, PriorityParam{StreamDep: 2, Weight: 15}) - ws.AdjustStream(6, PriorityParam{StreamDep: 3, Weight: 15}) - - want := "2{weight:15,parent:0} 3{weight:20,parent:2} 4{weight:15,parent:0} 5{weight:15,parent:2} 6{weight:15,parent:3}" - if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want { - t.Errorf("After open\ngot %q\nwant %q", got, want) - } - if err := checkPriorityWellFormed(ws); err != nil { - t.Error(err) - } -} - -func TestPriorityIdleStreamsDisabled(t *testing.T) { - ws := NewPriorityWriteScheduler(&PriorityWriteSchedulerConfig{}).(*priorityWriteScheduler) - ws.AdjustStream(1, PriorityParam{StreamDep: 0, Weight: 15}) // idle - ws.AdjustStream(2, PriorityParam{StreamDep: 0, Weight: 15}) // idle - ws.AdjustStream(3, PriorityParam{StreamDep: 2, Weight: 20}) // idle - ws.OpenStream(4, OpenStreamOptions{}) - - want := "4{weight:15,parent:0}" - if got := fmtTree(ws, fmtNodeWeightParentSkipRoot); got != want { - t.Errorf("After open\ngot %q\nwant %q", got, want) - } - if err := checkPriorityWellFormed(ws); err != nil { - t.Error(err) - } -} - -func TestPrioritySection531NonExclusive(t *testing.T) { - // Example from RFC 7540 Section 5.3.1. - // A,B,C,D = 1,2,3,4 - ws := defaultPriorityWriteScheduler() - ws.OpenStream(1, OpenStreamOptions{}) - ws.OpenStream(2, OpenStreamOptions{PusherID: 1}) - ws.OpenStream(3, OpenStreamOptions{PusherID: 1}) - ws.OpenStream(4, OpenStreamOptions{}) - ws.AdjustStream(4, PriorityParam{ - StreamDep: 1, - Weight: 15, - Exclusive: false, - }) - want := "1{parent:0} 2{parent:1} 3{parent:1} 4{parent:1}" - if got := fmtTree(ws, fmtNodeParentSkipRoot); got != want { - t.Errorf("After adjust\ngot %q\nwant %q", got, want) - } - if err := checkPriorityWellFormed(ws); err != nil { - t.Error(err) - } -} - -func TestPrioritySection531Exclusive(t *testing.T) { - // Example from RFC 7540 Section 5.3.1. - // A,B,C,D = 1,2,3,4 - ws := defaultPriorityWriteScheduler() - ws.OpenStream(1, OpenStreamOptions{}) - ws.OpenStream(2, OpenStreamOptions{PusherID: 1}) - ws.OpenStream(3, OpenStreamOptions{PusherID: 1}) - ws.OpenStream(4, OpenStreamOptions{}) - ws.AdjustStream(4, PriorityParam{ - StreamDep: 1, - Weight: 15, - Exclusive: true, - }) - want := "1{parent:0} 2{parent:4} 3{parent:4} 4{parent:1}" - if got := fmtTree(ws, fmtNodeParentSkipRoot); got != want { - t.Errorf("After adjust\ngot %q\nwant %q", got, want) - } - if err := checkPriorityWellFormed(ws); err != nil { - t.Error(err) - } -} - -func makeSection533Tree() *priorityWriteScheduler { - // Initial tree from RFC 7540 Section 5.3.3. - // A,B,C,D,E,F = 1,2,3,4,5,6 - ws := defaultPriorityWriteScheduler() - ws.OpenStream(1, OpenStreamOptions{}) - ws.OpenStream(2, OpenStreamOptions{PusherID: 1}) - ws.OpenStream(3, OpenStreamOptions{PusherID: 1}) - ws.OpenStream(4, OpenStreamOptions{PusherID: 3}) - ws.OpenStream(5, OpenStreamOptions{PusherID: 3}) - ws.OpenStream(6, OpenStreamOptions{PusherID: 4}) - return ws -} - -func TestPrioritySection533NonExclusive(t *testing.T) { - // Example from RFC 7540 Section 5.3.3. - // A,B,C,D,E,F = 1,2,3,4,5,6 - ws := defaultPriorityWriteScheduler() - ws.OpenStream(1, OpenStreamOptions{}) - ws.OpenStream(2, OpenStreamOptions{PusherID: 1}) - ws.OpenStream(3, OpenStreamOptions{PusherID: 1}) - ws.OpenStream(4, OpenStreamOptions{PusherID: 3}) - ws.OpenStream(5, OpenStreamOptions{PusherID: 3}) - ws.OpenStream(6, OpenStreamOptions{PusherID: 4}) - ws.AdjustStream(1, PriorityParam{ - StreamDep: 4, - Weight: 15, - Exclusive: false, - }) - want := "1{parent:4} 2{parent:1} 3{parent:1} 4{parent:0} 5{parent:3} 6{parent:4}" - if got := fmtTree(ws, fmtNodeParentSkipRoot); got != want { - t.Errorf("After adjust\ngot %q\nwant %q", got, want) - } - if err := checkPriorityWellFormed(ws); err != nil { - t.Error(err) - } -} - -func TestPrioritySection533Exclusive(t *testing.T) { - // Example from RFC 7540 Section 5.3.3. - // A,B,C,D,E,F = 1,2,3,4,5,6 - ws := defaultPriorityWriteScheduler() - ws.OpenStream(1, OpenStreamOptions{}) - ws.OpenStream(2, OpenStreamOptions{PusherID: 1}) - ws.OpenStream(3, OpenStreamOptions{PusherID: 1}) - ws.OpenStream(4, OpenStreamOptions{PusherID: 3}) - ws.OpenStream(5, OpenStreamOptions{PusherID: 3}) - ws.OpenStream(6, OpenStreamOptions{PusherID: 4}) - ws.AdjustStream(1, PriorityParam{ - StreamDep: 4, - Weight: 15, - Exclusive: true, - }) - want := "1{parent:4} 2{parent:1} 3{parent:1} 4{parent:0} 5{parent:3} 6{parent:1}" - if got := fmtTree(ws, fmtNodeParentSkipRoot); got != want { - t.Errorf("After adjust\ngot %q\nwant %q", got, want) - } - if err := checkPriorityWellFormed(ws); err != nil { - t.Error(err) - } -} - -func checkPopAll(ws WriteScheduler, order []uint32) error { - for k, id := range order { - wr, ok := ws.Pop() - if !ok { - return fmt.Errorf("Pop[%d]: got ok=false, want %d (order=%v)", k, id, order) - } - if got := wr.StreamID(); got != id { - return fmt.Errorf("Pop[%d]: got %v, want %d (order=%v)", k, got, id, order) - } - } - wr, ok := ws.Pop() - if ok { - return fmt.Errorf("Pop[%d]: got %v, want ok=false (order=%v)", len(order), wr.StreamID(), order) - } - return nil -} - -func TestPriorityPopFrom533Tree(t *testing.T) { - ws := makeSection533Tree() - - ws.Push(makeWriteHeadersRequest(3 /*C*/)) - ws.Push(makeWriteNonStreamRequest()) - ws.Push(makeWriteHeadersRequest(5 /*E*/)) - ws.Push(makeWriteHeadersRequest(1 /*A*/)) - t.Log("tree:", fmtTree(ws, fmtNodeParentSkipRoot)) - - if err := checkPopAll(ws, []uint32{0 /*NonStream*/, 1, 3, 5}); err != nil { - t.Error(err) - } -} - -func TestPriorityPopFromLinearTree(t *testing.T) { - ws := defaultPriorityWriteScheduler() - ws.OpenStream(1, OpenStreamOptions{}) - ws.OpenStream(2, OpenStreamOptions{PusherID: 1}) - ws.OpenStream(3, OpenStreamOptions{PusherID: 2}) - ws.OpenStream(4, OpenStreamOptions{PusherID: 3}) - - ws.Push(makeWriteHeadersRequest(3)) - ws.Push(makeWriteHeadersRequest(4)) - ws.Push(makeWriteHeadersRequest(1)) - ws.Push(makeWriteHeadersRequest(2)) - ws.Push(makeWriteNonStreamRequest()) - ws.Push(makeWriteNonStreamRequest()) - t.Log("tree:", fmtTree(ws, fmtNodeParentSkipRoot)) - - if err := checkPopAll(ws, []uint32{0, 0 /*NonStreams*/, 1, 2, 3, 4}); err != nil { - t.Error(err) - } -} - -func TestPriorityFlowControl(t *testing.T) { - ws := NewPriorityWriteScheduler(&PriorityWriteSchedulerConfig{ThrottleOutOfOrderWrites: false}) - ws.OpenStream(1, OpenStreamOptions{}) - ws.OpenStream(2, OpenStreamOptions{PusherID: 1}) - - sc := &serverConn{maxFrameSize: 16} - st1 := &stream{id: 1, sc: sc} - st2 := &stream{id: 2, sc: sc} - - ws.Push(FrameWriteRequest{&writeData{1, make([]byte, 16), false}, st1, nil}) - ws.Push(FrameWriteRequest{&writeData{2, make([]byte, 16), false}, st2, nil}) - ws.AdjustStream(2, PriorityParam{StreamDep: 1}) - - // No flow-control bytes available. - if wr, ok := ws.Pop(); ok { - t.Fatalf("Pop(limited by flow control)=%v,true, want false", wr) - } - - // Add enough flow-control bytes to write st2 in two Pop calls. - // Should write data from st2 even though it's lower priority than st1. - for i := 1; i <= 2; i++ { - st2.flow.add(8) - wr, ok := ws.Pop() - if !ok { - t.Fatalf("Pop(%d)=false, want true", i) - } - if got, want := wr.DataSize(), 8; got != want { - t.Fatalf("Pop(%d)=%d bytes, want %d bytes", i, got, want) - } - } -} - -func TestPriorityThrottleOutOfOrderWrites(t *testing.T) { - ws := NewPriorityWriteScheduler(&PriorityWriteSchedulerConfig{ThrottleOutOfOrderWrites: true}) - ws.OpenStream(1, OpenStreamOptions{}) - ws.OpenStream(2, OpenStreamOptions{PusherID: 1}) - - sc := &serverConn{maxFrameSize: 4096} - st1 := &stream{id: 1, sc: sc} - st2 := &stream{id: 2, sc: sc} - st1.flow.add(4096) - st2.flow.add(4096) - ws.Push(FrameWriteRequest{&writeData{2, make([]byte, 4096), false}, st2, nil}) - ws.AdjustStream(2, PriorityParam{StreamDep: 1}) - - // We have enough flow-control bytes to write st2 in a single Pop call. - // However, due to out-of-order write throttling, the first call should - // only write 1KB. - wr, ok := ws.Pop() - if !ok { - t.Fatalf("Pop(st2.first)=false, want true") - } - if got, want := wr.StreamID(), uint32(2); got != want { - t.Fatalf("Pop(st2.first)=stream %d, want stream %d", got, want) - } - if got, want := wr.DataSize(), 1024; got != want { - t.Fatalf("Pop(st2.first)=%d bytes, want %d bytes", got, want) - } - - // Now add data on st1. This should take precedence. - ws.Push(FrameWriteRequest{&writeData{1, make([]byte, 4096), false}, st1, nil}) - wr, ok = ws.Pop() - if !ok { - t.Fatalf("Pop(st1)=false, want true") - } - if got, want := wr.StreamID(), uint32(1); got != want { - t.Fatalf("Pop(st1)=stream %d, want stream %d", got, want) - } - if got, want := wr.DataSize(), 4096; got != want { - t.Fatalf("Pop(st1)=%d bytes, want %d bytes", got, want) - } - - // Should go back to writing 1KB from st2. - wr, ok = ws.Pop() - if !ok { - t.Fatalf("Pop(st2.last)=false, want true") - } - if got, want := wr.StreamID(), uint32(2); got != want { - t.Fatalf("Pop(st2.last)=stream %d, want stream %d", got, want) - } - if got, want := wr.DataSize(), 1024; got != want { - t.Fatalf("Pop(st2.last)=%d bytes, want %d bytes", got, want) - } -} - -func TestPriorityWeights(t *testing.T) { - ws := defaultPriorityWriteScheduler() - ws.OpenStream(1, OpenStreamOptions{}) - ws.OpenStream(2, OpenStreamOptions{}) - - sc := &serverConn{maxFrameSize: 8} - st1 := &stream{id: 1, sc: sc} - st2 := &stream{id: 2, sc: sc} - st1.flow.add(40) - st2.flow.add(40) - - ws.Push(FrameWriteRequest{&writeData{1, make([]byte, 40), false}, st1, nil}) - ws.Push(FrameWriteRequest{&writeData{2, make([]byte, 40), false}, st2, nil}) - ws.AdjustStream(1, PriorityParam{StreamDep: 0, Weight: 34}) - ws.AdjustStream(2, PriorityParam{StreamDep: 0, Weight: 9}) - - // st1 gets 3.5x the bandwidth of st2 (3.5 = (34+1)/(9+1)). - // The maximum frame size is 8 bytes. The write sequence should be: - // st1, total bytes so far is (st1=8, st=0) - // st2, total bytes so far is (st1=8, st=8) - // st1, total bytes so far is (st1=16, st=8) - // st1, total bytes so far is (st1=24, st=8) // 3x bandwidth - // st1, total bytes so far is (st1=32, st=8) // 4x bandwidth - // st2, total bytes so far is (st1=32, st=16) // 2x bandwidth - // st1, total bytes so far is (st1=40, st=16) - // st2, total bytes so far is (st1=40, st=24) - // st2, total bytes so far is (st1=40, st=32) - // st2, total bytes so far is (st1=40, st=40) - if err := checkPopAll(ws, []uint32{1, 2, 1, 1, 1, 2, 1, 2, 2, 2}); err != nil { - t.Error(err) - } -} - -func TestPriorityRstStreamOnNonOpenStreams(t *testing.T) { - ws := NewPriorityWriteScheduler(&PriorityWriteSchedulerConfig{ - MaxClosedNodesInTree: 0, - MaxIdleNodesInTree: 0, - }) - ws.OpenStream(1, OpenStreamOptions{}) - ws.CloseStream(1) - ws.Push(FrameWriteRequest{write: streamError(1, ErrCodeProtocol)}) - ws.Push(FrameWriteRequest{write: streamError(2, ErrCodeProtocol)}) - - if err := checkPopAll(ws, []uint32{1, 2}); err != nil { - t.Error(err) - } -} diff --git a/vendor/golang.org/x/net/http2/writesched_random_test.go b/vendor/golang.org/x/net/http2/writesched_random_test.go deleted file mode 100644 index 3bf4aa36..00000000 --- a/vendor/golang.org/x/net/http2/writesched_random_test.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package http2 - -import "testing" - -func TestRandomScheduler(t *testing.T) { - ws := NewRandomWriteScheduler() - ws.Push(makeWriteHeadersRequest(3)) - ws.Push(makeWriteHeadersRequest(4)) - ws.Push(makeWriteHeadersRequest(1)) - ws.Push(makeWriteHeadersRequest(2)) - ws.Push(makeWriteNonStreamRequest()) - ws.Push(makeWriteNonStreamRequest()) - - // Pop all frames. Should get the non-stream requests first, - // followed by the stream requests in any order. - var order []FrameWriteRequest - for { - wr, ok := ws.Pop() - if !ok { - break - } - order = append(order, wr) - } - t.Logf("got frames: %v", order) - if len(order) != 6 { - t.Fatalf("got %d frames, expected 6", len(order)) - } - if order[0].StreamID() != 0 || order[1].StreamID() != 0 { - t.Fatal("expected non-stream frames first", order[0], order[1]) - } - got := make(map[uint32]bool) - for _, wr := range order[2:] { - got[wr.StreamID()] = true - } - for id := uint32(1); id <= 4; id++ { - if !got[id] { - t.Errorf("frame not found for stream %d", id) - } - } -} diff --git a/vendor/golang.org/x/net/http2/writesched_test.go b/vendor/golang.org/x/net/http2/writesched_test.go deleted file mode 100644 index 0807056b..00000000 --- a/vendor/golang.org/x/net/http2/writesched_test.go +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package http2 - -import ( - "fmt" - "math" - "reflect" - "testing" -) - -func makeWriteNonStreamRequest() FrameWriteRequest { - return FrameWriteRequest{writeSettingsAck{}, nil, nil} -} - -func makeWriteHeadersRequest(streamID uint32) FrameWriteRequest { - st := &stream{id: streamID} - return FrameWriteRequest{&writeResHeaders{streamID: streamID, httpResCode: 200}, st, nil} -} - -func checkConsume(wr FrameWriteRequest, nbytes int32, want []FrameWriteRequest) error { - consumed, rest, n := wr.Consume(nbytes) - var wantConsumed, wantRest FrameWriteRequest - switch len(want) { - case 0: - case 1: - wantConsumed = want[0] - case 2: - wantConsumed = want[0] - wantRest = want[1] - } - if !reflect.DeepEqual(consumed, wantConsumed) || !reflect.DeepEqual(rest, wantRest) || n != len(want) { - return fmt.Errorf("got %v, %v, %v\nwant %v, %v, %v", consumed, rest, n, wantConsumed, wantRest, len(want)) - } - return nil -} - -func TestFrameWriteRequestNonData(t *testing.T) { - wr := makeWriteNonStreamRequest() - if got, want := wr.DataSize(), 0; got != want { - t.Errorf("DataSize: got %v, want %v", got, want) - } - - // Non-DATA frames are always consumed whole. - if err := checkConsume(wr, 0, []FrameWriteRequest{wr}); err != nil { - t.Errorf("Consume:\n%v", err) - } -} - -func TestFrameWriteRequestData(t *testing.T) { - st := &stream{ - id: 1, - sc: &serverConn{maxFrameSize: 16}, - } - const size = 32 - wr := FrameWriteRequest{&writeData{st.id, make([]byte, size), true}, st, make(chan error)} - if got, want := wr.DataSize(), size; got != want { - t.Errorf("DataSize: got %v, want %v", got, want) - } - - // No flow-control bytes available: cannot consume anything. - if err := checkConsume(wr, math.MaxInt32, []FrameWriteRequest{}); err != nil { - t.Errorf("Consume(limited by flow control):\n%v", err) - } - - // Add enough flow-control bytes to consume the entire frame, - // but we're now restricted by st.sc.maxFrameSize. - st.flow.add(size) - want := []FrameWriteRequest{ - { - write: &writeData{st.id, make([]byte, st.sc.maxFrameSize), false}, - stream: st, - done: nil, - }, - { - write: &writeData{st.id, make([]byte, size-st.sc.maxFrameSize), true}, - stream: st, - done: wr.done, - }, - } - if err := checkConsume(wr, math.MaxInt32, want); err != nil { - t.Errorf("Consume(limited by maxFrameSize):\n%v", err) - } - rest := want[1] - - // Consume 8 bytes from the remaining frame. - want = []FrameWriteRequest{ - { - write: &writeData{st.id, make([]byte, 8), false}, - stream: st, - done: nil, - }, - { - write: &writeData{st.id, make([]byte, size-st.sc.maxFrameSize-8), true}, - stream: st, - done: wr.done, - }, - } - if err := checkConsume(rest, 8, want); err != nil { - t.Errorf("Consume(8):\n%v", err) - } - rest = want[1] - - // Consume all remaining bytes. - want = []FrameWriteRequest{ - { - write: &writeData{st.id, make([]byte, size-st.sc.maxFrameSize-8), true}, - stream: st, - done: wr.done, - }, - } - if err := checkConsume(rest, math.MaxInt32, want); err != nil { - t.Errorf("Consume(remainder):\n%v", err) - } -} - -func TestFrameWriteRequest_StreamID(t *testing.T) { - const streamID = 123 - wr := FrameWriteRequest{write: streamError(streamID, ErrCodeNo)} - if got := wr.StreamID(); got != streamID { - t.Errorf("FrameWriteRequest(StreamError) = %v; want %v", got, streamID) - } -} diff --git a/vendor/golang.org/x/net/http2/z_spec_test.go b/vendor/golang.org/x/net/http2/z_spec_test.go deleted file mode 100644 index 610b2cdb..00000000 --- a/vendor/golang.org/x/net/http2/z_spec_test.go +++ /dev/null @@ -1,356 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package http2 - -import ( - "bytes" - "encoding/xml" - "flag" - "fmt" - "io" - "os" - "reflect" - "regexp" - "sort" - "strconv" - "strings" - "sync" - "testing" -) - -var coverSpec = flag.Bool("coverspec", false, "Run spec coverage tests") - -// The global map of sentence coverage for the http2 spec. -var defaultSpecCoverage specCoverage - -var loadSpecOnce sync.Once - -func loadSpec() { - if f, err := os.Open("testdata/draft-ietf-httpbis-http2.xml"); err != nil { - panic(err) - } else { - defaultSpecCoverage = readSpecCov(f) - f.Close() - } -} - -// covers marks all sentences for section sec in defaultSpecCoverage. Sentences not -// "covered" will be included in report outputted by TestSpecCoverage. -func covers(sec, sentences string) { - loadSpecOnce.Do(loadSpec) - defaultSpecCoverage.cover(sec, sentences) -} - -type specPart struct { - section string - sentence string -} - -func (ss specPart) Less(oo specPart) bool { - atoi := func(s string) int { - n, err := strconv.Atoi(s) - if err != nil { - panic(err) - } - return n - } - a := strings.Split(ss.section, ".") - b := strings.Split(oo.section, ".") - for len(a) > 0 { - if len(b) == 0 { - return false - } - x, y := atoi(a[0]), atoi(b[0]) - if x == y { - a, b = a[1:], b[1:] - continue - } - return x < y - } - if len(b) > 0 { - return true - } - return false -} - -type bySpecSection []specPart - -func (a bySpecSection) Len() int { return len(a) } -func (a bySpecSection) Less(i, j int) bool { return a[i].Less(a[j]) } -func (a bySpecSection) Swap(i, j int) { a[i], a[j] = a[j], a[i] } - -type specCoverage struct { - coverage map[specPart]bool - d *xml.Decoder -} - -func joinSection(sec []int) string { - s := fmt.Sprintf("%d", sec[0]) - for _, n := range sec[1:] { - s = fmt.Sprintf("%s.%d", s, n) - } - return s -} - -func (sc specCoverage) readSection(sec []int) { - var ( - buf = new(bytes.Buffer) - sub = 0 - ) - for { - tk, err := sc.d.Token() - if err != nil { - if err == io.EOF { - return - } - panic(err) - } - switch v := tk.(type) { - case xml.StartElement: - if skipElement(v) { - if err := sc.d.Skip(); err != nil { - panic(err) - } - if v.Name.Local == "section" { - sub++ - } - break - } - switch v.Name.Local { - case "section": - sub++ - sc.readSection(append(sec, sub)) - case "xref": - buf.Write(sc.readXRef(v)) - } - case xml.CharData: - if len(sec) == 0 { - break - } - buf.Write(v) - case xml.EndElement: - if v.Name.Local == "section" { - sc.addSentences(joinSection(sec), buf.String()) - return - } - } - } -} - -func (sc specCoverage) readXRef(se xml.StartElement) []byte { - var b []byte - for { - tk, err := sc.d.Token() - if err != nil { - panic(err) - } - switch v := tk.(type) { - case xml.CharData: - if b != nil { - panic("unexpected CharData") - } - b = []byte(string(v)) - case xml.EndElement: - if v.Name.Local != "xref" { - panic("expected ") - } - if b != nil { - return b - } - sig := attrSig(se) - switch sig { - case "target": - return []byte(fmt.Sprintf("[%s]", attrValue(se, "target"))) - case "fmt-of,rel,target", "fmt-,,rel,target": - return []byte(fmt.Sprintf("[%s, %s]", attrValue(se, "target"), attrValue(se, "rel"))) - case "fmt-of,sec,target", "fmt-,,sec,target": - return []byte(fmt.Sprintf("[section %s of %s]", attrValue(se, "sec"), attrValue(se, "target"))) - case "fmt-of,rel,sec,target": - return []byte(fmt.Sprintf("[section %s of %s, %s]", attrValue(se, "sec"), attrValue(se, "target"), attrValue(se, "rel"))) - default: - panic(fmt.Sprintf("unknown attribute signature %q in %#v", sig, fmt.Sprintf("%#v", se))) - } - default: - panic(fmt.Sprintf("unexpected tag %q", v)) - } - } -} - -var skipAnchor = map[string]bool{ - "intro": true, - "Overview": true, -} - -var skipTitle = map[string]bool{ - "Acknowledgements": true, - "Change Log": true, - "Document Organization": true, - "Conventions and Terminology": true, -} - -func skipElement(s xml.StartElement) bool { - switch s.Name.Local { - case "artwork": - return true - case "section": - for _, attr := range s.Attr { - switch attr.Name.Local { - case "anchor": - if skipAnchor[attr.Value] || strings.HasPrefix(attr.Value, "changes.since.") { - return true - } - case "title": - if skipTitle[attr.Value] { - return true - } - } - } - } - return false -} - -func readSpecCov(r io.Reader) specCoverage { - sc := specCoverage{ - coverage: map[specPart]bool{}, - d: xml.NewDecoder(r)} - sc.readSection(nil) - return sc -} - -func (sc specCoverage) addSentences(sec string, sentence string) { - for _, s := range parseSentences(sentence) { - sc.coverage[specPart{sec, s}] = false - } -} - -func (sc specCoverage) cover(sec string, sentence string) { - for _, s := range parseSentences(sentence) { - p := specPart{sec, s} - if _, ok := sc.coverage[p]; !ok { - panic(fmt.Sprintf("Not found in spec: %q, %q", sec, s)) - } - sc.coverage[specPart{sec, s}] = true - } - -} - -var whitespaceRx = regexp.MustCompile(`\s+`) - -func parseSentences(sens string) []string { - sens = strings.TrimSpace(sens) - if sens == "" { - return nil - } - ss := strings.Split(whitespaceRx.ReplaceAllString(sens, " "), ". ") - for i, s := range ss { - s = strings.TrimSpace(s) - if !strings.HasSuffix(s, ".") { - s += "." - } - ss[i] = s - } - return ss -} - -func TestSpecParseSentences(t *testing.T) { - tests := []struct { - ss string - want []string - }{ - {"Sentence 1. Sentence 2.", - []string{ - "Sentence 1.", - "Sentence 2.", - }}, - {"Sentence 1. \nSentence 2.\tSentence 3.", - []string{ - "Sentence 1.", - "Sentence 2.", - "Sentence 3.", - }}, - } - - for i, tt := range tests { - got := parseSentences(tt.ss) - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("%d: got = %q, want %q", i, got, tt.want) - } - } -} - -func TestSpecCoverage(t *testing.T) { - if !*coverSpec { - t.Skip() - } - - loadSpecOnce.Do(loadSpec) - - var ( - list []specPart - cv = defaultSpecCoverage.coverage - total = len(cv) - complete = 0 - ) - - for sp, touched := range defaultSpecCoverage.coverage { - if touched { - complete++ - } else { - list = append(list, sp) - } - } - sort.Stable(bySpecSection(list)) - - if testing.Short() && len(list) > 5 { - list = list[:5] - } - - for _, p := range list { - t.Errorf("\tSECTION %s: %s", p.section, p.sentence) - } - - t.Logf("%d/%d (%d%%) sentences covered", complete, total, (complete/total)*100) -} - -func attrSig(se xml.StartElement) string { - var names []string - for _, attr := range se.Attr { - if attr.Name.Local == "fmt" { - names = append(names, "fmt-"+attr.Value) - } else { - names = append(names, attr.Name.Local) - } - } - sort.Strings(names) - return strings.Join(names, ",") -} - -func attrValue(se xml.StartElement, attr string) string { - for _, a := range se.Attr { - if a.Name.Local == attr { - return a.Value - } - } - panic("unknown attribute " + attr) -} - -func TestSpecPartLess(t *testing.T) { - tests := []struct { - sec1, sec2 string - want bool - }{ - {"6.2.1", "6.2", false}, - {"6.2", "6.2.1", true}, - {"6.10", "6.10.1", true}, - {"6.10", "6.1.1", false}, // 10, not 1 - {"6.1", "6.1", false}, // equal, so not less - } - for _, tt := range tests { - got := (specPart{tt.sec1, "foo"}).Less(specPart{tt.sec2, "foo"}) - if got != tt.want { - t.Errorf("Less(%q, %q) = %v; want %v", tt.sec1, tt.sec2, got, tt.want) - } - } -} diff --git a/vendor/golang.org/x/net/idna/example_test.go b/vendor/golang.org/x/net/idna/example_test.go deleted file mode 100644 index 948f6eb2..00000000 --- a/vendor/golang.org/x/net/idna/example_test.go +++ /dev/null @@ -1,70 +0,0 @@ -// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. - -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package idna_test - -import ( - "fmt" - - "golang.org/x/net/idna" -) - -func ExampleProfile() { - // Raw Punycode has no restrictions and does no mappings. - fmt.Println(idna.ToASCII("")) - fmt.Println(idna.ToASCII("*.faß.com")) - fmt.Println(idna.Punycode.ToASCII("*.faß.com")) - - // Rewrite IDN for lookup. This (currently) uses transitional mappings to - // find a balance between IDNA2003 and IDNA2008 compatibility. - fmt.Println(idna.Lookup.ToASCII("")) - fmt.Println(idna.Lookup.ToASCII("www.faß.com")) - - // Convert an IDN to ASCII for registration purposes. This changes the - // encoding, but reports an error if the input was illformed. - fmt.Println(idna.Registration.ToASCII("")) - fmt.Println(idna.Registration.ToASCII("www.faß.com")) - - // Output: - // - // *.xn--fa-hia.com - // *.xn--fa-hia.com - // - // www.fass.com - // idna: invalid label "" - // www.xn--fa-hia.com -} - -func ExampleNew() { - var p *idna.Profile - - // Raw Punycode has no restrictions and does no mappings. - p = idna.New() - fmt.Println(p.ToASCII("*.faß.com")) - - // Do mappings. Note that star is not allowed in a DNS lookup. - p = idna.New( - idna.MapForLookup(), - idna.Transitional(true)) // Map ß -> ss - fmt.Println(p.ToASCII("*.faß.com")) - - // Lookup for registration. Also does not allow '*'. - p = idna.New(idna.ValidateForRegistration()) - fmt.Println(p.ToUnicode("*.faß.com")) - - // Set up a profile maps for lookup, but allows wild cards. - p = idna.New( - idna.MapForLookup(), - idna.Transitional(true), // Map ß -> ss - idna.StrictDomainName(false)) // Set more permissive ASCII rules. - fmt.Println(p.ToASCII("*.faß.com")) - - // Output: - // *.xn--fa-hia.com - // *.fass.com idna: disallowed rune U+002A - // *.faß.com idna: disallowed rune U+002A - // *.fass.com -} diff --git a/vendor/golang.org/x/net/idna/idna_test.go b/vendor/golang.org/x/net/idna/idna_test.go deleted file mode 100644 index 0b067cac..00000000 --- a/vendor/golang.org/x/net/idna/idna_test.go +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package idna - -import ( - "testing" -) - -var idnaTestCases = [...]struct { - ascii, unicode string -}{ - // Labels. - {"books", "books"}, - {"xn--bcher-kva", "bücher"}, - - // Domains. - {"foo--xn--bar.org", "foo--xn--bar.org"}, - {"golang.org", "golang.org"}, - {"example.xn--p1ai", "example.рф"}, - {"xn--czrw28b.tw", "商業.tw"}, - {"www.xn--mller-kva.de", "www.müller.de"}, -} - -func TestIDNA(t *testing.T) { - for _, tc := range idnaTestCases { - if a, err := ToASCII(tc.unicode); err != nil { - t.Errorf("ToASCII(%q): %v", tc.unicode, err) - } else if a != tc.ascii { - t.Errorf("ToASCII(%q): got %q, want %q", tc.unicode, a, tc.ascii) - } - - if u, err := ToUnicode(tc.ascii); err != nil { - t.Errorf("ToUnicode(%q): %v", tc.ascii, err) - } else if u != tc.unicode { - t.Errorf("ToUnicode(%q): got %q, want %q", tc.ascii, u, tc.unicode) - } - } -} - -func TestIDNASeparators(t *testing.T) { - type subCase struct { - unicode string - wantASCII string - wantErr bool - } - - testCases := []struct { - name string - profile *Profile - subCases []subCase - }{ - { - name: "Punycode", profile: Punycode, - subCases: []subCase{ - {"example\u3002jp", "xn--examplejp-ck3h", false}, - {"東京\uFF0Ejp", "xn--jp-l92cn98g071o", false}, - {"大阪\uFF61jp", "xn--jp-ku9cz72u463f", false}, - }, - }, - { - name: "Lookup", profile: Lookup, - subCases: []subCase{ - {"example\u3002jp", "example.jp", false}, - {"東京\uFF0Ejp", "xn--1lqs71d.jp", false}, - {"大阪\uFF61jp", "xn--pssu33l.jp", false}, - }, - }, - { - name: "Display", profile: Display, - subCases: []subCase{ - {"example\u3002jp", "example.jp", false}, - {"東京\uFF0Ejp", "xn--1lqs71d.jp", false}, - {"大阪\uFF61jp", "xn--pssu33l.jp", false}, - }, - }, - { - name: "Registration", profile: Registration, - subCases: []subCase{ - {"example\u3002jp", "", true}, - {"東京\uFF0Ejp", "", true}, - {"大阪\uFF61jp", "", true}, - }, - }, - } - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - for _, c := range tc.subCases { - gotA, err := tc.profile.ToASCII(c.unicode) - if c.wantErr { - if err == nil { - t.Errorf("ToASCII(%q): got no error, but an error expected", c.unicode) - } - } else { - if err != nil { - t.Errorf("ToASCII(%q): got err=%v, but no error expected", c.unicode, err) - } else if gotA != c.wantASCII { - t.Errorf("ToASCII(%q): got %q, want %q", c.unicode, gotA, c.wantASCII) - } - } - } - }) - } -} - -// TODO(nigeltao): test errors, once we've specified when ToASCII and ToUnicode -// return errors. diff --git a/vendor/golang.org/x/net/idna/punycode_test.go b/vendor/golang.org/x/net/idna/punycode_test.go deleted file mode 100644 index bfec81de..00000000 --- a/vendor/golang.org/x/net/idna/punycode_test.go +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package idna - -import ( - "strings" - "testing" -) - -var punycodeTestCases = [...]struct { - s, encoded string -}{ - {"", ""}, - {"-", "--"}, - {"-a", "-a-"}, - {"-a-", "-a--"}, - {"a", "a-"}, - {"a-", "a--"}, - {"a-b", "a-b-"}, - {"books", "books-"}, - {"bücher", "bcher-kva"}, - {"Hello世界", "Hello-ck1hg65u"}, - {"ü", "tda"}, - {"üý", "tdac"}, - - // The test cases below come from RFC 3492 section 7.1 with Errata 3026. - { - // (A) Arabic (Egyptian). - "\u0644\u064A\u0647\u0645\u0627\u0628\u062A\u0643\u0644" + - "\u0645\u0648\u0634\u0639\u0631\u0628\u064A\u061F", - "egbpdaj6bu4bxfgehfvwxn", - }, - { - // (B) Chinese (simplified). - "\u4ED6\u4EEC\u4E3A\u4EC0\u4E48\u4E0D\u8BF4\u4E2D\u6587", - "ihqwcrb4cv8a8dqg056pqjye", - }, - { - // (C) Chinese (traditional). - "\u4ED6\u5011\u7232\u4EC0\u9EBD\u4E0D\u8AAA\u4E2D\u6587", - "ihqwctvzc91f659drss3x8bo0yb", - }, - { - // (D) Czech. - "\u0050\u0072\u006F\u010D\u0070\u0072\u006F\u0073\u0074" + - "\u011B\u006E\u0065\u006D\u006C\u0075\u0076\u00ED\u010D" + - "\u0065\u0073\u006B\u0079", - "Proprostnemluvesky-uyb24dma41a", - }, - { - // (E) Hebrew. - "\u05DC\u05DE\u05D4\u05D4\u05DD\u05E4\u05E9\u05D5\u05D8" + - "\u05DC\u05D0\u05DE\u05D3\u05D1\u05E8\u05D9\u05DD\u05E2" + - "\u05D1\u05E8\u05D9\u05EA", - "4dbcagdahymbxekheh6e0a7fei0b", - }, - { - // (F) Hindi (Devanagari). - "\u092F\u0939\u0932\u094B\u0917\u0939\u093F\u0928\u094D" + - "\u0926\u0940\u0915\u094D\u092F\u094B\u0902\u0928\u0939" + - "\u0940\u0902\u092C\u094B\u0932\u0938\u0915\u0924\u0947" + - "\u0939\u0948\u0902", - "i1baa7eci9glrd9b2ae1bj0hfcgg6iyaf8o0a1dig0cd", - }, - { - // (G) Japanese (kanji and hiragana). - "\u306A\u305C\u307F\u3093\u306A\u65E5\u672C\u8A9E\u3092" + - "\u8A71\u3057\u3066\u304F\u308C\u306A\u3044\u306E\u304B", - "n8jok5ay5dzabd5bym9f0cm5685rrjetr6pdxa", - }, - { - // (H) Korean (Hangul syllables). - "\uC138\uACC4\uC758\uBAA8\uB4E0\uC0AC\uB78C\uB4E4\uC774" + - "\uD55C\uAD6D\uC5B4\uB97C\uC774\uD574\uD55C\uB2E4\uBA74" + - "\uC5BC\uB9C8\uB098\uC88B\uC744\uAE4C", - "989aomsvi5e83db1d2a355cv1e0vak1dwrv93d5xbh15a0dt30a5j" + - "psd879ccm6fea98c", - }, - { - // (I) Russian (Cyrillic). - "\u043F\u043E\u0447\u0435\u043C\u0443\u0436\u0435\u043E" + - "\u043D\u0438\u043D\u0435\u0433\u043E\u0432\u043E\u0440" + - "\u044F\u0442\u043F\u043E\u0440\u0443\u0441\u0441\u043A" + - "\u0438", - "b1abfaaepdrnnbgefbadotcwatmq2g4l", - }, - { - // (J) Spanish. - "\u0050\u006F\u0072\u0071\u0075\u00E9\u006E\u006F\u0070" + - "\u0075\u0065\u0064\u0065\u006E\u0073\u0069\u006D\u0070" + - "\u006C\u0065\u006D\u0065\u006E\u0074\u0065\u0068\u0061" + - "\u0062\u006C\u0061\u0072\u0065\u006E\u0045\u0073\u0070" + - "\u0061\u00F1\u006F\u006C", - "PorqunopuedensimplementehablarenEspaol-fmd56a", - }, - { - // (K) Vietnamese. - "\u0054\u1EA1\u0069\u0073\u0061\u006F\u0068\u1ECD\u006B" + - "\u0068\u00F4\u006E\u0067\u0074\u0068\u1EC3\u0063\u0068" + - "\u1EC9\u006E\u00F3\u0069\u0074\u0069\u1EBF\u006E\u0067" + - "\u0056\u0069\u1EC7\u0074", - "TisaohkhngthchnitingVit-kjcr8268qyxafd2f1b9g", - }, - { - // (L) 3B. - "\u0033\u5E74\u0042\u7D44\u91D1\u516B\u5148\u751F", - "3B-ww4c5e180e575a65lsy2b", - }, - { - // (M) -with-SUPER-MONKEYS. - "\u5B89\u5BA4\u5948\u7F8E\u6075\u002D\u0077\u0069\u0074" + - "\u0068\u002D\u0053\u0055\u0050\u0045\u0052\u002D\u004D" + - "\u004F\u004E\u004B\u0045\u0059\u0053", - "-with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n", - }, - { - // (N) Hello-Another-Way-. - "\u0048\u0065\u006C\u006C\u006F\u002D\u0041\u006E\u006F" + - "\u0074\u0068\u0065\u0072\u002D\u0057\u0061\u0079\u002D" + - "\u305D\u308C\u305E\u308C\u306E\u5834\u6240", - "Hello-Another-Way--fc4qua05auwb3674vfr0b", - }, - { - // (O) 2. - "\u3072\u3068\u3064\u5C4B\u6839\u306E\u4E0B\u0032", - "2-u9tlzr9756bt3uc0v", - }, - { - // (P) MajiKoi5 - "\u004D\u0061\u006A\u0069\u3067\u004B\u006F\u0069\u3059" + - "\u308B\u0035\u79D2\u524D", - "MajiKoi5-783gue6qz075azm5e", - }, - { - // (Q) de - "\u30D1\u30D5\u30A3\u30FC\u0064\u0065\u30EB\u30F3\u30D0", - "de-jg4avhby1noc0d", - }, - { - // (R) - "\u305D\u306E\u30B9\u30D4\u30FC\u30C9\u3067", - "d9juau41awczczp", - }, - { - // (S) -> $1.00 <- - "\u002D\u003E\u0020\u0024\u0031\u002E\u0030\u0030\u0020" + - "\u003C\u002D", - "-> $1.00 <--", - }, -} - -func TestPunycode(t *testing.T) { - for _, tc := range punycodeTestCases { - if got, err := decode(tc.encoded); err != nil { - t.Errorf("decode(%q): %v", tc.encoded, err) - } else if got != tc.s { - t.Errorf("decode(%q): got %q, want %q", tc.encoded, got, tc.s) - } - - if got, err := encode("", tc.s); err != nil { - t.Errorf(`encode("", %q): %v`, tc.s, err) - } else if got != tc.encoded { - t.Errorf(`encode("", %q): got %q, want %q`, tc.s, got, tc.encoded) - } - } -} - -var punycodeErrorTestCases = [...]string{ - "decode -", // A sole '-' is invalid. - "decode foo\x00bar", // '\x00' is not in [0-9A-Za-z]. - "decode foo#bar", // '#' is not in [0-9A-Za-z]. - "decode foo\u00A3bar", // '\u00A3' is not in [0-9A-Za-z]. - "decode 9", // "9a" decodes to codepoint \u00A3; "9" is truncated. - "decode 99999a", // "99999a" decodes to codepoint \U0048A3C1, which is > \U0010FFFF. - "decode 9999999999a", // "9999999999a" overflows the int32 calculation. - - "encode " + strings.Repeat("x", 65536) + "\uff00", // int32 overflow. -} - -func TestPunycodeErrors(t *testing.T) { - for _, tc := range punycodeErrorTestCases { - var err error - switch { - case strings.HasPrefix(tc, "decode "): - _, err = decode(tc[7:]) - case strings.HasPrefix(tc, "encode "): - _, err = encode("", tc[7:]) - } - if err == nil { - if len(tc) > 256 { - tc = tc[:100] + "..." + tc[len(tc)-100:] - } - t.Errorf("no error for %s", tc) - } - } -} diff --git a/vendor/golang.org/x/net/internal/timeseries/timeseries_test.go b/vendor/golang.org/x/net/internal/timeseries/timeseries_test.go deleted file mode 100644 index 66325a91..00000000 --- a/vendor/golang.org/x/net/internal/timeseries/timeseries_test.go +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package timeseries - -import ( - "math" - "testing" - "time" -) - -func isNear(x *Float, y float64, tolerance float64) bool { - return math.Abs(x.Value()-y) < tolerance -} - -func isApproximate(x *Float, y float64) bool { - return isNear(x, y, 1e-2) -} - -func checkApproximate(t *testing.T, o Observable, y float64) { - x := o.(*Float) - if !isApproximate(x, y) { - t.Errorf("Wanted %g, got %g", y, x.Value()) - } -} - -func checkNear(t *testing.T, o Observable, y, tolerance float64) { - x := o.(*Float) - if !isNear(x, y, tolerance) { - t.Errorf("Wanted %g +- %g, got %g", y, tolerance, x.Value()) - } -} - -var baseTime = time.Date(2013, 1, 1, 0, 0, 0, 0, time.UTC) - -func tu(s int64) time.Time { - return baseTime.Add(time.Duration(s) * time.Second) -} - -func tu2(s int64, ns int64) time.Time { - return baseTime.Add(time.Duration(s)*time.Second + time.Duration(ns)*time.Nanosecond) -} - -func TestBasicTimeSeries(t *testing.T) { - ts := NewTimeSeries(NewFloat) - fo := new(Float) - *fo = Float(10) - ts.AddWithTime(fo, tu(1)) - ts.AddWithTime(fo, tu(1)) - ts.AddWithTime(fo, tu(1)) - ts.AddWithTime(fo, tu(1)) - checkApproximate(t, ts.Range(tu(0), tu(1)), 40) - checkApproximate(t, ts.Total(), 40) - ts.AddWithTime(fo, tu(3)) - ts.AddWithTime(fo, tu(3)) - ts.AddWithTime(fo, tu(3)) - checkApproximate(t, ts.Range(tu(0), tu(2)), 40) - checkApproximate(t, ts.Range(tu(2), tu(4)), 30) - checkApproximate(t, ts.Total(), 70) - ts.AddWithTime(fo, tu(1)) - ts.AddWithTime(fo, tu(1)) - checkApproximate(t, ts.Range(tu(0), tu(2)), 60) - checkApproximate(t, ts.Range(tu(2), tu(4)), 30) - checkApproximate(t, ts.Total(), 90) - *fo = Float(100) - ts.AddWithTime(fo, tu(100)) - checkApproximate(t, ts.Range(tu(99), tu(100)), 100) - checkApproximate(t, ts.Range(tu(0), tu(4)), 36) - checkApproximate(t, ts.Total(), 190) - *fo = Float(10) - ts.AddWithTime(fo, tu(1)) - ts.AddWithTime(fo, tu(1)) - checkApproximate(t, ts.Range(tu(0), tu(4)), 44) - checkApproximate(t, ts.Range(tu(37), tu2(100, 100e6)), 100) - checkApproximate(t, ts.Range(tu(50), tu2(100, 100e6)), 100) - checkApproximate(t, ts.Range(tu(99), tu2(100, 100e6)), 100) - checkApproximate(t, ts.Total(), 210) - - for i, l := range ts.ComputeRange(tu(36), tu(100), 64) { - if i == 63 { - checkApproximate(t, l, 100) - } else { - checkApproximate(t, l, 0) - } - } - - checkApproximate(t, ts.Range(tu(0), tu(100)), 210) - checkApproximate(t, ts.Range(tu(10), tu(100)), 100) - - for i, l := range ts.ComputeRange(tu(0), tu(100), 100) { - if i < 10 { - checkApproximate(t, l, 11) - } else if i >= 90 { - checkApproximate(t, l, 10) - } else { - checkApproximate(t, l, 0) - } - } -} - -func TestFloat(t *testing.T) { - f := Float(1) - if g, w := f.String(), "1"; g != w { - t.Errorf("Float(1).String = %q; want %q", g, w) - } - f2 := Float(2) - var o Observable = &f2 - f.Add(o) - if g, w := f.Value(), 3.0; g != w { - t.Errorf("Float post-add = %v; want %v", g, w) - } - f.Multiply(2) - if g, w := f.Value(), 6.0; g != w { - t.Errorf("Float post-multiply = %v; want %v", g, w) - } - f.Clear() - if g, w := f.Value(), 0.0; g != w { - t.Errorf("Float post-clear = %v; want %v", g, w) - } - f.CopyFrom(&f2) - if g, w := f.Value(), 2.0; g != w { - t.Errorf("Float post-CopyFrom = %v; want %v", g, w) - } -} - -type mockClock struct { - time time.Time -} - -func (m *mockClock) Time() time.Time { return m.time } -func (m *mockClock) Set(t time.Time) { m.time = t } - -const buckets = 6 - -var testResolutions = []time.Duration{ - 10 * time.Second, // level holds one minute of observations - 100 * time.Second, // level holds ten minutes of observations - 10 * time.Minute, // level holds one hour of observations -} - -// TestTimeSeries uses a small number of buckets to force a higher -// error rate on approximations from the timeseries. -type TestTimeSeries struct { - timeSeries -} - -func TestExpectedErrorRate(t *testing.T) { - ts := new(TestTimeSeries) - fake := new(mockClock) - fake.Set(time.Now()) - ts.timeSeries.init(testResolutions, NewFloat, buckets, fake) - for i := 1; i <= 61*61; i++ { - fake.Set(fake.Time().Add(1 * time.Second)) - ob := Float(1) - ts.AddWithTime(&ob, fake.Time()) - - // The results should be accurate within one missing bucket (1/6) of the observations recorded. - checkNear(t, ts.Latest(0, buckets), min(float64(i), 60), 10) - checkNear(t, ts.Latest(1, buckets), min(float64(i), 600), 100) - checkNear(t, ts.Latest(2, buckets), min(float64(i), 3600), 600) - } -} - -func min(a, b float64) float64 { - if a < b { - return a - } - return b -} diff --git a/vendor/golang.org/x/net/trace/histogram_test.go b/vendor/golang.org/x/net/trace/histogram_test.go deleted file mode 100644 index d384b933..00000000 --- a/vendor/golang.org/x/net/trace/histogram_test.go +++ /dev/null @@ -1,325 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package trace - -import ( - "math" - "testing" -) - -type sumTest struct { - value int64 - sum int64 - sumOfSquares float64 - total int64 -} - -var sumTests = []sumTest{ - {100, 100, 10000, 1}, - {50, 150, 12500, 2}, - {50, 200, 15000, 3}, - {50, 250, 17500, 4}, -} - -type bucketingTest struct { - in int64 - log int - bucket int -} - -var bucketingTests = []bucketingTest{ - {0, 0, 0}, - {1, 1, 0}, - {2, 2, 1}, - {3, 2, 1}, - {4, 3, 2}, - {1000, 10, 9}, - {1023, 10, 9}, - {1024, 11, 10}, - {1000000, 20, 19}, -} - -type multiplyTest struct { - in int64 - ratio float64 - expectedSum int64 - expectedTotal int64 - expectedSumOfSquares float64 -} - -var multiplyTests = []multiplyTest{ - {15, 2.5, 37, 2, 562.5}, - {128, 4.6, 758, 13, 77953.9}, -} - -type percentileTest struct { - fraction float64 - expected int64 -} - -var percentileTests = []percentileTest{ - {0.25, 48}, - {0.5, 96}, - {0.6, 109}, - {0.75, 128}, - {0.90, 205}, - {0.95, 230}, - {0.99, 256}, -} - -func TestSum(t *testing.T) { - var h histogram - - for _, test := range sumTests { - h.addMeasurement(test.value) - sum := h.sum - if sum != test.sum { - t.Errorf("h.Sum = %v WANT: %v", sum, test.sum) - } - - sumOfSquares := h.sumOfSquares - if sumOfSquares != test.sumOfSquares { - t.Errorf("h.SumOfSquares = %v WANT: %v", sumOfSquares, test.sumOfSquares) - } - - total := h.total() - if total != test.total { - t.Errorf("h.Total = %v WANT: %v", total, test.total) - } - } -} - -func TestMultiply(t *testing.T) { - var h histogram - for i, test := range multiplyTests { - h.addMeasurement(test.in) - h.Multiply(test.ratio) - if h.sum != test.expectedSum { - t.Errorf("#%v: h.sum = %v WANT: %v", i, h.sum, test.expectedSum) - } - if h.total() != test.expectedTotal { - t.Errorf("#%v: h.total = %v WANT: %v", i, h.total(), test.expectedTotal) - } - if h.sumOfSquares != test.expectedSumOfSquares { - t.Errorf("#%v: h.SumOfSquares = %v WANT: %v", i, test.expectedSumOfSquares, h.sumOfSquares) - } - } -} - -func TestBucketingFunctions(t *testing.T) { - for _, test := range bucketingTests { - log := log2(test.in) - if log != test.log { - t.Errorf("log2 = %v WANT: %v", log, test.log) - } - - bucket := getBucket(test.in) - if bucket != test.bucket { - t.Errorf("getBucket = %v WANT: %v", bucket, test.bucket) - } - } -} - -func TestAverage(t *testing.T) { - a := new(histogram) - average := a.average() - if average != 0 { - t.Errorf("Average of empty histogram was %v WANT: 0", average) - } - - a.addMeasurement(1) - a.addMeasurement(1) - a.addMeasurement(3) - const expected = float64(5) / float64(3) - average = a.average() - - if !isApproximate(average, expected) { - t.Errorf("Average = %g WANT: %v", average, expected) - } -} - -func TestStandardDeviation(t *testing.T) { - a := new(histogram) - add(a, 10, 1<<4) - add(a, 10, 1<<5) - add(a, 10, 1<<6) - stdDev := a.standardDeviation() - const expected = 19.95 - - if !isApproximate(stdDev, expected) { - t.Errorf("StandardDeviation = %v WANT: %v", stdDev, expected) - } - - // No values - a = new(histogram) - stdDev = a.standardDeviation() - - if !isApproximate(stdDev, 0) { - t.Errorf("StandardDeviation = %v WANT: 0", stdDev) - } - - add(a, 1, 1<<4) - if !isApproximate(stdDev, 0) { - t.Errorf("StandardDeviation = %v WANT: 0", stdDev) - } - - add(a, 10, 1<<4) - if !isApproximate(stdDev, 0) { - t.Errorf("StandardDeviation = %v WANT: 0", stdDev) - } -} - -func TestPercentileBoundary(t *testing.T) { - a := new(histogram) - add(a, 5, 1<<4) - add(a, 10, 1<<6) - add(a, 5, 1<<7) - - for _, test := range percentileTests { - percentile := a.percentileBoundary(test.fraction) - if percentile != test.expected { - t.Errorf("h.PercentileBoundary (fraction=%v) = %v WANT: %v", test.fraction, percentile, test.expected) - } - } -} - -func TestCopyFrom(t *testing.T) { - a := histogram{5, 25, []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38}, 4, -1} - b := histogram{6, 36, []int64{2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39}, 5, -1} - - a.CopyFrom(&b) - - if a.String() != b.String() { - t.Errorf("a.String = %s WANT: %s", a.String(), b.String()) - } -} - -func TestClear(t *testing.T) { - a := histogram{5, 25, []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38}, 4, -1} - - a.Clear() - - expected := "0, 0.000000, 0, 0, []" - if a.String() != expected { - t.Errorf("a.String = %s WANT %s", a.String(), expected) - } -} - -func TestNew(t *testing.T) { - a := histogram{5, 25, []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38}, 4, -1} - b := a.New() - - expected := "0, 0.000000, 0, 0, []" - if b.(*histogram).String() != expected { - t.Errorf("b.(*histogram).String = %s WANT: %s", b.(*histogram).String(), expected) - } -} - -func TestAdd(t *testing.T) { - // The tests here depend on the associativity of addMeasurement and Add. - // Add empty observation - a := histogram{5, 25, []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38}, 4, -1} - b := a.New() - - expected := a.String() - a.Add(b) - if a.String() != expected { - t.Errorf("a.String = %s WANT: %s", a.String(), expected) - } - - // Add same bucketed value, no new buckets - c := new(histogram) - d := new(histogram) - e := new(histogram) - c.addMeasurement(12) - d.addMeasurement(11) - e.addMeasurement(12) - e.addMeasurement(11) - c.Add(d) - if c.String() != e.String() { - t.Errorf("c.String = %s WANT: %s", c.String(), e.String()) - } - - // Add bucketed values - f := new(histogram) - g := new(histogram) - h := new(histogram) - f.addMeasurement(4) - f.addMeasurement(12) - f.addMeasurement(100) - g.addMeasurement(18) - g.addMeasurement(36) - g.addMeasurement(255) - h.addMeasurement(4) - h.addMeasurement(12) - h.addMeasurement(100) - h.addMeasurement(18) - h.addMeasurement(36) - h.addMeasurement(255) - f.Add(g) - if f.String() != h.String() { - t.Errorf("f.String = %q WANT: %q", f.String(), h.String()) - } - - // add buckets to no buckets - i := new(histogram) - j := new(histogram) - k := new(histogram) - j.addMeasurement(18) - j.addMeasurement(36) - j.addMeasurement(255) - k.addMeasurement(18) - k.addMeasurement(36) - k.addMeasurement(255) - i.Add(j) - if i.String() != k.String() { - t.Errorf("i.String = %q WANT: %q", i.String(), k.String()) - } - - // add buckets to single value (no overlap) - l := new(histogram) - m := new(histogram) - n := new(histogram) - l.addMeasurement(0) - m.addMeasurement(18) - m.addMeasurement(36) - m.addMeasurement(255) - n.addMeasurement(0) - n.addMeasurement(18) - n.addMeasurement(36) - n.addMeasurement(255) - l.Add(m) - if l.String() != n.String() { - t.Errorf("l.String = %q WANT: %q", l.String(), n.String()) - } - - // mixed order - o := new(histogram) - p := new(histogram) - o.addMeasurement(0) - o.addMeasurement(2) - o.addMeasurement(0) - p.addMeasurement(0) - p.addMeasurement(0) - p.addMeasurement(2) - if o.String() != p.String() { - t.Errorf("o.String = %q WANT: %q", o.String(), p.String()) - } -} - -func add(h *histogram, times int, val int64) { - for i := 0; i < times; i++ { - h.addMeasurement(val) - } -} - -func isApproximate(x, y float64) bool { - return math.Abs(x-y) < 1e-2 -} diff --git a/vendor/golang.org/x/net/trace/trace_test.go b/vendor/golang.org/x/net/trace/trace_test.go deleted file mode 100644 index bfd9dfe9..00000000 --- a/vendor/golang.org/x/net/trace/trace_test.go +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package trace - -import ( - "net/http" - "reflect" - "testing" -) - -type s struct{} - -func (s) String() string { return "lazy string" } - -// TestReset checks whether all the fields are zeroed after reset. -func TestReset(t *testing.T) { - tr := New("foo", "bar") - tr.LazyLog(s{}, false) - tr.LazyPrintf("%d", 1) - tr.SetRecycler(func(_ interface{}) {}) - tr.SetTraceInfo(3, 4) - tr.SetMaxEvents(100) - tr.SetError() - tr.Finish() - - tr.(*trace).reset() - - if !reflect.DeepEqual(tr, new(trace)) { - t.Errorf("reset didn't clear all fields: %+v", tr) - } -} - -// TestResetLog checks whether all the fields are zeroed after reset. -func TestResetLog(t *testing.T) { - el := NewEventLog("foo", "bar") - el.Printf("message") - el.Errorf("error") - el.Finish() - - el.(*eventLog).reset() - - if !reflect.DeepEqual(el, new(eventLog)) { - t.Errorf("reset didn't clear all fields: %+v", el) - } -} - -func TestAuthRequest(t *testing.T) { - testCases := []struct { - host string - want bool - }{ - {host: "192.168.23.1", want: false}, - {host: "192.168.23.1:8080", want: false}, - {host: "malformed remote addr", want: false}, - {host: "localhost", want: true}, - {host: "localhost:8080", want: true}, - {host: "127.0.0.1", want: true}, - {host: "127.0.0.1:8080", want: true}, - {host: "::1", want: true}, - {host: "[::1]:8080", want: true}, - } - for _, tt := range testCases { - req := &http.Request{RemoteAddr: tt.host} - any, sensitive := AuthRequest(req) - if any != tt.want || sensitive != tt.want { - t.Errorf("AuthRequest(%q) = %t, %t; want %t, %t", tt.host, any, sensitive, tt.want, tt.want) - } - } -} - -// TestParseTemplate checks that all templates used by this package are valid -// as they are parsed on first usage -func TestParseTemplate(t *testing.T) { - if tmpl := distTmpl(); tmpl == nil { - t.Error("invalid template returned from distTmpl()") - } - if tmpl := pageTmpl(); tmpl == nil { - t.Error("invalid template returned from pageTmpl()") - } - if tmpl := eventsTmpl(); tmpl == nil { - t.Error("invalid template returned from eventsTmpl()") - } -} - -func benchmarkTrace(b *testing.B, maxEvents, numEvents int) { - numSpans := (b.N + numEvents + 1) / numEvents - - for i := 0; i < numSpans; i++ { - tr := New("test", "test") - tr.SetMaxEvents(maxEvents) - for j := 0; j < numEvents; j++ { - tr.LazyPrintf("%d", j) - } - tr.Finish() - } -} - -func BenchmarkTrace_Default_2(b *testing.B) { - benchmarkTrace(b, 0, 2) -} - -func BenchmarkTrace_Default_10(b *testing.B) { - benchmarkTrace(b, 0, 10) -} - -func BenchmarkTrace_Default_100(b *testing.B) { - benchmarkTrace(b, 0, 100) -} - -func BenchmarkTrace_Default_1000(b *testing.B) { - benchmarkTrace(b, 0, 1000) -} - -func BenchmarkTrace_Default_10000(b *testing.B) { - benchmarkTrace(b, 0, 10000) -} - -func BenchmarkTrace_10_2(b *testing.B) { - benchmarkTrace(b, 10, 2) -} - -func BenchmarkTrace_10_10(b *testing.B) { - benchmarkTrace(b, 10, 10) -} - -func BenchmarkTrace_10_100(b *testing.B) { - benchmarkTrace(b, 10, 100) -} - -func BenchmarkTrace_10_1000(b *testing.B) { - benchmarkTrace(b, 10, 1000) -} - -func BenchmarkTrace_10_10000(b *testing.B) { - benchmarkTrace(b, 10, 10000) -} - -func BenchmarkTrace_100_2(b *testing.B) { - benchmarkTrace(b, 100, 2) -} - -func BenchmarkTrace_100_10(b *testing.B) { - benchmarkTrace(b, 100, 10) -} - -func BenchmarkTrace_100_100(b *testing.B) { - benchmarkTrace(b, 100, 100) -} - -func BenchmarkTrace_100_1000(b *testing.B) { - benchmarkTrace(b, 100, 1000) -} - -func BenchmarkTrace_100_10000(b *testing.B) { - benchmarkTrace(b, 100, 10000) -} - -func BenchmarkTrace_1000_2(b *testing.B) { - benchmarkTrace(b, 1000, 2) -} - -func BenchmarkTrace_1000_10(b *testing.B) { - benchmarkTrace(b, 1000, 10) -} - -func BenchmarkTrace_1000_100(b *testing.B) { - benchmarkTrace(b, 1000, 100) -} - -func BenchmarkTrace_1000_1000(b *testing.B) { - benchmarkTrace(b, 1000, 1000) -} - -func BenchmarkTrace_1000_10000(b *testing.B) { - benchmarkTrace(b, 1000, 10000) -} diff --git a/vendor/golang.org/x/sync/CONTRIBUTING.md b/vendor/golang.org/x/sync/CONTRIBUTING.md deleted file mode 100644 index d0485e88..00000000 --- a/vendor/golang.org/x/sync/CONTRIBUTING.md +++ /dev/null @@ -1,26 +0,0 @@ -# Contributing to Go - -Go is an open source project. - -It is the work of hundreds of contributors. We appreciate your help! - -## Filing issues - -When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions: - -1. What version of Go are you using (`go version`)? -2. What operating system and processor architecture are you using? -3. What did you do? -4. What did you expect to see? -5. What did you see instead? - -General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker. -The gophers there will answer or ask you to file an issue if you've tripped over a bug. - -## Contributing code - -Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html) -before sending patches. - -Unless otherwise noted, the Go source files are distributed under -the BSD-style license found in the LICENSE file. diff --git a/vendor/golang.org/x/sync/README.md b/vendor/golang.org/x/sync/README.md deleted file mode 100644 index 1f8436cc..00000000 --- a/vendor/golang.org/x/sync/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# Go Sync - -This repository provides Go concurrency primitives in addition to the -ones provided by the language and "sync" and "sync/atomic" packages. - -## Download/Install - -The easiest way to install is to run `go get -u golang.org/x/sync`. You can -also manually git clone the repository to `$GOPATH/src/golang.org/x/sync`. - -## Report Issues / Send Patches - -This repository uses Gerrit for code changes. To learn how to submit changes to -this repository, see https://golang.org/doc/contribute.html. - -The main issue tracker for the sync repository is located at -https://github.com/golang/go/issues. Prefix your issue with "x/sync:" in the -subject line, so it is easy to find. diff --git a/vendor/golang.org/x/sync/codereview.cfg b/vendor/golang.org/x/sync/codereview.cfg deleted file mode 100644 index 3f8b14b6..00000000 --- a/vendor/golang.org/x/sync/codereview.cfg +++ /dev/null @@ -1 +0,0 @@ -issuerepo: golang/go diff --git a/vendor/golang.org/x/sync/semaphore/semaphore_bench_test.go b/vendor/golang.org/x/sync/semaphore/semaphore_bench_test.go deleted file mode 100644 index f96d349e..00000000 --- a/vendor/golang.org/x/sync/semaphore/semaphore_bench_test.go +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build go1.7 - -package semaphore_test - -import ( - "context" - "fmt" - "testing" - - "golang.org/x/sync/semaphore" -) - -// weighted is an interface matching a subset of *Weighted. It allows -// alternate implementations for testing and benchmarking. -type weighted interface { - Acquire(context.Context, int64) error - TryAcquire(int64) bool - Release(int64) -} - -// semChan implements Weighted using a channel for -// comparing against the condition variable-based implementation. -type semChan chan struct{} - -func newSemChan(n int64) semChan { - return semChan(make(chan struct{}, n)) -} - -func (s semChan) Acquire(_ context.Context, n int64) error { - for i := int64(0); i < n; i++ { - s <- struct{}{} - } - return nil -} - -func (s semChan) TryAcquire(n int64) bool { - if int64(len(s))+n > int64(cap(s)) { - return false - } - - for i := int64(0); i < n; i++ { - s <- struct{}{} - } - return true -} - -func (s semChan) Release(n int64) { - for i := int64(0); i < n; i++ { - <-s - } -} - -// acquireN calls Acquire(size) on sem N times and then calls Release(size) N times. -func acquireN(b *testing.B, sem weighted, size int64, N int) { - b.ResetTimer() - for i := 0; i < b.N; i++ { - for j := 0; j < N; j++ { - sem.Acquire(context.Background(), size) - } - for j := 0; j < N; j++ { - sem.Release(size) - } - } -} - -// tryAcquireN calls TryAcquire(size) on sem N times and then calls Release(size) N times. -func tryAcquireN(b *testing.B, sem weighted, size int64, N int) { - b.ResetTimer() - for i := 0; i < b.N; i++ { - for j := 0; j < N; j++ { - if !sem.TryAcquire(size) { - b.Fatalf("TryAcquire(%v) = false, want true", size) - } - } - for j := 0; j < N; j++ { - sem.Release(size) - } - } -} - -func BenchmarkNewSeq(b *testing.B) { - for _, cap := range []int64{1, 128} { - b.Run(fmt.Sprintf("Weighted-%d", cap), func(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = semaphore.NewWeighted(cap) - } - }) - b.Run(fmt.Sprintf("semChan-%d", cap), func(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = newSemChan(cap) - } - }) - } -} - -func BenchmarkAcquireSeq(b *testing.B) { - for _, c := range []struct { - cap, size int64 - N int - }{ - {1, 1, 1}, - {2, 1, 1}, - {16, 1, 1}, - {128, 1, 1}, - {2, 2, 1}, - {16, 2, 8}, - {128, 2, 64}, - {2, 1, 2}, - {16, 8, 2}, - {128, 64, 2}, - } { - for _, w := range []struct { - name string - w weighted - }{ - {"Weighted", semaphore.NewWeighted(c.cap)}, - {"semChan", newSemChan(c.cap)}, - } { - b.Run(fmt.Sprintf("%s-acquire-%d-%d-%d", w.name, c.cap, c.size, c.N), func(b *testing.B) { - acquireN(b, w.w, c.size, c.N) - }) - b.Run(fmt.Sprintf("%s-tryAcquire-%d-%d-%d", w.name, c.cap, c.size, c.N), func(b *testing.B) { - tryAcquireN(b, w.w, c.size, c.N) - }) - } - } -} diff --git a/vendor/golang.org/x/sync/semaphore/semaphore_example_test.go b/vendor/golang.org/x/sync/semaphore/semaphore_example_test.go deleted file mode 100644 index e75cd79f..00000000 --- a/vendor/golang.org/x/sync/semaphore/semaphore_example_test.go +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package semaphore_test - -import ( - "context" - "fmt" - "log" - "runtime" - - "golang.org/x/sync/semaphore" -) - -// Example_workerPool demonstrates how to use a semaphore to limit the number of -// goroutines working on parallel tasks. -// -// This use of a semaphore mimics a typical “worker pool” pattern, but without -// the need to explicitly shut down idle workers when the work is done. -func Example_workerPool() { - ctx := context.TODO() - - var ( - maxWorkers = runtime.GOMAXPROCS(0) - sem = semaphore.NewWeighted(int64(maxWorkers)) - out = make([]int, 32) - ) - - // Compute the output using up to maxWorkers goroutines at a time. - for i := range out { - // When maxWorkers goroutines are in flight, Acquire blocks until one of the - // workers finishes. - if err := sem.Acquire(ctx, 1); err != nil { - log.Printf("Failed to acquire semaphore: %v", err) - break - } - - go func(i int) { - defer sem.Release(1) - out[i] = collatzSteps(i + 1) - }(i) - } - - // Acquire all of the tokens to wait for any remaining workers to finish. - // - // If you are already waiting for the workers by some other means (such as an - // errgroup.Group), you can omit this final Acquire call. - if err := sem.Acquire(ctx, int64(maxWorkers)); err != nil { - log.Printf("Failed to acquire semaphore: %v", err) - } - - fmt.Println(out) - - // Output: - // [0 1 7 2 5 8 16 3 19 6 14 9 9 17 17 4 12 20 20 7 7 15 15 10 23 10 111 18 18 18 106 5] -} - -// collatzSteps computes the number of steps to reach 1 under the Collatz -// conjecture. (See https://en.wikipedia.org/wiki/Collatz_conjecture.) -func collatzSteps(n int) (steps int) { - if n <= 0 { - panic("nonpositive input") - } - - for ; n > 1; steps++ { - if steps < 0 { - panic("too many steps") - } - - if n%2 == 0 { - n /= 2 - continue - } - - const maxInt = int(^uint(0) >> 1) - if n > (maxInt-1)/3 { - panic("overflow") - } - n = 3*n + 1 - } - - return steps -} diff --git a/vendor/golang.org/x/sync/semaphore/semaphore_test.go b/vendor/golang.org/x/sync/semaphore/semaphore_test.go deleted file mode 100644 index b5f8f133..00000000 --- a/vendor/golang.org/x/sync/semaphore/semaphore_test.go +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package semaphore_test - -import ( - "context" - "math/rand" - "runtime" - "sync" - "testing" - "time" - - "golang.org/x/sync/errgroup" - "golang.org/x/sync/semaphore" -) - -const maxSleep = 1 * time.Millisecond - -func HammerWeighted(sem *semaphore.Weighted, n int64, loops int) { - for i := 0; i < loops; i++ { - sem.Acquire(context.Background(), n) - time.Sleep(time.Duration(rand.Int63n(int64(maxSleep/time.Nanosecond))) * time.Nanosecond) - sem.Release(n) - } -} - -func TestWeighted(t *testing.T) { - t.Parallel() - - n := runtime.GOMAXPROCS(0) - loops := 10000 / n - sem := semaphore.NewWeighted(int64(n)) - var wg sync.WaitGroup - wg.Add(n) - for i := 0; i < n; i++ { - i := i - go func() { - defer wg.Done() - HammerWeighted(sem, int64(i), loops) - }() - } - wg.Wait() -} - -func TestWeightedPanic(t *testing.T) { - t.Parallel() - - defer func() { - if recover() == nil { - t.Fatal("release of an unacquired weighted semaphore did not panic") - } - }() - w := semaphore.NewWeighted(1) - w.Release(1) -} - -func TestWeightedTryAcquire(t *testing.T) { - t.Parallel() - - ctx := context.Background() - sem := semaphore.NewWeighted(2) - tries := []bool{} - sem.Acquire(ctx, 1) - tries = append(tries, sem.TryAcquire(1)) - tries = append(tries, sem.TryAcquire(1)) - - sem.Release(2) - - tries = append(tries, sem.TryAcquire(1)) - sem.Acquire(ctx, 1) - tries = append(tries, sem.TryAcquire(1)) - - want := []bool{true, false, true, false} - for i := range tries { - if tries[i] != want[i] { - t.Errorf("tries[%d]: got %t, want %t", i, tries[i], want[i]) - } - } -} - -func TestWeightedAcquire(t *testing.T) { - t.Parallel() - - ctx := context.Background() - sem := semaphore.NewWeighted(2) - tryAcquire := func(n int64) bool { - ctx, cancel := context.WithTimeout(ctx, 10*time.Millisecond) - defer cancel() - return sem.Acquire(ctx, n) == nil - } - - tries := []bool{} - sem.Acquire(ctx, 1) - tries = append(tries, tryAcquire(1)) - tries = append(tries, tryAcquire(1)) - - sem.Release(2) - - tries = append(tries, tryAcquire(1)) - sem.Acquire(ctx, 1) - tries = append(tries, tryAcquire(1)) - - want := []bool{true, false, true, false} - for i := range tries { - if tries[i] != want[i] { - t.Errorf("tries[%d]: got %t, want %t", i, tries[i], want[i]) - } - } -} - -func TestWeightedDoesntBlockIfTooBig(t *testing.T) { - t.Parallel() - - const n = 2 - sem := semaphore.NewWeighted(n) - { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - go sem.Acquire(ctx, n+1) - } - - g, ctx := errgroup.WithContext(context.Background()) - for i := n * 3; i > 0; i-- { - g.Go(func() error { - err := sem.Acquire(ctx, 1) - if err == nil { - time.Sleep(1 * time.Millisecond) - sem.Release(1) - } - return err - }) - } - if err := g.Wait(); err != nil { - t.Errorf("semaphore.NewWeighted(%v) failed to AcquireCtx(_, 1) with AcquireCtx(_, %v) pending", n, n+1) - } -} - -// TestLargeAcquireDoesntStarve times out if a large call to Acquire starves. -// Merely returning from the test function indicates success. -func TestLargeAcquireDoesntStarve(t *testing.T) { - t.Parallel() - - ctx := context.Background() - n := int64(runtime.GOMAXPROCS(0)) - sem := semaphore.NewWeighted(n) - running := true - - var wg sync.WaitGroup - wg.Add(int(n)) - for i := n; i > 0; i-- { - sem.Acquire(ctx, 1) - go func() { - defer func() { - sem.Release(1) - wg.Done() - }() - for running { - time.Sleep(1 * time.Millisecond) - sem.Release(1) - sem.Acquire(ctx, 1) - } - }() - } - - sem.Acquire(ctx, n) - running = false - sem.Release(n) - wg.Wait() -} diff --git a/vendor/golang.org/x/sys/CONTRIBUTING.md b/vendor/golang.org/x/sys/CONTRIBUTING.md deleted file mode 100644 index d0485e88..00000000 --- a/vendor/golang.org/x/sys/CONTRIBUTING.md +++ /dev/null @@ -1,26 +0,0 @@ -# Contributing to Go - -Go is an open source project. - -It is the work of hundreds of contributors. We appreciate your help! - -## Filing issues - -When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions: - -1. What version of Go are you using (`go version`)? -2. What operating system and processor architecture are you using? -3. What did you do? -4. What did you expect to see? -5. What did you see instead? - -General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker. -The gophers there will answer or ask you to file an issue if you've tripped over a bug. - -## Contributing code - -Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html) -before sending patches. - -Unless otherwise noted, the Go source files are distributed under -the BSD-style license found in the LICENSE file. diff --git a/vendor/golang.org/x/sys/README.md b/vendor/golang.org/x/sys/README.md deleted file mode 100644 index ef6c9e59..00000000 --- a/vendor/golang.org/x/sys/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# sys - -This repository holds supplemental Go packages for low-level interactions with -the operating system. - -## Download/Install - -The easiest way to install is to run `go get -u golang.org/x/sys`. You can -also manually git clone the repository to `$GOPATH/src/golang.org/x/sys`. - -## Report Issues / Send Patches - -This repository uses Gerrit for code changes. To learn how to submit changes to -this repository, see https://golang.org/doc/contribute.html. - -The main issue tracker for the sys repository is located at -https://github.com/golang/go/issues. Prefix your issue with "x/sys:" in the -subject line, so it is easy to find. diff --git a/vendor/golang.org/x/sys/codereview.cfg b/vendor/golang.org/x/sys/codereview.cfg deleted file mode 100644 index 3f8b14b6..00000000 --- a/vendor/golang.org/x/sys/codereview.cfg +++ /dev/null @@ -1 +0,0 @@ -issuerepo: golang/go diff --git a/vendor/golang.org/x/sys/unix/README.md b/vendor/golang.org/x/sys/unix/README.md deleted file mode 100644 index 2bf415fb..00000000 --- a/vendor/golang.org/x/sys/unix/README.md +++ /dev/null @@ -1,173 +0,0 @@ -# Building `sys/unix` - -The sys/unix package provides access to the raw system call interface of the -underlying operating system. See: https://godoc.org/golang.org/x/sys/unix - -Porting Go to a new architecture/OS combination or adding syscalls, types, or -constants to an existing architecture/OS pair requires some manual effort; -however, there are tools that automate much of the process. - -## Build Systems - -There are currently two ways we generate the necessary files. We are currently -migrating the build system to use containers so the builds are reproducible. -This is being done on an OS-by-OS basis. Please update this documentation as -components of the build system change. - -### Old Build System (currently for `GOOS != "linux"`) - -The old build system generates the Go files based on the C header files -present on your system. This means that files -for a given GOOS/GOARCH pair must be generated on a system with that OS and -architecture. This also means that the generated code can differ from system -to system, based on differences in the header files. - -To avoid this, if you are using the old build system, only generate the Go -files on an installation with unmodified header files. It is also important to -keep track of which version of the OS the files were generated from (ex. -Darwin 14 vs Darwin 15). This makes it easier to track the progress of changes -and have each OS upgrade correspond to a single change. - -To build the files for your current OS and architecture, make sure GOOS and -GOARCH are set correctly and run `mkall.sh`. This will generate the files for -your specific system. Running `mkall.sh -n` shows the commands that will be run. - -Requirements: bash, perl, go - -### New Build System (currently for `GOOS == "linux"`) - -The new build system uses a Docker container to generate the go files directly -from source checkouts of the kernel and various system libraries. This means -that on any platform that supports Docker, all the files using the new build -system can be generated at once, and generated files will not change based on -what the person running the scripts has installed on their computer. - -The OS specific files for the new build system are located in the `${GOOS}` -directory, and the build is coordinated by the `${GOOS}/mkall.go` program. When -the kernel or system library updates, modify the Dockerfile at -`${GOOS}/Dockerfile` to checkout the new release of the source. - -To build all the files under the new build system, you must be on an amd64/Linux -system and have your GOOS and GOARCH set accordingly. Running `mkall.sh` will -then generate all of the files for all of the GOOS/GOARCH pairs in the new build -system. Running `mkall.sh -n` shows the commands that will be run. - -Requirements: bash, perl, go, docker - -## Component files - -This section describes the various files used in the code generation process. -It also contains instructions on how to modify these files to add a new -architecture/OS or to add additional syscalls, types, or constants. Note that -if you are using the new build system, the scripts cannot be called normally. -They must be called from within the docker container. - -### asm files - -The hand-written assembly file at `asm_${GOOS}_${GOARCH}.s` implements system -call dispatch. There are three entry points: -``` - func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) - func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) - func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) -``` -The first and second are the standard ones; they differ only in how many -arguments can be passed to the kernel. The third is for low-level use by the -ForkExec wrapper. Unlike the first two, it does not call into the scheduler to -let it know that a system call is running. - -When porting Go to an new architecture/OS, this file must be implemented for -each GOOS/GOARCH pair. - -### mksysnum - -Mksysnum is a script located at `${GOOS}/mksysnum.pl` (or `mksysnum_${GOOS}.pl` -for the old system). This script takes in a list of header files containing the -syscall number declarations and parses them to produce the corresponding list of -Go numeric constants. See `zsysnum_${GOOS}_${GOARCH}.go` for the generated -constants. - -Adding new syscall numbers is mostly done by running the build on a sufficiently -new installation of the target OS (or updating the source checkouts for the -new build system). However, depending on the OS, you make need to update the -parsing in mksysnum. - -### mksyscall.pl - -The `syscall.go`, `syscall_${GOOS}.go`, `syscall_${GOOS}_${GOARCH}.go` are -hand-written Go files which implement system calls (for unix, the specific OS, -or the specific OS/Architecture pair respectively) that need special handling -and list `//sys` comments giving prototypes for ones that can be generated. - -The mksyscall.pl script takes the `//sys` and `//sysnb` comments and converts -them into syscalls. This requires the name of the prototype in the comment to -match a syscall number in the `zsysnum_${GOOS}_${GOARCH}.go` file. The function -prototype can be exported (capitalized) or not. - -Adding a new syscall often just requires adding a new `//sys` function prototype -with the desired arguments and a capitalized name so it is exported. However, if -you want the interface to the syscall to be different, often one will make an -unexported `//sys` prototype, an then write a custom wrapper in -`syscall_${GOOS}.go`. - -### types files - -For each OS, there is a hand-written Go file at `${GOOS}/types.go` (or -`types_${GOOS}.go` on the old system). This file includes standard C headers and -creates Go type aliases to the corresponding C types. The file is then fed -through godef to get the Go compatible definitions. Finally, the generated code -is fed though mkpost.go to format the code correctly and remove any hidden or -private identifiers. This cleaned-up code is written to -`ztypes_${GOOS}_${GOARCH}.go`. - -The hardest part about preparing this file is figuring out which headers to -include and which symbols need to be `#define`d to get the actual data -structures that pass through to the kernel system calls. Some C libraries -preset alternate versions for binary compatibility and translate them on the -way in and out of system calls, but there is almost always a `#define` that can -get the real ones. -See `types_darwin.go` and `linux/types.go` for examples. - -To add a new type, add in the necessary include statement at the top of the -file (if it is not already there) and add in a type alias line. Note that if -your type is significantly different on different architectures, you may need -some `#if/#elif` macros in your include statements. - -### mkerrors.sh - -This script is used to generate the system's various constants. This doesn't -just include the error numbers and error strings, but also the signal numbers -an a wide variety of miscellaneous constants. The constants come from the list -of include files in the `includes_${uname}` variable. A regex then picks out -the desired `#define` statements, and generates the corresponding Go constants. -The error numbers and strings are generated from `#include `, and the -signal numbers and strings are generated from `#include `. All of -these constants are written to `zerrors_${GOOS}_${GOARCH}.go` via a C program, -`_errors.c`, which prints out all the constants. - -To add a constant, add the header that includes it to the appropriate variable. -Then, edit the regex (if necessary) to match the desired constant. Avoid making -the regex too broad to avoid matching unintended constants. - - -## Generated files - -### `zerror_${GOOS}_${GOARCH}.go` - -A file containing all of the system's generated error numbers, error strings, -signal numbers, and constants. Generated by `mkerrors.sh` (see above). - -### `zsyscall_${GOOS}_${GOARCH}.go` - -A file containing all the generated syscalls for a specific GOOS and GOARCH. -Generated by `mksyscall.pl` (see above). - -### `zsysnum_${GOOS}_${GOARCH}.go` - -A list of numeric constants for all the syscall number of the specific GOOS -and GOARCH. Generated by mksysnum (see above). - -### `ztypes_${GOOS}_${GOARCH}.go` - -A file containing Go types for passing into (or returning from) syscalls. -Generated by godefs and the types file (see above). diff --git a/vendor/golang.org/x/sys/unix/creds_test.go b/vendor/golang.org/x/sys/unix/creds_test.go deleted file mode 100644 index 1b508319..00000000 --- a/vendor/golang.org/x/sys/unix/creds_test.go +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build linux - -package unix_test - -import ( - "bytes" - "go/build" - "net" - "os" - "testing" - - "golang.org/x/sys/unix" -) - -// TestSCMCredentials tests the sending and receiving of credentials -// (PID, UID, GID) in an ancillary message between two UNIX -// sockets. The SO_PASSCRED socket option is enabled on the sending -// socket for this to work. -func TestSCMCredentials(t *testing.T) { - socketTypeTests := []struct { - socketType int - dataLen int - }{ - { - unix.SOCK_STREAM, - 1, - }, { - unix.SOCK_DGRAM, - 0, - }, - } - - for _, tt := range socketTypeTests { - if tt.socketType == unix.SOCK_DGRAM && !atLeast1p10() { - t.Log("skipping DGRAM test on pre-1.10") - continue - } - - fds, err := unix.Socketpair(unix.AF_LOCAL, tt.socketType, 0) - if err != nil { - t.Fatalf("Socketpair: %v", err) - } - defer unix.Close(fds[0]) - defer unix.Close(fds[1]) - - err = unix.SetsockoptInt(fds[0], unix.SOL_SOCKET, unix.SO_PASSCRED, 1) - if err != nil { - t.Fatalf("SetsockoptInt: %v", err) - } - - srvFile := os.NewFile(uintptr(fds[0]), "server") - defer srvFile.Close() - srv, err := net.FileConn(srvFile) - if err != nil { - t.Errorf("FileConn: %v", err) - return - } - defer srv.Close() - - cliFile := os.NewFile(uintptr(fds[1]), "client") - defer cliFile.Close() - cli, err := net.FileConn(cliFile) - if err != nil { - t.Errorf("FileConn: %v", err) - return - } - defer cli.Close() - - var ucred unix.Ucred - ucred.Pid = int32(os.Getpid()) - ucred.Uid = uint32(os.Getuid()) - ucred.Gid = uint32(os.Getgid()) - oob := unix.UnixCredentials(&ucred) - - // On SOCK_STREAM, this is internally going to send a dummy byte - n, oobn, err := cli.(*net.UnixConn).WriteMsgUnix(nil, oob, nil) - if err != nil { - t.Fatalf("WriteMsgUnix: %v", err) - } - if n != 0 { - t.Fatalf("WriteMsgUnix n = %d, want 0", n) - } - if oobn != len(oob) { - t.Fatalf("WriteMsgUnix oobn = %d, want %d", oobn, len(oob)) - } - - oob2 := make([]byte, 10*len(oob)) - n, oobn2, flags, _, err := srv.(*net.UnixConn).ReadMsgUnix(nil, oob2) - if err != nil { - t.Fatalf("ReadMsgUnix: %v", err) - } - if flags != 0 { - t.Fatalf("ReadMsgUnix flags = 0x%x, want 0", flags) - } - if n != tt.dataLen { - t.Fatalf("ReadMsgUnix n = %d, want %d", n, tt.dataLen) - } - if oobn2 != oobn { - // without SO_PASSCRED set on the socket, ReadMsgUnix will - // return zero oob bytes - t.Fatalf("ReadMsgUnix oobn = %d, want %d", oobn2, oobn) - } - oob2 = oob2[:oobn2] - if !bytes.Equal(oob, oob2) { - t.Fatal("ReadMsgUnix oob bytes don't match") - } - - scm, err := unix.ParseSocketControlMessage(oob2) - if err != nil { - t.Fatalf("ParseSocketControlMessage: %v", err) - } - newUcred, err := unix.ParseUnixCredentials(&scm[0]) - if err != nil { - t.Fatalf("ParseUnixCredentials: %v", err) - } - if *newUcred != ucred { - t.Fatalf("ParseUnixCredentials = %+v, want %+v", newUcred, ucred) - } - } -} - -// atLeast1p10 reports whether we are running on Go 1.10 or later. -func atLeast1p10() bool { - for _, ver := range build.Default.ReleaseTags { - if ver == "go1.10" { - return true - } - } - return false -} diff --git a/vendor/golang.org/x/sys/unix/darwin_test.go b/vendor/golang.org/x/sys/unix/darwin_test.go deleted file mode 100644 index 29af36f1..00000000 --- a/vendor/golang.org/x/sys/unix/darwin_test.go +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build darwin,go1.12,amd64 darwin,go1.12,386 - -package unix - -import ( - "os" - "os/exec" - "strings" - "testing" -) - -type darwinTest struct { - name string - f func() -} - -// TODO(khr): decide whether to keep this test enabled permanently or -// only temporarily. -func TestDarwinLoader(t *testing.T) { - // Make sure the Darwin dynamic loader can actually resolve - // all the system calls into libSystem.dylib. Unfortunately - // there is no easy way to test this at compile time. So we - // implement a crazy hack here, calling into the syscall - // function with all its arguments set to junk, and see what - // error we get. We are happy with any error (or none) except - // an error from the dynamic loader. - // - // We have to run each test in a separate subprocess for fault isolation. - // - // Hopefully the junk args won't accidentally ask the system to do "rm -fr /". - // - // In an ideal world each syscall would have its own test, so this test - // would be unnecessary. Unfortunately, we do not live in that world. - for _, test := range darwinTests { - // Call the test binary recursively, giving it a magic argument - // (see init below) and the name of the test to run. - cmd := exec.Command(os.Args[0], "testDarwinLoader", test.name) - - // Run subprocess, collect results. Note that we expect the subprocess - // to fail somehow, so the error is irrelevant. - out, _ := cmd.CombinedOutput() - - if strings.Contains(string(out), "dyld: Symbol not found:") { - t.Errorf("can't resolve %s in libSystem.dylib", test.name) - } - if !strings.Contains(string(out), "success") { - // Not really an error. Might be a syscall that never returns, - // like exit, or one that segfaults, like gettimeofday. - t.Logf("test never finished: %s: %s", test.name, string(out)) - } - } -} - -func init() { - // The test binary execs itself with the "testDarwinLoader" argument. - // Run the test specified by os.Args[2], then panic. - if len(os.Args) >= 3 && os.Args[1] == "testDarwinLoader" { - for _, test := range darwinTests { - if test.name == os.Args[2] { - test.f() - } - } - // Panic with a "success" label, so the parent process can check it. - panic("success") - } -} - -// All the _trampoline functions in zsyscall_darwin_$ARCH.s -var darwinTests = [...]darwinTest{ - {"getgroups", libc_getgroups_trampoline}, - {"setgroups", libc_setgroups_trampoline}, - {"wait4", libc_wait4_trampoline}, - {"accept", libc_accept_trampoline}, - {"bind", libc_bind_trampoline}, - {"connect", libc_connect_trampoline}, - {"socket", libc_socket_trampoline}, - {"getsockopt", libc_getsockopt_trampoline}, - {"setsockopt", libc_setsockopt_trampoline}, - {"getpeername", libc_getpeername_trampoline}, - {"getsockname", libc_getsockname_trampoline}, - {"shutdown", libc_shutdown_trampoline}, - {"socketpair", libc_socketpair_trampoline}, - {"recvfrom", libc_recvfrom_trampoline}, - {"sendto", libc_sendto_trampoline}, - {"recvmsg", libc_recvmsg_trampoline}, - {"sendmsg", libc_sendmsg_trampoline}, - {"kevent", libc_kevent_trampoline}, - {"__sysctl", libc___sysctl_trampoline}, - {"utimes", libc_utimes_trampoline}, - {"futimes", libc_futimes_trampoline}, - {"fcntl", libc_fcntl_trampoline}, - {"poll", libc_poll_trampoline}, - {"madvise", libc_madvise_trampoline}, - {"mlock", libc_mlock_trampoline}, - {"mlockall", libc_mlockall_trampoline}, - {"mprotect", libc_mprotect_trampoline}, - {"msync", libc_msync_trampoline}, - {"munlock", libc_munlock_trampoline}, - {"munlockall", libc_munlockall_trampoline}, - {"ptrace", libc_ptrace_trampoline}, - {"pipe", libc_pipe_trampoline}, - {"getxattr", libc_getxattr_trampoline}, - {"fgetxattr", libc_fgetxattr_trampoline}, - {"setxattr", libc_setxattr_trampoline}, - {"fsetxattr", libc_fsetxattr_trampoline}, - {"removexattr", libc_removexattr_trampoline}, - {"fremovexattr", libc_fremovexattr_trampoline}, - {"listxattr", libc_listxattr_trampoline}, - {"flistxattr", libc_flistxattr_trampoline}, - {"kill", libc_kill_trampoline}, - {"ioctl", libc_ioctl_trampoline}, - {"access", libc_access_trampoline}, - {"adjtime", libc_adjtime_trampoline}, - {"chdir", libc_chdir_trampoline}, - {"chflags", libc_chflags_trampoline}, - {"chmod", libc_chmod_trampoline}, - {"chown", libc_chown_trampoline}, - {"chroot", libc_chroot_trampoline}, - {"close", libc_close_trampoline}, - {"dup", libc_dup_trampoline}, - {"dup2", libc_dup2_trampoline}, - {"exchangedata", libc_exchangedata_trampoline}, - {"exit", libc_exit_trampoline}, - {"faccessat", libc_faccessat_trampoline}, - {"fchdir", libc_fchdir_trampoline}, - {"fchflags", libc_fchflags_trampoline}, - {"fchmod", libc_fchmod_trampoline}, - {"fchmodat", libc_fchmodat_trampoline}, - {"fchown", libc_fchown_trampoline}, - {"fchownat", libc_fchownat_trampoline}, - {"flock", libc_flock_trampoline}, - {"fpathconf", libc_fpathconf_trampoline}, - {"fstat64", libc_fstat64_trampoline}, - {"fstatat64", libc_fstatat64_trampoline}, - {"fstatfs64", libc_fstatfs64_trampoline}, - {"fsync", libc_fsync_trampoline}, - {"ftruncate", libc_ftruncate_trampoline}, - {"__getdirentries64", libc___getdirentries64_trampoline}, - {"getdtablesize", libc_getdtablesize_trampoline}, - {"getegid", libc_getegid_trampoline}, - {"geteuid", libc_geteuid_trampoline}, - {"getgid", libc_getgid_trampoline}, - {"getpgid", libc_getpgid_trampoline}, - {"getpgrp", libc_getpgrp_trampoline}, - {"getpid", libc_getpid_trampoline}, - {"getppid", libc_getppid_trampoline}, - {"getpriority", libc_getpriority_trampoline}, - {"getrlimit", libc_getrlimit_trampoline}, - {"getrusage", libc_getrusage_trampoline}, - {"getsid", libc_getsid_trampoline}, - {"getuid", libc_getuid_trampoline}, - {"issetugid", libc_issetugid_trampoline}, - {"kqueue", libc_kqueue_trampoline}, - {"lchown", libc_lchown_trampoline}, - {"link", libc_link_trampoline}, - {"linkat", libc_linkat_trampoline}, - {"listen", libc_listen_trampoline}, - {"lstat64", libc_lstat64_trampoline}, - {"mkdir", libc_mkdir_trampoline}, - {"mkdirat", libc_mkdirat_trampoline}, - {"mkfifo", libc_mkfifo_trampoline}, - {"mknod", libc_mknod_trampoline}, - {"open", libc_open_trampoline}, - {"openat", libc_openat_trampoline}, - {"pathconf", libc_pathconf_trampoline}, - {"pread", libc_pread_trampoline}, - {"pwrite", libc_pwrite_trampoline}, - {"read", libc_read_trampoline}, - {"readlink", libc_readlink_trampoline}, - {"readlinkat", libc_readlinkat_trampoline}, - {"rename", libc_rename_trampoline}, - {"renameat", libc_renameat_trampoline}, - {"revoke", libc_revoke_trampoline}, - {"rmdir", libc_rmdir_trampoline}, - {"lseek", libc_lseek_trampoline}, - {"select", libc_select_trampoline}, - {"setegid", libc_setegid_trampoline}, - {"seteuid", libc_seteuid_trampoline}, - {"setgid", libc_setgid_trampoline}, - {"setlogin", libc_setlogin_trampoline}, - {"setpgid", libc_setpgid_trampoline}, - {"setpriority", libc_setpriority_trampoline}, - {"setprivexec", libc_setprivexec_trampoline}, - {"setregid", libc_setregid_trampoline}, - {"setreuid", libc_setreuid_trampoline}, - {"setrlimit", libc_setrlimit_trampoline}, - {"setsid", libc_setsid_trampoline}, - {"settimeofday", libc_settimeofday_trampoline}, - {"setuid", libc_setuid_trampoline}, - {"stat64", libc_stat64_trampoline}, - {"statfs64", libc_statfs64_trampoline}, - {"symlink", libc_symlink_trampoline}, - {"symlinkat", libc_symlinkat_trampoline}, - {"sync", libc_sync_trampoline}, - {"truncate", libc_truncate_trampoline}, - {"umask", libc_umask_trampoline}, - {"undelete", libc_undelete_trampoline}, - {"unlink", libc_unlink_trampoline}, - {"unlinkat", libc_unlinkat_trampoline}, - {"unmount", libc_unmount_trampoline}, - {"write", libc_write_trampoline}, - {"mmap", libc_mmap_trampoline}, - {"munmap", libc_munmap_trampoline}, - {"gettimeofday", libc_gettimeofday_trampoline}, - {"getfsstat64", libc_getfsstat64_trampoline}, -} diff --git a/vendor/golang.org/x/sys/unix/dev_linux_test.go b/vendor/golang.org/x/sys/unix/dev_linux_test.go deleted file mode 100644 index 51645289..00000000 --- a/vendor/golang.org/x/sys/unix/dev_linux_test.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build go1.7 - -package unix_test - -import ( - "fmt" - "testing" - - "golang.org/x/sys/unix" -) - -func TestDevices(t *testing.T) { - testCases := []struct { - path string - major uint32 - minor uint32 - }{ - // well known major/minor numbers according to - // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/admin-guide/devices.txt - {"/dev/null", 1, 3}, - {"/dev/zero", 1, 5}, - {"/dev/random", 1, 8}, - {"/dev/full", 1, 7}, - {"/dev/urandom", 1, 9}, - {"/dev/tty", 5, 0}, - } - for _, tc := range testCases { - t.Run(fmt.Sprintf("%s %v:%v", tc.path, tc.major, tc.minor), func(t *testing.T) { - var stat unix.Stat_t - err := unix.Stat(tc.path, &stat) - if err != nil { - if err == unix.EACCES { - t.Skip("no permission to stat device, skipping test") - } - t.Errorf("failed to stat device: %v", err) - return - } - - dev := uint64(stat.Rdev) - if unix.Major(dev) != tc.major { - t.Errorf("for %s Major(%#x) == %d, want %d", tc.path, dev, unix.Major(dev), tc.major) - } - if unix.Minor(dev) != tc.minor { - t.Errorf("for %s Minor(%#x) == %d, want %d", tc.path, dev, unix.Minor(dev), tc.minor) - } - if unix.Mkdev(tc.major, tc.minor) != dev { - t.Errorf("for %s Mkdev(%d, %d) == %#x, want %#x", tc.path, tc.major, tc.minor, unix.Mkdev(tc.major, tc.minor), dev) - } - }) - - } -} diff --git a/vendor/golang.org/x/sys/unix/example_exec_test.go b/vendor/golang.org/x/sys/unix/example_exec_test.go deleted file mode 100644 index bb4d3bf5..00000000 --- a/vendor/golang.org/x/sys/unix/example_exec_test.go +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris - -package unix_test - -import ( - "log" - "os" - - "golang.org/x/sys/unix" -) - -func ExampleExec() { - err := unix.Exec("/bin/ls", []string{"ls", "-al"}, os.Environ()) - log.Fatal(err) -} diff --git a/vendor/golang.org/x/sys/unix/example_flock_test.go b/vendor/golang.org/x/sys/unix/example_flock_test.go deleted file mode 100644 index 6c917485..00000000 --- a/vendor/golang.org/x/sys/unix/example_flock_test.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build darwin dragonfly freebsd linux netbsd openbsd solaris - -package unix_test - -import ( - "log" - "os" - - "golang.org/x/sys/unix" -) - -func ExampleFlock() { - f, _ := os.Create("example.lock") - if err := unix.Flock(int(f.Fd()), unix.LOCK_EX); err != nil { - log.Fatal(err) - } - // Do work here that requires the lock. When finished, release the lock: - if err := unix.Flock(int(f.Fd()), unix.LOCK_UN); err != nil { - log.Fatal(err) - } -} diff --git a/vendor/golang.org/x/sys/unix/export_test.go b/vendor/golang.org/x/sys/unix/export_test.go deleted file mode 100644 index f8ae0e0e..00000000 --- a/vendor/golang.org/x/sys/unix/export_test.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris - -package unix - -var Itoa = itoa diff --git a/vendor/golang.org/x/sys/unix/mkall.sh b/vendor/golang.org/x/sys/unix/mkall.sh deleted file mode 100755 index 0b2a7a7a..00000000 --- a/vendor/golang.org/x/sys/unix/mkall.sh +++ /dev/null @@ -1,214 +0,0 @@ -#!/usr/bin/env bash -# Copyright 2009 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -# This script runs or (given -n) prints suggested commands to generate files for -# the Architecture/OS specified by the GOARCH and GOOS environment variables. -# See README.md for more information about how the build system works. - -GOOSARCH="${GOOS}_${GOARCH}" - -# defaults -mksyscall="go run mksyscall.go" -mkerrors="./mkerrors.sh" -zerrors="zerrors_$GOOSARCH.go" -mksysctl="" -zsysctl="zsysctl_$GOOSARCH.go" -mksysnum= -mktypes= -mkasm= -run="sh" -cmd="" - -case "$1" in --syscalls) - for i in zsyscall*go - do - # Run the command line that appears in the first line - # of the generated file to regenerate it. - sed 1q $i | sed 's;^// ;;' | sh > _$i && gofmt < _$i > $i - rm _$i - done - exit 0 - ;; --n) - run="cat" - cmd="echo" - shift -esac - -case "$#" in -0) - ;; -*) - echo 'usage: mkall.sh [-n]' 1>&2 - exit 2 -esac - -if [[ "$GOOS" = "linux" ]]; then - # Use the Docker-based build system - # Files generated through docker (use $cmd so you can Ctl-C the build or run) - $cmd docker build --tag generate:$GOOS $GOOS - $cmd docker run --interactive --tty --volume $(dirname "$(readlink -f "$0")"):/build generate:$GOOS - exit -fi - -GOOSARCH_in=syscall_$GOOSARCH.go -case "$GOOSARCH" in -_* | *_ | _) - echo 'undefined $GOOS_$GOARCH:' "$GOOSARCH" 1>&2 - exit 1 - ;; -aix_ppc) - mkerrors="$mkerrors -maix32" - mksyscall="go run mksyscall_aix_ppc.go -aix" - mktypes="GOARCH=$GOARCH go tool cgo -godefs" - ;; -aix_ppc64) - mkerrors="$mkerrors -maix64" - mksyscall="./mksyscall_aix_ppc64.pl -aix" - mktypes="GOARCH=$GOARCH go tool cgo -godefs" - ;; -darwin_386) - mkerrors="$mkerrors -m32" - mksyscall="go run mksyscall.go -l32" - mksysnum="go run mksysnum.go $(xcrun --show-sdk-path --sdk macosx)/usr/include/sys/syscall.h" - mktypes="GOARCH=$GOARCH go tool cgo -godefs" - mkasm="go run mkasm_darwin.go" - ;; -darwin_amd64) - mkerrors="$mkerrors -m64" - mksysnum="go run mksysnum.go $(xcrun --show-sdk-path --sdk macosx)/usr/include/sys/syscall.h" - mktypes="GOARCH=$GOARCH go tool cgo -godefs" - mkasm="go run mkasm_darwin.go" - ;; -darwin_arm) - mkerrors="$mkerrors" - mksyscall="go run mksyscall.go -l32" - mksysnum="go run mksysnum.go $(xcrun --show-sdk-path --sdk iphoneos)/usr/include/sys/syscall.h" - mktypes="GOARCH=$GOARCH go tool cgo -godefs" - mkasm="go run mkasm_darwin.go" - ;; -darwin_arm64) - mkerrors="$mkerrors -m64" - mksysnum="go run mksysnum.go $(xcrun --show-sdk-path --sdk iphoneos)/usr/include/sys/syscall.h" - mktypes="GOARCH=$GOARCH go tool cgo -godefs" - mkasm="go run mkasm_darwin.go" - ;; -dragonfly_amd64) - mkerrors="$mkerrors -m64" - mksyscall="go run mksyscall.go -dragonfly" - mksysnum="go run mksysnum.go 'http://gitweb.dragonflybsd.org/dragonfly.git/blob_plain/HEAD:/sys/kern/syscalls.master'" - mktypes="GOARCH=$GOARCH go tool cgo -godefs" - ;; -freebsd_386) - mkerrors="$mkerrors -m32" - mksyscall="go run mksyscall.go -l32" - mksysnum="go run mksysnum.go 'http://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master'" - mktypes="GOARCH=$GOARCH go tool cgo -godefs" - ;; -freebsd_amd64) - mkerrors="$mkerrors -m64" - mksysnum="go run mksysnum.go 'http://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master'" - mktypes="GOARCH=$GOARCH go tool cgo -godefs" - ;; -freebsd_arm) - mkerrors="$mkerrors" - mksyscall="go run mksyscall.go -l32 -arm" - mksysnum="go run mksysnum.go 'http://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master'" - # Let the type of C char be signed for making the bare syscall - # API consistent across platforms. - mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char" - ;; -freebsd_arm64) - mkerrors="$mkerrors -m64" - mksysnum="go run mksysnum.go 'http://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master'" - mktypes="GOARCH=$GOARCH go tool cgo -godefs" - ;; -netbsd_386) - mkerrors="$mkerrors -m32" - mksyscall="go run mksyscall.go -l32 -netbsd" - mksysnum="go run mksysnum.go 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master'" - mktypes="GOARCH=$GOARCH go tool cgo -godefs" - ;; -netbsd_amd64) - mkerrors="$mkerrors -m64" - mksyscall="go run mksyscall.go -netbsd" - mksysnum="go run mksysnum.go 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master'" - mktypes="GOARCH=$GOARCH go tool cgo -godefs" - ;; -netbsd_arm) - mkerrors="$mkerrors" - mksyscall="go run mksyscall.go -l32 -netbsd -arm" - mksysnum="go run mksysnum.go 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master'" - # Let the type of C char be signed for making the bare syscall - # API consistent across platforms. - mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char" - ;; -openbsd_386) - mkerrors="$mkerrors -m32" - mksyscall="go run mksyscall.go -l32 -openbsd" - mksysctl="./mksysctl_openbsd.pl" - mksysnum="go run mksysnum.go 'http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'" - mktypes="GOARCH=$GOARCH go tool cgo -godefs" - ;; -openbsd_amd64) - mkerrors="$mkerrors -m64" - mksyscall="go run mksyscall.go -openbsd" - mksysctl="./mksysctl_openbsd.pl" - mksysnum="go run mksysnum.go 'http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'" - mktypes="GOARCH=$GOARCH go tool cgo -godefs" - ;; -openbsd_arm) - mkerrors="$mkerrors" - mksyscall="go run mksyscall.go -l32 -openbsd -arm" - mksysctl="./mksysctl_openbsd.pl" - mksysnum="go run mksysnum.go 'http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'" - # Let the type of C char be signed for making the bare syscall - # API consistent across platforms. - mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char" - ;; -solaris_amd64) - mksyscall="./mksyscall_solaris.pl" - mkerrors="$mkerrors -m64" - mksysnum= - mktypes="GOARCH=$GOARCH go tool cgo -godefs" - ;; -*) - echo 'unrecognized $GOOS_$GOARCH: ' "$GOOSARCH" 1>&2 - exit 1 - ;; -esac - -( - if [ -n "$mkerrors" ]; then echo "$mkerrors |gofmt >$zerrors"; fi - case "$GOOS" in - *) - syscall_goos="syscall_$GOOS.go" - case "$GOOS" in - darwin | dragonfly | freebsd | netbsd | openbsd) - syscall_goos="syscall_bsd.go $syscall_goos" - ;; - esac - if [ -n "$mksyscall" ]; then - if [ "$GOOSARCH" == "aix_ppc64" ]; then - # aix/ppc64 script generates files instead of writing to stdin. - echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in && gofmt -w zsyscall_$GOOSARCH.go && gofmt -w zsyscall_"$GOOSARCH"_gccgo.go && gofmt -w zsyscall_"$GOOSARCH"_gc.go " ; - elif [ "$GOOS" == "darwin" ]; then - # pre-1.12, direct syscalls - echo "$mksyscall -tags $GOOS,$GOARCH,!go1.12 $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.1_11.go"; - # 1.12 and later, syscalls via libSystem - echo "$mksyscall -tags $GOOS,$GOARCH,go1.12 $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go"; - else - echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go"; - fi - fi - esac - if [ -n "$mksysctl" ]; then echo "$mksysctl |gofmt >$zsysctl"; fi - if [ -n "$mksysnum" ]; then echo "$mksysnum |gofmt >zsysnum_$GOOSARCH.go"; fi - if [ -n "$mktypes" ]; then - echo "$mktypes types_$GOOS.go | go run mkpost.go > ztypes_$GOOSARCH.go"; - if [ -n "$mkasm" ]; then echo "$mkasm $GOARCH"; fi - fi -) | $run diff --git a/vendor/golang.org/x/sys/unix/mkerrors.sh b/vendor/golang.org/x/sys/unix/mkerrors.sh deleted file mode 100755 index 178077f4..00000000 --- a/vendor/golang.org/x/sys/unix/mkerrors.sh +++ /dev/null @@ -1,664 +0,0 @@ -#!/usr/bin/env bash -# Copyright 2009 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -# Generate Go code listing errors and other #defined constant -# values (ENAMETOOLONG etc.), by asking the preprocessor -# about the definitions. - -unset LANG -export LC_ALL=C -export LC_CTYPE=C - -if test -z "$GOARCH" -o -z "$GOOS"; then - echo 1>&2 "GOARCH or GOOS not defined in environment" - exit 1 -fi - -# Check that we are using the new build system if we should -if [[ "$GOOS" = "linux" ]] && [[ "$GOLANG_SYS_BUILD" != "docker" ]]; then - echo 1>&2 "In the Docker based build system, mkerrors should not be called directly." - echo 1>&2 "See README.md" - exit 1 -fi - -if [[ "$GOOS" = "aix" ]]; then - CC=${CC:-gcc} -else - CC=${CC:-cc} -fi - -if [[ "$GOOS" = "solaris" ]]; then - # Assumes GNU versions of utilities in PATH. - export PATH=/usr/gnu/bin:$PATH -fi - -uname=$(uname) - -includes_AIX=' -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define AF_LOCAL AF_UNIX -' - -includes_Darwin=' -#define _DARWIN_C_SOURCE -#define KERNEL -#define _DARWIN_USE_64_BIT_INODE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -' - -includes_DragonFly=' -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -' - -includes_FreeBSD=' -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if __FreeBSD__ >= 10 -#define IFT_CARP 0xf8 // IFT_CARP is deprecated in FreeBSD 10 -#undef SIOCAIFADDR -#define SIOCAIFADDR _IOW(105, 26, struct oifaliasreq) // ifaliasreq contains if_data -#undef SIOCSIFPHYADDR -#define SIOCSIFPHYADDR _IOW(105, 70, struct oifaliasreq) // ifaliasreq contains if_data -#endif -' - -includes_Linux=' -#define _LARGEFILE_SOURCE -#define _LARGEFILE64_SOURCE -#ifndef __LP64__ -#define _FILE_OFFSET_BITS 64 -#endif -#define _GNU_SOURCE - -// is broken on powerpc64, as it fails to include definitions of -// these structures. We just include them copied from . -#if defined(__powerpc__) -struct sgttyb { - char sg_ispeed; - char sg_ospeed; - char sg_erase; - char sg_kill; - short sg_flags; -}; - -struct tchars { - char t_intrc; - char t_quitc; - char t_startc; - char t_stopc; - char t_eofc; - char t_brkc; -}; - -struct ltchars { - char t_suspc; - char t_dsuspc; - char t_rprntc; - char t_flushc; - char t_werasc; - char t_lnextc; -}; -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(__sparc__) -// On sparc{,64}, the kernel defines struct termios2 itself which clashes with the -// definition in glibc. As only the error constants are needed here, include the -// generic termibits.h (which is included by termbits.h on sparc). -#include -#else -#include -#endif - -#ifndef MSG_FASTOPEN -#define MSG_FASTOPEN 0x20000000 -#endif - -#ifndef PTRACE_GETREGS -#define PTRACE_GETREGS 0xc -#endif - -#ifndef PTRACE_SETREGS -#define PTRACE_SETREGS 0xd -#endif - -#ifndef SOL_NETLINK -#define SOL_NETLINK 270 -#endif - -#ifdef SOL_BLUETOOTH -// SPARC includes this in /usr/include/sparc64-linux-gnu/bits/socket.h -// but it is already in bluetooth_linux.go -#undef SOL_BLUETOOTH -#endif - -// Certain constants are missing from the fs/crypto UAPI -#define FS_KEY_DESC_PREFIX "fscrypt:" -#define FS_KEY_DESC_PREFIX_SIZE 8 -#define FS_MAX_KEY_SIZE 64 - -// XDP socket constants do not appear to be picked up otherwise. -// Copied from samples/bpf/xdpsock_user.c. -#ifndef SOL_XDP -#define SOL_XDP 283 -#endif - -#ifndef AF_XDP -#define AF_XDP 44 -#endif -' - -includes_NetBSD=' -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// Needed since refers to it... -#define schedppq 1 -' - -includes_OpenBSD=' -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// We keep some constants not supported in OpenBSD 5.5 and beyond for -// the promise of compatibility. -#define EMUL_ENABLED 0x1 -#define EMUL_NATIVE 0x2 -#define IPV6_FAITH 0x1d -#define IPV6_OPTIONS 0x1 -#define IPV6_RTHDR_STRICT 0x1 -#define IPV6_SOCKOPT_RESERVED1 0x3 -#define SIOCGIFGENERIC 0xc020693a -#define SIOCSIFGENERIC 0x80206939 -#define WALTSIG 0x4 -' - -includes_SunOS=' -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -' - - -includes=' -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -' -ccflags="$@" - -# Write go tool cgo -godefs input. -( - echo package unix - echo - echo '/*' - indirect="includes_$(uname)" - echo "${!indirect} $includes" - echo '*/' - echo 'import "C"' - echo 'import "syscall"' - echo - echo 'const (' - - # The gcc command line prints all the #defines - # it encounters while processing the input - echo "${!indirect} $includes" | $CC -x c - -E -dM $ccflags | - awk ' - $1 != "#define" || $2 ~ /\(/ || $3 == "" {next} - - $2 ~ /^E([ABCD]X|[BIS]P|[SD]I|S|FL)$/ {next} # 386 registers - $2 ~ /^(SIGEV_|SIGSTKSZ|SIGRT(MIN|MAX))/ {next} - $2 ~ /^(SCM_SRCRT)$/ {next} - $2 ~ /^(MAP_FAILED)$/ {next} - $2 ~ /^ELF_.*$/ {next}# contains ELF_ARCH, etc. - - $2 ~ /^EXTATTR_NAMESPACE_NAMES/ || - $2 ~ /^EXTATTR_NAMESPACE_[A-Z]+_STRING/ {next} - - $2 !~ /^ECCAPBITS/ && - $2 !~ /^ETH_/ && - $2 !~ /^EPROC_/ && - $2 !~ /^EQUIV_/ && - $2 !~ /^EXPR_/ && - $2 ~ /^E[A-Z0-9_]+$/ || - $2 ~ /^B[0-9_]+$/ || - $2 ~ /^(OLD|NEW)DEV$/ || - $2 == "BOTHER" || - $2 ~ /^CI?BAUD(EX)?$/ || - $2 == "IBSHIFT" || - $2 ~ /^V[A-Z0-9]+$/ || - $2 ~ /^CS[A-Z0-9]/ || - $2 ~ /^I(SIG|CANON|CRNL|UCLC|EXTEN|MAXBEL|STRIP|UTF8)$/ || - $2 ~ /^IGN/ || - $2 ~ /^IX(ON|ANY|OFF)$/ || - $2 ~ /^IN(LCR|PCK)$/ || - $2 !~ "X86_CR3_PCID_NOFLUSH" && - $2 ~ /(^FLU?SH)|(FLU?SH$)/ || - $2 ~ /^C(LOCAL|READ|MSPAR|RTSCTS)$/ || - $2 == "BRKINT" || - $2 == "HUPCL" || - $2 == "PENDIN" || - $2 == "TOSTOP" || - $2 == "XCASE" || - $2 == "ALTWERASE" || - $2 == "NOKERNINFO" || - $2 ~ /^PAR/ || - $2 ~ /^SIG[^_]/ || - $2 ~ /^O[CNPFPL][A-Z]+[^_][A-Z]+$/ || - $2 ~ /^(NL|CR|TAB|BS|VT|FF)DLY$/ || - $2 ~ /^(NL|CR|TAB|BS|VT|FF)[0-9]$/ || - $2 ~ /^O?XTABS$/ || - $2 ~ /^TC[IO](ON|OFF)$/ || - $2 ~ /^IN_/ || - $2 ~ /^LOCK_(SH|EX|NB|UN)$/ || - $2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|ICMP6|TCP|EVFILT|NOTE|EV|SHUT|PROT|MAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR)_/ || - $2 ~ /^TP_STATUS_/ || - $2 ~ /^FALLOC_/ || - $2 == "ICMPV6_FILTER" || - $2 == "SOMAXCONN" || - $2 == "NAME_MAX" || - $2 == "IFNAMSIZ" || - $2 ~ /^CTL_(HW|KERN|MAXNAME|NET|QUERY)$/ || - $2 ~ /^KERN_(HOSTNAME|OS(RELEASE|TYPE)|VERSION)$/ || - $2 ~ /^HW_MACHINE$/ || - $2 ~ /^SYSCTL_VERS/ || - $2 !~ "MNT_BITS" && - $2 ~ /^(MS|MNT|UMOUNT)_/ || - $2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ || - $2 ~ /^(O|F|E?FD|NAME|S|PTRACE|PT)_/ || - $2 ~ /^KEXEC_/ || - $2 ~ /^LINUX_REBOOT_CMD_/ || - $2 ~ /^LINUX_REBOOT_MAGIC[12]$/ || - $2 ~ /^MODULE_INIT_/ || - $2 !~ "NLA_TYPE_MASK" && - $2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTC|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P|NETNSA)_/ || - $2 ~ /^SIOC/ || - $2 ~ /^TIOC/ || - $2 ~ /^TCGET/ || - $2 ~ /^TCSET/ || - $2 ~ /^TC(FLSH|SBRKP?|XONC)$/ || - $2 !~ "RTF_BITS" && - $2 ~ /^(IFF|IFT|NET_RT|RTM|RTF|RTV|RTA|RTAX)_/ || - $2 ~ /^BIOC/ || - $2 ~ /^RUSAGE_(SELF|CHILDREN|THREAD)/ || - $2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|LOCKS|MEMLOCK|MSGQUEUE|NICE|NOFILE|NPROC|RSS|RTPRIO|RTTIME|SIGPENDING|STACK)|RLIM_INFINITY/ || - $2 ~ /^PRIO_(PROCESS|PGRP|USER)/ || - $2 ~ /^CLONE_[A-Z_]+/ || - $2 !~ /^(BPF_TIMEVAL)$/ && - $2 ~ /^(BPF|DLT)_/ || - $2 ~ /^CLOCK_/ || - $2 ~ /^CAN_/ || - $2 ~ /^CAP_/ || - $2 ~ /^ALG_/ || - $2 ~ /^FS_(POLICY_FLAGS|KEY_DESC|ENCRYPTION_MODE|[A-Z0-9_]+_KEY_SIZE|IOC_(GET|SET)_ENCRYPTION)/ || - $2 ~ /^GRND_/ || - $2 ~ /^KEY_(SPEC|REQKEY_DEFL)_/ || - $2 ~ /^KEYCTL_/ || - $2 ~ /^PERF_EVENT_IOC_/ || - $2 ~ /^SECCOMP_MODE_/ || - $2 ~ /^SPLICE_/ || - $2 ~ /^SYNC_FILE_RANGE_/ || - $2 !~ /^AUDIT_RECORD_MAGIC/ && - $2 !~ /IOC_MAGIC/ && - $2 ~ /^[A-Z][A-Z0-9_]+_MAGIC2?$/ || - $2 ~ /^(VM|VMADDR)_/ || - $2 ~ /^IOCTL_VM_SOCKETS_/ || - $2 ~ /^(TASKSTATS|TS)_/ || - $2 ~ /^CGROUPSTATS_/ || - $2 ~ /^GENL_/ || - $2 ~ /^STATX_/ || - $2 ~ /^RENAME/ || - $2 ~ /^UBI_IOC[A-Z]/ || - $2 ~ /^UTIME_/ || - $2 ~ /^XATTR_(CREATE|REPLACE|NO(DEFAULT|FOLLOW|SECURITY)|SHOWCOMPRESSION)/ || - $2 ~ /^ATTR_(BIT_MAP_COUNT|(CMN|VOL|FILE)_)/ || - $2 ~ /^FSOPT_/ || - $2 ~ /^WDIOC_/ || - $2 ~ /^NFN/ || - $2 ~ /^XDP_/ || - $2 ~ /^(HDIO|WIN|SMART)_/ || - $2 !~ "WMESGLEN" && - $2 ~ /^W[A-Z0-9]+$/ || - $2 ~/^PPPIOC/ || - $2 ~ /^BLK[A-Z]*(GET$|SET$|BUF$|PART$|SIZE)/ {printf("\t%s = C.%s\n", $2, $2)} - $2 ~ /^__WCOREFLAG$/ {next} - $2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)} - - {next} - ' | sort - - echo ')' -) >_const.go - -# Pull out the error names for later. -errors=$( - echo '#include ' | $CC -x c - -E -dM $ccflags | - awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print $2 }' | - sort -) - -# Pull out the signal names for later. -signals=$( - echo '#include ' | $CC -x c - -E -dM $ccflags | - awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print $2 }' | - egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT|SIGMAX64)' | - sort -) - -# Again, writing regexps to a file. -echo '#include ' | $CC -x c - -E -dM $ccflags | - awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print "^\t" $2 "[ \t]*=" }' | - sort >_error.grep -echo '#include ' | $CC -x c - -E -dM $ccflags | - awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print "^\t" $2 "[ \t]*=" }' | - egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT|SIGMAX64)' | - sort >_signal.grep - -echo '// mkerrors.sh' "$@" -echo '// Code generated by the command above; see README.md. DO NOT EDIT.' -echo -echo "// +build ${GOARCH},${GOOS}" -echo -go tool cgo -godefs -- "$@" _const.go >_error.out -cat _error.out | grep -vf _error.grep | grep -vf _signal.grep -echo -echo '// Errors' -echo 'const (' -cat _error.out | grep -f _error.grep | sed 's/=\(.*\)/= syscall.Errno(\1)/' -echo ')' - -echo -echo '// Signals' -echo 'const (' -cat _error.out | grep -f _signal.grep | sed 's/=\(.*\)/= syscall.Signal(\1)/' -echo ')' - -# Run C program to print error and syscall strings. -( - echo -E " -#include -#include -#include -#include -#include -#include - -#define nelem(x) (sizeof(x)/sizeof((x)[0])) - -enum { A = 'A', Z = 'Z', a = 'a', z = 'z' }; // avoid need for single quotes below - -struct tuple { - int num; - const char *name; -}; - -struct tuple errors[] = { -" - for i in $errors - do - echo -E ' {'$i', "'$i'" },' - done - - echo -E " -}; - -struct tuple signals[] = { -" - for i in $signals - do - echo -E ' {'$i', "'$i'" },' - done - - # Use -E because on some systems bash builtin interprets \n itself. - echo -E ' -}; - -static int -tuplecmp(const void *a, const void *b) -{ - return ((struct tuple *)a)->num - ((struct tuple *)b)->num; -} - -int -main(void) -{ - int i, e; - char buf[1024], *p; - - printf("\n\n// Error table\n"); - printf("var errorList = [...]struct {\n"); - printf("\tnum syscall.Errno\n"); - printf("\tname string\n"); - printf("\tdesc string\n"); - printf("} {\n"); - qsort(errors, nelem(errors), sizeof errors[0], tuplecmp); - for(i=0; i 0 && errors[i-1].num == e) - continue; - strcpy(buf, strerror(e)); - // lowercase first letter: Bad -> bad, but STREAM -> STREAM. - if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z) - buf[0] += a - A; - printf("\t{ %d, \"%s\", \"%s\" },\n", e, errors[i].name, buf); - } - printf("}\n\n"); - - printf("\n\n// Signal table\n"); - printf("var signalList = [...]struct {\n"); - printf("\tnum syscall.Signal\n"); - printf("\tname string\n"); - printf("\tdesc string\n"); - printf("} {\n"); - qsort(signals, nelem(signals), sizeof signals[0], tuplecmp); - for(i=0; i 0 && signals[i-1].num == e) - continue; - strcpy(buf, strsignal(e)); - // lowercase first letter: Bad -> bad, but STREAM -> STREAM. - if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z) - buf[0] += a - A; - // cut trailing : number. - p = strrchr(buf, ":"[0]); - if(p) - *p = '\0'; - printf("\t{ %d, \"%s\", \"%s\" },\n", e, signals[i].name, buf); - } - printf("}\n\n"); - - return 0; -} - -' -) >_errors.c - -$CC $ccflags -o _errors _errors.c && $GORUN ./_errors && rm -f _errors.c _errors _const.go _error.grep _signal.grep _error.out diff --git a/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.pl b/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.pl deleted file mode 100755 index 53df26bb..00000000 --- a/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.pl +++ /dev/null @@ -1,579 +0,0 @@ -#!/usr/bin/env perl -# Copyright 2018 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -# This program reads a file containing function prototypes -# (like syscall_aix.go) and generates system call bodies. -# The prototypes are marked by lines beginning with "//sys" -# and read like func declarations if //sys is replaced by func, but: -# * The parameter lists must give a name for each argument. -# This includes return parameters. -# * The parameter lists must give a type for each argument: -# the (x, y, z int) shorthand is not allowed. -# * If the return parameter is an error number, it must be named err. -# * If go func name needs to be different than its libc name, -# * or the function is not in libc, name could be specified -# * at the end, after "=" sign, like -# //sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt - -# This program will generate three files and handle both gc and gccgo implementation: -# - zsyscall_aix_ppc64.go: the common part of each implementation (error handler, pointer creation) -# - zsyscall_aix_ppc64_gc.go: gc part with //go_cgo_import_dynamic and a call to syscall6 -# - zsyscall_aix_ppc64_gccgo.go: gccgo part with C function and conversion to C type. - -# The generated code looks like this -# -# zsyscall_aix_ppc64.go -# func asyscall(...) (n int, err error) { -# // Pointer Creation -# r1, e1 := callasyscall(...) -# // Type Conversion -# // Error Handler -# return -# } -# -# zsyscall_aix_ppc64_gc.go -# //go:cgo_import_dynamic libc_asyscall asyscall "libc.a/shr_64.o" -# //go:linkname libc_asyscall libc_asyscall -# var asyscall syscallFunc -# -# func callasyscall(...) (r1 uintptr, e1 Errno) { -# r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_asyscall)), "nb_args", ... ) -# return -# } -# -# zsyscall_aix_ppc64_ggcgo.go -# /* -# int asyscall(...) -# -# */ -# import "C" -# -# func callasyscall(...) (r1 uintptr, e1 Errno) { -# r1 = uintptr(C.asyscall(...)) -# e1 = syscall.GetErrno() -# return -# } - - - -use strict; - -my $cmdline = "mksyscall_aix_ppc64.pl " . join(' ', @ARGV); -my $errors = 0; -my $_32bit = ""; -my $tags = ""; # build tags -my $aix = 0; -my $solaris = 0; - -binmode STDOUT; - -if($ARGV[0] eq "-b32") { - $_32bit = "big-endian"; - shift; -} elsif($ARGV[0] eq "-l32") { - $_32bit = "little-endian"; - shift; -} -if($ARGV[0] eq "-aix") { - $aix = 1; - shift; -} -if($ARGV[0] eq "-tags") { - shift; - $tags = $ARGV[0]; - shift; -} - -if($ARGV[0] =~ /^-/) { - print STDERR "usage: mksyscall_aix.pl [-b32 | -l32] [-tags x,y] [file ...]\n"; - exit 1; -} - -sub parseparamlist($) { - my ($list) = @_; - $list =~ s/^\s*//; - $list =~ s/\s*$//; - if($list eq "") { - return (); - } - return split(/\s*,\s*/, $list); -} - -sub parseparam($) { - my ($p) = @_; - if($p !~ /^(\S*) (\S*)$/) { - print STDERR "$ARGV:$.: malformed parameter: $p\n"; - $errors = 1; - return ("xx", "int"); - } - return ($1, $2); -} - -my $package = ""; -# GCCGO -my $textgccgo = ""; -my $c_extern = "/*\n#include \n"; -# GC -my $textgc = ""; -my $dynimports = ""; -my $linknames = ""; -my @vars = (); -# COMMUN -my $textcommon = ""; - -while(<>) { - chomp; - s/\s+/ /g; - s/^\s+//; - s/\s+$//; - $package = $1 if !$package && /^package (\S+)$/; - my $nonblock = /^\/\/sysnb /; - next if !/^\/\/sys / && !$nonblock; - - # Line must be of the form - # func Open(path string, mode int, perm int) (fd int, err error) - # Split into name, in params, out params. - if(!/^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$/) { - print STDERR "$ARGV:$.: malformed //sys declaration\n"; - $errors = 1; - next; - } - my ($nb, $func, $in, $out, $modname, $sysname) = ($1, $2, $3, $4, $5, $6); - - # Split argument lists on comma. - my @in = parseparamlist($in); - my @out = parseparamlist($out); - - $in = join(', ', @in); - $out = join(', ', @out); - - if($sysname eq "") { - $sysname = "$func"; - } - - my $onlyCommon = 0; - if ($func eq "readlen" || $func eq "writelen" || $func eq "FcntlInt" || $func eq "FcntlFlock") { - # This function call another syscall which is already implemented. - # Therefore, the gc and gccgo part must not be generated. - $onlyCommon = 1 - } - - # Try in vain to keep people from editing this file. - # The theory is that they jump into the middle of the file - # without reading the header. - - $textcommon .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"; - if (!$onlyCommon) { - $textgccgo .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"; - $textgc .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"; - } - - - # Check if value return, err return available - my $errvar = ""; - my $retvar = ""; - my $rettype = ""; - foreach my $p (@out) { - my ($name, $type) = parseparam($p); - if($type eq "error") { - $errvar = $name; - } else { - $retvar = $name; - $rettype = $type; - } - } - - - $sysname =~ s/([a-z])([A-Z])/${1}_$2/g; - $sysname =~ y/A-Z/a-z/; # All libc functions are lowercase. - - # GCCGO Prototype return type - my $C_rettype = ""; - if($rettype eq "unsafe.Pointer") { - $C_rettype = "uintptr_t"; - } elsif($rettype eq "uintptr") { - $C_rettype = "uintptr_t"; - } elsif($rettype =~ /^_/) { - $C_rettype = "uintptr_t"; - } elsif($rettype eq "int") { - $C_rettype = "int"; - } elsif($rettype eq "int32") { - $C_rettype = "int"; - } elsif($rettype eq "int64") { - $C_rettype = "long long"; - } elsif($rettype eq "uint32") { - $C_rettype = "unsigned int"; - } elsif($rettype eq "uint64") { - $C_rettype = "unsigned long long"; - } else { - $C_rettype = "int"; - } - if($sysname eq "exit") { - $C_rettype = "void"; - } - - # GCCGO Prototype arguments type - my @c_in = (); - foreach my $i (0 .. $#in) { - my ($name, $type) = parseparam($in[$i]); - if($type =~ /^\*/) { - push @c_in, "uintptr_t"; - } elsif($type eq "string") { - push @c_in, "uintptr_t"; - } elsif($type =~ /^\[\](.*)/) { - push @c_in, "uintptr_t", "size_t"; - } elsif($type eq "unsafe.Pointer") { - push @c_in, "uintptr_t"; - } elsif($type eq "uintptr") { - push @c_in, "uintptr_t"; - } elsif($type =~ /^_/) { - push @c_in, "uintptr_t"; - } elsif($type eq "int") { - if (($i == 0 || $i == 2) && $func eq "fcntl"){ - # These fcntl arguments needs to be uintptr to be able to call FcntlInt and FcntlFlock - push @c_in, "uintptr_t"; - } else { - push @c_in, "int"; - } - } elsif($type eq "int32") { - push @c_in, "int"; - } elsif($type eq "int64") { - push @c_in, "long long"; - } elsif($type eq "uint32") { - push @c_in, "unsigned int"; - } elsif($type eq "uint64") { - push @c_in, "unsigned long long"; - } else { - push @c_in, "int"; - } - } - - if (!$onlyCommon){ - # GCCGO Prototype Generation - # Imports of system calls from libc - $c_extern .= "$C_rettype $sysname"; - my $c_in = join(', ', @c_in); - $c_extern .= "($c_in);\n"; - } - - # GC Library name - if($modname eq "") { - $modname = "libc.a/shr_64.o"; - } else { - print STDERR "$func: only syscall using libc are available\n"; - $errors = 1; - next; - } - my $sysvarname = "libc_${sysname}"; - - if (!$onlyCommon){ - # GC Runtime import of function to allow cross-platform builds. - $dynimports .= "//go:cgo_import_dynamic ${sysvarname} ${sysname} \"$modname\"\n"; - # GC Link symbol to proc address variable. - $linknames .= "//go:linkname ${sysvarname} ${sysvarname}\n"; - # GC Library proc address variable. - push @vars, $sysvarname; - } - - my $strconvfunc ="BytePtrFromString"; - my $strconvtype = "*byte"; - - # Go function header. - if($out ne "") { - $out = " ($out)"; - } - if($textcommon ne "") { - $textcommon .= "\n" - } - - $textcommon .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out ; - - # Prepare arguments to call. - my @argscommun = (); # Arguments in the commun part - my @argscall = (); # Arguments for call prototype - my @argsgc = (); # Arguments for gc call (with syscall6) - my @argsgccgo = (); # Arguments for gccgo call (with C.name_of_syscall) - my $n = 0; - my $arg_n = 0; - foreach my $p (@in) { - my ($name, $type) = parseparam($p); - if($type =~ /^\*/) { - push @argscommun, "uintptr(unsafe.Pointer($name))"; - push @argscall, "$name uintptr"; - push @argsgc, "$name"; - push @argsgccgo, "C.uintptr_t($name)"; - } elsif($type eq "string" && $errvar ne "") { - $textcommon .= "\tvar _p$n $strconvtype\n"; - $textcommon .= "\t_p$n, $errvar = $strconvfunc($name)\n"; - $textcommon .= "\tif $errvar != nil {\n\t\treturn\n\t}\n"; - - push @argscommun, "uintptr(unsafe.Pointer(_p$n))"; - push @argscall, "_p$n uintptr "; - push @argsgc, "_p$n"; - push @argsgccgo, "C.uintptr_t(_p$n)"; - $n++; - } elsif($type eq "string") { - print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n"; - $textcommon .= "\tvar _p$n $strconvtype\n"; - $textcommon .= "\t_p$n, $errvar = $strconvfunc($name)\n"; - $textcommon .= "\tif $errvar != nil {\n\t\treturn\n\t}\n"; - - push @argscommun, "uintptr(unsafe.Pointer(_p$n))"; - push @argscall, "_p$n uintptr"; - push @argsgc, "_p$n"; - push @argsgccgo, "C.uintptr_t(_p$n)"; - $n++; - } elsif($type =~ /^\[\](.*)/) { - # Convert slice into pointer, length. - # Have to be careful not to take address of &a[0] if len == 0: - # pass nil in that case. - $textcommon .= "\tvar _p$n *$1\n"; - $textcommon .= "\tif len($name) > 0 {\n\t\t_p$n = \&$name\[0]\n\t}\n"; - push @argscommun, "uintptr(unsafe.Pointer(_p$n))", "len($name)"; - push @argscall, "_p$n uintptr", "_lenp$n int"; - push @argsgc, "_p$n", "uintptr(_lenp$n)"; - push @argsgccgo, "C.uintptr_t(_p$n)", "C.size_t(_lenp$n)"; - $n++; - } elsif($type eq "int64" && $_32bit ne "") { - print STDERR "$ARGV:$.: $func uses int64 with 32 bits mode. Case not yet implemented\n"; - # if($_32bit eq "big-endian") { - # push @args, "uintptr($name >> 32)", "uintptr($name)"; - # } else { - # push @args, "uintptr($name)", "uintptr($name >> 32)"; - # } - # $n++; - } elsif($type eq "bool") { - print STDERR "$ARGV:$.: $func uses bool. Case not yet implemented\n"; - # $text .= "\tvar _p$n uint32\n"; - # $text .= "\tif $name {\n\t\t_p$n = 1\n\t} else {\n\t\t_p$n = 0\n\t}\n"; - # push @args, "_p$n"; - # $n++; - } elsif($type =~ /^_/ ||$type eq "unsafe.Pointer") { - push @argscommun, "uintptr($name)"; - push @argscall, "$name uintptr"; - push @argsgc, "$name"; - push @argsgccgo, "C.uintptr_t($name)"; - } elsif($type eq "int") { - if (($arg_n == 0 || $arg_n == 2) && ($func eq "fcntl" || $func eq "FcntlInt" || $func eq "FcntlFlock")) { - # These fcntl arguments need to be uintptr to be able to call FcntlInt and FcntlFlock - push @argscommun, "uintptr($name)"; - push @argscall, "$name uintptr"; - push @argsgc, "$name"; - push @argsgccgo, "C.uintptr_t($name)"; - } else { - push @argscommun, "$name"; - push @argscall, "$name int"; - push @argsgc, "uintptr($name)"; - push @argsgccgo, "C.int($name)"; - } - } elsif($type eq "int32") { - push @argscommun, "$name"; - push @argscall, "$name int32"; - push @argsgc, "uintptr($name)"; - push @argsgccgo, "C.int($name)"; - } elsif($type eq "int64") { - push @argscommun, "$name"; - push @argscall, "$name int64"; - push @argsgc, "uintptr($name)"; - push @argsgccgo, "C.longlong($name)"; - } elsif($type eq "uint32") { - push @argscommun, "$name"; - push @argscall, "$name uint32"; - push @argsgc, "uintptr($name)"; - push @argsgccgo, "C.uint($name)"; - } elsif($type eq "uint64") { - push @argscommun, "$name"; - push @argscall, "$name uint64"; - push @argsgc, "uintptr($name)"; - push @argsgccgo, "C.ulonglong($name)"; - } elsif($type eq "uintptr") { - push @argscommun, "$name"; - push @argscall, "$name uintptr"; - push @argsgc, "$name"; - push @argsgccgo, "C.uintptr_t($name)"; - } else { - push @argscommun, "int($name)"; - push @argscall, "$name int"; - push @argsgc, "uintptr($name)"; - push @argsgccgo, "C.int($name)"; - } - $arg_n++; - } - my $nargs = @argsgc; - - # COMMUN function generation - my $argscommun = join(', ', @argscommun); - my $callcommun = "call$sysname($argscommun)"; - my @ret = ("_", "_"); - my $body = ""; - my $do_errno = 0; - for(my $i=0; $i<@out; $i++) { - my $p = $out[$i]; - my ($name, $type) = parseparam($p); - my $reg = ""; - if($name eq "err") { - $reg = "e1"; - $ret[1] = $reg; - $do_errno = 1; - } else { - $reg = "r0"; - $ret[0] = $reg; - } - if($type eq "bool") { - $reg = "$reg != 0"; - } - if($reg ne "e1") { - $body .= "\t$name = $type($reg)\n"; - } - } - if ($ret[0] eq "_" && $ret[1] eq "_") { - $textcommon .= "\t$callcommun\n"; - } else { - $textcommon .= "\t$ret[0], $ret[1] := $callcommun\n"; - } - $textcommon .= $body; - - if ($do_errno) { - $textcommon .= "\tif e1 != 0 {\n"; - $textcommon .= "\t\terr = errnoErr(e1)\n"; - $textcommon .= "\t}\n"; - } - $textcommon .= "\treturn\n"; - $textcommon .= "}\n"; - - if ($onlyCommon){ - next - } - # CALL Prototype - my $callProto = sprintf "func call%s(%s) (r1 uintptr, e1 Errno) {\n", $sysname, join(', ', @argscall); - - # GC function generation - my $asm = "syscall6"; - if ($nonblock) { - $asm = "rawSyscall6"; - } - - if(@argsgc <= 6) { - while(@argsgc < 6) { - push @argsgc, "0"; - } - } else { - print STDERR "$ARGV:$.: too many arguments to system call\n"; - } - my $argsgc = join(', ', @argsgc); - my $callgc = "$asm(uintptr(unsafe.Pointer(&$sysvarname)), $nargs, $argsgc)"; - - $textgc .= $callProto; - $textgc .= "\tr1, _, e1 = $callgc\n"; - $textgc .= "\treturn\n}\n"; - - # GCCGO function generation - my $argsgccgo = join(', ', @argsgccgo); - my $callgccgo = "C.$sysname($argsgccgo)"; - $textgccgo .= $callProto; - $textgccgo .= "\tr1 = uintptr($callgccgo)\n"; - $textgccgo .= "\te1 = syscall.GetErrno()\n"; - $textgccgo .= "\treturn\n}\n"; -} - -if($errors) { - exit 1; -} - -# Print zsyscall_aix_ppc64.go -open(my $fcommun, '>', 'zsyscall_aix_ppc64.go'); -my $tofcommun = <', 'zsyscall_aix_ppc64_gc.go'); -my $tofgc = <', 'zsyscall_aix_ppc64_gccgo.go'); -my $tofgccgo = <) { - chomp; - s/\s+/ /g; - s/^\s+//; - s/\s+$//; - $package = $1 if !$package && /^package (\S+)$/; - my $nonblock = /^\/\/sysnb /; - next if !/^\/\/sys / && !$nonblock; - - # Line must be of the form - # func Open(path string, mode int, perm int) (fd int, err error) - # Split into name, in params, out params. - if(!/^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$/) { - print STDERR "$ARGV:$.: malformed //sys declaration\n"; - $errors = 1; - next; - } - my ($nb, $func, $in, $out, $modname, $sysname) = ($1, $2, $3, $4, $5, $6); - - # Split argument lists on comma. - my @in = parseparamlist($in); - my @out = parseparamlist($out); - - # Try in vain to keep people from editing this file. - # The theory is that they jump into the middle of the file - # without reading the header. - $text .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"; - - # So file name. - if($modname eq "") { - $modname = "libc"; - } - - # System call name. - if($sysname eq "") { - $sysname = "$func"; - } - - # System call pointer variable name. - my $sysvarname = "proc$sysname"; - - my $strconvfunc = "BytePtrFromString"; - my $strconvtype = "*byte"; - - $sysname =~ y/A-Z/a-z/; # All libc functions are lowercase. - - # Runtime import of function to allow cross-platform builds. - $dynimports .= "//go:cgo_import_dynamic libc_${sysname} ${sysname} \"$modname.so\"\n"; - # Link symbol to proc address variable. - $linknames .= "//go:linkname ${sysvarname} libc_${sysname}\n"; - # Library proc address variable. - push @vars, $sysvarname; - - # Go function header. - $out = join(', ', @out); - if($out ne "") { - $out = " ($out)"; - } - if($text ne "") { - $text .= "\n" - } - $text .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out; - - # Check if err return available - my $errvar = ""; - foreach my $p (@out) { - my ($name, $type) = parseparam($p); - if($type eq "error") { - $errvar = $name; - last; - } - } - - # Prepare arguments to Syscall. - my @args = (); - my $n = 0; - foreach my $p (@in) { - my ($name, $type) = parseparam($p); - if($type =~ /^\*/) { - push @args, "uintptr(unsafe.Pointer($name))"; - } elsif($type eq "string" && $errvar ne "") { - $text .= "\tvar _p$n $strconvtype\n"; - $text .= "\t_p$n, $errvar = $strconvfunc($name)\n"; - $text .= "\tif $errvar != nil {\n\t\treturn\n\t}\n"; - push @args, "uintptr(unsafe.Pointer(_p$n))"; - $n++; - } elsif($type eq "string") { - print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n"; - $text .= "\tvar _p$n $strconvtype\n"; - $text .= "\t_p$n, _ = $strconvfunc($name)\n"; - push @args, "uintptr(unsafe.Pointer(_p$n))"; - $n++; - } elsif($type =~ /^\[\](.*)/) { - # Convert slice into pointer, length. - # Have to be careful not to take address of &a[0] if len == 0: - # pass nil in that case. - $text .= "\tvar _p$n *$1\n"; - $text .= "\tif len($name) > 0 {\n\t\t_p$n = \&$name\[0]\n\t}\n"; - push @args, "uintptr(unsafe.Pointer(_p$n))", "uintptr(len($name))"; - $n++; - } elsif($type eq "int64" && $_32bit ne "") { - if($_32bit eq "big-endian") { - push @args, "uintptr($name >> 32)", "uintptr($name)"; - } else { - push @args, "uintptr($name)", "uintptr($name >> 32)"; - } - } elsif($type eq "bool") { - $text .= "\tvar _p$n uint32\n"; - $text .= "\tif $name {\n\t\t_p$n = 1\n\t} else {\n\t\t_p$n = 0\n\t}\n"; - push @args, "uintptr(_p$n)"; - $n++; - } else { - push @args, "uintptr($name)"; - } - } - my $nargs = @args; - - # Determine which form to use; pad args with zeros. - my $asm = "sysvicall6"; - if ($nonblock) { - $asm = "rawSysvicall6"; - } - if(@args <= 6) { - while(@args < 6) { - push @args, "0"; - } - } else { - print STDERR "$ARGV:$.: too many arguments to system call\n"; - } - - # Actual call. - my $args = join(', ', @args); - my $call = "$asm(uintptr(unsafe.Pointer(&$sysvarname)), $nargs, $args)"; - - # Assign return values. - my $body = ""; - my $failexpr = ""; - my @ret = ("_", "_", "_"); - my @pout= (); - my $do_errno = 0; - for(my $i=0; $i<@out; $i++) { - my $p = $out[$i]; - my ($name, $type) = parseparam($p); - my $reg = ""; - if($name eq "err") { - $reg = "e1"; - $ret[2] = $reg; - $do_errno = 1; - } else { - $reg = sprintf("r%d", $i); - $ret[$i] = $reg; - } - if($type eq "bool") { - $reg = "$reg != 0"; - } - if($type eq "int64" && $_32bit ne "") { - # 64-bit number in r1:r0 or r0:r1. - if($i+2 > @out) { - print STDERR "$ARGV:$.: not enough registers for int64 return\n"; - } - if($_32bit eq "big-endian") { - $reg = sprintf("int64(r%d)<<32 | int64(r%d)", $i, $i+1); - } else { - $reg = sprintf("int64(r%d)<<32 | int64(r%d)", $i+1, $i); - } - $ret[$i] = sprintf("r%d", $i); - $ret[$i+1] = sprintf("r%d", $i+1); - } - if($reg ne "e1") { - $body .= "\t$name = $type($reg)\n"; - } - } - if ($ret[0] eq "_" && $ret[1] eq "_" && $ret[2] eq "_") { - $text .= "\t$call\n"; - } else { - $text .= "\t$ret[0], $ret[1], $ret[2] := $call\n"; - } - $text .= $body; - - if ($do_errno) { - $text .= "\tif e1 != 0 {\n"; - $text .= "\t\terr = e1\n"; - $text .= "\t}\n"; - } - $text .= "\treturn\n"; - $text .= "}\n"; -} - -if($errors) { - exit 1; -} - -print < "net.inet", - "net.inet.ipproto" => "net.inet", - "net.inet6.ipv6proto" => "net.inet6", - "net.inet6.ipv6" => "net.inet6.ip6", - "net.inet.icmpv6" => "net.inet6.icmp6", - "net.inet6.divert6" => "net.inet6.divert", - "net.inet6.tcp6" => "net.inet.tcp", - "net.inet6.udp6" => "net.inet.udp", - "mpls" => "net.mpls", - "swpenc" => "vm.swapencrypt" -); - -# Node mappings -my %node_map = ( - "net.inet.ip.ifq" => "net.ifq", - "net.inet.pfsync" => "net.pfsync", - "net.mpls.ifq" => "net.ifq" -); - -my $ctlname; -my %mib = (); -my %sysctl = (); -my $node; - -sub debug() { - print STDERR "$_[0]\n" if $debug; -} - -# Walk the MIB and build a sysctl name to OID mapping. -sub build_sysctl() { - my ($node, $name, $oid) = @_; - my %node = %{$node}; - my @oid = @{$oid}; - - foreach my $key (sort keys %node) { - my @node = @{$node{$key}}; - my $nodename = $name.($name ne '' ? '.' : '').$key; - my @nodeoid = (@oid, $node[0]); - if ($node[1] eq 'CTLTYPE_NODE') { - if (exists $node_map{$nodename}) { - $node = \%mib; - $ctlname = $node_map{$nodename}; - foreach my $part (split /\./, $ctlname) { - $node = \%{@{$$node{$part}}[2]}; - } - } else { - $node = $node[2]; - } - &build_sysctl($node, $nodename, \@nodeoid); - } elsif ($node[1] ne '') { - $sysctl{$nodename} = \@nodeoid; - } - } -} - -foreach my $ctl (@ctls) { - $ctls{$ctl} = $ctl; -} - -# Build MIB -foreach my $header (@headers) { - &debug("Processing $header..."); - open HEADER, "/usr/include/$header" || - print STDERR "Failed to open $header\n"; - while (
) { - if ($_ =~ /^#define\s+(CTL_NAMES)\s+{/ || - $_ =~ /^#define\s+(CTL_(.*)_NAMES)\s+{/ || - $_ =~ /^#define\s+((.*)CTL_NAMES)\s+{/) { - if ($1 eq 'CTL_NAMES') { - # Top level. - $node = \%mib; - } else { - # Node. - my $nodename = lc($2); - if ($header =~ /^netinet\//) { - $ctlname = "net.inet.$nodename"; - } elsif ($header =~ /^netinet6\//) { - $ctlname = "net.inet6.$nodename"; - } elsif ($header =~ /^net\//) { - $ctlname = "net.$nodename"; - } else { - $ctlname = "$nodename"; - $ctlname =~ s/^(fs|net|kern)_/$1\./; - } - if (exists $ctl_map{$ctlname}) { - $ctlname = $ctl_map{$ctlname}; - } - if (not exists $ctls{$ctlname}) { - &debug("Ignoring $ctlname..."); - next; - } - - # Walk down from the top of the MIB. - $node = \%mib; - foreach my $part (split /\./, $ctlname) { - if (not exists $$node{$part}) { - &debug("Missing node $part"); - $$node{$part} = [ 0, '', {} ]; - } - $node = \%{@{$$node{$part}}[2]}; - } - } - - # Populate current node with entries. - my $i = -1; - while (defined($_) && $_ !~ /^}/) { - $_ =
; - $i++ if $_ =~ /{.*}/; - next if $_ !~ /{\s+"(\w+)",\s+(CTLTYPE_[A-Z]+)\s+}/; - $$node{$1} = [ $i, $2, {} ]; - } - } - } - close HEADER; -} - -&build_sysctl(\%mib, "", []); - -print <= 0 { - t.Fatal("bad math") - } - s := unix.Itoa(i) - f := fmt.Sprint(i) - if s != f { - t.Fatalf("itoa(%d) = %s, want %s", i, s, f) - } -} - -func TestUname(t *testing.T) { - var utsname unix.Utsname - err := unix.Uname(&utsname) - if err != nil { - t.Fatalf("Uname: %v", err) - } - - t.Logf("OS: %s/%s %s", utsname.Sysname[:], utsname.Machine[:], utsname.Release[:]) -} diff --git a/vendor/golang.org/x/sys/unix/syscall_unix_test.go b/vendor/golang.org/x/sys/unix/syscall_unix_test.go deleted file mode 100644 index c1b1ea59..00000000 --- a/vendor/golang.org/x/sys/unix/syscall_unix_test.go +++ /dev/null @@ -1,677 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris - -package unix_test - -import ( - "flag" - "fmt" - "io/ioutil" - "net" - "os" - "os/exec" - "path/filepath" - "runtime" - "syscall" - "testing" - "time" - - "golang.org/x/sys/unix" -) - -// Tests that below functions, structures and constants are consistent -// on all Unix-like systems. -func _() { - // program scheduling priority functions and constants - var ( - _ func(int, int, int) error = unix.Setpriority - _ func(int, int) (int, error) = unix.Getpriority - ) - const ( - _ int = unix.PRIO_USER - _ int = unix.PRIO_PROCESS - _ int = unix.PRIO_PGRP - ) - - // termios constants - const ( - _ int = unix.TCIFLUSH - _ int = unix.TCIOFLUSH - _ int = unix.TCOFLUSH - ) - - // fcntl file locking structure and constants - var ( - _ = unix.Flock_t{ - Type: int16(0), - Whence: int16(0), - Start: int64(0), - Len: int64(0), - Pid: int32(0), - } - ) - const ( - _ = unix.F_GETLK - _ = unix.F_SETLK - _ = unix.F_SETLKW - ) -} - -func TestErrnoSignalName(t *testing.T) { - testErrors := []struct { - num syscall.Errno - name string - }{ - {syscall.EPERM, "EPERM"}, - {syscall.EINVAL, "EINVAL"}, - {syscall.ENOENT, "ENOENT"}, - } - - for _, te := range testErrors { - t.Run(fmt.Sprintf("%d/%s", te.num, te.name), func(t *testing.T) { - e := unix.ErrnoName(te.num) - if e != te.name { - t.Errorf("ErrnoName(%d) returned %s, want %s", te.num, e, te.name) - } - }) - } - - testSignals := []struct { - num syscall.Signal - name string - }{ - {syscall.SIGHUP, "SIGHUP"}, - {syscall.SIGPIPE, "SIGPIPE"}, - {syscall.SIGSEGV, "SIGSEGV"}, - } - - for _, ts := range testSignals { - t.Run(fmt.Sprintf("%d/%s", ts.num, ts.name), func(t *testing.T) { - s := unix.SignalName(ts.num) - if s != ts.name { - t.Errorf("SignalName(%d) returned %s, want %s", ts.num, s, ts.name) - } - }) - } -} - -func TestFcntlInt(t *testing.T) { - t.Parallel() - file, err := ioutil.TempFile("", "TestFnctlInt") - if err != nil { - t.Fatal(err) - } - defer os.Remove(file.Name()) - defer file.Close() - f := file.Fd() - flags, err := unix.FcntlInt(f, unix.F_GETFD, 0) - if err != nil { - t.Fatal(err) - } - if flags&unix.FD_CLOEXEC == 0 { - t.Errorf("flags %#x do not include FD_CLOEXEC", flags) - } -} - -// TestFcntlFlock tests whether the file locking structure matches -// the calling convention of each kernel. -func TestFcntlFlock(t *testing.T) { - name := filepath.Join(os.TempDir(), "TestFcntlFlock") - fd, err := unix.Open(name, unix.O_CREAT|unix.O_RDWR|unix.O_CLOEXEC, 0) - if err != nil { - t.Fatalf("Open failed: %v", err) - } - defer unix.Unlink(name) - defer unix.Close(fd) - flock := unix.Flock_t{ - Type: unix.F_RDLCK, - Start: 0, Len: 0, Whence: 1, - } - if err := unix.FcntlFlock(uintptr(fd), unix.F_GETLK, &flock); err != nil { - t.Fatalf("FcntlFlock failed: %v", err) - } -} - -// TestPassFD tests passing a file descriptor over a Unix socket. -// -// This test involved both a parent and child process. The parent -// process is invoked as a normal test, with "go test", which then -// runs the child process by running the current test binary with args -// "-test.run=^TestPassFD$" and an environment variable used to signal -// that the test should become the child process instead. -func TestPassFD(t *testing.T) { - if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") { - t.Skip("cannot exec subprocess on iOS, skipping test") - } - if runtime.GOOS == "aix" { - t.Skip("getsockname issue on AIX 7.2 tl1, skipping test") - } - - if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" { - passFDChild() - return - } - - tempDir, err := ioutil.TempDir("", "TestPassFD") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tempDir) - - fds, err := unix.Socketpair(unix.AF_LOCAL, unix.SOCK_STREAM, 0) - if err != nil { - t.Fatalf("Socketpair: %v", err) - } - defer unix.Close(fds[0]) - defer unix.Close(fds[1]) - writeFile := os.NewFile(uintptr(fds[0]), "child-writes") - readFile := os.NewFile(uintptr(fds[1]), "parent-reads") - defer writeFile.Close() - defer readFile.Close() - - cmd := exec.Command(os.Args[0], "-test.run=^TestPassFD$", "--", tempDir) - cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"} - if lp := os.Getenv("LD_LIBRARY_PATH"); lp != "" { - cmd.Env = append(cmd.Env, "LD_LIBRARY_PATH="+lp) - } - cmd.ExtraFiles = []*os.File{writeFile} - - out, err := cmd.CombinedOutput() - if len(out) > 0 || err != nil { - t.Fatalf("child process: %q, %v", out, err) - } - - c, err := net.FileConn(readFile) - if err != nil { - t.Fatalf("FileConn: %v", err) - } - defer c.Close() - - uc, ok := c.(*net.UnixConn) - if !ok { - t.Fatalf("unexpected FileConn type; expected UnixConn, got %T", c) - } - - buf := make([]byte, 32) // expect 1 byte - oob := make([]byte, 32) // expect 24 bytes - closeUnix := time.AfterFunc(5*time.Second, func() { - t.Logf("timeout reading from unix socket") - uc.Close() - }) - _, oobn, _, _, err := uc.ReadMsgUnix(buf, oob) - if err != nil { - t.Fatalf("ReadMsgUnix: %v", err) - } - closeUnix.Stop() - - scms, err := unix.ParseSocketControlMessage(oob[:oobn]) - if err != nil { - t.Fatalf("ParseSocketControlMessage: %v", err) - } - if len(scms) != 1 { - t.Fatalf("expected 1 SocketControlMessage; got scms = %#v", scms) - } - scm := scms[0] - gotFds, err := unix.ParseUnixRights(&scm) - if err != nil { - t.Fatalf("unix.ParseUnixRights: %v", err) - } - if len(gotFds) != 1 { - t.Fatalf("wanted 1 fd; got %#v", gotFds) - } - - f := os.NewFile(uintptr(gotFds[0]), "fd-from-child") - defer f.Close() - - got, err := ioutil.ReadAll(f) - want := "Hello from child process!\n" - if string(got) != want { - t.Errorf("child process ReadAll: %q, %v; want %q", got, err, want) - } -} - -// passFDChild is the child process used by TestPassFD. -func passFDChild() { - defer os.Exit(0) - - // Look for our fd. It should be fd 3, but we work around an fd leak - // bug here (http://golang.org/issue/2603) to let it be elsewhere. - var uc *net.UnixConn - for fd := uintptr(3); fd <= 10; fd++ { - f := os.NewFile(fd, "unix-conn") - var ok bool - netc, _ := net.FileConn(f) - uc, ok = netc.(*net.UnixConn) - if ok { - break - } - } - if uc == nil { - fmt.Println("failed to find unix fd") - return - } - - // Make a file f to send to our parent process on uc. - // We make it in tempDir, which our parent will clean up. - flag.Parse() - tempDir := flag.Arg(0) - f, err := ioutil.TempFile(tempDir, "") - if err != nil { - fmt.Printf("TempFile: %v", err) - return - } - - f.Write([]byte("Hello from child process!\n")) - f.Seek(0, 0) - - rights := unix.UnixRights(int(f.Fd())) - dummyByte := []byte("x") - n, oobn, err := uc.WriteMsgUnix(dummyByte, rights, nil) - if err != nil { - fmt.Printf("WriteMsgUnix: %v", err) - return - } - if n != 1 || oobn != len(rights) { - fmt.Printf("WriteMsgUnix = %d, %d; want 1, %d", n, oobn, len(rights)) - return - } -} - -// TestUnixRightsRoundtrip tests that UnixRights, ParseSocketControlMessage, -// and ParseUnixRights are able to successfully round-trip lists of file descriptors. -func TestUnixRightsRoundtrip(t *testing.T) { - testCases := [...][][]int{ - {{42}}, - {{1, 2}}, - {{3, 4, 5}}, - {{}}, - {{1, 2}, {3, 4, 5}, {}, {7}}, - } - for _, testCase := range testCases { - b := []byte{} - var n int - for _, fds := range testCase { - // Last assignment to n wins - n = len(b) + unix.CmsgLen(4*len(fds)) - b = append(b, unix.UnixRights(fds...)...) - } - // Truncate b - b = b[:n] - - scms, err := unix.ParseSocketControlMessage(b) - if err != nil { - t.Fatalf("ParseSocketControlMessage: %v", err) - } - if len(scms) != len(testCase) { - t.Fatalf("expected %v SocketControlMessage; got scms = %#v", len(testCase), scms) - } - for i, scm := range scms { - gotFds, err := unix.ParseUnixRights(&scm) - if err != nil { - t.Fatalf("ParseUnixRights: %v", err) - } - wantFds := testCase[i] - if len(gotFds) != len(wantFds) { - t.Fatalf("expected %v fds, got %#v", len(wantFds), gotFds) - } - for j, fd := range gotFds { - if fd != wantFds[j] { - t.Fatalf("expected fd %v, got %v", wantFds[j], fd) - } - } - } - } -} - -func TestRlimit(t *testing.T) { - var rlimit, zero unix.Rlimit - err := unix.Getrlimit(unix.RLIMIT_NOFILE, &rlimit) - if err != nil { - t.Fatalf("Getrlimit: save failed: %v", err) - } - if zero == rlimit { - t.Fatalf("Getrlimit: save failed: got zero value %#v", rlimit) - } - set := rlimit - set.Cur = set.Max - 1 - if runtime.GOOS == "darwin" && set.Cur > 10240 { - // The max file limit is 10240, even though - // the max returned by Getrlimit is 1<<63-1. - // This is OPEN_MAX in sys/syslimits.h. - set.Cur = 10240 - } - err = unix.Setrlimit(unix.RLIMIT_NOFILE, &set) - if err != nil { - t.Fatalf("Setrlimit: set failed: %#v %v", set, err) - } - var get unix.Rlimit - err = unix.Getrlimit(unix.RLIMIT_NOFILE, &get) - if err != nil { - t.Fatalf("Getrlimit: get failed: %v", err) - } - set = rlimit - set.Cur = set.Max - 1 - if set != get { - // Seems like Darwin requires some privilege to - // increase the soft limit of rlimit sandbox, though - // Setrlimit never reports an error. - switch runtime.GOOS { - case "darwin": - default: - t.Fatalf("Rlimit: change failed: wanted %#v got %#v", set, get) - } - } - err = unix.Setrlimit(unix.RLIMIT_NOFILE, &rlimit) - if err != nil { - t.Fatalf("Setrlimit: restore failed: %#v %v", rlimit, err) - } -} - -func TestSeekFailure(t *testing.T) { - _, err := unix.Seek(-1, 0, 0) - if err == nil { - t.Fatalf("Seek(-1, 0, 0) did not fail") - } - str := err.Error() // used to crash on Linux - t.Logf("Seek: %v", str) - if str == "" { - t.Fatalf("Seek(-1, 0, 0) return error with empty message") - } -} - -func TestDup(t *testing.T) { - file, err := ioutil.TempFile("", "TestDup") - if err != nil { - t.Fatalf("Tempfile failed: %v", err) - } - defer os.Remove(file.Name()) - defer file.Close() - f := int(file.Fd()) - - newFd, err := unix.Dup(f) - if err != nil { - t.Fatalf("Dup: %v", err) - } - - err = unix.Dup2(newFd, newFd+1) - if err != nil { - t.Fatalf("Dup2: %v", err) - } - - b1 := []byte("Test123") - b2 := make([]byte, 7) - _, err = unix.Write(newFd+1, b1) - if err != nil { - t.Fatalf("Write to dup2 fd failed: %v", err) - } - _, err = unix.Seek(f, 0, 0) - if err != nil { - t.Fatalf("Seek failed: %v", err) - } - _, err = unix.Read(f, b2) - if err != nil { - t.Fatalf("Read back failed: %v", err) - } - if string(b1) != string(b2) { - t.Errorf("Dup: stdout write not in file, expected %v, got %v", string(b1), string(b2)) - } -} - -func TestPoll(t *testing.T) { - if runtime.GOOS == "android" || - (runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64")) { - t.Skip("mkfifo syscall is not available on android and iOS, skipping test") - } - - f, cleanup := mktmpfifo(t) - defer cleanup() - - const timeout = 100 - - ok := make(chan bool, 1) - go func() { - select { - case <-time.After(10 * timeout * time.Millisecond): - t.Errorf("Poll: failed to timeout after %d milliseconds", 10*timeout) - case <-ok: - } - }() - - fds := []unix.PollFd{{Fd: int32(f.Fd()), Events: unix.POLLIN}} - n, err := unix.Poll(fds, timeout) - ok <- true - if err != nil { - t.Errorf("Poll: unexpected error: %v", err) - return - } - if n != 0 { - t.Errorf("Poll: wrong number of events: got %v, expected %v", n, 0) - return - } -} - -func TestGetwd(t *testing.T) { - fd, err := os.Open(".") - if err != nil { - t.Fatalf("Open .: %s", err) - } - defer fd.Close() - // Directory list for test. Do not worry if any are symlinks or do not - // exist on some common unix desktop environments. That will be checked. - dirs := []string{"/", "/usr/bin", "/etc", "/var", "/opt"} - switch runtime.GOOS { - case "android": - dirs = []string{"/", "/system/bin"} - case "darwin": - switch runtime.GOARCH { - case "arm", "arm64": - d1, err := ioutil.TempDir("", "d1") - if err != nil { - t.Fatalf("TempDir: %v", err) - } - d2, err := ioutil.TempDir("", "d2") - if err != nil { - t.Fatalf("TempDir: %v", err) - } - dirs = []string{d1, d2} - } - } - oldwd := os.Getenv("PWD") - for _, d := range dirs { - // Check whether d exists, is a dir and that d's path does not contain a symlink - fi, err := os.Stat(d) - if err != nil || !fi.IsDir() { - t.Logf("Test dir %s stat error (%v) or not a directory, skipping", d, err) - continue - } - check, err := filepath.EvalSymlinks(d) - if err != nil || check != d { - t.Logf("Test dir %s (%s) is symlink or other error (%v), skipping", d, check, err) - continue - } - err = os.Chdir(d) - if err != nil { - t.Fatalf("Chdir: %v", err) - } - pwd, err := unix.Getwd() - if err != nil { - t.Fatalf("Getwd in %s: %s", d, err) - } - os.Setenv("PWD", oldwd) - err = fd.Chdir() - if err != nil { - // We changed the current directory and cannot go back. - // Don't let the tests continue; they'll scribble - // all over some other directory. - fmt.Fprintf(os.Stderr, "fchdir back to dot failed: %s\n", err) - os.Exit(1) - } - if pwd != d { - t.Fatalf("Getwd returned %q want %q", pwd, d) - } - } -} - -func TestFstatat(t *testing.T) { - defer chtmpdir(t)() - - touch(t, "file1") - - var st1 unix.Stat_t - err := unix.Stat("file1", &st1) - if err != nil { - t.Fatalf("Stat: %v", err) - } - - var st2 unix.Stat_t - err = unix.Fstatat(unix.AT_FDCWD, "file1", &st2, 0) - if err != nil { - t.Fatalf("Fstatat: %v", err) - } - - if st1 != st2 { - t.Errorf("Fstatat: returned stat does not match Stat") - } - - err = os.Symlink("file1", "symlink1") - if err != nil { - t.Fatal(err) - } - - err = unix.Lstat("symlink1", &st1) - if err != nil { - t.Fatalf("Lstat: %v", err) - } - - err = unix.Fstatat(unix.AT_FDCWD, "symlink1", &st2, unix.AT_SYMLINK_NOFOLLOW) - if err != nil { - t.Fatalf("Fstatat: %v", err) - } - - if st1 != st2 { - t.Errorf("Fstatat: returned stat does not match Lstat") - } -} - -func TestFchmodat(t *testing.T) { - defer chtmpdir(t)() - - touch(t, "file1") - err := os.Symlink("file1", "symlink1") - if err != nil { - t.Fatal(err) - } - - mode := os.FileMode(0444) - err = unix.Fchmodat(unix.AT_FDCWD, "symlink1", uint32(mode), 0) - if err != nil { - t.Fatalf("Fchmodat: unexpected error: %v", err) - } - - fi, err := os.Stat("file1") - if err != nil { - t.Fatal(err) - } - - if fi.Mode() != mode { - t.Errorf("Fchmodat: failed to change file mode: expected %v, got %v", mode, fi.Mode()) - } - - mode = os.FileMode(0644) - didChmodSymlink := true - err = unix.Fchmodat(unix.AT_FDCWD, "symlink1", uint32(mode), unix.AT_SYMLINK_NOFOLLOW) - if err != nil { - if (runtime.GOOS == "android" || runtime.GOOS == "linux" || runtime.GOOS == "solaris") && err == unix.EOPNOTSUPP { - // Linux and Illumos don't support flags != 0 - didChmodSymlink = false - } else { - t.Fatalf("Fchmodat: unexpected error: %v", err) - } - } - - if !didChmodSymlink { - // Didn't change mode of the symlink. On Linux, the permissions - // of a symbolic link are always 0777 according to symlink(7) - mode = os.FileMode(0777) - } - - var st unix.Stat_t - err = unix.Lstat("symlink1", &st) - if err != nil { - t.Fatal(err) - } - - got := os.FileMode(st.Mode & 0777) - if got != mode { - t.Errorf("Fchmodat: failed to change symlink mode: expected %v, got %v", mode, got) - } -} - -func TestMkdev(t *testing.T) { - major := uint32(42) - minor := uint32(7) - dev := unix.Mkdev(major, minor) - - if unix.Major(dev) != major { - t.Errorf("Major(%#x) == %d, want %d", dev, unix.Major(dev), major) - } - if unix.Minor(dev) != minor { - t.Errorf("Minor(%#x) == %d, want %d", dev, unix.Minor(dev), minor) - } -} - -// mktmpfifo creates a temporary FIFO and provides a cleanup function. -func mktmpfifo(t *testing.T) (*os.File, func()) { - err := unix.Mkfifo("fifo", 0666) - if err != nil { - t.Fatalf("mktmpfifo: failed to create FIFO: %v", err) - } - - f, err := os.OpenFile("fifo", os.O_RDWR, 0666) - if err != nil { - os.Remove("fifo") - t.Fatalf("mktmpfifo: failed to open FIFO: %v", err) - } - - return f, func() { - f.Close() - os.Remove("fifo") - } -} - -// utilities taken from os/os_test.go - -func touch(t *testing.T, name string) { - f, err := os.Create(name) - if err != nil { - t.Fatal(err) - } - if err := f.Close(); err != nil { - t.Fatal(err) - } -} - -// chtmpdir changes the working directory to a new temporary directory and -// provides a cleanup function. Used when PWD is read-only. -func chtmpdir(t *testing.T) func() { - oldwd, err := os.Getwd() - if err != nil { - t.Fatalf("chtmpdir: %v", err) - } - d, err := ioutil.TempDir("", "test") - if err != nil { - t.Fatalf("chtmpdir: %v", err) - } - if err := os.Chdir(d); err != nil { - t.Fatalf("chtmpdir: %v", err) - } - return func() { - if err := os.Chdir(oldwd); err != nil { - t.Fatalf("chtmpdir: %v", err) - } - os.RemoveAll(d) - } -} diff --git a/vendor/golang.org/x/sys/unix/timestruct_test.go b/vendor/golang.org/x/sys/unix/timestruct_test.go deleted file mode 100644 index 1a72fdb3..00000000 --- a/vendor/golang.org/x/sys/unix/timestruct_test.go +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2017 The Go Authors. All right reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris - -package unix_test - -import ( - "testing" - "time" - "unsafe" - - "golang.org/x/sys/unix" -) - -func TestTimeToTimespec(t *testing.T) { - timeTests := []struct { - time time.Time - valid bool - }{ - {time.Unix(0, 0), true}, - {time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC), true}, - {time.Date(2262, time.December, 31, 23, 0, 0, 0, time.UTC), false}, - {time.Unix(0x7FFFFFFF, 0), true}, - {time.Unix(0x80000000, 0), false}, - {time.Unix(0x7FFFFFFF, 1000000000), false}, - {time.Unix(0x7FFFFFFF, 999999999), true}, - {time.Unix(-0x80000000, 0), true}, - {time.Unix(-0x80000001, 0), false}, - {time.Date(2038, time.January, 19, 3, 14, 7, 0, time.UTC), true}, - {time.Date(2038, time.January, 19, 3, 14, 8, 0, time.UTC), false}, - {time.Date(1901, time.December, 13, 20, 45, 52, 0, time.UTC), true}, - {time.Date(1901, time.December, 13, 20, 45, 51, 0, time.UTC), false}, - } - - // Currently all targets have either int32 or int64 for Timespec.Sec. - // If there were a new target with unsigned or floating point type for - // it, this test must be adjusted. - have64BitTime := (unsafe.Sizeof(unix.Timespec{}.Sec) == 8) - for _, tt := range timeTests { - ts, err := unix.TimeToTimespec(tt.time) - tt.valid = tt.valid || have64BitTime - if tt.valid && err != nil { - t.Errorf("TimeToTimespec(%v): %v", tt.time, err) - } - if err == nil { - tstime := time.Unix(int64(ts.Sec), int64(ts.Nsec)) - if !tstime.Equal(tt.time) { - t.Errorf("TimeToTimespec(%v) is the time %v", tt.time, tstime) - } - } - } -} diff --git a/vendor/golang.org/x/sys/unix/xattr_test.go b/vendor/golang.org/x/sys/unix/xattr_test.go deleted file mode 100644 index 57fc84fb..00000000 --- a/vendor/golang.org/x/sys/unix/xattr_test.go +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build darwin freebsd linux netbsd - -package unix_test - -import ( - "io/ioutil" - "os" - "runtime" - "strings" - "testing" - - "golang.org/x/sys/unix" -) - -func TestXattr(t *testing.T) { - defer chtmpdir(t)() - - f := "xattr1" - touch(t, f) - - xattrName := "user.test" - xattrDataSet := "gopher" - - err := unix.Setxattr(f, xattrName, []byte{}, 0) - if err == unix.ENOTSUP || err == unix.EOPNOTSUPP { - t.Skip("filesystem does not support extended attributes, skipping test") - } else if err != nil { - t.Fatalf("Setxattr: %v", err) - } - - err = unix.Setxattr(f, xattrName, []byte(xattrDataSet), 0) - if err != nil { - t.Fatalf("Setxattr: %v", err) - } - - // find size - size, err := unix.Listxattr(f, nil) - if err != nil { - t.Fatalf("Listxattr: %v", err) - } - - if size <= 0 { - t.Fatalf("Listxattr returned an empty list of attributes") - } - - buf := make([]byte, size) - read, err := unix.Listxattr(f, buf) - if err != nil { - t.Fatalf("Listxattr: %v", err) - } - - xattrs := stringsFromByteSlice(buf[:read]) - - xattrWant := xattrName - if runtime.GOOS == "freebsd" { - // On FreeBSD, the namespace is stored separately from the xattr - // name and Listxattr doesn't return the namespace prefix. - xattrWant = strings.TrimPrefix(xattrWant, "user.") - } - found := false - for _, name := range xattrs { - if name == xattrWant { - found = true - } - } - - if !found { - t.Errorf("Listxattr did not return previously set attribute '%s'", xattrName) - } - - // find size - size, err = unix.Getxattr(f, xattrName, nil) - if err != nil { - t.Fatalf("Getxattr: %v", err) - } - - if size <= 0 { - t.Fatalf("Getxattr returned an empty attribute") - } - - xattrDataGet := make([]byte, size) - _, err = unix.Getxattr(f, xattrName, xattrDataGet) - if err != nil { - t.Fatalf("Getxattr: %v", err) - } - - got := string(xattrDataGet) - if got != xattrDataSet { - t.Errorf("Getxattr: expected attribute value %s, got %s", xattrDataSet, got) - } - - err = unix.Removexattr(f, xattrName) - if err != nil { - t.Fatalf("Removexattr: %v", err) - } - - n := "nonexistent" - err = unix.Lsetxattr(n, xattrName, []byte(xattrDataSet), 0) - if err != unix.ENOENT { - t.Errorf("Lsetxattr: expected %v on non-existent file, got %v", unix.ENOENT, err) - } - - _, err = unix.Lgetxattr(n, xattrName, nil) - if err != unix.ENOENT { - t.Errorf("Lgetxattr: %v", err) - } - - s := "symlink1" - err = os.Symlink(n, s) - if err != nil { - t.Fatal(err) - } - - err = unix.Lsetxattr(s, xattrName, []byte(xattrDataSet), 0) - if err != nil { - // Linux and Android doen't support xattrs on symlinks according - // to xattr(7), so just test that we get the proper error. - if (runtime.GOOS != "linux" && runtime.GOOS != "android") || err != unix.EPERM { - t.Fatalf("Lsetxattr: %v", err) - } - } -} - -func TestFdXattr(t *testing.T) { - file, err := ioutil.TempFile("", "TestFdXattr") - if err != nil { - t.Fatal(err) - } - defer os.Remove(file.Name()) - defer file.Close() - - fd := int(file.Fd()) - xattrName := "user.test" - xattrDataSet := "gopher" - - err = unix.Fsetxattr(fd, xattrName, []byte(xattrDataSet), 0) - if err == unix.ENOTSUP || err == unix.EOPNOTSUPP { - t.Skip("filesystem does not support extended attributes, skipping test") - } else if err != nil { - t.Fatalf("Fsetxattr: %v", err) - } - - // find size - size, err := unix.Flistxattr(fd, nil) - if err != nil { - t.Fatalf("Flistxattr: %v", err) - } - - if size <= 0 { - t.Fatalf("Flistxattr returned an empty list of attributes") - } - - buf := make([]byte, size) - read, err := unix.Flistxattr(fd, buf) - if err != nil { - t.Fatalf("Flistxattr: %v", err) - } - - xattrs := stringsFromByteSlice(buf[:read]) - - xattrWant := xattrName - if runtime.GOOS == "freebsd" { - // On FreeBSD, the namespace is stored separately from the xattr - // name and Listxattr doesn't return the namespace prefix. - xattrWant = strings.TrimPrefix(xattrWant, "user.") - } - found := false - for _, name := range xattrs { - if name == xattrWant { - found = true - } - } - - if !found { - t.Errorf("Flistxattr did not return previously set attribute '%s'", xattrName) - } - - // find size - size, err = unix.Fgetxattr(fd, xattrName, nil) - if err != nil { - t.Fatalf("Fgetxattr: %v", err) - } - - if size <= 0 { - t.Fatalf("Fgetxattr returned an empty attribute") - } - - xattrDataGet := make([]byte, size) - _, err = unix.Fgetxattr(fd, xattrName, xattrDataGet) - if err != nil { - t.Fatalf("Fgetxattr: %v", err) - } - - got := string(xattrDataGet) - if got != xattrDataSet { - t.Errorf("Fgetxattr: expected attribute value %s, got %s", xattrDataSet, got) - } - - err = unix.Fremovexattr(fd, xattrName) - if err != nil { - t.Fatalf("Fremovexattr: %v", err) - } -} diff --git a/vendor/golang.org/x/text/CONTRIBUTING.md b/vendor/golang.org/x/text/CONTRIBUTING.md deleted file mode 100644 index 88dff59b..00000000 --- a/vendor/golang.org/x/text/CONTRIBUTING.md +++ /dev/null @@ -1,31 +0,0 @@ -# Contributing to Go - -Go is an open source project. - -It is the work of hundreds of contributors. We appreciate your help! - - -## Filing issues - -When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions: - -1. What version of Go are you using (`go version`)? -2. What operating system and processor architecture are you using? -3. What did you do? -4. What did you expect to see? -5. What did you see instead? - -General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker. -The gophers there will answer or ask you to file an issue if you've tripped over a bug. - -## Contributing code - -Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html) -before sending patches. - -**We do not accept GitHub pull requests** -(we use [Gerrit](https://code.google.com/p/gerrit/) instead for code review). - -Unless otherwise noted, the Go source files are distributed under -the BSD-style license found in the LICENSE file. - diff --git a/vendor/golang.org/x/text/README.md b/vendor/golang.org/x/text/README.md deleted file mode 100644 index b3f365ee..00000000 --- a/vendor/golang.org/x/text/README.md +++ /dev/null @@ -1,93 +0,0 @@ -# Go Text - -This repository holds supplementary Go libraries for text processing, many involving Unicode. - -## Semantic Versioning -This repo uses Semantic versioning (http://semver.org/), so -1. MAJOR version when you make incompatible API changes, -1. MINOR version when you add functionality in a backwards-compatible manner, - and -1. PATCH version when you make backwards-compatible bug fixes. - -Until version 1.0.0 of x/text is reached, the minor version is considered a -major version. So going from 0.1.0 to 0.2.0 is considered to be a major version -bump. - -A major new CLDR version is mapped to a minor version increase in x/text. -Any other new CLDR version is mapped to a patch version increase in x/text. - -It is important that the Unicode version used in `x/text` matches the one used -by your Go compiler. The `x/text` repository supports multiple versions of -Unicode and will match the version of Unicode to that of the Go compiler. At the -moment this is supported for Go compilers from version 1.7. - -## Download/Install - -The easiest way to install is to run `go get -u golang.org/x/text`. You can -also manually git clone the repository to `$GOPATH/src/golang.org/x/text`. - -## Contribute -To submit changes to this repository, see http://golang.org/doc/contribute.html. - -To generate the tables in this repository (except for the encoding tables), -run go generate from this directory. By default tables are generated for the -Unicode version in core and the CLDR version defined in -golang.org/x/text/unicode/cldr. - -Running go generate will as a side effect create a DATA subdirectory in this -directory, which holds all files that are used as a source for generating the -tables. This directory will also serve as a cache. - -## Testing -Run - - go test ./... - -from this directory to run all tests. Add the "-tags icu" flag to also run -ICU conformance tests (if available). This requires that you have the correct -ICU version installed on your system. - -TODO: -- updating unversioned source files. - -## Generating Tables - -To generate the tables in this repository (except for the encoding -tables), run `go generate` from this directory. By default tables are -generated for the Unicode version in core and the CLDR version defined in -golang.org/x/text/unicode/cldr. - -Running go generate will as a side effect create a DATA subdirectory in this -directory which holds all files that are used as a source for generating the -tables. This directory will also serve as a cache. - -## Versions -To update a Unicode version run - - UNICODE_VERSION=x.x.x go generate - -where `x.x.x` must correspond to a directory in http://www.unicode.org/Public/. -If this version is newer than the version in core it will also update the -relevant packages there. The idna package in x/net will always be updated. - -To update a CLDR version run - - CLDR_VERSION=version go generate - -where `version` must correspond to a directory in -http://www.unicode.org/Public/cldr/. - -Note that the code gets adapted over time to changes in the data and that -backwards compatibility is not maintained. -So updating to a different version may not work. - -The files in DATA/{iana|icu|w3|whatwg} are currently not versioned. - -## Report Issues / Send Patches - -This repository uses Gerrit for code changes. To learn how to submit changes to -this repository, see https://golang.org/doc/contribute.html. - -The main issue tracker for the image repository is located at -https://github.com/golang/go/issues. Prefix your issue with "x/image:" in the -subject line, so it is easy to find. diff --git a/vendor/golang.org/x/text/codereview.cfg b/vendor/golang.org/x/text/codereview.cfg deleted file mode 100644 index 3f8b14b6..00000000 --- a/vendor/golang.org/x/text/codereview.cfg +++ /dev/null @@ -1 +0,0 @@ -issuerepo: golang/go diff --git a/vendor/golang.org/x/text/collate/build/builder_test.go b/vendor/golang.org/x/text/collate/build/builder_test.go deleted file mode 100644 index ff0aba3a..00000000 --- a/vendor/golang.org/x/text/collate/build/builder_test.go +++ /dev/null @@ -1,290 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package build - -import "testing" - -// cjk returns an implicit collation element for a CJK rune. -func cjk(r rune) []rawCE { - // A CJK character C is represented in the DUCET as - // [.AAAA.0020.0002.C][.BBBB.0000.0000.C] - // Where AAAA is the most significant 15 bits plus a base value. - // Any base value will work for the test, so we pick the common value of FB40. - const base = 0xFB40 - return []rawCE{ - {w: []int{base + int(r>>15), defaultSecondary, defaultTertiary, int(r)}}, - {w: []int{int(r&0x7FFF) | 0x8000, 0, 0, int(r)}}, - } -} - -func pCE(p int) []rawCE { - return mkCE([]int{p, defaultSecondary, defaultTertiary, 0}, 0) -} - -func pqCE(p, q int) []rawCE { - return mkCE([]int{p, defaultSecondary, defaultTertiary, q}, 0) -} - -func ptCE(p, t int) []rawCE { - return mkCE([]int{p, defaultSecondary, t, 0}, 0) -} - -func ptcCE(p, t int, ccc uint8) []rawCE { - return mkCE([]int{p, defaultSecondary, t, 0}, ccc) -} - -func sCE(s int) []rawCE { - return mkCE([]int{0, s, defaultTertiary, 0}, 0) -} - -func stCE(s, t int) []rawCE { - return mkCE([]int{0, s, t, 0}, 0) -} - -func scCE(s int, ccc uint8) []rawCE { - return mkCE([]int{0, s, defaultTertiary, 0}, ccc) -} - -func mkCE(w []int, ccc uint8) []rawCE { - return []rawCE{rawCE{w, ccc}} -} - -// ducetElem is used to define test data that is used to generate a table. -type ducetElem struct { - str string - ces []rawCE -} - -func newBuilder(t *testing.T, ducet []ducetElem) *Builder { - b := NewBuilder() - for _, e := range ducet { - ces := [][]int{} - for _, ce := range e.ces { - ces = append(ces, ce.w) - } - if err := b.Add([]rune(e.str), ces, nil); err != nil { - t.Errorf(err.Error()) - } - } - b.t = &table{} - b.root.sort() - return b -} - -type convertTest struct { - in, out []rawCE - err bool -} - -var convLargeTests = []convertTest{ - {pCE(0xFB39), pCE(0xFB39), false}, - {cjk(0x2F9B2), pqCE(0x3F9B2, 0x2F9B2), false}, - {pCE(0xFB40), pCE(0), true}, - {append(pCE(0xFB40), pCE(0)[0]), pCE(0), true}, - {pCE(0xFFFE), pCE(illegalOffset), false}, - {pCE(0xFFFF), pCE(illegalOffset + 1), false}, -} - -func TestConvertLarge(t *testing.T) { - for i, tt := range convLargeTests { - e := new(entry) - for _, ce := range tt.in { - e.elems = append(e.elems, makeRawCE(ce.w, ce.ccc)) - } - elems, err := convertLargeWeights(e.elems) - if tt.err { - if err == nil { - t.Errorf("%d: expected error; none found", i) - } - continue - } else if err != nil { - t.Errorf("%d: unexpected error: %v", i, err) - } - if !equalCEArrays(elems, tt.out) { - t.Errorf("%d: conversion was %x; want %x", i, elems, tt.out) - } - } -} - -// Collation element table for simplify tests. -var simplifyTest = []ducetElem{ - {"\u0300", sCE(30)}, // grave - {"\u030C", sCE(40)}, // caron - {"A", ptCE(100, 8)}, - {"D", ptCE(104, 8)}, - {"E", ptCE(105, 8)}, - {"I", ptCE(110, 8)}, - {"z", ptCE(130, 8)}, - {"\u05F2", append(ptCE(200, 4), ptCE(200, 4)[0])}, - {"\u05B7", sCE(80)}, - {"\u00C0", append(ptCE(100, 8), sCE(30)...)}, // A with grave, can be removed - {"\u00C8", append(ptCE(105, 8), sCE(30)...)}, // E with grave - {"\uFB1F", append(ptCE(200, 4), ptCE(200, 4)[0], sCE(80)[0])}, // eliminated by NFD - {"\u00C8\u0302", ptCE(106, 8)}, // block previous from simplifying - {"\u01C5", append(ptCE(104, 9), ptCE(130, 4)[0], stCE(40, maxTertiary)[0])}, // eliminated by NFKD - // no removal: tertiary value of third element is not maxTertiary - {"\u2162", append(ptCE(110, 9), ptCE(110, 4)[0], ptCE(110, 8)[0])}, -} - -var genColTests = []ducetElem{ - {"\uFA70", pqCE(0x1FA70, 0xFA70)}, - {"A\u0300", append(ptCE(100, 8), sCE(30)...)}, - {"A\u0300\uFA70", append(ptCE(100, 8), sCE(30)[0], pqCE(0x1FA70, 0xFA70)[0])}, - {"A\u0300A\u0300", append(ptCE(100, 8), sCE(30)[0], ptCE(100, 8)[0], sCE(30)[0])}, -} - -func TestGenColElems(t *testing.T) { - b := newBuilder(t, simplifyTest[:5]) - - for i, tt := range genColTests { - res := b.root.genColElems(tt.str) - if !equalCEArrays(tt.ces, res) { - t.Errorf("%d: result %X; want %X", i, res, tt.ces) - } - } -} - -type strArray []string - -func (sa strArray) contains(s string) bool { - for _, e := range sa { - if e == s { - return true - } - } - return false -} - -var simplifyRemoved = strArray{"\u00C0", "\uFB1F"} -var simplifyMarked = strArray{"\u01C5"} - -func TestSimplify(t *testing.T) { - b := newBuilder(t, simplifyTest) - o := &b.root - simplify(o) - - for i, tt := range simplifyTest { - if simplifyRemoved.contains(tt.str) { - continue - } - e := o.find(tt.str) - if e.str != tt.str || !equalCEArrays(e.elems, tt.ces) { - t.Errorf("%d: found element %s -> %X; want %s -> %X", i, e.str, e.elems, tt.str, tt.ces) - break - } - } - var i, k int - for e := o.front(); e != nil; e, _ = e.nextIndexed() { - gold := simplifyMarked.contains(e.str) - if gold { - k++ - } - if gold != e.decompose { - t.Errorf("%d: %s has decompose %v; want %v", i, e.str, e.decompose, gold) - } - i++ - } - if k != len(simplifyMarked) { - t.Errorf(" an entry that should be marked as decompose was deleted") - } -} - -var expandTest = []ducetElem{ - {"\u0300", append(scCE(29, 230), scCE(30, 230)...)}, - {"\u00C0", append(ptCE(100, 8), scCE(30, 230)...)}, - {"\u00C8", append(ptCE(105, 8), scCE(30, 230)...)}, - {"\u00C9", append(ptCE(105, 8), scCE(30, 230)...)}, // identical expansion - {"\u05F2", append(ptCE(200, 4), ptCE(200, 4)[0], ptCE(200, 4)[0])}, - {"\u01FF", append(ptCE(200, 4), ptcCE(201, 4, 0)[0], scCE(30, 230)[0])}, -} - -func TestExpand(t *testing.T) { - const ( - totalExpansions = 5 - totalElements = 2 + 2 + 2 + 3 + 3 + totalExpansions - ) - b := newBuilder(t, expandTest) - o := &b.root - b.processExpansions(o) - - e := o.front() - for _, tt := range expandTest { - exp := b.t.ExpandElem[e.expansionIndex:] - if int(exp[0]) != len(tt.ces) { - t.Errorf("%U: len(expansion)==%d; want %d", []rune(tt.str)[0], exp[0], len(tt.ces)) - } - exp = exp[1:] - for j, w := range tt.ces { - if ce, _ := makeCE(w); exp[j] != ce { - t.Errorf("%U: element %d is %X; want %X", []rune(tt.str)[0], j, exp[j], ce) - } - } - e, _ = e.nextIndexed() - } - // Verify uniquing. - if len(b.t.ExpandElem) != totalElements { - t.Errorf("len(expandElem)==%d; want %d", len(b.t.ExpandElem), totalElements) - } -} - -var contractTest = []ducetElem{ - {"abc", pCE(102)}, - {"abd", pCE(103)}, - {"a", pCE(100)}, - {"ab", pCE(101)}, - {"ac", pCE(104)}, - {"bcd", pCE(202)}, - {"b", pCE(200)}, - {"bc", pCE(201)}, - {"bd", pCE(203)}, - // shares suffixes with a* - {"Ab", pCE(301)}, - {"A", pCE(300)}, - {"Ac", pCE(304)}, - {"Abc", pCE(302)}, - {"Abd", pCE(303)}, - // starter to be ignored - {"z", pCE(1000)}, -} - -func TestContract(t *testing.T) { - const ( - totalElements = 5 + 5 + 4 - ) - b := newBuilder(t, contractTest) - o := &b.root - b.processContractions(o) - - indexMap := make(map[int]bool) - handleMap := make(map[rune]*entry) - for e := o.front(); e != nil; e, _ = e.nextIndexed() { - if e.contractionHandle.n > 0 { - handleMap[e.runes[0]] = e - indexMap[e.contractionHandle.index] = true - } - } - // Verify uniquing. - if len(indexMap) != 2 { - t.Errorf("number of tries is %d; want %d", len(indexMap), 2) - } - for _, tt := range contractTest { - e, ok := handleMap[[]rune(tt.str)[0]] - if !ok { - continue - } - str := tt.str[1:] - offset, n := lookup(&b.t.ContractTries, e.contractionHandle, []byte(str)) - if len(str) != n { - t.Errorf("%s: bytes consumed==%d; want %d", tt.str, n, len(str)) - } - ce := b.t.ContractElem[offset+e.contractionIndex] - if want, _ := makeCE(tt.ces[0]); want != ce { - t.Errorf("%s: element %X; want %X", tt.str, ce, want) - } - } - if len(b.t.ContractElem) != totalElements { - t.Errorf("len(expandElem)==%d; want %d", len(b.t.ContractElem), totalElements) - } -} diff --git a/vendor/golang.org/x/text/collate/build/colelem_test.go b/vendor/golang.org/x/text/collate/build/colelem_test.go deleted file mode 100644 index d0c8d07d..00000000 --- a/vendor/golang.org/x/text/collate/build/colelem_test.go +++ /dev/null @@ -1,215 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package build - -import ( - "testing" - - "golang.org/x/text/internal/colltab" -) - -type ceTest struct { - f func(in []int) (uint32, error) - arg []int - val uint32 -} - -func normalCE(in []int) (ce uint32, err error) { - return makeCE(rawCE{w: in[:3], ccc: uint8(in[3])}) -} - -func expandCE(in []int) (ce uint32, err error) { - return makeExpandIndex(in[0]) -} - -func contractCE(in []int) (ce uint32, err error) { - return makeContractIndex(ctHandle{in[0], in[1]}, in[2]) -} - -func decompCE(in []int) (ce uint32, err error) { - return makeDecompose(in[0], in[1]) -} - -var ceTests = []ceTest{ - {normalCE, []int{0, 0, 0, 0}, 0xA0000000}, - {normalCE, []int{0, 0x28, 3, 0}, 0xA0002803}, - {normalCE, []int{0, 0x28, 3, 0xFF}, 0xAFF02803}, - {normalCE, []int{100, defaultSecondary, 3, 0}, 0x0000C883}, - // non-ignorable primary with non-default secondary - {normalCE, []int{100, 0x28, defaultTertiary, 0}, 0x4000C828}, - {normalCE, []int{100, defaultSecondary + 8, 3, 0}, 0x0000C983}, - {normalCE, []int{100, 0, 3, 0}, 0xFFFF}, // non-ignorable primary with non-supported secondary - {normalCE, []int{100, 1, 3, 0}, 0xFFFF}, - {normalCE, []int{1 << maxPrimaryBits, defaultSecondary, 0, 0}, 0xFFFF}, - {normalCE, []int{0, 1 << maxSecondaryBits, 0, 0}, 0xFFFF}, - {normalCE, []int{100, defaultSecondary, 1 << maxTertiaryBits, 0}, 0xFFFF}, - {normalCE, []int{0x123, defaultSecondary, 8, 0xFF}, 0x88FF0123}, - {normalCE, []int{0x123, defaultSecondary + 1, 8, 0xFF}, 0xFFFF}, - - {contractCE, []int{0, 0, 0}, 0xC0000000}, - {contractCE, []int{1, 1, 1}, 0xC0010011}, - {contractCE, []int{1, (1 << maxNBits) - 1, 1}, 0xC001001F}, - {contractCE, []int{(1 << maxTrieIndexBits) - 1, 1, 1}, 0xC001FFF1}, - {contractCE, []int{1, 1, (1 << maxContractOffsetBits) - 1}, 0xDFFF0011}, - {contractCE, []int{1, (1 << maxNBits), 1}, 0xFFFF}, - {contractCE, []int{(1 << maxTrieIndexBits), 1, 1}, 0xFFFF}, - {contractCE, []int{1, (1 << maxContractOffsetBits), 1}, 0xFFFF}, - - {expandCE, []int{0}, 0xE0000000}, - {expandCE, []int{5}, 0xE0000005}, - {expandCE, []int{(1 << maxExpandIndexBits) - 1}, 0xE000FFFF}, - {expandCE, []int{1 << maxExpandIndexBits}, 0xFFFF}, - - {decompCE, []int{0, 0}, 0xF0000000}, - {decompCE, []int{1, 1}, 0xF0000101}, - {decompCE, []int{0x1F, 0x1F}, 0xF0001F1F}, - {decompCE, []int{256, 0x1F}, 0xFFFF}, - {decompCE, []int{0x1F, 256}, 0xFFFF}, -} - -func TestColElem(t *testing.T) { - for i, tt := range ceTests { - in := make([]int, len(tt.arg)) - copy(in, tt.arg) - ce, err := tt.f(in) - if tt.val == 0xFFFF { - if err == nil { - t.Errorf("%d: expected error for args %x", i, tt.arg) - } - continue - } - if err != nil { - t.Errorf("%d: unexpected error: %v", i, err.Error()) - } - if ce != tt.val { - t.Errorf("%d: colElem=%X; want %X", i, ce, tt.val) - } - } -} - -func mkRawCES(in [][]int) []rawCE { - out := []rawCE{} - for _, w := range in { - out = append(out, rawCE{w: w}) - } - return out -} - -type weightsTest struct { - a, b [][]int - level colltab.Level - result int -} - -var nextWeightTests = []weightsTest{ - { - a: [][]int{{100, 20, 5, 0}}, - b: [][]int{{101, defaultSecondary, defaultTertiary, 0}}, - level: colltab.Primary, - }, - { - a: [][]int{{100, 20, 5, 0}}, - b: [][]int{{100, 21, defaultTertiary, 0}}, - level: colltab.Secondary, - }, - { - a: [][]int{{100, 20, 5, 0}}, - b: [][]int{{100, 20, 6, 0}}, - level: colltab.Tertiary, - }, - { - a: [][]int{{100, 20, 5, 0}}, - b: [][]int{{100, 20, 5, 0}}, - level: colltab.Identity, - }, -} - -var extra = [][]int{{200, 32, 8, 0}, {0, 32, 8, 0}, {0, 0, 8, 0}, {0, 0, 0, 0}} - -func TestNextWeight(t *testing.T) { - for i, tt := range nextWeightTests { - test := func(l colltab.Level, tt weightsTest, a, gold [][]int) { - res := nextWeight(tt.level, mkRawCES(a)) - if !equalCEArrays(mkRawCES(gold), res) { - t.Errorf("%d:%d: expected weights %d; found %d", i, l, gold, res) - } - } - test(-1, tt, tt.a, tt.b) - for l := colltab.Primary; l <= colltab.Tertiary; l++ { - if tt.level <= l { - test(l, tt, append(tt.a, extra[l]), tt.b) - } else { - test(l, tt, append(tt.a, extra[l]), append(tt.b, extra[l])) - } - } - } -} - -var compareTests = []weightsTest{ - { - [][]int{{100, 20, 5, 0}}, - [][]int{{100, 20, 5, 0}}, - colltab.Identity, - 0, - }, - { - [][]int{{100, 20, 5, 0}, extra[0]}, - [][]int{{100, 20, 5, 1}}, - colltab.Primary, - 1, - }, - { - [][]int{{100, 20, 5, 0}}, - [][]int{{101, 20, 5, 0}}, - colltab.Primary, - -1, - }, - { - [][]int{{101, 20, 5, 0}}, - [][]int{{100, 20, 5, 0}}, - colltab.Primary, - 1, - }, - { - [][]int{{100, 0, 0, 0}, {0, 20, 5, 0}}, - [][]int{{0, 20, 5, 0}, {100, 0, 0, 0}}, - colltab.Identity, - 0, - }, - { - [][]int{{100, 20, 5, 0}}, - [][]int{{100, 21, 5, 0}}, - colltab.Secondary, - -1, - }, - { - [][]int{{100, 20, 5, 0}}, - [][]int{{100, 20, 2, 0}}, - colltab.Tertiary, - 1, - }, - { - [][]int{{100, 20, 5, 1}}, - [][]int{{100, 20, 5, 2}}, - colltab.Quaternary, - -1, - }, -} - -func TestCompareWeights(t *testing.T) { - for i, tt := range compareTests { - test := func(tt weightsTest, a, b [][]int) { - res, level := compareWeights(mkRawCES(a), mkRawCES(b)) - if res != tt.result { - t.Errorf("%d: expected comparison result %d; found %d", i, tt.result, res) - } - if level != tt.level { - t.Errorf("%d: expected level %d; found %d", i, tt.level, level) - } - } - test(tt, tt.a, tt.b) - test(tt, append(tt.a, extra[0]), append(tt.b, extra[0])) - } -} diff --git a/vendor/golang.org/x/text/collate/build/contract_test.go b/vendor/golang.org/x/text/collate/build/contract_test.go deleted file mode 100644 index 2e0eaecd..00000000 --- a/vendor/golang.org/x/text/collate/build/contract_test.go +++ /dev/null @@ -1,266 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package build - -import ( - "bytes" - "sort" - "testing" - - "golang.org/x/text/internal/colltab" -) - -var largetosmall = []stridx{ - {"a", 5}, - {"ab", 4}, - {"abc", 3}, - {"abcd", 2}, - {"abcde", 1}, - {"abcdef", 0}, -} - -var offsetSortTests = [][]stridx{ - { - {"bcde", 1}, - {"bc", 5}, - {"ab", 4}, - {"bcd", 3}, - {"abcd", 0}, - {"abc", 2}, - }, - largetosmall, -} - -func TestOffsetSort(t *testing.T) { - for i, st := range offsetSortTests { - sort.Sort(offsetSort(st)) - for j, si := range st { - if j != si.index { - t.Errorf("%d: failed: %v", i, st) - } - } - } - for i, tt := range genStateTests { - // ensure input is well-formed - sort.Sort(offsetSort(tt.in)) - for j, si := range tt.in { - if si.index != j+1 { - t.Errorf("%dth sort failed: %v", i, tt.in) - } - } - } -} - -var genidxtest1 = []stridx{ - {"bcde", 3}, - {"bc", 6}, - {"ab", 2}, - {"bcd", 5}, - {"abcd", 0}, - {"abc", 1}, - {"bcdf", 4}, -} - -var genidxSortTests = [][]stridx{ - genidxtest1, - largetosmall, -} - -func TestGenIdxSort(t *testing.T) { - for i, st := range genidxSortTests { - sort.Sort(genidxSort(st)) - for j, si := range st { - if j != si.index { - t.Errorf("%dth sort failed %v", i, st) - break - } - } - } -} - -var entrySortTests = []colltab.ContractTrieSet{ - { - {10, 0, 1, 3}, - {99, 0, 1, 0}, - {20, 50, 0, 2}, - {30, 0, 1, 1}, - }, -} - -func TestEntrySort(t *testing.T) { - for i, et := range entrySortTests { - sort.Sort(entrySort(et)) - for j, fe := range et { - if j != int(fe.I) { - t.Errorf("%dth sort failed %v", i, et) - break - } - } - } -} - -type GenStateTest struct { - in []stridx - firstBlockLen int - out colltab.ContractTrieSet -} - -var genStateTests = []GenStateTest{ - {[]stridx{ - {"abc", 1}, - }, - 1, - colltab.ContractTrieSet{ - {'a', 0, 1, noIndex}, - {'b', 0, 1, noIndex}, - {'c', 'c', final, 1}, - }, - }, - {[]stridx{ - {"abc", 1}, - {"abd", 2}, - {"abe", 3}, - }, - 1, - colltab.ContractTrieSet{ - {'a', 0, 1, noIndex}, - {'b', 0, 1, noIndex}, - {'c', 'e', final, 1}, - }, - }, - {[]stridx{ - {"abc", 1}, - {"ab", 2}, - {"a", 3}, - }, - 1, - colltab.ContractTrieSet{ - {'a', 0, 1, 3}, - {'b', 0, 1, 2}, - {'c', 'c', final, 1}, - }, - }, - {[]stridx{ - {"abc", 1}, - {"abd", 2}, - {"ab", 3}, - {"ac", 4}, - {"a", 5}, - {"b", 6}, - }, - 2, - colltab.ContractTrieSet{ - {'b', 'b', final, 6}, - {'a', 0, 2, 5}, - {'c', 'c', final, 4}, - {'b', 0, 1, 3}, - {'c', 'd', final, 1}, - }, - }, - {[]stridx{ - {"bcde", 2}, - {"bc", 7}, - {"ab", 6}, - {"bcd", 5}, - {"abcd", 1}, - {"abc", 4}, - {"bcdf", 3}, - }, - 2, - colltab.ContractTrieSet{ - {'b', 3, 1, noIndex}, - {'a', 0, 1, noIndex}, - {'b', 0, 1, 6}, - {'c', 0, 1, 4}, - {'d', 'd', final, 1}, - {'c', 0, 1, 7}, - {'d', 0, 1, 5}, - {'e', 'f', final, 2}, - }, - }, -} - -func TestGenStates(t *testing.T) { - for i, tt := range genStateTests { - si := []stridx{} - for _, e := range tt.in { - si = append(si, e) - } - // ensure input is well-formed - sort.Sort(genidxSort(si)) - ct := colltab.ContractTrieSet{} - n, _ := genStates(&ct, si) - if nn := tt.firstBlockLen; nn != n { - t.Errorf("%d: block len %v; want %v", i, n, nn) - } - if lv, lw := len(ct), len(tt.out); lv != lw { - t.Errorf("%d: len %v; want %v", i, lv, lw) - continue - } - for j, fe := range tt.out { - const msg = "%d:%d: value %s=%v; want %v" - if fe.L != ct[j].L { - t.Errorf(msg, i, j, "l", ct[j].L, fe.L) - } - if fe.H != ct[j].H { - t.Errorf(msg, i, j, "h", ct[j].H, fe.H) - } - if fe.N != ct[j].N { - t.Errorf(msg, i, j, "n", ct[j].N, fe.N) - } - if fe.I != ct[j].I { - t.Errorf(msg, i, j, "i", ct[j].I, fe.I) - } - } - } -} - -func TestLookupContraction(t *testing.T) { - for i, tt := range genStateTests { - input := []string{} - for _, e := range tt.in { - input = append(input, e.str) - } - cts := colltab.ContractTrieSet{} - h, _ := appendTrie(&cts, input) - for j, si := range tt.in { - str := si.str - for _, s := range []string{str, str + "X"} { - msg := "%d:%d: %s(%s) %v; want %v" - idx, sn := lookup(&cts, h, []byte(s)) - if idx != si.index { - t.Errorf(msg, i, j, "index", s, idx, si.index) - } - if sn != len(str) { - t.Errorf(msg, i, j, "sn", s, sn, len(str)) - } - } - } - } -} - -func TestPrintContractionTrieSet(t *testing.T) { - testdata := colltab.ContractTrieSet(genStateTests[4].out) - buf := &bytes.Buffer{} - print(&testdata, buf, "test") - if contractTrieOutput != buf.String() { - t.Errorf("output differs; found\n%s", buf.String()) - println(string(buf.Bytes())) - } -} - -const contractTrieOutput = `// testCTEntries: 8 entries, 32 bytes -var testCTEntries = [8]struct{L,H,N,I uint8}{ - {0x62, 0x3, 1, 255}, - {0x61, 0x0, 1, 255}, - {0x62, 0x0, 1, 6}, - {0x63, 0x0, 1, 4}, - {0x64, 0x64, 0, 1}, - {0x63, 0x0, 1, 7}, - {0x64, 0x0, 1, 5}, - {0x65, 0x66, 0, 2}, -} -var testContractTrieSet = colltab.ContractTrieSet( testCTEntries[:] ) -` diff --git a/vendor/golang.org/x/text/collate/build/order_test.go b/vendor/golang.org/x/text/collate/build/order_test.go deleted file mode 100644 index 0e174bfb..00000000 --- a/vendor/golang.org/x/text/collate/build/order_test.go +++ /dev/null @@ -1,229 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package build - -import ( - "strconv" - "testing" - - "golang.org/x/text/internal/colltab" -) - -type entryTest struct { - f func(in []int) (uint32, error) - arg []int - val uint32 -} - -// makeList returns a list of entries of length n+2, with n normal -// entries plus a leading and trailing anchor. -func makeList(n int) []*entry { - es := make([]*entry, n+2) - weights := []rawCE{{w: []int{100, 20, 5, 0}}} - for i := range es { - runes := []rune{rune(i)} - es[i] = &entry{ - runes: runes, - elems: weights, - } - weights = nextWeight(colltab.Primary, weights) - } - for i := 1; i < len(es); i++ { - es[i-1].next = es[i] - es[i].prev = es[i-1] - _, es[i-1].level = compareWeights(es[i-1].elems, es[i].elems) - } - es[0].exclude = true - es[0].logical = firstAnchor - es[len(es)-1].exclude = true - es[len(es)-1].logical = lastAnchor - return es -} - -func TestNextIndexed(t *testing.T) { - const n = 5 - es := makeList(n) - for i := int64(0); i < 1<= 0; i-- { - if a[i] < a[i+1] { - break - } - } - if i < 0 { - return false - } - for j := len(a) - 1; j >= i; j-- { - if a[j] > a[i] { - a[i], a[j] = a[j], a[i] - break - } - } - for j := i + 1; j < (len(a)+i+1)/2; j++ { - a[j], a[len(a)+i-j] = a[len(a)+i-j], a[j] - } - return true -} - -func TestInsertAfter(t *testing.T) { - const n = 5 - orig := makeList(n) - perm := make([]int, n) - for i := range perm { - perm[i] = i + 1 - } - for ok := true; ok; ok = nextPerm(perm) { - es := makeList(n) - last := es[0] - for _, i := range perm { - last.insertAfter(es[i]) - last = es[i] - } - for _, e := range es { - e.elems = es[0].elems - } - e := es[0] - for _, i := range perm { - e, _ = e.nextIndexed() - if e.runes[0] != orig[i].runes[0] { - t.Errorf("%d:%d: expected entry %X; found %X", perm, i, orig[i].runes, e.runes) - break - } - } - } -} - -func TestInsertBefore(t *testing.T) { - const n = 5 - orig := makeList(n) - perm := make([]int, n) - for i := range perm { - perm[i] = i + 1 - } - for ok := true; ok; ok = nextPerm(perm) { - es := makeList(n) - last := es[len(es)-1] - for _, i := range perm { - last.insertBefore(es[i]) - last = es[i] - } - for _, e := range es { - e.elems = es[0].elems - } - e := es[0] - for i := n - 1; i >= 0; i-- { - e, _ = e.nextIndexed() - if e.runes[0] != rune(perm[i]) { - t.Errorf("%d:%d: expected entry %X; found %X", perm, i, orig[i].runes, e.runes) - break - } - } - } -} - -type entryLessTest struct { - a, b *entry - res bool -} - -var ( - w1 = []rawCE{{w: []int{100, 20, 5, 5}}} - w2 = []rawCE{{w: []int{101, 20, 5, 5}}} -) - -var entryLessTests = []entryLessTest{ - {&entry{str: "a", elems: w1}, - &entry{str: "a", elems: w1}, - false, - }, - {&entry{str: "a", elems: w1}, - &entry{str: "a", elems: w2}, - true, - }, - {&entry{str: "a", elems: w1}, - &entry{str: "b", elems: w1}, - true, - }, - {&entry{str: "a", elems: w2}, - &entry{str: "a", elems: w1}, - false, - }, - {&entry{str: "c", elems: w1}, - &entry{str: "b", elems: w1}, - false, - }, - {&entry{str: "a", elems: w1, logical: firstAnchor}, - &entry{str: "a", elems: w1}, - true, - }, - {&entry{str: "a", elems: w1}, - &entry{str: "b", elems: w1, logical: firstAnchor}, - false, - }, - {&entry{str: "b", elems: w1}, - &entry{str: "a", elems: w1, logical: lastAnchor}, - true, - }, - {&entry{str: "a", elems: w1, logical: lastAnchor}, - &entry{str: "c", elems: w1}, - false, - }, -} - -func TestEntryLess(t *testing.T) { - for i, tt := range entryLessTests { - if res := entryLess(tt.a, tt.b); res != tt.res { - t.Errorf("%d: was %v; want %v", i, res, tt.res) - } - } -} diff --git a/vendor/golang.org/x/text/collate/build/trie_test.go b/vendor/golang.org/x/text/collate/build/trie_test.go deleted file mode 100644 index 4d4f6e4d..00000000 --- a/vendor/golang.org/x/text/collate/build/trie_test.go +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package build - -import ( - "bytes" - "fmt" - "testing" -) - -// We take the smallest, largest and an arbitrary value for each -// of the UTF-8 sequence lengths. -var testRunes = []rune{ - 0x01, 0x0C, 0x7F, // 1-byte sequences - 0x80, 0x100, 0x7FF, // 2-byte sequences - 0x800, 0x999, 0xFFFF, // 3-byte sequences - 0x10000, 0x10101, 0x10FFFF, // 4-byte sequences - 0x200, 0x201, 0x202, 0x210, 0x215, // five entries in one sparse block -} - -func makeTestTrie(t *testing.T) trie { - n := newNode() - for i, r := range testRunes { - n.insert(r, uint32(i)) - } - idx := newTrieBuilder() - idx.addTrie(n) - tr, err := idx.generate() - if err != nil { - t.Errorf(err.Error()) - } - return *tr -} - -func TestGenerateTrie(t *testing.T) { - testdata := makeTestTrie(t) - buf := &bytes.Buffer{} - testdata.printArrays(buf, "test") - fmt.Fprintf(buf, "var testTrie = ") - testdata.printStruct(buf, &trieHandle{19, 0}, "test") - if output != buf.String() { - t.Error("output differs") - } -} - -var output = `// testValues: 832 entries, 3328 bytes -// Block 2 is the null block. -var testValues = [832]uint32 { - // Block 0x0, offset 0x0 - 0x000c:0x00000001, - // Block 0x1, offset 0x40 - 0x007f:0x00000002, - // Block 0x2, offset 0x80 - // Block 0x3, offset 0xc0 - 0x00c0:0x00000003, - // Block 0x4, offset 0x100 - 0x0100:0x00000004, - // Block 0x5, offset 0x140 - 0x0140:0x0000000c, 0x0141:0x0000000d, 0x0142:0x0000000e, - 0x0150:0x0000000f, - 0x0155:0x00000010, - // Block 0x6, offset 0x180 - 0x01bf:0x00000005, - // Block 0x7, offset 0x1c0 - 0x01c0:0x00000006, - // Block 0x8, offset 0x200 - 0x0219:0x00000007, - // Block 0x9, offset 0x240 - 0x027f:0x00000008, - // Block 0xa, offset 0x280 - 0x0280:0x00000009, - // Block 0xb, offset 0x2c0 - 0x02c1:0x0000000a, - // Block 0xc, offset 0x300 - 0x033f:0x0000000b, -} - -// testLookup: 640 entries, 1280 bytes -// Block 0 is the null block. -var testLookup = [640]uint16 { - // Block 0x0, offset 0x0 - // Block 0x1, offset 0x40 - // Block 0x2, offset 0x80 - // Block 0x3, offset 0xc0 - 0x0e0:0x05, 0x0e6:0x06, - // Block 0x4, offset 0x100 - 0x13f:0x07, - // Block 0x5, offset 0x140 - 0x140:0x08, 0x144:0x09, - // Block 0x6, offset 0x180 - 0x190:0x03, - // Block 0x7, offset 0x1c0 - 0x1ff:0x0a, - // Block 0x8, offset 0x200 - 0x20f:0x05, - // Block 0x9, offset 0x240 - 0x242:0x01, 0x244:0x02, - 0x248:0x03, - 0x25f:0x04, - 0x260:0x01, - 0x26f:0x02, - 0x270:0x04, 0x274:0x06, -} - -var testTrie = trie{ testLookup[1216:], testValues[0:], testLookup[:], testValues[:]}` diff --git a/vendor/golang.org/x/text/collate/collate_test.go b/vendor/golang.org/x/text/collate/collate_test.go deleted file mode 100644 index 0e78b96f..00000000 --- a/vendor/golang.org/x/text/collate/collate_test.go +++ /dev/null @@ -1,482 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package collate - -import ( - "bytes" - "testing" - - "golang.org/x/text/internal/colltab" - "golang.org/x/text/language" -) - -type weightsTest struct { - opt opts - in, out ColElems -} - -type opts struct { - lev int - alt alternateHandling - top int - - backwards bool - caseLevel bool -} - -// ignore returns an initialized boolean array based on the given Level. -// A negative value means using the default setting of quaternary. -func ignore(level colltab.Level) (ignore [colltab.NumLevels]bool) { - if level < 0 { - level = colltab.Quaternary - } - for i := range ignore { - ignore[i] = level < colltab.Level(i) - } - return ignore -} - -func makeCE(w []int) colltab.Elem { - ce, err := colltab.MakeElem(w[0], w[1], w[2], uint8(w[3])) - if err != nil { - panic(err) - } - return ce -} - -func (o opts) collator() *Collator { - c := &Collator{ - options: options{ - ignore: ignore(colltab.Level(o.lev - 1)), - alternate: o.alt, - backwards: o.backwards, - caseLevel: o.caseLevel, - variableTop: uint32(o.top), - }, - } - return c -} - -const ( - maxQ = 0x1FFFFF -) - -func wpq(p, q int) Weights { - return W(p, defaults.Secondary, defaults.Tertiary, q) -} - -func wsq(s, q int) Weights { - return W(0, s, defaults.Tertiary, q) -} - -func wq(q int) Weights { - return W(0, 0, 0, q) -} - -var zero = W(0, 0, 0, 0) - -var processTests = []weightsTest{ - // Shifted - { // simple sequence of non-variables - opt: opts{alt: altShifted, top: 100}, - in: ColElems{W(200), W(300), W(400)}, - out: ColElems{wpq(200, maxQ), wpq(300, maxQ), wpq(400, maxQ)}, - }, - { // first is a variable - opt: opts{alt: altShifted, top: 250}, - in: ColElems{W(200), W(300), W(400)}, - out: ColElems{wq(200), wpq(300, maxQ), wpq(400, maxQ)}, - }, - { // all but first are variable - opt: opts{alt: altShifted, top: 999}, - in: ColElems{W(1000), W(200), W(300), W(400)}, - out: ColElems{wpq(1000, maxQ), wq(200), wq(300), wq(400)}, - }, - { // first is a modifier - opt: opts{alt: altShifted, top: 999}, - in: ColElems{W(0, 10), W(1000)}, - out: ColElems{wsq(10, maxQ), wpq(1000, maxQ)}, - }, - { // primary ignorables - opt: opts{alt: altShifted, top: 250}, - in: ColElems{W(200), W(0, 10), W(300), W(0, 15), W(400)}, - out: ColElems{wq(200), zero, wpq(300, maxQ), wsq(15, maxQ), wpq(400, maxQ)}, - }, - { // secondary ignorables - opt: opts{alt: altShifted, top: 250}, - in: ColElems{W(200), W(0, 0, 10), W(300), W(0, 0, 15), W(400)}, - out: ColElems{wq(200), zero, wpq(300, maxQ), W(0, 0, 15, maxQ), wpq(400, maxQ)}, - }, - { // tertiary ignorables, no change - opt: opts{alt: altShifted, top: 250}, - in: ColElems{W(200), zero, W(300), zero, W(400)}, - out: ColElems{wq(200), zero, wpq(300, maxQ), zero, wpq(400, maxQ)}, - }, - - // ShiftTrimmed (same as Shifted) - { // simple sequence of non-variables - opt: opts{alt: altShiftTrimmed, top: 100}, - in: ColElems{W(200), W(300), W(400)}, - out: ColElems{wpq(200, maxQ), wpq(300, maxQ), wpq(400, maxQ)}, - }, - { // first is a variable - opt: opts{alt: altShiftTrimmed, top: 250}, - in: ColElems{W(200), W(300), W(400)}, - out: ColElems{wq(200), wpq(300, maxQ), wpq(400, maxQ)}, - }, - { // all but first are variable - opt: opts{alt: altShiftTrimmed, top: 999}, - in: ColElems{W(1000), W(200), W(300), W(400)}, - out: ColElems{wpq(1000, maxQ), wq(200), wq(300), wq(400)}, - }, - { // first is a modifier - opt: opts{alt: altShiftTrimmed, top: 999}, - in: ColElems{W(0, 10), W(1000)}, - out: ColElems{wsq(10, maxQ), wpq(1000, maxQ)}, - }, - { // primary ignorables - opt: opts{alt: altShiftTrimmed, top: 250}, - in: ColElems{W(200), W(0, 10), W(300), W(0, 15), W(400)}, - out: ColElems{wq(200), zero, wpq(300, maxQ), wsq(15, maxQ), wpq(400, maxQ)}, - }, - { // secondary ignorables - opt: opts{alt: altShiftTrimmed, top: 250}, - in: ColElems{W(200), W(0, 0, 10), W(300), W(0, 0, 15), W(400)}, - out: ColElems{wq(200), zero, wpq(300, maxQ), W(0, 0, 15, maxQ), wpq(400, maxQ)}, - }, - { // tertiary ignorables, no change - opt: opts{alt: altShiftTrimmed, top: 250}, - in: ColElems{W(200), zero, W(300), zero, W(400)}, - out: ColElems{wq(200), zero, wpq(300, maxQ), zero, wpq(400, maxQ)}, - }, - - // Blanked - { // simple sequence of non-variables - opt: opts{alt: altBlanked, top: 100}, - in: ColElems{W(200), W(300), W(400)}, - out: ColElems{W(200), W(300), W(400)}, - }, - { // first is a variable - opt: opts{alt: altBlanked, top: 250}, - in: ColElems{W(200), W(300), W(400)}, - out: ColElems{zero, W(300), W(400)}, - }, - { // all but first are variable - opt: opts{alt: altBlanked, top: 999}, - in: ColElems{W(1000), W(200), W(300), W(400)}, - out: ColElems{W(1000), zero, zero, zero}, - }, - { // first is a modifier - opt: opts{alt: altBlanked, top: 999}, - in: ColElems{W(0, 10), W(1000)}, - out: ColElems{W(0, 10), W(1000)}, - }, - { // primary ignorables - opt: opts{alt: altBlanked, top: 250}, - in: ColElems{W(200), W(0, 10), W(300), W(0, 15), W(400)}, - out: ColElems{zero, zero, W(300), W(0, 15), W(400)}, - }, - { // secondary ignorables - opt: opts{alt: altBlanked, top: 250}, - in: ColElems{W(200), W(0, 0, 10), W(300), W(0, 0, 15), W(400)}, - out: ColElems{zero, zero, W(300), W(0, 0, 15), W(400)}, - }, - { // tertiary ignorables, no change - opt: opts{alt: altBlanked, top: 250}, - in: ColElems{W(200), zero, W(300), zero, W(400)}, - out: ColElems{zero, zero, W(300), zero, W(400)}, - }, - - // Non-ignorable: input is always equal to output. - { // all but first are variable - opt: opts{alt: altNonIgnorable, top: 999}, - in: ColElems{W(1000), W(200), W(300), W(400)}, - out: ColElems{W(1000), W(200), W(300), W(400)}, - }, - { // primary ignorables - opt: opts{alt: altNonIgnorable, top: 250}, - in: ColElems{W(200), W(0, 10), W(300), W(0, 15), W(400)}, - out: ColElems{W(200), W(0, 10), W(300), W(0, 15), W(400)}, - }, - { // secondary ignorables - opt: opts{alt: altNonIgnorable, top: 250}, - in: ColElems{W(200), W(0, 0, 10), W(300), W(0, 0, 15), W(400)}, - out: ColElems{W(200), W(0, 0, 10), W(300), W(0, 0, 15), W(400)}, - }, - { // tertiary ignorables, no change - opt: opts{alt: altNonIgnorable, top: 250}, - in: ColElems{W(200), zero, W(300), zero, W(400)}, - out: ColElems{W(200), zero, W(300), zero, W(400)}, - }, -} - -func TestProcessWeights(t *testing.T) { - for i, tt := range processTests { - in := convertFromWeights(tt.in) - out := convertFromWeights(tt.out) - processWeights(tt.opt.alt, uint32(tt.opt.top), in) - for j, w := range in { - if w != out[j] { - t.Errorf("%d: Weights %d was %v; want %v", i, j, w, out[j]) - } - } - } -} - -type keyFromElemTest struct { - opt opts - in ColElems - out []byte -} - -var defS = byte(defaults.Secondary) -var defT = byte(defaults.Tertiary) - -const sep = 0 // separator byte - -var keyFromElemTests = []keyFromElemTest{ - { // simple primary and secondary weights. - opts{alt: altShifted}, - ColElems{W(0x200), W(0x7FFF), W(0, 0x30), W(0x100)}, - []byte{0x2, 0, 0x7F, 0xFF, 0x1, 0x00, // primary - sep, sep, 0, defS, 0, defS, 0, 0x30, 0, defS, // secondary - sep, sep, defT, defT, defT, defT, // tertiary - sep, 0xFF, 0xFF, 0xFF, 0xFF, // quaternary - }, - }, - { // same as first, but with zero element that need to be removed - opts{alt: altShifted}, - ColElems{W(0x200), zero, W(0x7FFF), W(0, 0x30), zero, W(0x100)}, - []byte{0x2, 0, 0x7F, 0xFF, 0x1, 0x00, // primary - sep, sep, 0, defS, 0, defS, 0, 0x30, 0, defS, // secondary - sep, sep, defT, defT, defT, defT, // tertiary - sep, 0xFF, 0xFF, 0xFF, 0xFF, // quaternary - }, - }, - { // same as first, with large primary values - opts{alt: altShifted}, - ColElems{W(0x200), W(0x8000), W(0, 0x30), W(0x12345)}, - []byte{0x2, 0, 0x80, 0x80, 0x00, 0x81, 0x23, 0x45, // primary - sep, sep, 0, defS, 0, defS, 0, 0x30, 0, defS, // secondary - sep, sep, defT, defT, defT, defT, // tertiary - sep, 0xFF, 0xFF, 0xFF, 0xFF, // quaternary - }, - }, - { // same as first, but with the secondary level backwards - opts{alt: altShifted, backwards: true}, - ColElems{W(0x200), W(0x7FFF), W(0, 0x30), W(0x100)}, - []byte{0x2, 0, 0x7F, 0xFF, 0x1, 0x00, // primary - sep, sep, 0, defS, 0, 0x30, 0, defS, 0, defS, // secondary - sep, sep, defT, defT, defT, defT, // tertiary - sep, 0xFF, 0xFF, 0xFF, 0xFF, // quaternary - }, - }, - { // same as first, ignoring quaternary level - opts{alt: altShifted, lev: 3}, - ColElems{W(0x200), zero, W(0x7FFF), W(0, 0x30), zero, W(0x100)}, - []byte{0x2, 0, 0x7F, 0xFF, 0x1, 0x00, // primary - sep, sep, 0, defS, 0, defS, 0, 0x30, 0, defS, // secondary - sep, sep, defT, defT, defT, defT, // tertiary - }, - }, - { // same as first, ignoring tertiary level - opts{alt: altShifted, lev: 2}, - ColElems{W(0x200), zero, W(0x7FFF), W(0, 0x30), zero, W(0x100)}, - []byte{0x2, 0, 0x7F, 0xFF, 0x1, 0x00, // primary - sep, sep, 0, defS, 0, defS, 0, 0x30, 0, defS, // secondary - }, - }, - { // same as first, ignoring secondary level - opts{alt: altShifted, lev: 1}, - ColElems{W(0x200), zero, W(0x7FFF), W(0, 0x30), zero, W(0x100)}, - []byte{0x2, 0, 0x7F, 0xFF, 0x1, 0x00}, - }, - { // simple primary and secondary weights. - opts{alt: altShiftTrimmed, top: 0x250}, - ColElems{W(0x300), W(0x200), W(0x7FFF), W(0, 0x30), W(0x800)}, - []byte{0x3, 0, 0x7F, 0xFF, 0x8, 0x00, // primary - sep, sep, 0, defS, 0, defS, 0, 0x30, 0, defS, // secondary - sep, sep, defT, defT, defT, defT, // tertiary - sep, 0xFF, 0x2, 0, // quaternary - }, - }, - { // as first, primary with case level enabled - opts{alt: altShifted, lev: 1, caseLevel: true}, - ColElems{W(0x200), W(0x7FFF), W(0, 0x30), W(0x100)}, - []byte{0x2, 0, 0x7F, 0xFF, 0x1, 0x00, // primary - sep, sep, // secondary - sep, sep, defT, defT, defT, defT, // tertiary - }, - }, -} - -func TestKeyFromElems(t *testing.T) { - buf := Buffer{} - for i, tt := range keyFromElemTests { - buf.Reset() - in := convertFromWeights(tt.in) - processWeights(tt.opt.alt, uint32(tt.opt.top), in) - tt.opt.collator().keyFromElems(&buf, in) - res := buf.key - if len(res) != len(tt.out) { - t.Errorf("%d: len(ws) was %d; want %d (%X should be %X)", i, len(res), len(tt.out), res, tt.out) - } - n := len(res) - if len(tt.out) < n { - n = len(tt.out) - } - for j, c := range res[:n] { - if c != tt.out[j] { - t.Errorf("%d: byte %d was %X; want %X", i, j, c, tt.out[j]) - } - } - } -} - -func TestGetColElems(t *testing.T) { - for i, tt := range appendNextTests { - c, err := makeTable(tt.in) - if err != nil { - // error is reported in TestAppendNext - continue - } - // Create one large test per table - str := make([]byte, 0, 4000) - out := ColElems{} - for len(str) < 3000 { - for _, chk := range tt.chk { - str = append(str, chk.in[:chk.n]...) - out = append(out, chk.out...) - } - } - for j, chk := range append(tt.chk, check{string(str), len(str), out}) { - out := convertFromWeights(chk.out) - ce := c.getColElems([]byte(chk.in)[:chk.n]) - if len(ce) != len(out) { - t.Errorf("%d:%d: len(ws) was %d; want %d", i, j, len(ce), len(out)) - continue - } - cnt := 0 - for k, w := range ce { - w, _ = colltab.MakeElem(w.Primary(), w.Secondary(), int(w.Tertiary()), 0) - if w != out[k] { - t.Errorf("%d:%d: Weights %d was %X; want %X", i, j, k, w, out[k]) - cnt++ - } - if cnt > 10 { - break - } - } - } - } -} - -type keyTest struct { - in string - out []byte -} - -var keyTests = []keyTest{ - {"abc", - []byte{0, 100, 0, 200, 1, 44, 0, 0, 0, 32, 0, 32, 0, 32, 0, 0, 2, 2, 2, 0, 255, 255, 255}, - }, - {"a\u0301", - []byte{0, 102, 0, 0, 0, 32, 0, 0, 2, 0, 255}, - }, - {"aaaaa", - []byte{0, 100, 0, 100, 0, 100, 0, 100, 0, 100, 0, 0, - 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 0, - 2, 2, 2, 2, 2, 0, - 255, 255, 255, 255, 255, - }, - }, - // Issue 16391: incomplete rune at end of UTF-8 sequence. - {"\xc2", []byte{133, 255, 253, 0, 0, 0, 32, 0, 0, 2, 0, 255}}, - {"\xc2a", []byte{133, 255, 253, 0, 100, 0, 0, 0, 32, 0, 32, 0, 0, 2, 2, 0, 255, 255}}, -} - -func TestKey(t *testing.T) { - c, _ := makeTable(appendNextTests[4].in) - c.alternate = altShifted - c.ignore = ignore(colltab.Quaternary) - buf := Buffer{} - keys1 := [][]byte{} - keys2 := [][]byte{} - for _, tt := range keyTests { - keys1 = append(keys1, c.Key(&buf, []byte(tt.in))) - keys2 = append(keys2, c.KeyFromString(&buf, tt.in)) - } - // Separate generation from testing to ensure buffers are not overwritten. - for i, tt := range keyTests { - if !bytes.Equal(keys1[i], tt.out) { - t.Errorf("%d: Key(%q) = %d; want %d", i, tt.in, keys1[i], tt.out) - } - if !bytes.Equal(keys2[i], tt.out) { - t.Errorf("%d: KeyFromString(%q) = %d; want %d", i, tt.in, keys2[i], tt.out) - } - } -} - -type compareTest struct { - a, b string - res int // comparison result -} - -var compareTests = []compareTest{ - {"a\u0301", "a", 1}, - {"a\u0301b", "ab", 1}, - {"a", "a\u0301", -1}, - {"ab", "a\u0301b", -1}, - {"bc", "a\u0301c", 1}, - {"ab", "aB", -1}, - {"a\u0301", "a\u0301", 0}, - {"a", "a", 0}, - // Only clip prefixes of whole runes. - {"\u302E", "\u302F", 1}, - // Don't clip prefixes when last rune of prefix may be part of contraction. - {"a\u035E", "a\u0301\u035F", -1}, - {"a\u0301\u035Fb", "a\u0301\u035F", -1}, -} - -func TestCompare(t *testing.T) { - c, _ := makeTable(appendNextTests[4].in) - for i, tt := range compareTests { - if res := c.Compare([]byte(tt.a), []byte(tt.b)); res != tt.res { - t.Errorf("%d: Compare(%q, %q) == %d; want %d", i, tt.a, tt.b, res, tt.res) - } - if res := c.CompareString(tt.a, tt.b); res != tt.res { - t.Errorf("%d: CompareString(%q, %q) == %d; want %d", i, tt.a, tt.b, res, tt.res) - } - } -} - -func TestNumeric(t *testing.T) { - c := New(language.English, Loose, Numeric) - - for i, tt := range []struct { - a, b string - want int - }{ - {"1", "2", -1}, - {"2", "12", -1}, - {"2", "12", -1}, // Fullwidth is sorted as usual. - {"₂", "₁₂", 1}, // Subscript is not sorted as numbers. - {"②", "①②", 1}, // Circled is not sorted as numbers. - { // Imperial Aramaic, is not sorted as number. - "\U00010859", - "\U00010858\U00010859", - 1, - }, - {"12", "2", 1}, - {"A-1", "A-2", -1}, - {"A-2", "A-12", -1}, - {"A-12", "A-2", 1}, - {"A-0001", "A-1", 0}, - } { - if got := c.CompareString(tt.a, tt.b); got != tt.want { - t.Errorf("%d: CompareString(%s, %s) = %d; want %d", i, tt.a, tt.b, got, tt.want) - } - } -} diff --git a/vendor/golang.org/x/text/collate/export_test.go b/vendor/golang.org/x/text/collate/export_test.go deleted file mode 100644 index 69bfeaf1..00000000 --- a/vendor/golang.org/x/text/collate/export_test.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package collate - -// Export for testing. -// TODO: no longer necessary. Remove at some point. - -import ( - "fmt" - - "golang.org/x/text/internal/colltab" -) - -const ( - defaultSecondary = 0x20 - defaultTertiary = 0x2 -) - -type Weights struct { - Primary, Secondary, Tertiary, Quaternary int -} - -func W(ce ...int) Weights { - w := Weights{ce[0], defaultSecondary, defaultTertiary, 0} - if len(ce) > 1 { - w.Secondary = ce[1] - } - if len(ce) > 2 { - w.Tertiary = ce[2] - } - if len(ce) > 3 { - w.Quaternary = ce[3] - } - return w -} -func (w Weights) String() string { - return fmt.Sprintf("[%X.%X.%X.%X]", w.Primary, w.Secondary, w.Tertiary, w.Quaternary) -} - -func convertFromWeights(ws []Weights) []colltab.Elem { - out := make([]colltab.Elem, len(ws)) - for i, w := range ws { - out[i], _ = colltab.MakeElem(w.Primary, w.Secondary, w.Tertiary, 0) - if out[i] == colltab.Ignore && w.Quaternary > 0 { - out[i] = colltab.MakeQuaternary(w.Quaternary) - } - } - return out -} diff --git a/vendor/golang.org/x/text/collate/option_test.go b/vendor/golang.org/x/text/collate/option_test.go deleted file mode 100644 index 0f6ba9bc..00000000 --- a/vendor/golang.org/x/text/collate/option_test.go +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -package collate - -import ( - "reflect" - "strings" - "testing" - - "golang.org/x/text/internal/colltab" - "golang.org/x/text/language" -) - -var ( - defaultIgnore = ignore(colltab.Tertiary) - defaultTable = getTable(locales[0]) -) - -func TestOptions(t *testing.T) { - for i, tt := range []struct { - in []Option - out options - }{ - 0: { - out: options{ - ignore: defaultIgnore, - }, - }, - 1: { - in: []Option{IgnoreDiacritics}, - out: options{ - ignore: [colltab.NumLevels]bool{false, true, false, true, true}, - }, - }, - 2: { - in: []Option{IgnoreCase, IgnoreDiacritics}, - out: options{ - ignore: ignore(colltab.Primary), - }, - }, - 3: { - in: []Option{ignoreDiacritics, IgnoreWidth}, - out: options{ - ignore: ignore(colltab.Primary), - caseLevel: true, - }, - }, - 4: { - in: []Option{IgnoreWidth, ignoreDiacritics}, - out: options{ - ignore: ignore(colltab.Primary), - caseLevel: true, - }, - }, - 5: { - in: []Option{IgnoreCase, IgnoreWidth}, - out: options{ - ignore: ignore(colltab.Secondary), - }, - }, - 6: { - in: []Option{IgnoreCase, IgnoreWidth, Loose}, - out: options{ - ignore: ignore(colltab.Primary), - }, - }, - 7: { - in: []Option{Force, IgnoreCase, IgnoreWidth, Loose}, - out: options{ - ignore: [colltab.NumLevels]bool{false, true, true, true, false}, - }, - }, - 8: { - in: []Option{IgnoreDiacritics, IgnoreCase}, - out: options{ - ignore: ignore(colltab.Primary), - }, - }, - 9: { - in: []Option{Numeric}, - out: options{ - ignore: defaultIgnore, - numeric: true, - }, - }, - 10: { - in: []Option{OptionsFromTag(language.MustParse("und-u-ks-level1"))}, - out: options{ - ignore: ignore(colltab.Primary), - }, - }, - 11: { - in: []Option{OptionsFromTag(language.MustParse("und-u-ks-level4"))}, - out: options{ - ignore: ignore(colltab.Quaternary), - }, - }, - 12: { - in: []Option{OptionsFromTag(language.MustParse("und-u-ks-identic"))}, - out: options{}, - }, - 13: { - in: []Option{ - OptionsFromTag(language.MustParse("und-u-kn-true-kb-true-kc-true")), - }, - out: options{ - ignore: defaultIgnore, - caseLevel: true, - backwards: true, - numeric: true, - }, - }, - 14: { - in: []Option{ - OptionsFromTag(language.MustParse("und-u-kn-true-kb-true-kc-true")), - OptionsFromTag(language.MustParse("und-u-kn-false-kb-false-kc-false")), - }, - out: options{ - ignore: defaultIgnore, - }, - }, - 15: { - in: []Option{ - OptionsFromTag(language.MustParse("und-u-kn-true-kb-true-kc-true")), - OptionsFromTag(language.MustParse("und-u-kn-foo-kb-foo-kc-foo")), - }, - out: options{ - ignore: defaultIgnore, - caseLevel: true, - backwards: true, - numeric: true, - }, - }, - 16: { // Normal options take precedence over tag options. - in: []Option{ - Numeric, IgnoreCase, - OptionsFromTag(language.MustParse("und-u-kn-false-kc-true")), - }, - out: options{ - ignore: ignore(colltab.Secondary), - caseLevel: false, - numeric: true, - }, - }, - 17: { - in: []Option{ - OptionsFromTag(language.MustParse("und-u-ka-shifted")), - }, - out: options{ - ignore: defaultIgnore, - alternate: altShifted, - }, - }, - 18: { - in: []Option{ - OptionsFromTag(language.MustParse("und-u-ka-blanked")), - }, - out: options{ - ignore: defaultIgnore, - alternate: altBlanked, - }, - }, - 19: { - in: []Option{ - OptionsFromTag(language.MustParse("und-u-ka-posix")), - }, - out: options{ - ignore: defaultIgnore, - alternate: altShiftTrimmed, - }, - }, - } { - c := newCollator(defaultTable) - c.t = nil - c.variableTop = 0 - c.f = 0 - - c.setOptions(tt.in) - if !reflect.DeepEqual(c.options, tt.out) { - t.Errorf("%d: got %v; want %v", i, c.options, tt.out) - } - } -} - -func TestAlternateSortTypes(t *testing.T) { - testCases := []struct { - lang string - in []string - want []string - }{{ - lang: "zh,cmn,zh-Hant-u-co-pinyin,zh-HK-u-co-pinyin,zh-pinyin", - in: []string{"爸爸", "妈妈", "儿子", "女儿"}, - want: []string{"爸爸", "儿子", "妈妈", "女儿"}, - }, { - lang: "zh-Hant,zh-u-co-stroke,zh-Hant-u-co-stroke", - in: []string{"爸爸", "妈妈", "儿子", "女儿"}, - want: []string{"儿子", "女儿", "妈妈", "爸爸"}, - }} - for _, tc := range testCases { - for _, tag := range strings.Split(tc.lang, ",") { - got := append([]string{}, tc.in...) - New(language.MustParse(tag)).SortStrings(got) - if !reflect.DeepEqual(got, tc.want) { - t.Errorf("New(%s).SortStrings(%v) = %v; want %v", tag, tc.in, got, tc.want) - } - } - } -} diff --git a/vendor/golang.org/x/text/collate/reg_test.go b/vendor/golang.org/x/text/collate/reg_test.go deleted file mode 100644 index 1ac5fedc..00000000 --- a/vendor/golang.org/x/text/collate/reg_test.go +++ /dev/null @@ -1,230 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package collate - -import ( - "archive/zip" - "bufio" - "bytes" - "flag" - "io" - "io/ioutil" - "log" - "path" - "regexp" - "strconv" - "strings" - "testing" - "unicode/utf8" - - "golang.org/x/text/collate/build" - "golang.org/x/text/internal/gen" - "golang.org/x/text/language" -) - -var long = flag.Bool("long", false, - "run time-consuming tests, such as tests that fetch data online") - -// This regression test runs tests for the test files in CollationTest.zip -// (taken from http://www.unicode.org/Public/UCA//). -// -// The test files have the following form: -// # header -// 0009 0021; # ('\u0009') [| | | 0201 025E] -// 0009 003F; # ('\u0009') [| | | 0201 0263] -// 000A 0021; # ('\u000A') [| | | 0202 025E] -// 000A 003F; # ('\u000A') [| | | 0202 0263] -// -// The part before the semicolon is the hex representation of a sequence -// of runes. After the hash mark is a comment. The strings -// represented by rune sequence are in the file in sorted order, as -// defined by the DUCET. - -type Test struct { - name string - str [][]byte - comment []string -} - -var versionRe = regexp.MustCompile(`# UCA Version: (.*)\n?$`) -var testRe = regexp.MustCompile(`^([\dA-F ]+);.*# (.*)\n?$`) - -func TestCollation(t *testing.T) { - if !gen.IsLocal() && !*long { - t.Skip("skipping test to prevent downloading; to run use -long or use -local to specify a local source") - } - t.Skip("must first update to new file format to support test") - for _, test := range loadTestData() { - doTest(t, test) - } -} - -func Error(e error) { - if e != nil { - log.Fatal(e) - } -} - -// parseUCA parses a Default Unicode Collation Element Table of the format -// specified in http://www.unicode.org/reports/tr10/#File_Format. -// It returns the variable top. -func parseUCA(builder *build.Builder) { - r := gen.OpenUnicodeFile("UCA", "", "allkeys.txt") - defer r.Close() - input := bufio.NewReader(r) - colelem := regexp.MustCompile(`\[([.*])([0-9A-F.]+)\]`) - for i := 1; true; i++ { - l, prefix, err := input.ReadLine() - if err == io.EOF { - break - } - Error(err) - line := string(l) - if prefix { - log.Fatalf("%d: buffer overflow", i) - } - if len(line) == 0 || line[0] == '#' { - continue - } - if line[0] == '@' { - if strings.HasPrefix(line[1:], "version ") { - if v := strings.Split(line[1:], " ")[1]; v != gen.UnicodeVersion() { - log.Fatalf("incompatible version %s; want %s", v, gen.UnicodeVersion()) - } - } - } else { - // parse entries - part := strings.Split(line, " ; ") - if len(part) != 2 { - log.Fatalf("%d: production rule without ';': %v", i, line) - } - lhs := []rune{} - for _, v := range strings.Split(part[0], " ") { - if v != "" { - lhs = append(lhs, rune(convHex(i, v))) - } - } - vars := []int{} - rhs := [][]int{} - for i, m := range colelem.FindAllStringSubmatch(part[1], -1) { - if m[1] == "*" { - vars = append(vars, i) - } - elem := []int{} - for _, h := range strings.Split(m[2], ".") { - elem = append(elem, convHex(i, h)) - } - rhs = append(rhs, elem) - } - builder.Add(lhs, rhs, vars) - } - } -} - -func convHex(line int, s string) int { - r, e := strconv.ParseInt(s, 16, 32) - if e != nil { - log.Fatalf("%d: %v", line, e) - } - return int(r) -} - -func loadTestData() []Test { - f := gen.OpenUnicodeFile("UCA", "", "CollationTest.zip") - buffer, err := ioutil.ReadAll(f) - f.Close() - Error(err) - archive, err := zip.NewReader(bytes.NewReader(buffer), int64(len(buffer))) - Error(err) - tests := []Test{} - for _, f := range archive.File { - // Skip the short versions, which are simply duplicates of the long versions. - if strings.Contains(f.Name, "SHORT") || f.FileInfo().IsDir() { - continue - } - ff, err := f.Open() - Error(err) - defer ff.Close() - scanner := bufio.NewScanner(ff) - test := Test{name: path.Base(f.Name)} - for scanner.Scan() { - line := scanner.Text() - if len(line) <= 1 || line[0] == '#' { - if m := versionRe.FindStringSubmatch(line); m != nil { - if m[1] != gen.UnicodeVersion() { - log.Printf("warning:%s: version is %s; want %s", f.Name, m[1], gen.UnicodeVersion()) - } - } - continue - } - m := testRe.FindStringSubmatch(line) - if m == nil || len(m) < 3 { - log.Fatalf(`Failed to parse: "%s" result: %#v`, line, m) - } - str := []byte{} - // In the regression test data (unpaired) surrogates are assigned a weight - // corresponding to their code point value. However, utf8.DecodeRune, - // which is used to compute the implicit weight, assigns FFFD to surrogates. - // We therefore skip tests with surrogates. This skips about 35 entries - // per test. - valid := true - for _, split := range strings.Split(m[1], " ") { - r, err := strconv.ParseUint(split, 16, 64) - Error(err) - valid = valid && utf8.ValidRune(rune(r)) - str = append(str, string(rune(r))...) - } - if valid { - test.str = append(test.str, str) - test.comment = append(test.comment, m[2]) - } - } - if scanner.Err() != nil { - log.Fatal(scanner.Err()) - } - tests = append(tests, test) - } - return tests -} - -var errorCount int - -func runes(b []byte) []rune { - return []rune(string(b)) -} - -var shifted = language.MustParse("und-u-ka-shifted-ks-level4") - -func doTest(t *testing.T, tc Test) { - bld := build.NewBuilder() - parseUCA(bld) - w, err := bld.Build() - Error(err) - var tag language.Tag - if !strings.Contains(tc.name, "NON_IGNOR") { - tag = shifted - } - c := NewFromTable(w, OptionsFromTag(tag)) - b := &Buffer{} - prev := tc.str[0] - for i := 1; i < len(tc.str); i++ { - b.Reset() - s := tc.str[i] - ka := c.Key(b, prev) - kb := c.Key(b, s) - if r := bytes.Compare(ka, kb); r == 1 { - t.Errorf("%s:%d: Key(%.4X) < Key(%.4X) (%X < %X) == %d; want -1 or 0", tc.name, i, []rune(string(prev)), []rune(string(s)), ka, kb, r) - prev = s - continue - } - if r := c.Compare(prev, s); r == 1 { - t.Errorf("%s:%d: Compare(%.4X, %.4X) == %d; want -1 or 0", tc.name, i, runes(prev), runes(s), r) - } - if r := c.Compare(s, prev); r == -1 { - t.Errorf("%s:%d: Compare(%.4X, %.4X) == %d; want 1 or 0", tc.name, i, runes(s), runes(prev), r) - } - prev = s - } -} diff --git a/vendor/golang.org/x/text/collate/sort_test.go b/vendor/golang.org/x/text/collate/sort_test.go deleted file mode 100644 index d9e7f31c..00000000 --- a/vendor/golang.org/x/text/collate/sort_test.go +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package collate_test - -import ( - "fmt" - "testing" - - "golang.org/x/text/collate" - "golang.org/x/text/language" -) - -func ExampleCollator_Strings() { - c := collate.New(language.Und) - strings := []string{ - "ad", - "ab", - "äb", - "ac", - } - c.SortStrings(strings) - fmt.Println(strings) - // Output: [ab äb ac ad] -} - -type sorter []string - -func (s sorter) Len() int { - return len(s) -} - -func (s sorter) Swap(i, j int) { - s[j], s[i] = s[i], s[j] -} - -func (s sorter) Bytes(i int) []byte { - return []byte(s[i]) -} - -func TestSort(t *testing.T) { - c := collate.New(language.English) - strings := []string{ - "bcd", - "abc", - "ddd", - } - c.Sort(sorter(strings)) - res := fmt.Sprint(strings) - want := "[abc bcd ddd]" - if res != want { - t.Errorf("found %s; want %s", res, want) - } -} diff --git a/vendor/golang.org/x/text/collate/table_test.go b/vendor/golang.org/x/text/collate/table_test.go deleted file mode 100644 index 3a6b12fd..00000000 --- a/vendor/golang.org/x/text/collate/table_test.go +++ /dev/null @@ -1,291 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package collate - -import ( - "testing" - - "golang.org/x/text/collate/build" - "golang.org/x/text/internal/colltab" - "golang.org/x/text/unicode/norm" -) - -type ColElems []Weights - -type input struct { - str string - ces [][]int -} - -type check struct { - in string - n int - out ColElems -} - -type tableTest struct { - in []input - chk []check -} - -func w(ce ...int) Weights { - return W(ce...) -} - -var defaults = w(0) - -func pt(p, t int) []int { - return []int{p, defaults.Secondary, t} -} - -func makeTable(in []input) (*Collator, error) { - b := build.NewBuilder() - for _, r := range in { - if e := b.Add([]rune(r.str), r.ces, nil); e != nil { - panic(e) - } - } - t, err := b.Build() - if err != nil { - return nil, err - } - return NewFromTable(t), nil -} - -// modSeq holds a seqeunce of modifiers in increasing order of CCC long enough -// to cause a segment overflow if not handled correctly. The last rune in this -// list has a CCC of 214. -var modSeq = []rune{ - 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7, 0x05B8, 0x05B9, 0x05BB, - 0x05BC, 0x05BD, 0x05BF, 0x05C1, 0x05C2, 0xFB1E, 0x064B, 0x064C, 0x064D, 0x064E, - 0x064F, 0x0650, 0x0651, 0x0652, 0x0670, 0x0711, 0x0C55, 0x0C56, 0x0E38, 0x0E48, - 0x0EB8, 0x0EC8, 0x0F71, 0x0F72, 0x0F74, 0x0321, 0x1DCE, -} - -var mods []input -var modW = func() ColElems { - ws := ColElems{} - for _, r := range modSeq { - rune := norm.NFC.PropertiesString(string(r)) - ws = append(ws, w(0, int(rune.CCC()))) - mods = append(mods, input{string(r), [][]int{{0, int(rune.CCC())}}}) - } - return ws -}() - -var appendNextTests = []tableTest{ - { // test getWeights - []input{ - {"a", [][]int{{100}}}, - {"b", [][]int{{105}}}, - {"c", [][]int{{110}}}, - {"ß", [][]int{{120}}}, - }, - []check{ - {"a", 1, ColElems{w(100)}}, - {"b", 1, ColElems{w(105)}}, - {"c", 1, ColElems{w(110)}}, - {"d", 1, ColElems{w(0x50064)}}, - {"ab", 1, ColElems{w(100)}}, - {"bc", 1, ColElems{w(105)}}, - {"dd", 1, ColElems{w(0x50064)}}, - {"ß", 2, ColElems{w(120)}}, - }, - }, - { // test expansion - []input{ - {"u", [][]int{{100}}}, - {"U", [][]int{{100}, {0, 25}}}, - {"w", [][]int{{100}, {100}}}, - {"W", [][]int{{100}, {0, 25}, {100}, {0, 25}}}, - }, - []check{ - {"u", 1, ColElems{w(100)}}, - {"U", 1, ColElems{w(100), w(0, 25)}}, - {"w", 1, ColElems{w(100), w(100)}}, - {"W", 1, ColElems{w(100), w(0, 25), w(100), w(0, 25)}}, - }, - }, - { // test decompose - []input{ - {"D", [][]int{pt(104, 8)}}, - {"z", [][]int{pt(130, 8)}}, - {"\u030C", [][]int{{0, 40}}}, // Caron - {"\u01C5", [][]int{pt(104, 9), pt(130, 4), {0, 40, 0x1F}}}, // Dž = D+z+caron - }, - []check{ - {"\u01C5", 2, ColElems{w(pt(104, 9)...), w(pt(130, 4)...), w(0, 40, 0x1F)}}, - }, - }, - { // test basic contraction - []input{ - {"a", [][]int{{100}}}, - {"ab", [][]int{{101}}}, - {"aab", [][]int{{101}, {101}}}, - {"abc", [][]int{{102}}}, - {"b", [][]int{{200}}}, - {"c", [][]int{{300}}}, - {"d", [][]int{{400}}}, - }, - []check{ - {"a", 1, ColElems{w(100)}}, - {"aa", 1, ColElems{w(100)}}, - {"aac", 1, ColElems{w(100)}}, - {"d", 1, ColElems{w(400)}}, - {"ab", 2, ColElems{w(101)}}, - {"abb", 2, ColElems{w(101)}}, - {"aab", 3, ColElems{w(101), w(101)}}, - {"aaba", 3, ColElems{w(101), w(101)}}, - {"abc", 3, ColElems{w(102)}}, - {"abcd", 3, ColElems{w(102)}}, - }, - }, - { // test discontinuous contraction - append(mods, []input{ - // modifiers; secondary weight equals ccc - {"\u0316", [][]int{{0, 220}}}, - {"\u0317", [][]int{{0, 220}, {0, 220}}}, - {"\u302D", [][]int{{0, 222}}}, - {"\u302E", [][]int{{0, 225}}}, // used as starter - {"\u302F", [][]int{{0, 224}}}, // used as starter - {"\u18A9", [][]int{{0, 228}}}, - {"\u0300", [][]int{{0, 230}}}, - {"\u0301", [][]int{{0, 230}}}, - {"\u0315", [][]int{{0, 232}}}, - {"\u031A", [][]int{{0, 232}}}, - {"\u035C", [][]int{{0, 233}}}, - {"\u035F", [][]int{{0, 233}}}, - {"\u035D", [][]int{{0, 234}}}, - {"\u035E", [][]int{{0, 234}}}, - {"\u0345", [][]int{{0, 240}}}, - - // starters - {"a", [][]int{{100}}}, - {"b", [][]int{{200}}}, - {"c", [][]int{{300}}}, - {"\u03B1", [][]int{{900}}}, - {"\x01", [][]int{{0, 0, 0, 0}}}, - - // contractions - {"a\u0300", [][]int{{101}}}, - {"a\u0301", [][]int{{102}}}, - {"a\u035E", [][]int{{110}}}, - {"a\u035Eb\u035E", [][]int{{115}}}, - {"ac\u035Eaca\u035E", [][]int{{116}}}, - {"a\u035Db\u035D", [][]int{{117}}}, - {"a\u0301\u035Db", [][]int{{120}}}, - {"a\u0301\u035F", [][]int{{121}}}, - {"a\u0301\u035Fb", [][]int{{119}}}, - {"\u03B1\u0345", [][]int{{901}, {902}}}, - {"\u302E\u302F", [][]int{{0, 131}, {0, 131}}}, - {"\u302F\u18A9", [][]int{{0, 130}}}, - }...), - []check{ - {"a\x01\u0300", 1, ColElems{w(100)}}, - {"ab", 1, ColElems{w(100)}}, // closing segment - {"a\u0316\u0300b", 5, ColElems{w(101), w(0, 220)}}, // closing segment - {"a\u0316\u0300", 5, ColElems{w(101), w(0, 220)}}, // no closing segment - {"a\u0316\u0300\u035Cb", 5, ColElems{w(101), w(0, 220)}}, // completes before segment end - {"a\u0316\u0300\u035C", 5, ColElems{w(101), w(0, 220)}}, // completes before segment end - - {"a\u0316\u0301b", 5, ColElems{w(102), w(0, 220)}}, // closing segment - {"a\u0316\u0301", 5, ColElems{w(102), w(0, 220)}}, // no closing segment - {"a\u0316\u0301\u035Cb", 5, ColElems{w(102), w(0, 220)}}, // completes before segment end - {"a\u0316\u0301\u035C", 5, ColElems{w(102), w(0, 220)}}, // completes before segment end - - // match blocked by modifier with same ccc - {"a\u0301\u0315\u031A\u035Fb", 3, ColElems{w(102)}}, - - // multiple gaps - {"a\u0301\u035Db", 6, ColElems{w(120)}}, - {"a\u0301\u035F", 5, ColElems{w(121)}}, - {"a\u0301\u035Fb", 6, ColElems{w(119)}}, - {"a\u0316\u0301\u035F", 7, ColElems{w(121), w(0, 220)}}, - {"a\u0301\u0315\u035Fb", 7, ColElems{w(121), w(0, 232)}}, - {"a\u0316\u0301\u0315\u035Db", 5, ColElems{w(102), w(0, 220)}}, - {"a\u0316\u0301\u0315\u035F", 9, ColElems{w(121), w(0, 220), w(0, 232)}}, - {"a\u0316\u0301\u0315\u035Fb", 9, ColElems{w(121), w(0, 220), w(0, 232)}}, - {"a\u0316\u0301\u0315\u035F\u035D", 9, ColElems{w(121), w(0, 220), w(0, 232)}}, - {"a\u0316\u0301\u0315\u035F\u035Db", 9, ColElems{w(121), w(0, 220), w(0, 232)}}, - - // handling of segment overflow - { // just fits within segment - "a" + string(modSeq[:30]) + "\u0301", - 3 + len(string(modSeq[:30])), - append(ColElems{w(102)}, modW[:30]...), - }, - {"a" + string(modSeq[:31]) + "\u0301", 1, ColElems{w(100)}}, // overflow - {"a" + string(modSeq) + "\u0301", 1, ColElems{w(100)}}, - { // just fits within segment with two interstitial runes - "a" + string(modSeq[:28]) + "\u0301\u0315\u035F", - 7 + len(string(modSeq[:28])), - append(append(ColElems{w(121)}, modW[:28]...), w(0, 232)), - }, - { // second half does not fit within segment - "a" + string(modSeq[:29]) + "\u0301\u0315\u035F", - 3 + len(string(modSeq[:29])), - append(ColElems{w(102)}, modW[:29]...), - }, - - // discontinuity can only occur in last normalization segment - {"a\u035Eb\u035E", 6, ColElems{w(115)}}, - {"a\u0316\u035Eb\u035E", 5, ColElems{w(110), w(0, 220)}}, - {"a\u035Db\u035D", 6, ColElems{w(117)}}, - {"a\u0316\u035Db\u035D", 1, ColElems{w(100)}}, - {"a\u035Eb\u0316\u035E", 8, ColElems{w(115), w(0, 220)}}, - {"a\u035Db\u0316\u035D", 8, ColElems{w(117), w(0, 220)}}, - {"ac\u035Eaca\u035E", 9, ColElems{w(116)}}, - {"a\u0316c\u035Eaca\u035E", 1, ColElems{w(100)}}, - {"ac\u035Eac\u0316a\u035E", 1, ColElems{w(100)}}, - - // expanding contraction - {"\u03B1\u0345", 4, ColElems{w(901), w(902)}}, - - // Theoretical possibilities - // contraction within a gap - {"a\u302F\u18A9\u0301", 9, ColElems{w(102), w(0, 130)}}, - // expansion within a gap - {"a\u0317\u0301", 5, ColElems{w(102), w(0, 220), w(0, 220)}}, - // repeating CCC blocks last modifier - {"a\u302E\u302F\u0301", 1, ColElems{w(100)}}, - // The trailing combining characters (with lower CCC) should block the first one. - // TODO: make the following pass. - // {"a\u035E\u0316\u0316", 1, ColElems{w(100)}}, - {"a\u035F\u035Eb", 5, ColElems{w(110), w(0, 233)}}, - // Last combiner should match after normalization. - // TODO: make the following pass. - // {"a\u035D\u0301", 3, ColElems{w(102), w(0, 234)}}, - // The first combiner is blocking the second one as they have the same CCC. - {"a\u035D\u035Eb", 1, ColElems{w(100)}}, - }, - }, -} - -func TestAppendNext(t *testing.T) { - for i, tt := range appendNextTests { - c, err := makeTable(tt.in) - if err != nil { - t.Errorf("%d: error creating table: %v", i, err) - continue - } - for j, chk := range tt.chk { - ws, n := c.t.AppendNext(nil, []byte(chk.in)) - if n != chk.n { - t.Errorf("%d:%d: bytes consumed was %d; want %d", i, j, n, chk.n) - } - out := convertFromWeights(chk.out) - if len(ws) != len(out) { - t.Errorf("%d:%d: len(ws) was %d; want %d (%X vs %X)\n%X", i, j, len(ws), len(out), ws, out, chk.in) - continue - } - for k, w := range ws { - w, _ = colltab.MakeElem(w.Primary(), w.Secondary(), int(w.Tertiary()), 0) - if w != out[k] { - t.Errorf("%d:%d: Weights %d was %X; want %X", i, j, k, w, out[k]) - } - } - } - } -} diff --git a/vendor/golang.org/x/text/doc.go b/vendor/golang.org/x/text/doc.go deleted file mode 100644 index a48e2843..00000000 --- a/vendor/golang.org/x/text/doc.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:generate go run gen.go - -// text is a repository of text-related packages related to internationalization -// (i18n) and localization (l10n), such as character encodings, text -// transformations, and locale-specific text handling. -package text - -// TODO: more documentation on general concepts, such as Transformers, use -// of normalization, etc. diff --git a/vendor/golang.org/x/text/gen.go b/vendor/golang.org/x/text/gen.go deleted file mode 100644 index 757fefb7..00000000 --- a/vendor/golang.org/x/text/gen.go +++ /dev/null @@ -1,319 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -// gen runs go generate on Unicode- and CLDR-related package in the text -// repositories, taking into account dependencies and versions. -package main - -import ( - "bytes" - "flag" - "fmt" - "go/build" - "go/format" - "io/ioutil" - "os" - "os/exec" - "path" - "path/filepath" - "regexp" - "runtime" - "strings" - "sync" - "unicode" - - "golang.org/x/text/collate" - "golang.org/x/text/internal/gen" - "golang.org/x/text/language" -) - -var ( - verbose = flag.Bool("v", false, "verbose output") - force = flag.Bool("force", false, "ignore failing dependencies") - doCore = flag.Bool("core", false, "force an update to core") - excludeList = flag.String("exclude", "", - "comma-separated list of packages to exclude") - - // The user can specify a selection of packages to build on the command line. - args []string -) - -func exclude(pkg string) bool { - if len(args) > 0 { - return !contains(args, pkg) - } - return contains(strings.Split(*excludeList, ","), pkg) -} - -// TODO: -// - Better version handling. -// - Generate tables for the core unicode package? -// - Add generation for encodings. This requires some retooling here and there. -// - Running repo-wide "long" tests. - -var vprintf = fmt.Printf - -func main() { - gen.Init() - args = flag.Args() - if !*verbose { - // Set vprintf to a no-op. - vprintf = func(string, ...interface{}) (int, error) { return 0, nil } - } - - // TODO: create temporary cache directory to load files and create and set - // a "cache" option if the user did not specify the UNICODE_DIR environment - // variable. This will prevent duplicate downloads and also will enable long - // tests, which really need to be run after each generated package. - - updateCore := *doCore - if gen.UnicodeVersion() != unicode.Version { - fmt.Printf("Requested Unicode version %s; core unicode version is %s.\n", - gen.UnicodeVersion(), - unicode.Version) - c := collate.New(language.Und, collate.Numeric) - if c.CompareString(gen.UnicodeVersion(), unicode.Version) < 0 && !*force { - os.Exit(2) - } - updateCore = true - goroot := os.Getenv("GOROOT") - appendToFile( - filepath.Join(goroot, "api", "except.txt"), - fmt.Sprintf("pkg unicode, const Version = %q\n", unicode.Version), - ) - const lines = `pkg unicode, const Version = %q -// TODO: add a new line of the following form for each new script and property. -pkg unicode, var *RangeTable -` - appendToFile( - filepath.Join(goroot, "api", "next.txt"), - fmt.Sprintf(lines, gen.UnicodeVersion()), - ) - } - - var unicode = &dependency{} - if updateCore { - fmt.Printf("Updating core to version %s...\n", gen.UnicodeVersion()) - unicode = generate("unicode") - - // Test some users of the unicode packages, especially the ones that - // keep a mirrored table. These may need to be corrected by hand. - generate("regexp", unicode) - generate("strconv", unicode) // mimics Unicode table - generate("strings", unicode) - generate("testing", unicode) // mimics Unicode table - } - - var ( - cldr = generate("./unicode/cldr", unicode) - language = generate("./language", cldr) - internal = generate("./internal", unicode, language) - norm = generate("./unicode/norm", unicode) - rangetable = generate("./unicode/rangetable", unicode) - cases = generate("./cases", unicode, norm, language, rangetable) - width = generate("./width", unicode) - bidi = generate("./unicode/bidi", unicode, norm, rangetable) - mib = generate("./encoding/internal/identifier", unicode) - number = generate("./internal/number", unicode, cldr, language, internal) - _ = generate("./encoding/htmlindex", unicode, language, mib) - _ = generate("./encoding/ianaindex", unicode, language, mib) - _ = generate("./secure/precis", unicode, norm, rangetable, cases, width, bidi) - _ = generate("./internal/cldrtree", language) - _ = generate("./currency", unicode, cldr, language, internal, number) - _ = generate("./feature/plural", unicode, cldr, language, internal, number) - _ = generate("./internal/export/idna", unicode, bidi, norm) - _ = generate("./language/display", unicode, cldr, language, internal, number) - _ = generate("./collate", unicode, norm, cldr, language, rangetable) - _ = generate("./search", unicode, norm, cldr, language, rangetable) - ) - all.Wait() - - // Copy exported packages to the destination golang.org repo. - copyExported("golang.org/x/net/idna") - - if updateCore { - copyVendored() - } - - if hasErrors { - fmt.Println("FAIL") - os.Exit(1) - } - vprintf("SUCCESS\n") -} - -func appendToFile(file, text string) { - fmt.Println("Augmenting", file) - w, err := os.OpenFile(file, os.O_APPEND|os.O_WRONLY, 0600) - if err != nil { - fmt.Println("Failed to open file:", err) - os.Exit(1) - } - defer w.Close() - if _, err := w.WriteString(text); err != nil { - fmt.Println("Failed to write to file:", err) - os.Exit(1) - } -} - -var ( - all sync.WaitGroup - hasErrors bool -) - -type dependency struct { - sync.WaitGroup - hasErrors bool -} - -func generate(pkg string, deps ...*dependency) *dependency { - var wg dependency - if exclude(pkg) { - return &wg - } - wg.Add(1) - all.Add(1) - go func() { - defer wg.Done() - defer all.Done() - // Wait for dependencies to finish. - for _, d := range deps { - d.Wait() - if d.hasErrors && !*force { - fmt.Printf("--- ABORT: %s\n", pkg) - wg.hasErrors = true - return - } - } - vprintf("=== GENERATE %s\n", pkg) - args := []string{"generate"} - if *verbose { - args = append(args, "-v") - } - args = append(args, pkg) - cmd := exec.Command(filepath.Join(runtime.GOROOT(), "bin", "go"), args...) - w := &bytes.Buffer{} - cmd.Stderr = w - cmd.Stdout = w - if err := cmd.Run(); err != nil { - fmt.Printf("--- FAIL: %s:\n\t%v\n\tError: %v\n", pkg, indent(w), err) - hasErrors = true - wg.hasErrors = true - return - } - - vprintf("=== TEST %s\n", pkg) - args[0] = "test" - cmd = exec.Command(filepath.Join(runtime.GOROOT(), "bin", "go"), args...) - wt := &bytes.Buffer{} - cmd.Stderr = wt - cmd.Stdout = wt - if err := cmd.Run(); err != nil { - fmt.Printf("--- FAIL: %s:\n\t%v\n\tError: %v\n", pkg, indent(wt), err) - hasErrors = true - wg.hasErrors = true - return - } - vprintf("--- SUCCESS: %s\n\t%v\n", pkg, indent(w)) - fmt.Print(wt.String()) - }() - return &wg -} - -// copyExported copies a package in x/text/internal/export to the -// destination repository. -func copyExported(p string) { - copyPackage( - filepath.Join("internal", "export", path.Base(p)), - filepath.Join("..", filepath.FromSlash(p[len("golang.org/x"):])), - "golang.org/x/text/internal/export/"+path.Base(p), - p) -} - -// copyVendored copies packages used by Go core into the vendored directory. -func copyVendored() { - root := filepath.Join(build.Default.GOROOT, filepath.FromSlash("src/vendor/golang_org/x")) - - err := filepath.Walk(root, func(dir string, info os.FileInfo, err error) error { - if err != nil || !info.IsDir() || root == dir { - return err - } - src := dir[len(root)+1:] - const slash = string(filepath.Separator) - if c := strings.Split(src, slash); c[0] == "text" { - // Copy a text repo package from its normal location. - src = strings.Join(c[1:], slash) - } else { - // Copy the vendored package if it exists in the export directory. - src = filepath.Join("internal", "export", filepath.Base(src)) - } - copyPackage(src, dir, "golang.org", "golang_org") - return nil - }) - if err != nil { - fmt.Printf("Seeding directory %s has failed %v:", root, err) - os.Exit(1) - } -} - -// goGenRE is used to remove go:generate lines. -var goGenRE = regexp.MustCompile("//go:generate[^\n]*\n") - -// copyPackage copies relevant files from a directory in x/text to the -// destination package directory. The destination package is assumed to have -// the same name. For each copied file go:generate lines are removed and -// and package comments are rewritten to the new path. -func copyPackage(dirSrc, dirDst, search, replace string) { - err := filepath.Walk(dirSrc, func(file string, info os.FileInfo, err error) error { - base := filepath.Base(file) - if err != nil || info.IsDir() || - !strings.HasSuffix(base, ".go") || - strings.HasSuffix(base, "_test.go") || - // Don't process subdirectories. - filepath.Dir(file) != dirSrc { - return nil - } - b, err := ioutil.ReadFile(file) - if err != nil || bytes.Contains(b, []byte("\n// +build ignore")) { - return err - } - // Fix paths. - b = bytes.Replace(b, []byte(search), []byte(replace), -1) - // Remove go:generate lines. - b = goGenRE.ReplaceAllLiteral(b, nil) - comment := "// Code generated by running \"go generate\" in golang.org/x/text. DO NOT EDIT.\n\n" - if *doCore { - comment = "// Code generated by running \"go run gen.go -core\" in golang.org/x/text. DO NOT EDIT.\n\n" - } - if !bytes.HasPrefix(b, []byte(comment)) { - b = append([]byte(comment), b...) - } - if b, err = format.Source(b); err != nil { - fmt.Println("Failed to format file:", err) - os.Exit(1) - } - file = filepath.Join(dirDst, base) - vprintf("=== COPY %s\n", file) - return ioutil.WriteFile(file, b, 0666) - }) - if err != nil { - fmt.Println("Copying exported files failed:", err) - os.Exit(1) - } -} - -func contains(a []string, s string) bool { - for _, e := range a { - if s == e { - return true - } - } - return false -} - -func indent(b *bytes.Buffer) string { - return strings.Replace(strings.TrimSpace(b.String()), "\n", "\n\t", -1) -} diff --git a/vendor/golang.org/x/text/internal/colltab/collate_test.go b/vendor/golang.org/x/text/internal/colltab/collate_test.go deleted file mode 100644 index 580c85c2..00000000 --- a/vendor/golang.org/x/text/internal/colltab/collate_test.go +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package colltab_test - -// This file contains tests which need to import package collate, which causes -// an import cycle when done within package colltab itself. - -import ( - "bytes" - "testing" - "unicode" - - "golang.org/x/text/collate" - "golang.org/x/text/language" - "golang.org/x/text/unicode/rangetable" -) - -// assigned is used to only test runes that are inside the scope of the Unicode -// version used to generation the collation table. -var assigned = rangetable.Assigned(collate.UnicodeVersion) - -func TestNonDigits(t *testing.T) { - c := collate.New(language.English, collate.Loose, collate.Numeric) - - // Verify that all non-digit numbers sort outside of the number range. - for r, hi := rune(unicode.N.R16[0].Lo), rune(unicode.N.R32[0].Hi); r <= hi; r++ { - if unicode.In(r, unicode.Nd) || !unicode.In(r, assigned) { - continue - } - if a := string(r); c.CompareString(a, "0") != -1 && c.CompareString(a, "999999") != 1 { - t.Errorf("%+q non-digit number is collated as digit", a) - } - } -} - -func TestNumericCompare(t *testing.T) { - c := collate.New(language.English, collate.Loose, collate.Numeric) - - // Iterate over all digits. - for _, r16 := range unicode.Nd.R16 { - testDigitCompare(t, c, rune(r16.Lo), rune(r16.Hi)) - } - for _, r32 := range unicode.Nd.R32 { - testDigitCompare(t, c, rune(r32.Lo), rune(r32.Hi)) - } -} - -func testDigitCompare(t *testing.T, c *collate.Collator, zero, nine rune) { - if !unicode.In(zero, assigned) { - return - } - n := int(nine - zero + 1) - if n%10 != 0 { - t.Fatalf("len([%+q, %+q]) = %d; want a multiple of 10", zero, nine, n) - } - for _, tt := range []struct { - prefix string - b [11]string - }{ - { - prefix: "", - b: [11]string{ - "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", - }, - }, - { - prefix: "1", - b: [11]string{ - "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", - }, - }, - { - prefix: "0", - b: [11]string{ - "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", - }, - }, - { - prefix: "00", - b: [11]string{ - "000", "001", "002", "003", "004", "005", "006", "007", "008", "009", "010", - }, - }, - { - prefix: "9", - b: [11]string{ - "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "100", - }, - }, - } { - for k := 0; k <= n; k++ { - i := k % 10 - a := tt.prefix + string(zero+rune(i)) - for j, b := range tt.b { - want := 0 - switch { - case i < j: - want = -1 - case i > j: - want = 1 - } - got := c.CompareString(a, b) - if got != want { - t.Errorf("Compare(%+q, %+q) = %d; want %d", a, b, got, want) - return - } - } - } - } -} - -func BenchmarkNumericWeighter(b *testing.B) { - c := collate.New(language.English, collate.Numeric) - input := bytes.Repeat([]byte("Testing, testing 123..."), 100) - b.SetBytes(int64(2 * len(input))) - for i := 0; i < b.N; i++ { - c.Compare(input, input) - } -} diff --git a/vendor/golang.org/x/text/internal/colltab/collelem_test.go b/vendor/golang.org/x/text/internal/colltab/collelem_test.go deleted file mode 100644 index f131ecc3..00000000 --- a/vendor/golang.org/x/text/internal/colltab/collelem_test.go +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package colltab - -import ( - "fmt" - "testing" - "unicode" -) - -func (e Elem) String() string { - q := "" - if v := e.Quaternary(); v == MaxQuaternary { - q = "max" - } else { - q = fmt.Sprint(v) - } - return fmt.Sprintf("[%d, %d, %d, %s]", - e.Primary(), - e.Secondary(), - e.Tertiary(), - q) -} - -type ceTest struct { - f func(inout []int) (Elem, ceType) - arg []int -} - -func makeCE(weights []int) Elem { - ce, _ := MakeElem(weights[0], weights[1], weights[2], uint8(weights[3])) - return ce -} - -var defaultValues = []int{0, defaultSecondary, defaultTertiary, 0} - -func e(w ...int) Elem { - return makeCE(append(w, defaultValues[len(w):]...)) -} - -func makeContractIndex(index, n, offset int) Elem { - const ( - contractID = 0xC0000000 - maxNBits = 4 - maxTrieIndexBits = 12 - maxContractOffsetBits = 13 - ) - ce := Elem(contractID) - ce += Elem(offset << (maxNBits + maxTrieIndexBits)) - ce += Elem(index << maxNBits) - ce += Elem(n) - return ce -} - -func makeExpandIndex(index int) Elem { - const expandID = 0xE0000000 - return expandID + Elem(index) -} - -func makeDecompose(t1, t2 int) Elem { - const decompID = 0xF0000000 - return Elem(t2<<8+t1) + decompID -} - -func normalCE(inout []int) (ce Elem, t ceType) { - ce = makeCE(inout) - inout[0] = ce.Primary() - inout[1] = ce.Secondary() - inout[2] = int(ce.Tertiary()) - inout[3] = int(ce.CCC()) - return ce, ceNormal -} - -func expandCE(inout []int) (ce Elem, t ceType) { - ce = makeExpandIndex(inout[0]) - inout[0] = splitExpandIndex(ce) - return ce, ceExpansionIndex -} - -func contractCE(inout []int) (ce Elem, t ceType) { - ce = makeContractIndex(inout[0], inout[1], inout[2]) - i, n, o := splitContractIndex(ce) - inout[0], inout[1], inout[2] = i, n, o - return ce, ceContractionIndex -} - -func decompCE(inout []int) (ce Elem, t ceType) { - ce = makeDecompose(inout[0], inout[1]) - t1, t2 := splitDecompose(ce) - inout[0], inout[1] = int(t1), int(t2) - return ce, ceDecompose -} - -var ceTests = []ceTest{ - {normalCE, []int{0, 0, 0, 0}}, - {normalCE, []int{0, 30, 3, 0}}, - {normalCE, []int{0, 30, 3, 0xFF}}, - {normalCE, []int{100, defaultSecondary, defaultTertiary, 0}}, - {normalCE, []int{100, defaultSecondary, defaultTertiary, 0xFF}}, - {normalCE, []int{100, defaultSecondary, 3, 0}}, - {normalCE, []int{0x123, defaultSecondary, 8, 0xFF}}, - - {contractCE, []int{0, 0, 0}}, - {contractCE, []int{1, 1, 1}}, - {contractCE, []int{1, (1 << maxNBits) - 1, 1}}, - {contractCE, []int{(1 << maxTrieIndexBits) - 1, 1, 1}}, - {contractCE, []int{1, 1, (1 << maxContractOffsetBits) - 1}}, - - {expandCE, []int{0}}, - {expandCE, []int{5}}, - {expandCE, []int{(1 << maxExpandIndexBits) - 1}}, - - {decompCE, []int{0, 0}}, - {decompCE, []int{1, 1}}, - {decompCE, []int{0x1F, 0x1F}}, -} - -func TestColElem(t *testing.T) { - for i, tt := range ceTests { - inout := make([]int, len(tt.arg)) - copy(inout, tt.arg) - ce, typ := tt.f(inout) - if ce.ctype() != typ { - t.Errorf("%d: type is %d; want %d (ColElem: %X)", i, ce.ctype(), typ, ce) - } - for j, a := range tt.arg { - if inout[j] != a { - t.Errorf("%d: argument %d is %X; want %X (ColElem: %X)", i, j, inout[j], a, ce) - } - } - } -} - -type implicitTest struct { - r rune - p int -} - -var implicitTests = []implicitTest{ - {0x33FF, 0x533FF}, - {0x3400, 0x23400}, - {0x4DC0, 0x54DC0}, - {0x4DFF, 0x54DFF}, - {0x4E00, 0x14E00}, - {0x9FCB, 0x19FCB}, - {0xA000, 0x5A000}, - {0xF8FF, 0x5F8FF}, - {0xF900, 0x1F900}, - {0xFA23, 0x1FA23}, - {0xFAD9, 0x1FAD9}, - {0xFB00, 0x5FB00}, - {0x20000, 0x40000}, - {0x2B81C, 0x4B81C}, - {unicode.MaxRune, 0x15FFFF}, // maximum primary value -} - -func TestImplicit(t *testing.T) { - for _, tt := range implicitTests { - if p := implicitPrimary(tt.r); p != tt.p { - t.Errorf("%U: was %X; want %X", tt.r, p, tt.p) - } - } -} - -func TestUpdateTertiary(t *testing.T) { - tests := []struct { - in, out Elem - t uint8 - }{ - {0x4000FE20, 0x0000FE8A, 0x0A}, - {0x4000FE21, 0x0000FEAA, 0x0A}, - {0x0000FE8B, 0x0000FE83, 0x03}, - {0x82FF0188, 0x9BFF0188, 0x1B}, - {0xAFF0CC02, 0xAFF0CC1B, 0x1B}, - } - for i, tt := range tests { - if out := tt.in.updateTertiary(tt.t); out != tt.out { - t.Errorf("%d: was %X; want %X", i, out, tt.out) - } - } -} diff --git a/vendor/golang.org/x/text/internal/colltab/colltab_test.go b/vendor/golang.org/x/text/internal/colltab/colltab_test.go deleted file mode 100644 index c403ac34..00000000 --- a/vendor/golang.org/x/text/internal/colltab/colltab_test.go +++ /dev/null @@ -1,64 +0,0 @@ -package colltab - -import ( - "testing" - - "golang.org/x/text/language" -) - -func TestMatchLang(t *testing.T) { - tags := []language.Tag{ - 0: language.Und, - 1: language.MustParse("bs"), - 2: language.German, - 3: language.English, - 4: language.AmericanEnglish, - 5: language.MustParse("en-US-u-va-posix"), - 6: language.Portuguese, - 7: language.Serbian, - 8: language.MustParse("sr-Latn"), - 9: language.Chinese, - 10: language.MustParse("zh-u-co-stroke"), - 11: language.MustParse("zh-Hant-u-co-pinyin"), - 12: language.TraditionalChinese, - } - for i, tc := range []struct { - x int - t language.Tag - }{ - {0, language.Und}, - {0, language.Persian}, // Default to first element when no match. - {3, language.English}, - {4, language.AmericanEnglish}, - {5, language.MustParse("en-US-u-va-posix")}, // Ext. variant match. - {4, language.MustParse("en-US-u-va-noposix")}, // Ext. variant mismatch. - {3, language.MustParse("en-UK-u-va-noposix")}, // Ext. variant mismatch. - {7, language.Serbian}, - {0, language.Croatian}, // Don't match to close language! - {0, language.MustParse("gsw")}, // Don't match to close language! - {1, language.MustParse("bs-Cyrl")}, // Odd, but correct. - {1, language.MustParse("bs-Latn")}, // Estimated script drops. - {8, language.MustParse("sr-Latn")}, - {9, language.Chinese}, - {9, language.SimplifiedChinese}, - {12, language.TraditionalChinese}, - {11, language.MustParse("zh-Hant-u-co-pinyin")}, - // TODO: should this be 12? Either inherited value (10) or default is - // fine in this case, though. Other locales are not affected. - {10, language.MustParse("zh-Hant-u-co-stroke")}, - // There is no "phonebk" sorting order for zh-Hant, so use default. - {12, language.MustParse("zh-Hant-u-co-phonebk")}, - {10, language.MustParse("zh-u-co-stroke")}, - {12, language.MustParse("und-TW")}, // Infer script and language. - {12, language.MustParse("und-HK")}, // Infer script and language. - {6, language.MustParse("und-BR")}, // Infer script and language. - {6, language.MustParse("und-PT")}, // Infer script and language. - {2, language.MustParse("und-Latn-DE")}, // Infer language. - {0, language.MustParse("und-Jpan-BR")}, // Infers "ja", so no match. - {0, language.MustParse("zu")}, // No match past index. - } { - if x := MatchLang(tc.t, tags); x != tc.x { - t.Errorf("%d: MatchLang(%q, tags) = %d; want %d", i, tc.t, x, tc.x) - } - } -} diff --git a/vendor/golang.org/x/text/internal/colltab/contract_test.go b/vendor/golang.org/x/text/internal/colltab/contract_test.go deleted file mode 100644 index ce2871dd..00000000 --- a/vendor/golang.org/x/text/internal/colltab/contract_test.go +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package colltab - -import ( - "testing" -) - -type lookupStrings struct { - str string - offset int - n int // bytes consumed from input -} - -type LookupTest struct { - lookup []lookupStrings - n int - tries ContractTrieSet -} - -var lookupTests = []LookupTest{{ - []lookupStrings{ - {"abc", 1, 3}, - {"a", 0, 0}, - {"b", 0, 0}, - {"c", 0, 0}, - {"d", 0, 0}, - }, - 1, - ContractTrieSet{ - {'a', 0, 1, 0xFF}, - {'b', 0, 1, 0xFF}, - {'c', 'c', 0, 1}, - }, -}, { - []lookupStrings{ - {"abc", 1, 3}, - {"abd", 2, 3}, - {"abe", 3, 3}, - {"a", 0, 0}, - {"ab", 0, 0}, - {"d", 0, 0}, - {"f", 0, 0}, - }, - 1, - ContractTrieSet{ - {'a', 0, 1, 0xFF}, - {'b', 0, 1, 0xFF}, - {'c', 'e', 0, 1}, - }, -}, { - []lookupStrings{ - {"abc", 1, 3}, - {"ab", 2, 2}, - {"a", 3, 1}, - {"abcd", 1, 3}, - {"abe", 2, 2}, - }, - 1, - ContractTrieSet{ - {'a', 0, 1, 3}, - {'b', 0, 1, 2}, - {'c', 'c', 0, 1}, - }, -}, { - []lookupStrings{ - {"abc", 1, 3}, - {"abd", 2, 3}, - {"ab", 3, 2}, - {"ac", 4, 2}, - {"a", 5, 1}, - {"b", 6, 1}, - {"ba", 6, 1}, - }, - 2, - ContractTrieSet{ - {'b', 'b', 0, 6}, - {'a', 0, 2, 5}, - {'c', 'c', 0, 4}, - {'b', 0, 1, 3}, - {'c', 'd', 0, 1}, - }, -}, { - []lookupStrings{ - {"bcde", 2, 4}, - {"bc", 7, 2}, - {"ab", 6, 2}, - {"bcd", 5, 3}, - {"abcd", 1, 4}, - {"abc", 4, 3}, - {"bcdf", 3, 4}, - }, - 2, - ContractTrieSet{ - {'b', 3, 1, 0xFF}, - {'a', 0, 1, 0xFF}, - {'b', 0, 1, 6}, - {'c', 0, 1, 4}, - {'d', 'd', 0, 1}, - {'c', 0, 1, 7}, - {'d', 0, 1, 5}, - {'e', 'f', 0, 2}, - }, -}} - -func lookup(c *ContractTrieSet, nnode int, s []uint8) (i, n int) { - scan := c.scanner(0, nnode, s) - scan.scan(0) - return scan.result() -} - -func TestLookupContraction(t *testing.T) { - for i, tt := range lookupTests { - cts := ContractTrieSet(tt.tries) - for j, lu := range tt.lookup { - str := lu.str - for _, s := range []string{str, str + "X"} { - const msg = `%d:%d: %s of "%s" %v; want %v` - offset, n := lookup(&cts, tt.n, []byte(s)) - if offset != lu.offset { - t.Errorf(msg, i, j, "offset", s, offset, lu.offset) - } - if n != lu.n { - t.Errorf(msg, i, j, "bytes consumed", s, n, len(str)) - } - } - } - } -} diff --git a/vendor/golang.org/x/text/internal/colltab/iter_test.go b/vendor/golang.org/x/text/internal/colltab/iter_test.go deleted file mode 100644 index 5783534c..00000000 --- a/vendor/golang.org/x/text/internal/colltab/iter_test.go +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package colltab - -import ( - "testing" -) - -func TestDoNorm(t *testing.T) { - const div = -1 // The insertion point of the next block. - tests := []struct { - in, out []int - }{{ - in: []int{4, div, 3}, - out: []int{3, 4}, - }, { - in: []int{4, div, 3, 3, 3}, - out: []int{3, 3, 3, 4}, - }, { - in: []int{0, 4, div, 3}, - out: []int{0, 3, 4}, - }, { - in: []int{0, 0, 4, 5, div, 3, 3}, - out: []int{0, 0, 3, 3, 4, 5}, - }, { - in: []int{0, 0, 1, 4, 5, div, 3, 3}, - out: []int{0, 0, 1, 3, 3, 4, 5}, - }, { - in: []int{0, 0, 1, 4, 5, div, 4, 4}, - out: []int{0, 0, 1, 4, 4, 4, 5}, - }, - } - for j, tt := range tests { - i := Iter{} - var w, p int - for k, cc := range tt.in { - - if cc == div { - w = 100 - p = k - continue - } - i.Elems = append(i.Elems, makeCE([]int{w, defaultSecondary, 2, cc})) - } - i.doNorm(p, i.Elems[p].CCC()) - if len(i.Elems) != len(tt.out) { - t.Errorf("%d: length was %d; want %d", j, len(i.Elems), len(tt.out)) - } - prevCCC := uint8(0) - for k, ce := range i.Elems { - if int(ce.CCC()) != tt.out[k] { - t.Errorf("%d:%d: unexpected CCC. Was %d; want %d", j, k, ce.CCC(), tt.out[k]) - } - if k > 0 && ce.CCC() == prevCCC && i.Elems[k-1].Primary() > ce.Primary() { - t.Errorf("%d:%d: normalization crossed across CCC boundary.", j, k) - } - } - } - - // Combining rune overflow is tested in search/pattern_test.go. -} diff --git a/vendor/golang.org/x/text/internal/colltab/numeric_test.go b/vendor/golang.org/x/text/internal/colltab/numeric_test.go deleted file mode 100644 index e9406ae3..00000000 --- a/vendor/golang.org/x/text/internal/colltab/numeric_test.go +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package colltab - -import ( - "reflect" - "strings" - "testing" - - "golang.org/x/text/internal/testtext" -) - -const ( - digSec = defaultSecondary - digTert = defaultTertiary -) - -var tPlus3 = e(0, 50, digTert+3) - -// numWeighter is a testWeighter used for testing numericWeighter. -var numWeighter = testWeighter{ - "0": p(100), - "0": []Elem{e(100, digSec, digTert+1)}, // U+FF10 FULLWIDTH DIGIT ZERO - "₀": []Elem{e(100, digSec, digTert+5)}, // U+2080 SUBSCRIPT ZERO - - "1": p(101), - // Allow non-primary collation elements to be inserted. - "١": append(p(101), tPlus3), // U+0661 ARABIC-INDIC DIGIT ONE - // Allow varying tertiary weight if the number is Nd. - "1": []Elem{e(101, digSec, digTert+1)}, // U+FF11 FULLWIDTH DIGIT ONE - "2": p(102), - // Allow non-primary collation elements to be inserted. - "٢": append(p(102), tPlus3), // U+0662 ARABIC-INDIC DIGIT TWO - // Varying tertiary weights should be ignored. - "2": []Elem{e(102, digSec, digTert+3)}, // U+FF12 FULLWIDTH DIGIT TWO - "3": p(103), - "4": p(104), - "5": p(105), - "6": p(106), - "7": p(107), - // Weights must be strictly monotonically increasing, but do not need to be - // consecutive. - "8": p(118), - "9": p(119), - // Allow non-primary collation elements to be inserted. - "٩": append(p(119), tPlus3), // U+0669 ARABIC-INDIC DIGIT NINE - // Varying tertiary weights should be ignored. - "9": []Elem{e(119, digSec, digTert+1)}, // U+FF19 FULLWIDTH DIGIT NINE - "₉": []Elem{e(119, digSec, digTert+5)}, // U+2089 SUBSCRIPT NINE - - "a": p(5), - "b": p(6), - "c": p(8, 2), - - "klm": p(99), - - "nop": p(121), - - "x": p(200), - "y": p(201), -} - -func p(w ...int) (elems []Elem) { - for _, x := range w { - e, _ := MakeElem(x, digSec, digTert, 0) - elems = append(elems, e) - } - return elems -} - -func TestNumericAppendNext(t *testing.T) { - for _, tt := range []struct { - in string - w []Elem - }{ - {"a", p(5)}, - {"klm", p(99)}, - {"aa", p(5, 5)}, - {"1", p(120, 1, 101)}, - {"0", p(120, 0)}, - {"01", p(120, 1, 101)}, - {"0001", p(120, 1, 101)}, - {"10", p(120, 2, 101, 100)}, - {"99", p(120, 2, 119, 119)}, - {"9999", p(120, 4, 119, 119, 119, 119)}, - {"1a", p(120, 1, 101, 5)}, - {"0b", p(120, 0, 6)}, - {"01c", p(120, 1, 101, 8, 2)}, - {"10x", p(120, 2, 101, 100, 200)}, - {"99y", p(120, 2, 119, 119, 201)}, - {"9999nop", p(120, 4, 119, 119, 119, 119, 121)}, - - // Allow follow-up collation elements if they have a zero non-primary. - {"١٢٩", []Elem{e(120), e(3), e(101), tPlus3, e(102), tPlus3, e(119), tPlus3}}, - { - "129", - []Elem{ - e(120), e(3), - e(101, digSec, digTert+1), - e(102, digSec, digTert+3), - e(119, digSec, digTert+1), - }, - }, - - // Ensure AppendNext* adds to the given buffer. - {"a10", p(5, 120, 2, 101, 100)}, - } { - nw := NewNumericWeighter(numWeighter) - - b := []byte(tt.in) - got := []Elem(nil) - for n, sz := 0, 0; n < len(b); { - got, sz = nw.AppendNext(got, b[n:]) - n += sz - } - if !reflect.DeepEqual(got, tt.w) { - t.Errorf("AppendNext(%q) =\n%v; want\n%v", tt.in, got, tt.w) - } - - got = nil - for n, sz := 0, 0; n < len(tt.in); { - got, sz = nw.AppendNextString(got, tt.in[n:]) - n += sz - } - if !reflect.DeepEqual(got, tt.w) { - t.Errorf("AppendNextString(%q) =\n%v; want\n%v", tt.in, got, tt.w) - } - } -} - -func TestNumericOverflow(t *testing.T) { - manyDigits := strings.Repeat("9", maxDigits+1) + "a" - - nw := NewNumericWeighter(numWeighter) - - got, n := nw.AppendNextString(nil, manyDigits) - - if n != maxDigits { - t.Errorf("n: got %d; want %d", n, maxDigits) - } - - if got[1].Primary() != maxDigits { - t.Errorf("primary(e[1]): got %d; want %d", n, maxDigits) - } -} - -func TestNumericWeighterAlloc(t *testing.T) { - buf := make([]Elem, 100) - w := NewNumericWeighter(numWeighter) - s := "1234567890a" - - nNormal := testtext.AllocsPerRun(3, func() { numWeighter.AppendNextString(buf, s) }) - nNumeric := testtext.AllocsPerRun(3, func() { w.AppendNextString(buf, s) }) - if n := nNumeric - nNormal; n > 0 { - t.Errorf("got %f; want 0", n) - } -} diff --git a/vendor/golang.org/x/text/internal/colltab/trie_test.go b/vendor/golang.org/x/text/internal/colltab/trie_test.go deleted file mode 100644 index b056a811..00000000 --- a/vendor/golang.org/x/text/internal/colltab/trie_test.go +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package colltab - -import ( - "testing" -) - -// We take the smallest, largest and an arbitrary value for each -// of the UTF-8 sequence lengths. -var testRunes = []rune{ - 0x01, 0x0C, 0x7F, // 1-byte sequences - 0x80, 0x100, 0x7FF, // 2-byte sequences - 0x800, 0x999, 0xFFFF, // 3-byte sequences - 0x10000, 0x10101, 0x10FFFF, // 4-byte sequences - 0x200, 0x201, 0x202, 0x210, 0x215, // five entries in one sparse block -} - -// Test cases for illegal runes. -type trietest struct { - size int - bytes []byte -} - -var tests = []trietest{ - // illegal runes - {1, []byte{0x80}}, - {1, []byte{0xFF}}, - {1, []byte{t2, tx - 1}}, - {1, []byte{t2, t2}}, - {2, []byte{t3, tx, tx - 1}}, - {2, []byte{t3, tx, t2}}, - {1, []byte{t3, tx - 1, tx}}, - {3, []byte{t4, tx, tx, tx - 1}}, - {3, []byte{t4, tx, tx, t2}}, - {1, []byte{t4, t2, tx, tx - 1}}, - {2, []byte{t4, tx, t2, tx - 1}}, - - // short runes - {0, []byte{t2}}, - {0, []byte{t3, tx}}, - {0, []byte{t4, tx, tx}}, - - // we only support UTF-8 up to utf8.UTFMax bytes (4 bytes) - {1, []byte{t5, tx, tx, tx, tx}}, - {1, []byte{t6, tx, tx, tx, tx, tx}}, -} - -func TestLookupTrie(t *testing.T) { - for i, r := range testRunes { - b := []byte(string(r)) - v, sz := testTrie.lookup(b) - if int(v) != i { - t.Errorf("lookup(%U): found value %#x, expected %#x", r, v, i) - } - if sz != len(b) { - t.Errorf("lookup(%U): found size %d, expected %d", r, sz, len(b)) - } - } - for i, tt := range tests { - v, sz := testTrie.lookup(tt.bytes) - if int(v) != 0 { - t.Errorf("lookup of illegal rune, case %d: found value %#x, expected 0", i, v) - } - if sz != tt.size { - t.Errorf("lookup of illegal rune, case %d: found size %d, expected %d", i, sz, tt.size) - } - } -} - -// test data is taken from exp/collate/locale/build/trie_test.go -var testValues = [832]uint32{ - 0x000c: 0x00000001, - 0x007f: 0x00000002, - 0x00c0: 0x00000003, - 0x0100: 0x00000004, - 0x0140: 0x0000000c, 0x0141: 0x0000000d, 0x0142: 0x0000000e, - 0x0150: 0x0000000f, - 0x0155: 0x00000010, - 0x01bf: 0x00000005, - 0x01c0: 0x00000006, - 0x0219: 0x00000007, - 0x027f: 0x00000008, - 0x0280: 0x00000009, - 0x02c1: 0x0000000a, - 0x033f: 0x0000000b, -} - -var testLookup = [640]uint16{ - 0x0e0: 0x05, 0x0e6: 0x06, - 0x13f: 0x07, - 0x140: 0x08, 0x144: 0x09, - 0x190: 0x03, - 0x1ff: 0x0a, - 0x20f: 0x05, - 0x242: 0x01, 0x244: 0x02, - 0x248: 0x03, - 0x25f: 0x04, - 0x260: 0x01, - 0x26f: 0x02, - 0x270: 0x04, 0x274: 0x06, -} - -var testTrie = Trie{testLookup[6*blockSize:], testValues[:], testLookup[:], testValues[:]} diff --git a/vendor/golang.org/x/text/internal/colltab/weighter_test.go b/vendor/golang.org/x/text/internal/colltab/weighter_test.go deleted file mode 100644 index b5f8487b..00000000 --- a/vendor/golang.org/x/text/internal/colltab/weighter_test.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package colltab - -// testWeighter is a simple Weighter that returns weights from a user-defined map. -type testWeighter map[string][]Elem - -func (t testWeighter) Start(int, []byte) int { return 0 } -func (t testWeighter) StartString(int, string) int { return 0 } -func (t testWeighter) Domain() []string { return nil } -func (t testWeighter) Top() uint32 { return 0 } - -// maxContractBytes is the maximum length of any key in the map. -const maxContractBytes = 10 - -func (t testWeighter) AppendNext(buf []Elem, s []byte) ([]Elem, int) { - n := len(s) - if n > maxContractBytes { - n = maxContractBytes - } - for i := n; i > 0; i-- { - if e, ok := t[string(s[:i])]; ok { - return append(buf, e...), i - } - } - panic("incomplete testWeighter: could not find " + string(s)) -} - -func (t testWeighter) AppendNextString(buf []Elem, s string) ([]Elem, int) { - n := len(s) - if n > maxContractBytes { - n = maxContractBytes - } - for i := n; i > 0; i-- { - if e, ok := t[s[:i]]; ok { - return append(buf, e...), i - } - } - panic("incomplete testWeighter: could not find " + s) -} diff --git a/vendor/golang.org/x/text/internal/gen.go b/vendor/golang.org/x/text/internal/gen.go deleted file mode 100644 index 1d678af5..00000000 --- a/vendor/golang.org/x/text/internal/gen.go +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -package main - -import ( - "log" - - "golang.org/x/text/internal/gen" - "golang.org/x/text/language" - "golang.org/x/text/unicode/cldr" -) - -func main() { - r := gen.OpenCLDRCoreZip() - defer r.Close() - - d := &cldr.Decoder{} - data, err := d.DecodeZip(r) - if err != nil { - log.Fatalf("DecodeZip: %v", err) - } - - w := gen.NewCodeWriter() - defer w.WriteGoFile("tables.go", "internal") - - // Create parents table. - parents := make([]uint16, language.NumCompactTags) - for _, loc := range data.Locales() { - tag := language.MustParse(loc) - index, ok := language.CompactIndex(tag) - if !ok { - continue - } - parentIndex := 0 // und - for p := tag.Parent(); p != language.Und; p = p.Parent() { - if x, ok := language.CompactIndex(p); ok { - parentIndex = x - break - } - } - parents[index] = uint16(parentIndex) - } - - w.WriteComment(` - Parent maps a compact index of a tag to the compact index of the parent of - this tag.`) - w.WriteVar("Parent", parents) -} diff --git a/vendor/golang.org/x/text/internal/gen_test.go b/vendor/golang.org/x/text/internal/gen_test.go deleted file mode 100644 index a2e1981a..00000000 --- a/vendor/golang.org/x/text/internal/gen_test.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package internal - -import ( - "testing" - - "golang.org/x/text/language" -) - -func TestParents(t *testing.T) { - testCases := []struct { - tag, parent string - }{ - {"af", "und"}, - {"en", "und"}, - {"en-001", "en"}, - {"en-AU", "en-001"}, - {"en-US", "en"}, - {"en-US-u-va-posix", "en-US"}, - {"ca-ES-valencia", "ca-ES"}, - } - for _, tc := range testCases { - tag, ok := language.CompactIndex(language.MustParse(tc.tag)) - if !ok { - t.Fatalf("Could not get index of flag %s", tc.tag) - } - want, ok := language.CompactIndex(language.MustParse(tc.parent)) - if !ok { - t.Fatalf("Could not get index of parent %s of tag %s", tc.parent, tc.tag) - } - if got := int(Parent[tag]); got != want { - t.Errorf("Parent[%s] = %d; want %d (%s)", tc.tag, got, want, tc.parent) - } - } -} diff --git a/vendor/golang.org/x/text/internal/internal.go b/vendor/golang.org/x/text/internal/internal.go deleted file mode 100644 index eac83285..00000000 --- a/vendor/golang.org/x/text/internal/internal.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:generate go run gen.go - -// Package internal contains non-exported functionality that are used by -// packages in the text repository. -package internal // import "golang.org/x/text/internal" - -import ( - "sort" - - "golang.org/x/text/language" -) - -// SortTags sorts tags in place. -func SortTags(tags []language.Tag) { - sort.Sort(sorter(tags)) -} - -type sorter []language.Tag - -func (s sorter) Len() int { - return len(s) -} - -func (s sorter) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} - -func (s sorter) Less(i, j int) bool { - return s[i].String() < s[j].String() -} - -// UniqueTags sorts and filters duplicate tags in place and returns a slice with -// only unique tags. -func UniqueTags(tags []language.Tag) []language.Tag { - if len(tags) <= 1 { - return tags - } - SortTags(tags) - k := 0 - for i := 1; i < len(tags); i++ { - if tags[k].String() < tags[i].String() { - k++ - tags[k] = tags[i] - } - } - return tags[:k+1] -} diff --git a/vendor/golang.org/x/text/internal/internal_test.go b/vendor/golang.org/x/text/internal/internal_test.go deleted file mode 100644 index ce1b9a38..00000000 --- a/vendor/golang.org/x/text/internal/internal_test.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package internal - -import ( - "fmt" - "strings" - "testing" - - "golang.org/x/text/language" -) - -func TestUnique(t *testing.T) { - testCases := []struct { - in, want string - }{ - {"", "[]"}, - {"en", "[en]"}, - {"en en", "[en]"}, - {"en en en", "[en]"}, - {"en-u-cu-eur en", "[en en-u-cu-eur]"}, - {"nl en", "[en nl]"}, - {"pt-Pt pt", "[pt pt-PT]"}, - } - for _, tc := range testCases { - tags := []language.Tag{} - for _, s := range strings.Split(tc.in, " ") { - if s != "" { - tags = append(tags, language.MustParse(s)) - } - } - if got := fmt.Sprint(UniqueTags(tags)); got != tc.want { - t.Errorf("Unique(%s) = %s; want %s", tc.in, got, tc.want) - } - } -} diff --git a/vendor/golang.org/x/text/internal/match.go b/vendor/golang.org/x/text/internal/match.go deleted file mode 100644 index a67fcaca..00000000 --- a/vendor/golang.org/x/text/internal/match.go +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package internal - -// This file contains matchers that implement CLDR inheritance. -// -// See http://unicode.org/reports/tr35/#Locale_Inheritance. -// -// Some of the inheritance described in this document is already handled by -// the cldr package. - -import ( - "golang.org/x/text/language" -) - -// TODO: consider if (some of the) matching algorithm needs to be public after -// getting some feel about what is generic and what is specific. - -// NewInheritanceMatcher returns a matcher that matches based on the inheritance -// chain. -// -// The matcher uses canonicalization and the parent relationship to find a -// match. The resulting match will always be either Und or a language with the -// same language and script as the requested language. It will not match -// languages for which there is understood to be mutual or one-directional -// intelligibility. -// -// A Match will indicate an Exact match if the language matches after -// canonicalization and High if the matched tag is a parent. -func NewInheritanceMatcher(t []language.Tag) *InheritanceMatcher { - tags := &InheritanceMatcher{make(map[language.Tag]int)} - for i, tag := range t { - ct, err := language.All.Canonicalize(tag) - if err != nil { - ct = tag - } - tags.index[ct] = i - } - return tags -} - -type InheritanceMatcher struct { - index map[language.Tag]int -} - -func (m InheritanceMatcher) Match(want ...language.Tag) (language.Tag, int, language.Confidence) { - for _, t := range want { - ct, err := language.All.Canonicalize(t) - if err != nil { - ct = t - } - conf := language.Exact - for { - if index, ok := m.index[ct]; ok { - return ct, index, conf - } - if ct == language.Und { - break - } - ct = ct.Parent() - conf = language.High - } - } - return language.Und, 0, language.No -} diff --git a/vendor/golang.org/x/text/internal/match_test.go b/vendor/golang.org/x/text/internal/match_test.go deleted file mode 100644 index 8a3fe657..00000000 --- a/vendor/golang.org/x/text/internal/match_test.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package internal - -import ( - "strings" - "testing" - - "golang.org/x/text/language" -) - -func TestInheritanceMatcher(t *testing.T) { - for i, tt := range []struct { - haveTags string - wantTags string - match string - conf language.Confidence - }{ - {"und,en,en-US", "en-US", "en-US", language.Exact}, // most specific match - {"zh-Hant,zh", "zh-TW", "zh-Hant", language.High}, // zh-TW implies Hant. - {"und,zh", "zh-TW", "und", language.High}, // zh-TW does not match zh. - {"zh", "zh-TW", "und", language.No}, // zh-TW does not match zh. - {"iw,en,nl", "he", "he", language.Exact}, // matches after canonicalization - {"he,en,nl", "iw", "he", language.Exact}, // matches after canonicalization - // Prefer first match over more specific match for various reasons: - // a) consistency of user interface is more important than an exact match, - // b) _if_ und is specified, it should be considered a correct and useful match, - // Note that a call to this Match will almost always be with a single tag. - {"und,en,en-US", "he,en-US", "und", language.High}, - } { - have := parseTags(tt.haveTags) - m := NewInheritanceMatcher(have) - tag, index, conf := m.Match(parseTags(tt.wantTags)...) - want := language.Raw.Make(tt.match) - if tag != want { - t.Errorf("%d:tag: got %q; want %q", i, tag, want) - } - if conf != language.No { - if got, _ := language.All.Canonicalize(have[index]); got != want { - t.Errorf("%d:index: got %q; want %q ", i, got, want) - } - } - if conf != tt.conf { - t.Errorf("%d:conf: got %v; want %v", i, conf, tt.conf) - } - } -} - -func parseTags(list string) (out []language.Tag) { - for _, s := range strings.Split(list, ",") { - out = append(out, language.Raw.Make(strings.TrimSpace(s))) - } - return out -} diff --git a/vendor/golang.org/x/text/internal/tables.go b/vendor/golang.org/x/text/internal/tables.go deleted file mode 100644 index 85991d3d..00000000 --- a/vendor/golang.org/x/text/internal/tables.go +++ /dev/null @@ -1,118 +0,0 @@ -// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. - -package internal - -// Parent maps a compact index of a tag to the compact index of the parent of -// this tag. -var Parent = []uint16{ // 768 elements - // Entry 0 - 3F - 0x0000, 0x0053, 0x00e8, 0x0000, 0x0003, 0x0003, 0x0000, 0x0006, - 0x0000, 0x0008, 0x0000, 0x000a, 0x0000, 0x000c, 0x000c, 0x000c, - 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, - 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, - 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, - 0x000c, 0x0000, 0x0000, 0x002a, 0x0000, 0x002c, 0x0000, 0x002e, - 0x0000, 0x0000, 0x0031, 0x0030, 0x0030, 0x0000, 0x0035, 0x0000, - 0x0037, 0x0000, 0x0039, 0x0000, 0x003b, 0x0000, 0x003d, 0x0000, - // Entry 40 - 7F - 0x0000, 0x0040, 0x0000, 0x0042, 0x0042, 0x0000, 0x0045, 0x0045, - 0x0000, 0x0048, 0x0000, 0x004a, 0x0000, 0x0000, 0x004d, 0x004c, - 0x004c, 0x0000, 0x0051, 0x0051, 0x0051, 0x0051, 0x0000, 0x0056, - 0x0056, 0x0000, 0x0059, 0x0000, 0x005b, 0x0000, 0x005d, 0x0000, - 0x005f, 0x005f, 0x0000, 0x0062, 0x0000, 0x0064, 0x0000, 0x0066, - 0x0000, 0x0068, 0x0068, 0x0000, 0x006b, 0x0000, 0x006d, 0x006d, - 0x006d, 0x006d, 0x006d, 0x006d, 0x006d, 0x0000, 0x0075, 0x0000, - 0x0077, 0x0000, 0x0079, 0x0000, 0x0000, 0x007c, 0x0000, 0x007e, - // Entry 80 - BF - 0x0000, 0x0080, 0x0000, 0x0082, 0x0082, 0x0000, 0x0085, 0x0085, - 0x0000, 0x0088, 0x0089, 0x0089, 0x0089, 0x0088, 0x008a, 0x0089, - 0x0089, 0x0089, 0x0088, 0x0089, 0x0089, 0x0089, 0x0089, 0x0089, - 0x0089, 0x008a, 0x0089, 0x0089, 0x0089, 0x0089, 0x008a, 0x0089, - 0x008a, 0x0089, 0x0089, 0x008a, 0x0089, 0x0089, 0x0089, 0x0089, - 0x0089, 0x0089, 0x0089, 0x0089, 0x0089, 0x0088, 0x0089, 0x0089, - 0x0089, 0x0089, 0x0089, 0x0089, 0x0089, 0x0089, 0x0089, 0x0089, - 0x0089, 0x0089, 0x0089, 0x0089, 0x0089, 0x0089, 0x0089, 0x0088, - // Entry C0 - FF - 0x0089, 0x0088, 0x0089, 0x0089, 0x0089, 0x0089, 0x0089, 0x0089, - 0x0089, 0x0089, 0x008a, 0x0089, 0x0089, 0x0089, 0x0089, 0x0089, - 0x0089, 0x0089, 0x0088, 0x0089, 0x0089, 0x0089, 0x0089, 0x0089, - 0x008a, 0x0089, 0x0089, 0x008a, 0x0089, 0x0089, 0x0089, 0x0089, - 0x0089, 0x0089, 0x0089, 0x0089, 0x0089, 0x0089, 0x0089, 0x0088, - 0x0088, 0x0089, 0x0089, 0x0088, 0x0089, 0x0089, 0x0089, 0x0089, - 0x0089, 0x0000, 0x00f1, 0x0000, 0x00f3, 0x00f4, 0x00f4, 0x00f4, - 0x00f4, 0x00f4, 0x00f4, 0x00f4, 0x00f4, 0x00f4, 0x00f3, 0x00f4, - // Entry 100 - 13F - 0x00f3, 0x00f3, 0x00f4, 0x00f4, 0x00f3, 0x00f4, 0x00f4, 0x00f4, - 0x00f4, 0x00f3, 0x00f4, 0x00f4, 0x00f4, 0x00f4, 0x00f4, 0x00f4, - 0x0000, 0x0110, 0x0000, 0x0112, 0x0000, 0x0114, 0x0000, 0x0116, - 0x0116, 0x0000, 0x0119, 0x0119, 0x0119, 0x0119, 0x0000, 0x011e, - 0x0000, 0x0120, 0x0000, 0x0122, 0x0122, 0x0000, 0x0125, 0x0125, - 0x0125, 0x0125, 0x0125, 0x0125, 0x0125, 0x0125, 0x0125, 0x0125, - 0x0125, 0x0125, 0x0125, 0x0125, 0x0125, 0x0125, 0x0125, 0x0125, - 0x0125, 0x0125, 0x0125, 0x0125, 0x0125, 0x0125, 0x0125, 0x0125, - // Entry 140 - 17F - 0x0125, 0x0125, 0x0125, 0x0125, 0x0125, 0x0125, 0x0125, 0x0125, - 0x0125, 0x0125, 0x0125, 0x0125, 0x0125, 0x0125, 0x0125, 0x0125, - 0x0125, 0x0125, 0x0125, 0x0125, 0x0000, 0x0154, 0x0000, 0x0156, - 0x0000, 0x0158, 0x0000, 0x015a, 0x0000, 0x015c, 0x0000, 0x015e, - 0x015e, 0x015e, 0x0000, 0x0162, 0x0000, 0x0000, 0x0165, 0x0000, - 0x0167, 0x0000, 0x0169, 0x0169, 0x0169, 0x0000, 0x016d, 0x0000, - 0x016f, 0x0000, 0x0171, 0x0000, 0x0173, 0x0173, 0x0000, 0x0176, - 0x0000, 0x0178, 0x0000, 0x017a, 0x0000, 0x017c, 0x0000, 0x017e, - // Entry 180 - 1BF - 0x0000, 0x0180, 0x0000, 0x0000, 0x0183, 0x0000, 0x0185, 0x0185, - 0x0185, 0x0185, 0x0000, 0x0000, 0x018b, 0x0000, 0x0000, 0x018e, - 0x0000, 0x0190, 0x0000, 0x0000, 0x0193, 0x0000, 0x0195, 0x0000, - 0x0000, 0x0198, 0x0000, 0x0000, 0x019b, 0x0000, 0x019d, 0x0000, - 0x019f, 0x0000, 0x01a1, 0x0000, 0x01a3, 0x0000, 0x01a5, 0x0000, - 0x01a7, 0x0000, 0x01a9, 0x0000, 0x01ab, 0x0000, 0x01ad, 0x0000, - 0x01af, 0x01af, 0x0000, 0x01b2, 0x0000, 0x01b4, 0x0000, 0x01b6, - 0x0000, 0x01b8, 0x0000, 0x01ba, 0x0000, 0x0000, 0x01bd, 0x0000, - // Entry 1C0 - 1FF - 0x01bf, 0x0000, 0x01c1, 0x0000, 0x01c3, 0x0000, 0x01c5, 0x0000, - 0x01c7, 0x0000, 0x01c9, 0x01c9, 0x01c9, 0x01c9, 0x0000, 0x01ce, - 0x0000, 0x01d0, 0x01d0, 0x0000, 0x01d3, 0x0000, 0x01d5, 0x0000, - 0x01d7, 0x0000, 0x01d9, 0x0000, 0x01db, 0x0000, 0x01dd, 0x01dd, - 0x0000, 0x01e0, 0x0000, 0x01e2, 0x0000, 0x01e4, 0x0000, 0x01e6, - 0x0000, 0x01e8, 0x0000, 0x01ea, 0x0000, 0x01ec, 0x0000, 0x01ee, - 0x0000, 0x01f0, 0x0000, 0x01f2, 0x01f2, 0x01f2, 0x0000, 0x01f6, - 0x0000, 0x01f8, 0x0000, 0x01fa, 0x0000, 0x01fc, 0x0000, 0x0000, - // Entry 200 - 23F - 0x01ff, 0x0000, 0x0201, 0x0201, 0x0000, 0x0204, 0x0000, 0x0206, - 0x0206, 0x0000, 0x0209, 0x0209, 0x0000, 0x020c, 0x020c, 0x020c, - 0x020c, 0x020c, 0x020c, 0x020c, 0x0000, 0x0214, 0x0000, 0x0216, - 0x0000, 0x0218, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x021e, - 0x0000, 0x0000, 0x0221, 0x0000, 0x0223, 0x0223, 0x0000, 0x0226, - 0x0000, 0x0228, 0x0228, 0x0000, 0x0000, 0x022c, 0x022b, 0x022b, - 0x0000, 0x0000, 0x0231, 0x0000, 0x0233, 0x0000, 0x0235, 0x0000, - 0x0241, 0x0237, 0x0241, 0x0241, 0x0241, 0x0241, 0x0241, 0x0241, - // Entry 240 - 27F - 0x0241, 0x0237, 0x0241, 0x0241, 0x0000, 0x0244, 0x0244, 0x0244, - 0x0000, 0x0248, 0x0000, 0x024a, 0x0000, 0x024c, 0x024c, 0x0000, - 0x024f, 0x0000, 0x0251, 0x0251, 0x0251, 0x0251, 0x0251, 0x0251, - 0x0000, 0x0258, 0x0000, 0x025a, 0x0000, 0x025c, 0x0000, 0x025e, - 0x0000, 0x0260, 0x0000, 0x0262, 0x0000, 0x0000, 0x0265, 0x0265, - 0x0265, 0x0000, 0x0269, 0x0000, 0x026b, 0x0000, 0x026d, 0x0000, - 0x0000, 0x0270, 0x026f, 0x026f, 0x0000, 0x0274, 0x0000, 0x0276, - 0x0000, 0x0278, 0x0000, 0x0000, 0x0000, 0x0000, 0x027d, 0x0000, - // Entry 280 - 2BF - 0x0000, 0x0280, 0x0000, 0x0282, 0x0282, 0x0282, 0x0282, 0x0000, - 0x0287, 0x0287, 0x0287, 0x0000, 0x028b, 0x028b, 0x028b, 0x028b, - 0x028b, 0x0000, 0x0291, 0x0291, 0x0291, 0x0291, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0299, 0x0299, 0x0299, 0x0000, 0x029d, 0x029d, - 0x029d, 0x029d, 0x0000, 0x0000, 0x02a3, 0x02a3, 0x02a3, 0x02a3, - 0x0000, 0x02a8, 0x0000, 0x02aa, 0x02aa, 0x0000, 0x02ad, 0x0000, - 0x02af, 0x0000, 0x02b1, 0x02b1, 0x0000, 0x0000, 0x02b5, 0x0000, - 0x0000, 0x02b8, 0x0000, 0x02ba, 0x02ba, 0x0000, 0x0000, 0x02be, - // Entry 2C0 - 2FF - 0x0000, 0x02c0, 0x0000, 0x02c2, 0x0000, 0x02c4, 0x0000, 0x02c6, - 0x0000, 0x02c8, 0x02c8, 0x0000, 0x0000, 0x02cc, 0x0000, 0x02ce, - 0x02cb, 0x02cb, 0x0000, 0x0000, 0x02d3, 0x02d2, 0x02d2, 0x0000, - 0x0000, 0x02d8, 0x0000, 0x02da, 0x0000, 0x02dc, 0x0000, 0x0000, - 0x02df, 0x0000, 0x02e1, 0x0000, 0x0000, 0x02e4, 0x0000, 0x02e6, - 0x0000, 0x02e8, 0x0000, 0x02ea, 0x02ea, 0x0000, 0x0000, 0x02ee, - 0x02ed, 0x02ed, 0x0000, 0x02f2, 0x0000, 0x02f4, 0x02f4, 0x02f4, - 0x02f4, 0x02f4, 0x0000, 0x02fa, 0x02fb, 0x02fa, 0x0000, 0x02fe, -} // Size: 1560 bytes - -// Total table size 1560 bytes (1KiB); checksum: 4897681C diff --git a/vendor/golang.org/x/text/internal/tag/tag_test.go b/vendor/golang.org/x/text/internal/tag/tag_test.go deleted file mode 100644 index da174a24..00000000 --- a/vendor/golang.org/x/text/internal/tag/tag_test.go +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package tag - -import ( - "strings" - "testing" -) - -var strdata = []string{ - "aa ", - "aaa ", - "aaaa", - "aaab", - "aab ", - "ab ", - "ba ", - "xxxx", - "\xff\xff\xff\xff", -} - -var testCases = map[string]int{ - "a": 0, - "aa": 0, - "aaa": 1, - "aa ": 0, - "aaaa": 2, - "aaab": 3, - "b": 6, - "ba": 6, - " ": -1, - "aaax": -1, - "bbbb": -1, - "zzzz": -1, -} - -func TestIndex(t *testing.T) { - index := Index(strings.Join(strdata, "")) - for k, v := range testCases { - if i := index.Index([]byte(k)); i != v { - t.Errorf("%s: got %d; want %d", k, i, v) - } - } -} - -func TestFixCase(t *testing.T) { - tests := []string{ - "aaaa", "AbCD", "abcd", - "Zzzz", "AbCD", "Abcd", - "Zzzz", "AbC", "", - "XXX", "ab ", "", - "XXX", "usd", "USD", - "cmn", "AB ", "", - "gsw", "CMN", "cmn", - } - for tc := tests; len(tc) > 0; tc = tc[3:] { - b := []byte(tc[1]) - if !FixCase(tc[0], b) { - b = nil - } - if string(b) != tc[2] { - t.Errorf("FixCase(%q, %q) = %q; want %q", tc[0], tc[1], b, tc[2]) - } - } -} diff --git a/vendor/golang.org/x/text/internal/triegen/data_test.go b/vendor/golang.org/x/text/internal/triegen/data_test.go deleted file mode 100644 index 91de547a..00000000 --- a/vendor/golang.org/x/text/internal/triegen/data_test.go +++ /dev/null @@ -1,875 +0,0 @@ -// This file is generated with "go test -tags generate". DO NOT EDIT! -// +build !generate - -package triegen_test - -// lookup returns the trie value for the first UTF-8 encoding in s and -// the width in bytes of this encoding. The size will be 0 if s does not -// hold enough bytes to complete the encoding. len(s) must be greater than 0. -func (t *randTrie) lookup(s []byte) (v uint8, sz int) { - c0 := s[0] - switch { - case c0 < 0x80: // is ASCII - return randValues[c0], 1 - case c0 < 0xC2: - return 0, 1 // Illegal UTF-8: not a starter, not ASCII. - case c0 < 0xE0: // 2-byte UTF-8 - if len(s) < 2 { - return 0, 0 - } - i := randIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c1), 2 - case c0 < 0xF0: // 3-byte UTF-8 - if len(s) < 3 { - return 0, 0 - } - i := randIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = randIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c2), 3 - case c0 < 0xF8: // 4-byte UTF-8 - if len(s) < 4 { - return 0, 0 - } - i := randIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = randIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - o = uint32(i)<<6 + uint32(c2) - i = randIndex[o] - c3 := s[3] - if c3 < 0x80 || 0xC0 <= c3 { - return 0, 3 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c3), 4 - } - // Illegal rune - return 0, 1 -} - -// lookupUnsafe returns the trie value for the first UTF-8 encoding in s. -// s must start with a full and valid UTF-8 encoded rune. -func (t *randTrie) lookupUnsafe(s []byte) uint8 { - c0 := s[0] - if c0 < 0x80 { // is ASCII - return randValues[c0] - } - i := randIndex[c0] - if c0 < 0xE0 { // 2-byte UTF-8 - return t.lookupValue(uint32(i), s[1]) - } - i = randIndex[uint32(i)<<6+uint32(s[1])] - if c0 < 0xF0 { // 3-byte UTF-8 - return t.lookupValue(uint32(i), s[2]) - } - i = randIndex[uint32(i)<<6+uint32(s[2])] - if c0 < 0xF8 { // 4-byte UTF-8 - return t.lookupValue(uint32(i), s[3]) - } - return 0 -} - -// lookupString returns the trie value for the first UTF-8 encoding in s and -// the width in bytes of this encoding. The size will be 0 if s does not -// hold enough bytes to complete the encoding. len(s) must be greater than 0. -func (t *randTrie) lookupString(s string) (v uint8, sz int) { - c0 := s[0] - switch { - case c0 < 0x80: // is ASCII - return randValues[c0], 1 - case c0 < 0xC2: - return 0, 1 // Illegal UTF-8: not a starter, not ASCII. - case c0 < 0xE0: // 2-byte UTF-8 - if len(s) < 2 { - return 0, 0 - } - i := randIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c1), 2 - case c0 < 0xF0: // 3-byte UTF-8 - if len(s) < 3 { - return 0, 0 - } - i := randIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = randIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c2), 3 - case c0 < 0xF8: // 4-byte UTF-8 - if len(s) < 4 { - return 0, 0 - } - i := randIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = randIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - o = uint32(i)<<6 + uint32(c2) - i = randIndex[o] - c3 := s[3] - if c3 < 0x80 || 0xC0 <= c3 { - return 0, 3 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c3), 4 - } - // Illegal rune - return 0, 1 -} - -// lookupStringUnsafe returns the trie value for the first UTF-8 encoding in s. -// s must start with a full and valid UTF-8 encoded rune. -func (t *randTrie) lookupStringUnsafe(s string) uint8 { - c0 := s[0] - if c0 < 0x80 { // is ASCII - return randValues[c0] - } - i := randIndex[c0] - if c0 < 0xE0 { // 2-byte UTF-8 - return t.lookupValue(uint32(i), s[1]) - } - i = randIndex[uint32(i)<<6+uint32(s[1])] - if c0 < 0xF0 { // 3-byte UTF-8 - return t.lookupValue(uint32(i), s[2]) - } - i = randIndex[uint32(i)<<6+uint32(s[2])] - if c0 < 0xF8 { // 4-byte UTF-8 - return t.lookupValue(uint32(i), s[3]) - } - return 0 -} - -// randTrie. Total size: 9280 bytes (9.06 KiB). Checksum: 6debd324a8debb8f. -type randTrie struct{} - -func newRandTrie(i int) *randTrie { - return &randTrie{} -} - -// lookupValue determines the type of block n and looks up the value for b. -func (t *randTrie) lookupValue(n uint32, b byte) uint8 { - switch { - default: - return uint8(randValues[n<<6+uint32(b)]) - } -} - -// randValues: 56 blocks, 3584 entries, 3584 bytes -// The third block is the zero block. -var randValues = [3584]uint8{ - // Block 0x0, offset 0x0 - // Block 0x1, offset 0x40 - // Block 0x2, offset 0x80 - // Block 0x3, offset 0xc0 - 0xc9: 0x0001, - // Block 0x4, offset 0x100 - 0x100: 0x0001, - // Block 0x5, offset 0x140 - 0x155: 0x0001, - // Block 0x6, offset 0x180 - 0x196: 0x0001, - // Block 0x7, offset 0x1c0 - 0x1ef: 0x0001, - // Block 0x8, offset 0x200 - 0x206: 0x0001, - // Block 0x9, offset 0x240 - 0x258: 0x0001, - // Block 0xa, offset 0x280 - 0x288: 0x0001, - // Block 0xb, offset 0x2c0 - 0x2f2: 0x0001, - // Block 0xc, offset 0x300 - 0x304: 0x0001, - // Block 0xd, offset 0x340 - 0x34b: 0x0001, - // Block 0xe, offset 0x380 - 0x3ba: 0x0001, - // Block 0xf, offset 0x3c0 - 0x3f5: 0x0001, - // Block 0x10, offset 0x400 - 0x41d: 0x0001, - // Block 0x11, offset 0x440 - 0x442: 0x0001, - // Block 0x12, offset 0x480 - 0x4bb: 0x0001, - // Block 0x13, offset 0x4c0 - 0x4e9: 0x0001, - // Block 0x14, offset 0x500 - 0x53e: 0x0001, - // Block 0x15, offset 0x540 - 0x55f: 0x0001, - // Block 0x16, offset 0x580 - 0x5b7: 0x0001, - // Block 0x17, offset 0x5c0 - 0x5d9: 0x0001, - // Block 0x18, offset 0x600 - 0x60e: 0x0001, - // Block 0x19, offset 0x640 - 0x652: 0x0001, - // Block 0x1a, offset 0x680 - 0x68f: 0x0001, - // Block 0x1b, offset 0x6c0 - 0x6dc: 0x0001, - // Block 0x1c, offset 0x700 - 0x703: 0x0001, - // Block 0x1d, offset 0x740 - 0x741: 0x0001, - // Block 0x1e, offset 0x780 - 0x79b: 0x0001, - // Block 0x1f, offset 0x7c0 - 0x7f1: 0x0001, - // Block 0x20, offset 0x800 - 0x833: 0x0001, - // Block 0x21, offset 0x840 - 0x853: 0x0001, - // Block 0x22, offset 0x880 - 0x8a2: 0x0001, - // Block 0x23, offset 0x8c0 - 0x8f8: 0x0001, - // Block 0x24, offset 0x900 - 0x917: 0x0001, - // Block 0x25, offset 0x940 - 0x945: 0x0001, - // Block 0x26, offset 0x980 - 0x99e: 0x0001, - // Block 0x27, offset 0x9c0 - 0x9fd: 0x0001, - // Block 0x28, offset 0xa00 - 0xa0d: 0x0001, - // Block 0x29, offset 0xa40 - 0xa66: 0x0001, - // Block 0x2a, offset 0xa80 - 0xaab: 0x0001, - // Block 0x2b, offset 0xac0 - 0xaea: 0x0001, - // Block 0x2c, offset 0xb00 - 0xb2d: 0x0001, - // Block 0x2d, offset 0xb40 - 0xb54: 0x0001, - // Block 0x2e, offset 0xb80 - 0xb90: 0x0001, - // Block 0x2f, offset 0xbc0 - 0xbe5: 0x0001, - // Block 0x30, offset 0xc00 - 0xc28: 0x0001, - // Block 0x31, offset 0xc40 - 0xc7c: 0x0001, - // Block 0x32, offset 0xc80 - 0xcbf: 0x0001, - // Block 0x33, offset 0xcc0 - 0xcc7: 0x0001, - // Block 0x34, offset 0xd00 - 0xd34: 0x0001, - // Block 0x35, offset 0xd40 - 0xd61: 0x0001, - // Block 0x36, offset 0xd80 - 0xdb9: 0x0001, - // Block 0x37, offset 0xdc0 - 0xdda: 0x0001, -} - -// randIndex: 89 blocks, 5696 entries, 5696 bytes -// Block 0 is the zero block. -var randIndex = [5696]uint8{ - // Block 0x0, offset 0x0 - // Block 0x1, offset 0x40 - // Block 0x2, offset 0x80 - // Block 0x3, offset 0xc0 - 0xe1: 0x02, 0xe3: 0x03, 0xe4: 0x04, - 0xea: 0x05, 0xeb: 0x06, 0xec: 0x07, - 0xf0: 0x10, 0xf1: 0x24, 0xf2: 0x3d, 0xf3: 0x4f, 0xf4: 0x56, - // Block 0x4, offset 0x100 - 0x107: 0x01, - // Block 0x5, offset 0x140 - 0x16c: 0x02, - // Block 0x6, offset 0x180 - 0x19c: 0x03, - 0x1ae: 0x04, - // Block 0x7, offset 0x1c0 - 0x1d8: 0x05, - 0x1f7: 0x06, - // Block 0x8, offset 0x200 - 0x20c: 0x07, - // Block 0x9, offset 0x240 - 0x24a: 0x08, - // Block 0xa, offset 0x280 - 0x2b6: 0x09, - // Block 0xb, offset 0x2c0 - 0x2d5: 0x0a, - // Block 0xc, offset 0x300 - 0x31a: 0x0b, - // Block 0xd, offset 0x340 - 0x373: 0x0c, - // Block 0xe, offset 0x380 - 0x38b: 0x0d, - // Block 0xf, offset 0x3c0 - 0x3f0: 0x0e, - // Block 0x10, offset 0x400 - 0x433: 0x0f, - // Block 0x11, offset 0x440 - 0x45d: 0x10, - // Block 0x12, offset 0x480 - 0x491: 0x08, 0x494: 0x09, 0x497: 0x0a, - 0x49b: 0x0b, 0x49c: 0x0c, - 0x4a1: 0x0d, - 0x4ad: 0x0e, - 0x4ba: 0x0f, - // Block 0x13, offset 0x4c0 - 0x4c1: 0x11, - // Block 0x14, offset 0x500 - 0x531: 0x12, - // Block 0x15, offset 0x540 - 0x546: 0x13, - // Block 0x16, offset 0x580 - 0x5ab: 0x14, - // Block 0x17, offset 0x5c0 - 0x5d4: 0x11, - 0x5fe: 0x11, - // Block 0x18, offset 0x600 - 0x618: 0x0a, - // Block 0x19, offset 0x640 - 0x65b: 0x15, - // Block 0x1a, offset 0x680 - 0x6a0: 0x16, - // Block 0x1b, offset 0x6c0 - 0x6d2: 0x17, - 0x6f6: 0x18, - // Block 0x1c, offset 0x700 - 0x711: 0x19, - // Block 0x1d, offset 0x740 - 0x768: 0x1a, - // Block 0x1e, offset 0x780 - 0x783: 0x1b, - // Block 0x1f, offset 0x7c0 - 0x7f9: 0x1c, - // Block 0x20, offset 0x800 - 0x831: 0x1d, - // Block 0x21, offset 0x840 - 0x85e: 0x1e, - // Block 0x22, offset 0x880 - 0x898: 0x1f, - // Block 0x23, offset 0x8c0 - 0x8c7: 0x18, - 0x8d5: 0x14, - 0x8f7: 0x20, - 0x8fe: 0x1f, - // Block 0x24, offset 0x900 - 0x905: 0x21, - // Block 0x25, offset 0x940 - 0x966: 0x03, - // Block 0x26, offset 0x980 - 0x981: 0x07, 0x983: 0x11, - 0x989: 0x12, 0x98a: 0x13, 0x98e: 0x14, 0x98f: 0x15, - 0x992: 0x16, 0x995: 0x17, 0x996: 0x18, - 0x998: 0x19, 0x999: 0x1a, 0x99b: 0x1b, 0x99f: 0x1c, - 0x9a3: 0x1d, - 0x9ad: 0x1e, 0x9af: 0x1f, - 0x9b0: 0x20, 0x9b1: 0x21, - 0x9b8: 0x22, 0x9bd: 0x23, - // Block 0x27, offset 0x9c0 - 0x9cd: 0x22, - // Block 0x28, offset 0xa00 - 0xa0c: 0x08, - // Block 0x29, offset 0xa40 - 0xa6f: 0x1c, - // Block 0x2a, offset 0xa80 - 0xa90: 0x1a, - 0xaaf: 0x23, - // Block 0x2b, offset 0xac0 - 0xae3: 0x19, - 0xae8: 0x24, - 0xafc: 0x25, - // Block 0x2c, offset 0xb00 - 0xb13: 0x26, - // Block 0x2d, offset 0xb40 - 0xb67: 0x1c, - // Block 0x2e, offset 0xb80 - 0xb8f: 0x0b, - // Block 0x2f, offset 0xbc0 - 0xbcb: 0x27, - 0xbe7: 0x26, - // Block 0x30, offset 0xc00 - 0xc34: 0x16, - // Block 0x31, offset 0xc40 - 0xc62: 0x03, - // Block 0x32, offset 0xc80 - 0xcbb: 0x12, - // Block 0x33, offset 0xcc0 - 0xcdf: 0x09, - // Block 0x34, offset 0xd00 - 0xd34: 0x0a, - // Block 0x35, offset 0xd40 - 0xd41: 0x1e, - // Block 0x36, offset 0xd80 - 0xd83: 0x28, - // Block 0x37, offset 0xdc0 - 0xdc0: 0x15, - // Block 0x38, offset 0xe00 - 0xe1a: 0x15, - // Block 0x39, offset 0xe40 - 0xe65: 0x29, - // Block 0x3a, offset 0xe80 - 0xe86: 0x1f, - // Block 0x3b, offset 0xec0 - 0xeec: 0x18, - // Block 0x3c, offset 0xf00 - 0xf28: 0x2a, - // Block 0x3d, offset 0xf40 - 0xf53: 0x08, - // Block 0x3e, offset 0xf80 - 0xfa2: 0x2b, - 0xfaa: 0x17, - // Block 0x3f, offset 0xfc0 - 0xfc0: 0x25, 0xfc2: 0x26, - 0xfc9: 0x27, 0xfcd: 0x28, 0xfce: 0x29, - 0xfd5: 0x2a, - 0xfd8: 0x2b, 0xfd9: 0x2c, 0xfdf: 0x2d, - 0xfe1: 0x2e, 0xfe2: 0x2f, 0xfe3: 0x30, 0xfe6: 0x31, - 0xfe9: 0x32, 0xfec: 0x33, 0xfed: 0x34, 0xfef: 0x35, - 0xff1: 0x36, 0xff2: 0x37, 0xff3: 0x38, 0xff4: 0x39, - 0xffa: 0x3a, 0xffc: 0x3b, 0xffe: 0x3c, - // Block 0x40, offset 0x1000 - 0x102c: 0x2c, - // Block 0x41, offset 0x1040 - 0x1074: 0x2c, - // Block 0x42, offset 0x1080 - 0x108c: 0x08, - 0x10a0: 0x2d, - // Block 0x43, offset 0x10c0 - 0x10e8: 0x10, - // Block 0x44, offset 0x1100 - 0x110f: 0x13, - // Block 0x45, offset 0x1140 - 0x114b: 0x2e, - // Block 0x46, offset 0x1180 - 0x118b: 0x23, - 0x119d: 0x0c, - // Block 0x47, offset 0x11c0 - 0x11c3: 0x12, - 0x11f9: 0x0f, - // Block 0x48, offset 0x1200 - 0x121e: 0x1b, - // Block 0x49, offset 0x1240 - 0x1270: 0x2f, - // Block 0x4a, offset 0x1280 - 0x128a: 0x1b, - 0x12a7: 0x02, - // Block 0x4b, offset 0x12c0 - 0x12fb: 0x14, - // Block 0x4c, offset 0x1300 - 0x1333: 0x30, - // Block 0x4d, offset 0x1340 - 0x134d: 0x31, - // Block 0x4e, offset 0x1380 - 0x138e: 0x15, - // Block 0x4f, offset 0x13c0 - 0x13f4: 0x32, - // Block 0x50, offset 0x1400 - 0x141b: 0x33, - // Block 0x51, offset 0x1440 - 0x1448: 0x3e, 0x1449: 0x3f, 0x144a: 0x40, 0x144f: 0x41, - 0x1459: 0x42, 0x145c: 0x43, 0x145e: 0x44, 0x145f: 0x45, - 0x1468: 0x46, 0x1469: 0x47, 0x146c: 0x48, 0x146d: 0x49, 0x146e: 0x4a, - 0x1472: 0x4b, 0x1473: 0x4c, - 0x1479: 0x4d, 0x147b: 0x4e, - // Block 0x52, offset 0x1480 - 0x1480: 0x34, - 0x1499: 0x11, - 0x14b6: 0x2c, - // Block 0x53, offset 0x14c0 - 0x14e4: 0x0d, - // Block 0x54, offset 0x1500 - 0x1527: 0x08, - // Block 0x55, offset 0x1540 - 0x1555: 0x2b, - // Block 0x56, offset 0x1580 - 0x15b2: 0x35, - // Block 0x57, offset 0x15c0 - 0x15f2: 0x1c, 0x15f4: 0x29, - // Block 0x58, offset 0x1600 - 0x1600: 0x50, 0x1603: 0x51, - 0x1608: 0x52, 0x160a: 0x53, 0x160d: 0x54, 0x160e: 0x55, -} - -// lookup returns the trie value for the first UTF-8 encoding in s and -// the width in bytes of this encoding. The size will be 0 if s does not -// hold enough bytes to complete the encoding. len(s) must be greater than 0. -func (t *multiTrie) lookup(s []byte) (v uint64, sz int) { - c0 := s[0] - switch { - case c0 < 0x80: // is ASCII - return t.ascii[c0], 1 - case c0 < 0xC2: - return 0, 1 // Illegal UTF-8: not a starter, not ASCII. - case c0 < 0xE0: // 2-byte UTF-8 - if len(s) < 2 { - return 0, 0 - } - i := t.utf8Start[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c1), 2 - case c0 < 0xF0: // 3-byte UTF-8 - if len(s) < 3 { - return 0, 0 - } - i := t.utf8Start[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = multiIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c2), 3 - case c0 < 0xF8: // 4-byte UTF-8 - if len(s) < 4 { - return 0, 0 - } - i := t.utf8Start[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = multiIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - o = uint32(i)<<6 + uint32(c2) - i = multiIndex[o] - c3 := s[3] - if c3 < 0x80 || 0xC0 <= c3 { - return 0, 3 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c3), 4 - } - // Illegal rune - return 0, 1 -} - -// lookupUnsafe returns the trie value for the first UTF-8 encoding in s. -// s must start with a full and valid UTF-8 encoded rune. -func (t *multiTrie) lookupUnsafe(s []byte) uint64 { - c0 := s[0] - if c0 < 0x80 { // is ASCII - return t.ascii[c0] - } - i := t.utf8Start[c0] - if c0 < 0xE0 { // 2-byte UTF-8 - return t.lookupValue(uint32(i), s[1]) - } - i = multiIndex[uint32(i)<<6+uint32(s[1])] - if c0 < 0xF0 { // 3-byte UTF-8 - return t.lookupValue(uint32(i), s[2]) - } - i = multiIndex[uint32(i)<<6+uint32(s[2])] - if c0 < 0xF8 { // 4-byte UTF-8 - return t.lookupValue(uint32(i), s[3]) - } - return 0 -} - -// lookupString returns the trie value for the first UTF-8 encoding in s and -// the width in bytes of this encoding. The size will be 0 if s does not -// hold enough bytes to complete the encoding. len(s) must be greater than 0. -func (t *multiTrie) lookupString(s string) (v uint64, sz int) { - c0 := s[0] - switch { - case c0 < 0x80: // is ASCII - return t.ascii[c0], 1 - case c0 < 0xC2: - return 0, 1 // Illegal UTF-8: not a starter, not ASCII. - case c0 < 0xE0: // 2-byte UTF-8 - if len(s) < 2 { - return 0, 0 - } - i := t.utf8Start[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c1), 2 - case c0 < 0xF0: // 3-byte UTF-8 - if len(s) < 3 { - return 0, 0 - } - i := t.utf8Start[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = multiIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c2), 3 - case c0 < 0xF8: // 4-byte UTF-8 - if len(s) < 4 { - return 0, 0 - } - i := t.utf8Start[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = multiIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - o = uint32(i)<<6 + uint32(c2) - i = multiIndex[o] - c3 := s[3] - if c3 < 0x80 || 0xC0 <= c3 { - return 0, 3 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c3), 4 - } - // Illegal rune - return 0, 1 -} - -// lookupStringUnsafe returns the trie value for the first UTF-8 encoding in s. -// s must start with a full and valid UTF-8 encoded rune. -func (t *multiTrie) lookupStringUnsafe(s string) uint64 { - c0 := s[0] - if c0 < 0x80 { // is ASCII - return t.ascii[c0] - } - i := t.utf8Start[c0] - if c0 < 0xE0 { // 2-byte UTF-8 - return t.lookupValue(uint32(i), s[1]) - } - i = multiIndex[uint32(i)<<6+uint32(s[1])] - if c0 < 0xF0 { // 3-byte UTF-8 - return t.lookupValue(uint32(i), s[2]) - } - i = multiIndex[uint32(i)<<6+uint32(s[2])] - if c0 < 0xF8 { // 4-byte UTF-8 - return t.lookupValue(uint32(i), s[3]) - } - return 0 -} - -// multiTrie. Total size: 18250 bytes (17.82 KiB). Checksum: a69a609d8696aa5e. -type multiTrie struct { - ascii []uint64 // index for ASCII bytes - utf8Start []uint8 // index for UTF-8 bytes >= 0xC0 -} - -func newMultiTrie(i int) *multiTrie { - h := multiTrieHandles[i] - return &multiTrie{multiValues[uint32(h.ascii)<<6:], multiIndex[uint32(h.multi)<<6:]} -} - -type multiTrieHandle struct { - ascii, multi uint8 -} - -// multiTrieHandles: 5 handles, 10 bytes -var multiTrieHandles = [5]multiTrieHandle{ - {0, 0}, // 8c1e77823143d35c: all - {0, 23}, // 8fb58ff8243b45b0: ASCII only - {0, 23}, // 8fb58ff8243b45b0: ASCII only 2 - {0, 24}, // 2ccc43994f11046f: BMP only - {30, 25}, // ce448591bdcb4733: No BMP -} - -// lookupValue determines the type of block n and looks up the value for b. -func (t *multiTrie) lookupValue(n uint32, b byte) uint64 { - switch { - default: - return uint64(multiValues[n<<6+uint32(b)]) - } -} - -// multiValues: 32 blocks, 2048 entries, 16384 bytes -// The third block is the zero block. -var multiValues = [2048]uint64{ - // Block 0x0, offset 0x0 - 0x03: 0x6e361699800b9fb8, 0x04: 0x52d3935a34f6f0b, 0x05: 0x2948319393e7ef10, - 0x07: 0x20f03b006704f663, 0x08: 0x6c15c0732bb2495f, 0x09: 0xe54e2c59d953551, - 0x0f: 0x33d8a825807d8037, 0x10: 0x6ecd93cb12168b92, 0x11: 0x6a81c9c0ce86e884, - 0x1f: 0xa03e77aac8be79b, 0x20: 0x28591d0e7e486efa, 0x21: 0x716fa3bc398dec8, - 0x3f: 0x4fd3bcfa72bce8b0, - // Block 0x1, offset 0x40 - 0x40: 0x3cbaef3db8ba5f12, 0x41: 0x2d262347c1f56357, - 0x7f: 0x782caa2d25a418a9, - // Block 0x2, offset 0x80 - // Block 0x3, offset 0xc0 - 0xc0: 0x6bbd1f937b1ff5d2, 0xc1: 0x732e23088d2eb8a4, - // Block 0x4, offset 0x100 - 0x13f: 0x56f8c4c82f5962dc, - // Block 0x5, offset 0x140 - 0x140: 0x57dc4544729a5da2, 0x141: 0x2f62f9cd307ffa0d, - // Block 0x6, offset 0x180 - 0x1bf: 0x7bf4d0ebf302a088, - // Block 0x7, offset 0x1c0 - 0x1c0: 0x1f0d67f249e59931, 0x1c1: 0x3011def73aa550c7, - // Block 0x8, offset 0x200 - 0x23f: 0x5de81c1dff6bf29d, - // Block 0x9, offset 0x240 - 0x240: 0x752c035737b825e8, 0x241: 0x1e793399081e3bb3, - // Block 0xa, offset 0x280 - 0x2bf: 0x6a28f01979cbf059, - // Block 0xb, offset 0x2c0 - 0x2c0: 0x373a4b0f2cbd4c74, 0x2c1: 0x4fd2c288683b767c, - // Block 0xc, offset 0x300 - 0x33f: 0x5a10ffa9e29184fb, - // Block 0xd, offset 0x340 - 0x340: 0x700f9bdb53fff6a5, 0x341: 0xcde93df0427eb79, - // Block 0xe, offset 0x380 - 0x3bf: 0x74071288fff39c76, - // Block 0xf, offset 0x3c0 - 0x3c0: 0x481fc2f510e5268a, 0x3c1: 0x7565c28164204849, - // Block 0x10, offset 0x400 - 0x43f: 0x5676a62fd49c6bec, - // Block 0x11, offset 0x440 - 0x440: 0x2f2d15776cbafc6b, 0x441: 0x4c55e8dc0ff11a3f, - // Block 0x12, offset 0x480 - 0x4bf: 0x69d6f0fe711fafc9, - // Block 0x13, offset 0x4c0 - 0x4c0: 0x33181de28cfb062d, 0x4c1: 0x2ef3adc6bb2f2d02, - // Block 0x14, offset 0x500 - 0x53f: 0xe03b31814c95f8b, - // Block 0x15, offset 0x540 - 0x540: 0x3bf6dc9a1c115603, 0x541: 0x6984ec9b7f51f7fc, - // Block 0x16, offset 0x580 - 0x5bf: 0x3c02ea92fb168559, - // Block 0x17, offset 0x5c0 - 0x5c0: 0x1badfe42e7629494, 0x5c1: 0x6dc4a554005f7645, - // Block 0x18, offset 0x600 - 0x63f: 0x3bb2ed2a72748f4b, - // Block 0x19, offset 0x640 - 0x640: 0x291354cd6767ec10, 0x641: 0x2c3a4715e3c070d6, - // Block 0x1a, offset 0x680 - 0x6bf: 0x352711cfb7236418, - // Block 0x1b, offset 0x6c0 - 0x6c0: 0x3a59d34fb8bceda, 0x6c1: 0x5e90d8ebedd64fa1, - // Block 0x1c, offset 0x700 - 0x73f: 0x7191a77b28d23110, - // Block 0x1d, offset 0x740 - 0x740: 0x4ca7f0c1623423d8, 0x741: 0x4f7156d996e2d0de, - // Block 0x1e, offset 0x780 - // Block 0x1f, offset 0x7c0 -} - -// multiIndex: 29 blocks, 1856 entries, 1856 bytes -// Block 0 is the zero block. -var multiIndex = [1856]uint8{ - // Block 0x0, offset 0x0 - // Block 0x1, offset 0x40 - // Block 0x2, offset 0x80 - // Block 0x3, offset 0xc0 - 0xc2: 0x01, 0xc3: 0x02, 0xc4: 0x03, 0xc7: 0x04, - 0xc8: 0x05, 0xcf: 0x06, - 0xd0: 0x07, - 0xdf: 0x08, - 0xe0: 0x02, 0xe1: 0x03, 0xe2: 0x04, 0xe3: 0x05, 0xe4: 0x06, 0xe7: 0x07, - 0xe8: 0x08, 0xef: 0x09, - 0xf0: 0x0e, 0xf1: 0x11, 0xf2: 0x13, 0xf3: 0x15, 0xf4: 0x17, - // Block 0x4, offset 0x100 - 0x120: 0x09, - 0x13f: 0x0a, - // Block 0x5, offset 0x140 - 0x140: 0x0b, - 0x17f: 0x0c, - // Block 0x6, offset 0x180 - 0x180: 0x0d, - // Block 0x7, offset 0x1c0 - 0x1ff: 0x0e, - // Block 0x8, offset 0x200 - 0x200: 0x0f, - // Block 0x9, offset 0x240 - 0x27f: 0x10, - // Block 0xa, offset 0x280 - 0x280: 0x11, - // Block 0xb, offset 0x2c0 - 0x2ff: 0x12, - // Block 0xc, offset 0x300 - 0x300: 0x13, - // Block 0xd, offset 0x340 - 0x37f: 0x14, - // Block 0xe, offset 0x380 - 0x380: 0x15, - // Block 0xf, offset 0x3c0 - 0x3ff: 0x16, - // Block 0x10, offset 0x400 - 0x410: 0x0a, - 0x41f: 0x0b, - 0x420: 0x0c, - 0x43f: 0x0d, - // Block 0x11, offset 0x440 - 0x440: 0x17, - // Block 0x12, offset 0x480 - 0x4bf: 0x18, - // Block 0x13, offset 0x4c0 - 0x4c0: 0x0f, - 0x4ff: 0x10, - // Block 0x14, offset 0x500 - 0x500: 0x19, - // Block 0x15, offset 0x540 - 0x540: 0x12, - // Block 0x16, offset 0x580 - 0x5bf: 0x1a, - // Block 0x17, offset 0x5c0 - 0x5ff: 0x14, - // Block 0x18, offset 0x600 - 0x600: 0x1b, - // Block 0x19, offset 0x640 - 0x640: 0x16, - // Block 0x1a, offset 0x680 - // Block 0x1b, offset 0x6c0 - 0x6c2: 0x01, 0x6c3: 0x02, 0x6c4: 0x03, 0x6c7: 0x04, - 0x6c8: 0x05, 0x6cf: 0x06, - 0x6d0: 0x07, - 0x6df: 0x08, - 0x6e0: 0x02, 0x6e1: 0x03, 0x6e2: 0x04, 0x6e3: 0x05, 0x6e4: 0x06, 0x6e7: 0x07, - 0x6e8: 0x08, 0x6ef: 0x09, - // Block 0x1c, offset 0x700 - 0x730: 0x0e, 0x731: 0x11, 0x732: 0x13, 0x733: 0x15, 0x734: 0x17, -} diff --git a/vendor/golang.org/x/text/internal/triegen/example_compact_test.go b/vendor/golang.org/x/text/internal/triegen/example_compact_test.go deleted file mode 100644 index 7cf604ca..00000000 --- a/vendor/golang.org/x/text/internal/triegen/example_compact_test.go +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package triegen_test - -import ( - "fmt" - "io" - "io/ioutil" - - "golang.org/x/text/internal/triegen" -) - -func ExampleCompacter() { - t := triegen.NewTrie("root") - for r := rune(0); r < 10000; r += 64 { - t.Insert(r, 0x9015BADA55^uint64(r)) - } - sz, _ := t.Gen(ioutil.Discard) - - fmt.Printf("Size normal: %5d\n", sz) - - var c myCompacter - sz, _ = t.Gen(ioutil.Discard, triegen.Compact(&c)) - - fmt.Printf("Size compacted: %5d\n", sz) - - // Output: - // Size normal: 81344 - // Size compacted: 3224 -} - -// A myCompacter accepts a block if only the first value is given. -type myCompacter []uint64 - -func (c *myCompacter) Size(values []uint64) (sz int, ok bool) { - for _, v := range values[1:] { - if v != 0 { - return 0, false - } - } - return 8, true // the size of a uint64 -} - -func (c *myCompacter) Store(v []uint64) uint32 { - x := uint32(len(*c)) - *c = append(*c, v[0]) - return x -} - -func (c *myCompacter) Print(w io.Writer) error { - fmt.Fprintln(w, "var firstValue = []uint64{") - for _, v := range *c { - fmt.Fprintf(w, "\t%#x,\n", v) - } - fmt.Fprintln(w, "}") - return nil -} - -func (c *myCompacter) Handler() string { - return "getFirstValue" - - // Where getFirstValue is included along with the generated code: - // func getFirstValue(n uint32, b byte) uint64 { - // if b == 0x80 { // the first continuation byte - // return firstValue[n] - // } - // return 0 - // } -} diff --git a/vendor/golang.org/x/text/internal/triegen/example_test.go b/vendor/golang.org/x/text/internal/triegen/example_test.go deleted file mode 100644 index 557a152e..00000000 --- a/vendor/golang.org/x/text/internal/triegen/example_test.go +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package triegen_test - -import ( - "fmt" - "io/ioutil" - "math/rand" - "unicode" - - "golang.org/x/text/internal/triegen" -) - -const seed = 0x12345 - -var genWriter = ioutil.Discard - -func randomRunes() map[rune]uint8 { - rnd := rand.New(rand.NewSource(seed)) - m := map[rune]uint8{} - for len(m) < 100 { - // Only set our random rune if it is a valid Unicode code point. - if r := rune(rnd.Int31n(unicode.MaxRune + 1)); []rune(string(r))[0] == r { - m[r] = 1 - } - } - return m -} - -// Example_build shows how to build a simple trie. It assigns the value 1 to -// 100 random runes generated by randomRunes. -func Example_build() { - t := triegen.NewTrie("rand") - - for r, _ := range randomRunes() { - t.Insert(r, 1) - } - sz, err := t.Gen(genWriter) - - fmt.Printf("Trie size: %d bytes\n", sz) - fmt.Printf("Error: %v\n", err) - - // Output: - // Trie size: 9280 bytes - // Error: -} - -// Example_lookup demonstrates how to use the trie generated by Example_build. -func Example_lookup() { - trie := newRandTrie(0) - - // The same set of runes used by Example_build. - runes := randomRunes() - - // Verify the right value is returned for all runes. - for r := rune(0); r <= unicode.MaxRune; r++ { - // Note that the return type of lookup is uint8. - if v, _ := trie.lookupString(string(r)); v != runes[r] { - fmt.Println("FAILURE") - return - } - } - fmt.Println("SUCCESS") - - // Output: - // SUCCESS -} - -// runeValues generates some random values for a set of interesting runes. -func runeValues() map[rune]uint64 { - rnd := rand.New(rand.NewSource(seed)) - m := map[rune]uint64{} - for p := 4; p <= unicode.MaxRune; p <<= 1 { - for d := -1; d <= 1; d++ { - m[rune(p+d)] = uint64(rnd.Int63()) - } - } - return m -} - -// ExampleGen_build demonstrates the creation of multiple tries sharing common -// blocks. ExampleGen_lookup demonstrates how to use the generated tries. -func ExampleGen_build() { - var tries []*triegen.Trie - - rv := runeValues() - for _, c := range []struct { - include func(rune) bool - name string - }{ - {func(r rune) bool { return true }, "all"}, - {func(r rune) bool { return r < 0x80 }, "ASCII only"}, - {func(r rune) bool { return r < 0x80 }, "ASCII only 2"}, - {func(r rune) bool { return r <= 0xFFFF }, "BMP only"}, - {func(r rune) bool { return r > 0xFFFF }, "No BMP"}, - } { - t := triegen.NewTrie(c.name) - tries = append(tries, t) - - for r, v := range rv { - if c.include(r) { - t.Insert(r, v) - } - } - } - sz, err := triegen.Gen(genWriter, "multi", tries) - - fmt.Printf("Trie size: %d bytes\n", sz) - fmt.Printf("Error: %v\n", err) - - // Output: - // Trie size: 18250 bytes - // Error: -} - -// ExampleGen_lookup shows how to look up values in the trie generated by -// ExampleGen_build. -func ExampleGen_lookup() { - rv := runeValues() - for i, include := range []func(rune) bool{ - func(r rune) bool { return true }, // all - func(r rune) bool { return r < 0x80 }, // ASCII only - func(r rune) bool { return r < 0x80 }, // ASCII only 2 - func(r rune) bool { return r <= 0xFFFF }, // BMP only - func(r rune) bool { return r > 0xFFFF }, // No BMP - } { - t := newMultiTrie(i) - - for r := rune(0); r <= unicode.MaxRune; r++ { - x := uint64(0) - if include(r) { - x = rv[r] - } - // As we convert from a valid rune, we know it is safe to use - // lookupStringUnsafe. - if v := t.lookupStringUnsafe(string(r)); x != v { - fmt.Println("FAILURE") - return - } - } - } - fmt.Println("SUCCESS") - - // Output: - // SUCCESS -} diff --git a/vendor/golang.org/x/text/internal/triegen/gen_test.go b/vendor/golang.org/x/text/internal/triegen/gen_test.go deleted file mode 100644 index 831627d7..00000000 --- a/vendor/golang.org/x/text/internal/triegen/gen_test.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build generate - -package triegen_test - -// The code in this file generates captures and writes the tries generated in -// the examples to data_test.go. To invoke it, run: -// go test -tags=generate -// -// Making the generation code a "test" allows us to link in the necessary test -// code. - -import ( - "log" - "os" - "os/exec" -) - -func init() { - const tmpfile = "tmpout" - const dstfile = "data_test.go" - - f, err := os.Create(tmpfile) - if err != nil { - log.Fatalf("Could not create output file: %v", err) - } - defer os.Remove(tmpfile) - defer f.Close() - - // We exit before this function returns, regardless of success or failure, - // so there's no need to save (and later restore) the existing genWriter - // value. - genWriter = f - - f.Write([]byte(header)) - - Example_build() - ExampleGen_build() - - if err := exec.Command("gofmt", "-w", tmpfile).Run(); err != nil { - log.Fatal(err) - } - os.Remove(dstfile) - os.Rename(tmpfile, dstfile) - - os.Exit(0) -} - -const header = `// This file is generated with "go test -tags generate". DO NOT EDIT! -// +build !generate - -package triegen_test -` - -// Stubs for generated tries. These are needed as we exclude data_test.go if -// the generate flag is set. This will clearly make the tests fail, but that -// is okay. It allows us to bootstrap. - -type trie struct{} - -func (t *trie) lookupString(string) (uint8, int) { return 0, 1 } -func (t *trie) lookupStringUnsafe(string) uint64 { return 0 } - -func newRandTrie(i int) *trie { return &trie{} } -func newMultiTrie(i int) *trie { return &trie{} } diff --git a/vendor/golang.org/x/text/internal/ucd/example_test.go b/vendor/golang.org/x/text/internal/ucd/example_test.go deleted file mode 100644 index 338a50d1..00000000 --- a/vendor/golang.org/x/text/internal/ucd/example_test.go +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ucd_test - -import ( - "fmt" - "strings" - - "golang.org/x/text/internal/ucd" -) - -func Example() { - // Read rune-by-rune from UnicodeData. - var count int - p := ucd.New(strings.NewReader(unicodeData)) - for p.Next() { - count++ - if lower := p.Runes(ucd.SimpleLowercaseMapping); lower != nil { - fmt.Printf("lower(%U) -> %U\n", p.Rune(0), lower[0]) - } - } - if err := p.Err(); err != nil { - fmt.Println(err) - } - fmt.Println("Number of runes visited:", count) - - // Read raw ranges from Scripts. - p = ucd.New(strings.NewReader(scripts), ucd.KeepRanges) - for p.Next() { - start, end := p.Range(0) - fmt.Printf("%04X..%04X: %s\n", start, end, p.String(1)) - } - if err := p.Err(); err != nil { - fmt.Println(err) - } - - // Output: - // lower(U+00C0) -> U+00E0 - // lower(U+00C1) -> U+00E1 - // lower(U+00C2) -> U+00E2 - // lower(U+00C3) -> U+00E3 - // lower(U+00C4) -> U+00E4 - // Number of runes visited: 6594 - // 0000..001F: Common - // 0020..0020: Common - // 0021..0023: Common - // 0024..0024: Common -} - -// Excerpt from UnicodeData.txt -const unicodeData = ` -00B9;SUPERSCRIPT ONE;No;0;EN; 0031;;1;1;N;SUPERSCRIPT DIGIT ONE;;;; -00BA;MASCULINE ORDINAL INDICATOR;Lo;0;L; 006F;;;;N;;;;; -00BB;RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK;Pf;0;ON;;;;;Y;RIGHT POINTING GUILLEMET;;;; -00BC;VULGAR FRACTION ONE QUARTER;No;0;ON; 0031 2044 0034;;;1/4;N;FRACTION ONE QUARTER;;;; -00BD;VULGAR FRACTION ONE HALF;No;0;ON; 0031 2044 0032;;;1/2;N;FRACTION ONE HALF;;;; -00BE;VULGAR FRACTION THREE QUARTERS;No;0;ON; 0033 2044 0034;;;3/4;N;FRACTION THREE QUARTERS;;;; -00BF;INVERTED QUESTION MARK;Po;0;ON;;;;;N;;;;; -00C0;LATIN CAPITAL LETTER A WITH GRAVE;Lu;0;L;0041 0300;;;;N;LATIN CAPITAL LETTER A GRAVE;;;00E0; -00C1;LATIN CAPITAL LETTER A WITH ACUTE;Lu;0;L;0041 0301;;;;N;LATIN CAPITAL LETTER A ACUTE;;;00E1; -00C2;LATIN CAPITAL LETTER A WITH CIRCUMFLEX;Lu;0;L;0041 0302;;;;N;LATIN CAPITAL LETTER A CIRCUMFLEX;;;00E2; -00C3;LATIN CAPITAL LETTER A WITH TILDE;Lu;0;L;0041 0303;;;;N;LATIN CAPITAL LETTER A TILDE;;;00E3; -00C4;LATIN CAPITAL LETTER A WITH DIAERESIS;Lu;0;L;0041 0308;;;;N;LATIN CAPITAL LETTER A DIAERESIS;;;00E4; - -# A legacy rune range. -3400;;Lo;0;L;;;;;N;;;;; -4DB5;;Lo;0;L;;;;;N;;;;; -` - -// Excerpt from Scripts.txt -const scripts = ` -# Property: Script -# ================================================ - -0000..001F ; Common # Cc [32] .. -0020 ; Common # Zs SPACE -0021..0023 ; Common # Po [3] EXCLAMATION MARK..NUMBER SIGN -0024 ; Common # Sc DOLLAR SIGN -` diff --git a/vendor/golang.org/x/text/internal/ucd/ucd_test.go b/vendor/golang.org/x/text/internal/ucd/ucd_test.go deleted file mode 100644 index 11a6542e..00000000 --- a/vendor/golang.org/x/text/internal/ucd/ucd_test.go +++ /dev/null @@ -1,105 +0,0 @@ -package ucd - -import ( - "strings" - "testing" -) - -const file = ` -# Comments should be skipped -# rune; bool; uint; int; float; runes; # Y -0..0005; Y; 0; 2; -5.25 ; 0 1 2 3 4 5; -6..0007; Yes ; 6; 1; -4.25 ; 0006 0007; -8; T ; 8 ; 0 ;-3.25 ;;# T -9; True ;9 ; -1;-2.25 ; 0009; - -# more comments to be ignored -@Part0 - -A; N; 10 ; -2; -1.25; ;# N -B; No; 11 ; -3; -0.25; -C; False;12; -4; 0.75; -D; ;13;-5;1.75; - -@Part1 # Another part. -# We test part comments get removed by not commenting the the next line. -E..10FFFF; F; 14 ; -6; 2.75; -` - -var want = []struct { - start, end rune -}{ - {0x00, 0x05}, - {0x06, 0x07}, - {0x08, 0x08}, - {0x09, 0x09}, - {0x0A, 0x0A}, - {0x0B, 0x0B}, - {0x0C, 0x0C}, - {0x0D, 0x0D}, - {0x0E, 0x10FFFF}, -} - -func TestGetters(t *testing.T) { - parts := [][2]string{ - {"Part0", ""}, - {"Part1", "Another part."}, - } - handler := func(p *Parser) { - if len(parts) == 0 { - t.Error("Part handler invoked too many times.") - return - } - want := parts[0] - parts = parts[1:] - if got0, got1 := p.String(0), p.Comment(); got0 != want[0] || got1 != want[1] { - t.Errorf(`part: got %q, %q; want %q"`, got0, got1, want) - } - } - - p := New(strings.NewReader(file), KeepRanges, Part(handler)) - for i := 0; p.Next(); i++ { - start, end := p.Range(0) - w := want[i] - if start != w.start || end != w.end { - t.Fatalf("%d:Range(0); got %#x..%#x; want %#x..%#x", i, start, end, w.start, w.end) - } - if w.start == w.end && p.Rune(0) != w.start { - t.Errorf("%d:Range(0).start: got %U; want %U", i, p.Rune(0), w.start) - } - if got, want := p.Bool(1), w.start <= 9; got != want { - t.Errorf("%d:Bool(1): got %v; want %v", i, got, want) - } - if got := p.Rune(4); got != 0 || p.Err() == nil { - t.Errorf("%d:Rune(%q): got no error; want error", i, p.String(1)) - } - p.err = nil - if got := p.Uint(2); rune(got) != start { - t.Errorf("%d:Uint(2): got %v; want %v", i, got, start) - } - if got, want := p.Int(3), 2-i; got != want { - t.Errorf("%d:Int(3): got %v; want %v", i, got, want) - } - if got, want := p.Float(4), -5.25+float64(i); got != want { - t.Errorf("%d:Int(3): got %v; want %v", i, got, want) - } - if got := p.Runes(5); got == nil { - if p.String(5) != "" { - t.Errorf("%d:Runes(5): expected non-empty list", i) - } - } else { - if got[0] != start || got[len(got)-1] != end { - t.Errorf("%d:Runes(5): got %#x; want %#x..%#x", i, got, start, end) - } - } - if got := p.Comment(); got != "" && got != p.String(1) { - t.Errorf("%d:Comment(): got %v; want %v", i, got, p.String(1)) - } - } - if err := p.Err(); err != nil { - t.Errorf("Parser error: %v", err) - } - if len(parts) != 0 { - t.Errorf("expected %d more invocations of part handler", len(parts)) - } -} diff --git a/vendor/golang.org/x/text/language/Makefile b/vendor/golang.org/x/text/language/Makefile deleted file mode 100644 index 79f00578..00000000 --- a/vendor/golang.org/x/text/language/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright 2013 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -CLEANFILES+=maketables - -maketables: maketables.go - go build $^ - -tables: maketables - ./maketables > tables.go - gofmt -w -s tables.go - -# Build (but do not run) maketables during testing, -# just to make sure it still compiles. -testshort: maketables diff --git a/vendor/golang.org/x/text/language/coverage_test.go b/vendor/golang.org/x/text/language/coverage_test.go deleted file mode 100644 index 8e08e5ca..00000000 --- a/vendor/golang.org/x/text/language/coverage_test.go +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package language - -import ( - "fmt" - "reflect" - "testing" -) - -func TestSupported(t *testing.T) { - // To prove the results are correct for a type, we test that the number of - // results is identical to the number of results on record, that all results - // are distinct and that all results are valid. - tests := map[string]int{ - "BaseLanguages": numLanguages, - "Scripts": numScripts, - "Regions": numRegions, - "Tags": 0, - } - sup := reflect.ValueOf(Supported) - for name, num := range tests { - v := sup.MethodByName(name).Call(nil)[0] - if n := v.Len(); n != num { - t.Errorf("len(%s()) was %d; want %d", name, n, num) - } - dup := make(map[string]bool) - for i := 0; i < v.Len(); i++ { - x := v.Index(i).Interface() - // An invalid value will either cause a crash or result in a - // duplicate when passed to Sprint. - s := fmt.Sprint(x) - if dup[s] { - t.Errorf("%s: duplicate entry %q", name, s) - } - dup[s] = true - } - if len(dup) != v.Len() { - t.Errorf("%s: # unique entries was %d; want %d", name, len(dup), v.Len()) - } - } -} - -func TestNewCoverage(t *testing.T) { - bases := []Base{Base{0}, Base{3}, Base{7}} - scripts := []Script{Script{11}, Script{17}, Script{23}} - regions := []Region{Region{101}, Region{103}, Region{107}} - tags := []Tag{Make("pt"), Make("en"), Make("en-GB"), Make("en-US"), Make("pt-PT")} - fbases := func() []Base { return bases } - fscripts := func() []Script { return scripts } - fregions := func() []Region { return regions } - ftags := func() []Tag { return tags } - - tests := []struct { - desc string - list []interface{} - bases []Base - scripts []Script - regions []Region - tags []Tag - }{ - { - desc: "empty", - }, - { - desc: "bases", - list: []interface{}{bases}, - bases: bases, - }, - { - desc: "scripts", - list: []interface{}{scripts}, - scripts: scripts, - }, - { - desc: "regions", - list: []interface{}{regions}, - regions: regions, - }, - { - desc: "bases derives from tags", - list: []interface{}{tags}, - bases: []Base{Base{_en}, Base{_pt}}, - tags: tags, - }, - { - desc: "tags and bases", - list: []interface{}{tags, bases}, - bases: bases, - tags: tags, - }, - { - desc: "fully specified", - list: []interface{}{tags, bases, scripts, regions}, - bases: bases, - scripts: scripts, - regions: regions, - tags: tags, - }, - { - desc: "bases func", - list: []interface{}{fbases}, - bases: bases, - }, - { - desc: "scripts func", - list: []interface{}{fscripts}, - scripts: scripts, - }, - { - desc: "regions func", - list: []interface{}{fregions}, - regions: regions, - }, - { - desc: "tags func", - list: []interface{}{ftags}, - bases: []Base{Base{_en}, Base{_pt}}, - tags: tags, - }, - { - desc: "tags and bases", - list: []interface{}{ftags, fbases}, - bases: bases, - tags: tags, - }, - { - desc: "fully specified", - list: []interface{}{ftags, fbases, fscripts, fregions}, - bases: bases, - scripts: scripts, - regions: regions, - tags: tags, - }, - } - - for i, tt := range tests { - l := NewCoverage(tt.list...) - if a := l.BaseLanguages(); !reflect.DeepEqual(a, tt.bases) { - t.Errorf("%d:%s: BaseLanguages was %v; want %v", i, tt.desc, a, tt.bases) - } - if a := l.Scripts(); !reflect.DeepEqual(a, tt.scripts) { - t.Errorf("%d:%s: Scripts was %v; want %v", i, tt.desc, a, tt.scripts) - } - if a := l.Regions(); !reflect.DeepEqual(a, tt.regions) { - t.Errorf("%d:%s: Regions was %v; want %v", i, tt.desc, a, tt.regions) - } - if a := l.Tags(); !reflect.DeepEqual(a, tt.tags) { - t.Errorf("%d:%s: Tags was %v; want %v", i, tt.desc, a, tt.tags) - } - } -} diff --git a/vendor/golang.org/x/text/language/examples_test.go b/vendor/golang.org/x/text/language/examples_test.go deleted file mode 100644 index d5e8176d..00000000 --- a/vendor/golang.org/x/text/language/examples_test.go +++ /dev/null @@ -1,413 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package language_test - -import ( - "fmt" - "net/http" - - "golang.org/x/text/language" -) - -func ExampleCanonType() { - p := func(id string) { - fmt.Printf("Default(%s) -> %s\n", id, language.Make(id)) - fmt.Printf("BCP47(%s) -> %s\n", id, language.BCP47.Make(id)) - fmt.Printf("Macro(%s) -> %s\n", id, language.Macro.Make(id)) - fmt.Printf("All(%s) -> %s\n", id, language.All.Make(id)) - } - p("en-Latn") - p("sh") - p("zh-cmn") - p("bjd") - p("iw-Latn-fonipa-u-cu-usd") - // Output: - // Default(en-Latn) -> en-Latn - // BCP47(en-Latn) -> en - // Macro(en-Latn) -> en-Latn - // All(en-Latn) -> en - // Default(sh) -> sr-Latn - // BCP47(sh) -> sh - // Macro(sh) -> sh - // All(sh) -> sr-Latn - // Default(zh-cmn) -> cmn - // BCP47(zh-cmn) -> cmn - // Macro(zh-cmn) -> zh - // All(zh-cmn) -> zh - // Default(bjd) -> drl - // BCP47(bjd) -> drl - // Macro(bjd) -> bjd - // All(bjd) -> drl - // Default(iw-Latn-fonipa-u-cu-usd) -> he-Latn-fonipa-u-cu-usd - // BCP47(iw-Latn-fonipa-u-cu-usd) -> he-Latn-fonipa-u-cu-usd - // Macro(iw-Latn-fonipa-u-cu-usd) -> iw-Latn-fonipa-u-cu-usd - // All(iw-Latn-fonipa-u-cu-usd) -> he-Latn-fonipa-u-cu-usd -} - -func ExampleTag_Base() { - fmt.Println(language.Make("und").Base()) - fmt.Println(language.Make("und-US").Base()) - fmt.Println(language.Make("und-NL").Base()) - fmt.Println(language.Make("und-419").Base()) // Latin America - fmt.Println(language.Make("und-ZZ").Base()) - // Output: - // en Low - // en High - // nl High - // es Low - // en Low -} - -func ExampleTag_Script() { - en := language.Make("en") - sr := language.Make("sr") - sr_Latn := language.Make("sr_Latn") - fmt.Println(en.Script()) - fmt.Println(sr.Script()) - // Was a script explicitly specified? - _, c := sr.Script() - fmt.Println(c == language.Exact) - _, c = sr_Latn.Script() - fmt.Println(c == language.Exact) - // Output: - // Latn High - // Cyrl Low - // false - // true -} - -func ExampleTag_Region() { - ru := language.Make("ru") - en := language.Make("en") - fmt.Println(ru.Region()) - fmt.Println(en.Region()) - // Output: - // RU Low - // US Low -} - -func ExampleRegion_TLD() { - us := language.MustParseRegion("US") - gb := language.MustParseRegion("GB") - uk := language.MustParseRegion("UK") - bu := language.MustParseRegion("BU") - - fmt.Println(us.TLD()) - fmt.Println(gb.TLD()) - fmt.Println(uk.TLD()) - fmt.Println(bu.TLD()) - - fmt.Println(us.Canonicalize().TLD()) - fmt.Println(gb.Canonicalize().TLD()) - fmt.Println(uk.Canonicalize().TLD()) - fmt.Println(bu.Canonicalize().TLD()) - // Output: - // US - // UK - // UK - // ZZ language: region is not a valid ccTLD - // US - // UK - // UK - // MM -} - -func ExampleCompose() { - nl, _ := language.ParseBase("nl") - us, _ := language.ParseRegion("US") - de := language.Make("de-1901-u-co-phonebk") - jp := language.Make("ja-JP") - fi := language.Make("fi-x-ing") - - u, _ := language.ParseExtension("u-nu-arabic") - x, _ := language.ParseExtension("x-piglatin") - - // Combine a base language and region. - fmt.Println(language.Compose(nl, us)) - // Combine a base language and extension. - fmt.Println(language.Compose(nl, x)) - // Replace the region. - fmt.Println(language.Compose(jp, us)) - // Combine several tags. - fmt.Println(language.Compose(us, nl, u)) - - // Replace the base language of a tag. - fmt.Println(language.Compose(de, nl)) - fmt.Println(language.Compose(de, nl, u)) - // Remove the base language. - fmt.Println(language.Compose(de, language.Base{})) - // Remove all variants. - fmt.Println(language.Compose(de, []language.Variant{})) - // Remove all extensions. - fmt.Println(language.Compose(de, []language.Extension{})) - fmt.Println(language.Compose(fi, []language.Extension{})) - // Remove all variants and extensions. - fmt.Println(language.Compose(de.Raw())) - - // An error is gobbled or returned if non-nil. - fmt.Println(language.Compose(language.ParseRegion("ZA"))) - fmt.Println(language.Compose(language.ParseRegion("HH"))) - - // Compose uses the same Default canonicalization as Make. - fmt.Println(language.Compose(language.Raw.Parse("en-Latn-UK"))) - - // Call compose on a different CanonType for different results. - fmt.Println(language.All.Compose(language.Raw.Parse("en-Latn-UK"))) - - // Output: - // nl-US - // nl-x-piglatin - // ja-US - // nl-US-u-nu-arabic - // nl-1901-u-co-phonebk - // nl-1901-u-nu-arabic - // und-1901-u-co-phonebk - // de-u-co-phonebk - // de-1901 - // fi - // de - // und-ZA - // und language: subtag "HH" is well-formed but unknown - // en-Latn-GB - // en-GB -} - -func ExampleParse_errors() { - for _, s := range []string{"Foo", "Bar", "Foobar"} { - _, err := language.Parse(s) - if err != nil { - if inv, ok := err.(language.ValueError); ok { - fmt.Println(inv.Subtag()) - } else { - fmt.Println(s) - } - } - } - for _, s := range []string{"en", "aa-Uuuu", "AC", "ac-u"} { - _, err := language.Parse(s) - switch e := err.(type) { - case language.ValueError: - fmt.Printf("%s: culprit %q\n", s, e.Subtag()) - case nil: - // No error. - default: - // A syntax error. - fmt.Printf("%s: ill-formed\n", s) - } - } - // Output: - // foo - // Foobar - // aa-Uuuu: culprit "Uuuu" - // AC: culprit "ac" - // ac-u: ill-formed -} - -func ExampleParent() { - p := func(tag string) { - fmt.Printf("parent(%v): %v\n", tag, language.Make(tag).Parent()) - } - p("zh-CN") - - // Australian English inherits from World English. - p("en-AU") - - // If the tag has a different maximized script from its parent, a tag with - // this maximized script is inserted. This allows different language tags - // which have the same base language and script in common to inherit from - // a common set of settings. - p("zh-HK") - - // If the maximized script of the parent is not identical, CLDR will skip - // inheriting from it, as it means there will not be many entries in common - // and inheriting from it is nonsensical. - p("zh-Hant") - - // The parent of a tag with variants and extensions is the tag with all - // variants and extensions removed. - p("de-1994-u-co-phonebk") - - // Remove default script. - p("de-Latn-LU") - - // Output: - // parent(zh-CN): zh - // parent(en-AU): en-001 - // parent(zh-HK): zh-Hant - // parent(zh-Hant): und - // parent(de-1994-u-co-phonebk): de - // parent(de-Latn-LU): de -} - -// ExampleMatcher_bestMatch gives some examples of getting the best match of -// a set of tags to any of the tags of given set. -func ExampleMatcher() { - // This is the set of tags from which we want to pick the best match. These - // can be, for example, the supported languages for some package. - tags := []language.Tag{ - language.English, - language.BritishEnglish, - language.French, - language.Afrikaans, - language.BrazilianPortuguese, - language.EuropeanPortuguese, - language.Croatian, - language.SimplifiedChinese, - language.Raw.Make("iw-IL"), - language.Raw.Make("iw"), - language.Raw.Make("he"), - } - m := language.NewMatcher(tags) - - // A simple match. - fmt.Println(m.Match(language.Make("fr"))) - - // Australian English is closer to British than American English. - fmt.Println(m.Match(language.Make("en-AU"))) - - // Default to the first tag passed to the Matcher if there is no match. - fmt.Println(m.Match(language.Make("ar"))) - - // Get the default tag. - fmt.Println(m.Match()) - - fmt.Println("----") - - // Someone specifying sr-Latn is probably fine with getting Croatian. - fmt.Println(m.Match(language.Make("sr-Latn"))) - - // We match SimplifiedChinese, but with Low confidence. - fmt.Println(m.Match(language.TraditionalChinese)) - - // Serbian in Latin script is a closer match to Croatian than Traditional - // Chinese to Simplified Chinese. - fmt.Println(m.Match(language.TraditionalChinese, language.Make("sr-Latn"))) - - fmt.Println("----") - - // In case a multiple variants of a language are available, the most spoken - // variant is typically returned. - fmt.Println(m.Match(language.Portuguese)) - - // Pick the first value passed to Match in case of a tie. - fmt.Println(m.Match(language.Dutch, language.Make("fr-BE"), language.Make("af-NA"))) - fmt.Println(m.Match(language.Dutch, language.Make("af-NA"), language.Make("fr-BE"))) - - fmt.Println("----") - - // If a Matcher is initialized with a language and it's deprecated version, - // it will distinguish between them. - fmt.Println(m.Match(language.Raw.Make("iw"))) - - // However, for non-exact matches, it will treat deprecated versions as - // equivalent and consider other factors first. - fmt.Println(m.Match(language.Raw.Make("he-IL"))) - - fmt.Println("----") - - // User settings passed to the Unicode extension are ignored for matching - // and preserved in the returned tag. - fmt.Println(m.Match(language.Make("de-u-co-phonebk"), language.Make("fr-u-cu-frf"))) - - // Even if the matching language is different. - fmt.Println(m.Match(language.Make("de-u-co-phonebk"), language.Make("br-u-cu-frf"))) - - // If there is no matching language, the options of the first preferred tag are used. - fmt.Println(m.Match(language.Make("de-u-co-phonebk"))) - - // Output: - // fr 2 Exact - // en-GB 1 High - // en 0 No - // en 0 No - // ---- - // hr 6 High - // zh-Hans 7 Low - // hr 6 High - // ---- - // pt-BR 4 High - // fr 2 High - // af 3 High - // ---- - // iw 9 Exact - // he 10 Exact - // ---- - // fr-u-cu-frf 2 Exact - // fr-u-cu-frf 2 High - // en-u-co-phonebk 0 No - - // TODO: "he" should be "he-u-rg-IL High" -} - -func ExampleMatchStrings() { - // languages supported by this service: - matcher := language.NewMatcher([]language.Tag{ - language.English, language.Dutch, language.German, - }) - - http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - lang, _ := r.Cookie("lang") - tag, _ := language.MatchStrings(matcher, lang.String(), r.Header.Get("Accept-Language")) - - fmt.Println("User language:", tag) - }) -} - -func ExampleComprehends() { - // Various levels of comprehensibility. - fmt.Println(language.Comprehends(language.English, language.English)) - fmt.Println(language.Comprehends(language.AmericanEnglish, language.BritishEnglish)) - - // An explicit Und results in no match. - fmt.Println(language.Comprehends(language.English, language.Und)) - - fmt.Println("----") - - // There is usually no mutual comprehensibility between different scripts. - fmt.Println(language.Comprehends(language.Make("en-Dsrt"), language.English)) - - // One exception is for Traditional versus Simplified Chinese, albeit with - // a low confidence. - fmt.Println(language.Comprehends(language.TraditionalChinese, language.SimplifiedChinese)) - - fmt.Println("----") - - // A Swiss German speaker will often understand High German. - fmt.Println(language.Comprehends(language.Make("gsw"), language.Make("de"))) - - // The converse is not generally the case. - fmt.Println(language.Comprehends(language.Make("de"), language.Make("gsw"))) - - // Output: - // Exact - // High - // No - // ---- - // No - // Low - // ---- - // High - // No -} - -func ExampleTag_values() { - us := language.MustParseRegion("US") - en := language.MustParseBase("en") - - lang, _, region := language.AmericanEnglish.Raw() - fmt.Println(lang == en, region == us) - - lang, _, region = language.BritishEnglish.Raw() - fmt.Println(lang == en, region == us) - - // Tags can be compared for exact equivalence using '=='. - en_us, _ := language.Compose(en, us) - fmt.Println(en_us == language.AmericanEnglish) - - // Output: - // true true - // true false - // true -} diff --git a/vendor/golang.org/x/text/language/httpexample_test.go b/vendor/golang.org/x/text/language/httpexample_test.go deleted file mode 100644 index 40d0663c..00000000 --- a/vendor/golang.org/x/text/language/httpexample_test.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package language_test - -import ( - "fmt" - "net/http" - "strings" - - "golang.org/x/text/language" -) - -// matcher is a language.Matcher configured for all supported languages. -var matcher = language.NewMatcher([]language.Tag{ - language.BritishEnglish, - language.Norwegian, - language.German, -}) - -// handler is a http.HandlerFunc. -func handler(w http.ResponseWriter, r *http.Request) { - t, q, err := language.ParseAcceptLanguage(r.Header.Get("Accept-Language")) - // We ignore the error: the default language will be selected for t == nil. - tag, _, _ := matcher.Match(t...) - fmt.Printf("%5v (t: %6v; q: %3v; err: %v)\n", tag, t, q, err) -} - -func ExampleParseAcceptLanguage() { - for _, al := range []string{ - "nn;q=0.3, en-us;q=0.8, en,", - "gsw, en;q=0.7, en-US;q=0.8", - "gsw, nl, da", - "invalid", - } { - // Create dummy request with Accept-Language set and pass it to handler. - r, _ := http.NewRequest("GET", "example.com", strings.NewReader("Hello")) - r.Header.Set("Accept-Language", al) - handler(nil, r) - } - - // Output: - // en-GB (t: [ en en-US nn]; q: [ 1 0.8 0.3]; err: ) - // en-GB (t: [ gsw en-US en]; q: [ 1 0.8 0.7]; err: ) - // de (t: [ gsw nl da]; q: [ 1 1 1]; err: ) - // en-GB (t: []; q: []; err: language: tag is not well-formed) -} diff --git a/vendor/golang.org/x/text/language/language_test.go b/vendor/golang.org/x/text/language/language_test.go deleted file mode 100644 index 9e42d15d..00000000 --- a/vendor/golang.org/x/text/language/language_test.go +++ /dev/null @@ -1,911 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package language - -import ( - "reflect" - "testing" - - "golang.org/x/text/internal/testtext" -) - -func TestTagSize(t *testing.T) { - id := Tag{} - typ := reflect.TypeOf(id) - if typ.Size() > 24 { - t.Errorf("size of Tag was %d; want 24", typ.Size()) - } -} - -func TestIsRoot(t *testing.T) { - loc := Tag{} - if !loc.IsRoot() { - t.Errorf("unspecified should be root.") - } - for i, tt := range parseTests() { - loc, _ := Parse(tt.in) - undef := tt.lang == "und" && tt.script == "" && tt.region == "" && tt.ext == "" - if loc.IsRoot() != undef { - t.Errorf("%d: was %v; want %v", i, loc.IsRoot(), undef) - } - } -} - -func TestEquality(t *testing.T) { - for i, tt := range parseTests()[48:49] { - s := tt.in - tag := Make(s) - t1 := Make(tag.String()) - if tag != t1 { - t.Errorf("%d:%s: equality test 1 failed\n got: %#v\nwant: %#v)", i, s, t1, tag) - } - t2, _ := Compose(tag) - if tag != t2 { - t.Errorf("%d:%s: equality test 2 failed\n got: %#v\nwant: %#v", i, s, t2, tag) - } - } -} - -func TestMakeString(t *testing.T) { - tests := []struct{ in, out string }{ - {"und", "und"}, - {"und", "und-CW"}, - {"nl", "nl-NL"}, - {"de-1901", "nl-1901"}, - {"de-1901", "de-Arab-1901"}, - {"x-a-b", "de-Arab-x-a-b"}, - {"x-a-b", "x-a-b"}, - } - for i, tt := range tests { - id, _ := Parse(tt.in) - mod, _ := Parse(tt.out) - id.setTagsFrom(mod) - for j := 0; j < 2; j++ { - id.remakeString() - if str := id.String(); str != tt.out { - t.Errorf("%d:%d: found %s; want %s", i, j, id.String(), tt.out) - } - } - // The bytes to string conversion as used in remakeString - // occasionally measures as more than one alloc, breaking this test. - // To alleviate this we set the number of runs to more than 1. - if n := testtext.AllocsPerRun(8, id.remakeString); n > 1 { - t.Errorf("%d: # allocs got %.1f; want <= 1", i, n) - } - } -} - -func TestCompactIndex(t *testing.T) { - tests := []struct { - tag string - index int - ok bool - }{ - // TODO: these values will change with each CLDR update. This issue - // will be solved if we decide to fix the indexes. - {"und", 0, true}, - {"ca-ES-valencia", 1, true}, - {"ca-ES-valencia-u-va-posix", 0, false}, - {"ca-ES-valencia-u-co-phonebk", 1, true}, - {"ca-ES-valencia-u-co-phonebk-va-posix", 0, false}, - {"x-klingon", 0, false}, - {"en-US", 232, true}, - {"en-US-u-va-posix", 2, true}, - {"en", 136, true}, - {"en-u-co-phonebk", 136, true}, - {"en-001", 137, true}, - {"sh", 0, false}, // We don't normalize. - } - for _, tt := range tests { - x, ok := CompactIndex(Raw.MustParse(tt.tag)) - if x != tt.index || ok != tt.ok { - t.Errorf("%s: got %d, %v; want %d %v", tt.tag, x, ok, tt.index, tt.ok) - } - } -} - -func TestMarshal(t *testing.T) { - testCases := []string{ - // TODO: these values will change with each CLDR update. This issue - // will be solved if we decide to fix the indexes. - "und", - "ca-ES-valencia", - "ca-ES-valencia-u-va-posix", - "ca-ES-valencia-u-co-phonebk", - "ca-ES-valencia-u-co-phonebk-va-posix", - "x-klingon", - "en-US", - "en-US-u-va-posix", - "en", - "en-u-co-phonebk", - "en-001", - "sh", - } - for _, tc := range testCases { - var tag Tag - err := tag.UnmarshalText([]byte(tc)) - if err != nil { - t.Errorf("UnmarshalText(%q): unexpected error: %v", tc, err) - } - b, err := tag.MarshalText() - if err != nil { - t.Errorf("MarshalText(%q): unexpected error: %v", tc, err) - } - if got := string(b); got != tc { - t.Errorf("%s: got %q; want %q", tc, got, tc) - } - } -} - -func TestBase(t *testing.T) { - tests := []struct { - loc, lang string - conf Confidence - }{ - {"und", "en", Low}, - {"x-abc", "und", No}, - {"en", "en", Exact}, - {"und-Cyrl", "ru", High}, - // If a region is not included, the official language should be English. - {"und-US", "en", High}, - // TODO: not-explicitly listed scripts should probably be und, No - // Modify addTags to return info on how the match was derived. - // {"und-Aghb", "und", No}, - } - for i, tt := range tests { - loc, _ := Parse(tt.loc) - lang, conf := loc.Base() - if lang.String() != tt.lang { - t.Errorf("%d: language was %s; want %s", i, lang, tt.lang) - } - if conf != tt.conf { - t.Errorf("%d: confidence was %d; want %d", i, conf, tt.conf) - } - } -} - -func TestParseBase(t *testing.T) { - tests := []struct { - in string - out string - ok bool - }{ - {"en", "en", true}, - {"EN", "en", true}, - {"nld", "nl", true}, - {"dut", "dut", true}, // bibliographic - {"aaj", "und", false}, // unknown - {"qaa", "qaa", true}, - {"a", "und", false}, - {"", "und", false}, - {"aaaa", "und", false}, - } - for i, tt := range tests { - x, err := ParseBase(tt.in) - if x.String() != tt.out || err == nil != tt.ok { - t.Errorf("%d:%s: was %s, %v; want %s, %v", i, tt.in, x, err == nil, tt.out, tt.ok) - } - if y, _, _ := Raw.Make(tt.out).Raw(); x != y { - t.Errorf("%d:%s: tag was %s; want %s", i, tt.in, x, y) - } - } -} - -func TestScript(t *testing.T) { - tests := []struct { - loc, scr string - conf Confidence - }{ - {"und", "Latn", Low}, - {"en-Latn", "Latn", Exact}, - {"en", "Latn", High}, - {"sr", "Cyrl", Low}, - {"kk", "Cyrl", High}, - {"kk-CN", "Arab", Low}, - {"cmn", "Hans", Low}, - {"ru", "Cyrl", High}, - {"ru-RU", "Cyrl", High}, - {"yue", "Hant", Low}, - {"x-abc", "Zzzz", Low}, - {"und-zyyy", "Zyyy", Exact}, - } - for i, tt := range tests { - loc, _ := Parse(tt.loc) - sc, conf := loc.Script() - if sc.String() != tt.scr { - t.Errorf("%d:%s: script was %s; want %s", i, tt.loc, sc, tt.scr) - } - if conf != tt.conf { - t.Errorf("%d:%s: confidence was %d; want %d", i, tt.loc, conf, tt.conf) - } - } -} - -func TestParseScript(t *testing.T) { - tests := []struct { - in string - out string - ok bool - }{ - {"Latn", "Latn", true}, - {"zzzz", "Zzzz", true}, - {"zyyy", "Zyyy", true}, - {"Latm", "Zzzz", false}, - {"Zzz", "Zzzz", false}, - {"", "Zzzz", false}, - {"Zzzxx", "Zzzz", false}, - } - for i, tt := range tests { - x, err := ParseScript(tt.in) - if x.String() != tt.out || err == nil != tt.ok { - t.Errorf("%d:%s: was %s, %v; want %s, %v", i, tt.in, x, err == nil, tt.out, tt.ok) - } - if err == nil { - if _, y, _ := Raw.Make("und-" + tt.out).Raw(); x != y { - t.Errorf("%d:%s: tag was %s; want %s", i, tt.in, x, y) - } - } - } -} - -func TestRegion(t *testing.T) { - tests := []struct { - loc, reg string - conf Confidence - }{ - {"und", "US", Low}, - {"en", "US", Low}, - {"zh-Hant", "TW", Low}, - {"en-US", "US", Exact}, - {"cmn", "CN", Low}, - {"ru", "RU", Low}, - {"yue", "HK", Low}, - {"x-abc", "ZZ", Low}, - } - for i, tt := range tests { - loc, _ := Raw.Parse(tt.loc) - reg, conf := loc.Region() - if reg.String() != tt.reg { - t.Errorf("%d:%s: region was %s; want %s", i, tt.loc, reg, tt.reg) - } - if conf != tt.conf { - t.Errorf("%d:%s: confidence was %d; want %d", i, tt.loc, conf, tt.conf) - } - } -} - -func TestEncodeM49(t *testing.T) { - tests := []struct { - m49 int - code string - ok bool - }{ - {1, "001", true}, - {840, "US", true}, - {899, "ZZ", false}, - } - for i, tt := range tests { - if r, err := EncodeM49(tt.m49); r.String() != tt.code || err == nil != tt.ok { - t.Errorf("%d:%d: was %s, %v; want %s, %v", i, tt.m49, r, err == nil, tt.code, tt.ok) - } - } - for i := 1; i <= 1000; i++ { - if r, err := EncodeM49(i); err == nil && r.M49() == 0 { - t.Errorf("%d has no error, but maps to undefined region", i) - } - } -} - -func TestParseRegion(t *testing.T) { - tests := []struct { - in string - out string - ok bool - }{ - {"001", "001", true}, - {"840", "US", true}, - {"899", "ZZ", false}, - {"USA", "US", true}, - {"US", "US", true}, - {"BC", "ZZ", false}, - {"C", "ZZ", false}, - {"CCCC", "ZZ", false}, - {"01", "ZZ", false}, - } - for i, tt := range tests { - r, err := ParseRegion(tt.in) - if r.String() != tt.out || err == nil != tt.ok { - t.Errorf("%d:%s: was %s, %v; want %s, %v", i, tt.in, r, err == nil, tt.out, tt.ok) - } - if err == nil { - if _, _, y := Raw.Make("und-" + tt.out).Raw(); r != y { - t.Errorf("%d:%s: tag was %s; want %s", i, tt.in, r, y) - } - } - } -} - -func TestIsCountry(t *testing.T) { - tests := []struct { - reg string - country bool - }{ - {"US", true}, - {"001", false}, - {"958", false}, - {"419", false}, - {"203", true}, - {"020", true}, - {"900", false}, - {"999", false}, - {"QO", false}, - {"EU", false}, - {"AA", false}, - {"XK", true}, - } - for i, tt := range tests { - reg, _ := getRegionID([]byte(tt.reg)) - r := Region{reg} - if r.IsCountry() != tt.country { - t.Errorf("%d: IsCountry(%s) was %v; want %v", i, tt.reg, r.IsCountry(), tt.country) - } - } -} - -func TestIsGroup(t *testing.T) { - tests := []struct { - reg string - group bool - }{ - {"US", false}, - {"001", true}, - {"958", false}, - {"419", true}, - {"203", false}, - {"020", false}, - {"900", false}, - {"999", false}, - {"QO", true}, - {"EU", true}, - {"AA", false}, - {"XK", false}, - } - for i, tt := range tests { - reg, _ := getRegionID([]byte(tt.reg)) - r := Region{reg} - if r.IsGroup() != tt.group { - t.Errorf("%d: IsGroup(%s) was %v; want %v", i, tt.reg, r.IsGroup(), tt.group) - } - } -} - -func TestContains(t *testing.T) { - tests := []struct { - enclosing, contained string - contains bool - }{ - // A region contains itself. - {"US", "US", true}, - {"001", "001", true}, - - // Direct containment. - {"001", "002", true}, - {"039", "XK", true}, - {"150", "XK", true}, - {"EU", "AT", true}, - {"QO", "AQ", true}, - - // Indirect containemnt. - {"001", "US", true}, - {"001", "419", true}, - {"001", "013", true}, - - // No containment. - {"US", "001", false}, - {"155", "EU", false}, - } - for i, tt := range tests { - enc, _ := getRegionID([]byte(tt.enclosing)) - con, _ := getRegionID([]byte(tt.contained)) - r := Region{enc} - if got := r.Contains(Region{con}); got != tt.contains { - t.Errorf("%d: %s.Contains(%s) was %v; want %v", i, tt.enclosing, tt.contained, got, tt.contains) - } - } -} - -func TestRegionCanonicalize(t *testing.T) { - for i, tt := range []struct{ in, out string }{ - {"UK", "GB"}, - {"TP", "TL"}, - {"QU", "EU"}, - {"SU", "SU"}, - {"VD", "VN"}, - {"DD", "DE"}, - } { - r := MustParseRegion(tt.in) - want := MustParseRegion(tt.out) - if got := r.Canonicalize(); got != want { - t.Errorf("%d: got %v; want %v", i, got, want) - } - } -} - -func TestRegionTLD(t *testing.T) { - for _, tt := range []struct { - in, out string - ok bool - }{ - {"EH", "EH", true}, - {"FR", "FR", true}, - {"TL", "TL", true}, - - // In ccTLD before in ISO. - {"GG", "GG", true}, - - // Non-standard assignment of ccTLD to ISO code. - {"GB", "UK", true}, - - // Exceptionally reserved in ISO and valid ccTLD. - {"UK", "UK", true}, - {"AC", "AC", true}, - {"EU", "EU", true}, - {"SU", "SU", true}, - - // Exceptionally reserved in ISO and invalid ccTLD. - {"CP", "ZZ", false}, - {"DG", "ZZ", false}, - {"EA", "ZZ", false}, - {"FX", "ZZ", false}, - {"IC", "ZZ", false}, - {"TA", "ZZ", false}, - - // Transitionally reserved in ISO (e.g. deprecated) but valid ccTLD as - // it is still being phased out. - {"AN", "AN", true}, - {"TP", "TP", true}, - - // Transitionally reserved in ISO (e.g. deprecated) and invalid ccTLD. - // Defined in package language as it has a mapping in CLDR. - {"BU", "ZZ", false}, - {"CS", "ZZ", false}, - {"NT", "ZZ", false}, - {"YU", "ZZ", false}, - {"ZR", "ZZ", false}, - // Not defined in package: SF. - - // Indeterminately reserved in ISO. - // Defined in package language as it has a legacy mapping in CLDR. - {"DY", "ZZ", false}, - {"RH", "ZZ", false}, - {"VD", "ZZ", false}, - // Not defined in package: EW, FL, JA, LF, PI, RA, RB, RC, RI, RL, RM, - // RN, RP, WG, WL, WV, and YV. - - // Not assigned in ISO, but legacy definitions in CLDR. - {"DD", "ZZ", false}, - {"YD", "ZZ", false}, - - // Normal mappings but somewhat special status in ccTLD. - {"BL", "BL", true}, - {"MF", "MF", true}, - {"BV", "BV", true}, - {"SJ", "SJ", true}, - - // Have values when normalized, but not as is. - {"QU", "ZZ", false}, - - // ISO Private Use. - {"AA", "ZZ", false}, - {"QM", "ZZ", false}, - {"QO", "ZZ", false}, - {"XA", "ZZ", false}, - {"XK", "ZZ", false}, // Sometimes used for Kosovo, but invalid ccTLD. - } { - if tt.in == "" { - continue - } - - r := MustParseRegion(tt.in) - var want Region - if tt.out != "ZZ" { - want = MustParseRegion(tt.out) - } - tld, err := r.TLD() - if got := err == nil; got != tt.ok { - t.Errorf("error(%v): got %v; want %v", r, got, tt.ok) - } - if tld != want { - t.Errorf("TLD(%v): got %v; want %v", r, tld, want) - } - } -} - -func TestCanonicalize(t *testing.T) { - // TODO: do a full test using CLDR data in a separate regression test. - tests := []struct { - in, out string - option CanonType - }{ - {"en-Latn", "en", SuppressScript}, - {"sr-Cyrl", "sr-Cyrl", SuppressScript}, - {"sh", "sr-Latn", Legacy}, - {"sh-HR", "sr-Latn-HR", Legacy}, - {"sh-Cyrl-HR", "sr-Cyrl-HR", Legacy}, - {"tl", "fil", Legacy}, - {"no", "no", Legacy}, - {"no", "nb", Legacy | CLDR}, - {"cmn", "cmn", Legacy}, - {"cmn", "zh", Macro}, - {"cmn-u-co-stroke", "zh-u-co-stroke", Macro}, - {"yue", "yue", Macro}, - {"nb", "no", Macro}, - {"nb", "nb", Macro | CLDR}, - {"no", "no", Macro}, - {"no", "no", Macro | CLDR}, - {"iw", "he", DeprecatedBase}, - {"iw", "he", Deprecated | CLDR}, - {"mo", "ro-MD", Deprecated}, // Adopted by CLDR as of version 25. - {"alb", "sq", Legacy}, // bibliographic - {"dut", "nl", Legacy}, // bibliographic - // As of CLDR 25, mo is no longer considered a legacy mapping. - {"mo", "mo", Legacy | CLDR}, - {"und-AN", "und-AN", Deprecated}, - {"und-YD", "und-YE", DeprecatedRegion}, - {"und-YD", "und-YD", DeprecatedBase}, - {"und-Qaai", "und-Zinh", DeprecatedScript}, - {"und-Qaai", "und-Qaai", DeprecatedBase}, - {"drh", "mn", All}, // drh -> khk -> mn - } - for i, tt := range tests { - in, _ := Raw.Parse(tt.in) - in, _ = tt.option.Canonicalize(in) - if in.String() != tt.out { - t.Errorf("%d:%s: was %s; want %s", i, tt.in, in.String(), tt.out) - } - if int(in.pVariant) > int(in.pExt) || int(in.pExt) > len(in.str) { - t.Errorf("%d:%s:offsets %d <= %d <= %d must be true", i, tt.in, in.pVariant, in.pExt, len(in.str)) - } - } - // Test idempotence. - for _, base := range Supported.BaseLanguages() { - tag, _ := Raw.Compose(base) - got, _ := All.Canonicalize(tag) - want, _ := All.Canonicalize(got) - if got != want { - t.Errorf("idem(%s): got %s; want %s", tag, got, want) - } - } -} - -func TestTypeForKey(t *testing.T) { - tests := []struct{ key, in, out string }{ - {"co", "en", ""}, - {"co", "en-u-abc", ""}, - {"co", "en-u-co-phonebk", "phonebk"}, - {"co", "en-u-co-phonebk-cu-aud", "phonebk"}, - {"co", "x-foo-u-co-phonebk", ""}, - {"nu", "en-u-co-phonebk-nu-arabic", "arabic"}, - {"kc", "cmn-u-co-stroke", ""}, - } - for _, tt := range tests { - if v := Make(tt.in).TypeForKey(tt.key); v != tt.out { - t.Errorf("%q[%q]: was %q; want %q", tt.in, tt.key, v, tt.out) - } - } -} - -func TestSetTypeForKey(t *testing.T) { - tests := []struct { - key, value, in, out string - err bool - }{ - // replace existing value - {"co", "pinyin", "en-u-co-phonebk", "en-u-co-pinyin", false}, - {"co", "pinyin", "en-u-co-phonebk-cu-xau", "en-u-co-pinyin-cu-xau", false}, - {"co", "pinyin", "en-u-co-phonebk-v-xx", "en-u-co-pinyin-v-xx", false}, - {"co", "pinyin", "en-u-co-phonebk-x-x", "en-u-co-pinyin-x-x", false}, - {"nu", "arabic", "en-u-co-phonebk-nu-vaai", "en-u-co-phonebk-nu-arabic", false}, - // add to existing -u extension - {"co", "pinyin", "en-u-ca-gregory", "en-u-ca-gregory-co-pinyin", false}, - {"co", "pinyin", "en-u-ca-gregory-nu-vaai", "en-u-ca-gregory-co-pinyin-nu-vaai", false}, - {"co", "pinyin", "en-u-ca-gregory-v-va", "en-u-ca-gregory-co-pinyin-v-va", false}, - {"co", "pinyin", "en-u-ca-gregory-x-a", "en-u-ca-gregory-co-pinyin-x-a", false}, - {"ca", "gregory", "en-u-co-pinyin", "en-u-ca-gregory-co-pinyin", false}, - // remove pair - {"co", "", "en-u-co-phonebk", "en", false}, - {"co", "", "en-u-ca-gregory-co-phonebk", "en-u-ca-gregory", false}, - {"co", "", "en-u-co-phonebk-nu-arabic", "en-u-nu-arabic", false}, - {"co", "", "en", "en", false}, - // add -u extension - {"co", "pinyin", "en", "en-u-co-pinyin", false}, - {"co", "pinyin", "und", "und-u-co-pinyin", false}, - {"co", "pinyin", "en-a-aaa", "en-a-aaa-u-co-pinyin", false}, - {"co", "pinyin", "en-x-aaa", "en-u-co-pinyin-x-aaa", false}, - {"co", "pinyin", "en-v-aa", "en-u-co-pinyin-v-aa", false}, - {"co", "pinyin", "en-a-aaa-x-x", "en-a-aaa-u-co-pinyin-x-x", false}, - {"co", "pinyin", "en-a-aaa-v-va", "en-a-aaa-u-co-pinyin-v-va", false}, - // error on invalid values - {"co", "pinyinxxx", "en", "en", true}, - {"co", "piny.n", "en", "en", true}, - {"co", "pinyinxxx", "en-a-aaa", "en-a-aaa", true}, - {"co", "pinyinxxx", "en-u-aaa", "en-u-aaa", true}, - {"co", "pinyinxxx", "en-u-aaa-co-pinyin", "en-u-aaa-co-pinyin", true}, - {"co", "pinyi.", "en-u-aaa-co-pinyin", "en-u-aaa-co-pinyin", true}, - {"col", "pinyin", "en", "en", true}, - {"co", "cu", "en", "en", true}, - // error when setting on a private use tag - {"co", "phonebook", "x-foo", "x-foo", true}, - } - for i, tt := range tests { - tag := Make(tt.in) - if v, err := tag.SetTypeForKey(tt.key, tt.value); v.String() != tt.out { - t.Errorf("%d:%q[%q]=%q: was %q; want %q", i, tt.in, tt.key, tt.value, v, tt.out) - } else if (err != nil) != tt.err { - t.Errorf("%d:%q[%q]=%q: error was %v; want %v", i, tt.in, tt.key, tt.value, err != nil, tt.err) - } else if val := v.TypeForKey(tt.key); err == nil && val != tt.value { - t.Errorf("%d:%q[%q]==%q: was %v; want %v", i, tt.out, tt.key, tt.value, val, tt.value) - } - if len(tag.String()) <= 3 { - // Simulate a tag for which the string has not been set. - tag.str, tag.pExt, tag.pVariant = "", 0, 0 - if tag, err := tag.SetTypeForKey(tt.key, tt.value); err == nil { - if val := tag.TypeForKey(tt.key); err == nil && val != tt.value { - t.Errorf("%d:%q[%q]==%q: was %v; want %v", i, tt.out, tt.key, tt.value, val, tt.value) - } - } - } - } -} - -func TestFindKeyAndType(t *testing.T) { - // out is either the matched type in case of a match or the original - // string up till the insertion point. - tests := []struct { - key string - hasExt bool - in, out string - }{ - // Don't search past a private use extension. - {"co", false, "en-x-foo-u-co-pinyin", "en"}, - {"co", false, "x-foo-u-co-pinyin", ""}, - {"co", false, "en-s-fff-x-foo", "en-s-fff"}, - // Insertion points in absence of -u extension. - {"cu", false, "en", ""}, // t.str is "" - {"cu", false, "en-v-va", "en"}, - {"cu", false, "en-a-va", "en-a-va"}, - {"cu", false, "en-a-va-v-va", "en-a-va"}, - {"cu", false, "en-x-a", "en"}, - // Tags with the -u extension. - {"co", true, "en-u-co-standard", "standard"}, - {"co", true, "yue-u-co-pinyin", "pinyin"}, - {"co", true, "en-u-co-abc", "abc"}, - {"co", true, "en-u-co-abc-def", "abc-def"}, - {"co", true, "en-u-co-abc-def-x-foo", "abc-def"}, - {"co", true, "en-u-co-standard-nu-arab", "standard"}, - {"co", true, "yue-u-co-pinyin-nu-arab", "pinyin"}, - // Insertion points. - {"cu", true, "en-u-co-standard", "en-u-co-standard"}, - {"cu", true, "yue-u-co-pinyin-x-foo", "yue-u-co-pinyin"}, - {"cu", true, "en-u-co-abc", "en-u-co-abc"}, - {"cu", true, "en-u-nu-arabic", "en-u"}, - {"cu", true, "en-u-co-abc-def-nu-arabic", "en-u-co-abc-def"}, - } - for i, tt := range tests { - start, end, hasExt := Make(tt.in).findTypeForKey(tt.key) - if start != end { - res := tt.in[start:end] - if res != tt.out { - t.Errorf("%d:%s: was %q; want %q", i, tt.in, res, tt.out) - } - } else { - if hasExt != tt.hasExt { - t.Errorf("%d:%s: hasExt was %v; want %v", i, tt.in, hasExt, tt.hasExt) - continue - } - if tt.in[:start] != tt.out { - t.Errorf("%d:%s: insertion point was %q; want %q", i, tt.in, tt.in[:start], tt.out) - } - } - } -} - -func TestParent(t *testing.T) { - tests := []struct{ in, out string }{ - // Strip variants and extensions first - {"de-u-co-phonebk", "de"}, - {"de-1994", "de"}, - {"de-Latn-1994", "de"}, // remove superfluous script. - - // Ensure the canonical Tag for an entry is in the chain for base-script - // pairs. - {"zh-Hans", "zh"}, - - // Skip the script if it is the maximized version. CLDR files for the - // skipped tag are always empty. - {"zh-Hans-TW", "zh"}, - {"zh-Hans-CN", "zh"}, - - // Insert the script if the maximized script is not the same as the - // maximized script of the base language. - {"zh-TW", "zh-Hant"}, - {"zh-HK", "zh-Hant"}, - {"zh-Hant-TW", "zh-Hant"}, - {"zh-Hant-HK", "zh-Hant"}, - - // Non-default script skips to und. - // CLDR - {"az-Cyrl", "und"}, - {"bs-Cyrl", "und"}, - {"en-Dsrt", "und"}, - {"ha-Arab", "und"}, - {"mn-Mong", "und"}, - {"pa-Arab", "und"}, - {"shi-Latn", "und"}, - {"sr-Latn", "und"}, - {"uz-Arab", "und"}, - {"uz-Cyrl", "und"}, - {"vai-Latn", "und"}, - {"zh-Hant", "und"}, - // extra - {"nl-Cyrl", "und"}, - - // World english inherits from en-001. - {"en-150", "en-001"}, - {"en-AU", "en-001"}, - {"en-BE", "en-001"}, - {"en-GG", "en-001"}, - {"en-GI", "en-001"}, - {"en-HK", "en-001"}, - {"en-IE", "en-001"}, - {"en-IM", "en-001"}, - {"en-IN", "en-001"}, - {"en-JE", "en-001"}, - {"en-MT", "en-001"}, - {"en-NZ", "en-001"}, - {"en-PK", "en-001"}, - {"en-SG", "en-001"}, - - // Spanish in Latin-American countries have es-419 as parent. - {"es-AR", "es-419"}, - {"es-BO", "es-419"}, - {"es-CL", "es-419"}, - {"es-CO", "es-419"}, - {"es-CR", "es-419"}, - {"es-CU", "es-419"}, - {"es-DO", "es-419"}, - {"es-EC", "es-419"}, - {"es-GT", "es-419"}, - {"es-HN", "es-419"}, - {"es-MX", "es-419"}, - {"es-NI", "es-419"}, - {"es-PA", "es-419"}, - {"es-PE", "es-419"}, - {"es-PR", "es-419"}, - {"es-PY", "es-419"}, - {"es-SV", "es-419"}, - {"es-US", "es-419"}, - {"es-UY", "es-419"}, - {"es-VE", "es-419"}, - // exceptions (according to CLDR) - {"es-CW", "es"}, - - // Inherit from pt-PT, instead of pt for these countries. - {"pt-AO", "pt-PT"}, - {"pt-CV", "pt-PT"}, - {"pt-GW", "pt-PT"}, - {"pt-MO", "pt-PT"}, - {"pt-MZ", "pt-PT"}, - {"pt-ST", "pt-PT"}, - {"pt-TL", "pt-PT"}, - } - for _, tt := range tests { - tag := Raw.MustParse(tt.in) - if p := Raw.MustParse(tt.out); p != tag.Parent() { - t.Errorf("%s: was %v; want %v", tt.in, tag.Parent(), p) - } - } -} - -var ( - // Tags without error that don't need to be changed. - benchBasic = []string{ - "en", - "en-Latn", - "en-GB", - "za", - "zh-Hant", - "zh", - "zh-HK", - "ar-MK", - "en-CA", - "fr-CA", - "fr-CH", - "fr", - "lv", - "he-IT", - "tlh", - "ja", - "ja-Jpan", - "ja-Jpan-JP", - "de-1996", - "de-CH", - "sr", - "sr-Latn", - } - // Tags with extensions, not changes required. - benchExt = []string{ - "x-a-b-c-d", - "x-aa-bbbb-cccccccc-d", - "en-x_cc-b-bbb-a-aaa", - "en-c_cc-b-bbb-a-aaa-x-x", - "en-u-co-phonebk", - "en-Cyrl-u-co-phonebk", - "en-US-u-co-phonebk-cu-xau", - "en-nedix-u-co-phonebk", - "en-t-t0-abcd", - "en-t-nl-latn", - "en-t-t0-abcd-x-a", - } - // Change, but not memory allocation required. - benchSimpleChange = []string{ - "EN", - "i-klingon", - "en-latn", - "zh-cmn-Hans-CN", - "iw-NL", - } - // Change and memory allocation required. - benchChangeAlloc = []string{ - "en-c_cc-b-bbb-a-aaa", - "en-u-cu-xua-co-phonebk", - "en-u-cu-xua-co-phonebk-a-cd", - "en-u-def-abc-cu-xua-co-phonebk", - "en-t-en-Cyrl-NL-1994", - "en-t-en-Cyrl-NL-1994-t0-abc-def", - } - // Tags that result in errors. - benchErr = []string{ - // IllFormed - "x_A.-B-C_D", - "en-u-cu-co-phonebk", - "en-u-cu-xau-co", - "en-t-nl-abcd", - // Invalid - "xx", - "nl-Uuuu", - "nl-QB", - } - benchChange = append(benchSimpleChange, benchChangeAlloc...) - benchAll = append(append(append(benchBasic, benchExt...), benchChange...), benchErr...) -) - -func doParse(b *testing.B, tag []string) { - for i := 0; i < b.N; i++ { - // Use the modulo instead of looping over all tags so that we get a somewhat - // meaningful ns/op. - Parse(tag[i%len(tag)]) - } -} - -func BenchmarkParse(b *testing.B) { - doParse(b, benchAll) -} - -func BenchmarkParseBasic(b *testing.B) { - doParse(b, benchBasic) -} - -func BenchmarkParseError(b *testing.B) { - doParse(b, benchErr) -} - -func BenchmarkParseSimpleChange(b *testing.B) { - doParse(b, benchSimpleChange) -} - -func BenchmarkParseChangeAlloc(b *testing.B) { - doParse(b, benchChangeAlloc) -} diff --git a/vendor/golang.org/x/text/language/lookup_test.go b/vendor/golang.org/x/text/language/lookup_test.go deleted file mode 100644 index 9833830c..00000000 --- a/vendor/golang.org/x/text/language/lookup_test.go +++ /dev/null @@ -1,457 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package language - -import ( - "testing" - - "golang.org/x/text/internal/tag" -) - -func b(s string) []byte { - return []byte(s) -} - -func TestLangID(t *testing.T) { - tests := []struct { - id, bcp47, iso3, norm string - err error - }{ - {id: "", bcp47: "und", iso3: "und", err: errSyntax}, - {id: " ", bcp47: "und", iso3: "und", err: errSyntax}, - {id: " ", bcp47: "und", iso3: "und", err: errSyntax}, - {id: " ", bcp47: "und", iso3: "und", err: errSyntax}, - {id: "xxx", bcp47: "und", iso3: "und", err: mkErrInvalid([]byte("xxx"))}, - {id: "und", bcp47: "und", iso3: "und"}, - {id: "aju", bcp47: "aju", iso3: "aju", norm: "jrb"}, - {id: "jrb", bcp47: "jrb", iso3: "jrb"}, - {id: "es", bcp47: "es", iso3: "spa"}, - {id: "spa", bcp47: "es", iso3: "spa"}, - {id: "ji", bcp47: "ji", iso3: "yid-", norm: "yi"}, - {id: "jw", bcp47: "jw", iso3: "jav-", norm: "jv"}, - {id: "ar", bcp47: "ar", iso3: "ara"}, - {id: "kw", bcp47: "kw", iso3: "cor"}, - {id: "arb", bcp47: "arb", iso3: "arb", norm: "ar"}, - {id: "ar", bcp47: "ar", iso3: "ara"}, - {id: "kur", bcp47: "ku", iso3: "kur"}, - {id: "nl", bcp47: "nl", iso3: "nld"}, - {id: "NL", bcp47: "nl", iso3: "nld"}, - {id: "gsw", bcp47: "gsw", iso3: "gsw"}, - {id: "gSW", bcp47: "gsw", iso3: "gsw"}, - {id: "und", bcp47: "und", iso3: "und"}, - {id: "sh", bcp47: "sh", iso3: "hbs", norm: "sr"}, - {id: "hbs", bcp47: "sh", iso3: "hbs", norm: "sr"}, - {id: "no", bcp47: "no", iso3: "nor", norm: "no"}, - {id: "nor", bcp47: "no", iso3: "nor", norm: "no"}, - {id: "cmn", bcp47: "cmn", iso3: "cmn", norm: "zh"}, - } - for i, tt := range tests { - want, err := getLangID(b(tt.id)) - if err != tt.err { - t.Errorf("%d:err(%s): found %q; want %q", i, tt.id, err, tt.err) - } - if err != nil { - continue - } - if id, _ := getLangISO2(b(tt.bcp47)); len(tt.bcp47) == 2 && want != id { - t.Errorf("%d:getISO2(%s): found %v; want %v", i, tt.bcp47, id, want) - } - if len(tt.iso3) == 3 { - if id, _ := getLangISO3(b(tt.iso3)); want != id { - t.Errorf("%d:getISO3(%s): found %q; want %q", i, tt.iso3, id, want) - } - if id, _ := getLangID(b(tt.iso3)); want != id { - t.Errorf("%d:getID3(%s): found %v; want %v", i, tt.iso3, id, want) - } - } - norm := want - if tt.norm != "" { - norm, _ = getLangID(b(tt.norm)) - } - id, _ := normLang(want) - if id != norm { - t.Errorf("%d:norm(%s): found %v; want %v", i, tt.id, id, norm) - } - if id := want.String(); tt.bcp47 != id { - t.Errorf("%d:String(): found %s; want %s", i, id, tt.bcp47) - } - if id := want.ISO3(); tt.iso3[:3] != id { - t.Errorf("%d:iso3(): found %s; want %s", i, id, tt.iso3[:3]) - } - } -} - -func TestGrandfathered(t *testing.T) { - for _, tt := range []struct{ in, out string }{ - {"art-lojban", "jbo"}, - {"i-ami", "ami"}, - {"i-bnn", "bnn"}, - {"i-hak", "hak"}, - {"i-klingon", "tlh"}, - {"i-lux", "lb"}, - {"i-navajo", "nv"}, - {"i-pwn", "pwn"}, - {"i-tao", "tao"}, - {"i-tay", "tay"}, - {"i-tsu", "tsu"}, - {"no-bok", "nb"}, - {"no-nyn", "nn"}, - {"sgn-BE-FR", "sfb"}, - {"sgn-BE-NL", "vgt"}, - {"sgn-CH-DE", "sgg"}, - {"sgn-ch-de", "sgg"}, - {"zh-guoyu", "cmn"}, - {"zh-hakka", "hak"}, - {"zh-min-nan", "nan"}, - {"zh-xiang", "hsn"}, - - // Grandfathered tags with no modern replacement will be converted as follows: - {"cel-gaulish", "xtg-x-cel-gaulish"}, - {"en-GB-oed", "en-GB-oxendict"}, - {"en-gb-oed", "en-GB-oxendict"}, - {"i-default", "en-x-i-default"}, - {"i-enochian", "und-x-i-enochian"}, - {"i-mingo", "see-x-i-mingo"}, - {"zh-min", "nan-x-zh-min"}, - - {"root", "und"}, - {"en_US_POSIX", "en-US-u-va-posix"}, - {"en_us_posix", "en-US-u-va-posix"}, - {"en-us-posix", "en-US-u-va-posix"}, - } { - got := Raw.Make(tt.in) - want := Raw.MustParse(tt.out) - if got != want { - t.Errorf("%s: got %q; want %q", tt.in, got, want) - } - } -} - -func TestRegionID(t *testing.T) { - tests := []struct { - in, out string - }{ - {"_ ", ""}, - {"_000", ""}, - {"419", "419"}, - {"AA", "AA"}, - {"ATF", "TF"}, - {"HV", "HV"}, - {"CT", "CT"}, - {"DY", "DY"}, - {"IC", "IC"}, - {"FQ", "FQ"}, - {"JT", "JT"}, - {"ZZ", "ZZ"}, - {"EU", "EU"}, - {"QO", "QO"}, - {"FX", "FX"}, - } - for i, tt := range tests { - if tt.in[0] == '_' { - id := tt.in[1:] - if _, err := getRegionID(b(id)); err == nil { - t.Errorf("%d:err(%s): found nil; want error", i, id) - } - continue - } - want, _ := getRegionID(b(tt.in)) - if s := want.String(); s != tt.out { - t.Errorf("%d:%s: found %q; want %q", i, tt.in, s, tt.out) - } - if len(tt.in) == 2 { - want, _ := getRegionISO2(b(tt.in)) - if s := want.String(); s != tt.out { - t.Errorf("%d:getISO2(%s): found %q; want %q", i, tt.in, s, tt.out) - } - } - } -} - -func TestRegionType(t *testing.T) { - for _, tt := range []struct { - r string - t byte - }{ - {"NL", bcp47Region | ccTLD}, - {"EU", bcp47Region | ccTLD}, // exceptionally reserved - {"AN", bcp47Region | ccTLD}, // transitionally reserved - - {"DD", bcp47Region}, // deleted in ISO, deprecated in BCP 47 - {"NT", bcp47Region}, // transitionally reserved, deprecated in BCP 47 - - {"XA", iso3166UserAssigned | bcp47Region}, - {"ZZ", iso3166UserAssigned | bcp47Region}, - {"AA", iso3166UserAssigned | bcp47Region}, - {"QO", iso3166UserAssigned | bcp47Region}, - {"QM", iso3166UserAssigned | bcp47Region}, - {"XK", iso3166UserAssigned | bcp47Region}, - - {"CT", 0}, // deleted in ISO, not in BCP 47, canonicalized in CLDR - } { - r := MustParseRegion(tt.r) - if tp := r.typ(); tp != tt.t { - t.Errorf("Type(%s): got %x; want %x", tt.r, tp, tt.t) - } - } -} - -func TestRegionISO3(t *testing.T) { - tests := []struct { - from, iso3, to string - }{ - {" ", "ZZZ", "ZZ"}, - {"000", "ZZZ", "ZZ"}, - {"AA", "AAA", ""}, - {"CT", "CTE", ""}, - {"DY", "DHY", ""}, - {"EU", "QUU", ""}, - {"HV", "HVO", ""}, - {"IC", "ZZZ", "ZZ"}, - {"JT", "JTN", ""}, - {"PZ", "PCZ", ""}, - {"QU", "QUU", "EU"}, - {"QO", "QOO", ""}, - {"YD", "YMD", ""}, - {"FQ", "ATF", "TF"}, - {"TF", "ATF", ""}, - {"FX", "FXX", ""}, - {"ZZ", "ZZZ", ""}, - {"419", "ZZZ", "ZZ"}, - } - for _, tt := range tests { - r, _ := getRegionID(b(tt.from)) - if s := r.ISO3(); s != tt.iso3 { - t.Errorf("iso3(%q): found %q; want %q", tt.from, s, tt.iso3) - } - if tt.iso3 == "" { - continue - } - want := tt.to - if tt.to == "" { - want = tt.from - } - r, _ = getRegionID(b(want)) - if id, _ := getRegionISO3(b(tt.iso3)); id != r { - t.Errorf("%s: found %q; want %q", tt.iso3, id, want) - } - } -} - -func TestRegionM49(t *testing.T) { - fromTests := []struct { - m49 int - id string - }{ - {0, ""}, - {-1, ""}, - {1000, ""}, - {10000, ""}, - - {001, "001"}, - {104, "MM"}, - {180, "CD"}, - {230, "ET"}, - {231, "ET"}, - {249, "FX"}, - {250, "FR"}, - {276, "DE"}, - {278, "DD"}, - {280, "DE"}, - {419, "419"}, - {626, "TL"}, - {736, "SD"}, - {840, "US"}, - {854, "BF"}, - {891, "CS"}, - {899, ""}, - {958, "AA"}, - {966, "QT"}, - {967, "EU"}, - {999, "ZZ"}, - } - for _, tt := range fromTests { - id, err := getRegionM49(tt.m49) - if want, have := err != nil, tt.id == ""; want != have { - t.Errorf("error(%d): have %v; want %v", tt.m49, have, want) - continue - } - r, _ := getRegionID(b(tt.id)) - if r != id { - t.Errorf("region(%d): have %s; want %s", tt.m49, id, r) - } - } - - toTests := []struct { - m49 int - id string - }{ - {0, "000"}, - {0, "IC"}, // Some codes don't have an ID - - {001, "001"}, - {104, "MM"}, - {104, "BU"}, - {180, "CD"}, - {180, "ZR"}, - {231, "ET"}, - {250, "FR"}, - {249, "FX"}, - {276, "DE"}, - {278, "DD"}, - {419, "419"}, - {626, "TL"}, - {626, "TP"}, - {729, "SD"}, - {826, "GB"}, - {840, "US"}, - {854, "BF"}, - {891, "YU"}, - {891, "CS"}, - {958, "AA"}, - {966, "QT"}, - {967, "EU"}, - {967, "QU"}, - {999, "ZZ"}, - // For codes that don't have an M49 code use the replacement value, - // if available. - {854, "HV"}, // maps to Burkino Faso - } - for _, tt := range toTests { - r, _ := getRegionID(b(tt.id)) - if r.M49() != tt.m49 { - t.Errorf("m49(%q): have %d; want %d", tt.id, r.M49(), tt.m49) - } - } -} - -func TestRegionDeprecation(t *testing.T) { - tests := []struct{ in, out string }{ - {"BU", "MM"}, - {"BUR", "MM"}, - {"CT", "KI"}, - {"DD", "DE"}, - {"DDR", "DE"}, - {"DY", "BJ"}, - {"FX", "FR"}, - {"HV", "BF"}, - {"JT", "UM"}, - {"MI", "UM"}, - {"NH", "VU"}, - {"NQ", "AQ"}, - {"PU", "UM"}, - {"PZ", "PA"}, - {"QU", "EU"}, - {"RH", "ZW"}, - {"TP", "TL"}, - {"UK", "GB"}, - {"VD", "VN"}, - {"WK", "UM"}, - {"YD", "YE"}, - {"NL", "NL"}, - } - for _, tt := range tests { - rIn, _ := getRegionID([]byte(tt.in)) - rOut, _ := getRegionISO2([]byte(tt.out)) - r := normRegion(rIn) - if rOut == rIn && r != 0 { - t.Errorf("%s: was %q; want %q", tt.in, r, tt.in) - } - if rOut != rIn && r != rOut { - t.Errorf("%s: was %q; want %q", tt.in, r, tt.out) - } - - } -} - -func TestGetScriptID(t *testing.T) { - idx := tag.Index("0000BbbbDdddEeeeZzzz\xff\xff\xff\xff") - tests := []struct { - in string - out scriptID - }{ - {" ", 0}, - {" ", 0}, - {" ", 0}, - {"", 0}, - {"Aaaa", 0}, - {"Bbbb", 1}, - {"Dddd", 2}, - {"dddd", 2}, - {"dDDD", 2}, - {"Eeee", 3}, - {"Zzzz", 4}, - } - for i, tt := range tests { - if id, err := getScriptID(idx, b(tt.in)); id != tt.out { - t.Errorf("%d:%s: found %d; want %d", i, tt.in, id, tt.out) - } else if id == 0 && err == nil { - t.Errorf("%d:%s: no error; expected one", i, tt.in) - } - } -} - -func TestIsPrivateUse(t *testing.T) { - type test struct { - s string - private bool - } - tests := []test{ - {"en", false}, - {"und", false}, - {"pzn", false}, - {"qaa", true}, - {"qtz", true}, - {"qua", false}, - } - for i, tt := range tests { - x, _ := getLangID([]byte(tt.s)) - if b := x.IsPrivateUse(); b != tt.private { - t.Errorf("%d: langID.IsPrivateUse(%s) was %v; want %v", i, tt.s, b, tt.private) - } - } - tests = []test{ - {"001", false}, - {"419", false}, - {"899", false}, - {"900", false}, - {"957", false}, - {"958", true}, - {"AA", true}, - {"AC", false}, - {"EU", false}, // CLDR grouping, exceptionally reserved in ISO. - {"QU", true}, // Canonicalizes to EU, User-assigned in ISO. - {"QO", true}, // CLDR grouping, User-assigned in ISO. - {"QA", false}, - {"QM", true}, - {"QZ", true}, - {"XA", true}, - {"XK", true}, // Assigned to Kosovo in CLDR, User-assigned in ISO. - {"XZ", true}, - {"ZW", false}, - {"ZZ", true}, - } - for i, tt := range tests { - x, _ := getRegionID([]byte(tt.s)) - if b := x.IsPrivateUse(); b != tt.private { - t.Errorf("%d: regionID.IsPrivateUse(%s) was %v; want %v", i, tt.s, b, tt.private) - } - } - tests = []test{ - {"Latn", false}, - {"Laaa", false}, // invalid - {"Qaaa", true}, - {"Qabx", true}, - {"Qaby", false}, - {"Zyyy", false}, - {"Zzzz", false}, - } - for i, tt := range tests { - x, _ := getScriptID(script, []byte(tt.s)) - if b := x.IsPrivateUse(); b != tt.private { - t.Errorf("%d: scriptID.IsPrivateUse(%s) was %v; want %v", i, tt.s, b, tt.private) - } - } -} diff --git a/vendor/golang.org/x/text/language/match_test.go b/vendor/golang.org/x/text/language/match_test.go deleted file mode 100644 index 8b60b07a..00000000 --- a/vendor/golang.org/x/text/language/match_test.go +++ /dev/null @@ -1,505 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package language - -import ( - "bytes" - "flag" - "fmt" - "os" - "path" - "path/filepath" - "strings" - "testing" - - "golang.org/x/text/internal/testtext" - "golang.org/x/text/internal/ucd" -) - -var verbose = flag.Bool("verbose", false, "set to true to print the internal tables of matchers") - -func TestCompliance(t *testing.T) { - filepath.Walk("testdata", func(file string, info os.FileInfo, err error) error { - if info.IsDir() { - return nil - } - r, err := os.Open(file) - if err != nil { - t.Fatal(err) - } - ucd.Parse(r, func(p *ucd.Parser) { - name := strings.Replace(path.Join(p.String(0), p.String(1)), " ", "", -1) - if skip[name] { - return - } - t.Run(info.Name()+"/"+name, func(t *testing.T) { - supported := makeTagList(p.String(0)) - desired := makeTagList(p.String(1)) - gotCombined, index, conf := NewMatcher(supported).Match(desired...) - - gotMatch := supported[index] - wantMatch := mk(p.String(2)) - if gotMatch != wantMatch { - t.Fatalf("match: got %q; want %q (%v)", gotMatch, wantMatch, conf) - } - wantCombined, err := Raw.Parse(p.String(3)) - if err == nil && gotCombined != wantCombined { - t.Errorf("combined: got %q; want %q (%v)", gotCombined, wantCombined, conf) - } - }) - }) - return nil - }) -} - -var skip = map[string]bool{ - // TODO: bugs - // Honor the wildcard match. This may only be useful to select non-exact - // stuff. - "mul,af/nl": true, // match: got "af"; want "mul" - - // TODO: include other extensions. - // combined: got "en-GB-u-ca-buddhist-nu-arab"; want "en-GB-fonipa-t-m0-iso-i0-pinyin-u-ca-buddhist-nu-arab" - "und,en-GB-u-sd-gbsct/en-fonipa-u-nu-Arab-ca-buddhist-t-m0-iso-i0-pinyin": true, - - // Inconsistencies with Mark Davis' implementation where it is not clear - // which is better. - - // Inconsistencies in combined. I think the Go approach is more appropriate. - // We could use -u-rg- and -u-va- as alternative. - "und,fr/fr-BE-fonipa": true, // combined: got "fr"; want "fr-BE-fonipa" - "und,fr-CA/fr-BE-fonipa": true, // combined: got "fr-CA"; want "fr-BE-fonipa" - "und,fr-fonupa/fr-BE-fonipa": true, // combined: got "fr-fonupa"; want "fr-BE-fonipa" - "und,no/nn-BE-fonipa": true, // combined: got "no"; want "no-BE-fonipa" - "50,und,fr-CA-fonupa/fr-BE-fonipa": true, // combined: got "fr-CA-fonupa"; want "fr-BE-fonipa" - - // The initial number is a threshold. As we don't use scoring, we will not - // implement this. - "50,und,fr-Cyrl-CA-fonupa/fr-BE-fonipa": true, - // match: got "und"; want "fr-Cyrl-CA-fonupa" - // combined: got "und"; want "fr-Cyrl-BE-fonipa" - - // Other interesting cases to test: - // - Should same language or same script have the preference if there is - // usually no understanding of the other script? - // - More specific region in desired may replace enclosing supported. -} - -func makeTagList(s string) (tags []Tag) { - for _, s := range strings.Split(s, ",") { - tags = append(tags, mk(strings.TrimSpace(s))) - } - return tags -} - -func TestMatchStrings(t *testing.T) { - testCases := []struct { - supported string - desired string // strings separted by | - tag string - index int - }{{ - supported: "en", - desired: "", - tag: "en", - index: 0, - }, { - supported: "en", - desired: "nl", - tag: "en", - index: 0, - }, { - supported: "en,nl", - desired: "nl", - tag: "nl", - index: 1, - }, { - supported: "en,nl", - desired: "nl|en", - tag: "nl", - index: 1, - }, { - supported: "en-GB,nl", - desired: "en ; q=0.1,nl", - tag: "nl", - index: 1, - }, { - supported: "en-GB,nl", - desired: "en;q=0.005 | dk; q=0.1,nl ", - tag: "en-GB", - index: 0, - }, { - // do not match faulty tags with und - supported: "en,und", - desired: "|en", - tag: "en", - index: 0, - }} - for _, tc := range testCases { - t.Run(path.Join(tc.supported, tc.desired), func(t *testing.T) { - m := NewMatcher(makeTagList(tc.supported)) - tag, index := MatchStrings(m, strings.Split(tc.desired, "|")...) - if tag.String() != tc.tag || index != tc.index { - t.Errorf("got %v, %d; want %v, %d", tag, index, tc.tag, tc.index) - } - }) - } -} - -func TestAddLikelySubtags(t *testing.T) { - tests := []struct{ in, out string }{ - {"aa", "aa-Latn-ET"}, - {"aa-Latn", "aa-Latn-ET"}, - {"aa-Arab", "aa-Arab-ET"}, - {"aa-Arab-ER", "aa-Arab-ER"}, - {"kk", "kk-Cyrl-KZ"}, - {"kk-CN", "kk-Arab-CN"}, - {"cmn", "cmn"}, - {"zh-AU", "zh-Hant-AU"}, - {"zh-VN", "zh-Hant-VN"}, - {"zh-SG", "zh-Hans-SG"}, - {"zh-Hant", "zh-Hant-TW"}, - {"zh-Hani", "zh-Hani-CN"}, - {"und-Hani", "zh-Hani-CN"}, - {"und", "en-Latn-US"}, - {"und-GB", "en-Latn-GB"}, - {"und-CW", "pap-Latn-CW"}, - {"und-YT", "fr-Latn-YT"}, - {"und-Arab", "ar-Arab-EG"}, - {"und-AM", "hy-Armn-AM"}, - {"und-TW", "zh-Hant-TW"}, - {"und-002", "en-Latn-NG"}, - {"und-Latn-002", "en-Latn-NG"}, - {"en-Latn-002", "en-Latn-NG"}, - {"en-002", "en-Latn-NG"}, - {"en-001", "en-Latn-US"}, - {"und-003", "en-Latn-US"}, - {"und-GB", "en-Latn-GB"}, - {"Latn-001", "en-Latn-US"}, - {"en-001", "en-Latn-US"}, - {"es-419", "es-Latn-419"}, - {"he-145", "he-Hebr-IL"}, - {"ky-145", "ky-Latn-TR"}, - {"kk", "kk-Cyrl-KZ"}, - // Don't specialize duplicate and ambiguous matches. - {"kk-034", "kk-Arab-034"}, // Matches IR and AF. Both are Arab. - {"ku-145", "ku-Latn-TR"}, // Matches IQ, TR, and LB, but kk -> TR. - {"und-Arab-CC", "ms-Arab-CC"}, - {"und-Arab-GB", "ks-Arab-GB"}, - {"und-Hans-CC", "zh-Hans-CC"}, - {"und-CC", "en-Latn-CC"}, - {"sr", "sr-Cyrl-RS"}, - {"sr-151", "sr-Latn-151"}, // Matches RO and RU. - // We would like addLikelySubtags to generate the same results if the input - // only changes by adding tags that would otherwise have been added - // by the expansion. - // In other words: - // und-AA -> xx-Scrp-AA implies und-Scrp-AA -> xx-Scrp-AA - // und-AA -> xx-Scrp-AA implies xx-AA -> xx-Scrp-AA - // und-Scrp -> xx-Scrp-AA implies und-Scrp-AA -> xx-Scrp-AA - // und-Scrp -> xx-Scrp-AA implies xx-Scrp -> xx-Scrp-AA - // xx -> xx-Scrp-AA implies xx-Scrp -> xx-Scrp-AA - // xx -> xx-Scrp-AA implies xx-AA -> xx-Scrp-AA - // - // The algorithm specified in - // http://unicode.org/reports/tr35/tr35-9.html#Supplemental_Data, - // Section C.10, does not handle the first case. For example, - // the CLDR data contains an entry und-BJ -> fr-Latn-BJ, but not - // there is no rule for und-Latn-BJ. According to spec, und-Latn-BJ - // would expand to en-Latn-BJ, violating the aforementioned principle. - // We deviate from the spec by letting und-Scrp-AA expand to xx-Scrp-AA - // if a rule of the form und-AA -> xx-Scrp-AA is defined. - // Note that as of version 23, CLDR has some explicitly specified - // entries that do not conform to these rules. The implementation - // will not correct these explicit inconsistencies. A later versions of CLDR - // is supposed to fix this. - {"und-Latn-BJ", "fr-Latn-BJ"}, - {"und-Bugi-ID", "bug-Bugi-ID"}, - // regions, scripts and languages without definitions - {"und-Arab-AA", "ar-Arab-AA"}, - {"und-Afak-RE", "fr-Afak-RE"}, - {"und-Arab-GB", "ks-Arab-GB"}, - {"abp-Arab-GB", "abp-Arab-GB"}, - // script has preference over region - {"und-Arab-NL", "ar-Arab-NL"}, - {"zza", "zza-Latn-TR"}, - // preserve variants and extensions - {"de-1901", "de-Latn-DE-1901"}, - {"de-x-abc", "de-Latn-DE-x-abc"}, - {"de-1901-x-abc", "de-Latn-DE-1901-x-abc"}, - {"x-abc", "x-abc"}, // TODO: is this the desired behavior? - } - for i, tt := range tests { - in, _ := Parse(tt.in) - out, _ := Parse(tt.out) - in, _ = in.addLikelySubtags() - if in.String() != out.String() { - t.Errorf("%d: add(%s) was %s; want %s", i, tt.in, in, tt.out) - } - } -} -func TestMinimize(t *testing.T) { - tests := []struct{ in, out string }{ - {"aa", "aa"}, - {"aa-Latn", "aa"}, - {"aa-Latn-ET", "aa"}, - {"aa-ET", "aa"}, - {"aa-Arab", "aa-Arab"}, - {"aa-Arab-ER", "aa-Arab-ER"}, - {"aa-Arab-ET", "aa-Arab"}, - {"und", "und"}, - {"und-Latn", "und"}, - {"und-Latn-US", "und"}, - {"en-Latn-US", "en"}, - {"cmn", "cmn"}, - {"cmn-Hans", "cmn-Hans"}, - {"cmn-Hant", "cmn-Hant"}, - {"zh-AU", "zh-AU"}, - {"zh-VN", "zh-VN"}, - {"zh-SG", "zh-SG"}, - {"zh-Hant", "zh-Hant"}, - {"zh-Hant-TW", "zh-TW"}, - {"zh-Hans", "zh"}, - {"zh-Hani", "zh-Hani"}, - {"und-Hans", "und-Hans"}, - {"und-Hani", "und-Hani"}, - - {"und-CW", "und-CW"}, - {"und-YT", "und-YT"}, - {"und-Arab", "und-Arab"}, - {"und-AM", "und-AM"}, - {"und-Arab-CC", "und-Arab-CC"}, - {"und-CC", "und-CC"}, - {"und-Latn-BJ", "und-BJ"}, - {"und-Bugi-ID", "und-Bugi"}, - {"bug-Bugi-ID", "bug-Bugi"}, - // regions, scripts and languages without definitions - {"und-Arab-AA", "und-Arab-AA"}, - // preserve variants and extensions - {"de-Latn-1901", "de-1901"}, - {"de-Latn-x-abc", "de-x-abc"}, - {"de-DE-1901-x-abc", "de-1901-x-abc"}, - {"x-abc", "x-abc"}, // TODO: is this the desired behavior? - } - for i, tt := range tests { - in, _ := Parse(tt.in) - out, _ := Parse(tt.out) - min, _ := in.minimize() - if min.String() != out.String() { - t.Errorf("%d: min(%s) was %s; want %s", i, tt.in, min, tt.out) - } - max, _ := min.addLikelySubtags() - if x, _ := in.addLikelySubtags(); x.String() != max.String() { - t.Errorf("%d: max(min(%s)) = %s; want %s", i, tt.in, max, x) - } - } -} - -func TestRegionGroups(t *testing.T) { - testCases := []struct { - a, b string - distance uint8 - }{ - {"zh-TW", "zh-HK", 5}, - {"zh-MO", "zh-HK", 4}, - {"es-ES", "es-AR", 5}, - {"es-ES", "es", 4}, - {"es-419", "es-MX", 4}, - {"es-AR", "es-MX", 4}, - {"es-ES", "es-MX", 5}, - {"es-PT", "es-MX", 5}, - } - for _, tc := range testCases { - a := MustParse(tc.a) - aScript, _ := a.Script() - b := MustParse(tc.b) - bScript, _ := b.Script() - - if aScript != bScript { - t.Errorf("scripts differ: %q vs %q", aScript, bScript) - continue - } - d, _ := regionGroupDist(a.region, b.region, aScript.scriptID, a.lang) - if d != tc.distance { - t.Errorf("got %q; want %q", d, tc.distance) - } - } -} - -func TestIsParadigmLocale(t *testing.T) { - testCases := map[string]bool{ - "en-US": true, - "en-GB": true, - "en-VI": false, - "es-GB": false, - "es-ES": true, - "es-419": true, - } - for str, want := range testCases { - tag := Make(str) - got := isParadigmLocale(tag.lang, tag.region) - if got != want { - t.Errorf("isPL(%q) = %v; want %v", str, got, want) - } - } -} - -// Implementation of String methods for various types for debugging purposes. - -func (m *matcher) String() string { - w := &bytes.Buffer{} - fmt.Fprintln(w, "Default:", m.default_) - for tag, h := range m.index { - fmt.Fprintf(w, " %s: %v\n", tag, h) - } - return w.String() -} - -func (h *matchHeader) String() string { - w := &bytes.Buffer{} - fmt.Fprint(w, "haveTag: ") - for _, h := range h.haveTags { - fmt.Fprintf(w, "%v, ", h) - } - return w.String() -} - -func (t haveTag) String() string { - return fmt.Sprintf("%v:%d:%v:%v-%v|%v", t.tag, t.index, t.conf, t.maxRegion, t.maxScript, t.altScript) -} - -func TestBestMatchAlloc(t *testing.T) { - m := NewMatcher(makeTagList("en sr nl")) - // Go allocates when creating a list of tags from a single tag! - list := []Tag{English} - avg := testtext.AllocsPerRun(1, func() { - m.Match(list...) - }) - if avg > 0 { - t.Errorf("got %f; want 0", avg) - } -} - -var benchHave = []Tag{ - mk("en"), - mk("en-GB"), - mk("za"), - mk("zh-Hant"), - mk("zh-Hans-CN"), - mk("zh"), - mk("zh-HK"), - mk("ar-MK"), - mk("en-CA"), - mk("fr-CA"), - mk("fr-US"), - mk("fr-CH"), - mk("fr"), - mk("lt"), - mk("lv"), - mk("iw"), - mk("iw-NL"), - mk("he"), - mk("he-IT"), - mk("tlh"), - mk("ja"), - mk("ja-Jpan"), - mk("ja-Jpan-JP"), - mk("de"), - mk("de-CH"), - mk("de-AT"), - mk("de-DE"), - mk("sr"), - mk("sr-Latn"), - mk("sr-Cyrl"), - mk("sr-ME"), -} - -var benchWant = [][]Tag{ - []Tag{ - mk("en"), - }, - []Tag{ - mk("en-AU"), - mk("de-HK"), - mk("nl"), - mk("fy"), - mk("lv"), - }, - []Tag{ - mk("en-AU"), - mk("de-HK"), - mk("nl"), - mk("fy"), - }, - []Tag{ - mk("ja-Hant"), - mk("da-HK"), - mk("nl"), - mk("zh-TW"), - }, - []Tag{ - mk("ja-Hant"), - mk("da-HK"), - mk("nl"), - mk("hr"), - }, -} - -func BenchmarkMatch(b *testing.B) { - m := newMatcher(benchHave, nil) - for i := 0; i < b.N; i++ { - for _, want := range benchWant { - m.getBest(want...) - } - } -} - -func BenchmarkMatchExact(b *testing.B) { - want := mk("en") - m := newMatcher(benchHave, nil) - for i := 0; i < b.N; i++ { - m.getBest(want) - } -} - -func BenchmarkMatchAltLanguagePresent(b *testing.B) { - want := mk("hr") - m := newMatcher(benchHave, nil) - for i := 0; i < b.N; i++ { - m.getBest(want) - } -} - -func BenchmarkMatchAltLanguageNotPresent(b *testing.B) { - want := mk("nn") - m := newMatcher(benchHave, nil) - for i := 0; i < b.N; i++ { - m.getBest(want) - } -} - -func BenchmarkMatchAltScriptPresent(b *testing.B) { - want := mk("zh-Hant-CN") - m := newMatcher(benchHave, nil) - for i := 0; i < b.N; i++ { - m.getBest(want) - } -} - -func BenchmarkMatchAltScriptNotPresent(b *testing.B) { - want := mk("fr-Cyrl") - m := newMatcher(benchHave, nil) - for i := 0; i < b.N; i++ { - m.getBest(want) - } -} - -func BenchmarkMatchLimitedExact(b *testing.B) { - want := []Tag{mk("he-NL"), mk("iw-NL")} - m := newMatcher(benchHave, nil) - for i := 0; i < b.N; i++ { - m.getBest(want...) - } -} diff --git a/vendor/golang.org/x/text/language/parse_test.go b/vendor/golang.org/x/text/language/parse_test.go deleted file mode 100644 index 9b40eb44..00000000 --- a/vendor/golang.org/x/text/language/parse_test.go +++ /dev/null @@ -1,517 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package language - -import ( - "bytes" - "strings" - "testing" - - "golang.org/x/text/internal/tag" -) - -type scanTest struct { - ok bool // true if scanning does not result in an error - in string - tok []string // the expected tokens -} - -var tests = []scanTest{ - {true, "", []string{}}, - {true, "1", []string{"1"}}, - {true, "en", []string{"en"}}, - {true, "root", []string{"root"}}, - {true, "maxchars", []string{"maxchars"}}, - {false, "bad/", []string{}}, - {false, "morethan8", []string{}}, - {false, "-", []string{}}, - {false, "----", []string{}}, - {false, "_", []string{}}, - {true, "en-US", []string{"en", "US"}}, - {true, "en_US", []string{"en", "US"}}, - {false, "en-US-", []string{"en", "US"}}, - {false, "en-US--", []string{"en", "US"}}, - {false, "en-US---", []string{"en", "US"}}, - {false, "en--US", []string{"en", "US"}}, - {false, "-en-US", []string{"en", "US"}}, - {false, "-en--US-", []string{"en", "US"}}, - {false, "-en--US-", []string{"en", "US"}}, - {false, "en-.-US", []string{"en", "US"}}, - {false, ".-en--US-.", []string{"en", "US"}}, - {false, "en-u.-US", []string{"en", "US"}}, - {true, "en-u1-US", []string{"en", "u1", "US"}}, - {true, "maxchar1_maxchar2-maxchar3", []string{"maxchar1", "maxchar2", "maxchar3"}}, - {false, "moreThan8-moreThan8-e", []string{"e"}}, -} - -func TestScan(t *testing.T) { - for i, tt := range tests { - scan := makeScannerString(tt.in) - for j := 0; !scan.done; j++ { - if j >= len(tt.tok) { - t.Errorf("%d: extra token %q", i, scan.token) - } else if tag.Compare(tt.tok[j], scan.token) != 0 { - t.Errorf("%d: token %d: found %q; want %q", i, j, scan.token, tt.tok[j]) - break - } - scan.scan() - } - if s := strings.Join(tt.tok, "-"); tag.Compare(s, bytes.Replace(scan.b, b("_"), b("-"), -1)) != 0 { - t.Errorf("%d: input: found %q; want %q", i, scan.b, s) - } - if (scan.err == nil) != tt.ok { - t.Errorf("%d: ok: found %v; want %v", i, scan.err == nil, tt.ok) - } - } -} - -func TestAcceptMinSize(t *testing.T) { - for i, tt := range tests { - // count number of successive tokens with a minimum size. - for sz := 1; sz <= 8; sz++ { - scan := makeScannerString(tt.in) - scan.end, scan.next = 0, 0 - end := scan.acceptMinSize(sz) - n := 0 - for i := 0; i < len(tt.tok) && len(tt.tok[i]) >= sz; i++ { - n += len(tt.tok[i]) - if i > 0 { - n++ - } - } - if end != n { - t.Errorf("%d:%d: found len %d; want %d", i, sz, end, n) - } - } - } -} - -type parseTest struct { - i int // the index of this test - in string - lang, script, region string - variants, ext string - extList []string // only used when more than one extension is present - invalid bool - rewrite bool // special rewrite not handled by parseTag - changed bool // string needed to be reformatted -} - -func parseTests() []parseTest { - tests := []parseTest{ - {in: "root", lang: "und"}, - {in: "und", lang: "und"}, - {in: "en", lang: "en"}, - {in: "xy", lang: "und", invalid: true}, - {in: "en-ZY", lang: "en", invalid: true}, - {in: "gsw", lang: "gsw"}, - {in: "sr_Latn", lang: "sr", script: "Latn"}, - {in: "af-Arab", lang: "af", script: "Arab"}, - {in: "nl-BE", lang: "nl", region: "BE"}, - {in: "es-419", lang: "es", region: "419"}, - {in: "und-001", lang: "und", region: "001"}, - {in: "de-latn-be", lang: "de", script: "Latn", region: "BE"}, - // Variants - {in: "de-1901", lang: "de", variants: "1901"}, - // Accept with unsuppressed script. - {in: "de-Latn-1901", lang: "de", script: "Latn", variants: "1901"}, - // Specialized. - {in: "sl-rozaj", lang: "sl", variants: "rozaj"}, - {in: "sl-rozaj-lipaw", lang: "sl", variants: "rozaj-lipaw"}, - {in: "sl-rozaj-biske", lang: "sl", variants: "rozaj-biske"}, - {in: "sl-rozaj-biske-1994", lang: "sl", variants: "rozaj-biske-1994"}, - {in: "sl-rozaj-1994", lang: "sl", variants: "rozaj-1994"}, - // Maximum number of variants while adhering to prefix rules. - {in: "sl-rozaj-biske-1994-alalc97-fonipa-fonupa-fonxsamp", lang: "sl", variants: "rozaj-biske-1994-alalc97-fonipa-fonupa-fonxsamp"}, - - // Sorting. - {in: "sl-1994-biske-rozaj", lang: "sl", variants: "rozaj-biske-1994", changed: true}, - {in: "sl-rozaj-biske-1994-alalc97-fonupa-fonipa-fonxsamp", lang: "sl", variants: "rozaj-biske-1994-alalc97-fonipa-fonupa-fonxsamp", changed: true}, - {in: "nl-fonxsamp-alalc97-fonipa-fonupa", lang: "nl", variants: "alalc97-fonipa-fonupa-fonxsamp", changed: true}, - - // Duplicates variants are removed, but not an error. - {in: "nl-fonupa-fonupa", lang: "nl", variants: "fonupa"}, - - // Variants that do not have correct prefixes. We still accept these. - {in: "de-Cyrl-1901", lang: "de", script: "Cyrl", variants: "1901"}, - {in: "sl-rozaj-lipaw-1994", lang: "sl", variants: "rozaj-lipaw-1994"}, - {in: "sl-1994-biske-rozaj-1994-biske-rozaj", lang: "sl", variants: "rozaj-biske-1994", changed: true}, - {in: "de-Cyrl-1901", lang: "de", script: "Cyrl", variants: "1901"}, - - // Invalid variant. - {in: "de-1902", lang: "de", variants: "", invalid: true}, - - {in: "EN_CYRL", lang: "en", script: "Cyrl"}, - // private use and extensions - {in: "x-a-b-c-d", ext: "x-a-b-c-d"}, - {in: "x_A.-B-C_D", ext: "x-b-c-d", invalid: true, changed: true}, - {in: "x-aa-bbbb-cccccccc-d", ext: "x-aa-bbbb-cccccccc-d"}, - {in: "en-c_cc-b-bbb-a-aaa", lang: "en", changed: true, extList: []string{"a-aaa", "b-bbb", "c-cc"}}, - {in: "en-x_cc-b-bbb-a-aaa", lang: "en", ext: "x-cc-b-bbb-a-aaa", changed: true}, - {in: "en-c_cc-b-bbb-a-aaa-x-x", lang: "en", changed: true, extList: []string{"a-aaa", "b-bbb", "c-cc", "x-x"}}, - {in: "en-v-c", lang: "en", ext: "", invalid: true}, - {in: "en-v-abcdefghi", lang: "en", ext: "", invalid: true}, - {in: "en-v-abc-x", lang: "en", ext: "v-abc", invalid: true}, - {in: "en-v-abc-x-", lang: "en", ext: "v-abc", invalid: true}, - {in: "en-v-abc-w-x-xx", lang: "en", extList: []string{"v-abc", "x-xx"}, invalid: true, changed: true}, - {in: "en-v-abc-w-y-yx", lang: "en", extList: []string{"v-abc", "y-yx"}, invalid: true, changed: true}, - {in: "en-v-c-abc", lang: "en", ext: "c-abc", invalid: true, changed: true}, - {in: "en-v-w-abc", lang: "en", ext: "w-abc", invalid: true, changed: true}, - {in: "en-v-x-abc", lang: "en", ext: "x-abc", invalid: true, changed: true}, - {in: "en-v-x-a", lang: "en", ext: "x-a", invalid: true, changed: true}, - {in: "en-9-aa-0-aa-z-bb-x-a", lang: "en", extList: []string{"0-aa", "9-aa", "z-bb", "x-a"}, changed: true}, - {in: "en-u-c", lang: "en", ext: "", invalid: true}, - {in: "en-u-co-phonebk", lang: "en", ext: "u-co-phonebk"}, - {in: "en-u-co-phonebk-ca", lang: "en", ext: "u-co-phonebk", invalid: true}, - {in: "en-u-nu-arabic-co-phonebk-ca", lang: "en", ext: "u-co-phonebk-nu-arabic", invalid: true, changed: true}, - {in: "en-u-nu-arabic-co-phonebk-ca-x", lang: "en", ext: "u-co-phonebk-nu-arabic", invalid: true, changed: true}, - {in: "en-u-nu-arabic-co-phonebk-ca-s", lang: "en", ext: "u-co-phonebk-nu-arabic", invalid: true, changed: true}, - {in: "en-u-nu-arabic-co-phonebk-ca-a12345678", lang: "en", ext: "u-co-phonebk-nu-arabic", invalid: true, changed: true}, - {in: "en-u-co-phonebook", lang: "en", ext: "", invalid: true}, - {in: "en-u-co-phonebook-cu-xau", lang: "en", ext: "u-cu-xau", invalid: true, changed: true}, - {in: "en-Cyrl-u-co-phonebk", lang: "en", script: "Cyrl", ext: "u-co-phonebk"}, - {in: "en-US-u-co-phonebk", lang: "en", region: "US", ext: "u-co-phonebk"}, - {in: "en-US-u-co-phonebk-cu-xau", lang: "en", region: "US", ext: "u-co-phonebk-cu-xau"}, - {in: "en-scotland-u-co-phonebk", lang: "en", variants: "scotland", ext: "u-co-phonebk"}, - {in: "en-u-cu-xua-co-phonebk", lang: "en", ext: "u-co-phonebk-cu-xua", changed: true}, - {in: "en-u-def-abc-cu-xua-co-phonebk", lang: "en", ext: "u-abc-def-co-phonebk-cu-xua", changed: true}, - {in: "en-u-def-abc", lang: "en", ext: "u-abc-def", changed: true}, - {in: "en-u-cu-xua-co-phonebk-a-cd", lang: "en", extList: []string{"a-cd", "u-co-phonebk-cu-xua"}, changed: true}, - // Invalid "u" extension. Drop invalid parts. - {in: "en-u-cu-co-phonebk", lang: "en", extList: []string{"u-co-phonebk"}, invalid: true, changed: true}, - {in: "en-u-cu-xau-co", lang: "en", extList: []string{"u-cu-xau"}, invalid: true}, - // We allow duplicate keys as the LDML spec does not explicitly prohibit it. - // TODO: Consider eliminating duplicates and returning an error. - {in: "en-u-cu-xau-co-phonebk-cu-xau", lang: "en", ext: "u-co-phonebk-cu-xau-cu-xau", changed: true}, - {in: "en-t-en-Cyrl-NL-fonipa", lang: "en", ext: "t-en-cyrl-nl-fonipa", changed: true}, - {in: "en-t-en-Cyrl-NL-fonipa-t0-abc-def", lang: "en", ext: "t-en-cyrl-nl-fonipa-t0-abc-def", changed: true}, - {in: "en-t-t0-abcd", lang: "en", ext: "t-t0-abcd"}, - // Not necessary to have changed here. - {in: "en-t-nl-abcd", lang: "en", ext: "t-nl", invalid: true}, - {in: "en-t-nl-latn", lang: "en", ext: "t-nl-latn"}, - {in: "en-t-t0-abcd-x-a", lang: "en", extList: []string{"t-t0-abcd", "x-a"}}, - // invalid - {in: "", lang: "und", invalid: true}, - {in: "-", lang: "und", invalid: true}, - {in: "x", lang: "und", invalid: true}, - {in: "x-", lang: "und", invalid: true}, - {in: "x--", lang: "und", invalid: true}, - {in: "a-a-b-c-d", lang: "und", invalid: true}, - {in: "en-", lang: "en", invalid: true}, - {in: "enne-", lang: "und", invalid: true}, - {in: "en.", lang: "und", invalid: true}, - {in: "en.-latn", lang: "und", invalid: true}, - {in: "en.-en", lang: "en", invalid: true}, - {in: "x-a-tooManyChars-c-d", ext: "x-a-c-d", invalid: true, changed: true}, - {in: "a-tooManyChars-c-d", lang: "und", invalid: true}, - // TODO: check key-value validity - // { in: "en-u-cu-xd", lang: "en", ext: "u-cu-xd", invalid: true }, - {in: "en-t-abcd", lang: "en", invalid: true}, - {in: "en-Latn-US-en", lang: "en", script: "Latn", region: "US", invalid: true}, - // rewrites (more tests in TestGrandfathered) - {in: "zh-min-nan", lang: "nan"}, - {in: "zh-yue", lang: "yue"}, - {in: "zh-xiang", lang: "hsn", rewrite: true}, - {in: "zh-guoyu", lang: "cmn", rewrite: true}, - {in: "iw", lang: "iw"}, - {in: "sgn-BE-FR", lang: "sfb", rewrite: true}, - {in: "i-klingon", lang: "tlh", rewrite: true}, - } - for i, tt := range tests { - tests[i].i = i - if tt.extList != nil { - tests[i].ext = strings.Join(tt.extList, "-") - } - if tt.ext != "" && tt.extList == nil { - tests[i].extList = []string{tt.ext} - } - } - return tests -} - -func TestParseExtensions(t *testing.T) { - for i, tt := range parseTests() { - if tt.ext == "" || tt.rewrite { - continue - } - scan := makeScannerString(tt.in) - if len(scan.b) > 1 && scan.b[1] != '-' { - scan.end = nextExtension(string(scan.b), 0) - scan.next = scan.end + 1 - scan.scan() - } - start := scan.start - scan.toLower(start, len(scan.b)) - parseExtensions(&scan) - ext := string(scan.b[start:]) - if ext != tt.ext { - t.Errorf("%d(%s): ext was %v; want %v", i, tt.in, ext, tt.ext) - } - if changed := !strings.HasPrefix(tt.in[start:], ext); changed != tt.changed { - t.Errorf("%d(%s): changed was %v; want %v", i, tt.in, changed, tt.changed) - } - } -} - -// partChecks runs checks for each part by calling the function returned by f. -func partChecks(t *testing.T, f func(*parseTest) (Tag, bool)) { - for i, tt := range parseTests() { - tag, skip := f(&tt) - if skip { - continue - } - if l, _ := getLangID(b(tt.lang)); l != tag.lang { - t.Errorf("%d: lang was %q; want %q", i, tag.lang, l) - } - if sc, _ := getScriptID(script, b(tt.script)); sc != tag.script { - t.Errorf("%d: script was %q; want %q", i, tag.script, sc) - } - if r, _ := getRegionID(b(tt.region)); r != tag.region { - t.Errorf("%d: region was %q; want %q", i, tag.region, r) - } - if tag.str == "" { - continue - } - p := int(tag.pVariant) - if p < int(tag.pExt) { - p++ - } - if s, g := tag.str[p:tag.pExt], tt.variants; s != g { - t.Errorf("%d: variants was %q; want %q", i, s, g) - } - p = int(tag.pExt) - if p > 0 && p < len(tag.str) { - p++ - } - if s, g := (tag.str)[p:], tt.ext; s != g { - t.Errorf("%d: extensions were %q; want %q", i, s, g) - } - } -} - -func TestParseTag(t *testing.T) { - partChecks(t, func(tt *parseTest) (id Tag, skip bool) { - if strings.HasPrefix(tt.in, "x-") || tt.rewrite { - return Tag{}, true - } - scan := makeScannerString(tt.in) - id, end := parseTag(&scan) - id.str = string(scan.b[:end]) - tt.ext = "" - tt.extList = []string{} - return id, false - }) -} - -func TestParse(t *testing.T) { - partChecks(t, func(tt *parseTest) (id Tag, skip bool) { - id, err := Raw.Parse(tt.in) - ext := "" - if id.str != "" { - if strings.HasPrefix(id.str, "x-") { - ext = id.str - } else if int(id.pExt) < len(id.str) && id.pExt > 0 { - ext = id.str[id.pExt+1:] - } - } - if tag, _ := Raw.Parse(id.String()); tag.String() != id.String() { - t.Errorf("%d:%s: reparse was %q; want %q", tt.i, tt.in, id.String(), tag.String()) - } - if ext != tt.ext { - t.Errorf("%d:%s: ext was %q; want %q", tt.i, tt.in, ext, tt.ext) - } - changed := id.str != "" && !strings.HasPrefix(tt.in, id.str) - if changed != tt.changed { - t.Errorf("%d:%s: changed was %v; want %v", tt.i, tt.in, changed, tt.changed) - } - if (err != nil) != tt.invalid { - t.Errorf("%d:%s: invalid was %v; want %v. Error: %v", tt.i, tt.in, err != nil, tt.invalid, err) - } - return id, false - }) -} - -func TestErrors(t *testing.T) { - mkInvalid := func(s string) error { - return mkErrInvalid([]byte(s)) - } - tests := []struct { - in string - out error - }{ - // invalid subtags. - {"ac", mkInvalid("ac")}, - {"AC", mkInvalid("ac")}, - {"aa-Uuuu", mkInvalid("Uuuu")}, - {"aa-AB", mkInvalid("AB")}, - // ill-formed wins over invalid. - {"ac-u", errSyntax}, - {"ac-u-ca", errSyntax}, - {"ac-u-ca-co-pinyin", errSyntax}, - {"noob", errSyntax}, - } - for _, tt := range tests { - _, err := Parse(tt.in) - if err != tt.out { - t.Errorf("%s: was %q; want %q", tt.in, err, tt.out) - } - } -} - -func TestCompose1(t *testing.T) { - partChecks(t, func(tt *parseTest) (id Tag, skip bool) { - l, _ := ParseBase(tt.lang) - s, _ := ParseScript(tt.script) - r, _ := ParseRegion(tt.region) - v := []Variant{} - for _, x := range strings.Split(tt.variants, "-") { - p, _ := ParseVariant(x) - v = append(v, p) - } - e := []Extension{} - for _, x := range tt.extList { - p, _ := ParseExtension(x) - e = append(e, p) - } - id, _ = Raw.Compose(l, s, r, v, e) - return id, false - }) -} - -func TestCompose2(t *testing.T) { - partChecks(t, func(tt *parseTest) (id Tag, skip bool) { - l, _ := ParseBase(tt.lang) - s, _ := ParseScript(tt.script) - r, _ := ParseRegion(tt.region) - p := []interface{}{l, s, r, s, r, l} - for _, x := range strings.Split(tt.variants, "-") { - v, _ := ParseVariant(x) - p = append(p, v) - } - for _, x := range tt.extList { - e, _ := ParseExtension(x) - p = append(p, e) - } - id, _ = Raw.Compose(p...) - return id, false - }) -} - -func TestCompose3(t *testing.T) { - partChecks(t, func(tt *parseTest) (id Tag, skip bool) { - id, _ = Raw.Parse(tt.in) - id, _ = Raw.Compose(id) - return id, false - }) -} - -func mk(s string) Tag { - return Raw.Make(s) -} - -func TestParseAcceptLanguage(t *testing.T) { - type res struct { - t Tag - q float32 - } - en := []res{{mk("en"), 1.0}} - tests := []struct { - out []res - in string - ok bool - }{ - {en, "en", true}, - {en, " en", true}, - {en, "en ", true}, - {en, " en ", true}, - {en, "en,", true}, - {en, ",en", true}, - {en, ",,,en,,,", true}, - {en, ",en;q=1", true}, - - // We allow an empty input, contrary to spec. - {nil, "", true}, - {[]res{{mk("aa"), 1}}, "aa;", true}, // allow unspecified weight - - // errors - {nil, ";", false}, - {nil, "$", false}, - {nil, "e;", false}, - {nil, "x;", false}, - {nil, "x", false}, - {nil, "ac", false}, // non-existing language - {nil, "aa;q", false}, - {nil, "aa;q=", false}, - {nil, "aa;q=.", false}, - - // odd fallbacks - { - []res{{mk("en"), 0.1}}, - " english ;q=.1", - true, - }, - { - []res{{mk("it"), 1.0}, {mk("de"), 1.0}, {mk("fr"), 1.0}}, - " italian, deutsch, french", - true, - }, - - // lists - { - []res{{mk("en"), 0.1}}, - "en;q=.1", - true, - }, - { - []res{{mk("mul"), 1.0}}, - "*", - true, - }, - { - []res{{mk("en"), 1.0}, {mk("de"), 1.0}}, - "en,de", - true, - }, - { - []res{{mk("en"), 1.0}, {mk("de"), .5}}, - "en,de;q=0.5", - true, - }, - { - []res{{mk("de"), 0.8}, {mk("en"), 0.5}}, - " en ; q = 0.5 , , de;q=0.8", - true, - }, - { - []res{{mk("en"), 1.0}, {mk("de"), 1.0}, {mk("fr"), 1.0}, {mk("tlh"), 1.0}}, - "en,de,fr,i-klingon", - true, - }, - // sorting - { - []res{{mk("tlh"), 0.4}, {mk("de"), 0.2}, {mk("fr"), 0.2}, {mk("en"), 0.1}}, - "en;q=0.1,de;q=0.2,fr;q=0.2,i-klingon;q=0.4", - true, - }, - // dropping - { - []res{{mk("fr"), 0.2}, {mk("en"), 0.1}}, - "en;q=0.1,de;q=0,fr;q=0.2,i-klingon;q=0.0", - true, - }, - } - for i, tt := range tests { - tags, qs, e := ParseAcceptLanguage(tt.in) - if e == nil != tt.ok { - t.Errorf("%d:%s:err: was %v; want %v", i, tt.in, e == nil, tt.ok) - } - for j, tag := range tags { - if out := tt.out[j]; !tag.equalTags(out.t) || qs[j] != out.q { - t.Errorf("%d:%s: was %s, %1f; want %s, %1f", i, tt.in, tag, qs[j], out.t, out.q) - break - } - } - } -} diff --git a/vendor/golang.org/x/text/secure/bidirule/bench_test.go b/vendor/golang.org/x/text/secure/bidirule/bench_test.go deleted file mode 100644 index 2db922bf..00000000 --- a/vendor/golang.org/x/text/secure/bidirule/bench_test.go +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package bidirule - -import ( - "testing" - - "golang.org/x/text/internal/testtext" -) - -var benchData = []struct{ name, data string }{ - {"ascii", "Scheveningen"}, - {"arabic", "دبي"}, - {"hangul", "다음과"}, -} - -func doBench(b *testing.B, fn func(b *testing.B, data string)) { - for _, d := range benchData { - testtext.Bench(b, d.name, func(b *testing.B) { fn(b, d.data) }) - } -} - -func BenchmarkSpan(b *testing.B) { - r := New() - doBench(b, func(b *testing.B, str string) { - b.SetBytes(int64(len(str))) - data := []byte(str) - for i := 0; i < b.N; i++ { - r.Reset() - r.Span(data, true) - } - }) -} - -func BenchmarkDirectionASCII(b *testing.B) { - doBench(b, func(b *testing.B, str string) { - b.SetBytes(int64(len(str))) - data := []byte(str) - for i := 0; i < b.N; i++ { - Direction(data) - } - }) -} - -func BenchmarkDirectionStringASCII(b *testing.B) { - doBench(b, func(b *testing.B, str string) { - b.SetBytes(int64(len(str))) - for i := 0; i < b.N; i++ { - DirectionString(str) - } - }) -} diff --git a/vendor/golang.org/x/text/secure/bidirule/bidirule10.0.0_test.go b/vendor/golang.org/x/text/secure/bidirule/bidirule10.0.0_test.go deleted file mode 100644 index 06ec5f5d..00000000 --- a/vendor/golang.org/x/text/secure/bidirule/bidirule10.0.0_test.go +++ /dev/null @@ -1,694 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build go1.10 - -package bidirule - -import ( - "golang.org/x/text/transform" - "golang.org/x/text/unicode/bidi" -) - -var testCases = [][]ruleTest{ - // Go-specific rules. - // Invalid UTF-8 is invalid. - 0: []ruleTest{{ - in: "", - dir: bidi.LeftToRight, - }, { - in: "\x80", - dir: bidi.LeftToRight, - err: ErrInvalid, - n: 0, - }, { - in: "\xcc", - dir: bidi.LeftToRight, - err: ErrInvalid, - n: 0, - }, { - in: "abc\x80", - dir: bidi.LeftToRight, - err: ErrInvalid, - n: 3, - }, { - in: "abc\xcc", - dir: bidi.LeftToRight, - err: ErrInvalid, - n: 3, - }, { - in: "abc\xccdef", - dir: bidi.LeftToRight, - err: ErrInvalid, - n: 3, - }, { - in: "\xccdef", - dir: bidi.LeftToRight, - err: ErrInvalid, - n: 0, - }, { - in: strR + "\x80", - dir: bidi.RightToLeft, - err: ErrInvalid, - n: len(strR), - }, { - in: strR + "\xcc", - dir: bidi.RightToLeft, - err: ErrInvalid, - n: len(strR), - }, { - in: strAL + "\xcc" + strR, - dir: bidi.RightToLeft, - err: ErrInvalid, - n: len(strAL), - }, { - in: "\xcc" + strR, - dir: bidi.RightToLeft, - err: ErrInvalid, - n: 0, - }}, - - // Rule 2.1: The first character must be a character with Bidi property L, - // R, or AL. If it has the R or AL property, it is an RTL label; if it has - // the L property, it is an LTR label. - 1: []ruleTest{{ - in: strL, - dir: bidi.LeftToRight, - }, { - in: strR, - dir: bidi.RightToLeft, - }, { - in: strAL, - dir: bidi.RightToLeft, - }, { - in: strAN, - dir: bidi.RightToLeft, - err: ErrInvalid, - }, { - in: strEN, - dir: bidi.LeftToRight, - err: ErrInvalid, - n: len(strEN), - }, { - in: strES, - dir: bidi.LeftToRight, - err: ErrInvalid, - n: len(strES), - }, { - in: strET, - dir: bidi.LeftToRight, - err: ErrInvalid, - n: len(strET), - }, { - in: strCS, - dir: bidi.LeftToRight, - err: ErrInvalid, - n: len(strCS), - }, { - in: strNSM, - dir: bidi.LeftToRight, - err: ErrInvalid, - n: len(strNSM), - }, { - in: strBN, - dir: bidi.LeftToRight, - err: ErrInvalid, - n: len(strBN), - }, { - in: strB, - dir: bidi.LeftToRight, - err: ErrInvalid, - n: len(strB), - }, { - in: strS, - dir: bidi.LeftToRight, - err: ErrInvalid, - n: len(strS), - }, { - in: strWS, - dir: bidi.LeftToRight, - err: ErrInvalid, - n: len(strWS), - }, { - in: strON, - dir: bidi.LeftToRight, - err: ErrInvalid, - n: len(strON), - }, { - in: strEN + strR, - dir: bidi.RightToLeft, - err: ErrInvalid, - n: 3, - }, { - in: strES + strR, - dir: bidi.RightToLeft, - err: ErrInvalid, - n: 2, - }, { - in: strET + strR, - dir: bidi.RightToLeft, - err: ErrInvalid, - n: 1, - }, { - in: strCS + strR, - dir: bidi.RightToLeft, - err: ErrInvalid, - n: 1, - }, { - in: strNSM + strR, - dir: bidi.RightToLeft, - err: ErrInvalid, - n: 2, - }, { - in: strBN + strR, - dir: bidi.RightToLeft, - err: ErrInvalid, - n: 3, - }, { - in: strB + strR, - dir: bidi.RightToLeft, - err: ErrInvalid, - n: 3, - }, { - in: strS + strR, - dir: bidi.RightToLeft, - err: ErrInvalid, - n: 1, - }, { - in: strWS + strR, - dir: bidi.RightToLeft, - err: ErrInvalid, - n: 1, - }, { - in: strON + strR, - dir: bidi.RightToLeft, - err: ErrInvalid, - n: 1, - }}, - - // Rule 2.2: In an RTL label, only characters with the Bidi properties R, - // AL, AN, EN, ES, CS, ET, ON, BN, or NSM are allowed. - 2: []ruleTest{{ - in: strR + strR + strAL, - dir: bidi.RightToLeft, - }, { - in: strR + strAL + strR, - dir: bidi.RightToLeft, - }, { - in: strR + strAN + strAL, - dir: bidi.RightToLeft, - }, { - in: strR + strEN + strR, - dir: bidi.RightToLeft, - }, { - in: strR + strES + strR, - dir: bidi.RightToLeft, - }, { - in: strR + strCS + strR, - dir: bidi.RightToLeft, - }, { - in: strR + strET + strAL, - dir: bidi.RightToLeft, - }, { - in: strR + strON + strR, - dir: bidi.RightToLeft, - }, { - in: strR + strBN + strR, - dir: bidi.RightToLeft, - }, { - in: strR + strNSM + strAL, - dir: bidi.RightToLeft, - }, { - in: strR + strL + strR, - dir: bidi.RightToLeft, - n: len(strR), - err: ErrInvalid, - }, { - in: strR + strB + strR, - dir: bidi.RightToLeft, - n: len(strR), - err: ErrInvalid, - }, { - in: strR + strS + strAL, - dir: bidi.RightToLeft, - n: len(strR), - err: ErrInvalid, - }, { - in: strR + strWS + strAL, - dir: bidi.RightToLeft, - n: len(strR), - err: ErrInvalid, - }, { - in: strAL + strR + strAL, - dir: bidi.RightToLeft, - }, { - in: strAL + strAL + strR, - dir: bidi.RightToLeft, - }, { - in: strAL + strAN + strAL, - dir: bidi.RightToLeft, - }, { - in: strAL + strEN + strR, - dir: bidi.RightToLeft, - }, { - in: strAL + strES + strR, - dir: bidi.RightToLeft, - }, { - in: strAL + strCS + strR, - dir: bidi.RightToLeft, - }, { - in: strAL + strET + strAL, - dir: bidi.RightToLeft, - }, { - in: strAL + strON + strR, - dir: bidi.RightToLeft, - }, { - in: strAL + strBN + strR, - dir: bidi.RightToLeft, - }, { - in: strAL + strNSM + strAL, - dir: bidi.RightToLeft, - }, { - in: strAL + strL + strR, - dir: bidi.RightToLeft, - n: len(strAL), - err: ErrInvalid, - }, { - in: strAL + strB + strR, - dir: bidi.RightToLeft, - n: len(strAL), - err: ErrInvalid, - }, { - in: strAL + strS + strAL, - dir: bidi.RightToLeft, - n: len(strAL), - err: ErrInvalid, - }, { - in: strAL + strWS + strAL, - dir: bidi.RightToLeft, - n: len(strAL), - err: ErrInvalid, - }}, - - // Rule 2.3: In an RTL label, the end of the label must be a character with - // Bidi property R, AL, EN, or AN, followed by zero or more characters with - // Bidi property NSM. - 3: []ruleTest{{ - in: strR + strNSM, - dir: bidi.RightToLeft, - }, { - in: strR + strR, - dir: bidi.RightToLeft, - }, { - in: strR + strAL + strNSM, - dir: bidi.RightToLeft, - }, { - in: strR + strEN + strNSM + strNSM, - dir: bidi.RightToLeft, - }, { - in: strR + strAN, - dir: bidi.RightToLeft, - }, { - in: strR + strES + strNSM, - dir: bidi.RightToLeft, - n: len(strR + strES + strNSM), - err: ErrInvalid, - }, { - in: strR + strCS + strNSM + strNSM, - dir: bidi.RightToLeft, - n: len(strR + strCS + strNSM + strNSM), - err: ErrInvalid, - }, { - in: strR + strET, - dir: bidi.RightToLeft, - n: len(strR + strET), - err: ErrInvalid, - }, { - in: strR + strON + strNSM, - dir: bidi.RightToLeft, - n: len(strR + strON + strNSM), - err: ErrInvalid, - }, { - in: strR + strBN + strNSM + strNSM, - dir: bidi.RightToLeft, - n: len(strR + strBN + strNSM + strNSM), - err: ErrInvalid, - }, { - in: strR + strL + strNSM, - dir: bidi.RightToLeft, - n: len(strR), - err: ErrInvalid, - }, { - in: strR + strB + strNSM + strNSM, - dir: bidi.RightToLeft, - n: len(strR), - err: ErrInvalid, - }, { - in: strR + strS, - dir: bidi.RightToLeft, - n: len(strR), - err: ErrInvalid, - }, { - in: strR + strWS, - dir: bidi.RightToLeft, - n: len(strR), - err: ErrInvalid, - }, { - in: strAL + strNSM, - dir: bidi.RightToLeft, - }, { - in: strAL + strR, - dir: bidi.RightToLeft, - }, { - in: strAL + strAL + strNSM, - dir: bidi.RightToLeft, - }, { - in: strAL + strEN + strNSM + strNSM, - dir: bidi.RightToLeft, - }, { - in: strAL + strAN, - dir: bidi.RightToLeft, - }, { - in: strAL + strES + strNSM, - dir: bidi.RightToLeft, - n: len(strAL + strES + strNSM), - err: ErrInvalid, - }, { - in: strAL + strCS + strNSM + strNSM, - dir: bidi.RightToLeft, - n: len(strAL + strCS + strNSM + strNSM), - err: ErrInvalid, - }, { - in: strAL + strET, - dir: bidi.RightToLeft, - n: len(strAL + strET), - err: ErrInvalid, - }, { - in: strAL + strON + strNSM, - dir: bidi.RightToLeft, - n: len(strAL + strON + strNSM), - err: ErrInvalid, - }, { - in: strAL + strBN + strNSM + strNSM, - dir: bidi.RightToLeft, - n: len(strAL + strBN + strNSM + strNSM), - err: ErrInvalid, - }, { - in: strAL + strL + strNSM, - dir: bidi.RightToLeft, - n: len(strAL), - err: ErrInvalid, - }, { - in: strAL + strB + strNSM + strNSM, - dir: bidi.RightToLeft, - n: len(strAL), - err: ErrInvalid, - }, { - in: strAL + strS, - dir: bidi.RightToLeft, - n: len(strAL), - err: ErrInvalid, - }, { - in: strAL + strWS, - dir: bidi.RightToLeft, - n: len(strAL), - err: ErrInvalid, - }}, - - // Rule 2.4: In an RTL label, if an EN is present, no AN may be present, - // and vice versa. - 4: []ruleTest{{ - in: strR + strEN + strAN, - dir: bidi.RightToLeft, - n: len(strR + strEN), - err: ErrInvalid, - }, { - in: strR + strAN + strEN + strNSM, - dir: bidi.RightToLeft, - n: len(strR + strAN), - err: ErrInvalid, - }, { - in: strAL + strEN + strAN, - dir: bidi.RightToLeft, - n: len(strAL + strEN), - err: ErrInvalid, - }, { - in: strAL + strAN + strEN + strNSM, - dir: bidi.RightToLeft, - n: len(strAL + strAN), - err: ErrInvalid, - }}, - - // Rule 2.5: In an LTR label, only characters with the Bidi properties L, - // EN, ES, CS, ET, ON, BN, or NSM are allowed. - 5: []ruleTest{{ - in: strL + strL + strL, - dir: bidi.LeftToRight, - }, { - in: strL + strEN + strL, - dir: bidi.LeftToRight, - }, { - in: strL + strES + strL, - dir: bidi.LeftToRight, - }, { - in: strL + strCS + strL, - dir: bidi.LeftToRight, - }, { - in: strL + strET + strL, - dir: bidi.LeftToRight, - }, { - in: strL + strON + strL, - dir: bidi.LeftToRight, - }, { - in: strL + strBN + strL, - dir: bidi.LeftToRight, - }, { - in: strL + strNSM + strL, - dir: bidi.LeftToRight, - }, { - in: strL + strR + strL, - dir: bidi.RightToLeft, - n: len(strL), - err: ErrInvalid, - }, { - in: strL + strAL + strL, - dir: bidi.RightToLeft, - n: len(strL), - err: ErrInvalid, - }, { - in: strL + strAN + strL, - dir: bidi.RightToLeft, - n: len(strL), - err: ErrInvalid, - }, { - in: strL + strB + strL, - dir: bidi.LeftToRight, - n: len(strL + strB + strL), - err: ErrInvalid, - }, { - in: strL + strB + strL + strR, - dir: bidi.RightToLeft, - n: len(strL + strB + strL), - err: ErrInvalid, - }, { - in: strL + strS + strL, - dir: bidi.LeftToRight, - n: len(strL + strS + strL), - err: ErrInvalid, - }, { - in: strL + strS + strL + strR, - dir: bidi.RightToLeft, - n: len(strL + strS + strL), - err: ErrInvalid, - }, { - in: strL + strWS + strL, - dir: bidi.LeftToRight, - n: len(strL + strWS + strL), - err: ErrInvalid, - }, { - in: strL + strWS + strL + strR, - dir: bidi.RightToLeft, - n: len(strL + strWS + strL), - err: ErrInvalid, - }}, - - // Rule 2.6: In an LTR label, the end of the label must be a character with - // Bidi property L or EN, followed by zero or more characters with Bidi - // property NSM. - 6: []ruleTest{{ - in: strL, - dir: bidi.LeftToRight, - }, { - in: strL + strNSM, - dir: bidi.LeftToRight, - }, { - in: strL + strNSM + strNSM, - dir: bidi.LeftToRight, - }, { - in: strL + strEN, - dir: bidi.LeftToRight, - }, { - in: strL + strEN + strNSM, - dir: bidi.LeftToRight, - }, { - in: strL + strEN + strNSM + strNSM, - dir: bidi.LeftToRight, - }, { - in: strL + strES, - dir: bidi.LeftToRight, - n: len(strL + strES), - err: ErrInvalid, - }, { - in: strL + strES + strR, - dir: bidi.RightToLeft, - n: len(strL + strES), - err: ErrInvalid, - }, { - in: strL + strCS, - dir: bidi.LeftToRight, - n: len(strL + strCS), - err: ErrInvalid, - }, { - in: strL + strCS + strR, - dir: bidi.RightToLeft, - n: len(strL + strCS), - err: ErrInvalid, - }, { - in: strL + strET, - dir: bidi.LeftToRight, - n: len(strL + strET), - err: ErrInvalid, - }, { - in: strL + strET + strR, - dir: bidi.RightToLeft, - n: len(strL + strET), - err: ErrInvalid, - }, { - in: strL + strON, - dir: bidi.LeftToRight, - n: len(strL + strON), - err: ErrInvalid, - }, { - in: strL + strON + strR, - dir: bidi.RightToLeft, - n: len(strL + strON), - err: ErrInvalid, - }, { - in: strL + strBN, - dir: bidi.LeftToRight, - n: len(strL + strBN), - err: ErrInvalid, - }, { - in: strL + strBN + strR, - dir: bidi.RightToLeft, - n: len(strL + strBN), - err: ErrInvalid, - }, { - in: strL + strR, - dir: bidi.RightToLeft, - n: len(strL), - err: ErrInvalid, - }, { - in: strL + strAL, - dir: bidi.RightToLeft, - n: len(strL), - err: ErrInvalid, - }, { - in: strL + strAN, - dir: bidi.RightToLeft, - n: len(strL), - err: ErrInvalid, - }, { - in: strL + strB, - dir: bidi.LeftToRight, - n: len(strL + strB), - err: ErrInvalid, - }, { - in: strL + strB + strR, - dir: bidi.RightToLeft, - n: len(strL + strB), - err: ErrInvalid, - }, { - in: strL + strS, - dir: bidi.LeftToRight, - n: len(strL + strS), - err: ErrInvalid, - }, { - in: strL + strS + strR, - dir: bidi.RightToLeft, - n: len(strL + strS), - err: ErrInvalid, - }, { - in: strL + strWS, - dir: bidi.LeftToRight, - n: len(strL + strWS), - err: ErrInvalid, - }, { - in: strL + strWS + strR, - dir: bidi.RightToLeft, - n: len(strL + strWS), - err: ErrInvalid, - }}, - - // Incremental processing. - 9: []ruleTest{{ - in: "e\u0301", // é - dir: bidi.LeftToRight, - - pSrc: 2, - nSrc: 1, - err0: transform.ErrShortSrc, - }, { - in: "e\u1000f", // é - dir: bidi.LeftToRight, - - pSrc: 3, - nSrc: 1, - err0: transform.ErrShortSrc, - }, { - // Remain invalid once invalid. - in: strR + "ab", - dir: bidi.RightToLeft, - n: len(strR), - err: ErrInvalid, - - pSrc: len(strR) + 1, - nSrc: len(strR), - err0: ErrInvalid, - }, { - // Short destination - in: "abcdefghij", - dir: bidi.LeftToRight, - - pSrc: 10, - szDst: 5, - nSrc: 5, - err0: transform.ErrShortDst, - }, { - in: "\U000102f7", - dir: bidi.LeftToRight, - n: len("\U000102f7"), - err: ErrInvalid, - }, { - // Short destination splitting input rune - in: "e\u0301", - dir: bidi.LeftToRight, - - pSrc: 3, - szDst: 2, - nSrc: 1, - err0: transform.ErrShortDst, - }, { - // Unicode 10.0.0 IDNA test string. - in: "FAX\u2a77\U0001d186", - dir: bidi.LeftToRight, - n: len("FAX\u2a77\U0001d186"), - err: ErrInvalid, - }, { - in: "\x80\u0660", - dir: bidi.RightToLeft, - n: 0, - err: ErrInvalid, - }}, -} diff --git a/vendor/golang.org/x/text/secure/bidirule/bidirule9.0.0_test.go b/vendor/golang.org/x/text/secure/bidirule/bidirule9.0.0_test.go deleted file mode 100644 index 008874ed..00000000 --- a/vendor/golang.org/x/text/secure/bidirule/bidirule9.0.0_test.go +++ /dev/null @@ -1,668 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !go1.10 - -package bidirule - -import ( - "golang.org/x/text/transform" - "golang.org/x/text/unicode/bidi" -) - -var testCases = [][]ruleTest{ - // Go-specific rules. - // Invalid UTF-8 is invalid. - 0: []ruleTest{{ - in: "", - dir: bidi.LeftToRight, - }, { - in: "\x80", - dir: bidi.LeftToRight, - err: ErrInvalid, - n: 0, - }, { - in: "\xcc", - dir: bidi.LeftToRight, - err: ErrInvalid, - n: 0, - }, { - in: "abc\x80", - dir: bidi.LeftToRight, - err: ErrInvalid, - n: 3, - }, { - in: "abc\xcc", - dir: bidi.LeftToRight, - err: ErrInvalid, - n: 3, - }, { - in: "abc\xccdef", - dir: bidi.LeftToRight, - err: ErrInvalid, - n: 3, - }, { - in: "\xccdef", - dir: bidi.LeftToRight, - err: ErrInvalid, - n: 0, - }, { - in: strR + "\x80", - dir: bidi.RightToLeft, - err: ErrInvalid, - n: len(strR), - }, { - in: strR + "\xcc", - dir: bidi.RightToLeft, - err: ErrInvalid, - n: len(strR), - }, { - in: strAL + "\xcc" + strR, - dir: bidi.RightToLeft, - err: ErrInvalid, - n: len(strAL), - }, { - in: "\xcc" + strR, - dir: bidi.RightToLeft, - err: ErrInvalid, - n: 0, - }}, - - // Rule 2.1: The first character must be a character with Bidi property L, - // R, or AL. If it has the R or AL property, it is an RTL label; if it has - // the L property, it is an LTR label. - 1: []ruleTest{{ - in: strL, - dir: bidi.LeftToRight, - }, { - in: strR, - dir: bidi.RightToLeft, - }, { - in: strAL, - dir: bidi.RightToLeft, - }, { - in: strAN, - dir: bidi.RightToLeft, - err: ErrInvalid, - }, { - in: strEN, - dir: bidi.LeftToRight, - err: nil, // not an RTL string - }, { - in: strES, - dir: bidi.LeftToRight, - err: nil, // not an RTL string - }, { - in: strET, - dir: bidi.LeftToRight, - err: nil, // not an RTL string - }, { - in: strCS, - dir: bidi.LeftToRight, - err: nil, // not an RTL string - }, { - in: strNSM, - dir: bidi.LeftToRight, - err: nil, // not an RTL string - }, { - in: strBN, - dir: bidi.LeftToRight, - err: nil, // not an RTL string - }, { - in: strB, - dir: bidi.LeftToRight, - err: nil, // not an RTL string - }, { - in: strS, - dir: bidi.LeftToRight, - err: nil, // not an RTL string - }, { - in: strWS, - dir: bidi.LeftToRight, - err: nil, // not an RTL string - }, { - in: strON, - dir: bidi.LeftToRight, - err: nil, // not an RTL string - }, { - in: strEN + strR, - dir: bidi.RightToLeft, - err: ErrInvalid, - n: 3, - }, { - in: strES + strR, - dir: bidi.RightToLeft, - err: ErrInvalid, - n: 2, - }, { - in: strET + strR, - dir: bidi.RightToLeft, - err: ErrInvalid, - n: 1, - }, { - in: strCS + strR, - dir: bidi.RightToLeft, - err: ErrInvalid, - n: 1, - }, { - in: strNSM + strR, - dir: bidi.RightToLeft, - err: ErrInvalid, - n: 2, - }, { - in: strBN + strR, - dir: bidi.RightToLeft, - err: ErrInvalid, - n: 3, - }, { - in: strB + strR, - dir: bidi.RightToLeft, - err: ErrInvalid, - n: 3, - }, { - in: strS + strR, - dir: bidi.RightToLeft, - err: ErrInvalid, - n: 1, - }, { - in: strWS + strR, - dir: bidi.RightToLeft, - err: ErrInvalid, - n: 1, - }, { - in: strON + strR, - dir: bidi.RightToLeft, - err: ErrInvalid, - n: 1, - }}, - - // Rule 2.2: In an RTL label, only characters with the Bidi properties R, - // AL, AN, EN, ES, CS, ET, ON, BN, or NSM are allowed. - 2: []ruleTest{{ - in: strR + strR + strAL, - dir: bidi.RightToLeft, - }, { - in: strR + strAL + strR, - dir: bidi.RightToLeft, - }, { - in: strR + strAN + strAL, - dir: bidi.RightToLeft, - }, { - in: strR + strEN + strR, - dir: bidi.RightToLeft, - }, { - in: strR + strES + strR, - dir: bidi.RightToLeft, - }, { - in: strR + strCS + strR, - dir: bidi.RightToLeft, - }, { - in: strR + strET + strAL, - dir: bidi.RightToLeft, - }, { - in: strR + strON + strR, - dir: bidi.RightToLeft, - }, { - in: strR + strBN + strR, - dir: bidi.RightToLeft, - }, { - in: strR + strNSM + strAL, - dir: bidi.RightToLeft, - }, { - in: strR + strL + strR, - dir: bidi.RightToLeft, - n: len(strR), - err: ErrInvalid, - }, { - in: strR + strB + strR, - dir: bidi.RightToLeft, - n: len(strR), - err: ErrInvalid, - }, { - in: strR + strS + strAL, - dir: bidi.RightToLeft, - n: len(strR), - err: ErrInvalid, - }, { - in: strR + strWS + strAL, - dir: bidi.RightToLeft, - n: len(strR), - err: ErrInvalid, - }, { - in: strAL + strR + strAL, - dir: bidi.RightToLeft, - }, { - in: strAL + strAL + strR, - dir: bidi.RightToLeft, - }, { - in: strAL + strAN + strAL, - dir: bidi.RightToLeft, - }, { - in: strAL + strEN + strR, - dir: bidi.RightToLeft, - }, { - in: strAL + strES + strR, - dir: bidi.RightToLeft, - }, { - in: strAL + strCS + strR, - dir: bidi.RightToLeft, - }, { - in: strAL + strET + strAL, - dir: bidi.RightToLeft, - }, { - in: strAL + strON + strR, - dir: bidi.RightToLeft, - }, { - in: strAL + strBN + strR, - dir: bidi.RightToLeft, - }, { - in: strAL + strNSM + strAL, - dir: bidi.RightToLeft, - }, { - in: strAL + strL + strR, - dir: bidi.RightToLeft, - n: len(strAL), - err: ErrInvalid, - }, { - in: strAL + strB + strR, - dir: bidi.RightToLeft, - n: len(strAL), - err: ErrInvalid, - }, { - in: strAL + strS + strAL, - dir: bidi.RightToLeft, - n: len(strAL), - err: ErrInvalid, - }, { - in: strAL + strWS + strAL, - dir: bidi.RightToLeft, - n: len(strAL), - err: ErrInvalid, - }}, - - // Rule 2.3: In an RTL label, the end of the label must be a character with - // Bidi property R, AL, EN, or AN, followed by zero or more characters with - // Bidi property NSM. - 3: []ruleTest{{ - in: strR + strNSM, - dir: bidi.RightToLeft, - }, { - in: strR + strR, - dir: bidi.RightToLeft, - }, { - in: strR + strAL + strNSM, - dir: bidi.RightToLeft, - }, { - in: strR + strEN + strNSM + strNSM, - dir: bidi.RightToLeft, - }, { - in: strR + strAN, - dir: bidi.RightToLeft, - }, { - in: strR + strES + strNSM, - dir: bidi.RightToLeft, - n: len(strR + strES + strNSM), - err: ErrInvalid, - }, { - in: strR + strCS + strNSM + strNSM, - dir: bidi.RightToLeft, - n: len(strR + strCS + strNSM + strNSM), - err: ErrInvalid, - }, { - in: strR + strET, - dir: bidi.RightToLeft, - n: len(strR + strET), - err: ErrInvalid, - }, { - in: strR + strON + strNSM, - dir: bidi.RightToLeft, - n: len(strR + strON + strNSM), - err: ErrInvalid, - }, { - in: strR + strBN + strNSM + strNSM, - dir: bidi.RightToLeft, - n: len(strR + strBN + strNSM + strNSM), - err: ErrInvalid, - }, { - in: strR + strL + strNSM, - dir: bidi.RightToLeft, - n: len(strR), - err: ErrInvalid, - }, { - in: strR + strB + strNSM + strNSM, - dir: bidi.RightToLeft, - n: len(strR), - err: ErrInvalid, - }, { - in: strR + strS, - dir: bidi.RightToLeft, - n: len(strR), - err: ErrInvalid, - }, { - in: strR + strWS, - dir: bidi.RightToLeft, - n: len(strR), - err: ErrInvalid, - }, { - in: strAL + strNSM, - dir: bidi.RightToLeft, - }, { - in: strAL + strR, - dir: bidi.RightToLeft, - }, { - in: strAL + strAL + strNSM, - dir: bidi.RightToLeft, - }, { - in: strAL + strEN + strNSM + strNSM, - dir: bidi.RightToLeft, - }, { - in: strAL + strAN, - dir: bidi.RightToLeft, - }, { - in: strAL + strES + strNSM, - dir: bidi.RightToLeft, - n: len(strAL + strES + strNSM), - err: ErrInvalid, - }, { - in: strAL + strCS + strNSM + strNSM, - dir: bidi.RightToLeft, - n: len(strAL + strCS + strNSM + strNSM), - err: ErrInvalid, - }, { - in: strAL + strET, - dir: bidi.RightToLeft, - n: len(strAL + strET), - err: ErrInvalid, - }, { - in: strAL + strON + strNSM, - dir: bidi.RightToLeft, - n: len(strAL + strON + strNSM), - err: ErrInvalid, - }, { - in: strAL + strBN + strNSM + strNSM, - dir: bidi.RightToLeft, - n: len(strAL + strBN + strNSM + strNSM), - err: ErrInvalid, - }, { - in: strAL + strL + strNSM, - dir: bidi.RightToLeft, - n: len(strAL), - err: ErrInvalid, - }, { - in: strAL + strB + strNSM + strNSM, - dir: bidi.RightToLeft, - n: len(strAL), - err: ErrInvalid, - }, { - in: strAL + strS, - dir: bidi.RightToLeft, - n: len(strAL), - err: ErrInvalid, - }, { - in: strAL + strWS, - dir: bidi.RightToLeft, - n: len(strAL), - err: ErrInvalid, - }}, - - // Rule 2.4: In an RTL label, if an EN is present, no AN may be present, - // and vice versa. - 4: []ruleTest{{ - in: strR + strEN + strAN, - dir: bidi.RightToLeft, - n: len(strR + strEN), - err: ErrInvalid, - }, { - in: strR + strAN + strEN + strNSM, - dir: bidi.RightToLeft, - n: len(strR + strAN), - err: ErrInvalid, - }, { - in: strAL + strEN + strAN, - dir: bidi.RightToLeft, - n: len(strAL + strEN), - err: ErrInvalid, - }, { - in: strAL + strAN + strEN + strNSM, - dir: bidi.RightToLeft, - n: len(strAL + strAN), - err: ErrInvalid, - }}, - - // Rule 2.5: In an LTR label, only characters with the Bidi properties L, - // EN, ES, CS, ET, ON, BN, or NSM are allowed. - 5: []ruleTest{{ - in: strL + strL + strL, - dir: bidi.LeftToRight, - }, { - in: strL + strEN + strL, - dir: bidi.LeftToRight, - }, { - in: strL + strES + strL, - dir: bidi.LeftToRight, - }, { - in: strL + strCS + strL, - dir: bidi.LeftToRight, - }, { - in: strL + strET + strL, - dir: bidi.LeftToRight, - }, { - in: strL + strON + strL, - dir: bidi.LeftToRight, - }, { - in: strL + strBN + strL, - dir: bidi.LeftToRight, - }, { - in: strL + strNSM + strL, - dir: bidi.LeftToRight, - }, { - in: strL + strR + strL, - dir: bidi.RightToLeft, - n: len(strL), - err: ErrInvalid, - }, { - in: strL + strAL + strL, - dir: bidi.RightToLeft, - n: len(strL), - err: ErrInvalid, - }, { - in: strL + strAN + strL, - dir: bidi.RightToLeft, - n: len(strL), - err: ErrInvalid, - }, { - in: strL + strB + strL, - dir: bidi.LeftToRight, - n: len(strL + strAN + strL), - err: nil, - }, { - in: strL + strB + strL + strR, - dir: bidi.RightToLeft, - n: len(strL + strB + strL), - err: ErrInvalid, - }, { - in: strL + strS + strL, - dir: bidi.LeftToRight, - n: len(strL + strS + strL), - err: nil, - }, { - in: strL + strS + strL + strR, - dir: bidi.RightToLeft, - n: len(strL + strS + strL), - err: ErrInvalid, - }, { - in: strL + strWS + strL, - dir: bidi.LeftToRight, - n: len(strL + strWS + strL), - err: nil, - }, { - in: strL + strWS + strL + strR, - dir: bidi.RightToLeft, - n: len(strL + strWS + strL), - err: ErrInvalid, - }}, - - // Rule 2.6: In an LTR label, the end of the label must be a character with - // Bidi property L or EN, followed by zero or more characters with Bidi - // property NSM. - 6: []ruleTest{{ - in: strL, - dir: bidi.LeftToRight, - }, { - in: strL + strNSM, - dir: bidi.LeftToRight, - }, { - in: strL + strNSM + strNSM, - dir: bidi.LeftToRight, - }, { - in: strL + strEN, - dir: bidi.LeftToRight, - }, { - in: strL + strEN + strNSM, - dir: bidi.LeftToRight, - }, { - in: strL + strEN + strNSM + strNSM, - dir: bidi.LeftToRight, - }, { - in: strL + strES, - dir: bidi.LeftToRight, - n: len(strL + strES), - err: nil, - }, { - in: strL + strES + strR, - dir: bidi.RightToLeft, - n: len(strL + strES), - err: ErrInvalid, - }, { - in: strL + strCS, - dir: bidi.LeftToRight, - n: len(strL + strCS), - err: nil, - }, { - in: strL + strCS + strR, - dir: bidi.RightToLeft, - n: len(strL + strCS), - err: ErrInvalid, - }, { - in: strL + strET, - dir: bidi.LeftToRight, - n: len(strL + strET), - err: nil, - }, { - in: strL + strET + strR, - dir: bidi.RightToLeft, - n: len(strL + strET), - err: ErrInvalid, - }, { - in: strL + strON, - dir: bidi.LeftToRight, - n: len(strL + strON), - err: nil, - }, { - in: strL + strON + strR, - dir: bidi.RightToLeft, - n: len(strL + strON), - err: ErrInvalid, - }, { - in: strL + strBN, - dir: bidi.LeftToRight, - n: len(strL + strBN), - err: nil, - }, { - in: strL + strBN + strR, - dir: bidi.RightToLeft, - n: len(strL + strBN), - err: ErrInvalid, - }, { - in: strL + strR, - dir: bidi.RightToLeft, - n: len(strL), - err: ErrInvalid, - }, { - in: strL + strAL, - dir: bidi.RightToLeft, - n: len(strL), - err: ErrInvalid, - }, { - in: strL + strAN, - dir: bidi.RightToLeft, - n: len(strL), - err: ErrInvalid, - }, { - in: strL + strB, - dir: bidi.LeftToRight, - n: len(strL + strB), - err: nil, - }, { - in: strL + strB + strR, - dir: bidi.RightToLeft, - n: len(strL + strB), - err: ErrInvalid, - }, { - in: strL + strB, - dir: bidi.LeftToRight, - n: len(strL + strB), - err: nil, - }, { - in: strL + strB + strR, - dir: bidi.RightToLeft, - n: len(strL + strB), - err: ErrInvalid, - }, { - in: strL + strB, - dir: bidi.LeftToRight, - n: len(strL + strB), - err: nil, - }, { - in: strL + strB + strR, - dir: bidi.RightToLeft, - n: len(strL + strB), - err: ErrInvalid, - }}, - - // Incremental processing. - 9: []ruleTest{{ - in: "e\u0301", // é - dir: bidi.LeftToRight, - - pSrc: 2, - nSrc: 1, - err0: transform.ErrShortSrc, - }, { - in: "e\u1000f", // é - dir: bidi.LeftToRight, - - pSrc: 3, - nSrc: 1, - err0: transform.ErrShortSrc, - }, { - // Remain invalid once invalid. - in: strR + "ab", - dir: bidi.RightToLeft, - n: len(strR), - err: ErrInvalid, - - pSrc: len(strR) + 1, - nSrc: len(strR), - err0: ErrInvalid, - }, { - // Short destination - in: "abcdefghij", - dir: bidi.LeftToRight, - - pSrc: 10, - szDst: 5, - nSrc: 5, - err0: transform.ErrShortDst, - }, { - // Short destination splitting input rune - in: "e\u0301", - dir: bidi.LeftToRight, - - pSrc: 3, - szDst: 2, - nSrc: 1, - err0: transform.ErrShortDst, - }}, -} diff --git a/vendor/golang.org/x/text/secure/bidirule/bidirule_test.go b/vendor/golang.org/x/text/secure/bidirule/bidirule_test.go deleted file mode 100644 index e8fde338..00000000 --- a/vendor/golang.org/x/text/secure/bidirule/bidirule_test.go +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package bidirule - -import ( - "fmt" - "testing" - - "golang.org/x/text/internal/testtext" - "golang.org/x/text/unicode/bidi" -) - -const ( - strL = "ABC" // Left to right - most letters in LTR scripts - strR = "עברית" // Right to left - most letters in non-Arabic RTL scripts - strAL = "دبي" // Arabic letters - most letters in the Arabic script - strEN = "123" // European Number (0-9, and Extended Arabic-Indic numbers) - strES = "+-" // European Number Separator (+ and -) - strET = "$" // European Number Terminator (currency symbols, the hash sign, the percent sign and so on) - strAN = "\u0660" // Arabic Number; this encompasses the Arabic-Indic numbers, but not the Extended Arabic-Indic numbers - strCS = "," // Common Number Separator (. , / : et al) - strNSM = "\u0300" // Nonspacing Mark - most combining accents - strBN = "\u200d" // Boundary Neutral - control characters (ZWNJ, ZWJ, and others) - strB = "\u2029" // Paragraph Separator - strS = "\u0009" // Segment Separator - strWS = " " // Whitespace, including the SPACE character - strON = "@" // Other Neutrals, including @, &, parentheses, MIDDLE DOT -) - -type ruleTest struct { - in string - dir bidi.Direction - n int // position at which the rule fails - err error - - // For tests that split the string in two. - pSrc int // number of source bytes to consume first - szDst int // size of destination buffer - nSrc int // source bytes consumed and bytes written - err0 error // error after first run -} - -func init() { - for rule, cases := range testCases { - for i, tc := range cases { - if tc.err == nil { - testCases[rule][i].n = len(tc.in) - } - } - } -} - -func doTests(t *testing.T, fn func(t *testing.T, tc ruleTest)) { - for rule, cases := range testCases { - for i, tc := range cases { - name := fmt.Sprintf("%d/%d:%+q:%s", rule, i, tc.in, tc.in) - testtext.Run(t, name, func(t *testing.T) { - fn(t, tc) - }) - } - } -} - -func TestDirection(t *testing.T) { - doTests(t, func(t *testing.T, tc ruleTest) { - dir := Direction([]byte(tc.in)) - if dir != tc.dir { - t.Errorf("dir was %v; want %v", dir, tc.dir) - } - }) -} - -func TestDirectionString(t *testing.T) { - doTests(t, func(t *testing.T, tc ruleTest) { - dir := DirectionString(tc.in) - if dir != tc.dir { - t.Errorf("dir was %v; want %v", dir, tc.dir) - } - }) -} - -func TestValid(t *testing.T) { - doTests(t, func(t *testing.T, tc ruleTest) { - got := Valid([]byte(tc.in)) - want := tc.err == nil - if got != want { - t.Fatalf("Valid: got %v; want %v", got, want) - } - - got = ValidString(tc.in) - want = tc.err == nil - if got != want { - t.Fatalf("Valid: got %v; want %v", got, want) - } - }) -} - -func TestSpan(t *testing.T) { - doTests(t, func(t *testing.T, tc ruleTest) { - // Skip tests that test for limited destination buffer size. - if tc.szDst > 0 { - return - } - - r := New() - src := []byte(tc.in) - - n, err := r.Span(src[:tc.pSrc], tc.pSrc == len(tc.in)) - if err != tc.err0 { - t.Errorf("err0 was %v; want %v", err, tc.err0) - } - if n != tc.nSrc { - t.Fatalf("nSrc was %d; want %d", n, tc.nSrc) - } - - n, err = r.Span(src[n:], true) - if err != tc.err { - t.Errorf("error was %v; want %v", err, tc.err) - } - if got := n + tc.nSrc; got != tc.n { - t.Errorf("n was %d; want %d", got, tc.n) - } - }) -} - -func TestTransform(t *testing.T) { - doTests(t, func(t *testing.T, tc ruleTest) { - r := New() - - src := []byte(tc.in) - dst := make([]byte, len(tc.in)) - if tc.szDst > 0 { - dst = make([]byte, tc.szDst) - } - - // First transform operates on a zero-length string for most tests. - nDst, nSrc, err := r.Transform(dst, src[:tc.pSrc], tc.pSrc == len(tc.in)) - if err != tc.err0 { - t.Errorf("err0 was %v; want %v", err, tc.err0) - } - if nDst != nSrc { - t.Fatalf("nDst (%d) and nSrc (%d) should match", nDst, nSrc) - } - if nSrc != tc.nSrc { - t.Fatalf("nSrc was %d; want %d", nSrc, tc.nSrc) - } - - dst1 := make([]byte, len(tc.in)) - copy(dst1, dst[:nDst]) - - nDst, nSrc, err = r.Transform(dst1[nDst:], src[nSrc:], true) - if err != tc.err { - t.Errorf("error was %v; want %v", err, tc.err) - } - if nDst != nSrc { - t.Fatalf("nDst (%d) and nSrc (%d) should match", nDst, nSrc) - } - n := nSrc + tc.nSrc - if n != tc.n { - t.Fatalf("n was %d; want %d", n, tc.n) - } - if got, want := string(dst1[:n]), tc.in[:tc.n]; got != want { - t.Errorf("got %+q; want %+q", got, want) - } - }) -} diff --git a/vendor/golang.org/x/text/secure/doc.go b/vendor/golang.org/x/text/secure/doc.go deleted file mode 100644 index e531c354..00000000 --- a/vendor/golang.org/x/text/secure/doc.go +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// secure is a repository of text security related packages. -package secure // import "golang.org/x/text/secure" diff --git a/vendor/golang.org/x/text/transform/examples_test.go b/vendor/golang.org/x/text/transform/examples_test.go deleted file mode 100644 index f2e284db..00000000 --- a/vendor/golang.org/x/text/transform/examples_test.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package transform_test - -import ( - "fmt" - "unicode" - - "golang.org/x/text/transform" - "golang.org/x/text/unicode/norm" -) - -func ExampleRemoveFunc() { - input := []byte(`tschüß; до свидания`) - - b := make([]byte, len(input)) - - t := transform.RemoveFunc(unicode.IsSpace) - n, _, _ := t.Transform(b, input, true) - fmt.Println(string(b[:n])) - - t = transform.RemoveFunc(func(r rune) bool { - return !unicode.Is(unicode.Latin, r) - }) - n, _, _ = t.Transform(b, input, true) - fmt.Println(string(b[:n])) - - n, _, _ = t.Transform(b, norm.NFD.Bytes(input), true) - fmt.Println(string(b[:n])) - - // Output: - // tschüß;досвидания - // tschüß - // tschuß -} diff --git a/vendor/golang.org/x/text/transform/transform_test.go b/vendor/golang.org/x/text/transform/transform_test.go deleted file mode 100644 index 771633d1..00000000 --- a/vendor/golang.org/x/text/transform/transform_test.go +++ /dev/null @@ -1,1317 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package transform - -import ( - "bytes" - "errors" - "fmt" - "io/ioutil" - "strconv" - "strings" - "testing" - "time" - "unicode/utf8" - - "golang.org/x/text/internal/testtext" -) - -type lowerCaseASCII struct{ NopResetter } - -func (lowerCaseASCII) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { - n := len(src) - if n > len(dst) { - n, err = len(dst), ErrShortDst - } - for i, c := range src[:n] { - if 'A' <= c && c <= 'Z' { - c += 'a' - 'A' - } - dst[i] = c - } - return n, n, err -} - -// lowerCaseASCIILookahead lowercases the string and reports ErrShortSrc as long -// as the input is not atEOF. -type lowerCaseASCIILookahead struct{ NopResetter } - -func (lowerCaseASCIILookahead) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { - n := len(src) - if n > len(dst) { - n, err = len(dst), ErrShortDst - } - for i, c := range src[:n] { - if 'A' <= c && c <= 'Z' { - c += 'a' - 'A' - } - dst[i] = c - } - if !atEOF { - err = ErrShortSrc - } - return n, n, err -} - -var errYouMentionedX = errors.New("you mentioned X") - -type dontMentionX struct{ NopResetter } - -func (dontMentionX) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { - n := len(src) - if n > len(dst) { - n, err = len(dst), ErrShortDst - } - for i, c := range src[:n] { - if c == 'X' { - return i, i, errYouMentionedX - } - dst[i] = c - } - return n, n, err -} - -var errAtEnd = errors.New("error after all text") - -type errorAtEnd struct{ NopResetter } - -func (errorAtEnd) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { - n := copy(dst, src) - if n < len(src) { - return n, n, ErrShortDst - } - if atEOF { - return n, n, errAtEnd - } - return n, n, nil -} - -type replaceWithConstant struct { - replacement string - written int -} - -func (t *replaceWithConstant) Reset() { - t.written = 0 -} - -func (t *replaceWithConstant) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { - if atEOF { - nDst = copy(dst, t.replacement[t.written:]) - t.written += nDst - if t.written < len(t.replacement) { - err = ErrShortDst - } - } - return nDst, len(src), err -} - -type addAnXAtTheEnd struct{ NopResetter } - -func (addAnXAtTheEnd) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { - n := copy(dst, src) - if n < len(src) { - return n, n, ErrShortDst - } - if !atEOF { - return n, n, nil - } - if len(dst) == n { - return n, n, ErrShortDst - } - dst[n] = 'X' - return n + 1, n, nil -} - -// doublerAtEOF is a strange Transformer that transforms "this" to "tthhiiss", -// but only if atEOF is true. -type doublerAtEOF struct{ NopResetter } - -func (doublerAtEOF) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { - if !atEOF { - return 0, 0, ErrShortSrc - } - for i, c := range src { - if 2*i+2 >= len(dst) { - return 2 * i, i, ErrShortDst - } - dst[2*i+0] = c - dst[2*i+1] = c - } - return 2 * len(src), len(src), nil -} - -// rleDecode and rleEncode implement a toy run-length encoding: "aabbbbbbbbbb" -// is encoded as "2a10b". The decoding is assumed to not contain any numbers. - -type rleDecode struct{ NopResetter } - -func (rleDecode) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { -loop: - for len(src) > 0 { - n := 0 - for i, c := range src { - if '0' <= c && c <= '9' { - n = 10*n + int(c-'0') - continue - } - if i == 0 { - return nDst, nSrc, errors.New("rleDecode: bad input") - } - if n > len(dst) { - return nDst, nSrc, ErrShortDst - } - for j := 0; j < n; j++ { - dst[j] = c - } - dst, src = dst[n:], src[i+1:] - nDst, nSrc = nDst+n, nSrc+i+1 - continue loop - } - if atEOF { - return nDst, nSrc, errors.New("rleDecode: bad input") - } - return nDst, nSrc, ErrShortSrc - } - return nDst, nSrc, nil -} - -type rleEncode struct { - NopResetter - - // allowStutter means that "xxxxxxxx" can be encoded as "5x3x" - // instead of always as "8x". - allowStutter bool -} - -func (e rleEncode) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { - for len(src) > 0 { - n, c0 := len(src), src[0] - for i, c := range src[1:] { - if c != c0 { - n = i + 1 - break - } - } - if n == len(src) && !atEOF && !e.allowStutter { - return nDst, nSrc, ErrShortSrc - } - s := strconv.Itoa(n) - if len(s) >= len(dst) { - return nDst, nSrc, ErrShortDst - } - copy(dst, s) - dst[len(s)] = c0 - dst, src = dst[len(s)+1:], src[n:] - nDst, nSrc = nDst+len(s)+1, nSrc+n - } - return nDst, nSrc, nil -} - -// trickler consumes all input bytes, but writes a single byte at a time to dst. -type trickler []byte - -func (t *trickler) Reset() { - *t = nil -} - -func (t *trickler) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { - *t = append(*t, src...) - if len(*t) == 0 { - return 0, 0, nil - } - if len(dst) == 0 { - return 0, len(src), ErrShortDst - } - dst[0] = (*t)[0] - *t = (*t)[1:] - if len(*t) > 0 { - err = ErrShortDst - } - return 1, len(src), err -} - -// delayedTrickler is like trickler, but delays writing output to dst. This is -// highly unlikely to be relevant in practice, but it seems like a good idea -// to have some tolerance as long as progress can be detected. -type delayedTrickler []byte - -func (t *delayedTrickler) Reset() { - *t = nil -} - -func (t *delayedTrickler) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { - if len(*t) > 0 && len(dst) > 0 { - dst[0] = (*t)[0] - *t = (*t)[1:] - nDst = 1 - } - *t = append(*t, src...) - if len(*t) > 0 { - err = ErrShortDst - } - return nDst, len(src), err -} - -type testCase struct { - desc string - t Transformer - src string - dstSize int - srcSize int - ioSize int - wantStr string - wantErr error - wantIter int // number of iterations taken; 0 means we don't care. -} - -func (t testCase) String() string { - return tstr(t.t) + "; " + t.desc -} - -func tstr(t Transformer) string { - if stringer, ok := t.(fmt.Stringer); ok { - return stringer.String() - } - s := fmt.Sprintf("%T", t) - return s[1+strings.Index(s, "."):] -} - -func (c chain) String() string { - buf := &bytes.Buffer{} - buf.WriteString("Chain(") - for i, l := range c.link[:len(c.link)-1] { - if i != 0 { - fmt.Fprint(buf, ", ") - } - buf.WriteString(tstr(l.t)) - } - buf.WriteString(")") - return buf.String() -} - -var testCases = []testCase{ - { - desc: "empty", - t: lowerCaseASCII{}, - src: "", - dstSize: 100, - srcSize: 100, - wantStr: "", - }, - - { - desc: "basic", - t: lowerCaseASCII{}, - src: "Hello WORLD.", - dstSize: 100, - srcSize: 100, - wantStr: "hello world.", - }, - - { - desc: "small dst", - t: lowerCaseASCII{}, - src: "Hello WORLD.", - dstSize: 3, - srcSize: 100, - wantStr: "hello world.", - }, - - { - desc: "small src", - t: lowerCaseASCII{}, - src: "Hello WORLD.", - dstSize: 100, - srcSize: 4, - wantStr: "hello world.", - }, - - { - desc: "small buffers", - t: lowerCaseASCII{}, - src: "Hello WORLD.", - dstSize: 3, - srcSize: 4, - wantStr: "hello world.", - }, - - { - desc: "very small buffers", - t: lowerCaseASCII{}, - src: "Hello WORLD.", - dstSize: 1, - srcSize: 1, - wantStr: "hello world.", - }, - - { - desc: "small dst with lookahead", - t: lowerCaseASCIILookahead{}, - src: "Hello WORLD.", - dstSize: 3, - srcSize: 100, - wantStr: "hello world.", - }, - - { - desc: "small src with lookahead", - t: lowerCaseASCIILookahead{}, - src: "Hello WORLD.", - dstSize: 100, - srcSize: 4, - wantStr: "hello world.", - }, - - { - desc: "small buffers with lookahead", - t: lowerCaseASCIILookahead{}, - src: "Hello WORLD.", - dstSize: 3, - srcSize: 4, - wantStr: "hello world.", - }, - - { - desc: "very small buffers with lookahead", - t: lowerCaseASCIILookahead{}, - src: "Hello WORLD.", - dstSize: 1, - srcSize: 2, - wantStr: "hello world.", - }, - - { - desc: "user error", - t: dontMentionX{}, - src: "The First Rule of Transform Club: don't mention Mister X, ever.", - dstSize: 100, - srcSize: 100, - wantStr: "The First Rule of Transform Club: don't mention Mister ", - wantErr: errYouMentionedX, - }, - - { - desc: "user error at end", - t: errorAtEnd{}, - src: "All goes well until it doesn't.", - dstSize: 100, - srcSize: 100, - wantStr: "All goes well until it doesn't.", - wantErr: errAtEnd, - }, - - { - desc: "user error at end, incremental", - t: errorAtEnd{}, - src: "All goes well until it doesn't.", - dstSize: 10, - srcSize: 10, - wantStr: "All goes well until it doesn't.", - wantErr: errAtEnd, - }, - - { - desc: "replace entire non-empty string with one byte", - t: &replaceWithConstant{replacement: "X"}, - src: "none of this will be copied", - dstSize: 1, - srcSize: 10, - wantStr: "X", - }, - - { - desc: "replace entire empty string with one byte", - t: &replaceWithConstant{replacement: "X"}, - src: "", - dstSize: 1, - srcSize: 10, - wantStr: "X", - }, - - { - desc: "replace entire empty string with seven bytes", - t: &replaceWithConstant{replacement: "ABCDEFG"}, - src: "", - dstSize: 3, - srcSize: 10, - wantStr: "ABCDEFG", - }, - - { - desc: "add an X (initialBufSize-1)", - t: addAnXAtTheEnd{}, - src: aaa[:initialBufSize-1], - dstSize: 10, - srcSize: 10, - wantStr: aaa[:initialBufSize-1] + "X", - }, - - { - desc: "add an X (initialBufSize+0)", - t: addAnXAtTheEnd{}, - src: aaa[:initialBufSize+0], - dstSize: 10, - srcSize: 10, - wantStr: aaa[:initialBufSize+0] + "X", - }, - - { - desc: "add an X (initialBufSize+1)", - t: addAnXAtTheEnd{}, - src: aaa[:initialBufSize+1], - dstSize: 10, - srcSize: 10, - wantStr: aaa[:initialBufSize+1] + "X", - }, - - { - desc: "small buffers", - t: dontMentionX{}, - src: "The First Rule of Transform Club: don't mention Mister X, ever.", - dstSize: 10, - srcSize: 10, - wantStr: "The First Rule of Transform Club: don't mention Mister ", - wantErr: errYouMentionedX, - }, - - { - desc: "very small buffers", - t: dontMentionX{}, - src: "The First Rule of Transform Club: don't mention Mister X, ever.", - dstSize: 1, - srcSize: 1, - wantStr: "The First Rule of Transform Club: don't mention Mister ", - wantErr: errYouMentionedX, - }, - - { - desc: "only transform at EOF", - t: doublerAtEOF{}, - src: "this", - dstSize: 100, - srcSize: 100, - wantStr: "tthhiiss", - }, - - { - desc: "basic", - t: rleDecode{}, - src: "1a2b3c10d11e0f1g", - dstSize: 100, - srcSize: 100, - wantStr: "abbcccddddddddddeeeeeeeeeeeg", - }, - - { - desc: "long", - t: rleDecode{}, - src: "12a23b34c45d56e99z", - dstSize: 100, - srcSize: 100, - wantStr: strings.Repeat("a", 12) + - strings.Repeat("b", 23) + - strings.Repeat("c", 34) + - strings.Repeat("d", 45) + - strings.Repeat("e", 56) + - strings.Repeat("z", 99), - }, - - { - desc: "tight buffers", - t: rleDecode{}, - src: "1a2b3c10d11e0f1g", - dstSize: 11, - srcSize: 3, - wantStr: "abbcccddddddddddeeeeeeeeeeeg", - }, - - { - desc: "short dst", - t: rleDecode{}, - src: "1a2b3c10d11e0f1g", - dstSize: 10, - srcSize: 3, - wantStr: "abbcccdddddddddd", - wantErr: ErrShortDst, - }, - - { - desc: "short src", - t: rleDecode{}, - src: "1a2b3c10d11e0f1g", - dstSize: 11, - srcSize: 2, - ioSize: 2, - wantStr: "abbccc", - wantErr: ErrShortSrc, - }, - - { - desc: "basic", - t: rleEncode{}, - src: "abbcccddddddddddeeeeeeeeeeeg", - dstSize: 100, - srcSize: 100, - wantStr: "1a2b3c10d11e1g", - }, - - { - desc: "long", - t: rleEncode{}, - src: strings.Repeat("a", 12) + - strings.Repeat("b", 23) + - strings.Repeat("c", 34) + - strings.Repeat("d", 45) + - strings.Repeat("e", 56) + - strings.Repeat("z", 99), - dstSize: 100, - srcSize: 100, - wantStr: "12a23b34c45d56e99z", - }, - - { - desc: "tight buffers", - t: rleEncode{}, - src: "abbcccddddddddddeeeeeeeeeeeg", - dstSize: 3, - srcSize: 12, - wantStr: "1a2b3c10d11e1g", - }, - - { - desc: "short dst", - t: rleEncode{}, - src: "abbcccddddddddddeeeeeeeeeeeg", - dstSize: 2, - srcSize: 12, - wantStr: "1a2b3c", - wantErr: ErrShortDst, - }, - - { - desc: "short src", - t: rleEncode{}, - src: "abbcccddddddddddeeeeeeeeeeeg", - dstSize: 3, - srcSize: 11, - ioSize: 11, - wantStr: "1a2b3c10d", - wantErr: ErrShortSrc, - }, - - { - desc: "allowStutter = false", - t: rleEncode{allowStutter: false}, - src: "aaaabbbbbbbbccccddddd", - dstSize: 10, - srcSize: 10, - wantStr: "4a8b4c5d", - }, - - { - desc: "allowStutter = true", - t: rleEncode{allowStutter: true}, - src: "aaaabbbbbbbbccccddddd", - dstSize: 10, - srcSize: 10, - ioSize: 10, - wantStr: "4a6b2b4c4d1d", - }, - - { - desc: "trickler", - t: &trickler{}, - src: "abcdefghijklm", - dstSize: 3, - srcSize: 15, - wantStr: "abcdefghijklm", - }, - - { - desc: "delayedTrickler", - t: &delayedTrickler{}, - src: "abcdefghijklm", - dstSize: 3, - srcSize: 15, - wantStr: "abcdefghijklm", - }, -} - -func TestReader(t *testing.T) { - for _, tc := range testCases { - testtext.Run(t, tc.desc, func(t *testing.T) { - r := NewReader(strings.NewReader(tc.src), tc.t) - // Differently sized dst and src buffers are not part of the - // exported API. We override them manually. - r.dst = make([]byte, tc.dstSize) - r.src = make([]byte, tc.srcSize) - got, err := ioutil.ReadAll(r) - str := string(got) - if str != tc.wantStr || err != tc.wantErr { - t.Errorf("\ngot %q, %v\nwant %q, %v", str, err, tc.wantStr, tc.wantErr) - } - }) - } -} - -func TestWriter(t *testing.T) { - tests := append(testCases, chainTests()...) - for _, tc := range tests { - sizes := []int{1, 2, 3, 4, 5, 10, 100, 1000} - if tc.ioSize > 0 { - sizes = []int{tc.ioSize} - } - for _, sz := range sizes { - testtext.Run(t, fmt.Sprintf("%s/%d", tc.desc, sz), func(t *testing.T) { - bb := &bytes.Buffer{} - w := NewWriter(bb, tc.t) - // Differently sized dst and src buffers are not part of the - // exported API. We override them manually. - w.dst = make([]byte, tc.dstSize) - w.src = make([]byte, tc.srcSize) - src := make([]byte, sz) - var err error - for b := tc.src; len(b) > 0 && err == nil; { - n := copy(src, b) - b = b[n:] - m := 0 - m, err = w.Write(src[:n]) - if m != n && err == nil { - t.Errorf("did not consume all bytes %d < %d", m, n) - } - } - if err == nil { - err = w.Close() - } - str := bb.String() - if str != tc.wantStr || err != tc.wantErr { - t.Errorf("\ngot %q, %v\nwant %q, %v", str, err, tc.wantStr, tc.wantErr) - } - }) - } - } -} - -func TestNop(t *testing.T) { - testCases := []struct { - str string - dstSize int - err error - }{ - {"", 0, nil}, - {"", 10, nil}, - {"a", 0, ErrShortDst}, - {"a", 1, nil}, - {"a", 10, nil}, - } - for i, tc := range testCases { - dst := make([]byte, tc.dstSize) - nDst, nSrc, err := Nop.Transform(dst, []byte(tc.str), true) - want := tc.str - if tc.dstSize < len(want) { - want = want[:tc.dstSize] - } - if got := string(dst[:nDst]); got != want || err != tc.err || nSrc != nDst { - t.Errorf("%d:\ngot %q, %d, %v\nwant %q, %d, %v", i, got, nSrc, err, want, nDst, tc.err) - } - } -} - -func TestDiscard(t *testing.T) { - testCases := []struct { - str string - dstSize int - }{ - {"", 0}, - {"", 10}, - {"a", 0}, - {"ab", 10}, - } - for i, tc := range testCases { - nDst, nSrc, err := Discard.Transform(make([]byte, tc.dstSize), []byte(tc.str), true) - if nDst != 0 || nSrc != len(tc.str) || err != nil { - t.Errorf("%d:\ngot %q, %d, %v\nwant 0, %d, nil", i, nDst, nSrc, err, len(tc.str)) - } - } -} - -// mkChain creates a Chain transformer. x must be alternating between transformer -// and bufSize, like T, (sz, T)* -func mkChain(x ...interface{}) *chain { - t := []Transformer{} - for i := 0; i < len(x); i += 2 { - t = append(t, x[i].(Transformer)) - } - c := Chain(t...).(*chain) - for i, j := 1, 1; i < len(x); i, j = i+2, j+1 { - c.link[j].b = make([]byte, x[i].(int)) - } - return c -} - -func chainTests() []testCase { - return []testCase{ - { - desc: "nil error", - t: mkChain(rleEncode{}, 100, lowerCaseASCII{}), - src: "ABB", - dstSize: 100, - srcSize: 100, - wantStr: "1a2b", - wantErr: nil, - wantIter: 1, - }, - - { - desc: "short dst buffer", - t: mkChain(lowerCaseASCII{}, 3, rleDecode{}), - src: "1a2b3c10d11e0f1g", - dstSize: 10, - srcSize: 3, - wantStr: "abbcccdddddddddd", - wantErr: ErrShortDst, - }, - - { - desc: "short internal dst buffer", - t: mkChain(lowerCaseASCII{}, 3, rleDecode{}, 10, Nop), - src: "1a2b3c10d11e0f1g", - dstSize: 100, - srcSize: 3, - wantStr: "abbcccdddddddddd", - wantErr: errShortInternal, - }, - - { - desc: "short internal dst buffer from input", - t: mkChain(rleDecode{}, 10, Nop), - src: "1a2b3c10d11e0f1g", - dstSize: 100, - srcSize: 3, - wantStr: "abbcccdddddddddd", - wantErr: errShortInternal, - }, - - { - desc: "empty short internal dst buffer", - t: mkChain(lowerCaseASCII{}, 3, rleDecode{}, 10, Nop), - src: "4a7b11e0f1g", - dstSize: 100, - srcSize: 3, - wantStr: "aaaabbbbbbb", - wantErr: errShortInternal, - }, - - { - desc: "empty short internal dst buffer from input", - t: mkChain(rleDecode{}, 10, Nop), - src: "4a7b11e0f1g", - dstSize: 100, - srcSize: 3, - wantStr: "aaaabbbbbbb", - wantErr: errShortInternal, - }, - - { - desc: "short internal src buffer after full dst buffer", - t: mkChain(Nop, 5, rleEncode{}, 10, Nop), - src: "cccccddddd", - dstSize: 100, - srcSize: 100, - wantStr: "", - wantErr: errShortInternal, - wantIter: 1, - }, - - { - desc: "short internal src buffer after short dst buffer; test lastFull", - t: mkChain(rleDecode{}, 5, rleEncode{}, 4, Nop), - src: "2a1b4c6d", - dstSize: 100, - srcSize: 100, - wantStr: "2a1b", - wantErr: errShortInternal, - }, - - { - desc: "short internal src buffer after successful complete fill", - t: mkChain(Nop, 3, rleDecode{}), - src: "123a4b", - dstSize: 4, - srcSize: 3, - wantStr: "", - wantErr: errShortInternal, - wantIter: 1, - }, - - { - desc: "short internal src buffer after short dst buffer; test lastFull", - t: mkChain(rleDecode{}, 5, rleEncode{}), - src: "2a1b4c6d", - dstSize: 4, - srcSize: 100, - wantStr: "2a1b", - wantErr: errShortInternal, - }, - - { - desc: "short src buffer", - t: mkChain(rleEncode{}, 5, Nop), - src: "abbcccddddeeeee", - dstSize: 4, - srcSize: 4, - ioSize: 4, - wantStr: "1a2b3c", - wantErr: ErrShortSrc, - }, - - { - desc: "process all in one go", - t: mkChain(rleEncode{}, 5, Nop), - src: "abbcccddddeeeeeffffff", - dstSize: 100, - srcSize: 100, - wantStr: "1a2b3c4d5e6f", - wantErr: nil, - wantIter: 1, - }, - - { - desc: "complete processing downstream after error", - t: mkChain(dontMentionX{}, 2, rleDecode{}, 5, Nop), - src: "3a4b5eX", - dstSize: 100, - srcSize: 100, - ioSize: 100, - wantStr: "aaabbbbeeeee", - wantErr: errYouMentionedX, - }, - - { - desc: "return downstream fatal errors first (followed by short dst)", - t: mkChain(dontMentionX{}, 8, rleDecode{}, 4, Nop), - src: "3a4b5eX", - dstSize: 100, - srcSize: 100, - ioSize: 100, - wantStr: "aaabbbb", - wantErr: errShortInternal, - }, - - { - desc: "return downstream fatal errors first (followed by short src)", - t: mkChain(dontMentionX{}, 5, Nop, 1, rleDecode{}), - src: "1a5bX", - dstSize: 100, - srcSize: 100, - ioSize: 100, - wantStr: "", - wantErr: errShortInternal, - }, - - { - desc: "short internal", - t: mkChain(Nop, 11, rleEncode{}, 3, Nop), - src: "abbcccddddddddddeeeeeeeeeeeg", - dstSize: 3, - srcSize: 100, - wantStr: "1a2b3c10d", - wantErr: errShortInternal, - }, - } -} - -func doTransform(tc testCase) (res string, iter int, err error) { - tc.t.Reset() - dst := make([]byte, tc.dstSize) - out, in := make([]byte, 0, 2*len(tc.src)), []byte(tc.src) - for { - iter++ - src, atEOF := in, true - if len(src) > tc.srcSize { - src, atEOF = src[:tc.srcSize], false - } - nDst, nSrc, err := tc.t.Transform(dst, src, atEOF) - out = append(out, dst[:nDst]...) - in = in[nSrc:] - switch { - case err == nil && len(in) != 0: - case err == ErrShortSrc && nSrc > 0: - case err == ErrShortDst && (nDst > 0 || nSrc > 0): - default: - return string(out), iter, err - } - } -} - -func TestChain(t *testing.T) { - if c, ok := Chain().(nop); !ok { - t.Errorf("empty chain: %v; want Nop", c) - } - - // Test Chain for a single Transformer. - for _, tc := range testCases { - tc.t = Chain(tc.t) - str, _, err := doTransform(tc) - if str != tc.wantStr || err != tc.wantErr { - t.Errorf("%s:\ngot %q, %v\nwant %q, %v", tc, str, err, tc.wantStr, tc.wantErr) - } - } - - tests := chainTests() - sizes := []int{1, 2, 3, 4, 5, 7, 10, 100, 1000} - addTest := func(tc testCase, t *chain) { - if t.link[0].t != tc.t && tc.wantErr == ErrShortSrc { - tc.wantErr = errShortInternal - } - if t.link[len(t.link)-2].t != tc.t && tc.wantErr == ErrShortDst { - tc.wantErr = errShortInternal - } - tc.t = t - tests = append(tests, tc) - } - for _, tc := range testCases { - for _, sz := range sizes { - tt := tc - tt.dstSize = sz - addTest(tt, mkChain(tc.t, tc.dstSize, Nop)) - addTest(tt, mkChain(tc.t, tc.dstSize, Nop, 2, Nop)) - addTest(tt, mkChain(Nop, tc.srcSize, tc.t, tc.dstSize, Nop)) - if sz >= tc.dstSize && (tc.wantErr != ErrShortDst || sz == tc.dstSize) { - addTest(tt, mkChain(Nop, tc.srcSize, tc.t)) - addTest(tt, mkChain(Nop, 100, Nop, tc.srcSize, tc.t)) - } - } - } - for _, tc := range testCases { - tt := tc - tt.dstSize = 1 - tt.wantStr = "" - addTest(tt, mkChain(tc.t, tc.dstSize, Discard)) - addTest(tt, mkChain(Nop, tc.srcSize, tc.t, tc.dstSize, Discard)) - addTest(tt, mkChain(Nop, tc.srcSize, tc.t, tc.dstSize, Nop, tc.dstSize, Discard)) - } - for _, tc := range testCases { - tt := tc - tt.dstSize = 100 - tt.wantStr = strings.Replace(tc.src, "0f", "", -1) - // Chain encoders and decoders. - if _, ok := tc.t.(rleEncode); ok && tc.wantErr == nil { - addTest(tt, mkChain(tc.t, tc.dstSize, Nop, 1000, rleDecode{})) - addTest(tt, mkChain(tc.t, tc.dstSize, Nop, tc.dstSize, rleDecode{})) - addTest(tt, mkChain(Nop, tc.srcSize, tc.t, tc.dstSize, Nop, 100, rleDecode{})) - // decoding needs larger destinations - addTest(tt, mkChain(Nop, tc.srcSize, tc.t, tc.dstSize, rleDecode{}, 100, Nop)) - addTest(tt, mkChain(Nop, tc.srcSize, tc.t, tc.dstSize, Nop, 100, rleDecode{}, 100, Nop)) - } else if _, ok := tc.t.(rleDecode); ok && tc.wantErr == nil { - // The internal buffer size may need to be the sum of the maximum segment - // size of the two encoders! - addTest(tt, mkChain(tc.t, 2*tc.dstSize, rleEncode{})) - addTest(tt, mkChain(tc.t, tc.dstSize, Nop, 101, rleEncode{})) - addTest(tt, mkChain(Nop, tc.srcSize, tc.t, tc.dstSize, Nop, 100, rleEncode{})) - addTest(tt, mkChain(Nop, tc.srcSize, tc.t, tc.dstSize, Nop, 200, rleEncode{}, 100, Nop)) - } - } - for _, tc := range tests { - str, iter, err := doTransform(tc) - mi := tc.wantIter != 0 && tc.wantIter != iter - if str != tc.wantStr || err != tc.wantErr || mi { - t.Errorf("%s:\ngot iter:%d, %q, %v\nwant iter:%d, %q, %v", tc, iter, str, err, tc.wantIter, tc.wantStr, tc.wantErr) - } - break - } -} - -func TestRemoveFunc(t *testing.T) { - filter := RemoveFunc(func(r rune) bool { - return strings.IndexRune("ab\u0300\u1234,", r) != -1 - }) - tests := []testCase{ - { - src: ",", - wantStr: "", - }, - - { - src: "c", - wantStr: "c", - }, - - { - src: "\u2345", - wantStr: "\u2345", - }, - - { - src: "tschüß", - wantStr: "tschüß", - }, - - { - src: ",до,свидания,", - wantStr: "досвидания", - }, - - { - src: "a\xbd\xb2=\xbc ⌘", - wantStr: "\uFFFD\uFFFD=\uFFFD ⌘", - }, - - { - // If we didn't replace illegal bytes with RuneError, the result - // would be \u0300 or the code would need to be more complex. - src: "\xcc\u0300\x80", - wantStr: "\uFFFD\uFFFD", - }, - - { - src: "\xcc\u0300\x80", - dstSize: 3, - wantStr: "\uFFFD\uFFFD", - wantIter: 2, - }, - - { - // Test a long buffer greater than the internal buffer size - src: "hello\xcc\xcc\xccworld", - srcSize: 13, - wantStr: "hello\uFFFD\uFFFD\uFFFDworld", - wantIter: 1, - }, - - { - src: "\u2345", - dstSize: 2, - wantStr: "", - wantErr: ErrShortDst, - }, - - { - src: "\xcc", - dstSize: 2, - wantStr: "", - wantErr: ErrShortDst, - }, - - { - src: "\u0300", - dstSize: 2, - srcSize: 1, - wantStr: "", - wantErr: ErrShortSrc, - }, - - { - t: RemoveFunc(func(r rune) bool { - return r == utf8.RuneError - }), - src: "\xcc\u0300\x80", - wantStr: "\u0300", - }, - } - - for _, tc := range tests { - tc.desc = tc.src - if tc.t == nil { - tc.t = filter - } - if tc.dstSize == 0 { - tc.dstSize = 100 - } - if tc.srcSize == 0 { - tc.srcSize = 100 - } - str, iter, err := doTransform(tc) - mi := tc.wantIter != 0 && tc.wantIter != iter - if str != tc.wantStr || err != tc.wantErr || mi { - t.Errorf("%+q:\ngot iter:%d, %+q, %v\nwant iter:%d, %+q, %v", tc.src, iter, str, err, tc.wantIter, tc.wantStr, tc.wantErr) - } - - tc.src = str - idem, _, _ := doTransform(tc) - if str != idem { - t.Errorf("%+q: found %+q; want %+q", tc.src, idem, str) - } - } -} - -func testString(t *testing.T, f func(Transformer, string) (string, int, error)) { - for _, tt := range append(testCases, chainTests()...) { - if tt.desc == "allowStutter = true" { - // We don't have control over the buffer size, so we eliminate tests - // that depend on a specific buffer size being set. - continue - } - if tt.wantErr == ErrShortDst || tt.wantErr == ErrShortSrc { - // The result string will be different. - continue - } - testtext.Run(t, tt.desc, func(t *testing.T) { - got, n, err := f(tt.t, tt.src) - if tt.wantErr != err { - t.Errorf("error: got %v; want %v", err, tt.wantErr) - } - // Check that err == nil implies that n == len(tt.src). Note that vice - // versa isn't necessarily true. - if err == nil && n != len(tt.src) { - t.Errorf("err == nil: got %d bytes, want %d", n, err) - } - if got != tt.wantStr { - t.Errorf("string: got %q; want %q", got, tt.wantStr) - } - }) - } -} - -func TestBytes(t *testing.T) { - testString(t, func(z Transformer, s string) (string, int, error) { - b, n, err := Bytes(z, []byte(s)) - return string(b), n, err - }) -} - -func TestAppend(t *testing.T) { - // Create a bunch of subtests for different buffer sizes. - testCases := [][]byte{ - nil, - make([]byte, 0, 0), - make([]byte, 0, 1), - make([]byte, 1, 1), - make([]byte, 1, 5), - make([]byte, 100, 100), - make([]byte, 100, 200), - } - for _, tc := range testCases { - testString(t, func(z Transformer, s string) (string, int, error) { - b, n, err := Append(z, tc, []byte(s)) - return string(b[len(tc):]), n, err - }) - } -} - -func TestString(t *testing.T) { - testtext.Run(t, "transform", func(t *testing.T) { testString(t, String) }) - - // Overrun the internal destination buffer. - for i, s := range []string{ - aaa[:1*initialBufSize-1], - aaa[:1*initialBufSize+0], - aaa[:1*initialBufSize+1], - AAA[:1*initialBufSize-1], - AAA[:1*initialBufSize+0], - AAA[:1*initialBufSize+1], - AAA[:2*initialBufSize-1], - AAA[:2*initialBufSize+0], - AAA[:2*initialBufSize+1], - aaa[:1*initialBufSize-2] + "A", - aaa[:1*initialBufSize-1] + "A", - aaa[:1*initialBufSize+0] + "A", - aaa[:1*initialBufSize+1] + "A", - } { - testtext.Run(t, fmt.Sprint("dst buffer test using lower/", i), func(t *testing.T) { - got, _, _ := String(lowerCaseASCII{}, s) - if want := strings.ToLower(s); got != want { - t.Errorf("got %s (%d); want %s (%d)", got, len(got), want, len(want)) - } - }) - } - - // Overrun the internal source buffer. - for i, s := range []string{ - aaa[:1*initialBufSize-1], - aaa[:1*initialBufSize+0], - aaa[:1*initialBufSize+1], - aaa[:2*initialBufSize+1], - aaa[:2*initialBufSize+0], - aaa[:2*initialBufSize+1], - } { - testtext.Run(t, fmt.Sprint("src buffer test using rleEncode/", i), func(t *testing.T) { - got, _, _ := String(rleEncode{}, s) - if want := fmt.Sprintf("%da", len(s)); got != want { - t.Errorf("got %s (%d); want %s (%d)", got, len(got), want, len(want)) - } - }) - } - - // Test allocations for non-changing strings. - // Note we still need to allocate a single buffer. - for i, s := range []string{ - "", - "123456789", - aaa[:initialBufSize-1], - aaa[:initialBufSize+0], - aaa[:initialBufSize+1], - aaa[:10*initialBufSize], - } { - testtext.Run(t, fmt.Sprint("alloc/", i), func(t *testing.T) { - if n := testtext.AllocsPerRun(5, func() { String(&lowerCaseASCIILookahead{}, s) }); n > 1 { - t.Errorf("#allocs was %f; want 1", n) - } - }) - } -} - -// TestBytesAllocation tests that buffer growth stays limited with the trickler -// transformer, which behaves oddly but within spec. In case buffer growth is -// not correctly handled, the test will either panic with a failed allocation or -// thrash. To ensure the tests terminate under the last condition, we time out -// after some sufficiently long period of time. -func TestBytesAllocation(t *testing.T) { - done := make(chan bool) - go func() { - in := bytes.Repeat([]byte{'a'}, 1000) - tr := trickler(make([]byte, 1)) - Bytes(&tr, in) - done <- true - }() - select { - case <-done: - case <-time.After(3 * time.Second): - t.Error("time out, likely due to excessive allocation") - } -} - -// TestStringAllocation tests that buffer growth stays limited with the trickler -// transformer, which behaves oddly but within spec. In case buffer growth is -// not correctly handled, the test will either panic with a failed allocation or -// thrash. To ensure the tests terminate under the last condition, we time out -// after some sufficiently long period of time. -func TestStringAllocation(t *testing.T) { - done := make(chan bool) - go func() { - tr := trickler(make([]byte, 1)) - String(&tr, aaa[:1000]) - done <- true - }() - select { - case <-done: - case <-time.After(3 * time.Second): - t.Error("time out, likely due to excessive allocation") - } -} - -func BenchmarkStringLowerEmpty(b *testing.B) { - for i := 0; i < b.N; i++ { - String(&lowerCaseASCIILookahead{}, "") - } -} - -func BenchmarkStringLowerIdentical(b *testing.B) { - for i := 0; i < b.N; i++ { - String(&lowerCaseASCIILookahead{}, aaa[:4096]) - } -} - -func BenchmarkStringLowerChanged(b *testing.B) { - for i := 0; i < b.N; i++ { - String(&lowerCaseASCIILookahead{}, AAA[:4096]) - } -} - -var ( - aaa = strings.Repeat("a", 4096) - AAA = strings.Repeat("A", 4096) -) diff --git a/vendor/golang.org/x/text/unicode/bidi/core_test.go b/vendor/golang.org/x/text/unicode/bidi/core_test.go deleted file mode 100644 index f28d386c..00000000 --- a/vendor/golang.org/x/text/unicode/bidi/core_test.go +++ /dev/null @@ -1,224 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package bidi - -import ( - "flag" - "fmt" - "log" - "strconv" - "strings" - "testing" - - "golang.org/x/text/internal/gen" - "golang.org/x/text/internal/testtext" - "golang.org/x/text/internal/ucd" - "golang.org/x/text/unicode/norm" -) - -var testLevels = flag.Bool("levels", false, "enable testing of levels") - -// TestBidiCore performs the tests in BidiTest.txt. -// See http://www.unicode.org/Public/UCD/latest/ucd/BidiTest.txt. -func TestBidiCore(t *testing.T) { - testtext.SkipIfNotLong(t) - - r := gen.OpenUCDFile("BidiTest.txt") - defer r.Close() - - var wantLevels, wantOrder []string - p := ucd.New(r, ucd.Part(func(p *ucd.Parser) { - s := strings.Split(p.String(0), ":") - switch s[0] { - case "Levels": - wantLevels = strings.Fields(s[1]) - case "Reorder": - wantOrder = strings.Fields(s[1]) - default: - log.Fatalf("Unknown part %q.", s[0]) - } - })) - - for p.Next() { - types := []Class{} - for _, s := range p.Strings(0) { - types = append(types, bidiClass[s]) - } - // We ignore the bracketing part of the algorithm. - pairTypes := make([]bracketType, len(types)) - pairValues := make([]rune, len(types)) - - for i := uint(0); i < 3; i++ { - if p.Uint(1)&(1< 5 { - return fmt.Errorf("before %d > 5", before) - } - r.calls = append(r.calls, fmt.Sprintf("R:%s-%d", anchor, before)) - return nil -} - -func (r *recorder) Insert(level int, str, context, extend string) error { - s := fmt.Sprintf("O:%d:%s", level, str) - if context != "" { - s += "|" + context - } - if extend != "" { - s += "/" + extend - } - r.calls = append(r.calls, s) - return nil -} - -func (r *recorder) Index(id string) { - r.calls = append(r.calls, fmt.Sprintf("I:%s", id)) -} - -func (r *recorder) Error(err error) { - r.calls = append(r.calls, fmt.Sprintf("E:%v", err)) -} - -func TestRuleProcessor(t *testing.T) { - for _, tt := range []struct { - desc string - in string - out string - }{ - {desc: "empty"}, - {desc: "whitespace and comments only", - in: ` - - - # adsfads -# adfadf - `, - }, - { - desc: "reset anchor", - in: ` - & a - &b # - & [ before 3 ] c - & [before 4] d & ee - & [first tertiary ignorable] - &'g' - & 'h''h'h'h' - &'\u0069' # LATIN SMALL LETTER I - `, - out: ` - R:a-0 - R:b-0 - R:c-3 - R:d-4 - R:ee-0 - R:-0 - R:g-0 - R:hhhh-0 - R:i-0 - `, - }, - { - desc: "ordering", - in: ` - & 0 - < 1 <<''2# -<<< 3'3''33'3# - <<<<4 - = 5 << 6 | s - <<<< 7 / z - << 8'' | s / ch - `, - out: ` - R:0-0 - O:1:1 - O:2:'2 - O:3:33333 - O:4:4 - O:5:5 - O:2:6|s - O:4:7/z - O:2:8'|s/ch - `, - }, - { - desc: "index", - in: "< '\ufdd0'A", - out: "I:A", - }, - { - desc: "sequence", - in: ` - & 0 - <<* 1234 - <* a-cde-f - =* q-q - `, - out: ` - R:0-0 - O:2:1 - O:2:2 - O:2:3 - O:2:4 - O:1:a - O:1:b - O:1:c - O:1:d - O:1:e - O:1:f - O:5:q - `, - }, - { - desc: "compact", - in: "&B 5", - }, - { - desc: "err empty order", - in: " < ", - out: "E:1: missing string", - }, - { - desc: "err empty identity", - in: " = ", - out: "E:1: missing string", - }, - { - desc: "err empty context", - in: " < a | ", - out: "E:1: missing string after context", - }, - { - desc: "err empty extend", - in: " < a / ", - out: "E:1: missing string after extension", - }, - { - desc: "err empty sequence", - in: " <* ", - out: "E:1: empty sequence", - }, - { - desc: "err sequence 1", - in: " <* -a", - out: "E:1: range without starter value", - }, - { - desc: "err sequence 3", - in: " <* a-a-b", - out: `O:1:a - E:1: range without starter value - `, - }, - { - desc: "err sequence 3", - in: " <* b-a", - out: `O:1:b - E:1: invalid range 'b'-'a' - `, - }, - { - desc: "err unmatched quote", - in: " < 'b", - out: ` E:1: unmatched single quote - `, - }, - } { - rec := &recorder{} - err := Collation{ - Cr: []*Common{ - {hidden: hidden{CharData: tt.in}}, - }, - }.Process(rec) - if err != nil { - rec.Error(err) - } - got := rec.calls - want := strings.Split(strings.TrimSpace(tt.out), "\n") - if tt.out == "" { - want = nil - } - if len(got) != len(want) { - t.Errorf("%s: nResults: got %d; want %d", tt.desc, len(got), len(want)) - continue - } - for i, g := range got { - if want := strings.TrimSpace(want[i]); g != want { - t.Errorf("%s:%d: got %q; want %q", tt.desc, i, g, want) - } - } - } -} diff --git a/vendor/golang.org/x/text/unicode/cldr/data_test.go b/vendor/golang.org/x/text/unicode/cldr/data_test.go deleted file mode 100644 index 16621896..00000000 --- a/vendor/golang.org/x/text/unicode/cldr/data_test.go +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cldr - -// This file contains test data. - -import ( - "io" - "strings" -) - -type testLoader struct { -} - -func (t testLoader) Len() int { - return len(testFiles) -} - -func (t testLoader) Path(i int) string { - return testPaths[i] -} - -func (t testLoader) Reader(i int) (io.ReadCloser, error) { - return &reader{*strings.NewReader(testFiles[i])}, nil -} - -// reader adds a dummy Close method to strings.Reader so that it -// satisfies the io.ReadCloser interface. -type reader struct { - strings.Reader -} - -func (r reader) Close() error { - return nil -} - -var ( - testFiles = []string{de_xml, gsw_xml, root_xml} - testPaths = []string{ - "common/main/de.xml", - "common/main/gsw.xml", - "common/main/root.xml", - } -) - -var root_xml = ` - - - - - - - - [] - [] - [\- ‐ – — … ' ‘ ‚ " “ „ \& #] - {0}… - …{0} - ? - - - - - - - - - - - - - - - - - - - - - - - - 11 - 22 - 33 - 44 - - - - - 1 - 2 - 3 - 4 - - - - - - - - - - -` - -var de_xml = ` - - - - - - - [a ä b c d e ö p q r s ß t u ü v w x y z] - [á à ă] - [A B C D E F G H Z] - {0} … - … {0} - ? - - der die das - - - - - - - - - BBB - - - bbb - - - - - - - - - M - A - - - Maerz - April - Mai - - - - - m - m - - - april - mai - - - - - - - - - yes:y - no:n - - - -` - -var gsw_xml = ` - - - - - - - - - -` diff --git a/vendor/golang.org/x/text/unicode/cldr/examples_test.go b/vendor/golang.org/x/text/unicode/cldr/examples_test.go deleted file mode 100644 index 1a69b007..00000000 --- a/vendor/golang.org/x/text/unicode/cldr/examples_test.go +++ /dev/null @@ -1,21 +0,0 @@ -package cldr_test - -import ( - "fmt" - - "golang.org/x/text/unicode/cldr" -) - -func ExampleSlice() { - var dr *cldr.CLDR // assume this is initialized - - x, _ := dr.LDML("en") - cs := x.Collations.Collation - // remove all but the default - cldr.MakeSlice(&cs).Filter(func(e cldr.Elem) bool { - return e.GetCommon().Type != x.Collations.Default() - }) - for i, c := range cs { - fmt.Println(i, c.Type) - } -} diff --git a/vendor/golang.org/x/text/unicode/cldr/resolve_test.go b/vendor/golang.org/x/text/unicode/cldr/resolve_test.go deleted file mode 100644 index 3d8edaec..00000000 --- a/vendor/golang.org/x/text/unicode/cldr/resolve_test.go +++ /dev/null @@ -1,368 +0,0 @@ -package cldr - -import ( - "fmt" - "log" - "reflect" - "testing" -) - -func failOnError(err error) { - if err != nil { - log.Panic(err) - } -} - -func data() *CLDR { - d := Decoder{} - data, err := d.Decode(testLoader{}) - failOnError(err) - return data -} - -type h struct { - A string `xml:"ha,attr"` - E string `xml:"he"` - D string `xml:",chardata"` - X string -} - -type fieldTest struct { - Common - To string `xml:"to,attr"` - Key string `xml:"key,attr"` - E string `xml:"e"` - D string `xml:",chardata"` - X string - h -} - -var testStruct = fieldTest{ - Common: Common{ - name: "mapping", // exclude "type" as distinguishing attribute - Type: "foo", - Alt: "foo", - }, - To: "nyc", - Key: "k", - E: "E", - D: "D", - h: h{ - A: "A", - E: "E", - D: "D", - }, -} - -func TestIter(t *testing.T) { - tests := map[string]string{ - "Type": "foo", - "Alt": "foo", - "To": "nyc", - "A": "A", - "Alias": "", - } - k := 0 - for i := iter(reflect.ValueOf(testStruct)); !i.done(); i.next() { - v := i.value() - if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.String { - v = v.Elem() - } - name := i.field().Name - if w, ok := tests[name]; ok { - s := fmt.Sprint(v.Interface()) - if w != s { - t.Errorf("value: found %q; want %q", w, s) - } - delete(tests, name) - } - k++ - } - if len(tests) != 0 { - t.Errorf("missing fields: %v", tests) - } -} - -func TestFindField(t *testing.T) { - tests := []struct { - name, val string - exist bool - }{ - {"type", "foo", true}, - {"alt", "foo", true}, - {"to", "nyc", true}, - {"he", "E", true}, - {"q", "", false}, - } - vf := reflect.ValueOf(testStruct) - for i, tt := range tests { - v, err := findField(vf, tt.name) - if (err == nil) != tt.exist { - t.Errorf("%d: field %q present is %v; want %v", i, tt.name, err == nil, tt.exist) - } else if tt.exist { - if v.Kind() == reflect.Ptr { - if v.IsNil() { - continue - } - v = v.Elem() - } - if v.String() != tt.val { - t.Errorf("%d: found value %q; want %q", i, v.String(), tt.val) - } - } - } -} - -var keyTests = []struct { - exclude []string - key string -}{ - {[]string{}, "alt=foo;key=k;to=nyc"}, - {[]string{"type"}, "alt=foo;key=k;to=nyc"}, - {[]string{"choice"}, "alt=foo;key=k;to=nyc"}, - {[]string{"alt"}, "key=k;to=nyc"}, - {[]string{"a"}, "alt=foo;key=k;to=nyc"}, - {[]string{"to"}, "alt=foo;key=k"}, - {[]string{"alt", "to"}, "key=k"}, - {[]string{"alt", "to", "key"}, ""}, -} - -func TestAttrKey(t *testing.T) { - v := reflect.ValueOf(&testStruct) - for i, tt := range keyTests { - key := attrKey(v, tt.exclude...) - if key != tt.key { - t.Errorf("%d: found %q, want %q", i, key, tt.key) - } - } -} - -func TestKey(t *testing.T) { - for i, tt := range keyTests { - key := Key(&testStruct, tt.exclude...) - if key != tt.key { - t.Errorf("%d: found %q, want %q", i, key, tt.key) - } - } -} - -func testEnclosing(t *testing.T, x *LDML, name string) { - eq := func(a, b Elem, i int) { - for ; i > 0; i-- { - b = b.enclosing() - } - if a != b { - t.Errorf("%s: found path %q, want %q", name, getPath(a), getPath(b)) - } - } - eq(x, x, 0) - eq(x, x.Identity, 1) - eq(x, x.Dates.Calendars, 2) - eq(x, x.Dates.Calendars.Calendar[0], 3) - eq(x, x.Dates.Calendars.Calendar[1], 3) - //eq(x, x.Dates.Calendars.Calendar[0].Months, 4) - eq(x, x.Dates.Calendars.Calendar[1].Months, 4) -} - -func TestEnclosing(t *testing.T) { - testEnclosing(t, data().RawLDML("de"), "enclosing-raw") - de, _ := data().LDML("de") - testEnclosing(t, de, "enclosing") -} - -func TestDeepCopy(t *testing.T) { - eq := func(have, want string) { - if have != want { - t.Errorf("found %q; want %q", have, want) - } - } - x, _ := data().LDML("de") - vc := deepCopy(reflect.ValueOf(x)) - c := vc.Interface().(*LDML) - linkEnclosing(nil, c) - if x == c { - t.Errorf("did not copy") - } - - eq(c.name, "ldml") - eq(c.Dates.name, "dates") - testEnclosing(t, c, "deepCopy") -} - -type getTest struct { - loc string - path string - field string // used in combination with length - data string - altData string // used for buddhist calendar if value != "" - typ string - length int - missing bool -} - -const ( - budMon = "dates/calendars/calendar[@type='buddhist']/months/" - chnMon = "dates/calendars/calendar[@type='chinese']/months/" - greMon = "dates/calendars/calendar[@type='gregorian']/months/" -) - -func monthVal(path, context, width string, month int) string { - const format = "%s/monthContext[@type='%s']/monthWidth[@type='%s']/month[@type='%d']" - return fmt.Sprintf(format, path, context, width, month) -} - -var rootGetTests = []getTest{ - {loc: "root", path: "identity/language", typ: "root"}, - {loc: "root", path: "characters/moreInformation", data: "?"}, - {loc: "root", path: "characters", field: "exemplarCharacters", length: 3}, - {loc: "root", path: greMon, field: "monthContext", length: 2}, - {loc: "root", path: greMon + "monthContext[@type='format']/monthWidth[@type='narrow']", field: "month", length: 4}, - {loc: "root", path: greMon + "monthContext[@type='stand-alone']/monthWidth[@type='wide']", field: "month", length: 4}, - // unescaping character data - {loc: "root", path: "characters/exemplarCharacters[@type='punctuation']", data: `[\- ‐ – — … ' ‘ ‚ " “ „ \& #]`}, - // default resolution - {loc: "root", path: "dates/calendars/calendar", typ: "gregorian"}, - // alias resolution - {loc: "root", path: budMon, field: "monthContext", length: 2}, - // crossing but non-circular alias resolution - {loc: "root", path: budMon + "monthContext[@type='format']/monthWidth[@type='narrow']", field: "month", length: 4}, - {loc: "root", path: budMon + "monthContext[@type='stand-alone']/monthWidth[@type='wide']", field: "month", length: 4}, - {loc: "root", path: monthVal(greMon, "format", "wide", 1), data: "11"}, - {loc: "root", path: monthVal(greMon, "format", "narrow", 2), data: "2"}, - {loc: "root", path: monthVal(greMon, "stand-alone", "wide", 3), data: "33"}, - {loc: "root", path: monthVal(greMon, "stand-alone", "narrow", 4), data: "4"}, - {loc: "root", path: monthVal(budMon, "format", "wide", 1), data: "11"}, - {loc: "root", path: monthVal(budMon, "format", "narrow", 2), data: "2"}, - {loc: "root", path: monthVal(budMon, "stand-alone", "wide", 3), data: "33"}, - {loc: "root", path: monthVal(budMon, "stand-alone", "narrow", 4), data: "4"}, -} - -// 19 -var deGetTests = []getTest{ - {loc: "de", path: "identity/language", typ: "de"}, - {loc: "de", path: "posix", length: 2}, - {loc: "de", path: "characters", field: "exemplarCharacters", length: 4}, - {loc: "de", path: "characters/exemplarCharacters[@type='auxiliary']", data: `[á à ă]`}, - // identity is a blocking element, so de should not inherit generation from root. - {loc: "de", path: "identity/generation", missing: true}, - // default resolution - {loc: "root", path: "dates/calendars/calendar", typ: "gregorian"}, - - // absolute path alias resolution - {loc: "gsw", path: "posix", field: "messages", length: 1}, - {loc: "gsw", path: "posix/messages/yesstr", data: "yes:y"}, -} - -// 27(greMon) - 52(budMon) - 77(chnMon) -func calGetTests(s string) []getTest { - tests := []getTest{ - {loc: "de", path: s, length: 2}, - {loc: "de", path: s + "monthContext[@type='format']/monthWidth[@type='wide']", field: "month", length: 5}, - {loc: "de", path: monthVal(s, "format", "wide", 1), data: "11"}, - {loc: "de", path: monthVal(s, "format", "wide", 2), data: "22"}, - {loc: "de", path: monthVal(s, "format", "wide", 3), data: "Maerz", altData: "bbb"}, - {loc: "de", path: monthVal(s, "format", "wide", 4), data: "April"}, - {loc: "de", path: monthVal(s, "format", "wide", 5), data: "Mai"}, - - {loc: "de", path: s + "monthContext[@type='format']/monthWidth[@type='narrow']", field: "month", length: 5}, - {loc: "de", path: monthVal(s, "format", "narrow", 1), data: "1"}, - {loc: "de", path: monthVal(s, "format", "narrow", 2), data: "2"}, - {loc: "de", path: monthVal(s, "format", "narrow", 3), data: "M", altData: "BBB"}, - {loc: "de", path: monthVal(s, "format", "narrow", 4), data: "A"}, - {loc: "de", path: monthVal(s, "format", "narrow", 5), data: "m"}, - - {loc: "de", path: s + "monthContext[@type='stand-alone']/monthWidth[@type='wide']", field: "month", length: 5}, - {loc: "de", path: monthVal(s, "stand-alone", "wide", 1), data: "11"}, - {loc: "de", path: monthVal(s, "stand-alone", "wide", 2), data: "22"}, - {loc: "de", path: monthVal(s, "stand-alone", "wide", 3), data: "Maerz", altData: "bbb"}, - {loc: "de", path: monthVal(s, "stand-alone", "wide", 4), data: "april"}, - {loc: "de", path: monthVal(s, "stand-alone", "wide", 5), data: "mai"}, - - {loc: "de", path: s + "monthContext[@type='stand-alone']/monthWidth[@type='narrow']", field: "month", length: 5}, - {loc: "de", path: monthVal(s, "stand-alone", "narrow", 1), data: "1"}, - {loc: "de", path: monthVal(s, "stand-alone", "narrow", 2), data: "2"}, - {loc: "de", path: monthVal(s, "stand-alone", "narrow", 3), data: "m"}, - {loc: "de", path: monthVal(s, "stand-alone", "narrow", 4), data: "4"}, - {loc: "de", path: monthVal(s, "stand-alone", "narrow", 5), data: "m"}, - } - if s == budMon { - for i, t := range tests { - if t.altData != "" { - tests[i].data = t.altData - } - } - } - return tests -} - -var getTests = append(rootGetTests, - append(deGetTests, - append(calGetTests(greMon), - append(calGetTests(budMon), - calGetTests(chnMon)...)...)...)...) - -func TestPath(t *testing.T) { - d := data() - for i, tt := range getTests { - x, _ := d.LDML(tt.loc) - e, err := walkXPath(x, tt.path) - if err != nil { - if !tt.missing { - t.Errorf("%d:error: %v %v", i, err, tt.missing) - } - continue - } - if tt.missing { - t.Errorf("%d: missing is %v; want %v", i, e == nil, tt.missing) - continue - } - if tt.data != "" && e.GetCommon().Data() != tt.data { - t.Errorf("%d: data is %v; want %v", i, e.GetCommon().Data(), tt.data) - continue - } - if tt.typ != "" && e.GetCommon().Type != tt.typ { - t.Errorf("%d: type is %v; want %v", i, e.GetCommon().Type, tt.typ) - continue - } - if tt.field != "" { - slice, _ := findField(reflect.ValueOf(e), tt.field) - if slice.Len() != tt.length { - t.Errorf("%d: length is %v; want %v", i, slice.Len(), tt.length) - continue - } - } - } -} - -func TestGet(t *testing.T) { - d := data() - for i, tt := range getTests { - x, _ := d.LDML(tt.loc) - e, err := Get(x, tt.path) - if err != nil { - if !tt.missing { - t.Errorf("%d:error: %v %v", i, err, tt.missing) - } - continue - } - if tt.missing { - t.Errorf("%d: missing is %v; want %v", i, e == nil, tt.missing) - continue - } - if tt.data != "" && e.GetCommon().Data() != tt.data { - t.Errorf("%d: data is %v; want %v", i, e.GetCommon().Data(), tt.data) - continue - } - if tt.typ != "" && e.GetCommon().Type != tt.typ { - t.Errorf("%d: type is %v; want %v", i, e.GetCommon().Type, tt.typ) - continue - } - if tt.field != "" { - slice, _ := findField(reflect.ValueOf(e), tt.field) - if slice.Len() != tt.length { - t.Errorf("%d: length is %v; want %v", i, slice.Len(), tt.length) - continue - } - } - } -} diff --git a/vendor/golang.org/x/text/unicode/cldr/slice_test.go b/vendor/golang.org/x/text/unicode/cldr/slice_test.go deleted file mode 100644 index 3d487d3b..00000000 --- a/vendor/golang.org/x/text/unicode/cldr/slice_test.go +++ /dev/null @@ -1,175 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cldr - -import ( - "reflect" - "testing" -) - -type testSlice []*Common - -func mkElem(alt, typ, ref string) *Common { - return &Common{ - Type: typ, - Reference: ref, - Alt: alt, - } -} - -var ( - testSlice1 = testSlice{ - mkElem("1", "a", "i.a"), - mkElem("1", "b", "i.b"), - mkElem("1", "c", "i.c"), - mkElem("2", "b", "ii"), - mkElem("3", "c", "iii"), - mkElem("4", "a", "iv.a"), - mkElem("4", "d", "iv.d"), - } - testSliceE = testSlice{} -) - -func panics(f func()) (panics bool) { - defer func() { - if err := recover(); err != nil { - panics = true - } - }() - f() - return panics -} - -func TestMakeSlice(t *testing.T) { - foo := 1 - bar := []int{} - tests := []struct { - i interface{} - panics bool - err string - }{ - {&foo, true, "should panic when passed a pointer to the wrong type"}, - {&bar, true, "should panic when slice element of the wrong type"}, - {testSlice1, true, "should panic when passed a slice"}, - {&testSlice1, false, "should not panic"}, - } - for i, tt := range tests { - if panics(func() { MakeSlice(tt.i) }) != tt.panics { - t.Errorf("%d: %s", i, tt.err) - } - } -} - -var anyOfTests = []struct { - sl testSlice - values []string - n int -}{ - {testSliceE, []string{}, 0}, - {testSliceE, []string{"1", "2", "3"}, 0}, - {testSlice1, []string{}, 0}, - {testSlice1, []string{"1"}, 3}, - {testSlice1, []string{"2"}, 1}, - {testSlice1, []string{"5"}, 0}, - {testSlice1, []string{"1", "2", "3"}, 5}, -} - -func TestSelectAnyOf(t *testing.T) { - for i, tt := range anyOfTests { - sl := tt.sl - s := MakeSlice(&sl) - s.SelectAnyOf("alt", tt.values...) - if len(sl) != tt.n { - t.Errorf("%d: found len == %d; want %d", i, len(sl), tt.n) - } - } - sl := testSlice1 - s := MakeSlice(&sl) - if !panics(func() { s.SelectAnyOf("foo") }) { - t.Errorf("should panic on non-existing attribute") - } -} - -func TestFilter(t *testing.T) { - for i, tt := range anyOfTests { - sl := tt.sl - s := MakeSlice(&sl) - s.Filter(func(e Elem) bool { - v, _ := findField(reflect.ValueOf(e), "alt") - return in(tt.values, v.String()) - }) - if len(sl) != tt.n { - t.Errorf("%d: found len == %d; want %d", i, len(sl), tt.n) - } - } -} - -func TestGroup(t *testing.T) { - f := func(excl ...string) func(Elem) string { - return func(e Elem) string { - return Key(e, excl...) - } - } - tests := []struct { - sl testSlice - f func(Elem) string - lens []int - }{ - {testSliceE, f(), []int{}}, - {testSlice1, f(), []int{1, 1, 1, 1, 1, 1, 1}}, - {testSlice1, f("type"), []int{3, 1, 1, 2}}, - {testSlice1, f("alt"), []int{2, 2, 2, 1}}, - {testSlice1, f("alt", "type"), []int{7}}, - {testSlice1, f("alt", "type"), []int{7}}, - } - for i, tt := range tests { - sl := tt.sl - s := MakeSlice(&sl) - g := s.Group(tt.f) - if len(tt.lens) != len(g) { - t.Errorf("%d: found %d; want %d", i, len(g), len(tt.lens)) - continue - } - for j, v := range tt.lens { - if n := g[j].Value().Len(); n != v { - t.Errorf("%d: found %d for length of group %d; want %d", i, n, j, v) - } - } - } -} - -func TestSelectOnePerGroup(t *testing.T) { - tests := []struct { - sl testSlice - attr string - values []string - refs []string - }{ - {testSliceE, "alt", []string{"1"}, []string{}}, - {testSliceE, "type", []string{"a"}, []string{}}, - {testSlice1, "alt", []string{"2", "3", "1"}, []string{"i.a", "ii", "iii"}}, - {testSlice1, "alt", []string{"1", "4"}, []string{"i.a", "i.b", "i.c", "iv.d"}}, - {testSlice1, "type", []string{"c", "d"}, []string{"i.c", "iii", "iv.d"}}, - } - for i, tt := range tests { - sl := tt.sl - s := MakeSlice(&sl) - s.SelectOnePerGroup(tt.attr, tt.values) - if len(sl) != len(tt.refs) { - t.Errorf("%d: found result length %d; want %d", i, len(sl), len(tt.refs)) - continue - } - for j, e := range sl { - if tt.refs[j] != e.Reference { - t.Errorf("%d:%d found %s; want %s", i, j, e.Reference, tt.refs[i]) - } - } - } - sl := testSlice1 - s := MakeSlice(&sl) - if !panics(func() { s.SelectOnePerGroup("foo", nil) }) { - t.Errorf("should panic on non-existing attribute") - } -} diff --git a/vendor/golang.org/x/text/unicode/doc.go b/vendor/golang.org/x/text/unicode/doc.go deleted file mode 100644 index e8f1032d..00000000 --- a/vendor/golang.org/x/text/unicode/doc.go +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// unicode holds packages with implementations of Unicode standards that are -// mostly used as building blocks for other packages in golang.org/x/text, -// layout engines, or are otherwise more low-level in nature. -package unicode diff --git a/vendor/golang.org/x/text/unicode/norm/composition_test.go b/vendor/golang.org/x/text/unicode/norm/composition_test.go deleted file mode 100644 index 11684069..00000000 --- a/vendor/golang.org/x/text/unicode/norm/composition_test.go +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package norm - -import "testing" - -// TestCase is used for most tests. -type TestCase struct { - in []rune - out []rune -} - -func runTests(t *testing.T, name string, fm Form, tests []TestCase) { - rb := reorderBuffer{} - rb.init(fm, nil) - for i, test := range tests { - rb.setFlusher(nil, appendFlush) - for j, rune := range test.in { - b := []byte(string(rune)) - src := inputBytes(b) - info := rb.f.info(src, 0) - if j == 0 { - rb.ss.first(info) - } else { - rb.ss.next(info) - } - if rb.insertFlush(src, 0, info) < 0 { - t.Errorf("%s:%d: insert failed for rune %d", name, i, j) - } - } - rb.doFlush() - was := string(rb.out) - want := string(test.out) - if len(was) != len(want) { - t.Errorf("%s:%d: length = %d; want %d", name, i, len(was), len(want)) - } - if was != want { - k, pfx := pidx(was, want) - t.Errorf("%s:%d: \nwas %s%+q; \nwant %s%+q", name, i, pfx, was[k:], pfx, want[k:]) - } - } -} - -func TestFlush(t *testing.T) { - const ( - hello = "Hello " - world = "world!" - ) - buf := make([]byte, maxByteBufferSize) - p := copy(buf, hello) - out := buf[p:] - rb := reorderBuffer{} - rb.initString(NFC, world) - if i := rb.flushCopy(out); i != 0 { - t.Errorf("wrote bytes on flush of empty buffer. (len(out) = %d)", i) - } - - for i := range world { - // No need to set streamSafe values for this test. - rb.insertFlush(rb.src, i, rb.f.info(rb.src, i)) - n := rb.flushCopy(out) - out = out[n:] - p += n - } - - was := buf[:p] - want := hello + world - if string(was) != want { - t.Errorf(`output after flush was "%s"; want "%s"`, string(was), want) - } - if rb.nrune != 0 { - t.Errorf("non-null size of info buffer (rb.nrune == %d)", rb.nrune) - } - if rb.nbyte != 0 { - t.Errorf("non-null size of byte buffer (rb.nbyte == %d)", rb.nbyte) - } -} - -var insertTests = []TestCase{ - {[]rune{'a'}, []rune{'a'}}, - {[]rune{0x300}, []rune{0x300}}, - {[]rune{0x300, 0x316}, []rune{0x316, 0x300}}, // CCC(0x300)==230; CCC(0x316)==220 - {[]rune{0x316, 0x300}, []rune{0x316, 0x300}}, - {[]rune{0x41, 0x316, 0x300}, []rune{0x41, 0x316, 0x300}}, - {[]rune{0x41, 0x300, 0x316}, []rune{0x41, 0x316, 0x300}}, - {[]rune{0x300, 0x316, 0x41}, []rune{0x316, 0x300, 0x41}}, - {[]rune{0x41, 0x300, 0x40, 0x316}, []rune{0x41, 0x300, 0x40, 0x316}}, -} - -func TestInsert(t *testing.T) { - runTests(t, "TestInsert", NFD, insertTests) -} - -var decompositionNFDTest = []TestCase{ - {[]rune{0xC0}, []rune{0x41, 0x300}}, - {[]rune{0xAC00}, []rune{0x1100, 0x1161}}, - {[]rune{0x01C4}, []rune{0x01C4}}, - {[]rune{0x320E}, []rune{0x320E}}, - {[]rune("음ẻ과"), []rune{0x110B, 0x1173, 0x11B7, 0x65, 0x309, 0x1100, 0x116A}}, -} - -var decompositionNFKDTest = []TestCase{ - {[]rune{0xC0}, []rune{0x41, 0x300}}, - {[]rune{0xAC00}, []rune{0x1100, 0x1161}}, - {[]rune{0x01C4}, []rune{0x44, 0x5A, 0x030C}}, - {[]rune{0x320E}, []rune{0x28, 0x1100, 0x1161, 0x29}}, -} - -func TestDecomposition(t *testing.T) { - runTests(t, "TestDecompositionNFD", NFD, decompositionNFDTest) - runTests(t, "TestDecompositionNFKD", NFKD, decompositionNFKDTest) -} - -var compositionTest = []TestCase{ - {[]rune{0x41, 0x300}, []rune{0xC0}}, - {[]rune{0x41, 0x316}, []rune{0x41, 0x316}}, - {[]rune{0x41, 0x300, 0x35D}, []rune{0xC0, 0x35D}}, - {[]rune{0x41, 0x316, 0x300}, []rune{0xC0, 0x316}}, - // blocking starter - {[]rune{0x41, 0x316, 0x40, 0x300}, []rune{0x41, 0x316, 0x40, 0x300}}, - {[]rune{0x1100, 0x1161}, []rune{0xAC00}}, - // parenthesized Hangul, alternate between ASCII and Hangul. - {[]rune{0x28, 0x1100, 0x1161, 0x29}, []rune{0x28, 0xAC00, 0x29}}, -} - -func TestComposition(t *testing.T) { - runTests(t, "TestComposition", NFC, compositionTest) -} diff --git a/vendor/golang.org/x/text/unicode/norm/data10.0.0_test.go b/vendor/golang.org/x/text/unicode/norm/data10.0.0_test.go deleted file mode 100644 index 1d0f73dc..00000000 --- a/vendor/golang.org/x/text/unicode/norm/data10.0.0_test.go +++ /dev/null @@ -1,7424 +0,0 @@ -// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. - -// +build go1.10 - -package norm - -const ( - Yes = iota - No - Maybe -) - -type formData struct { - qc uint8 - combinesForward bool - decomposition string -} - -type runeData struct { - r rune - ccc uint8 - nLead uint8 - nTrail uint8 - f [2]formData // 0: canonical; 1: compatibility -} - -func f(qc uint8, cf bool, dec string) [2]formData { - return [2]formData{{qc, cf, dec}, {qc, cf, dec}} -} - -func g(qc, qck uint8, cf, cfk bool, d, dk string) [2]formData { - return [2]formData{{qc, cf, d}, {qck, cfk, dk}} -} - -var testData = []runeData{ - {0x0, 0, 0, 0, f(Yes, false, "")}, - {0x3c, 0, 0, 0, f(Yes, true, "")}, - {0x3f, 0, 0, 0, f(Yes, false, "")}, - {0x41, 0, 0, 0, f(Yes, true, "")}, - {0x51, 0, 0, 0, f(Yes, false, "")}, - {0x52, 0, 0, 0, f(Yes, true, "")}, - {0x5b, 0, 0, 0, f(Yes, false, "")}, - {0x61, 0, 0, 0, f(Yes, true, "")}, - {0x71, 0, 0, 0, f(Yes, false, "")}, - {0x72, 0, 0, 0, f(Yes, true, "")}, - {0x7b, 0, 0, 0, f(Yes, false, "")}, - {0xa0, 0, 0, 0, g(Yes, No, false, false, "", " ")}, - {0xa1, 0, 0, 0, f(Yes, false, "")}, - {0xa8, 0, 0, 1, g(Yes, No, true, false, "", " ̈")}, - {0xa9, 0, 0, 0, f(Yes, false, "")}, - {0xaa, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0xab, 0, 0, 0, f(Yes, false, "")}, - {0xaf, 0, 0, 1, g(Yes, No, false, false, "", " ̄")}, - {0xb0, 0, 0, 0, f(Yes, false, "")}, - {0xb2, 0, 0, 0, g(Yes, No, false, false, "", "2")}, - {0xb3, 0, 0, 0, g(Yes, No, false, false, "", "3")}, - {0xb4, 0, 0, 1, g(Yes, No, false, false, "", " ́")}, - {0xb5, 0, 0, 0, g(Yes, No, false, false, "", "μ")}, - {0xb6, 0, 0, 0, f(Yes, false, "")}, - {0xb8, 0, 0, 1, g(Yes, No, false, false, "", " ̧")}, - {0xb9, 0, 0, 0, g(Yes, No, false, false, "", "1")}, - {0xba, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0xbb, 0, 0, 0, f(Yes, false, "")}, - {0xbc, 0, 0, 0, g(Yes, No, false, false, "", "1⁄4")}, - {0xbd, 0, 0, 0, g(Yes, No, false, false, "", "1⁄2")}, - {0xbe, 0, 0, 0, g(Yes, No, false, false, "", "3⁄4")}, - {0xbf, 0, 0, 0, f(Yes, false, "")}, - {0xc0, 0, 0, 1, f(Yes, false, "À")}, - {0xc1, 0, 0, 1, f(Yes, false, "Á")}, - {0xc2, 0, 0, 1, f(Yes, true, "Â")}, - {0xc3, 0, 0, 1, f(Yes, false, "Ã")}, - {0xc4, 0, 0, 1, f(Yes, true, "Ä")}, - {0xc5, 0, 0, 1, f(Yes, true, "Å")}, - {0xc6, 0, 0, 0, f(Yes, true, "")}, - {0xc7, 0, 0, 1, f(Yes, true, "Ç")}, - {0xc8, 0, 0, 1, f(Yes, false, "È")}, - {0xc9, 0, 0, 1, f(Yes, false, "É")}, - {0xca, 0, 0, 1, f(Yes, true, "Ê")}, - {0xcb, 0, 0, 1, f(Yes, false, "Ë")}, - {0xcc, 0, 0, 1, f(Yes, false, "Ì")}, - {0xcd, 0, 0, 1, f(Yes, false, "Í")}, - {0xce, 0, 0, 1, f(Yes, false, "Î")}, - {0xcf, 0, 0, 1, f(Yes, true, "Ï")}, - {0xd0, 0, 0, 0, f(Yes, false, "")}, - {0xd1, 0, 0, 1, f(Yes, false, "Ñ")}, - {0xd2, 0, 0, 1, f(Yes, false, "Ò")}, - {0xd3, 0, 0, 1, f(Yes, false, "Ó")}, - {0xd4, 0, 0, 1, f(Yes, true, "Ô")}, - {0xd5, 0, 0, 1, f(Yes, true, "Õ")}, - {0xd6, 0, 0, 1, f(Yes, true, "Ö")}, - {0xd7, 0, 0, 0, f(Yes, false, "")}, - {0xd8, 0, 0, 0, f(Yes, true, "")}, - {0xd9, 0, 0, 1, f(Yes, false, "Ù")}, - {0xda, 0, 0, 1, f(Yes, false, "Ú")}, - {0xdb, 0, 0, 1, f(Yes, false, "Û")}, - {0xdc, 0, 0, 1, f(Yes, true, "Ü")}, - {0xdd, 0, 0, 1, f(Yes, false, "Ý")}, - {0xde, 0, 0, 0, f(Yes, false, "")}, - {0xe0, 0, 0, 1, f(Yes, false, "à")}, - {0xe1, 0, 0, 1, f(Yes, false, "á")}, - {0xe2, 0, 0, 1, f(Yes, true, "â")}, - {0xe3, 0, 0, 1, f(Yes, false, "ã")}, - {0xe4, 0, 0, 1, f(Yes, true, "ä")}, - {0xe5, 0, 0, 1, f(Yes, true, "å")}, - {0xe6, 0, 0, 0, f(Yes, true, "")}, - {0xe7, 0, 0, 1, f(Yes, true, "ç")}, - {0xe8, 0, 0, 1, f(Yes, false, "è")}, - {0xe9, 0, 0, 1, f(Yes, false, "é")}, - {0xea, 0, 0, 1, f(Yes, true, "ê")}, - {0xeb, 0, 0, 1, f(Yes, false, "ë")}, - {0xec, 0, 0, 1, f(Yes, false, "ì")}, - {0xed, 0, 0, 1, f(Yes, false, "í")}, - {0xee, 0, 0, 1, f(Yes, false, "î")}, - {0xef, 0, 0, 1, f(Yes, true, "ï")}, - {0xf0, 0, 0, 0, f(Yes, false, "")}, - {0xf1, 0, 0, 1, f(Yes, false, "ñ")}, - {0xf2, 0, 0, 1, f(Yes, false, "ò")}, - {0xf3, 0, 0, 1, f(Yes, false, "ó")}, - {0xf4, 0, 0, 1, f(Yes, true, "ô")}, - {0xf5, 0, 0, 1, f(Yes, true, "õ")}, - {0xf6, 0, 0, 1, f(Yes, true, "ö")}, - {0xf7, 0, 0, 0, f(Yes, false, "")}, - {0xf8, 0, 0, 0, f(Yes, true, "")}, - {0xf9, 0, 0, 1, f(Yes, false, "ù")}, - {0xfa, 0, 0, 1, f(Yes, false, "ú")}, - {0xfb, 0, 0, 1, f(Yes, false, "û")}, - {0xfc, 0, 0, 1, f(Yes, true, "ü")}, - {0xfd, 0, 0, 1, f(Yes, false, "ý")}, - {0xfe, 0, 0, 0, f(Yes, false, "")}, - {0xff, 0, 0, 1, f(Yes, false, "ÿ")}, - {0x100, 0, 0, 1, f(Yes, false, "Ā")}, - {0x101, 0, 0, 1, f(Yes, false, "ā")}, - {0x102, 0, 0, 1, f(Yes, true, "Ă")}, - {0x103, 0, 0, 1, f(Yes, true, "ă")}, - {0x104, 0, 0, 1, f(Yes, false, "Ą")}, - {0x105, 0, 0, 1, f(Yes, false, "ą")}, - {0x106, 0, 0, 1, f(Yes, false, "Ć")}, - {0x107, 0, 0, 1, f(Yes, false, "ć")}, - {0x108, 0, 0, 1, f(Yes, false, "Ĉ")}, - {0x109, 0, 0, 1, f(Yes, false, "ĉ")}, - {0x10a, 0, 0, 1, f(Yes, false, "Ċ")}, - {0x10b, 0, 0, 1, f(Yes, false, "ċ")}, - {0x10c, 0, 0, 1, f(Yes, false, "Č")}, - {0x10d, 0, 0, 1, f(Yes, false, "č")}, - {0x10e, 0, 0, 1, f(Yes, false, "Ď")}, - {0x10f, 0, 0, 1, f(Yes, false, "ď")}, - {0x110, 0, 0, 0, f(Yes, false, "")}, - {0x112, 0, 0, 1, f(Yes, true, "Ē")}, - {0x113, 0, 0, 1, f(Yes, true, "ē")}, - {0x114, 0, 0, 1, f(Yes, false, "Ĕ")}, - {0x115, 0, 0, 1, f(Yes, false, "ĕ")}, - {0x116, 0, 0, 1, f(Yes, false, "Ė")}, - {0x117, 0, 0, 1, f(Yes, false, "ė")}, - {0x118, 0, 0, 1, f(Yes, false, "Ę")}, - {0x119, 0, 0, 1, f(Yes, false, "ę")}, - {0x11a, 0, 0, 1, f(Yes, false, "Ě")}, - {0x11b, 0, 0, 1, f(Yes, false, "ě")}, - {0x11c, 0, 0, 1, f(Yes, false, "Ĝ")}, - {0x11d, 0, 0, 1, f(Yes, false, "ĝ")}, - {0x11e, 0, 0, 1, f(Yes, false, "Ğ")}, - {0x11f, 0, 0, 1, f(Yes, false, "ğ")}, - {0x120, 0, 0, 1, f(Yes, false, "Ġ")}, - {0x121, 0, 0, 1, f(Yes, false, "ġ")}, - {0x122, 0, 0, 1, f(Yes, false, "Ģ")}, - {0x123, 0, 0, 1, f(Yes, false, "ģ")}, - {0x124, 0, 0, 1, f(Yes, false, "Ĥ")}, - {0x125, 0, 0, 1, f(Yes, false, "ĥ")}, - {0x126, 0, 0, 0, f(Yes, false, "")}, - {0x128, 0, 0, 1, f(Yes, false, "Ĩ")}, - {0x129, 0, 0, 1, f(Yes, false, "ĩ")}, - {0x12a, 0, 0, 1, f(Yes, false, "Ī")}, - {0x12b, 0, 0, 1, f(Yes, false, "ī")}, - {0x12c, 0, 0, 1, f(Yes, false, "Ĭ")}, - {0x12d, 0, 0, 1, f(Yes, false, "ĭ")}, - {0x12e, 0, 0, 1, f(Yes, false, "Į")}, - {0x12f, 0, 0, 1, f(Yes, false, "į")}, - {0x130, 0, 0, 1, f(Yes, false, "İ")}, - {0x131, 0, 0, 0, f(Yes, false, "")}, - {0x132, 0, 0, 0, g(Yes, No, false, false, "", "IJ")}, - {0x133, 0, 0, 0, g(Yes, No, false, false, "", "ij")}, - {0x134, 0, 0, 1, f(Yes, false, "Ĵ")}, - {0x135, 0, 0, 1, f(Yes, false, "ĵ")}, - {0x136, 0, 0, 1, f(Yes, false, "Ķ")}, - {0x137, 0, 0, 1, f(Yes, false, "ķ")}, - {0x138, 0, 0, 0, f(Yes, false, "")}, - {0x139, 0, 0, 1, f(Yes, false, "Ĺ")}, - {0x13a, 0, 0, 1, f(Yes, false, "ĺ")}, - {0x13b, 0, 0, 1, f(Yes, false, "Ļ")}, - {0x13c, 0, 0, 1, f(Yes, false, "ļ")}, - {0x13d, 0, 0, 1, f(Yes, false, "Ľ")}, - {0x13e, 0, 0, 1, f(Yes, false, "ľ")}, - {0x13f, 0, 0, 0, g(Yes, No, false, false, "", "L·")}, - {0x140, 0, 0, 0, g(Yes, No, false, false, "", "l·")}, - {0x141, 0, 0, 0, f(Yes, false, "")}, - {0x143, 0, 0, 1, f(Yes, false, "Ń")}, - {0x144, 0, 0, 1, f(Yes, false, "ń")}, - {0x145, 0, 0, 1, f(Yes, false, "Ņ")}, - {0x146, 0, 0, 1, f(Yes, false, "ņ")}, - {0x147, 0, 0, 1, f(Yes, false, "Ň")}, - {0x148, 0, 0, 1, f(Yes, false, "ň")}, - {0x149, 0, 0, 0, g(Yes, No, false, false, "", "ʼn")}, - {0x14a, 0, 0, 0, f(Yes, false, "")}, - {0x14c, 0, 0, 1, f(Yes, true, "Ō")}, - {0x14d, 0, 0, 1, f(Yes, true, "ō")}, - {0x14e, 0, 0, 1, f(Yes, false, "Ŏ")}, - {0x14f, 0, 0, 1, f(Yes, false, "ŏ")}, - {0x150, 0, 0, 1, f(Yes, false, "Ő")}, - {0x151, 0, 0, 1, f(Yes, false, "ő")}, - {0x152, 0, 0, 0, f(Yes, false, "")}, - {0x154, 0, 0, 1, f(Yes, false, "Ŕ")}, - {0x155, 0, 0, 1, f(Yes, false, "ŕ")}, - {0x156, 0, 0, 1, f(Yes, false, "Ŗ")}, - {0x157, 0, 0, 1, f(Yes, false, "ŗ")}, - {0x158, 0, 0, 1, f(Yes, false, "Ř")}, - {0x159, 0, 0, 1, f(Yes, false, "ř")}, - {0x15a, 0, 0, 1, f(Yes, true, "Ś")}, - {0x15b, 0, 0, 1, f(Yes, true, "ś")}, - {0x15c, 0, 0, 1, f(Yes, false, "Ŝ")}, - {0x15d, 0, 0, 1, f(Yes, false, "ŝ")}, - {0x15e, 0, 0, 1, f(Yes, false, "Ş")}, - {0x15f, 0, 0, 1, f(Yes, false, "ş")}, - {0x160, 0, 0, 1, f(Yes, true, "Š")}, - {0x161, 0, 0, 1, f(Yes, true, "š")}, - {0x162, 0, 0, 1, f(Yes, false, "Ţ")}, - {0x163, 0, 0, 1, f(Yes, false, "ţ")}, - {0x164, 0, 0, 1, f(Yes, false, "Ť")}, - {0x165, 0, 0, 1, f(Yes, false, "ť")}, - {0x166, 0, 0, 0, f(Yes, false, "")}, - {0x168, 0, 0, 1, f(Yes, true, "Ũ")}, - {0x169, 0, 0, 1, f(Yes, true, "ũ")}, - {0x16a, 0, 0, 1, f(Yes, true, "Ū")}, - {0x16b, 0, 0, 1, f(Yes, true, "ū")}, - {0x16c, 0, 0, 1, f(Yes, false, "Ŭ")}, - {0x16d, 0, 0, 1, f(Yes, false, "ŭ")}, - {0x16e, 0, 0, 1, f(Yes, false, "Ů")}, - {0x16f, 0, 0, 1, f(Yes, false, "ů")}, - {0x170, 0, 0, 1, f(Yes, false, "Ű")}, - {0x171, 0, 0, 1, f(Yes, false, "ű")}, - {0x172, 0, 0, 1, f(Yes, false, "Ų")}, - {0x173, 0, 0, 1, f(Yes, false, "ų")}, - {0x174, 0, 0, 1, f(Yes, false, "Ŵ")}, - {0x175, 0, 0, 1, f(Yes, false, "ŵ")}, - {0x176, 0, 0, 1, f(Yes, false, "Ŷ")}, - {0x177, 0, 0, 1, f(Yes, false, "ŷ")}, - {0x178, 0, 0, 1, f(Yes, false, "Ÿ")}, - {0x179, 0, 0, 1, f(Yes, false, "Ź")}, - {0x17a, 0, 0, 1, f(Yes, false, "ź")}, - {0x17b, 0, 0, 1, f(Yes, false, "Ż")}, - {0x17c, 0, 0, 1, f(Yes, false, "ż")}, - {0x17d, 0, 0, 1, f(Yes, false, "Ž")}, - {0x17e, 0, 0, 1, f(Yes, false, "ž")}, - {0x17f, 0, 0, 0, g(Yes, No, true, false, "", "s")}, - {0x180, 0, 0, 0, f(Yes, false, "")}, - {0x1a0, 0, 0, 1, f(Yes, true, "Ơ")}, - {0x1a1, 0, 0, 1, f(Yes, true, "ơ")}, - {0x1a2, 0, 0, 0, f(Yes, false, "")}, - {0x1af, 0, 0, 1, f(Yes, true, "Ư")}, - {0x1b0, 0, 0, 1, f(Yes, true, "ư")}, - {0x1b1, 0, 0, 0, f(Yes, false, "")}, - {0x1b7, 0, 0, 0, f(Yes, true, "")}, - {0x1b8, 0, 0, 0, f(Yes, false, "")}, - {0x1c4, 0, 0, 1, g(Yes, No, false, false, "", "DŽ")}, - {0x1c5, 0, 0, 1, g(Yes, No, false, false, "", "Dž")}, - {0x1c6, 0, 0, 1, g(Yes, No, false, false, "", "dž")}, - {0x1c7, 0, 0, 0, g(Yes, No, false, false, "", "LJ")}, - {0x1c8, 0, 0, 0, g(Yes, No, false, false, "", "Lj")}, - {0x1c9, 0, 0, 0, g(Yes, No, false, false, "", "lj")}, - {0x1ca, 0, 0, 0, g(Yes, No, false, false, "", "NJ")}, - {0x1cb, 0, 0, 0, g(Yes, No, false, false, "", "Nj")}, - {0x1cc, 0, 0, 0, g(Yes, No, false, false, "", "nj")}, - {0x1cd, 0, 0, 1, f(Yes, false, "Ǎ")}, - {0x1ce, 0, 0, 1, f(Yes, false, "ǎ")}, - {0x1cf, 0, 0, 1, f(Yes, false, "Ǐ")}, - {0x1d0, 0, 0, 1, f(Yes, false, "ǐ")}, - {0x1d1, 0, 0, 1, f(Yes, false, "Ǒ")}, - {0x1d2, 0, 0, 1, f(Yes, false, "ǒ")}, - {0x1d3, 0, 0, 1, f(Yes, false, "Ǔ")}, - {0x1d4, 0, 0, 1, f(Yes, false, "ǔ")}, - {0x1d5, 0, 0, 2, f(Yes, false, "Ǖ")}, - {0x1d6, 0, 0, 2, f(Yes, false, "ǖ")}, - {0x1d7, 0, 0, 2, f(Yes, false, "Ǘ")}, - {0x1d8, 0, 0, 2, f(Yes, false, "ǘ")}, - {0x1d9, 0, 0, 2, f(Yes, false, "Ǚ")}, - {0x1da, 0, 0, 2, f(Yes, false, "ǚ")}, - {0x1db, 0, 0, 2, f(Yes, false, "Ǜ")}, - {0x1dc, 0, 0, 2, f(Yes, false, "ǜ")}, - {0x1dd, 0, 0, 0, f(Yes, false, "")}, - {0x1de, 0, 0, 2, f(Yes, false, "Ǟ")}, - {0x1df, 0, 0, 2, f(Yes, false, "ǟ")}, - {0x1e0, 0, 0, 2, f(Yes, false, "Ǡ")}, - {0x1e1, 0, 0, 2, f(Yes, false, "ǡ")}, - {0x1e2, 0, 0, 1, f(Yes, false, "Ǣ")}, - {0x1e3, 0, 0, 1, f(Yes, false, "ǣ")}, - {0x1e4, 0, 0, 0, f(Yes, false, "")}, - {0x1e6, 0, 0, 1, f(Yes, false, "Ǧ")}, - {0x1e7, 0, 0, 1, f(Yes, false, "ǧ")}, - {0x1e8, 0, 0, 1, f(Yes, false, "Ǩ")}, - {0x1e9, 0, 0, 1, f(Yes, false, "ǩ")}, - {0x1ea, 0, 0, 1, f(Yes, true, "Ǫ")}, - {0x1eb, 0, 0, 1, f(Yes, true, "ǫ")}, - {0x1ec, 0, 0, 2, f(Yes, false, "Ǭ")}, - {0x1ed, 0, 0, 2, f(Yes, false, "ǭ")}, - {0x1ee, 0, 0, 1, f(Yes, false, "Ǯ")}, - {0x1ef, 0, 0, 1, f(Yes, false, "ǯ")}, - {0x1f0, 0, 0, 1, f(Yes, false, "ǰ")}, - {0x1f1, 0, 0, 0, g(Yes, No, false, false, "", "DZ")}, - {0x1f2, 0, 0, 0, g(Yes, No, false, false, "", "Dz")}, - {0x1f3, 0, 0, 0, g(Yes, No, false, false, "", "dz")}, - {0x1f4, 0, 0, 1, f(Yes, false, "Ǵ")}, - {0x1f5, 0, 0, 1, f(Yes, false, "ǵ")}, - {0x1f6, 0, 0, 0, f(Yes, false, "")}, - {0x1f8, 0, 0, 1, f(Yes, false, "Ǹ")}, - {0x1f9, 0, 0, 1, f(Yes, false, "ǹ")}, - {0x1fa, 0, 0, 2, f(Yes, false, "Ǻ")}, - {0x1fb, 0, 0, 2, f(Yes, false, "ǻ")}, - {0x1fc, 0, 0, 1, f(Yes, false, "Ǽ")}, - {0x1fd, 0, 0, 1, f(Yes, false, "ǽ")}, - {0x1fe, 0, 0, 1, f(Yes, false, "Ǿ")}, - {0x1ff, 0, 0, 1, f(Yes, false, "ǿ")}, - {0x200, 0, 0, 1, f(Yes, false, "Ȁ")}, - {0x201, 0, 0, 1, f(Yes, false, "ȁ")}, - {0x202, 0, 0, 1, f(Yes, false, "Ȃ")}, - {0x203, 0, 0, 1, f(Yes, false, "ȃ")}, - {0x204, 0, 0, 1, f(Yes, false, "Ȅ")}, - {0x205, 0, 0, 1, f(Yes, false, "ȅ")}, - {0x206, 0, 0, 1, f(Yes, false, "Ȇ")}, - {0x207, 0, 0, 1, f(Yes, false, "ȇ")}, - {0x208, 0, 0, 1, f(Yes, false, "Ȉ")}, - {0x209, 0, 0, 1, f(Yes, false, "ȉ")}, - {0x20a, 0, 0, 1, f(Yes, false, "Ȋ")}, - {0x20b, 0, 0, 1, f(Yes, false, "ȋ")}, - {0x20c, 0, 0, 1, f(Yes, false, "Ȍ")}, - {0x20d, 0, 0, 1, f(Yes, false, "ȍ")}, - {0x20e, 0, 0, 1, f(Yes, false, "Ȏ")}, - {0x20f, 0, 0, 1, f(Yes, false, "ȏ")}, - {0x210, 0, 0, 1, f(Yes, false, "Ȑ")}, - {0x211, 0, 0, 1, f(Yes, false, "ȑ")}, - {0x212, 0, 0, 1, f(Yes, false, "Ȓ")}, - {0x213, 0, 0, 1, f(Yes, false, "ȓ")}, - {0x214, 0, 0, 1, f(Yes, false, "Ȕ")}, - {0x215, 0, 0, 1, f(Yes, false, "ȕ")}, - {0x216, 0, 0, 1, f(Yes, false, "Ȗ")}, - {0x217, 0, 0, 1, f(Yes, false, "ȗ")}, - {0x218, 0, 0, 1, f(Yes, false, "Ș")}, - {0x219, 0, 0, 1, f(Yes, false, "ș")}, - {0x21a, 0, 0, 1, f(Yes, false, "Ț")}, - {0x21b, 0, 0, 1, f(Yes, false, "ț")}, - {0x21c, 0, 0, 0, f(Yes, false, "")}, - {0x21e, 0, 0, 1, f(Yes, false, "Ȟ")}, - {0x21f, 0, 0, 1, f(Yes, false, "ȟ")}, - {0x220, 0, 0, 0, f(Yes, false, "")}, - {0x226, 0, 0, 1, f(Yes, true, "Ȧ")}, - {0x227, 0, 0, 1, f(Yes, true, "ȧ")}, - {0x228, 0, 0, 1, f(Yes, true, "Ȩ")}, - {0x229, 0, 0, 1, f(Yes, true, "ȩ")}, - {0x22a, 0, 0, 2, f(Yes, false, "Ȫ")}, - {0x22b, 0, 0, 2, f(Yes, false, "ȫ")}, - {0x22c, 0, 0, 2, f(Yes, false, "Ȭ")}, - {0x22d, 0, 0, 2, f(Yes, false, "ȭ")}, - {0x22e, 0, 0, 1, f(Yes, true, "Ȯ")}, - {0x22f, 0, 0, 1, f(Yes, true, "ȯ")}, - {0x230, 0, 0, 2, f(Yes, false, "Ȱ")}, - {0x231, 0, 0, 2, f(Yes, false, "ȱ")}, - {0x232, 0, 0, 1, f(Yes, false, "Ȳ")}, - {0x233, 0, 0, 1, f(Yes, false, "ȳ")}, - {0x234, 0, 0, 0, f(Yes, false, "")}, - {0x292, 0, 0, 0, f(Yes, true, "")}, - {0x293, 0, 0, 0, f(Yes, false, "")}, - {0x2b0, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0x2b1, 0, 0, 0, g(Yes, No, false, false, "", "ɦ")}, - {0x2b2, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x2b3, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0x2b4, 0, 0, 0, g(Yes, No, false, false, "", "ɹ")}, - {0x2b5, 0, 0, 0, g(Yes, No, false, false, "", "ɻ")}, - {0x2b6, 0, 0, 0, g(Yes, No, false, false, "", "ʁ")}, - {0x2b7, 0, 0, 0, g(Yes, No, false, false, "", "w")}, - {0x2b8, 0, 0, 0, g(Yes, No, false, false, "", "y")}, - {0x2b9, 0, 0, 0, f(Yes, false, "")}, - {0x2d8, 0, 0, 1, g(Yes, No, false, false, "", " ̆")}, - {0x2d9, 0, 0, 1, g(Yes, No, false, false, "", " ̇")}, - {0x2da, 0, 0, 1, g(Yes, No, false, false, "", " ̊")}, - {0x2db, 0, 0, 1, g(Yes, No, false, false, "", " ̨")}, - {0x2dc, 0, 0, 1, g(Yes, No, false, false, "", " ̃")}, - {0x2dd, 0, 0, 1, g(Yes, No, false, false, "", " ̋")}, - {0x2de, 0, 0, 0, f(Yes, false, "")}, - {0x2e0, 0, 0, 0, g(Yes, No, false, false, "", "ɣ")}, - {0x2e1, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x2e2, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0x2e3, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x2e4, 0, 0, 0, g(Yes, No, false, false, "", "ʕ")}, - {0x2e5, 0, 0, 0, f(Yes, false, "")}, - {0x300, 230, 1, 1, f(Maybe, false, "")}, - {0x305, 230, 1, 1, f(Yes, false, "")}, - {0x306, 230, 1, 1, f(Maybe, false, "")}, - {0x30d, 230, 1, 1, f(Yes, false, "")}, - {0x30f, 230, 1, 1, f(Maybe, false, "")}, - {0x310, 230, 1, 1, f(Yes, false, "")}, - {0x311, 230, 1, 1, f(Maybe, false, "")}, - {0x312, 230, 1, 1, f(Yes, false, "")}, - {0x313, 230, 1, 1, f(Maybe, false, "")}, - {0x315, 232, 1, 1, f(Yes, false, "")}, - {0x316, 220, 1, 1, f(Yes, false, "")}, - {0x31a, 232, 1, 1, f(Yes, false, "")}, - {0x31b, 216, 1, 1, f(Maybe, false, "")}, - {0x31c, 220, 1, 1, f(Yes, false, "")}, - {0x321, 202, 1, 1, f(Yes, false, "")}, - {0x323, 220, 1, 1, f(Maybe, false, "")}, - {0x327, 202, 1, 1, f(Maybe, false, "")}, - {0x329, 220, 1, 1, f(Yes, false, "")}, - {0x32d, 220, 1, 1, f(Maybe, false, "")}, - {0x32f, 220, 1, 1, f(Yes, false, "")}, - {0x330, 220, 1, 1, f(Maybe, false, "")}, - {0x332, 220, 1, 1, f(Yes, false, "")}, - {0x334, 1, 1, 1, f(Yes, false, "")}, - {0x338, 1, 1, 1, f(Maybe, false, "")}, - {0x339, 220, 1, 1, f(Yes, false, "")}, - {0x33d, 230, 1, 1, f(Yes, false, "")}, - {0x340, 230, 1, 1, f(No, false, "̀")}, - {0x341, 230, 1, 1, f(No, false, "́")}, - {0x342, 230, 1, 1, f(Maybe, false, "")}, - {0x343, 230, 1, 1, f(No, false, "̓")}, - {0x344, 230, 2, 2, f(No, false, "̈́")}, - {0x345, 240, 1, 1, f(Maybe, false, "")}, - {0x346, 230, 1, 1, f(Yes, false, "")}, - {0x347, 220, 1, 1, f(Yes, false, "")}, - {0x34a, 230, 1, 1, f(Yes, false, "")}, - {0x34d, 220, 1, 1, f(Yes, false, "")}, - {0x34f, 0, 0, 0, f(Yes, false, "")}, - {0x350, 230, 1, 1, f(Yes, false, "")}, - {0x353, 220, 1, 1, f(Yes, false, "")}, - {0x357, 230, 1, 1, f(Yes, false, "")}, - {0x358, 232, 1, 1, f(Yes, false, "")}, - {0x359, 220, 1, 1, f(Yes, false, "")}, - {0x35b, 230, 1, 1, f(Yes, false, "")}, - {0x35c, 233, 1, 1, f(Yes, false, "")}, - {0x35d, 234, 1, 1, f(Yes, false, "")}, - {0x35f, 233, 1, 1, f(Yes, false, "")}, - {0x360, 234, 1, 1, f(Yes, false, "")}, - {0x362, 233, 1, 1, f(Yes, false, "")}, - {0x363, 230, 1, 1, f(Yes, false, "")}, - {0x370, 0, 0, 0, f(Yes, false, "")}, - {0x374, 0, 0, 0, f(No, false, "ʹ")}, - {0x375, 0, 0, 0, f(Yes, false, "")}, - {0x37a, 0, 0, 1, g(Yes, No, false, false, "", " ͅ")}, - {0x37b, 0, 0, 0, f(Yes, false, "")}, - {0x37e, 0, 0, 0, f(No, false, ";")}, - {0x37f, 0, 0, 0, f(Yes, false, "")}, - {0x384, 0, 0, 1, g(Yes, No, false, false, "", " ́")}, - {0x385, 0, 0, 2, g(Yes, No, false, false, "΅", " ̈́")}, - {0x386, 0, 0, 1, f(Yes, false, "Ά")}, - {0x387, 0, 0, 0, f(No, false, "·")}, - {0x388, 0, 0, 1, f(Yes, false, "Έ")}, - {0x389, 0, 0, 1, f(Yes, false, "Ή")}, - {0x38a, 0, 0, 1, f(Yes, false, "Ί")}, - {0x38b, 0, 0, 0, f(Yes, false, "")}, - {0x38c, 0, 0, 1, f(Yes, false, "Ό")}, - {0x38d, 0, 0, 0, f(Yes, false, "")}, - {0x38e, 0, 0, 1, f(Yes, false, "Ύ")}, - {0x38f, 0, 0, 1, f(Yes, false, "Ώ")}, - {0x390, 0, 0, 2, f(Yes, false, "ΐ")}, - {0x391, 0, 0, 0, f(Yes, true, "")}, - {0x392, 0, 0, 0, f(Yes, false, "")}, - {0x395, 0, 0, 0, f(Yes, true, "")}, - {0x396, 0, 0, 0, f(Yes, false, "")}, - {0x397, 0, 0, 0, f(Yes, true, "")}, - {0x398, 0, 0, 0, f(Yes, false, "")}, - {0x399, 0, 0, 0, f(Yes, true, "")}, - {0x39a, 0, 0, 0, f(Yes, false, "")}, - {0x39f, 0, 0, 0, f(Yes, true, "")}, - {0x3a0, 0, 0, 0, f(Yes, false, "")}, - {0x3a1, 0, 0, 0, f(Yes, true, "")}, - {0x3a2, 0, 0, 0, f(Yes, false, "")}, - {0x3a5, 0, 0, 0, f(Yes, true, "")}, - {0x3a6, 0, 0, 0, f(Yes, false, "")}, - {0x3a9, 0, 0, 0, f(Yes, true, "")}, - {0x3aa, 0, 0, 1, f(Yes, false, "Ϊ")}, - {0x3ab, 0, 0, 1, f(Yes, false, "Ϋ")}, - {0x3ac, 0, 0, 1, f(Yes, true, "ά")}, - {0x3ad, 0, 0, 1, f(Yes, false, "έ")}, - {0x3ae, 0, 0, 1, f(Yes, true, "ή")}, - {0x3af, 0, 0, 1, f(Yes, false, "ί")}, - {0x3b0, 0, 0, 2, f(Yes, false, "ΰ")}, - {0x3b1, 0, 0, 0, f(Yes, true, "")}, - {0x3b2, 0, 0, 0, f(Yes, false, "")}, - {0x3b5, 0, 0, 0, f(Yes, true, "")}, - {0x3b6, 0, 0, 0, f(Yes, false, "")}, - {0x3b7, 0, 0, 0, f(Yes, true, "")}, - {0x3b8, 0, 0, 0, f(Yes, false, "")}, - {0x3b9, 0, 0, 0, f(Yes, true, "")}, - {0x3ba, 0, 0, 0, f(Yes, false, "")}, - {0x3bf, 0, 0, 0, f(Yes, true, "")}, - {0x3c0, 0, 0, 0, f(Yes, false, "")}, - {0x3c1, 0, 0, 0, f(Yes, true, "")}, - {0x3c2, 0, 0, 0, f(Yes, false, "")}, - {0x3c5, 0, 0, 0, f(Yes, true, "")}, - {0x3c6, 0, 0, 0, f(Yes, false, "")}, - {0x3c9, 0, 0, 0, f(Yes, true, "")}, - {0x3ca, 0, 0, 1, f(Yes, true, "ϊ")}, - {0x3cb, 0, 0, 1, f(Yes, true, "ϋ")}, - {0x3cc, 0, 0, 1, f(Yes, false, "ό")}, - {0x3cd, 0, 0, 1, f(Yes, false, "ύ")}, - {0x3ce, 0, 0, 1, f(Yes, true, "ώ")}, - {0x3cf, 0, 0, 0, f(Yes, false, "")}, - {0x3d0, 0, 0, 0, g(Yes, No, false, false, "", "β")}, - {0x3d1, 0, 0, 0, g(Yes, No, false, false, "", "θ")}, - {0x3d2, 0, 0, 0, g(Yes, No, true, false, "", "Υ")}, - {0x3d3, 0, 0, 1, g(Yes, No, false, false, "ϓ", "Ύ")}, - {0x3d4, 0, 0, 1, g(Yes, No, false, false, "ϔ", "Ϋ")}, - {0x3d5, 0, 0, 0, g(Yes, No, false, false, "", "φ")}, - {0x3d6, 0, 0, 0, g(Yes, No, false, false, "", "π")}, - {0x3d7, 0, 0, 0, f(Yes, false, "")}, - {0x3f0, 0, 0, 0, g(Yes, No, false, false, "", "κ")}, - {0x3f1, 0, 0, 0, g(Yes, No, false, false, "", "ρ")}, - {0x3f2, 0, 0, 0, g(Yes, No, false, false, "", "ς")}, - {0x3f3, 0, 0, 0, f(Yes, false, "")}, - {0x3f4, 0, 0, 0, g(Yes, No, false, false, "", "Θ")}, - {0x3f5, 0, 0, 0, g(Yes, No, false, false, "", "ε")}, - {0x3f6, 0, 0, 0, f(Yes, false, "")}, - {0x3f9, 0, 0, 0, g(Yes, No, false, false, "", "Σ")}, - {0x3fa, 0, 0, 0, f(Yes, false, "")}, - {0x400, 0, 0, 1, f(Yes, false, "Ѐ")}, - {0x401, 0, 0, 1, f(Yes, false, "Ё")}, - {0x402, 0, 0, 0, f(Yes, false, "")}, - {0x403, 0, 0, 1, f(Yes, false, "Ѓ")}, - {0x404, 0, 0, 0, f(Yes, false, "")}, - {0x406, 0, 0, 0, f(Yes, true, "")}, - {0x407, 0, 0, 1, f(Yes, false, "Ї")}, - {0x408, 0, 0, 0, f(Yes, false, "")}, - {0x40c, 0, 0, 1, f(Yes, false, "Ќ")}, - {0x40d, 0, 0, 1, f(Yes, false, "Ѝ")}, - {0x40e, 0, 0, 1, f(Yes, false, "Ў")}, - {0x40f, 0, 0, 0, f(Yes, false, "")}, - {0x410, 0, 0, 0, f(Yes, true, "")}, - {0x411, 0, 0, 0, f(Yes, false, "")}, - {0x413, 0, 0, 0, f(Yes, true, "")}, - {0x414, 0, 0, 0, f(Yes, false, "")}, - {0x415, 0, 0, 0, f(Yes, true, "")}, - {0x419, 0, 0, 1, f(Yes, false, "Й")}, - {0x41a, 0, 0, 0, f(Yes, true, "")}, - {0x41b, 0, 0, 0, f(Yes, false, "")}, - {0x41e, 0, 0, 0, f(Yes, true, "")}, - {0x41f, 0, 0, 0, f(Yes, false, "")}, - {0x423, 0, 0, 0, f(Yes, true, "")}, - {0x424, 0, 0, 0, f(Yes, false, "")}, - {0x427, 0, 0, 0, f(Yes, true, "")}, - {0x428, 0, 0, 0, f(Yes, false, "")}, - {0x42b, 0, 0, 0, f(Yes, true, "")}, - {0x42c, 0, 0, 0, f(Yes, false, "")}, - {0x42d, 0, 0, 0, f(Yes, true, "")}, - {0x42e, 0, 0, 0, f(Yes, false, "")}, - {0x430, 0, 0, 0, f(Yes, true, "")}, - {0x431, 0, 0, 0, f(Yes, false, "")}, - {0x433, 0, 0, 0, f(Yes, true, "")}, - {0x434, 0, 0, 0, f(Yes, false, "")}, - {0x435, 0, 0, 0, f(Yes, true, "")}, - {0x439, 0, 0, 1, f(Yes, false, "й")}, - {0x43a, 0, 0, 0, f(Yes, true, "")}, - {0x43b, 0, 0, 0, f(Yes, false, "")}, - {0x43e, 0, 0, 0, f(Yes, true, "")}, - {0x43f, 0, 0, 0, f(Yes, false, "")}, - {0x443, 0, 0, 0, f(Yes, true, "")}, - {0x444, 0, 0, 0, f(Yes, false, "")}, - {0x447, 0, 0, 0, f(Yes, true, "")}, - {0x448, 0, 0, 0, f(Yes, false, "")}, - {0x44b, 0, 0, 0, f(Yes, true, "")}, - {0x44c, 0, 0, 0, f(Yes, false, "")}, - {0x44d, 0, 0, 0, f(Yes, true, "")}, - {0x44e, 0, 0, 0, f(Yes, false, "")}, - {0x450, 0, 0, 1, f(Yes, false, "ѐ")}, - {0x451, 0, 0, 1, f(Yes, false, "ё")}, - {0x452, 0, 0, 0, f(Yes, false, "")}, - {0x453, 0, 0, 1, f(Yes, false, "ѓ")}, - {0x454, 0, 0, 0, f(Yes, false, "")}, - {0x456, 0, 0, 0, f(Yes, true, "")}, - {0x457, 0, 0, 1, f(Yes, false, "ї")}, - {0x458, 0, 0, 0, f(Yes, false, "")}, - {0x45c, 0, 0, 1, f(Yes, false, "ќ")}, - {0x45d, 0, 0, 1, f(Yes, false, "ѝ")}, - {0x45e, 0, 0, 1, f(Yes, false, "ў")}, - {0x45f, 0, 0, 0, f(Yes, false, "")}, - {0x474, 0, 0, 0, f(Yes, true, "")}, - {0x476, 0, 0, 1, f(Yes, false, "Ѷ")}, - {0x477, 0, 0, 1, f(Yes, false, "ѷ")}, - {0x478, 0, 0, 0, f(Yes, false, "")}, - {0x483, 230, 1, 1, f(Yes, false, "")}, - {0x488, 0, 0, 0, f(Yes, false, "")}, - {0x4c1, 0, 0, 1, f(Yes, false, "Ӂ")}, - {0x4c2, 0, 0, 1, f(Yes, false, "ӂ")}, - {0x4c3, 0, 0, 0, f(Yes, false, "")}, - {0x4d0, 0, 0, 1, f(Yes, false, "Ӑ")}, - {0x4d1, 0, 0, 1, f(Yes, false, "ӑ")}, - {0x4d2, 0, 0, 1, f(Yes, false, "Ӓ")}, - {0x4d3, 0, 0, 1, f(Yes, false, "ӓ")}, - {0x4d4, 0, 0, 0, f(Yes, false, "")}, - {0x4d6, 0, 0, 1, f(Yes, false, "Ӗ")}, - {0x4d7, 0, 0, 1, f(Yes, false, "ӗ")}, - {0x4d8, 0, 0, 0, f(Yes, true, "")}, - {0x4da, 0, 0, 1, f(Yes, false, "Ӛ")}, - {0x4db, 0, 0, 1, f(Yes, false, "ӛ")}, - {0x4dc, 0, 0, 1, f(Yes, false, "Ӝ")}, - {0x4dd, 0, 0, 1, f(Yes, false, "ӝ")}, - {0x4de, 0, 0, 1, f(Yes, false, "Ӟ")}, - {0x4df, 0, 0, 1, f(Yes, false, "ӟ")}, - {0x4e0, 0, 0, 0, f(Yes, false, "")}, - {0x4e2, 0, 0, 1, f(Yes, false, "Ӣ")}, - {0x4e3, 0, 0, 1, f(Yes, false, "ӣ")}, - {0x4e4, 0, 0, 1, f(Yes, false, "Ӥ")}, - {0x4e5, 0, 0, 1, f(Yes, false, "ӥ")}, - {0x4e6, 0, 0, 1, f(Yes, false, "Ӧ")}, - {0x4e7, 0, 0, 1, f(Yes, false, "ӧ")}, - {0x4e8, 0, 0, 0, f(Yes, true, "")}, - {0x4ea, 0, 0, 1, f(Yes, false, "Ӫ")}, - {0x4eb, 0, 0, 1, f(Yes, false, "ӫ")}, - {0x4ec, 0, 0, 1, f(Yes, false, "Ӭ")}, - {0x4ed, 0, 0, 1, f(Yes, false, "ӭ")}, - {0x4ee, 0, 0, 1, f(Yes, false, "Ӯ")}, - {0x4ef, 0, 0, 1, f(Yes, false, "ӯ")}, - {0x4f0, 0, 0, 1, f(Yes, false, "Ӱ")}, - {0x4f1, 0, 0, 1, f(Yes, false, "ӱ")}, - {0x4f2, 0, 0, 1, f(Yes, false, "Ӳ")}, - {0x4f3, 0, 0, 1, f(Yes, false, "ӳ")}, - {0x4f4, 0, 0, 1, f(Yes, false, "Ӵ")}, - {0x4f5, 0, 0, 1, f(Yes, false, "ӵ")}, - {0x4f6, 0, 0, 0, f(Yes, false, "")}, - {0x4f8, 0, 0, 1, f(Yes, false, "Ӹ")}, - {0x4f9, 0, 0, 1, f(Yes, false, "ӹ")}, - {0x4fa, 0, 0, 0, f(Yes, false, "")}, - {0x587, 0, 0, 0, g(Yes, No, false, false, "", "եւ")}, - {0x588, 0, 0, 0, f(Yes, false, "")}, - {0x591, 220, 1, 1, f(Yes, false, "")}, - {0x592, 230, 1, 1, f(Yes, false, "")}, - {0x596, 220, 1, 1, f(Yes, false, "")}, - {0x597, 230, 1, 1, f(Yes, false, "")}, - {0x59a, 222, 1, 1, f(Yes, false, "")}, - {0x59b, 220, 1, 1, f(Yes, false, "")}, - {0x59c, 230, 1, 1, f(Yes, false, "")}, - {0x5a2, 220, 1, 1, f(Yes, false, "")}, - {0x5a8, 230, 1, 1, f(Yes, false, "")}, - {0x5aa, 220, 1, 1, f(Yes, false, "")}, - {0x5ab, 230, 1, 1, f(Yes, false, "")}, - {0x5ad, 222, 1, 1, f(Yes, false, "")}, - {0x5ae, 228, 1, 1, f(Yes, false, "")}, - {0x5af, 230, 1, 1, f(Yes, false, "")}, - {0x5b0, 10, 1, 1, f(Yes, false, "")}, - {0x5b1, 11, 1, 1, f(Yes, false, "")}, - {0x5b2, 12, 1, 1, f(Yes, false, "")}, - {0x5b3, 13, 1, 1, f(Yes, false, "")}, - {0x5b4, 14, 1, 1, f(Yes, false, "")}, - {0x5b5, 15, 1, 1, f(Yes, false, "")}, - {0x5b6, 16, 1, 1, f(Yes, false, "")}, - {0x5b7, 17, 1, 1, f(Yes, false, "")}, - {0x5b8, 18, 1, 1, f(Yes, false, "")}, - {0x5b9, 19, 1, 1, f(Yes, false, "")}, - {0x5bb, 20, 1, 1, f(Yes, false, "")}, - {0x5bc, 21, 1, 1, f(Yes, false, "")}, - {0x5bd, 22, 1, 1, f(Yes, false, "")}, - {0x5be, 0, 0, 0, f(Yes, false, "")}, - {0x5bf, 23, 1, 1, f(Yes, false, "")}, - {0x5c0, 0, 0, 0, f(Yes, false, "")}, - {0x5c1, 24, 1, 1, f(Yes, false, "")}, - {0x5c2, 25, 1, 1, f(Yes, false, "")}, - {0x5c3, 0, 0, 0, f(Yes, false, "")}, - {0x5c4, 230, 1, 1, f(Yes, false, "")}, - {0x5c5, 220, 1, 1, f(Yes, false, "")}, - {0x5c6, 0, 0, 0, f(Yes, false, "")}, - {0x5c7, 18, 1, 1, f(Yes, false, "")}, - {0x5c8, 0, 0, 0, f(Yes, false, "")}, - {0x610, 230, 1, 1, f(Yes, false, "")}, - {0x618, 30, 1, 1, f(Yes, false, "")}, - {0x619, 31, 1, 1, f(Yes, false, "")}, - {0x61a, 32, 1, 1, f(Yes, false, "")}, - {0x61b, 0, 0, 0, f(Yes, false, "")}, - {0x622, 0, 0, 1, f(Yes, false, "آ")}, - {0x623, 0, 0, 1, f(Yes, false, "أ")}, - {0x624, 0, 0, 1, f(Yes, false, "ؤ")}, - {0x625, 0, 0, 1, f(Yes, false, "إ")}, - {0x626, 0, 0, 1, f(Yes, false, "ئ")}, - {0x627, 0, 0, 0, f(Yes, true, "")}, - {0x628, 0, 0, 0, f(Yes, false, "")}, - {0x648, 0, 0, 0, f(Yes, true, "")}, - {0x649, 0, 0, 0, f(Yes, false, "")}, - {0x64a, 0, 0, 0, f(Yes, true, "")}, - {0x64b, 27, 1, 1, f(Yes, false, "")}, - {0x64c, 28, 1, 1, f(Yes, false, "")}, - {0x64d, 29, 1, 1, f(Yes, false, "")}, - {0x64e, 30, 1, 1, f(Yes, false, "")}, - {0x64f, 31, 1, 1, f(Yes, false, "")}, - {0x650, 32, 1, 1, f(Yes, false, "")}, - {0x651, 33, 1, 1, f(Yes, false, "")}, - {0x652, 34, 1, 1, f(Yes, false, "")}, - {0x653, 230, 1, 1, f(Maybe, false, "")}, - {0x655, 220, 1, 1, f(Maybe, false, "")}, - {0x656, 220, 1, 1, f(Yes, false, "")}, - {0x657, 230, 1, 1, f(Yes, false, "")}, - {0x65c, 220, 1, 1, f(Yes, false, "")}, - {0x65d, 230, 1, 1, f(Yes, false, "")}, - {0x65f, 220, 1, 1, f(Yes, false, "")}, - {0x660, 0, 0, 0, f(Yes, false, "")}, - {0x670, 35, 1, 1, f(Yes, false, "")}, - {0x671, 0, 0, 0, f(Yes, false, "")}, - {0x675, 0, 0, 0, g(Yes, No, false, false, "", "اٴ")}, - {0x676, 0, 0, 0, g(Yes, No, false, false, "", "وٴ")}, - {0x677, 0, 0, 0, g(Yes, No, false, false, "", "ۇٴ")}, - {0x678, 0, 0, 0, g(Yes, No, false, false, "", "يٴ")}, - {0x679, 0, 0, 0, f(Yes, false, "")}, - {0x6c0, 0, 0, 1, f(Yes, false, "ۀ")}, - {0x6c1, 0, 0, 0, f(Yes, true, "")}, - {0x6c2, 0, 0, 1, f(Yes, false, "ۂ")}, - {0x6c3, 0, 0, 0, f(Yes, false, "")}, - {0x6d2, 0, 0, 0, f(Yes, true, "")}, - {0x6d3, 0, 0, 1, f(Yes, false, "ۓ")}, - {0x6d4, 0, 0, 0, f(Yes, false, "")}, - {0x6d5, 0, 0, 0, f(Yes, true, "")}, - {0x6d6, 230, 1, 1, f(Yes, false, "")}, - {0x6dd, 0, 0, 0, f(Yes, false, "")}, - {0x6df, 230, 1, 1, f(Yes, false, "")}, - {0x6e3, 220, 1, 1, f(Yes, false, "")}, - {0x6e4, 230, 1, 1, f(Yes, false, "")}, - {0x6e5, 0, 0, 0, f(Yes, false, "")}, - {0x6e7, 230, 1, 1, f(Yes, false, "")}, - {0x6e9, 0, 0, 0, f(Yes, false, "")}, - {0x6ea, 220, 1, 1, f(Yes, false, "")}, - {0x6eb, 230, 1, 1, f(Yes, false, "")}, - {0x6ed, 220, 1, 1, f(Yes, false, "")}, - {0x6ee, 0, 0, 0, f(Yes, false, "")}, - {0x711, 36, 1, 1, f(Yes, false, "")}, - {0x712, 0, 0, 0, f(Yes, false, "")}, - {0x730, 230, 1, 1, f(Yes, false, "")}, - {0x731, 220, 1, 1, f(Yes, false, "")}, - {0x732, 230, 1, 1, f(Yes, false, "")}, - {0x734, 220, 1, 1, f(Yes, false, "")}, - {0x735, 230, 1, 1, f(Yes, false, "")}, - {0x737, 220, 1, 1, f(Yes, false, "")}, - {0x73a, 230, 1, 1, f(Yes, false, "")}, - {0x73b, 220, 1, 1, f(Yes, false, "")}, - {0x73d, 230, 1, 1, f(Yes, false, "")}, - {0x73e, 220, 1, 1, f(Yes, false, "")}, - {0x73f, 230, 1, 1, f(Yes, false, "")}, - {0x742, 220, 1, 1, f(Yes, false, "")}, - {0x743, 230, 1, 1, f(Yes, false, "")}, - {0x744, 220, 1, 1, f(Yes, false, "")}, - {0x745, 230, 1, 1, f(Yes, false, "")}, - {0x746, 220, 1, 1, f(Yes, false, "")}, - {0x747, 230, 1, 1, f(Yes, false, "")}, - {0x748, 220, 1, 1, f(Yes, false, "")}, - {0x749, 230, 1, 1, f(Yes, false, "")}, - {0x74b, 0, 0, 0, f(Yes, false, "")}, - {0x7eb, 230, 1, 1, f(Yes, false, "")}, - {0x7f2, 220, 1, 1, f(Yes, false, "")}, - {0x7f3, 230, 1, 1, f(Yes, false, "")}, - {0x7f4, 0, 0, 0, f(Yes, false, "")}, - {0x816, 230, 1, 1, f(Yes, false, "")}, - {0x81a, 0, 0, 0, f(Yes, false, "")}, - {0x81b, 230, 1, 1, f(Yes, false, "")}, - {0x824, 0, 0, 0, f(Yes, false, "")}, - {0x825, 230, 1, 1, f(Yes, false, "")}, - {0x828, 0, 0, 0, f(Yes, false, "")}, - {0x829, 230, 1, 1, f(Yes, false, "")}, - {0x82e, 0, 0, 0, f(Yes, false, "")}, - {0x859, 220, 1, 1, f(Yes, false, "")}, - {0x85c, 0, 0, 0, f(Yes, false, "")}, - {0x8d4, 230, 1, 1, f(Yes, false, "")}, - {0x8e2, 0, 0, 0, f(Yes, false, "")}, - {0x8e3, 220, 1, 1, f(Yes, false, "")}, - {0x8e4, 230, 1, 1, f(Yes, false, "")}, - {0x8e6, 220, 1, 1, f(Yes, false, "")}, - {0x8e7, 230, 1, 1, f(Yes, false, "")}, - {0x8e9, 220, 1, 1, f(Yes, false, "")}, - {0x8ea, 230, 1, 1, f(Yes, false, "")}, - {0x8ed, 220, 1, 1, f(Yes, false, "")}, - {0x8f0, 27, 1, 1, f(Yes, false, "")}, - {0x8f1, 28, 1, 1, f(Yes, false, "")}, - {0x8f2, 29, 1, 1, f(Yes, false, "")}, - {0x8f3, 230, 1, 1, f(Yes, false, "")}, - {0x8f6, 220, 1, 1, f(Yes, false, "")}, - {0x8f7, 230, 1, 1, f(Yes, false, "")}, - {0x8f9, 220, 1, 1, f(Yes, false, "")}, - {0x8fb, 230, 1, 1, f(Yes, false, "")}, - {0x900, 0, 0, 0, f(Yes, false, "")}, - {0x928, 0, 0, 0, f(Yes, true, "")}, - {0x929, 0, 0, 1, f(Yes, false, "ऩ")}, - {0x92a, 0, 0, 0, f(Yes, false, "")}, - {0x930, 0, 0, 0, f(Yes, true, "")}, - {0x931, 0, 0, 1, f(Yes, false, "ऱ")}, - {0x932, 0, 0, 0, f(Yes, false, "")}, - {0x933, 0, 0, 0, f(Yes, true, "")}, - {0x934, 0, 0, 1, f(Yes, false, "ऴ")}, - {0x935, 0, 0, 0, f(Yes, false, "")}, - {0x93c, 7, 1, 1, f(Maybe, false, "")}, - {0x93d, 0, 0, 0, f(Yes, false, "")}, - {0x94d, 9, 1, 1, f(Yes, false, "")}, - {0x94e, 0, 0, 0, f(Yes, false, "")}, - {0x951, 230, 1, 1, f(Yes, false, "")}, - {0x952, 220, 1, 1, f(Yes, false, "")}, - {0x953, 230, 1, 1, f(Yes, false, "")}, - {0x955, 0, 0, 0, f(Yes, false, "")}, - {0x958, 0, 0, 1, f(No, false, "क़")}, - {0x959, 0, 0, 1, f(No, false, "ख़")}, - {0x95a, 0, 0, 1, f(No, false, "ग़")}, - {0x95b, 0, 0, 1, f(No, false, "ज़")}, - {0x95c, 0, 0, 1, f(No, false, "ड़")}, - {0x95d, 0, 0, 1, f(No, false, "ढ़")}, - {0x95e, 0, 0, 1, f(No, false, "फ़")}, - {0x95f, 0, 0, 1, f(No, false, "य़")}, - {0x960, 0, 0, 0, f(Yes, false, "")}, - {0x9bc, 7, 1, 1, f(Yes, false, "")}, - {0x9bd, 0, 0, 0, f(Yes, false, "")}, - {0x9be, 0, 1, 1, f(Maybe, false, "")}, - {0x9bf, 0, 0, 0, f(Yes, false, "")}, - {0x9c7, 0, 0, 0, f(Yes, true, "")}, - {0x9c8, 0, 0, 0, f(Yes, false, "")}, - {0x9cb, 0, 0, 1, f(Yes, false, "ো")}, - {0x9cc, 0, 0, 1, f(Yes, false, "ৌ")}, - {0x9cd, 9, 1, 1, f(Yes, false, "")}, - {0x9ce, 0, 0, 0, f(Yes, false, "")}, - {0x9d7, 0, 1, 1, f(Maybe, false, "")}, - {0x9d8, 0, 0, 0, f(Yes, false, "")}, - {0x9dc, 0, 0, 1, f(No, false, "ড়")}, - {0x9dd, 0, 0, 1, f(No, false, "ঢ়")}, - {0x9de, 0, 0, 0, f(Yes, false, "")}, - {0x9df, 0, 0, 1, f(No, false, "য়")}, - {0x9e0, 0, 0, 0, f(Yes, false, "")}, - {0xa33, 0, 0, 1, f(No, false, "ਲ਼")}, - {0xa34, 0, 0, 0, f(Yes, false, "")}, - {0xa36, 0, 0, 1, f(No, false, "ਸ਼")}, - {0xa37, 0, 0, 0, f(Yes, false, "")}, - {0xa3c, 7, 1, 1, f(Yes, false, "")}, - {0xa3d, 0, 0, 0, f(Yes, false, "")}, - {0xa4d, 9, 1, 1, f(Yes, false, "")}, - {0xa4e, 0, 0, 0, f(Yes, false, "")}, - {0xa59, 0, 0, 1, f(No, false, "ਖ਼")}, - {0xa5a, 0, 0, 1, f(No, false, "ਗ਼")}, - {0xa5b, 0, 0, 1, f(No, false, "ਜ਼")}, - {0xa5c, 0, 0, 0, f(Yes, false, "")}, - {0xa5e, 0, 0, 1, f(No, false, "ਫ਼")}, - {0xa5f, 0, 0, 0, f(Yes, false, "")}, - {0xabc, 7, 1, 1, f(Yes, false, "")}, - {0xabd, 0, 0, 0, f(Yes, false, "")}, - {0xacd, 9, 1, 1, f(Yes, false, "")}, - {0xace, 0, 0, 0, f(Yes, false, "")}, - {0xb3c, 7, 1, 1, f(Yes, false, "")}, - {0xb3d, 0, 0, 0, f(Yes, false, "")}, - {0xb3e, 0, 1, 1, f(Maybe, false, "")}, - {0xb3f, 0, 0, 0, f(Yes, false, "")}, - {0xb47, 0, 0, 0, f(Yes, true, "")}, - {0xb48, 0, 0, 1, f(Yes, false, "ୈ")}, - {0xb49, 0, 0, 0, f(Yes, false, "")}, - {0xb4b, 0, 0, 1, f(Yes, false, "ୋ")}, - {0xb4c, 0, 0, 1, f(Yes, false, "ୌ")}, - {0xb4d, 9, 1, 1, f(Yes, false, "")}, - {0xb4e, 0, 0, 0, f(Yes, false, "")}, - {0xb56, 0, 1, 1, f(Maybe, false, "")}, - {0xb58, 0, 0, 0, f(Yes, false, "")}, - {0xb5c, 0, 0, 1, f(No, false, "ଡ଼")}, - {0xb5d, 0, 0, 1, f(No, false, "ଢ଼")}, - {0xb5e, 0, 0, 0, f(Yes, false, "")}, - {0xb92, 0, 0, 0, f(Yes, true, "")}, - {0xb93, 0, 0, 0, f(Yes, false, "")}, - {0xb94, 0, 0, 1, f(Yes, false, "ஔ")}, - {0xb95, 0, 0, 0, f(Yes, false, "")}, - {0xbbe, 0, 1, 1, f(Maybe, false, "")}, - {0xbbf, 0, 0, 0, f(Yes, false, "")}, - {0xbc6, 0, 0, 0, f(Yes, true, "")}, - {0xbc8, 0, 0, 0, f(Yes, false, "")}, - {0xbca, 0, 0, 1, f(Yes, false, "ொ")}, - {0xbcb, 0, 0, 1, f(Yes, false, "ோ")}, - {0xbcc, 0, 0, 1, f(Yes, false, "ௌ")}, - {0xbcd, 9, 1, 1, f(Yes, false, "")}, - {0xbce, 0, 0, 0, f(Yes, false, "")}, - {0xbd7, 0, 1, 1, f(Maybe, false, "")}, - {0xbd8, 0, 0, 0, f(Yes, false, "")}, - {0xc46, 0, 0, 0, f(Yes, true, "")}, - {0xc47, 0, 0, 0, f(Yes, false, "")}, - {0xc48, 0, 0, 1, f(Yes, false, "ై")}, - {0xc49, 0, 0, 0, f(Yes, false, "")}, - {0xc4d, 9, 1, 1, f(Yes, false, "")}, - {0xc4e, 0, 0, 0, f(Yes, false, "")}, - {0xc55, 84, 1, 1, f(Yes, false, "")}, - {0xc56, 91, 1, 1, f(Maybe, false, "")}, - {0xc57, 0, 0, 0, f(Yes, false, "")}, - {0xcbc, 7, 1, 1, f(Yes, false, "")}, - {0xcbd, 0, 0, 0, f(Yes, false, "")}, - {0xcbf, 0, 0, 0, f(Yes, true, "")}, - {0xcc0, 0, 0, 1, f(Yes, false, "ೀ")}, - {0xcc1, 0, 0, 0, f(Yes, false, "")}, - {0xcc2, 0, 1, 1, f(Maybe, false, "")}, - {0xcc3, 0, 0, 0, f(Yes, false, "")}, - {0xcc6, 0, 0, 0, f(Yes, true, "")}, - {0xcc7, 0, 0, 1, f(Yes, false, "ೇ")}, - {0xcc8, 0, 0, 1, f(Yes, false, "ೈ")}, - {0xcc9, 0, 0, 0, f(Yes, false, "")}, - {0xcca, 0, 0, 1, f(Yes, true, "ೊ")}, - {0xccb, 0, 0, 2, f(Yes, false, "ೋ")}, - {0xccc, 0, 0, 0, f(Yes, false, "")}, - {0xccd, 9, 1, 1, f(Yes, false, "")}, - {0xcce, 0, 0, 0, f(Yes, false, "")}, - {0xcd5, 0, 1, 1, f(Maybe, false, "")}, - {0xcd7, 0, 0, 0, f(Yes, false, "")}, - {0xd3b, 9, 1, 1, f(Yes, false, "")}, - {0xd3d, 0, 0, 0, f(Yes, false, "")}, - {0xd3e, 0, 1, 1, f(Maybe, false, "")}, - {0xd3f, 0, 0, 0, f(Yes, false, "")}, - {0xd46, 0, 0, 0, f(Yes, true, "")}, - {0xd48, 0, 0, 0, f(Yes, false, "")}, - {0xd4a, 0, 0, 1, f(Yes, false, "ൊ")}, - {0xd4b, 0, 0, 1, f(Yes, false, "ോ")}, - {0xd4c, 0, 0, 1, f(Yes, false, "ൌ")}, - {0xd4d, 9, 1, 1, f(Yes, false, "")}, - {0xd4e, 0, 0, 0, f(Yes, false, "")}, - {0xd57, 0, 1, 1, f(Maybe, false, "")}, - {0xd58, 0, 0, 0, f(Yes, false, "")}, - {0xdca, 9, 1, 1, f(Maybe, false, "")}, - {0xdcb, 0, 0, 0, f(Yes, false, "")}, - {0xdcf, 0, 1, 1, f(Maybe, false, "")}, - {0xdd0, 0, 0, 0, f(Yes, false, "")}, - {0xdd9, 0, 0, 0, f(Yes, true, "")}, - {0xdda, 0, 0, 1, f(Yes, false, "ේ")}, - {0xddb, 0, 0, 0, f(Yes, false, "")}, - {0xddc, 0, 0, 1, f(Yes, true, "ො")}, - {0xddd, 0, 0, 2, f(Yes, false, "ෝ")}, - {0xdde, 0, 0, 1, f(Yes, false, "ෞ")}, - {0xddf, 0, 1, 1, f(Maybe, false, "")}, - {0xde0, 0, 0, 0, f(Yes, false, "")}, - {0xe33, 0, 0, 0, g(Yes, No, false, false, "", "ํา")}, - {0xe34, 0, 0, 0, f(Yes, false, "")}, - {0xe38, 103, 1, 1, f(Yes, false, "")}, - {0xe3a, 9, 1, 1, f(Yes, false, "")}, - {0xe3b, 0, 0, 0, f(Yes, false, "")}, - {0xe48, 107, 1, 1, f(Yes, false, "")}, - {0xe4c, 0, 0, 0, f(Yes, false, "")}, - {0xeb3, 0, 0, 0, g(Yes, No, false, false, "", "ໍາ")}, - {0xeb4, 0, 0, 0, f(Yes, false, "")}, - {0xeb8, 118, 1, 1, f(Yes, false, "")}, - {0xeba, 0, 0, 0, f(Yes, false, "")}, - {0xec8, 122, 1, 1, f(Yes, false, "")}, - {0xecc, 0, 0, 0, f(Yes, false, "")}, - {0xedc, 0, 0, 0, g(Yes, No, false, false, "", "ຫນ")}, - {0xedd, 0, 0, 0, g(Yes, No, false, false, "", "ຫມ")}, - {0xede, 0, 0, 0, f(Yes, false, "")}, - {0xf0c, 0, 0, 0, g(Yes, No, false, false, "", "་")}, - {0xf0d, 0, 0, 0, f(Yes, false, "")}, - {0xf18, 220, 1, 1, f(Yes, false, "")}, - {0xf1a, 0, 0, 0, f(Yes, false, "")}, - {0xf35, 220, 1, 1, f(Yes, false, "")}, - {0xf36, 0, 0, 0, f(Yes, false, "")}, - {0xf37, 220, 1, 1, f(Yes, false, "")}, - {0xf38, 0, 0, 0, f(Yes, false, "")}, - {0xf39, 216, 1, 1, f(Yes, false, "")}, - {0xf3a, 0, 0, 0, f(Yes, false, "")}, - {0xf43, 0, 0, 0, f(No, false, "གྷ")}, - {0xf44, 0, 0, 0, f(Yes, false, "")}, - {0xf4d, 0, 0, 0, f(No, false, "ཌྷ")}, - {0xf4e, 0, 0, 0, f(Yes, false, "")}, - {0xf52, 0, 0, 0, f(No, false, "དྷ")}, - {0xf53, 0, 0, 0, f(Yes, false, "")}, - {0xf57, 0, 0, 0, f(No, false, "བྷ")}, - {0xf58, 0, 0, 0, f(Yes, false, "")}, - {0xf5c, 0, 0, 0, f(No, false, "ཛྷ")}, - {0xf5d, 0, 0, 0, f(Yes, false, "")}, - {0xf69, 0, 0, 0, f(No, false, "ཀྵ")}, - {0xf6a, 0, 0, 0, f(Yes, false, "")}, - {0xf71, 129, 1, 1, f(Yes, false, "")}, - {0xf72, 130, 1, 1, f(Yes, false, "")}, - {0xf73, 0, 2, 2, f(No, false, "ཱི")}, - {0xf74, 132, 1, 1, f(Yes, false, "")}, - {0xf75, 0, 2, 2, f(No, false, "ཱུ")}, - {0xf76, 0, 0, 1, f(No, false, "ྲྀ")}, - {0xf77, 0, 0, 2, g(Yes, No, false, false, "", "ྲཱྀ")}, - {0xf78, 0, 0, 1, f(No, false, "ླྀ")}, - {0xf79, 0, 0, 2, g(Yes, No, false, false, "", "ླཱྀ")}, - {0xf7a, 130, 1, 1, f(Yes, false, "")}, - {0xf7e, 0, 0, 0, f(Yes, false, "")}, - {0xf80, 130, 1, 1, f(Yes, false, "")}, - {0xf81, 0, 2, 2, f(No, false, "ཱྀ")}, - {0xf82, 230, 1, 1, f(Yes, false, "")}, - {0xf84, 9, 1, 1, f(Yes, false, "")}, - {0xf85, 0, 0, 0, f(Yes, false, "")}, - {0xf86, 230, 1, 1, f(Yes, false, "")}, - {0xf88, 0, 0, 0, f(Yes, false, "")}, - {0xf93, 0, 0, 0, f(No, false, "ྒྷ")}, - {0xf94, 0, 0, 0, f(Yes, false, "")}, - {0xf9d, 0, 0, 0, f(No, false, "ྜྷ")}, - {0xf9e, 0, 0, 0, f(Yes, false, "")}, - {0xfa2, 0, 0, 0, f(No, false, "ྡྷ")}, - {0xfa3, 0, 0, 0, f(Yes, false, "")}, - {0xfa7, 0, 0, 0, f(No, false, "ྦྷ")}, - {0xfa8, 0, 0, 0, f(Yes, false, "")}, - {0xfac, 0, 0, 0, f(No, false, "ྫྷ")}, - {0xfad, 0, 0, 0, f(Yes, false, "")}, - {0xfb9, 0, 0, 0, f(No, false, "ྐྵ")}, - {0xfba, 0, 0, 0, f(Yes, false, "")}, - {0xfc6, 220, 1, 1, f(Yes, false, "")}, - {0xfc7, 0, 0, 0, f(Yes, false, "")}, - {0x1025, 0, 0, 0, f(Yes, true, "")}, - {0x1026, 0, 0, 1, f(Yes, false, "ဦ")}, - {0x1027, 0, 0, 0, f(Yes, false, "")}, - {0x102e, 0, 1, 1, f(Maybe, false, "")}, - {0x102f, 0, 0, 0, f(Yes, false, "")}, - {0x1037, 7, 1, 1, f(Yes, false, "")}, - {0x1038, 0, 0, 0, f(Yes, false, "")}, - {0x1039, 9, 1, 1, f(Yes, false, "")}, - {0x103b, 0, 0, 0, f(Yes, false, "")}, - {0x108d, 220, 1, 1, f(Yes, false, "")}, - {0x108e, 0, 0, 0, f(Yes, false, "")}, - {0x10fc, 0, 0, 0, g(Yes, No, false, false, "", "ნ")}, - {0x10fd, 0, 0, 0, f(Yes, false, "")}, - {0x1100, 0, 0, 0, f(Yes, true, "")}, - {0x1113, 0, 0, 0, f(Yes, false, "")}, - {0x1161, 0, 1, 1, f(Maybe, true, "")}, - {0x1176, 0, 0, 0, f(Yes, false, "")}, - {0x11a8, 0, 1, 1, f(Maybe, false, "")}, - {0x11c3, 0, 0, 0, f(Yes, false, "")}, - {0x135d, 230, 1, 1, f(Yes, false, "")}, - {0x1360, 0, 0, 0, f(Yes, false, "")}, - {0x1714, 9, 1, 1, f(Yes, false, "")}, - {0x1715, 0, 0, 0, f(Yes, false, "")}, - {0x1734, 9, 1, 1, f(Yes, false, "")}, - {0x1735, 0, 0, 0, f(Yes, false, "")}, - {0x17d2, 9, 1, 1, f(Yes, false, "")}, - {0x17d3, 0, 0, 0, f(Yes, false, "")}, - {0x17dd, 230, 1, 1, f(Yes, false, "")}, - {0x17de, 0, 0, 0, f(Yes, false, "")}, - {0x18a9, 228, 1, 1, f(Yes, false, "")}, - {0x18aa, 0, 0, 0, f(Yes, false, "")}, - {0x1939, 222, 1, 1, f(Yes, false, "")}, - {0x193a, 230, 1, 1, f(Yes, false, "")}, - {0x193b, 220, 1, 1, f(Yes, false, "")}, - {0x193c, 0, 0, 0, f(Yes, false, "")}, - {0x1a17, 230, 1, 1, f(Yes, false, "")}, - {0x1a18, 220, 1, 1, f(Yes, false, "")}, - {0x1a19, 0, 0, 0, f(Yes, false, "")}, - {0x1a60, 9, 1, 1, f(Yes, false, "")}, - {0x1a61, 0, 0, 0, f(Yes, false, "")}, - {0x1a75, 230, 1, 1, f(Yes, false, "")}, - {0x1a7d, 0, 0, 0, f(Yes, false, "")}, - {0x1a7f, 220, 1, 1, f(Yes, false, "")}, - {0x1a80, 0, 0, 0, f(Yes, false, "")}, - {0x1ab0, 230, 1, 1, f(Yes, false, "")}, - {0x1ab5, 220, 1, 1, f(Yes, false, "")}, - {0x1abb, 230, 1, 1, f(Yes, false, "")}, - {0x1abd, 220, 1, 1, f(Yes, false, "")}, - {0x1abe, 0, 0, 0, f(Yes, false, "")}, - {0x1b05, 0, 0, 0, f(Yes, true, "")}, - {0x1b06, 0, 0, 1, f(Yes, false, "ᬆ")}, - {0x1b07, 0, 0, 0, f(Yes, true, "")}, - {0x1b08, 0, 0, 1, f(Yes, false, "ᬈ")}, - {0x1b09, 0, 0, 0, f(Yes, true, "")}, - {0x1b0a, 0, 0, 1, f(Yes, false, "ᬊ")}, - {0x1b0b, 0, 0, 0, f(Yes, true, "")}, - {0x1b0c, 0, 0, 1, f(Yes, false, "ᬌ")}, - {0x1b0d, 0, 0, 0, f(Yes, true, "")}, - {0x1b0e, 0, 0, 1, f(Yes, false, "ᬎ")}, - {0x1b0f, 0, 0, 0, f(Yes, false, "")}, - {0x1b11, 0, 0, 0, f(Yes, true, "")}, - {0x1b12, 0, 0, 1, f(Yes, false, "ᬒ")}, - {0x1b13, 0, 0, 0, f(Yes, false, "")}, - {0x1b34, 7, 1, 1, f(Yes, false, "")}, - {0x1b35, 0, 1, 1, f(Maybe, false, "")}, - {0x1b36, 0, 0, 0, f(Yes, false, "")}, - {0x1b3a, 0, 0, 0, f(Yes, true, "")}, - {0x1b3b, 0, 0, 1, f(Yes, false, "ᬻ")}, - {0x1b3c, 0, 0, 0, f(Yes, true, "")}, - {0x1b3d, 0, 0, 1, f(Yes, false, "ᬽ")}, - {0x1b3e, 0, 0, 0, f(Yes, true, "")}, - {0x1b40, 0, 0, 1, f(Yes, false, "ᭀ")}, - {0x1b41, 0, 0, 1, f(Yes, false, "ᭁ")}, - {0x1b42, 0, 0, 0, f(Yes, true, "")}, - {0x1b43, 0, 0, 1, f(Yes, false, "ᭃ")}, - {0x1b44, 9, 1, 1, f(Yes, false, "")}, - {0x1b45, 0, 0, 0, f(Yes, false, "")}, - {0x1b6b, 230, 1, 1, f(Yes, false, "")}, - {0x1b6c, 220, 1, 1, f(Yes, false, "")}, - {0x1b6d, 230, 1, 1, f(Yes, false, "")}, - {0x1b74, 0, 0, 0, f(Yes, false, "")}, - {0x1baa, 9, 1, 1, f(Yes, false, "")}, - {0x1bac, 0, 0, 0, f(Yes, false, "")}, - {0x1be6, 7, 1, 1, f(Yes, false, "")}, - {0x1be7, 0, 0, 0, f(Yes, false, "")}, - {0x1bf2, 9, 1, 1, f(Yes, false, "")}, - {0x1bf4, 0, 0, 0, f(Yes, false, "")}, - {0x1c37, 7, 1, 1, f(Yes, false, "")}, - {0x1c38, 0, 0, 0, f(Yes, false, "")}, - {0x1cd0, 230, 1, 1, f(Yes, false, "")}, - {0x1cd3, 0, 0, 0, f(Yes, false, "")}, - {0x1cd4, 1, 1, 1, f(Yes, false, "")}, - {0x1cd5, 220, 1, 1, f(Yes, false, "")}, - {0x1cda, 230, 1, 1, f(Yes, false, "")}, - {0x1cdc, 220, 1, 1, f(Yes, false, "")}, - {0x1ce0, 230, 1, 1, f(Yes, false, "")}, - {0x1ce1, 0, 0, 0, f(Yes, false, "")}, - {0x1ce2, 1, 1, 1, f(Yes, false, "")}, - {0x1ce9, 0, 0, 0, f(Yes, false, "")}, - {0x1ced, 220, 1, 1, f(Yes, false, "")}, - {0x1cee, 0, 0, 0, f(Yes, false, "")}, - {0x1cf4, 230, 1, 1, f(Yes, false, "")}, - {0x1cf5, 0, 0, 0, f(Yes, false, "")}, - {0x1cf8, 230, 1, 1, f(Yes, false, "")}, - {0x1cfa, 0, 0, 0, f(Yes, false, "")}, - {0x1d2c, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0x1d2d, 0, 0, 0, g(Yes, No, false, false, "", "Æ")}, - {0x1d2e, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0x1d2f, 0, 0, 0, f(Yes, false, "")}, - {0x1d30, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x1d31, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0x1d32, 0, 0, 0, g(Yes, No, false, false, "", "Ǝ")}, - {0x1d33, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0x1d34, 0, 0, 0, g(Yes, No, false, false, "", "H")}, - {0x1d35, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0x1d36, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0x1d37, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0x1d38, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x1d39, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x1d3a, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0x1d3b, 0, 0, 0, f(Yes, false, "")}, - {0x1d3c, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0x1d3d, 0, 0, 0, g(Yes, No, false, false, "", "Ȣ")}, - {0x1d3e, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0x1d3f, 0, 0, 0, g(Yes, No, false, false, "", "R")}, - {0x1d40, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0x1d41, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0x1d42, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0x1d43, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0x1d44, 0, 0, 0, g(Yes, No, false, false, "", "ɐ")}, - {0x1d45, 0, 0, 0, g(Yes, No, false, false, "", "ɑ")}, - {0x1d46, 0, 0, 0, g(Yes, No, false, false, "", "ᴂ")}, - {0x1d47, 0, 0, 0, g(Yes, No, false, false, "", "b")}, - {0x1d48, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x1d49, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x1d4a, 0, 0, 0, g(Yes, No, false, false, "", "ə")}, - {0x1d4b, 0, 0, 0, g(Yes, No, false, false, "", "ɛ")}, - {0x1d4c, 0, 0, 0, g(Yes, No, false, false, "", "ɜ")}, - {0x1d4d, 0, 0, 0, g(Yes, No, false, false, "", "g")}, - {0x1d4e, 0, 0, 0, f(Yes, false, "")}, - {0x1d4f, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0x1d50, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x1d51, 0, 0, 0, g(Yes, No, false, false, "", "ŋ")}, - {0x1d52, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0x1d53, 0, 0, 0, g(Yes, No, false, false, "", "ɔ")}, - {0x1d54, 0, 0, 0, g(Yes, No, false, false, "", "ᴖ")}, - {0x1d55, 0, 0, 0, g(Yes, No, false, false, "", "ᴗ")}, - {0x1d56, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0x1d57, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0x1d58, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0x1d59, 0, 0, 0, g(Yes, No, false, false, "", "ᴝ")}, - {0x1d5a, 0, 0, 0, g(Yes, No, false, false, "", "ɯ")}, - {0x1d5b, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x1d5c, 0, 0, 0, g(Yes, No, false, false, "", "ᴥ")}, - {0x1d5d, 0, 0, 0, g(Yes, No, false, false, "", "β")}, - {0x1d5e, 0, 0, 0, g(Yes, No, false, false, "", "γ")}, - {0x1d5f, 0, 0, 0, g(Yes, No, false, false, "", "δ")}, - {0x1d60, 0, 0, 0, g(Yes, No, false, false, "", "φ")}, - {0x1d61, 0, 0, 0, g(Yes, No, false, false, "", "χ")}, - {0x1d62, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x1d63, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0x1d64, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0x1d65, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x1d66, 0, 0, 0, g(Yes, No, false, false, "", "β")}, - {0x1d67, 0, 0, 0, g(Yes, No, false, false, "", "γ")}, - {0x1d68, 0, 0, 0, g(Yes, No, false, false, "", "ρ")}, - {0x1d69, 0, 0, 0, g(Yes, No, false, false, "", "φ")}, - {0x1d6a, 0, 0, 0, g(Yes, No, false, false, "", "χ")}, - {0x1d6b, 0, 0, 0, f(Yes, false, "")}, - {0x1d78, 0, 0, 0, g(Yes, No, false, false, "", "н")}, - {0x1d79, 0, 0, 0, f(Yes, false, "")}, - {0x1d9b, 0, 0, 0, g(Yes, No, false, false, "", "ɒ")}, - {0x1d9c, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0x1d9d, 0, 0, 0, g(Yes, No, false, false, "", "ɕ")}, - {0x1d9e, 0, 0, 0, g(Yes, No, false, false, "", "ð")}, - {0x1d9f, 0, 0, 0, g(Yes, No, false, false, "", "ɜ")}, - {0x1da0, 0, 0, 0, g(Yes, No, false, false, "", "f")}, - {0x1da1, 0, 0, 0, g(Yes, No, false, false, "", "ɟ")}, - {0x1da2, 0, 0, 0, g(Yes, No, false, false, "", "ɡ")}, - {0x1da3, 0, 0, 0, g(Yes, No, false, false, "", "ɥ")}, - {0x1da4, 0, 0, 0, g(Yes, No, false, false, "", "ɨ")}, - {0x1da5, 0, 0, 0, g(Yes, No, false, false, "", "ɩ")}, - {0x1da6, 0, 0, 0, g(Yes, No, false, false, "", "ɪ")}, - {0x1da7, 0, 0, 0, g(Yes, No, false, false, "", "ᵻ")}, - {0x1da8, 0, 0, 0, g(Yes, No, false, false, "", "ʝ")}, - {0x1da9, 0, 0, 0, g(Yes, No, false, false, "", "ɭ")}, - {0x1daa, 0, 0, 0, g(Yes, No, false, false, "", "ᶅ")}, - {0x1dab, 0, 0, 0, g(Yes, No, false, false, "", "ʟ")}, - {0x1dac, 0, 0, 0, g(Yes, No, false, false, "", "ɱ")}, - {0x1dad, 0, 0, 0, g(Yes, No, false, false, "", "ɰ")}, - {0x1dae, 0, 0, 0, g(Yes, No, false, false, "", "ɲ")}, - {0x1daf, 0, 0, 0, g(Yes, No, false, false, "", "ɳ")}, - {0x1db0, 0, 0, 0, g(Yes, No, false, false, "", "ɴ")}, - {0x1db1, 0, 0, 0, g(Yes, No, false, false, "", "ɵ")}, - {0x1db2, 0, 0, 0, g(Yes, No, false, false, "", "ɸ")}, - {0x1db3, 0, 0, 0, g(Yes, No, false, false, "", "ʂ")}, - {0x1db4, 0, 0, 0, g(Yes, No, false, false, "", "ʃ")}, - {0x1db5, 0, 0, 0, g(Yes, No, false, false, "", "ƫ")}, - {0x1db6, 0, 0, 0, g(Yes, No, false, false, "", "ʉ")}, - {0x1db7, 0, 0, 0, g(Yes, No, false, false, "", "ʊ")}, - {0x1db8, 0, 0, 0, g(Yes, No, false, false, "", "ᴜ")}, - {0x1db9, 0, 0, 0, g(Yes, No, false, false, "", "ʋ")}, - {0x1dba, 0, 0, 0, g(Yes, No, false, false, "", "ʌ")}, - {0x1dbb, 0, 0, 0, g(Yes, No, false, false, "", "z")}, - {0x1dbc, 0, 0, 0, g(Yes, No, false, false, "", "ʐ")}, - {0x1dbd, 0, 0, 0, g(Yes, No, false, false, "", "ʑ")}, - {0x1dbe, 0, 0, 0, g(Yes, No, false, false, "", "ʒ")}, - {0x1dbf, 0, 0, 0, g(Yes, No, false, false, "", "θ")}, - {0x1dc0, 230, 1, 1, f(Yes, false, "")}, - {0x1dc2, 220, 1, 1, f(Yes, false, "")}, - {0x1dc3, 230, 1, 1, f(Yes, false, "")}, - {0x1dca, 220, 1, 1, f(Yes, false, "")}, - {0x1dcb, 230, 1, 1, f(Yes, false, "")}, - {0x1dcd, 234, 1, 1, f(Yes, false, "")}, - {0x1dce, 214, 1, 1, f(Yes, false, "")}, - {0x1dcf, 220, 1, 1, f(Yes, false, "")}, - {0x1dd0, 202, 1, 1, f(Yes, false, "")}, - {0x1dd1, 230, 1, 1, f(Yes, false, "")}, - {0x1df6, 232, 1, 1, f(Yes, false, "")}, - {0x1df7, 228, 1, 1, f(Yes, false, "")}, - {0x1df9, 220, 1, 1, f(Yes, false, "")}, - {0x1dfa, 0, 0, 0, f(Yes, false, "")}, - {0x1dfb, 230, 1, 1, f(Yes, false, "")}, - {0x1dfc, 233, 1, 1, f(Yes, false, "")}, - {0x1dfd, 220, 1, 1, f(Yes, false, "")}, - {0x1dfe, 230, 1, 1, f(Yes, false, "")}, - {0x1dff, 220, 1, 1, f(Yes, false, "")}, - {0x1e00, 0, 0, 1, f(Yes, false, "Ḁ")}, - {0x1e01, 0, 0, 1, f(Yes, false, "ḁ")}, - {0x1e02, 0, 0, 1, f(Yes, false, "Ḃ")}, - {0x1e03, 0, 0, 1, f(Yes, false, "ḃ")}, - {0x1e04, 0, 0, 1, f(Yes, false, "Ḅ")}, - {0x1e05, 0, 0, 1, f(Yes, false, "ḅ")}, - {0x1e06, 0, 0, 1, f(Yes, false, "Ḇ")}, - {0x1e07, 0, 0, 1, f(Yes, false, "ḇ")}, - {0x1e08, 0, 0, 2, f(Yes, false, "Ḉ")}, - {0x1e09, 0, 0, 2, f(Yes, false, "ḉ")}, - {0x1e0a, 0, 0, 1, f(Yes, false, "Ḋ")}, - {0x1e0b, 0, 0, 1, f(Yes, false, "ḋ")}, - {0x1e0c, 0, 0, 1, f(Yes, false, "Ḍ")}, - {0x1e0d, 0, 0, 1, f(Yes, false, "ḍ")}, - {0x1e0e, 0, 0, 1, f(Yes, false, "Ḏ")}, - {0x1e0f, 0, 0, 1, f(Yes, false, "ḏ")}, - {0x1e10, 0, 0, 1, f(Yes, false, "Ḑ")}, - {0x1e11, 0, 0, 1, f(Yes, false, "ḑ")}, - {0x1e12, 0, 0, 1, f(Yes, false, "Ḓ")}, - {0x1e13, 0, 0, 1, f(Yes, false, "ḓ")}, - {0x1e14, 0, 0, 2, f(Yes, false, "Ḕ")}, - {0x1e15, 0, 0, 2, f(Yes, false, "ḕ")}, - {0x1e16, 0, 0, 2, f(Yes, false, "Ḗ")}, - {0x1e17, 0, 0, 2, f(Yes, false, "ḗ")}, - {0x1e18, 0, 0, 1, f(Yes, false, "Ḙ")}, - {0x1e19, 0, 0, 1, f(Yes, false, "ḙ")}, - {0x1e1a, 0, 0, 1, f(Yes, false, "Ḛ")}, - {0x1e1b, 0, 0, 1, f(Yes, false, "ḛ")}, - {0x1e1c, 0, 0, 2, f(Yes, false, "Ḝ")}, - {0x1e1d, 0, 0, 2, f(Yes, false, "ḝ")}, - {0x1e1e, 0, 0, 1, f(Yes, false, "Ḟ")}, - {0x1e1f, 0, 0, 1, f(Yes, false, "ḟ")}, - {0x1e20, 0, 0, 1, f(Yes, false, "Ḡ")}, - {0x1e21, 0, 0, 1, f(Yes, false, "ḡ")}, - {0x1e22, 0, 0, 1, f(Yes, false, "Ḣ")}, - {0x1e23, 0, 0, 1, f(Yes, false, "ḣ")}, - {0x1e24, 0, 0, 1, f(Yes, false, "Ḥ")}, - {0x1e25, 0, 0, 1, f(Yes, false, "ḥ")}, - {0x1e26, 0, 0, 1, f(Yes, false, "Ḧ")}, - {0x1e27, 0, 0, 1, f(Yes, false, "ḧ")}, - {0x1e28, 0, 0, 1, f(Yes, false, "Ḩ")}, - {0x1e29, 0, 0, 1, f(Yes, false, "ḩ")}, - {0x1e2a, 0, 0, 1, f(Yes, false, "Ḫ")}, - {0x1e2b, 0, 0, 1, f(Yes, false, "ḫ")}, - {0x1e2c, 0, 0, 1, f(Yes, false, "Ḭ")}, - {0x1e2d, 0, 0, 1, f(Yes, false, "ḭ")}, - {0x1e2e, 0, 0, 2, f(Yes, false, "Ḯ")}, - {0x1e2f, 0, 0, 2, f(Yes, false, "ḯ")}, - {0x1e30, 0, 0, 1, f(Yes, false, "Ḱ")}, - {0x1e31, 0, 0, 1, f(Yes, false, "ḱ")}, - {0x1e32, 0, 0, 1, f(Yes, false, "Ḳ")}, - {0x1e33, 0, 0, 1, f(Yes, false, "ḳ")}, - {0x1e34, 0, 0, 1, f(Yes, false, "Ḵ")}, - {0x1e35, 0, 0, 1, f(Yes, false, "ḵ")}, - {0x1e36, 0, 0, 1, f(Yes, true, "Ḷ")}, - {0x1e37, 0, 0, 1, f(Yes, true, "ḷ")}, - {0x1e38, 0, 0, 2, f(Yes, false, "Ḹ")}, - {0x1e39, 0, 0, 2, f(Yes, false, "ḹ")}, - {0x1e3a, 0, 0, 1, f(Yes, false, "Ḻ")}, - {0x1e3b, 0, 0, 1, f(Yes, false, "ḻ")}, - {0x1e3c, 0, 0, 1, f(Yes, false, "Ḽ")}, - {0x1e3d, 0, 0, 1, f(Yes, false, "ḽ")}, - {0x1e3e, 0, 0, 1, f(Yes, false, "Ḿ")}, - {0x1e3f, 0, 0, 1, f(Yes, false, "ḿ")}, - {0x1e40, 0, 0, 1, f(Yes, false, "Ṁ")}, - {0x1e41, 0, 0, 1, f(Yes, false, "ṁ")}, - {0x1e42, 0, 0, 1, f(Yes, false, "Ṃ")}, - {0x1e43, 0, 0, 1, f(Yes, false, "ṃ")}, - {0x1e44, 0, 0, 1, f(Yes, false, "Ṅ")}, - {0x1e45, 0, 0, 1, f(Yes, false, "ṅ")}, - {0x1e46, 0, 0, 1, f(Yes, false, "Ṇ")}, - {0x1e47, 0, 0, 1, f(Yes, false, "ṇ")}, - {0x1e48, 0, 0, 1, f(Yes, false, "Ṉ")}, - {0x1e49, 0, 0, 1, f(Yes, false, "ṉ")}, - {0x1e4a, 0, 0, 1, f(Yes, false, "Ṋ")}, - {0x1e4b, 0, 0, 1, f(Yes, false, "ṋ")}, - {0x1e4c, 0, 0, 2, f(Yes, false, "Ṍ")}, - {0x1e4d, 0, 0, 2, f(Yes, false, "ṍ")}, - {0x1e4e, 0, 0, 2, f(Yes, false, "Ṏ")}, - {0x1e4f, 0, 0, 2, f(Yes, false, "ṏ")}, - {0x1e50, 0, 0, 2, f(Yes, false, "Ṑ")}, - {0x1e51, 0, 0, 2, f(Yes, false, "ṑ")}, - {0x1e52, 0, 0, 2, f(Yes, false, "Ṓ")}, - {0x1e53, 0, 0, 2, f(Yes, false, "ṓ")}, - {0x1e54, 0, 0, 1, f(Yes, false, "Ṕ")}, - {0x1e55, 0, 0, 1, f(Yes, false, "ṕ")}, - {0x1e56, 0, 0, 1, f(Yes, false, "Ṗ")}, - {0x1e57, 0, 0, 1, f(Yes, false, "ṗ")}, - {0x1e58, 0, 0, 1, f(Yes, false, "Ṙ")}, - {0x1e59, 0, 0, 1, f(Yes, false, "ṙ")}, - {0x1e5a, 0, 0, 1, f(Yes, true, "Ṛ")}, - {0x1e5b, 0, 0, 1, f(Yes, true, "ṛ")}, - {0x1e5c, 0, 0, 2, f(Yes, false, "Ṝ")}, - {0x1e5d, 0, 0, 2, f(Yes, false, "ṝ")}, - {0x1e5e, 0, 0, 1, f(Yes, false, "Ṟ")}, - {0x1e5f, 0, 0, 1, f(Yes, false, "ṟ")}, - {0x1e60, 0, 0, 1, f(Yes, false, "Ṡ")}, - {0x1e61, 0, 0, 1, f(Yes, false, "ṡ")}, - {0x1e62, 0, 0, 1, f(Yes, true, "Ṣ")}, - {0x1e63, 0, 0, 1, f(Yes, true, "ṣ")}, - {0x1e64, 0, 0, 2, f(Yes, false, "Ṥ")}, - {0x1e65, 0, 0, 2, f(Yes, false, "ṥ")}, - {0x1e66, 0, 0, 2, f(Yes, false, "Ṧ")}, - {0x1e67, 0, 0, 2, f(Yes, false, "ṧ")}, - {0x1e68, 0, 0, 2, f(Yes, false, "Ṩ")}, - {0x1e69, 0, 0, 2, f(Yes, false, "ṩ")}, - {0x1e6a, 0, 0, 1, f(Yes, false, "Ṫ")}, - {0x1e6b, 0, 0, 1, f(Yes, false, "ṫ")}, - {0x1e6c, 0, 0, 1, f(Yes, false, "Ṭ")}, - {0x1e6d, 0, 0, 1, f(Yes, false, "ṭ")}, - {0x1e6e, 0, 0, 1, f(Yes, false, "Ṯ")}, - {0x1e6f, 0, 0, 1, f(Yes, false, "ṯ")}, - {0x1e70, 0, 0, 1, f(Yes, false, "Ṱ")}, - {0x1e71, 0, 0, 1, f(Yes, false, "ṱ")}, - {0x1e72, 0, 0, 1, f(Yes, false, "Ṳ")}, - {0x1e73, 0, 0, 1, f(Yes, false, "ṳ")}, - {0x1e74, 0, 0, 1, f(Yes, false, "Ṵ")}, - {0x1e75, 0, 0, 1, f(Yes, false, "ṵ")}, - {0x1e76, 0, 0, 1, f(Yes, false, "Ṷ")}, - {0x1e77, 0, 0, 1, f(Yes, false, "ṷ")}, - {0x1e78, 0, 0, 2, f(Yes, false, "Ṹ")}, - {0x1e79, 0, 0, 2, f(Yes, false, "ṹ")}, - {0x1e7a, 0, 0, 2, f(Yes, false, "Ṻ")}, - {0x1e7b, 0, 0, 2, f(Yes, false, "ṻ")}, - {0x1e7c, 0, 0, 1, f(Yes, false, "Ṽ")}, - {0x1e7d, 0, 0, 1, f(Yes, false, "ṽ")}, - {0x1e7e, 0, 0, 1, f(Yes, false, "Ṿ")}, - {0x1e7f, 0, 0, 1, f(Yes, false, "ṿ")}, - {0x1e80, 0, 0, 1, f(Yes, false, "Ẁ")}, - {0x1e81, 0, 0, 1, f(Yes, false, "ẁ")}, - {0x1e82, 0, 0, 1, f(Yes, false, "Ẃ")}, - {0x1e83, 0, 0, 1, f(Yes, false, "ẃ")}, - {0x1e84, 0, 0, 1, f(Yes, false, "Ẅ")}, - {0x1e85, 0, 0, 1, f(Yes, false, "ẅ")}, - {0x1e86, 0, 0, 1, f(Yes, false, "Ẇ")}, - {0x1e87, 0, 0, 1, f(Yes, false, "ẇ")}, - {0x1e88, 0, 0, 1, f(Yes, false, "Ẉ")}, - {0x1e89, 0, 0, 1, f(Yes, false, "ẉ")}, - {0x1e8a, 0, 0, 1, f(Yes, false, "Ẋ")}, - {0x1e8b, 0, 0, 1, f(Yes, false, "ẋ")}, - {0x1e8c, 0, 0, 1, f(Yes, false, "Ẍ")}, - {0x1e8d, 0, 0, 1, f(Yes, false, "ẍ")}, - {0x1e8e, 0, 0, 1, f(Yes, false, "Ẏ")}, - {0x1e8f, 0, 0, 1, f(Yes, false, "ẏ")}, - {0x1e90, 0, 0, 1, f(Yes, false, "Ẑ")}, - {0x1e91, 0, 0, 1, f(Yes, false, "ẑ")}, - {0x1e92, 0, 0, 1, f(Yes, false, "Ẓ")}, - {0x1e93, 0, 0, 1, f(Yes, false, "ẓ")}, - {0x1e94, 0, 0, 1, f(Yes, false, "Ẕ")}, - {0x1e95, 0, 0, 1, f(Yes, false, "ẕ")}, - {0x1e96, 0, 0, 1, f(Yes, false, "ẖ")}, - {0x1e97, 0, 0, 1, f(Yes, false, "ẗ")}, - {0x1e98, 0, 0, 1, f(Yes, false, "ẘ")}, - {0x1e99, 0, 0, 1, f(Yes, false, "ẙ")}, - {0x1e9a, 0, 0, 0, g(Yes, No, false, false, "", "aʾ")}, - {0x1e9b, 0, 0, 1, g(Yes, No, false, false, "ẛ", "ṡ")}, - {0x1e9c, 0, 0, 0, f(Yes, false, "")}, - {0x1ea0, 0, 0, 1, f(Yes, true, "Ạ")}, - {0x1ea1, 0, 0, 1, f(Yes, true, "ạ")}, - {0x1ea2, 0, 0, 1, f(Yes, false, "Ả")}, - {0x1ea3, 0, 0, 1, f(Yes, false, "ả")}, - {0x1ea4, 0, 0, 2, f(Yes, false, "Ấ")}, - {0x1ea5, 0, 0, 2, f(Yes, false, "ấ")}, - {0x1ea6, 0, 0, 2, f(Yes, false, "Ầ")}, - {0x1ea7, 0, 0, 2, f(Yes, false, "ầ")}, - {0x1ea8, 0, 0, 2, f(Yes, false, "Ẩ")}, - {0x1ea9, 0, 0, 2, f(Yes, false, "ẩ")}, - {0x1eaa, 0, 0, 2, f(Yes, false, "Ẫ")}, - {0x1eab, 0, 0, 2, f(Yes, false, "ẫ")}, - {0x1eac, 0, 0, 2, f(Yes, false, "Ậ")}, - {0x1ead, 0, 0, 2, f(Yes, false, "ậ")}, - {0x1eae, 0, 0, 2, f(Yes, false, "Ắ")}, - {0x1eaf, 0, 0, 2, f(Yes, false, "ắ")}, - {0x1eb0, 0, 0, 2, f(Yes, false, "Ằ")}, - {0x1eb1, 0, 0, 2, f(Yes, false, "ằ")}, - {0x1eb2, 0, 0, 2, f(Yes, false, "Ẳ")}, - {0x1eb3, 0, 0, 2, f(Yes, false, "ẳ")}, - {0x1eb4, 0, 0, 2, f(Yes, false, "Ẵ")}, - {0x1eb5, 0, 0, 2, f(Yes, false, "ẵ")}, - {0x1eb6, 0, 0, 2, f(Yes, false, "Ặ")}, - {0x1eb7, 0, 0, 2, f(Yes, false, "ặ")}, - {0x1eb8, 0, 0, 1, f(Yes, true, "Ẹ")}, - {0x1eb9, 0, 0, 1, f(Yes, true, "ẹ")}, - {0x1eba, 0, 0, 1, f(Yes, false, "Ẻ")}, - {0x1ebb, 0, 0, 1, f(Yes, false, "ẻ")}, - {0x1ebc, 0, 0, 1, f(Yes, false, "Ẽ")}, - {0x1ebd, 0, 0, 1, f(Yes, false, "ẽ")}, - {0x1ebe, 0, 0, 2, f(Yes, false, "Ế")}, - {0x1ebf, 0, 0, 2, f(Yes, false, "ế")}, - {0x1ec0, 0, 0, 2, f(Yes, false, "Ề")}, - {0x1ec1, 0, 0, 2, f(Yes, false, "ề")}, - {0x1ec2, 0, 0, 2, f(Yes, false, "Ể")}, - {0x1ec3, 0, 0, 2, f(Yes, false, "ể")}, - {0x1ec4, 0, 0, 2, f(Yes, false, "Ễ")}, - {0x1ec5, 0, 0, 2, f(Yes, false, "ễ")}, - {0x1ec6, 0, 0, 2, f(Yes, false, "Ệ")}, - {0x1ec7, 0, 0, 2, f(Yes, false, "ệ")}, - {0x1ec8, 0, 0, 1, f(Yes, false, "Ỉ")}, - {0x1ec9, 0, 0, 1, f(Yes, false, "ỉ")}, - {0x1eca, 0, 0, 1, f(Yes, false, "Ị")}, - {0x1ecb, 0, 0, 1, f(Yes, false, "ị")}, - {0x1ecc, 0, 0, 1, f(Yes, true, "Ọ")}, - {0x1ecd, 0, 0, 1, f(Yes, true, "ọ")}, - {0x1ece, 0, 0, 1, f(Yes, false, "Ỏ")}, - {0x1ecf, 0, 0, 1, f(Yes, false, "ỏ")}, - {0x1ed0, 0, 0, 2, f(Yes, false, "Ố")}, - {0x1ed1, 0, 0, 2, f(Yes, false, "ố")}, - {0x1ed2, 0, 0, 2, f(Yes, false, "Ồ")}, - {0x1ed3, 0, 0, 2, f(Yes, false, "ồ")}, - {0x1ed4, 0, 0, 2, f(Yes, false, "Ổ")}, - {0x1ed5, 0, 0, 2, f(Yes, false, "ổ")}, - {0x1ed6, 0, 0, 2, f(Yes, false, "Ỗ")}, - {0x1ed7, 0, 0, 2, f(Yes, false, "ỗ")}, - {0x1ed8, 0, 0, 2, f(Yes, false, "Ộ")}, - {0x1ed9, 0, 0, 2, f(Yes, false, "ộ")}, - {0x1eda, 0, 0, 2, f(Yes, false, "Ớ")}, - {0x1edb, 0, 0, 2, f(Yes, false, "ớ")}, - {0x1edc, 0, 0, 2, f(Yes, false, "Ờ")}, - {0x1edd, 0, 0, 2, f(Yes, false, "ờ")}, - {0x1ede, 0, 0, 2, f(Yes, false, "Ở")}, - {0x1edf, 0, 0, 2, f(Yes, false, "ở")}, - {0x1ee0, 0, 0, 2, f(Yes, false, "Ỡ")}, - {0x1ee1, 0, 0, 2, f(Yes, false, "ỡ")}, - {0x1ee2, 0, 0, 2, f(Yes, false, "Ợ")}, - {0x1ee3, 0, 0, 2, f(Yes, false, "ợ")}, - {0x1ee4, 0, 0, 1, f(Yes, false, "Ụ")}, - {0x1ee5, 0, 0, 1, f(Yes, false, "ụ")}, - {0x1ee6, 0, 0, 1, f(Yes, false, "Ủ")}, - {0x1ee7, 0, 0, 1, f(Yes, false, "ủ")}, - {0x1ee8, 0, 0, 2, f(Yes, false, "Ứ")}, - {0x1ee9, 0, 0, 2, f(Yes, false, "ứ")}, - {0x1eea, 0, 0, 2, f(Yes, false, "Ừ")}, - {0x1eeb, 0, 0, 2, f(Yes, false, "ừ")}, - {0x1eec, 0, 0, 2, f(Yes, false, "Ử")}, - {0x1eed, 0, 0, 2, f(Yes, false, "ử")}, - {0x1eee, 0, 0, 2, f(Yes, false, "Ữ")}, - {0x1eef, 0, 0, 2, f(Yes, false, "ữ")}, - {0x1ef0, 0, 0, 2, f(Yes, false, "Ự")}, - {0x1ef1, 0, 0, 2, f(Yes, false, "ự")}, - {0x1ef2, 0, 0, 1, f(Yes, false, "Ỳ")}, - {0x1ef3, 0, 0, 1, f(Yes, false, "ỳ")}, - {0x1ef4, 0, 0, 1, f(Yes, false, "Ỵ")}, - {0x1ef5, 0, 0, 1, f(Yes, false, "ỵ")}, - {0x1ef6, 0, 0, 1, f(Yes, false, "Ỷ")}, - {0x1ef7, 0, 0, 1, f(Yes, false, "ỷ")}, - {0x1ef8, 0, 0, 1, f(Yes, false, "Ỹ")}, - {0x1ef9, 0, 0, 1, f(Yes, false, "ỹ")}, - {0x1efa, 0, 0, 0, f(Yes, false, "")}, - {0x1f00, 0, 0, 1, f(Yes, true, "ἀ")}, - {0x1f01, 0, 0, 1, f(Yes, true, "ἁ")}, - {0x1f02, 0, 0, 2, f(Yes, true, "ἂ")}, - {0x1f03, 0, 0, 2, f(Yes, true, "ἃ")}, - {0x1f04, 0, 0, 2, f(Yes, true, "ἄ")}, - {0x1f05, 0, 0, 2, f(Yes, true, "ἅ")}, - {0x1f06, 0, 0, 2, f(Yes, true, "ἆ")}, - {0x1f07, 0, 0, 2, f(Yes, true, "ἇ")}, - {0x1f08, 0, 0, 1, f(Yes, true, "Ἀ")}, - {0x1f09, 0, 0, 1, f(Yes, true, "Ἁ")}, - {0x1f0a, 0, 0, 2, f(Yes, true, "Ἂ")}, - {0x1f0b, 0, 0, 2, f(Yes, true, "Ἃ")}, - {0x1f0c, 0, 0, 2, f(Yes, true, "Ἄ")}, - {0x1f0d, 0, 0, 2, f(Yes, true, "Ἅ")}, - {0x1f0e, 0, 0, 2, f(Yes, true, "Ἆ")}, - {0x1f0f, 0, 0, 2, f(Yes, true, "Ἇ")}, - {0x1f10, 0, 0, 1, f(Yes, true, "ἐ")}, - {0x1f11, 0, 0, 1, f(Yes, true, "ἑ")}, - {0x1f12, 0, 0, 2, f(Yes, false, "ἒ")}, - {0x1f13, 0, 0, 2, f(Yes, false, "ἓ")}, - {0x1f14, 0, 0, 2, f(Yes, false, "ἔ")}, - {0x1f15, 0, 0, 2, f(Yes, false, "ἕ")}, - {0x1f16, 0, 0, 0, f(Yes, false, "")}, - {0x1f18, 0, 0, 1, f(Yes, true, "Ἐ")}, - {0x1f19, 0, 0, 1, f(Yes, true, "Ἑ")}, - {0x1f1a, 0, 0, 2, f(Yes, false, "Ἒ")}, - {0x1f1b, 0, 0, 2, f(Yes, false, "Ἓ")}, - {0x1f1c, 0, 0, 2, f(Yes, false, "Ἔ")}, - {0x1f1d, 0, 0, 2, f(Yes, false, "Ἕ")}, - {0x1f1e, 0, 0, 0, f(Yes, false, "")}, - {0x1f20, 0, 0, 1, f(Yes, true, "ἠ")}, - {0x1f21, 0, 0, 1, f(Yes, true, "ἡ")}, - {0x1f22, 0, 0, 2, f(Yes, true, "ἢ")}, - {0x1f23, 0, 0, 2, f(Yes, true, "ἣ")}, - {0x1f24, 0, 0, 2, f(Yes, true, "ἤ")}, - {0x1f25, 0, 0, 2, f(Yes, true, "ἥ")}, - {0x1f26, 0, 0, 2, f(Yes, true, "ἦ")}, - {0x1f27, 0, 0, 2, f(Yes, true, "ἧ")}, - {0x1f28, 0, 0, 1, f(Yes, true, "Ἠ")}, - {0x1f29, 0, 0, 1, f(Yes, true, "Ἡ")}, - {0x1f2a, 0, 0, 2, f(Yes, true, "Ἢ")}, - {0x1f2b, 0, 0, 2, f(Yes, true, "Ἣ")}, - {0x1f2c, 0, 0, 2, f(Yes, true, "Ἤ")}, - {0x1f2d, 0, 0, 2, f(Yes, true, "Ἥ")}, - {0x1f2e, 0, 0, 2, f(Yes, true, "Ἦ")}, - {0x1f2f, 0, 0, 2, f(Yes, true, "Ἧ")}, - {0x1f30, 0, 0, 1, f(Yes, true, "ἰ")}, - {0x1f31, 0, 0, 1, f(Yes, true, "ἱ")}, - {0x1f32, 0, 0, 2, f(Yes, false, "ἲ")}, - {0x1f33, 0, 0, 2, f(Yes, false, "ἳ")}, - {0x1f34, 0, 0, 2, f(Yes, false, "ἴ")}, - {0x1f35, 0, 0, 2, f(Yes, false, "ἵ")}, - {0x1f36, 0, 0, 2, f(Yes, false, "ἶ")}, - {0x1f37, 0, 0, 2, f(Yes, false, "ἷ")}, - {0x1f38, 0, 0, 1, f(Yes, true, "Ἰ")}, - {0x1f39, 0, 0, 1, f(Yes, true, "Ἱ")}, - {0x1f3a, 0, 0, 2, f(Yes, false, "Ἲ")}, - {0x1f3b, 0, 0, 2, f(Yes, false, "Ἳ")}, - {0x1f3c, 0, 0, 2, f(Yes, false, "Ἴ")}, - {0x1f3d, 0, 0, 2, f(Yes, false, "Ἵ")}, - {0x1f3e, 0, 0, 2, f(Yes, false, "Ἶ")}, - {0x1f3f, 0, 0, 2, f(Yes, false, "Ἷ")}, - {0x1f40, 0, 0, 1, f(Yes, true, "ὀ")}, - {0x1f41, 0, 0, 1, f(Yes, true, "ὁ")}, - {0x1f42, 0, 0, 2, f(Yes, false, "ὂ")}, - {0x1f43, 0, 0, 2, f(Yes, false, "ὃ")}, - {0x1f44, 0, 0, 2, f(Yes, false, "ὄ")}, - {0x1f45, 0, 0, 2, f(Yes, false, "ὅ")}, - {0x1f46, 0, 0, 0, f(Yes, false, "")}, - {0x1f48, 0, 0, 1, f(Yes, true, "Ὀ")}, - {0x1f49, 0, 0, 1, f(Yes, true, "Ὁ")}, - {0x1f4a, 0, 0, 2, f(Yes, false, "Ὂ")}, - {0x1f4b, 0, 0, 2, f(Yes, false, "Ὃ")}, - {0x1f4c, 0, 0, 2, f(Yes, false, "Ὄ")}, - {0x1f4d, 0, 0, 2, f(Yes, false, "Ὅ")}, - {0x1f4e, 0, 0, 0, f(Yes, false, "")}, - {0x1f50, 0, 0, 1, f(Yes, true, "ὐ")}, - {0x1f51, 0, 0, 1, f(Yes, true, "ὑ")}, - {0x1f52, 0, 0, 2, f(Yes, false, "ὒ")}, - {0x1f53, 0, 0, 2, f(Yes, false, "ὓ")}, - {0x1f54, 0, 0, 2, f(Yes, false, "ὔ")}, - {0x1f55, 0, 0, 2, f(Yes, false, "ὕ")}, - {0x1f56, 0, 0, 2, f(Yes, false, "ὖ")}, - {0x1f57, 0, 0, 2, f(Yes, false, "ὗ")}, - {0x1f58, 0, 0, 0, f(Yes, false, "")}, - {0x1f59, 0, 0, 1, f(Yes, true, "Ὑ")}, - {0x1f5a, 0, 0, 0, f(Yes, false, "")}, - {0x1f5b, 0, 0, 2, f(Yes, false, "Ὓ")}, - {0x1f5c, 0, 0, 0, f(Yes, false, "")}, - {0x1f5d, 0, 0, 2, f(Yes, false, "Ὕ")}, - {0x1f5e, 0, 0, 0, f(Yes, false, "")}, - {0x1f5f, 0, 0, 2, f(Yes, false, "Ὗ")}, - {0x1f60, 0, 0, 1, f(Yes, true, "ὠ")}, - {0x1f61, 0, 0, 1, f(Yes, true, "ὡ")}, - {0x1f62, 0, 0, 2, f(Yes, true, "ὢ")}, - {0x1f63, 0, 0, 2, f(Yes, true, "ὣ")}, - {0x1f64, 0, 0, 2, f(Yes, true, "ὤ")}, - {0x1f65, 0, 0, 2, f(Yes, true, "ὥ")}, - {0x1f66, 0, 0, 2, f(Yes, true, "ὦ")}, - {0x1f67, 0, 0, 2, f(Yes, true, "ὧ")}, - {0x1f68, 0, 0, 1, f(Yes, true, "Ὠ")}, - {0x1f69, 0, 0, 1, f(Yes, true, "Ὡ")}, - {0x1f6a, 0, 0, 2, f(Yes, true, "Ὢ")}, - {0x1f6b, 0, 0, 2, f(Yes, true, "Ὣ")}, - {0x1f6c, 0, 0, 2, f(Yes, true, "Ὤ")}, - {0x1f6d, 0, 0, 2, f(Yes, true, "Ὥ")}, - {0x1f6e, 0, 0, 2, f(Yes, true, "Ὦ")}, - {0x1f6f, 0, 0, 2, f(Yes, true, "Ὧ")}, - {0x1f70, 0, 0, 1, f(Yes, true, "ὰ")}, - {0x1f71, 0, 0, 1, f(No, false, "ά")}, - {0x1f72, 0, 0, 1, f(Yes, false, "ὲ")}, - {0x1f73, 0, 0, 1, f(No, false, "έ")}, - {0x1f74, 0, 0, 1, f(Yes, true, "ὴ")}, - {0x1f75, 0, 0, 1, f(No, false, "ή")}, - {0x1f76, 0, 0, 1, f(Yes, false, "ὶ")}, - {0x1f77, 0, 0, 1, f(No, false, "ί")}, - {0x1f78, 0, 0, 1, f(Yes, false, "ὸ")}, - {0x1f79, 0, 0, 1, f(No, false, "ό")}, - {0x1f7a, 0, 0, 1, f(Yes, false, "ὺ")}, - {0x1f7b, 0, 0, 1, f(No, false, "ύ")}, - {0x1f7c, 0, 0, 1, f(Yes, true, "ὼ")}, - {0x1f7d, 0, 0, 1, f(No, false, "ώ")}, - {0x1f7e, 0, 0, 0, f(Yes, false, "")}, - {0x1f80, 0, 0, 2, f(Yes, false, "ᾀ")}, - {0x1f81, 0, 0, 2, f(Yes, false, "ᾁ")}, - {0x1f82, 0, 0, 3, f(Yes, false, "ᾂ")}, - {0x1f83, 0, 0, 3, f(Yes, false, "ᾃ")}, - {0x1f84, 0, 0, 3, f(Yes, false, "ᾄ")}, - {0x1f85, 0, 0, 3, f(Yes, false, "ᾅ")}, - {0x1f86, 0, 0, 3, f(Yes, false, "ᾆ")}, - {0x1f87, 0, 0, 3, f(Yes, false, "ᾇ")}, - {0x1f88, 0, 0, 2, f(Yes, false, "ᾈ")}, - {0x1f89, 0, 0, 2, f(Yes, false, "ᾉ")}, - {0x1f8a, 0, 0, 3, f(Yes, false, "ᾊ")}, - {0x1f8b, 0, 0, 3, f(Yes, false, "ᾋ")}, - {0x1f8c, 0, 0, 3, f(Yes, false, "ᾌ")}, - {0x1f8d, 0, 0, 3, f(Yes, false, "ᾍ")}, - {0x1f8e, 0, 0, 3, f(Yes, false, "ᾎ")}, - {0x1f8f, 0, 0, 3, f(Yes, false, "ᾏ")}, - {0x1f90, 0, 0, 2, f(Yes, false, "ᾐ")}, - {0x1f91, 0, 0, 2, f(Yes, false, "ᾑ")}, - {0x1f92, 0, 0, 3, f(Yes, false, "ᾒ")}, - {0x1f93, 0, 0, 3, f(Yes, false, "ᾓ")}, - {0x1f94, 0, 0, 3, f(Yes, false, "ᾔ")}, - {0x1f95, 0, 0, 3, f(Yes, false, "ᾕ")}, - {0x1f96, 0, 0, 3, f(Yes, false, "ᾖ")}, - {0x1f97, 0, 0, 3, f(Yes, false, "ᾗ")}, - {0x1f98, 0, 0, 2, f(Yes, false, "ᾘ")}, - {0x1f99, 0, 0, 2, f(Yes, false, "ᾙ")}, - {0x1f9a, 0, 0, 3, f(Yes, false, "ᾚ")}, - {0x1f9b, 0, 0, 3, f(Yes, false, "ᾛ")}, - {0x1f9c, 0, 0, 3, f(Yes, false, "ᾜ")}, - {0x1f9d, 0, 0, 3, f(Yes, false, "ᾝ")}, - {0x1f9e, 0, 0, 3, f(Yes, false, "ᾞ")}, - {0x1f9f, 0, 0, 3, f(Yes, false, "ᾟ")}, - {0x1fa0, 0, 0, 2, f(Yes, false, "ᾠ")}, - {0x1fa1, 0, 0, 2, f(Yes, false, "ᾡ")}, - {0x1fa2, 0, 0, 3, f(Yes, false, "ᾢ")}, - {0x1fa3, 0, 0, 3, f(Yes, false, "ᾣ")}, - {0x1fa4, 0, 0, 3, f(Yes, false, "ᾤ")}, - {0x1fa5, 0, 0, 3, f(Yes, false, "ᾥ")}, - {0x1fa6, 0, 0, 3, f(Yes, false, "ᾦ")}, - {0x1fa7, 0, 0, 3, f(Yes, false, "ᾧ")}, - {0x1fa8, 0, 0, 2, f(Yes, false, "ᾨ")}, - {0x1fa9, 0, 0, 2, f(Yes, false, "ᾩ")}, - {0x1faa, 0, 0, 3, f(Yes, false, "ᾪ")}, - {0x1fab, 0, 0, 3, f(Yes, false, "ᾫ")}, - {0x1fac, 0, 0, 3, f(Yes, false, "ᾬ")}, - {0x1fad, 0, 0, 3, f(Yes, false, "ᾭ")}, - {0x1fae, 0, 0, 3, f(Yes, false, "ᾮ")}, - {0x1faf, 0, 0, 3, f(Yes, false, "ᾯ")}, - {0x1fb0, 0, 0, 1, f(Yes, false, "ᾰ")}, - {0x1fb1, 0, 0, 1, f(Yes, false, "ᾱ")}, - {0x1fb2, 0, 0, 2, f(Yes, false, "ᾲ")}, - {0x1fb3, 0, 0, 1, f(Yes, false, "ᾳ")}, - {0x1fb4, 0, 0, 2, f(Yes, false, "ᾴ")}, - {0x1fb5, 0, 0, 0, f(Yes, false, "")}, - {0x1fb6, 0, 0, 1, f(Yes, true, "ᾶ")}, - {0x1fb7, 0, 0, 2, f(Yes, false, "ᾷ")}, - {0x1fb8, 0, 0, 1, f(Yes, false, "Ᾰ")}, - {0x1fb9, 0, 0, 1, f(Yes, false, "Ᾱ")}, - {0x1fba, 0, 0, 1, f(Yes, false, "Ὰ")}, - {0x1fbb, 0, 0, 1, f(No, false, "Ά")}, - {0x1fbc, 0, 0, 1, f(Yes, false, "ᾼ")}, - {0x1fbd, 0, 0, 1, g(Yes, No, false, false, "", " ̓")}, - {0x1fbe, 0, 0, 0, f(No, false, "ι")}, - {0x1fbf, 0, 0, 1, g(Yes, No, true, false, "", " ̓")}, - {0x1fc0, 0, 0, 1, g(Yes, No, false, false, "", " ͂")}, - {0x1fc1, 0, 0, 2, g(Yes, No, false, false, "῁", " ̈͂")}, - {0x1fc2, 0, 0, 2, f(Yes, false, "ῂ")}, - {0x1fc3, 0, 0, 1, f(Yes, false, "ῃ")}, - {0x1fc4, 0, 0, 2, f(Yes, false, "ῄ")}, - {0x1fc5, 0, 0, 0, f(Yes, false, "")}, - {0x1fc6, 0, 0, 1, f(Yes, true, "ῆ")}, - {0x1fc7, 0, 0, 2, f(Yes, false, "ῇ")}, - {0x1fc8, 0, 0, 1, f(Yes, false, "Ὲ")}, - {0x1fc9, 0, 0, 1, f(No, false, "Έ")}, - {0x1fca, 0, 0, 1, f(Yes, false, "Ὴ")}, - {0x1fcb, 0, 0, 1, f(No, false, "Ή")}, - {0x1fcc, 0, 0, 1, f(Yes, false, "ῌ")}, - {0x1fcd, 0, 0, 2, g(Yes, No, false, false, "῍", " ̓̀")}, - {0x1fce, 0, 0, 2, g(Yes, No, false, false, "῎", " ̓́")}, - {0x1fcf, 0, 0, 2, g(Yes, No, false, false, "῏", " ̓͂")}, - {0x1fd0, 0, 0, 1, f(Yes, false, "ῐ")}, - {0x1fd1, 0, 0, 1, f(Yes, false, "ῑ")}, - {0x1fd2, 0, 0, 2, f(Yes, false, "ῒ")}, - {0x1fd3, 0, 0, 2, f(No, false, "ΐ")}, - {0x1fd4, 0, 0, 0, f(Yes, false, "")}, - {0x1fd6, 0, 0, 1, f(Yes, false, "ῖ")}, - {0x1fd7, 0, 0, 2, f(Yes, false, "ῗ")}, - {0x1fd8, 0, 0, 1, f(Yes, false, "Ῐ")}, - {0x1fd9, 0, 0, 1, f(Yes, false, "Ῑ")}, - {0x1fda, 0, 0, 1, f(Yes, false, "Ὶ")}, - {0x1fdb, 0, 0, 1, f(No, false, "Ί")}, - {0x1fdc, 0, 0, 0, f(Yes, false, "")}, - {0x1fdd, 0, 0, 2, g(Yes, No, false, false, "῝", " ̔̀")}, - {0x1fde, 0, 0, 2, g(Yes, No, false, false, "῞", " ̔́")}, - {0x1fdf, 0, 0, 2, g(Yes, No, false, false, "῟", " ̔͂")}, - {0x1fe0, 0, 0, 1, f(Yes, false, "ῠ")}, - {0x1fe1, 0, 0, 1, f(Yes, false, "ῡ")}, - {0x1fe2, 0, 0, 2, f(Yes, false, "ῢ")}, - {0x1fe3, 0, 0, 2, f(No, false, "ΰ")}, - {0x1fe4, 0, 0, 1, f(Yes, false, "ῤ")}, - {0x1fe5, 0, 0, 1, f(Yes, false, "ῥ")}, - {0x1fe6, 0, 0, 1, f(Yes, false, "ῦ")}, - {0x1fe7, 0, 0, 2, f(Yes, false, "ῧ")}, - {0x1fe8, 0, 0, 1, f(Yes, false, "Ῠ")}, - {0x1fe9, 0, 0, 1, f(Yes, false, "Ῡ")}, - {0x1fea, 0, 0, 1, f(Yes, false, "Ὺ")}, - {0x1feb, 0, 0, 1, f(No, false, "Ύ")}, - {0x1fec, 0, 0, 1, f(Yes, false, "Ῥ")}, - {0x1fed, 0, 0, 2, g(Yes, No, false, false, "῭", " ̈̀")}, - {0x1fee, 0, 0, 2, g(No, No, false, false, "΅", " ̈́")}, - {0x1fef, 0, 0, 0, f(No, false, "`")}, - {0x1ff0, 0, 0, 0, f(Yes, false, "")}, - {0x1ff2, 0, 0, 2, f(Yes, false, "ῲ")}, - {0x1ff3, 0, 0, 1, f(Yes, false, "ῳ")}, - {0x1ff4, 0, 0, 2, f(Yes, false, "ῴ")}, - {0x1ff5, 0, 0, 0, f(Yes, false, "")}, - {0x1ff6, 0, 0, 1, f(Yes, true, "ῶ")}, - {0x1ff7, 0, 0, 2, f(Yes, false, "ῷ")}, - {0x1ff8, 0, 0, 1, f(Yes, false, "Ὸ")}, - {0x1ff9, 0, 0, 1, f(No, false, "Ό")}, - {0x1ffa, 0, 0, 1, f(Yes, false, "Ὼ")}, - {0x1ffb, 0, 0, 1, f(No, false, "Ώ")}, - {0x1ffc, 0, 0, 1, f(Yes, false, "ῼ")}, - {0x1ffd, 0, 0, 1, g(No, No, false, false, "´", " ́")}, - {0x1ffe, 0, 0, 1, g(Yes, No, true, false, "", " ̔")}, - {0x1fff, 0, 0, 0, f(Yes, false, "")}, - {0x2000, 0, 0, 0, g(No, No, false, false, "\u2002", " ")}, - {0x2001, 0, 0, 0, g(No, No, false, false, "\u2003", " ")}, - {0x2002, 0, 0, 0, g(Yes, No, false, false, "", " ")}, - {0x200b, 0, 0, 0, f(Yes, false, "")}, - {0x2011, 0, 0, 0, g(Yes, No, false, false, "", "‐")}, - {0x2012, 0, 0, 0, f(Yes, false, "")}, - {0x2017, 0, 0, 1, g(Yes, No, false, false, "", " ̳")}, - {0x2018, 0, 0, 0, f(Yes, false, "")}, - {0x2024, 0, 0, 0, g(Yes, No, false, false, "", ".")}, - {0x2025, 0, 0, 0, g(Yes, No, false, false, "", "..")}, - {0x2026, 0, 0, 0, g(Yes, No, false, false, "", "...")}, - {0x2027, 0, 0, 0, f(Yes, false, "")}, - {0x202f, 0, 0, 0, g(Yes, No, false, false, "", " ")}, - {0x2030, 0, 0, 0, f(Yes, false, "")}, - {0x2033, 0, 0, 0, g(Yes, No, false, false, "", "′′")}, - {0x2034, 0, 0, 0, g(Yes, No, false, false, "", "′′′")}, - {0x2035, 0, 0, 0, f(Yes, false, "")}, - {0x2036, 0, 0, 0, g(Yes, No, false, false, "", "‵‵")}, - {0x2037, 0, 0, 0, g(Yes, No, false, false, "", "‵‵‵")}, - {0x2038, 0, 0, 0, f(Yes, false, "")}, - {0x203c, 0, 0, 0, g(Yes, No, false, false, "", "!!")}, - {0x203d, 0, 0, 0, f(Yes, false, "")}, - {0x203e, 0, 0, 1, g(Yes, No, false, false, "", " ̅")}, - {0x203f, 0, 0, 0, f(Yes, false, "")}, - {0x2047, 0, 0, 0, g(Yes, No, false, false, "", "??")}, - {0x2048, 0, 0, 0, g(Yes, No, false, false, "", "?!")}, - {0x2049, 0, 0, 0, g(Yes, No, false, false, "", "!?")}, - {0x204a, 0, 0, 0, f(Yes, false, "")}, - {0x2057, 0, 0, 0, g(Yes, No, false, false, "", "′′′′")}, - {0x2058, 0, 0, 0, f(Yes, false, "")}, - {0x205f, 0, 0, 0, g(Yes, No, false, false, "", " ")}, - {0x2060, 0, 0, 0, f(Yes, false, "")}, - {0x2070, 0, 0, 0, g(Yes, No, false, false, "", "0")}, - {0x2071, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x2072, 0, 0, 0, f(Yes, false, "")}, - {0x2074, 0, 0, 0, g(Yes, No, false, false, "", "4")}, - {0x2075, 0, 0, 0, g(Yes, No, false, false, "", "5")}, - {0x2076, 0, 0, 0, g(Yes, No, false, false, "", "6")}, - {0x2077, 0, 0, 0, g(Yes, No, false, false, "", "7")}, - {0x2078, 0, 0, 0, g(Yes, No, false, false, "", "8")}, - {0x2079, 0, 0, 0, g(Yes, No, false, false, "", "9")}, - {0x207a, 0, 0, 0, g(Yes, No, false, false, "", "+")}, - {0x207b, 0, 0, 0, g(Yes, No, false, false, "", "−")}, - {0x207c, 0, 0, 0, g(Yes, No, false, false, "", "=")}, - {0x207d, 0, 0, 0, g(Yes, No, false, false, "", "(")}, - {0x207e, 0, 0, 0, g(Yes, No, false, false, "", ")")}, - {0x207f, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0x2080, 0, 0, 0, g(Yes, No, false, false, "", "0")}, - {0x2081, 0, 0, 0, g(Yes, No, false, false, "", "1")}, - {0x2082, 0, 0, 0, g(Yes, No, false, false, "", "2")}, - {0x2083, 0, 0, 0, g(Yes, No, false, false, "", "3")}, - {0x2084, 0, 0, 0, g(Yes, No, false, false, "", "4")}, - {0x2085, 0, 0, 0, g(Yes, No, false, false, "", "5")}, - {0x2086, 0, 0, 0, g(Yes, No, false, false, "", "6")}, - {0x2087, 0, 0, 0, g(Yes, No, false, false, "", "7")}, - {0x2088, 0, 0, 0, g(Yes, No, false, false, "", "8")}, - {0x2089, 0, 0, 0, g(Yes, No, false, false, "", "9")}, - {0x208a, 0, 0, 0, g(Yes, No, false, false, "", "+")}, - {0x208b, 0, 0, 0, g(Yes, No, false, false, "", "−")}, - {0x208c, 0, 0, 0, g(Yes, No, false, false, "", "=")}, - {0x208d, 0, 0, 0, g(Yes, No, false, false, "", "(")}, - {0x208e, 0, 0, 0, g(Yes, No, false, false, "", ")")}, - {0x208f, 0, 0, 0, f(Yes, false, "")}, - {0x2090, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0x2091, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x2092, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0x2093, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x2094, 0, 0, 0, g(Yes, No, false, false, "", "ə")}, - {0x2095, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0x2096, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0x2097, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x2098, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x2099, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0x209a, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0x209b, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0x209c, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0x209d, 0, 0, 0, f(Yes, false, "")}, - {0x20a8, 0, 0, 0, g(Yes, No, false, false, "", "Rs")}, - {0x20a9, 0, 0, 0, f(Yes, false, "")}, - {0x20d0, 230, 1, 1, f(Yes, false, "")}, - {0x20d2, 1, 1, 1, f(Yes, false, "")}, - {0x20d4, 230, 1, 1, f(Yes, false, "")}, - {0x20d8, 1, 1, 1, f(Yes, false, "")}, - {0x20db, 230, 1, 1, f(Yes, false, "")}, - {0x20dd, 0, 0, 0, f(Yes, false, "")}, - {0x20e1, 230, 1, 1, f(Yes, false, "")}, - {0x20e2, 0, 0, 0, f(Yes, false, "")}, - {0x20e5, 1, 1, 1, f(Yes, false, "")}, - {0x20e7, 230, 1, 1, f(Yes, false, "")}, - {0x20e8, 220, 1, 1, f(Yes, false, "")}, - {0x20e9, 230, 1, 1, f(Yes, false, "")}, - {0x20ea, 1, 1, 1, f(Yes, false, "")}, - {0x20ec, 220, 1, 1, f(Yes, false, "")}, - {0x20f0, 230, 1, 1, f(Yes, false, "")}, - {0x20f1, 0, 0, 0, f(Yes, false, "")}, - {0x2100, 0, 0, 0, g(Yes, No, false, false, "", "a/c")}, - {0x2101, 0, 0, 0, g(Yes, No, false, false, "", "a/s")}, - {0x2102, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x2103, 0, 0, 0, g(Yes, No, false, false, "", "°C")}, - {0x2104, 0, 0, 0, f(Yes, false, "")}, - {0x2105, 0, 0, 0, g(Yes, No, false, false, "", "c/o")}, - {0x2106, 0, 0, 0, g(Yes, No, false, false, "", "c/u")}, - {0x2107, 0, 0, 0, g(Yes, No, false, false, "", "Ɛ")}, - {0x2108, 0, 0, 0, f(Yes, false, "")}, - {0x2109, 0, 0, 0, g(Yes, No, false, false, "", "°F")}, - {0x210a, 0, 0, 0, g(Yes, No, false, false, "", "g")}, - {0x210b, 0, 0, 0, g(Yes, No, false, false, "", "H")}, - {0x210e, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0x210f, 0, 0, 0, g(Yes, No, false, false, "", "ħ")}, - {0x2110, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0x2112, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x2113, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x2114, 0, 0, 0, f(Yes, false, "")}, - {0x2115, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0x2116, 0, 0, 0, g(Yes, No, false, false, "", "No")}, - {0x2117, 0, 0, 0, f(Yes, false, "")}, - {0x2119, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0x211a, 0, 0, 0, g(Yes, No, false, false, "", "Q")}, - {0x211b, 0, 0, 0, g(Yes, No, false, false, "", "R")}, - {0x211e, 0, 0, 0, f(Yes, false, "")}, - {0x2120, 0, 0, 0, g(Yes, No, false, false, "", "SM")}, - {0x2121, 0, 0, 0, g(Yes, No, false, false, "", "TEL")}, - {0x2122, 0, 0, 0, g(Yes, No, false, false, "", "TM")}, - {0x2123, 0, 0, 0, f(Yes, false, "")}, - {0x2124, 0, 0, 0, g(Yes, No, false, false, "", "Z")}, - {0x2125, 0, 0, 0, f(Yes, false, "")}, - {0x2126, 0, 0, 0, f(No, false, "Ω")}, - {0x2127, 0, 0, 0, f(Yes, false, "")}, - {0x2128, 0, 0, 0, g(Yes, No, false, false, "", "Z")}, - {0x2129, 0, 0, 0, f(Yes, false, "")}, - {0x212a, 0, 0, 0, f(No, false, "K")}, - {0x212b, 0, 0, 1, f(No, false, "Å")}, - {0x212c, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0x212d, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x212e, 0, 0, 0, f(Yes, false, "")}, - {0x212f, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x2130, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0x2131, 0, 0, 0, g(Yes, No, false, false, "", "F")}, - {0x2132, 0, 0, 0, f(Yes, false, "")}, - {0x2133, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x2134, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0x2135, 0, 0, 0, g(Yes, No, false, false, "", "א")}, - {0x2136, 0, 0, 0, g(Yes, No, false, false, "", "ב")}, - {0x2137, 0, 0, 0, g(Yes, No, false, false, "", "ג")}, - {0x2138, 0, 0, 0, g(Yes, No, false, false, "", "ד")}, - {0x2139, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x213a, 0, 0, 0, f(Yes, false, "")}, - {0x213b, 0, 0, 0, g(Yes, No, false, false, "", "FAX")}, - {0x213c, 0, 0, 0, g(Yes, No, false, false, "", "π")}, - {0x213d, 0, 0, 0, g(Yes, No, false, false, "", "γ")}, - {0x213e, 0, 0, 0, g(Yes, No, false, false, "", "Γ")}, - {0x213f, 0, 0, 0, g(Yes, No, false, false, "", "Π")}, - {0x2140, 0, 0, 0, g(Yes, No, false, false, "", "∑")}, - {0x2141, 0, 0, 0, f(Yes, false, "")}, - {0x2145, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x2146, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x2147, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x2148, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x2149, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x214a, 0, 0, 0, f(Yes, false, "")}, - {0x2150, 0, 0, 0, g(Yes, No, false, false, "", "1⁄7")}, - {0x2151, 0, 0, 0, g(Yes, No, false, false, "", "1⁄9")}, - {0x2152, 0, 0, 0, g(Yes, No, false, false, "", "1⁄10")}, - {0x2153, 0, 0, 0, g(Yes, No, false, false, "", "1⁄3")}, - {0x2154, 0, 0, 0, g(Yes, No, false, false, "", "2⁄3")}, - {0x2155, 0, 0, 0, g(Yes, No, false, false, "", "1⁄5")}, - {0x2156, 0, 0, 0, g(Yes, No, false, false, "", "2⁄5")}, - {0x2157, 0, 0, 0, g(Yes, No, false, false, "", "3⁄5")}, - {0x2158, 0, 0, 0, g(Yes, No, false, false, "", "4⁄5")}, - {0x2159, 0, 0, 0, g(Yes, No, false, false, "", "1⁄6")}, - {0x215a, 0, 0, 0, g(Yes, No, false, false, "", "5⁄6")}, - {0x215b, 0, 0, 0, g(Yes, No, false, false, "", "1⁄8")}, - {0x215c, 0, 0, 0, g(Yes, No, false, false, "", "3⁄8")}, - {0x215d, 0, 0, 0, g(Yes, No, false, false, "", "5⁄8")}, - {0x215e, 0, 0, 0, g(Yes, No, false, false, "", "7⁄8")}, - {0x215f, 0, 0, 0, g(Yes, No, false, false, "", "1⁄")}, - {0x2160, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0x2161, 0, 0, 0, g(Yes, No, false, false, "", "II")}, - {0x2162, 0, 0, 0, g(Yes, No, false, false, "", "III")}, - {0x2163, 0, 0, 0, g(Yes, No, false, false, "", "IV")}, - {0x2164, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x2165, 0, 0, 0, g(Yes, No, false, false, "", "VI")}, - {0x2166, 0, 0, 0, g(Yes, No, false, false, "", "VII")}, - {0x2167, 0, 0, 0, g(Yes, No, false, false, "", "VIII")}, - {0x2168, 0, 0, 0, g(Yes, No, false, false, "", "IX")}, - {0x2169, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0x216a, 0, 0, 0, g(Yes, No, false, false, "", "XI")}, - {0x216b, 0, 0, 0, g(Yes, No, false, false, "", "XII")}, - {0x216c, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x216d, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x216e, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x216f, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x2170, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x2171, 0, 0, 0, g(Yes, No, false, false, "", "ii")}, - {0x2172, 0, 0, 0, g(Yes, No, false, false, "", "iii")}, - {0x2173, 0, 0, 0, g(Yes, No, false, false, "", "iv")}, - {0x2174, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x2175, 0, 0, 0, g(Yes, No, false, false, "", "vi")}, - {0x2176, 0, 0, 0, g(Yes, No, false, false, "", "vii")}, - {0x2177, 0, 0, 0, g(Yes, No, false, false, "", "viii")}, - {0x2178, 0, 0, 0, g(Yes, No, false, false, "", "ix")}, - {0x2179, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x217a, 0, 0, 0, g(Yes, No, false, false, "", "xi")}, - {0x217b, 0, 0, 0, g(Yes, No, false, false, "", "xii")}, - {0x217c, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x217d, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0x217e, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x217f, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x2180, 0, 0, 0, f(Yes, false, "")}, - {0x2189, 0, 0, 0, g(Yes, No, false, false, "", "0⁄3")}, - {0x218a, 0, 0, 0, f(Yes, false, "")}, - {0x2190, 0, 0, 0, f(Yes, true, "")}, - {0x2191, 0, 0, 0, f(Yes, false, "")}, - {0x2192, 0, 0, 0, f(Yes, true, "")}, - {0x2193, 0, 0, 0, f(Yes, false, "")}, - {0x2194, 0, 0, 0, f(Yes, true, "")}, - {0x2195, 0, 0, 0, f(Yes, false, "")}, - {0x219a, 0, 0, 1, f(Yes, false, "↚")}, - {0x219b, 0, 0, 1, f(Yes, false, "↛")}, - {0x219c, 0, 0, 0, f(Yes, false, "")}, - {0x21ae, 0, 0, 1, f(Yes, false, "↮")}, - {0x21af, 0, 0, 0, f(Yes, false, "")}, - {0x21cd, 0, 0, 1, f(Yes, false, "⇍")}, - {0x21ce, 0, 0, 1, f(Yes, false, "⇎")}, - {0x21cf, 0, 0, 1, f(Yes, false, "⇏")}, - {0x21d0, 0, 0, 0, f(Yes, true, "")}, - {0x21d1, 0, 0, 0, f(Yes, false, "")}, - {0x21d2, 0, 0, 0, f(Yes, true, "")}, - {0x21d3, 0, 0, 0, f(Yes, false, "")}, - {0x21d4, 0, 0, 0, f(Yes, true, "")}, - {0x21d5, 0, 0, 0, f(Yes, false, "")}, - {0x2203, 0, 0, 0, f(Yes, true, "")}, - {0x2204, 0, 0, 1, f(Yes, false, "∄")}, - {0x2205, 0, 0, 0, f(Yes, false, "")}, - {0x2208, 0, 0, 0, f(Yes, true, "")}, - {0x2209, 0, 0, 1, f(Yes, false, "∉")}, - {0x220a, 0, 0, 0, f(Yes, false, "")}, - {0x220b, 0, 0, 0, f(Yes, true, "")}, - {0x220c, 0, 0, 1, f(Yes, false, "∌")}, - {0x220d, 0, 0, 0, f(Yes, false, "")}, - {0x2223, 0, 0, 0, f(Yes, true, "")}, - {0x2224, 0, 0, 1, f(Yes, false, "∤")}, - {0x2225, 0, 0, 0, f(Yes, true, "")}, - {0x2226, 0, 0, 1, f(Yes, false, "∦")}, - {0x2227, 0, 0, 0, f(Yes, false, "")}, - {0x222c, 0, 0, 0, g(Yes, No, false, false, "", "∫∫")}, - {0x222d, 0, 0, 0, g(Yes, No, false, false, "", "∫∫∫")}, - {0x222e, 0, 0, 0, f(Yes, false, "")}, - {0x222f, 0, 0, 0, g(Yes, No, false, false, "", "∮∮")}, - {0x2230, 0, 0, 0, g(Yes, No, false, false, "", "∮∮∮")}, - {0x2231, 0, 0, 0, f(Yes, false, "")}, - {0x223c, 0, 0, 0, f(Yes, true, "")}, - {0x223d, 0, 0, 0, f(Yes, false, "")}, - {0x2241, 0, 0, 1, f(Yes, false, "≁")}, - {0x2242, 0, 0, 0, f(Yes, false, "")}, - {0x2243, 0, 0, 0, f(Yes, true, "")}, - {0x2244, 0, 0, 1, f(Yes, false, "≄")}, - {0x2245, 0, 0, 0, f(Yes, true, "")}, - {0x2246, 0, 0, 0, f(Yes, false, "")}, - {0x2247, 0, 0, 1, f(Yes, false, "≇")}, - {0x2248, 0, 0, 0, f(Yes, true, "")}, - {0x2249, 0, 0, 1, f(Yes, false, "≉")}, - {0x224a, 0, 0, 0, f(Yes, false, "")}, - {0x224d, 0, 0, 0, f(Yes, true, "")}, - {0x224e, 0, 0, 0, f(Yes, false, "")}, - {0x2260, 0, 0, 1, f(Yes, false, "≠")}, - {0x2261, 0, 0, 0, f(Yes, true, "")}, - {0x2262, 0, 0, 1, f(Yes, false, "≢")}, - {0x2263, 0, 0, 0, f(Yes, false, "")}, - {0x2264, 0, 0, 0, f(Yes, true, "")}, - {0x2266, 0, 0, 0, f(Yes, false, "")}, - {0x226d, 0, 0, 1, f(Yes, false, "≭")}, - {0x226e, 0, 0, 1, f(Yes, false, "≮")}, - {0x226f, 0, 0, 1, f(Yes, false, "≯")}, - {0x2270, 0, 0, 1, f(Yes, false, "≰")}, - {0x2271, 0, 0, 1, f(Yes, false, "≱")}, - {0x2272, 0, 0, 0, f(Yes, true, "")}, - {0x2274, 0, 0, 1, f(Yes, false, "≴")}, - {0x2275, 0, 0, 1, f(Yes, false, "≵")}, - {0x2276, 0, 0, 0, f(Yes, true, "")}, - {0x2278, 0, 0, 1, f(Yes, false, "≸")}, - {0x2279, 0, 0, 1, f(Yes, false, "≹")}, - {0x227a, 0, 0, 0, f(Yes, true, "")}, - {0x227e, 0, 0, 0, f(Yes, false, "")}, - {0x2280, 0, 0, 1, f(Yes, false, "⊀")}, - {0x2281, 0, 0, 1, f(Yes, false, "⊁")}, - {0x2282, 0, 0, 0, f(Yes, true, "")}, - {0x2284, 0, 0, 1, f(Yes, false, "⊄")}, - {0x2285, 0, 0, 1, f(Yes, false, "⊅")}, - {0x2286, 0, 0, 0, f(Yes, true, "")}, - {0x2288, 0, 0, 1, f(Yes, false, "⊈")}, - {0x2289, 0, 0, 1, f(Yes, false, "⊉")}, - {0x228a, 0, 0, 0, f(Yes, false, "")}, - {0x2291, 0, 0, 0, f(Yes, true, "")}, - {0x2293, 0, 0, 0, f(Yes, false, "")}, - {0x22a2, 0, 0, 0, f(Yes, true, "")}, - {0x22a3, 0, 0, 0, f(Yes, false, "")}, - {0x22a8, 0, 0, 0, f(Yes, true, "")}, - {0x22aa, 0, 0, 0, f(Yes, false, "")}, - {0x22ab, 0, 0, 0, f(Yes, true, "")}, - {0x22ac, 0, 0, 1, f(Yes, false, "⊬")}, - {0x22ad, 0, 0, 1, f(Yes, false, "⊭")}, - {0x22ae, 0, 0, 1, f(Yes, false, "⊮")}, - {0x22af, 0, 0, 1, f(Yes, false, "⊯")}, - {0x22b0, 0, 0, 0, f(Yes, false, "")}, - {0x22b2, 0, 0, 0, f(Yes, true, "")}, - {0x22b6, 0, 0, 0, f(Yes, false, "")}, - {0x22e0, 0, 0, 1, f(Yes, false, "⋠")}, - {0x22e1, 0, 0, 1, f(Yes, false, "⋡")}, - {0x22e2, 0, 0, 1, f(Yes, false, "⋢")}, - {0x22e3, 0, 0, 1, f(Yes, false, "⋣")}, - {0x22e4, 0, 0, 0, f(Yes, false, "")}, - {0x22ea, 0, 0, 1, f(Yes, false, "⋪")}, - {0x22eb, 0, 0, 1, f(Yes, false, "⋫")}, - {0x22ec, 0, 0, 1, f(Yes, false, "⋬")}, - {0x22ed, 0, 0, 1, f(Yes, false, "⋭")}, - {0x22ee, 0, 0, 0, f(Yes, false, "")}, - {0x2329, 0, 0, 0, f(No, false, "〈")}, - {0x232a, 0, 0, 0, f(No, false, "〉")}, - {0x232b, 0, 0, 0, f(Yes, false, "")}, - {0x2460, 0, 0, 0, g(Yes, No, false, false, "", "1")}, - {0x2461, 0, 0, 0, g(Yes, No, false, false, "", "2")}, - {0x2462, 0, 0, 0, g(Yes, No, false, false, "", "3")}, - {0x2463, 0, 0, 0, g(Yes, No, false, false, "", "4")}, - {0x2464, 0, 0, 0, g(Yes, No, false, false, "", "5")}, - {0x2465, 0, 0, 0, g(Yes, No, false, false, "", "6")}, - {0x2466, 0, 0, 0, g(Yes, No, false, false, "", "7")}, - {0x2467, 0, 0, 0, g(Yes, No, false, false, "", "8")}, - {0x2468, 0, 0, 0, g(Yes, No, false, false, "", "9")}, - {0x2469, 0, 0, 0, g(Yes, No, false, false, "", "10")}, - {0x246a, 0, 0, 0, g(Yes, No, false, false, "", "11")}, - {0x246b, 0, 0, 0, g(Yes, No, false, false, "", "12")}, - {0x246c, 0, 0, 0, g(Yes, No, false, false, "", "13")}, - {0x246d, 0, 0, 0, g(Yes, No, false, false, "", "14")}, - {0x246e, 0, 0, 0, g(Yes, No, false, false, "", "15")}, - {0x246f, 0, 0, 0, g(Yes, No, false, false, "", "16")}, - {0x2470, 0, 0, 0, g(Yes, No, false, false, "", "17")}, - {0x2471, 0, 0, 0, g(Yes, No, false, false, "", "18")}, - {0x2472, 0, 0, 0, g(Yes, No, false, false, "", "19")}, - {0x2473, 0, 0, 0, g(Yes, No, false, false, "", "20")}, - {0x2474, 0, 0, 0, g(Yes, No, false, false, "", "(1)")}, - {0x2475, 0, 0, 0, g(Yes, No, false, false, "", "(2)")}, - {0x2476, 0, 0, 0, g(Yes, No, false, false, "", "(3)")}, - {0x2477, 0, 0, 0, g(Yes, No, false, false, "", "(4)")}, - {0x2478, 0, 0, 0, g(Yes, No, false, false, "", "(5)")}, - {0x2479, 0, 0, 0, g(Yes, No, false, false, "", "(6)")}, - {0x247a, 0, 0, 0, g(Yes, No, false, false, "", "(7)")}, - {0x247b, 0, 0, 0, g(Yes, No, false, false, "", "(8)")}, - {0x247c, 0, 0, 0, g(Yes, No, false, false, "", "(9)")}, - {0x247d, 0, 0, 0, g(Yes, No, false, false, "", "(10)")}, - {0x247e, 0, 0, 0, g(Yes, No, false, false, "", "(11)")}, - {0x247f, 0, 0, 0, g(Yes, No, false, false, "", "(12)")}, - {0x2480, 0, 0, 0, g(Yes, No, false, false, "", "(13)")}, - {0x2481, 0, 0, 0, g(Yes, No, false, false, "", "(14)")}, - {0x2482, 0, 0, 0, g(Yes, No, false, false, "", "(15)")}, - {0x2483, 0, 0, 0, g(Yes, No, false, false, "", "(16)")}, - {0x2484, 0, 0, 0, g(Yes, No, false, false, "", "(17)")}, - {0x2485, 0, 0, 0, g(Yes, No, false, false, "", "(18)")}, - {0x2486, 0, 0, 0, g(Yes, No, false, false, "", "(19)")}, - {0x2487, 0, 0, 0, g(Yes, No, false, false, "", "(20)")}, - {0x2488, 0, 0, 0, g(Yes, No, false, false, "", "1.")}, - {0x2489, 0, 0, 0, g(Yes, No, false, false, "", "2.")}, - {0x248a, 0, 0, 0, g(Yes, No, false, false, "", "3.")}, - {0x248b, 0, 0, 0, g(Yes, No, false, false, "", "4.")}, - {0x248c, 0, 0, 0, g(Yes, No, false, false, "", "5.")}, - {0x248d, 0, 0, 0, g(Yes, No, false, false, "", "6.")}, - {0x248e, 0, 0, 0, g(Yes, No, false, false, "", "7.")}, - {0x248f, 0, 0, 0, g(Yes, No, false, false, "", "8.")}, - {0x2490, 0, 0, 0, g(Yes, No, false, false, "", "9.")}, - {0x2491, 0, 0, 0, g(Yes, No, false, false, "", "10.")}, - {0x2492, 0, 0, 0, g(Yes, No, false, false, "", "11.")}, - {0x2493, 0, 0, 0, g(Yes, No, false, false, "", "12.")}, - {0x2494, 0, 0, 0, g(Yes, No, false, false, "", "13.")}, - {0x2495, 0, 0, 0, g(Yes, No, false, false, "", "14.")}, - {0x2496, 0, 0, 0, g(Yes, No, false, false, "", "15.")}, - {0x2497, 0, 0, 0, g(Yes, No, false, false, "", "16.")}, - {0x2498, 0, 0, 0, g(Yes, No, false, false, "", "17.")}, - {0x2499, 0, 0, 0, g(Yes, No, false, false, "", "18.")}, - {0x249a, 0, 0, 0, g(Yes, No, false, false, "", "19.")}, - {0x249b, 0, 0, 0, g(Yes, No, false, false, "", "20.")}, - {0x249c, 0, 0, 0, g(Yes, No, false, false, "", "(a)")}, - {0x249d, 0, 0, 0, g(Yes, No, false, false, "", "(b)")}, - {0x249e, 0, 0, 0, g(Yes, No, false, false, "", "(c)")}, - {0x249f, 0, 0, 0, g(Yes, No, false, false, "", "(d)")}, - {0x24a0, 0, 0, 0, g(Yes, No, false, false, "", "(e)")}, - {0x24a1, 0, 0, 0, g(Yes, No, false, false, "", "(f)")}, - {0x24a2, 0, 0, 0, g(Yes, No, false, false, "", "(g)")}, - {0x24a3, 0, 0, 0, g(Yes, No, false, false, "", "(h)")}, - {0x24a4, 0, 0, 0, g(Yes, No, false, false, "", "(i)")}, - {0x24a5, 0, 0, 0, g(Yes, No, false, false, "", "(j)")}, - {0x24a6, 0, 0, 0, g(Yes, No, false, false, "", "(k)")}, - {0x24a7, 0, 0, 0, g(Yes, No, false, false, "", "(l)")}, - {0x24a8, 0, 0, 0, g(Yes, No, false, false, "", "(m)")}, - {0x24a9, 0, 0, 0, g(Yes, No, false, false, "", "(n)")}, - {0x24aa, 0, 0, 0, g(Yes, No, false, false, "", "(o)")}, - {0x24ab, 0, 0, 0, g(Yes, No, false, false, "", "(p)")}, - {0x24ac, 0, 0, 0, g(Yes, No, false, false, "", "(q)")}, - {0x24ad, 0, 0, 0, g(Yes, No, false, false, "", "(r)")}, - {0x24ae, 0, 0, 0, g(Yes, No, false, false, "", "(s)")}, - {0x24af, 0, 0, 0, g(Yes, No, false, false, "", "(t)")}, - {0x24b0, 0, 0, 0, g(Yes, No, false, false, "", "(u)")}, - {0x24b1, 0, 0, 0, g(Yes, No, false, false, "", "(v)")}, - {0x24b2, 0, 0, 0, g(Yes, No, false, false, "", "(w)")}, - {0x24b3, 0, 0, 0, g(Yes, No, false, false, "", "(x)")}, - {0x24b4, 0, 0, 0, g(Yes, No, false, false, "", "(y)")}, - {0x24b5, 0, 0, 0, g(Yes, No, false, false, "", "(z)")}, - {0x24b6, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0x24b7, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0x24b8, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x24b9, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x24ba, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0x24bb, 0, 0, 0, g(Yes, No, false, false, "", "F")}, - {0x24bc, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0x24bd, 0, 0, 0, g(Yes, No, false, false, "", "H")}, - {0x24be, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0x24bf, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0x24c0, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0x24c1, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x24c2, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x24c3, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0x24c4, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0x24c5, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0x24c6, 0, 0, 0, g(Yes, No, false, false, "", "Q")}, - {0x24c7, 0, 0, 0, g(Yes, No, false, false, "", "R")}, - {0x24c8, 0, 0, 0, g(Yes, No, false, false, "", "S")}, - {0x24c9, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0x24ca, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0x24cb, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x24cc, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0x24cd, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0x24ce, 0, 0, 0, g(Yes, No, false, false, "", "Y")}, - {0x24cf, 0, 0, 0, g(Yes, No, false, false, "", "Z")}, - {0x24d0, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0x24d1, 0, 0, 0, g(Yes, No, false, false, "", "b")}, - {0x24d2, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0x24d3, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x24d4, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x24d5, 0, 0, 0, g(Yes, No, false, false, "", "f")}, - {0x24d6, 0, 0, 0, g(Yes, No, false, false, "", "g")}, - {0x24d7, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0x24d8, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x24d9, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x24da, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0x24db, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x24dc, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x24dd, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0x24de, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0x24df, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0x24e0, 0, 0, 0, g(Yes, No, false, false, "", "q")}, - {0x24e1, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0x24e2, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0x24e3, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0x24e4, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0x24e5, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x24e6, 0, 0, 0, g(Yes, No, false, false, "", "w")}, - {0x24e7, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x24e8, 0, 0, 0, g(Yes, No, false, false, "", "y")}, - {0x24e9, 0, 0, 0, g(Yes, No, false, false, "", "z")}, - {0x24ea, 0, 0, 0, g(Yes, No, false, false, "", "0")}, - {0x24eb, 0, 0, 0, f(Yes, false, "")}, - {0x2a0c, 0, 0, 0, g(Yes, No, false, false, "", "∫∫∫∫")}, - {0x2a0d, 0, 0, 0, f(Yes, false, "")}, - {0x2a74, 0, 0, 0, g(Yes, No, false, false, "", "::=")}, - {0x2a75, 0, 0, 0, g(Yes, No, false, false, "", "==")}, - {0x2a76, 0, 0, 0, g(Yes, No, false, false, "", "===")}, - {0x2a77, 0, 0, 0, f(Yes, false, "")}, - {0x2adc, 0, 0, 1, f(No, false, "⫝̸")}, - {0x2add, 0, 0, 0, f(Yes, false, "")}, - {0x2c7c, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x2c7d, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x2c7e, 0, 0, 0, f(Yes, false, "")}, - {0x2cef, 230, 1, 1, f(Yes, false, "")}, - {0x2cf2, 0, 0, 0, f(Yes, false, "")}, - {0x2d6f, 0, 0, 0, g(Yes, No, false, false, "", "ⵡ")}, - {0x2d70, 0, 0, 0, f(Yes, false, "")}, - {0x2d7f, 9, 1, 1, f(Yes, false, "")}, - {0x2d80, 0, 0, 0, f(Yes, false, "")}, - {0x2de0, 230, 1, 1, f(Yes, false, "")}, - {0x2e00, 0, 0, 0, f(Yes, false, "")}, - {0x2e9f, 0, 0, 0, g(Yes, No, false, false, "", "母")}, - {0x2ea0, 0, 0, 0, f(Yes, false, "")}, - {0x2ef3, 0, 0, 0, g(Yes, No, false, false, "", "龟")}, - {0x2ef4, 0, 0, 0, f(Yes, false, "")}, - {0x2f00, 0, 0, 0, g(Yes, No, false, false, "", "一")}, - {0x2f01, 0, 0, 0, g(Yes, No, false, false, "", "丨")}, - {0x2f02, 0, 0, 0, g(Yes, No, false, false, "", "丶")}, - {0x2f03, 0, 0, 0, g(Yes, No, false, false, "", "丿")}, - {0x2f04, 0, 0, 0, g(Yes, No, false, false, "", "乙")}, - {0x2f05, 0, 0, 0, g(Yes, No, false, false, "", "亅")}, - {0x2f06, 0, 0, 0, g(Yes, No, false, false, "", "二")}, - {0x2f07, 0, 0, 0, g(Yes, No, false, false, "", "亠")}, - {0x2f08, 0, 0, 0, g(Yes, No, false, false, "", "人")}, - {0x2f09, 0, 0, 0, g(Yes, No, false, false, "", "儿")}, - {0x2f0a, 0, 0, 0, g(Yes, No, false, false, "", "入")}, - {0x2f0b, 0, 0, 0, g(Yes, No, false, false, "", "八")}, - {0x2f0c, 0, 0, 0, g(Yes, No, false, false, "", "冂")}, - {0x2f0d, 0, 0, 0, g(Yes, No, false, false, "", "冖")}, - {0x2f0e, 0, 0, 0, g(Yes, No, false, false, "", "冫")}, - {0x2f0f, 0, 0, 0, g(Yes, No, false, false, "", "几")}, - {0x2f10, 0, 0, 0, g(Yes, No, false, false, "", "凵")}, - {0x2f11, 0, 0, 0, g(Yes, No, false, false, "", "刀")}, - {0x2f12, 0, 0, 0, g(Yes, No, false, false, "", "力")}, - {0x2f13, 0, 0, 0, g(Yes, No, false, false, "", "勹")}, - {0x2f14, 0, 0, 0, g(Yes, No, false, false, "", "匕")}, - {0x2f15, 0, 0, 0, g(Yes, No, false, false, "", "匚")}, - {0x2f16, 0, 0, 0, g(Yes, No, false, false, "", "匸")}, - {0x2f17, 0, 0, 0, g(Yes, No, false, false, "", "十")}, - {0x2f18, 0, 0, 0, g(Yes, No, false, false, "", "卜")}, - {0x2f19, 0, 0, 0, g(Yes, No, false, false, "", "卩")}, - {0x2f1a, 0, 0, 0, g(Yes, No, false, false, "", "厂")}, - {0x2f1b, 0, 0, 0, g(Yes, No, false, false, "", "厶")}, - {0x2f1c, 0, 0, 0, g(Yes, No, false, false, "", "又")}, - {0x2f1d, 0, 0, 0, g(Yes, No, false, false, "", "口")}, - {0x2f1e, 0, 0, 0, g(Yes, No, false, false, "", "囗")}, - {0x2f1f, 0, 0, 0, g(Yes, No, false, false, "", "土")}, - {0x2f20, 0, 0, 0, g(Yes, No, false, false, "", "士")}, - {0x2f21, 0, 0, 0, g(Yes, No, false, false, "", "夂")}, - {0x2f22, 0, 0, 0, g(Yes, No, false, false, "", "夊")}, - {0x2f23, 0, 0, 0, g(Yes, No, false, false, "", "夕")}, - {0x2f24, 0, 0, 0, g(Yes, No, false, false, "", "大")}, - {0x2f25, 0, 0, 0, g(Yes, No, false, false, "", "女")}, - {0x2f26, 0, 0, 0, g(Yes, No, false, false, "", "子")}, - {0x2f27, 0, 0, 0, g(Yes, No, false, false, "", "宀")}, - {0x2f28, 0, 0, 0, g(Yes, No, false, false, "", "寸")}, - {0x2f29, 0, 0, 0, g(Yes, No, false, false, "", "小")}, - {0x2f2a, 0, 0, 0, g(Yes, No, false, false, "", "尢")}, - {0x2f2b, 0, 0, 0, g(Yes, No, false, false, "", "尸")}, - {0x2f2c, 0, 0, 0, g(Yes, No, false, false, "", "屮")}, - {0x2f2d, 0, 0, 0, g(Yes, No, false, false, "", "山")}, - {0x2f2e, 0, 0, 0, g(Yes, No, false, false, "", "巛")}, - {0x2f2f, 0, 0, 0, g(Yes, No, false, false, "", "工")}, - {0x2f30, 0, 0, 0, g(Yes, No, false, false, "", "己")}, - {0x2f31, 0, 0, 0, g(Yes, No, false, false, "", "巾")}, - {0x2f32, 0, 0, 0, g(Yes, No, false, false, "", "干")}, - {0x2f33, 0, 0, 0, g(Yes, No, false, false, "", "幺")}, - {0x2f34, 0, 0, 0, g(Yes, No, false, false, "", "广")}, - {0x2f35, 0, 0, 0, g(Yes, No, false, false, "", "廴")}, - {0x2f36, 0, 0, 0, g(Yes, No, false, false, "", "廾")}, - {0x2f37, 0, 0, 0, g(Yes, No, false, false, "", "弋")}, - {0x2f38, 0, 0, 0, g(Yes, No, false, false, "", "弓")}, - {0x2f39, 0, 0, 0, g(Yes, No, false, false, "", "彐")}, - {0x2f3a, 0, 0, 0, g(Yes, No, false, false, "", "彡")}, - {0x2f3b, 0, 0, 0, g(Yes, No, false, false, "", "彳")}, - {0x2f3c, 0, 0, 0, g(Yes, No, false, false, "", "心")}, - {0x2f3d, 0, 0, 0, g(Yes, No, false, false, "", "戈")}, - {0x2f3e, 0, 0, 0, g(Yes, No, false, false, "", "戶")}, - {0x2f3f, 0, 0, 0, g(Yes, No, false, false, "", "手")}, - {0x2f40, 0, 0, 0, g(Yes, No, false, false, "", "支")}, - {0x2f41, 0, 0, 0, g(Yes, No, false, false, "", "攴")}, - {0x2f42, 0, 0, 0, g(Yes, No, false, false, "", "文")}, - {0x2f43, 0, 0, 0, g(Yes, No, false, false, "", "斗")}, - {0x2f44, 0, 0, 0, g(Yes, No, false, false, "", "斤")}, - {0x2f45, 0, 0, 0, g(Yes, No, false, false, "", "方")}, - {0x2f46, 0, 0, 0, g(Yes, No, false, false, "", "无")}, - {0x2f47, 0, 0, 0, g(Yes, No, false, false, "", "日")}, - {0x2f48, 0, 0, 0, g(Yes, No, false, false, "", "曰")}, - {0x2f49, 0, 0, 0, g(Yes, No, false, false, "", "月")}, - {0x2f4a, 0, 0, 0, g(Yes, No, false, false, "", "木")}, - {0x2f4b, 0, 0, 0, g(Yes, No, false, false, "", "欠")}, - {0x2f4c, 0, 0, 0, g(Yes, No, false, false, "", "止")}, - {0x2f4d, 0, 0, 0, g(Yes, No, false, false, "", "歹")}, - {0x2f4e, 0, 0, 0, g(Yes, No, false, false, "", "殳")}, - {0x2f4f, 0, 0, 0, g(Yes, No, false, false, "", "毋")}, - {0x2f50, 0, 0, 0, g(Yes, No, false, false, "", "比")}, - {0x2f51, 0, 0, 0, g(Yes, No, false, false, "", "毛")}, - {0x2f52, 0, 0, 0, g(Yes, No, false, false, "", "氏")}, - {0x2f53, 0, 0, 0, g(Yes, No, false, false, "", "气")}, - {0x2f54, 0, 0, 0, g(Yes, No, false, false, "", "水")}, - {0x2f55, 0, 0, 0, g(Yes, No, false, false, "", "火")}, - {0x2f56, 0, 0, 0, g(Yes, No, false, false, "", "爪")}, - {0x2f57, 0, 0, 0, g(Yes, No, false, false, "", "父")}, - {0x2f58, 0, 0, 0, g(Yes, No, false, false, "", "爻")}, - {0x2f59, 0, 0, 0, g(Yes, No, false, false, "", "爿")}, - {0x2f5a, 0, 0, 0, g(Yes, No, false, false, "", "片")}, - {0x2f5b, 0, 0, 0, g(Yes, No, false, false, "", "牙")}, - {0x2f5c, 0, 0, 0, g(Yes, No, false, false, "", "牛")}, - {0x2f5d, 0, 0, 0, g(Yes, No, false, false, "", "犬")}, - {0x2f5e, 0, 0, 0, g(Yes, No, false, false, "", "玄")}, - {0x2f5f, 0, 0, 0, g(Yes, No, false, false, "", "玉")}, - {0x2f60, 0, 0, 0, g(Yes, No, false, false, "", "瓜")}, - {0x2f61, 0, 0, 0, g(Yes, No, false, false, "", "瓦")}, - {0x2f62, 0, 0, 0, g(Yes, No, false, false, "", "甘")}, - {0x2f63, 0, 0, 0, g(Yes, No, false, false, "", "生")}, - {0x2f64, 0, 0, 0, g(Yes, No, false, false, "", "用")}, - {0x2f65, 0, 0, 0, g(Yes, No, false, false, "", "田")}, - {0x2f66, 0, 0, 0, g(Yes, No, false, false, "", "疋")}, - {0x2f67, 0, 0, 0, g(Yes, No, false, false, "", "疒")}, - {0x2f68, 0, 0, 0, g(Yes, No, false, false, "", "癶")}, - {0x2f69, 0, 0, 0, g(Yes, No, false, false, "", "白")}, - {0x2f6a, 0, 0, 0, g(Yes, No, false, false, "", "皮")}, - {0x2f6b, 0, 0, 0, g(Yes, No, false, false, "", "皿")}, - {0x2f6c, 0, 0, 0, g(Yes, No, false, false, "", "目")}, - {0x2f6d, 0, 0, 0, g(Yes, No, false, false, "", "矛")}, - {0x2f6e, 0, 0, 0, g(Yes, No, false, false, "", "矢")}, - {0x2f6f, 0, 0, 0, g(Yes, No, false, false, "", "石")}, - {0x2f70, 0, 0, 0, g(Yes, No, false, false, "", "示")}, - {0x2f71, 0, 0, 0, g(Yes, No, false, false, "", "禸")}, - {0x2f72, 0, 0, 0, g(Yes, No, false, false, "", "禾")}, - {0x2f73, 0, 0, 0, g(Yes, No, false, false, "", "穴")}, - {0x2f74, 0, 0, 0, g(Yes, No, false, false, "", "立")}, - {0x2f75, 0, 0, 0, g(Yes, No, false, false, "", "竹")}, - {0x2f76, 0, 0, 0, g(Yes, No, false, false, "", "米")}, - {0x2f77, 0, 0, 0, g(Yes, No, false, false, "", "糸")}, - {0x2f78, 0, 0, 0, g(Yes, No, false, false, "", "缶")}, - {0x2f79, 0, 0, 0, g(Yes, No, false, false, "", "网")}, - {0x2f7a, 0, 0, 0, g(Yes, No, false, false, "", "羊")}, - {0x2f7b, 0, 0, 0, g(Yes, No, false, false, "", "羽")}, - {0x2f7c, 0, 0, 0, g(Yes, No, false, false, "", "老")}, - {0x2f7d, 0, 0, 0, g(Yes, No, false, false, "", "而")}, - {0x2f7e, 0, 0, 0, g(Yes, No, false, false, "", "耒")}, - {0x2f7f, 0, 0, 0, g(Yes, No, false, false, "", "耳")}, - {0x2f80, 0, 0, 0, g(Yes, No, false, false, "", "聿")}, - {0x2f81, 0, 0, 0, g(Yes, No, false, false, "", "肉")}, - {0x2f82, 0, 0, 0, g(Yes, No, false, false, "", "臣")}, - {0x2f83, 0, 0, 0, g(Yes, No, false, false, "", "自")}, - {0x2f84, 0, 0, 0, g(Yes, No, false, false, "", "至")}, - {0x2f85, 0, 0, 0, g(Yes, No, false, false, "", "臼")}, - {0x2f86, 0, 0, 0, g(Yes, No, false, false, "", "舌")}, - {0x2f87, 0, 0, 0, g(Yes, No, false, false, "", "舛")}, - {0x2f88, 0, 0, 0, g(Yes, No, false, false, "", "舟")}, - {0x2f89, 0, 0, 0, g(Yes, No, false, false, "", "艮")}, - {0x2f8a, 0, 0, 0, g(Yes, No, false, false, "", "色")}, - {0x2f8b, 0, 0, 0, g(Yes, No, false, false, "", "艸")}, - {0x2f8c, 0, 0, 0, g(Yes, No, false, false, "", "虍")}, - {0x2f8d, 0, 0, 0, g(Yes, No, false, false, "", "虫")}, - {0x2f8e, 0, 0, 0, g(Yes, No, false, false, "", "血")}, - {0x2f8f, 0, 0, 0, g(Yes, No, false, false, "", "行")}, - {0x2f90, 0, 0, 0, g(Yes, No, false, false, "", "衣")}, - {0x2f91, 0, 0, 0, g(Yes, No, false, false, "", "襾")}, - {0x2f92, 0, 0, 0, g(Yes, No, false, false, "", "見")}, - {0x2f93, 0, 0, 0, g(Yes, No, false, false, "", "角")}, - {0x2f94, 0, 0, 0, g(Yes, No, false, false, "", "言")}, - {0x2f95, 0, 0, 0, g(Yes, No, false, false, "", "谷")}, - {0x2f96, 0, 0, 0, g(Yes, No, false, false, "", "豆")}, - {0x2f97, 0, 0, 0, g(Yes, No, false, false, "", "豕")}, - {0x2f98, 0, 0, 0, g(Yes, No, false, false, "", "豸")}, - {0x2f99, 0, 0, 0, g(Yes, No, false, false, "", "貝")}, - {0x2f9a, 0, 0, 0, g(Yes, No, false, false, "", "赤")}, - {0x2f9b, 0, 0, 0, g(Yes, No, false, false, "", "走")}, - {0x2f9c, 0, 0, 0, g(Yes, No, false, false, "", "足")}, - {0x2f9d, 0, 0, 0, g(Yes, No, false, false, "", "身")}, - {0x2f9e, 0, 0, 0, g(Yes, No, false, false, "", "車")}, - {0x2f9f, 0, 0, 0, g(Yes, No, false, false, "", "辛")}, - {0x2fa0, 0, 0, 0, g(Yes, No, false, false, "", "辰")}, - {0x2fa1, 0, 0, 0, g(Yes, No, false, false, "", "辵")}, - {0x2fa2, 0, 0, 0, g(Yes, No, false, false, "", "邑")}, - {0x2fa3, 0, 0, 0, g(Yes, No, false, false, "", "酉")}, - {0x2fa4, 0, 0, 0, g(Yes, No, false, false, "", "釆")}, - {0x2fa5, 0, 0, 0, g(Yes, No, false, false, "", "里")}, - {0x2fa6, 0, 0, 0, g(Yes, No, false, false, "", "金")}, - {0x2fa7, 0, 0, 0, g(Yes, No, false, false, "", "長")}, - {0x2fa8, 0, 0, 0, g(Yes, No, false, false, "", "門")}, - {0x2fa9, 0, 0, 0, g(Yes, No, false, false, "", "阜")}, - {0x2faa, 0, 0, 0, g(Yes, No, false, false, "", "隶")}, - {0x2fab, 0, 0, 0, g(Yes, No, false, false, "", "隹")}, - {0x2fac, 0, 0, 0, g(Yes, No, false, false, "", "雨")}, - {0x2fad, 0, 0, 0, g(Yes, No, false, false, "", "靑")}, - {0x2fae, 0, 0, 0, g(Yes, No, false, false, "", "非")}, - {0x2faf, 0, 0, 0, g(Yes, No, false, false, "", "面")}, - {0x2fb0, 0, 0, 0, g(Yes, No, false, false, "", "革")}, - {0x2fb1, 0, 0, 0, g(Yes, No, false, false, "", "韋")}, - {0x2fb2, 0, 0, 0, g(Yes, No, false, false, "", "韭")}, - {0x2fb3, 0, 0, 0, g(Yes, No, false, false, "", "音")}, - {0x2fb4, 0, 0, 0, g(Yes, No, false, false, "", "頁")}, - {0x2fb5, 0, 0, 0, g(Yes, No, false, false, "", "風")}, - {0x2fb6, 0, 0, 0, g(Yes, No, false, false, "", "飛")}, - {0x2fb7, 0, 0, 0, g(Yes, No, false, false, "", "食")}, - {0x2fb8, 0, 0, 0, g(Yes, No, false, false, "", "首")}, - {0x2fb9, 0, 0, 0, g(Yes, No, false, false, "", "香")}, - {0x2fba, 0, 0, 0, g(Yes, No, false, false, "", "馬")}, - {0x2fbb, 0, 0, 0, g(Yes, No, false, false, "", "骨")}, - {0x2fbc, 0, 0, 0, g(Yes, No, false, false, "", "高")}, - {0x2fbd, 0, 0, 0, g(Yes, No, false, false, "", "髟")}, - {0x2fbe, 0, 0, 0, g(Yes, No, false, false, "", "鬥")}, - {0x2fbf, 0, 0, 0, g(Yes, No, false, false, "", "鬯")}, - {0x2fc0, 0, 0, 0, g(Yes, No, false, false, "", "鬲")}, - {0x2fc1, 0, 0, 0, g(Yes, No, false, false, "", "鬼")}, - {0x2fc2, 0, 0, 0, g(Yes, No, false, false, "", "魚")}, - {0x2fc3, 0, 0, 0, g(Yes, No, false, false, "", "鳥")}, - {0x2fc4, 0, 0, 0, g(Yes, No, false, false, "", "鹵")}, - {0x2fc5, 0, 0, 0, g(Yes, No, false, false, "", "鹿")}, - {0x2fc6, 0, 0, 0, g(Yes, No, false, false, "", "麥")}, - {0x2fc7, 0, 0, 0, g(Yes, No, false, false, "", "麻")}, - {0x2fc8, 0, 0, 0, g(Yes, No, false, false, "", "黃")}, - {0x2fc9, 0, 0, 0, g(Yes, No, false, false, "", "黍")}, - {0x2fca, 0, 0, 0, g(Yes, No, false, false, "", "黑")}, - {0x2fcb, 0, 0, 0, g(Yes, No, false, false, "", "黹")}, - {0x2fcc, 0, 0, 0, g(Yes, No, false, false, "", "黽")}, - {0x2fcd, 0, 0, 0, g(Yes, No, false, false, "", "鼎")}, - {0x2fce, 0, 0, 0, g(Yes, No, false, false, "", "鼓")}, - {0x2fcf, 0, 0, 0, g(Yes, No, false, false, "", "鼠")}, - {0x2fd0, 0, 0, 0, g(Yes, No, false, false, "", "鼻")}, - {0x2fd1, 0, 0, 0, g(Yes, No, false, false, "", "齊")}, - {0x2fd2, 0, 0, 0, g(Yes, No, false, false, "", "齒")}, - {0x2fd3, 0, 0, 0, g(Yes, No, false, false, "", "龍")}, - {0x2fd4, 0, 0, 0, g(Yes, No, false, false, "", "龜")}, - {0x2fd5, 0, 0, 0, g(Yes, No, false, false, "", "龠")}, - {0x2fd6, 0, 0, 0, f(Yes, false, "")}, - {0x3000, 0, 0, 0, g(Yes, No, false, false, "", " ")}, - {0x3001, 0, 0, 0, f(Yes, false, "")}, - {0x302a, 218, 1, 1, f(Yes, false, "")}, - {0x302b, 228, 1, 1, f(Yes, false, "")}, - {0x302c, 232, 1, 1, f(Yes, false, "")}, - {0x302d, 222, 1, 1, f(Yes, false, "")}, - {0x302e, 224, 1, 1, f(Yes, false, "")}, - {0x3030, 0, 0, 0, f(Yes, false, "")}, - {0x3036, 0, 0, 0, g(Yes, No, false, false, "", "〒")}, - {0x3037, 0, 0, 0, f(Yes, false, "")}, - {0x3038, 0, 0, 0, g(Yes, No, false, false, "", "十")}, - {0x3039, 0, 0, 0, g(Yes, No, false, false, "", "卄")}, - {0x303a, 0, 0, 0, g(Yes, No, false, false, "", "卅")}, - {0x303b, 0, 0, 0, f(Yes, false, "")}, - {0x3046, 0, 0, 0, f(Yes, true, "")}, - {0x3047, 0, 0, 0, f(Yes, false, "")}, - {0x304b, 0, 0, 0, f(Yes, true, "")}, - {0x304c, 0, 0, 1, f(Yes, false, "が")}, - {0x304d, 0, 0, 0, f(Yes, true, "")}, - {0x304e, 0, 0, 1, f(Yes, false, "ぎ")}, - {0x304f, 0, 0, 0, f(Yes, true, "")}, - {0x3050, 0, 0, 1, f(Yes, false, "ぐ")}, - {0x3051, 0, 0, 0, f(Yes, true, "")}, - {0x3052, 0, 0, 1, f(Yes, false, "げ")}, - {0x3053, 0, 0, 0, f(Yes, true, "")}, - {0x3054, 0, 0, 1, f(Yes, false, "ご")}, - {0x3055, 0, 0, 0, f(Yes, true, "")}, - {0x3056, 0, 0, 1, f(Yes, false, "ざ")}, - {0x3057, 0, 0, 0, f(Yes, true, "")}, - {0x3058, 0, 0, 1, f(Yes, false, "じ")}, - {0x3059, 0, 0, 0, f(Yes, true, "")}, - {0x305a, 0, 0, 1, f(Yes, false, "ず")}, - {0x305b, 0, 0, 0, f(Yes, true, "")}, - {0x305c, 0, 0, 1, f(Yes, false, "ぜ")}, - {0x305d, 0, 0, 0, f(Yes, true, "")}, - {0x305e, 0, 0, 1, f(Yes, false, "ぞ")}, - {0x305f, 0, 0, 0, f(Yes, true, "")}, - {0x3060, 0, 0, 1, f(Yes, false, "だ")}, - {0x3061, 0, 0, 0, f(Yes, true, "")}, - {0x3062, 0, 0, 1, f(Yes, false, "ぢ")}, - {0x3063, 0, 0, 0, f(Yes, false, "")}, - {0x3064, 0, 0, 0, f(Yes, true, "")}, - {0x3065, 0, 0, 1, f(Yes, false, "づ")}, - {0x3066, 0, 0, 0, f(Yes, true, "")}, - {0x3067, 0, 0, 1, f(Yes, false, "で")}, - {0x3068, 0, 0, 0, f(Yes, true, "")}, - {0x3069, 0, 0, 1, f(Yes, false, "ど")}, - {0x306a, 0, 0, 0, f(Yes, false, "")}, - {0x306f, 0, 0, 0, f(Yes, true, "")}, - {0x3070, 0, 0, 1, f(Yes, false, "ば")}, - {0x3071, 0, 0, 1, f(Yes, false, "ぱ")}, - {0x3072, 0, 0, 0, f(Yes, true, "")}, - {0x3073, 0, 0, 1, f(Yes, false, "び")}, - {0x3074, 0, 0, 1, f(Yes, false, "ぴ")}, - {0x3075, 0, 0, 0, f(Yes, true, "")}, - {0x3076, 0, 0, 1, f(Yes, false, "ぶ")}, - {0x3077, 0, 0, 1, f(Yes, false, "ぷ")}, - {0x3078, 0, 0, 0, f(Yes, true, "")}, - {0x3079, 0, 0, 1, f(Yes, false, "べ")}, - {0x307a, 0, 0, 1, f(Yes, false, "ぺ")}, - {0x307b, 0, 0, 0, f(Yes, true, "")}, - {0x307c, 0, 0, 1, f(Yes, false, "ぼ")}, - {0x307d, 0, 0, 1, f(Yes, false, "ぽ")}, - {0x307e, 0, 0, 0, f(Yes, false, "")}, - {0x3094, 0, 0, 1, f(Yes, false, "ゔ")}, - {0x3095, 0, 0, 0, f(Yes, false, "")}, - {0x3099, 8, 1, 1, f(Maybe, false, "")}, - {0x309b, 0, 0, 1, g(Yes, No, false, false, "", " ゙")}, - {0x309c, 0, 0, 1, g(Yes, No, false, false, "", " ゚")}, - {0x309d, 0, 0, 0, f(Yes, true, "")}, - {0x309e, 0, 0, 1, f(Yes, false, "ゞ")}, - {0x309f, 0, 0, 0, g(Yes, No, false, false, "", "より")}, - {0x30a0, 0, 0, 0, f(Yes, false, "")}, - {0x30a6, 0, 0, 0, f(Yes, true, "")}, - {0x30a7, 0, 0, 0, f(Yes, false, "")}, - {0x30ab, 0, 0, 0, f(Yes, true, "")}, - {0x30ac, 0, 0, 1, f(Yes, false, "ガ")}, - {0x30ad, 0, 0, 0, f(Yes, true, "")}, - {0x30ae, 0, 0, 1, f(Yes, false, "ギ")}, - {0x30af, 0, 0, 0, f(Yes, true, "")}, - {0x30b0, 0, 0, 1, f(Yes, false, "グ")}, - {0x30b1, 0, 0, 0, f(Yes, true, "")}, - {0x30b2, 0, 0, 1, f(Yes, false, "ゲ")}, - {0x30b3, 0, 0, 0, f(Yes, true, "")}, - {0x30b4, 0, 0, 1, f(Yes, false, "ゴ")}, - {0x30b5, 0, 0, 0, f(Yes, true, "")}, - {0x30b6, 0, 0, 1, f(Yes, false, "ザ")}, - {0x30b7, 0, 0, 0, f(Yes, true, "")}, - {0x30b8, 0, 0, 1, f(Yes, false, "ジ")}, - {0x30b9, 0, 0, 0, f(Yes, true, "")}, - {0x30ba, 0, 0, 1, f(Yes, false, "ズ")}, - {0x30bb, 0, 0, 0, f(Yes, true, "")}, - {0x30bc, 0, 0, 1, f(Yes, false, "ゼ")}, - {0x30bd, 0, 0, 0, f(Yes, true, "")}, - {0x30be, 0, 0, 1, f(Yes, false, "ゾ")}, - {0x30bf, 0, 0, 0, f(Yes, true, "")}, - {0x30c0, 0, 0, 1, f(Yes, false, "ダ")}, - {0x30c1, 0, 0, 0, f(Yes, true, "")}, - {0x30c2, 0, 0, 1, f(Yes, false, "ヂ")}, - {0x30c3, 0, 0, 0, f(Yes, false, "")}, - {0x30c4, 0, 0, 0, f(Yes, true, "")}, - {0x30c5, 0, 0, 1, f(Yes, false, "ヅ")}, - {0x30c6, 0, 0, 0, f(Yes, true, "")}, - {0x30c7, 0, 0, 1, f(Yes, false, "デ")}, - {0x30c8, 0, 0, 0, f(Yes, true, "")}, - {0x30c9, 0, 0, 1, f(Yes, false, "ド")}, - {0x30ca, 0, 0, 0, f(Yes, false, "")}, - {0x30cf, 0, 0, 0, f(Yes, true, "")}, - {0x30d0, 0, 0, 1, f(Yes, false, "バ")}, - {0x30d1, 0, 0, 1, f(Yes, false, "パ")}, - {0x30d2, 0, 0, 0, f(Yes, true, "")}, - {0x30d3, 0, 0, 1, f(Yes, false, "ビ")}, - {0x30d4, 0, 0, 1, f(Yes, false, "ピ")}, - {0x30d5, 0, 0, 0, f(Yes, true, "")}, - {0x30d6, 0, 0, 1, f(Yes, false, "ブ")}, - {0x30d7, 0, 0, 1, f(Yes, false, "プ")}, - {0x30d8, 0, 0, 0, f(Yes, true, "")}, - {0x30d9, 0, 0, 1, f(Yes, false, "ベ")}, - {0x30da, 0, 0, 1, f(Yes, false, "ペ")}, - {0x30db, 0, 0, 0, f(Yes, true, "")}, - {0x30dc, 0, 0, 1, f(Yes, false, "ボ")}, - {0x30dd, 0, 0, 1, f(Yes, false, "ポ")}, - {0x30de, 0, 0, 0, f(Yes, false, "")}, - {0x30ef, 0, 0, 0, f(Yes, true, "")}, - {0x30f3, 0, 0, 0, f(Yes, false, "")}, - {0x30f4, 0, 0, 1, f(Yes, false, "ヴ")}, - {0x30f5, 0, 0, 0, f(Yes, false, "")}, - {0x30f7, 0, 0, 1, f(Yes, false, "ヷ")}, - {0x30f8, 0, 0, 1, f(Yes, false, "ヸ")}, - {0x30f9, 0, 0, 1, f(Yes, false, "ヹ")}, - {0x30fa, 0, 0, 1, f(Yes, false, "ヺ")}, - {0x30fb, 0, 0, 0, f(Yes, false, "")}, - {0x30fd, 0, 0, 0, f(Yes, true, "")}, - {0x30fe, 0, 0, 1, f(Yes, false, "ヾ")}, - {0x30ff, 0, 0, 0, g(Yes, No, false, false, "", "コト")}, - {0x3100, 0, 0, 0, f(Yes, false, "")}, - {0x3131, 0, 0, 0, g(Yes, No, false, false, "", "ᄀ")}, - {0x3132, 0, 0, 0, g(Yes, No, false, false, "", "ᄁ")}, - {0x3133, 0, 1, 1, g(Yes, No, false, false, "", "ᆪ")}, - {0x3134, 0, 0, 0, g(Yes, No, false, false, "", "ᄂ")}, - {0x3135, 0, 1, 1, g(Yes, No, false, false, "", "ᆬ")}, - {0x3136, 0, 1, 1, g(Yes, No, false, false, "", "ᆭ")}, - {0x3137, 0, 0, 0, g(Yes, No, false, false, "", "ᄃ")}, - {0x3138, 0, 0, 0, g(Yes, No, false, false, "", "ᄄ")}, - {0x3139, 0, 0, 0, g(Yes, No, false, false, "", "ᄅ")}, - {0x313a, 0, 1, 1, g(Yes, No, false, false, "", "ᆰ")}, - {0x313b, 0, 1, 1, g(Yes, No, false, false, "", "ᆱ")}, - {0x313c, 0, 1, 1, g(Yes, No, false, false, "", "ᆲ")}, - {0x313d, 0, 1, 1, g(Yes, No, false, false, "", "ᆳ")}, - {0x313e, 0, 1, 1, g(Yes, No, false, false, "", "ᆴ")}, - {0x313f, 0, 1, 1, g(Yes, No, false, false, "", "ᆵ")}, - {0x3140, 0, 0, 0, g(Yes, No, false, false, "", "ᄚ")}, - {0x3141, 0, 0, 0, g(Yes, No, false, false, "", "ᄆ")}, - {0x3142, 0, 0, 0, g(Yes, No, false, false, "", "ᄇ")}, - {0x3143, 0, 0, 0, g(Yes, No, false, false, "", "ᄈ")}, - {0x3144, 0, 0, 0, g(Yes, No, false, false, "", "ᄡ")}, - {0x3145, 0, 0, 0, g(Yes, No, false, false, "", "ᄉ")}, - {0x3146, 0, 0, 0, g(Yes, No, false, false, "", "ᄊ")}, - {0x3147, 0, 0, 0, g(Yes, No, false, false, "", "ᄋ")}, - {0x3148, 0, 0, 0, g(Yes, No, false, false, "", "ᄌ")}, - {0x3149, 0, 0, 0, g(Yes, No, false, false, "", "ᄍ")}, - {0x314a, 0, 0, 0, g(Yes, No, false, false, "", "ᄎ")}, - {0x314b, 0, 0, 0, g(Yes, No, false, false, "", "ᄏ")}, - {0x314c, 0, 0, 0, g(Yes, No, false, false, "", "ᄐ")}, - {0x314d, 0, 0, 0, g(Yes, No, false, false, "", "ᄑ")}, - {0x314e, 0, 0, 0, g(Yes, No, false, false, "", "ᄒ")}, - {0x314f, 0, 1, 1, g(Yes, No, false, false, "", "ᅡ")}, - {0x3150, 0, 1, 1, g(Yes, No, false, false, "", "ᅢ")}, - {0x3151, 0, 1, 1, g(Yes, No, false, false, "", "ᅣ")}, - {0x3152, 0, 1, 1, g(Yes, No, false, false, "", "ᅤ")}, - {0x3153, 0, 1, 1, g(Yes, No, false, false, "", "ᅥ")}, - {0x3154, 0, 1, 1, g(Yes, No, false, false, "", "ᅦ")}, - {0x3155, 0, 1, 1, g(Yes, No, false, false, "", "ᅧ")}, - {0x3156, 0, 1, 1, g(Yes, No, false, false, "", "ᅨ")}, - {0x3157, 0, 1, 1, g(Yes, No, false, false, "", "ᅩ")}, - {0x3158, 0, 1, 1, g(Yes, No, false, false, "", "ᅪ")}, - {0x3159, 0, 1, 1, g(Yes, No, false, false, "", "ᅫ")}, - {0x315a, 0, 1, 1, g(Yes, No, false, false, "", "ᅬ")}, - {0x315b, 0, 1, 1, g(Yes, No, false, false, "", "ᅭ")}, - {0x315c, 0, 1, 1, g(Yes, No, false, false, "", "ᅮ")}, - {0x315d, 0, 1, 1, g(Yes, No, false, false, "", "ᅯ")}, - {0x315e, 0, 1, 1, g(Yes, No, false, false, "", "ᅰ")}, - {0x315f, 0, 1, 1, g(Yes, No, false, false, "", "ᅱ")}, - {0x3160, 0, 1, 1, g(Yes, No, false, false, "", "ᅲ")}, - {0x3161, 0, 1, 1, g(Yes, No, false, false, "", "ᅳ")}, - {0x3162, 0, 1, 1, g(Yes, No, false, false, "", "ᅴ")}, - {0x3163, 0, 1, 1, g(Yes, No, false, false, "", "ᅵ")}, - {0x3164, 0, 0, 0, g(Yes, No, false, false, "", "ᅠ")}, - {0x3165, 0, 0, 0, g(Yes, No, false, false, "", "ᄔ")}, - {0x3166, 0, 0, 0, g(Yes, No, false, false, "", "ᄕ")}, - {0x3167, 0, 0, 0, g(Yes, No, false, false, "", "ᇇ")}, - {0x3168, 0, 0, 0, g(Yes, No, false, false, "", "ᇈ")}, - {0x3169, 0, 0, 0, g(Yes, No, false, false, "", "ᇌ")}, - {0x316a, 0, 0, 0, g(Yes, No, false, false, "", "ᇎ")}, - {0x316b, 0, 0, 0, g(Yes, No, false, false, "", "ᇓ")}, - {0x316c, 0, 0, 0, g(Yes, No, false, false, "", "ᇗ")}, - {0x316d, 0, 0, 0, g(Yes, No, false, false, "", "ᇙ")}, - {0x316e, 0, 0, 0, g(Yes, No, false, false, "", "ᄜ")}, - {0x316f, 0, 0, 0, g(Yes, No, false, false, "", "ᇝ")}, - {0x3170, 0, 0, 0, g(Yes, No, false, false, "", "ᇟ")}, - {0x3171, 0, 0, 0, g(Yes, No, false, false, "", "ᄝ")}, - {0x3172, 0, 0, 0, g(Yes, No, false, false, "", "ᄞ")}, - {0x3173, 0, 0, 0, g(Yes, No, false, false, "", "ᄠ")}, - {0x3174, 0, 0, 0, g(Yes, No, false, false, "", "ᄢ")}, - {0x3175, 0, 0, 0, g(Yes, No, false, false, "", "ᄣ")}, - {0x3176, 0, 0, 0, g(Yes, No, false, false, "", "ᄧ")}, - {0x3177, 0, 0, 0, g(Yes, No, false, false, "", "ᄩ")}, - {0x3178, 0, 0, 0, g(Yes, No, false, false, "", "ᄫ")}, - {0x3179, 0, 0, 0, g(Yes, No, false, false, "", "ᄬ")}, - {0x317a, 0, 0, 0, g(Yes, No, false, false, "", "ᄭ")}, - {0x317b, 0, 0, 0, g(Yes, No, false, false, "", "ᄮ")}, - {0x317c, 0, 0, 0, g(Yes, No, false, false, "", "ᄯ")}, - {0x317d, 0, 0, 0, g(Yes, No, false, false, "", "ᄲ")}, - {0x317e, 0, 0, 0, g(Yes, No, false, false, "", "ᄶ")}, - {0x317f, 0, 0, 0, g(Yes, No, false, false, "", "ᅀ")}, - {0x3180, 0, 0, 0, g(Yes, No, false, false, "", "ᅇ")}, - {0x3181, 0, 0, 0, g(Yes, No, false, false, "", "ᅌ")}, - {0x3182, 0, 0, 0, g(Yes, No, false, false, "", "ᇱ")}, - {0x3183, 0, 0, 0, g(Yes, No, false, false, "", "ᇲ")}, - {0x3184, 0, 0, 0, g(Yes, No, false, false, "", "ᅗ")}, - {0x3185, 0, 0, 0, g(Yes, No, false, false, "", "ᅘ")}, - {0x3186, 0, 0, 0, g(Yes, No, false, false, "", "ᅙ")}, - {0x3187, 0, 0, 0, g(Yes, No, false, false, "", "ᆄ")}, - {0x3188, 0, 0, 0, g(Yes, No, false, false, "", "ᆅ")}, - {0x3189, 0, 0, 0, g(Yes, No, false, false, "", "ᆈ")}, - {0x318a, 0, 0, 0, g(Yes, No, false, false, "", "ᆑ")}, - {0x318b, 0, 0, 0, g(Yes, No, false, false, "", "ᆒ")}, - {0x318c, 0, 0, 0, g(Yes, No, false, false, "", "ᆔ")}, - {0x318d, 0, 0, 0, g(Yes, No, false, false, "", "ᆞ")}, - {0x318e, 0, 0, 0, g(Yes, No, false, false, "", "ᆡ")}, - {0x318f, 0, 0, 0, f(Yes, false, "")}, - {0x3192, 0, 0, 0, g(Yes, No, false, false, "", "一")}, - {0x3193, 0, 0, 0, g(Yes, No, false, false, "", "二")}, - {0x3194, 0, 0, 0, g(Yes, No, false, false, "", "三")}, - {0x3195, 0, 0, 0, g(Yes, No, false, false, "", "四")}, - {0x3196, 0, 0, 0, g(Yes, No, false, false, "", "上")}, - {0x3197, 0, 0, 0, g(Yes, No, false, false, "", "中")}, - {0x3198, 0, 0, 0, g(Yes, No, false, false, "", "下")}, - {0x3199, 0, 0, 0, g(Yes, No, false, false, "", "甲")}, - {0x319a, 0, 0, 0, g(Yes, No, false, false, "", "乙")}, - {0x319b, 0, 0, 0, g(Yes, No, false, false, "", "丙")}, - {0x319c, 0, 0, 0, g(Yes, No, false, false, "", "丁")}, - {0x319d, 0, 0, 0, g(Yes, No, false, false, "", "天")}, - {0x319e, 0, 0, 0, g(Yes, No, false, false, "", "地")}, - {0x319f, 0, 0, 0, g(Yes, No, false, false, "", "人")}, - {0x31a0, 0, 0, 0, f(Yes, false, "")}, - {0x3200, 0, 0, 0, g(Yes, No, false, false, "", "(ᄀ)")}, - {0x3201, 0, 0, 0, g(Yes, No, false, false, "", "(ᄂ)")}, - {0x3202, 0, 0, 0, g(Yes, No, false, false, "", "(ᄃ)")}, - {0x3203, 0, 0, 0, g(Yes, No, false, false, "", "(ᄅ)")}, - {0x3204, 0, 0, 0, g(Yes, No, false, false, "", "(ᄆ)")}, - {0x3205, 0, 0, 0, g(Yes, No, false, false, "", "(ᄇ)")}, - {0x3206, 0, 0, 0, g(Yes, No, false, false, "", "(ᄉ)")}, - {0x3207, 0, 0, 0, g(Yes, No, false, false, "", "(ᄋ)")}, - {0x3208, 0, 0, 0, g(Yes, No, false, false, "", "(ᄌ)")}, - {0x3209, 0, 0, 0, g(Yes, No, false, false, "", "(ᄎ)")}, - {0x320a, 0, 0, 0, g(Yes, No, false, false, "", "(ᄏ)")}, - {0x320b, 0, 0, 0, g(Yes, No, false, false, "", "(ᄐ)")}, - {0x320c, 0, 0, 0, g(Yes, No, false, false, "", "(ᄑ)")}, - {0x320d, 0, 0, 0, g(Yes, No, false, false, "", "(ᄒ)")}, - {0x320e, 0, 0, 0, g(Yes, No, false, false, "", "(가)")}, - {0x320f, 0, 0, 0, g(Yes, No, false, false, "", "(나)")}, - {0x3210, 0, 0, 0, g(Yes, No, false, false, "", "(다)")}, - {0x3211, 0, 0, 0, g(Yes, No, false, false, "", "(라)")}, - {0x3212, 0, 0, 0, g(Yes, No, false, false, "", "(마)")}, - {0x3213, 0, 0, 0, g(Yes, No, false, false, "", "(바)")}, - {0x3214, 0, 0, 0, g(Yes, No, false, false, "", "(사)")}, - {0x3215, 0, 0, 0, g(Yes, No, false, false, "", "(아)")}, - {0x3216, 0, 0, 0, g(Yes, No, false, false, "", "(자)")}, - {0x3217, 0, 0, 0, g(Yes, No, false, false, "", "(차)")}, - {0x3218, 0, 0, 0, g(Yes, No, false, false, "", "(카)")}, - {0x3219, 0, 0, 0, g(Yes, No, false, false, "", "(타)")}, - {0x321a, 0, 0, 0, g(Yes, No, false, false, "", "(파)")}, - {0x321b, 0, 0, 0, g(Yes, No, false, false, "", "(하)")}, - {0x321c, 0, 0, 0, g(Yes, No, false, false, "", "(주)")}, - {0x321d, 0, 0, 0, g(Yes, No, false, false, "", "(오전)")}, - {0x321e, 0, 0, 0, g(Yes, No, false, false, "", "(오후)")}, - {0x321f, 0, 0, 0, f(Yes, false, "")}, - {0x3220, 0, 0, 0, g(Yes, No, false, false, "", "(一)")}, - {0x3221, 0, 0, 0, g(Yes, No, false, false, "", "(二)")}, - {0x3222, 0, 0, 0, g(Yes, No, false, false, "", "(三)")}, - {0x3223, 0, 0, 0, g(Yes, No, false, false, "", "(四)")}, - {0x3224, 0, 0, 0, g(Yes, No, false, false, "", "(五)")}, - {0x3225, 0, 0, 0, g(Yes, No, false, false, "", "(六)")}, - {0x3226, 0, 0, 0, g(Yes, No, false, false, "", "(七)")}, - {0x3227, 0, 0, 0, g(Yes, No, false, false, "", "(八)")}, - {0x3228, 0, 0, 0, g(Yes, No, false, false, "", "(九)")}, - {0x3229, 0, 0, 0, g(Yes, No, false, false, "", "(十)")}, - {0x322a, 0, 0, 0, g(Yes, No, false, false, "", "(月)")}, - {0x322b, 0, 0, 0, g(Yes, No, false, false, "", "(火)")}, - {0x322c, 0, 0, 0, g(Yes, No, false, false, "", "(水)")}, - {0x322d, 0, 0, 0, g(Yes, No, false, false, "", "(木)")}, - {0x322e, 0, 0, 0, g(Yes, No, false, false, "", "(金)")}, - {0x322f, 0, 0, 0, g(Yes, No, false, false, "", "(土)")}, - {0x3230, 0, 0, 0, g(Yes, No, false, false, "", "(日)")}, - {0x3231, 0, 0, 0, g(Yes, No, false, false, "", "(株)")}, - {0x3232, 0, 0, 0, g(Yes, No, false, false, "", "(有)")}, - {0x3233, 0, 0, 0, g(Yes, No, false, false, "", "(社)")}, - {0x3234, 0, 0, 0, g(Yes, No, false, false, "", "(名)")}, - {0x3235, 0, 0, 0, g(Yes, No, false, false, "", "(特)")}, - {0x3236, 0, 0, 0, g(Yes, No, false, false, "", "(財)")}, - {0x3237, 0, 0, 0, g(Yes, No, false, false, "", "(祝)")}, - {0x3238, 0, 0, 0, g(Yes, No, false, false, "", "(労)")}, - {0x3239, 0, 0, 0, g(Yes, No, false, false, "", "(代)")}, - {0x323a, 0, 0, 0, g(Yes, No, false, false, "", "(呼)")}, - {0x323b, 0, 0, 0, g(Yes, No, false, false, "", "(学)")}, - {0x323c, 0, 0, 0, g(Yes, No, false, false, "", "(監)")}, - {0x323d, 0, 0, 0, g(Yes, No, false, false, "", "(企)")}, - {0x323e, 0, 0, 0, g(Yes, No, false, false, "", "(資)")}, - {0x323f, 0, 0, 0, g(Yes, No, false, false, "", "(協)")}, - {0x3240, 0, 0, 0, g(Yes, No, false, false, "", "(祭)")}, - {0x3241, 0, 0, 0, g(Yes, No, false, false, "", "(休)")}, - {0x3242, 0, 0, 0, g(Yes, No, false, false, "", "(自)")}, - {0x3243, 0, 0, 0, g(Yes, No, false, false, "", "(至)")}, - {0x3244, 0, 0, 0, g(Yes, No, false, false, "", "問")}, - {0x3245, 0, 0, 0, g(Yes, No, false, false, "", "幼")}, - {0x3246, 0, 0, 0, g(Yes, No, false, false, "", "文")}, - {0x3247, 0, 0, 0, g(Yes, No, false, false, "", "箏")}, - {0x3248, 0, 0, 0, f(Yes, false, "")}, - {0x3250, 0, 0, 0, g(Yes, No, false, false, "", "PTE")}, - {0x3251, 0, 0, 0, g(Yes, No, false, false, "", "21")}, - {0x3252, 0, 0, 0, g(Yes, No, false, false, "", "22")}, - {0x3253, 0, 0, 0, g(Yes, No, false, false, "", "23")}, - {0x3254, 0, 0, 0, g(Yes, No, false, false, "", "24")}, - {0x3255, 0, 0, 0, g(Yes, No, false, false, "", "25")}, - {0x3256, 0, 0, 0, g(Yes, No, false, false, "", "26")}, - {0x3257, 0, 0, 0, g(Yes, No, false, false, "", "27")}, - {0x3258, 0, 0, 0, g(Yes, No, false, false, "", "28")}, - {0x3259, 0, 0, 0, g(Yes, No, false, false, "", "29")}, - {0x325a, 0, 0, 0, g(Yes, No, false, false, "", "30")}, - {0x325b, 0, 0, 0, g(Yes, No, false, false, "", "31")}, - {0x325c, 0, 0, 0, g(Yes, No, false, false, "", "32")}, - {0x325d, 0, 0, 0, g(Yes, No, false, false, "", "33")}, - {0x325e, 0, 0, 0, g(Yes, No, false, false, "", "34")}, - {0x325f, 0, 0, 0, g(Yes, No, false, false, "", "35")}, - {0x3260, 0, 0, 0, g(Yes, No, false, false, "", "ᄀ")}, - {0x3261, 0, 0, 0, g(Yes, No, false, false, "", "ᄂ")}, - {0x3262, 0, 0, 0, g(Yes, No, false, false, "", "ᄃ")}, - {0x3263, 0, 0, 0, g(Yes, No, false, false, "", "ᄅ")}, - {0x3264, 0, 0, 0, g(Yes, No, false, false, "", "ᄆ")}, - {0x3265, 0, 0, 0, g(Yes, No, false, false, "", "ᄇ")}, - {0x3266, 0, 0, 0, g(Yes, No, false, false, "", "ᄉ")}, - {0x3267, 0, 0, 0, g(Yes, No, false, false, "", "ᄋ")}, - {0x3268, 0, 0, 0, g(Yes, No, false, false, "", "ᄌ")}, - {0x3269, 0, 0, 0, g(Yes, No, false, false, "", "ᄎ")}, - {0x326a, 0, 0, 0, g(Yes, No, false, false, "", "ᄏ")}, - {0x326b, 0, 0, 0, g(Yes, No, false, false, "", "ᄐ")}, - {0x326c, 0, 0, 0, g(Yes, No, false, false, "", "ᄑ")}, - {0x326d, 0, 0, 0, g(Yes, No, false, false, "", "ᄒ")}, - {0x326e, 0, 0, 1, g(Yes, No, false, false, "", "가")}, - {0x326f, 0, 0, 1, g(Yes, No, false, false, "", "나")}, - {0x3270, 0, 0, 1, g(Yes, No, false, false, "", "다")}, - {0x3271, 0, 0, 1, g(Yes, No, false, false, "", "라")}, - {0x3272, 0, 0, 1, g(Yes, No, false, false, "", "마")}, - {0x3273, 0, 0, 1, g(Yes, No, false, false, "", "바")}, - {0x3274, 0, 0, 1, g(Yes, No, false, false, "", "사")}, - {0x3275, 0, 0, 1, g(Yes, No, false, false, "", "아")}, - {0x3276, 0, 0, 1, g(Yes, No, false, false, "", "자")}, - {0x3277, 0, 0, 1, g(Yes, No, false, false, "", "차")}, - {0x3278, 0, 0, 1, g(Yes, No, false, false, "", "카")}, - {0x3279, 0, 0, 1, g(Yes, No, false, false, "", "타")}, - {0x327a, 0, 0, 1, g(Yes, No, false, false, "", "파")}, - {0x327b, 0, 0, 1, g(Yes, No, false, false, "", "하")}, - {0x327c, 0, 0, 1, g(Yes, No, false, false, "", "참고")}, - {0x327d, 0, 0, 1, g(Yes, No, false, false, "", "주의")}, - {0x327e, 0, 0, 1, g(Yes, No, false, false, "", "우")}, - {0x327f, 0, 0, 0, f(Yes, false, "")}, - {0x3280, 0, 0, 0, g(Yes, No, false, false, "", "一")}, - {0x3281, 0, 0, 0, g(Yes, No, false, false, "", "二")}, - {0x3282, 0, 0, 0, g(Yes, No, false, false, "", "三")}, - {0x3283, 0, 0, 0, g(Yes, No, false, false, "", "四")}, - {0x3284, 0, 0, 0, g(Yes, No, false, false, "", "五")}, - {0x3285, 0, 0, 0, g(Yes, No, false, false, "", "六")}, - {0x3286, 0, 0, 0, g(Yes, No, false, false, "", "七")}, - {0x3287, 0, 0, 0, g(Yes, No, false, false, "", "八")}, - {0x3288, 0, 0, 0, g(Yes, No, false, false, "", "九")}, - {0x3289, 0, 0, 0, g(Yes, No, false, false, "", "十")}, - {0x328a, 0, 0, 0, g(Yes, No, false, false, "", "月")}, - {0x328b, 0, 0, 0, g(Yes, No, false, false, "", "火")}, - {0x328c, 0, 0, 0, g(Yes, No, false, false, "", "水")}, - {0x328d, 0, 0, 0, g(Yes, No, false, false, "", "木")}, - {0x328e, 0, 0, 0, g(Yes, No, false, false, "", "金")}, - {0x328f, 0, 0, 0, g(Yes, No, false, false, "", "土")}, - {0x3290, 0, 0, 0, g(Yes, No, false, false, "", "日")}, - {0x3291, 0, 0, 0, g(Yes, No, false, false, "", "株")}, - {0x3292, 0, 0, 0, g(Yes, No, false, false, "", "有")}, - {0x3293, 0, 0, 0, g(Yes, No, false, false, "", "社")}, - {0x3294, 0, 0, 0, g(Yes, No, false, false, "", "名")}, - {0x3295, 0, 0, 0, g(Yes, No, false, false, "", "特")}, - {0x3296, 0, 0, 0, g(Yes, No, false, false, "", "財")}, - {0x3297, 0, 0, 0, g(Yes, No, false, false, "", "祝")}, - {0x3298, 0, 0, 0, g(Yes, No, false, false, "", "労")}, - {0x3299, 0, 0, 0, g(Yes, No, false, false, "", "秘")}, - {0x329a, 0, 0, 0, g(Yes, No, false, false, "", "男")}, - {0x329b, 0, 0, 0, g(Yes, No, false, false, "", "女")}, - {0x329c, 0, 0, 0, g(Yes, No, false, false, "", "適")}, - {0x329d, 0, 0, 0, g(Yes, No, false, false, "", "優")}, - {0x329e, 0, 0, 0, g(Yes, No, false, false, "", "印")}, - {0x329f, 0, 0, 0, g(Yes, No, false, false, "", "注")}, - {0x32a0, 0, 0, 0, g(Yes, No, false, false, "", "項")}, - {0x32a1, 0, 0, 0, g(Yes, No, false, false, "", "休")}, - {0x32a2, 0, 0, 0, g(Yes, No, false, false, "", "写")}, - {0x32a3, 0, 0, 0, g(Yes, No, false, false, "", "正")}, - {0x32a4, 0, 0, 0, g(Yes, No, false, false, "", "上")}, - {0x32a5, 0, 0, 0, g(Yes, No, false, false, "", "中")}, - {0x32a6, 0, 0, 0, g(Yes, No, false, false, "", "下")}, - {0x32a7, 0, 0, 0, g(Yes, No, false, false, "", "左")}, - {0x32a8, 0, 0, 0, g(Yes, No, false, false, "", "右")}, - {0x32a9, 0, 0, 0, g(Yes, No, false, false, "", "医")}, - {0x32aa, 0, 0, 0, g(Yes, No, false, false, "", "宗")}, - {0x32ab, 0, 0, 0, g(Yes, No, false, false, "", "学")}, - {0x32ac, 0, 0, 0, g(Yes, No, false, false, "", "監")}, - {0x32ad, 0, 0, 0, g(Yes, No, false, false, "", "企")}, - {0x32ae, 0, 0, 0, g(Yes, No, false, false, "", "資")}, - {0x32af, 0, 0, 0, g(Yes, No, false, false, "", "協")}, - {0x32b0, 0, 0, 0, g(Yes, No, false, false, "", "夜")}, - {0x32b1, 0, 0, 0, g(Yes, No, false, false, "", "36")}, - {0x32b2, 0, 0, 0, g(Yes, No, false, false, "", "37")}, - {0x32b3, 0, 0, 0, g(Yes, No, false, false, "", "38")}, - {0x32b4, 0, 0, 0, g(Yes, No, false, false, "", "39")}, - {0x32b5, 0, 0, 0, g(Yes, No, false, false, "", "40")}, - {0x32b6, 0, 0, 0, g(Yes, No, false, false, "", "41")}, - {0x32b7, 0, 0, 0, g(Yes, No, false, false, "", "42")}, - {0x32b8, 0, 0, 0, g(Yes, No, false, false, "", "43")}, - {0x32b9, 0, 0, 0, g(Yes, No, false, false, "", "44")}, - {0x32ba, 0, 0, 0, g(Yes, No, false, false, "", "45")}, - {0x32bb, 0, 0, 0, g(Yes, No, false, false, "", "46")}, - {0x32bc, 0, 0, 0, g(Yes, No, false, false, "", "47")}, - {0x32bd, 0, 0, 0, g(Yes, No, false, false, "", "48")}, - {0x32be, 0, 0, 0, g(Yes, No, false, false, "", "49")}, - {0x32bf, 0, 0, 0, g(Yes, No, false, false, "", "50")}, - {0x32c0, 0, 0, 0, g(Yes, No, false, false, "", "1月")}, - {0x32c1, 0, 0, 0, g(Yes, No, false, false, "", "2月")}, - {0x32c2, 0, 0, 0, g(Yes, No, false, false, "", "3月")}, - {0x32c3, 0, 0, 0, g(Yes, No, false, false, "", "4月")}, - {0x32c4, 0, 0, 0, g(Yes, No, false, false, "", "5月")}, - {0x32c5, 0, 0, 0, g(Yes, No, false, false, "", "6月")}, - {0x32c6, 0, 0, 0, g(Yes, No, false, false, "", "7月")}, - {0x32c7, 0, 0, 0, g(Yes, No, false, false, "", "8月")}, - {0x32c8, 0, 0, 0, g(Yes, No, false, false, "", "9月")}, - {0x32c9, 0, 0, 0, g(Yes, No, false, false, "", "10月")}, - {0x32ca, 0, 0, 0, g(Yes, No, false, false, "", "11月")}, - {0x32cb, 0, 0, 0, g(Yes, No, false, false, "", "12月")}, - {0x32cc, 0, 0, 0, g(Yes, No, false, false, "", "Hg")}, - {0x32cd, 0, 0, 0, g(Yes, No, false, false, "", "erg")}, - {0x32ce, 0, 0, 0, g(Yes, No, false, false, "", "eV")}, - {0x32cf, 0, 0, 0, g(Yes, No, false, false, "", "LTD")}, - {0x32d0, 0, 0, 0, g(Yes, No, false, false, "", "ア")}, - {0x32d1, 0, 0, 0, g(Yes, No, false, false, "", "イ")}, - {0x32d2, 0, 0, 0, g(Yes, No, false, false, "", "ウ")}, - {0x32d3, 0, 0, 0, g(Yes, No, false, false, "", "エ")}, - {0x32d4, 0, 0, 0, g(Yes, No, false, false, "", "オ")}, - {0x32d5, 0, 0, 0, g(Yes, No, false, false, "", "カ")}, - {0x32d6, 0, 0, 0, g(Yes, No, false, false, "", "キ")}, - {0x32d7, 0, 0, 0, g(Yes, No, false, false, "", "ク")}, - {0x32d8, 0, 0, 0, g(Yes, No, false, false, "", "ケ")}, - {0x32d9, 0, 0, 0, g(Yes, No, false, false, "", "コ")}, - {0x32da, 0, 0, 0, g(Yes, No, false, false, "", "サ")}, - {0x32db, 0, 0, 0, g(Yes, No, false, false, "", "シ")}, - {0x32dc, 0, 0, 0, g(Yes, No, false, false, "", "ス")}, - {0x32dd, 0, 0, 0, g(Yes, No, false, false, "", "セ")}, - {0x32de, 0, 0, 0, g(Yes, No, false, false, "", "ソ")}, - {0x32df, 0, 0, 0, g(Yes, No, false, false, "", "タ")}, - {0x32e0, 0, 0, 0, g(Yes, No, false, false, "", "チ")}, - {0x32e1, 0, 0, 0, g(Yes, No, false, false, "", "ツ")}, - {0x32e2, 0, 0, 0, g(Yes, No, false, false, "", "テ")}, - {0x32e3, 0, 0, 0, g(Yes, No, false, false, "", "ト")}, - {0x32e4, 0, 0, 0, g(Yes, No, false, false, "", "ナ")}, - {0x32e5, 0, 0, 0, g(Yes, No, false, false, "", "ニ")}, - {0x32e6, 0, 0, 0, g(Yes, No, false, false, "", "ヌ")}, - {0x32e7, 0, 0, 0, g(Yes, No, false, false, "", "ネ")}, - {0x32e8, 0, 0, 0, g(Yes, No, false, false, "", "ノ")}, - {0x32e9, 0, 0, 0, g(Yes, No, false, false, "", "ハ")}, - {0x32ea, 0, 0, 0, g(Yes, No, false, false, "", "ヒ")}, - {0x32eb, 0, 0, 0, g(Yes, No, false, false, "", "フ")}, - {0x32ec, 0, 0, 0, g(Yes, No, false, false, "", "ヘ")}, - {0x32ed, 0, 0, 0, g(Yes, No, false, false, "", "ホ")}, - {0x32ee, 0, 0, 0, g(Yes, No, false, false, "", "マ")}, - {0x32ef, 0, 0, 0, g(Yes, No, false, false, "", "ミ")}, - {0x32f0, 0, 0, 0, g(Yes, No, false, false, "", "ム")}, - {0x32f1, 0, 0, 0, g(Yes, No, false, false, "", "メ")}, - {0x32f2, 0, 0, 0, g(Yes, No, false, false, "", "モ")}, - {0x32f3, 0, 0, 0, g(Yes, No, false, false, "", "ヤ")}, - {0x32f4, 0, 0, 0, g(Yes, No, false, false, "", "ユ")}, - {0x32f5, 0, 0, 0, g(Yes, No, false, false, "", "ヨ")}, - {0x32f6, 0, 0, 0, g(Yes, No, false, false, "", "ラ")}, - {0x32f7, 0, 0, 0, g(Yes, No, false, false, "", "リ")}, - {0x32f8, 0, 0, 0, g(Yes, No, false, false, "", "ル")}, - {0x32f9, 0, 0, 0, g(Yes, No, false, false, "", "レ")}, - {0x32fa, 0, 0, 0, g(Yes, No, false, false, "", "ロ")}, - {0x32fb, 0, 0, 0, g(Yes, No, false, false, "", "ワ")}, - {0x32fc, 0, 0, 0, g(Yes, No, false, false, "", "ヰ")}, - {0x32fd, 0, 0, 0, g(Yes, No, false, false, "", "ヱ")}, - {0x32fe, 0, 0, 0, g(Yes, No, false, false, "", "ヲ")}, - {0x32ff, 0, 0, 0, f(Yes, false, "")}, - {0x3300, 0, 0, 0, g(Yes, No, false, false, "", "アパート")}, - {0x3301, 0, 0, 0, g(Yes, No, false, false, "", "アルファ")}, - {0x3302, 0, 0, 0, g(Yes, No, false, false, "", "アンペア")}, - {0x3303, 0, 0, 0, g(Yes, No, false, false, "", "アール")}, - {0x3304, 0, 0, 1, g(Yes, No, false, false, "", "イニング")}, - {0x3305, 0, 0, 0, g(Yes, No, false, false, "", "インチ")}, - {0x3306, 0, 0, 0, g(Yes, No, false, false, "", "ウォン")}, - {0x3307, 0, 0, 1, g(Yes, No, false, false, "", "エスクード")}, - {0x3308, 0, 0, 0, g(Yes, No, false, false, "", "エーカー")}, - {0x3309, 0, 0, 0, g(Yes, No, false, false, "", "オンス")}, - {0x330a, 0, 0, 0, g(Yes, No, false, false, "", "オーム")}, - {0x330b, 0, 0, 0, g(Yes, No, false, false, "", "カイリ")}, - {0x330c, 0, 0, 0, g(Yes, No, false, false, "", "カラット")}, - {0x330d, 0, 0, 0, g(Yes, No, false, false, "", "カロリー")}, - {0x330e, 0, 0, 0, g(Yes, No, false, false, "", "ガロン")}, - {0x330f, 0, 0, 0, g(Yes, No, false, false, "", "ガンマ")}, - {0x3310, 0, 0, 1, g(Yes, No, false, false, "", "ギガ")}, - {0x3311, 0, 0, 0, g(Yes, No, false, false, "", "ギニー")}, - {0x3312, 0, 0, 0, g(Yes, No, false, false, "", "キュリー")}, - {0x3313, 0, 0, 0, g(Yes, No, false, false, "", "ギルダー")}, - {0x3314, 0, 0, 0, g(Yes, No, false, false, "", "キロ")}, - {0x3315, 0, 0, 0, g(Yes, No, false, false, "", "キログラム")}, - {0x3316, 0, 0, 0, g(Yes, No, false, false, "", "キロメートル")}, - {0x3317, 0, 0, 0, g(Yes, No, false, false, "", "キロワット")}, - {0x3318, 0, 0, 0, g(Yes, No, false, false, "", "グラム")}, - {0x3319, 0, 0, 0, g(Yes, No, false, false, "", "グラムトン")}, - {0x331a, 0, 0, 0, g(Yes, No, false, false, "", "クルゼイロ")}, - {0x331b, 0, 0, 0, g(Yes, No, false, false, "", "クローネ")}, - {0x331c, 0, 0, 0, g(Yes, No, false, false, "", "ケース")}, - {0x331d, 0, 0, 0, g(Yes, No, false, false, "", "コルナ")}, - {0x331e, 0, 0, 1, g(Yes, No, false, false, "", "コーポ")}, - {0x331f, 0, 0, 0, g(Yes, No, false, false, "", "サイクル")}, - {0x3320, 0, 0, 0, g(Yes, No, false, false, "", "サンチーム")}, - {0x3321, 0, 0, 1, g(Yes, No, false, false, "", "シリング")}, - {0x3322, 0, 0, 0, g(Yes, No, false, false, "", "センチ")}, - {0x3323, 0, 0, 0, g(Yes, No, false, false, "", "セント")}, - {0x3324, 0, 0, 0, g(Yes, No, false, false, "", "ダース")}, - {0x3325, 0, 0, 0, g(Yes, No, false, false, "", "デシ")}, - {0x3326, 0, 0, 0, g(Yes, No, false, false, "", "ドル")}, - {0x3327, 0, 0, 0, g(Yes, No, false, false, "", "トン")}, - {0x3328, 0, 0, 0, g(Yes, No, false, false, "", "ナノ")}, - {0x3329, 0, 0, 0, g(Yes, No, false, false, "", "ノット")}, - {0x332a, 0, 0, 0, g(Yes, No, false, false, "", "ハイツ")}, - {0x332b, 0, 0, 0, g(Yes, No, false, false, "", "パーセント")}, - {0x332c, 0, 0, 0, g(Yes, No, false, false, "", "パーツ")}, - {0x332d, 0, 0, 0, g(Yes, No, false, false, "", "バーレル")}, - {0x332e, 0, 0, 0, g(Yes, No, false, false, "", "ピアストル")}, - {0x332f, 0, 0, 0, g(Yes, No, false, false, "", "ピクル")}, - {0x3330, 0, 0, 0, g(Yes, No, false, false, "", "ピコ")}, - {0x3331, 0, 0, 0, g(Yes, No, false, false, "", "ビル")}, - {0x3332, 0, 0, 1, g(Yes, No, false, false, "", "ファラッド")}, - {0x3333, 0, 0, 0, g(Yes, No, false, false, "", "フィート")}, - {0x3334, 0, 0, 0, g(Yes, No, false, false, "", "ブッシェル")}, - {0x3335, 0, 0, 0, g(Yes, No, false, false, "", "フラン")}, - {0x3336, 0, 0, 0, g(Yes, No, false, false, "", "ヘクタール")}, - {0x3337, 0, 0, 0, g(Yes, No, false, false, "", "ペソ")}, - {0x3338, 0, 0, 0, g(Yes, No, false, false, "", "ペニヒ")}, - {0x3339, 0, 0, 0, g(Yes, No, false, false, "", "ヘルツ")}, - {0x333a, 0, 0, 0, g(Yes, No, false, false, "", "ペンス")}, - {0x333b, 0, 0, 1, g(Yes, No, false, false, "", "ページ")}, - {0x333c, 0, 0, 0, g(Yes, No, false, false, "", "ベータ")}, - {0x333d, 0, 0, 0, g(Yes, No, false, false, "", "ポイント")}, - {0x333e, 0, 0, 0, g(Yes, No, false, false, "", "ボルト")}, - {0x333f, 0, 0, 0, g(Yes, No, false, false, "", "ホン")}, - {0x3340, 0, 0, 1, g(Yes, No, false, false, "", "ポンド")}, - {0x3341, 0, 0, 0, g(Yes, No, false, false, "", "ホール")}, - {0x3342, 0, 0, 0, g(Yes, No, false, false, "", "ホーン")}, - {0x3343, 0, 0, 0, g(Yes, No, false, false, "", "マイクロ")}, - {0x3344, 0, 0, 0, g(Yes, No, false, false, "", "マイル")}, - {0x3345, 0, 0, 0, g(Yes, No, false, false, "", "マッハ")}, - {0x3346, 0, 0, 0, g(Yes, No, false, false, "", "マルク")}, - {0x3347, 0, 0, 0, g(Yes, No, false, false, "", "マンション")}, - {0x3348, 0, 0, 0, g(Yes, No, false, false, "", "ミクロン")}, - {0x3349, 0, 0, 0, g(Yes, No, false, false, "", "ミリ")}, - {0x334a, 0, 0, 0, g(Yes, No, false, false, "", "ミリバール")}, - {0x334b, 0, 0, 1, g(Yes, No, false, false, "", "メガ")}, - {0x334c, 0, 0, 0, g(Yes, No, false, false, "", "メガトン")}, - {0x334d, 0, 0, 0, g(Yes, No, false, false, "", "メートル")}, - {0x334e, 0, 0, 1, g(Yes, No, false, false, "", "ヤード")}, - {0x334f, 0, 0, 0, g(Yes, No, false, false, "", "ヤール")}, - {0x3350, 0, 0, 0, g(Yes, No, false, false, "", "ユアン")}, - {0x3351, 0, 0, 0, g(Yes, No, false, false, "", "リットル")}, - {0x3352, 0, 0, 0, g(Yes, No, false, false, "", "リラ")}, - {0x3353, 0, 0, 0, g(Yes, No, false, false, "", "ルピー")}, - {0x3354, 0, 0, 0, g(Yes, No, false, false, "", "ルーブル")}, - {0x3355, 0, 0, 0, g(Yes, No, false, false, "", "レム")}, - {0x3356, 0, 0, 0, g(Yes, No, false, false, "", "レントゲン")}, - {0x3357, 0, 0, 0, g(Yes, No, false, false, "", "ワット")}, - {0x3358, 0, 0, 0, g(Yes, No, false, false, "", "0点")}, - {0x3359, 0, 0, 0, g(Yes, No, false, false, "", "1点")}, - {0x335a, 0, 0, 0, g(Yes, No, false, false, "", "2点")}, - {0x335b, 0, 0, 0, g(Yes, No, false, false, "", "3点")}, - {0x335c, 0, 0, 0, g(Yes, No, false, false, "", "4点")}, - {0x335d, 0, 0, 0, g(Yes, No, false, false, "", "5点")}, - {0x335e, 0, 0, 0, g(Yes, No, false, false, "", "6点")}, - {0x335f, 0, 0, 0, g(Yes, No, false, false, "", "7点")}, - {0x3360, 0, 0, 0, g(Yes, No, false, false, "", "8点")}, - {0x3361, 0, 0, 0, g(Yes, No, false, false, "", "9点")}, - {0x3362, 0, 0, 0, g(Yes, No, false, false, "", "10点")}, - {0x3363, 0, 0, 0, g(Yes, No, false, false, "", "11点")}, - {0x3364, 0, 0, 0, g(Yes, No, false, false, "", "12点")}, - {0x3365, 0, 0, 0, g(Yes, No, false, false, "", "13点")}, - {0x3366, 0, 0, 0, g(Yes, No, false, false, "", "14点")}, - {0x3367, 0, 0, 0, g(Yes, No, false, false, "", "15点")}, - {0x3368, 0, 0, 0, g(Yes, No, false, false, "", "16点")}, - {0x3369, 0, 0, 0, g(Yes, No, false, false, "", "17点")}, - {0x336a, 0, 0, 0, g(Yes, No, false, false, "", "18点")}, - {0x336b, 0, 0, 0, g(Yes, No, false, false, "", "19点")}, - {0x336c, 0, 0, 0, g(Yes, No, false, false, "", "20点")}, - {0x336d, 0, 0, 0, g(Yes, No, false, false, "", "21点")}, - {0x336e, 0, 0, 0, g(Yes, No, false, false, "", "22点")}, - {0x336f, 0, 0, 0, g(Yes, No, false, false, "", "23点")}, - {0x3370, 0, 0, 0, g(Yes, No, false, false, "", "24点")}, - {0x3371, 0, 0, 0, g(Yes, No, false, false, "", "hPa")}, - {0x3372, 0, 0, 0, g(Yes, No, false, false, "", "da")}, - {0x3373, 0, 0, 0, g(Yes, No, false, false, "", "AU")}, - {0x3374, 0, 0, 0, g(Yes, No, false, false, "", "bar")}, - {0x3375, 0, 0, 0, g(Yes, No, false, false, "", "oV")}, - {0x3376, 0, 0, 0, g(Yes, No, false, false, "", "pc")}, - {0x3377, 0, 0, 0, g(Yes, No, false, false, "", "dm")}, - {0x3378, 0, 0, 0, g(Yes, No, false, false, "", "dm2")}, - {0x3379, 0, 0, 0, g(Yes, No, false, false, "", "dm3")}, - {0x337a, 0, 0, 0, g(Yes, No, false, false, "", "IU")}, - {0x337b, 0, 0, 0, g(Yes, No, false, false, "", "平成")}, - {0x337c, 0, 0, 0, g(Yes, No, false, false, "", "昭和")}, - {0x337d, 0, 0, 0, g(Yes, No, false, false, "", "大正")}, - {0x337e, 0, 0, 0, g(Yes, No, false, false, "", "明治")}, - {0x337f, 0, 0, 0, g(Yes, No, false, false, "", "株式会社")}, - {0x3380, 0, 0, 0, g(Yes, No, false, false, "", "pA")}, - {0x3381, 0, 0, 0, g(Yes, No, false, false, "", "nA")}, - {0x3382, 0, 0, 0, g(Yes, No, false, false, "", "μA")}, - {0x3383, 0, 0, 0, g(Yes, No, false, false, "", "mA")}, - {0x3384, 0, 0, 0, g(Yes, No, false, false, "", "kA")}, - {0x3385, 0, 0, 0, g(Yes, No, false, false, "", "KB")}, - {0x3386, 0, 0, 0, g(Yes, No, false, false, "", "MB")}, - {0x3387, 0, 0, 0, g(Yes, No, false, false, "", "GB")}, - {0x3388, 0, 0, 0, g(Yes, No, false, false, "", "cal")}, - {0x3389, 0, 0, 0, g(Yes, No, false, false, "", "kcal")}, - {0x338a, 0, 0, 0, g(Yes, No, false, false, "", "pF")}, - {0x338b, 0, 0, 0, g(Yes, No, false, false, "", "nF")}, - {0x338c, 0, 0, 0, g(Yes, No, false, false, "", "μF")}, - {0x338d, 0, 0, 0, g(Yes, No, false, false, "", "μg")}, - {0x338e, 0, 0, 0, g(Yes, No, false, false, "", "mg")}, - {0x338f, 0, 0, 0, g(Yes, No, false, false, "", "kg")}, - {0x3390, 0, 0, 0, g(Yes, No, false, false, "", "Hz")}, - {0x3391, 0, 0, 0, g(Yes, No, false, false, "", "kHz")}, - {0x3392, 0, 0, 0, g(Yes, No, false, false, "", "MHz")}, - {0x3393, 0, 0, 0, g(Yes, No, false, false, "", "GHz")}, - {0x3394, 0, 0, 0, g(Yes, No, false, false, "", "THz")}, - {0x3395, 0, 0, 0, g(Yes, No, false, false, "", "μl")}, - {0x3396, 0, 0, 0, g(Yes, No, false, false, "", "ml")}, - {0x3397, 0, 0, 0, g(Yes, No, false, false, "", "dl")}, - {0x3398, 0, 0, 0, g(Yes, No, false, false, "", "kl")}, - {0x3399, 0, 0, 0, g(Yes, No, false, false, "", "fm")}, - {0x339a, 0, 0, 0, g(Yes, No, false, false, "", "nm")}, - {0x339b, 0, 0, 0, g(Yes, No, false, false, "", "μm")}, - {0x339c, 0, 0, 0, g(Yes, No, false, false, "", "mm")}, - {0x339d, 0, 0, 0, g(Yes, No, false, false, "", "cm")}, - {0x339e, 0, 0, 0, g(Yes, No, false, false, "", "km")}, - {0x339f, 0, 0, 0, g(Yes, No, false, false, "", "mm2")}, - {0x33a0, 0, 0, 0, g(Yes, No, false, false, "", "cm2")}, - {0x33a1, 0, 0, 0, g(Yes, No, false, false, "", "m2")}, - {0x33a2, 0, 0, 0, g(Yes, No, false, false, "", "km2")}, - {0x33a3, 0, 0, 0, g(Yes, No, false, false, "", "mm3")}, - {0x33a4, 0, 0, 0, g(Yes, No, false, false, "", "cm3")}, - {0x33a5, 0, 0, 0, g(Yes, No, false, false, "", "m3")}, - {0x33a6, 0, 0, 0, g(Yes, No, false, false, "", "km3")}, - {0x33a7, 0, 0, 0, g(Yes, No, false, false, "", "m∕s")}, - {0x33a8, 0, 0, 0, g(Yes, No, false, false, "", "m∕s2")}, - {0x33a9, 0, 0, 0, g(Yes, No, false, false, "", "Pa")}, - {0x33aa, 0, 0, 0, g(Yes, No, false, false, "", "kPa")}, - {0x33ab, 0, 0, 0, g(Yes, No, false, false, "", "MPa")}, - {0x33ac, 0, 0, 0, g(Yes, No, false, false, "", "GPa")}, - {0x33ad, 0, 0, 0, g(Yes, No, false, false, "", "rad")}, - {0x33ae, 0, 0, 0, g(Yes, No, false, false, "", "rad∕s")}, - {0x33af, 0, 0, 0, g(Yes, No, false, false, "", "rad∕s2")}, - {0x33b0, 0, 0, 0, g(Yes, No, false, false, "", "ps")}, - {0x33b1, 0, 0, 0, g(Yes, No, false, false, "", "ns")}, - {0x33b2, 0, 0, 0, g(Yes, No, false, false, "", "μs")}, - {0x33b3, 0, 0, 0, g(Yes, No, false, false, "", "ms")}, - {0x33b4, 0, 0, 0, g(Yes, No, false, false, "", "pV")}, - {0x33b5, 0, 0, 0, g(Yes, No, false, false, "", "nV")}, - {0x33b6, 0, 0, 0, g(Yes, No, false, false, "", "μV")}, - {0x33b7, 0, 0, 0, g(Yes, No, false, false, "", "mV")}, - {0x33b8, 0, 0, 0, g(Yes, No, false, false, "", "kV")}, - {0x33b9, 0, 0, 0, g(Yes, No, false, false, "", "MV")}, - {0x33ba, 0, 0, 0, g(Yes, No, false, false, "", "pW")}, - {0x33bb, 0, 0, 0, g(Yes, No, false, false, "", "nW")}, - {0x33bc, 0, 0, 0, g(Yes, No, false, false, "", "μW")}, - {0x33bd, 0, 0, 0, g(Yes, No, false, false, "", "mW")}, - {0x33be, 0, 0, 0, g(Yes, No, false, false, "", "kW")}, - {0x33bf, 0, 0, 0, g(Yes, No, false, false, "", "MW")}, - {0x33c0, 0, 0, 0, g(Yes, No, false, false, "", "kΩ")}, - {0x33c1, 0, 0, 0, g(Yes, No, false, false, "", "MΩ")}, - {0x33c2, 0, 0, 0, g(Yes, No, false, false, "", "a.m.")}, - {0x33c3, 0, 0, 0, g(Yes, No, false, false, "", "Bq")}, - {0x33c4, 0, 0, 0, g(Yes, No, false, false, "", "cc")}, - {0x33c5, 0, 0, 0, g(Yes, No, false, false, "", "cd")}, - {0x33c6, 0, 0, 0, g(Yes, No, false, false, "", "C∕kg")}, - {0x33c7, 0, 0, 0, g(Yes, No, false, false, "", "Co.")}, - {0x33c8, 0, 0, 0, g(Yes, No, false, false, "", "dB")}, - {0x33c9, 0, 0, 0, g(Yes, No, false, false, "", "Gy")}, - {0x33ca, 0, 0, 0, g(Yes, No, false, false, "", "ha")}, - {0x33cb, 0, 0, 0, g(Yes, No, false, false, "", "HP")}, - {0x33cc, 0, 0, 0, g(Yes, No, false, false, "", "in")}, - {0x33cd, 0, 0, 0, g(Yes, No, false, false, "", "KK")}, - {0x33ce, 0, 0, 0, g(Yes, No, false, false, "", "KM")}, - {0x33cf, 0, 0, 0, g(Yes, No, false, false, "", "kt")}, - {0x33d0, 0, 0, 0, g(Yes, No, false, false, "", "lm")}, - {0x33d1, 0, 0, 0, g(Yes, No, false, false, "", "ln")}, - {0x33d2, 0, 0, 0, g(Yes, No, false, false, "", "log")}, - {0x33d3, 0, 0, 0, g(Yes, No, false, false, "", "lx")}, - {0x33d4, 0, 0, 0, g(Yes, No, false, false, "", "mb")}, - {0x33d5, 0, 0, 0, g(Yes, No, false, false, "", "mil")}, - {0x33d6, 0, 0, 0, g(Yes, No, false, false, "", "mol")}, - {0x33d7, 0, 0, 0, g(Yes, No, false, false, "", "PH")}, - {0x33d8, 0, 0, 0, g(Yes, No, false, false, "", "p.m.")}, - {0x33d9, 0, 0, 0, g(Yes, No, false, false, "", "PPM")}, - {0x33da, 0, 0, 0, g(Yes, No, false, false, "", "PR")}, - {0x33db, 0, 0, 0, g(Yes, No, false, false, "", "sr")}, - {0x33dc, 0, 0, 0, g(Yes, No, false, false, "", "Sv")}, - {0x33dd, 0, 0, 0, g(Yes, No, false, false, "", "Wb")}, - {0x33de, 0, 0, 0, g(Yes, No, false, false, "", "V∕m")}, - {0x33df, 0, 0, 0, g(Yes, No, false, false, "", "A∕m")}, - {0x33e0, 0, 0, 0, g(Yes, No, false, false, "", "1日")}, - {0x33e1, 0, 0, 0, g(Yes, No, false, false, "", "2日")}, - {0x33e2, 0, 0, 0, g(Yes, No, false, false, "", "3日")}, - {0x33e3, 0, 0, 0, g(Yes, No, false, false, "", "4日")}, - {0x33e4, 0, 0, 0, g(Yes, No, false, false, "", "5日")}, - {0x33e5, 0, 0, 0, g(Yes, No, false, false, "", "6日")}, - {0x33e6, 0, 0, 0, g(Yes, No, false, false, "", "7日")}, - {0x33e7, 0, 0, 0, g(Yes, No, false, false, "", "8日")}, - {0x33e8, 0, 0, 0, g(Yes, No, false, false, "", "9日")}, - {0x33e9, 0, 0, 0, g(Yes, No, false, false, "", "10日")}, - {0x33ea, 0, 0, 0, g(Yes, No, false, false, "", "11日")}, - {0x33eb, 0, 0, 0, g(Yes, No, false, false, "", "12日")}, - {0x33ec, 0, 0, 0, g(Yes, No, false, false, "", "13日")}, - {0x33ed, 0, 0, 0, g(Yes, No, false, false, "", "14日")}, - {0x33ee, 0, 0, 0, g(Yes, No, false, false, "", "15日")}, - {0x33ef, 0, 0, 0, g(Yes, No, false, false, "", "16日")}, - {0x33f0, 0, 0, 0, g(Yes, No, false, false, "", "17日")}, - {0x33f1, 0, 0, 0, g(Yes, No, false, false, "", "18日")}, - {0x33f2, 0, 0, 0, g(Yes, No, false, false, "", "19日")}, - {0x33f3, 0, 0, 0, g(Yes, No, false, false, "", "20日")}, - {0x33f4, 0, 0, 0, g(Yes, No, false, false, "", "21日")}, - {0x33f5, 0, 0, 0, g(Yes, No, false, false, "", "22日")}, - {0x33f6, 0, 0, 0, g(Yes, No, false, false, "", "23日")}, - {0x33f7, 0, 0, 0, g(Yes, No, false, false, "", "24日")}, - {0x33f8, 0, 0, 0, g(Yes, No, false, false, "", "25日")}, - {0x33f9, 0, 0, 0, g(Yes, No, false, false, "", "26日")}, - {0x33fa, 0, 0, 0, g(Yes, No, false, false, "", "27日")}, - {0x33fb, 0, 0, 0, g(Yes, No, false, false, "", "28日")}, - {0x33fc, 0, 0, 0, g(Yes, No, false, false, "", "29日")}, - {0x33fd, 0, 0, 0, g(Yes, No, false, false, "", "30日")}, - {0x33fe, 0, 0, 0, g(Yes, No, false, false, "", "31日")}, - {0x33ff, 0, 0, 0, g(Yes, No, false, false, "", "gal")}, - {0x3400, 0, 0, 0, f(Yes, false, "")}, - {0xa66f, 230, 1, 1, f(Yes, false, "")}, - {0xa670, 0, 0, 0, f(Yes, false, "")}, - {0xa674, 230, 1, 1, f(Yes, false, "")}, - {0xa67e, 0, 0, 0, f(Yes, false, "")}, - {0xa69c, 0, 0, 0, g(Yes, No, false, false, "", "ъ")}, - {0xa69d, 0, 0, 0, g(Yes, No, false, false, "", "ь")}, - {0xa69e, 230, 1, 1, f(Yes, false, "")}, - {0xa6a0, 0, 0, 0, f(Yes, false, "")}, - {0xa6f0, 230, 1, 1, f(Yes, false, "")}, - {0xa6f2, 0, 0, 0, f(Yes, false, "")}, - {0xa770, 0, 0, 0, g(Yes, No, false, false, "", "ꝯ")}, - {0xa771, 0, 0, 0, f(Yes, false, "")}, - {0xa7f8, 0, 0, 0, g(Yes, No, false, false, "", "Ħ")}, - {0xa7f9, 0, 0, 0, g(Yes, No, false, false, "", "œ")}, - {0xa7fa, 0, 0, 0, f(Yes, false, "")}, - {0xa806, 9, 1, 1, f(Yes, false, "")}, - {0xa807, 0, 0, 0, f(Yes, false, "")}, - {0xa8c4, 9, 1, 1, f(Yes, false, "")}, - {0xa8c5, 0, 0, 0, f(Yes, false, "")}, - {0xa8e0, 230, 1, 1, f(Yes, false, "")}, - {0xa8f2, 0, 0, 0, f(Yes, false, "")}, - {0xa92b, 220, 1, 1, f(Yes, false, "")}, - {0xa92e, 0, 0, 0, f(Yes, false, "")}, - {0xa953, 9, 1, 1, f(Yes, false, "")}, - {0xa954, 0, 0, 0, f(Yes, false, "")}, - {0xa9b3, 7, 1, 1, f(Yes, false, "")}, - {0xa9b4, 0, 0, 0, f(Yes, false, "")}, - {0xa9c0, 9, 1, 1, f(Yes, false, "")}, - {0xa9c1, 0, 0, 0, f(Yes, false, "")}, - {0xaab0, 230, 1, 1, f(Yes, false, "")}, - {0xaab1, 0, 0, 0, f(Yes, false, "")}, - {0xaab2, 230, 1, 1, f(Yes, false, "")}, - {0xaab4, 220, 1, 1, f(Yes, false, "")}, - {0xaab5, 0, 0, 0, f(Yes, false, "")}, - {0xaab7, 230, 1, 1, f(Yes, false, "")}, - {0xaab9, 0, 0, 0, f(Yes, false, "")}, - {0xaabe, 230, 1, 1, f(Yes, false, "")}, - {0xaac0, 0, 0, 0, f(Yes, false, "")}, - {0xaac1, 230, 1, 1, f(Yes, false, "")}, - {0xaac2, 0, 0, 0, f(Yes, false, "")}, - {0xaaf6, 9, 1, 1, f(Yes, false, "")}, - {0xaaf7, 0, 0, 0, f(Yes, false, "")}, - {0xab5c, 0, 0, 0, g(Yes, No, false, false, "", "ꜧ")}, - {0xab5d, 0, 0, 0, g(Yes, No, false, false, "", "ꬷ")}, - {0xab5e, 0, 0, 0, g(Yes, No, false, false, "", "ɫ")}, - {0xab5f, 0, 0, 0, g(Yes, No, false, false, "", "ꭒ")}, - {0xab60, 0, 0, 0, f(Yes, false, "")}, - {0xabed, 9, 1, 1, f(Yes, false, "")}, - {0xabee, 0, 0, 0, f(Yes, false, "")}, - {0xac00, 0, 0, 1, f(Yes, true, "")}, - {0xac01, 0, 0, 2, f(Yes, false, "")}, - {0xac1c, 0, 0, 1, f(Yes, true, "")}, - {0xac1d, 0, 0, 2, f(Yes, false, "")}, - {0xac38, 0, 0, 1, f(Yes, true, "")}, - {0xac39, 0, 0, 2, f(Yes, false, "")}, - {0xac54, 0, 0, 1, f(Yes, true, "")}, - {0xac55, 0, 0, 2, f(Yes, false, "")}, - {0xac70, 0, 0, 1, f(Yes, true, "")}, - {0xac71, 0, 0, 2, f(Yes, false, "")}, - {0xac8c, 0, 0, 1, f(Yes, true, "")}, - {0xac8d, 0, 0, 2, f(Yes, false, "")}, - {0xaca8, 0, 0, 1, f(Yes, true, "")}, - {0xaca9, 0, 0, 2, f(Yes, false, "")}, - {0xacc4, 0, 0, 1, f(Yes, true, "")}, - {0xacc5, 0, 0, 2, f(Yes, false, "")}, - {0xace0, 0, 0, 1, f(Yes, true, "")}, - {0xace1, 0, 0, 2, f(Yes, false, "")}, - {0xacfc, 0, 0, 1, f(Yes, true, "")}, - {0xacfd, 0, 0, 2, f(Yes, false, "")}, - {0xad18, 0, 0, 1, f(Yes, true, "")}, - {0xad19, 0, 0, 2, f(Yes, false, "")}, - {0xad34, 0, 0, 1, f(Yes, true, "")}, - {0xad35, 0, 0, 2, f(Yes, false, "")}, - {0xad50, 0, 0, 1, f(Yes, true, "")}, - {0xad51, 0, 0, 2, f(Yes, false, "")}, - {0xad6c, 0, 0, 1, f(Yes, true, "")}, - {0xad6d, 0, 0, 2, f(Yes, false, "")}, - {0xad88, 0, 0, 1, f(Yes, true, "")}, - {0xad89, 0, 0, 2, f(Yes, false, "")}, - {0xada4, 0, 0, 1, f(Yes, true, "")}, - {0xada5, 0, 0, 2, f(Yes, false, "")}, - {0xadc0, 0, 0, 1, f(Yes, true, "")}, - {0xadc1, 0, 0, 2, f(Yes, false, "")}, - {0xaddc, 0, 0, 1, f(Yes, true, "")}, - {0xaddd, 0, 0, 2, f(Yes, false, "")}, - {0xadf8, 0, 0, 1, f(Yes, true, "")}, - {0xadf9, 0, 0, 2, f(Yes, false, "")}, - {0xae14, 0, 0, 1, f(Yes, true, "")}, - {0xae15, 0, 0, 2, f(Yes, false, "")}, - {0xae30, 0, 0, 1, f(Yes, true, "")}, - {0xae31, 0, 0, 2, f(Yes, false, "")}, - {0xae4c, 0, 0, 1, f(Yes, true, "")}, - {0xae4d, 0, 0, 2, f(Yes, false, "")}, - {0xae68, 0, 0, 1, f(Yes, true, "")}, - {0xae69, 0, 0, 2, f(Yes, false, "")}, - {0xae84, 0, 0, 1, f(Yes, true, "")}, - {0xae85, 0, 0, 2, f(Yes, false, "")}, - {0xaea0, 0, 0, 1, f(Yes, true, "")}, - {0xaea1, 0, 0, 2, f(Yes, false, "")}, - {0xaebc, 0, 0, 1, f(Yes, true, "")}, - {0xaebd, 0, 0, 2, f(Yes, false, "")}, - {0xaed8, 0, 0, 1, f(Yes, true, "")}, - {0xaed9, 0, 0, 2, f(Yes, false, "")}, - {0xaef4, 0, 0, 1, f(Yes, true, "")}, - {0xaef5, 0, 0, 2, f(Yes, false, "")}, - {0xaf10, 0, 0, 1, f(Yes, true, "")}, - {0xaf11, 0, 0, 2, f(Yes, false, "")}, - {0xaf2c, 0, 0, 1, f(Yes, true, "")}, - {0xaf2d, 0, 0, 2, f(Yes, false, "")}, - {0xaf48, 0, 0, 1, f(Yes, true, "")}, - {0xaf49, 0, 0, 2, f(Yes, false, "")}, - {0xaf64, 0, 0, 1, f(Yes, true, "")}, - {0xaf65, 0, 0, 2, f(Yes, false, "")}, - {0xaf80, 0, 0, 1, f(Yes, true, "")}, - {0xaf81, 0, 0, 2, f(Yes, false, "")}, - {0xaf9c, 0, 0, 1, f(Yes, true, "")}, - {0xaf9d, 0, 0, 2, f(Yes, false, "")}, - {0xafb8, 0, 0, 1, f(Yes, true, "")}, - {0xafb9, 0, 0, 2, f(Yes, false, "")}, - {0xafd4, 0, 0, 1, f(Yes, true, "")}, - {0xafd5, 0, 0, 2, f(Yes, false, "")}, - {0xaff0, 0, 0, 1, f(Yes, true, "")}, - {0xaff1, 0, 0, 2, f(Yes, false, "")}, - {0xb00c, 0, 0, 1, f(Yes, true, "")}, - {0xb00d, 0, 0, 2, f(Yes, false, "")}, - {0xb028, 0, 0, 1, f(Yes, true, "")}, - {0xb029, 0, 0, 2, f(Yes, false, "")}, - {0xb044, 0, 0, 1, f(Yes, true, "")}, - {0xb045, 0, 0, 2, f(Yes, false, "")}, - {0xb060, 0, 0, 1, f(Yes, true, "")}, - {0xb061, 0, 0, 2, f(Yes, false, "")}, - {0xb07c, 0, 0, 1, f(Yes, true, "")}, - {0xb07d, 0, 0, 2, f(Yes, false, "")}, - {0xb098, 0, 0, 1, f(Yes, true, "")}, - {0xb099, 0, 0, 2, f(Yes, false, "")}, - {0xb0b4, 0, 0, 1, f(Yes, true, "")}, - {0xb0b5, 0, 0, 2, f(Yes, false, "")}, - {0xb0d0, 0, 0, 1, f(Yes, true, "")}, - {0xb0d1, 0, 0, 2, f(Yes, false, "")}, - {0xb0ec, 0, 0, 1, f(Yes, true, "")}, - {0xb0ed, 0, 0, 2, f(Yes, false, "")}, - {0xb108, 0, 0, 1, f(Yes, true, "")}, - {0xb109, 0, 0, 2, f(Yes, false, "")}, - {0xb124, 0, 0, 1, f(Yes, true, "")}, - {0xb125, 0, 0, 2, f(Yes, false, "")}, - {0xb140, 0, 0, 1, f(Yes, true, "")}, - {0xb141, 0, 0, 2, f(Yes, false, "")}, - {0xb15c, 0, 0, 1, f(Yes, true, "")}, - {0xb15d, 0, 0, 2, f(Yes, false, "")}, - {0xb178, 0, 0, 1, f(Yes, true, "")}, - {0xb179, 0, 0, 2, f(Yes, false, "")}, - {0xb194, 0, 0, 1, f(Yes, true, "")}, - {0xb195, 0, 0, 2, f(Yes, false, "")}, - {0xb1b0, 0, 0, 1, f(Yes, true, "")}, - {0xb1b1, 0, 0, 2, f(Yes, false, "")}, - {0xb1cc, 0, 0, 1, f(Yes, true, "")}, - {0xb1cd, 0, 0, 2, f(Yes, false, "")}, - {0xb1e8, 0, 0, 1, f(Yes, true, "")}, - {0xb1e9, 0, 0, 2, f(Yes, false, "")}, - {0xb204, 0, 0, 1, f(Yes, true, "")}, - {0xb205, 0, 0, 2, f(Yes, false, "")}, - {0xb220, 0, 0, 1, f(Yes, true, "")}, - {0xb221, 0, 0, 2, f(Yes, false, "")}, - {0xb23c, 0, 0, 1, f(Yes, true, "")}, - {0xb23d, 0, 0, 2, f(Yes, false, "")}, - {0xb258, 0, 0, 1, f(Yes, true, "")}, - {0xb259, 0, 0, 2, f(Yes, false, "")}, - {0xb274, 0, 0, 1, f(Yes, true, "")}, - {0xb275, 0, 0, 2, f(Yes, false, "")}, - {0xb290, 0, 0, 1, f(Yes, true, "")}, - {0xb291, 0, 0, 2, f(Yes, false, "")}, - {0xb2ac, 0, 0, 1, f(Yes, true, "")}, - {0xb2ad, 0, 0, 2, f(Yes, false, "")}, - {0xb2c8, 0, 0, 1, f(Yes, true, "")}, - {0xb2c9, 0, 0, 2, f(Yes, false, "")}, - {0xb2e4, 0, 0, 1, f(Yes, true, "")}, - {0xb2e5, 0, 0, 2, f(Yes, false, "")}, - {0xb300, 0, 0, 1, f(Yes, true, "")}, - {0xb301, 0, 0, 2, f(Yes, false, "")}, - {0xb31c, 0, 0, 1, f(Yes, true, "")}, - {0xb31d, 0, 0, 2, f(Yes, false, "")}, - {0xb338, 0, 0, 1, f(Yes, true, "")}, - {0xb339, 0, 0, 2, f(Yes, false, "")}, - {0xb354, 0, 0, 1, f(Yes, true, "")}, - {0xb355, 0, 0, 2, f(Yes, false, "")}, - {0xb370, 0, 0, 1, f(Yes, true, "")}, - {0xb371, 0, 0, 2, f(Yes, false, "")}, - {0xb38c, 0, 0, 1, f(Yes, true, "")}, - {0xb38d, 0, 0, 2, f(Yes, false, "")}, - {0xb3a8, 0, 0, 1, f(Yes, true, "")}, - {0xb3a9, 0, 0, 2, f(Yes, false, "")}, - {0xb3c4, 0, 0, 1, f(Yes, true, "")}, - {0xb3c5, 0, 0, 2, f(Yes, false, "")}, - {0xb3e0, 0, 0, 1, f(Yes, true, "")}, - {0xb3e1, 0, 0, 2, f(Yes, false, "")}, - {0xb3fc, 0, 0, 1, f(Yes, true, "")}, - {0xb3fd, 0, 0, 2, f(Yes, false, "")}, - {0xb418, 0, 0, 1, f(Yes, true, "")}, - {0xb419, 0, 0, 2, f(Yes, false, "")}, - {0xb434, 0, 0, 1, f(Yes, true, "")}, - {0xb435, 0, 0, 2, f(Yes, false, "")}, - {0xb450, 0, 0, 1, f(Yes, true, "")}, - {0xb451, 0, 0, 2, f(Yes, false, "")}, - {0xb46c, 0, 0, 1, f(Yes, true, "")}, - {0xb46d, 0, 0, 2, f(Yes, false, "")}, - {0xb488, 0, 0, 1, f(Yes, true, "")}, - {0xb489, 0, 0, 2, f(Yes, false, "")}, - {0xb4a4, 0, 0, 1, f(Yes, true, "")}, - {0xb4a5, 0, 0, 2, f(Yes, false, "")}, - {0xb4c0, 0, 0, 1, f(Yes, true, "")}, - {0xb4c1, 0, 0, 2, f(Yes, false, "")}, - {0xb4dc, 0, 0, 1, f(Yes, true, "")}, - {0xb4dd, 0, 0, 2, f(Yes, false, "")}, - {0xb4f8, 0, 0, 1, f(Yes, true, "")}, - {0xb4f9, 0, 0, 2, f(Yes, false, "")}, - {0xb514, 0, 0, 1, f(Yes, true, "")}, - {0xb515, 0, 0, 2, f(Yes, false, "")}, - {0xb530, 0, 0, 1, f(Yes, true, "")}, - {0xb531, 0, 0, 2, f(Yes, false, "")}, - {0xb54c, 0, 0, 1, f(Yes, true, "")}, - {0xb54d, 0, 0, 2, f(Yes, false, "")}, - {0xb568, 0, 0, 1, f(Yes, true, "")}, - {0xb569, 0, 0, 2, f(Yes, false, "")}, - {0xb584, 0, 0, 1, f(Yes, true, "")}, - {0xb585, 0, 0, 2, f(Yes, false, "")}, - {0xb5a0, 0, 0, 1, f(Yes, true, "")}, - {0xb5a1, 0, 0, 2, f(Yes, false, "")}, - {0xb5bc, 0, 0, 1, f(Yes, true, "")}, - {0xb5bd, 0, 0, 2, f(Yes, false, "")}, - {0xb5d8, 0, 0, 1, f(Yes, true, "")}, - {0xb5d9, 0, 0, 2, f(Yes, false, "")}, - {0xb5f4, 0, 0, 1, f(Yes, true, "")}, - {0xb5f5, 0, 0, 2, f(Yes, false, "")}, - {0xb610, 0, 0, 1, f(Yes, true, "")}, - {0xb611, 0, 0, 2, f(Yes, false, "")}, - {0xb62c, 0, 0, 1, f(Yes, true, "")}, - {0xb62d, 0, 0, 2, f(Yes, false, "")}, - {0xb648, 0, 0, 1, f(Yes, true, "")}, - {0xb649, 0, 0, 2, f(Yes, false, "")}, - {0xb664, 0, 0, 1, f(Yes, true, "")}, - {0xb665, 0, 0, 2, f(Yes, false, "")}, - {0xb680, 0, 0, 1, f(Yes, true, "")}, - {0xb681, 0, 0, 2, f(Yes, false, "")}, - {0xb69c, 0, 0, 1, f(Yes, true, "")}, - {0xb69d, 0, 0, 2, f(Yes, false, "")}, - {0xb6b8, 0, 0, 1, f(Yes, true, "")}, - {0xb6b9, 0, 0, 2, f(Yes, false, "")}, - {0xb6d4, 0, 0, 1, f(Yes, true, "")}, - {0xb6d5, 0, 0, 2, f(Yes, false, "")}, - {0xb6f0, 0, 0, 1, f(Yes, true, "")}, - {0xb6f1, 0, 0, 2, f(Yes, false, "")}, - {0xb70c, 0, 0, 1, f(Yes, true, "")}, - {0xb70d, 0, 0, 2, f(Yes, false, "")}, - {0xb728, 0, 0, 1, f(Yes, true, "")}, - {0xb729, 0, 0, 2, f(Yes, false, "")}, - {0xb744, 0, 0, 1, f(Yes, true, "")}, - {0xb745, 0, 0, 2, f(Yes, false, "")}, - {0xb760, 0, 0, 1, f(Yes, true, "")}, - {0xb761, 0, 0, 2, f(Yes, false, "")}, - {0xb77c, 0, 0, 1, f(Yes, true, "")}, - {0xb77d, 0, 0, 2, f(Yes, false, "")}, - {0xb798, 0, 0, 1, f(Yes, true, "")}, - {0xb799, 0, 0, 2, f(Yes, false, "")}, - {0xb7b4, 0, 0, 1, f(Yes, true, "")}, - {0xb7b5, 0, 0, 2, f(Yes, false, "")}, - {0xb7d0, 0, 0, 1, f(Yes, true, "")}, - {0xb7d1, 0, 0, 2, f(Yes, false, "")}, - {0xb7ec, 0, 0, 1, f(Yes, true, "")}, - {0xb7ed, 0, 0, 2, f(Yes, false, "")}, - {0xb808, 0, 0, 1, f(Yes, true, "")}, - {0xb809, 0, 0, 2, f(Yes, false, "")}, - {0xb824, 0, 0, 1, f(Yes, true, "")}, - {0xb825, 0, 0, 2, f(Yes, false, "")}, - {0xb840, 0, 0, 1, f(Yes, true, "")}, - {0xb841, 0, 0, 2, f(Yes, false, "")}, - {0xb85c, 0, 0, 1, f(Yes, true, "")}, - {0xb85d, 0, 0, 2, f(Yes, false, "")}, - {0xb878, 0, 0, 1, f(Yes, true, "")}, - {0xb879, 0, 0, 2, f(Yes, false, "")}, - {0xb894, 0, 0, 1, f(Yes, true, "")}, - {0xb895, 0, 0, 2, f(Yes, false, "")}, - {0xb8b0, 0, 0, 1, f(Yes, true, "")}, - {0xb8b1, 0, 0, 2, f(Yes, false, "")}, - {0xb8cc, 0, 0, 1, f(Yes, true, "")}, - {0xb8cd, 0, 0, 2, f(Yes, false, "")}, - {0xb8e8, 0, 0, 1, f(Yes, true, "")}, - {0xb8e9, 0, 0, 2, f(Yes, false, "")}, - {0xb904, 0, 0, 1, f(Yes, true, "")}, - {0xb905, 0, 0, 2, f(Yes, false, "")}, - {0xb920, 0, 0, 1, f(Yes, true, "")}, - {0xb921, 0, 0, 2, f(Yes, false, "")}, - {0xb93c, 0, 0, 1, f(Yes, true, "")}, - {0xb93d, 0, 0, 2, f(Yes, false, "")}, - {0xb958, 0, 0, 1, f(Yes, true, "")}, - {0xb959, 0, 0, 2, f(Yes, false, "")}, - {0xb974, 0, 0, 1, f(Yes, true, "")}, - {0xb975, 0, 0, 2, f(Yes, false, "")}, - {0xb990, 0, 0, 1, f(Yes, true, "")}, - {0xb991, 0, 0, 2, f(Yes, false, "")}, - {0xb9ac, 0, 0, 1, f(Yes, true, "")}, - {0xb9ad, 0, 0, 2, f(Yes, false, "")}, - {0xb9c8, 0, 0, 1, f(Yes, true, "")}, - {0xb9c9, 0, 0, 2, f(Yes, false, "")}, - {0xb9e4, 0, 0, 1, f(Yes, true, "")}, - {0xb9e5, 0, 0, 2, f(Yes, false, "")}, - {0xba00, 0, 0, 1, f(Yes, true, "")}, - {0xba01, 0, 0, 2, f(Yes, false, "")}, - {0xba1c, 0, 0, 1, f(Yes, true, "")}, - {0xba1d, 0, 0, 2, f(Yes, false, "")}, - {0xba38, 0, 0, 1, f(Yes, true, "")}, - {0xba39, 0, 0, 2, f(Yes, false, "")}, - {0xba54, 0, 0, 1, f(Yes, true, "")}, - {0xba55, 0, 0, 2, f(Yes, false, "")}, - {0xba70, 0, 0, 1, f(Yes, true, "")}, - {0xba71, 0, 0, 2, f(Yes, false, "")}, - {0xba8c, 0, 0, 1, f(Yes, true, "")}, - {0xba8d, 0, 0, 2, f(Yes, false, "")}, - {0xbaa8, 0, 0, 1, f(Yes, true, "")}, - {0xbaa9, 0, 0, 2, f(Yes, false, "")}, - {0xbac4, 0, 0, 1, f(Yes, true, "")}, - {0xbac5, 0, 0, 2, f(Yes, false, "")}, - {0xbae0, 0, 0, 1, f(Yes, true, "")}, - {0xbae1, 0, 0, 2, f(Yes, false, "")}, - {0xbafc, 0, 0, 1, f(Yes, true, "")}, - {0xbafd, 0, 0, 2, f(Yes, false, "")}, - {0xbb18, 0, 0, 1, f(Yes, true, "")}, - {0xbb19, 0, 0, 2, f(Yes, false, "")}, - {0xbb34, 0, 0, 1, f(Yes, true, "")}, - {0xbb35, 0, 0, 2, f(Yes, false, "")}, - {0xbb50, 0, 0, 1, f(Yes, true, "")}, - {0xbb51, 0, 0, 2, f(Yes, false, "")}, - {0xbb6c, 0, 0, 1, f(Yes, true, "")}, - {0xbb6d, 0, 0, 2, f(Yes, false, "")}, - {0xbb88, 0, 0, 1, f(Yes, true, "")}, - {0xbb89, 0, 0, 2, f(Yes, false, "")}, - {0xbba4, 0, 0, 1, f(Yes, true, "")}, - {0xbba5, 0, 0, 2, f(Yes, false, "")}, - {0xbbc0, 0, 0, 1, f(Yes, true, "")}, - {0xbbc1, 0, 0, 2, f(Yes, false, "")}, - {0xbbdc, 0, 0, 1, f(Yes, true, "")}, - {0xbbdd, 0, 0, 2, f(Yes, false, "")}, - {0xbbf8, 0, 0, 1, f(Yes, true, "")}, - {0xbbf9, 0, 0, 2, f(Yes, false, "")}, - {0xbc14, 0, 0, 1, f(Yes, true, "")}, - {0xbc15, 0, 0, 2, f(Yes, false, "")}, - {0xbc30, 0, 0, 1, f(Yes, true, "")}, - {0xbc31, 0, 0, 2, f(Yes, false, "")}, - {0xbc4c, 0, 0, 1, f(Yes, true, "")}, - {0xbc4d, 0, 0, 2, f(Yes, false, "")}, - {0xbc68, 0, 0, 1, f(Yes, true, "")}, - {0xbc69, 0, 0, 2, f(Yes, false, "")}, - {0xbc84, 0, 0, 1, f(Yes, true, "")}, - {0xbc85, 0, 0, 2, f(Yes, false, "")}, - {0xbca0, 0, 0, 1, f(Yes, true, "")}, - {0xbca1, 0, 0, 2, f(Yes, false, "")}, - {0xbcbc, 0, 0, 1, f(Yes, true, "")}, - {0xbcbd, 0, 0, 2, f(Yes, false, "")}, - {0xbcd8, 0, 0, 1, f(Yes, true, "")}, - {0xbcd9, 0, 0, 2, f(Yes, false, "")}, - {0xbcf4, 0, 0, 1, f(Yes, true, "")}, - {0xbcf5, 0, 0, 2, f(Yes, false, "")}, - {0xbd10, 0, 0, 1, f(Yes, true, "")}, - {0xbd11, 0, 0, 2, f(Yes, false, "")}, - {0xbd2c, 0, 0, 1, f(Yes, true, "")}, - {0xbd2d, 0, 0, 2, f(Yes, false, "")}, - {0xbd48, 0, 0, 1, f(Yes, true, "")}, - {0xbd49, 0, 0, 2, f(Yes, false, "")}, - {0xbd64, 0, 0, 1, f(Yes, true, "")}, - {0xbd65, 0, 0, 2, f(Yes, false, "")}, - {0xbd80, 0, 0, 1, f(Yes, true, "")}, - {0xbd81, 0, 0, 2, f(Yes, false, "")}, - {0xbd9c, 0, 0, 1, f(Yes, true, "")}, - {0xbd9d, 0, 0, 2, f(Yes, false, "")}, - {0xbdb8, 0, 0, 1, f(Yes, true, "")}, - {0xbdb9, 0, 0, 2, f(Yes, false, "")}, - {0xbdd4, 0, 0, 1, f(Yes, true, "")}, - {0xbdd5, 0, 0, 2, f(Yes, false, "")}, - {0xbdf0, 0, 0, 1, f(Yes, true, "")}, - {0xbdf1, 0, 0, 2, f(Yes, false, "")}, - {0xbe0c, 0, 0, 1, f(Yes, true, "")}, - {0xbe0d, 0, 0, 2, f(Yes, false, "")}, - {0xbe28, 0, 0, 1, f(Yes, true, "")}, - {0xbe29, 0, 0, 2, f(Yes, false, "")}, - {0xbe44, 0, 0, 1, f(Yes, true, "")}, - {0xbe45, 0, 0, 2, f(Yes, false, "")}, - {0xbe60, 0, 0, 1, f(Yes, true, "")}, - {0xbe61, 0, 0, 2, f(Yes, false, "")}, - {0xbe7c, 0, 0, 1, f(Yes, true, "")}, - {0xbe7d, 0, 0, 2, f(Yes, false, "")}, - {0xbe98, 0, 0, 1, f(Yes, true, "")}, - {0xbe99, 0, 0, 2, f(Yes, false, "")}, - {0xbeb4, 0, 0, 1, f(Yes, true, "")}, - {0xbeb5, 0, 0, 2, f(Yes, false, "")}, - {0xbed0, 0, 0, 1, f(Yes, true, "")}, - {0xbed1, 0, 0, 2, f(Yes, false, "")}, - {0xbeec, 0, 0, 1, f(Yes, true, "")}, - {0xbeed, 0, 0, 2, f(Yes, false, "")}, - {0xbf08, 0, 0, 1, f(Yes, true, "")}, - {0xbf09, 0, 0, 2, f(Yes, false, "")}, - {0xbf24, 0, 0, 1, f(Yes, true, "")}, - {0xbf25, 0, 0, 2, f(Yes, false, "")}, - {0xbf40, 0, 0, 1, f(Yes, true, "")}, - {0xbf41, 0, 0, 2, f(Yes, false, "")}, - {0xbf5c, 0, 0, 1, f(Yes, true, "")}, - {0xbf5d, 0, 0, 2, f(Yes, false, "")}, - {0xbf78, 0, 0, 1, f(Yes, true, "")}, - {0xbf79, 0, 0, 2, f(Yes, false, "")}, - {0xbf94, 0, 0, 1, f(Yes, true, "")}, - {0xbf95, 0, 0, 2, f(Yes, false, "")}, - {0xbfb0, 0, 0, 1, f(Yes, true, "")}, - {0xbfb1, 0, 0, 2, f(Yes, false, "")}, - {0xbfcc, 0, 0, 1, f(Yes, true, "")}, - {0xbfcd, 0, 0, 2, f(Yes, false, "")}, - {0xbfe8, 0, 0, 1, f(Yes, true, "")}, - {0xbfe9, 0, 0, 2, f(Yes, false, "")}, - {0xc004, 0, 0, 1, f(Yes, true, "")}, - {0xc005, 0, 0, 2, f(Yes, false, "")}, - {0xc020, 0, 0, 1, f(Yes, true, "")}, - {0xc021, 0, 0, 2, f(Yes, false, "")}, - {0xc03c, 0, 0, 1, f(Yes, true, "")}, - {0xc03d, 0, 0, 2, f(Yes, false, "")}, - {0xc058, 0, 0, 1, f(Yes, true, "")}, - {0xc059, 0, 0, 2, f(Yes, false, "")}, - {0xc074, 0, 0, 1, f(Yes, true, "")}, - {0xc075, 0, 0, 2, f(Yes, false, "")}, - {0xc090, 0, 0, 1, f(Yes, true, "")}, - {0xc091, 0, 0, 2, f(Yes, false, "")}, - {0xc0ac, 0, 0, 1, f(Yes, true, "")}, - {0xc0ad, 0, 0, 2, f(Yes, false, "")}, - {0xc0c8, 0, 0, 1, f(Yes, true, "")}, - {0xc0c9, 0, 0, 2, f(Yes, false, "")}, - {0xc0e4, 0, 0, 1, f(Yes, true, "")}, - {0xc0e5, 0, 0, 2, f(Yes, false, "")}, - {0xc100, 0, 0, 1, f(Yes, true, "")}, - {0xc101, 0, 0, 2, f(Yes, false, "")}, - {0xc11c, 0, 0, 1, f(Yes, true, "")}, - {0xc11d, 0, 0, 2, f(Yes, false, "")}, - {0xc138, 0, 0, 1, f(Yes, true, "")}, - {0xc139, 0, 0, 2, f(Yes, false, "")}, - {0xc154, 0, 0, 1, f(Yes, true, "")}, - {0xc155, 0, 0, 2, f(Yes, false, "")}, - {0xc170, 0, 0, 1, f(Yes, true, "")}, - {0xc171, 0, 0, 2, f(Yes, false, "")}, - {0xc18c, 0, 0, 1, f(Yes, true, "")}, - {0xc18d, 0, 0, 2, f(Yes, false, "")}, - {0xc1a8, 0, 0, 1, f(Yes, true, "")}, - {0xc1a9, 0, 0, 2, f(Yes, false, "")}, - {0xc1c4, 0, 0, 1, f(Yes, true, "")}, - {0xc1c5, 0, 0, 2, f(Yes, false, "")}, - {0xc1e0, 0, 0, 1, f(Yes, true, "")}, - {0xc1e1, 0, 0, 2, f(Yes, false, "")}, - {0xc1fc, 0, 0, 1, f(Yes, true, "")}, - {0xc1fd, 0, 0, 2, f(Yes, false, "")}, - {0xc218, 0, 0, 1, f(Yes, true, "")}, - {0xc219, 0, 0, 2, f(Yes, false, "")}, - {0xc234, 0, 0, 1, f(Yes, true, "")}, - {0xc235, 0, 0, 2, f(Yes, false, "")}, - {0xc250, 0, 0, 1, f(Yes, true, "")}, - {0xc251, 0, 0, 2, f(Yes, false, "")}, - {0xc26c, 0, 0, 1, f(Yes, true, "")}, - {0xc26d, 0, 0, 2, f(Yes, false, "")}, - {0xc288, 0, 0, 1, f(Yes, true, "")}, - {0xc289, 0, 0, 2, f(Yes, false, "")}, - {0xc2a4, 0, 0, 1, f(Yes, true, "")}, - {0xc2a5, 0, 0, 2, f(Yes, false, "")}, - {0xc2c0, 0, 0, 1, f(Yes, true, "")}, - {0xc2c1, 0, 0, 2, f(Yes, false, "")}, - {0xc2dc, 0, 0, 1, f(Yes, true, "")}, - {0xc2dd, 0, 0, 2, f(Yes, false, "")}, - {0xc2f8, 0, 0, 1, f(Yes, true, "")}, - {0xc2f9, 0, 0, 2, f(Yes, false, "")}, - {0xc314, 0, 0, 1, f(Yes, true, "")}, - {0xc315, 0, 0, 2, f(Yes, false, "")}, - {0xc330, 0, 0, 1, f(Yes, true, "")}, - {0xc331, 0, 0, 2, f(Yes, false, "")}, - {0xc34c, 0, 0, 1, f(Yes, true, "")}, - {0xc34d, 0, 0, 2, f(Yes, false, "")}, - {0xc368, 0, 0, 1, f(Yes, true, "")}, - {0xc369, 0, 0, 2, f(Yes, false, "")}, - {0xc384, 0, 0, 1, f(Yes, true, "")}, - {0xc385, 0, 0, 2, f(Yes, false, "")}, - {0xc3a0, 0, 0, 1, f(Yes, true, "")}, - {0xc3a1, 0, 0, 2, f(Yes, false, "")}, - {0xc3bc, 0, 0, 1, f(Yes, true, "")}, - {0xc3bd, 0, 0, 2, f(Yes, false, "")}, - {0xc3d8, 0, 0, 1, f(Yes, true, "")}, - {0xc3d9, 0, 0, 2, f(Yes, false, "")}, - {0xc3f4, 0, 0, 1, f(Yes, true, "")}, - {0xc3f5, 0, 0, 2, f(Yes, false, "")}, - {0xc410, 0, 0, 1, f(Yes, true, "")}, - {0xc411, 0, 0, 2, f(Yes, false, "")}, - {0xc42c, 0, 0, 1, f(Yes, true, "")}, - {0xc42d, 0, 0, 2, f(Yes, false, "")}, - {0xc448, 0, 0, 1, f(Yes, true, "")}, - {0xc449, 0, 0, 2, f(Yes, false, "")}, - {0xc464, 0, 0, 1, f(Yes, true, "")}, - {0xc465, 0, 0, 2, f(Yes, false, "")}, - {0xc480, 0, 0, 1, f(Yes, true, "")}, - {0xc481, 0, 0, 2, f(Yes, false, "")}, - {0xc49c, 0, 0, 1, f(Yes, true, "")}, - {0xc49d, 0, 0, 2, f(Yes, false, "")}, - {0xc4b8, 0, 0, 1, f(Yes, true, "")}, - {0xc4b9, 0, 0, 2, f(Yes, false, "")}, - {0xc4d4, 0, 0, 1, f(Yes, true, "")}, - {0xc4d5, 0, 0, 2, f(Yes, false, "")}, - {0xc4f0, 0, 0, 1, f(Yes, true, "")}, - {0xc4f1, 0, 0, 2, f(Yes, false, "")}, - {0xc50c, 0, 0, 1, f(Yes, true, "")}, - {0xc50d, 0, 0, 2, f(Yes, false, "")}, - {0xc528, 0, 0, 1, f(Yes, true, "")}, - {0xc529, 0, 0, 2, f(Yes, false, "")}, - {0xc544, 0, 0, 1, f(Yes, true, "")}, - {0xc545, 0, 0, 2, f(Yes, false, "")}, - {0xc560, 0, 0, 1, f(Yes, true, "")}, - {0xc561, 0, 0, 2, f(Yes, false, "")}, - {0xc57c, 0, 0, 1, f(Yes, true, "")}, - {0xc57d, 0, 0, 2, f(Yes, false, "")}, - {0xc598, 0, 0, 1, f(Yes, true, "")}, - {0xc599, 0, 0, 2, f(Yes, false, "")}, - {0xc5b4, 0, 0, 1, f(Yes, true, "")}, - {0xc5b5, 0, 0, 2, f(Yes, false, "")}, - {0xc5d0, 0, 0, 1, f(Yes, true, "")}, - {0xc5d1, 0, 0, 2, f(Yes, false, "")}, - {0xc5ec, 0, 0, 1, f(Yes, true, "")}, - {0xc5ed, 0, 0, 2, f(Yes, false, "")}, - {0xc608, 0, 0, 1, f(Yes, true, "")}, - {0xc609, 0, 0, 2, f(Yes, false, "")}, - {0xc624, 0, 0, 1, f(Yes, true, "")}, - {0xc625, 0, 0, 2, f(Yes, false, "")}, - {0xc640, 0, 0, 1, f(Yes, true, "")}, - {0xc641, 0, 0, 2, f(Yes, false, "")}, - {0xc65c, 0, 0, 1, f(Yes, true, "")}, - {0xc65d, 0, 0, 2, f(Yes, false, "")}, - {0xc678, 0, 0, 1, f(Yes, true, "")}, - {0xc679, 0, 0, 2, f(Yes, false, "")}, - {0xc694, 0, 0, 1, f(Yes, true, "")}, - {0xc695, 0, 0, 2, f(Yes, false, "")}, - {0xc6b0, 0, 0, 1, f(Yes, true, "")}, - {0xc6b1, 0, 0, 2, f(Yes, false, "")}, - {0xc6cc, 0, 0, 1, f(Yes, true, "")}, - {0xc6cd, 0, 0, 2, f(Yes, false, "")}, - {0xc6e8, 0, 0, 1, f(Yes, true, "")}, - {0xc6e9, 0, 0, 2, f(Yes, false, "")}, - {0xc704, 0, 0, 1, f(Yes, true, "")}, - {0xc705, 0, 0, 2, f(Yes, false, "")}, - {0xc720, 0, 0, 1, f(Yes, true, "")}, - {0xc721, 0, 0, 2, f(Yes, false, "")}, - {0xc73c, 0, 0, 1, f(Yes, true, "")}, - {0xc73d, 0, 0, 2, f(Yes, false, "")}, - {0xc758, 0, 0, 1, f(Yes, true, "")}, - {0xc759, 0, 0, 2, f(Yes, false, "")}, - {0xc774, 0, 0, 1, f(Yes, true, "")}, - {0xc775, 0, 0, 2, f(Yes, false, "")}, - {0xc790, 0, 0, 1, f(Yes, true, "")}, - {0xc791, 0, 0, 2, f(Yes, false, "")}, - {0xc7ac, 0, 0, 1, f(Yes, true, "")}, - {0xc7ad, 0, 0, 2, f(Yes, false, "")}, - {0xc7c8, 0, 0, 1, f(Yes, true, "")}, - {0xc7c9, 0, 0, 2, f(Yes, false, "")}, - {0xc7e4, 0, 0, 1, f(Yes, true, "")}, - {0xc7e5, 0, 0, 2, f(Yes, false, "")}, - {0xc800, 0, 0, 1, f(Yes, true, "")}, - {0xc801, 0, 0, 2, f(Yes, false, "")}, - {0xc81c, 0, 0, 1, f(Yes, true, "")}, - {0xc81d, 0, 0, 2, f(Yes, false, "")}, - {0xc838, 0, 0, 1, f(Yes, true, "")}, - {0xc839, 0, 0, 2, f(Yes, false, "")}, - {0xc854, 0, 0, 1, f(Yes, true, "")}, - {0xc855, 0, 0, 2, f(Yes, false, "")}, - {0xc870, 0, 0, 1, f(Yes, true, "")}, - {0xc871, 0, 0, 2, f(Yes, false, "")}, - {0xc88c, 0, 0, 1, f(Yes, true, "")}, - {0xc88d, 0, 0, 2, f(Yes, false, "")}, - {0xc8a8, 0, 0, 1, f(Yes, true, "")}, - {0xc8a9, 0, 0, 2, f(Yes, false, "")}, - {0xc8c4, 0, 0, 1, f(Yes, true, "")}, - {0xc8c5, 0, 0, 2, f(Yes, false, "")}, - {0xc8e0, 0, 0, 1, f(Yes, true, "")}, - {0xc8e1, 0, 0, 2, f(Yes, false, "")}, - {0xc8fc, 0, 0, 1, f(Yes, true, "")}, - {0xc8fd, 0, 0, 2, f(Yes, false, "")}, - {0xc918, 0, 0, 1, f(Yes, true, "")}, - {0xc919, 0, 0, 2, f(Yes, false, "")}, - {0xc934, 0, 0, 1, f(Yes, true, "")}, - {0xc935, 0, 0, 2, f(Yes, false, "")}, - {0xc950, 0, 0, 1, f(Yes, true, "")}, - {0xc951, 0, 0, 2, f(Yes, false, "")}, - {0xc96c, 0, 0, 1, f(Yes, true, "")}, - {0xc96d, 0, 0, 2, f(Yes, false, "")}, - {0xc988, 0, 0, 1, f(Yes, true, "")}, - {0xc989, 0, 0, 2, f(Yes, false, "")}, - {0xc9a4, 0, 0, 1, f(Yes, true, "")}, - {0xc9a5, 0, 0, 2, f(Yes, false, "")}, - {0xc9c0, 0, 0, 1, f(Yes, true, "")}, - {0xc9c1, 0, 0, 2, f(Yes, false, "")}, - {0xc9dc, 0, 0, 1, f(Yes, true, "")}, - {0xc9dd, 0, 0, 2, f(Yes, false, "")}, - {0xc9f8, 0, 0, 1, f(Yes, true, "")}, - {0xc9f9, 0, 0, 2, f(Yes, false, "")}, - {0xca14, 0, 0, 1, f(Yes, true, "")}, - {0xca15, 0, 0, 2, f(Yes, false, "")}, - {0xca30, 0, 0, 1, f(Yes, true, "")}, - {0xca31, 0, 0, 2, f(Yes, false, "")}, - {0xca4c, 0, 0, 1, f(Yes, true, "")}, - {0xca4d, 0, 0, 2, f(Yes, false, "")}, - {0xca68, 0, 0, 1, f(Yes, true, "")}, - {0xca69, 0, 0, 2, f(Yes, false, "")}, - {0xca84, 0, 0, 1, f(Yes, true, "")}, - {0xca85, 0, 0, 2, f(Yes, false, "")}, - {0xcaa0, 0, 0, 1, f(Yes, true, "")}, - {0xcaa1, 0, 0, 2, f(Yes, false, "")}, - {0xcabc, 0, 0, 1, f(Yes, true, "")}, - {0xcabd, 0, 0, 2, f(Yes, false, "")}, - {0xcad8, 0, 0, 1, f(Yes, true, "")}, - {0xcad9, 0, 0, 2, f(Yes, false, "")}, - {0xcaf4, 0, 0, 1, f(Yes, true, "")}, - {0xcaf5, 0, 0, 2, f(Yes, false, "")}, - {0xcb10, 0, 0, 1, f(Yes, true, "")}, - {0xcb11, 0, 0, 2, f(Yes, false, "")}, - {0xcb2c, 0, 0, 1, f(Yes, true, "")}, - {0xcb2d, 0, 0, 2, f(Yes, false, "")}, - {0xcb48, 0, 0, 1, f(Yes, true, "")}, - {0xcb49, 0, 0, 2, f(Yes, false, "")}, - {0xcb64, 0, 0, 1, f(Yes, true, "")}, - {0xcb65, 0, 0, 2, f(Yes, false, "")}, - {0xcb80, 0, 0, 1, f(Yes, true, "")}, - {0xcb81, 0, 0, 2, f(Yes, false, "")}, - {0xcb9c, 0, 0, 1, f(Yes, true, "")}, - {0xcb9d, 0, 0, 2, f(Yes, false, "")}, - {0xcbb8, 0, 0, 1, f(Yes, true, "")}, - {0xcbb9, 0, 0, 2, f(Yes, false, "")}, - {0xcbd4, 0, 0, 1, f(Yes, true, "")}, - {0xcbd5, 0, 0, 2, f(Yes, false, "")}, - {0xcbf0, 0, 0, 1, f(Yes, true, "")}, - {0xcbf1, 0, 0, 2, f(Yes, false, "")}, - {0xcc0c, 0, 0, 1, f(Yes, true, "")}, - {0xcc0d, 0, 0, 2, f(Yes, false, "")}, - {0xcc28, 0, 0, 1, f(Yes, true, "")}, - {0xcc29, 0, 0, 2, f(Yes, false, "")}, - {0xcc44, 0, 0, 1, f(Yes, true, "")}, - {0xcc45, 0, 0, 2, f(Yes, false, "")}, - {0xcc60, 0, 0, 1, f(Yes, true, "")}, - {0xcc61, 0, 0, 2, f(Yes, false, "")}, - {0xcc7c, 0, 0, 1, f(Yes, true, "")}, - {0xcc7d, 0, 0, 2, f(Yes, false, "")}, - {0xcc98, 0, 0, 1, f(Yes, true, "")}, - {0xcc99, 0, 0, 2, f(Yes, false, "")}, - {0xccb4, 0, 0, 1, f(Yes, true, "")}, - {0xccb5, 0, 0, 2, f(Yes, false, "")}, - {0xccd0, 0, 0, 1, f(Yes, true, "")}, - {0xccd1, 0, 0, 2, f(Yes, false, "")}, - {0xccec, 0, 0, 1, f(Yes, true, "")}, - {0xcced, 0, 0, 2, f(Yes, false, "")}, - {0xcd08, 0, 0, 1, f(Yes, true, "")}, - {0xcd09, 0, 0, 2, f(Yes, false, "")}, - {0xcd24, 0, 0, 1, f(Yes, true, "")}, - {0xcd25, 0, 0, 2, f(Yes, false, "")}, - {0xcd40, 0, 0, 1, f(Yes, true, "")}, - {0xcd41, 0, 0, 2, f(Yes, false, "")}, - {0xcd5c, 0, 0, 1, f(Yes, true, "")}, - {0xcd5d, 0, 0, 2, f(Yes, false, "")}, - {0xcd78, 0, 0, 1, f(Yes, true, "")}, - {0xcd79, 0, 0, 2, f(Yes, false, "")}, - {0xcd94, 0, 0, 1, f(Yes, true, "")}, - {0xcd95, 0, 0, 2, f(Yes, false, "")}, - {0xcdb0, 0, 0, 1, f(Yes, true, "")}, - {0xcdb1, 0, 0, 2, f(Yes, false, "")}, - {0xcdcc, 0, 0, 1, f(Yes, true, "")}, - {0xcdcd, 0, 0, 2, f(Yes, false, "")}, - {0xcde8, 0, 0, 1, f(Yes, true, "")}, - {0xcde9, 0, 0, 2, f(Yes, false, "")}, - {0xce04, 0, 0, 1, f(Yes, true, "")}, - {0xce05, 0, 0, 2, f(Yes, false, "")}, - {0xce20, 0, 0, 1, f(Yes, true, "")}, - {0xce21, 0, 0, 2, f(Yes, false, "")}, - {0xce3c, 0, 0, 1, f(Yes, true, "")}, - {0xce3d, 0, 0, 2, f(Yes, false, "")}, - {0xce58, 0, 0, 1, f(Yes, true, "")}, - {0xce59, 0, 0, 2, f(Yes, false, "")}, - {0xce74, 0, 0, 1, f(Yes, true, "")}, - {0xce75, 0, 0, 2, f(Yes, false, "")}, - {0xce90, 0, 0, 1, f(Yes, true, "")}, - {0xce91, 0, 0, 2, f(Yes, false, "")}, - {0xceac, 0, 0, 1, f(Yes, true, "")}, - {0xcead, 0, 0, 2, f(Yes, false, "")}, - {0xcec8, 0, 0, 1, f(Yes, true, "")}, - {0xcec9, 0, 0, 2, f(Yes, false, "")}, - {0xcee4, 0, 0, 1, f(Yes, true, "")}, - {0xcee5, 0, 0, 2, f(Yes, false, "")}, - {0xcf00, 0, 0, 1, f(Yes, true, "")}, - {0xcf01, 0, 0, 2, f(Yes, false, "")}, - {0xcf1c, 0, 0, 1, f(Yes, true, "")}, - {0xcf1d, 0, 0, 2, f(Yes, false, "")}, - {0xcf38, 0, 0, 1, f(Yes, true, "")}, - {0xcf39, 0, 0, 2, f(Yes, false, "")}, - {0xcf54, 0, 0, 1, f(Yes, true, "")}, - {0xcf55, 0, 0, 2, f(Yes, false, "")}, - {0xcf70, 0, 0, 1, f(Yes, true, "")}, - {0xcf71, 0, 0, 2, f(Yes, false, "")}, - {0xcf8c, 0, 0, 1, f(Yes, true, "")}, - {0xcf8d, 0, 0, 2, f(Yes, false, "")}, - {0xcfa8, 0, 0, 1, f(Yes, true, "")}, - {0xcfa9, 0, 0, 2, f(Yes, false, "")}, - {0xcfc4, 0, 0, 1, f(Yes, true, "")}, - {0xcfc5, 0, 0, 2, f(Yes, false, "")}, - {0xcfe0, 0, 0, 1, f(Yes, true, "")}, - {0xcfe1, 0, 0, 2, f(Yes, false, "")}, - {0xcffc, 0, 0, 1, f(Yes, true, "")}, - {0xcffd, 0, 0, 2, f(Yes, false, "")}, - {0xd018, 0, 0, 1, f(Yes, true, "")}, - {0xd019, 0, 0, 2, f(Yes, false, "")}, - {0xd034, 0, 0, 1, f(Yes, true, "")}, - {0xd035, 0, 0, 2, f(Yes, false, "")}, - {0xd050, 0, 0, 1, f(Yes, true, "")}, - {0xd051, 0, 0, 2, f(Yes, false, "")}, - {0xd06c, 0, 0, 1, f(Yes, true, "")}, - {0xd06d, 0, 0, 2, f(Yes, false, "")}, - {0xd088, 0, 0, 1, f(Yes, true, "")}, - {0xd089, 0, 0, 2, f(Yes, false, "")}, - {0xd0a4, 0, 0, 1, f(Yes, true, "")}, - {0xd0a5, 0, 0, 2, f(Yes, false, "")}, - {0xd0c0, 0, 0, 1, f(Yes, true, "")}, - {0xd0c1, 0, 0, 2, f(Yes, false, "")}, - {0xd0dc, 0, 0, 1, f(Yes, true, "")}, - {0xd0dd, 0, 0, 2, f(Yes, false, "")}, - {0xd0f8, 0, 0, 1, f(Yes, true, "")}, - {0xd0f9, 0, 0, 2, f(Yes, false, "")}, - {0xd114, 0, 0, 1, f(Yes, true, "")}, - {0xd115, 0, 0, 2, f(Yes, false, "")}, - {0xd130, 0, 0, 1, f(Yes, true, "")}, - {0xd131, 0, 0, 2, f(Yes, false, "")}, - {0xd14c, 0, 0, 1, f(Yes, true, "")}, - {0xd14d, 0, 0, 2, f(Yes, false, "")}, - {0xd168, 0, 0, 1, f(Yes, true, "")}, - {0xd169, 0, 0, 2, f(Yes, false, "")}, - {0xd184, 0, 0, 1, f(Yes, true, "")}, - {0xd185, 0, 0, 2, f(Yes, false, "")}, - {0xd1a0, 0, 0, 1, f(Yes, true, "")}, - {0xd1a1, 0, 0, 2, f(Yes, false, "")}, - {0xd1bc, 0, 0, 1, f(Yes, true, "")}, - {0xd1bd, 0, 0, 2, f(Yes, false, "")}, - {0xd1d8, 0, 0, 1, f(Yes, true, "")}, - {0xd1d9, 0, 0, 2, f(Yes, false, "")}, - {0xd1f4, 0, 0, 1, f(Yes, true, "")}, - {0xd1f5, 0, 0, 2, f(Yes, false, "")}, - {0xd210, 0, 0, 1, f(Yes, true, "")}, - {0xd211, 0, 0, 2, f(Yes, false, "")}, - {0xd22c, 0, 0, 1, f(Yes, true, "")}, - {0xd22d, 0, 0, 2, f(Yes, false, "")}, - {0xd248, 0, 0, 1, f(Yes, true, "")}, - {0xd249, 0, 0, 2, f(Yes, false, "")}, - {0xd264, 0, 0, 1, f(Yes, true, "")}, - {0xd265, 0, 0, 2, f(Yes, false, "")}, - {0xd280, 0, 0, 1, f(Yes, true, "")}, - {0xd281, 0, 0, 2, f(Yes, false, "")}, - {0xd29c, 0, 0, 1, f(Yes, true, "")}, - {0xd29d, 0, 0, 2, f(Yes, false, "")}, - {0xd2b8, 0, 0, 1, f(Yes, true, "")}, - {0xd2b9, 0, 0, 2, f(Yes, false, "")}, - {0xd2d4, 0, 0, 1, f(Yes, true, "")}, - {0xd2d5, 0, 0, 2, f(Yes, false, "")}, - {0xd2f0, 0, 0, 1, f(Yes, true, "")}, - {0xd2f1, 0, 0, 2, f(Yes, false, "")}, - {0xd30c, 0, 0, 1, f(Yes, true, "")}, - {0xd30d, 0, 0, 2, f(Yes, false, "")}, - {0xd328, 0, 0, 1, f(Yes, true, "")}, - {0xd329, 0, 0, 2, f(Yes, false, "")}, - {0xd344, 0, 0, 1, f(Yes, true, "")}, - {0xd345, 0, 0, 2, f(Yes, false, "")}, - {0xd360, 0, 0, 1, f(Yes, true, "")}, - {0xd361, 0, 0, 2, f(Yes, false, "")}, - {0xd37c, 0, 0, 1, f(Yes, true, "")}, - {0xd37d, 0, 0, 2, f(Yes, false, "")}, - {0xd398, 0, 0, 1, f(Yes, true, "")}, - {0xd399, 0, 0, 2, f(Yes, false, "")}, - {0xd3b4, 0, 0, 1, f(Yes, true, "")}, - {0xd3b5, 0, 0, 2, f(Yes, false, "")}, - {0xd3d0, 0, 0, 1, f(Yes, true, "")}, - {0xd3d1, 0, 0, 2, f(Yes, false, "")}, - {0xd3ec, 0, 0, 1, f(Yes, true, "")}, - {0xd3ed, 0, 0, 2, f(Yes, false, "")}, - {0xd408, 0, 0, 1, f(Yes, true, "")}, - {0xd409, 0, 0, 2, f(Yes, false, "")}, - {0xd424, 0, 0, 1, f(Yes, true, "")}, - {0xd425, 0, 0, 2, f(Yes, false, "")}, - {0xd440, 0, 0, 1, f(Yes, true, "")}, - {0xd441, 0, 0, 2, f(Yes, false, "")}, - {0xd45c, 0, 0, 1, f(Yes, true, "")}, - {0xd45d, 0, 0, 2, f(Yes, false, "")}, - {0xd478, 0, 0, 1, f(Yes, true, "")}, - {0xd479, 0, 0, 2, f(Yes, false, "")}, - {0xd494, 0, 0, 1, f(Yes, true, "")}, - {0xd495, 0, 0, 2, f(Yes, false, "")}, - {0xd4b0, 0, 0, 1, f(Yes, true, "")}, - {0xd4b1, 0, 0, 2, f(Yes, false, "")}, - {0xd4cc, 0, 0, 1, f(Yes, true, "")}, - {0xd4cd, 0, 0, 2, f(Yes, false, "")}, - {0xd4e8, 0, 0, 1, f(Yes, true, "")}, - {0xd4e9, 0, 0, 2, f(Yes, false, "")}, - {0xd504, 0, 0, 1, f(Yes, true, "")}, - {0xd505, 0, 0, 2, f(Yes, false, "")}, - {0xd520, 0, 0, 1, f(Yes, true, "")}, - {0xd521, 0, 0, 2, f(Yes, false, "")}, - {0xd53c, 0, 0, 1, f(Yes, true, "")}, - {0xd53d, 0, 0, 2, f(Yes, false, "")}, - {0xd558, 0, 0, 1, f(Yes, true, "")}, - {0xd559, 0, 0, 2, f(Yes, false, "")}, - {0xd574, 0, 0, 1, f(Yes, true, "")}, - {0xd575, 0, 0, 2, f(Yes, false, "")}, - {0xd590, 0, 0, 1, f(Yes, true, "")}, - {0xd591, 0, 0, 2, f(Yes, false, "")}, - {0xd5ac, 0, 0, 1, f(Yes, true, "")}, - {0xd5ad, 0, 0, 2, f(Yes, false, "")}, - {0xd5c8, 0, 0, 1, f(Yes, true, "")}, - {0xd5c9, 0, 0, 2, f(Yes, false, "")}, - {0xd5e4, 0, 0, 1, f(Yes, true, "")}, - {0xd5e5, 0, 0, 2, f(Yes, false, "")}, - {0xd600, 0, 0, 1, f(Yes, true, "")}, - {0xd601, 0, 0, 2, f(Yes, false, "")}, - {0xd61c, 0, 0, 1, f(Yes, true, "")}, - {0xd61d, 0, 0, 2, f(Yes, false, "")}, - {0xd638, 0, 0, 1, f(Yes, true, "")}, - {0xd639, 0, 0, 2, f(Yes, false, "")}, - {0xd654, 0, 0, 1, f(Yes, true, "")}, - {0xd655, 0, 0, 2, f(Yes, false, "")}, - {0xd670, 0, 0, 1, f(Yes, true, "")}, - {0xd671, 0, 0, 2, f(Yes, false, "")}, - {0xd68c, 0, 0, 1, f(Yes, true, "")}, - {0xd68d, 0, 0, 2, f(Yes, false, "")}, - {0xd6a8, 0, 0, 1, f(Yes, true, "")}, - {0xd6a9, 0, 0, 2, f(Yes, false, "")}, - {0xd6c4, 0, 0, 1, f(Yes, true, "")}, - {0xd6c5, 0, 0, 2, f(Yes, false, "")}, - {0xd6e0, 0, 0, 1, f(Yes, true, "")}, - {0xd6e1, 0, 0, 2, f(Yes, false, "")}, - {0xd6fc, 0, 0, 1, f(Yes, true, "")}, - {0xd6fd, 0, 0, 2, f(Yes, false, "")}, - {0xd718, 0, 0, 1, f(Yes, true, "")}, - {0xd719, 0, 0, 2, f(Yes, false, "")}, - {0xd734, 0, 0, 1, f(Yes, true, "")}, - {0xd735, 0, 0, 2, f(Yes, false, "")}, - {0xd750, 0, 0, 1, f(Yes, true, "")}, - {0xd751, 0, 0, 2, f(Yes, false, "")}, - {0xd76c, 0, 0, 1, f(Yes, true, "")}, - {0xd76d, 0, 0, 2, f(Yes, false, "")}, - {0xd788, 0, 0, 1, f(Yes, true, "")}, - {0xd789, 0, 0, 2, f(Yes, false, "")}, - {0xd7a4, 0, 0, 0, f(Yes, false, "")}, - {0xf900, 0, 0, 0, f(No, false, "豈")}, - {0xf901, 0, 0, 0, f(No, false, "更")}, - {0xf902, 0, 0, 0, f(No, false, "車")}, - {0xf903, 0, 0, 0, f(No, false, "賈")}, - {0xf904, 0, 0, 0, f(No, false, "滑")}, - {0xf905, 0, 0, 0, f(No, false, "串")}, - {0xf906, 0, 0, 0, f(No, false, "句")}, - {0xf907, 0, 0, 0, f(No, false, "龜")}, - {0xf909, 0, 0, 0, f(No, false, "契")}, - {0xf90a, 0, 0, 0, f(No, false, "金")}, - {0xf90b, 0, 0, 0, f(No, false, "喇")}, - {0xf90c, 0, 0, 0, f(No, false, "奈")}, - {0xf90d, 0, 0, 0, f(No, false, "懶")}, - {0xf90e, 0, 0, 0, f(No, false, "癩")}, - {0xf90f, 0, 0, 0, f(No, false, "羅")}, - {0xf910, 0, 0, 0, f(No, false, "蘿")}, - {0xf911, 0, 0, 0, f(No, false, "螺")}, - {0xf912, 0, 0, 0, f(No, false, "裸")}, - {0xf913, 0, 0, 0, f(No, false, "邏")}, - {0xf914, 0, 0, 0, f(No, false, "樂")}, - {0xf915, 0, 0, 0, f(No, false, "洛")}, - {0xf916, 0, 0, 0, f(No, false, "烙")}, - {0xf917, 0, 0, 0, f(No, false, "珞")}, - {0xf918, 0, 0, 0, f(No, false, "落")}, - {0xf919, 0, 0, 0, f(No, false, "酪")}, - {0xf91a, 0, 0, 0, f(No, false, "駱")}, - {0xf91b, 0, 0, 0, f(No, false, "亂")}, - {0xf91c, 0, 0, 0, f(No, false, "卵")}, - {0xf91d, 0, 0, 0, f(No, false, "欄")}, - {0xf91e, 0, 0, 0, f(No, false, "爛")}, - {0xf91f, 0, 0, 0, f(No, false, "蘭")}, - {0xf920, 0, 0, 0, f(No, false, "鸞")}, - {0xf921, 0, 0, 0, f(No, false, "嵐")}, - {0xf922, 0, 0, 0, f(No, false, "濫")}, - {0xf923, 0, 0, 0, f(No, false, "藍")}, - {0xf924, 0, 0, 0, f(No, false, "襤")}, - {0xf925, 0, 0, 0, f(No, false, "拉")}, - {0xf926, 0, 0, 0, f(No, false, "臘")}, - {0xf927, 0, 0, 0, f(No, false, "蠟")}, - {0xf928, 0, 0, 0, f(No, false, "廊")}, - {0xf929, 0, 0, 0, f(No, false, "朗")}, - {0xf92a, 0, 0, 0, f(No, false, "浪")}, - {0xf92b, 0, 0, 0, f(No, false, "狼")}, - {0xf92c, 0, 0, 0, f(No, false, "郎")}, - {0xf92d, 0, 0, 0, f(No, false, "來")}, - {0xf92e, 0, 0, 0, f(No, false, "冷")}, - {0xf92f, 0, 0, 0, f(No, false, "勞")}, - {0xf930, 0, 0, 0, f(No, false, "擄")}, - {0xf931, 0, 0, 0, f(No, false, "櫓")}, - {0xf932, 0, 0, 0, f(No, false, "爐")}, - {0xf933, 0, 0, 0, f(No, false, "盧")}, - {0xf934, 0, 0, 0, f(No, false, "老")}, - {0xf935, 0, 0, 0, f(No, false, "蘆")}, - {0xf936, 0, 0, 0, f(No, false, "虜")}, - {0xf937, 0, 0, 0, f(No, false, "路")}, - {0xf938, 0, 0, 0, f(No, false, "露")}, - {0xf939, 0, 0, 0, f(No, false, "魯")}, - {0xf93a, 0, 0, 0, f(No, false, "鷺")}, - {0xf93b, 0, 0, 0, f(No, false, "碌")}, - {0xf93c, 0, 0, 0, f(No, false, "祿")}, - {0xf93d, 0, 0, 0, f(No, false, "綠")}, - {0xf93e, 0, 0, 0, f(No, false, "菉")}, - {0xf93f, 0, 0, 0, f(No, false, "錄")}, - {0xf940, 0, 0, 0, f(No, false, "鹿")}, - {0xf941, 0, 0, 0, f(No, false, "論")}, - {0xf942, 0, 0, 0, f(No, false, "壟")}, - {0xf943, 0, 0, 0, f(No, false, "弄")}, - {0xf944, 0, 0, 0, f(No, false, "籠")}, - {0xf945, 0, 0, 0, f(No, false, "聾")}, - {0xf946, 0, 0, 0, f(No, false, "牢")}, - {0xf947, 0, 0, 0, f(No, false, "磊")}, - {0xf948, 0, 0, 0, f(No, false, "賂")}, - {0xf949, 0, 0, 0, f(No, false, "雷")}, - {0xf94a, 0, 0, 0, f(No, false, "壘")}, - {0xf94b, 0, 0, 0, f(No, false, "屢")}, - {0xf94c, 0, 0, 0, f(No, false, "樓")}, - {0xf94d, 0, 0, 0, f(No, false, "淚")}, - {0xf94e, 0, 0, 0, f(No, false, "漏")}, - {0xf94f, 0, 0, 0, f(No, false, "累")}, - {0xf950, 0, 0, 0, f(No, false, "縷")}, - {0xf951, 0, 0, 0, f(No, false, "陋")}, - {0xf952, 0, 0, 0, f(No, false, "勒")}, - {0xf953, 0, 0, 0, f(No, false, "肋")}, - {0xf954, 0, 0, 0, f(No, false, "凜")}, - {0xf955, 0, 0, 0, f(No, false, "凌")}, - {0xf956, 0, 0, 0, f(No, false, "稜")}, - {0xf957, 0, 0, 0, f(No, false, "綾")}, - {0xf958, 0, 0, 0, f(No, false, "菱")}, - {0xf959, 0, 0, 0, f(No, false, "陵")}, - {0xf95a, 0, 0, 0, f(No, false, "讀")}, - {0xf95b, 0, 0, 0, f(No, false, "拏")}, - {0xf95c, 0, 0, 0, f(No, false, "樂")}, - {0xf95d, 0, 0, 0, f(No, false, "諾")}, - {0xf95e, 0, 0, 0, f(No, false, "丹")}, - {0xf95f, 0, 0, 0, f(No, false, "寧")}, - {0xf960, 0, 0, 0, f(No, false, "怒")}, - {0xf961, 0, 0, 0, f(No, false, "率")}, - {0xf962, 0, 0, 0, f(No, false, "異")}, - {0xf963, 0, 0, 0, f(No, false, "北")}, - {0xf964, 0, 0, 0, f(No, false, "磻")}, - {0xf965, 0, 0, 0, f(No, false, "便")}, - {0xf966, 0, 0, 0, f(No, false, "復")}, - {0xf967, 0, 0, 0, f(No, false, "不")}, - {0xf968, 0, 0, 0, f(No, false, "泌")}, - {0xf969, 0, 0, 0, f(No, false, "數")}, - {0xf96a, 0, 0, 0, f(No, false, "索")}, - {0xf96b, 0, 0, 0, f(No, false, "參")}, - {0xf96c, 0, 0, 0, f(No, false, "塞")}, - {0xf96d, 0, 0, 0, f(No, false, "省")}, - {0xf96e, 0, 0, 0, f(No, false, "葉")}, - {0xf96f, 0, 0, 0, f(No, false, "說")}, - {0xf970, 0, 0, 0, f(No, false, "殺")}, - {0xf971, 0, 0, 0, f(No, false, "辰")}, - {0xf972, 0, 0, 0, f(No, false, "沈")}, - {0xf973, 0, 0, 0, f(No, false, "拾")}, - {0xf974, 0, 0, 0, f(No, false, "若")}, - {0xf975, 0, 0, 0, f(No, false, "掠")}, - {0xf976, 0, 0, 0, f(No, false, "略")}, - {0xf977, 0, 0, 0, f(No, false, "亮")}, - {0xf978, 0, 0, 0, f(No, false, "兩")}, - {0xf979, 0, 0, 0, f(No, false, "凉")}, - {0xf97a, 0, 0, 0, f(No, false, "梁")}, - {0xf97b, 0, 0, 0, f(No, false, "糧")}, - {0xf97c, 0, 0, 0, f(No, false, "良")}, - {0xf97d, 0, 0, 0, f(No, false, "諒")}, - {0xf97e, 0, 0, 0, f(No, false, "量")}, - {0xf97f, 0, 0, 0, f(No, false, "勵")}, - {0xf980, 0, 0, 0, f(No, false, "呂")}, - {0xf981, 0, 0, 0, f(No, false, "女")}, - {0xf982, 0, 0, 0, f(No, false, "廬")}, - {0xf983, 0, 0, 0, f(No, false, "旅")}, - {0xf984, 0, 0, 0, f(No, false, "濾")}, - {0xf985, 0, 0, 0, f(No, false, "礪")}, - {0xf986, 0, 0, 0, f(No, false, "閭")}, - {0xf987, 0, 0, 0, f(No, false, "驪")}, - {0xf988, 0, 0, 0, f(No, false, "麗")}, - {0xf989, 0, 0, 0, f(No, false, "黎")}, - {0xf98a, 0, 0, 0, f(No, false, "力")}, - {0xf98b, 0, 0, 0, f(No, false, "曆")}, - {0xf98c, 0, 0, 0, f(No, false, "歷")}, - {0xf98d, 0, 0, 0, f(No, false, "轢")}, - {0xf98e, 0, 0, 0, f(No, false, "年")}, - {0xf98f, 0, 0, 0, f(No, false, "憐")}, - {0xf990, 0, 0, 0, f(No, false, "戀")}, - {0xf991, 0, 0, 0, f(No, false, "撚")}, - {0xf992, 0, 0, 0, f(No, false, "漣")}, - {0xf993, 0, 0, 0, f(No, false, "煉")}, - {0xf994, 0, 0, 0, f(No, false, "璉")}, - {0xf995, 0, 0, 0, f(No, false, "秊")}, - {0xf996, 0, 0, 0, f(No, false, "練")}, - {0xf997, 0, 0, 0, f(No, false, "聯")}, - {0xf998, 0, 0, 0, f(No, false, "輦")}, - {0xf999, 0, 0, 0, f(No, false, "蓮")}, - {0xf99a, 0, 0, 0, f(No, false, "連")}, - {0xf99b, 0, 0, 0, f(No, false, "鍊")}, - {0xf99c, 0, 0, 0, f(No, false, "列")}, - {0xf99d, 0, 0, 0, f(No, false, "劣")}, - {0xf99e, 0, 0, 0, f(No, false, "咽")}, - {0xf99f, 0, 0, 0, f(No, false, "烈")}, - {0xf9a0, 0, 0, 0, f(No, false, "裂")}, - {0xf9a1, 0, 0, 0, f(No, false, "說")}, - {0xf9a2, 0, 0, 0, f(No, false, "廉")}, - {0xf9a3, 0, 0, 0, f(No, false, "念")}, - {0xf9a4, 0, 0, 0, f(No, false, "捻")}, - {0xf9a5, 0, 0, 0, f(No, false, "殮")}, - {0xf9a6, 0, 0, 0, f(No, false, "簾")}, - {0xf9a7, 0, 0, 0, f(No, false, "獵")}, - {0xf9a8, 0, 0, 0, f(No, false, "令")}, - {0xf9a9, 0, 0, 0, f(No, false, "囹")}, - {0xf9aa, 0, 0, 0, f(No, false, "寧")}, - {0xf9ab, 0, 0, 0, f(No, false, "嶺")}, - {0xf9ac, 0, 0, 0, f(No, false, "怜")}, - {0xf9ad, 0, 0, 0, f(No, false, "玲")}, - {0xf9ae, 0, 0, 0, f(No, false, "瑩")}, - {0xf9af, 0, 0, 0, f(No, false, "羚")}, - {0xf9b0, 0, 0, 0, f(No, false, "聆")}, - {0xf9b1, 0, 0, 0, f(No, false, "鈴")}, - {0xf9b2, 0, 0, 0, f(No, false, "零")}, - {0xf9b3, 0, 0, 0, f(No, false, "靈")}, - {0xf9b4, 0, 0, 0, f(No, false, "領")}, - {0xf9b5, 0, 0, 0, f(No, false, "例")}, - {0xf9b6, 0, 0, 0, f(No, false, "禮")}, - {0xf9b7, 0, 0, 0, f(No, false, "醴")}, - {0xf9b8, 0, 0, 0, f(No, false, "隸")}, - {0xf9b9, 0, 0, 0, f(No, false, "惡")}, - {0xf9ba, 0, 0, 0, f(No, false, "了")}, - {0xf9bb, 0, 0, 0, f(No, false, "僚")}, - {0xf9bc, 0, 0, 0, f(No, false, "寮")}, - {0xf9bd, 0, 0, 0, f(No, false, "尿")}, - {0xf9be, 0, 0, 0, f(No, false, "料")}, - {0xf9bf, 0, 0, 0, f(No, false, "樂")}, - {0xf9c0, 0, 0, 0, f(No, false, "燎")}, - {0xf9c1, 0, 0, 0, f(No, false, "療")}, - {0xf9c2, 0, 0, 0, f(No, false, "蓼")}, - {0xf9c3, 0, 0, 0, f(No, false, "遼")}, - {0xf9c4, 0, 0, 0, f(No, false, "龍")}, - {0xf9c5, 0, 0, 0, f(No, false, "暈")}, - {0xf9c6, 0, 0, 0, f(No, false, "阮")}, - {0xf9c7, 0, 0, 0, f(No, false, "劉")}, - {0xf9c8, 0, 0, 0, f(No, false, "杻")}, - {0xf9c9, 0, 0, 0, f(No, false, "柳")}, - {0xf9ca, 0, 0, 0, f(No, false, "流")}, - {0xf9cb, 0, 0, 0, f(No, false, "溜")}, - {0xf9cc, 0, 0, 0, f(No, false, "琉")}, - {0xf9cd, 0, 0, 0, f(No, false, "留")}, - {0xf9ce, 0, 0, 0, f(No, false, "硫")}, - {0xf9cf, 0, 0, 0, f(No, false, "紐")}, - {0xf9d0, 0, 0, 0, f(No, false, "類")}, - {0xf9d1, 0, 0, 0, f(No, false, "六")}, - {0xf9d2, 0, 0, 0, f(No, false, "戮")}, - {0xf9d3, 0, 0, 0, f(No, false, "陸")}, - {0xf9d4, 0, 0, 0, f(No, false, "倫")}, - {0xf9d5, 0, 0, 0, f(No, false, "崙")}, - {0xf9d6, 0, 0, 0, f(No, false, "淪")}, - {0xf9d7, 0, 0, 0, f(No, false, "輪")}, - {0xf9d8, 0, 0, 0, f(No, false, "律")}, - {0xf9d9, 0, 0, 0, f(No, false, "慄")}, - {0xf9da, 0, 0, 0, f(No, false, "栗")}, - {0xf9db, 0, 0, 0, f(No, false, "率")}, - {0xf9dc, 0, 0, 0, f(No, false, "隆")}, - {0xf9dd, 0, 0, 0, f(No, false, "利")}, - {0xf9de, 0, 0, 0, f(No, false, "吏")}, - {0xf9df, 0, 0, 0, f(No, false, "履")}, - {0xf9e0, 0, 0, 0, f(No, false, "易")}, - {0xf9e1, 0, 0, 0, f(No, false, "李")}, - {0xf9e2, 0, 0, 0, f(No, false, "梨")}, - {0xf9e3, 0, 0, 0, f(No, false, "泥")}, - {0xf9e4, 0, 0, 0, f(No, false, "理")}, - {0xf9e5, 0, 0, 0, f(No, false, "痢")}, - {0xf9e6, 0, 0, 0, f(No, false, "罹")}, - {0xf9e7, 0, 0, 0, f(No, false, "裏")}, - {0xf9e8, 0, 0, 0, f(No, false, "裡")}, - {0xf9e9, 0, 0, 0, f(No, false, "里")}, - {0xf9ea, 0, 0, 0, f(No, false, "離")}, - {0xf9eb, 0, 0, 0, f(No, false, "匿")}, - {0xf9ec, 0, 0, 0, f(No, false, "溺")}, - {0xf9ed, 0, 0, 0, f(No, false, "吝")}, - {0xf9ee, 0, 0, 0, f(No, false, "燐")}, - {0xf9ef, 0, 0, 0, f(No, false, "璘")}, - {0xf9f0, 0, 0, 0, f(No, false, "藺")}, - {0xf9f1, 0, 0, 0, f(No, false, "隣")}, - {0xf9f2, 0, 0, 0, f(No, false, "鱗")}, - {0xf9f3, 0, 0, 0, f(No, false, "麟")}, - {0xf9f4, 0, 0, 0, f(No, false, "林")}, - {0xf9f5, 0, 0, 0, f(No, false, "淋")}, - {0xf9f6, 0, 0, 0, f(No, false, "臨")}, - {0xf9f7, 0, 0, 0, f(No, false, "立")}, - {0xf9f8, 0, 0, 0, f(No, false, "笠")}, - {0xf9f9, 0, 0, 0, f(No, false, "粒")}, - {0xf9fa, 0, 0, 0, f(No, false, "狀")}, - {0xf9fb, 0, 0, 0, f(No, false, "炙")}, - {0xf9fc, 0, 0, 0, f(No, false, "識")}, - {0xf9fd, 0, 0, 0, f(No, false, "什")}, - {0xf9fe, 0, 0, 0, f(No, false, "茶")}, - {0xf9ff, 0, 0, 0, f(No, false, "刺")}, - {0xfa00, 0, 0, 0, f(No, false, "切")}, - {0xfa01, 0, 0, 0, f(No, false, "度")}, - {0xfa02, 0, 0, 0, f(No, false, "拓")}, - {0xfa03, 0, 0, 0, f(No, false, "糖")}, - {0xfa04, 0, 0, 0, f(No, false, "宅")}, - {0xfa05, 0, 0, 0, f(No, false, "洞")}, - {0xfa06, 0, 0, 0, f(No, false, "暴")}, - {0xfa07, 0, 0, 0, f(No, false, "輻")}, - {0xfa08, 0, 0, 0, f(No, false, "行")}, - {0xfa09, 0, 0, 0, f(No, false, "降")}, - {0xfa0a, 0, 0, 0, f(No, false, "見")}, - {0xfa0b, 0, 0, 0, f(No, false, "廓")}, - {0xfa0c, 0, 0, 0, f(No, false, "兀")}, - {0xfa0d, 0, 0, 0, f(No, false, "嗀")}, - {0xfa0e, 0, 0, 0, f(Yes, false, "")}, - {0xfa10, 0, 0, 0, f(No, false, "塚")}, - {0xfa11, 0, 0, 0, f(Yes, false, "")}, - {0xfa12, 0, 0, 0, f(No, false, "晴")}, - {0xfa13, 0, 0, 0, f(Yes, false, "")}, - {0xfa15, 0, 0, 0, f(No, false, "凞")}, - {0xfa16, 0, 0, 0, f(No, false, "猪")}, - {0xfa17, 0, 0, 0, f(No, false, "益")}, - {0xfa18, 0, 0, 0, f(No, false, "礼")}, - {0xfa19, 0, 0, 0, f(No, false, "神")}, - {0xfa1a, 0, 0, 0, f(No, false, "祥")}, - {0xfa1b, 0, 0, 0, f(No, false, "福")}, - {0xfa1c, 0, 0, 0, f(No, false, "靖")}, - {0xfa1d, 0, 0, 0, f(No, false, "精")}, - {0xfa1e, 0, 0, 0, f(No, false, "羽")}, - {0xfa1f, 0, 0, 0, f(Yes, false, "")}, - {0xfa20, 0, 0, 0, f(No, false, "蘒")}, - {0xfa21, 0, 0, 0, f(Yes, false, "")}, - {0xfa22, 0, 0, 0, f(No, false, "諸")}, - {0xfa23, 0, 0, 0, f(Yes, false, "")}, - {0xfa25, 0, 0, 0, f(No, false, "逸")}, - {0xfa26, 0, 0, 0, f(No, false, "都")}, - {0xfa27, 0, 0, 0, f(Yes, false, "")}, - {0xfa2a, 0, 0, 0, f(No, false, "飯")}, - {0xfa2b, 0, 0, 0, f(No, false, "飼")}, - {0xfa2c, 0, 0, 0, f(No, false, "館")}, - {0xfa2d, 0, 0, 0, f(No, false, "鶴")}, - {0xfa2e, 0, 0, 0, f(No, false, "郞")}, - {0xfa2f, 0, 0, 0, f(No, false, "隷")}, - {0xfa30, 0, 0, 0, f(No, false, "侮")}, - {0xfa31, 0, 0, 0, f(No, false, "僧")}, - {0xfa32, 0, 0, 0, f(No, false, "免")}, - {0xfa33, 0, 0, 0, f(No, false, "勉")}, - {0xfa34, 0, 0, 0, f(No, false, "勤")}, - {0xfa35, 0, 0, 0, f(No, false, "卑")}, - {0xfa36, 0, 0, 0, f(No, false, "喝")}, - {0xfa37, 0, 0, 0, f(No, false, "嘆")}, - {0xfa38, 0, 0, 0, f(No, false, "器")}, - {0xfa39, 0, 0, 0, f(No, false, "塀")}, - {0xfa3a, 0, 0, 0, f(No, false, "墨")}, - {0xfa3b, 0, 0, 0, f(No, false, "層")}, - {0xfa3c, 0, 0, 0, f(No, false, "屮")}, - {0xfa3d, 0, 0, 0, f(No, false, "悔")}, - {0xfa3e, 0, 0, 0, f(No, false, "慨")}, - {0xfa3f, 0, 0, 0, f(No, false, "憎")}, - {0xfa40, 0, 0, 0, f(No, false, "懲")}, - {0xfa41, 0, 0, 0, f(No, false, "敏")}, - {0xfa42, 0, 0, 0, f(No, false, "既")}, - {0xfa43, 0, 0, 0, f(No, false, "暑")}, - {0xfa44, 0, 0, 0, f(No, false, "梅")}, - {0xfa45, 0, 0, 0, f(No, false, "海")}, - {0xfa46, 0, 0, 0, f(No, false, "渚")}, - {0xfa47, 0, 0, 0, f(No, false, "漢")}, - {0xfa48, 0, 0, 0, f(No, false, "煮")}, - {0xfa49, 0, 0, 0, f(No, false, "爫")}, - {0xfa4a, 0, 0, 0, f(No, false, "琢")}, - {0xfa4b, 0, 0, 0, f(No, false, "碑")}, - {0xfa4c, 0, 0, 0, f(No, false, "社")}, - {0xfa4d, 0, 0, 0, f(No, false, "祉")}, - {0xfa4e, 0, 0, 0, f(No, false, "祈")}, - {0xfa4f, 0, 0, 0, f(No, false, "祐")}, - {0xfa50, 0, 0, 0, f(No, false, "祖")}, - {0xfa51, 0, 0, 0, f(No, false, "祝")}, - {0xfa52, 0, 0, 0, f(No, false, "禍")}, - {0xfa53, 0, 0, 0, f(No, false, "禎")}, - {0xfa54, 0, 0, 0, f(No, false, "穀")}, - {0xfa55, 0, 0, 0, f(No, false, "突")}, - {0xfa56, 0, 0, 0, f(No, false, "節")}, - {0xfa57, 0, 0, 0, f(No, false, "練")}, - {0xfa58, 0, 0, 0, f(No, false, "縉")}, - {0xfa59, 0, 0, 0, f(No, false, "繁")}, - {0xfa5a, 0, 0, 0, f(No, false, "署")}, - {0xfa5b, 0, 0, 0, f(No, false, "者")}, - {0xfa5c, 0, 0, 0, f(No, false, "臭")}, - {0xfa5d, 0, 0, 0, f(No, false, "艹")}, - {0xfa5f, 0, 0, 0, f(No, false, "著")}, - {0xfa60, 0, 0, 0, f(No, false, "褐")}, - {0xfa61, 0, 0, 0, f(No, false, "視")}, - {0xfa62, 0, 0, 0, f(No, false, "謁")}, - {0xfa63, 0, 0, 0, f(No, false, "謹")}, - {0xfa64, 0, 0, 0, f(No, false, "賓")}, - {0xfa65, 0, 0, 0, f(No, false, "贈")}, - {0xfa66, 0, 0, 0, f(No, false, "辶")}, - {0xfa67, 0, 0, 0, f(No, false, "逸")}, - {0xfa68, 0, 0, 0, f(No, false, "難")}, - {0xfa69, 0, 0, 0, f(No, false, "響")}, - {0xfa6a, 0, 0, 0, f(No, false, "頻")}, - {0xfa6b, 0, 0, 0, f(No, false, "恵")}, - {0xfa6c, 0, 0, 0, f(No, false, "𤋮")}, - {0xfa6d, 0, 0, 0, f(No, false, "舘")}, - {0xfa6e, 0, 0, 0, f(Yes, false, "")}, - {0xfa70, 0, 0, 0, f(No, false, "並")}, - {0xfa71, 0, 0, 0, f(No, false, "况")}, - {0xfa72, 0, 0, 0, f(No, false, "全")}, - {0xfa73, 0, 0, 0, f(No, false, "侀")}, - {0xfa74, 0, 0, 0, f(No, false, "充")}, - {0xfa75, 0, 0, 0, f(No, false, "冀")}, - {0xfa76, 0, 0, 0, f(No, false, "勇")}, - {0xfa77, 0, 0, 0, f(No, false, "勺")}, - {0xfa78, 0, 0, 0, f(No, false, "喝")}, - {0xfa79, 0, 0, 0, f(No, false, "啕")}, - {0xfa7a, 0, 0, 0, f(No, false, "喙")}, - {0xfa7b, 0, 0, 0, f(No, false, "嗢")}, - {0xfa7c, 0, 0, 0, f(No, false, "塚")}, - {0xfa7d, 0, 0, 0, f(No, false, "墳")}, - {0xfa7e, 0, 0, 0, f(No, false, "奄")}, - {0xfa7f, 0, 0, 0, f(No, false, "奔")}, - {0xfa80, 0, 0, 0, f(No, false, "婢")}, - {0xfa81, 0, 0, 0, f(No, false, "嬨")}, - {0xfa82, 0, 0, 0, f(No, false, "廒")}, - {0xfa83, 0, 0, 0, f(No, false, "廙")}, - {0xfa84, 0, 0, 0, f(No, false, "彩")}, - {0xfa85, 0, 0, 0, f(No, false, "徭")}, - {0xfa86, 0, 0, 0, f(No, false, "惘")}, - {0xfa87, 0, 0, 0, f(No, false, "慎")}, - {0xfa88, 0, 0, 0, f(No, false, "愈")}, - {0xfa89, 0, 0, 0, f(No, false, "憎")}, - {0xfa8a, 0, 0, 0, f(No, false, "慠")}, - {0xfa8b, 0, 0, 0, f(No, false, "懲")}, - {0xfa8c, 0, 0, 0, f(No, false, "戴")}, - {0xfa8d, 0, 0, 0, f(No, false, "揄")}, - {0xfa8e, 0, 0, 0, f(No, false, "搜")}, - {0xfa8f, 0, 0, 0, f(No, false, "摒")}, - {0xfa90, 0, 0, 0, f(No, false, "敖")}, - {0xfa91, 0, 0, 0, f(No, false, "晴")}, - {0xfa92, 0, 0, 0, f(No, false, "朗")}, - {0xfa93, 0, 0, 0, f(No, false, "望")}, - {0xfa94, 0, 0, 0, f(No, false, "杖")}, - {0xfa95, 0, 0, 0, f(No, false, "歹")}, - {0xfa96, 0, 0, 0, f(No, false, "殺")}, - {0xfa97, 0, 0, 0, f(No, false, "流")}, - {0xfa98, 0, 0, 0, f(No, false, "滛")}, - {0xfa99, 0, 0, 0, f(No, false, "滋")}, - {0xfa9a, 0, 0, 0, f(No, false, "漢")}, - {0xfa9b, 0, 0, 0, f(No, false, "瀞")}, - {0xfa9c, 0, 0, 0, f(No, false, "煮")}, - {0xfa9d, 0, 0, 0, f(No, false, "瞧")}, - {0xfa9e, 0, 0, 0, f(No, false, "爵")}, - {0xfa9f, 0, 0, 0, f(No, false, "犯")}, - {0xfaa0, 0, 0, 0, f(No, false, "猪")}, - {0xfaa1, 0, 0, 0, f(No, false, "瑱")}, - {0xfaa2, 0, 0, 0, f(No, false, "甆")}, - {0xfaa3, 0, 0, 0, f(No, false, "画")}, - {0xfaa4, 0, 0, 0, f(No, false, "瘝")}, - {0xfaa5, 0, 0, 0, f(No, false, "瘟")}, - {0xfaa6, 0, 0, 0, f(No, false, "益")}, - {0xfaa7, 0, 0, 0, f(No, false, "盛")}, - {0xfaa8, 0, 0, 0, f(No, false, "直")}, - {0xfaa9, 0, 0, 0, f(No, false, "睊")}, - {0xfaaa, 0, 0, 0, f(No, false, "着")}, - {0xfaab, 0, 0, 0, f(No, false, "磌")}, - {0xfaac, 0, 0, 0, f(No, false, "窱")}, - {0xfaad, 0, 0, 0, f(No, false, "節")}, - {0xfaae, 0, 0, 0, f(No, false, "类")}, - {0xfaaf, 0, 0, 0, f(No, false, "絛")}, - {0xfab0, 0, 0, 0, f(No, false, "練")}, - {0xfab1, 0, 0, 0, f(No, false, "缾")}, - {0xfab2, 0, 0, 0, f(No, false, "者")}, - {0xfab3, 0, 0, 0, f(No, false, "荒")}, - {0xfab4, 0, 0, 0, f(No, false, "華")}, - {0xfab5, 0, 0, 0, f(No, false, "蝹")}, - {0xfab6, 0, 0, 0, f(No, false, "襁")}, - {0xfab7, 0, 0, 0, f(No, false, "覆")}, - {0xfab8, 0, 0, 0, f(No, false, "視")}, - {0xfab9, 0, 0, 0, f(No, false, "調")}, - {0xfaba, 0, 0, 0, f(No, false, "諸")}, - {0xfabb, 0, 0, 0, f(No, false, "請")}, - {0xfabc, 0, 0, 0, f(No, false, "謁")}, - {0xfabd, 0, 0, 0, f(No, false, "諾")}, - {0xfabe, 0, 0, 0, f(No, false, "諭")}, - {0xfabf, 0, 0, 0, f(No, false, "謹")}, - {0xfac0, 0, 0, 0, f(No, false, "變")}, - {0xfac1, 0, 0, 0, f(No, false, "贈")}, - {0xfac2, 0, 0, 0, f(No, false, "輸")}, - {0xfac3, 0, 0, 0, f(No, false, "遲")}, - {0xfac4, 0, 0, 0, f(No, false, "醙")}, - {0xfac5, 0, 0, 0, f(No, false, "鉶")}, - {0xfac6, 0, 0, 0, f(No, false, "陼")}, - {0xfac7, 0, 0, 0, f(No, false, "難")}, - {0xfac8, 0, 0, 0, f(No, false, "靖")}, - {0xfac9, 0, 0, 0, f(No, false, "韛")}, - {0xfaca, 0, 0, 0, f(No, false, "響")}, - {0xfacb, 0, 0, 0, f(No, false, "頋")}, - {0xfacc, 0, 0, 0, f(No, false, "頻")}, - {0xfacd, 0, 0, 0, f(No, false, "鬒")}, - {0xface, 0, 0, 0, f(No, false, "龜")}, - {0xfacf, 0, 0, 0, f(No, false, "𢡊")}, - {0xfad0, 0, 0, 0, f(No, false, "𢡄")}, - {0xfad1, 0, 0, 0, f(No, false, "𣏕")}, - {0xfad2, 0, 0, 0, f(No, false, "㮝")}, - {0xfad3, 0, 0, 0, f(No, false, "䀘")}, - {0xfad4, 0, 0, 0, f(No, false, "䀹")}, - {0xfad5, 0, 0, 0, f(No, false, "𥉉")}, - {0xfad6, 0, 0, 0, f(No, false, "𥳐")}, - {0xfad7, 0, 0, 0, f(No, false, "𧻓")}, - {0xfad8, 0, 0, 0, f(No, false, "齃")}, - {0xfad9, 0, 0, 0, f(No, false, "龎")}, - {0xfada, 0, 0, 0, f(Yes, false, "")}, - {0xfb00, 0, 0, 0, g(Yes, No, false, false, "", "ff")}, - {0xfb01, 0, 0, 0, g(Yes, No, false, false, "", "fi")}, - {0xfb02, 0, 0, 0, g(Yes, No, false, false, "", "fl")}, - {0xfb03, 0, 0, 0, g(Yes, No, false, false, "", "ffi")}, - {0xfb04, 0, 0, 0, g(Yes, No, false, false, "", "ffl")}, - {0xfb05, 0, 0, 0, g(Yes, No, false, false, "", "st")}, - {0xfb07, 0, 0, 0, f(Yes, false, "")}, - {0xfb13, 0, 0, 0, g(Yes, No, false, false, "", "մն")}, - {0xfb14, 0, 0, 0, g(Yes, No, false, false, "", "մե")}, - {0xfb15, 0, 0, 0, g(Yes, No, false, false, "", "մի")}, - {0xfb16, 0, 0, 0, g(Yes, No, false, false, "", "վն")}, - {0xfb17, 0, 0, 0, g(Yes, No, false, false, "", "մխ")}, - {0xfb18, 0, 0, 0, f(Yes, false, "")}, - {0xfb1d, 0, 0, 1, f(No, false, "יִ")}, - {0xfb1e, 26, 1, 1, f(Yes, false, "")}, - {0xfb1f, 0, 0, 1, f(No, false, "ײַ")}, - {0xfb20, 0, 0, 0, g(Yes, No, false, false, "", "ע")}, - {0xfb21, 0, 0, 0, g(Yes, No, false, false, "", "א")}, - {0xfb22, 0, 0, 0, g(Yes, No, false, false, "", "ד")}, - {0xfb23, 0, 0, 0, g(Yes, No, false, false, "", "ה")}, - {0xfb24, 0, 0, 0, g(Yes, No, false, false, "", "כ")}, - {0xfb25, 0, 0, 0, g(Yes, No, false, false, "", "ל")}, - {0xfb26, 0, 0, 0, g(Yes, No, false, false, "", "ם")}, - {0xfb27, 0, 0, 0, g(Yes, No, false, false, "", "ר")}, - {0xfb28, 0, 0, 0, g(Yes, No, false, false, "", "ת")}, - {0xfb29, 0, 0, 0, g(Yes, No, false, false, "", "+")}, - {0xfb2a, 0, 0, 1, f(No, false, "שׁ")}, - {0xfb2b, 0, 0, 1, f(No, false, "שׂ")}, - {0xfb2c, 0, 0, 2, f(No, false, "שּׁ")}, - {0xfb2d, 0, 0, 2, f(No, false, "שּׂ")}, - {0xfb2e, 0, 0, 1, f(No, false, "אַ")}, - {0xfb2f, 0, 0, 1, f(No, false, "אָ")}, - {0xfb30, 0, 0, 1, f(No, false, "אּ")}, - {0xfb31, 0, 0, 1, f(No, false, "בּ")}, - {0xfb32, 0, 0, 1, f(No, false, "גּ")}, - {0xfb33, 0, 0, 1, f(No, false, "דּ")}, - {0xfb34, 0, 0, 1, f(No, false, "הּ")}, - {0xfb35, 0, 0, 1, f(No, false, "וּ")}, - {0xfb36, 0, 0, 1, f(No, false, "זּ")}, - {0xfb37, 0, 0, 0, f(Yes, false, "")}, - {0xfb38, 0, 0, 1, f(No, false, "טּ")}, - {0xfb39, 0, 0, 1, f(No, false, "יּ")}, - {0xfb3a, 0, 0, 1, f(No, false, "ךּ")}, - {0xfb3b, 0, 0, 1, f(No, false, "כּ")}, - {0xfb3c, 0, 0, 1, f(No, false, "לּ")}, - {0xfb3d, 0, 0, 0, f(Yes, false, "")}, - {0xfb3e, 0, 0, 1, f(No, false, "מּ")}, - {0xfb3f, 0, 0, 0, f(Yes, false, "")}, - {0xfb40, 0, 0, 1, f(No, false, "נּ")}, - {0xfb41, 0, 0, 1, f(No, false, "סּ")}, - {0xfb42, 0, 0, 0, f(Yes, false, "")}, - {0xfb43, 0, 0, 1, f(No, false, "ףּ")}, - {0xfb44, 0, 0, 1, f(No, false, "פּ")}, - {0xfb45, 0, 0, 0, f(Yes, false, "")}, - {0xfb46, 0, 0, 1, f(No, false, "צּ")}, - {0xfb47, 0, 0, 1, f(No, false, "קּ")}, - {0xfb48, 0, 0, 1, f(No, false, "רּ")}, - {0xfb49, 0, 0, 1, f(No, false, "שּ")}, - {0xfb4a, 0, 0, 1, f(No, false, "תּ")}, - {0xfb4b, 0, 0, 1, f(No, false, "וֹ")}, - {0xfb4c, 0, 0, 1, f(No, false, "בֿ")}, - {0xfb4d, 0, 0, 1, f(No, false, "כֿ")}, - {0xfb4e, 0, 0, 1, f(No, false, "פֿ")}, - {0xfb4f, 0, 0, 0, g(Yes, No, false, false, "", "אל")}, - {0xfb50, 0, 0, 0, g(Yes, No, false, false, "", "ٱ")}, - {0xfb52, 0, 0, 0, g(Yes, No, false, false, "", "ٻ")}, - {0xfb56, 0, 0, 0, g(Yes, No, false, false, "", "پ")}, - {0xfb5a, 0, 0, 0, g(Yes, No, false, false, "", "ڀ")}, - {0xfb5e, 0, 0, 0, g(Yes, No, false, false, "", "ٺ")}, - {0xfb62, 0, 0, 0, g(Yes, No, false, false, "", "ٿ")}, - {0xfb66, 0, 0, 0, g(Yes, No, false, false, "", "ٹ")}, - {0xfb6a, 0, 0, 0, g(Yes, No, false, false, "", "ڤ")}, - {0xfb6e, 0, 0, 0, g(Yes, No, false, false, "", "ڦ")}, - {0xfb72, 0, 0, 0, g(Yes, No, false, false, "", "ڄ")}, - {0xfb76, 0, 0, 0, g(Yes, No, false, false, "", "ڃ")}, - {0xfb7a, 0, 0, 0, g(Yes, No, false, false, "", "چ")}, - {0xfb7e, 0, 0, 0, g(Yes, No, false, false, "", "ڇ")}, - {0xfb82, 0, 0, 0, g(Yes, No, false, false, "", "ڍ")}, - {0xfb84, 0, 0, 0, g(Yes, No, false, false, "", "ڌ")}, - {0xfb86, 0, 0, 0, g(Yes, No, false, false, "", "ڎ")}, - {0xfb88, 0, 0, 0, g(Yes, No, false, false, "", "ڈ")}, - {0xfb8a, 0, 0, 0, g(Yes, No, false, false, "", "ژ")}, - {0xfb8c, 0, 0, 0, g(Yes, No, false, false, "", "ڑ")}, - {0xfb8e, 0, 0, 0, g(Yes, No, false, false, "", "ک")}, - {0xfb92, 0, 0, 0, g(Yes, No, false, false, "", "گ")}, - {0xfb96, 0, 0, 0, g(Yes, No, false, false, "", "ڳ")}, - {0xfb9a, 0, 0, 0, g(Yes, No, false, false, "", "ڱ")}, - {0xfb9e, 0, 0, 0, g(Yes, No, false, false, "", "ں")}, - {0xfba0, 0, 0, 0, g(Yes, No, false, false, "", "ڻ")}, - {0xfba4, 0, 0, 1, g(Yes, No, false, false, "", "ۀ")}, - {0xfba6, 0, 0, 0, g(Yes, No, false, false, "", "ہ")}, - {0xfbaa, 0, 0, 0, g(Yes, No, false, false, "", "ھ")}, - {0xfbae, 0, 0, 0, g(Yes, No, false, false, "", "ے")}, - {0xfbb0, 0, 0, 1, g(Yes, No, false, false, "", "ۓ")}, - {0xfbb2, 0, 0, 0, f(Yes, false, "")}, - {0xfbd3, 0, 0, 0, g(Yes, No, false, false, "", "ڭ")}, - {0xfbd7, 0, 0, 0, g(Yes, No, false, false, "", "ۇ")}, - {0xfbd9, 0, 0, 0, g(Yes, No, false, false, "", "ۆ")}, - {0xfbdb, 0, 0, 0, g(Yes, No, false, false, "", "ۈ")}, - {0xfbdd, 0, 0, 0, g(Yes, No, false, false, "", "ۇٴ")}, - {0xfbde, 0, 0, 0, g(Yes, No, false, false, "", "ۋ")}, - {0xfbe0, 0, 0, 0, g(Yes, No, false, false, "", "ۅ")}, - {0xfbe2, 0, 0, 0, g(Yes, No, false, false, "", "ۉ")}, - {0xfbe4, 0, 0, 0, g(Yes, No, false, false, "", "ې")}, - {0xfbe8, 0, 0, 0, g(Yes, No, false, false, "", "ى")}, - {0xfbea, 0, 0, 0, g(Yes, No, false, false, "", "ئا")}, - {0xfbec, 0, 0, 0, g(Yes, No, false, false, "", "ئە")}, - {0xfbee, 0, 0, 0, g(Yes, No, false, false, "", "ئو")}, - {0xfbf0, 0, 0, 0, g(Yes, No, false, false, "", "ئۇ")}, - {0xfbf2, 0, 0, 0, g(Yes, No, false, false, "", "ئۆ")}, - {0xfbf4, 0, 0, 0, g(Yes, No, false, false, "", "ئۈ")}, - {0xfbf6, 0, 0, 0, g(Yes, No, false, false, "", "ئې")}, - {0xfbf9, 0, 0, 0, g(Yes, No, false, false, "", "ئى")}, - {0xfbfc, 0, 0, 0, g(Yes, No, false, false, "", "ی")}, - {0xfc00, 0, 0, 0, g(Yes, No, false, false, "", "ئج")}, - {0xfc01, 0, 0, 0, g(Yes, No, false, false, "", "ئح")}, - {0xfc02, 0, 0, 0, g(Yes, No, false, false, "", "ئم")}, - {0xfc03, 0, 0, 0, g(Yes, No, false, false, "", "ئى")}, - {0xfc04, 0, 0, 0, g(Yes, No, false, false, "", "ئي")}, - {0xfc05, 0, 0, 0, g(Yes, No, false, false, "", "بج")}, - {0xfc06, 0, 0, 0, g(Yes, No, false, false, "", "بح")}, - {0xfc07, 0, 0, 0, g(Yes, No, false, false, "", "بخ")}, - {0xfc08, 0, 0, 0, g(Yes, No, false, false, "", "بم")}, - {0xfc09, 0, 0, 0, g(Yes, No, false, false, "", "بى")}, - {0xfc0a, 0, 0, 0, g(Yes, No, false, false, "", "بي")}, - {0xfc0b, 0, 0, 0, g(Yes, No, false, false, "", "تج")}, - {0xfc0c, 0, 0, 0, g(Yes, No, false, false, "", "تح")}, - {0xfc0d, 0, 0, 0, g(Yes, No, false, false, "", "تخ")}, - {0xfc0e, 0, 0, 0, g(Yes, No, false, false, "", "تم")}, - {0xfc0f, 0, 0, 0, g(Yes, No, false, false, "", "تى")}, - {0xfc10, 0, 0, 0, g(Yes, No, false, false, "", "تي")}, - {0xfc11, 0, 0, 0, g(Yes, No, false, false, "", "ثج")}, - {0xfc12, 0, 0, 0, g(Yes, No, false, false, "", "ثم")}, - {0xfc13, 0, 0, 0, g(Yes, No, false, false, "", "ثى")}, - {0xfc14, 0, 0, 0, g(Yes, No, false, false, "", "ثي")}, - {0xfc15, 0, 0, 0, g(Yes, No, false, false, "", "جح")}, - {0xfc16, 0, 0, 0, g(Yes, No, false, false, "", "جم")}, - {0xfc17, 0, 0, 0, g(Yes, No, false, false, "", "حج")}, - {0xfc18, 0, 0, 0, g(Yes, No, false, false, "", "حم")}, - {0xfc19, 0, 0, 0, g(Yes, No, false, false, "", "خج")}, - {0xfc1a, 0, 0, 0, g(Yes, No, false, false, "", "خح")}, - {0xfc1b, 0, 0, 0, g(Yes, No, false, false, "", "خم")}, - {0xfc1c, 0, 0, 0, g(Yes, No, false, false, "", "سج")}, - {0xfc1d, 0, 0, 0, g(Yes, No, false, false, "", "سح")}, - {0xfc1e, 0, 0, 0, g(Yes, No, false, false, "", "سخ")}, - {0xfc1f, 0, 0, 0, g(Yes, No, false, false, "", "سم")}, - {0xfc20, 0, 0, 0, g(Yes, No, false, false, "", "صح")}, - {0xfc21, 0, 0, 0, g(Yes, No, false, false, "", "صم")}, - {0xfc22, 0, 0, 0, g(Yes, No, false, false, "", "ضج")}, - {0xfc23, 0, 0, 0, g(Yes, No, false, false, "", "ضح")}, - {0xfc24, 0, 0, 0, g(Yes, No, false, false, "", "ضخ")}, - {0xfc25, 0, 0, 0, g(Yes, No, false, false, "", "ضم")}, - {0xfc26, 0, 0, 0, g(Yes, No, false, false, "", "طح")}, - {0xfc27, 0, 0, 0, g(Yes, No, false, false, "", "طم")}, - {0xfc28, 0, 0, 0, g(Yes, No, false, false, "", "ظم")}, - {0xfc29, 0, 0, 0, g(Yes, No, false, false, "", "عج")}, - {0xfc2a, 0, 0, 0, g(Yes, No, false, false, "", "عم")}, - {0xfc2b, 0, 0, 0, g(Yes, No, false, false, "", "غج")}, - {0xfc2c, 0, 0, 0, g(Yes, No, false, false, "", "غم")}, - {0xfc2d, 0, 0, 0, g(Yes, No, false, false, "", "فج")}, - {0xfc2e, 0, 0, 0, g(Yes, No, false, false, "", "فح")}, - {0xfc2f, 0, 0, 0, g(Yes, No, false, false, "", "فخ")}, - {0xfc30, 0, 0, 0, g(Yes, No, false, false, "", "فم")}, - {0xfc31, 0, 0, 0, g(Yes, No, false, false, "", "فى")}, - {0xfc32, 0, 0, 0, g(Yes, No, false, false, "", "في")}, - {0xfc33, 0, 0, 0, g(Yes, No, false, false, "", "قح")}, - {0xfc34, 0, 0, 0, g(Yes, No, false, false, "", "قم")}, - {0xfc35, 0, 0, 0, g(Yes, No, false, false, "", "قى")}, - {0xfc36, 0, 0, 0, g(Yes, No, false, false, "", "قي")}, - {0xfc37, 0, 0, 0, g(Yes, No, false, false, "", "كا")}, - {0xfc38, 0, 0, 0, g(Yes, No, false, false, "", "كج")}, - {0xfc39, 0, 0, 0, g(Yes, No, false, false, "", "كح")}, - {0xfc3a, 0, 0, 0, g(Yes, No, false, false, "", "كخ")}, - {0xfc3b, 0, 0, 0, g(Yes, No, false, false, "", "كل")}, - {0xfc3c, 0, 0, 0, g(Yes, No, false, false, "", "كم")}, - {0xfc3d, 0, 0, 0, g(Yes, No, false, false, "", "كى")}, - {0xfc3e, 0, 0, 0, g(Yes, No, false, false, "", "كي")}, - {0xfc3f, 0, 0, 0, g(Yes, No, false, false, "", "لج")}, - {0xfc40, 0, 0, 0, g(Yes, No, false, false, "", "لح")}, - {0xfc41, 0, 0, 0, g(Yes, No, false, false, "", "لخ")}, - {0xfc42, 0, 0, 0, g(Yes, No, false, false, "", "لم")}, - {0xfc43, 0, 0, 0, g(Yes, No, false, false, "", "لى")}, - {0xfc44, 0, 0, 0, g(Yes, No, false, false, "", "لي")}, - {0xfc45, 0, 0, 0, g(Yes, No, false, false, "", "مج")}, - {0xfc46, 0, 0, 0, g(Yes, No, false, false, "", "مح")}, - {0xfc47, 0, 0, 0, g(Yes, No, false, false, "", "مخ")}, - {0xfc48, 0, 0, 0, g(Yes, No, false, false, "", "مم")}, - {0xfc49, 0, 0, 0, g(Yes, No, false, false, "", "مى")}, - {0xfc4a, 0, 0, 0, g(Yes, No, false, false, "", "مي")}, - {0xfc4b, 0, 0, 0, g(Yes, No, false, false, "", "نج")}, - {0xfc4c, 0, 0, 0, g(Yes, No, false, false, "", "نح")}, - {0xfc4d, 0, 0, 0, g(Yes, No, false, false, "", "نخ")}, - {0xfc4e, 0, 0, 0, g(Yes, No, false, false, "", "نم")}, - {0xfc4f, 0, 0, 0, g(Yes, No, false, false, "", "نى")}, - {0xfc50, 0, 0, 0, g(Yes, No, false, false, "", "ني")}, - {0xfc51, 0, 0, 0, g(Yes, No, false, false, "", "هج")}, - {0xfc52, 0, 0, 0, g(Yes, No, false, false, "", "هم")}, - {0xfc53, 0, 0, 0, g(Yes, No, false, false, "", "هى")}, - {0xfc54, 0, 0, 0, g(Yes, No, false, false, "", "هي")}, - {0xfc55, 0, 0, 0, g(Yes, No, false, false, "", "يج")}, - {0xfc56, 0, 0, 0, g(Yes, No, false, false, "", "يح")}, - {0xfc57, 0, 0, 0, g(Yes, No, false, false, "", "يخ")}, - {0xfc58, 0, 0, 0, g(Yes, No, false, false, "", "يم")}, - {0xfc59, 0, 0, 0, g(Yes, No, false, false, "", "يى")}, - {0xfc5a, 0, 0, 0, g(Yes, No, false, false, "", "يي")}, - {0xfc5b, 0, 0, 1, g(Yes, No, false, false, "", "ذٰ")}, - {0xfc5c, 0, 0, 1, g(Yes, No, false, false, "", "رٰ")}, - {0xfc5d, 0, 0, 1, g(Yes, No, false, false, "", "ىٰ")}, - {0xfc5e, 0, 0, 2, g(Yes, No, false, false, "", " ٌّ")}, - {0xfc5f, 0, 0, 2, g(Yes, No, false, false, "", " ٍّ")}, - {0xfc60, 0, 0, 2, g(Yes, No, false, false, "", " َّ")}, - {0xfc61, 0, 0, 2, g(Yes, No, false, false, "", " ُّ")}, - {0xfc62, 0, 0, 2, g(Yes, No, false, false, "", " ِّ")}, - {0xfc63, 0, 0, 2, g(Yes, No, false, false, "", " ّٰ")}, - {0xfc64, 0, 0, 0, g(Yes, No, false, false, "", "ئر")}, - {0xfc65, 0, 0, 0, g(Yes, No, false, false, "", "ئز")}, - {0xfc66, 0, 0, 0, g(Yes, No, false, false, "", "ئم")}, - {0xfc67, 0, 0, 0, g(Yes, No, false, false, "", "ئن")}, - {0xfc68, 0, 0, 0, g(Yes, No, false, false, "", "ئى")}, - {0xfc69, 0, 0, 0, g(Yes, No, false, false, "", "ئي")}, - {0xfc6a, 0, 0, 0, g(Yes, No, false, false, "", "بر")}, - {0xfc6b, 0, 0, 0, g(Yes, No, false, false, "", "بز")}, - {0xfc6c, 0, 0, 0, g(Yes, No, false, false, "", "بم")}, - {0xfc6d, 0, 0, 0, g(Yes, No, false, false, "", "بن")}, - {0xfc6e, 0, 0, 0, g(Yes, No, false, false, "", "بى")}, - {0xfc6f, 0, 0, 0, g(Yes, No, false, false, "", "بي")}, - {0xfc70, 0, 0, 0, g(Yes, No, false, false, "", "تر")}, - {0xfc71, 0, 0, 0, g(Yes, No, false, false, "", "تز")}, - {0xfc72, 0, 0, 0, g(Yes, No, false, false, "", "تم")}, - {0xfc73, 0, 0, 0, g(Yes, No, false, false, "", "تن")}, - {0xfc74, 0, 0, 0, g(Yes, No, false, false, "", "تى")}, - {0xfc75, 0, 0, 0, g(Yes, No, false, false, "", "تي")}, - {0xfc76, 0, 0, 0, g(Yes, No, false, false, "", "ثر")}, - {0xfc77, 0, 0, 0, g(Yes, No, false, false, "", "ثز")}, - {0xfc78, 0, 0, 0, g(Yes, No, false, false, "", "ثم")}, - {0xfc79, 0, 0, 0, g(Yes, No, false, false, "", "ثن")}, - {0xfc7a, 0, 0, 0, g(Yes, No, false, false, "", "ثى")}, - {0xfc7b, 0, 0, 0, g(Yes, No, false, false, "", "ثي")}, - {0xfc7c, 0, 0, 0, g(Yes, No, false, false, "", "فى")}, - {0xfc7d, 0, 0, 0, g(Yes, No, false, false, "", "في")}, - {0xfc7e, 0, 0, 0, g(Yes, No, false, false, "", "قى")}, - {0xfc7f, 0, 0, 0, g(Yes, No, false, false, "", "قي")}, - {0xfc80, 0, 0, 0, g(Yes, No, false, false, "", "كا")}, - {0xfc81, 0, 0, 0, g(Yes, No, false, false, "", "كل")}, - {0xfc82, 0, 0, 0, g(Yes, No, false, false, "", "كم")}, - {0xfc83, 0, 0, 0, g(Yes, No, false, false, "", "كى")}, - {0xfc84, 0, 0, 0, g(Yes, No, false, false, "", "كي")}, - {0xfc85, 0, 0, 0, g(Yes, No, false, false, "", "لم")}, - {0xfc86, 0, 0, 0, g(Yes, No, false, false, "", "لى")}, - {0xfc87, 0, 0, 0, g(Yes, No, false, false, "", "لي")}, - {0xfc88, 0, 0, 0, g(Yes, No, false, false, "", "ما")}, - {0xfc89, 0, 0, 0, g(Yes, No, false, false, "", "مم")}, - {0xfc8a, 0, 0, 0, g(Yes, No, false, false, "", "نر")}, - {0xfc8b, 0, 0, 0, g(Yes, No, false, false, "", "نز")}, - {0xfc8c, 0, 0, 0, g(Yes, No, false, false, "", "نم")}, - {0xfc8d, 0, 0, 0, g(Yes, No, false, false, "", "نن")}, - {0xfc8e, 0, 0, 0, g(Yes, No, false, false, "", "نى")}, - {0xfc8f, 0, 0, 0, g(Yes, No, false, false, "", "ني")}, - {0xfc90, 0, 0, 1, g(Yes, No, false, false, "", "ىٰ")}, - {0xfc91, 0, 0, 0, g(Yes, No, false, false, "", "ير")}, - {0xfc92, 0, 0, 0, g(Yes, No, false, false, "", "يز")}, - {0xfc93, 0, 0, 0, g(Yes, No, false, false, "", "يم")}, - {0xfc94, 0, 0, 0, g(Yes, No, false, false, "", "ين")}, - {0xfc95, 0, 0, 0, g(Yes, No, false, false, "", "يى")}, - {0xfc96, 0, 0, 0, g(Yes, No, false, false, "", "يي")}, - {0xfc97, 0, 0, 0, g(Yes, No, false, false, "", "ئج")}, - {0xfc98, 0, 0, 0, g(Yes, No, false, false, "", "ئح")}, - {0xfc99, 0, 0, 0, g(Yes, No, false, false, "", "ئخ")}, - {0xfc9a, 0, 0, 0, g(Yes, No, false, false, "", "ئم")}, - {0xfc9b, 0, 0, 0, g(Yes, No, false, false, "", "ئه")}, - {0xfc9c, 0, 0, 0, g(Yes, No, false, false, "", "بج")}, - {0xfc9d, 0, 0, 0, g(Yes, No, false, false, "", "بح")}, - {0xfc9e, 0, 0, 0, g(Yes, No, false, false, "", "بخ")}, - {0xfc9f, 0, 0, 0, g(Yes, No, false, false, "", "بم")}, - {0xfca0, 0, 0, 0, g(Yes, No, false, false, "", "به")}, - {0xfca1, 0, 0, 0, g(Yes, No, false, false, "", "تج")}, - {0xfca2, 0, 0, 0, g(Yes, No, false, false, "", "تح")}, - {0xfca3, 0, 0, 0, g(Yes, No, false, false, "", "تخ")}, - {0xfca4, 0, 0, 0, g(Yes, No, false, false, "", "تم")}, - {0xfca5, 0, 0, 0, g(Yes, No, false, false, "", "ته")}, - {0xfca6, 0, 0, 0, g(Yes, No, false, false, "", "ثم")}, - {0xfca7, 0, 0, 0, g(Yes, No, false, false, "", "جح")}, - {0xfca8, 0, 0, 0, g(Yes, No, false, false, "", "جم")}, - {0xfca9, 0, 0, 0, g(Yes, No, false, false, "", "حج")}, - {0xfcaa, 0, 0, 0, g(Yes, No, false, false, "", "حم")}, - {0xfcab, 0, 0, 0, g(Yes, No, false, false, "", "خج")}, - {0xfcac, 0, 0, 0, g(Yes, No, false, false, "", "خم")}, - {0xfcad, 0, 0, 0, g(Yes, No, false, false, "", "سج")}, - {0xfcae, 0, 0, 0, g(Yes, No, false, false, "", "سح")}, - {0xfcaf, 0, 0, 0, g(Yes, No, false, false, "", "سخ")}, - {0xfcb0, 0, 0, 0, g(Yes, No, false, false, "", "سم")}, - {0xfcb1, 0, 0, 0, g(Yes, No, false, false, "", "صح")}, - {0xfcb2, 0, 0, 0, g(Yes, No, false, false, "", "صخ")}, - {0xfcb3, 0, 0, 0, g(Yes, No, false, false, "", "صم")}, - {0xfcb4, 0, 0, 0, g(Yes, No, false, false, "", "ضج")}, - {0xfcb5, 0, 0, 0, g(Yes, No, false, false, "", "ضح")}, - {0xfcb6, 0, 0, 0, g(Yes, No, false, false, "", "ضخ")}, - {0xfcb7, 0, 0, 0, g(Yes, No, false, false, "", "ضم")}, - {0xfcb8, 0, 0, 0, g(Yes, No, false, false, "", "طح")}, - {0xfcb9, 0, 0, 0, g(Yes, No, false, false, "", "ظم")}, - {0xfcba, 0, 0, 0, g(Yes, No, false, false, "", "عج")}, - {0xfcbb, 0, 0, 0, g(Yes, No, false, false, "", "عم")}, - {0xfcbc, 0, 0, 0, g(Yes, No, false, false, "", "غج")}, - {0xfcbd, 0, 0, 0, g(Yes, No, false, false, "", "غم")}, - {0xfcbe, 0, 0, 0, g(Yes, No, false, false, "", "فج")}, - {0xfcbf, 0, 0, 0, g(Yes, No, false, false, "", "فح")}, - {0xfcc0, 0, 0, 0, g(Yes, No, false, false, "", "فخ")}, - {0xfcc1, 0, 0, 0, g(Yes, No, false, false, "", "فم")}, - {0xfcc2, 0, 0, 0, g(Yes, No, false, false, "", "قح")}, - {0xfcc3, 0, 0, 0, g(Yes, No, false, false, "", "قم")}, - {0xfcc4, 0, 0, 0, g(Yes, No, false, false, "", "كج")}, - {0xfcc5, 0, 0, 0, g(Yes, No, false, false, "", "كح")}, - {0xfcc6, 0, 0, 0, g(Yes, No, false, false, "", "كخ")}, - {0xfcc7, 0, 0, 0, g(Yes, No, false, false, "", "كل")}, - {0xfcc8, 0, 0, 0, g(Yes, No, false, false, "", "كم")}, - {0xfcc9, 0, 0, 0, g(Yes, No, false, false, "", "لج")}, - {0xfcca, 0, 0, 0, g(Yes, No, false, false, "", "لح")}, - {0xfccb, 0, 0, 0, g(Yes, No, false, false, "", "لخ")}, - {0xfccc, 0, 0, 0, g(Yes, No, false, false, "", "لم")}, - {0xfccd, 0, 0, 0, g(Yes, No, false, false, "", "له")}, - {0xfcce, 0, 0, 0, g(Yes, No, false, false, "", "مج")}, - {0xfccf, 0, 0, 0, g(Yes, No, false, false, "", "مح")}, - {0xfcd0, 0, 0, 0, g(Yes, No, false, false, "", "مخ")}, - {0xfcd1, 0, 0, 0, g(Yes, No, false, false, "", "مم")}, - {0xfcd2, 0, 0, 0, g(Yes, No, false, false, "", "نج")}, - {0xfcd3, 0, 0, 0, g(Yes, No, false, false, "", "نح")}, - {0xfcd4, 0, 0, 0, g(Yes, No, false, false, "", "نخ")}, - {0xfcd5, 0, 0, 0, g(Yes, No, false, false, "", "نم")}, - {0xfcd6, 0, 0, 0, g(Yes, No, false, false, "", "نه")}, - {0xfcd7, 0, 0, 0, g(Yes, No, false, false, "", "هج")}, - {0xfcd8, 0, 0, 0, g(Yes, No, false, false, "", "هم")}, - {0xfcd9, 0, 0, 1, g(Yes, No, false, false, "", "هٰ")}, - {0xfcda, 0, 0, 0, g(Yes, No, false, false, "", "يج")}, - {0xfcdb, 0, 0, 0, g(Yes, No, false, false, "", "يح")}, - {0xfcdc, 0, 0, 0, g(Yes, No, false, false, "", "يخ")}, - {0xfcdd, 0, 0, 0, g(Yes, No, false, false, "", "يم")}, - {0xfcde, 0, 0, 0, g(Yes, No, false, false, "", "يه")}, - {0xfcdf, 0, 0, 0, g(Yes, No, false, false, "", "ئم")}, - {0xfce0, 0, 0, 0, g(Yes, No, false, false, "", "ئه")}, - {0xfce1, 0, 0, 0, g(Yes, No, false, false, "", "بم")}, - {0xfce2, 0, 0, 0, g(Yes, No, false, false, "", "به")}, - {0xfce3, 0, 0, 0, g(Yes, No, false, false, "", "تم")}, - {0xfce4, 0, 0, 0, g(Yes, No, false, false, "", "ته")}, - {0xfce5, 0, 0, 0, g(Yes, No, false, false, "", "ثم")}, - {0xfce6, 0, 0, 0, g(Yes, No, false, false, "", "ثه")}, - {0xfce7, 0, 0, 0, g(Yes, No, false, false, "", "سم")}, - {0xfce8, 0, 0, 0, g(Yes, No, false, false, "", "سه")}, - {0xfce9, 0, 0, 0, g(Yes, No, false, false, "", "شم")}, - {0xfcea, 0, 0, 0, g(Yes, No, false, false, "", "شه")}, - {0xfceb, 0, 0, 0, g(Yes, No, false, false, "", "كل")}, - {0xfcec, 0, 0, 0, g(Yes, No, false, false, "", "كم")}, - {0xfced, 0, 0, 0, g(Yes, No, false, false, "", "لم")}, - {0xfcee, 0, 0, 0, g(Yes, No, false, false, "", "نم")}, - {0xfcef, 0, 0, 0, g(Yes, No, false, false, "", "نه")}, - {0xfcf0, 0, 0, 0, g(Yes, No, false, false, "", "يم")}, - {0xfcf1, 0, 0, 0, g(Yes, No, false, false, "", "يه")}, - {0xfcf2, 0, 0, 2, g(Yes, No, false, false, "", "ـَّ")}, - {0xfcf3, 0, 0, 2, g(Yes, No, false, false, "", "ـُّ")}, - {0xfcf4, 0, 0, 2, g(Yes, No, false, false, "", "ـِّ")}, - {0xfcf5, 0, 0, 0, g(Yes, No, false, false, "", "طى")}, - {0xfcf6, 0, 0, 0, g(Yes, No, false, false, "", "طي")}, - {0xfcf7, 0, 0, 0, g(Yes, No, false, false, "", "عى")}, - {0xfcf8, 0, 0, 0, g(Yes, No, false, false, "", "عي")}, - {0xfcf9, 0, 0, 0, g(Yes, No, false, false, "", "غى")}, - {0xfcfa, 0, 0, 0, g(Yes, No, false, false, "", "غي")}, - {0xfcfb, 0, 0, 0, g(Yes, No, false, false, "", "سى")}, - {0xfcfc, 0, 0, 0, g(Yes, No, false, false, "", "سي")}, - {0xfcfd, 0, 0, 0, g(Yes, No, false, false, "", "شى")}, - {0xfcfe, 0, 0, 0, g(Yes, No, false, false, "", "شي")}, - {0xfcff, 0, 0, 0, g(Yes, No, false, false, "", "حى")}, - {0xfd00, 0, 0, 0, g(Yes, No, false, false, "", "حي")}, - {0xfd01, 0, 0, 0, g(Yes, No, false, false, "", "جى")}, - {0xfd02, 0, 0, 0, g(Yes, No, false, false, "", "جي")}, - {0xfd03, 0, 0, 0, g(Yes, No, false, false, "", "خى")}, - {0xfd04, 0, 0, 0, g(Yes, No, false, false, "", "خي")}, - {0xfd05, 0, 0, 0, g(Yes, No, false, false, "", "صى")}, - {0xfd06, 0, 0, 0, g(Yes, No, false, false, "", "صي")}, - {0xfd07, 0, 0, 0, g(Yes, No, false, false, "", "ضى")}, - {0xfd08, 0, 0, 0, g(Yes, No, false, false, "", "ضي")}, - {0xfd09, 0, 0, 0, g(Yes, No, false, false, "", "شج")}, - {0xfd0a, 0, 0, 0, g(Yes, No, false, false, "", "شح")}, - {0xfd0b, 0, 0, 0, g(Yes, No, false, false, "", "شخ")}, - {0xfd0c, 0, 0, 0, g(Yes, No, false, false, "", "شم")}, - {0xfd0d, 0, 0, 0, g(Yes, No, false, false, "", "شر")}, - {0xfd0e, 0, 0, 0, g(Yes, No, false, false, "", "سر")}, - {0xfd0f, 0, 0, 0, g(Yes, No, false, false, "", "صر")}, - {0xfd10, 0, 0, 0, g(Yes, No, false, false, "", "ضر")}, - {0xfd11, 0, 0, 0, g(Yes, No, false, false, "", "طى")}, - {0xfd12, 0, 0, 0, g(Yes, No, false, false, "", "طي")}, - {0xfd13, 0, 0, 0, g(Yes, No, false, false, "", "عى")}, - {0xfd14, 0, 0, 0, g(Yes, No, false, false, "", "عي")}, - {0xfd15, 0, 0, 0, g(Yes, No, false, false, "", "غى")}, - {0xfd16, 0, 0, 0, g(Yes, No, false, false, "", "غي")}, - {0xfd17, 0, 0, 0, g(Yes, No, false, false, "", "سى")}, - {0xfd18, 0, 0, 0, g(Yes, No, false, false, "", "سي")}, - {0xfd19, 0, 0, 0, g(Yes, No, false, false, "", "شى")}, - {0xfd1a, 0, 0, 0, g(Yes, No, false, false, "", "شي")}, - {0xfd1b, 0, 0, 0, g(Yes, No, false, false, "", "حى")}, - {0xfd1c, 0, 0, 0, g(Yes, No, false, false, "", "حي")}, - {0xfd1d, 0, 0, 0, g(Yes, No, false, false, "", "جى")}, - {0xfd1e, 0, 0, 0, g(Yes, No, false, false, "", "جي")}, - {0xfd1f, 0, 0, 0, g(Yes, No, false, false, "", "خى")}, - {0xfd20, 0, 0, 0, g(Yes, No, false, false, "", "خي")}, - {0xfd21, 0, 0, 0, g(Yes, No, false, false, "", "صى")}, - {0xfd22, 0, 0, 0, g(Yes, No, false, false, "", "صي")}, - {0xfd23, 0, 0, 0, g(Yes, No, false, false, "", "ضى")}, - {0xfd24, 0, 0, 0, g(Yes, No, false, false, "", "ضي")}, - {0xfd25, 0, 0, 0, g(Yes, No, false, false, "", "شج")}, - {0xfd26, 0, 0, 0, g(Yes, No, false, false, "", "شح")}, - {0xfd27, 0, 0, 0, g(Yes, No, false, false, "", "شخ")}, - {0xfd28, 0, 0, 0, g(Yes, No, false, false, "", "شم")}, - {0xfd29, 0, 0, 0, g(Yes, No, false, false, "", "شر")}, - {0xfd2a, 0, 0, 0, g(Yes, No, false, false, "", "سر")}, - {0xfd2b, 0, 0, 0, g(Yes, No, false, false, "", "صر")}, - {0xfd2c, 0, 0, 0, g(Yes, No, false, false, "", "ضر")}, - {0xfd2d, 0, 0, 0, g(Yes, No, false, false, "", "شج")}, - {0xfd2e, 0, 0, 0, g(Yes, No, false, false, "", "شح")}, - {0xfd2f, 0, 0, 0, g(Yes, No, false, false, "", "شخ")}, - {0xfd30, 0, 0, 0, g(Yes, No, false, false, "", "شم")}, - {0xfd31, 0, 0, 0, g(Yes, No, false, false, "", "سه")}, - {0xfd32, 0, 0, 0, g(Yes, No, false, false, "", "شه")}, - {0xfd33, 0, 0, 0, g(Yes, No, false, false, "", "طم")}, - {0xfd34, 0, 0, 0, g(Yes, No, false, false, "", "سج")}, - {0xfd35, 0, 0, 0, g(Yes, No, false, false, "", "سح")}, - {0xfd36, 0, 0, 0, g(Yes, No, false, false, "", "سخ")}, - {0xfd37, 0, 0, 0, g(Yes, No, false, false, "", "شج")}, - {0xfd38, 0, 0, 0, g(Yes, No, false, false, "", "شح")}, - {0xfd39, 0, 0, 0, g(Yes, No, false, false, "", "شخ")}, - {0xfd3a, 0, 0, 0, g(Yes, No, false, false, "", "طم")}, - {0xfd3b, 0, 0, 0, g(Yes, No, false, false, "", "ظم")}, - {0xfd3c, 0, 0, 1, g(Yes, No, false, false, "", "اً")}, - {0xfd3e, 0, 0, 0, f(Yes, false, "")}, - {0xfd50, 0, 0, 0, g(Yes, No, false, false, "", "تجم")}, - {0xfd51, 0, 0, 0, g(Yes, No, false, false, "", "تحج")}, - {0xfd53, 0, 0, 0, g(Yes, No, false, false, "", "تحم")}, - {0xfd54, 0, 0, 0, g(Yes, No, false, false, "", "تخم")}, - {0xfd55, 0, 0, 0, g(Yes, No, false, false, "", "تمج")}, - {0xfd56, 0, 0, 0, g(Yes, No, false, false, "", "تمح")}, - {0xfd57, 0, 0, 0, g(Yes, No, false, false, "", "تمخ")}, - {0xfd58, 0, 0, 0, g(Yes, No, false, false, "", "جمح")}, - {0xfd5a, 0, 0, 0, g(Yes, No, false, false, "", "حمي")}, - {0xfd5b, 0, 0, 0, g(Yes, No, false, false, "", "حمى")}, - {0xfd5c, 0, 0, 0, g(Yes, No, false, false, "", "سحج")}, - {0xfd5d, 0, 0, 0, g(Yes, No, false, false, "", "سجح")}, - {0xfd5e, 0, 0, 0, g(Yes, No, false, false, "", "سجى")}, - {0xfd5f, 0, 0, 0, g(Yes, No, false, false, "", "سمح")}, - {0xfd61, 0, 0, 0, g(Yes, No, false, false, "", "سمج")}, - {0xfd62, 0, 0, 0, g(Yes, No, false, false, "", "سمم")}, - {0xfd64, 0, 0, 0, g(Yes, No, false, false, "", "صحح")}, - {0xfd66, 0, 0, 0, g(Yes, No, false, false, "", "صمم")}, - {0xfd67, 0, 0, 0, g(Yes, No, false, false, "", "شحم")}, - {0xfd69, 0, 0, 0, g(Yes, No, false, false, "", "شجي")}, - {0xfd6a, 0, 0, 0, g(Yes, No, false, false, "", "شمخ")}, - {0xfd6c, 0, 0, 0, g(Yes, No, false, false, "", "شمم")}, - {0xfd6e, 0, 0, 0, g(Yes, No, false, false, "", "ضحى")}, - {0xfd6f, 0, 0, 0, g(Yes, No, false, false, "", "ضخم")}, - {0xfd71, 0, 0, 0, g(Yes, No, false, false, "", "طمح")}, - {0xfd73, 0, 0, 0, g(Yes, No, false, false, "", "طمم")}, - {0xfd74, 0, 0, 0, g(Yes, No, false, false, "", "طمي")}, - {0xfd75, 0, 0, 0, g(Yes, No, false, false, "", "عجم")}, - {0xfd76, 0, 0, 0, g(Yes, No, false, false, "", "عمم")}, - {0xfd78, 0, 0, 0, g(Yes, No, false, false, "", "عمى")}, - {0xfd79, 0, 0, 0, g(Yes, No, false, false, "", "غمم")}, - {0xfd7a, 0, 0, 0, g(Yes, No, false, false, "", "غمي")}, - {0xfd7b, 0, 0, 0, g(Yes, No, false, false, "", "غمى")}, - {0xfd7c, 0, 0, 0, g(Yes, No, false, false, "", "فخم")}, - {0xfd7e, 0, 0, 0, g(Yes, No, false, false, "", "قمح")}, - {0xfd7f, 0, 0, 0, g(Yes, No, false, false, "", "قمم")}, - {0xfd80, 0, 0, 0, g(Yes, No, false, false, "", "لحم")}, - {0xfd81, 0, 0, 0, g(Yes, No, false, false, "", "لحي")}, - {0xfd82, 0, 0, 0, g(Yes, No, false, false, "", "لحى")}, - {0xfd83, 0, 0, 0, g(Yes, No, false, false, "", "لجج")}, - {0xfd85, 0, 0, 0, g(Yes, No, false, false, "", "لخم")}, - {0xfd87, 0, 0, 0, g(Yes, No, false, false, "", "لمح")}, - {0xfd89, 0, 0, 0, g(Yes, No, false, false, "", "محج")}, - {0xfd8a, 0, 0, 0, g(Yes, No, false, false, "", "محم")}, - {0xfd8b, 0, 0, 0, g(Yes, No, false, false, "", "محي")}, - {0xfd8c, 0, 0, 0, g(Yes, No, false, false, "", "مجح")}, - {0xfd8d, 0, 0, 0, g(Yes, No, false, false, "", "مجم")}, - {0xfd8e, 0, 0, 0, g(Yes, No, false, false, "", "مخج")}, - {0xfd8f, 0, 0, 0, g(Yes, No, false, false, "", "مخم")}, - {0xfd90, 0, 0, 0, f(Yes, false, "")}, - {0xfd92, 0, 0, 0, g(Yes, No, false, false, "", "مجخ")}, - {0xfd93, 0, 0, 0, g(Yes, No, false, false, "", "همج")}, - {0xfd94, 0, 0, 0, g(Yes, No, false, false, "", "همم")}, - {0xfd95, 0, 0, 0, g(Yes, No, false, false, "", "نحم")}, - {0xfd96, 0, 0, 0, g(Yes, No, false, false, "", "نحى")}, - {0xfd97, 0, 0, 0, g(Yes, No, false, false, "", "نجم")}, - {0xfd99, 0, 0, 0, g(Yes, No, false, false, "", "نجى")}, - {0xfd9a, 0, 0, 0, g(Yes, No, false, false, "", "نمي")}, - {0xfd9b, 0, 0, 0, g(Yes, No, false, false, "", "نمى")}, - {0xfd9c, 0, 0, 0, g(Yes, No, false, false, "", "يمم")}, - {0xfd9e, 0, 0, 0, g(Yes, No, false, false, "", "بخي")}, - {0xfd9f, 0, 0, 0, g(Yes, No, false, false, "", "تجي")}, - {0xfda0, 0, 0, 0, g(Yes, No, false, false, "", "تجى")}, - {0xfda1, 0, 0, 0, g(Yes, No, false, false, "", "تخي")}, - {0xfda2, 0, 0, 0, g(Yes, No, false, false, "", "تخى")}, - {0xfda3, 0, 0, 0, g(Yes, No, false, false, "", "تمي")}, - {0xfda4, 0, 0, 0, g(Yes, No, false, false, "", "تمى")}, - {0xfda5, 0, 0, 0, g(Yes, No, false, false, "", "جمي")}, - {0xfda6, 0, 0, 0, g(Yes, No, false, false, "", "جحى")}, - {0xfda7, 0, 0, 0, g(Yes, No, false, false, "", "جمى")}, - {0xfda8, 0, 0, 0, g(Yes, No, false, false, "", "سخى")}, - {0xfda9, 0, 0, 0, g(Yes, No, false, false, "", "صحي")}, - {0xfdaa, 0, 0, 0, g(Yes, No, false, false, "", "شحي")}, - {0xfdab, 0, 0, 0, g(Yes, No, false, false, "", "ضحي")}, - {0xfdac, 0, 0, 0, g(Yes, No, false, false, "", "لجي")}, - {0xfdad, 0, 0, 0, g(Yes, No, false, false, "", "لمي")}, - {0xfdae, 0, 0, 0, g(Yes, No, false, false, "", "يحي")}, - {0xfdaf, 0, 0, 0, g(Yes, No, false, false, "", "يجي")}, - {0xfdb0, 0, 0, 0, g(Yes, No, false, false, "", "يمي")}, - {0xfdb1, 0, 0, 0, g(Yes, No, false, false, "", "ممي")}, - {0xfdb2, 0, 0, 0, g(Yes, No, false, false, "", "قمي")}, - {0xfdb3, 0, 0, 0, g(Yes, No, false, false, "", "نحي")}, - {0xfdb4, 0, 0, 0, g(Yes, No, false, false, "", "قمح")}, - {0xfdb5, 0, 0, 0, g(Yes, No, false, false, "", "لحم")}, - {0xfdb6, 0, 0, 0, g(Yes, No, false, false, "", "عمي")}, - {0xfdb7, 0, 0, 0, g(Yes, No, false, false, "", "كمي")}, - {0xfdb8, 0, 0, 0, g(Yes, No, false, false, "", "نجح")}, - {0xfdb9, 0, 0, 0, g(Yes, No, false, false, "", "مخي")}, - {0xfdba, 0, 0, 0, g(Yes, No, false, false, "", "لجم")}, - {0xfdbb, 0, 0, 0, g(Yes, No, false, false, "", "كمم")}, - {0xfdbc, 0, 0, 0, g(Yes, No, false, false, "", "لجم")}, - {0xfdbd, 0, 0, 0, g(Yes, No, false, false, "", "نجح")}, - {0xfdbe, 0, 0, 0, g(Yes, No, false, false, "", "جحي")}, - {0xfdbf, 0, 0, 0, g(Yes, No, false, false, "", "حجي")}, - {0xfdc0, 0, 0, 0, g(Yes, No, false, false, "", "مجي")}, - {0xfdc1, 0, 0, 0, g(Yes, No, false, false, "", "فمي")}, - {0xfdc2, 0, 0, 0, g(Yes, No, false, false, "", "بحي")}, - {0xfdc3, 0, 0, 0, g(Yes, No, false, false, "", "كمم")}, - {0xfdc4, 0, 0, 0, g(Yes, No, false, false, "", "عجم")}, - {0xfdc5, 0, 0, 0, g(Yes, No, false, false, "", "صمم")}, - {0xfdc6, 0, 0, 0, g(Yes, No, false, false, "", "سخي")}, - {0xfdc7, 0, 0, 0, g(Yes, No, false, false, "", "نجي")}, - {0xfdc8, 0, 0, 0, f(Yes, false, "")}, - {0xfdf0, 0, 0, 0, g(Yes, No, false, false, "", "صلے")}, - {0xfdf1, 0, 0, 0, g(Yes, No, false, false, "", "قلے")}, - {0xfdf2, 0, 0, 0, g(Yes, No, false, false, "", "الله")}, - {0xfdf3, 0, 0, 0, g(Yes, No, false, false, "", "اكبر")}, - {0xfdf4, 0, 0, 0, g(Yes, No, false, false, "", "محمد")}, - {0xfdf5, 0, 0, 0, g(Yes, No, false, false, "", "صلعم")}, - {0xfdf6, 0, 0, 0, g(Yes, No, false, false, "", "رسول")}, - {0xfdf7, 0, 0, 0, g(Yes, No, false, false, "", "عليه")}, - {0xfdf8, 0, 0, 0, g(Yes, No, false, false, "", "وسلم")}, - {0xfdf9, 0, 0, 0, g(Yes, No, false, false, "", "صلى")}, - {0xfdfa, 0, 0, 0, g(Yes, No, false, false, "", "صلى الله عليه وسلم")}, - {0xfdfb, 0, 0, 0, g(Yes, No, false, false, "", "جل جلاله")}, - {0xfdfc, 0, 0, 0, g(Yes, No, false, false, "", "ریال")}, - {0xfdfd, 0, 0, 0, f(Yes, false, "")}, - {0xfe10, 0, 0, 0, g(Yes, No, false, false, "", ",")}, - {0xfe11, 0, 0, 0, g(Yes, No, false, false, "", "、")}, - {0xfe12, 0, 0, 0, g(Yes, No, false, false, "", "。")}, - {0xfe13, 0, 0, 0, g(Yes, No, false, false, "", ":")}, - {0xfe14, 0, 0, 0, g(Yes, No, false, false, "", ";")}, - {0xfe15, 0, 0, 0, g(Yes, No, false, false, "", "!")}, - {0xfe16, 0, 0, 0, g(Yes, No, false, false, "", "?")}, - {0xfe17, 0, 0, 0, g(Yes, No, false, false, "", "〖")}, - {0xfe18, 0, 0, 0, g(Yes, No, false, false, "", "〗")}, - {0xfe19, 0, 0, 0, g(Yes, No, false, false, "", "...")}, - {0xfe1a, 0, 0, 0, f(Yes, false, "")}, - {0xfe20, 230, 1, 1, f(Yes, false, "")}, - {0xfe27, 220, 1, 1, f(Yes, false, "")}, - {0xfe2e, 230, 1, 1, f(Yes, false, "")}, - {0xfe30, 0, 0, 0, g(Yes, No, false, false, "", "..")}, - {0xfe31, 0, 0, 0, g(Yes, No, false, false, "", "—")}, - {0xfe32, 0, 0, 0, g(Yes, No, false, false, "", "–")}, - {0xfe33, 0, 0, 0, g(Yes, No, false, false, "", "_")}, - {0xfe35, 0, 0, 0, g(Yes, No, false, false, "", "(")}, - {0xfe36, 0, 0, 0, g(Yes, No, false, false, "", ")")}, - {0xfe37, 0, 0, 0, g(Yes, No, false, false, "", "{")}, - {0xfe38, 0, 0, 0, g(Yes, No, false, false, "", "}")}, - {0xfe39, 0, 0, 0, g(Yes, No, false, false, "", "〔")}, - {0xfe3a, 0, 0, 0, g(Yes, No, false, false, "", "〕")}, - {0xfe3b, 0, 0, 0, g(Yes, No, false, false, "", "【")}, - {0xfe3c, 0, 0, 0, g(Yes, No, false, false, "", "】")}, - {0xfe3d, 0, 0, 0, g(Yes, No, false, false, "", "《")}, - {0xfe3e, 0, 0, 0, g(Yes, No, false, false, "", "》")}, - {0xfe3f, 0, 0, 0, g(Yes, No, false, false, "", "〈")}, - {0xfe40, 0, 0, 0, g(Yes, No, false, false, "", "〉")}, - {0xfe41, 0, 0, 0, g(Yes, No, false, false, "", "「")}, - {0xfe42, 0, 0, 0, g(Yes, No, false, false, "", "」")}, - {0xfe43, 0, 0, 0, g(Yes, No, false, false, "", "『")}, - {0xfe44, 0, 0, 0, g(Yes, No, false, false, "", "』")}, - {0xfe45, 0, 0, 0, f(Yes, false, "")}, - {0xfe47, 0, 0, 0, g(Yes, No, false, false, "", "[")}, - {0xfe48, 0, 0, 0, g(Yes, No, false, false, "", "]")}, - {0xfe49, 0, 0, 1, g(Yes, No, false, false, "", " ̅")}, - {0xfe4d, 0, 0, 0, g(Yes, No, false, false, "", "_")}, - {0xfe50, 0, 0, 0, g(Yes, No, false, false, "", ",")}, - {0xfe51, 0, 0, 0, g(Yes, No, false, false, "", "、")}, - {0xfe52, 0, 0, 0, g(Yes, No, false, false, "", ".")}, - {0xfe53, 0, 0, 0, f(Yes, false, "")}, - {0xfe54, 0, 0, 0, g(Yes, No, false, false, "", ";")}, - {0xfe55, 0, 0, 0, g(Yes, No, false, false, "", ":")}, - {0xfe56, 0, 0, 0, g(Yes, No, false, false, "", "?")}, - {0xfe57, 0, 0, 0, g(Yes, No, false, false, "", "!")}, - {0xfe58, 0, 0, 0, g(Yes, No, false, false, "", "—")}, - {0xfe59, 0, 0, 0, g(Yes, No, false, false, "", "(")}, - {0xfe5a, 0, 0, 0, g(Yes, No, false, false, "", ")")}, - {0xfe5b, 0, 0, 0, g(Yes, No, false, false, "", "{")}, - {0xfe5c, 0, 0, 0, g(Yes, No, false, false, "", "}")}, - {0xfe5d, 0, 0, 0, g(Yes, No, false, false, "", "〔")}, - {0xfe5e, 0, 0, 0, g(Yes, No, false, false, "", "〕")}, - {0xfe5f, 0, 0, 0, g(Yes, No, false, false, "", "#")}, - {0xfe60, 0, 0, 0, g(Yes, No, false, false, "", "&")}, - {0xfe61, 0, 0, 0, g(Yes, No, false, false, "", "*")}, - {0xfe62, 0, 0, 0, g(Yes, No, false, false, "", "+")}, - {0xfe63, 0, 0, 0, g(Yes, No, false, false, "", "-")}, - {0xfe64, 0, 0, 0, g(Yes, No, false, false, "", "<")}, - {0xfe65, 0, 0, 0, g(Yes, No, false, false, "", ">")}, - {0xfe66, 0, 0, 0, g(Yes, No, false, false, "", "=")}, - {0xfe67, 0, 0, 0, f(Yes, false, "")}, - {0xfe68, 0, 0, 0, g(Yes, No, false, false, "", "\\")}, - {0xfe69, 0, 0, 0, g(Yes, No, false, false, "", "$")}, - {0xfe6a, 0, 0, 0, g(Yes, No, false, false, "", "%")}, - {0xfe6b, 0, 0, 0, g(Yes, No, false, false, "", "@")}, - {0xfe6c, 0, 0, 0, f(Yes, false, "")}, - {0xfe70, 0, 0, 1, g(Yes, No, false, false, "", " ً")}, - {0xfe71, 0, 0, 1, g(Yes, No, false, false, "", "ـً")}, - {0xfe72, 0, 0, 1, g(Yes, No, false, false, "", " ٌ")}, - {0xfe73, 0, 0, 0, f(Yes, false, "")}, - {0xfe74, 0, 0, 1, g(Yes, No, false, false, "", " ٍ")}, - {0xfe75, 0, 0, 0, f(Yes, false, "")}, - {0xfe76, 0, 0, 1, g(Yes, No, false, false, "", " َ")}, - {0xfe77, 0, 0, 1, g(Yes, No, false, false, "", "ـَ")}, - {0xfe78, 0, 0, 1, g(Yes, No, false, false, "", " ُ")}, - {0xfe79, 0, 0, 1, g(Yes, No, false, false, "", "ـُ")}, - {0xfe7a, 0, 0, 1, g(Yes, No, false, false, "", " ِ")}, - {0xfe7b, 0, 0, 1, g(Yes, No, false, false, "", "ـِ")}, - {0xfe7c, 0, 0, 1, g(Yes, No, false, false, "", " ّ")}, - {0xfe7d, 0, 0, 1, g(Yes, No, false, false, "", "ـّ")}, - {0xfe7e, 0, 0, 1, g(Yes, No, false, false, "", " ْ")}, - {0xfe7f, 0, 0, 1, g(Yes, No, false, false, "", "ـْ")}, - {0xfe80, 0, 0, 0, g(Yes, No, false, false, "", "ء")}, - {0xfe81, 0, 0, 1, g(Yes, No, false, false, "", "آ")}, - {0xfe83, 0, 0, 1, g(Yes, No, false, false, "", "أ")}, - {0xfe85, 0, 0, 1, g(Yes, No, false, false, "", "ؤ")}, - {0xfe87, 0, 0, 1, g(Yes, No, false, false, "", "إ")}, - {0xfe89, 0, 0, 1, g(Yes, No, false, false, "", "ئ")}, - {0xfe8d, 0, 0, 0, g(Yes, No, false, false, "", "ا")}, - {0xfe8f, 0, 0, 0, g(Yes, No, false, false, "", "ب")}, - {0xfe93, 0, 0, 0, g(Yes, No, false, false, "", "ة")}, - {0xfe95, 0, 0, 0, g(Yes, No, false, false, "", "ت")}, - {0xfe99, 0, 0, 0, g(Yes, No, false, false, "", "ث")}, - {0xfe9d, 0, 0, 0, g(Yes, No, false, false, "", "ج")}, - {0xfea1, 0, 0, 0, g(Yes, No, false, false, "", "ح")}, - {0xfea5, 0, 0, 0, g(Yes, No, false, false, "", "خ")}, - {0xfea9, 0, 0, 0, g(Yes, No, false, false, "", "د")}, - {0xfeab, 0, 0, 0, g(Yes, No, false, false, "", "ذ")}, - {0xfead, 0, 0, 0, g(Yes, No, false, false, "", "ر")}, - {0xfeaf, 0, 0, 0, g(Yes, No, false, false, "", "ز")}, - {0xfeb1, 0, 0, 0, g(Yes, No, false, false, "", "س")}, - {0xfeb5, 0, 0, 0, g(Yes, No, false, false, "", "ش")}, - {0xfeb9, 0, 0, 0, g(Yes, No, false, false, "", "ص")}, - {0xfebd, 0, 0, 0, g(Yes, No, false, false, "", "ض")}, - {0xfec1, 0, 0, 0, g(Yes, No, false, false, "", "ط")}, - {0xfec5, 0, 0, 0, g(Yes, No, false, false, "", "ظ")}, - {0xfec9, 0, 0, 0, g(Yes, No, false, false, "", "ع")}, - {0xfecd, 0, 0, 0, g(Yes, No, false, false, "", "غ")}, - {0xfed1, 0, 0, 0, g(Yes, No, false, false, "", "ف")}, - {0xfed5, 0, 0, 0, g(Yes, No, false, false, "", "ق")}, - {0xfed9, 0, 0, 0, g(Yes, No, false, false, "", "ك")}, - {0xfedd, 0, 0, 0, g(Yes, No, false, false, "", "ل")}, - {0xfee1, 0, 0, 0, g(Yes, No, false, false, "", "م")}, - {0xfee5, 0, 0, 0, g(Yes, No, false, false, "", "ن")}, - {0xfee9, 0, 0, 0, g(Yes, No, false, false, "", "ه")}, - {0xfeed, 0, 0, 0, g(Yes, No, false, false, "", "و")}, - {0xfeef, 0, 0, 0, g(Yes, No, false, false, "", "ى")}, - {0xfef1, 0, 0, 0, g(Yes, No, false, false, "", "ي")}, - {0xfef5, 0, 0, 1, g(Yes, No, false, false, "", "لآ")}, - {0xfef7, 0, 0, 1, g(Yes, No, false, false, "", "لأ")}, - {0xfef9, 0, 0, 1, g(Yes, No, false, false, "", "لإ")}, - {0xfefb, 0, 0, 0, g(Yes, No, false, false, "", "لا")}, - {0xfefd, 0, 0, 0, f(Yes, false, "")}, - {0xff01, 0, 0, 0, g(Yes, No, false, false, "", "!")}, - {0xff02, 0, 0, 0, g(Yes, No, false, false, "", "\"")}, - {0xff03, 0, 0, 0, g(Yes, No, false, false, "", "#")}, - {0xff04, 0, 0, 0, g(Yes, No, false, false, "", "$")}, - {0xff05, 0, 0, 0, g(Yes, No, false, false, "", "%")}, - {0xff06, 0, 0, 0, g(Yes, No, false, false, "", "&")}, - {0xff07, 0, 0, 0, g(Yes, No, false, false, "", "'")}, - {0xff08, 0, 0, 0, g(Yes, No, false, false, "", "(")}, - {0xff09, 0, 0, 0, g(Yes, No, false, false, "", ")")}, - {0xff0a, 0, 0, 0, g(Yes, No, false, false, "", "*")}, - {0xff0b, 0, 0, 0, g(Yes, No, false, false, "", "+")}, - {0xff0c, 0, 0, 0, g(Yes, No, false, false, "", ",")}, - {0xff0d, 0, 0, 0, g(Yes, No, false, false, "", "-")}, - {0xff0e, 0, 0, 0, g(Yes, No, false, false, "", ".")}, - {0xff0f, 0, 0, 0, g(Yes, No, false, false, "", "/")}, - {0xff10, 0, 0, 0, g(Yes, No, false, false, "", "0")}, - {0xff11, 0, 0, 0, g(Yes, No, false, false, "", "1")}, - {0xff12, 0, 0, 0, g(Yes, No, false, false, "", "2")}, - {0xff13, 0, 0, 0, g(Yes, No, false, false, "", "3")}, - {0xff14, 0, 0, 0, g(Yes, No, false, false, "", "4")}, - {0xff15, 0, 0, 0, g(Yes, No, false, false, "", "5")}, - {0xff16, 0, 0, 0, g(Yes, No, false, false, "", "6")}, - {0xff17, 0, 0, 0, g(Yes, No, false, false, "", "7")}, - {0xff18, 0, 0, 0, g(Yes, No, false, false, "", "8")}, - {0xff19, 0, 0, 0, g(Yes, No, false, false, "", "9")}, - {0xff1a, 0, 0, 0, g(Yes, No, false, false, "", ":")}, - {0xff1b, 0, 0, 0, g(Yes, No, false, false, "", ";")}, - {0xff1c, 0, 0, 0, g(Yes, No, false, false, "", "<")}, - {0xff1d, 0, 0, 0, g(Yes, No, false, false, "", "=")}, - {0xff1e, 0, 0, 0, g(Yes, No, false, false, "", ">")}, - {0xff1f, 0, 0, 0, g(Yes, No, false, false, "", "?")}, - {0xff20, 0, 0, 0, g(Yes, No, false, false, "", "@")}, - {0xff21, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0xff22, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0xff23, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0xff24, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0xff25, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0xff26, 0, 0, 0, g(Yes, No, false, false, "", "F")}, - {0xff27, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0xff28, 0, 0, 0, g(Yes, No, false, false, "", "H")}, - {0xff29, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0xff2a, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0xff2b, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0xff2c, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0xff2d, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0xff2e, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0xff2f, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0xff30, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0xff31, 0, 0, 0, g(Yes, No, false, false, "", "Q")}, - {0xff32, 0, 0, 0, g(Yes, No, false, false, "", "R")}, - {0xff33, 0, 0, 0, g(Yes, No, false, false, "", "S")}, - {0xff34, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0xff35, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0xff36, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0xff37, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0xff38, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0xff39, 0, 0, 0, g(Yes, No, false, false, "", "Y")}, - {0xff3a, 0, 0, 0, g(Yes, No, false, false, "", "Z")}, - {0xff3b, 0, 0, 0, g(Yes, No, false, false, "", "[")}, - {0xff3c, 0, 0, 0, g(Yes, No, false, false, "", "\\")}, - {0xff3d, 0, 0, 0, g(Yes, No, false, false, "", "]")}, - {0xff3e, 0, 0, 0, g(Yes, No, false, false, "", "^")}, - {0xff3f, 0, 0, 0, g(Yes, No, false, false, "", "_")}, - {0xff40, 0, 0, 0, g(Yes, No, false, false, "", "`")}, - {0xff41, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0xff42, 0, 0, 0, g(Yes, No, false, false, "", "b")}, - {0xff43, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0xff44, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0xff45, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0xff46, 0, 0, 0, g(Yes, No, false, false, "", "f")}, - {0xff47, 0, 0, 0, g(Yes, No, false, false, "", "g")}, - {0xff48, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0xff49, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0xff4a, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0xff4b, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0xff4c, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0xff4d, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0xff4e, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0xff4f, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0xff50, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0xff51, 0, 0, 0, g(Yes, No, false, false, "", "q")}, - {0xff52, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0xff53, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0xff54, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0xff55, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0xff56, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0xff57, 0, 0, 0, g(Yes, No, false, false, "", "w")}, - {0xff58, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0xff59, 0, 0, 0, g(Yes, No, false, false, "", "y")}, - {0xff5a, 0, 0, 0, g(Yes, No, false, false, "", "z")}, - {0xff5b, 0, 0, 0, g(Yes, No, false, false, "", "{")}, - {0xff5c, 0, 0, 0, g(Yes, No, false, false, "", "|")}, - {0xff5d, 0, 0, 0, g(Yes, No, false, false, "", "}")}, - {0xff5e, 0, 0, 0, g(Yes, No, false, false, "", "~")}, - {0xff5f, 0, 0, 0, g(Yes, No, false, false, "", "⦅")}, - {0xff60, 0, 0, 0, g(Yes, No, false, false, "", "⦆")}, - {0xff61, 0, 0, 0, g(Yes, No, false, false, "", "。")}, - {0xff62, 0, 0, 0, g(Yes, No, false, false, "", "「")}, - {0xff63, 0, 0, 0, g(Yes, No, false, false, "", "」")}, - {0xff64, 0, 0, 0, g(Yes, No, false, false, "", "、")}, - {0xff65, 0, 0, 0, g(Yes, No, false, false, "", "・")}, - {0xff66, 0, 0, 0, g(Yes, No, false, false, "", "ヲ")}, - {0xff67, 0, 0, 0, g(Yes, No, false, false, "", "ァ")}, - {0xff68, 0, 0, 0, g(Yes, No, false, false, "", "ィ")}, - {0xff69, 0, 0, 0, g(Yes, No, false, false, "", "ゥ")}, - {0xff6a, 0, 0, 0, g(Yes, No, false, false, "", "ェ")}, - {0xff6b, 0, 0, 0, g(Yes, No, false, false, "", "ォ")}, - {0xff6c, 0, 0, 0, g(Yes, No, false, false, "", "ャ")}, - {0xff6d, 0, 0, 0, g(Yes, No, false, false, "", "ュ")}, - {0xff6e, 0, 0, 0, g(Yes, No, false, false, "", "ョ")}, - {0xff6f, 0, 0, 0, g(Yes, No, false, false, "", "ッ")}, - {0xff70, 0, 0, 0, g(Yes, No, false, false, "", "ー")}, - {0xff71, 0, 0, 0, g(Yes, No, false, false, "", "ア")}, - {0xff72, 0, 0, 0, g(Yes, No, false, false, "", "イ")}, - {0xff73, 0, 0, 0, g(Yes, No, false, false, "", "ウ")}, - {0xff74, 0, 0, 0, g(Yes, No, false, false, "", "エ")}, - {0xff75, 0, 0, 0, g(Yes, No, false, false, "", "オ")}, - {0xff76, 0, 0, 0, g(Yes, No, false, false, "", "カ")}, - {0xff77, 0, 0, 0, g(Yes, No, false, false, "", "キ")}, - {0xff78, 0, 0, 0, g(Yes, No, false, false, "", "ク")}, - {0xff79, 0, 0, 0, g(Yes, No, false, false, "", "ケ")}, - {0xff7a, 0, 0, 0, g(Yes, No, false, false, "", "コ")}, - {0xff7b, 0, 0, 0, g(Yes, No, false, false, "", "サ")}, - {0xff7c, 0, 0, 0, g(Yes, No, false, false, "", "シ")}, - {0xff7d, 0, 0, 0, g(Yes, No, false, false, "", "ス")}, - {0xff7e, 0, 0, 0, g(Yes, No, false, false, "", "セ")}, - {0xff7f, 0, 0, 0, g(Yes, No, false, false, "", "ソ")}, - {0xff80, 0, 0, 0, g(Yes, No, false, false, "", "タ")}, - {0xff81, 0, 0, 0, g(Yes, No, false, false, "", "チ")}, - {0xff82, 0, 0, 0, g(Yes, No, false, false, "", "ツ")}, - {0xff83, 0, 0, 0, g(Yes, No, false, false, "", "テ")}, - {0xff84, 0, 0, 0, g(Yes, No, false, false, "", "ト")}, - {0xff85, 0, 0, 0, g(Yes, No, false, false, "", "ナ")}, - {0xff86, 0, 0, 0, g(Yes, No, false, false, "", "ニ")}, - {0xff87, 0, 0, 0, g(Yes, No, false, false, "", "ヌ")}, - {0xff88, 0, 0, 0, g(Yes, No, false, false, "", "ネ")}, - {0xff89, 0, 0, 0, g(Yes, No, false, false, "", "ノ")}, - {0xff8a, 0, 0, 0, g(Yes, No, false, false, "", "ハ")}, - {0xff8b, 0, 0, 0, g(Yes, No, false, false, "", "ヒ")}, - {0xff8c, 0, 0, 0, g(Yes, No, false, false, "", "フ")}, - {0xff8d, 0, 0, 0, g(Yes, No, false, false, "", "ヘ")}, - {0xff8e, 0, 0, 0, g(Yes, No, false, false, "", "ホ")}, - {0xff8f, 0, 0, 0, g(Yes, No, false, false, "", "マ")}, - {0xff90, 0, 0, 0, g(Yes, No, false, false, "", "ミ")}, - {0xff91, 0, 0, 0, g(Yes, No, false, false, "", "ム")}, - {0xff92, 0, 0, 0, g(Yes, No, false, false, "", "メ")}, - {0xff93, 0, 0, 0, g(Yes, No, false, false, "", "モ")}, - {0xff94, 0, 0, 0, g(Yes, No, false, false, "", "ヤ")}, - {0xff95, 0, 0, 0, g(Yes, No, false, false, "", "ユ")}, - {0xff96, 0, 0, 0, g(Yes, No, false, false, "", "ヨ")}, - {0xff97, 0, 0, 0, g(Yes, No, false, false, "", "ラ")}, - {0xff98, 0, 0, 0, g(Yes, No, false, false, "", "リ")}, - {0xff99, 0, 0, 0, g(Yes, No, false, false, "", "ル")}, - {0xff9a, 0, 0, 0, g(Yes, No, false, false, "", "レ")}, - {0xff9b, 0, 0, 0, g(Yes, No, false, false, "", "ロ")}, - {0xff9c, 0, 0, 0, g(Yes, No, false, false, "", "ワ")}, - {0xff9d, 0, 0, 0, g(Yes, No, false, false, "", "ン")}, - {0xff9e, 0, 1, 1, g(Yes, No, false, false, "", "゙")}, - {0xff9f, 0, 1, 1, g(Yes, No, false, false, "", "゚")}, - {0xffa0, 0, 0, 0, g(Yes, No, false, false, "", "ᅠ")}, - {0xffa1, 0, 0, 0, g(Yes, No, false, false, "", "ᄀ")}, - {0xffa2, 0, 0, 0, g(Yes, No, false, false, "", "ᄁ")}, - {0xffa3, 0, 1, 1, g(Yes, No, false, false, "", "ᆪ")}, - {0xffa4, 0, 0, 0, g(Yes, No, false, false, "", "ᄂ")}, - {0xffa5, 0, 1, 1, g(Yes, No, false, false, "", "ᆬ")}, - {0xffa6, 0, 1, 1, g(Yes, No, false, false, "", "ᆭ")}, - {0xffa7, 0, 0, 0, g(Yes, No, false, false, "", "ᄃ")}, - {0xffa8, 0, 0, 0, g(Yes, No, false, false, "", "ᄄ")}, - {0xffa9, 0, 0, 0, g(Yes, No, false, false, "", "ᄅ")}, - {0xffaa, 0, 1, 1, g(Yes, No, false, false, "", "ᆰ")}, - {0xffab, 0, 1, 1, g(Yes, No, false, false, "", "ᆱ")}, - {0xffac, 0, 1, 1, g(Yes, No, false, false, "", "ᆲ")}, - {0xffad, 0, 1, 1, g(Yes, No, false, false, "", "ᆳ")}, - {0xffae, 0, 1, 1, g(Yes, No, false, false, "", "ᆴ")}, - {0xffaf, 0, 1, 1, g(Yes, No, false, false, "", "ᆵ")}, - {0xffb0, 0, 0, 0, g(Yes, No, false, false, "", "ᄚ")}, - {0xffb1, 0, 0, 0, g(Yes, No, false, false, "", "ᄆ")}, - {0xffb2, 0, 0, 0, g(Yes, No, false, false, "", "ᄇ")}, - {0xffb3, 0, 0, 0, g(Yes, No, false, false, "", "ᄈ")}, - {0xffb4, 0, 0, 0, g(Yes, No, false, false, "", "ᄡ")}, - {0xffb5, 0, 0, 0, g(Yes, No, false, false, "", "ᄉ")}, - {0xffb6, 0, 0, 0, g(Yes, No, false, false, "", "ᄊ")}, - {0xffb7, 0, 0, 0, g(Yes, No, false, false, "", "ᄋ")}, - {0xffb8, 0, 0, 0, g(Yes, No, false, false, "", "ᄌ")}, - {0xffb9, 0, 0, 0, g(Yes, No, false, false, "", "ᄍ")}, - {0xffba, 0, 0, 0, g(Yes, No, false, false, "", "ᄎ")}, - {0xffbb, 0, 0, 0, g(Yes, No, false, false, "", "ᄏ")}, - {0xffbc, 0, 0, 0, g(Yes, No, false, false, "", "ᄐ")}, - {0xffbd, 0, 0, 0, g(Yes, No, false, false, "", "ᄑ")}, - {0xffbe, 0, 0, 0, g(Yes, No, false, false, "", "ᄒ")}, - {0xffbf, 0, 0, 0, f(Yes, false, "")}, - {0xffc2, 0, 1, 1, g(Yes, No, false, false, "", "ᅡ")}, - {0xffc3, 0, 1, 1, g(Yes, No, false, false, "", "ᅢ")}, - {0xffc4, 0, 1, 1, g(Yes, No, false, false, "", "ᅣ")}, - {0xffc5, 0, 1, 1, g(Yes, No, false, false, "", "ᅤ")}, - {0xffc6, 0, 1, 1, g(Yes, No, false, false, "", "ᅥ")}, - {0xffc7, 0, 1, 1, g(Yes, No, false, false, "", "ᅦ")}, - {0xffc8, 0, 0, 0, f(Yes, false, "")}, - {0xffca, 0, 1, 1, g(Yes, No, false, false, "", "ᅧ")}, - {0xffcb, 0, 1, 1, g(Yes, No, false, false, "", "ᅨ")}, - {0xffcc, 0, 1, 1, g(Yes, No, false, false, "", "ᅩ")}, - {0xffcd, 0, 1, 1, g(Yes, No, false, false, "", "ᅪ")}, - {0xffce, 0, 1, 1, g(Yes, No, false, false, "", "ᅫ")}, - {0xffcf, 0, 1, 1, g(Yes, No, false, false, "", "ᅬ")}, - {0xffd0, 0, 0, 0, f(Yes, false, "")}, - {0xffd2, 0, 1, 1, g(Yes, No, false, false, "", "ᅭ")}, - {0xffd3, 0, 1, 1, g(Yes, No, false, false, "", "ᅮ")}, - {0xffd4, 0, 1, 1, g(Yes, No, false, false, "", "ᅯ")}, - {0xffd5, 0, 1, 1, g(Yes, No, false, false, "", "ᅰ")}, - {0xffd6, 0, 1, 1, g(Yes, No, false, false, "", "ᅱ")}, - {0xffd7, 0, 1, 1, g(Yes, No, false, false, "", "ᅲ")}, - {0xffd8, 0, 0, 0, f(Yes, false, "")}, - {0xffda, 0, 1, 1, g(Yes, No, false, false, "", "ᅳ")}, - {0xffdb, 0, 1, 1, g(Yes, No, false, false, "", "ᅴ")}, - {0xffdc, 0, 1, 1, g(Yes, No, false, false, "", "ᅵ")}, - {0xffdd, 0, 0, 0, f(Yes, false, "")}, - {0xffe0, 0, 0, 0, g(Yes, No, false, false, "", "¢")}, - {0xffe1, 0, 0, 0, g(Yes, No, false, false, "", "£")}, - {0xffe2, 0, 0, 0, g(Yes, No, false, false, "", "¬")}, - {0xffe3, 0, 0, 1, g(Yes, No, false, false, "", " ̄")}, - {0xffe4, 0, 0, 0, g(Yes, No, false, false, "", "¦")}, - {0xffe5, 0, 0, 0, g(Yes, No, false, false, "", "¥")}, - {0xffe6, 0, 0, 0, g(Yes, No, false, false, "", "₩")}, - {0xffe7, 0, 0, 0, f(Yes, false, "")}, - {0xffe8, 0, 0, 0, g(Yes, No, false, false, "", "│")}, - {0xffe9, 0, 0, 0, g(Yes, No, false, false, "", "←")}, - {0xffea, 0, 0, 0, g(Yes, No, false, false, "", "↑")}, - {0xffeb, 0, 0, 0, g(Yes, No, false, false, "", "→")}, - {0xffec, 0, 0, 0, g(Yes, No, false, false, "", "↓")}, - {0xffed, 0, 0, 0, g(Yes, No, false, false, "", "■")}, - {0xffee, 0, 0, 0, g(Yes, No, false, false, "", "○")}, - {0xffef, 0, 0, 0, f(Yes, false, "")}, - {0x101fd, 220, 1, 1, f(Yes, false, "")}, - {0x101fe, 0, 0, 0, f(Yes, false, "")}, - {0x102e0, 220, 1, 1, f(Yes, false, "")}, - {0x102e1, 0, 0, 0, f(Yes, false, "")}, - {0x10376, 230, 1, 1, f(Yes, false, "")}, - {0x1037b, 0, 0, 0, f(Yes, false, "")}, - {0x10a0d, 220, 1, 1, f(Yes, false, "")}, - {0x10a0e, 0, 0, 0, f(Yes, false, "")}, - {0x10a0f, 230, 1, 1, f(Yes, false, "")}, - {0x10a10, 0, 0, 0, f(Yes, false, "")}, - {0x10a38, 230, 1, 1, f(Yes, false, "")}, - {0x10a39, 1, 1, 1, f(Yes, false, "")}, - {0x10a3a, 220, 1, 1, f(Yes, false, "")}, - {0x10a3b, 0, 0, 0, f(Yes, false, "")}, - {0x10a3f, 9, 1, 1, f(Yes, false, "")}, - {0x10a40, 0, 0, 0, f(Yes, false, "")}, - {0x10ae5, 230, 1, 1, f(Yes, false, "")}, - {0x10ae6, 220, 1, 1, f(Yes, false, "")}, - {0x10ae7, 0, 0, 0, f(Yes, false, "")}, - {0x11046, 9, 1, 1, f(Yes, false, "")}, - {0x11047, 0, 0, 0, f(Yes, false, "")}, - {0x1107f, 9, 1, 1, f(Yes, false, "")}, - {0x11080, 0, 0, 0, f(Yes, false, "")}, - {0x11099, 0, 0, 0, f(Yes, true, "")}, - {0x1109a, 0, 0, 1, f(Yes, false, "𑂚")}, - {0x1109b, 0, 0, 0, f(Yes, true, "")}, - {0x1109c, 0, 0, 1, f(Yes, false, "𑂜")}, - {0x1109d, 0, 0, 0, f(Yes, false, "")}, - {0x110a5, 0, 0, 0, f(Yes, true, "")}, - {0x110a6, 0, 0, 0, f(Yes, false, "")}, - {0x110ab, 0, 0, 1, f(Yes, false, "𑂫")}, - {0x110ac, 0, 0, 0, f(Yes, false, "")}, - {0x110b9, 9, 1, 1, f(Yes, false, "")}, - {0x110ba, 7, 1, 1, f(Maybe, false, "")}, - {0x110bb, 0, 0, 0, f(Yes, false, "")}, - {0x11100, 230, 1, 1, f(Yes, false, "")}, - {0x11103, 0, 0, 0, f(Yes, false, "")}, - {0x11127, 0, 1, 1, f(Maybe, false, "")}, - {0x11128, 0, 0, 0, f(Yes, false, "")}, - {0x1112e, 0, 0, 1, f(Yes, false, "𑄮")}, - {0x1112f, 0, 0, 1, f(Yes, false, "𑄯")}, - {0x11130, 0, 0, 0, f(Yes, false, "")}, - {0x11131, 0, 0, 0, f(Yes, true, "")}, - {0x11133, 9, 1, 1, f(Yes, false, "")}, - {0x11135, 0, 0, 0, f(Yes, false, "")}, - {0x11173, 7, 1, 1, f(Yes, false, "")}, - {0x11174, 0, 0, 0, f(Yes, false, "")}, - {0x111c0, 9, 1, 1, f(Yes, false, "")}, - {0x111c1, 0, 0, 0, f(Yes, false, "")}, - {0x111ca, 7, 1, 1, f(Yes, false, "")}, - {0x111cb, 0, 0, 0, f(Yes, false, "")}, - {0x11235, 9, 1, 1, f(Yes, false, "")}, - {0x11236, 7, 1, 1, f(Yes, false, "")}, - {0x11237, 0, 0, 0, f(Yes, false, "")}, - {0x112e9, 7, 1, 1, f(Yes, false, "")}, - {0x112ea, 9, 1, 1, f(Yes, false, "")}, - {0x112eb, 0, 0, 0, f(Yes, false, "")}, - {0x1133c, 7, 1, 1, f(Yes, false, "")}, - {0x1133d, 0, 0, 0, f(Yes, false, "")}, - {0x1133e, 0, 1, 1, f(Maybe, false, "")}, - {0x1133f, 0, 0, 0, f(Yes, false, "")}, - {0x11347, 0, 0, 0, f(Yes, true, "")}, - {0x11348, 0, 0, 0, f(Yes, false, "")}, - {0x1134b, 0, 0, 1, f(Yes, false, "𑍋")}, - {0x1134c, 0, 0, 1, f(Yes, false, "𑍌")}, - {0x1134d, 9, 1, 1, f(Yes, false, "")}, - {0x1134e, 0, 0, 0, f(Yes, false, "")}, - {0x11357, 0, 1, 1, f(Maybe, false, "")}, - {0x11358, 0, 0, 0, f(Yes, false, "")}, - {0x11366, 230, 1, 1, f(Yes, false, "")}, - {0x1136d, 0, 0, 0, f(Yes, false, "")}, - {0x11370, 230, 1, 1, f(Yes, false, "")}, - {0x11375, 0, 0, 0, f(Yes, false, "")}, - {0x11442, 9, 1, 1, f(Yes, false, "")}, - {0x11443, 0, 0, 0, f(Yes, false, "")}, - {0x11446, 7, 1, 1, f(Yes, false, "")}, - {0x11447, 0, 0, 0, f(Yes, false, "")}, - {0x114b0, 0, 1, 1, f(Maybe, false, "")}, - {0x114b1, 0, 0, 0, f(Yes, false, "")}, - {0x114b9, 0, 0, 0, f(Yes, true, "")}, - {0x114ba, 0, 1, 1, f(Maybe, false, "")}, - {0x114bb, 0, 0, 1, f(Yes, false, "𑒻")}, - {0x114bc, 0, 0, 1, f(Yes, false, "𑒼")}, - {0x114bd, 0, 1, 1, f(Maybe, false, "")}, - {0x114be, 0, 0, 1, f(Yes, false, "𑒾")}, - {0x114bf, 0, 0, 0, f(Yes, false, "")}, - {0x114c2, 9, 1, 1, f(Yes, false, "")}, - {0x114c3, 7, 1, 1, f(Yes, false, "")}, - {0x114c4, 0, 0, 0, f(Yes, false, "")}, - {0x115af, 0, 1, 1, f(Maybe, false, "")}, - {0x115b0, 0, 0, 0, f(Yes, false, "")}, - {0x115b8, 0, 0, 0, f(Yes, true, "")}, - {0x115ba, 0, 0, 1, f(Yes, false, "𑖺")}, - {0x115bb, 0, 0, 1, f(Yes, false, "𑖻")}, - {0x115bc, 0, 0, 0, f(Yes, false, "")}, - {0x115bf, 9, 1, 1, f(Yes, false, "")}, - {0x115c0, 7, 1, 1, f(Yes, false, "")}, - {0x115c1, 0, 0, 0, f(Yes, false, "")}, - {0x1163f, 9, 1, 1, f(Yes, false, "")}, - {0x11640, 0, 0, 0, f(Yes, false, "")}, - {0x116b6, 9, 1, 1, f(Yes, false, "")}, - {0x116b7, 7, 1, 1, f(Yes, false, "")}, - {0x116b8, 0, 0, 0, f(Yes, false, "")}, - {0x1172b, 9, 1, 1, f(Yes, false, "")}, - {0x1172c, 0, 0, 0, f(Yes, false, "")}, - {0x11a34, 9, 1, 1, f(Yes, false, "")}, - {0x11a35, 0, 0, 0, f(Yes, false, "")}, - {0x11a47, 9, 1, 1, f(Yes, false, "")}, - {0x11a48, 0, 0, 0, f(Yes, false, "")}, - {0x11a99, 9, 1, 1, f(Yes, false, "")}, - {0x11a9a, 0, 0, 0, f(Yes, false, "")}, - {0x11c3f, 9, 1, 1, f(Yes, false, "")}, - {0x11c40, 0, 0, 0, f(Yes, false, "")}, - {0x11d42, 7, 1, 1, f(Yes, false, "")}, - {0x11d43, 0, 0, 0, f(Yes, false, "")}, - {0x11d44, 9, 1, 1, f(Yes, false, "")}, - {0x11d46, 0, 0, 0, f(Yes, false, "")}, - {0x16af0, 1, 1, 1, f(Yes, false, "")}, - {0x16af5, 0, 0, 0, f(Yes, false, "")}, - {0x16b30, 230, 1, 1, f(Yes, false, "")}, - {0x16b37, 0, 0, 0, f(Yes, false, "")}, - {0x1bc9e, 1, 1, 1, f(Yes, false, "")}, - {0x1bc9f, 0, 0, 0, f(Yes, false, "")}, - {0x1d15e, 0, 0, 1, f(No, false, "𝅗𝅥")}, - {0x1d15f, 0, 0, 1, f(No, false, "𝅘𝅥")}, - {0x1d160, 0, 0, 2, f(No, false, "𝅘𝅥𝅮")}, - {0x1d161, 0, 0, 2, f(No, false, "𝅘𝅥𝅯")}, - {0x1d162, 0, 0, 2, f(No, false, "𝅘𝅥𝅰")}, - {0x1d163, 0, 0, 2, f(No, false, "𝅘𝅥𝅱")}, - {0x1d164, 0, 0, 2, f(No, false, "𝅘𝅥𝅲")}, - {0x1d165, 216, 1, 1, f(Yes, false, "")}, - {0x1d167, 1, 1, 1, f(Yes, false, "")}, - {0x1d16a, 0, 0, 0, f(Yes, false, "")}, - {0x1d16d, 226, 1, 1, f(Yes, false, "")}, - {0x1d16e, 216, 1, 1, f(Yes, false, "")}, - {0x1d173, 0, 0, 0, f(Yes, false, "")}, - {0x1d17b, 220, 1, 1, f(Yes, false, "")}, - {0x1d183, 0, 0, 0, f(Yes, false, "")}, - {0x1d185, 230, 1, 1, f(Yes, false, "")}, - {0x1d18a, 220, 1, 1, f(Yes, false, "")}, - {0x1d18c, 0, 0, 0, f(Yes, false, "")}, - {0x1d1aa, 230, 1, 1, f(Yes, false, "")}, - {0x1d1ae, 0, 0, 0, f(Yes, false, "")}, - {0x1d1bb, 0, 0, 1, f(No, false, "𝆹𝅥")}, - {0x1d1bc, 0, 0, 1, f(No, false, "𝆺𝅥")}, - {0x1d1bd, 0, 0, 2, f(No, false, "𝆹𝅥𝅮")}, - {0x1d1be, 0, 0, 2, f(No, false, "𝆺𝅥𝅮")}, - {0x1d1bf, 0, 0, 2, f(No, false, "𝆹𝅥𝅯")}, - {0x1d1c0, 0, 0, 2, f(No, false, "𝆺𝅥𝅯")}, - {0x1d1c1, 0, 0, 0, f(Yes, false, "")}, - {0x1d242, 230, 1, 1, f(Yes, false, "")}, - {0x1d245, 0, 0, 0, f(Yes, false, "")}, - {0x1d400, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0x1d401, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0x1d402, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x1d403, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x1d404, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0x1d405, 0, 0, 0, g(Yes, No, false, false, "", "F")}, - {0x1d406, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0x1d407, 0, 0, 0, g(Yes, No, false, false, "", "H")}, - {0x1d408, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0x1d409, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0x1d40a, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0x1d40b, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x1d40c, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x1d40d, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0x1d40e, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0x1d40f, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0x1d410, 0, 0, 0, g(Yes, No, false, false, "", "Q")}, - {0x1d411, 0, 0, 0, g(Yes, No, false, false, "", "R")}, - {0x1d412, 0, 0, 0, g(Yes, No, false, false, "", "S")}, - {0x1d413, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0x1d414, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0x1d415, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x1d416, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0x1d417, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0x1d418, 0, 0, 0, g(Yes, No, false, false, "", "Y")}, - {0x1d419, 0, 0, 0, g(Yes, No, false, false, "", "Z")}, - {0x1d41a, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0x1d41b, 0, 0, 0, g(Yes, No, false, false, "", "b")}, - {0x1d41c, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0x1d41d, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x1d41e, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x1d41f, 0, 0, 0, g(Yes, No, false, false, "", "f")}, - {0x1d420, 0, 0, 0, g(Yes, No, false, false, "", "g")}, - {0x1d421, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0x1d422, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x1d423, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x1d424, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0x1d425, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x1d426, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x1d427, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0x1d428, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0x1d429, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0x1d42a, 0, 0, 0, g(Yes, No, false, false, "", "q")}, - {0x1d42b, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0x1d42c, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0x1d42d, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0x1d42e, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0x1d42f, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x1d430, 0, 0, 0, g(Yes, No, false, false, "", "w")}, - {0x1d431, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x1d432, 0, 0, 0, g(Yes, No, false, false, "", "y")}, - {0x1d433, 0, 0, 0, g(Yes, No, false, false, "", "z")}, - {0x1d434, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0x1d435, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0x1d436, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x1d437, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x1d438, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0x1d439, 0, 0, 0, g(Yes, No, false, false, "", "F")}, - {0x1d43a, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0x1d43b, 0, 0, 0, g(Yes, No, false, false, "", "H")}, - {0x1d43c, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0x1d43d, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0x1d43e, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0x1d43f, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x1d440, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x1d441, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0x1d442, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0x1d443, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0x1d444, 0, 0, 0, g(Yes, No, false, false, "", "Q")}, - {0x1d445, 0, 0, 0, g(Yes, No, false, false, "", "R")}, - {0x1d446, 0, 0, 0, g(Yes, No, false, false, "", "S")}, - {0x1d447, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0x1d448, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0x1d449, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x1d44a, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0x1d44b, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0x1d44c, 0, 0, 0, g(Yes, No, false, false, "", "Y")}, - {0x1d44d, 0, 0, 0, g(Yes, No, false, false, "", "Z")}, - {0x1d44e, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0x1d44f, 0, 0, 0, g(Yes, No, false, false, "", "b")}, - {0x1d450, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0x1d451, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x1d452, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x1d453, 0, 0, 0, g(Yes, No, false, false, "", "f")}, - {0x1d454, 0, 0, 0, g(Yes, No, false, false, "", "g")}, - {0x1d455, 0, 0, 0, f(Yes, false, "")}, - {0x1d456, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x1d457, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x1d458, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0x1d459, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x1d45a, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x1d45b, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0x1d45c, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0x1d45d, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0x1d45e, 0, 0, 0, g(Yes, No, false, false, "", "q")}, - {0x1d45f, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0x1d460, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0x1d461, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0x1d462, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0x1d463, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x1d464, 0, 0, 0, g(Yes, No, false, false, "", "w")}, - {0x1d465, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x1d466, 0, 0, 0, g(Yes, No, false, false, "", "y")}, - {0x1d467, 0, 0, 0, g(Yes, No, false, false, "", "z")}, - {0x1d468, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0x1d469, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0x1d46a, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x1d46b, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x1d46c, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0x1d46d, 0, 0, 0, g(Yes, No, false, false, "", "F")}, - {0x1d46e, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0x1d46f, 0, 0, 0, g(Yes, No, false, false, "", "H")}, - {0x1d470, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0x1d471, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0x1d472, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0x1d473, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x1d474, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x1d475, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0x1d476, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0x1d477, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0x1d478, 0, 0, 0, g(Yes, No, false, false, "", "Q")}, - {0x1d479, 0, 0, 0, g(Yes, No, false, false, "", "R")}, - {0x1d47a, 0, 0, 0, g(Yes, No, false, false, "", "S")}, - {0x1d47b, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0x1d47c, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0x1d47d, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x1d47e, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0x1d47f, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0x1d480, 0, 0, 0, g(Yes, No, false, false, "", "Y")}, - {0x1d481, 0, 0, 0, g(Yes, No, false, false, "", "Z")}, - {0x1d482, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0x1d483, 0, 0, 0, g(Yes, No, false, false, "", "b")}, - {0x1d484, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0x1d485, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x1d486, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x1d487, 0, 0, 0, g(Yes, No, false, false, "", "f")}, - {0x1d488, 0, 0, 0, g(Yes, No, false, false, "", "g")}, - {0x1d489, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0x1d48a, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x1d48b, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x1d48c, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0x1d48d, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x1d48e, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x1d48f, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0x1d490, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0x1d491, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0x1d492, 0, 0, 0, g(Yes, No, false, false, "", "q")}, - {0x1d493, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0x1d494, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0x1d495, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0x1d496, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0x1d497, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x1d498, 0, 0, 0, g(Yes, No, false, false, "", "w")}, - {0x1d499, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x1d49a, 0, 0, 0, g(Yes, No, false, false, "", "y")}, - {0x1d49b, 0, 0, 0, g(Yes, No, false, false, "", "z")}, - {0x1d49c, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0x1d49d, 0, 0, 0, f(Yes, false, "")}, - {0x1d49e, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x1d49f, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x1d4a0, 0, 0, 0, f(Yes, false, "")}, - {0x1d4a2, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0x1d4a3, 0, 0, 0, f(Yes, false, "")}, - {0x1d4a5, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0x1d4a6, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0x1d4a7, 0, 0, 0, f(Yes, false, "")}, - {0x1d4a9, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0x1d4aa, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0x1d4ab, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0x1d4ac, 0, 0, 0, g(Yes, No, false, false, "", "Q")}, - {0x1d4ad, 0, 0, 0, f(Yes, false, "")}, - {0x1d4ae, 0, 0, 0, g(Yes, No, false, false, "", "S")}, - {0x1d4af, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0x1d4b0, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0x1d4b1, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x1d4b2, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0x1d4b3, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0x1d4b4, 0, 0, 0, g(Yes, No, false, false, "", "Y")}, - {0x1d4b5, 0, 0, 0, g(Yes, No, false, false, "", "Z")}, - {0x1d4b6, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0x1d4b7, 0, 0, 0, g(Yes, No, false, false, "", "b")}, - {0x1d4b8, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0x1d4b9, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x1d4ba, 0, 0, 0, f(Yes, false, "")}, - {0x1d4bb, 0, 0, 0, g(Yes, No, false, false, "", "f")}, - {0x1d4bc, 0, 0, 0, f(Yes, false, "")}, - {0x1d4bd, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0x1d4be, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x1d4bf, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x1d4c0, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0x1d4c1, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x1d4c2, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x1d4c3, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0x1d4c4, 0, 0, 0, f(Yes, false, "")}, - {0x1d4c5, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0x1d4c6, 0, 0, 0, g(Yes, No, false, false, "", "q")}, - {0x1d4c7, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0x1d4c8, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0x1d4c9, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0x1d4ca, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0x1d4cb, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x1d4cc, 0, 0, 0, g(Yes, No, false, false, "", "w")}, - {0x1d4cd, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x1d4ce, 0, 0, 0, g(Yes, No, false, false, "", "y")}, - {0x1d4cf, 0, 0, 0, g(Yes, No, false, false, "", "z")}, - {0x1d4d0, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0x1d4d1, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0x1d4d2, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x1d4d3, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x1d4d4, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0x1d4d5, 0, 0, 0, g(Yes, No, false, false, "", "F")}, - {0x1d4d6, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0x1d4d7, 0, 0, 0, g(Yes, No, false, false, "", "H")}, - {0x1d4d8, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0x1d4d9, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0x1d4da, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0x1d4db, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x1d4dc, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x1d4dd, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0x1d4de, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0x1d4df, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0x1d4e0, 0, 0, 0, g(Yes, No, false, false, "", "Q")}, - {0x1d4e1, 0, 0, 0, g(Yes, No, false, false, "", "R")}, - {0x1d4e2, 0, 0, 0, g(Yes, No, false, false, "", "S")}, - {0x1d4e3, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0x1d4e4, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0x1d4e5, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x1d4e6, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0x1d4e7, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0x1d4e8, 0, 0, 0, g(Yes, No, false, false, "", "Y")}, - {0x1d4e9, 0, 0, 0, g(Yes, No, false, false, "", "Z")}, - {0x1d4ea, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0x1d4eb, 0, 0, 0, g(Yes, No, false, false, "", "b")}, - {0x1d4ec, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0x1d4ed, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x1d4ee, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x1d4ef, 0, 0, 0, g(Yes, No, false, false, "", "f")}, - {0x1d4f0, 0, 0, 0, g(Yes, No, false, false, "", "g")}, - {0x1d4f1, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0x1d4f2, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x1d4f3, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x1d4f4, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0x1d4f5, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x1d4f6, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x1d4f7, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0x1d4f8, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0x1d4f9, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0x1d4fa, 0, 0, 0, g(Yes, No, false, false, "", "q")}, - {0x1d4fb, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0x1d4fc, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0x1d4fd, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0x1d4fe, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0x1d4ff, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x1d500, 0, 0, 0, g(Yes, No, false, false, "", "w")}, - {0x1d501, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x1d502, 0, 0, 0, g(Yes, No, false, false, "", "y")}, - {0x1d503, 0, 0, 0, g(Yes, No, false, false, "", "z")}, - {0x1d504, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0x1d505, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0x1d506, 0, 0, 0, f(Yes, false, "")}, - {0x1d507, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x1d508, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0x1d509, 0, 0, 0, g(Yes, No, false, false, "", "F")}, - {0x1d50a, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0x1d50b, 0, 0, 0, f(Yes, false, "")}, - {0x1d50d, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0x1d50e, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0x1d50f, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x1d510, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x1d511, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0x1d512, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0x1d513, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0x1d514, 0, 0, 0, g(Yes, No, false, false, "", "Q")}, - {0x1d515, 0, 0, 0, f(Yes, false, "")}, - {0x1d516, 0, 0, 0, g(Yes, No, false, false, "", "S")}, - {0x1d517, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0x1d518, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0x1d519, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x1d51a, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0x1d51b, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0x1d51c, 0, 0, 0, g(Yes, No, false, false, "", "Y")}, - {0x1d51d, 0, 0, 0, f(Yes, false, "")}, - {0x1d51e, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0x1d51f, 0, 0, 0, g(Yes, No, false, false, "", "b")}, - {0x1d520, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0x1d521, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x1d522, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x1d523, 0, 0, 0, g(Yes, No, false, false, "", "f")}, - {0x1d524, 0, 0, 0, g(Yes, No, false, false, "", "g")}, - {0x1d525, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0x1d526, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x1d527, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x1d528, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0x1d529, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x1d52a, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x1d52b, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0x1d52c, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0x1d52d, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0x1d52e, 0, 0, 0, g(Yes, No, false, false, "", "q")}, - {0x1d52f, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0x1d530, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0x1d531, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0x1d532, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0x1d533, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x1d534, 0, 0, 0, g(Yes, No, false, false, "", "w")}, - {0x1d535, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x1d536, 0, 0, 0, g(Yes, No, false, false, "", "y")}, - {0x1d537, 0, 0, 0, g(Yes, No, false, false, "", "z")}, - {0x1d538, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0x1d539, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0x1d53a, 0, 0, 0, f(Yes, false, "")}, - {0x1d53b, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x1d53c, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0x1d53d, 0, 0, 0, g(Yes, No, false, false, "", "F")}, - {0x1d53e, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0x1d53f, 0, 0, 0, f(Yes, false, "")}, - {0x1d540, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0x1d541, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0x1d542, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0x1d543, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x1d544, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x1d545, 0, 0, 0, f(Yes, false, "")}, - {0x1d546, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0x1d547, 0, 0, 0, f(Yes, false, "")}, - {0x1d54a, 0, 0, 0, g(Yes, No, false, false, "", "S")}, - {0x1d54b, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0x1d54c, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0x1d54d, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x1d54e, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0x1d54f, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0x1d550, 0, 0, 0, g(Yes, No, false, false, "", "Y")}, - {0x1d551, 0, 0, 0, f(Yes, false, "")}, - {0x1d552, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0x1d553, 0, 0, 0, g(Yes, No, false, false, "", "b")}, - {0x1d554, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0x1d555, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x1d556, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x1d557, 0, 0, 0, g(Yes, No, false, false, "", "f")}, - {0x1d558, 0, 0, 0, g(Yes, No, false, false, "", "g")}, - {0x1d559, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0x1d55a, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x1d55b, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x1d55c, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0x1d55d, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x1d55e, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x1d55f, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0x1d560, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0x1d561, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0x1d562, 0, 0, 0, g(Yes, No, false, false, "", "q")}, - {0x1d563, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0x1d564, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0x1d565, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0x1d566, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0x1d567, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x1d568, 0, 0, 0, g(Yes, No, false, false, "", "w")}, - {0x1d569, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x1d56a, 0, 0, 0, g(Yes, No, false, false, "", "y")}, - {0x1d56b, 0, 0, 0, g(Yes, No, false, false, "", "z")}, - {0x1d56c, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0x1d56d, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0x1d56e, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x1d56f, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x1d570, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0x1d571, 0, 0, 0, g(Yes, No, false, false, "", "F")}, - {0x1d572, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0x1d573, 0, 0, 0, g(Yes, No, false, false, "", "H")}, - {0x1d574, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0x1d575, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0x1d576, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0x1d577, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x1d578, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x1d579, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0x1d57a, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0x1d57b, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0x1d57c, 0, 0, 0, g(Yes, No, false, false, "", "Q")}, - {0x1d57d, 0, 0, 0, g(Yes, No, false, false, "", "R")}, - {0x1d57e, 0, 0, 0, g(Yes, No, false, false, "", "S")}, - {0x1d57f, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0x1d580, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0x1d581, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x1d582, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0x1d583, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0x1d584, 0, 0, 0, g(Yes, No, false, false, "", "Y")}, - {0x1d585, 0, 0, 0, g(Yes, No, false, false, "", "Z")}, - {0x1d586, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0x1d587, 0, 0, 0, g(Yes, No, false, false, "", "b")}, - {0x1d588, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0x1d589, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x1d58a, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x1d58b, 0, 0, 0, g(Yes, No, false, false, "", "f")}, - {0x1d58c, 0, 0, 0, g(Yes, No, false, false, "", "g")}, - {0x1d58d, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0x1d58e, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x1d58f, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x1d590, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0x1d591, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x1d592, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x1d593, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0x1d594, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0x1d595, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0x1d596, 0, 0, 0, g(Yes, No, false, false, "", "q")}, - {0x1d597, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0x1d598, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0x1d599, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0x1d59a, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0x1d59b, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x1d59c, 0, 0, 0, g(Yes, No, false, false, "", "w")}, - {0x1d59d, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x1d59e, 0, 0, 0, g(Yes, No, false, false, "", "y")}, - {0x1d59f, 0, 0, 0, g(Yes, No, false, false, "", "z")}, - {0x1d5a0, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0x1d5a1, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0x1d5a2, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x1d5a3, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x1d5a4, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0x1d5a5, 0, 0, 0, g(Yes, No, false, false, "", "F")}, - {0x1d5a6, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0x1d5a7, 0, 0, 0, g(Yes, No, false, false, "", "H")}, - {0x1d5a8, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0x1d5a9, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0x1d5aa, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0x1d5ab, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x1d5ac, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x1d5ad, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0x1d5ae, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0x1d5af, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0x1d5b0, 0, 0, 0, g(Yes, No, false, false, "", "Q")}, - {0x1d5b1, 0, 0, 0, g(Yes, No, false, false, "", "R")}, - {0x1d5b2, 0, 0, 0, g(Yes, No, false, false, "", "S")}, - {0x1d5b3, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0x1d5b4, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0x1d5b5, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x1d5b6, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0x1d5b7, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0x1d5b8, 0, 0, 0, g(Yes, No, false, false, "", "Y")}, - {0x1d5b9, 0, 0, 0, g(Yes, No, false, false, "", "Z")}, - {0x1d5ba, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0x1d5bb, 0, 0, 0, g(Yes, No, false, false, "", "b")}, - {0x1d5bc, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0x1d5bd, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x1d5be, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x1d5bf, 0, 0, 0, g(Yes, No, false, false, "", "f")}, - {0x1d5c0, 0, 0, 0, g(Yes, No, false, false, "", "g")}, - {0x1d5c1, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0x1d5c2, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x1d5c3, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x1d5c4, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0x1d5c5, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x1d5c6, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x1d5c7, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0x1d5c8, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0x1d5c9, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0x1d5ca, 0, 0, 0, g(Yes, No, false, false, "", "q")}, - {0x1d5cb, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0x1d5cc, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0x1d5cd, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0x1d5ce, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0x1d5cf, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x1d5d0, 0, 0, 0, g(Yes, No, false, false, "", "w")}, - {0x1d5d1, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x1d5d2, 0, 0, 0, g(Yes, No, false, false, "", "y")}, - {0x1d5d3, 0, 0, 0, g(Yes, No, false, false, "", "z")}, - {0x1d5d4, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0x1d5d5, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0x1d5d6, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x1d5d7, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x1d5d8, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0x1d5d9, 0, 0, 0, g(Yes, No, false, false, "", "F")}, - {0x1d5da, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0x1d5db, 0, 0, 0, g(Yes, No, false, false, "", "H")}, - {0x1d5dc, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0x1d5dd, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0x1d5de, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0x1d5df, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x1d5e0, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x1d5e1, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0x1d5e2, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0x1d5e3, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0x1d5e4, 0, 0, 0, g(Yes, No, false, false, "", "Q")}, - {0x1d5e5, 0, 0, 0, g(Yes, No, false, false, "", "R")}, - {0x1d5e6, 0, 0, 0, g(Yes, No, false, false, "", "S")}, - {0x1d5e7, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0x1d5e8, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0x1d5e9, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x1d5ea, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0x1d5eb, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0x1d5ec, 0, 0, 0, g(Yes, No, false, false, "", "Y")}, - {0x1d5ed, 0, 0, 0, g(Yes, No, false, false, "", "Z")}, - {0x1d5ee, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0x1d5ef, 0, 0, 0, g(Yes, No, false, false, "", "b")}, - {0x1d5f0, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0x1d5f1, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x1d5f2, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x1d5f3, 0, 0, 0, g(Yes, No, false, false, "", "f")}, - {0x1d5f4, 0, 0, 0, g(Yes, No, false, false, "", "g")}, - {0x1d5f5, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0x1d5f6, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x1d5f7, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x1d5f8, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0x1d5f9, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x1d5fa, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x1d5fb, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0x1d5fc, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0x1d5fd, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0x1d5fe, 0, 0, 0, g(Yes, No, false, false, "", "q")}, - {0x1d5ff, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0x1d600, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0x1d601, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0x1d602, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0x1d603, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x1d604, 0, 0, 0, g(Yes, No, false, false, "", "w")}, - {0x1d605, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x1d606, 0, 0, 0, g(Yes, No, false, false, "", "y")}, - {0x1d607, 0, 0, 0, g(Yes, No, false, false, "", "z")}, - {0x1d608, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0x1d609, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0x1d60a, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x1d60b, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x1d60c, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0x1d60d, 0, 0, 0, g(Yes, No, false, false, "", "F")}, - {0x1d60e, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0x1d60f, 0, 0, 0, g(Yes, No, false, false, "", "H")}, - {0x1d610, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0x1d611, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0x1d612, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0x1d613, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x1d614, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x1d615, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0x1d616, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0x1d617, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0x1d618, 0, 0, 0, g(Yes, No, false, false, "", "Q")}, - {0x1d619, 0, 0, 0, g(Yes, No, false, false, "", "R")}, - {0x1d61a, 0, 0, 0, g(Yes, No, false, false, "", "S")}, - {0x1d61b, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0x1d61c, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0x1d61d, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x1d61e, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0x1d61f, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0x1d620, 0, 0, 0, g(Yes, No, false, false, "", "Y")}, - {0x1d621, 0, 0, 0, g(Yes, No, false, false, "", "Z")}, - {0x1d622, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0x1d623, 0, 0, 0, g(Yes, No, false, false, "", "b")}, - {0x1d624, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0x1d625, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x1d626, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x1d627, 0, 0, 0, g(Yes, No, false, false, "", "f")}, - {0x1d628, 0, 0, 0, g(Yes, No, false, false, "", "g")}, - {0x1d629, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0x1d62a, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x1d62b, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x1d62c, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0x1d62d, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x1d62e, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x1d62f, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0x1d630, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0x1d631, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0x1d632, 0, 0, 0, g(Yes, No, false, false, "", "q")}, - {0x1d633, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0x1d634, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0x1d635, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0x1d636, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0x1d637, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x1d638, 0, 0, 0, g(Yes, No, false, false, "", "w")}, - {0x1d639, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x1d63a, 0, 0, 0, g(Yes, No, false, false, "", "y")}, - {0x1d63b, 0, 0, 0, g(Yes, No, false, false, "", "z")}, - {0x1d63c, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0x1d63d, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0x1d63e, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x1d63f, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x1d640, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0x1d641, 0, 0, 0, g(Yes, No, false, false, "", "F")}, - {0x1d642, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0x1d643, 0, 0, 0, g(Yes, No, false, false, "", "H")}, - {0x1d644, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0x1d645, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0x1d646, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0x1d647, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x1d648, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x1d649, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0x1d64a, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0x1d64b, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0x1d64c, 0, 0, 0, g(Yes, No, false, false, "", "Q")}, - {0x1d64d, 0, 0, 0, g(Yes, No, false, false, "", "R")}, - {0x1d64e, 0, 0, 0, g(Yes, No, false, false, "", "S")}, - {0x1d64f, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0x1d650, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0x1d651, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x1d652, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0x1d653, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0x1d654, 0, 0, 0, g(Yes, No, false, false, "", "Y")}, - {0x1d655, 0, 0, 0, g(Yes, No, false, false, "", "Z")}, - {0x1d656, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0x1d657, 0, 0, 0, g(Yes, No, false, false, "", "b")}, - {0x1d658, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0x1d659, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x1d65a, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x1d65b, 0, 0, 0, g(Yes, No, false, false, "", "f")}, - {0x1d65c, 0, 0, 0, g(Yes, No, false, false, "", "g")}, - {0x1d65d, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0x1d65e, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x1d65f, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x1d660, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0x1d661, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x1d662, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x1d663, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0x1d664, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0x1d665, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0x1d666, 0, 0, 0, g(Yes, No, false, false, "", "q")}, - {0x1d667, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0x1d668, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0x1d669, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0x1d66a, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0x1d66b, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x1d66c, 0, 0, 0, g(Yes, No, false, false, "", "w")}, - {0x1d66d, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x1d66e, 0, 0, 0, g(Yes, No, false, false, "", "y")}, - {0x1d66f, 0, 0, 0, g(Yes, No, false, false, "", "z")}, - {0x1d670, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0x1d671, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0x1d672, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x1d673, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x1d674, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0x1d675, 0, 0, 0, g(Yes, No, false, false, "", "F")}, - {0x1d676, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0x1d677, 0, 0, 0, g(Yes, No, false, false, "", "H")}, - {0x1d678, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0x1d679, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0x1d67a, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0x1d67b, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x1d67c, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x1d67d, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0x1d67e, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0x1d67f, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0x1d680, 0, 0, 0, g(Yes, No, false, false, "", "Q")}, - {0x1d681, 0, 0, 0, g(Yes, No, false, false, "", "R")}, - {0x1d682, 0, 0, 0, g(Yes, No, false, false, "", "S")}, - {0x1d683, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0x1d684, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0x1d685, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x1d686, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0x1d687, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0x1d688, 0, 0, 0, g(Yes, No, false, false, "", "Y")}, - {0x1d689, 0, 0, 0, g(Yes, No, false, false, "", "Z")}, - {0x1d68a, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0x1d68b, 0, 0, 0, g(Yes, No, false, false, "", "b")}, - {0x1d68c, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0x1d68d, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x1d68e, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x1d68f, 0, 0, 0, g(Yes, No, false, false, "", "f")}, - {0x1d690, 0, 0, 0, g(Yes, No, false, false, "", "g")}, - {0x1d691, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0x1d692, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x1d693, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x1d694, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0x1d695, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x1d696, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x1d697, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0x1d698, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0x1d699, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0x1d69a, 0, 0, 0, g(Yes, No, false, false, "", "q")}, - {0x1d69b, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0x1d69c, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0x1d69d, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0x1d69e, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0x1d69f, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x1d6a0, 0, 0, 0, g(Yes, No, false, false, "", "w")}, - {0x1d6a1, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x1d6a2, 0, 0, 0, g(Yes, No, false, false, "", "y")}, - {0x1d6a3, 0, 0, 0, g(Yes, No, false, false, "", "z")}, - {0x1d6a4, 0, 0, 0, g(Yes, No, false, false, "", "ı")}, - {0x1d6a5, 0, 0, 0, g(Yes, No, false, false, "", "ȷ")}, - {0x1d6a6, 0, 0, 0, f(Yes, false, "")}, - {0x1d6a8, 0, 0, 0, g(Yes, No, false, false, "", "Α")}, - {0x1d6a9, 0, 0, 0, g(Yes, No, false, false, "", "Β")}, - {0x1d6aa, 0, 0, 0, g(Yes, No, false, false, "", "Γ")}, - {0x1d6ab, 0, 0, 0, g(Yes, No, false, false, "", "Δ")}, - {0x1d6ac, 0, 0, 0, g(Yes, No, false, false, "", "Ε")}, - {0x1d6ad, 0, 0, 0, g(Yes, No, false, false, "", "Ζ")}, - {0x1d6ae, 0, 0, 0, g(Yes, No, false, false, "", "Η")}, - {0x1d6af, 0, 0, 0, g(Yes, No, false, false, "", "Θ")}, - {0x1d6b0, 0, 0, 0, g(Yes, No, false, false, "", "Ι")}, - {0x1d6b1, 0, 0, 0, g(Yes, No, false, false, "", "Κ")}, - {0x1d6b2, 0, 0, 0, g(Yes, No, false, false, "", "Λ")}, - {0x1d6b3, 0, 0, 0, g(Yes, No, false, false, "", "Μ")}, - {0x1d6b4, 0, 0, 0, g(Yes, No, false, false, "", "Ν")}, - {0x1d6b5, 0, 0, 0, g(Yes, No, false, false, "", "Ξ")}, - {0x1d6b6, 0, 0, 0, g(Yes, No, false, false, "", "Ο")}, - {0x1d6b7, 0, 0, 0, g(Yes, No, false, false, "", "Π")}, - {0x1d6b8, 0, 0, 0, g(Yes, No, false, false, "", "Ρ")}, - {0x1d6b9, 0, 0, 0, g(Yes, No, false, false, "", "Θ")}, - {0x1d6ba, 0, 0, 0, g(Yes, No, false, false, "", "Σ")}, - {0x1d6bb, 0, 0, 0, g(Yes, No, false, false, "", "Τ")}, - {0x1d6bc, 0, 0, 0, g(Yes, No, false, false, "", "Υ")}, - {0x1d6bd, 0, 0, 0, g(Yes, No, false, false, "", "Φ")}, - {0x1d6be, 0, 0, 0, g(Yes, No, false, false, "", "Χ")}, - {0x1d6bf, 0, 0, 0, g(Yes, No, false, false, "", "Ψ")}, - {0x1d6c0, 0, 0, 0, g(Yes, No, false, false, "", "Ω")}, - {0x1d6c1, 0, 0, 0, g(Yes, No, false, false, "", "∇")}, - {0x1d6c2, 0, 0, 0, g(Yes, No, false, false, "", "α")}, - {0x1d6c3, 0, 0, 0, g(Yes, No, false, false, "", "β")}, - {0x1d6c4, 0, 0, 0, g(Yes, No, false, false, "", "γ")}, - {0x1d6c5, 0, 0, 0, g(Yes, No, false, false, "", "δ")}, - {0x1d6c6, 0, 0, 0, g(Yes, No, false, false, "", "ε")}, - {0x1d6c7, 0, 0, 0, g(Yes, No, false, false, "", "ζ")}, - {0x1d6c8, 0, 0, 0, g(Yes, No, false, false, "", "η")}, - {0x1d6c9, 0, 0, 0, g(Yes, No, false, false, "", "θ")}, - {0x1d6ca, 0, 0, 0, g(Yes, No, false, false, "", "ι")}, - {0x1d6cb, 0, 0, 0, g(Yes, No, false, false, "", "κ")}, - {0x1d6cc, 0, 0, 0, g(Yes, No, false, false, "", "λ")}, - {0x1d6cd, 0, 0, 0, g(Yes, No, false, false, "", "μ")}, - {0x1d6ce, 0, 0, 0, g(Yes, No, false, false, "", "ν")}, - {0x1d6cf, 0, 0, 0, g(Yes, No, false, false, "", "ξ")}, - {0x1d6d0, 0, 0, 0, g(Yes, No, false, false, "", "ο")}, - {0x1d6d1, 0, 0, 0, g(Yes, No, false, false, "", "π")}, - {0x1d6d2, 0, 0, 0, g(Yes, No, false, false, "", "ρ")}, - {0x1d6d3, 0, 0, 0, g(Yes, No, false, false, "", "ς")}, - {0x1d6d4, 0, 0, 0, g(Yes, No, false, false, "", "σ")}, - {0x1d6d5, 0, 0, 0, g(Yes, No, false, false, "", "τ")}, - {0x1d6d6, 0, 0, 0, g(Yes, No, false, false, "", "υ")}, - {0x1d6d7, 0, 0, 0, g(Yes, No, false, false, "", "φ")}, - {0x1d6d8, 0, 0, 0, g(Yes, No, false, false, "", "χ")}, - {0x1d6d9, 0, 0, 0, g(Yes, No, false, false, "", "ψ")}, - {0x1d6da, 0, 0, 0, g(Yes, No, false, false, "", "ω")}, - {0x1d6db, 0, 0, 0, g(Yes, No, false, false, "", "∂")}, - {0x1d6dc, 0, 0, 0, g(Yes, No, false, false, "", "ε")}, - {0x1d6dd, 0, 0, 0, g(Yes, No, false, false, "", "θ")}, - {0x1d6de, 0, 0, 0, g(Yes, No, false, false, "", "κ")}, - {0x1d6df, 0, 0, 0, g(Yes, No, false, false, "", "φ")}, - {0x1d6e0, 0, 0, 0, g(Yes, No, false, false, "", "ρ")}, - {0x1d6e1, 0, 0, 0, g(Yes, No, false, false, "", "π")}, - {0x1d6e2, 0, 0, 0, g(Yes, No, false, false, "", "Α")}, - {0x1d6e3, 0, 0, 0, g(Yes, No, false, false, "", "Β")}, - {0x1d6e4, 0, 0, 0, g(Yes, No, false, false, "", "Γ")}, - {0x1d6e5, 0, 0, 0, g(Yes, No, false, false, "", "Δ")}, - {0x1d6e6, 0, 0, 0, g(Yes, No, false, false, "", "Ε")}, - {0x1d6e7, 0, 0, 0, g(Yes, No, false, false, "", "Ζ")}, - {0x1d6e8, 0, 0, 0, g(Yes, No, false, false, "", "Η")}, - {0x1d6e9, 0, 0, 0, g(Yes, No, false, false, "", "Θ")}, - {0x1d6ea, 0, 0, 0, g(Yes, No, false, false, "", "Ι")}, - {0x1d6eb, 0, 0, 0, g(Yes, No, false, false, "", "Κ")}, - {0x1d6ec, 0, 0, 0, g(Yes, No, false, false, "", "Λ")}, - {0x1d6ed, 0, 0, 0, g(Yes, No, false, false, "", "Μ")}, - {0x1d6ee, 0, 0, 0, g(Yes, No, false, false, "", "Ν")}, - {0x1d6ef, 0, 0, 0, g(Yes, No, false, false, "", "Ξ")}, - {0x1d6f0, 0, 0, 0, g(Yes, No, false, false, "", "Ο")}, - {0x1d6f1, 0, 0, 0, g(Yes, No, false, false, "", "Π")}, - {0x1d6f2, 0, 0, 0, g(Yes, No, false, false, "", "Ρ")}, - {0x1d6f3, 0, 0, 0, g(Yes, No, false, false, "", "Θ")}, - {0x1d6f4, 0, 0, 0, g(Yes, No, false, false, "", "Σ")}, - {0x1d6f5, 0, 0, 0, g(Yes, No, false, false, "", "Τ")}, - {0x1d6f6, 0, 0, 0, g(Yes, No, false, false, "", "Υ")}, - {0x1d6f7, 0, 0, 0, g(Yes, No, false, false, "", "Φ")}, - {0x1d6f8, 0, 0, 0, g(Yes, No, false, false, "", "Χ")}, - {0x1d6f9, 0, 0, 0, g(Yes, No, false, false, "", "Ψ")}, - {0x1d6fa, 0, 0, 0, g(Yes, No, false, false, "", "Ω")}, - {0x1d6fb, 0, 0, 0, g(Yes, No, false, false, "", "∇")}, - {0x1d6fc, 0, 0, 0, g(Yes, No, false, false, "", "α")}, - {0x1d6fd, 0, 0, 0, g(Yes, No, false, false, "", "β")}, - {0x1d6fe, 0, 0, 0, g(Yes, No, false, false, "", "γ")}, - {0x1d6ff, 0, 0, 0, g(Yes, No, false, false, "", "δ")}, - {0x1d700, 0, 0, 0, g(Yes, No, false, false, "", "ε")}, - {0x1d701, 0, 0, 0, g(Yes, No, false, false, "", "ζ")}, - {0x1d702, 0, 0, 0, g(Yes, No, false, false, "", "η")}, - {0x1d703, 0, 0, 0, g(Yes, No, false, false, "", "θ")}, - {0x1d704, 0, 0, 0, g(Yes, No, false, false, "", "ι")}, - {0x1d705, 0, 0, 0, g(Yes, No, false, false, "", "κ")}, - {0x1d706, 0, 0, 0, g(Yes, No, false, false, "", "λ")}, - {0x1d707, 0, 0, 0, g(Yes, No, false, false, "", "μ")}, - {0x1d708, 0, 0, 0, g(Yes, No, false, false, "", "ν")}, - {0x1d709, 0, 0, 0, g(Yes, No, false, false, "", "ξ")}, - {0x1d70a, 0, 0, 0, g(Yes, No, false, false, "", "ο")}, - {0x1d70b, 0, 0, 0, g(Yes, No, false, false, "", "π")}, - {0x1d70c, 0, 0, 0, g(Yes, No, false, false, "", "ρ")}, - {0x1d70d, 0, 0, 0, g(Yes, No, false, false, "", "ς")}, - {0x1d70e, 0, 0, 0, g(Yes, No, false, false, "", "σ")}, - {0x1d70f, 0, 0, 0, g(Yes, No, false, false, "", "τ")}, - {0x1d710, 0, 0, 0, g(Yes, No, false, false, "", "υ")}, - {0x1d711, 0, 0, 0, g(Yes, No, false, false, "", "φ")}, - {0x1d712, 0, 0, 0, g(Yes, No, false, false, "", "χ")}, - {0x1d713, 0, 0, 0, g(Yes, No, false, false, "", "ψ")}, - {0x1d714, 0, 0, 0, g(Yes, No, false, false, "", "ω")}, - {0x1d715, 0, 0, 0, g(Yes, No, false, false, "", "∂")}, - {0x1d716, 0, 0, 0, g(Yes, No, false, false, "", "ε")}, - {0x1d717, 0, 0, 0, g(Yes, No, false, false, "", "θ")}, - {0x1d718, 0, 0, 0, g(Yes, No, false, false, "", "κ")}, - {0x1d719, 0, 0, 0, g(Yes, No, false, false, "", "φ")}, - {0x1d71a, 0, 0, 0, g(Yes, No, false, false, "", "ρ")}, - {0x1d71b, 0, 0, 0, g(Yes, No, false, false, "", "π")}, - {0x1d71c, 0, 0, 0, g(Yes, No, false, false, "", "Α")}, - {0x1d71d, 0, 0, 0, g(Yes, No, false, false, "", "Β")}, - {0x1d71e, 0, 0, 0, g(Yes, No, false, false, "", "Γ")}, - {0x1d71f, 0, 0, 0, g(Yes, No, false, false, "", "Δ")}, - {0x1d720, 0, 0, 0, g(Yes, No, false, false, "", "Ε")}, - {0x1d721, 0, 0, 0, g(Yes, No, false, false, "", "Ζ")}, - {0x1d722, 0, 0, 0, g(Yes, No, false, false, "", "Η")}, - {0x1d723, 0, 0, 0, g(Yes, No, false, false, "", "Θ")}, - {0x1d724, 0, 0, 0, g(Yes, No, false, false, "", "Ι")}, - {0x1d725, 0, 0, 0, g(Yes, No, false, false, "", "Κ")}, - {0x1d726, 0, 0, 0, g(Yes, No, false, false, "", "Λ")}, - {0x1d727, 0, 0, 0, g(Yes, No, false, false, "", "Μ")}, - {0x1d728, 0, 0, 0, g(Yes, No, false, false, "", "Ν")}, - {0x1d729, 0, 0, 0, g(Yes, No, false, false, "", "Ξ")}, - {0x1d72a, 0, 0, 0, g(Yes, No, false, false, "", "Ο")}, - {0x1d72b, 0, 0, 0, g(Yes, No, false, false, "", "Π")}, - {0x1d72c, 0, 0, 0, g(Yes, No, false, false, "", "Ρ")}, - {0x1d72d, 0, 0, 0, g(Yes, No, false, false, "", "Θ")}, - {0x1d72e, 0, 0, 0, g(Yes, No, false, false, "", "Σ")}, - {0x1d72f, 0, 0, 0, g(Yes, No, false, false, "", "Τ")}, - {0x1d730, 0, 0, 0, g(Yes, No, false, false, "", "Υ")}, - {0x1d731, 0, 0, 0, g(Yes, No, false, false, "", "Φ")}, - {0x1d732, 0, 0, 0, g(Yes, No, false, false, "", "Χ")}, - {0x1d733, 0, 0, 0, g(Yes, No, false, false, "", "Ψ")}, - {0x1d734, 0, 0, 0, g(Yes, No, false, false, "", "Ω")}, - {0x1d735, 0, 0, 0, g(Yes, No, false, false, "", "∇")}, - {0x1d736, 0, 0, 0, g(Yes, No, false, false, "", "α")}, - {0x1d737, 0, 0, 0, g(Yes, No, false, false, "", "β")}, - {0x1d738, 0, 0, 0, g(Yes, No, false, false, "", "γ")}, - {0x1d739, 0, 0, 0, g(Yes, No, false, false, "", "δ")}, - {0x1d73a, 0, 0, 0, g(Yes, No, false, false, "", "ε")}, - {0x1d73b, 0, 0, 0, g(Yes, No, false, false, "", "ζ")}, - {0x1d73c, 0, 0, 0, g(Yes, No, false, false, "", "η")}, - {0x1d73d, 0, 0, 0, g(Yes, No, false, false, "", "θ")}, - {0x1d73e, 0, 0, 0, g(Yes, No, false, false, "", "ι")}, - {0x1d73f, 0, 0, 0, g(Yes, No, false, false, "", "κ")}, - {0x1d740, 0, 0, 0, g(Yes, No, false, false, "", "λ")}, - {0x1d741, 0, 0, 0, g(Yes, No, false, false, "", "μ")}, - {0x1d742, 0, 0, 0, g(Yes, No, false, false, "", "ν")}, - {0x1d743, 0, 0, 0, g(Yes, No, false, false, "", "ξ")}, - {0x1d744, 0, 0, 0, g(Yes, No, false, false, "", "ο")}, - {0x1d745, 0, 0, 0, g(Yes, No, false, false, "", "π")}, - {0x1d746, 0, 0, 0, g(Yes, No, false, false, "", "ρ")}, - {0x1d747, 0, 0, 0, g(Yes, No, false, false, "", "ς")}, - {0x1d748, 0, 0, 0, g(Yes, No, false, false, "", "σ")}, - {0x1d749, 0, 0, 0, g(Yes, No, false, false, "", "τ")}, - {0x1d74a, 0, 0, 0, g(Yes, No, false, false, "", "υ")}, - {0x1d74b, 0, 0, 0, g(Yes, No, false, false, "", "φ")}, - {0x1d74c, 0, 0, 0, g(Yes, No, false, false, "", "χ")}, - {0x1d74d, 0, 0, 0, g(Yes, No, false, false, "", "ψ")}, - {0x1d74e, 0, 0, 0, g(Yes, No, false, false, "", "ω")}, - {0x1d74f, 0, 0, 0, g(Yes, No, false, false, "", "∂")}, - {0x1d750, 0, 0, 0, g(Yes, No, false, false, "", "ε")}, - {0x1d751, 0, 0, 0, g(Yes, No, false, false, "", "θ")}, - {0x1d752, 0, 0, 0, g(Yes, No, false, false, "", "κ")}, - {0x1d753, 0, 0, 0, g(Yes, No, false, false, "", "φ")}, - {0x1d754, 0, 0, 0, g(Yes, No, false, false, "", "ρ")}, - {0x1d755, 0, 0, 0, g(Yes, No, false, false, "", "π")}, - {0x1d756, 0, 0, 0, g(Yes, No, false, false, "", "Α")}, - {0x1d757, 0, 0, 0, g(Yes, No, false, false, "", "Β")}, - {0x1d758, 0, 0, 0, g(Yes, No, false, false, "", "Γ")}, - {0x1d759, 0, 0, 0, g(Yes, No, false, false, "", "Δ")}, - {0x1d75a, 0, 0, 0, g(Yes, No, false, false, "", "Ε")}, - {0x1d75b, 0, 0, 0, g(Yes, No, false, false, "", "Ζ")}, - {0x1d75c, 0, 0, 0, g(Yes, No, false, false, "", "Η")}, - {0x1d75d, 0, 0, 0, g(Yes, No, false, false, "", "Θ")}, - {0x1d75e, 0, 0, 0, g(Yes, No, false, false, "", "Ι")}, - {0x1d75f, 0, 0, 0, g(Yes, No, false, false, "", "Κ")}, - {0x1d760, 0, 0, 0, g(Yes, No, false, false, "", "Λ")}, - {0x1d761, 0, 0, 0, g(Yes, No, false, false, "", "Μ")}, - {0x1d762, 0, 0, 0, g(Yes, No, false, false, "", "Ν")}, - {0x1d763, 0, 0, 0, g(Yes, No, false, false, "", "Ξ")}, - {0x1d764, 0, 0, 0, g(Yes, No, false, false, "", "Ο")}, - {0x1d765, 0, 0, 0, g(Yes, No, false, false, "", "Π")}, - {0x1d766, 0, 0, 0, g(Yes, No, false, false, "", "Ρ")}, - {0x1d767, 0, 0, 0, g(Yes, No, false, false, "", "Θ")}, - {0x1d768, 0, 0, 0, g(Yes, No, false, false, "", "Σ")}, - {0x1d769, 0, 0, 0, g(Yes, No, false, false, "", "Τ")}, - {0x1d76a, 0, 0, 0, g(Yes, No, false, false, "", "Υ")}, - {0x1d76b, 0, 0, 0, g(Yes, No, false, false, "", "Φ")}, - {0x1d76c, 0, 0, 0, g(Yes, No, false, false, "", "Χ")}, - {0x1d76d, 0, 0, 0, g(Yes, No, false, false, "", "Ψ")}, - {0x1d76e, 0, 0, 0, g(Yes, No, false, false, "", "Ω")}, - {0x1d76f, 0, 0, 0, g(Yes, No, false, false, "", "∇")}, - {0x1d770, 0, 0, 0, g(Yes, No, false, false, "", "α")}, - {0x1d771, 0, 0, 0, g(Yes, No, false, false, "", "β")}, - {0x1d772, 0, 0, 0, g(Yes, No, false, false, "", "γ")}, - {0x1d773, 0, 0, 0, g(Yes, No, false, false, "", "δ")}, - {0x1d774, 0, 0, 0, g(Yes, No, false, false, "", "ε")}, - {0x1d775, 0, 0, 0, g(Yes, No, false, false, "", "ζ")}, - {0x1d776, 0, 0, 0, g(Yes, No, false, false, "", "η")}, - {0x1d777, 0, 0, 0, g(Yes, No, false, false, "", "θ")}, - {0x1d778, 0, 0, 0, g(Yes, No, false, false, "", "ι")}, - {0x1d779, 0, 0, 0, g(Yes, No, false, false, "", "κ")}, - {0x1d77a, 0, 0, 0, g(Yes, No, false, false, "", "λ")}, - {0x1d77b, 0, 0, 0, g(Yes, No, false, false, "", "μ")}, - {0x1d77c, 0, 0, 0, g(Yes, No, false, false, "", "ν")}, - {0x1d77d, 0, 0, 0, g(Yes, No, false, false, "", "ξ")}, - {0x1d77e, 0, 0, 0, g(Yes, No, false, false, "", "ο")}, - {0x1d77f, 0, 0, 0, g(Yes, No, false, false, "", "π")}, - {0x1d780, 0, 0, 0, g(Yes, No, false, false, "", "ρ")}, - {0x1d781, 0, 0, 0, g(Yes, No, false, false, "", "ς")}, - {0x1d782, 0, 0, 0, g(Yes, No, false, false, "", "σ")}, - {0x1d783, 0, 0, 0, g(Yes, No, false, false, "", "τ")}, - {0x1d784, 0, 0, 0, g(Yes, No, false, false, "", "υ")}, - {0x1d785, 0, 0, 0, g(Yes, No, false, false, "", "φ")}, - {0x1d786, 0, 0, 0, g(Yes, No, false, false, "", "χ")}, - {0x1d787, 0, 0, 0, g(Yes, No, false, false, "", "ψ")}, - {0x1d788, 0, 0, 0, g(Yes, No, false, false, "", "ω")}, - {0x1d789, 0, 0, 0, g(Yes, No, false, false, "", "∂")}, - {0x1d78a, 0, 0, 0, g(Yes, No, false, false, "", "ε")}, - {0x1d78b, 0, 0, 0, g(Yes, No, false, false, "", "θ")}, - {0x1d78c, 0, 0, 0, g(Yes, No, false, false, "", "κ")}, - {0x1d78d, 0, 0, 0, g(Yes, No, false, false, "", "φ")}, - {0x1d78e, 0, 0, 0, g(Yes, No, false, false, "", "ρ")}, - {0x1d78f, 0, 0, 0, g(Yes, No, false, false, "", "π")}, - {0x1d790, 0, 0, 0, g(Yes, No, false, false, "", "Α")}, - {0x1d791, 0, 0, 0, g(Yes, No, false, false, "", "Β")}, - {0x1d792, 0, 0, 0, g(Yes, No, false, false, "", "Γ")}, - {0x1d793, 0, 0, 0, g(Yes, No, false, false, "", "Δ")}, - {0x1d794, 0, 0, 0, g(Yes, No, false, false, "", "Ε")}, - {0x1d795, 0, 0, 0, g(Yes, No, false, false, "", "Ζ")}, - {0x1d796, 0, 0, 0, g(Yes, No, false, false, "", "Η")}, - {0x1d797, 0, 0, 0, g(Yes, No, false, false, "", "Θ")}, - {0x1d798, 0, 0, 0, g(Yes, No, false, false, "", "Ι")}, - {0x1d799, 0, 0, 0, g(Yes, No, false, false, "", "Κ")}, - {0x1d79a, 0, 0, 0, g(Yes, No, false, false, "", "Λ")}, - {0x1d79b, 0, 0, 0, g(Yes, No, false, false, "", "Μ")}, - {0x1d79c, 0, 0, 0, g(Yes, No, false, false, "", "Ν")}, - {0x1d79d, 0, 0, 0, g(Yes, No, false, false, "", "Ξ")}, - {0x1d79e, 0, 0, 0, g(Yes, No, false, false, "", "Ο")}, - {0x1d79f, 0, 0, 0, g(Yes, No, false, false, "", "Π")}, - {0x1d7a0, 0, 0, 0, g(Yes, No, false, false, "", "Ρ")}, - {0x1d7a1, 0, 0, 0, g(Yes, No, false, false, "", "Θ")}, - {0x1d7a2, 0, 0, 0, g(Yes, No, false, false, "", "Σ")}, - {0x1d7a3, 0, 0, 0, g(Yes, No, false, false, "", "Τ")}, - {0x1d7a4, 0, 0, 0, g(Yes, No, false, false, "", "Υ")}, - {0x1d7a5, 0, 0, 0, g(Yes, No, false, false, "", "Φ")}, - {0x1d7a6, 0, 0, 0, g(Yes, No, false, false, "", "Χ")}, - {0x1d7a7, 0, 0, 0, g(Yes, No, false, false, "", "Ψ")}, - {0x1d7a8, 0, 0, 0, g(Yes, No, false, false, "", "Ω")}, - {0x1d7a9, 0, 0, 0, g(Yes, No, false, false, "", "∇")}, - {0x1d7aa, 0, 0, 0, g(Yes, No, false, false, "", "α")}, - {0x1d7ab, 0, 0, 0, g(Yes, No, false, false, "", "β")}, - {0x1d7ac, 0, 0, 0, g(Yes, No, false, false, "", "γ")}, - {0x1d7ad, 0, 0, 0, g(Yes, No, false, false, "", "δ")}, - {0x1d7ae, 0, 0, 0, g(Yes, No, false, false, "", "ε")}, - {0x1d7af, 0, 0, 0, g(Yes, No, false, false, "", "ζ")}, - {0x1d7b0, 0, 0, 0, g(Yes, No, false, false, "", "η")}, - {0x1d7b1, 0, 0, 0, g(Yes, No, false, false, "", "θ")}, - {0x1d7b2, 0, 0, 0, g(Yes, No, false, false, "", "ι")}, - {0x1d7b3, 0, 0, 0, g(Yes, No, false, false, "", "κ")}, - {0x1d7b4, 0, 0, 0, g(Yes, No, false, false, "", "λ")}, - {0x1d7b5, 0, 0, 0, g(Yes, No, false, false, "", "μ")}, - {0x1d7b6, 0, 0, 0, g(Yes, No, false, false, "", "ν")}, - {0x1d7b7, 0, 0, 0, g(Yes, No, false, false, "", "ξ")}, - {0x1d7b8, 0, 0, 0, g(Yes, No, false, false, "", "ο")}, - {0x1d7b9, 0, 0, 0, g(Yes, No, false, false, "", "π")}, - {0x1d7ba, 0, 0, 0, g(Yes, No, false, false, "", "ρ")}, - {0x1d7bb, 0, 0, 0, g(Yes, No, false, false, "", "ς")}, - {0x1d7bc, 0, 0, 0, g(Yes, No, false, false, "", "σ")}, - {0x1d7bd, 0, 0, 0, g(Yes, No, false, false, "", "τ")}, - {0x1d7be, 0, 0, 0, g(Yes, No, false, false, "", "υ")}, - {0x1d7bf, 0, 0, 0, g(Yes, No, false, false, "", "φ")}, - {0x1d7c0, 0, 0, 0, g(Yes, No, false, false, "", "χ")}, - {0x1d7c1, 0, 0, 0, g(Yes, No, false, false, "", "ψ")}, - {0x1d7c2, 0, 0, 0, g(Yes, No, false, false, "", "ω")}, - {0x1d7c3, 0, 0, 0, g(Yes, No, false, false, "", "∂")}, - {0x1d7c4, 0, 0, 0, g(Yes, No, false, false, "", "ε")}, - {0x1d7c5, 0, 0, 0, g(Yes, No, false, false, "", "θ")}, - {0x1d7c6, 0, 0, 0, g(Yes, No, false, false, "", "κ")}, - {0x1d7c7, 0, 0, 0, g(Yes, No, false, false, "", "φ")}, - {0x1d7c8, 0, 0, 0, g(Yes, No, false, false, "", "ρ")}, - {0x1d7c9, 0, 0, 0, g(Yes, No, false, false, "", "π")}, - {0x1d7ca, 0, 0, 0, g(Yes, No, false, false, "", "Ϝ")}, - {0x1d7cb, 0, 0, 0, g(Yes, No, false, false, "", "ϝ")}, - {0x1d7cc, 0, 0, 0, f(Yes, false, "")}, - {0x1d7ce, 0, 0, 0, g(Yes, No, false, false, "", "0")}, - {0x1d7cf, 0, 0, 0, g(Yes, No, false, false, "", "1")}, - {0x1d7d0, 0, 0, 0, g(Yes, No, false, false, "", "2")}, - {0x1d7d1, 0, 0, 0, g(Yes, No, false, false, "", "3")}, - {0x1d7d2, 0, 0, 0, g(Yes, No, false, false, "", "4")}, - {0x1d7d3, 0, 0, 0, g(Yes, No, false, false, "", "5")}, - {0x1d7d4, 0, 0, 0, g(Yes, No, false, false, "", "6")}, - {0x1d7d5, 0, 0, 0, g(Yes, No, false, false, "", "7")}, - {0x1d7d6, 0, 0, 0, g(Yes, No, false, false, "", "8")}, - {0x1d7d7, 0, 0, 0, g(Yes, No, false, false, "", "9")}, - {0x1d7d8, 0, 0, 0, g(Yes, No, false, false, "", "0")}, - {0x1d7d9, 0, 0, 0, g(Yes, No, false, false, "", "1")}, - {0x1d7da, 0, 0, 0, g(Yes, No, false, false, "", "2")}, - {0x1d7db, 0, 0, 0, g(Yes, No, false, false, "", "3")}, - {0x1d7dc, 0, 0, 0, g(Yes, No, false, false, "", "4")}, - {0x1d7dd, 0, 0, 0, g(Yes, No, false, false, "", "5")}, - {0x1d7de, 0, 0, 0, g(Yes, No, false, false, "", "6")}, - {0x1d7df, 0, 0, 0, g(Yes, No, false, false, "", "7")}, - {0x1d7e0, 0, 0, 0, g(Yes, No, false, false, "", "8")}, - {0x1d7e1, 0, 0, 0, g(Yes, No, false, false, "", "9")}, - {0x1d7e2, 0, 0, 0, g(Yes, No, false, false, "", "0")}, - {0x1d7e3, 0, 0, 0, g(Yes, No, false, false, "", "1")}, - {0x1d7e4, 0, 0, 0, g(Yes, No, false, false, "", "2")}, - {0x1d7e5, 0, 0, 0, g(Yes, No, false, false, "", "3")}, - {0x1d7e6, 0, 0, 0, g(Yes, No, false, false, "", "4")}, - {0x1d7e7, 0, 0, 0, g(Yes, No, false, false, "", "5")}, - {0x1d7e8, 0, 0, 0, g(Yes, No, false, false, "", "6")}, - {0x1d7e9, 0, 0, 0, g(Yes, No, false, false, "", "7")}, - {0x1d7ea, 0, 0, 0, g(Yes, No, false, false, "", "8")}, - {0x1d7eb, 0, 0, 0, g(Yes, No, false, false, "", "9")}, - {0x1d7ec, 0, 0, 0, g(Yes, No, false, false, "", "0")}, - {0x1d7ed, 0, 0, 0, g(Yes, No, false, false, "", "1")}, - {0x1d7ee, 0, 0, 0, g(Yes, No, false, false, "", "2")}, - {0x1d7ef, 0, 0, 0, g(Yes, No, false, false, "", "3")}, - {0x1d7f0, 0, 0, 0, g(Yes, No, false, false, "", "4")}, - {0x1d7f1, 0, 0, 0, g(Yes, No, false, false, "", "5")}, - {0x1d7f2, 0, 0, 0, g(Yes, No, false, false, "", "6")}, - {0x1d7f3, 0, 0, 0, g(Yes, No, false, false, "", "7")}, - {0x1d7f4, 0, 0, 0, g(Yes, No, false, false, "", "8")}, - {0x1d7f5, 0, 0, 0, g(Yes, No, false, false, "", "9")}, - {0x1d7f6, 0, 0, 0, g(Yes, No, false, false, "", "0")}, - {0x1d7f7, 0, 0, 0, g(Yes, No, false, false, "", "1")}, - {0x1d7f8, 0, 0, 0, g(Yes, No, false, false, "", "2")}, - {0x1d7f9, 0, 0, 0, g(Yes, No, false, false, "", "3")}, - {0x1d7fa, 0, 0, 0, g(Yes, No, false, false, "", "4")}, - {0x1d7fb, 0, 0, 0, g(Yes, No, false, false, "", "5")}, - {0x1d7fc, 0, 0, 0, g(Yes, No, false, false, "", "6")}, - {0x1d7fd, 0, 0, 0, g(Yes, No, false, false, "", "7")}, - {0x1d7fe, 0, 0, 0, g(Yes, No, false, false, "", "8")}, - {0x1d7ff, 0, 0, 0, g(Yes, No, false, false, "", "9")}, - {0x1d800, 0, 0, 0, f(Yes, false, "")}, - {0x1e000, 230, 1, 1, f(Yes, false, "")}, - {0x1e007, 0, 0, 0, f(Yes, false, "")}, - {0x1e008, 230, 1, 1, f(Yes, false, "")}, - {0x1e019, 0, 0, 0, f(Yes, false, "")}, - {0x1e01b, 230, 1, 1, f(Yes, false, "")}, - {0x1e022, 0, 0, 0, f(Yes, false, "")}, - {0x1e023, 230, 1, 1, f(Yes, false, "")}, - {0x1e025, 0, 0, 0, f(Yes, false, "")}, - {0x1e026, 230, 1, 1, f(Yes, false, "")}, - {0x1e02b, 0, 0, 0, f(Yes, false, "")}, - {0x1e8d0, 220, 1, 1, f(Yes, false, "")}, - {0x1e8d7, 0, 0, 0, f(Yes, false, "")}, - {0x1e944, 230, 1, 1, f(Yes, false, "")}, - {0x1e94a, 7, 1, 1, f(Yes, false, "")}, - {0x1e94b, 0, 0, 0, f(Yes, false, "")}, - {0x1ee00, 0, 0, 0, g(Yes, No, false, false, "", "ا")}, - {0x1ee01, 0, 0, 0, g(Yes, No, false, false, "", "ب")}, - {0x1ee02, 0, 0, 0, g(Yes, No, false, false, "", "ج")}, - {0x1ee03, 0, 0, 0, g(Yes, No, false, false, "", "د")}, - {0x1ee04, 0, 0, 0, f(Yes, false, "")}, - {0x1ee05, 0, 0, 0, g(Yes, No, false, false, "", "و")}, - {0x1ee06, 0, 0, 0, g(Yes, No, false, false, "", "ز")}, - {0x1ee07, 0, 0, 0, g(Yes, No, false, false, "", "ح")}, - {0x1ee08, 0, 0, 0, g(Yes, No, false, false, "", "ط")}, - {0x1ee09, 0, 0, 0, g(Yes, No, false, false, "", "ي")}, - {0x1ee0a, 0, 0, 0, g(Yes, No, false, false, "", "ك")}, - {0x1ee0b, 0, 0, 0, g(Yes, No, false, false, "", "ل")}, - {0x1ee0c, 0, 0, 0, g(Yes, No, false, false, "", "م")}, - {0x1ee0d, 0, 0, 0, g(Yes, No, false, false, "", "ن")}, - {0x1ee0e, 0, 0, 0, g(Yes, No, false, false, "", "س")}, - {0x1ee0f, 0, 0, 0, g(Yes, No, false, false, "", "ع")}, - {0x1ee10, 0, 0, 0, g(Yes, No, false, false, "", "ف")}, - {0x1ee11, 0, 0, 0, g(Yes, No, false, false, "", "ص")}, - {0x1ee12, 0, 0, 0, g(Yes, No, false, false, "", "ق")}, - {0x1ee13, 0, 0, 0, g(Yes, No, false, false, "", "ر")}, - {0x1ee14, 0, 0, 0, g(Yes, No, false, false, "", "ش")}, - {0x1ee15, 0, 0, 0, g(Yes, No, false, false, "", "ت")}, - {0x1ee16, 0, 0, 0, g(Yes, No, false, false, "", "ث")}, - {0x1ee17, 0, 0, 0, g(Yes, No, false, false, "", "خ")}, - {0x1ee18, 0, 0, 0, g(Yes, No, false, false, "", "ذ")}, - {0x1ee19, 0, 0, 0, g(Yes, No, false, false, "", "ض")}, - {0x1ee1a, 0, 0, 0, g(Yes, No, false, false, "", "ظ")}, - {0x1ee1b, 0, 0, 0, g(Yes, No, false, false, "", "غ")}, - {0x1ee1c, 0, 0, 0, g(Yes, No, false, false, "", "ٮ")}, - {0x1ee1d, 0, 0, 0, g(Yes, No, false, false, "", "ں")}, - {0x1ee1e, 0, 0, 0, g(Yes, No, false, false, "", "ڡ")}, - {0x1ee1f, 0, 0, 0, g(Yes, No, false, false, "", "ٯ")}, - {0x1ee20, 0, 0, 0, f(Yes, false, "")}, - {0x1ee21, 0, 0, 0, g(Yes, No, false, false, "", "ب")}, - {0x1ee22, 0, 0, 0, g(Yes, No, false, false, "", "ج")}, - {0x1ee23, 0, 0, 0, f(Yes, false, "")}, - {0x1ee24, 0, 0, 0, g(Yes, No, false, false, "", "ه")}, - {0x1ee25, 0, 0, 0, f(Yes, false, "")}, - {0x1ee27, 0, 0, 0, g(Yes, No, false, false, "", "ح")}, - {0x1ee28, 0, 0, 0, f(Yes, false, "")}, - {0x1ee29, 0, 0, 0, g(Yes, No, false, false, "", "ي")}, - {0x1ee2a, 0, 0, 0, g(Yes, No, false, false, "", "ك")}, - {0x1ee2b, 0, 0, 0, g(Yes, No, false, false, "", "ل")}, - {0x1ee2c, 0, 0, 0, g(Yes, No, false, false, "", "م")}, - {0x1ee2d, 0, 0, 0, g(Yes, No, false, false, "", "ن")}, - {0x1ee2e, 0, 0, 0, g(Yes, No, false, false, "", "س")}, - {0x1ee2f, 0, 0, 0, g(Yes, No, false, false, "", "ع")}, - {0x1ee30, 0, 0, 0, g(Yes, No, false, false, "", "ف")}, - {0x1ee31, 0, 0, 0, g(Yes, No, false, false, "", "ص")}, - {0x1ee32, 0, 0, 0, g(Yes, No, false, false, "", "ق")}, - {0x1ee33, 0, 0, 0, f(Yes, false, "")}, - {0x1ee34, 0, 0, 0, g(Yes, No, false, false, "", "ش")}, - {0x1ee35, 0, 0, 0, g(Yes, No, false, false, "", "ت")}, - {0x1ee36, 0, 0, 0, g(Yes, No, false, false, "", "ث")}, - {0x1ee37, 0, 0, 0, g(Yes, No, false, false, "", "خ")}, - {0x1ee38, 0, 0, 0, f(Yes, false, "")}, - {0x1ee39, 0, 0, 0, g(Yes, No, false, false, "", "ض")}, - {0x1ee3a, 0, 0, 0, f(Yes, false, "")}, - {0x1ee3b, 0, 0, 0, g(Yes, No, false, false, "", "غ")}, - {0x1ee3c, 0, 0, 0, f(Yes, false, "")}, - {0x1ee42, 0, 0, 0, g(Yes, No, false, false, "", "ج")}, - {0x1ee43, 0, 0, 0, f(Yes, false, "")}, - {0x1ee47, 0, 0, 0, g(Yes, No, false, false, "", "ح")}, - {0x1ee48, 0, 0, 0, f(Yes, false, "")}, - {0x1ee49, 0, 0, 0, g(Yes, No, false, false, "", "ي")}, - {0x1ee4a, 0, 0, 0, f(Yes, false, "")}, - {0x1ee4b, 0, 0, 0, g(Yes, No, false, false, "", "ل")}, - {0x1ee4c, 0, 0, 0, f(Yes, false, "")}, - {0x1ee4d, 0, 0, 0, g(Yes, No, false, false, "", "ن")}, - {0x1ee4e, 0, 0, 0, g(Yes, No, false, false, "", "س")}, - {0x1ee4f, 0, 0, 0, g(Yes, No, false, false, "", "ع")}, - {0x1ee50, 0, 0, 0, f(Yes, false, "")}, - {0x1ee51, 0, 0, 0, g(Yes, No, false, false, "", "ص")}, - {0x1ee52, 0, 0, 0, g(Yes, No, false, false, "", "ق")}, - {0x1ee53, 0, 0, 0, f(Yes, false, "")}, - {0x1ee54, 0, 0, 0, g(Yes, No, false, false, "", "ش")}, - {0x1ee55, 0, 0, 0, f(Yes, false, "")}, - {0x1ee57, 0, 0, 0, g(Yes, No, false, false, "", "خ")}, - {0x1ee58, 0, 0, 0, f(Yes, false, "")}, - {0x1ee59, 0, 0, 0, g(Yes, No, false, false, "", "ض")}, - {0x1ee5a, 0, 0, 0, f(Yes, false, "")}, - {0x1ee5b, 0, 0, 0, g(Yes, No, false, false, "", "غ")}, - {0x1ee5c, 0, 0, 0, f(Yes, false, "")}, - {0x1ee5d, 0, 0, 0, g(Yes, No, false, false, "", "ں")}, - {0x1ee5e, 0, 0, 0, f(Yes, false, "")}, - {0x1ee5f, 0, 0, 0, g(Yes, No, false, false, "", "ٯ")}, - {0x1ee60, 0, 0, 0, f(Yes, false, "")}, - {0x1ee61, 0, 0, 0, g(Yes, No, false, false, "", "ب")}, - {0x1ee62, 0, 0, 0, g(Yes, No, false, false, "", "ج")}, - {0x1ee63, 0, 0, 0, f(Yes, false, "")}, - {0x1ee64, 0, 0, 0, g(Yes, No, false, false, "", "ه")}, - {0x1ee65, 0, 0, 0, f(Yes, false, "")}, - {0x1ee67, 0, 0, 0, g(Yes, No, false, false, "", "ح")}, - {0x1ee68, 0, 0, 0, g(Yes, No, false, false, "", "ط")}, - {0x1ee69, 0, 0, 0, g(Yes, No, false, false, "", "ي")}, - {0x1ee6a, 0, 0, 0, g(Yes, No, false, false, "", "ك")}, - {0x1ee6b, 0, 0, 0, f(Yes, false, "")}, - {0x1ee6c, 0, 0, 0, g(Yes, No, false, false, "", "م")}, - {0x1ee6d, 0, 0, 0, g(Yes, No, false, false, "", "ن")}, - {0x1ee6e, 0, 0, 0, g(Yes, No, false, false, "", "س")}, - {0x1ee6f, 0, 0, 0, g(Yes, No, false, false, "", "ع")}, - {0x1ee70, 0, 0, 0, g(Yes, No, false, false, "", "ف")}, - {0x1ee71, 0, 0, 0, g(Yes, No, false, false, "", "ص")}, - {0x1ee72, 0, 0, 0, g(Yes, No, false, false, "", "ق")}, - {0x1ee73, 0, 0, 0, f(Yes, false, "")}, - {0x1ee74, 0, 0, 0, g(Yes, No, false, false, "", "ش")}, - {0x1ee75, 0, 0, 0, g(Yes, No, false, false, "", "ت")}, - {0x1ee76, 0, 0, 0, g(Yes, No, false, false, "", "ث")}, - {0x1ee77, 0, 0, 0, g(Yes, No, false, false, "", "خ")}, - {0x1ee78, 0, 0, 0, f(Yes, false, "")}, - {0x1ee79, 0, 0, 0, g(Yes, No, false, false, "", "ض")}, - {0x1ee7a, 0, 0, 0, g(Yes, No, false, false, "", "ظ")}, - {0x1ee7b, 0, 0, 0, g(Yes, No, false, false, "", "غ")}, - {0x1ee7c, 0, 0, 0, g(Yes, No, false, false, "", "ٮ")}, - {0x1ee7d, 0, 0, 0, f(Yes, false, "")}, - {0x1ee7e, 0, 0, 0, g(Yes, No, false, false, "", "ڡ")}, - {0x1ee7f, 0, 0, 0, f(Yes, false, "")}, - {0x1ee80, 0, 0, 0, g(Yes, No, false, false, "", "ا")}, - {0x1ee81, 0, 0, 0, g(Yes, No, false, false, "", "ب")}, - {0x1ee82, 0, 0, 0, g(Yes, No, false, false, "", "ج")}, - {0x1ee83, 0, 0, 0, g(Yes, No, false, false, "", "د")}, - {0x1ee84, 0, 0, 0, g(Yes, No, false, false, "", "ه")}, - {0x1ee85, 0, 0, 0, g(Yes, No, false, false, "", "و")}, - {0x1ee86, 0, 0, 0, g(Yes, No, false, false, "", "ز")}, - {0x1ee87, 0, 0, 0, g(Yes, No, false, false, "", "ح")}, - {0x1ee88, 0, 0, 0, g(Yes, No, false, false, "", "ط")}, - {0x1ee89, 0, 0, 0, g(Yes, No, false, false, "", "ي")}, - {0x1ee8a, 0, 0, 0, f(Yes, false, "")}, - {0x1ee8b, 0, 0, 0, g(Yes, No, false, false, "", "ل")}, - {0x1ee8c, 0, 0, 0, g(Yes, No, false, false, "", "م")}, - {0x1ee8d, 0, 0, 0, g(Yes, No, false, false, "", "ن")}, - {0x1ee8e, 0, 0, 0, g(Yes, No, false, false, "", "س")}, - {0x1ee8f, 0, 0, 0, g(Yes, No, false, false, "", "ع")}, - {0x1ee90, 0, 0, 0, g(Yes, No, false, false, "", "ف")}, - {0x1ee91, 0, 0, 0, g(Yes, No, false, false, "", "ص")}, - {0x1ee92, 0, 0, 0, g(Yes, No, false, false, "", "ق")}, - {0x1ee93, 0, 0, 0, g(Yes, No, false, false, "", "ر")}, - {0x1ee94, 0, 0, 0, g(Yes, No, false, false, "", "ش")}, - {0x1ee95, 0, 0, 0, g(Yes, No, false, false, "", "ت")}, - {0x1ee96, 0, 0, 0, g(Yes, No, false, false, "", "ث")}, - {0x1ee97, 0, 0, 0, g(Yes, No, false, false, "", "خ")}, - {0x1ee98, 0, 0, 0, g(Yes, No, false, false, "", "ذ")}, - {0x1ee99, 0, 0, 0, g(Yes, No, false, false, "", "ض")}, - {0x1ee9a, 0, 0, 0, g(Yes, No, false, false, "", "ظ")}, - {0x1ee9b, 0, 0, 0, g(Yes, No, false, false, "", "غ")}, - {0x1ee9c, 0, 0, 0, f(Yes, false, "")}, - {0x1eea1, 0, 0, 0, g(Yes, No, false, false, "", "ب")}, - {0x1eea2, 0, 0, 0, g(Yes, No, false, false, "", "ج")}, - {0x1eea3, 0, 0, 0, g(Yes, No, false, false, "", "د")}, - {0x1eea4, 0, 0, 0, f(Yes, false, "")}, - {0x1eea5, 0, 0, 0, g(Yes, No, false, false, "", "و")}, - {0x1eea6, 0, 0, 0, g(Yes, No, false, false, "", "ز")}, - {0x1eea7, 0, 0, 0, g(Yes, No, false, false, "", "ح")}, - {0x1eea8, 0, 0, 0, g(Yes, No, false, false, "", "ط")}, - {0x1eea9, 0, 0, 0, g(Yes, No, false, false, "", "ي")}, - {0x1eeaa, 0, 0, 0, f(Yes, false, "")}, - {0x1eeab, 0, 0, 0, g(Yes, No, false, false, "", "ل")}, - {0x1eeac, 0, 0, 0, g(Yes, No, false, false, "", "م")}, - {0x1eead, 0, 0, 0, g(Yes, No, false, false, "", "ن")}, - {0x1eeae, 0, 0, 0, g(Yes, No, false, false, "", "س")}, - {0x1eeaf, 0, 0, 0, g(Yes, No, false, false, "", "ع")}, - {0x1eeb0, 0, 0, 0, g(Yes, No, false, false, "", "ف")}, - {0x1eeb1, 0, 0, 0, g(Yes, No, false, false, "", "ص")}, - {0x1eeb2, 0, 0, 0, g(Yes, No, false, false, "", "ق")}, - {0x1eeb3, 0, 0, 0, g(Yes, No, false, false, "", "ر")}, - {0x1eeb4, 0, 0, 0, g(Yes, No, false, false, "", "ش")}, - {0x1eeb5, 0, 0, 0, g(Yes, No, false, false, "", "ت")}, - {0x1eeb6, 0, 0, 0, g(Yes, No, false, false, "", "ث")}, - {0x1eeb7, 0, 0, 0, g(Yes, No, false, false, "", "خ")}, - {0x1eeb8, 0, 0, 0, g(Yes, No, false, false, "", "ذ")}, - {0x1eeb9, 0, 0, 0, g(Yes, No, false, false, "", "ض")}, - {0x1eeba, 0, 0, 0, g(Yes, No, false, false, "", "ظ")}, - {0x1eebb, 0, 0, 0, g(Yes, No, false, false, "", "غ")}, - {0x1eebc, 0, 0, 0, f(Yes, false, "")}, - {0x1f100, 0, 0, 0, g(Yes, No, false, false, "", "0.")}, - {0x1f101, 0, 0, 0, g(Yes, No, false, false, "", "0,")}, - {0x1f102, 0, 0, 0, g(Yes, No, false, false, "", "1,")}, - {0x1f103, 0, 0, 0, g(Yes, No, false, false, "", "2,")}, - {0x1f104, 0, 0, 0, g(Yes, No, false, false, "", "3,")}, - {0x1f105, 0, 0, 0, g(Yes, No, false, false, "", "4,")}, - {0x1f106, 0, 0, 0, g(Yes, No, false, false, "", "5,")}, - {0x1f107, 0, 0, 0, g(Yes, No, false, false, "", "6,")}, - {0x1f108, 0, 0, 0, g(Yes, No, false, false, "", "7,")}, - {0x1f109, 0, 0, 0, g(Yes, No, false, false, "", "8,")}, - {0x1f10a, 0, 0, 0, g(Yes, No, false, false, "", "9,")}, - {0x1f10b, 0, 0, 0, f(Yes, false, "")}, - {0x1f110, 0, 0, 0, g(Yes, No, false, false, "", "(A)")}, - {0x1f111, 0, 0, 0, g(Yes, No, false, false, "", "(B)")}, - {0x1f112, 0, 0, 0, g(Yes, No, false, false, "", "(C)")}, - {0x1f113, 0, 0, 0, g(Yes, No, false, false, "", "(D)")}, - {0x1f114, 0, 0, 0, g(Yes, No, false, false, "", "(E)")}, - {0x1f115, 0, 0, 0, g(Yes, No, false, false, "", "(F)")}, - {0x1f116, 0, 0, 0, g(Yes, No, false, false, "", "(G)")}, - {0x1f117, 0, 0, 0, g(Yes, No, false, false, "", "(H)")}, - {0x1f118, 0, 0, 0, g(Yes, No, false, false, "", "(I)")}, - {0x1f119, 0, 0, 0, g(Yes, No, false, false, "", "(J)")}, - {0x1f11a, 0, 0, 0, g(Yes, No, false, false, "", "(K)")}, - {0x1f11b, 0, 0, 0, g(Yes, No, false, false, "", "(L)")}, - {0x1f11c, 0, 0, 0, g(Yes, No, false, false, "", "(M)")}, - {0x1f11d, 0, 0, 0, g(Yes, No, false, false, "", "(N)")}, - {0x1f11e, 0, 0, 0, g(Yes, No, false, false, "", "(O)")}, - {0x1f11f, 0, 0, 0, g(Yes, No, false, false, "", "(P)")}, - {0x1f120, 0, 0, 0, g(Yes, No, false, false, "", "(Q)")}, - {0x1f121, 0, 0, 0, g(Yes, No, false, false, "", "(R)")}, - {0x1f122, 0, 0, 0, g(Yes, No, false, false, "", "(S)")}, - {0x1f123, 0, 0, 0, g(Yes, No, false, false, "", "(T)")}, - {0x1f124, 0, 0, 0, g(Yes, No, false, false, "", "(U)")}, - {0x1f125, 0, 0, 0, g(Yes, No, false, false, "", "(V)")}, - {0x1f126, 0, 0, 0, g(Yes, No, false, false, "", "(W)")}, - {0x1f127, 0, 0, 0, g(Yes, No, false, false, "", "(X)")}, - {0x1f128, 0, 0, 0, g(Yes, No, false, false, "", "(Y)")}, - {0x1f129, 0, 0, 0, g(Yes, No, false, false, "", "(Z)")}, - {0x1f12a, 0, 0, 0, g(Yes, No, false, false, "", "〔S〕")}, - {0x1f12b, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x1f12c, 0, 0, 0, g(Yes, No, false, false, "", "R")}, - {0x1f12d, 0, 0, 0, g(Yes, No, false, false, "", "CD")}, - {0x1f12e, 0, 0, 0, g(Yes, No, false, false, "", "WZ")}, - {0x1f12f, 0, 0, 0, f(Yes, false, "")}, - {0x1f130, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0x1f131, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0x1f132, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x1f133, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x1f134, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0x1f135, 0, 0, 0, g(Yes, No, false, false, "", "F")}, - {0x1f136, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0x1f137, 0, 0, 0, g(Yes, No, false, false, "", "H")}, - {0x1f138, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0x1f139, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0x1f13a, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0x1f13b, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x1f13c, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x1f13d, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0x1f13e, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0x1f13f, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0x1f140, 0, 0, 0, g(Yes, No, false, false, "", "Q")}, - {0x1f141, 0, 0, 0, g(Yes, No, false, false, "", "R")}, - {0x1f142, 0, 0, 0, g(Yes, No, false, false, "", "S")}, - {0x1f143, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0x1f144, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0x1f145, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x1f146, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0x1f147, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0x1f148, 0, 0, 0, g(Yes, No, false, false, "", "Y")}, - {0x1f149, 0, 0, 0, g(Yes, No, false, false, "", "Z")}, - {0x1f14a, 0, 0, 0, g(Yes, No, false, false, "", "HV")}, - {0x1f14b, 0, 0, 0, g(Yes, No, false, false, "", "MV")}, - {0x1f14c, 0, 0, 0, g(Yes, No, false, false, "", "SD")}, - {0x1f14d, 0, 0, 0, g(Yes, No, false, false, "", "SS")}, - {0x1f14e, 0, 0, 0, g(Yes, No, false, false, "", "PPV")}, - {0x1f14f, 0, 0, 0, g(Yes, No, false, false, "", "WC")}, - {0x1f150, 0, 0, 0, f(Yes, false, "")}, - {0x1f16a, 0, 0, 0, g(Yes, No, false, false, "", "MC")}, - {0x1f16b, 0, 0, 0, g(Yes, No, false, false, "", "MD")}, - {0x1f16c, 0, 0, 0, f(Yes, false, "")}, - {0x1f190, 0, 0, 0, g(Yes, No, false, false, "", "DJ")}, - {0x1f191, 0, 0, 0, f(Yes, false, "")}, - {0x1f200, 0, 0, 0, g(Yes, No, false, false, "", "ほか")}, - {0x1f201, 0, 0, 0, g(Yes, No, false, false, "", "ココ")}, - {0x1f202, 0, 0, 0, g(Yes, No, false, false, "", "サ")}, - {0x1f203, 0, 0, 0, f(Yes, false, "")}, - {0x1f210, 0, 0, 0, g(Yes, No, false, false, "", "手")}, - {0x1f211, 0, 0, 0, g(Yes, No, false, false, "", "字")}, - {0x1f212, 0, 0, 0, g(Yes, No, false, false, "", "双")}, - {0x1f213, 0, 0, 1, g(Yes, No, false, false, "", "デ")}, - {0x1f214, 0, 0, 0, g(Yes, No, false, false, "", "二")}, - {0x1f215, 0, 0, 0, g(Yes, No, false, false, "", "多")}, - {0x1f216, 0, 0, 0, g(Yes, No, false, false, "", "解")}, - {0x1f217, 0, 0, 0, g(Yes, No, false, false, "", "天")}, - {0x1f218, 0, 0, 0, g(Yes, No, false, false, "", "交")}, - {0x1f219, 0, 0, 0, g(Yes, No, false, false, "", "映")}, - {0x1f21a, 0, 0, 0, g(Yes, No, false, false, "", "無")}, - {0x1f21b, 0, 0, 0, g(Yes, No, false, false, "", "料")}, - {0x1f21c, 0, 0, 0, g(Yes, No, false, false, "", "前")}, - {0x1f21d, 0, 0, 0, g(Yes, No, false, false, "", "後")}, - {0x1f21e, 0, 0, 0, g(Yes, No, false, false, "", "再")}, - {0x1f21f, 0, 0, 0, g(Yes, No, false, false, "", "新")}, - {0x1f220, 0, 0, 0, g(Yes, No, false, false, "", "初")}, - {0x1f221, 0, 0, 0, g(Yes, No, false, false, "", "終")}, - {0x1f222, 0, 0, 0, g(Yes, No, false, false, "", "生")}, - {0x1f223, 0, 0, 0, g(Yes, No, false, false, "", "販")}, - {0x1f224, 0, 0, 0, g(Yes, No, false, false, "", "声")}, - {0x1f225, 0, 0, 0, g(Yes, No, false, false, "", "吹")}, - {0x1f226, 0, 0, 0, g(Yes, No, false, false, "", "演")}, - {0x1f227, 0, 0, 0, g(Yes, No, false, false, "", "投")}, - {0x1f228, 0, 0, 0, g(Yes, No, false, false, "", "捕")}, - {0x1f229, 0, 0, 0, g(Yes, No, false, false, "", "一")}, - {0x1f22a, 0, 0, 0, g(Yes, No, false, false, "", "三")}, - {0x1f22b, 0, 0, 0, g(Yes, No, false, false, "", "遊")}, - {0x1f22c, 0, 0, 0, g(Yes, No, false, false, "", "左")}, - {0x1f22d, 0, 0, 0, g(Yes, No, false, false, "", "中")}, - {0x1f22e, 0, 0, 0, g(Yes, No, false, false, "", "右")}, - {0x1f22f, 0, 0, 0, g(Yes, No, false, false, "", "指")}, - {0x1f230, 0, 0, 0, g(Yes, No, false, false, "", "走")}, - {0x1f231, 0, 0, 0, g(Yes, No, false, false, "", "打")}, - {0x1f232, 0, 0, 0, g(Yes, No, false, false, "", "禁")}, - {0x1f233, 0, 0, 0, g(Yes, No, false, false, "", "空")}, - {0x1f234, 0, 0, 0, g(Yes, No, false, false, "", "合")}, - {0x1f235, 0, 0, 0, g(Yes, No, false, false, "", "満")}, - {0x1f236, 0, 0, 0, g(Yes, No, false, false, "", "有")}, - {0x1f237, 0, 0, 0, g(Yes, No, false, false, "", "月")}, - {0x1f238, 0, 0, 0, g(Yes, No, false, false, "", "申")}, - {0x1f239, 0, 0, 0, g(Yes, No, false, false, "", "割")}, - {0x1f23a, 0, 0, 0, g(Yes, No, false, false, "", "営")}, - {0x1f23b, 0, 0, 0, g(Yes, No, false, false, "", "配")}, - {0x1f23c, 0, 0, 0, f(Yes, false, "")}, - {0x1f240, 0, 0, 0, g(Yes, No, false, false, "", "〔本〕")}, - {0x1f241, 0, 0, 0, g(Yes, No, false, false, "", "〔三〕")}, - {0x1f242, 0, 0, 0, g(Yes, No, false, false, "", "〔二〕")}, - {0x1f243, 0, 0, 0, g(Yes, No, false, false, "", "〔安〕")}, - {0x1f244, 0, 0, 0, g(Yes, No, false, false, "", "〔点〕")}, - {0x1f245, 0, 0, 0, g(Yes, No, false, false, "", "〔打〕")}, - {0x1f246, 0, 0, 0, g(Yes, No, false, false, "", "〔盗〕")}, - {0x1f247, 0, 0, 0, g(Yes, No, false, false, "", "〔勝〕")}, - {0x1f248, 0, 0, 0, g(Yes, No, false, false, "", "〔敗〕")}, - {0x1f249, 0, 0, 0, f(Yes, false, "")}, - {0x1f250, 0, 0, 0, g(Yes, No, false, false, "", "得")}, - {0x1f251, 0, 0, 0, g(Yes, No, false, false, "", "可")}, - {0x1f252, 0, 0, 0, f(Yes, false, "")}, - {0x2f800, 0, 0, 0, f(No, false, "丽")}, - {0x2f801, 0, 0, 0, f(No, false, "丸")}, - {0x2f802, 0, 0, 0, f(No, false, "乁")}, - {0x2f803, 0, 0, 0, f(No, false, "𠄢")}, - {0x2f804, 0, 0, 0, f(No, false, "你")}, - {0x2f805, 0, 0, 0, f(No, false, "侮")}, - {0x2f806, 0, 0, 0, f(No, false, "侻")}, - {0x2f807, 0, 0, 0, f(No, false, "倂")}, - {0x2f808, 0, 0, 0, f(No, false, "偺")}, - {0x2f809, 0, 0, 0, f(No, false, "備")}, - {0x2f80a, 0, 0, 0, f(No, false, "僧")}, - {0x2f80b, 0, 0, 0, f(No, false, "像")}, - {0x2f80c, 0, 0, 0, f(No, false, "㒞")}, - {0x2f80d, 0, 0, 0, f(No, false, "𠘺")}, - {0x2f80e, 0, 0, 0, f(No, false, "免")}, - {0x2f80f, 0, 0, 0, f(No, false, "兔")}, - {0x2f810, 0, 0, 0, f(No, false, "兤")}, - {0x2f811, 0, 0, 0, f(No, false, "具")}, - {0x2f812, 0, 0, 0, f(No, false, "𠔜")}, - {0x2f813, 0, 0, 0, f(No, false, "㒹")}, - {0x2f814, 0, 0, 0, f(No, false, "內")}, - {0x2f815, 0, 0, 0, f(No, false, "再")}, - {0x2f816, 0, 0, 0, f(No, false, "𠕋")}, - {0x2f817, 0, 0, 0, f(No, false, "冗")}, - {0x2f818, 0, 0, 0, f(No, false, "冤")}, - {0x2f819, 0, 0, 0, f(No, false, "仌")}, - {0x2f81a, 0, 0, 0, f(No, false, "冬")}, - {0x2f81b, 0, 0, 0, f(No, false, "况")}, - {0x2f81c, 0, 0, 0, f(No, false, "𩇟")}, - {0x2f81d, 0, 0, 0, f(No, false, "凵")}, - {0x2f81e, 0, 0, 0, f(No, false, "刃")}, - {0x2f81f, 0, 0, 0, f(No, false, "㓟")}, - {0x2f820, 0, 0, 0, f(No, false, "刻")}, - {0x2f821, 0, 0, 0, f(No, false, "剆")}, - {0x2f822, 0, 0, 0, f(No, false, "割")}, - {0x2f823, 0, 0, 0, f(No, false, "剷")}, - {0x2f824, 0, 0, 0, f(No, false, "㔕")}, - {0x2f825, 0, 0, 0, f(No, false, "勇")}, - {0x2f826, 0, 0, 0, f(No, false, "勉")}, - {0x2f827, 0, 0, 0, f(No, false, "勤")}, - {0x2f828, 0, 0, 0, f(No, false, "勺")}, - {0x2f829, 0, 0, 0, f(No, false, "包")}, - {0x2f82a, 0, 0, 0, f(No, false, "匆")}, - {0x2f82b, 0, 0, 0, f(No, false, "北")}, - {0x2f82c, 0, 0, 0, f(No, false, "卉")}, - {0x2f82d, 0, 0, 0, f(No, false, "卑")}, - {0x2f82e, 0, 0, 0, f(No, false, "博")}, - {0x2f82f, 0, 0, 0, f(No, false, "即")}, - {0x2f830, 0, 0, 0, f(No, false, "卽")}, - {0x2f831, 0, 0, 0, f(No, false, "卿")}, - {0x2f834, 0, 0, 0, f(No, false, "𠨬")}, - {0x2f835, 0, 0, 0, f(No, false, "灰")}, - {0x2f836, 0, 0, 0, f(No, false, "及")}, - {0x2f837, 0, 0, 0, f(No, false, "叟")}, - {0x2f838, 0, 0, 0, f(No, false, "𠭣")}, - {0x2f839, 0, 0, 0, f(No, false, "叫")}, - {0x2f83a, 0, 0, 0, f(No, false, "叱")}, - {0x2f83b, 0, 0, 0, f(No, false, "吆")}, - {0x2f83c, 0, 0, 0, f(No, false, "咞")}, - {0x2f83d, 0, 0, 0, f(No, false, "吸")}, - {0x2f83e, 0, 0, 0, f(No, false, "呈")}, - {0x2f83f, 0, 0, 0, f(No, false, "周")}, - {0x2f840, 0, 0, 0, f(No, false, "咢")}, - {0x2f841, 0, 0, 0, f(No, false, "哶")}, - {0x2f842, 0, 0, 0, f(No, false, "唐")}, - {0x2f843, 0, 0, 0, f(No, false, "啓")}, - {0x2f844, 0, 0, 0, f(No, false, "啣")}, - {0x2f845, 0, 0, 0, f(No, false, "善")}, - {0x2f847, 0, 0, 0, f(No, false, "喙")}, - {0x2f848, 0, 0, 0, f(No, false, "喫")}, - {0x2f849, 0, 0, 0, f(No, false, "喳")}, - {0x2f84a, 0, 0, 0, f(No, false, "嗂")}, - {0x2f84b, 0, 0, 0, f(No, false, "圖")}, - {0x2f84c, 0, 0, 0, f(No, false, "嘆")}, - {0x2f84d, 0, 0, 0, f(No, false, "圗")}, - {0x2f84e, 0, 0, 0, f(No, false, "噑")}, - {0x2f84f, 0, 0, 0, f(No, false, "噴")}, - {0x2f850, 0, 0, 0, f(No, false, "切")}, - {0x2f851, 0, 0, 0, f(No, false, "壮")}, - {0x2f852, 0, 0, 0, f(No, false, "城")}, - {0x2f853, 0, 0, 0, f(No, false, "埴")}, - {0x2f854, 0, 0, 0, f(No, false, "堍")}, - {0x2f855, 0, 0, 0, f(No, false, "型")}, - {0x2f856, 0, 0, 0, f(No, false, "堲")}, - {0x2f857, 0, 0, 0, f(No, false, "報")}, - {0x2f858, 0, 0, 0, f(No, false, "墬")}, - {0x2f859, 0, 0, 0, f(No, false, "𡓤")}, - {0x2f85a, 0, 0, 0, f(No, false, "売")}, - {0x2f85b, 0, 0, 0, f(No, false, "壷")}, - {0x2f85c, 0, 0, 0, f(No, false, "夆")}, - {0x2f85d, 0, 0, 0, f(No, false, "多")}, - {0x2f85e, 0, 0, 0, f(No, false, "夢")}, - {0x2f85f, 0, 0, 0, f(No, false, "奢")}, - {0x2f860, 0, 0, 0, f(No, false, "𡚨")}, - {0x2f861, 0, 0, 0, f(No, false, "𡛪")}, - {0x2f862, 0, 0, 0, f(No, false, "姬")}, - {0x2f863, 0, 0, 0, f(No, false, "娛")}, - {0x2f864, 0, 0, 0, f(No, false, "娧")}, - {0x2f865, 0, 0, 0, f(No, false, "姘")}, - {0x2f866, 0, 0, 0, f(No, false, "婦")}, - {0x2f867, 0, 0, 0, f(No, false, "㛮")}, - {0x2f868, 0, 0, 0, f(No, false, "㛼")}, - {0x2f869, 0, 0, 0, f(No, false, "嬈")}, - {0x2f86a, 0, 0, 0, f(No, false, "嬾")}, - {0x2f86c, 0, 0, 0, f(No, false, "𡧈")}, - {0x2f86d, 0, 0, 0, f(No, false, "寃")}, - {0x2f86e, 0, 0, 0, f(No, false, "寘")}, - {0x2f86f, 0, 0, 0, f(No, false, "寧")}, - {0x2f870, 0, 0, 0, f(No, false, "寳")}, - {0x2f871, 0, 0, 0, f(No, false, "𡬘")}, - {0x2f872, 0, 0, 0, f(No, false, "寿")}, - {0x2f873, 0, 0, 0, f(No, false, "将")}, - {0x2f874, 0, 0, 0, f(No, false, "当")}, - {0x2f875, 0, 0, 0, f(No, false, "尢")}, - {0x2f876, 0, 0, 0, f(No, false, "㞁")}, - {0x2f877, 0, 0, 0, f(No, false, "屠")}, - {0x2f878, 0, 0, 0, f(No, false, "屮")}, - {0x2f879, 0, 0, 0, f(No, false, "峀")}, - {0x2f87a, 0, 0, 0, f(No, false, "岍")}, - {0x2f87b, 0, 0, 0, f(No, false, "𡷤")}, - {0x2f87c, 0, 0, 0, f(No, false, "嵃")}, - {0x2f87d, 0, 0, 0, f(No, false, "𡷦")}, - {0x2f87e, 0, 0, 0, f(No, false, "嵮")}, - {0x2f87f, 0, 0, 0, f(No, false, "嵫")}, - {0x2f880, 0, 0, 0, f(No, false, "嵼")}, - {0x2f881, 0, 0, 0, f(No, false, "巡")}, - {0x2f882, 0, 0, 0, f(No, false, "巢")}, - {0x2f883, 0, 0, 0, f(No, false, "㠯")}, - {0x2f884, 0, 0, 0, f(No, false, "巽")}, - {0x2f885, 0, 0, 0, f(No, false, "帨")}, - {0x2f886, 0, 0, 0, f(No, false, "帽")}, - {0x2f887, 0, 0, 0, f(No, false, "幩")}, - {0x2f888, 0, 0, 0, f(No, false, "㡢")}, - {0x2f889, 0, 0, 0, f(No, false, "𢆃")}, - {0x2f88a, 0, 0, 0, f(No, false, "㡼")}, - {0x2f88b, 0, 0, 0, f(No, false, "庰")}, - {0x2f88c, 0, 0, 0, f(No, false, "庳")}, - {0x2f88d, 0, 0, 0, f(No, false, "庶")}, - {0x2f88e, 0, 0, 0, f(No, false, "廊")}, - {0x2f88f, 0, 0, 0, f(No, false, "𪎒")}, - {0x2f890, 0, 0, 0, f(No, false, "廾")}, - {0x2f891, 0, 0, 0, f(No, false, "𢌱")}, - {0x2f893, 0, 0, 0, f(No, false, "舁")}, - {0x2f894, 0, 0, 0, f(No, false, "弢")}, - {0x2f896, 0, 0, 0, f(No, false, "㣇")}, - {0x2f897, 0, 0, 0, f(No, false, "𣊸")}, - {0x2f898, 0, 0, 0, f(No, false, "𦇚")}, - {0x2f899, 0, 0, 0, f(No, false, "形")}, - {0x2f89a, 0, 0, 0, f(No, false, "彫")}, - {0x2f89b, 0, 0, 0, f(No, false, "㣣")}, - {0x2f89c, 0, 0, 0, f(No, false, "徚")}, - {0x2f89d, 0, 0, 0, f(No, false, "忍")}, - {0x2f89e, 0, 0, 0, f(No, false, "志")}, - {0x2f89f, 0, 0, 0, f(No, false, "忹")}, - {0x2f8a0, 0, 0, 0, f(No, false, "悁")}, - {0x2f8a1, 0, 0, 0, f(No, false, "㤺")}, - {0x2f8a2, 0, 0, 0, f(No, false, "㤜")}, - {0x2f8a3, 0, 0, 0, f(No, false, "悔")}, - {0x2f8a4, 0, 0, 0, f(No, false, "𢛔")}, - {0x2f8a5, 0, 0, 0, f(No, false, "惇")}, - {0x2f8a6, 0, 0, 0, f(No, false, "慈")}, - {0x2f8a7, 0, 0, 0, f(No, false, "慌")}, - {0x2f8a8, 0, 0, 0, f(No, false, "慎")}, - {0x2f8a9, 0, 0, 0, f(No, false, "慌")}, - {0x2f8aa, 0, 0, 0, f(No, false, "慺")}, - {0x2f8ab, 0, 0, 0, f(No, false, "憎")}, - {0x2f8ac, 0, 0, 0, f(No, false, "憲")}, - {0x2f8ad, 0, 0, 0, f(No, false, "憤")}, - {0x2f8ae, 0, 0, 0, f(No, false, "憯")}, - {0x2f8af, 0, 0, 0, f(No, false, "懞")}, - {0x2f8b0, 0, 0, 0, f(No, false, "懲")}, - {0x2f8b1, 0, 0, 0, f(No, false, "懶")}, - {0x2f8b2, 0, 0, 0, f(No, false, "成")}, - {0x2f8b3, 0, 0, 0, f(No, false, "戛")}, - {0x2f8b4, 0, 0, 0, f(No, false, "扝")}, - {0x2f8b5, 0, 0, 0, f(No, false, "抱")}, - {0x2f8b6, 0, 0, 0, f(No, false, "拔")}, - {0x2f8b7, 0, 0, 0, f(No, false, "捐")}, - {0x2f8b8, 0, 0, 0, f(No, false, "𢬌")}, - {0x2f8b9, 0, 0, 0, f(No, false, "挽")}, - {0x2f8ba, 0, 0, 0, f(No, false, "拼")}, - {0x2f8bb, 0, 0, 0, f(No, false, "捨")}, - {0x2f8bc, 0, 0, 0, f(No, false, "掃")}, - {0x2f8bd, 0, 0, 0, f(No, false, "揤")}, - {0x2f8be, 0, 0, 0, f(No, false, "𢯱")}, - {0x2f8bf, 0, 0, 0, f(No, false, "搢")}, - {0x2f8c0, 0, 0, 0, f(No, false, "揅")}, - {0x2f8c1, 0, 0, 0, f(No, false, "掩")}, - {0x2f8c2, 0, 0, 0, f(No, false, "㨮")}, - {0x2f8c3, 0, 0, 0, f(No, false, "摩")}, - {0x2f8c4, 0, 0, 0, f(No, false, "摾")}, - {0x2f8c5, 0, 0, 0, f(No, false, "撝")}, - {0x2f8c6, 0, 0, 0, f(No, false, "摷")}, - {0x2f8c7, 0, 0, 0, f(No, false, "㩬")}, - {0x2f8c8, 0, 0, 0, f(No, false, "敏")}, - {0x2f8c9, 0, 0, 0, f(No, false, "敬")}, - {0x2f8ca, 0, 0, 0, f(No, false, "𣀊")}, - {0x2f8cb, 0, 0, 0, f(No, false, "旣")}, - {0x2f8cc, 0, 0, 0, f(No, false, "書")}, - {0x2f8cd, 0, 0, 0, f(No, false, "晉")}, - {0x2f8ce, 0, 0, 0, f(No, false, "㬙")}, - {0x2f8cf, 0, 0, 0, f(No, false, "暑")}, - {0x2f8d0, 0, 0, 0, f(No, false, "㬈")}, - {0x2f8d1, 0, 0, 0, f(No, false, "㫤")}, - {0x2f8d2, 0, 0, 0, f(No, false, "冒")}, - {0x2f8d3, 0, 0, 0, f(No, false, "冕")}, - {0x2f8d4, 0, 0, 0, f(No, false, "最")}, - {0x2f8d5, 0, 0, 0, f(No, false, "暜")}, - {0x2f8d6, 0, 0, 0, f(No, false, "肭")}, - {0x2f8d7, 0, 0, 0, f(No, false, "䏙")}, - {0x2f8d8, 0, 0, 0, f(No, false, "朗")}, - {0x2f8d9, 0, 0, 0, f(No, false, "望")}, - {0x2f8da, 0, 0, 0, f(No, false, "朡")}, - {0x2f8db, 0, 0, 0, f(No, false, "杞")}, - {0x2f8dc, 0, 0, 0, f(No, false, "杓")}, - {0x2f8dd, 0, 0, 0, f(No, false, "𣏃")}, - {0x2f8de, 0, 0, 0, f(No, false, "㭉")}, - {0x2f8df, 0, 0, 0, f(No, false, "柺")}, - {0x2f8e0, 0, 0, 0, f(No, false, "枅")}, - {0x2f8e1, 0, 0, 0, f(No, false, "桒")}, - {0x2f8e2, 0, 0, 0, f(No, false, "梅")}, - {0x2f8e3, 0, 0, 0, f(No, false, "𣑭")}, - {0x2f8e4, 0, 0, 0, f(No, false, "梎")}, - {0x2f8e5, 0, 0, 0, f(No, false, "栟")}, - {0x2f8e6, 0, 0, 0, f(No, false, "椔")}, - {0x2f8e7, 0, 0, 0, f(No, false, "㮝")}, - {0x2f8e8, 0, 0, 0, f(No, false, "楂")}, - {0x2f8e9, 0, 0, 0, f(No, false, "榣")}, - {0x2f8ea, 0, 0, 0, f(No, false, "槪")}, - {0x2f8eb, 0, 0, 0, f(No, false, "檨")}, - {0x2f8ec, 0, 0, 0, f(No, false, "𣚣")}, - {0x2f8ed, 0, 0, 0, f(No, false, "櫛")}, - {0x2f8ee, 0, 0, 0, f(No, false, "㰘")}, - {0x2f8ef, 0, 0, 0, f(No, false, "次")}, - {0x2f8f0, 0, 0, 0, f(No, false, "𣢧")}, - {0x2f8f1, 0, 0, 0, f(No, false, "歔")}, - {0x2f8f2, 0, 0, 0, f(No, false, "㱎")}, - {0x2f8f3, 0, 0, 0, f(No, false, "歲")}, - {0x2f8f4, 0, 0, 0, f(No, false, "殟")}, - {0x2f8f5, 0, 0, 0, f(No, false, "殺")}, - {0x2f8f6, 0, 0, 0, f(No, false, "殻")}, - {0x2f8f7, 0, 0, 0, f(No, false, "𣪍")}, - {0x2f8f8, 0, 0, 0, f(No, false, "𡴋")}, - {0x2f8f9, 0, 0, 0, f(No, false, "𣫺")}, - {0x2f8fa, 0, 0, 0, f(No, false, "汎")}, - {0x2f8fb, 0, 0, 0, f(No, false, "𣲼")}, - {0x2f8fc, 0, 0, 0, f(No, false, "沿")}, - {0x2f8fd, 0, 0, 0, f(No, false, "泍")}, - {0x2f8fe, 0, 0, 0, f(No, false, "汧")}, - {0x2f8ff, 0, 0, 0, f(No, false, "洖")}, - {0x2f900, 0, 0, 0, f(No, false, "派")}, - {0x2f901, 0, 0, 0, f(No, false, "海")}, - {0x2f902, 0, 0, 0, f(No, false, "流")}, - {0x2f903, 0, 0, 0, f(No, false, "浩")}, - {0x2f904, 0, 0, 0, f(No, false, "浸")}, - {0x2f905, 0, 0, 0, f(No, false, "涅")}, - {0x2f906, 0, 0, 0, f(No, false, "𣴞")}, - {0x2f907, 0, 0, 0, f(No, false, "洴")}, - {0x2f908, 0, 0, 0, f(No, false, "港")}, - {0x2f909, 0, 0, 0, f(No, false, "湮")}, - {0x2f90a, 0, 0, 0, f(No, false, "㴳")}, - {0x2f90b, 0, 0, 0, f(No, false, "滋")}, - {0x2f90c, 0, 0, 0, f(No, false, "滇")}, - {0x2f90d, 0, 0, 0, f(No, false, "𣻑")}, - {0x2f90e, 0, 0, 0, f(No, false, "淹")}, - {0x2f90f, 0, 0, 0, f(No, false, "潮")}, - {0x2f910, 0, 0, 0, f(No, false, "𣽞")}, - {0x2f911, 0, 0, 0, f(No, false, "𣾎")}, - {0x2f912, 0, 0, 0, f(No, false, "濆")}, - {0x2f913, 0, 0, 0, f(No, false, "瀹")}, - {0x2f914, 0, 0, 0, f(No, false, "瀞")}, - {0x2f915, 0, 0, 0, f(No, false, "瀛")}, - {0x2f916, 0, 0, 0, f(No, false, "㶖")}, - {0x2f917, 0, 0, 0, f(No, false, "灊")}, - {0x2f918, 0, 0, 0, f(No, false, "災")}, - {0x2f919, 0, 0, 0, f(No, false, "灷")}, - {0x2f91a, 0, 0, 0, f(No, false, "炭")}, - {0x2f91b, 0, 0, 0, f(No, false, "𠔥")}, - {0x2f91c, 0, 0, 0, f(No, false, "煅")}, - {0x2f91d, 0, 0, 0, f(No, false, "𤉣")}, - {0x2f91e, 0, 0, 0, f(No, false, "熜")}, - {0x2f91f, 0, 0, 0, f(No, false, "𤎫")}, - {0x2f920, 0, 0, 0, f(No, false, "爨")}, - {0x2f921, 0, 0, 0, f(No, false, "爵")}, - {0x2f922, 0, 0, 0, f(No, false, "牐")}, - {0x2f923, 0, 0, 0, f(No, false, "𤘈")}, - {0x2f924, 0, 0, 0, f(No, false, "犀")}, - {0x2f925, 0, 0, 0, f(No, false, "犕")}, - {0x2f926, 0, 0, 0, f(No, false, "𤜵")}, - {0x2f927, 0, 0, 0, f(No, false, "𤠔")}, - {0x2f928, 0, 0, 0, f(No, false, "獺")}, - {0x2f929, 0, 0, 0, f(No, false, "王")}, - {0x2f92a, 0, 0, 0, f(No, false, "㺬")}, - {0x2f92b, 0, 0, 0, f(No, false, "玥")}, - {0x2f92c, 0, 0, 0, f(No, false, "㺸")}, - {0x2f92e, 0, 0, 0, f(No, false, "瑇")}, - {0x2f92f, 0, 0, 0, f(No, false, "瑜")}, - {0x2f930, 0, 0, 0, f(No, false, "瑱")}, - {0x2f931, 0, 0, 0, f(No, false, "璅")}, - {0x2f932, 0, 0, 0, f(No, false, "瓊")}, - {0x2f933, 0, 0, 0, f(No, false, "㼛")}, - {0x2f934, 0, 0, 0, f(No, false, "甤")}, - {0x2f935, 0, 0, 0, f(No, false, "𤰶")}, - {0x2f936, 0, 0, 0, f(No, false, "甾")}, - {0x2f937, 0, 0, 0, f(No, false, "𤲒")}, - {0x2f938, 0, 0, 0, f(No, false, "異")}, - {0x2f939, 0, 0, 0, f(No, false, "𢆟")}, - {0x2f93a, 0, 0, 0, f(No, false, "瘐")}, - {0x2f93b, 0, 0, 0, f(No, false, "𤾡")}, - {0x2f93c, 0, 0, 0, f(No, false, "𤾸")}, - {0x2f93d, 0, 0, 0, f(No, false, "𥁄")}, - {0x2f93e, 0, 0, 0, f(No, false, "㿼")}, - {0x2f93f, 0, 0, 0, f(No, false, "䀈")}, - {0x2f940, 0, 0, 0, f(No, false, "直")}, - {0x2f941, 0, 0, 0, f(No, false, "𥃳")}, - {0x2f942, 0, 0, 0, f(No, false, "𥃲")}, - {0x2f943, 0, 0, 0, f(No, false, "𥄙")}, - {0x2f944, 0, 0, 0, f(No, false, "𥄳")}, - {0x2f945, 0, 0, 0, f(No, false, "眞")}, - {0x2f946, 0, 0, 0, f(No, false, "真")}, - {0x2f948, 0, 0, 0, f(No, false, "睊")}, - {0x2f949, 0, 0, 0, f(No, false, "䀹")}, - {0x2f94a, 0, 0, 0, f(No, false, "瞋")}, - {0x2f94b, 0, 0, 0, f(No, false, "䁆")}, - {0x2f94c, 0, 0, 0, f(No, false, "䂖")}, - {0x2f94d, 0, 0, 0, f(No, false, "𥐝")}, - {0x2f94e, 0, 0, 0, f(No, false, "硎")}, - {0x2f94f, 0, 0, 0, f(No, false, "碌")}, - {0x2f950, 0, 0, 0, f(No, false, "磌")}, - {0x2f951, 0, 0, 0, f(No, false, "䃣")}, - {0x2f952, 0, 0, 0, f(No, false, "𥘦")}, - {0x2f953, 0, 0, 0, f(No, false, "祖")}, - {0x2f954, 0, 0, 0, f(No, false, "𥚚")}, - {0x2f955, 0, 0, 0, f(No, false, "𥛅")}, - {0x2f956, 0, 0, 0, f(No, false, "福")}, - {0x2f957, 0, 0, 0, f(No, false, "秫")}, - {0x2f958, 0, 0, 0, f(No, false, "䄯")}, - {0x2f959, 0, 0, 0, f(No, false, "穀")}, - {0x2f95a, 0, 0, 0, f(No, false, "穊")}, - {0x2f95b, 0, 0, 0, f(No, false, "穏")}, - {0x2f95c, 0, 0, 0, f(No, false, "𥥼")}, - {0x2f95d, 0, 0, 0, f(No, false, "𥪧")}, - {0x2f95f, 0, 0, 0, f(No, false, "竮")}, - {0x2f960, 0, 0, 0, f(No, false, "䈂")}, - {0x2f961, 0, 0, 0, f(No, false, "𥮫")}, - {0x2f962, 0, 0, 0, f(No, false, "篆")}, - {0x2f963, 0, 0, 0, f(No, false, "築")}, - {0x2f964, 0, 0, 0, f(No, false, "䈧")}, - {0x2f965, 0, 0, 0, f(No, false, "𥲀")}, - {0x2f966, 0, 0, 0, f(No, false, "糒")}, - {0x2f967, 0, 0, 0, f(No, false, "䊠")}, - {0x2f968, 0, 0, 0, f(No, false, "糨")}, - {0x2f969, 0, 0, 0, f(No, false, "糣")}, - {0x2f96a, 0, 0, 0, f(No, false, "紀")}, - {0x2f96b, 0, 0, 0, f(No, false, "𥾆")}, - {0x2f96c, 0, 0, 0, f(No, false, "絣")}, - {0x2f96d, 0, 0, 0, f(No, false, "䌁")}, - {0x2f96e, 0, 0, 0, f(No, false, "緇")}, - {0x2f96f, 0, 0, 0, f(No, false, "縂")}, - {0x2f970, 0, 0, 0, f(No, false, "繅")}, - {0x2f971, 0, 0, 0, f(No, false, "䌴")}, - {0x2f972, 0, 0, 0, f(No, false, "𦈨")}, - {0x2f973, 0, 0, 0, f(No, false, "𦉇")}, - {0x2f974, 0, 0, 0, f(No, false, "䍙")}, - {0x2f975, 0, 0, 0, f(No, false, "𦋙")}, - {0x2f976, 0, 0, 0, f(No, false, "罺")}, - {0x2f977, 0, 0, 0, f(No, false, "𦌾")}, - {0x2f978, 0, 0, 0, f(No, false, "羕")}, - {0x2f979, 0, 0, 0, f(No, false, "翺")}, - {0x2f97a, 0, 0, 0, f(No, false, "者")}, - {0x2f97b, 0, 0, 0, f(No, false, "𦓚")}, - {0x2f97c, 0, 0, 0, f(No, false, "𦔣")}, - {0x2f97d, 0, 0, 0, f(No, false, "聠")}, - {0x2f97e, 0, 0, 0, f(No, false, "𦖨")}, - {0x2f97f, 0, 0, 0, f(No, false, "聰")}, - {0x2f980, 0, 0, 0, f(No, false, "𣍟")}, - {0x2f981, 0, 0, 0, f(No, false, "䏕")}, - {0x2f982, 0, 0, 0, f(No, false, "育")}, - {0x2f983, 0, 0, 0, f(No, false, "脃")}, - {0x2f984, 0, 0, 0, f(No, false, "䐋")}, - {0x2f985, 0, 0, 0, f(No, false, "脾")}, - {0x2f986, 0, 0, 0, f(No, false, "媵")}, - {0x2f987, 0, 0, 0, f(No, false, "𦞧")}, - {0x2f988, 0, 0, 0, f(No, false, "𦞵")}, - {0x2f989, 0, 0, 0, f(No, false, "𣎓")}, - {0x2f98a, 0, 0, 0, f(No, false, "𣎜")}, - {0x2f98b, 0, 0, 0, f(No, false, "舁")}, - {0x2f98c, 0, 0, 0, f(No, false, "舄")}, - {0x2f98d, 0, 0, 0, f(No, false, "辞")}, - {0x2f98e, 0, 0, 0, f(No, false, "䑫")}, - {0x2f98f, 0, 0, 0, f(No, false, "芑")}, - {0x2f990, 0, 0, 0, f(No, false, "芋")}, - {0x2f991, 0, 0, 0, f(No, false, "芝")}, - {0x2f992, 0, 0, 0, f(No, false, "劳")}, - {0x2f993, 0, 0, 0, f(No, false, "花")}, - {0x2f994, 0, 0, 0, f(No, false, "芳")}, - {0x2f995, 0, 0, 0, f(No, false, "芽")}, - {0x2f996, 0, 0, 0, f(No, false, "苦")}, - {0x2f997, 0, 0, 0, f(No, false, "𦬼")}, - {0x2f998, 0, 0, 0, f(No, false, "若")}, - {0x2f999, 0, 0, 0, f(No, false, "茝")}, - {0x2f99a, 0, 0, 0, f(No, false, "荣")}, - {0x2f99b, 0, 0, 0, f(No, false, "莭")}, - {0x2f99c, 0, 0, 0, f(No, false, "茣")}, - {0x2f99d, 0, 0, 0, f(No, false, "莽")}, - {0x2f99e, 0, 0, 0, f(No, false, "菧")}, - {0x2f99f, 0, 0, 0, f(No, false, "著")}, - {0x2f9a0, 0, 0, 0, f(No, false, "荓")}, - {0x2f9a1, 0, 0, 0, f(No, false, "菊")}, - {0x2f9a2, 0, 0, 0, f(No, false, "菌")}, - {0x2f9a3, 0, 0, 0, f(No, false, "菜")}, - {0x2f9a4, 0, 0, 0, f(No, false, "𦰶")}, - {0x2f9a5, 0, 0, 0, f(No, false, "𦵫")}, - {0x2f9a6, 0, 0, 0, f(No, false, "𦳕")}, - {0x2f9a7, 0, 0, 0, f(No, false, "䔫")}, - {0x2f9a8, 0, 0, 0, f(No, false, "蓱")}, - {0x2f9a9, 0, 0, 0, f(No, false, "蓳")}, - {0x2f9aa, 0, 0, 0, f(No, false, "蔖")}, - {0x2f9ab, 0, 0, 0, f(No, false, "𧏊")}, - {0x2f9ac, 0, 0, 0, f(No, false, "蕤")}, - {0x2f9ad, 0, 0, 0, f(No, false, "𦼬")}, - {0x2f9ae, 0, 0, 0, f(No, false, "䕝")}, - {0x2f9af, 0, 0, 0, f(No, false, "䕡")}, - {0x2f9b0, 0, 0, 0, f(No, false, "𦾱")}, - {0x2f9b1, 0, 0, 0, f(No, false, "𧃒")}, - {0x2f9b2, 0, 0, 0, f(No, false, "䕫")}, - {0x2f9b3, 0, 0, 0, f(No, false, "虐")}, - {0x2f9b4, 0, 0, 0, f(No, false, "虜")}, - {0x2f9b5, 0, 0, 0, f(No, false, "虧")}, - {0x2f9b6, 0, 0, 0, f(No, false, "虩")}, - {0x2f9b7, 0, 0, 0, f(No, false, "蚩")}, - {0x2f9b8, 0, 0, 0, f(No, false, "蚈")}, - {0x2f9b9, 0, 0, 0, f(No, false, "蜎")}, - {0x2f9ba, 0, 0, 0, f(No, false, "蛢")}, - {0x2f9bb, 0, 0, 0, f(No, false, "蝹")}, - {0x2f9bc, 0, 0, 0, f(No, false, "蜨")}, - {0x2f9bd, 0, 0, 0, f(No, false, "蝫")}, - {0x2f9be, 0, 0, 0, f(No, false, "螆")}, - {0x2f9bf, 0, 0, 0, f(No, false, "䗗")}, - {0x2f9c0, 0, 0, 0, f(No, false, "蟡")}, - {0x2f9c1, 0, 0, 0, f(No, false, "蠁")}, - {0x2f9c2, 0, 0, 0, f(No, false, "䗹")}, - {0x2f9c3, 0, 0, 0, f(No, false, "衠")}, - {0x2f9c4, 0, 0, 0, f(No, false, "衣")}, - {0x2f9c5, 0, 0, 0, f(No, false, "𧙧")}, - {0x2f9c6, 0, 0, 0, f(No, false, "裗")}, - {0x2f9c7, 0, 0, 0, f(No, false, "裞")}, - {0x2f9c8, 0, 0, 0, f(No, false, "䘵")}, - {0x2f9c9, 0, 0, 0, f(No, false, "裺")}, - {0x2f9ca, 0, 0, 0, f(No, false, "㒻")}, - {0x2f9cb, 0, 0, 0, f(No, false, "𧢮")}, - {0x2f9cc, 0, 0, 0, f(No, false, "𧥦")}, - {0x2f9cd, 0, 0, 0, f(No, false, "䚾")}, - {0x2f9ce, 0, 0, 0, f(No, false, "䛇")}, - {0x2f9cf, 0, 0, 0, f(No, false, "誠")}, - {0x2f9d0, 0, 0, 0, f(No, false, "諭")}, - {0x2f9d1, 0, 0, 0, f(No, false, "變")}, - {0x2f9d2, 0, 0, 0, f(No, false, "豕")}, - {0x2f9d3, 0, 0, 0, f(No, false, "𧲨")}, - {0x2f9d4, 0, 0, 0, f(No, false, "貫")}, - {0x2f9d5, 0, 0, 0, f(No, false, "賁")}, - {0x2f9d6, 0, 0, 0, f(No, false, "贛")}, - {0x2f9d7, 0, 0, 0, f(No, false, "起")}, - {0x2f9d8, 0, 0, 0, f(No, false, "𧼯")}, - {0x2f9d9, 0, 0, 0, f(No, false, "𠠄")}, - {0x2f9da, 0, 0, 0, f(No, false, "跋")}, - {0x2f9db, 0, 0, 0, f(No, false, "趼")}, - {0x2f9dc, 0, 0, 0, f(No, false, "跰")}, - {0x2f9dd, 0, 0, 0, f(No, false, "𠣞")}, - {0x2f9de, 0, 0, 0, f(No, false, "軔")}, - {0x2f9df, 0, 0, 0, f(No, false, "輸")}, - {0x2f9e0, 0, 0, 0, f(No, false, "𨗒")}, - {0x2f9e1, 0, 0, 0, f(No, false, "𨗭")}, - {0x2f9e2, 0, 0, 0, f(No, false, "邔")}, - {0x2f9e3, 0, 0, 0, f(No, false, "郱")}, - {0x2f9e4, 0, 0, 0, f(No, false, "鄑")}, - {0x2f9e5, 0, 0, 0, f(No, false, "𨜮")}, - {0x2f9e6, 0, 0, 0, f(No, false, "鄛")}, - {0x2f9e7, 0, 0, 0, f(No, false, "鈸")}, - {0x2f9e8, 0, 0, 0, f(No, false, "鋗")}, - {0x2f9e9, 0, 0, 0, f(No, false, "鋘")}, - {0x2f9ea, 0, 0, 0, f(No, false, "鉼")}, - {0x2f9eb, 0, 0, 0, f(No, false, "鏹")}, - {0x2f9ec, 0, 0, 0, f(No, false, "鐕")}, - {0x2f9ed, 0, 0, 0, f(No, false, "𨯺")}, - {0x2f9ee, 0, 0, 0, f(No, false, "開")}, - {0x2f9ef, 0, 0, 0, f(No, false, "䦕")}, - {0x2f9f0, 0, 0, 0, f(No, false, "閷")}, - {0x2f9f1, 0, 0, 0, f(No, false, "𨵷")}, - {0x2f9f2, 0, 0, 0, f(No, false, "䧦")}, - {0x2f9f3, 0, 0, 0, f(No, false, "雃")}, - {0x2f9f4, 0, 0, 0, f(No, false, "嶲")}, - {0x2f9f5, 0, 0, 0, f(No, false, "霣")}, - {0x2f9f6, 0, 0, 0, f(No, false, "𩅅")}, - {0x2f9f7, 0, 0, 0, f(No, false, "𩈚")}, - {0x2f9f8, 0, 0, 0, f(No, false, "䩮")}, - {0x2f9f9, 0, 0, 0, f(No, false, "䩶")}, - {0x2f9fa, 0, 0, 0, f(No, false, "韠")}, - {0x2f9fb, 0, 0, 0, f(No, false, "𩐊")}, - {0x2f9fc, 0, 0, 0, f(No, false, "䪲")}, - {0x2f9fd, 0, 0, 0, f(No, false, "𩒖")}, - {0x2f9fe, 0, 0, 0, f(No, false, "頋")}, - {0x2fa00, 0, 0, 0, f(No, false, "頩")}, - {0x2fa01, 0, 0, 0, f(No, false, "𩖶")}, - {0x2fa02, 0, 0, 0, f(No, false, "飢")}, - {0x2fa03, 0, 0, 0, f(No, false, "䬳")}, - {0x2fa04, 0, 0, 0, f(No, false, "餩")}, - {0x2fa05, 0, 0, 0, f(No, false, "馧")}, - {0x2fa06, 0, 0, 0, f(No, false, "駂")}, - {0x2fa07, 0, 0, 0, f(No, false, "駾")}, - {0x2fa08, 0, 0, 0, f(No, false, "䯎")}, - {0x2fa09, 0, 0, 0, f(No, false, "𩬰")}, - {0x2fa0a, 0, 0, 0, f(No, false, "鬒")}, - {0x2fa0b, 0, 0, 0, f(No, false, "鱀")}, - {0x2fa0c, 0, 0, 0, f(No, false, "鳽")}, - {0x2fa0d, 0, 0, 0, f(No, false, "䳎")}, - {0x2fa0e, 0, 0, 0, f(No, false, "䳭")}, - {0x2fa0f, 0, 0, 0, f(No, false, "鵧")}, - {0x2fa10, 0, 0, 0, f(No, false, "𪃎")}, - {0x2fa11, 0, 0, 0, f(No, false, "䳸")}, - {0x2fa12, 0, 0, 0, f(No, false, "𪄅")}, - {0x2fa13, 0, 0, 0, f(No, false, "𪈎")}, - {0x2fa14, 0, 0, 0, f(No, false, "𪊑")}, - {0x2fa15, 0, 0, 0, f(No, false, "麻")}, - {0x2fa16, 0, 0, 0, f(No, false, "䵖")}, - {0x2fa17, 0, 0, 0, f(No, false, "黹")}, - {0x2fa18, 0, 0, 0, f(No, false, "黾")}, - {0x2fa19, 0, 0, 0, f(No, false, "鼅")}, - {0x2fa1a, 0, 0, 0, f(No, false, "鼏")}, - {0x2fa1b, 0, 0, 0, f(No, false, "鼖")}, - {0x2fa1c, 0, 0, 0, f(No, false, "鼻")}, - {0x2fa1d, 0, 0, 0, f(No, false, "𪘀")}, - {0x2fa1e, 0, 0, 0, f(Yes, false, "")}, -} diff --git a/vendor/golang.org/x/text/unicode/norm/data9.0.0_test.go b/vendor/golang.org/x/text/unicode/norm/data9.0.0_test.go deleted file mode 100644 index b1be64d5..00000000 --- a/vendor/golang.org/x/text/unicode/norm/data9.0.0_test.go +++ /dev/null @@ -1,7409 +0,0 @@ -// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. - -// +build !go1.10 - -package norm - -const ( - Yes = iota - No - Maybe -) - -type formData struct { - qc uint8 - combinesForward bool - decomposition string -} - -type runeData struct { - r rune - ccc uint8 - nLead uint8 - nTrail uint8 - f [2]formData // 0: canonical; 1: compatibility -} - -func f(qc uint8, cf bool, dec string) [2]formData { - return [2]formData{{qc, cf, dec}, {qc, cf, dec}} -} - -func g(qc, qck uint8, cf, cfk bool, d, dk string) [2]formData { - return [2]formData{{qc, cf, d}, {qck, cfk, dk}} -} - -var testData = []runeData{ - {0x0, 0, 0, 0, f(Yes, false, "")}, - {0x3c, 0, 0, 0, f(Yes, true, "")}, - {0x3f, 0, 0, 0, f(Yes, false, "")}, - {0x41, 0, 0, 0, f(Yes, true, "")}, - {0x51, 0, 0, 0, f(Yes, false, "")}, - {0x52, 0, 0, 0, f(Yes, true, "")}, - {0x5b, 0, 0, 0, f(Yes, false, "")}, - {0x61, 0, 0, 0, f(Yes, true, "")}, - {0x71, 0, 0, 0, f(Yes, false, "")}, - {0x72, 0, 0, 0, f(Yes, true, "")}, - {0x7b, 0, 0, 0, f(Yes, false, "")}, - {0xa0, 0, 0, 0, g(Yes, No, false, false, "", " ")}, - {0xa1, 0, 0, 0, f(Yes, false, "")}, - {0xa8, 0, 0, 1, g(Yes, No, true, false, "", " ̈")}, - {0xa9, 0, 0, 0, f(Yes, false, "")}, - {0xaa, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0xab, 0, 0, 0, f(Yes, false, "")}, - {0xaf, 0, 0, 1, g(Yes, No, false, false, "", " ̄")}, - {0xb0, 0, 0, 0, f(Yes, false, "")}, - {0xb2, 0, 0, 0, g(Yes, No, false, false, "", "2")}, - {0xb3, 0, 0, 0, g(Yes, No, false, false, "", "3")}, - {0xb4, 0, 0, 1, g(Yes, No, false, false, "", " ́")}, - {0xb5, 0, 0, 0, g(Yes, No, false, false, "", "μ")}, - {0xb6, 0, 0, 0, f(Yes, false, "")}, - {0xb8, 0, 0, 1, g(Yes, No, false, false, "", " ̧")}, - {0xb9, 0, 0, 0, g(Yes, No, false, false, "", "1")}, - {0xba, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0xbb, 0, 0, 0, f(Yes, false, "")}, - {0xbc, 0, 0, 0, g(Yes, No, false, false, "", "1⁄4")}, - {0xbd, 0, 0, 0, g(Yes, No, false, false, "", "1⁄2")}, - {0xbe, 0, 0, 0, g(Yes, No, false, false, "", "3⁄4")}, - {0xbf, 0, 0, 0, f(Yes, false, "")}, - {0xc0, 0, 0, 1, f(Yes, false, "À")}, - {0xc1, 0, 0, 1, f(Yes, false, "Á")}, - {0xc2, 0, 0, 1, f(Yes, true, "Â")}, - {0xc3, 0, 0, 1, f(Yes, false, "Ã")}, - {0xc4, 0, 0, 1, f(Yes, true, "Ä")}, - {0xc5, 0, 0, 1, f(Yes, true, "Å")}, - {0xc6, 0, 0, 0, f(Yes, true, "")}, - {0xc7, 0, 0, 1, f(Yes, true, "Ç")}, - {0xc8, 0, 0, 1, f(Yes, false, "È")}, - {0xc9, 0, 0, 1, f(Yes, false, "É")}, - {0xca, 0, 0, 1, f(Yes, true, "Ê")}, - {0xcb, 0, 0, 1, f(Yes, false, "Ë")}, - {0xcc, 0, 0, 1, f(Yes, false, "Ì")}, - {0xcd, 0, 0, 1, f(Yes, false, "Í")}, - {0xce, 0, 0, 1, f(Yes, false, "Î")}, - {0xcf, 0, 0, 1, f(Yes, true, "Ï")}, - {0xd0, 0, 0, 0, f(Yes, false, "")}, - {0xd1, 0, 0, 1, f(Yes, false, "Ñ")}, - {0xd2, 0, 0, 1, f(Yes, false, "Ò")}, - {0xd3, 0, 0, 1, f(Yes, false, "Ó")}, - {0xd4, 0, 0, 1, f(Yes, true, "Ô")}, - {0xd5, 0, 0, 1, f(Yes, true, "Õ")}, - {0xd6, 0, 0, 1, f(Yes, true, "Ö")}, - {0xd7, 0, 0, 0, f(Yes, false, "")}, - {0xd8, 0, 0, 0, f(Yes, true, "")}, - {0xd9, 0, 0, 1, f(Yes, false, "Ù")}, - {0xda, 0, 0, 1, f(Yes, false, "Ú")}, - {0xdb, 0, 0, 1, f(Yes, false, "Û")}, - {0xdc, 0, 0, 1, f(Yes, true, "Ü")}, - {0xdd, 0, 0, 1, f(Yes, false, "Ý")}, - {0xde, 0, 0, 0, f(Yes, false, "")}, - {0xe0, 0, 0, 1, f(Yes, false, "à")}, - {0xe1, 0, 0, 1, f(Yes, false, "á")}, - {0xe2, 0, 0, 1, f(Yes, true, "â")}, - {0xe3, 0, 0, 1, f(Yes, false, "ã")}, - {0xe4, 0, 0, 1, f(Yes, true, "ä")}, - {0xe5, 0, 0, 1, f(Yes, true, "å")}, - {0xe6, 0, 0, 0, f(Yes, true, "")}, - {0xe7, 0, 0, 1, f(Yes, true, "ç")}, - {0xe8, 0, 0, 1, f(Yes, false, "è")}, - {0xe9, 0, 0, 1, f(Yes, false, "é")}, - {0xea, 0, 0, 1, f(Yes, true, "ê")}, - {0xeb, 0, 0, 1, f(Yes, false, "ë")}, - {0xec, 0, 0, 1, f(Yes, false, "ì")}, - {0xed, 0, 0, 1, f(Yes, false, "í")}, - {0xee, 0, 0, 1, f(Yes, false, "î")}, - {0xef, 0, 0, 1, f(Yes, true, "ï")}, - {0xf0, 0, 0, 0, f(Yes, false, "")}, - {0xf1, 0, 0, 1, f(Yes, false, "ñ")}, - {0xf2, 0, 0, 1, f(Yes, false, "ò")}, - {0xf3, 0, 0, 1, f(Yes, false, "ó")}, - {0xf4, 0, 0, 1, f(Yes, true, "ô")}, - {0xf5, 0, 0, 1, f(Yes, true, "õ")}, - {0xf6, 0, 0, 1, f(Yes, true, "ö")}, - {0xf7, 0, 0, 0, f(Yes, false, "")}, - {0xf8, 0, 0, 0, f(Yes, true, "")}, - {0xf9, 0, 0, 1, f(Yes, false, "ù")}, - {0xfa, 0, 0, 1, f(Yes, false, "ú")}, - {0xfb, 0, 0, 1, f(Yes, false, "û")}, - {0xfc, 0, 0, 1, f(Yes, true, "ü")}, - {0xfd, 0, 0, 1, f(Yes, false, "ý")}, - {0xfe, 0, 0, 0, f(Yes, false, "")}, - {0xff, 0, 0, 1, f(Yes, false, "ÿ")}, - {0x100, 0, 0, 1, f(Yes, false, "Ā")}, - {0x101, 0, 0, 1, f(Yes, false, "ā")}, - {0x102, 0, 0, 1, f(Yes, true, "Ă")}, - {0x103, 0, 0, 1, f(Yes, true, "ă")}, - {0x104, 0, 0, 1, f(Yes, false, "Ą")}, - {0x105, 0, 0, 1, f(Yes, false, "ą")}, - {0x106, 0, 0, 1, f(Yes, false, "Ć")}, - {0x107, 0, 0, 1, f(Yes, false, "ć")}, - {0x108, 0, 0, 1, f(Yes, false, "Ĉ")}, - {0x109, 0, 0, 1, f(Yes, false, "ĉ")}, - {0x10a, 0, 0, 1, f(Yes, false, "Ċ")}, - {0x10b, 0, 0, 1, f(Yes, false, "ċ")}, - {0x10c, 0, 0, 1, f(Yes, false, "Č")}, - {0x10d, 0, 0, 1, f(Yes, false, "č")}, - {0x10e, 0, 0, 1, f(Yes, false, "Ď")}, - {0x10f, 0, 0, 1, f(Yes, false, "ď")}, - {0x110, 0, 0, 0, f(Yes, false, "")}, - {0x112, 0, 0, 1, f(Yes, true, "Ē")}, - {0x113, 0, 0, 1, f(Yes, true, "ē")}, - {0x114, 0, 0, 1, f(Yes, false, "Ĕ")}, - {0x115, 0, 0, 1, f(Yes, false, "ĕ")}, - {0x116, 0, 0, 1, f(Yes, false, "Ė")}, - {0x117, 0, 0, 1, f(Yes, false, "ė")}, - {0x118, 0, 0, 1, f(Yes, false, "Ę")}, - {0x119, 0, 0, 1, f(Yes, false, "ę")}, - {0x11a, 0, 0, 1, f(Yes, false, "Ě")}, - {0x11b, 0, 0, 1, f(Yes, false, "ě")}, - {0x11c, 0, 0, 1, f(Yes, false, "Ĝ")}, - {0x11d, 0, 0, 1, f(Yes, false, "ĝ")}, - {0x11e, 0, 0, 1, f(Yes, false, "Ğ")}, - {0x11f, 0, 0, 1, f(Yes, false, "ğ")}, - {0x120, 0, 0, 1, f(Yes, false, "Ġ")}, - {0x121, 0, 0, 1, f(Yes, false, "ġ")}, - {0x122, 0, 0, 1, f(Yes, false, "Ģ")}, - {0x123, 0, 0, 1, f(Yes, false, "ģ")}, - {0x124, 0, 0, 1, f(Yes, false, "Ĥ")}, - {0x125, 0, 0, 1, f(Yes, false, "ĥ")}, - {0x126, 0, 0, 0, f(Yes, false, "")}, - {0x128, 0, 0, 1, f(Yes, false, "Ĩ")}, - {0x129, 0, 0, 1, f(Yes, false, "ĩ")}, - {0x12a, 0, 0, 1, f(Yes, false, "Ī")}, - {0x12b, 0, 0, 1, f(Yes, false, "ī")}, - {0x12c, 0, 0, 1, f(Yes, false, "Ĭ")}, - {0x12d, 0, 0, 1, f(Yes, false, "ĭ")}, - {0x12e, 0, 0, 1, f(Yes, false, "Į")}, - {0x12f, 0, 0, 1, f(Yes, false, "į")}, - {0x130, 0, 0, 1, f(Yes, false, "İ")}, - {0x131, 0, 0, 0, f(Yes, false, "")}, - {0x132, 0, 0, 0, g(Yes, No, false, false, "", "IJ")}, - {0x133, 0, 0, 0, g(Yes, No, false, false, "", "ij")}, - {0x134, 0, 0, 1, f(Yes, false, "Ĵ")}, - {0x135, 0, 0, 1, f(Yes, false, "ĵ")}, - {0x136, 0, 0, 1, f(Yes, false, "Ķ")}, - {0x137, 0, 0, 1, f(Yes, false, "ķ")}, - {0x138, 0, 0, 0, f(Yes, false, "")}, - {0x139, 0, 0, 1, f(Yes, false, "Ĺ")}, - {0x13a, 0, 0, 1, f(Yes, false, "ĺ")}, - {0x13b, 0, 0, 1, f(Yes, false, "Ļ")}, - {0x13c, 0, 0, 1, f(Yes, false, "ļ")}, - {0x13d, 0, 0, 1, f(Yes, false, "Ľ")}, - {0x13e, 0, 0, 1, f(Yes, false, "ľ")}, - {0x13f, 0, 0, 0, g(Yes, No, false, false, "", "L·")}, - {0x140, 0, 0, 0, g(Yes, No, false, false, "", "l·")}, - {0x141, 0, 0, 0, f(Yes, false, "")}, - {0x143, 0, 0, 1, f(Yes, false, "Ń")}, - {0x144, 0, 0, 1, f(Yes, false, "ń")}, - {0x145, 0, 0, 1, f(Yes, false, "Ņ")}, - {0x146, 0, 0, 1, f(Yes, false, "ņ")}, - {0x147, 0, 0, 1, f(Yes, false, "Ň")}, - {0x148, 0, 0, 1, f(Yes, false, "ň")}, - {0x149, 0, 0, 0, g(Yes, No, false, false, "", "ʼn")}, - {0x14a, 0, 0, 0, f(Yes, false, "")}, - {0x14c, 0, 0, 1, f(Yes, true, "Ō")}, - {0x14d, 0, 0, 1, f(Yes, true, "ō")}, - {0x14e, 0, 0, 1, f(Yes, false, "Ŏ")}, - {0x14f, 0, 0, 1, f(Yes, false, "ŏ")}, - {0x150, 0, 0, 1, f(Yes, false, "Ő")}, - {0x151, 0, 0, 1, f(Yes, false, "ő")}, - {0x152, 0, 0, 0, f(Yes, false, "")}, - {0x154, 0, 0, 1, f(Yes, false, "Ŕ")}, - {0x155, 0, 0, 1, f(Yes, false, "ŕ")}, - {0x156, 0, 0, 1, f(Yes, false, "Ŗ")}, - {0x157, 0, 0, 1, f(Yes, false, "ŗ")}, - {0x158, 0, 0, 1, f(Yes, false, "Ř")}, - {0x159, 0, 0, 1, f(Yes, false, "ř")}, - {0x15a, 0, 0, 1, f(Yes, true, "Ś")}, - {0x15b, 0, 0, 1, f(Yes, true, "ś")}, - {0x15c, 0, 0, 1, f(Yes, false, "Ŝ")}, - {0x15d, 0, 0, 1, f(Yes, false, "ŝ")}, - {0x15e, 0, 0, 1, f(Yes, false, "Ş")}, - {0x15f, 0, 0, 1, f(Yes, false, "ş")}, - {0x160, 0, 0, 1, f(Yes, true, "Š")}, - {0x161, 0, 0, 1, f(Yes, true, "š")}, - {0x162, 0, 0, 1, f(Yes, false, "Ţ")}, - {0x163, 0, 0, 1, f(Yes, false, "ţ")}, - {0x164, 0, 0, 1, f(Yes, false, "Ť")}, - {0x165, 0, 0, 1, f(Yes, false, "ť")}, - {0x166, 0, 0, 0, f(Yes, false, "")}, - {0x168, 0, 0, 1, f(Yes, true, "Ũ")}, - {0x169, 0, 0, 1, f(Yes, true, "ũ")}, - {0x16a, 0, 0, 1, f(Yes, true, "Ū")}, - {0x16b, 0, 0, 1, f(Yes, true, "ū")}, - {0x16c, 0, 0, 1, f(Yes, false, "Ŭ")}, - {0x16d, 0, 0, 1, f(Yes, false, "ŭ")}, - {0x16e, 0, 0, 1, f(Yes, false, "Ů")}, - {0x16f, 0, 0, 1, f(Yes, false, "ů")}, - {0x170, 0, 0, 1, f(Yes, false, "Ű")}, - {0x171, 0, 0, 1, f(Yes, false, "ű")}, - {0x172, 0, 0, 1, f(Yes, false, "Ų")}, - {0x173, 0, 0, 1, f(Yes, false, "ų")}, - {0x174, 0, 0, 1, f(Yes, false, "Ŵ")}, - {0x175, 0, 0, 1, f(Yes, false, "ŵ")}, - {0x176, 0, 0, 1, f(Yes, false, "Ŷ")}, - {0x177, 0, 0, 1, f(Yes, false, "ŷ")}, - {0x178, 0, 0, 1, f(Yes, false, "Ÿ")}, - {0x179, 0, 0, 1, f(Yes, false, "Ź")}, - {0x17a, 0, 0, 1, f(Yes, false, "ź")}, - {0x17b, 0, 0, 1, f(Yes, false, "Ż")}, - {0x17c, 0, 0, 1, f(Yes, false, "ż")}, - {0x17d, 0, 0, 1, f(Yes, false, "Ž")}, - {0x17e, 0, 0, 1, f(Yes, false, "ž")}, - {0x17f, 0, 0, 0, g(Yes, No, true, false, "", "s")}, - {0x180, 0, 0, 0, f(Yes, false, "")}, - {0x1a0, 0, 0, 1, f(Yes, true, "Ơ")}, - {0x1a1, 0, 0, 1, f(Yes, true, "ơ")}, - {0x1a2, 0, 0, 0, f(Yes, false, "")}, - {0x1af, 0, 0, 1, f(Yes, true, "Ư")}, - {0x1b0, 0, 0, 1, f(Yes, true, "ư")}, - {0x1b1, 0, 0, 0, f(Yes, false, "")}, - {0x1b7, 0, 0, 0, f(Yes, true, "")}, - {0x1b8, 0, 0, 0, f(Yes, false, "")}, - {0x1c4, 0, 0, 1, g(Yes, No, false, false, "", "DŽ")}, - {0x1c5, 0, 0, 1, g(Yes, No, false, false, "", "Dž")}, - {0x1c6, 0, 0, 1, g(Yes, No, false, false, "", "dž")}, - {0x1c7, 0, 0, 0, g(Yes, No, false, false, "", "LJ")}, - {0x1c8, 0, 0, 0, g(Yes, No, false, false, "", "Lj")}, - {0x1c9, 0, 0, 0, g(Yes, No, false, false, "", "lj")}, - {0x1ca, 0, 0, 0, g(Yes, No, false, false, "", "NJ")}, - {0x1cb, 0, 0, 0, g(Yes, No, false, false, "", "Nj")}, - {0x1cc, 0, 0, 0, g(Yes, No, false, false, "", "nj")}, - {0x1cd, 0, 0, 1, f(Yes, false, "Ǎ")}, - {0x1ce, 0, 0, 1, f(Yes, false, "ǎ")}, - {0x1cf, 0, 0, 1, f(Yes, false, "Ǐ")}, - {0x1d0, 0, 0, 1, f(Yes, false, "ǐ")}, - {0x1d1, 0, 0, 1, f(Yes, false, "Ǒ")}, - {0x1d2, 0, 0, 1, f(Yes, false, "ǒ")}, - {0x1d3, 0, 0, 1, f(Yes, false, "Ǔ")}, - {0x1d4, 0, 0, 1, f(Yes, false, "ǔ")}, - {0x1d5, 0, 0, 2, f(Yes, false, "Ǖ")}, - {0x1d6, 0, 0, 2, f(Yes, false, "ǖ")}, - {0x1d7, 0, 0, 2, f(Yes, false, "Ǘ")}, - {0x1d8, 0, 0, 2, f(Yes, false, "ǘ")}, - {0x1d9, 0, 0, 2, f(Yes, false, "Ǚ")}, - {0x1da, 0, 0, 2, f(Yes, false, "ǚ")}, - {0x1db, 0, 0, 2, f(Yes, false, "Ǜ")}, - {0x1dc, 0, 0, 2, f(Yes, false, "ǜ")}, - {0x1dd, 0, 0, 0, f(Yes, false, "")}, - {0x1de, 0, 0, 2, f(Yes, false, "Ǟ")}, - {0x1df, 0, 0, 2, f(Yes, false, "ǟ")}, - {0x1e0, 0, 0, 2, f(Yes, false, "Ǡ")}, - {0x1e1, 0, 0, 2, f(Yes, false, "ǡ")}, - {0x1e2, 0, 0, 1, f(Yes, false, "Ǣ")}, - {0x1e3, 0, 0, 1, f(Yes, false, "ǣ")}, - {0x1e4, 0, 0, 0, f(Yes, false, "")}, - {0x1e6, 0, 0, 1, f(Yes, false, "Ǧ")}, - {0x1e7, 0, 0, 1, f(Yes, false, "ǧ")}, - {0x1e8, 0, 0, 1, f(Yes, false, "Ǩ")}, - {0x1e9, 0, 0, 1, f(Yes, false, "ǩ")}, - {0x1ea, 0, 0, 1, f(Yes, true, "Ǫ")}, - {0x1eb, 0, 0, 1, f(Yes, true, "ǫ")}, - {0x1ec, 0, 0, 2, f(Yes, false, "Ǭ")}, - {0x1ed, 0, 0, 2, f(Yes, false, "ǭ")}, - {0x1ee, 0, 0, 1, f(Yes, false, "Ǯ")}, - {0x1ef, 0, 0, 1, f(Yes, false, "ǯ")}, - {0x1f0, 0, 0, 1, f(Yes, false, "ǰ")}, - {0x1f1, 0, 0, 0, g(Yes, No, false, false, "", "DZ")}, - {0x1f2, 0, 0, 0, g(Yes, No, false, false, "", "Dz")}, - {0x1f3, 0, 0, 0, g(Yes, No, false, false, "", "dz")}, - {0x1f4, 0, 0, 1, f(Yes, false, "Ǵ")}, - {0x1f5, 0, 0, 1, f(Yes, false, "ǵ")}, - {0x1f6, 0, 0, 0, f(Yes, false, "")}, - {0x1f8, 0, 0, 1, f(Yes, false, "Ǹ")}, - {0x1f9, 0, 0, 1, f(Yes, false, "ǹ")}, - {0x1fa, 0, 0, 2, f(Yes, false, "Ǻ")}, - {0x1fb, 0, 0, 2, f(Yes, false, "ǻ")}, - {0x1fc, 0, 0, 1, f(Yes, false, "Ǽ")}, - {0x1fd, 0, 0, 1, f(Yes, false, "ǽ")}, - {0x1fe, 0, 0, 1, f(Yes, false, "Ǿ")}, - {0x1ff, 0, 0, 1, f(Yes, false, "ǿ")}, - {0x200, 0, 0, 1, f(Yes, false, "Ȁ")}, - {0x201, 0, 0, 1, f(Yes, false, "ȁ")}, - {0x202, 0, 0, 1, f(Yes, false, "Ȃ")}, - {0x203, 0, 0, 1, f(Yes, false, "ȃ")}, - {0x204, 0, 0, 1, f(Yes, false, "Ȅ")}, - {0x205, 0, 0, 1, f(Yes, false, "ȅ")}, - {0x206, 0, 0, 1, f(Yes, false, "Ȇ")}, - {0x207, 0, 0, 1, f(Yes, false, "ȇ")}, - {0x208, 0, 0, 1, f(Yes, false, "Ȉ")}, - {0x209, 0, 0, 1, f(Yes, false, "ȉ")}, - {0x20a, 0, 0, 1, f(Yes, false, "Ȋ")}, - {0x20b, 0, 0, 1, f(Yes, false, "ȋ")}, - {0x20c, 0, 0, 1, f(Yes, false, "Ȍ")}, - {0x20d, 0, 0, 1, f(Yes, false, "ȍ")}, - {0x20e, 0, 0, 1, f(Yes, false, "Ȏ")}, - {0x20f, 0, 0, 1, f(Yes, false, "ȏ")}, - {0x210, 0, 0, 1, f(Yes, false, "Ȑ")}, - {0x211, 0, 0, 1, f(Yes, false, "ȑ")}, - {0x212, 0, 0, 1, f(Yes, false, "Ȓ")}, - {0x213, 0, 0, 1, f(Yes, false, "ȓ")}, - {0x214, 0, 0, 1, f(Yes, false, "Ȕ")}, - {0x215, 0, 0, 1, f(Yes, false, "ȕ")}, - {0x216, 0, 0, 1, f(Yes, false, "Ȗ")}, - {0x217, 0, 0, 1, f(Yes, false, "ȗ")}, - {0x218, 0, 0, 1, f(Yes, false, "Ș")}, - {0x219, 0, 0, 1, f(Yes, false, "ș")}, - {0x21a, 0, 0, 1, f(Yes, false, "Ț")}, - {0x21b, 0, 0, 1, f(Yes, false, "ț")}, - {0x21c, 0, 0, 0, f(Yes, false, "")}, - {0x21e, 0, 0, 1, f(Yes, false, "Ȟ")}, - {0x21f, 0, 0, 1, f(Yes, false, "ȟ")}, - {0x220, 0, 0, 0, f(Yes, false, "")}, - {0x226, 0, 0, 1, f(Yes, true, "Ȧ")}, - {0x227, 0, 0, 1, f(Yes, true, "ȧ")}, - {0x228, 0, 0, 1, f(Yes, true, "Ȩ")}, - {0x229, 0, 0, 1, f(Yes, true, "ȩ")}, - {0x22a, 0, 0, 2, f(Yes, false, "Ȫ")}, - {0x22b, 0, 0, 2, f(Yes, false, "ȫ")}, - {0x22c, 0, 0, 2, f(Yes, false, "Ȭ")}, - {0x22d, 0, 0, 2, f(Yes, false, "ȭ")}, - {0x22e, 0, 0, 1, f(Yes, true, "Ȯ")}, - {0x22f, 0, 0, 1, f(Yes, true, "ȯ")}, - {0x230, 0, 0, 2, f(Yes, false, "Ȱ")}, - {0x231, 0, 0, 2, f(Yes, false, "ȱ")}, - {0x232, 0, 0, 1, f(Yes, false, "Ȳ")}, - {0x233, 0, 0, 1, f(Yes, false, "ȳ")}, - {0x234, 0, 0, 0, f(Yes, false, "")}, - {0x292, 0, 0, 0, f(Yes, true, "")}, - {0x293, 0, 0, 0, f(Yes, false, "")}, - {0x2b0, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0x2b1, 0, 0, 0, g(Yes, No, false, false, "", "ɦ")}, - {0x2b2, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x2b3, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0x2b4, 0, 0, 0, g(Yes, No, false, false, "", "ɹ")}, - {0x2b5, 0, 0, 0, g(Yes, No, false, false, "", "ɻ")}, - {0x2b6, 0, 0, 0, g(Yes, No, false, false, "", "ʁ")}, - {0x2b7, 0, 0, 0, g(Yes, No, false, false, "", "w")}, - {0x2b8, 0, 0, 0, g(Yes, No, false, false, "", "y")}, - {0x2b9, 0, 0, 0, f(Yes, false, "")}, - {0x2d8, 0, 0, 1, g(Yes, No, false, false, "", " ̆")}, - {0x2d9, 0, 0, 1, g(Yes, No, false, false, "", " ̇")}, - {0x2da, 0, 0, 1, g(Yes, No, false, false, "", " ̊")}, - {0x2db, 0, 0, 1, g(Yes, No, false, false, "", " ̨")}, - {0x2dc, 0, 0, 1, g(Yes, No, false, false, "", " ̃")}, - {0x2dd, 0, 0, 1, g(Yes, No, false, false, "", " ̋")}, - {0x2de, 0, 0, 0, f(Yes, false, "")}, - {0x2e0, 0, 0, 0, g(Yes, No, false, false, "", "ɣ")}, - {0x2e1, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x2e2, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0x2e3, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x2e4, 0, 0, 0, g(Yes, No, false, false, "", "ʕ")}, - {0x2e5, 0, 0, 0, f(Yes, false, "")}, - {0x300, 230, 1, 1, f(Maybe, false, "")}, - {0x305, 230, 1, 1, f(Yes, false, "")}, - {0x306, 230, 1, 1, f(Maybe, false, "")}, - {0x30d, 230, 1, 1, f(Yes, false, "")}, - {0x30f, 230, 1, 1, f(Maybe, false, "")}, - {0x310, 230, 1, 1, f(Yes, false, "")}, - {0x311, 230, 1, 1, f(Maybe, false, "")}, - {0x312, 230, 1, 1, f(Yes, false, "")}, - {0x313, 230, 1, 1, f(Maybe, false, "")}, - {0x315, 232, 1, 1, f(Yes, false, "")}, - {0x316, 220, 1, 1, f(Yes, false, "")}, - {0x31a, 232, 1, 1, f(Yes, false, "")}, - {0x31b, 216, 1, 1, f(Maybe, false, "")}, - {0x31c, 220, 1, 1, f(Yes, false, "")}, - {0x321, 202, 1, 1, f(Yes, false, "")}, - {0x323, 220, 1, 1, f(Maybe, false, "")}, - {0x327, 202, 1, 1, f(Maybe, false, "")}, - {0x329, 220, 1, 1, f(Yes, false, "")}, - {0x32d, 220, 1, 1, f(Maybe, false, "")}, - {0x32f, 220, 1, 1, f(Yes, false, "")}, - {0x330, 220, 1, 1, f(Maybe, false, "")}, - {0x332, 220, 1, 1, f(Yes, false, "")}, - {0x334, 1, 1, 1, f(Yes, false, "")}, - {0x338, 1, 1, 1, f(Maybe, false, "")}, - {0x339, 220, 1, 1, f(Yes, false, "")}, - {0x33d, 230, 1, 1, f(Yes, false, "")}, - {0x340, 230, 1, 1, f(No, false, "̀")}, - {0x341, 230, 1, 1, f(No, false, "́")}, - {0x342, 230, 1, 1, f(Maybe, false, "")}, - {0x343, 230, 1, 1, f(No, false, "̓")}, - {0x344, 230, 2, 2, f(No, false, "̈́")}, - {0x345, 240, 1, 1, f(Maybe, false, "")}, - {0x346, 230, 1, 1, f(Yes, false, "")}, - {0x347, 220, 1, 1, f(Yes, false, "")}, - {0x34a, 230, 1, 1, f(Yes, false, "")}, - {0x34d, 220, 1, 1, f(Yes, false, "")}, - {0x34f, 0, 0, 0, f(Yes, false, "")}, - {0x350, 230, 1, 1, f(Yes, false, "")}, - {0x353, 220, 1, 1, f(Yes, false, "")}, - {0x357, 230, 1, 1, f(Yes, false, "")}, - {0x358, 232, 1, 1, f(Yes, false, "")}, - {0x359, 220, 1, 1, f(Yes, false, "")}, - {0x35b, 230, 1, 1, f(Yes, false, "")}, - {0x35c, 233, 1, 1, f(Yes, false, "")}, - {0x35d, 234, 1, 1, f(Yes, false, "")}, - {0x35f, 233, 1, 1, f(Yes, false, "")}, - {0x360, 234, 1, 1, f(Yes, false, "")}, - {0x362, 233, 1, 1, f(Yes, false, "")}, - {0x363, 230, 1, 1, f(Yes, false, "")}, - {0x370, 0, 0, 0, f(Yes, false, "")}, - {0x374, 0, 0, 0, f(No, false, "ʹ")}, - {0x375, 0, 0, 0, f(Yes, false, "")}, - {0x37a, 0, 0, 1, g(Yes, No, false, false, "", " ͅ")}, - {0x37b, 0, 0, 0, f(Yes, false, "")}, - {0x37e, 0, 0, 0, f(No, false, ";")}, - {0x37f, 0, 0, 0, f(Yes, false, "")}, - {0x384, 0, 0, 1, g(Yes, No, false, false, "", " ́")}, - {0x385, 0, 0, 2, g(Yes, No, false, false, "΅", " ̈́")}, - {0x386, 0, 0, 1, f(Yes, false, "Ά")}, - {0x387, 0, 0, 0, f(No, false, "·")}, - {0x388, 0, 0, 1, f(Yes, false, "Έ")}, - {0x389, 0, 0, 1, f(Yes, false, "Ή")}, - {0x38a, 0, 0, 1, f(Yes, false, "Ί")}, - {0x38b, 0, 0, 0, f(Yes, false, "")}, - {0x38c, 0, 0, 1, f(Yes, false, "Ό")}, - {0x38d, 0, 0, 0, f(Yes, false, "")}, - {0x38e, 0, 0, 1, f(Yes, false, "Ύ")}, - {0x38f, 0, 0, 1, f(Yes, false, "Ώ")}, - {0x390, 0, 0, 2, f(Yes, false, "ΐ")}, - {0x391, 0, 0, 0, f(Yes, true, "")}, - {0x392, 0, 0, 0, f(Yes, false, "")}, - {0x395, 0, 0, 0, f(Yes, true, "")}, - {0x396, 0, 0, 0, f(Yes, false, "")}, - {0x397, 0, 0, 0, f(Yes, true, "")}, - {0x398, 0, 0, 0, f(Yes, false, "")}, - {0x399, 0, 0, 0, f(Yes, true, "")}, - {0x39a, 0, 0, 0, f(Yes, false, "")}, - {0x39f, 0, 0, 0, f(Yes, true, "")}, - {0x3a0, 0, 0, 0, f(Yes, false, "")}, - {0x3a1, 0, 0, 0, f(Yes, true, "")}, - {0x3a2, 0, 0, 0, f(Yes, false, "")}, - {0x3a5, 0, 0, 0, f(Yes, true, "")}, - {0x3a6, 0, 0, 0, f(Yes, false, "")}, - {0x3a9, 0, 0, 0, f(Yes, true, "")}, - {0x3aa, 0, 0, 1, f(Yes, false, "Ϊ")}, - {0x3ab, 0, 0, 1, f(Yes, false, "Ϋ")}, - {0x3ac, 0, 0, 1, f(Yes, true, "ά")}, - {0x3ad, 0, 0, 1, f(Yes, false, "έ")}, - {0x3ae, 0, 0, 1, f(Yes, true, "ή")}, - {0x3af, 0, 0, 1, f(Yes, false, "ί")}, - {0x3b0, 0, 0, 2, f(Yes, false, "ΰ")}, - {0x3b1, 0, 0, 0, f(Yes, true, "")}, - {0x3b2, 0, 0, 0, f(Yes, false, "")}, - {0x3b5, 0, 0, 0, f(Yes, true, "")}, - {0x3b6, 0, 0, 0, f(Yes, false, "")}, - {0x3b7, 0, 0, 0, f(Yes, true, "")}, - {0x3b8, 0, 0, 0, f(Yes, false, "")}, - {0x3b9, 0, 0, 0, f(Yes, true, "")}, - {0x3ba, 0, 0, 0, f(Yes, false, "")}, - {0x3bf, 0, 0, 0, f(Yes, true, "")}, - {0x3c0, 0, 0, 0, f(Yes, false, "")}, - {0x3c1, 0, 0, 0, f(Yes, true, "")}, - {0x3c2, 0, 0, 0, f(Yes, false, "")}, - {0x3c5, 0, 0, 0, f(Yes, true, "")}, - {0x3c6, 0, 0, 0, f(Yes, false, "")}, - {0x3c9, 0, 0, 0, f(Yes, true, "")}, - {0x3ca, 0, 0, 1, f(Yes, true, "ϊ")}, - {0x3cb, 0, 0, 1, f(Yes, true, "ϋ")}, - {0x3cc, 0, 0, 1, f(Yes, false, "ό")}, - {0x3cd, 0, 0, 1, f(Yes, false, "ύ")}, - {0x3ce, 0, 0, 1, f(Yes, true, "ώ")}, - {0x3cf, 0, 0, 0, f(Yes, false, "")}, - {0x3d0, 0, 0, 0, g(Yes, No, false, false, "", "β")}, - {0x3d1, 0, 0, 0, g(Yes, No, false, false, "", "θ")}, - {0x3d2, 0, 0, 0, g(Yes, No, true, false, "", "Υ")}, - {0x3d3, 0, 0, 1, g(Yes, No, false, false, "ϓ", "Ύ")}, - {0x3d4, 0, 0, 1, g(Yes, No, false, false, "ϔ", "Ϋ")}, - {0x3d5, 0, 0, 0, g(Yes, No, false, false, "", "φ")}, - {0x3d6, 0, 0, 0, g(Yes, No, false, false, "", "π")}, - {0x3d7, 0, 0, 0, f(Yes, false, "")}, - {0x3f0, 0, 0, 0, g(Yes, No, false, false, "", "κ")}, - {0x3f1, 0, 0, 0, g(Yes, No, false, false, "", "ρ")}, - {0x3f2, 0, 0, 0, g(Yes, No, false, false, "", "ς")}, - {0x3f3, 0, 0, 0, f(Yes, false, "")}, - {0x3f4, 0, 0, 0, g(Yes, No, false, false, "", "Θ")}, - {0x3f5, 0, 0, 0, g(Yes, No, false, false, "", "ε")}, - {0x3f6, 0, 0, 0, f(Yes, false, "")}, - {0x3f9, 0, 0, 0, g(Yes, No, false, false, "", "Σ")}, - {0x3fa, 0, 0, 0, f(Yes, false, "")}, - {0x400, 0, 0, 1, f(Yes, false, "Ѐ")}, - {0x401, 0, 0, 1, f(Yes, false, "Ё")}, - {0x402, 0, 0, 0, f(Yes, false, "")}, - {0x403, 0, 0, 1, f(Yes, false, "Ѓ")}, - {0x404, 0, 0, 0, f(Yes, false, "")}, - {0x406, 0, 0, 0, f(Yes, true, "")}, - {0x407, 0, 0, 1, f(Yes, false, "Ї")}, - {0x408, 0, 0, 0, f(Yes, false, "")}, - {0x40c, 0, 0, 1, f(Yes, false, "Ќ")}, - {0x40d, 0, 0, 1, f(Yes, false, "Ѝ")}, - {0x40e, 0, 0, 1, f(Yes, false, "Ў")}, - {0x40f, 0, 0, 0, f(Yes, false, "")}, - {0x410, 0, 0, 0, f(Yes, true, "")}, - {0x411, 0, 0, 0, f(Yes, false, "")}, - {0x413, 0, 0, 0, f(Yes, true, "")}, - {0x414, 0, 0, 0, f(Yes, false, "")}, - {0x415, 0, 0, 0, f(Yes, true, "")}, - {0x419, 0, 0, 1, f(Yes, false, "Й")}, - {0x41a, 0, 0, 0, f(Yes, true, "")}, - {0x41b, 0, 0, 0, f(Yes, false, "")}, - {0x41e, 0, 0, 0, f(Yes, true, "")}, - {0x41f, 0, 0, 0, f(Yes, false, "")}, - {0x423, 0, 0, 0, f(Yes, true, "")}, - {0x424, 0, 0, 0, f(Yes, false, "")}, - {0x427, 0, 0, 0, f(Yes, true, "")}, - {0x428, 0, 0, 0, f(Yes, false, "")}, - {0x42b, 0, 0, 0, f(Yes, true, "")}, - {0x42c, 0, 0, 0, f(Yes, false, "")}, - {0x42d, 0, 0, 0, f(Yes, true, "")}, - {0x42e, 0, 0, 0, f(Yes, false, "")}, - {0x430, 0, 0, 0, f(Yes, true, "")}, - {0x431, 0, 0, 0, f(Yes, false, "")}, - {0x433, 0, 0, 0, f(Yes, true, "")}, - {0x434, 0, 0, 0, f(Yes, false, "")}, - {0x435, 0, 0, 0, f(Yes, true, "")}, - {0x439, 0, 0, 1, f(Yes, false, "й")}, - {0x43a, 0, 0, 0, f(Yes, true, "")}, - {0x43b, 0, 0, 0, f(Yes, false, "")}, - {0x43e, 0, 0, 0, f(Yes, true, "")}, - {0x43f, 0, 0, 0, f(Yes, false, "")}, - {0x443, 0, 0, 0, f(Yes, true, "")}, - {0x444, 0, 0, 0, f(Yes, false, "")}, - {0x447, 0, 0, 0, f(Yes, true, "")}, - {0x448, 0, 0, 0, f(Yes, false, "")}, - {0x44b, 0, 0, 0, f(Yes, true, "")}, - {0x44c, 0, 0, 0, f(Yes, false, "")}, - {0x44d, 0, 0, 0, f(Yes, true, "")}, - {0x44e, 0, 0, 0, f(Yes, false, "")}, - {0x450, 0, 0, 1, f(Yes, false, "ѐ")}, - {0x451, 0, 0, 1, f(Yes, false, "ё")}, - {0x452, 0, 0, 0, f(Yes, false, "")}, - {0x453, 0, 0, 1, f(Yes, false, "ѓ")}, - {0x454, 0, 0, 0, f(Yes, false, "")}, - {0x456, 0, 0, 0, f(Yes, true, "")}, - {0x457, 0, 0, 1, f(Yes, false, "ї")}, - {0x458, 0, 0, 0, f(Yes, false, "")}, - {0x45c, 0, 0, 1, f(Yes, false, "ќ")}, - {0x45d, 0, 0, 1, f(Yes, false, "ѝ")}, - {0x45e, 0, 0, 1, f(Yes, false, "ў")}, - {0x45f, 0, 0, 0, f(Yes, false, "")}, - {0x474, 0, 0, 0, f(Yes, true, "")}, - {0x476, 0, 0, 1, f(Yes, false, "Ѷ")}, - {0x477, 0, 0, 1, f(Yes, false, "ѷ")}, - {0x478, 0, 0, 0, f(Yes, false, "")}, - {0x483, 230, 1, 1, f(Yes, false, "")}, - {0x488, 0, 0, 0, f(Yes, false, "")}, - {0x4c1, 0, 0, 1, f(Yes, false, "Ӂ")}, - {0x4c2, 0, 0, 1, f(Yes, false, "ӂ")}, - {0x4c3, 0, 0, 0, f(Yes, false, "")}, - {0x4d0, 0, 0, 1, f(Yes, false, "Ӑ")}, - {0x4d1, 0, 0, 1, f(Yes, false, "ӑ")}, - {0x4d2, 0, 0, 1, f(Yes, false, "Ӓ")}, - {0x4d3, 0, 0, 1, f(Yes, false, "ӓ")}, - {0x4d4, 0, 0, 0, f(Yes, false, "")}, - {0x4d6, 0, 0, 1, f(Yes, false, "Ӗ")}, - {0x4d7, 0, 0, 1, f(Yes, false, "ӗ")}, - {0x4d8, 0, 0, 0, f(Yes, true, "")}, - {0x4da, 0, 0, 1, f(Yes, false, "Ӛ")}, - {0x4db, 0, 0, 1, f(Yes, false, "ӛ")}, - {0x4dc, 0, 0, 1, f(Yes, false, "Ӝ")}, - {0x4dd, 0, 0, 1, f(Yes, false, "ӝ")}, - {0x4de, 0, 0, 1, f(Yes, false, "Ӟ")}, - {0x4df, 0, 0, 1, f(Yes, false, "ӟ")}, - {0x4e0, 0, 0, 0, f(Yes, false, "")}, - {0x4e2, 0, 0, 1, f(Yes, false, "Ӣ")}, - {0x4e3, 0, 0, 1, f(Yes, false, "ӣ")}, - {0x4e4, 0, 0, 1, f(Yes, false, "Ӥ")}, - {0x4e5, 0, 0, 1, f(Yes, false, "ӥ")}, - {0x4e6, 0, 0, 1, f(Yes, false, "Ӧ")}, - {0x4e7, 0, 0, 1, f(Yes, false, "ӧ")}, - {0x4e8, 0, 0, 0, f(Yes, true, "")}, - {0x4ea, 0, 0, 1, f(Yes, false, "Ӫ")}, - {0x4eb, 0, 0, 1, f(Yes, false, "ӫ")}, - {0x4ec, 0, 0, 1, f(Yes, false, "Ӭ")}, - {0x4ed, 0, 0, 1, f(Yes, false, "ӭ")}, - {0x4ee, 0, 0, 1, f(Yes, false, "Ӯ")}, - {0x4ef, 0, 0, 1, f(Yes, false, "ӯ")}, - {0x4f0, 0, 0, 1, f(Yes, false, "Ӱ")}, - {0x4f1, 0, 0, 1, f(Yes, false, "ӱ")}, - {0x4f2, 0, 0, 1, f(Yes, false, "Ӳ")}, - {0x4f3, 0, 0, 1, f(Yes, false, "ӳ")}, - {0x4f4, 0, 0, 1, f(Yes, false, "Ӵ")}, - {0x4f5, 0, 0, 1, f(Yes, false, "ӵ")}, - {0x4f6, 0, 0, 0, f(Yes, false, "")}, - {0x4f8, 0, 0, 1, f(Yes, false, "Ӹ")}, - {0x4f9, 0, 0, 1, f(Yes, false, "ӹ")}, - {0x4fa, 0, 0, 0, f(Yes, false, "")}, - {0x587, 0, 0, 0, g(Yes, No, false, false, "", "եւ")}, - {0x588, 0, 0, 0, f(Yes, false, "")}, - {0x591, 220, 1, 1, f(Yes, false, "")}, - {0x592, 230, 1, 1, f(Yes, false, "")}, - {0x596, 220, 1, 1, f(Yes, false, "")}, - {0x597, 230, 1, 1, f(Yes, false, "")}, - {0x59a, 222, 1, 1, f(Yes, false, "")}, - {0x59b, 220, 1, 1, f(Yes, false, "")}, - {0x59c, 230, 1, 1, f(Yes, false, "")}, - {0x5a2, 220, 1, 1, f(Yes, false, "")}, - {0x5a8, 230, 1, 1, f(Yes, false, "")}, - {0x5aa, 220, 1, 1, f(Yes, false, "")}, - {0x5ab, 230, 1, 1, f(Yes, false, "")}, - {0x5ad, 222, 1, 1, f(Yes, false, "")}, - {0x5ae, 228, 1, 1, f(Yes, false, "")}, - {0x5af, 230, 1, 1, f(Yes, false, "")}, - {0x5b0, 10, 1, 1, f(Yes, false, "")}, - {0x5b1, 11, 1, 1, f(Yes, false, "")}, - {0x5b2, 12, 1, 1, f(Yes, false, "")}, - {0x5b3, 13, 1, 1, f(Yes, false, "")}, - {0x5b4, 14, 1, 1, f(Yes, false, "")}, - {0x5b5, 15, 1, 1, f(Yes, false, "")}, - {0x5b6, 16, 1, 1, f(Yes, false, "")}, - {0x5b7, 17, 1, 1, f(Yes, false, "")}, - {0x5b8, 18, 1, 1, f(Yes, false, "")}, - {0x5b9, 19, 1, 1, f(Yes, false, "")}, - {0x5bb, 20, 1, 1, f(Yes, false, "")}, - {0x5bc, 21, 1, 1, f(Yes, false, "")}, - {0x5bd, 22, 1, 1, f(Yes, false, "")}, - {0x5be, 0, 0, 0, f(Yes, false, "")}, - {0x5bf, 23, 1, 1, f(Yes, false, "")}, - {0x5c0, 0, 0, 0, f(Yes, false, "")}, - {0x5c1, 24, 1, 1, f(Yes, false, "")}, - {0x5c2, 25, 1, 1, f(Yes, false, "")}, - {0x5c3, 0, 0, 0, f(Yes, false, "")}, - {0x5c4, 230, 1, 1, f(Yes, false, "")}, - {0x5c5, 220, 1, 1, f(Yes, false, "")}, - {0x5c6, 0, 0, 0, f(Yes, false, "")}, - {0x5c7, 18, 1, 1, f(Yes, false, "")}, - {0x5c8, 0, 0, 0, f(Yes, false, "")}, - {0x610, 230, 1, 1, f(Yes, false, "")}, - {0x618, 30, 1, 1, f(Yes, false, "")}, - {0x619, 31, 1, 1, f(Yes, false, "")}, - {0x61a, 32, 1, 1, f(Yes, false, "")}, - {0x61b, 0, 0, 0, f(Yes, false, "")}, - {0x622, 0, 0, 1, f(Yes, false, "آ")}, - {0x623, 0, 0, 1, f(Yes, false, "أ")}, - {0x624, 0, 0, 1, f(Yes, false, "ؤ")}, - {0x625, 0, 0, 1, f(Yes, false, "إ")}, - {0x626, 0, 0, 1, f(Yes, false, "ئ")}, - {0x627, 0, 0, 0, f(Yes, true, "")}, - {0x628, 0, 0, 0, f(Yes, false, "")}, - {0x648, 0, 0, 0, f(Yes, true, "")}, - {0x649, 0, 0, 0, f(Yes, false, "")}, - {0x64a, 0, 0, 0, f(Yes, true, "")}, - {0x64b, 27, 1, 1, f(Yes, false, "")}, - {0x64c, 28, 1, 1, f(Yes, false, "")}, - {0x64d, 29, 1, 1, f(Yes, false, "")}, - {0x64e, 30, 1, 1, f(Yes, false, "")}, - {0x64f, 31, 1, 1, f(Yes, false, "")}, - {0x650, 32, 1, 1, f(Yes, false, "")}, - {0x651, 33, 1, 1, f(Yes, false, "")}, - {0x652, 34, 1, 1, f(Yes, false, "")}, - {0x653, 230, 1, 1, f(Maybe, false, "")}, - {0x655, 220, 1, 1, f(Maybe, false, "")}, - {0x656, 220, 1, 1, f(Yes, false, "")}, - {0x657, 230, 1, 1, f(Yes, false, "")}, - {0x65c, 220, 1, 1, f(Yes, false, "")}, - {0x65d, 230, 1, 1, f(Yes, false, "")}, - {0x65f, 220, 1, 1, f(Yes, false, "")}, - {0x660, 0, 0, 0, f(Yes, false, "")}, - {0x670, 35, 1, 1, f(Yes, false, "")}, - {0x671, 0, 0, 0, f(Yes, false, "")}, - {0x675, 0, 0, 0, g(Yes, No, false, false, "", "اٴ")}, - {0x676, 0, 0, 0, g(Yes, No, false, false, "", "وٴ")}, - {0x677, 0, 0, 0, g(Yes, No, false, false, "", "ۇٴ")}, - {0x678, 0, 0, 0, g(Yes, No, false, false, "", "يٴ")}, - {0x679, 0, 0, 0, f(Yes, false, "")}, - {0x6c0, 0, 0, 1, f(Yes, false, "ۀ")}, - {0x6c1, 0, 0, 0, f(Yes, true, "")}, - {0x6c2, 0, 0, 1, f(Yes, false, "ۂ")}, - {0x6c3, 0, 0, 0, f(Yes, false, "")}, - {0x6d2, 0, 0, 0, f(Yes, true, "")}, - {0x6d3, 0, 0, 1, f(Yes, false, "ۓ")}, - {0x6d4, 0, 0, 0, f(Yes, false, "")}, - {0x6d5, 0, 0, 0, f(Yes, true, "")}, - {0x6d6, 230, 1, 1, f(Yes, false, "")}, - {0x6dd, 0, 0, 0, f(Yes, false, "")}, - {0x6df, 230, 1, 1, f(Yes, false, "")}, - {0x6e3, 220, 1, 1, f(Yes, false, "")}, - {0x6e4, 230, 1, 1, f(Yes, false, "")}, - {0x6e5, 0, 0, 0, f(Yes, false, "")}, - {0x6e7, 230, 1, 1, f(Yes, false, "")}, - {0x6e9, 0, 0, 0, f(Yes, false, "")}, - {0x6ea, 220, 1, 1, f(Yes, false, "")}, - {0x6eb, 230, 1, 1, f(Yes, false, "")}, - {0x6ed, 220, 1, 1, f(Yes, false, "")}, - {0x6ee, 0, 0, 0, f(Yes, false, "")}, - {0x711, 36, 1, 1, f(Yes, false, "")}, - {0x712, 0, 0, 0, f(Yes, false, "")}, - {0x730, 230, 1, 1, f(Yes, false, "")}, - {0x731, 220, 1, 1, f(Yes, false, "")}, - {0x732, 230, 1, 1, f(Yes, false, "")}, - {0x734, 220, 1, 1, f(Yes, false, "")}, - {0x735, 230, 1, 1, f(Yes, false, "")}, - {0x737, 220, 1, 1, f(Yes, false, "")}, - {0x73a, 230, 1, 1, f(Yes, false, "")}, - {0x73b, 220, 1, 1, f(Yes, false, "")}, - {0x73d, 230, 1, 1, f(Yes, false, "")}, - {0x73e, 220, 1, 1, f(Yes, false, "")}, - {0x73f, 230, 1, 1, f(Yes, false, "")}, - {0x742, 220, 1, 1, f(Yes, false, "")}, - {0x743, 230, 1, 1, f(Yes, false, "")}, - {0x744, 220, 1, 1, f(Yes, false, "")}, - {0x745, 230, 1, 1, f(Yes, false, "")}, - {0x746, 220, 1, 1, f(Yes, false, "")}, - {0x747, 230, 1, 1, f(Yes, false, "")}, - {0x748, 220, 1, 1, f(Yes, false, "")}, - {0x749, 230, 1, 1, f(Yes, false, "")}, - {0x74b, 0, 0, 0, f(Yes, false, "")}, - {0x7eb, 230, 1, 1, f(Yes, false, "")}, - {0x7f2, 220, 1, 1, f(Yes, false, "")}, - {0x7f3, 230, 1, 1, f(Yes, false, "")}, - {0x7f4, 0, 0, 0, f(Yes, false, "")}, - {0x816, 230, 1, 1, f(Yes, false, "")}, - {0x81a, 0, 0, 0, f(Yes, false, "")}, - {0x81b, 230, 1, 1, f(Yes, false, "")}, - {0x824, 0, 0, 0, f(Yes, false, "")}, - {0x825, 230, 1, 1, f(Yes, false, "")}, - {0x828, 0, 0, 0, f(Yes, false, "")}, - {0x829, 230, 1, 1, f(Yes, false, "")}, - {0x82e, 0, 0, 0, f(Yes, false, "")}, - {0x859, 220, 1, 1, f(Yes, false, "")}, - {0x85c, 0, 0, 0, f(Yes, false, "")}, - {0x8d4, 230, 1, 1, f(Yes, false, "")}, - {0x8e2, 0, 0, 0, f(Yes, false, "")}, - {0x8e3, 220, 1, 1, f(Yes, false, "")}, - {0x8e4, 230, 1, 1, f(Yes, false, "")}, - {0x8e6, 220, 1, 1, f(Yes, false, "")}, - {0x8e7, 230, 1, 1, f(Yes, false, "")}, - {0x8e9, 220, 1, 1, f(Yes, false, "")}, - {0x8ea, 230, 1, 1, f(Yes, false, "")}, - {0x8ed, 220, 1, 1, f(Yes, false, "")}, - {0x8f0, 27, 1, 1, f(Yes, false, "")}, - {0x8f1, 28, 1, 1, f(Yes, false, "")}, - {0x8f2, 29, 1, 1, f(Yes, false, "")}, - {0x8f3, 230, 1, 1, f(Yes, false, "")}, - {0x8f6, 220, 1, 1, f(Yes, false, "")}, - {0x8f7, 230, 1, 1, f(Yes, false, "")}, - {0x8f9, 220, 1, 1, f(Yes, false, "")}, - {0x8fb, 230, 1, 1, f(Yes, false, "")}, - {0x900, 0, 0, 0, f(Yes, false, "")}, - {0x928, 0, 0, 0, f(Yes, true, "")}, - {0x929, 0, 0, 1, f(Yes, false, "ऩ")}, - {0x92a, 0, 0, 0, f(Yes, false, "")}, - {0x930, 0, 0, 0, f(Yes, true, "")}, - {0x931, 0, 0, 1, f(Yes, false, "ऱ")}, - {0x932, 0, 0, 0, f(Yes, false, "")}, - {0x933, 0, 0, 0, f(Yes, true, "")}, - {0x934, 0, 0, 1, f(Yes, false, "ऴ")}, - {0x935, 0, 0, 0, f(Yes, false, "")}, - {0x93c, 7, 1, 1, f(Maybe, false, "")}, - {0x93d, 0, 0, 0, f(Yes, false, "")}, - {0x94d, 9, 1, 1, f(Yes, false, "")}, - {0x94e, 0, 0, 0, f(Yes, false, "")}, - {0x951, 230, 1, 1, f(Yes, false, "")}, - {0x952, 220, 1, 1, f(Yes, false, "")}, - {0x953, 230, 1, 1, f(Yes, false, "")}, - {0x955, 0, 0, 0, f(Yes, false, "")}, - {0x958, 0, 0, 1, f(No, false, "क़")}, - {0x959, 0, 0, 1, f(No, false, "ख़")}, - {0x95a, 0, 0, 1, f(No, false, "ग़")}, - {0x95b, 0, 0, 1, f(No, false, "ज़")}, - {0x95c, 0, 0, 1, f(No, false, "ड़")}, - {0x95d, 0, 0, 1, f(No, false, "ढ़")}, - {0x95e, 0, 0, 1, f(No, false, "फ़")}, - {0x95f, 0, 0, 1, f(No, false, "य़")}, - {0x960, 0, 0, 0, f(Yes, false, "")}, - {0x9bc, 7, 1, 1, f(Yes, false, "")}, - {0x9bd, 0, 0, 0, f(Yes, false, "")}, - {0x9be, 0, 1, 1, f(Maybe, false, "")}, - {0x9bf, 0, 0, 0, f(Yes, false, "")}, - {0x9c7, 0, 0, 0, f(Yes, true, "")}, - {0x9c8, 0, 0, 0, f(Yes, false, "")}, - {0x9cb, 0, 0, 1, f(Yes, false, "ো")}, - {0x9cc, 0, 0, 1, f(Yes, false, "ৌ")}, - {0x9cd, 9, 1, 1, f(Yes, false, "")}, - {0x9ce, 0, 0, 0, f(Yes, false, "")}, - {0x9d7, 0, 1, 1, f(Maybe, false, "")}, - {0x9d8, 0, 0, 0, f(Yes, false, "")}, - {0x9dc, 0, 0, 1, f(No, false, "ড়")}, - {0x9dd, 0, 0, 1, f(No, false, "ঢ়")}, - {0x9de, 0, 0, 0, f(Yes, false, "")}, - {0x9df, 0, 0, 1, f(No, false, "য়")}, - {0x9e0, 0, 0, 0, f(Yes, false, "")}, - {0xa33, 0, 0, 1, f(No, false, "ਲ਼")}, - {0xa34, 0, 0, 0, f(Yes, false, "")}, - {0xa36, 0, 0, 1, f(No, false, "ਸ਼")}, - {0xa37, 0, 0, 0, f(Yes, false, "")}, - {0xa3c, 7, 1, 1, f(Yes, false, "")}, - {0xa3d, 0, 0, 0, f(Yes, false, "")}, - {0xa4d, 9, 1, 1, f(Yes, false, "")}, - {0xa4e, 0, 0, 0, f(Yes, false, "")}, - {0xa59, 0, 0, 1, f(No, false, "ਖ਼")}, - {0xa5a, 0, 0, 1, f(No, false, "ਗ਼")}, - {0xa5b, 0, 0, 1, f(No, false, "ਜ਼")}, - {0xa5c, 0, 0, 0, f(Yes, false, "")}, - {0xa5e, 0, 0, 1, f(No, false, "ਫ਼")}, - {0xa5f, 0, 0, 0, f(Yes, false, "")}, - {0xabc, 7, 1, 1, f(Yes, false, "")}, - {0xabd, 0, 0, 0, f(Yes, false, "")}, - {0xacd, 9, 1, 1, f(Yes, false, "")}, - {0xace, 0, 0, 0, f(Yes, false, "")}, - {0xb3c, 7, 1, 1, f(Yes, false, "")}, - {0xb3d, 0, 0, 0, f(Yes, false, "")}, - {0xb3e, 0, 1, 1, f(Maybe, false, "")}, - {0xb3f, 0, 0, 0, f(Yes, false, "")}, - {0xb47, 0, 0, 0, f(Yes, true, "")}, - {0xb48, 0, 0, 1, f(Yes, false, "ୈ")}, - {0xb49, 0, 0, 0, f(Yes, false, "")}, - {0xb4b, 0, 0, 1, f(Yes, false, "ୋ")}, - {0xb4c, 0, 0, 1, f(Yes, false, "ୌ")}, - {0xb4d, 9, 1, 1, f(Yes, false, "")}, - {0xb4e, 0, 0, 0, f(Yes, false, "")}, - {0xb56, 0, 1, 1, f(Maybe, false, "")}, - {0xb58, 0, 0, 0, f(Yes, false, "")}, - {0xb5c, 0, 0, 1, f(No, false, "ଡ଼")}, - {0xb5d, 0, 0, 1, f(No, false, "ଢ଼")}, - {0xb5e, 0, 0, 0, f(Yes, false, "")}, - {0xb92, 0, 0, 0, f(Yes, true, "")}, - {0xb93, 0, 0, 0, f(Yes, false, "")}, - {0xb94, 0, 0, 1, f(Yes, false, "ஔ")}, - {0xb95, 0, 0, 0, f(Yes, false, "")}, - {0xbbe, 0, 1, 1, f(Maybe, false, "")}, - {0xbbf, 0, 0, 0, f(Yes, false, "")}, - {0xbc6, 0, 0, 0, f(Yes, true, "")}, - {0xbc8, 0, 0, 0, f(Yes, false, "")}, - {0xbca, 0, 0, 1, f(Yes, false, "ொ")}, - {0xbcb, 0, 0, 1, f(Yes, false, "ோ")}, - {0xbcc, 0, 0, 1, f(Yes, false, "ௌ")}, - {0xbcd, 9, 1, 1, f(Yes, false, "")}, - {0xbce, 0, 0, 0, f(Yes, false, "")}, - {0xbd7, 0, 1, 1, f(Maybe, false, "")}, - {0xbd8, 0, 0, 0, f(Yes, false, "")}, - {0xc46, 0, 0, 0, f(Yes, true, "")}, - {0xc47, 0, 0, 0, f(Yes, false, "")}, - {0xc48, 0, 0, 1, f(Yes, false, "ై")}, - {0xc49, 0, 0, 0, f(Yes, false, "")}, - {0xc4d, 9, 1, 1, f(Yes, false, "")}, - {0xc4e, 0, 0, 0, f(Yes, false, "")}, - {0xc55, 84, 1, 1, f(Yes, false, "")}, - {0xc56, 91, 1, 1, f(Maybe, false, "")}, - {0xc57, 0, 0, 0, f(Yes, false, "")}, - {0xcbc, 7, 1, 1, f(Yes, false, "")}, - {0xcbd, 0, 0, 0, f(Yes, false, "")}, - {0xcbf, 0, 0, 0, f(Yes, true, "")}, - {0xcc0, 0, 0, 1, f(Yes, false, "ೀ")}, - {0xcc1, 0, 0, 0, f(Yes, false, "")}, - {0xcc2, 0, 1, 1, f(Maybe, false, "")}, - {0xcc3, 0, 0, 0, f(Yes, false, "")}, - {0xcc6, 0, 0, 0, f(Yes, true, "")}, - {0xcc7, 0, 0, 1, f(Yes, false, "ೇ")}, - {0xcc8, 0, 0, 1, f(Yes, false, "ೈ")}, - {0xcc9, 0, 0, 0, f(Yes, false, "")}, - {0xcca, 0, 0, 1, f(Yes, true, "ೊ")}, - {0xccb, 0, 0, 2, f(Yes, false, "ೋ")}, - {0xccc, 0, 0, 0, f(Yes, false, "")}, - {0xccd, 9, 1, 1, f(Yes, false, "")}, - {0xcce, 0, 0, 0, f(Yes, false, "")}, - {0xcd5, 0, 1, 1, f(Maybe, false, "")}, - {0xcd7, 0, 0, 0, f(Yes, false, "")}, - {0xd3e, 0, 1, 1, f(Maybe, false, "")}, - {0xd3f, 0, 0, 0, f(Yes, false, "")}, - {0xd46, 0, 0, 0, f(Yes, true, "")}, - {0xd48, 0, 0, 0, f(Yes, false, "")}, - {0xd4a, 0, 0, 1, f(Yes, false, "ൊ")}, - {0xd4b, 0, 0, 1, f(Yes, false, "ോ")}, - {0xd4c, 0, 0, 1, f(Yes, false, "ൌ")}, - {0xd4d, 9, 1, 1, f(Yes, false, "")}, - {0xd4e, 0, 0, 0, f(Yes, false, "")}, - {0xd57, 0, 1, 1, f(Maybe, false, "")}, - {0xd58, 0, 0, 0, f(Yes, false, "")}, - {0xdca, 9, 1, 1, f(Maybe, false, "")}, - {0xdcb, 0, 0, 0, f(Yes, false, "")}, - {0xdcf, 0, 1, 1, f(Maybe, false, "")}, - {0xdd0, 0, 0, 0, f(Yes, false, "")}, - {0xdd9, 0, 0, 0, f(Yes, true, "")}, - {0xdda, 0, 0, 1, f(Yes, false, "ේ")}, - {0xddb, 0, 0, 0, f(Yes, false, "")}, - {0xddc, 0, 0, 1, f(Yes, true, "ො")}, - {0xddd, 0, 0, 2, f(Yes, false, "ෝ")}, - {0xdde, 0, 0, 1, f(Yes, false, "ෞ")}, - {0xddf, 0, 1, 1, f(Maybe, false, "")}, - {0xde0, 0, 0, 0, f(Yes, false, "")}, - {0xe33, 0, 0, 0, g(Yes, No, false, false, "", "ํา")}, - {0xe34, 0, 0, 0, f(Yes, false, "")}, - {0xe38, 103, 1, 1, f(Yes, false, "")}, - {0xe3a, 9, 1, 1, f(Yes, false, "")}, - {0xe3b, 0, 0, 0, f(Yes, false, "")}, - {0xe48, 107, 1, 1, f(Yes, false, "")}, - {0xe4c, 0, 0, 0, f(Yes, false, "")}, - {0xeb3, 0, 0, 0, g(Yes, No, false, false, "", "ໍາ")}, - {0xeb4, 0, 0, 0, f(Yes, false, "")}, - {0xeb8, 118, 1, 1, f(Yes, false, "")}, - {0xeba, 0, 0, 0, f(Yes, false, "")}, - {0xec8, 122, 1, 1, f(Yes, false, "")}, - {0xecc, 0, 0, 0, f(Yes, false, "")}, - {0xedc, 0, 0, 0, g(Yes, No, false, false, "", "ຫນ")}, - {0xedd, 0, 0, 0, g(Yes, No, false, false, "", "ຫມ")}, - {0xede, 0, 0, 0, f(Yes, false, "")}, - {0xf0c, 0, 0, 0, g(Yes, No, false, false, "", "་")}, - {0xf0d, 0, 0, 0, f(Yes, false, "")}, - {0xf18, 220, 1, 1, f(Yes, false, "")}, - {0xf1a, 0, 0, 0, f(Yes, false, "")}, - {0xf35, 220, 1, 1, f(Yes, false, "")}, - {0xf36, 0, 0, 0, f(Yes, false, "")}, - {0xf37, 220, 1, 1, f(Yes, false, "")}, - {0xf38, 0, 0, 0, f(Yes, false, "")}, - {0xf39, 216, 1, 1, f(Yes, false, "")}, - {0xf3a, 0, 0, 0, f(Yes, false, "")}, - {0xf43, 0, 0, 0, f(No, false, "གྷ")}, - {0xf44, 0, 0, 0, f(Yes, false, "")}, - {0xf4d, 0, 0, 0, f(No, false, "ཌྷ")}, - {0xf4e, 0, 0, 0, f(Yes, false, "")}, - {0xf52, 0, 0, 0, f(No, false, "དྷ")}, - {0xf53, 0, 0, 0, f(Yes, false, "")}, - {0xf57, 0, 0, 0, f(No, false, "བྷ")}, - {0xf58, 0, 0, 0, f(Yes, false, "")}, - {0xf5c, 0, 0, 0, f(No, false, "ཛྷ")}, - {0xf5d, 0, 0, 0, f(Yes, false, "")}, - {0xf69, 0, 0, 0, f(No, false, "ཀྵ")}, - {0xf6a, 0, 0, 0, f(Yes, false, "")}, - {0xf71, 129, 1, 1, f(Yes, false, "")}, - {0xf72, 130, 1, 1, f(Yes, false, "")}, - {0xf73, 0, 2, 2, f(No, false, "ཱི")}, - {0xf74, 132, 1, 1, f(Yes, false, "")}, - {0xf75, 0, 2, 2, f(No, false, "ཱུ")}, - {0xf76, 0, 0, 1, f(No, false, "ྲྀ")}, - {0xf77, 0, 0, 2, g(Yes, No, false, false, "", "ྲཱྀ")}, - {0xf78, 0, 0, 1, f(No, false, "ླྀ")}, - {0xf79, 0, 0, 2, g(Yes, No, false, false, "", "ླཱྀ")}, - {0xf7a, 130, 1, 1, f(Yes, false, "")}, - {0xf7e, 0, 0, 0, f(Yes, false, "")}, - {0xf80, 130, 1, 1, f(Yes, false, "")}, - {0xf81, 0, 2, 2, f(No, false, "ཱྀ")}, - {0xf82, 230, 1, 1, f(Yes, false, "")}, - {0xf84, 9, 1, 1, f(Yes, false, "")}, - {0xf85, 0, 0, 0, f(Yes, false, "")}, - {0xf86, 230, 1, 1, f(Yes, false, "")}, - {0xf88, 0, 0, 0, f(Yes, false, "")}, - {0xf93, 0, 0, 0, f(No, false, "ྒྷ")}, - {0xf94, 0, 0, 0, f(Yes, false, "")}, - {0xf9d, 0, 0, 0, f(No, false, "ྜྷ")}, - {0xf9e, 0, 0, 0, f(Yes, false, "")}, - {0xfa2, 0, 0, 0, f(No, false, "ྡྷ")}, - {0xfa3, 0, 0, 0, f(Yes, false, "")}, - {0xfa7, 0, 0, 0, f(No, false, "ྦྷ")}, - {0xfa8, 0, 0, 0, f(Yes, false, "")}, - {0xfac, 0, 0, 0, f(No, false, "ྫྷ")}, - {0xfad, 0, 0, 0, f(Yes, false, "")}, - {0xfb9, 0, 0, 0, f(No, false, "ྐྵ")}, - {0xfba, 0, 0, 0, f(Yes, false, "")}, - {0xfc6, 220, 1, 1, f(Yes, false, "")}, - {0xfc7, 0, 0, 0, f(Yes, false, "")}, - {0x1025, 0, 0, 0, f(Yes, true, "")}, - {0x1026, 0, 0, 1, f(Yes, false, "ဦ")}, - {0x1027, 0, 0, 0, f(Yes, false, "")}, - {0x102e, 0, 1, 1, f(Maybe, false, "")}, - {0x102f, 0, 0, 0, f(Yes, false, "")}, - {0x1037, 7, 1, 1, f(Yes, false, "")}, - {0x1038, 0, 0, 0, f(Yes, false, "")}, - {0x1039, 9, 1, 1, f(Yes, false, "")}, - {0x103b, 0, 0, 0, f(Yes, false, "")}, - {0x108d, 220, 1, 1, f(Yes, false, "")}, - {0x108e, 0, 0, 0, f(Yes, false, "")}, - {0x10fc, 0, 0, 0, g(Yes, No, false, false, "", "ნ")}, - {0x10fd, 0, 0, 0, f(Yes, false, "")}, - {0x1100, 0, 0, 0, f(Yes, true, "")}, - {0x1113, 0, 0, 0, f(Yes, false, "")}, - {0x1161, 0, 1, 1, f(Maybe, true, "")}, - {0x1176, 0, 0, 0, f(Yes, false, "")}, - {0x11a8, 0, 1, 1, f(Maybe, false, "")}, - {0x11c3, 0, 0, 0, f(Yes, false, "")}, - {0x135d, 230, 1, 1, f(Yes, false, "")}, - {0x1360, 0, 0, 0, f(Yes, false, "")}, - {0x1714, 9, 1, 1, f(Yes, false, "")}, - {0x1715, 0, 0, 0, f(Yes, false, "")}, - {0x1734, 9, 1, 1, f(Yes, false, "")}, - {0x1735, 0, 0, 0, f(Yes, false, "")}, - {0x17d2, 9, 1, 1, f(Yes, false, "")}, - {0x17d3, 0, 0, 0, f(Yes, false, "")}, - {0x17dd, 230, 1, 1, f(Yes, false, "")}, - {0x17de, 0, 0, 0, f(Yes, false, "")}, - {0x18a9, 228, 1, 1, f(Yes, false, "")}, - {0x18aa, 0, 0, 0, f(Yes, false, "")}, - {0x1939, 222, 1, 1, f(Yes, false, "")}, - {0x193a, 230, 1, 1, f(Yes, false, "")}, - {0x193b, 220, 1, 1, f(Yes, false, "")}, - {0x193c, 0, 0, 0, f(Yes, false, "")}, - {0x1a17, 230, 1, 1, f(Yes, false, "")}, - {0x1a18, 220, 1, 1, f(Yes, false, "")}, - {0x1a19, 0, 0, 0, f(Yes, false, "")}, - {0x1a60, 9, 1, 1, f(Yes, false, "")}, - {0x1a61, 0, 0, 0, f(Yes, false, "")}, - {0x1a75, 230, 1, 1, f(Yes, false, "")}, - {0x1a7d, 0, 0, 0, f(Yes, false, "")}, - {0x1a7f, 220, 1, 1, f(Yes, false, "")}, - {0x1a80, 0, 0, 0, f(Yes, false, "")}, - {0x1ab0, 230, 1, 1, f(Yes, false, "")}, - {0x1ab5, 220, 1, 1, f(Yes, false, "")}, - {0x1abb, 230, 1, 1, f(Yes, false, "")}, - {0x1abd, 220, 1, 1, f(Yes, false, "")}, - {0x1abe, 0, 0, 0, f(Yes, false, "")}, - {0x1b05, 0, 0, 0, f(Yes, true, "")}, - {0x1b06, 0, 0, 1, f(Yes, false, "ᬆ")}, - {0x1b07, 0, 0, 0, f(Yes, true, "")}, - {0x1b08, 0, 0, 1, f(Yes, false, "ᬈ")}, - {0x1b09, 0, 0, 0, f(Yes, true, "")}, - {0x1b0a, 0, 0, 1, f(Yes, false, "ᬊ")}, - {0x1b0b, 0, 0, 0, f(Yes, true, "")}, - {0x1b0c, 0, 0, 1, f(Yes, false, "ᬌ")}, - {0x1b0d, 0, 0, 0, f(Yes, true, "")}, - {0x1b0e, 0, 0, 1, f(Yes, false, "ᬎ")}, - {0x1b0f, 0, 0, 0, f(Yes, false, "")}, - {0x1b11, 0, 0, 0, f(Yes, true, "")}, - {0x1b12, 0, 0, 1, f(Yes, false, "ᬒ")}, - {0x1b13, 0, 0, 0, f(Yes, false, "")}, - {0x1b34, 7, 1, 1, f(Yes, false, "")}, - {0x1b35, 0, 1, 1, f(Maybe, false, "")}, - {0x1b36, 0, 0, 0, f(Yes, false, "")}, - {0x1b3a, 0, 0, 0, f(Yes, true, "")}, - {0x1b3b, 0, 0, 1, f(Yes, false, "ᬻ")}, - {0x1b3c, 0, 0, 0, f(Yes, true, "")}, - {0x1b3d, 0, 0, 1, f(Yes, false, "ᬽ")}, - {0x1b3e, 0, 0, 0, f(Yes, true, "")}, - {0x1b40, 0, 0, 1, f(Yes, false, "ᭀ")}, - {0x1b41, 0, 0, 1, f(Yes, false, "ᭁ")}, - {0x1b42, 0, 0, 0, f(Yes, true, "")}, - {0x1b43, 0, 0, 1, f(Yes, false, "ᭃ")}, - {0x1b44, 9, 1, 1, f(Yes, false, "")}, - {0x1b45, 0, 0, 0, f(Yes, false, "")}, - {0x1b6b, 230, 1, 1, f(Yes, false, "")}, - {0x1b6c, 220, 1, 1, f(Yes, false, "")}, - {0x1b6d, 230, 1, 1, f(Yes, false, "")}, - {0x1b74, 0, 0, 0, f(Yes, false, "")}, - {0x1baa, 9, 1, 1, f(Yes, false, "")}, - {0x1bac, 0, 0, 0, f(Yes, false, "")}, - {0x1be6, 7, 1, 1, f(Yes, false, "")}, - {0x1be7, 0, 0, 0, f(Yes, false, "")}, - {0x1bf2, 9, 1, 1, f(Yes, false, "")}, - {0x1bf4, 0, 0, 0, f(Yes, false, "")}, - {0x1c37, 7, 1, 1, f(Yes, false, "")}, - {0x1c38, 0, 0, 0, f(Yes, false, "")}, - {0x1cd0, 230, 1, 1, f(Yes, false, "")}, - {0x1cd3, 0, 0, 0, f(Yes, false, "")}, - {0x1cd4, 1, 1, 1, f(Yes, false, "")}, - {0x1cd5, 220, 1, 1, f(Yes, false, "")}, - {0x1cda, 230, 1, 1, f(Yes, false, "")}, - {0x1cdc, 220, 1, 1, f(Yes, false, "")}, - {0x1ce0, 230, 1, 1, f(Yes, false, "")}, - {0x1ce1, 0, 0, 0, f(Yes, false, "")}, - {0x1ce2, 1, 1, 1, f(Yes, false, "")}, - {0x1ce9, 0, 0, 0, f(Yes, false, "")}, - {0x1ced, 220, 1, 1, f(Yes, false, "")}, - {0x1cee, 0, 0, 0, f(Yes, false, "")}, - {0x1cf4, 230, 1, 1, f(Yes, false, "")}, - {0x1cf5, 0, 0, 0, f(Yes, false, "")}, - {0x1cf8, 230, 1, 1, f(Yes, false, "")}, - {0x1cfa, 0, 0, 0, f(Yes, false, "")}, - {0x1d2c, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0x1d2d, 0, 0, 0, g(Yes, No, false, false, "", "Æ")}, - {0x1d2e, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0x1d2f, 0, 0, 0, f(Yes, false, "")}, - {0x1d30, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x1d31, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0x1d32, 0, 0, 0, g(Yes, No, false, false, "", "Ǝ")}, - {0x1d33, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0x1d34, 0, 0, 0, g(Yes, No, false, false, "", "H")}, - {0x1d35, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0x1d36, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0x1d37, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0x1d38, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x1d39, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x1d3a, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0x1d3b, 0, 0, 0, f(Yes, false, "")}, - {0x1d3c, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0x1d3d, 0, 0, 0, g(Yes, No, false, false, "", "Ȣ")}, - {0x1d3e, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0x1d3f, 0, 0, 0, g(Yes, No, false, false, "", "R")}, - {0x1d40, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0x1d41, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0x1d42, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0x1d43, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0x1d44, 0, 0, 0, g(Yes, No, false, false, "", "ɐ")}, - {0x1d45, 0, 0, 0, g(Yes, No, false, false, "", "ɑ")}, - {0x1d46, 0, 0, 0, g(Yes, No, false, false, "", "ᴂ")}, - {0x1d47, 0, 0, 0, g(Yes, No, false, false, "", "b")}, - {0x1d48, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x1d49, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x1d4a, 0, 0, 0, g(Yes, No, false, false, "", "ə")}, - {0x1d4b, 0, 0, 0, g(Yes, No, false, false, "", "ɛ")}, - {0x1d4c, 0, 0, 0, g(Yes, No, false, false, "", "ɜ")}, - {0x1d4d, 0, 0, 0, g(Yes, No, false, false, "", "g")}, - {0x1d4e, 0, 0, 0, f(Yes, false, "")}, - {0x1d4f, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0x1d50, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x1d51, 0, 0, 0, g(Yes, No, false, false, "", "ŋ")}, - {0x1d52, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0x1d53, 0, 0, 0, g(Yes, No, false, false, "", "ɔ")}, - {0x1d54, 0, 0, 0, g(Yes, No, false, false, "", "ᴖ")}, - {0x1d55, 0, 0, 0, g(Yes, No, false, false, "", "ᴗ")}, - {0x1d56, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0x1d57, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0x1d58, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0x1d59, 0, 0, 0, g(Yes, No, false, false, "", "ᴝ")}, - {0x1d5a, 0, 0, 0, g(Yes, No, false, false, "", "ɯ")}, - {0x1d5b, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x1d5c, 0, 0, 0, g(Yes, No, false, false, "", "ᴥ")}, - {0x1d5d, 0, 0, 0, g(Yes, No, false, false, "", "β")}, - {0x1d5e, 0, 0, 0, g(Yes, No, false, false, "", "γ")}, - {0x1d5f, 0, 0, 0, g(Yes, No, false, false, "", "δ")}, - {0x1d60, 0, 0, 0, g(Yes, No, false, false, "", "φ")}, - {0x1d61, 0, 0, 0, g(Yes, No, false, false, "", "χ")}, - {0x1d62, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x1d63, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0x1d64, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0x1d65, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x1d66, 0, 0, 0, g(Yes, No, false, false, "", "β")}, - {0x1d67, 0, 0, 0, g(Yes, No, false, false, "", "γ")}, - {0x1d68, 0, 0, 0, g(Yes, No, false, false, "", "ρ")}, - {0x1d69, 0, 0, 0, g(Yes, No, false, false, "", "φ")}, - {0x1d6a, 0, 0, 0, g(Yes, No, false, false, "", "χ")}, - {0x1d6b, 0, 0, 0, f(Yes, false, "")}, - {0x1d78, 0, 0, 0, g(Yes, No, false, false, "", "н")}, - {0x1d79, 0, 0, 0, f(Yes, false, "")}, - {0x1d9b, 0, 0, 0, g(Yes, No, false, false, "", "ɒ")}, - {0x1d9c, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0x1d9d, 0, 0, 0, g(Yes, No, false, false, "", "ɕ")}, - {0x1d9e, 0, 0, 0, g(Yes, No, false, false, "", "ð")}, - {0x1d9f, 0, 0, 0, g(Yes, No, false, false, "", "ɜ")}, - {0x1da0, 0, 0, 0, g(Yes, No, false, false, "", "f")}, - {0x1da1, 0, 0, 0, g(Yes, No, false, false, "", "ɟ")}, - {0x1da2, 0, 0, 0, g(Yes, No, false, false, "", "ɡ")}, - {0x1da3, 0, 0, 0, g(Yes, No, false, false, "", "ɥ")}, - {0x1da4, 0, 0, 0, g(Yes, No, false, false, "", "ɨ")}, - {0x1da5, 0, 0, 0, g(Yes, No, false, false, "", "ɩ")}, - {0x1da6, 0, 0, 0, g(Yes, No, false, false, "", "ɪ")}, - {0x1da7, 0, 0, 0, g(Yes, No, false, false, "", "ᵻ")}, - {0x1da8, 0, 0, 0, g(Yes, No, false, false, "", "ʝ")}, - {0x1da9, 0, 0, 0, g(Yes, No, false, false, "", "ɭ")}, - {0x1daa, 0, 0, 0, g(Yes, No, false, false, "", "ᶅ")}, - {0x1dab, 0, 0, 0, g(Yes, No, false, false, "", "ʟ")}, - {0x1dac, 0, 0, 0, g(Yes, No, false, false, "", "ɱ")}, - {0x1dad, 0, 0, 0, g(Yes, No, false, false, "", "ɰ")}, - {0x1dae, 0, 0, 0, g(Yes, No, false, false, "", "ɲ")}, - {0x1daf, 0, 0, 0, g(Yes, No, false, false, "", "ɳ")}, - {0x1db0, 0, 0, 0, g(Yes, No, false, false, "", "ɴ")}, - {0x1db1, 0, 0, 0, g(Yes, No, false, false, "", "ɵ")}, - {0x1db2, 0, 0, 0, g(Yes, No, false, false, "", "ɸ")}, - {0x1db3, 0, 0, 0, g(Yes, No, false, false, "", "ʂ")}, - {0x1db4, 0, 0, 0, g(Yes, No, false, false, "", "ʃ")}, - {0x1db5, 0, 0, 0, g(Yes, No, false, false, "", "ƫ")}, - {0x1db6, 0, 0, 0, g(Yes, No, false, false, "", "ʉ")}, - {0x1db7, 0, 0, 0, g(Yes, No, false, false, "", "ʊ")}, - {0x1db8, 0, 0, 0, g(Yes, No, false, false, "", "ᴜ")}, - {0x1db9, 0, 0, 0, g(Yes, No, false, false, "", "ʋ")}, - {0x1dba, 0, 0, 0, g(Yes, No, false, false, "", "ʌ")}, - {0x1dbb, 0, 0, 0, g(Yes, No, false, false, "", "z")}, - {0x1dbc, 0, 0, 0, g(Yes, No, false, false, "", "ʐ")}, - {0x1dbd, 0, 0, 0, g(Yes, No, false, false, "", "ʑ")}, - {0x1dbe, 0, 0, 0, g(Yes, No, false, false, "", "ʒ")}, - {0x1dbf, 0, 0, 0, g(Yes, No, false, false, "", "θ")}, - {0x1dc0, 230, 1, 1, f(Yes, false, "")}, - {0x1dc2, 220, 1, 1, f(Yes, false, "")}, - {0x1dc3, 230, 1, 1, f(Yes, false, "")}, - {0x1dca, 220, 1, 1, f(Yes, false, "")}, - {0x1dcb, 230, 1, 1, f(Yes, false, "")}, - {0x1dcd, 234, 1, 1, f(Yes, false, "")}, - {0x1dce, 214, 1, 1, f(Yes, false, "")}, - {0x1dcf, 220, 1, 1, f(Yes, false, "")}, - {0x1dd0, 202, 1, 1, f(Yes, false, "")}, - {0x1dd1, 230, 1, 1, f(Yes, false, "")}, - {0x1df6, 0, 0, 0, f(Yes, false, "")}, - {0x1dfb, 230, 1, 1, f(Yes, false, "")}, - {0x1dfc, 233, 1, 1, f(Yes, false, "")}, - {0x1dfd, 220, 1, 1, f(Yes, false, "")}, - {0x1dfe, 230, 1, 1, f(Yes, false, "")}, - {0x1dff, 220, 1, 1, f(Yes, false, "")}, - {0x1e00, 0, 0, 1, f(Yes, false, "Ḁ")}, - {0x1e01, 0, 0, 1, f(Yes, false, "ḁ")}, - {0x1e02, 0, 0, 1, f(Yes, false, "Ḃ")}, - {0x1e03, 0, 0, 1, f(Yes, false, "ḃ")}, - {0x1e04, 0, 0, 1, f(Yes, false, "Ḅ")}, - {0x1e05, 0, 0, 1, f(Yes, false, "ḅ")}, - {0x1e06, 0, 0, 1, f(Yes, false, "Ḇ")}, - {0x1e07, 0, 0, 1, f(Yes, false, "ḇ")}, - {0x1e08, 0, 0, 2, f(Yes, false, "Ḉ")}, - {0x1e09, 0, 0, 2, f(Yes, false, "ḉ")}, - {0x1e0a, 0, 0, 1, f(Yes, false, "Ḋ")}, - {0x1e0b, 0, 0, 1, f(Yes, false, "ḋ")}, - {0x1e0c, 0, 0, 1, f(Yes, false, "Ḍ")}, - {0x1e0d, 0, 0, 1, f(Yes, false, "ḍ")}, - {0x1e0e, 0, 0, 1, f(Yes, false, "Ḏ")}, - {0x1e0f, 0, 0, 1, f(Yes, false, "ḏ")}, - {0x1e10, 0, 0, 1, f(Yes, false, "Ḑ")}, - {0x1e11, 0, 0, 1, f(Yes, false, "ḑ")}, - {0x1e12, 0, 0, 1, f(Yes, false, "Ḓ")}, - {0x1e13, 0, 0, 1, f(Yes, false, "ḓ")}, - {0x1e14, 0, 0, 2, f(Yes, false, "Ḕ")}, - {0x1e15, 0, 0, 2, f(Yes, false, "ḕ")}, - {0x1e16, 0, 0, 2, f(Yes, false, "Ḗ")}, - {0x1e17, 0, 0, 2, f(Yes, false, "ḗ")}, - {0x1e18, 0, 0, 1, f(Yes, false, "Ḙ")}, - {0x1e19, 0, 0, 1, f(Yes, false, "ḙ")}, - {0x1e1a, 0, 0, 1, f(Yes, false, "Ḛ")}, - {0x1e1b, 0, 0, 1, f(Yes, false, "ḛ")}, - {0x1e1c, 0, 0, 2, f(Yes, false, "Ḝ")}, - {0x1e1d, 0, 0, 2, f(Yes, false, "ḝ")}, - {0x1e1e, 0, 0, 1, f(Yes, false, "Ḟ")}, - {0x1e1f, 0, 0, 1, f(Yes, false, "ḟ")}, - {0x1e20, 0, 0, 1, f(Yes, false, "Ḡ")}, - {0x1e21, 0, 0, 1, f(Yes, false, "ḡ")}, - {0x1e22, 0, 0, 1, f(Yes, false, "Ḣ")}, - {0x1e23, 0, 0, 1, f(Yes, false, "ḣ")}, - {0x1e24, 0, 0, 1, f(Yes, false, "Ḥ")}, - {0x1e25, 0, 0, 1, f(Yes, false, "ḥ")}, - {0x1e26, 0, 0, 1, f(Yes, false, "Ḧ")}, - {0x1e27, 0, 0, 1, f(Yes, false, "ḧ")}, - {0x1e28, 0, 0, 1, f(Yes, false, "Ḩ")}, - {0x1e29, 0, 0, 1, f(Yes, false, "ḩ")}, - {0x1e2a, 0, 0, 1, f(Yes, false, "Ḫ")}, - {0x1e2b, 0, 0, 1, f(Yes, false, "ḫ")}, - {0x1e2c, 0, 0, 1, f(Yes, false, "Ḭ")}, - {0x1e2d, 0, 0, 1, f(Yes, false, "ḭ")}, - {0x1e2e, 0, 0, 2, f(Yes, false, "Ḯ")}, - {0x1e2f, 0, 0, 2, f(Yes, false, "ḯ")}, - {0x1e30, 0, 0, 1, f(Yes, false, "Ḱ")}, - {0x1e31, 0, 0, 1, f(Yes, false, "ḱ")}, - {0x1e32, 0, 0, 1, f(Yes, false, "Ḳ")}, - {0x1e33, 0, 0, 1, f(Yes, false, "ḳ")}, - {0x1e34, 0, 0, 1, f(Yes, false, "Ḵ")}, - {0x1e35, 0, 0, 1, f(Yes, false, "ḵ")}, - {0x1e36, 0, 0, 1, f(Yes, true, "Ḷ")}, - {0x1e37, 0, 0, 1, f(Yes, true, "ḷ")}, - {0x1e38, 0, 0, 2, f(Yes, false, "Ḹ")}, - {0x1e39, 0, 0, 2, f(Yes, false, "ḹ")}, - {0x1e3a, 0, 0, 1, f(Yes, false, "Ḻ")}, - {0x1e3b, 0, 0, 1, f(Yes, false, "ḻ")}, - {0x1e3c, 0, 0, 1, f(Yes, false, "Ḽ")}, - {0x1e3d, 0, 0, 1, f(Yes, false, "ḽ")}, - {0x1e3e, 0, 0, 1, f(Yes, false, "Ḿ")}, - {0x1e3f, 0, 0, 1, f(Yes, false, "ḿ")}, - {0x1e40, 0, 0, 1, f(Yes, false, "Ṁ")}, - {0x1e41, 0, 0, 1, f(Yes, false, "ṁ")}, - {0x1e42, 0, 0, 1, f(Yes, false, "Ṃ")}, - {0x1e43, 0, 0, 1, f(Yes, false, "ṃ")}, - {0x1e44, 0, 0, 1, f(Yes, false, "Ṅ")}, - {0x1e45, 0, 0, 1, f(Yes, false, "ṅ")}, - {0x1e46, 0, 0, 1, f(Yes, false, "Ṇ")}, - {0x1e47, 0, 0, 1, f(Yes, false, "ṇ")}, - {0x1e48, 0, 0, 1, f(Yes, false, "Ṉ")}, - {0x1e49, 0, 0, 1, f(Yes, false, "ṉ")}, - {0x1e4a, 0, 0, 1, f(Yes, false, "Ṋ")}, - {0x1e4b, 0, 0, 1, f(Yes, false, "ṋ")}, - {0x1e4c, 0, 0, 2, f(Yes, false, "Ṍ")}, - {0x1e4d, 0, 0, 2, f(Yes, false, "ṍ")}, - {0x1e4e, 0, 0, 2, f(Yes, false, "Ṏ")}, - {0x1e4f, 0, 0, 2, f(Yes, false, "ṏ")}, - {0x1e50, 0, 0, 2, f(Yes, false, "Ṑ")}, - {0x1e51, 0, 0, 2, f(Yes, false, "ṑ")}, - {0x1e52, 0, 0, 2, f(Yes, false, "Ṓ")}, - {0x1e53, 0, 0, 2, f(Yes, false, "ṓ")}, - {0x1e54, 0, 0, 1, f(Yes, false, "Ṕ")}, - {0x1e55, 0, 0, 1, f(Yes, false, "ṕ")}, - {0x1e56, 0, 0, 1, f(Yes, false, "Ṗ")}, - {0x1e57, 0, 0, 1, f(Yes, false, "ṗ")}, - {0x1e58, 0, 0, 1, f(Yes, false, "Ṙ")}, - {0x1e59, 0, 0, 1, f(Yes, false, "ṙ")}, - {0x1e5a, 0, 0, 1, f(Yes, true, "Ṛ")}, - {0x1e5b, 0, 0, 1, f(Yes, true, "ṛ")}, - {0x1e5c, 0, 0, 2, f(Yes, false, "Ṝ")}, - {0x1e5d, 0, 0, 2, f(Yes, false, "ṝ")}, - {0x1e5e, 0, 0, 1, f(Yes, false, "Ṟ")}, - {0x1e5f, 0, 0, 1, f(Yes, false, "ṟ")}, - {0x1e60, 0, 0, 1, f(Yes, false, "Ṡ")}, - {0x1e61, 0, 0, 1, f(Yes, false, "ṡ")}, - {0x1e62, 0, 0, 1, f(Yes, true, "Ṣ")}, - {0x1e63, 0, 0, 1, f(Yes, true, "ṣ")}, - {0x1e64, 0, 0, 2, f(Yes, false, "Ṥ")}, - {0x1e65, 0, 0, 2, f(Yes, false, "ṥ")}, - {0x1e66, 0, 0, 2, f(Yes, false, "Ṧ")}, - {0x1e67, 0, 0, 2, f(Yes, false, "ṧ")}, - {0x1e68, 0, 0, 2, f(Yes, false, "Ṩ")}, - {0x1e69, 0, 0, 2, f(Yes, false, "ṩ")}, - {0x1e6a, 0, 0, 1, f(Yes, false, "Ṫ")}, - {0x1e6b, 0, 0, 1, f(Yes, false, "ṫ")}, - {0x1e6c, 0, 0, 1, f(Yes, false, "Ṭ")}, - {0x1e6d, 0, 0, 1, f(Yes, false, "ṭ")}, - {0x1e6e, 0, 0, 1, f(Yes, false, "Ṯ")}, - {0x1e6f, 0, 0, 1, f(Yes, false, "ṯ")}, - {0x1e70, 0, 0, 1, f(Yes, false, "Ṱ")}, - {0x1e71, 0, 0, 1, f(Yes, false, "ṱ")}, - {0x1e72, 0, 0, 1, f(Yes, false, "Ṳ")}, - {0x1e73, 0, 0, 1, f(Yes, false, "ṳ")}, - {0x1e74, 0, 0, 1, f(Yes, false, "Ṵ")}, - {0x1e75, 0, 0, 1, f(Yes, false, "ṵ")}, - {0x1e76, 0, 0, 1, f(Yes, false, "Ṷ")}, - {0x1e77, 0, 0, 1, f(Yes, false, "ṷ")}, - {0x1e78, 0, 0, 2, f(Yes, false, "Ṹ")}, - {0x1e79, 0, 0, 2, f(Yes, false, "ṹ")}, - {0x1e7a, 0, 0, 2, f(Yes, false, "Ṻ")}, - {0x1e7b, 0, 0, 2, f(Yes, false, "ṻ")}, - {0x1e7c, 0, 0, 1, f(Yes, false, "Ṽ")}, - {0x1e7d, 0, 0, 1, f(Yes, false, "ṽ")}, - {0x1e7e, 0, 0, 1, f(Yes, false, "Ṿ")}, - {0x1e7f, 0, 0, 1, f(Yes, false, "ṿ")}, - {0x1e80, 0, 0, 1, f(Yes, false, "Ẁ")}, - {0x1e81, 0, 0, 1, f(Yes, false, "ẁ")}, - {0x1e82, 0, 0, 1, f(Yes, false, "Ẃ")}, - {0x1e83, 0, 0, 1, f(Yes, false, "ẃ")}, - {0x1e84, 0, 0, 1, f(Yes, false, "Ẅ")}, - {0x1e85, 0, 0, 1, f(Yes, false, "ẅ")}, - {0x1e86, 0, 0, 1, f(Yes, false, "Ẇ")}, - {0x1e87, 0, 0, 1, f(Yes, false, "ẇ")}, - {0x1e88, 0, 0, 1, f(Yes, false, "Ẉ")}, - {0x1e89, 0, 0, 1, f(Yes, false, "ẉ")}, - {0x1e8a, 0, 0, 1, f(Yes, false, "Ẋ")}, - {0x1e8b, 0, 0, 1, f(Yes, false, "ẋ")}, - {0x1e8c, 0, 0, 1, f(Yes, false, "Ẍ")}, - {0x1e8d, 0, 0, 1, f(Yes, false, "ẍ")}, - {0x1e8e, 0, 0, 1, f(Yes, false, "Ẏ")}, - {0x1e8f, 0, 0, 1, f(Yes, false, "ẏ")}, - {0x1e90, 0, 0, 1, f(Yes, false, "Ẑ")}, - {0x1e91, 0, 0, 1, f(Yes, false, "ẑ")}, - {0x1e92, 0, 0, 1, f(Yes, false, "Ẓ")}, - {0x1e93, 0, 0, 1, f(Yes, false, "ẓ")}, - {0x1e94, 0, 0, 1, f(Yes, false, "Ẕ")}, - {0x1e95, 0, 0, 1, f(Yes, false, "ẕ")}, - {0x1e96, 0, 0, 1, f(Yes, false, "ẖ")}, - {0x1e97, 0, 0, 1, f(Yes, false, "ẗ")}, - {0x1e98, 0, 0, 1, f(Yes, false, "ẘ")}, - {0x1e99, 0, 0, 1, f(Yes, false, "ẙ")}, - {0x1e9a, 0, 0, 0, g(Yes, No, false, false, "", "aʾ")}, - {0x1e9b, 0, 0, 1, g(Yes, No, false, false, "ẛ", "ṡ")}, - {0x1e9c, 0, 0, 0, f(Yes, false, "")}, - {0x1ea0, 0, 0, 1, f(Yes, true, "Ạ")}, - {0x1ea1, 0, 0, 1, f(Yes, true, "ạ")}, - {0x1ea2, 0, 0, 1, f(Yes, false, "Ả")}, - {0x1ea3, 0, 0, 1, f(Yes, false, "ả")}, - {0x1ea4, 0, 0, 2, f(Yes, false, "Ấ")}, - {0x1ea5, 0, 0, 2, f(Yes, false, "ấ")}, - {0x1ea6, 0, 0, 2, f(Yes, false, "Ầ")}, - {0x1ea7, 0, 0, 2, f(Yes, false, "ầ")}, - {0x1ea8, 0, 0, 2, f(Yes, false, "Ẩ")}, - {0x1ea9, 0, 0, 2, f(Yes, false, "ẩ")}, - {0x1eaa, 0, 0, 2, f(Yes, false, "Ẫ")}, - {0x1eab, 0, 0, 2, f(Yes, false, "ẫ")}, - {0x1eac, 0, 0, 2, f(Yes, false, "Ậ")}, - {0x1ead, 0, 0, 2, f(Yes, false, "ậ")}, - {0x1eae, 0, 0, 2, f(Yes, false, "Ắ")}, - {0x1eaf, 0, 0, 2, f(Yes, false, "ắ")}, - {0x1eb0, 0, 0, 2, f(Yes, false, "Ằ")}, - {0x1eb1, 0, 0, 2, f(Yes, false, "ằ")}, - {0x1eb2, 0, 0, 2, f(Yes, false, "Ẳ")}, - {0x1eb3, 0, 0, 2, f(Yes, false, "ẳ")}, - {0x1eb4, 0, 0, 2, f(Yes, false, "Ẵ")}, - {0x1eb5, 0, 0, 2, f(Yes, false, "ẵ")}, - {0x1eb6, 0, 0, 2, f(Yes, false, "Ặ")}, - {0x1eb7, 0, 0, 2, f(Yes, false, "ặ")}, - {0x1eb8, 0, 0, 1, f(Yes, true, "Ẹ")}, - {0x1eb9, 0, 0, 1, f(Yes, true, "ẹ")}, - {0x1eba, 0, 0, 1, f(Yes, false, "Ẻ")}, - {0x1ebb, 0, 0, 1, f(Yes, false, "ẻ")}, - {0x1ebc, 0, 0, 1, f(Yes, false, "Ẽ")}, - {0x1ebd, 0, 0, 1, f(Yes, false, "ẽ")}, - {0x1ebe, 0, 0, 2, f(Yes, false, "Ế")}, - {0x1ebf, 0, 0, 2, f(Yes, false, "ế")}, - {0x1ec0, 0, 0, 2, f(Yes, false, "Ề")}, - {0x1ec1, 0, 0, 2, f(Yes, false, "ề")}, - {0x1ec2, 0, 0, 2, f(Yes, false, "Ể")}, - {0x1ec3, 0, 0, 2, f(Yes, false, "ể")}, - {0x1ec4, 0, 0, 2, f(Yes, false, "Ễ")}, - {0x1ec5, 0, 0, 2, f(Yes, false, "ễ")}, - {0x1ec6, 0, 0, 2, f(Yes, false, "Ệ")}, - {0x1ec7, 0, 0, 2, f(Yes, false, "ệ")}, - {0x1ec8, 0, 0, 1, f(Yes, false, "Ỉ")}, - {0x1ec9, 0, 0, 1, f(Yes, false, "ỉ")}, - {0x1eca, 0, 0, 1, f(Yes, false, "Ị")}, - {0x1ecb, 0, 0, 1, f(Yes, false, "ị")}, - {0x1ecc, 0, 0, 1, f(Yes, true, "Ọ")}, - {0x1ecd, 0, 0, 1, f(Yes, true, "ọ")}, - {0x1ece, 0, 0, 1, f(Yes, false, "Ỏ")}, - {0x1ecf, 0, 0, 1, f(Yes, false, "ỏ")}, - {0x1ed0, 0, 0, 2, f(Yes, false, "Ố")}, - {0x1ed1, 0, 0, 2, f(Yes, false, "ố")}, - {0x1ed2, 0, 0, 2, f(Yes, false, "Ồ")}, - {0x1ed3, 0, 0, 2, f(Yes, false, "ồ")}, - {0x1ed4, 0, 0, 2, f(Yes, false, "Ổ")}, - {0x1ed5, 0, 0, 2, f(Yes, false, "ổ")}, - {0x1ed6, 0, 0, 2, f(Yes, false, "Ỗ")}, - {0x1ed7, 0, 0, 2, f(Yes, false, "ỗ")}, - {0x1ed8, 0, 0, 2, f(Yes, false, "Ộ")}, - {0x1ed9, 0, 0, 2, f(Yes, false, "ộ")}, - {0x1eda, 0, 0, 2, f(Yes, false, "Ớ")}, - {0x1edb, 0, 0, 2, f(Yes, false, "ớ")}, - {0x1edc, 0, 0, 2, f(Yes, false, "Ờ")}, - {0x1edd, 0, 0, 2, f(Yes, false, "ờ")}, - {0x1ede, 0, 0, 2, f(Yes, false, "Ở")}, - {0x1edf, 0, 0, 2, f(Yes, false, "ở")}, - {0x1ee0, 0, 0, 2, f(Yes, false, "Ỡ")}, - {0x1ee1, 0, 0, 2, f(Yes, false, "ỡ")}, - {0x1ee2, 0, 0, 2, f(Yes, false, "Ợ")}, - {0x1ee3, 0, 0, 2, f(Yes, false, "ợ")}, - {0x1ee4, 0, 0, 1, f(Yes, false, "Ụ")}, - {0x1ee5, 0, 0, 1, f(Yes, false, "ụ")}, - {0x1ee6, 0, 0, 1, f(Yes, false, "Ủ")}, - {0x1ee7, 0, 0, 1, f(Yes, false, "ủ")}, - {0x1ee8, 0, 0, 2, f(Yes, false, "Ứ")}, - {0x1ee9, 0, 0, 2, f(Yes, false, "ứ")}, - {0x1eea, 0, 0, 2, f(Yes, false, "Ừ")}, - {0x1eeb, 0, 0, 2, f(Yes, false, "ừ")}, - {0x1eec, 0, 0, 2, f(Yes, false, "Ử")}, - {0x1eed, 0, 0, 2, f(Yes, false, "ử")}, - {0x1eee, 0, 0, 2, f(Yes, false, "Ữ")}, - {0x1eef, 0, 0, 2, f(Yes, false, "ữ")}, - {0x1ef0, 0, 0, 2, f(Yes, false, "Ự")}, - {0x1ef1, 0, 0, 2, f(Yes, false, "ự")}, - {0x1ef2, 0, 0, 1, f(Yes, false, "Ỳ")}, - {0x1ef3, 0, 0, 1, f(Yes, false, "ỳ")}, - {0x1ef4, 0, 0, 1, f(Yes, false, "Ỵ")}, - {0x1ef5, 0, 0, 1, f(Yes, false, "ỵ")}, - {0x1ef6, 0, 0, 1, f(Yes, false, "Ỷ")}, - {0x1ef7, 0, 0, 1, f(Yes, false, "ỷ")}, - {0x1ef8, 0, 0, 1, f(Yes, false, "Ỹ")}, - {0x1ef9, 0, 0, 1, f(Yes, false, "ỹ")}, - {0x1efa, 0, 0, 0, f(Yes, false, "")}, - {0x1f00, 0, 0, 1, f(Yes, true, "ἀ")}, - {0x1f01, 0, 0, 1, f(Yes, true, "ἁ")}, - {0x1f02, 0, 0, 2, f(Yes, true, "ἂ")}, - {0x1f03, 0, 0, 2, f(Yes, true, "ἃ")}, - {0x1f04, 0, 0, 2, f(Yes, true, "ἄ")}, - {0x1f05, 0, 0, 2, f(Yes, true, "ἅ")}, - {0x1f06, 0, 0, 2, f(Yes, true, "ἆ")}, - {0x1f07, 0, 0, 2, f(Yes, true, "ἇ")}, - {0x1f08, 0, 0, 1, f(Yes, true, "Ἀ")}, - {0x1f09, 0, 0, 1, f(Yes, true, "Ἁ")}, - {0x1f0a, 0, 0, 2, f(Yes, true, "Ἂ")}, - {0x1f0b, 0, 0, 2, f(Yes, true, "Ἃ")}, - {0x1f0c, 0, 0, 2, f(Yes, true, "Ἄ")}, - {0x1f0d, 0, 0, 2, f(Yes, true, "Ἅ")}, - {0x1f0e, 0, 0, 2, f(Yes, true, "Ἆ")}, - {0x1f0f, 0, 0, 2, f(Yes, true, "Ἇ")}, - {0x1f10, 0, 0, 1, f(Yes, true, "ἐ")}, - {0x1f11, 0, 0, 1, f(Yes, true, "ἑ")}, - {0x1f12, 0, 0, 2, f(Yes, false, "ἒ")}, - {0x1f13, 0, 0, 2, f(Yes, false, "ἓ")}, - {0x1f14, 0, 0, 2, f(Yes, false, "ἔ")}, - {0x1f15, 0, 0, 2, f(Yes, false, "ἕ")}, - {0x1f16, 0, 0, 0, f(Yes, false, "")}, - {0x1f18, 0, 0, 1, f(Yes, true, "Ἐ")}, - {0x1f19, 0, 0, 1, f(Yes, true, "Ἑ")}, - {0x1f1a, 0, 0, 2, f(Yes, false, "Ἒ")}, - {0x1f1b, 0, 0, 2, f(Yes, false, "Ἓ")}, - {0x1f1c, 0, 0, 2, f(Yes, false, "Ἔ")}, - {0x1f1d, 0, 0, 2, f(Yes, false, "Ἕ")}, - {0x1f1e, 0, 0, 0, f(Yes, false, "")}, - {0x1f20, 0, 0, 1, f(Yes, true, "ἠ")}, - {0x1f21, 0, 0, 1, f(Yes, true, "ἡ")}, - {0x1f22, 0, 0, 2, f(Yes, true, "ἢ")}, - {0x1f23, 0, 0, 2, f(Yes, true, "ἣ")}, - {0x1f24, 0, 0, 2, f(Yes, true, "ἤ")}, - {0x1f25, 0, 0, 2, f(Yes, true, "ἥ")}, - {0x1f26, 0, 0, 2, f(Yes, true, "ἦ")}, - {0x1f27, 0, 0, 2, f(Yes, true, "ἧ")}, - {0x1f28, 0, 0, 1, f(Yes, true, "Ἠ")}, - {0x1f29, 0, 0, 1, f(Yes, true, "Ἡ")}, - {0x1f2a, 0, 0, 2, f(Yes, true, "Ἢ")}, - {0x1f2b, 0, 0, 2, f(Yes, true, "Ἣ")}, - {0x1f2c, 0, 0, 2, f(Yes, true, "Ἤ")}, - {0x1f2d, 0, 0, 2, f(Yes, true, "Ἥ")}, - {0x1f2e, 0, 0, 2, f(Yes, true, "Ἦ")}, - {0x1f2f, 0, 0, 2, f(Yes, true, "Ἧ")}, - {0x1f30, 0, 0, 1, f(Yes, true, "ἰ")}, - {0x1f31, 0, 0, 1, f(Yes, true, "ἱ")}, - {0x1f32, 0, 0, 2, f(Yes, false, "ἲ")}, - {0x1f33, 0, 0, 2, f(Yes, false, "ἳ")}, - {0x1f34, 0, 0, 2, f(Yes, false, "ἴ")}, - {0x1f35, 0, 0, 2, f(Yes, false, "ἵ")}, - {0x1f36, 0, 0, 2, f(Yes, false, "ἶ")}, - {0x1f37, 0, 0, 2, f(Yes, false, "ἷ")}, - {0x1f38, 0, 0, 1, f(Yes, true, "Ἰ")}, - {0x1f39, 0, 0, 1, f(Yes, true, "Ἱ")}, - {0x1f3a, 0, 0, 2, f(Yes, false, "Ἲ")}, - {0x1f3b, 0, 0, 2, f(Yes, false, "Ἳ")}, - {0x1f3c, 0, 0, 2, f(Yes, false, "Ἴ")}, - {0x1f3d, 0, 0, 2, f(Yes, false, "Ἵ")}, - {0x1f3e, 0, 0, 2, f(Yes, false, "Ἶ")}, - {0x1f3f, 0, 0, 2, f(Yes, false, "Ἷ")}, - {0x1f40, 0, 0, 1, f(Yes, true, "ὀ")}, - {0x1f41, 0, 0, 1, f(Yes, true, "ὁ")}, - {0x1f42, 0, 0, 2, f(Yes, false, "ὂ")}, - {0x1f43, 0, 0, 2, f(Yes, false, "ὃ")}, - {0x1f44, 0, 0, 2, f(Yes, false, "ὄ")}, - {0x1f45, 0, 0, 2, f(Yes, false, "ὅ")}, - {0x1f46, 0, 0, 0, f(Yes, false, "")}, - {0x1f48, 0, 0, 1, f(Yes, true, "Ὀ")}, - {0x1f49, 0, 0, 1, f(Yes, true, "Ὁ")}, - {0x1f4a, 0, 0, 2, f(Yes, false, "Ὂ")}, - {0x1f4b, 0, 0, 2, f(Yes, false, "Ὃ")}, - {0x1f4c, 0, 0, 2, f(Yes, false, "Ὄ")}, - {0x1f4d, 0, 0, 2, f(Yes, false, "Ὅ")}, - {0x1f4e, 0, 0, 0, f(Yes, false, "")}, - {0x1f50, 0, 0, 1, f(Yes, true, "ὐ")}, - {0x1f51, 0, 0, 1, f(Yes, true, "ὑ")}, - {0x1f52, 0, 0, 2, f(Yes, false, "ὒ")}, - {0x1f53, 0, 0, 2, f(Yes, false, "ὓ")}, - {0x1f54, 0, 0, 2, f(Yes, false, "ὔ")}, - {0x1f55, 0, 0, 2, f(Yes, false, "ὕ")}, - {0x1f56, 0, 0, 2, f(Yes, false, "ὖ")}, - {0x1f57, 0, 0, 2, f(Yes, false, "ὗ")}, - {0x1f58, 0, 0, 0, f(Yes, false, "")}, - {0x1f59, 0, 0, 1, f(Yes, true, "Ὑ")}, - {0x1f5a, 0, 0, 0, f(Yes, false, "")}, - {0x1f5b, 0, 0, 2, f(Yes, false, "Ὓ")}, - {0x1f5c, 0, 0, 0, f(Yes, false, "")}, - {0x1f5d, 0, 0, 2, f(Yes, false, "Ὕ")}, - {0x1f5e, 0, 0, 0, f(Yes, false, "")}, - {0x1f5f, 0, 0, 2, f(Yes, false, "Ὗ")}, - {0x1f60, 0, 0, 1, f(Yes, true, "ὠ")}, - {0x1f61, 0, 0, 1, f(Yes, true, "ὡ")}, - {0x1f62, 0, 0, 2, f(Yes, true, "ὢ")}, - {0x1f63, 0, 0, 2, f(Yes, true, "ὣ")}, - {0x1f64, 0, 0, 2, f(Yes, true, "ὤ")}, - {0x1f65, 0, 0, 2, f(Yes, true, "ὥ")}, - {0x1f66, 0, 0, 2, f(Yes, true, "ὦ")}, - {0x1f67, 0, 0, 2, f(Yes, true, "ὧ")}, - {0x1f68, 0, 0, 1, f(Yes, true, "Ὠ")}, - {0x1f69, 0, 0, 1, f(Yes, true, "Ὡ")}, - {0x1f6a, 0, 0, 2, f(Yes, true, "Ὢ")}, - {0x1f6b, 0, 0, 2, f(Yes, true, "Ὣ")}, - {0x1f6c, 0, 0, 2, f(Yes, true, "Ὤ")}, - {0x1f6d, 0, 0, 2, f(Yes, true, "Ὥ")}, - {0x1f6e, 0, 0, 2, f(Yes, true, "Ὦ")}, - {0x1f6f, 0, 0, 2, f(Yes, true, "Ὧ")}, - {0x1f70, 0, 0, 1, f(Yes, true, "ὰ")}, - {0x1f71, 0, 0, 1, f(No, false, "ά")}, - {0x1f72, 0, 0, 1, f(Yes, false, "ὲ")}, - {0x1f73, 0, 0, 1, f(No, false, "έ")}, - {0x1f74, 0, 0, 1, f(Yes, true, "ὴ")}, - {0x1f75, 0, 0, 1, f(No, false, "ή")}, - {0x1f76, 0, 0, 1, f(Yes, false, "ὶ")}, - {0x1f77, 0, 0, 1, f(No, false, "ί")}, - {0x1f78, 0, 0, 1, f(Yes, false, "ὸ")}, - {0x1f79, 0, 0, 1, f(No, false, "ό")}, - {0x1f7a, 0, 0, 1, f(Yes, false, "ὺ")}, - {0x1f7b, 0, 0, 1, f(No, false, "ύ")}, - {0x1f7c, 0, 0, 1, f(Yes, true, "ὼ")}, - {0x1f7d, 0, 0, 1, f(No, false, "ώ")}, - {0x1f7e, 0, 0, 0, f(Yes, false, "")}, - {0x1f80, 0, 0, 2, f(Yes, false, "ᾀ")}, - {0x1f81, 0, 0, 2, f(Yes, false, "ᾁ")}, - {0x1f82, 0, 0, 3, f(Yes, false, "ᾂ")}, - {0x1f83, 0, 0, 3, f(Yes, false, "ᾃ")}, - {0x1f84, 0, 0, 3, f(Yes, false, "ᾄ")}, - {0x1f85, 0, 0, 3, f(Yes, false, "ᾅ")}, - {0x1f86, 0, 0, 3, f(Yes, false, "ᾆ")}, - {0x1f87, 0, 0, 3, f(Yes, false, "ᾇ")}, - {0x1f88, 0, 0, 2, f(Yes, false, "ᾈ")}, - {0x1f89, 0, 0, 2, f(Yes, false, "ᾉ")}, - {0x1f8a, 0, 0, 3, f(Yes, false, "ᾊ")}, - {0x1f8b, 0, 0, 3, f(Yes, false, "ᾋ")}, - {0x1f8c, 0, 0, 3, f(Yes, false, "ᾌ")}, - {0x1f8d, 0, 0, 3, f(Yes, false, "ᾍ")}, - {0x1f8e, 0, 0, 3, f(Yes, false, "ᾎ")}, - {0x1f8f, 0, 0, 3, f(Yes, false, "ᾏ")}, - {0x1f90, 0, 0, 2, f(Yes, false, "ᾐ")}, - {0x1f91, 0, 0, 2, f(Yes, false, "ᾑ")}, - {0x1f92, 0, 0, 3, f(Yes, false, "ᾒ")}, - {0x1f93, 0, 0, 3, f(Yes, false, "ᾓ")}, - {0x1f94, 0, 0, 3, f(Yes, false, "ᾔ")}, - {0x1f95, 0, 0, 3, f(Yes, false, "ᾕ")}, - {0x1f96, 0, 0, 3, f(Yes, false, "ᾖ")}, - {0x1f97, 0, 0, 3, f(Yes, false, "ᾗ")}, - {0x1f98, 0, 0, 2, f(Yes, false, "ᾘ")}, - {0x1f99, 0, 0, 2, f(Yes, false, "ᾙ")}, - {0x1f9a, 0, 0, 3, f(Yes, false, "ᾚ")}, - {0x1f9b, 0, 0, 3, f(Yes, false, "ᾛ")}, - {0x1f9c, 0, 0, 3, f(Yes, false, "ᾜ")}, - {0x1f9d, 0, 0, 3, f(Yes, false, "ᾝ")}, - {0x1f9e, 0, 0, 3, f(Yes, false, "ᾞ")}, - {0x1f9f, 0, 0, 3, f(Yes, false, "ᾟ")}, - {0x1fa0, 0, 0, 2, f(Yes, false, "ᾠ")}, - {0x1fa1, 0, 0, 2, f(Yes, false, "ᾡ")}, - {0x1fa2, 0, 0, 3, f(Yes, false, "ᾢ")}, - {0x1fa3, 0, 0, 3, f(Yes, false, "ᾣ")}, - {0x1fa4, 0, 0, 3, f(Yes, false, "ᾤ")}, - {0x1fa5, 0, 0, 3, f(Yes, false, "ᾥ")}, - {0x1fa6, 0, 0, 3, f(Yes, false, "ᾦ")}, - {0x1fa7, 0, 0, 3, f(Yes, false, "ᾧ")}, - {0x1fa8, 0, 0, 2, f(Yes, false, "ᾨ")}, - {0x1fa9, 0, 0, 2, f(Yes, false, "ᾩ")}, - {0x1faa, 0, 0, 3, f(Yes, false, "ᾪ")}, - {0x1fab, 0, 0, 3, f(Yes, false, "ᾫ")}, - {0x1fac, 0, 0, 3, f(Yes, false, "ᾬ")}, - {0x1fad, 0, 0, 3, f(Yes, false, "ᾭ")}, - {0x1fae, 0, 0, 3, f(Yes, false, "ᾮ")}, - {0x1faf, 0, 0, 3, f(Yes, false, "ᾯ")}, - {0x1fb0, 0, 0, 1, f(Yes, false, "ᾰ")}, - {0x1fb1, 0, 0, 1, f(Yes, false, "ᾱ")}, - {0x1fb2, 0, 0, 2, f(Yes, false, "ᾲ")}, - {0x1fb3, 0, 0, 1, f(Yes, false, "ᾳ")}, - {0x1fb4, 0, 0, 2, f(Yes, false, "ᾴ")}, - {0x1fb5, 0, 0, 0, f(Yes, false, "")}, - {0x1fb6, 0, 0, 1, f(Yes, true, "ᾶ")}, - {0x1fb7, 0, 0, 2, f(Yes, false, "ᾷ")}, - {0x1fb8, 0, 0, 1, f(Yes, false, "Ᾰ")}, - {0x1fb9, 0, 0, 1, f(Yes, false, "Ᾱ")}, - {0x1fba, 0, 0, 1, f(Yes, false, "Ὰ")}, - {0x1fbb, 0, 0, 1, f(No, false, "Ά")}, - {0x1fbc, 0, 0, 1, f(Yes, false, "ᾼ")}, - {0x1fbd, 0, 0, 1, g(Yes, No, false, false, "", " ̓")}, - {0x1fbe, 0, 0, 0, f(No, false, "ι")}, - {0x1fbf, 0, 0, 1, g(Yes, No, true, false, "", " ̓")}, - {0x1fc0, 0, 0, 1, g(Yes, No, false, false, "", " ͂")}, - {0x1fc1, 0, 0, 2, g(Yes, No, false, false, "῁", " ̈͂")}, - {0x1fc2, 0, 0, 2, f(Yes, false, "ῂ")}, - {0x1fc3, 0, 0, 1, f(Yes, false, "ῃ")}, - {0x1fc4, 0, 0, 2, f(Yes, false, "ῄ")}, - {0x1fc5, 0, 0, 0, f(Yes, false, "")}, - {0x1fc6, 0, 0, 1, f(Yes, true, "ῆ")}, - {0x1fc7, 0, 0, 2, f(Yes, false, "ῇ")}, - {0x1fc8, 0, 0, 1, f(Yes, false, "Ὲ")}, - {0x1fc9, 0, 0, 1, f(No, false, "Έ")}, - {0x1fca, 0, 0, 1, f(Yes, false, "Ὴ")}, - {0x1fcb, 0, 0, 1, f(No, false, "Ή")}, - {0x1fcc, 0, 0, 1, f(Yes, false, "ῌ")}, - {0x1fcd, 0, 0, 2, g(Yes, No, false, false, "῍", " ̓̀")}, - {0x1fce, 0, 0, 2, g(Yes, No, false, false, "῎", " ̓́")}, - {0x1fcf, 0, 0, 2, g(Yes, No, false, false, "῏", " ̓͂")}, - {0x1fd0, 0, 0, 1, f(Yes, false, "ῐ")}, - {0x1fd1, 0, 0, 1, f(Yes, false, "ῑ")}, - {0x1fd2, 0, 0, 2, f(Yes, false, "ῒ")}, - {0x1fd3, 0, 0, 2, f(No, false, "ΐ")}, - {0x1fd4, 0, 0, 0, f(Yes, false, "")}, - {0x1fd6, 0, 0, 1, f(Yes, false, "ῖ")}, - {0x1fd7, 0, 0, 2, f(Yes, false, "ῗ")}, - {0x1fd8, 0, 0, 1, f(Yes, false, "Ῐ")}, - {0x1fd9, 0, 0, 1, f(Yes, false, "Ῑ")}, - {0x1fda, 0, 0, 1, f(Yes, false, "Ὶ")}, - {0x1fdb, 0, 0, 1, f(No, false, "Ί")}, - {0x1fdc, 0, 0, 0, f(Yes, false, "")}, - {0x1fdd, 0, 0, 2, g(Yes, No, false, false, "῝", " ̔̀")}, - {0x1fde, 0, 0, 2, g(Yes, No, false, false, "῞", " ̔́")}, - {0x1fdf, 0, 0, 2, g(Yes, No, false, false, "῟", " ̔͂")}, - {0x1fe0, 0, 0, 1, f(Yes, false, "ῠ")}, - {0x1fe1, 0, 0, 1, f(Yes, false, "ῡ")}, - {0x1fe2, 0, 0, 2, f(Yes, false, "ῢ")}, - {0x1fe3, 0, 0, 2, f(No, false, "ΰ")}, - {0x1fe4, 0, 0, 1, f(Yes, false, "ῤ")}, - {0x1fe5, 0, 0, 1, f(Yes, false, "ῥ")}, - {0x1fe6, 0, 0, 1, f(Yes, false, "ῦ")}, - {0x1fe7, 0, 0, 2, f(Yes, false, "ῧ")}, - {0x1fe8, 0, 0, 1, f(Yes, false, "Ῠ")}, - {0x1fe9, 0, 0, 1, f(Yes, false, "Ῡ")}, - {0x1fea, 0, 0, 1, f(Yes, false, "Ὺ")}, - {0x1feb, 0, 0, 1, f(No, false, "Ύ")}, - {0x1fec, 0, 0, 1, f(Yes, false, "Ῥ")}, - {0x1fed, 0, 0, 2, g(Yes, No, false, false, "῭", " ̈̀")}, - {0x1fee, 0, 0, 2, g(No, No, false, false, "΅", " ̈́")}, - {0x1fef, 0, 0, 0, f(No, false, "`")}, - {0x1ff0, 0, 0, 0, f(Yes, false, "")}, - {0x1ff2, 0, 0, 2, f(Yes, false, "ῲ")}, - {0x1ff3, 0, 0, 1, f(Yes, false, "ῳ")}, - {0x1ff4, 0, 0, 2, f(Yes, false, "ῴ")}, - {0x1ff5, 0, 0, 0, f(Yes, false, "")}, - {0x1ff6, 0, 0, 1, f(Yes, true, "ῶ")}, - {0x1ff7, 0, 0, 2, f(Yes, false, "ῷ")}, - {0x1ff8, 0, 0, 1, f(Yes, false, "Ὸ")}, - {0x1ff9, 0, 0, 1, f(No, false, "Ό")}, - {0x1ffa, 0, 0, 1, f(Yes, false, "Ὼ")}, - {0x1ffb, 0, 0, 1, f(No, false, "Ώ")}, - {0x1ffc, 0, 0, 1, f(Yes, false, "ῼ")}, - {0x1ffd, 0, 0, 1, g(No, No, false, false, "´", " ́")}, - {0x1ffe, 0, 0, 1, g(Yes, No, true, false, "", " ̔")}, - {0x1fff, 0, 0, 0, f(Yes, false, "")}, - {0x2000, 0, 0, 0, g(No, No, false, false, "\u2002", " ")}, - {0x2001, 0, 0, 0, g(No, No, false, false, "\u2003", " ")}, - {0x2002, 0, 0, 0, g(Yes, No, false, false, "", " ")}, - {0x200b, 0, 0, 0, f(Yes, false, "")}, - {0x2011, 0, 0, 0, g(Yes, No, false, false, "", "‐")}, - {0x2012, 0, 0, 0, f(Yes, false, "")}, - {0x2017, 0, 0, 1, g(Yes, No, false, false, "", " ̳")}, - {0x2018, 0, 0, 0, f(Yes, false, "")}, - {0x2024, 0, 0, 0, g(Yes, No, false, false, "", ".")}, - {0x2025, 0, 0, 0, g(Yes, No, false, false, "", "..")}, - {0x2026, 0, 0, 0, g(Yes, No, false, false, "", "...")}, - {0x2027, 0, 0, 0, f(Yes, false, "")}, - {0x202f, 0, 0, 0, g(Yes, No, false, false, "", " ")}, - {0x2030, 0, 0, 0, f(Yes, false, "")}, - {0x2033, 0, 0, 0, g(Yes, No, false, false, "", "′′")}, - {0x2034, 0, 0, 0, g(Yes, No, false, false, "", "′′′")}, - {0x2035, 0, 0, 0, f(Yes, false, "")}, - {0x2036, 0, 0, 0, g(Yes, No, false, false, "", "‵‵")}, - {0x2037, 0, 0, 0, g(Yes, No, false, false, "", "‵‵‵")}, - {0x2038, 0, 0, 0, f(Yes, false, "")}, - {0x203c, 0, 0, 0, g(Yes, No, false, false, "", "!!")}, - {0x203d, 0, 0, 0, f(Yes, false, "")}, - {0x203e, 0, 0, 1, g(Yes, No, false, false, "", " ̅")}, - {0x203f, 0, 0, 0, f(Yes, false, "")}, - {0x2047, 0, 0, 0, g(Yes, No, false, false, "", "??")}, - {0x2048, 0, 0, 0, g(Yes, No, false, false, "", "?!")}, - {0x2049, 0, 0, 0, g(Yes, No, false, false, "", "!?")}, - {0x204a, 0, 0, 0, f(Yes, false, "")}, - {0x2057, 0, 0, 0, g(Yes, No, false, false, "", "′′′′")}, - {0x2058, 0, 0, 0, f(Yes, false, "")}, - {0x205f, 0, 0, 0, g(Yes, No, false, false, "", " ")}, - {0x2060, 0, 0, 0, f(Yes, false, "")}, - {0x2070, 0, 0, 0, g(Yes, No, false, false, "", "0")}, - {0x2071, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x2072, 0, 0, 0, f(Yes, false, "")}, - {0x2074, 0, 0, 0, g(Yes, No, false, false, "", "4")}, - {0x2075, 0, 0, 0, g(Yes, No, false, false, "", "5")}, - {0x2076, 0, 0, 0, g(Yes, No, false, false, "", "6")}, - {0x2077, 0, 0, 0, g(Yes, No, false, false, "", "7")}, - {0x2078, 0, 0, 0, g(Yes, No, false, false, "", "8")}, - {0x2079, 0, 0, 0, g(Yes, No, false, false, "", "9")}, - {0x207a, 0, 0, 0, g(Yes, No, false, false, "", "+")}, - {0x207b, 0, 0, 0, g(Yes, No, false, false, "", "−")}, - {0x207c, 0, 0, 0, g(Yes, No, false, false, "", "=")}, - {0x207d, 0, 0, 0, g(Yes, No, false, false, "", "(")}, - {0x207e, 0, 0, 0, g(Yes, No, false, false, "", ")")}, - {0x207f, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0x2080, 0, 0, 0, g(Yes, No, false, false, "", "0")}, - {0x2081, 0, 0, 0, g(Yes, No, false, false, "", "1")}, - {0x2082, 0, 0, 0, g(Yes, No, false, false, "", "2")}, - {0x2083, 0, 0, 0, g(Yes, No, false, false, "", "3")}, - {0x2084, 0, 0, 0, g(Yes, No, false, false, "", "4")}, - {0x2085, 0, 0, 0, g(Yes, No, false, false, "", "5")}, - {0x2086, 0, 0, 0, g(Yes, No, false, false, "", "6")}, - {0x2087, 0, 0, 0, g(Yes, No, false, false, "", "7")}, - {0x2088, 0, 0, 0, g(Yes, No, false, false, "", "8")}, - {0x2089, 0, 0, 0, g(Yes, No, false, false, "", "9")}, - {0x208a, 0, 0, 0, g(Yes, No, false, false, "", "+")}, - {0x208b, 0, 0, 0, g(Yes, No, false, false, "", "−")}, - {0x208c, 0, 0, 0, g(Yes, No, false, false, "", "=")}, - {0x208d, 0, 0, 0, g(Yes, No, false, false, "", "(")}, - {0x208e, 0, 0, 0, g(Yes, No, false, false, "", ")")}, - {0x208f, 0, 0, 0, f(Yes, false, "")}, - {0x2090, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0x2091, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x2092, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0x2093, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x2094, 0, 0, 0, g(Yes, No, false, false, "", "ə")}, - {0x2095, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0x2096, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0x2097, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x2098, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x2099, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0x209a, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0x209b, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0x209c, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0x209d, 0, 0, 0, f(Yes, false, "")}, - {0x20a8, 0, 0, 0, g(Yes, No, false, false, "", "Rs")}, - {0x20a9, 0, 0, 0, f(Yes, false, "")}, - {0x20d0, 230, 1, 1, f(Yes, false, "")}, - {0x20d2, 1, 1, 1, f(Yes, false, "")}, - {0x20d4, 230, 1, 1, f(Yes, false, "")}, - {0x20d8, 1, 1, 1, f(Yes, false, "")}, - {0x20db, 230, 1, 1, f(Yes, false, "")}, - {0x20dd, 0, 0, 0, f(Yes, false, "")}, - {0x20e1, 230, 1, 1, f(Yes, false, "")}, - {0x20e2, 0, 0, 0, f(Yes, false, "")}, - {0x20e5, 1, 1, 1, f(Yes, false, "")}, - {0x20e7, 230, 1, 1, f(Yes, false, "")}, - {0x20e8, 220, 1, 1, f(Yes, false, "")}, - {0x20e9, 230, 1, 1, f(Yes, false, "")}, - {0x20ea, 1, 1, 1, f(Yes, false, "")}, - {0x20ec, 220, 1, 1, f(Yes, false, "")}, - {0x20f0, 230, 1, 1, f(Yes, false, "")}, - {0x20f1, 0, 0, 0, f(Yes, false, "")}, - {0x2100, 0, 0, 0, g(Yes, No, false, false, "", "a/c")}, - {0x2101, 0, 0, 0, g(Yes, No, false, false, "", "a/s")}, - {0x2102, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x2103, 0, 0, 0, g(Yes, No, false, false, "", "°C")}, - {0x2104, 0, 0, 0, f(Yes, false, "")}, - {0x2105, 0, 0, 0, g(Yes, No, false, false, "", "c/o")}, - {0x2106, 0, 0, 0, g(Yes, No, false, false, "", "c/u")}, - {0x2107, 0, 0, 0, g(Yes, No, false, false, "", "Ɛ")}, - {0x2108, 0, 0, 0, f(Yes, false, "")}, - {0x2109, 0, 0, 0, g(Yes, No, false, false, "", "°F")}, - {0x210a, 0, 0, 0, g(Yes, No, false, false, "", "g")}, - {0x210b, 0, 0, 0, g(Yes, No, false, false, "", "H")}, - {0x210e, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0x210f, 0, 0, 0, g(Yes, No, false, false, "", "ħ")}, - {0x2110, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0x2112, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x2113, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x2114, 0, 0, 0, f(Yes, false, "")}, - {0x2115, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0x2116, 0, 0, 0, g(Yes, No, false, false, "", "No")}, - {0x2117, 0, 0, 0, f(Yes, false, "")}, - {0x2119, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0x211a, 0, 0, 0, g(Yes, No, false, false, "", "Q")}, - {0x211b, 0, 0, 0, g(Yes, No, false, false, "", "R")}, - {0x211e, 0, 0, 0, f(Yes, false, "")}, - {0x2120, 0, 0, 0, g(Yes, No, false, false, "", "SM")}, - {0x2121, 0, 0, 0, g(Yes, No, false, false, "", "TEL")}, - {0x2122, 0, 0, 0, g(Yes, No, false, false, "", "TM")}, - {0x2123, 0, 0, 0, f(Yes, false, "")}, - {0x2124, 0, 0, 0, g(Yes, No, false, false, "", "Z")}, - {0x2125, 0, 0, 0, f(Yes, false, "")}, - {0x2126, 0, 0, 0, f(No, false, "Ω")}, - {0x2127, 0, 0, 0, f(Yes, false, "")}, - {0x2128, 0, 0, 0, g(Yes, No, false, false, "", "Z")}, - {0x2129, 0, 0, 0, f(Yes, false, "")}, - {0x212a, 0, 0, 0, f(No, false, "K")}, - {0x212b, 0, 0, 1, f(No, false, "Å")}, - {0x212c, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0x212d, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x212e, 0, 0, 0, f(Yes, false, "")}, - {0x212f, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x2130, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0x2131, 0, 0, 0, g(Yes, No, false, false, "", "F")}, - {0x2132, 0, 0, 0, f(Yes, false, "")}, - {0x2133, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x2134, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0x2135, 0, 0, 0, g(Yes, No, false, false, "", "א")}, - {0x2136, 0, 0, 0, g(Yes, No, false, false, "", "ב")}, - {0x2137, 0, 0, 0, g(Yes, No, false, false, "", "ג")}, - {0x2138, 0, 0, 0, g(Yes, No, false, false, "", "ד")}, - {0x2139, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x213a, 0, 0, 0, f(Yes, false, "")}, - {0x213b, 0, 0, 0, g(Yes, No, false, false, "", "FAX")}, - {0x213c, 0, 0, 0, g(Yes, No, false, false, "", "π")}, - {0x213d, 0, 0, 0, g(Yes, No, false, false, "", "γ")}, - {0x213e, 0, 0, 0, g(Yes, No, false, false, "", "Γ")}, - {0x213f, 0, 0, 0, g(Yes, No, false, false, "", "Π")}, - {0x2140, 0, 0, 0, g(Yes, No, false, false, "", "∑")}, - {0x2141, 0, 0, 0, f(Yes, false, "")}, - {0x2145, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x2146, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x2147, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x2148, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x2149, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x214a, 0, 0, 0, f(Yes, false, "")}, - {0x2150, 0, 0, 0, g(Yes, No, false, false, "", "1⁄7")}, - {0x2151, 0, 0, 0, g(Yes, No, false, false, "", "1⁄9")}, - {0x2152, 0, 0, 0, g(Yes, No, false, false, "", "1⁄10")}, - {0x2153, 0, 0, 0, g(Yes, No, false, false, "", "1⁄3")}, - {0x2154, 0, 0, 0, g(Yes, No, false, false, "", "2⁄3")}, - {0x2155, 0, 0, 0, g(Yes, No, false, false, "", "1⁄5")}, - {0x2156, 0, 0, 0, g(Yes, No, false, false, "", "2⁄5")}, - {0x2157, 0, 0, 0, g(Yes, No, false, false, "", "3⁄5")}, - {0x2158, 0, 0, 0, g(Yes, No, false, false, "", "4⁄5")}, - {0x2159, 0, 0, 0, g(Yes, No, false, false, "", "1⁄6")}, - {0x215a, 0, 0, 0, g(Yes, No, false, false, "", "5⁄6")}, - {0x215b, 0, 0, 0, g(Yes, No, false, false, "", "1⁄8")}, - {0x215c, 0, 0, 0, g(Yes, No, false, false, "", "3⁄8")}, - {0x215d, 0, 0, 0, g(Yes, No, false, false, "", "5⁄8")}, - {0x215e, 0, 0, 0, g(Yes, No, false, false, "", "7⁄8")}, - {0x215f, 0, 0, 0, g(Yes, No, false, false, "", "1⁄")}, - {0x2160, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0x2161, 0, 0, 0, g(Yes, No, false, false, "", "II")}, - {0x2162, 0, 0, 0, g(Yes, No, false, false, "", "III")}, - {0x2163, 0, 0, 0, g(Yes, No, false, false, "", "IV")}, - {0x2164, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x2165, 0, 0, 0, g(Yes, No, false, false, "", "VI")}, - {0x2166, 0, 0, 0, g(Yes, No, false, false, "", "VII")}, - {0x2167, 0, 0, 0, g(Yes, No, false, false, "", "VIII")}, - {0x2168, 0, 0, 0, g(Yes, No, false, false, "", "IX")}, - {0x2169, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0x216a, 0, 0, 0, g(Yes, No, false, false, "", "XI")}, - {0x216b, 0, 0, 0, g(Yes, No, false, false, "", "XII")}, - {0x216c, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x216d, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x216e, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x216f, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x2170, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x2171, 0, 0, 0, g(Yes, No, false, false, "", "ii")}, - {0x2172, 0, 0, 0, g(Yes, No, false, false, "", "iii")}, - {0x2173, 0, 0, 0, g(Yes, No, false, false, "", "iv")}, - {0x2174, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x2175, 0, 0, 0, g(Yes, No, false, false, "", "vi")}, - {0x2176, 0, 0, 0, g(Yes, No, false, false, "", "vii")}, - {0x2177, 0, 0, 0, g(Yes, No, false, false, "", "viii")}, - {0x2178, 0, 0, 0, g(Yes, No, false, false, "", "ix")}, - {0x2179, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x217a, 0, 0, 0, g(Yes, No, false, false, "", "xi")}, - {0x217b, 0, 0, 0, g(Yes, No, false, false, "", "xii")}, - {0x217c, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x217d, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0x217e, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x217f, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x2180, 0, 0, 0, f(Yes, false, "")}, - {0x2189, 0, 0, 0, g(Yes, No, false, false, "", "0⁄3")}, - {0x218a, 0, 0, 0, f(Yes, false, "")}, - {0x2190, 0, 0, 0, f(Yes, true, "")}, - {0x2191, 0, 0, 0, f(Yes, false, "")}, - {0x2192, 0, 0, 0, f(Yes, true, "")}, - {0x2193, 0, 0, 0, f(Yes, false, "")}, - {0x2194, 0, 0, 0, f(Yes, true, "")}, - {0x2195, 0, 0, 0, f(Yes, false, "")}, - {0x219a, 0, 0, 1, f(Yes, false, "↚")}, - {0x219b, 0, 0, 1, f(Yes, false, "↛")}, - {0x219c, 0, 0, 0, f(Yes, false, "")}, - {0x21ae, 0, 0, 1, f(Yes, false, "↮")}, - {0x21af, 0, 0, 0, f(Yes, false, "")}, - {0x21cd, 0, 0, 1, f(Yes, false, "⇍")}, - {0x21ce, 0, 0, 1, f(Yes, false, "⇎")}, - {0x21cf, 0, 0, 1, f(Yes, false, "⇏")}, - {0x21d0, 0, 0, 0, f(Yes, true, "")}, - {0x21d1, 0, 0, 0, f(Yes, false, "")}, - {0x21d2, 0, 0, 0, f(Yes, true, "")}, - {0x21d3, 0, 0, 0, f(Yes, false, "")}, - {0x21d4, 0, 0, 0, f(Yes, true, "")}, - {0x21d5, 0, 0, 0, f(Yes, false, "")}, - {0x2203, 0, 0, 0, f(Yes, true, "")}, - {0x2204, 0, 0, 1, f(Yes, false, "∄")}, - {0x2205, 0, 0, 0, f(Yes, false, "")}, - {0x2208, 0, 0, 0, f(Yes, true, "")}, - {0x2209, 0, 0, 1, f(Yes, false, "∉")}, - {0x220a, 0, 0, 0, f(Yes, false, "")}, - {0x220b, 0, 0, 0, f(Yes, true, "")}, - {0x220c, 0, 0, 1, f(Yes, false, "∌")}, - {0x220d, 0, 0, 0, f(Yes, false, "")}, - {0x2223, 0, 0, 0, f(Yes, true, "")}, - {0x2224, 0, 0, 1, f(Yes, false, "∤")}, - {0x2225, 0, 0, 0, f(Yes, true, "")}, - {0x2226, 0, 0, 1, f(Yes, false, "∦")}, - {0x2227, 0, 0, 0, f(Yes, false, "")}, - {0x222c, 0, 0, 0, g(Yes, No, false, false, "", "∫∫")}, - {0x222d, 0, 0, 0, g(Yes, No, false, false, "", "∫∫∫")}, - {0x222e, 0, 0, 0, f(Yes, false, "")}, - {0x222f, 0, 0, 0, g(Yes, No, false, false, "", "∮∮")}, - {0x2230, 0, 0, 0, g(Yes, No, false, false, "", "∮∮∮")}, - {0x2231, 0, 0, 0, f(Yes, false, "")}, - {0x223c, 0, 0, 0, f(Yes, true, "")}, - {0x223d, 0, 0, 0, f(Yes, false, "")}, - {0x2241, 0, 0, 1, f(Yes, false, "≁")}, - {0x2242, 0, 0, 0, f(Yes, false, "")}, - {0x2243, 0, 0, 0, f(Yes, true, "")}, - {0x2244, 0, 0, 1, f(Yes, false, "≄")}, - {0x2245, 0, 0, 0, f(Yes, true, "")}, - {0x2246, 0, 0, 0, f(Yes, false, "")}, - {0x2247, 0, 0, 1, f(Yes, false, "≇")}, - {0x2248, 0, 0, 0, f(Yes, true, "")}, - {0x2249, 0, 0, 1, f(Yes, false, "≉")}, - {0x224a, 0, 0, 0, f(Yes, false, "")}, - {0x224d, 0, 0, 0, f(Yes, true, "")}, - {0x224e, 0, 0, 0, f(Yes, false, "")}, - {0x2260, 0, 0, 1, f(Yes, false, "≠")}, - {0x2261, 0, 0, 0, f(Yes, true, "")}, - {0x2262, 0, 0, 1, f(Yes, false, "≢")}, - {0x2263, 0, 0, 0, f(Yes, false, "")}, - {0x2264, 0, 0, 0, f(Yes, true, "")}, - {0x2266, 0, 0, 0, f(Yes, false, "")}, - {0x226d, 0, 0, 1, f(Yes, false, "≭")}, - {0x226e, 0, 0, 1, f(Yes, false, "≮")}, - {0x226f, 0, 0, 1, f(Yes, false, "≯")}, - {0x2270, 0, 0, 1, f(Yes, false, "≰")}, - {0x2271, 0, 0, 1, f(Yes, false, "≱")}, - {0x2272, 0, 0, 0, f(Yes, true, "")}, - {0x2274, 0, 0, 1, f(Yes, false, "≴")}, - {0x2275, 0, 0, 1, f(Yes, false, "≵")}, - {0x2276, 0, 0, 0, f(Yes, true, "")}, - {0x2278, 0, 0, 1, f(Yes, false, "≸")}, - {0x2279, 0, 0, 1, f(Yes, false, "≹")}, - {0x227a, 0, 0, 0, f(Yes, true, "")}, - {0x227e, 0, 0, 0, f(Yes, false, "")}, - {0x2280, 0, 0, 1, f(Yes, false, "⊀")}, - {0x2281, 0, 0, 1, f(Yes, false, "⊁")}, - {0x2282, 0, 0, 0, f(Yes, true, "")}, - {0x2284, 0, 0, 1, f(Yes, false, "⊄")}, - {0x2285, 0, 0, 1, f(Yes, false, "⊅")}, - {0x2286, 0, 0, 0, f(Yes, true, "")}, - {0x2288, 0, 0, 1, f(Yes, false, "⊈")}, - {0x2289, 0, 0, 1, f(Yes, false, "⊉")}, - {0x228a, 0, 0, 0, f(Yes, false, "")}, - {0x2291, 0, 0, 0, f(Yes, true, "")}, - {0x2293, 0, 0, 0, f(Yes, false, "")}, - {0x22a2, 0, 0, 0, f(Yes, true, "")}, - {0x22a3, 0, 0, 0, f(Yes, false, "")}, - {0x22a8, 0, 0, 0, f(Yes, true, "")}, - {0x22aa, 0, 0, 0, f(Yes, false, "")}, - {0x22ab, 0, 0, 0, f(Yes, true, "")}, - {0x22ac, 0, 0, 1, f(Yes, false, "⊬")}, - {0x22ad, 0, 0, 1, f(Yes, false, "⊭")}, - {0x22ae, 0, 0, 1, f(Yes, false, "⊮")}, - {0x22af, 0, 0, 1, f(Yes, false, "⊯")}, - {0x22b0, 0, 0, 0, f(Yes, false, "")}, - {0x22b2, 0, 0, 0, f(Yes, true, "")}, - {0x22b6, 0, 0, 0, f(Yes, false, "")}, - {0x22e0, 0, 0, 1, f(Yes, false, "⋠")}, - {0x22e1, 0, 0, 1, f(Yes, false, "⋡")}, - {0x22e2, 0, 0, 1, f(Yes, false, "⋢")}, - {0x22e3, 0, 0, 1, f(Yes, false, "⋣")}, - {0x22e4, 0, 0, 0, f(Yes, false, "")}, - {0x22ea, 0, 0, 1, f(Yes, false, "⋪")}, - {0x22eb, 0, 0, 1, f(Yes, false, "⋫")}, - {0x22ec, 0, 0, 1, f(Yes, false, "⋬")}, - {0x22ed, 0, 0, 1, f(Yes, false, "⋭")}, - {0x22ee, 0, 0, 0, f(Yes, false, "")}, - {0x2329, 0, 0, 0, f(No, false, "〈")}, - {0x232a, 0, 0, 0, f(No, false, "〉")}, - {0x232b, 0, 0, 0, f(Yes, false, "")}, - {0x2460, 0, 0, 0, g(Yes, No, false, false, "", "1")}, - {0x2461, 0, 0, 0, g(Yes, No, false, false, "", "2")}, - {0x2462, 0, 0, 0, g(Yes, No, false, false, "", "3")}, - {0x2463, 0, 0, 0, g(Yes, No, false, false, "", "4")}, - {0x2464, 0, 0, 0, g(Yes, No, false, false, "", "5")}, - {0x2465, 0, 0, 0, g(Yes, No, false, false, "", "6")}, - {0x2466, 0, 0, 0, g(Yes, No, false, false, "", "7")}, - {0x2467, 0, 0, 0, g(Yes, No, false, false, "", "8")}, - {0x2468, 0, 0, 0, g(Yes, No, false, false, "", "9")}, - {0x2469, 0, 0, 0, g(Yes, No, false, false, "", "10")}, - {0x246a, 0, 0, 0, g(Yes, No, false, false, "", "11")}, - {0x246b, 0, 0, 0, g(Yes, No, false, false, "", "12")}, - {0x246c, 0, 0, 0, g(Yes, No, false, false, "", "13")}, - {0x246d, 0, 0, 0, g(Yes, No, false, false, "", "14")}, - {0x246e, 0, 0, 0, g(Yes, No, false, false, "", "15")}, - {0x246f, 0, 0, 0, g(Yes, No, false, false, "", "16")}, - {0x2470, 0, 0, 0, g(Yes, No, false, false, "", "17")}, - {0x2471, 0, 0, 0, g(Yes, No, false, false, "", "18")}, - {0x2472, 0, 0, 0, g(Yes, No, false, false, "", "19")}, - {0x2473, 0, 0, 0, g(Yes, No, false, false, "", "20")}, - {0x2474, 0, 0, 0, g(Yes, No, false, false, "", "(1)")}, - {0x2475, 0, 0, 0, g(Yes, No, false, false, "", "(2)")}, - {0x2476, 0, 0, 0, g(Yes, No, false, false, "", "(3)")}, - {0x2477, 0, 0, 0, g(Yes, No, false, false, "", "(4)")}, - {0x2478, 0, 0, 0, g(Yes, No, false, false, "", "(5)")}, - {0x2479, 0, 0, 0, g(Yes, No, false, false, "", "(6)")}, - {0x247a, 0, 0, 0, g(Yes, No, false, false, "", "(7)")}, - {0x247b, 0, 0, 0, g(Yes, No, false, false, "", "(8)")}, - {0x247c, 0, 0, 0, g(Yes, No, false, false, "", "(9)")}, - {0x247d, 0, 0, 0, g(Yes, No, false, false, "", "(10)")}, - {0x247e, 0, 0, 0, g(Yes, No, false, false, "", "(11)")}, - {0x247f, 0, 0, 0, g(Yes, No, false, false, "", "(12)")}, - {0x2480, 0, 0, 0, g(Yes, No, false, false, "", "(13)")}, - {0x2481, 0, 0, 0, g(Yes, No, false, false, "", "(14)")}, - {0x2482, 0, 0, 0, g(Yes, No, false, false, "", "(15)")}, - {0x2483, 0, 0, 0, g(Yes, No, false, false, "", "(16)")}, - {0x2484, 0, 0, 0, g(Yes, No, false, false, "", "(17)")}, - {0x2485, 0, 0, 0, g(Yes, No, false, false, "", "(18)")}, - {0x2486, 0, 0, 0, g(Yes, No, false, false, "", "(19)")}, - {0x2487, 0, 0, 0, g(Yes, No, false, false, "", "(20)")}, - {0x2488, 0, 0, 0, g(Yes, No, false, false, "", "1.")}, - {0x2489, 0, 0, 0, g(Yes, No, false, false, "", "2.")}, - {0x248a, 0, 0, 0, g(Yes, No, false, false, "", "3.")}, - {0x248b, 0, 0, 0, g(Yes, No, false, false, "", "4.")}, - {0x248c, 0, 0, 0, g(Yes, No, false, false, "", "5.")}, - {0x248d, 0, 0, 0, g(Yes, No, false, false, "", "6.")}, - {0x248e, 0, 0, 0, g(Yes, No, false, false, "", "7.")}, - {0x248f, 0, 0, 0, g(Yes, No, false, false, "", "8.")}, - {0x2490, 0, 0, 0, g(Yes, No, false, false, "", "9.")}, - {0x2491, 0, 0, 0, g(Yes, No, false, false, "", "10.")}, - {0x2492, 0, 0, 0, g(Yes, No, false, false, "", "11.")}, - {0x2493, 0, 0, 0, g(Yes, No, false, false, "", "12.")}, - {0x2494, 0, 0, 0, g(Yes, No, false, false, "", "13.")}, - {0x2495, 0, 0, 0, g(Yes, No, false, false, "", "14.")}, - {0x2496, 0, 0, 0, g(Yes, No, false, false, "", "15.")}, - {0x2497, 0, 0, 0, g(Yes, No, false, false, "", "16.")}, - {0x2498, 0, 0, 0, g(Yes, No, false, false, "", "17.")}, - {0x2499, 0, 0, 0, g(Yes, No, false, false, "", "18.")}, - {0x249a, 0, 0, 0, g(Yes, No, false, false, "", "19.")}, - {0x249b, 0, 0, 0, g(Yes, No, false, false, "", "20.")}, - {0x249c, 0, 0, 0, g(Yes, No, false, false, "", "(a)")}, - {0x249d, 0, 0, 0, g(Yes, No, false, false, "", "(b)")}, - {0x249e, 0, 0, 0, g(Yes, No, false, false, "", "(c)")}, - {0x249f, 0, 0, 0, g(Yes, No, false, false, "", "(d)")}, - {0x24a0, 0, 0, 0, g(Yes, No, false, false, "", "(e)")}, - {0x24a1, 0, 0, 0, g(Yes, No, false, false, "", "(f)")}, - {0x24a2, 0, 0, 0, g(Yes, No, false, false, "", "(g)")}, - {0x24a3, 0, 0, 0, g(Yes, No, false, false, "", "(h)")}, - {0x24a4, 0, 0, 0, g(Yes, No, false, false, "", "(i)")}, - {0x24a5, 0, 0, 0, g(Yes, No, false, false, "", "(j)")}, - {0x24a6, 0, 0, 0, g(Yes, No, false, false, "", "(k)")}, - {0x24a7, 0, 0, 0, g(Yes, No, false, false, "", "(l)")}, - {0x24a8, 0, 0, 0, g(Yes, No, false, false, "", "(m)")}, - {0x24a9, 0, 0, 0, g(Yes, No, false, false, "", "(n)")}, - {0x24aa, 0, 0, 0, g(Yes, No, false, false, "", "(o)")}, - {0x24ab, 0, 0, 0, g(Yes, No, false, false, "", "(p)")}, - {0x24ac, 0, 0, 0, g(Yes, No, false, false, "", "(q)")}, - {0x24ad, 0, 0, 0, g(Yes, No, false, false, "", "(r)")}, - {0x24ae, 0, 0, 0, g(Yes, No, false, false, "", "(s)")}, - {0x24af, 0, 0, 0, g(Yes, No, false, false, "", "(t)")}, - {0x24b0, 0, 0, 0, g(Yes, No, false, false, "", "(u)")}, - {0x24b1, 0, 0, 0, g(Yes, No, false, false, "", "(v)")}, - {0x24b2, 0, 0, 0, g(Yes, No, false, false, "", "(w)")}, - {0x24b3, 0, 0, 0, g(Yes, No, false, false, "", "(x)")}, - {0x24b4, 0, 0, 0, g(Yes, No, false, false, "", "(y)")}, - {0x24b5, 0, 0, 0, g(Yes, No, false, false, "", "(z)")}, - {0x24b6, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0x24b7, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0x24b8, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x24b9, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x24ba, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0x24bb, 0, 0, 0, g(Yes, No, false, false, "", "F")}, - {0x24bc, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0x24bd, 0, 0, 0, g(Yes, No, false, false, "", "H")}, - {0x24be, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0x24bf, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0x24c0, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0x24c1, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x24c2, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x24c3, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0x24c4, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0x24c5, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0x24c6, 0, 0, 0, g(Yes, No, false, false, "", "Q")}, - {0x24c7, 0, 0, 0, g(Yes, No, false, false, "", "R")}, - {0x24c8, 0, 0, 0, g(Yes, No, false, false, "", "S")}, - {0x24c9, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0x24ca, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0x24cb, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x24cc, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0x24cd, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0x24ce, 0, 0, 0, g(Yes, No, false, false, "", "Y")}, - {0x24cf, 0, 0, 0, g(Yes, No, false, false, "", "Z")}, - {0x24d0, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0x24d1, 0, 0, 0, g(Yes, No, false, false, "", "b")}, - {0x24d2, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0x24d3, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x24d4, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x24d5, 0, 0, 0, g(Yes, No, false, false, "", "f")}, - {0x24d6, 0, 0, 0, g(Yes, No, false, false, "", "g")}, - {0x24d7, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0x24d8, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x24d9, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x24da, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0x24db, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x24dc, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x24dd, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0x24de, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0x24df, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0x24e0, 0, 0, 0, g(Yes, No, false, false, "", "q")}, - {0x24e1, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0x24e2, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0x24e3, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0x24e4, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0x24e5, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x24e6, 0, 0, 0, g(Yes, No, false, false, "", "w")}, - {0x24e7, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x24e8, 0, 0, 0, g(Yes, No, false, false, "", "y")}, - {0x24e9, 0, 0, 0, g(Yes, No, false, false, "", "z")}, - {0x24ea, 0, 0, 0, g(Yes, No, false, false, "", "0")}, - {0x24eb, 0, 0, 0, f(Yes, false, "")}, - {0x2a0c, 0, 0, 0, g(Yes, No, false, false, "", "∫∫∫∫")}, - {0x2a0d, 0, 0, 0, f(Yes, false, "")}, - {0x2a74, 0, 0, 0, g(Yes, No, false, false, "", "::=")}, - {0x2a75, 0, 0, 0, g(Yes, No, false, false, "", "==")}, - {0x2a76, 0, 0, 0, g(Yes, No, false, false, "", "===")}, - {0x2a77, 0, 0, 0, f(Yes, false, "")}, - {0x2adc, 0, 0, 1, f(No, false, "⫝̸")}, - {0x2add, 0, 0, 0, f(Yes, false, "")}, - {0x2c7c, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x2c7d, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x2c7e, 0, 0, 0, f(Yes, false, "")}, - {0x2cef, 230, 1, 1, f(Yes, false, "")}, - {0x2cf2, 0, 0, 0, f(Yes, false, "")}, - {0x2d6f, 0, 0, 0, g(Yes, No, false, false, "", "ⵡ")}, - {0x2d70, 0, 0, 0, f(Yes, false, "")}, - {0x2d7f, 9, 1, 1, f(Yes, false, "")}, - {0x2d80, 0, 0, 0, f(Yes, false, "")}, - {0x2de0, 230, 1, 1, f(Yes, false, "")}, - {0x2e00, 0, 0, 0, f(Yes, false, "")}, - {0x2e9f, 0, 0, 0, g(Yes, No, false, false, "", "母")}, - {0x2ea0, 0, 0, 0, f(Yes, false, "")}, - {0x2ef3, 0, 0, 0, g(Yes, No, false, false, "", "龟")}, - {0x2ef4, 0, 0, 0, f(Yes, false, "")}, - {0x2f00, 0, 0, 0, g(Yes, No, false, false, "", "一")}, - {0x2f01, 0, 0, 0, g(Yes, No, false, false, "", "丨")}, - {0x2f02, 0, 0, 0, g(Yes, No, false, false, "", "丶")}, - {0x2f03, 0, 0, 0, g(Yes, No, false, false, "", "丿")}, - {0x2f04, 0, 0, 0, g(Yes, No, false, false, "", "乙")}, - {0x2f05, 0, 0, 0, g(Yes, No, false, false, "", "亅")}, - {0x2f06, 0, 0, 0, g(Yes, No, false, false, "", "二")}, - {0x2f07, 0, 0, 0, g(Yes, No, false, false, "", "亠")}, - {0x2f08, 0, 0, 0, g(Yes, No, false, false, "", "人")}, - {0x2f09, 0, 0, 0, g(Yes, No, false, false, "", "儿")}, - {0x2f0a, 0, 0, 0, g(Yes, No, false, false, "", "入")}, - {0x2f0b, 0, 0, 0, g(Yes, No, false, false, "", "八")}, - {0x2f0c, 0, 0, 0, g(Yes, No, false, false, "", "冂")}, - {0x2f0d, 0, 0, 0, g(Yes, No, false, false, "", "冖")}, - {0x2f0e, 0, 0, 0, g(Yes, No, false, false, "", "冫")}, - {0x2f0f, 0, 0, 0, g(Yes, No, false, false, "", "几")}, - {0x2f10, 0, 0, 0, g(Yes, No, false, false, "", "凵")}, - {0x2f11, 0, 0, 0, g(Yes, No, false, false, "", "刀")}, - {0x2f12, 0, 0, 0, g(Yes, No, false, false, "", "力")}, - {0x2f13, 0, 0, 0, g(Yes, No, false, false, "", "勹")}, - {0x2f14, 0, 0, 0, g(Yes, No, false, false, "", "匕")}, - {0x2f15, 0, 0, 0, g(Yes, No, false, false, "", "匚")}, - {0x2f16, 0, 0, 0, g(Yes, No, false, false, "", "匸")}, - {0x2f17, 0, 0, 0, g(Yes, No, false, false, "", "十")}, - {0x2f18, 0, 0, 0, g(Yes, No, false, false, "", "卜")}, - {0x2f19, 0, 0, 0, g(Yes, No, false, false, "", "卩")}, - {0x2f1a, 0, 0, 0, g(Yes, No, false, false, "", "厂")}, - {0x2f1b, 0, 0, 0, g(Yes, No, false, false, "", "厶")}, - {0x2f1c, 0, 0, 0, g(Yes, No, false, false, "", "又")}, - {0x2f1d, 0, 0, 0, g(Yes, No, false, false, "", "口")}, - {0x2f1e, 0, 0, 0, g(Yes, No, false, false, "", "囗")}, - {0x2f1f, 0, 0, 0, g(Yes, No, false, false, "", "土")}, - {0x2f20, 0, 0, 0, g(Yes, No, false, false, "", "士")}, - {0x2f21, 0, 0, 0, g(Yes, No, false, false, "", "夂")}, - {0x2f22, 0, 0, 0, g(Yes, No, false, false, "", "夊")}, - {0x2f23, 0, 0, 0, g(Yes, No, false, false, "", "夕")}, - {0x2f24, 0, 0, 0, g(Yes, No, false, false, "", "大")}, - {0x2f25, 0, 0, 0, g(Yes, No, false, false, "", "女")}, - {0x2f26, 0, 0, 0, g(Yes, No, false, false, "", "子")}, - {0x2f27, 0, 0, 0, g(Yes, No, false, false, "", "宀")}, - {0x2f28, 0, 0, 0, g(Yes, No, false, false, "", "寸")}, - {0x2f29, 0, 0, 0, g(Yes, No, false, false, "", "小")}, - {0x2f2a, 0, 0, 0, g(Yes, No, false, false, "", "尢")}, - {0x2f2b, 0, 0, 0, g(Yes, No, false, false, "", "尸")}, - {0x2f2c, 0, 0, 0, g(Yes, No, false, false, "", "屮")}, - {0x2f2d, 0, 0, 0, g(Yes, No, false, false, "", "山")}, - {0x2f2e, 0, 0, 0, g(Yes, No, false, false, "", "巛")}, - {0x2f2f, 0, 0, 0, g(Yes, No, false, false, "", "工")}, - {0x2f30, 0, 0, 0, g(Yes, No, false, false, "", "己")}, - {0x2f31, 0, 0, 0, g(Yes, No, false, false, "", "巾")}, - {0x2f32, 0, 0, 0, g(Yes, No, false, false, "", "干")}, - {0x2f33, 0, 0, 0, g(Yes, No, false, false, "", "幺")}, - {0x2f34, 0, 0, 0, g(Yes, No, false, false, "", "广")}, - {0x2f35, 0, 0, 0, g(Yes, No, false, false, "", "廴")}, - {0x2f36, 0, 0, 0, g(Yes, No, false, false, "", "廾")}, - {0x2f37, 0, 0, 0, g(Yes, No, false, false, "", "弋")}, - {0x2f38, 0, 0, 0, g(Yes, No, false, false, "", "弓")}, - {0x2f39, 0, 0, 0, g(Yes, No, false, false, "", "彐")}, - {0x2f3a, 0, 0, 0, g(Yes, No, false, false, "", "彡")}, - {0x2f3b, 0, 0, 0, g(Yes, No, false, false, "", "彳")}, - {0x2f3c, 0, 0, 0, g(Yes, No, false, false, "", "心")}, - {0x2f3d, 0, 0, 0, g(Yes, No, false, false, "", "戈")}, - {0x2f3e, 0, 0, 0, g(Yes, No, false, false, "", "戶")}, - {0x2f3f, 0, 0, 0, g(Yes, No, false, false, "", "手")}, - {0x2f40, 0, 0, 0, g(Yes, No, false, false, "", "支")}, - {0x2f41, 0, 0, 0, g(Yes, No, false, false, "", "攴")}, - {0x2f42, 0, 0, 0, g(Yes, No, false, false, "", "文")}, - {0x2f43, 0, 0, 0, g(Yes, No, false, false, "", "斗")}, - {0x2f44, 0, 0, 0, g(Yes, No, false, false, "", "斤")}, - {0x2f45, 0, 0, 0, g(Yes, No, false, false, "", "方")}, - {0x2f46, 0, 0, 0, g(Yes, No, false, false, "", "无")}, - {0x2f47, 0, 0, 0, g(Yes, No, false, false, "", "日")}, - {0x2f48, 0, 0, 0, g(Yes, No, false, false, "", "曰")}, - {0x2f49, 0, 0, 0, g(Yes, No, false, false, "", "月")}, - {0x2f4a, 0, 0, 0, g(Yes, No, false, false, "", "木")}, - {0x2f4b, 0, 0, 0, g(Yes, No, false, false, "", "欠")}, - {0x2f4c, 0, 0, 0, g(Yes, No, false, false, "", "止")}, - {0x2f4d, 0, 0, 0, g(Yes, No, false, false, "", "歹")}, - {0x2f4e, 0, 0, 0, g(Yes, No, false, false, "", "殳")}, - {0x2f4f, 0, 0, 0, g(Yes, No, false, false, "", "毋")}, - {0x2f50, 0, 0, 0, g(Yes, No, false, false, "", "比")}, - {0x2f51, 0, 0, 0, g(Yes, No, false, false, "", "毛")}, - {0x2f52, 0, 0, 0, g(Yes, No, false, false, "", "氏")}, - {0x2f53, 0, 0, 0, g(Yes, No, false, false, "", "气")}, - {0x2f54, 0, 0, 0, g(Yes, No, false, false, "", "水")}, - {0x2f55, 0, 0, 0, g(Yes, No, false, false, "", "火")}, - {0x2f56, 0, 0, 0, g(Yes, No, false, false, "", "爪")}, - {0x2f57, 0, 0, 0, g(Yes, No, false, false, "", "父")}, - {0x2f58, 0, 0, 0, g(Yes, No, false, false, "", "爻")}, - {0x2f59, 0, 0, 0, g(Yes, No, false, false, "", "爿")}, - {0x2f5a, 0, 0, 0, g(Yes, No, false, false, "", "片")}, - {0x2f5b, 0, 0, 0, g(Yes, No, false, false, "", "牙")}, - {0x2f5c, 0, 0, 0, g(Yes, No, false, false, "", "牛")}, - {0x2f5d, 0, 0, 0, g(Yes, No, false, false, "", "犬")}, - {0x2f5e, 0, 0, 0, g(Yes, No, false, false, "", "玄")}, - {0x2f5f, 0, 0, 0, g(Yes, No, false, false, "", "玉")}, - {0x2f60, 0, 0, 0, g(Yes, No, false, false, "", "瓜")}, - {0x2f61, 0, 0, 0, g(Yes, No, false, false, "", "瓦")}, - {0x2f62, 0, 0, 0, g(Yes, No, false, false, "", "甘")}, - {0x2f63, 0, 0, 0, g(Yes, No, false, false, "", "生")}, - {0x2f64, 0, 0, 0, g(Yes, No, false, false, "", "用")}, - {0x2f65, 0, 0, 0, g(Yes, No, false, false, "", "田")}, - {0x2f66, 0, 0, 0, g(Yes, No, false, false, "", "疋")}, - {0x2f67, 0, 0, 0, g(Yes, No, false, false, "", "疒")}, - {0x2f68, 0, 0, 0, g(Yes, No, false, false, "", "癶")}, - {0x2f69, 0, 0, 0, g(Yes, No, false, false, "", "白")}, - {0x2f6a, 0, 0, 0, g(Yes, No, false, false, "", "皮")}, - {0x2f6b, 0, 0, 0, g(Yes, No, false, false, "", "皿")}, - {0x2f6c, 0, 0, 0, g(Yes, No, false, false, "", "目")}, - {0x2f6d, 0, 0, 0, g(Yes, No, false, false, "", "矛")}, - {0x2f6e, 0, 0, 0, g(Yes, No, false, false, "", "矢")}, - {0x2f6f, 0, 0, 0, g(Yes, No, false, false, "", "石")}, - {0x2f70, 0, 0, 0, g(Yes, No, false, false, "", "示")}, - {0x2f71, 0, 0, 0, g(Yes, No, false, false, "", "禸")}, - {0x2f72, 0, 0, 0, g(Yes, No, false, false, "", "禾")}, - {0x2f73, 0, 0, 0, g(Yes, No, false, false, "", "穴")}, - {0x2f74, 0, 0, 0, g(Yes, No, false, false, "", "立")}, - {0x2f75, 0, 0, 0, g(Yes, No, false, false, "", "竹")}, - {0x2f76, 0, 0, 0, g(Yes, No, false, false, "", "米")}, - {0x2f77, 0, 0, 0, g(Yes, No, false, false, "", "糸")}, - {0x2f78, 0, 0, 0, g(Yes, No, false, false, "", "缶")}, - {0x2f79, 0, 0, 0, g(Yes, No, false, false, "", "网")}, - {0x2f7a, 0, 0, 0, g(Yes, No, false, false, "", "羊")}, - {0x2f7b, 0, 0, 0, g(Yes, No, false, false, "", "羽")}, - {0x2f7c, 0, 0, 0, g(Yes, No, false, false, "", "老")}, - {0x2f7d, 0, 0, 0, g(Yes, No, false, false, "", "而")}, - {0x2f7e, 0, 0, 0, g(Yes, No, false, false, "", "耒")}, - {0x2f7f, 0, 0, 0, g(Yes, No, false, false, "", "耳")}, - {0x2f80, 0, 0, 0, g(Yes, No, false, false, "", "聿")}, - {0x2f81, 0, 0, 0, g(Yes, No, false, false, "", "肉")}, - {0x2f82, 0, 0, 0, g(Yes, No, false, false, "", "臣")}, - {0x2f83, 0, 0, 0, g(Yes, No, false, false, "", "自")}, - {0x2f84, 0, 0, 0, g(Yes, No, false, false, "", "至")}, - {0x2f85, 0, 0, 0, g(Yes, No, false, false, "", "臼")}, - {0x2f86, 0, 0, 0, g(Yes, No, false, false, "", "舌")}, - {0x2f87, 0, 0, 0, g(Yes, No, false, false, "", "舛")}, - {0x2f88, 0, 0, 0, g(Yes, No, false, false, "", "舟")}, - {0x2f89, 0, 0, 0, g(Yes, No, false, false, "", "艮")}, - {0x2f8a, 0, 0, 0, g(Yes, No, false, false, "", "色")}, - {0x2f8b, 0, 0, 0, g(Yes, No, false, false, "", "艸")}, - {0x2f8c, 0, 0, 0, g(Yes, No, false, false, "", "虍")}, - {0x2f8d, 0, 0, 0, g(Yes, No, false, false, "", "虫")}, - {0x2f8e, 0, 0, 0, g(Yes, No, false, false, "", "血")}, - {0x2f8f, 0, 0, 0, g(Yes, No, false, false, "", "行")}, - {0x2f90, 0, 0, 0, g(Yes, No, false, false, "", "衣")}, - {0x2f91, 0, 0, 0, g(Yes, No, false, false, "", "襾")}, - {0x2f92, 0, 0, 0, g(Yes, No, false, false, "", "見")}, - {0x2f93, 0, 0, 0, g(Yes, No, false, false, "", "角")}, - {0x2f94, 0, 0, 0, g(Yes, No, false, false, "", "言")}, - {0x2f95, 0, 0, 0, g(Yes, No, false, false, "", "谷")}, - {0x2f96, 0, 0, 0, g(Yes, No, false, false, "", "豆")}, - {0x2f97, 0, 0, 0, g(Yes, No, false, false, "", "豕")}, - {0x2f98, 0, 0, 0, g(Yes, No, false, false, "", "豸")}, - {0x2f99, 0, 0, 0, g(Yes, No, false, false, "", "貝")}, - {0x2f9a, 0, 0, 0, g(Yes, No, false, false, "", "赤")}, - {0x2f9b, 0, 0, 0, g(Yes, No, false, false, "", "走")}, - {0x2f9c, 0, 0, 0, g(Yes, No, false, false, "", "足")}, - {0x2f9d, 0, 0, 0, g(Yes, No, false, false, "", "身")}, - {0x2f9e, 0, 0, 0, g(Yes, No, false, false, "", "車")}, - {0x2f9f, 0, 0, 0, g(Yes, No, false, false, "", "辛")}, - {0x2fa0, 0, 0, 0, g(Yes, No, false, false, "", "辰")}, - {0x2fa1, 0, 0, 0, g(Yes, No, false, false, "", "辵")}, - {0x2fa2, 0, 0, 0, g(Yes, No, false, false, "", "邑")}, - {0x2fa3, 0, 0, 0, g(Yes, No, false, false, "", "酉")}, - {0x2fa4, 0, 0, 0, g(Yes, No, false, false, "", "釆")}, - {0x2fa5, 0, 0, 0, g(Yes, No, false, false, "", "里")}, - {0x2fa6, 0, 0, 0, g(Yes, No, false, false, "", "金")}, - {0x2fa7, 0, 0, 0, g(Yes, No, false, false, "", "長")}, - {0x2fa8, 0, 0, 0, g(Yes, No, false, false, "", "門")}, - {0x2fa9, 0, 0, 0, g(Yes, No, false, false, "", "阜")}, - {0x2faa, 0, 0, 0, g(Yes, No, false, false, "", "隶")}, - {0x2fab, 0, 0, 0, g(Yes, No, false, false, "", "隹")}, - {0x2fac, 0, 0, 0, g(Yes, No, false, false, "", "雨")}, - {0x2fad, 0, 0, 0, g(Yes, No, false, false, "", "靑")}, - {0x2fae, 0, 0, 0, g(Yes, No, false, false, "", "非")}, - {0x2faf, 0, 0, 0, g(Yes, No, false, false, "", "面")}, - {0x2fb0, 0, 0, 0, g(Yes, No, false, false, "", "革")}, - {0x2fb1, 0, 0, 0, g(Yes, No, false, false, "", "韋")}, - {0x2fb2, 0, 0, 0, g(Yes, No, false, false, "", "韭")}, - {0x2fb3, 0, 0, 0, g(Yes, No, false, false, "", "音")}, - {0x2fb4, 0, 0, 0, g(Yes, No, false, false, "", "頁")}, - {0x2fb5, 0, 0, 0, g(Yes, No, false, false, "", "風")}, - {0x2fb6, 0, 0, 0, g(Yes, No, false, false, "", "飛")}, - {0x2fb7, 0, 0, 0, g(Yes, No, false, false, "", "食")}, - {0x2fb8, 0, 0, 0, g(Yes, No, false, false, "", "首")}, - {0x2fb9, 0, 0, 0, g(Yes, No, false, false, "", "香")}, - {0x2fba, 0, 0, 0, g(Yes, No, false, false, "", "馬")}, - {0x2fbb, 0, 0, 0, g(Yes, No, false, false, "", "骨")}, - {0x2fbc, 0, 0, 0, g(Yes, No, false, false, "", "高")}, - {0x2fbd, 0, 0, 0, g(Yes, No, false, false, "", "髟")}, - {0x2fbe, 0, 0, 0, g(Yes, No, false, false, "", "鬥")}, - {0x2fbf, 0, 0, 0, g(Yes, No, false, false, "", "鬯")}, - {0x2fc0, 0, 0, 0, g(Yes, No, false, false, "", "鬲")}, - {0x2fc1, 0, 0, 0, g(Yes, No, false, false, "", "鬼")}, - {0x2fc2, 0, 0, 0, g(Yes, No, false, false, "", "魚")}, - {0x2fc3, 0, 0, 0, g(Yes, No, false, false, "", "鳥")}, - {0x2fc4, 0, 0, 0, g(Yes, No, false, false, "", "鹵")}, - {0x2fc5, 0, 0, 0, g(Yes, No, false, false, "", "鹿")}, - {0x2fc6, 0, 0, 0, g(Yes, No, false, false, "", "麥")}, - {0x2fc7, 0, 0, 0, g(Yes, No, false, false, "", "麻")}, - {0x2fc8, 0, 0, 0, g(Yes, No, false, false, "", "黃")}, - {0x2fc9, 0, 0, 0, g(Yes, No, false, false, "", "黍")}, - {0x2fca, 0, 0, 0, g(Yes, No, false, false, "", "黑")}, - {0x2fcb, 0, 0, 0, g(Yes, No, false, false, "", "黹")}, - {0x2fcc, 0, 0, 0, g(Yes, No, false, false, "", "黽")}, - {0x2fcd, 0, 0, 0, g(Yes, No, false, false, "", "鼎")}, - {0x2fce, 0, 0, 0, g(Yes, No, false, false, "", "鼓")}, - {0x2fcf, 0, 0, 0, g(Yes, No, false, false, "", "鼠")}, - {0x2fd0, 0, 0, 0, g(Yes, No, false, false, "", "鼻")}, - {0x2fd1, 0, 0, 0, g(Yes, No, false, false, "", "齊")}, - {0x2fd2, 0, 0, 0, g(Yes, No, false, false, "", "齒")}, - {0x2fd3, 0, 0, 0, g(Yes, No, false, false, "", "龍")}, - {0x2fd4, 0, 0, 0, g(Yes, No, false, false, "", "龜")}, - {0x2fd5, 0, 0, 0, g(Yes, No, false, false, "", "龠")}, - {0x2fd6, 0, 0, 0, f(Yes, false, "")}, - {0x3000, 0, 0, 0, g(Yes, No, false, false, "", " ")}, - {0x3001, 0, 0, 0, f(Yes, false, "")}, - {0x302a, 218, 1, 1, f(Yes, false, "")}, - {0x302b, 228, 1, 1, f(Yes, false, "")}, - {0x302c, 232, 1, 1, f(Yes, false, "")}, - {0x302d, 222, 1, 1, f(Yes, false, "")}, - {0x302e, 224, 1, 1, f(Yes, false, "")}, - {0x3030, 0, 0, 0, f(Yes, false, "")}, - {0x3036, 0, 0, 0, g(Yes, No, false, false, "", "〒")}, - {0x3037, 0, 0, 0, f(Yes, false, "")}, - {0x3038, 0, 0, 0, g(Yes, No, false, false, "", "十")}, - {0x3039, 0, 0, 0, g(Yes, No, false, false, "", "卄")}, - {0x303a, 0, 0, 0, g(Yes, No, false, false, "", "卅")}, - {0x303b, 0, 0, 0, f(Yes, false, "")}, - {0x3046, 0, 0, 0, f(Yes, true, "")}, - {0x3047, 0, 0, 0, f(Yes, false, "")}, - {0x304b, 0, 0, 0, f(Yes, true, "")}, - {0x304c, 0, 0, 1, f(Yes, false, "が")}, - {0x304d, 0, 0, 0, f(Yes, true, "")}, - {0x304e, 0, 0, 1, f(Yes, false, "ぎ")}, - {0x304f, 0, 0, 0, f(Yes, true, "")}, - {0x3050, 0, 0, 1, f(Yes, false, "ぐ")}, - {0x3051, 0, 0, 0, f(Yes, true, "")}, - {0x3052, 0, 0, 1, f(Yes, false, "げ")}, - {0x3053, 0, 0, 0, f(Yes, true, "")}, - {0x3054, 0, 0, 1, f(Yes, false, "ご")}, - {0x3055, 0, 0, 0, f(Yes, true, "")}, - {0x3056, 0, 0, 1, f(Yes, false, "ざ")}, - {0x3057, 0, 0, 0, f(Yes, true, "")}, - {0x3058, 0, 0, 1, f(Yes, false, "じ")}, - {0x3059, 0, 0, 0, f(Yes, true, "")}, - {0x305a, 0, 0, 1, f(Yes, false, "ず")}, - {0x305b, 0, 0, 0, f(Yes, true, "")}, - {0x305c, 0, 0, 1, f(Yes, false, "ぜ")}, - {0x305d, 0, 0, 0, f(Yes, true, "")}, - {0x305e, 0, 0, 1, f(Yes, false, "ぞ")}, - {0x305f, 0, 0, 0, f(Yes, true, "")}, - {0x3060, 0, 0, 1, f(Yes, false, "だ")}, - {0x3061, 0, 0, 0, f(Yes, true, "")}, - {0x3062, 0, 0, 1, f(Yes, false, "ぢ")}, - {0x3063, 0, 0, 0, f(Yes, false, "")}, - {0x3064, 0, 0, 0, f(Yes, true, "")}, - {0x3065, 0, 0, 1, f(Yes, false, "づ")}, - {0x3066, 0, 0, 0, f(Yes, true, "")}, - {0x3067, 0, 0, 1, f(Yes, false, "で")}, - {0x3068, 0, 0, 0, f(Yes, true, "")}, - {0x3069, 0, 0, 1, f(Yes, false, "ど")}, - {0x306a, 0, 0, 0, f(Yes, false, "")}, - {0x306f, 0, 0, 0, f(Yes, true, "")}, - {0x3070, 0, 0, 1, f(Yes, false, "ば")}, - {0x3071, 0, 0, 1, f(Yes, false, "ぱ")}, - {0x3072, 0, 0, 0, f(Yes, true, "")}, - {0x3073, 0, 0, 1, f(Yes, false, "び")}, - {0x3074, 0, 0, 1, f(Yes, false, "ぴ")}, - {0x3075, 0, 0, 0, f(Yes, true, "")}, - {0x3076, 0, 0, 1, f(Yes, false, "ぶ")}, - {0x3077, 0, 0, 1, f(Yes, false, "ぷ")}, - {0x3078, 0, 0, 0, f(Yes, true, "")}, - {0x3079, 0, 0, 1, f(Yes, false, "べ")}, - {0x307a, 0, 0, 1, f(Yes, false, "ぺ")}, - {0x307b, 0, 0, 0, f(Yes, true, "")}, - {0x307c, 0, 0, 1, f(Yes, false, "ぼ")}, - {0x307d, 0, 0, 1, f(Yes, false, "ぽ")}, - {0x307e, 0, 0, 0, f(Yes, false, "")}, - {0x3094, 0, 0, 1, f(Yes, false, "ゔ")}, - {0x3095, 0, 0, 0, f(Yes, false, "")}, - {0x3099, 8, 1, 1, f(Maybe, false, "")}, - {0x309b, 0, 0, 1, g(Yes, No, false, false, "", " ゙")}, - {0x309c, 0, 0, 1, g(Yes, No, false, false, "", " ゚")}, - {0x309d, 0, 0, 0, f(Yes, true, "")}, - {0x309e, 0, 0, 1, f(Yes, false, "ゞ")}, - {0x309f, 0, 0, 0, g(Yes, No, false, false, "", "より")}, - {0x30a0, 0, 0, 0, f(Yes, false, "")}, - {0x30a6, 0, 0, 0, f(Yes, true, "")}, - {0x30a7, 0, 0, 0, f(Yes, false, "")}, - {0x30ab, 0, 0, 0, f(Yes, true, "")}, - {0x30ac, 0, 0, 1, f(Yes, false, "ガ")}, - {0x30ad, 0, 0, 0, f(Yes, true, "")}, - {0x30ae, 0, 0, 1, f(Yes, false, "ギ")}, - {0x30af, 0, 0, 0, f(Yes, true, "")}, - {0x30b0, 0, 0, 1, f(Yes, false, "グ")}, - {0x30b1, 0, 0, 0, f(Yes, true, "")}, - {0x30b2, 0, 0, 1, f(Yes, false, "ゲ")}, - {0x30b3, 0, 0, 0, f(Yes, true, "")}, - {0x30b4, 0, 0, 1, f(Yes, false, "ゴ")}, - {0x30b5, 0, 0, 0, f(Yes, true, "")}, - {0x30b6, 0, 0, 1, f(Yes, false, "ザ")}, - {0x30b7, 0, 0, 0, f(Yes, true, "")}, - {0x30b8, 0, 0, 1, f(Yes, false, "ジ")}, - {0x30b9, 0, 0, 0, f(Yes, true, "")}, - {0x30ba, 0, 0, 1, f(Yes, false, "ズ")}, - {0x30bb, 0, 0, 0, f(Yes, true, "")}, - {0x30bc, 0, 0, 1, f(Yes, false, "ゼ")}, - {0x30bd, 0, 0, 0, f(Yes, true, "")}, - {0x30be, 0, 0, 1, f(Yes, false, "ゾ")}, - {0x30bf, 0, 0, 0, f(Yes, true, "")}, - {0x30c0, 0, 0, 1, f(Yes, false, "ダ")}, - {0x30c1, 0, 0, 0, f(Yes, true, "")}, - {0x30c2, 0, 0, 1, f(Yes, false, "ヂ")}, - {0x30c3, 0, 0, 0, f(Yes, false, "")}, - {0x30c4, 0, 0, 0, f(Yes, true, "")}, - {0x30c5, 0, 0, 1, f(Yes, false, "ヅ")}, - {0x30c6, 0, 0, 0, f(Yes, true, "")}, - {0x30c7, 0, 0, 1, f(Yes, false, "デ")}, - {0x30c8, 0, 0, 0, f(Yes, true, "")}, - {0x30c9, 0, 0, 1, f(Yes, false, "ド")}, - {0x30ca, 0, 0, 0, f(Yes, false, "")}, - {0x30cf, 0, 0, 0, f(Yes, true, "")}, - {0x30d0, 0, 0, 1, f(Yes, false, "バ")}, - {0x30d1, 0, 0, 1, f(Yes, false, "パ")}, - {0x30d2, 0, 0, 0, f(Yes, true, "")}, - {0x30d3, 0, 0, 1, f(Yes, false, "ビ")}, - {0x30d4, 0, 0, 1, f(Yes, false, "ピ")}, - {0x30d5, 0, 0, 0, f(Yes, true, "")}, - {0x30d6, 0, 0, 1, f(Yes, false, "ブ")}, - {0x30d7, 0, 0, 1, f(Yes, false, "プ")}, - {0x30d8, 0, 0, 0, f(Yes, true, "")}, - {0x30d9, 0, 0, 1, f(Yes, false, "ベ")}, - {0x30da, 0, 0, 1, f(Yes, false, "ペ")}, - {0x30db, 0, 0, 0, f(Yes, true, "")}, - {0x30dc, 0, 0, 1, f(Yes, false, "ボ")}, - {0x30dd, 0, 0, 1, f(Yes, false, "ポ")}, - {0x30de, 0, 0, 0, f(Yes, false, "")}, - {0x30ef, 0, 0, 0, f(Yes, true, "")}, - {0x30f3, 0, 0, 0, f(Yes, false, "")}, - {0x30f4, 0, 0, 1, f(Yes, false, "ヴ")}, - {0x30f5, 0, 0, 0, f(Yes, false, "")}, - {0x30f7, 0, 0, 1, f(Yes, false, "ヷ")}, - {0x30f8, 0, 0, 1, f(Yes, false, "ヸ")}, - {0x30f9, 0, 0, 1, f(Yes, false, "ヹ")}, - {0x30fa, 0, 0, 1, f(Yes, false, "ヺ")}, - {0x30fb, 0, 0, 0, f(Yes, false, "")}, - {0x30fd, 0, 0, 0, f(Yes, true, "")}, - {0x30fe, 0, 0, 1, f(Yes, false, "ヾ")}, - {0x30ff, 0, 0, 0, g(Yes, No, false, false, "", "コト")}, - {0x3100, 0, 0, 0, f(Yes, false, "")}, - {0x3131, 0, 0, 0, g(Yes, No, false, false, "", "ᄀ")}, - {0x3132, 0, 0, 0, g(Yes, No, false, false, "", "ᄁ")}, - {0x3133, 0, 1, 1, g(Yes, No, false, false, "", "ᆪ")}, - {0x3134, 0, 0, 0, g(Yes, No, false, false, "", "ᄂ")}, - {0x3135, 0, 1, 1, g(Yes, No, false, false, "", "ᆬ")}, - {0x3136, 0, 1, 1, g(Yes, No, false, false, "", "ᆭ")}, - {0x3137, 0, 0, 0, g(Yes, No, false, false, "", "ᄃ")}, - {0x3138, 0, 0, 0, g(Yes, No, false, false, "", "ᄄ")}, - {0x3139, 0, 0, 0, g(Yes, No, false, false, "", "ᄅ")}, - {0x313a, 0, 1, 1, g(Yes, No, false, false, "", "ᆰ")}, - {0x313b, 0, 1, 1, g(Yes, No, false, false, "", "ᆱ")}, - {0x313c, 0, 1, 1, g(Yes, No, false, false, "", "ᆲ")}, - {0x313d, 0, 1, 1, g(Yes, No, false, false, "", "ᆳ")}, - {0x313e, 0, 1, 1, g(Yes, No, false, false, "", "ᆴ")}, - {0x313f, 0, 1, 1, g(Yes, No, false, false, "", "ᆵ")}, - {0x3140, 0, 0, 0, g(Yes, No, false, false, "", "ᄚ")}, - {0x3141, 0, 0, 0, g(Yes, No, false, false, "", "ᄆ")}, - {0x3142, 0, 0, 0, g(Yes, No, false, false, "", "ᄇ")}, - {0x3143, 0, 0, 0, g(Yes, No, false, false, "", "ᄈ")}, - {0x3144, 0, 0, 0, g(Yes, No, false, false, "", "ᄡ")}, - {0x3145, 0, 0, 0, g(Yes, No, false, false, "", "ᄉ")}, - {0x3146, 0, 0, 0, g(Yes, No, false, false, "", "ᄊ")}, - {0x3147, 0, 0, 0, g(Yes, No, false, false, "", "ᄋ")}, - {0x3148, 0, 0, 0, g(Yes, No, false, false, "", "ᄌ")}, - {0x3149, 0, 0, 0, g(Yes, No, false, false, "", "ᄍ")}, - {0x314a, 0, 0, 0, g(Yes, No, false, false, "", "ᄎ")}, - {0x314b, 0, 0, 0, g(Yes, No, false, false, "", "ᄏ")}, - {0x314c, 0, 0, 0, g(Yes, No, false, false, "", "ᄐ")}, - {0x314d, 0, 0, 0, g(Yes, No, false, false, "", "ᄑ")}, - {0x314e, 0, 0, 0, g(Yes, No, false, false, "", "ᄒ")}, - {0x314f, 0, 1, 1, g(Yes, No, false, false, "", "ᅡ")}, - {0x3150, 0, 1, 1, g(Yes, No, false, false, "", "ᅢ")}, - {0x3151, 0, 1, 1, g(Yes, No, false, false, "", "ᅣ")}, - {0x3152, 0, 1, 1, g(Yes, No, false, false, "", "ᅤ")}, - {0x3153, 0, 1, 1, g(Yes, No, false, false, "", "ᅥ")}, - {0x3154, 0, 1, 1, g(Yes, No, false, false, "", "ᅦ")}, - {0x3155, 0, 1, 1, g(Yes, No, false, false, "", "ᅧ")}, - {0x3156, 0, 1, 1, g(Yes, No, false, false, "", "ᅨ")}, - {0x3157, 0, 1, 1, g(Yes, No, false, false, "", "ᅩ")}, - {0x3158, 0, 1, 1, g(Yes, No, false, false, "", "ᅪ")}, - {0x3159, 0, 1, 1, g(Yes, No, false, false, "", "ᅫ")}, - {0x315a, 0, 1, 1, g(Yes, No, false, false, "", "ᅬ")}, - {0x315b, 0, 1, 1, g(Yes, No, false, false, "", "ᅭ")}, - {0x315c, 0, 1, 1, g(Yes, No, false, false, "", "ᅮ")}, - {0x315d, 0, 1, 1, g(Yes, No, false, false, "", "ᅯ")}, - {0x315e, 0, 1, 1, g(Yes, No, false, false, "", "ᅰ")}, - {0x315f, 0, 1, 1, g(Yes, No, false, false, "", "ᅱ")}, - {0x3160, 0, 1, 1, g(Yes, No, false, false, "", "ᅲ")}, - {0x3161, 0, 1, 1, g(Yes, No, false, false, "", "ᅳ")}, - {0x3162, 0, 1, 1, g(Yes, No, false, false, "", "ᅴ")}, - {0x3163, 0, 1, 1, g(Yes, No, false, false, "", "ᅵ")}, - {0x3164, 0, 0, 0, g(Yes, No, false, false, "", "ᅠ")}, - {0x3165, 0, 0, 0, g(Yes, No, false, false, "", "ᄔ")}, - {0x3166, 0, 0, 0, g(Yes, No, false, false, "", "ᄕ")}, - {0x3167, 0, 0, 0, g(Yes, No, false, false, "", "ᇇ")}, - {0x3168, 0, 0, 0, g(Yes, No, false, false, "", "ᇈ")}, - {0x3169, 0, 0, 0, g(Yes, No, false, false, "", "ᇌ")}, - {0x316a, 0, 0, 0, g(Yes, No, false, false, "", "ᇎ")}, - {0x316b, 0, 0, 0, g(Yes, No, false, false, "", "ᇓ")}, - {0x316c, 0, 0, 0, g(Yes, No, false, false, "", "ᇗ")}, - {0x316d, 0, 0, 0, g(Yes, No, false, false, "", "ᇙ")}, - {0x316e, 0, 0, 0, g(Yes, No, false, false, "", "ᄜ")}, - {0x316f, 0, 0, 0, g(Yes, No, false, false, "", "ᇝ")}, - {0x3170, 0, 0, 0, g(Yes, No, false, false, "", "ᇟ")}, - {0x3171, 0, 0, 0, g(Yes, No, false, false, "", "ᄝ")}, - {0x3172, 0, 0, 0, g(Yes, No, false, false, "", "ᄞ")}, - {0x3173, 0, 0, 0, g(Yes, No, false, false, "", "ᄠ")}, - {0x3174, 0, 0, 0, g(Yes, No, false, false, "", "ᄢ")}, - {0x3175, 0, 0, 0, g(Yes, No, false, false, "", "ᄣ")}, - {0x3176, 0, 0, 0, g(Yes, No, false, false, "", "ᄧ")}, - {0x3177, 0, 0, 0, g(Yes, No, false, false, "", "ᄩ")}, - {0x3178, 0, 0, 0, g(Yes, No, false, false, "", "ᄫ")}, - {0x3179, 0, 0, 0, g(Yes, No, false, false, "", "ᄬ")}, - {0x317a, 0, 0, 0, g(Yes, No, false, false, "", "ᄭ")}, - {0x317b, 0, 0, 0, g(Yes, No, false, false, "", "ᄮ")}, - {0x317c, 0, 0, 0, g(Yes, No, false, false, "", "ᄯ")}, - {0x317d, 0, 0, 0, g(Yes, No, false, false, "", "ᄲ")}, - {0x317e, 0, 0, 0, g(Yes, No, false, false, "", "ᄶ")}, - {0x317f, 0, 0, 0, g(Yes, No, false, false, "", "ᅀ")}, - {0x3180, 0, 0, 0, g(Yes, No, false, false, "", "ᅇ")}, - {0x3181, 0, 0, 0, g(Yes, No, false, false, "", "ᅌ")}, - {0x3182, 0, 0, 0, g(Yes, No, false, false, "", "ᇱ")}, - {0x3183, 0, 0, 0, g(Yes, No, false, false, "", "ᇲ")}, - {0x3184, 0, 0, 0, g(Yes, No, false, false, "", "ᅗ")}, - {0x3185, 0, 0, 0, g(Yes, No, false, false, "", "ᅘ")}, - {0x3186, 0, 0, 0, g(Yes, No, false, false, "", "ᅙ")}, - {0x3187, 0, 0, 0, g(Yes, No, false, false, "", "ᆄ")}, - {0x3188, 0, 0, 0, g(Yes, No, false, false, "", "ᆅ")}, - {0x3189, 0, 0, 0, g(Yes, No, false, false, "", "ᆈ")}, - {0x318a, 0, 0, 0, g(Yes, No, false, false, "", "ᆑ")}, - {0x318b, 0, 0, 0, g(Yes, No, false, false, "", "ᆒ")}, - {0x318c, 0, 0, 0, g(Yes, No, false, false, "", "ᆔ")}, - {0x318d, 0, 0, 0, g(Yes, No, false, false, "", "ᆞ")}, - {0x318e, 0, 0, 0, g(Yes, No, false, false, "", "ᆡ")}, - {0x318f, 0, 0, 0, f(Yes, false, "")}, - {0x3192, 0, 0, 0, g(Yes, No, false, false, "", "一")}, - {0x3193, 0, 0, 0, g(Yes, No, false, false, "", "二")}, - {0x3194, 0, 0, 0, g(Yes, No, false, false, "", "三")}, - {0x3195, 0, 0, 0, g(Yes, No, false, false, "", "四")}, - {0x3196, 0, 0, 0, g(Yes, No, false, false, "", "上")}, - {0x3197, 0, 0, 0, g(Yes, No, false, false, "", "中")}, - {0x3198, 0, 0, 0, g(Yes, No, false, false, "", "下")}, - {0x3199, 0, 0, 0, g(Yes, No, false, false, "", "甲")}, - {0x319a, 0, 0, 0, g(Yes, No, false, false, "", "乙")}, - {0x319b, 0, 0, 0, g(Yes, No, false, false, "", "丙")}, - {0x319c, 0, 0, 0, g(Yes, No, false, false, "", "丁")}, - {0x319d, 0, 0, 0, g(Yes, No, false, false, "", "天")}, - {0x319e, 0, 0, 0, g(Yes, No, false, false, "", "地")}, - {0x319f, 0, 0, 0, g(Yes, No, false, false, "", "人")}, - {0x31a0, 0, 0, 0, f(Yes, false, "")}, - {0x3200, 0, 0, 0, g(Yes, No, false, false, "", "(ᄀ)")}, - {0x3201, 0, 0, 0, g(Yes, No, false, false, "", "(ᄂ)")}, - {0x3202, 0, 0, 0, g(Yes, No, false, false, "", "(ᄃ)")}, - {0x3203, 0, 0, 0, g(Yes, No, false, false, "", "(ᄅ)")}, - {0x3204, 0, 0, 0, g(Yes, No, false, false, "", "(ᄆ)")}, - {0x3205, 0, 0, 0, g(Yes, No, false, false, "", "(ᄇ)")}, - {0x3206, 0, 0, 0, g(Yes, No, false, false, "", "(ᄉ)")}, - {0x3207, 0, 0, 0, g(Yes, No, false, false, "", "(ᄋ)")}, - {0x3208, 0, 0, 0, g(Yes, No, false, false, "", "(ᄌ)")}, - {0x3209, 0, 0, 0, g(Yes, No, false, false, "", "(ᄎ)")}, - {0x320a, 0, 0, 0, g(Yes, No, false, false, "", "(ᄏ)")}, - {0x320b, 0, 0, 0, g(Yes, No, false, false, "", "(ᄐ)")}, - {0x320c, 0, 0, 0, g(Yes, No, false, false, "", "(ᄑ)")}, - {0x320d, 0, 0, 0, g(Yes, No, false, false, "", "(ᄒ)")}, - {0x320e, 0, 0, 0, g(Yes, No, false, false, "", "(가)")}, - {0x320f, 0, 0, 0, g(Yes, No, false, false, "", "(나)")}, - {0x3210, 0, 0, 0, g(Yes, No, false, false, "", "(다)")}, - {0x3211, 0, 0, 0, g(Yes, No, false, false, "", "(라)")}, - {0x3212, 0, 0, 0, g(Yes, No, false, false, "", "(마)")}, - {0x3213, 0, 0, 0, g(Yes, No, false, false, "", "(바)")}, - {0x3214, 0, 0, 0, g(Yes, No, false, false, "", "(사)")}, - {0x3215, 0, 0, 0, g(Yes, No, false, false, "", "(아)")}, - {0x3216, 0, 0, 0, g(Yes, No, false, false, "", "(자)")}, - {0x3217, 0, 0, 0, g(Yes, No, false, false, "", "(차)")}, - {0x3218, 0, 0, 0, g(Yes, No, false, false, "", "(카)")}, - {0x3219, 0, 0, 0, g(Yes, No, false, false, "", "(타)")}, - {0x321a, 0, 0, 0, g(Yes, No, false, false, "", "(파)")}, - {0x321b, 0, 0, 0, g(Yes, No, false, false, "", "(하)")}, - {0x321c, 0, 0, 0, g(Yes, No, false, false, "", "(주)")}, - {0x321d, 0, 0, 0, g(Yes, No, false, false, "", "(오전)")}, - {0x321e, 0, 0, 0, g(Yes, No, false, false, "", "(오후)")}, - {0x321f, 0, 0, 0, f(Yes, false, "")}, - {0x3220, 0, 0, 0, g(Yes, No, false, false, "", "(一)")}, - {0x3221, 0, 0, 0, g(Yes, No, false, false, "", "(二)")}, - {0x3222, 0, 0, 0, g(Yes, No, false, false, "", "(三)")}, - {0x3223, 0, 0, 0, g(Yes, No, false, false, "", "(四)")}, - {0x3224, 0, 0, 0, g(Yes, No, false, false, "", "(五)")}, - {0x3225, 0, 0, 0, g(Yes, No, false, false, "", "(六)")}, - {0x3226, 0, 0, 0, g(Yes, No, false, false, "", "(七)")}, - {0x3227, 0, 0, 0, g(Yes, No, false, false, "", "(八)")}, - {0x3228, 0, 0, 0, g(Yes, No, false, false, "", "(九)")}, - {0x3229, 0, 0, 0, g(Yes, No, false, false, "", "(十)")}, - {0x322a, 0, 0, 0, g(Yes, No, false, false, "", "(月)")}, - {0x322b, 0, 0, 0, g(Yes, No, false, false, "", "(火)")}, - {0x322c, 0, 0, 0, g(Yes, No, false, false, "", "(水)")}, - {0x322d, 0, 0, 0, g(Yes, No, false, false, "", "(木)")}, - {0x322e, 0, 0, 0, g(Yes, No, false, false, "", "(金)")}, - {0x322f, 0, 0, 0, g(Yes, No, false, false, "", "(土)")}, - {0x3230, 0, 0, 0, g(Yes, No, false, false, "", "(日)")}, - {0x3231, 0, 0, 0, g(Yes, No, false, false, "", "(株)")}, - {0x3232, 0, 0, 0, g(Yes, No, false, false, "", "(有)")}, - {0x3233, 0, 0, 0, g(Yes, No, false, false, "", "(社)")}, - {0x3234, 0, 0, 0, g(Yes, No, false, false, "", "(名)")}, - {0x3235, 0, 0, 0, g(Yes, No, false, false, "", "(特)")}, - {0x3236, 0, 0, 0, g(Yes, No, false, false, "", "(財)")}, - {0x3237, 0, 0, 0, g(Yes, No, false, false, "", "(祝)")}, - {0x3238, 0, 0, 0, g(Yes, No, false, false, "", "(労)")}, - {0x3239, 0, 0, 0, g(Yes, No, false, false, "", "(代)")}, - {0x323a, 0, 0, 0, g(Yes, No, false, false, "", "(呼)")}, - {0x323b, 0, 0, 0, g(Yes, No, false, false, "", "(学)")}, - {0x323c, 0, 0, 0, g(Yes, No, false, false, "", "(監)")}, - {0x323d, 0, 0, 0, g(Yes, No, false, false, "", "(企)")}, - {0x323e, 0, 0, 0, g(Yes, No, false, false, "", "(資)")}, - {0x323f, 0, 0, 0, g(Yes, No, false, false, "", "(協)")}, - {0x3240, 0, 0, 0, g(Yes, No, false, false, "", "(祭)")}, - {0x3241, 0, 0, 0, g(Yes, No, false, false, "", "(休)")}, - {0x3242, 0, 0, 0, g(Yes, No, false, false, "", "(自)")}, - {0x3243, 0, 0, 0, g(Yes, No, false, false, "", "(至)")}, - {0x3244, 0, 0, 0, g(Yes, No, false, false, "", "問")}, - {0x3245, 0, 0, 0, g(Yes, No, false, false, "", "幼")}, - {0x3246, 0, 0, 0, g(Yes, No, false, false, "", "文")}, - {0x3247, 0, 0, 0, g(Yes, No, false, false, "", "箏")}, - {0x3248, 0, 0, 0, f(Yes, false, "")}, - {0x3250, 0, 0, 0, g(Yes, No, false, false, "", "PTE")}, - {0x3251, 0, 0, 0, g(Yes, No, false, false, "", "21")}, - {0x3252, 0, 0, 0, g(Yes, No, false, false, "", "22")}, - {0x3253, 0, 0, 0, g(Yes, No, false, false, "", "23")}, - {0x3254, 0, 0, 0, g(Yes, No, false, false, "", "24")}, - {0x3255, 0, 0, 0, g(Yes, No, false, false, "", "25")}, - {0x3256, 0, 0, 0, g(Yes, No, false, false, "", "26")}, - {0x3257, 0, 0, 0, g(Yes, No, false, false, "", "27")}, - {0x3258, 0, 0, 0, g(Yes, No, false, false, "", "28")}, - {0x3259, 0, 0, 0, g(Yes, No, false, false, "", "29")}, - {0x325a, 0, 0, 0, g(Yes, No, false, false, "", "30")}, - {0x325b, 0, 0, 0, g(Yes, No, false, false, "", "31")}, - {0x325c, 0, 0, 0, g(Yes, No, false, false, "", "32")}, - {0x325d, 0, 0, 0, g(Yes, No, false, false, "", "33")}, - {0x325e, 0, 0, 0, g(Yes, No, false, false, "", "34")}, - {0x325f, 0, 0, 0, g(Yes, No, false, false, "", "35")}, - {0x3260, 0, 0, 0, g(Yes, No, false, false, "", "ᄀ")}, - {0x3261, 0, 0, 0, g(Yes, No, false, false, "", "ᄂ")}, - {0x3262, 0, 0, 0, g(Yes, No, false, false, "", "ᄃ")}, - {0x3263, 0, 0, 0, g(Yes, No, false, false, "", "ᄅ")}, - {0x3264, 0, 0, 0, g(Yes, No, false, false, "", "ᄆ")}, - {0x3265, 0, 0, 0, g(Yes, No, false, false, "", "ᄇ")}, - {0x3266, 0, 0, 0, g(Yes, No, false, false, "", "ᄉ")}, - {0x3267, 0, 0, 0, g(Yes, No, false, false, "", "ᄋ")}, - {0x3268, 0, 0, 0, g(Yes, No, false, false, "", "ᄌ")}, - {0x3269, 0, 0, 0, g(Yes, No, false, false, "", "ᄎ")}, - {0x326a, 0, 0, 0, g(Yes, No, false, false, "", "ᄏ")}, - {0x326b, 0, 0, 0, g(Yes, No, false, false, "", "ᄐ")}, - {0x326c, 0, 0, 0, g(Yes, No, false, false, "", "ᄑ")}, - {0x326d, 0, 0, 0, g(Yes, No, false, false, "", "ᄒ")}, - {0x326e, 0, 0, 1, g(Yes, No, false, false, "", "가")}, - {0x326f, 0, 0, 1, g(Yes, No, false, false, "", "나")}, - {0x3270, 0, 0, 1, g(Yes, No, false, false, "", "다")}, - {0x3271, 0, 0, 1, g(Yes, No, false, false, "", "라")}, - {0x3272, 0, 0, 1, g(Yes, No, false, false, "", "마")}, - {0x3273, 0, 0, 1, g(Yes, No, false, false, "", "바")}, - {0x3274, 0, 0, 1, g(Yes, No, false, false, "", "사")}, - {0x3275, 0, 0, 1, g(Yes, No, false, false, "", "아")}, - {0x3276, 0, 0, 1, g(Yes, No, false, false, "", "자")}, - {0x3277, 0, 0, 1, g(Yes, No, false, false, "", "차")}, - {0x3278, 0, 0, 1, g(Yes, No, false, false, "", "카")}, - {0x3279, 0, 0, 1, g(Yes, No, false, false, "", "타")}, - {0x327a, 0, 0, 1, g(Yes, No, false, false, "", "파")}, - {0x327b, 0, 0, 1, g(Yes, No, false, false, "", "하")}, - {0x327c, 0, 0, 1, g(Yes, No, false, false, "", "참고")}, - {0x327d, 0, 0, 1, g(Yes, No, false, false, "", "주의")}, - {0x327e, 0, 0, 1, g(Yes, No, false, false, "", "우")}, - {0x327f, 0, 0, 0, f(Yes, false, "")}, - {0x3280, 0, 0, 0, g(Yes, No, false, false, "", "一")}, - {0x3281, 0, 0, 0, g(Yes, No, false, false, "", "二")}, - {0x3282, 0, 0, 0, g(Yes, No, false, false, "", "三")}, - {0x3283, 0, 0, 0, g(Yes, No, false, false, "", "四")}, - {0x3284, 0, 0, 0, g(Yes, No, false, false, "", "五")}, - {0x3285, 0, 0, 0, g(Yes, No, false, false, "", "六")}, - {0x3286, 0, 0, 0, g(Yes, No, false, false, "", "七")}, - {0x3287, 0, 0, 0, g(Yes, No, false, false, "", "八")}, - {0x3288, 0, 0, 0, g(Yes, No, false, false, "", "九")}, - {0x3289, 0, 0, 0, g(Yes, No, false, false, "", "十")}, - {0x328a, 0, 0, 0, g(Yes, No, false, false, "", "月")}, - {0x328b, 0, 0, 0, g(Yes, No, false, false, "", "火")}, - {0x328c, 0, 0, 0, g(Yes, No, false, false, "", "水")}, - {0x328d, 0, 0, 0, g(Yes, No, false, false, "", "木")}, - {0x328e, 0, 0, 0, g(Yes, No, false, false, "", "金")}, - {0x328f, 0, 0, 0, g(Yes, No, false, false, "", "土")}, - {0x3290, 0, 0, 0, g(Yes, No, false, false, "", "日")}, - {0x3291, 0, 0, 0, g(Yes, No, false, false, "", "株")}, - {0x3292, 0, 0, 0, g(Yes, No, false, false, "", "有")}, - {0x3293, 0, 0, 0, g(Yes, No, false, false, "", "社")}, - {0x3294, 0, 0, 0, g(Yes, No, false, false, "", "名")}, - {0x3295, 0, 0, 0, g(Yes, No, false, false, "", "特")}, - {0x3296, 0, 0, 0, g(Yes, No, false, false, "", "財")}, - {0x3297, 0, 0, 0, g(Yes, No, false, false, "", "祝")}, - {0x3298, 0, 0, 0, g(Yes, No, false, false, "", "労")}, - {0x3299, 0, 0, 0, g(Yes, No, false, false, "", "秘")}, - {0x329a, 0, 0, 0, g(Yes, No, false, false, "", "男")}, - {0x329b, 0, 0, 0, g(Yes, No, false, false, "", "女")}, - {0x329c, 0, 0, 0, g(Yes, No, false, false, "", "適")}, - {0x329d, 0, 0, 0, g(Yes, No, false, false, "", "優")}, - {0x329e, 0, 0, 0, g(Yes, No, false, false, "", "印")}, - {0x329f, 0, 0, 0, g(Yes, No, false, false, "", "注")}, - {0x32a0, 0, 0, 0, g(Yes, No, false, false, "", "項")}, - {0x32a1, 0, 0, 0, g(Yes, No, false, false, "", "休")}, - {0x32a2, 0, 0, 0, g(Yes, No, false, false, "", "写")}, - {0x32a3, 0, 0, 0, g(Yes, No, false, false, "", "正")}, - {0x32a4, 0, 0, 0, g(Yes, No, false, false, "", "上")}, - {0x32a5, 0, 0, 0, g(Yes, No, false, false, "", "中")}, - {0x32a6, 0, 0, 0, g(Yes, No, false, false, "", "下")}, - {0x32a7, 0, 0, 0, g(Yes, No, false, false, "", "左")}, - {0x32a8, 0, 0, 0, g(Yes, No, false, false, "", "右")}, - {0x32a9, 0, 0, 0, g(Yes, No, false, false, "", "医")}, - {0x32aa, 0, 0, 0, g(Yes, No, false, false, "", "宗")}, - {0x32ab, 0, 0, 0, g(Yes, No, false, false, "", "学")}, - {0x32ac, 0, 0, 0, g(Yes, No, false, false, "", "監")}, - {0x32ad, 0, 0, 0, g(Yes, No, false, false, "", "企")}, - {0x32ae, 0, 0, 0, g(Yes, No, false, false, "", "資")}, - {0x32af, 0, 0, 0, g(Yes, No, false, false, "", "協")}, - {0x32b0, 0, 0, 0, g(Yes, No, false, false, "", "夜")}, - {0x32b1, 0, 0, 0, g(Yes, No, false, false, "", "36")}, - {0x32b2, 0, 0, 0, g(Yes, No, false, false, "", "37")}, - {0x32b3, 0, 0, 0, g(Yes, No, false, false, "", "38")}, - {0x32b4, 0, 0, 0, g(Yes, No, false, false, "", "39")}, - {0x32b5, 0, 0, 0, g(Yes, No, false, false, "", "40")}, - {0x32b6, 0, 0, 0, g(Yes, No, false, false, "", "41")}, - {0x32b7, 0, 0, 0, g(Yes, No, false, false, "", "42")}, - {0x32b8, 0, 0, 0, g(Yes, No, false, false, "", "43")}, - {0x32b9, 0, 0, 0, g(Yes, No, false, false, "", "44")}, - {0x32ba, 0, 0, 0, g(Yes, No, false, false, "", "45")}, - {0x32bb, 0, 0, 0, g(Yes, No, false, false, "", "46")}, - {0x32bc, 0, 0, 0, g(Yes, No, false, false, "", "47")}, - {0x32bd, 0, 0, 0, g(Yes, No, false, false, "", "48")}, - {0x32be, 0, 0, 0, g(Yes, No, false, false, "", "49")}, - {0x32bf, 0, 0, 0, g(Yes, No, false, false, "", "50")}, - {0x32c0, 0, 0, 0, g(Yes, No, false, false, "", "1月")}, - {0x32c1, 0, 0, 0, g(Yes, No, false, false, "", "2月")}, - {0x32c2, 0, 0, 0, g(Yes, No, false, false, "", "3月")}, - {0x32c3, 0, 0, 0, g(Yes, No, false, false, "", "4月")}, - {0x32c4, 0, 0, 0, g(Yes, No, false, false, "", "5月")}, - {0x32c5, 0, 0, 0, g(Yes, No, false, false, "", "6月")}, - {0x32c6, 0, 0, 0, g(Yes, No, false, false, "", "7月")}, - {0x32c7, 0, 0, 0, g(Yes, No, false, false, "", "8月")}, - {0x32c8, 0, 0, 0, g(Yes, No, false, false, "", "9月")}, - {0x32c9, 0, 0, 0, g(Yes, No, false, false, "", "10月")}, - {0x32ca, 0, 0, 0, g(Yes, No, false, false, "", "11月")}, - {0x32cb, 0, 0, 0, g(Yes, No, false, false, "", "12月")}, - {0x32cc, 0, 0, 0, g(Yes, No, false, false, "", "Hg")}, - {0x32cd, 0, 0, 0, g(Yes, No, false, false, "", "erg")}, - {0x32ce, 0, 0, 0, g(Yes, No, false, false, "", "eV")}, - {0x32cf, 0, 0, 0, g(Yes, No, false, false, "", "LTD")}, - {0x32d0, 0, 0, 0, g(Yes, No, false, false, "", "ア")}, - {0x32d1, 0, 0, 0, g(Yes, No, false, false, "", "イ")}, - {0x32d2, 0, 0, 0, g(Yes, No, false, false, "", "ウ")}, - {0x32d3, 0, 0, 0, g(Yes, No, false, false, "", "エ")}, - {0x32d4, 0, 0, 0, g(Yes, No, false, false, "", "オ")}, - {0x32d5, 0, 0, 0, g(Yes, No, false, false, "", "カ")}, - {0x32d6, 0, 0, 0, g(Yes, No, false, false, "", "キ")}, - {0x32d7, 0, 0, 0, g(Yes, No, false, false, "", "ク")}, - {0x32d8, 0, 0, 0, g(Yes, No, false, false, "", "ケ")}, - {0x32d9, 0, 0, 0, g(Yes, No, false, false, "", "コ")}, - {0x32da, 0, 0, 0, g(Yes, No, false, false, "", "サ")}, - {0x32db, 0, 0, 0, g(Yes, No, false, false, "", "シ")}, - {0x32dc, 0, 0, 0, g(Yes, No, false, false, "", "ス")}, - {0x32dd, 0, 0, 0, g(Yes, No, false, false, "", "セ")}, - {0x32de, 0, 0, 0, g(Yes, No, false, false, "", "ソ")}, - {0x32df, 0, 0, 0, g(Yes, No, false, false, "", "タ")}, - {0x32e0, 0, 0, 0, g(Yes, No, false, false, "", "チ")}, - {0x32e1, 0, 0, 0, g(Yes, No, false, false, "", "ツ")}, - {0x32e2, 0, 0, 0, g(Yes, No, false, false, "", "テ")}, - {0x32e3, 0, 0, 0, g(Yes, No, false, false, "", "ト")}, - {0x32e4, 0, 0, 0, g(Yes, No, false, false, "", "ナ")}, - {0x32e5, 0, 0, 0, g(Yes, No, false, false, "", "ニ")}, - {0x32e6, 0, 0, 0, g(Yes, No, false, false, "", "ヌ")}, - {0x32e7, 0, 0, 0, g(Yes, No, false, false, "", "ネ")}, - {0x32e8, 0, 0, 0, g(Yes, No, false, false, "", "ノ")}, - {0x32e9, 0, 0, 0, g(Yes, No, false, false, "", "ハ")}, - {0x32ea, 0, 0, 0, g(Yes, No, false, false, "", "ヒ")}, - {0x32eb, 0, 0, 0, g(Yes, No, false, false, "", "フ")}, - {0x32ec, 0, 0, 0, g(Yes, No, false, false, "", "ヘ")}, - {0x32ed, 0, 0, 0, g(Yes, No, false, false, "", "ホ")}, - {0x32ee, 0, 0, 0, g(Yes, No, false, false, "", "マ")}, - {0x32ef, 0, 0, 0, g(Yes, No, false, false, "", "ミ")}, - {0x32f0, 0, 0, 0, g(Yes, No, false, false, "", "ム")}, - {0x32f1, 0, 0, 0, g(Yes, No, false, false, "", "メ")}, - {0x32f2, 0, 0, 0, g(Yes, No, false, false, "", "モ")}, - {0x32f3, 0, 0, 0, g(Yes, No, false, false, "", "ヤ")}, - {0x32f4, 0, 0, 0, g(Yes, No, false, false, "", "ユ")}, - {0x32f5, 0, 0, 0, g(Yes, No, false, false, "", "ヨ")}, - {0x32f6, 0, 0, 0, g(Yes, No, false, false, "", "ラ")}, - {0x32f7, 0, 0, 0, g(Yes, No, false, false, "", "リ")}, - {0x32f8, 0, 0, 0, g(Yes, No, false, false, "", "ル")}, - {0x32f9, 0, 0, 0, g(Yes, No, false, false, "", "レ")}, - {0x32fa, 0, 0, 0, g(Yes, No, false, false, "", "ロ")}, - {0x32fb, 0, 0, 0, g(Yes, No, false, false, "", "ワ")}, - {0x32fc, 0, 0, 0, g(Yes, No, false, false, "", "ヰ")}, - {0x32fd, 0, 0, 0, g(Yes, No, false, false, "", "ヱ")}, - {0x32fe, 0, 0, 0, g(Yes, No, false, false, "", "ヲ")}, - {0x32ff, 0, 0, 0, f(Yes, false, "")}, - {0x3300, 0, 0, 0, g(Yes, No, false, false, "", "アパート")}, - {0x3301, 0, 0, 0, g(Yes, No, false, false, "", "アルファ")}, - {0x3302, 0, 0, 0, g(Yes, No, false, false, "", "アンペア")}, - {0x3303, 0, 0, 0, g(Yes, No, false, false, "", "アール")}, - {0x3304, 0, 0, 1, g(Yes, No, false, false, "", "イニング")}, - {0x3305, 0, 0, 0, g(Yes, No, false, false, "", "インチ")}, - {0x3306, 0, 0, 0, g(Yes, No, false, false, "", "ウォン")}, - {0x3307, 0, 0, 1, g(Yes, No, false, false, "", "エスクード")}, - {0x3308, 0, 0, 0, g(Yes, No, false, false, "", "エーカー")}, - {0x3309, 0, 0, 0, g(Yes, No, false, false, "", "オンス")}, - {0x330a, 0, 0, 0, g(Yes, No, false, false, "", "オーム")}, - {0x330b, 0, 0, 0, g(Yes, No, false, false, "", "カイリ")}, - {0x330c, 0, 0, 0, g(Yes, No, false, false, "", "カラット")}, - {0x330d, 0, 0, 0, g(Yes, No, false, false, "", "カロリー")}, - {0x330e, 0, 0, 0, g(Yes, No, false, false, "", "ガロン")}, - {0x330f, 0, 0, 0, g(Yes, No, false, false, "", "ガンマ")}, - {0x3310, 0, 0, 1, g(Yes, No, false, false, "", "ギガ")}, - {0x3311, 0, 0, 0, g(Yes, No, false, false, "", "ギニー")}, - {0x3312, 0, 0, 0, g(Yes, No, false, false, "", "キュリー")}, - {0x3313, 0, 0, 0, g(Yes, No, false, false, "", "ギルダー")}, - {0x3314, 0, 0, 0, g(Yes, No, false, false, "", "キロ")}, - {0x3315, 0, 0, 0, g(Yes, No, false, false, "", "キログラム")}, - {0x3316, 0, 0, 0, g(Yes, No, false, false, "", "キロメートル")}, - {0x3317, 0, 0, 0, g(Yes, No, false, false, "", "キロワット")}, - {0x3318, 0, 0, 0, g(Yes, No, false, false, "", "グラム")}, - {0x3319, 0, 0, 0, g(Yes, No, false, false, "", "グラムトン")}, - {0x331a, 0, 0, 0, g(Yes, No, false, false, "", "クルゼイロ")}, - {0x331b, 0, 0, 0, g(Yes, No, false, false, "", "クローネ")}, - {0x331c, 0, 0, 0, g(Yes, No, false, false, "", "ケース")}, - {0x331d, 0, 0, 0, g(Yes, No, false, false, "", "コルナ")}, - {0x331e, 0, 0, 1, g(Yes, No, false, false, "", "コーポ")}, - {0x331f, 0, 0, 0, g(Yes, No, false, false, "", "サイクル")}, - {0x3320, 0, 0, 0, g(Yes, No, false, false, "", "サンチーム")}, - {0x3321, 0, 0, 1, g(Yes, No, false, false, "", "シリング")}, - {0x3322, 0, 0, 0, g(Yes, No, false, false, "", "センチ")}, - {0x3323, 0, 0, 0, g(Yes, No, false, false, "", "セント")}, - {0x3324, 0, 0, 0, g(Yes, No, false, false, "", "ダース")}, - {0x3325, 0, 0, 0, g(Yes, No, false, false, "", "デシ")}, - {0x3326, 0, 0, 0, g(Yes, No, false, false, "", "ドル")}, - {0x3327, 0, 0, 0, g(Yes, No, false, false, "", "トン")}, - {0x3328, 0, 0, 0, g(Yes, No, false, false, "", "ナノ")}, - {0x3329, 0, 0, 0, g(Yes, No, false, false, "", "ノット")}, - {0x332a, 0, 0, 0, g(Yes, No, false, false, "", "ハイツ")}, - {0x332b, 0, 0, 0, g(Yes, No, false, false, "", "パーセント")}, - {0x332c, 0, 0, 0, g(Yes, No, false, false, "", "パーツ")}, - {0x332d, 0, 0, 0, g(Yes, No, false, false, "", "バーレル")}, - {0x332e, 0, 0, 0, g(Yes, No, false, false, "", "ピアストル")}, - {0x332f, 0, 0, 0, g(Yes, No, false, false, "", "ピクル")}, - {0x3330, 0, 0, 0, g(Yes, No, false, false, "", "ピコ")}, - {0x3331, 0, 0, 0, g(Yes, No, false, false, "", "ビル")}, - {0x3332, 0, 0, 1, g(Yes, No, false, false, "", "ファラッド")}, - {0x3333, 0, 0, 0, g(Yes, No, false, false, "", "フィート")}, - {0x3334, 0, 0, 0, g(Yes, No, false, false, "", "ブッシェル")}, - {0x3335, 0, 0, 0, g(Yes, No, false, false, "", "フラン")}, - {0x3336, 0, 0, 0, g(Yes, No, false, false, "", "ヘクタール")}, - {0x3337, 0, 0, 0, g(Yes, No, false, false, "", "ペソ")}, - {0x3338, 0, 0, 0, g(Yes, No, false, false, "", "ペニヒ")}, - {0x3339, 0, 0, 0, g(Yes, No, false, false, "", "ヘルツ")}, - {0x333a, 0, 0, 0, g(Yes, No, false, false, "", "ペンス")}, - {0x333b, 0, 0, 1, g(Yes, No, false, false, "", "ページ")}, - {0x333c, 0, 0, 0, g(Yes, No, false, false, "", "ベータ")}, - {0x333d, 0, 0, 0, g(Yes, No, false, false, "", "ポイント")}, - {0x333e, 0, 0, 0, g(Yes, No, false, false, "", "ボルト")}, - {0x333f, 0, 0, 0, g(Yes, No, false, false, "", "ホン")}, - {0x3340, 0, 0, 1, g(Yes, No, false, false, "", "ポンド")}, - {0x3341, 0, 0, 0, g(Yes, No, false, false, "", "ホール")}, - {0x3342, 0, 0, 0, g(Yes, No, false, false, "", "ホーン")}, - {0x3343, 0, 0, 0, g(Yes, No, false, false, "", "マイクロ")}, - {0x3344, 0, 0, 0, g(Yes, No, false, false, "", "マイル")}, - {0x3345, 0, 0, 0, g(Yes, No, false, false, "", "マッハ")}, - {0x3346, 0, 0, 0, g(Yes, No, false, false, "", "マルク")}, - {0x3347, 0, 0, 0, g(Yes, No, false, false, "", "マンション")}, - {0x3348, 0, 0, 0, g(Yes, No, false, false, "", "ミクロン")}, - {0x3349, 0, 0, 0, g(Yes, No, false, false, "", "ミリ")}, - {0x334a, 0, 0, 0, g(Yes, No, false, false, "", "ミリバール")}, - {0x334b, 0, 0, 1, g(Yes, No, false, false, "", "メガ")}, - {0x334c, 0, 0, 0, g(Yes, No, false, false, "", "メガトン")}, - {0x334d, 0, 0, 0, g(Yes, No, false, false, "", "メートル")}, - {0x334e, 0, 0, 1, g(Yes, No, false, false, "", "ヤード")}, - {0x334f, 0, 0, 0, g(Yes, No, false, false, "", "ヤール")}, - {0x3350, 0, 0, 0, g(Yes, No, false, false, "", "ユアン")}, - {0x3351, 0, 0, 0, g(Yes, No, false, false, "", "リットル")}, - {0x3352, 0, 0, 0, g(Yes, No, false, false, "", "リラ")}, - {0x3353, 0, 0, 0, g(Yes, No, false, false, "", "ルピー")}, - {0x3354, 0, 0, 0, g(Yes, No, false, false, "", "ルーブル")}, - {0x3355, 0, 0, 0, g(Yes, No, false, false, "", "レム")}, - {0x3356, 0, 0, 0, g(Yes, No, false, false, "", "レントゲン")}, - {0x3357, 0, 0, 0, g(Yes, No, false, false, "", "ワット")}, - {0x3358, 0, 0, 0, g(Yes, No, false, false, "", "0点")}, - {0x3359, 0, 0, 0, g(Yes, No, false, false, "", "1点")}, - {0x335a, 0, 0, 0, g(Yes, No, false, false, "", "2点")}, - {0x335b, 0, 0, 0, g(Yes, No, false, false, "", "3点")}, - {0x335c, 0, 0, 0, g(Yes, No, false, false, "", "4点")}, - {0x335d, 0, 0, 0, g(Yes, No, false, false, "", "5点")}, - {0x335e, 0, 0, 0, g(Yes, No, false, false, "", "6点")}, - {0x335f, 0, 0, 0, g(Yes, No, false, false, "", "7点")}, - {0x3360, 0, 0, 0, g(Yes, No, false, false, "", "8点")}, - {0x3361, 0, 0, 0, g(Yes, No, false, false, "", "9点")}, - {0x3362, 0, 0, 0, g(Yes, No, false, false, "", "10点")}, - {0x3363, 0, 0, 0, g(Yes, No, false, false, "", "11点")}, - {0x3364, 0, 0, 0, g(Yes, No, false, false, "", "12点")}, - {0x3365, 0, 0, 0, g(Yes, No, false, false, "", "13点")}, - {0x3366, 0, 0, 0, g(Yes, No, false, false, "", "14点")}, - {0x3367, 0, 0, 0, g(Yes, No, false, false, "", "15点")}, - {0x3368, 0, 0, 0, g(Yes, No, false, false, "", "16点")}, - {0x3369, 0, 0, 0, g(Yes, No, false, false, "", "17点")}, - {0x336a, 0, 0, 0, g(Yes, No, false, false, "", "18点")}, - {0x336b, 0, 0, 0, g(Yes, No, false, false, "", "19点")}, - {0x336c, 0, 0, 0, g(Yes, No, false, false, "", "20点")}, - {0x336d, 0, 0, 0, g(Yes, No, false, false, "", "21点")}, - {0x336e, 0, 0, 0, g(Yes, No, false, false, "", "22点")}, - {0x336f, 0, 0, 0, g(Yes, No, false, false, "", "23点")}, - {0x3370, 0, 0, 0, g(Yes, No, false, false, "", "24点")}, - {0x3371, 0, 0, 0, g(Yes, No, false, false, "", "hPa")}, - {0x3372, 0, 0, 0, g(Yes, No, false, false, "", "da")}, - {0x3373, 0, 0, 0, g(Yes, No, false, false, "", "AU")}, - {0x3374, 0, 0, 0, g(Yes, No, false, false, "", "bar")}, - {0x3375, 0, 0, 0, g(Yes, No, false, false, "", "oV")}, - {0x3376, 0, 0, 0, g(Yes, No, false, false, "", "pc")}, - {0x3377, 0, 0, 0, g(Yes, No, false, false, "", "dm")}, - {0x3378, 0, 0, 0, g(Yes, No, false, false, "", "dm2")}, - {0x3379, 0, 0, 0, g(Yes, No, false, false, "", "dm3")}, - {0x337a, 0, 0, 0, g(Yes, No, false, false, "", "IU")}, - {0x337b, 0, 0, 0, g(Yes, No, false, false, "", "平成")}, - {0x337c, 0, 0, 0, g(Yes, No, false, false, "", "昭和")}, - {0x337d, 0, 0, 0, g(Yes, No, false, false, "", "大正")}, - {0x337e, 0, 0, 0, g(Yes, No, false, false, "", "明治")}, - {0x337f, 0, 0, 0, g(Yes, No, false, false, "", "株式会社")}, - {0x3380, 0, 0, 0, g(Yes, No, false, false, "", "pA")}, - {0x3381, 0, 0, 0, g(Yes, No, false, false, "", "nA")}, - {0x3382, 0, 0, 0, g(Yes, No, false, false, "", "μA")}, - {0x3383, 0, 0, 0, g(Yes, No, false, false, "", "mA")}, - {0x3384, 0, 0, 0, g(Yes, No, false, false, "", "kA")}, - {0x3385, 0, 0, 0, g(Yes, No, false, false, "", "KB")}, - {0x3386, 0, 0, 0, g(Yes, No, false, false, "", "MB")}, - {0x3387, 0, 0, 0, g(Yes, No, false, false, "", "GB")}, - {0x3388, 0, 0, 0, g(Yes, No, false, false, "", "cal")}, - {0x3389, 0, 0, 0, g(Yes, No, false, false, "", "kcal")}, - {0x338a, 0, 0, 0, g(Yes, No, false, false, "", "pF")}, - {0x338b, 0, 0, 0, g(Yes, No, false, false, "", "nF")}, - {0x338c, 0, 0, 0, g(Yes, No, false, false, "", "μF")}, - {0x338d, 0, 0, 0, g(Yes, No, false, false, "", "μg")}, - {0x338e, 0, 0, 0, g(Yes, No, false, false, "", "mg")}, - {0x338f, 0, 0, 0, g(Yes, No, false, false, "", "kg")}, - {0x3390, 0, 0, 0, g(Yes, No, false, false, "", "Hz")}, - {0x3391, 0, 0, 0, g(Yes, No, false, false, "", "kHz")}, - {0x3392, 0, 0, 0, g(Yes, No, false, false, "", "MHz")}, - {0x3393, 0, 0, 0, g(Yes, No, false, false, "", "GHz")}, - {0x3394, 0, 0, 0, g(Yes, No, false, false, "", "THz")}, - {0x3395, 0, 0, 0, g(Yes, No, false, false, "", "μl")}, - {0x3396, 0, 0, 0, g(Yes, No, false, false, "", "ml")}, - {0x3397, 0, 0, 0, g(Yes, No, false, false, "", "dl")}, - {0x3398, 0, 0, 0, g(Yes, No, false, false, "", "kl")}, - {0x3399, 0, 0, 0, g(Yes, No, false, false, "", "fm")}, - {0x339a, 0, 0, 0, g(Yes, No, false, false, "", "nm")}, - {0x339b, 0, 0, 0, g(Yes, No, false, false, "", "μm")}, - {0x339c, 0, 0, 0, g(Yes, No, false, false, "", "mm")}, - {0x339d, 0, 0, 0, g(Yes, No, false, false, "", "cm")}, - {0x339e, 0, 0, 0, g(Yes, No, false, false, "", "km")}, - {0x339f, 0, 0, 0, g(Yes, No, false, false, "", "mm2")}, - {0x33a0, 0, 0, 0, g(Yes, No, false, false, "", "cm2")}, - {0x33a1, 0, 0, 0, g(Yes, No, false, false, "", "m2")}, - {0x33a2, 0, 0, 0, g(Yes, No, false, false, "", "km2")}, - {0x33a3, 0, 0, 0, g(Yes, No, false, false, "", "mm3")}, - {0x33a4, 0, 0, 0, g(Yes, No, false, false, "", "cm3")}, - {0x33a5, 0, 0, 0, g(Yes, No, false, false, "", "m3")}, - {0x33a6, 0, 0, 0, g(Yes, No, false, false, "", "km3")}, - {0x33a7, 0, 0, 0, g(Yes, No, false, false, "", "m∕s")}, - {0x33a8, 0, 0, 0, g(Yes, No, false, false, "", "m∕s2")}, - {0x33a9, 0, 0, 0, g(Yes, No, false, false, "", "Pa")}, - {0x33aa, 0, 0, 0, g(Yes, No, false, false, "", "kPa")}, - {0x33ab, 0, 0, 0, g(Yes, No, false, false, "", "MPa")}, - {0x33ac, 0, 0, 0, g(Yes, No, false, false, "", "GPa")}, - {0x33ad, 0, 0, 0, g(Yes, No, false, false, "", "rad")}, - {0x33ae, 0, 0, 0, g(Yes, No, false, false, "", "rad∕s")}, - {0x33af, 0, 0, 0, g(Yes, No, false, false, "", "rad∕s2")}, - {0x33b0, 0, 0, 0, g(Yes, No, false, false, "", "ps")}, - {0x33b1, 0, 0, 0, g(Yes, No, false, false, "", "ns")}, - {0x33b2, 0, 0, 0, g(Yes, No, false, false, "", "μs")}, - {0x33b3, 0, 0, 0, g(Yes, No, false, false, "", "ms")}, - {0x33b4, 0, 0, 0, g(Yes, No, false, false, "", "pV")}, - {0x33b5, 0, 0, 0, g(Yes, No, false, false, "", "nV")}, - {0x33b6, 0, 0, 0, g(Yes, No, false, false, "", "μV")}, - {0x33b7, 0, 0, 0, g(Yes, No, false, false, "", "mV")}, - {0x33b8, 0, 0, 0, g(Yes, No, false, false, "", "kV")}, - {0x33b9, 0, 0, 0, g(Yes, No, false, false, "", "MV")}, - {0x33ba, 0, 0, 0, g(Yes, No, false, false, "", "pW")}, - {0x33bb, 0, 0, 0, g(Yes, No, false, false, "", "nW")}, - {0x33bc, 0, 0, 0, g(Yes, No, false, false, "", "μW")}, - {0x33bd, 0, 0, 0, g(Yes, No, false, false, "", "mW")}, - {0x33be, 0, 0, 0, g(Yes, No, false, false, "", "kW")}, - {0x33bf, 0, 0, 0, g(Yes, No, false, false, "", "MW")}, - {0x33c0, 0, 0, 0, g(Yes, No, false, false, "", "kΩ")}, - {0x33c1, 0, 0, 0, g(Yes, No, false, false, "", "MΩ")}, - {0x33c2, 0, 0, 0, g(Yes, No, false, false, "", "a.m.")}, - {0x33c3, 0, 0, 0, g(Yes, No, false, false, "", "Bq")}, - {0x33c4, 0, 0, 0, g(Yes, No, false, false, "", "cc")}, - {0x33c5, 0, 0, 0, g(Yes, No, false, false, "", "cd")}, - {0x33c6, 0, 0, 0, g(Yes, No, false, false, "", "C∕kg")}, - {0x33c7, 0, 0, 0, g(Yes, No, false, false, "", "Co.")}, - {0x33c8, 0, 0, 0, g(Yes, No, false, false, "", "dB")}, - {0x33c9, 0, 0, 0, g(Yes, No, false, false, "", "Gy")}, - {0x33ca, 0, 0, 0, g(Yes, No, false, false, "", "ha")}, - {0x33cb, 0, 0, 0, g(Yes, No, false, false, "", "HP")}, - {0x33cc, 0, 0, 0, g(Yes, No, false, false, "", "in")}, - {0x33cd, 0, 0, 0, g(Yes, No, false, false, "", "KK")}, - {0x33ce, 0, 0, 0, g(Yes, No, false, false, "", "KM")}, - {0x33cf, 0, 0, 0, g(Yes, No, false, false, "", "kt")}, - {0x33d0, 0, 0, 0, g(Yes, No, false, false, "", "lm")}, - {0x33d1, 0, 0, 0, g(Yes, No, false, false, "", "ln")}, - {0x33d2, 0, 0, 0, g(Yes, No, false, false, "", "log")}, - {0x33d3, 0, 0, 0, g(Yes, No, false, false, "", "lx")}, - {0x33d4, 0, 0, 0, g(Yes, No, false, false, "", "mb")}, - {0x33d5, 0, 0, 0, g(Yes, No, false, false, "", "mil")}, - {0x33d6, 0, 0, 0, g(Yes, No, false, false, "", "mol")}, - {0x33d7, 0, 0, 0, g(Yes, No, false, false, "", "PH")}, - {0x33d8, 0, 0, 0, g(Yes, No, false, false, "", "p.m.")}, - {0x33d9, 0, 0, 0, g(Yes, No, false, false, "", "PPM")}, - {0x33da, 0, 0, 0, g(Yes, No, false, false, "", "PR")}, - {0x33db, 0, 0, 0, g(Yes, No, false, false, "", "sr")}, - {0x33dc, 0, 0, 0, g(Yes, No, false, false, "", "Sv")}, - {0x33dd, 0, 0, 0, g(Yes, No, false, false, "", "Wb")}, - {0x33de, 0, 0, 0, g(Yes, No, false, false, "", "V∕m")}, - {0x33df, 0, 0, 0, g(Yes, No, false, false, "", "A∕m")}, - {0x33e0, 0, 0, 0, g(Yes, No, false, false, "", "1日")}, - {0x33e1, 0, 0, 0, g(Yes, No, false, false, "", "2日")}, - {0x33e2, 0, 0, 0, g(Yes, No, false, false, "", "3日")}, - {0x33e3, 0, 0, 0, g(Yes, No, false, false, "", "4日")}, - {0x33e4, 0, 0, 0, g(Yes, No, false, false, "", "5日")}, - {0x33e5, 0, 0, 0, g(Yes, No, false, false, "", "6日")}, - {0x33e6, 0, 0, 0, g(Yes, No, false, false, "", "7日")}, - {0x33e7, 0, 0, 0, g(Yes, No, false, false, "", "8日")}, - {0x33e8, 0, 0, 0, g(Yes, No, false, false, "", "9日")}, - {0x33e9, 0, 0, 0, g(Yes, No, false, false, "", "10日")}, - {0x33ea, 0, 0, 0, g(Yes, No, false, false, "", "11日")}, - {0x33eb, 0, 0, 0, g(Yes, No, false, false, "", "12日")}, - {0x33ec, 0, 0, 0, g(Yes, No, false, false, "", "13日")}, - {0x33ed, 0, 0, 0, g(Yes, No, false, false, "", "14日")}, - {0x33ee, 0, 0, 0, g(Yes, No, false, false, "", "15日")}, - {0x33ef, 0, 0, 0, g(Yes, No, false, false, "", "16日")}, - {0x33f0, 0, 0, 0, g(Yes, No, false, false, "", "17日")}, - {0x33f1, 0, 0, 0, g(Yes, No, false, false, "", "18日")}, - {0x33f2, 0, 0, 0, g(Yes, No, false, false, "", "19日")}, - {0x33f3, 0, 0, 0, g(Yes, No, false, false, "", "20日")}, - {0x33f4, 0, 0, 0, g(Yes, No, false, false, "", "21日")}, - {0x33f5, 0, 0, 0, g(Yes, No, false, false, "", "22日")}, - {0x33f6, 0, 0, 0, g(Yes, No, false, false, "", "23日")}, - {0x33f7, 0, 0, 0, g(Yes, No, false, false, "", "24日")}, - {0x33f8, 0, 0, 0, g(Yes, No, false, false, "", "25日")}, - {0x33f9, 0, 0, 0, g(Yes, No, false, false, "", "26日")}, - {0x33fa, 0, 0, 0, g(Yes, No, false, false, "", "27日")}, - {0x33fb, 0, 0, 0, g(Yes, No, false, false, "", "28日")}, - {0x33fc, 0, 0, 0, g(Yes, No, false, false, "", "29日")}, - {0x33fd, 0, 0, 0, g(Yes, No, false, false, "", "30日")}, - {0x33fe, 0, 0, 0, g(Yes, No, false, false, "", "31日")}, - {0x33ff, 0, 0, 0, g(Yes, No, false, false, "", "gal")}, - {0x3400, 0, 0, 0, f(Yes, false, "")}, - {0xa66f, 230, 1, 1, f(Yes, false, "")}, - {0xa670, 0, 0, 0, f(Yes, false, "")}, - {0xa674, 230, 1, 1, f(Yes, false, "")}, - {0xa67e, 0, 0, 0, f(Yes, false, "")}, - {0xa69c, 0, 0, 0, g(Yes, No, false, false, "", "ъ")}, - {0xa69d, 0, 0, 0, g(Yes, No, false, false, "", "ь")}, - {0xa69e, 230, 1, 1, f(Yes, false, "")}, - {0xa6a0, 0, 0, 0, f(Yes, false, "")}, - {0xa6f0, 230, 1, 1, f(Yes, false, "")}, - {0xa6f2, 0, 0, 0, f(Yes, false, "")}, - {0xa770, 0, 0, 0, g(Yes, No, false, false, "", "ꝯ")}, - {0xa771, 0, 0, 0, f(Yes, false, "")}, - {0xa7f8, 0, 0, 0, g(Yes, No, false, false, "", "Ħ")}, - {0xa7f9, 0, 0, 0, g(Yes, No, false, false, "", "œ")}, - {0xa7fa, 0, 0, 0, f(Yes, false, "")}, - {0xa806, 9, 1, 1, f(Yes, false, "")}, - {0xa807, 0, 0, 0, f(Yes, false, "")}, - {0xa8c4, 9, 1, 1, f(Yes, false, "")}, - {0xa8c5, 0, 0, 0, f(Yes, false, "")}, - {0xa8e0, 230, 1, 1, f(Yes, false, "")}, - {0xa8f2, 0, 0, 0, f(Yes, false, "")}, - {0xa92b, 220, 1, 1, f(Yes, false, "")}, - {0xa92e, 0, 0, 0, f(Yes, false, "")}, - {0xa953, 9, 1, 1, f(Yes, false, "")}, - {0xa954, 0, 0, 0, f(Yes, false, "")}, - {0xa9b3, 7, 1, 1, f(Yes, false, "")}, - {0xa9b4, 0, 0, 0, f(Yes, false, "")}, - {0xa9c0, 9, 1, 1, f(Yes, false, "")}, - {0xa9c1, 0, 0, 0, f(Yes, false, "")}, - {0xaab0, 230, 1, 1, f(Yes, false, "")}, - {0xaab1, 0, 0, 0, f(Yes, false, "")}, - {0xaab2, 230, 1, 1, f(Yes, false, "")}, - {0xaab4, 220, 1, 1, f(Yes, false, "")}, - {0xaab5, 0, 0, 0, f(Yes, false, "")}, - {0xaab7, 230, 1, 1, f(Yes, false, "")}, - {0xaab9, 0, 0, 0, f(Yes, false, "")}, - {0xaabe, 230, 1, 1, f(Yes, false, "")}, - {0xaac0, 0, 0, 0, f(Yes, false, "")}, - {0xaac1, 230, 1, 1, f(Yes, false, "")}, - {0xaac2, 0, 0, 0, f(Yes, false, "")}, - {0xaaf6, 9, 1, 1, f(Yes, false, "")}, - {0xaaf7, 0, 0, 0, f(Yes, false, "")}, - {0xab5c, 0, 0, 0, g(Yes, No, false, false, "", "ꜧ")}, - {0xab5d, 0, 0, 0, g(Yes, No, false, false, "", "ꬷ")}, - {0xab5e, 0, 0, 0, g(Yes, No, false, false, "", "ɫ")}, - {0xab5f, 0, 0, 0, g(Yes, No, false, false, "", "ꭒ")}, - {0xab60, 0, 0, 0, f(Yes, false, "")}, - {0xabed, 9, 1, 1, f(Yes, false, "")}, - {0xabee, 0, 0, 0, f(Yes, false, "")}, - {0xac00, 0, 0, 1, f(Yes, true, "")}, - {0xac01, 0, 0, 2, f(Yes, false, "")}, - {0xac1c, 0, 0, 1, f(Yes, true, "")}, - {0xac1d, 0, 0, 2, f(Yes, false, "")}, - {0xac38, 0, 0, 1, f(Yes, true, "")}, - {0xac39, 0, 0, 2, f(Yes, false, "")}, - {0xac54, 0, 0, 1, f(Yes, true, "")}, - {0xac55, 0, 0, 2, f(Yes, false, "")}, - {0xac70, 0, 0, 1, f(Yes, true, "")}, - {0xac71, 0, 0, 2, f(Yes, false, "")}, - {0xac8c, 0, 0, 1, f(Yes, true, "")}, - {0xac8d, 0, 0, 2, f(Yes, false, "")}, - {0xaca8, 0, 0, 1, f(Yes, true, "")}, - {0xaca9, 0, 0, 2, f(Yes, false, "")}, - {0xacc4, 0, 0, 1, f(Yes, true, "")}, - {0xacc5, 0, 0, 2, f(Yes, false, "")}, - {0xace0, 0, 0, 1, f(Yes, true, "")}, - {0xace1, 0, 0, 2, f(Yes, false, "")}, - {0xacfc, 0, 0, 1, f(Yes, true, "")}, - {0xacfd, 0, 0, 2, f(Yes, false, "")}, - {0xad18, 0, 0, 1, f(Yes, true, "")}, - {0xad19, 0, 0, 2, f(Yes, false, "")}, - {0xad34, 0, 0, 1, f(Yes, true, "")}, - {0xad35, 0, 0, 2, f(Yes, false, "")}, - {0xad50, 0, 0, 1, f(Yes, true, "")}, - {0xad51, 0, 0, 2, f(Yes, false, "")}, - {0xad6c, 0, 0, 1, f(Yes, true, "")}, - {0xad6d, 0, 0, 2, f(Yes, false, "")}, - {0xad88, 0, 0, 1, f(Yes, true, "")}, - {0xad89, 0, 0, 2, f(Yes, false, "")}, - {0xada4, 0, 0, 1, f(Yes, true, "")}, - {0xada5, 0, 0, 2, f(Yes, false, "")}, - {0xadc0, 0, 0, 1, f(Yes, true, "")}, - {0xadc1, 0, 0, 2, f(Yes, false, "")}, - {0xaddc, 0, 0, 1, f(Yes, true, "")}, - {0xaddd, 0, 0, 2, f(Yes, false, "")}, - {0xadf8, 0, 0, 1, f(Yes, true, "")}, - {0xadf9, 0, 0, 2, f(Yes, false, "")}, - {0xae14, 0, 0, 1, f(Yes, true, "")}, - {0xae15, 0, 0, 2, f(Yes, false, "")}, - {0xae30, 0, 0, 1, f(Yes, true, "")}, - {0xae31, 0, 0, 2, f(Yes, false, "")}, - {0xae4c, 0, 0, 1, f(Yes, true, "")}, - {0xae4d, 0, 0, 2, f(Yes, false, "")}, - {0xae68, 0, 0, 1, f(Yes, true, "")}, - {0xae69, 0, 0, 2, f(Yes, false, "")}, - {0xae84, 0, 0, 1, f(Yes, true, "")}, - {0xae85, 0, 0, 2, f(Yes, false, "")}, - {0xaea0, 0, 0, 1, f(Yes, true, "")}, - {0xaea1, 0, 0, 2, f(Yes, false, "")}, - {0xaebc, 0, 0, 1, f(Yes, true, "")}, - {0xaebd, 0, 0, 2, f(Yes, false, "")}, - {0xaed8, 0, 0, 1, f(Yes, true, "")}, - {0xaed9, 0, 0, 2, f(Yes, false, "")}, - {0xaef4, 0, 0, 1, f(Yes, true, "")}, - {0xaef5, 0, 0, 2, f(Yes, false, "")}, - {0xaf10, 0, 0, 1, f(Yes, true, "")}, - {0xaf11, 0, 0, 2, f(Yes, false, "")}, - {0xaf2c, 0, 0, 1, f(Yes, true, "")}, - {0xaf2d, 0, 0, 2, f(Yes, false, "")}, - {0xaf48, 0, 0, 1, f(Yes, true, "")}, - {0xaf49, 0, 0, 2, f(Yes, false, "")}, - {0xaf64, 0, 0, 1, f(Yes, true, "")}, - {0xaf65, 0, 0, 2, f(Yes, false, "")}, - {0xaf80, 0, 0, 1, f(Yes, true, "")}, - {0xaf81, 0, 0, 2, f(Yes, false, "")}, - {0xaf9c, 0, 0, 1, f(Yes, true, "")}, - {0xaf9d, 0, 0, 2, f(Yes, false, "")}, - {0xafb8, 0, 0, 1, f(Yes, true, "")}, - {0xafb9, 0, 0, 2, f(Yes, false, "")}, - {0xafd4, 0, 0, 1, f(Yes, true, "")}, - {0xafd5, 0, 0, 2, f(Yes, false, "")}, - {0xaff0, 0, 0, 1, f(Yes, true, "")}, - {0xaff1, 0, 0, 2, f(Yes, false, "")}, - {0xb00c, 0, 0, 1, f(Yes, true, "")}, - {0xb00d, 0, 0, 2, f(Yes, false, "")}, - {0xb028, 0, 0, 1, f(Yes, true, "")}, - {0xb029, 0, 0, 2, f(Yes, false, "")}, - {0xb044, 0, 0, 1, f(Yes, true, "")}, - {0xb045, 0, 0, 2, f(Yes, false, "")}, - {0xb060, 0, 0, 1, f(Yes, true, "")}, - {0xb061, 0, 0, 2, f(Yes, false, "")}, - {0xb07c, 0, 0, 1, f(Yes, true, "")}, - {0xb07d, 0, 0, 2, f(Yes, false, "")}, - {0xb098, 0, 0, 1, f(Yes, true, "")}, - {0xb099, 0, 0, 2, f(Yes, false, "")}, - {0xb0b4, 0, 0, 1, f(Yes, true, "")}, - {0xb0b5, 0, 0, 2, f(Yes, false, "")}, - {0xb0d0, 0, 0, 1, f(Yes, true, "")}, - {0xb0d1, 0, 0, 2, f(Yes, false, "")}, - {0xb0ec, 0, 0, 1, f(Yes, true, "")}, - {0xb0ed, 0, 0, 2, f(Yes, false, "")}, - {0xb108, 0, 0, 1, f(Yes, true, "")}, - {0xb109, 0, 0, 2, f(Yes, false, "")}, - {0xb124, 0, 0, 1, f(Yes, true, "")}, - {0xb125, 0, 0, 2, f(Yes, false, "")}, - {0xb140, 0, 0, 1, f(Yes, true, "")}, - {0xb141, 0, 0, 2, f(Yes, false, "")}, - {0xb15c, 0, 0, 1, f(Yes, true, "")}, - {0xb15d, 0, 0, 2, f(Yes, false, "")}, - {0xb178, 0, 0, 1, f(Yes, true, "")}, - {0xb179, 0, 0, 2, f(Yes, false, "")}, - {0xb194, 0, 0, 1, f(Yes, true, "")}, - {0xb195, 0, 0, 2, f(Yes, false, "")}, - {0xb1b0, 0, 0, 1, f(Yes, true, "")}, - {0xb1b1, 0, 0, 2, f(Yes, false, "")}, - {0xb1cc, 0, 0, 1, f(Yes, true, "")}, - {0xb1cd, 0, 0, 2, f(Yes, false, "")}, - {0xb1e8, 0, 0, 1, f(Yes, true, "")}, - {0xb1e9, 0, 0, 2, f(Yes, false, "")}, - {0xb204, 0, 0, 1, f(Yes, true, "")}, - {0xb205, 0, 0, 2, f(Yes, false, "")}, - {0xb220, 0, 0, 1, f(Yes, true, "")}, - {0xb221, 0, 0, 2, f(Yes, false, "")}, - {0xb23c, 0, 0, 1, f(Yes, true, "")}, - {0xb23d, 0, 0, 2, f(Yes, false, "")}, - {0xb258, 0, 0, 1, f(Yes, true, "")}, - {0xb259, 0, 0, 2, f(Yes, false, "")}, - {0xb274, 0, 0, 1, f(Yes, true, "")}, - {0xb275, 0, 0, 2, f(Yes, false, "")}, - {0xb290, 0, 0, 1, f(Yes, true, "")}, - {0xb291, 0, 0, 2, f(Yes, false, "")}, - {0xb2ac, 0, 0, 1, f(Yes, true, "")}, - {0xb2ad, 0, 0, 2, f(Yes, false, "")}, - {0xb2c8, 0, 0, 1, f(Yes, true, "")}, - {0xb2c9, 0, 0, 2, f(Yes, false, "")}, - {0xb2e4, 0, 0, 1, f(Yes, true, "")}, - {0xb2e5, 0, 0, 2, f(Yes, false, "")}, - {0xb300, 0, 0, 1, f(Yes, true, "")}, - {0xb301, 0, 0, 2, f(Yes, false, "")}, - {0xb31c, 0, 0, 1, f(Yes, true, "")}, - {0xb31d, 0, 0, 2, f(Yes, false, "")}, - {0xb338, 0, 0, 1, f(Yes, true, "")}, - {0xb339, 0, 0, 2, f(Yes, false, "")}, - {0xb354, 0, 0, 1, f(Yes, true, "")}, - {0xb355, 0, 0, 2, f(Yes, false, "")}, - {0xb370, 0, 0, 1, f(Yes, true, "")}, - {0xb371, 0, 0, 2, f(Yes, false, "")}, - {0xb38c, 0, 0, 1, f(Yes, true, "")}, - {0xb38d, 0, 0, 2, f(Yes, false, "")}, - {0xb3a8, 0, 0, 1, f(Yes, true, "")}, - {0xb3a9, 0, 0, 2, f(Yes, false, "")}, - {0xb3c4, 0, 0, 1, f(Yes, true, "")}, - {0xb3c5, 0, 0, 2, f(Yes, false, "")}, - {0xb3e0, 0, 0, 1, f(Yes, true, "")}, - {0xb3e1, 0, 0, 2, f(Yes, false, "")}, - {0xb3fc, 0, 0, 1, f(Yes, true, "")}, - {0xb3fd, 0, 0, 2, f(Yes, false, "")}, - {0xb418, 0, 0, 1, f(Yes, true, "")}, - {0xb419, 0, 0, 2, f(Yes, false, "")}, - {0xb434, 0, 0, 1, f(Yes, true, "")}, - {0xb435, 0, 0, 2, f(Yes, false, "")}, - {0xb450, 0, 0, 1, f(Yes, true, "")}, - {0xb451, 0, 0, 2, f(Yes, false, "")}, - {0xb46c, 0, 0, 1, f(Yes, true, "")}, - {0xb46d, 0, 0, 2, f(Yes, false, "")}, - {0xb488, 0, 0, 1, f(Yes, true, "")}, - {0xb489, 0, 0, 2, f(Yes, false, "")}, - {0xb4a4, 0, 0, 1, f(Yes, true, "")}, - {0xb4a5, 0, 0, 2, f(Yes, false, "")}, - {0xb4c0, 0, 0, 1, f(Yes, true, "")}, - {0xb4c1, 0, 0, 2, f(Yes, false, "")}, - {0xb4dc, 0, 0, 1, f(Yes, true, "")}, - {0xb4dd, 0, 0, 2, f(Yes, false, "")}, - {0xb4f8, 0, 0, 1, f(Yes, true, "")}, - {0xb4f9, 0, 0, 2, f(Yes, false, "")}, - {0xb514, 0, 0, 1, f(Yes, true, "")}, - {0xb515, 0, 0, 2, f(Yes, false, "")}, - {0xb530, 0, 0, 1, f(Yes, true, "")}, - {0xb531, 0, 0, 2, f(Yes, false, "")}, - {0xb54c, 0, 0, 1, f(Yes, true, "")}, - {0xb54d, 0, 0, 2, f(Yes, false, "")}, - {0xb568, 0, 0, 1, f(Yes, true, "")}, - {0xb569, 0, 0, 2, f(Yes, false, "")}, - {0xb584, 0, 0, 1, f(Yes, true, "")}, - {0xb585, 0, 0, 2, f(Yes, false, "")}, - {0xb5a0, 0, 0, 1, f(Yes, true, "")}, - {0xb5a1, 0, 0, 2, f(Yes, false, "")}, - {0xb5bc, 0, 0, 1, f(Yes, true, "")}, - {0xb5bd, 0, 0, 2, f(Yes, false, "")}, - {0xb5d8, 0, 0, 1, f(Yes, true, "")}, - {0xb5d9, 0, 0, 2, f(Yes, false, "")}, - {0xb5f4, 0, 0, 1, f(Yes, true, "")}, - {0xb5f5, 0, 0, 2, f(Yes, false, "")}, - {0xb610, 0, 0, 1, f(Yes, true, "")}, - {0xb611, 0, 0, 2, f(Yes, false, "")}, - {0xb62c, 0, 0, 1, f(Yes, true, "")}, - {0xb62d, 0, 0, 2, f(Yes, false, "")}, - {0xb648, 0, 0, 1, f(Yes, true, "")}, - {0xb649, 0, 0, 2, f(Yes, false, "")}, - {0xb664, 0, 0, 1, f(Yes, true, "")}, - {0xb665, 0, 0, 2, f(Yes, false, "")}, - {0xb680, 0, 0, 1, f(Yes, true, "")}, - {0xb681, 0, 0, 2, f(Yes, false, "")}, - {0xb69c, 0, 0, 1, f(Yes, true, "")}, - {0xb69d, 0, 0, 2, f(Yes, false, "")}, - {0xb6b8, 0, 0, 1, f(Yes, true, "")}, - {0xb6b9, 0, 0, 2, f(Yes, false, "")}, - {0xb6d4, 0, 0, 1, f(Yes, true, "")}, - {0xb6d5, 0, 0, 2, f(Yes, false, "")}, - {0xb6f0, 0, 0, 1, f(Yes, true, "")}, - {0xb6f1, 0, 0, 2, f(Yes, false, "")}, - {0xb70c, 0, 0, 1, f(Yes, true, "")}, - {0xb70d, 0, 0, 2, f(Yes, false, "")}, - {0xb728, 0, 0, 1, f(Yes, true, "")}, - {0xb729, 0, 0, 2, f(Yes, false, "")}, - {0xb744, 0, 0, 1, f(Yes, true, "")}, - {0xb745, 0, 0, 2, f(Yes, false, "")}, - {0xb760, 0, 0, 1, f(Yes, true, "")}, - {0xb761, 0, 0, 2, f(Yes, false, "")}, - {0xb77c, 0, 0, 1, f(Yes, true, "")}, - {0xb77d, 0, 0, 2, f(Yes, false, "")}, - {0xb798, 0, 0, 1, f(Yes, true, "")}, - {0xb799, 0, 0, 2, f(Yes, false, "")}, - {0xb7b4, 0, 0, 1, f(Yes, true, "")}, - {0xb7b5, 0, 0, 2, f(Yes, false, "")}, - {0xb7d0, 0, 0, 1, f(Yes, true, "")}, - {0xb7d1, 0, 0, 2, f(Yes, false, "")}, - {0xb7ec, 0, 0, 1, f(Yes, true, "")}, - {0xb7ed, 0, 0, 2, f(Yes, false, "")}, - {0xb808, 0, 0, 1, f(Yes, true, "")}, - {0xb809, 0, 0, 2, f(Yes, false, "")}, - {0xb824, 0, 0, 1, f(Yes, true, "")}, - {0xb825, 0, 0, 2, f(Yes, false, "")}, - {0xb840, 0, 0, 1, f(Yes, true, "")}, - {0xb841, 0, 0, 2, f(Yes, false, "")}, - {0xb85c, 0, 0, 1, f(Yes, true, "")}, - {0xb85d, 0, 0, 2, f(Yes, false, "")}, - {0xb878, 0, 0, 1, f(Yes, true, "")}, - {0xb879, 0, 0, 2, f(Yes, false, "")}, - {0xb894, 0, 0, 1, f(Yes, true, "")}, - {0xb895, 0, 0, 2, f(Yes, false, "")}, - {0xb8b0, 0, 0, 1, f(Yes, true, "")}, - {0xb8b1, 0, 0, 2, f(Yes, false, "")}, - {0xb8cc, 0, 0, 1, f(Yes, true, "")}, - {0xb8cd, 0, 0, 2, f(Yes, false, "")}, - {0xb8e8, 0, 0, 1, f(Yes, true, "")}, - {0xb8e9, 0, 0, 2, f(Yes, false, "")}, - {0xb904, 0, 0, 1, f(Yes, true, "")}, - {0xb905, 0, 0, 2, f(Yes, false, "")}, - {0xb920, 0, 0, 1, f(Yes, true, "")}, - {0xb921, 0, 0, 2, f(Yes, false, "")}, - {0xb93c, 0, 0, 1, f(Yes, true, "")}, - {0xb93d, 0, 0, 2, f(Yes, false, "")}, - {0xb958, 0, 0, 1, f(Yes, true, "")}, - {0xb959, 0, 0, 2, f(Yes, false, "")}, - {0xb974, 0, 0, 1, f(Yes, true, "")}, - {0xb975, 0, 0, 2, f(Yes, false, "")}, - {0xb990, 0, 0, 1, f(Yes, true, "")}, - {0xb991, 0, 0, 2, f(Yes, false, "")}, - {0xb9ac, 0, 0, 1, f(Yes, true, "")}, - {0xb9ad, 0, 0, 2, f(Yes, false, "")}, - {0xb9c8, 0, 0, 1, f(Yes, true, "")}, - {0xb9c9, 0, 0, 2, f(Yes, false, "")}, - {0xb9e4, 0, 0, 1, f(Yes, true, "")}, - {0xb9e5, 0, 0, 2, f(Yes, false, "")}, - {0xba00, 0, 0, 1, f(Yes, true, "")}, - {0xba01, 0, 0, 2, f(Yes, false, "")}, - {0xba1c, 0, 0, 1, f(Yes, true, "")}, - {0xba1d, 0, 0, 2, f(Yes, false, "")}, - {0xba38, 0, 0, 1, f(Yes, true, "")}, - {0xba39, 0, 0, 2, f(Yes, false, "")}, - {0xba54, 0, 0, 1, f(Yes, true, "")}, - {0xba55, 0, 0, 2, f(Yes, false, "")}, - {0xba70, 0, 0, 1, f(Yes, true, "")}, - {0xba71, 0, 0, 2, f(Yes, false, "")}, - {0xba8c, 0, 0, 1, f(Yes, true, "")}, - {0xba8d, 0, 0, 2, f(Yes, false, "")}, - {0xbaa8, 0, 0, 1, f(Yes, true, "")}, - {0xbaa9, 0, 0, 2, f(Yes, false, "")}, - {0xbac4, 0, 0, 1, f(Yes, true, "")}, - {0xbac5, 0, 0, 2, f(Yes, false, "")}, - {0xbae0, 0, 0, 1, f(Yes, true, "")}, - {0xbae1, 0, 0, 2, f(Yes, false, "")}, - {0xbafc, 0, 0, 1, f(Yes, true, "")}, - {0xbafd, 0, 0, 2, f(Yes, false, "")}, - {0xbb18, 0, 0, 1, f(Yes, true, "")}, - {0xbb19, 0, 0, 2, f(Yes, false, "")}, - {0xbb34, 0, 0, 1, f(Yes, true, "")}, - {0xbb35, 0, 0, 2, f(Yes, false, "")}, - {0xbb50, 0, 0, 1, f(Yes, true, "")}, - {0xbb51, 0, 0, 2, f(Yes, false, "")}, - {0xbb6c, 0, 0, 1, f(Yes, true, "")}, - {0xbb6d, 0, 0, 2, f(Yes, false, "")}, - {0xbb88, 0, 0, 1, f(Yes, true, "")}, - {0xbb89, 0, 0, 2, f(Yes, false, "")}, - {0xbba4, 0, 0, 1, f(Yes, true, "")}, - {0xbba5, 0, 0, 2, f(Yes, false, "")}, - {0xbbc0, 0, 0, 1, f(Yes, true, "")}, - {0xbbc1, 0, 0, 2, f(Yes, false, "")}, - {0xbbdc, 0, 0, 1, f(Yes, true, "")}, - {0xbbdd, 0, 0, 2, f(Yes, false, "")}, - {0xbbf8, 0, 0, 1, f(Yes, true, "")}, - {0xbbf9, 0, 0, 2, f(Yes, false, "")}, - {0xbc14, 0, 0, 1, f(Yes, true, "")}, - {0xbc15, 0, 0, 2, f(Yes, false, "")}, - {0xbc30, 0, 0, 1, f(Yes, true, "")}, - {0xbc31, 0, 0, 2, f(Yes, false, "")}, - {0xbc4c, 0, 0, 1, f(Yes, true, "")}, - {0xbc4d, 0, 0, 2, f(Yes, false, "")}, - {0xbc68, 0, 0, 1, f(Yes, true, "")}, - {0xbc69, 0, 0, 2, f(Yes, false, "")}, - {0xbc84, 0, 0, 1, f(Yes, true, "")}, - {0xbc85, 0, 0, 2, f(Yes, false, "")}, - {0xbca0, 0, 0, 1, f(Yes, true, "")}, - {0xbca1, 0, 0, 2, f(Yes, false, "")}, - {0xbcbc, 0, 0, 1, f(Yes, true, "")}, - {0xbcbd, 0, 0, 2, f(Yes, false, "")}, - {0xbcd8, 0, 0, 1, f(Yes, true, "")}, - {0xbcd9, 0, 0, 2, f(Yes, false, "")}, - {0xbcf4, 0, 0, 1, f(Yes, true, "")}, - {0xbcf5, 0, 0, 2, f(Yes, false, "")}, - {0xbd10, 0, 0, 1, f(Yes, true, "")}, - {0xbd11, 0, 0, 2, f(Yes, false, "")}, - {0xbd2c, 0, 0, 1, f(Yes, true, "")}, - {0xbd2d, 0, 0, 2, f(Yes, false, "")}, - {0xbd48, 0, 0, 1, f(Yes, true, "")}, - {0xbd49, 0, 0, 2, f(Yes, false, "")}, - {0xbd64, 0, 0, 1, f(Yes, true, "")}, - {0xbd65, 0, 0, 2, f(Yes, false, "")}, - {0xbd80, 0, 0, 1, f(Yes, true, "")}, - {0xbd81, 0, 0, 2, f(Yes, false, "")}, - {0xbd9c, 0, 0, 1, f(Yes, true, "")}, - {0xbd9d, 0, 0, 2, f(Yes, false, "")}, - {0xbdb8, 0, 0, 1, f(Yes, true, "")}, - {0xbdb9, 0, 0, 2, f(Yes, false, "")}, - {0xbdd4, 0, 0, 1, f(Yes, true, "")}, - {0xbdd5, 0, 0, 2, f(Yes, false, "")}, - {0xbdf0, 0, 0, 1, f(Yes, true, "")}, - {0xbdf1, 0, 0, 2, f(Yes, false, "")}, - {0xbe0c, 0, 0, 1, f(Yes, true, "")}, - {0xbe0d, 0, 0, 2, f(Yes, false, "")}, - {0xbe28, 0, 0, 1, f(Yes, true, "")}, - {0xbe29, 0, 0, 2, f(Yes, false, "")}, - {0xbe44, 0, 0, 1, f(Yes, true, "")}, - {0xbe45, 0, 0, 2, f(Yes, false, "")}, - {0xbe60, 0, 0, 1, f(Yes, true, "")}, - {0xbe61, 0, 0, 2, f(Yes, false, "")}, - {0xbe7c, 0, 0, 1, f(Yes, true, "")}, - {0xbe7d, 0, 0, 2, f(Yes, false, "")}, - {0xbe98, 0, 0, 1, f(Yes, true, "")}, - {0xbe99, 0, 0, 2, f(Yes, false, "")}, - {0xbeb4, 0, 0, 1, f(Yes, true, "")}, - {0xbeb5, 0, 0, 2, f(Yes, false, "")}, - {0xbed0, 0, 0, 1, f(Yes, true, "")}, - {0xbed1, 0, 0, 2, f(Yes, false, "")}, - {0xbeec, 0, 0, 1, f(Yes, true, "")}, - {0xbeed, 0, 0, 2, f(Yes, false, "")}, - {0xbf08, 0, 0, 1, f(Yes, true, "")}, - {0xbf09, 0, 0, 2, f(Yes, false, "")}, - {0xbf24, 0, 0, 1, f(Yes, true, "")}, - {0xbf25, 0, 0, 2, f(Yes, false, "")}, - {0xbf40, 0, 0, 1, f(Yes, true, "")}, - {0xbf41, 0, 0, 2, f(Yes, false, "")}, - {0xbf5c, 0, 0, 1, f(Yes, true, "")}, - {0xbf5d, 0, 0, 2, f(Yes, false, "")}, - {0xbf78, 0, 0, 1, f(Yes, true, "")}, - {0xbf79, 0, 0, 2, f(Yes, false, "")}, - {0xbf94, 0, 0, 1, f(Yes, true, "")}, - {0xbf95, 0, 0, 2, f(Yes, false, "")}, - {0xbfb0, 0, 0, 1, f(Yes, true, "")}, - {0xbfb1, 0, 0, 2, f(Yes, false, "")}, - {0xbfcc, 0, 0, 1, f(Yes, true, "")}, - {0xbfcd, 0, 0, 2, f(Yes, false, "")}, - {0xbfe8, 0, 0, 1, f(Yes, true, "")}, - {0xbfe9, 0, 0, 2, f(Yes, false, "")}, - {0xc004, 0, 0, 1, f(Yes, true, "")}, - {0xc005, 0, 0, 2, f(Yes, false, "")}, - {0xc020, 0, 0, 1, f(Yes, true, "")}, - {0xc021, 0, 0, 2, f(Yes, false, "")}, - {0xc03c, 0, 0, 1, f(Yes, true, "")}, - {0xc03d, 0, 0, 2, f(Yes, false, "")}, - {0xc058, 0, 0, 1, f(Yes, true, "")}, - {0xc059, 0, 0, 2, f(Yes, false, "")}, - {0xc074, 0, 0, 1, f(Yes, true, "")}, - {0xc075, 0, 0, 2, f(Yes, false, "")}, - {0xc090, 0, 0, 1, f(Yes, true, "")}, - {0xc091, 0, 0, 2, f(Yes, false, "")}, - {0xc0ac, 0, 0, 1, f(Yes, true, "")}, - {0xc0ad, 0, 0, 2, f(Yes, false, "")}, - {0xc0c8, 0, 0, 1, f(Yes, true, "")}, - {0xc0c9, 0, 0, 2, f(Yes, false, "")}, - {0xc0e4, 0, 0, 1, f(Yes, true, "")}, - {0xc0e5, 0, 0, 2, f(Yes, false, "")}, - {0xc100, 0, 0, 1, f(Yes, true, "")}, - {0xc101, 0, 0, 2, f(Yes, false, "")}, - {0xc11c, 0, 0, 1, f(Yes, true, "")}, - {0xc11d, 0, 0, 2, f(Yes, false, "")}, - {0xc138, 0, 0, 1, f(Yes, true, "")}, - {0xc139, 0, 0, 2, f(Yes, false, "")}, - {0xc154, 0, 0, 1, f(Yes, true, "")}, - {0xc155, 0, 0, 2, f(Yes, false, "")}, - {0xc170, 0, 0, 1, f(Yes, true, "")}, - {0xc171, 0, 0, 2, f(Yes, false, "")}, - {0xc18c, 0, 0, 1, f(Yes, true, "")}, - {0xc18d, 0, 0, 2, f(Yes, false, "")}, - {0xc1a8, 0, 0, 1, f(Yes, true, "")}, - {0xc1a9, 0, 0, 2, f(Yes, false, "")}, - {0xc1c4, 0, 0, 1, f(Yes, true, "")}, - {0xc1c5, 0, 0, 2, f(Yes, false, "")}, - {0xc1e0, 0, 0, 1, f(Yes, true, "")}, - {0xc1e1, 0, 0, 2, f(Yes, false, "")}, - {0xc1fc, 0, 0, 1, f(Yes, true, "")}, - {0xc1fd, 0, 0, 2, f(Yes, false, "")}, - {0xc218, 0, 0, 1, f(Yes, true, "")}, - {0xc219, 0, 0, 2, f(Yes, false, "")}, - {0xc234, 0, 0, 1, f(Yes, true, "")}, - {0xc235, 0, 0, 2, f(Yes, false, "")}, - {0xc250, 0, 0, 1, f(Yes, true, "")}, - {0xc251, 0, 0, 2, f(Yes, false, "")}, - {0xc26c, 0, 0, 1, f(Yes, true, "")}, - {0xc26d, 0, 0, 2, f(Yes, false, "")}, - {0xc288, 0, 0, 1, f(Yes, true, "")}, - {0xc289, 0, 0, 2, f(Yes, false, "")}, - {0xc2a4, 0, 0, 1, f(Yes, true, "")}, - {0xc2a5, 0, 0, 2, f(Yes, false, "")}, - {0xc2c0, 0, 0, 1, f(Yes, true, "")}, - {0xc2c1, 0, 0, 2, f(Yes, false, "")}, - {0xc2dc, 0, 0, 1, f(Yes, true, "")}, - {0xc2dd, 0, 0, 2, f(Yes, false, "")}, - {0xc2f8, 0, 0, 1, f(Yes, true, "")}, - {0xc2f9, 0, 0, 2, f(Yes, false, "")}, - {0xc314, 0, 0, 1, f(Yes, true, "")}, - {0xc315, 0, 0, 2, f(Yes, false, "")}, - {0xc330, 0, 0, 1, f(Yes, true, "")}, - {0xc331, 0, 0, 2, f(Yes, false, "")}, - {0xc34c, 0, 0, 1, f(Yes, true, "")}, - {0xc34d, 0, 0, 2, f(Yes, false, "")}, - {0xc368, 0, 0, 1, f(Yes, true, "")}, - {0xc369, 0, 0, 2, f(Yes, false, "")}, - {0xc384, 0, 0, 1, f(Yes, true, "")}, - {0xc385, 0, 0, 2, f(Yes, false, "")}, - {0xc3a0, 0, 0, 1, f(Yes, true, "")}, - {0xc3a1, 0, 0, 2, f(Yes, false, "")}, - {0xc3bc, 0, 0, 1, f(Yes, true, "")}, - {0xc3bd, 0, 0, 2, f(Yes, false, "")}, - {0xc3d8, 0, 0, 1, f(Yes, true, "")}, - {0xc3d9, 0, 0, 2, f(Yes, false, "")}, - {0xc3f4, 0, 0, 1, f(Yes, true, "")}, - {0xc3f5, 0, 0, 2, f(Yes, false, "")}, - {0xc410, 0, 0, 1, f(Yes, true, "")}, - {0xc411, 0, 0, 2, f(Yes, false, "")}, - {0xc42c, 0, 0, 1, f(Yes, true, "")}, - {0xc42d, 0, 0, 2, f(Yes, false, "")}, - {0xc448, 0, 0, 1, f(Yes, true, "")}, - {0xc449, 0, 0, 2, f(Yes, false, "")}, - {0xc464, 0, 0, 1, f(Yes, true, "")}, - {0xc465, 0, 0, 2, f(Yes, false, "")}, - {0xc480, 0, 0, 1, f(Yes, true, "")}, - {0xc481, 0, 0, 2, f(Yes, false, "")}, - {0xc49c, 0, 0, 1, f(Yes, true, "")}, - {0xc49d, 0, 0, 2, f(Yes, false, "")}, - {0xc4b8, 0, 0, 1, f(Yes, true, "")}, - {0xc4b9, 0, 0, 2, f(Yes, false, "")}, - {0xc4d4, 0, 0, 1, f(Yes, true, "")}, - {0xc4d5, 0, 0, 2, f(Yes, false, "")}, - {0xc4f0, 0, 0, 1, f(Yes, true, "")}, - {0xc4f1, 0, 0, 2, f(Yes, false, "")}, - {0xc50c, 0, 0, 1, f(Yes, true, "")}, - {0xc50d, 0, 0, 2, f(Yes, false, "")}, - {0xc528, 0, 0, 1, f(Yes, true, "")}, - {0xc529, 0, 0, 2, f(Yes, false, "")}, - {0xc544, 0, 0, 1, f(Yes, true, "")}, - {0xc545, 0, 0, 2, f(Yes, false, "")}, - {0xc560, 0, 0, 1, f(Yes, true, "")}, - {0xc561, 0, 0, 2, f(Yes, false, "")}, - {0xc57c, 0, 0, 1, f(Yes, true, "")}, - {0xc57d, 0, 0, 2, f(Yes, false, "")}, - {0xc598, 0, 0, 1, f(Yes, true, "")}, - {0xc599, 0, 0, 2, f(Yes, false, "")}, - {0xc5b4, 0, 0, 1, f(Yes, true, "")}, - {0xc5b5, 0, 0, 2, f(Yes, false, "")}, - {0xc5d0, 0, 0, 1, f(Yes, true, "")}, - {0xc5d1, 0, 0, 2, f(Yes, false, "")}, - {0xc5ec, 0, 0, 1, f(Yes, true, "")}, - {0xc5ed, 0, 0, 2, f(Yes, false, "")}, - {0xc608, 0, 0, 1, f(Yes, true, "")}, - {0xc609, 0, 0, 2, f(Yes, false, "")}, - {0xc624, 0, 0, 1, f(Yes, true, "")}, - {0xc625, 0, 0, 2, f(Yes, false, "")}, - {0xc640, 0, 0, 1, f(Yes, true, "")}, - {0xc641, 0, 0, 2, f(Yes, false, "")}, - {0xc65c, 0, 0, 1, f(Yes, true, "")}, - {0xc65d, 0, 0, 2, f(Yes, false, "")}, - {0xc678, 0, 0, 1, f(Yes, true, "")}, - {0xc679, 0, 0, 2, f(Yes, false, "")}, - {0xc694, 0, 0, 1, f(Yes, true, "")}, - {0xc695, 0, 0, 2, f(Yes, false, "")}, - {0xc6b0, 0, 0, 1, f(Yes, true, "")}, - {0xc6b1, 0, 0, 2, f(Yes, false, "")}, - {0xc6cc, 0, 0, 1, f(Yes, true, "")}, - {0xc6cd, 0, 0, 2, f(Yes, false, "")}, - {0xc6e8, 0, 0, 1, f(Yes, true, "")}, - {0xc6e9, 0, 0, 2, f(Yes, false, "")}, - {0xc704, 0, 0, 1, f(Yes, true, "")}, - {0xc705, 0, 0, 2, f(Yes, false, "")}, - {0xc720, 0, 0, 1, f(Yes, true, "")}, - {0xc721, 0, 0, 2, f(Yes, false, "")}, - {0xc73c, 0, 0, 1, f(Yes, true, "")}, - {0xc73d, 0, 0, 2, f(Yes, false, "")}, - {0xc758, 0, 0, 1, f(Yes, true, "")}, - {0xc759, 0, 0, 2, f(Yes, false, "")}, - {0xc774, 0, 0, 1, f(Yes, true, "")}, - {0xc775, 0, 0, 2, f(Yes, false, "")}, - {0xc790, 0, 0, 1, f(Yes, true, "")}, - {0xc791, 0, 0, 2, f(Yes, false, "")}, - {0xc7ac, 0, 0, 1, f(Yes, true, "")}, - {0xc7ad, 0, 0, 2, f(Yes, false, "")}, - {0xc7c8, 0, 0, 1, f(Yes, true, "")}, - {0xc7c9, 0, 0, 2, f(Yes, false, "")}, - {0xc7e4, 0, 0, 1, f(Yes, true, "")}, - {0xc7e5, 0, 0, 2, f(Yes, false, "")}, - {0xc800, 0, 0, 1, f(Yes, true, "")}, - {0xc801, 0, 0, 2, f(Yes, false, "")}, - {0xc81c, 0, 0, 1, f(Yes, true, "")}, - {0xc81d, 0, 0, 2, f(Yes, false, "")}, - {0xc838, 0, 0, 1, f(Yes, true, "")}, - {0xc839, 0, 0, 2, f(Yes, false, "")}, - {0xc854, 0, 0, 1, f(Yes, true, "")}, - {0xc855, 0, 0, 2, f(Yes, false, "")}, - {0xc870, 0, 0, 1, f(Yes, true, "")}, - {0xc871, 0, 0, 2, f(Yes, false, "")}, - {0xc88c, 0, 0, 1, f(Yes, true, "")}, - {0xc88d, 0, 0, 2, f(Yes, false, "")}, - {0xc8a8, 0, 0, 1, f(Yes, true, "")}, - {0xc8a9, 0, 0, 2, f(Yes, false, "")}, - {0xc8c4, 0, 0, 1, f(Yes, true, "")}, - {0xc8c5, 0, 0, 2, f(Yes, false, "")}, - {0xc8e0, 0, 0, 1, f(Yes, true, "")}, - {0xc8e1, 0, 0, 2, f(Yes, false, "")}, - {0xc8fc, 0, 0, 1, f(Yes, true, "")}, - {0xc8fd, 0, 0, 2, f(Yes, false, "")}, - {0xc918, 0, 0, 1, f(Yes, true, "")}, - {0xc919, 0, 0, 2, f(Yes, false, "")}, - {0xc934, 0, 0, 1, f(Yes, true, "")}, - {0xc935, 0, 0, 2, f(Yes, false, "")}, - {0xc950, 0, 0, 1, f(Yes, true, "")}, - {0xc951, 0, 0, 2, f(Yes, false, "")}, - {0xc96c, 0, 0, 1, f(Yes, true, "")}, - {0xc96d, 0, 0, 2, f(Yes, false, "")}, - {0xc988, 0, 0, 1, f(Yes, true, "")}, - {0xc989, 0, 0, 2, f(Yes, false, "")}, - {0xc9a4, 0, 0, 1, f(Yes, true, "")}, - {0xc9a5, 0, 0, 2, f(Yes, false, "")}, - {0xc9c0, 0, 0, 1, f(Yes, true, "")}, - {0xc9c1, 0, 0, 2, f(Yes, false, "")}, - {0xc9dc, 0, 0, 1, f(Yes, true, "")}, - {0xc9dd, 0, 0, 2, f(Yes, false, "")}, - {0xc9f8, 0, 0, 1, f(Yes, true, "")}, - {0xc9f9, 0, 0, 2, f(Yes, false, "")}, - {0xca14, 0, 0, 1, f(Yes, true, "")}, - {0xca15, 0, 0, 2, f(Yes, false, "")}, - {0xca30, 0, 0, 1, f(Yes, true, "")}, - {0xca31, 0, 0, 2, f(Yes, false, "")}, - {0xca4c, 0, 0, 1, f(Yes, true, "")}, - {0xca4d, 0, 0, 2, f(Yes, false, "")}, - {0xca68, 0, 0, 1, f(Yes, true, "")}, - {0xca69, 0, 0, 2, f(Yes, false, "")}, - {0xca84, 0, 0, 1, f(Yes, true, "")}, - {0xca85, 0, 0, 2, f(Yes, false, "")}, - {0xcaa0, 0, 0, 1, f(Yes, true, "")}, - {0xcaa1, 0, 0, 2, f(Yes, false, "")}, - {0xcabc, 0, 0, 1, f(Yes, true, "")}, - {0xcabd, 0, 0, 2, f(Yes, false, "")}, - {0xcad8, 0, 0, 1, f(Yes, true, "")}, - {0xcad9, 0, 0, 2, f(Yes, false, "")}, - {0xcaf4, 0, 0, 1, f(Yes, true, "")}, - {0xcaf5, 0, 0, 2, f(Yes, false, "")}, - {0xcb10, 0, 0, 1, f(Yes, true, "")}, - {0xcb11, 0, 0, 2, f(Yes, false, "")}, - {0xcb2c, 0, 0, 1, f(Yes, true, "")}, - {0xcb2d, 0, 0, 2, f(Yes, false, "")}, - {0xcb48, 0, 0, 1, f(Yes, true, "")}, - {0xcb49, 0, 0, 2, f(Yes, false, "")}, - {0xcb64, 0, 0, 1, f(Yes, true, "")}, - {0xcb65, 0, 0, 2, f(Yes, false, "")}, - {0xcb80, 0, 0, 1, f(Yes, true, "")}, - {0xcb81, 0, 0, 2, f(Yes, false, "")}, - {0xcb9c, 0, 0, 1, f(Yes, true, "")}, - {0xcb9d, 0, 0, 2, f(Yes, false, "")}, - {0xcbb8, 0, 0, 1, f(Yes, true, "")}, - {0xcbb9, 0, 0, 2, f(Yes, false, "")}, - {0xcbd4, 0, 0, 1, f(Yes, true, "")}, - {0xcbd5, 0, 0, 2, f(Yes, false, "")}, - {0xcbf0, 0, 0, 1, f(Yes, true, "")}, - {0xcbf1, 0, 0, 2, f(Yes, false, "")}, - {0xcc0c, 0, 0, 1, f(Yes, true, "")}, - {0xcc0d, 0, 0, 2, f(Yes, false, "")}, - {0xcc28, 0, 0, 1, f(Yes, true, "")}, - {0xcc29, 0, 0, 2, f(Yes, false, "")}, - {0xcc44, 0, 0, 1, f(Yes, true, "")}, - {0xcc45, 0, 0, 2, f(Yes, false, "")}, - {0xcc60, 0, 0, 1, f(Yes, true, "")}, - {0xcc61, 0, 0, 2, f(Yes, false, "")}, - {0xcc7c, 0, 0, 1, f(Yes, true, "")}, - {0xcc7d, 0, 0, 2, f(Yes, false, "")}, - {0xcc98, 0, 0, 1, f(Yes, true, "")}, - {0xcc99, 0, 0, 2, f(Yes, false, "")}, - {0xccb4, 0, 0, 1, f(Yes, true, "")}, - {0xccb5, 0, 0, 2, f(Yes, false, "")}, - {0xccd0, 0, 0, 1, f(Yes, true, "")}, - {0xccd1, 0, 0, 2, f(Yes, false, "")}, - {0xccec, 0, 0, 1, f(Yes, true, "")}, - {0xcced, 0, 0, 2, f(Yes, false, "")}, - {0xcd08, 0, 0, 1, f(Yes, true, "")}, - {0xcd09, 0, 0, 2, f(Yes, false, "")}, - {0xcd24, 0, 0, 1, f(Yes, true, "")}, - {0xcd25, 0, 0, 2, f(Yes, false, "")}, - {0xcd40, 0, 0, 1, f(Yes, true, "")}, - {0xcd41, 0, 0, 2, f(Yes, false, "")}, - {0xcd5c, 0, 0, 1, f(Yes, true, "")}, - {0xcd5d, 0, 0, 2, f(Yes, false, "")}, - {0xcd78, 0, 0, 1, f(Yes, true, "")}, - {0xcd79, 0, 0, 2, f(Yes, false, "")}, - {0xcd94, 0, 0, 1, f(Yes, true, "")}, - {0xcd95, 0, 0, 2, f(Yes, false, "")}, - {0xcdb0, 0, 0, 1, f(Yes, true, "")}, - {0xcdb1, 0, 0, 2, f(Yes, false, "")}, - {0xcdcc, 0, 0, 1, f(Yes, true, "")}, - {0xcdcd, 0, 0, 2, f(Yes, false, "")}, - {0xcde8, 0, 0, 1, f(Yes, true, "")}, - {0xcde9, 0, 0, 2, f(Yes, false, "")}, - {0xce04, 0, 0, 1, f(Yes, true, "")}, - {0xce05, 0, 0, 2, f(Yes, false, "")}, - {0xce20, 0, 0, 1, f(Yes, true, "")}, - {0xce21, 0, 0, 2, f(Yes, false, "")}, - {0xce3c, 0, 0, 1, f(Yes, true, "")}, - {0xce3d, 0, 0, 2, f(Yes, false, "")}, - {0xce58, 0, 0, 1, f(Yes, true, "")}, - {0xce59, 0, 0, 2, f(Yes, false, "")}, - {0xce74, 0, 0, 1, f(Yes, true, "")}, - {0xce75, 0, 0, 2, f(Yes, false, "")}, - {0xce90, 0, 0, 1, f(Yes, true, "")}, - {0xce91, 0, 0, 2, f(Yes, false, "")}, - {0xceac, 0, 0, 1, f(Yes, true, "")}, - {0xcead, 0, 0, 2, f(Yes, false, "")}, - {0xcec8, 0, 0, 1, f(Yes, true, "")}, - {0xcec9, 0, 0, 2, f(Yes, false, "")}, - {0xcee4, 0, 0, 1, f(Yes, true, "")}, - {0xcee5, 0, 0, 2, f(Yes, false, "")}, - {0xcf00, 0, 0, 1, f(Yes, true, "")}, - {0xcf01, 0, 0, 2, f(Yes, false, "")}, - {0xcf1c, 0, 0, 1, f(Yes, true, "")}, - {0xcf1d, 0, 0, 2, f(Yes, false, "")}, - {0xcf38, 0, 0, 1, f(Yes, true, "")}, - {0xcf39, 0, 0, 2, f(Yes, false, "")}, - {0xcf54, 0, 0, 1, f(Yes, true, "")}, - {0xcf55, 0, 0, 2, f(Yes, false, "")}, - {0xcf70, 0, 0, 1, f(Yes, true, "")}, - {0xcf71, 0, 0, 2, f(Yes, false, "")}, - {0xcf8c, 0, 0, 1, f(Yes, true, "")}, - {0xcf8d, 0, 0, 2, f(Yes, false, "")}, - {0xcfa8, 0, 0, 1, f(Yes, true, "")}, - {0xcfa9, 0, 0, 2, f(Yes, false, "")}, - {0xcfc4, 0, 0, 1, f(Yes, true, "")}, - {0xcfc5, 0, 0, 2, f(Yes, false, "")}, - {0xcfe0, 0, 0, 1, f(Yes, true, "")}, - {0xcfe1, 0, 0, 2, f(Yes, false, "")}, - {0xcffc, 0, 0, 1, f(Yes, true, "")}, - {0xcffd, 0, 0, 2, f(Yes, false, "")}, - {0xd018, 0, 0, 1, f(Yes, true, "")}, - {0xd019, 0, 0, 2, f(Yes, false, "")}, - {0xd034, 0, 0, 1, f(Yes, true, "")}, - {0xd035, 0, 0, 2, f(Yes, false, "")}, - {0xd050, 0, 0, 1, f(Yes, true, "")}, - {0xd051, 0, 0, 2, f(Yes, false, "")}, - {0xd06c, 0, 0, 1, f(Yes, true, "")}, - {0xd06d, 0, 0, 2, f(Yes, false, "")}, - {0xd088, 0, 0, 1, f(Yes, true, "")}, - {0xd089, 0, 0, 2, f(Yes, false, "")}, - {0xd0a4, 0, 0, 1, f(Yes, true, "")}, - {0xd0a5, 0, 0, 2, f(Yes, false, "")}, - {0xd0c0, 0, 0, 1, f(Yes, true, "")}, - {0xd0c1, 0, 0, 2, f(Yes, false, "")}, - {0xd0dc, 0, 0, 1, f(Yes, true, "")}, - {0xd0dd, 0, 0, 2, f(Yes, false, "")}, - {0xd0f8, 0, 0, 1, f(Yes, true, "")}, - {0xd0f9, 0, 0, 2, f(Yes, false, "")}, - {0xd114, 0, 0, 1, f(Yes, true, "")}, - {0xd115, 0, 0, 2, f(Yes, false, "")}, - {0xd130, 0, 0, 1, f(Yes, true, "")}, - {0xd131, 0, 0, 2, f(Yes, false, "")}, - {0xd14c, 0, 0, 1, f(Yes, true, "")}, - {0xd14d, 0, 0, 2, f(Yes, false, "")}, - {0xd168, 0, 0, 1, f(Yes, true, "")}, - {0xd169, 0, 0, 2, f(Yes, false, "")}, - {0xd184, 0, 0, 1, f(Yes, true, "")}, - {0xd185, 0, 0, 2, f(Yes, false, "")}, - {0xd1a0, 0, 0, 1, f(Yes, true, "")}, - {0xd1a1, 0, 0, 2, f(Yes, false, "")}, - {0xd1bc, 0, 0, 1, f(Yes, true, "")}, - {0xd1bd, 0, 0, 2, f(Yes, false, "")}, - {0xd1d8, 0, 0, 1, f(Yes, true, "")}, - {0xd1d9, 0, 0, 2, f(Yes, false, "")}, - {0xd1f4, 0, 0, 1, f(Yes, true, "")}, - {0xd1f5, 0, 0, 2, f(Yes, false, "")}, - {0xd210, 0, 0, 1, f(Yes, true, "")}, - {0xd211, 0, 0, 2, f(Yes, false, "")}, - {0xd22c, 0, 0, 1, f(Yes, true, "")}, - {0xd22d, 0, 0, 2, f(Yes, false, "")}, - {0xd248, 0, 0, 1, f(Yes, true, "")}, - {0xd249, 0, 0, 2, f(Yes, false, "")}, - {0xd264, 0, 0, 1, f(Yes, true, "")}, - {0xd265, 0, 0, 2, f(Yes, false, "")}, - {0xd280, 0, 0, 1, f(Yes, true, "")}, - {0xd281, 0, 0, 2, f(Yes, false, "")}, - {0xd29c, 0, 0, 1, f(Yes, true, "")}, - {0xd29d, 0, 0, 2, f(Yes, false, "")}, - {0xd2b8, 0, 0, 1, f(Yes, true, "")}, - {0xd2b9, 0, 0, 2, f(Yes, false, "")}, - {0xd2d4, 0, 0, 1, f(Yes, true, "")}, - {0xd2d5, 0, 0, 2, f(Yes, false, "")}, - {0xd2f0, 0, 0, 1, f(Yes, true, "")}, - {0xd2f1, 0, 0, 2, f(Yes, false, "")}, - {0xd30c, 0, 0, 1, f(Yes, true, "")}, - {0xd30d, 0, 0, 2, f(Yes, false, "")}, - {0xd328, 0, 0, 1, f(Yes, true, "")}, - {0xd329, 0, 0, 2, f(Yes, false, "")}, - {0xd344, 0, 0, 1, f(Yes, true, "")}, - {0xd345, 0, 0, 2, f(Yes, false, "")}, - {0xd360, 0, 0, 1, f(Yes, true, "")}, - {0xd361, 0, 0, 2, f(Yes, false, "")}, - {0xd37c, 0, 0, 1, f(Yes, true, "")}, - {0xd37d, 0, 0, 2, f(Yes, false, "")}, - {0xd398, 0, 0, 1, f(Yes, true, "")}, - {0xd399, 0, 0, 2, f(Yes, false, "")}, - {0xd3b4, 0, 0, 1, f(Yes, true, "")}, - {0xd3b5, 0, 0, 2, f(Yes, false, "")}, - {0xd3d0, 0, 0, 1, f(Yes, true, "")}, - {0xd3d1, 0, 0, 2, f(Yes, false, "")}, - {0xd3ec, 0, 0, 1, f(Yes, true, "")}, - {0xd3ed, 0, 0, 2, f(Yes, false, "")}, - {0xd408, 0, 0, 1, f(Yes, true, "")}, - {0xd409, 0, 0, 2, f(Yes, false, "")}, - {0xd424, 0, 0, 1, f(Yes, true, "")}, - {0xd425, 0, 0, 2, f(Yes, false, "")}, - {0xd440, 0, 0, 1, f(Yes, true, "")}, - {0xd441, 0, 0, 2, f(Yes, false, "")}, - {0xd45c, 0, 0, 1, f(Yes, true, "")}, - {0xd45d, 0, 0, 2, f(Yes, false, "")}, - {0xd478, 0, 0, 1, f(Yes, true, "")}, - {0xd479, 0, 0, 2, f(Yes, false, "")}, - {0xd494, 0, 0, 1, f(Yes, true, "")}, - {0xd495, 0, 0, 2, f(Yes, false, "")}, - {0xd4b0, 0, 0, 1, f(Yes, true, "")}, - {0xd4b1, 0, 0, 2, f(Yes, false, "")}, - {0xd4cc, 0, 0, 1, f(Yes, true, "")}, - {0xd4cd, 0, 0, 2, f(Yes, false, "")}, - {0xd4e8, 0, 0, 1, f(Yes, true, "")}, - {0xd4e9, 0, 0, 2, f(Yes, false, "")}, - {0xd504, 0, 0, 1, f(Yes, true, "")}, - {0xd505, 0, 0, 2, f(Yes, false, "")}, - {0xd520, 0, 0, 1, f(Yes, true, "")}, - {0xd521, 0, 0, 2, f(Yes, false, "")}, - {0xd53c, 0, 0, 1, f(Yes, true, "")}, - {0xd53d, 0, 0, 2, f(Yes, false, "")}, - {0xd558, 0, 0, 1, f(Yes, true, "")}, - {0xd559, 0, 0, 2, f(Yes, false, "")}, - {0xd574, 0, 0, 1, f(Yes, true, "")}, - {0xd575, 0, 0, 2, f(Yes, false, "")}, - {0xd590, 0, 0, 1, f(Yes, true, "")}, - {0xd591, 0, 0, 2, f(Yes, false, "")}, - {0xd5ac, 0, 0, 1, f(Yes, true, "")}, - {0xd5ad, 0, 0, 2, f(Yes, false, "")}, - {0xd5c8, 0, 0, 1, f(Yes, true, "")}, - {0xd5c9, 0, 0, 2, f(Yes, false, "")}, - {0xd5e4, 0, 0, 1, f(Yes, true, "")}, - {0xd5e5, 0, 0, 2, f(Yes, false, "")}, - {0xd600, 0, 0, 1, f(Yes, true, "")}, - {0xd601, 0, 0, 2, f(Yes, false, "")}, - {0xd61c, 0, 0, 1, f(Yes, true, "")}, - {0xd61d, 0, 0, 2, f(Yes, false, "")}, - {0xd638, 0, 0, 1, f(Yes, true, "")}, - {0xd639, 0, 0, 2, f(Yes, false, "")}, - {0xd654, 0, 0, 1, f(Yes, true, "")}, - {0xd655, 0, 0, 2, f(Yes, false, "")}, - {0xd670, 0, 0, 1, f(Yes, true, "")}, - {0xd671, 0, 0, 2, f(Yes, false, "")}, - {0xd68c, 0, 0, 1, f(Yes, true, "")}, - {0xd68d, 0, 0, 2, f(Yes, false, "")}, - {0xd6a8, 0, 0, 1, f(Yes, true, "")}, - {0xd6a9, 0, 0, 2, f(Yes, false, "")}, - {0xd6c4, 0, 0, 1, f(Yes, true, "")}, - {0xd6c5, 0, 0, 2, f(Yes, false, "")}, - {0xd6e0, 0, 0, 1, f(Yes, true, "")}, - {0xd6e1, 0, 0, 2, f(Yes, false, "")}, - {0xd6fc, 0, 0, 1, f(Yes, true, "")}, - {0xd6fd, 0, 0, 2, f(Yes, false, "")}, - {0xd718, 0, 0, 1, f(Yes, true, "")}, - {0xd719, 0, 0, 2, f(Yes, false, "")}, - {0xd734, 0, 0, 1, f(Yes, true, "")}, - {0xd735, 0, 0, 2, f(Yes, false, "")}, - {0xd750, 0, 0, 1, f(Yes, true, "")}, - {0xd751, 0, 0, 2, f(Yes, false, "")}, - {0xd76c, 0, 0, 1, f(Yes, true, "")}, - {0xd76d, 0, 0, 2, f(Yes, false, "")}, - {0xd788, 0, 0, 1, f(Yes, true, "")}, - {0xd789, 0, 0, 2, f(Yes, false, "")}, - {0xd7a4, 0, 0, 0, f(Yes, false, "")}, - {0xf900, 0, 0, 0, f(No, false, "豈")}, - {0xf901, 0, 0, 0, f(No, false, "更")}, - {0xf902, 0, 0, 0, f(No, false, "車")}, - {0xf903, 0, 0, 0, f(No, false, "賈")}, - {0xf904, 0, 0, 0, f(No, false, "滑")}, - {0xf905, 0, 0, 0, f(No, false, "串")}, - {0xf906, 0, 0, 0, f(No, false, "句")}, - {0xf907, 0, 0, 0, f(No, false, "龜")}, - {0xf909, 0, 0, 0, f(No, false, "契")}, - {0xf90a, 0, 0, 0, f(No, false, "金")}, - {0xf90b, 0, 0, 0, f(No, false, "喇")}, - {0xf90c, 0, 0, 0, f(No, false, "奈")}, - {0xf90d, 0, 0, 0, f(No, false, "懶")}, - {0xf90e, 0, 0, 0, f(No, false, "癩")}, - {0xf90f, 0, 0, 0, f(No, false, "羅")}, - {0xf910, 0, 0, 0, f(No, false, "蘿")}, - {0xf911, 0, 0, 0, f(No, false, "螺")}, - {0xf912, 0, 0, 0, f(No, false, "裸")}, - {0xf913, 0, 0, 0, f(No, false, "邏")}, - {0xf914, 0, 0, 0, f(No, false, "樂")}, - {0xf915, 0, 0, 0, f(No, false, "洛")}, - {0xf916, 0, 0, 0, f(No, false, "烙")}, - {0xf917, 0, 0, 0, f(No, false, "珞")}, - {0xf918, 0, 0, 0, f(No, false, "落")}, - {0xf919, 0, 0, 0, f(No, false, "酪")}, - {0xf91a, 0, 0, 0, f(No, false, "駱")}, - {0xf91b, 0, 0, 0, f(No, false, "亂")}, - {0xf91c, 0, 0, 0, f(No, false, "卵")}, - {0xf91d, 0, 0, 0, f(No, false, "欄")}, - {0xf91e, 0, 0, 0, f(No, false, "爛")}, - {0xf91f, 0, 0, 0, f(No, false, "蘭")}, - {0xf920, 0, 0, 0, f(No, false, "鸞")}, - {0xf921, 0, 0, 0, f(No, false, "嵐")}, - {0xf922, 0, 0, 0, f(No, false, "濫")}, - {0xf923, 0, 0, 0, f(No, false, "藍")}, - {0xf924, 0, 0, 0, f(No, false, "襤")}, - {0xf925, 0, 0, 0, f(No, false, "拉")}, - {0xf926, 0, 0, 0, f(No, false, "臘")}, - {0xf927, 0, 0, 0, f(No, false, "蠟")}, - {0xf928, 0, 0, 0, f(No, false, "廊")}, - {0xf929, 0, 0, 0, f(No, false, "朗")}, - {0xf92a, 0, 0, 0, f(No, false, "浪")}, - {0xf92b, 0, 0, 0, f(No, false, "狼")}, - {0xf92c, 0, 0, 0, f(No, false, "郎")}, - {0xf92d, 0, 0, 0, f(No, false, "來")}, - {0xf92e, 0, 0, 0, f(No, false, "冷")}, - {0xf92f, 0, 0, 0, f(No, false, "勞")}, - {0xf930, 0, 0, 0, f(No, false, "擄")}, - {0xf931, 0, 0, 0, f(No, false, "櫓")}, - {0xf932, 0, 0, 0, f(No, false, "爐")}, - {0xf933, 0, 0, 0, f(No, false, "盧")}, - {0xf934, 0, 0, 0, f(No, false, "老")}, - {0xf935, 0, 0, 0, f(No, false, "蘆")}, - {0xf936, 0, 0, 0, f(No, false, "虜")}, - {0xf937, 0, 0, 0, f(No, false, "路")}, - {0xf938, 0, 0, 0, f(No, false, "露")}, - {0xf939, 0, 0, 0, f(No, false, "魯")}, - {0xf93a, 0, 0, 0, f(No, false, "鷺")}, - {0xf93b, 0, 0, 0, f(No, false, "碌")}, - {0xf93c, 0, 0, 0, f(No, false, "祿")}, - {0xf93d, 0, 0, 0, f(No, false, "綠")}, - {0xf93e, 0, 0, 0, f(No, false, "菉")}, - {0xf93f, 0, 0, 0, f(No, false, "錄")}, - {0xf940, 0, 0, 0, f(No, false, "鹿")}, - {0xf941, 0, 0, 0, f(No, false, "論")}, - {0xf942, 0, 0, 0, f(No, false, "壟")}, - {0xf943, 0, 0, 0, f(No, false, "弄")}, - {0xf944, 0, 0, 0, f(No, false, "籠")}, - {0xf945, 0, 0, 0, f(No, false, "聾")}, - {0xf946, 0, 0, 0, f(No, false, "牢")}, - {0xf947, 0, 0, 0, f(No, false, "磊")}, - {0xf948, 0, 0, 0, f(No, false, "賂")}, - {0xf949, 0, 0, 0, f(No, false, "雷")}, - {0xf94a, 0, 0, 0, f(No, false, "壘")}, - {0xf94b, 0, 0, 0, f(No, false, "屢")}, - {0xf94c, 0, 0, 0, f(No, false, "樓")}, - {0xf94d, 0, 0, 0, f(No, false, "淚")}, - {0xf94e, 0, 0, 0, f(No, false, "漏")}, - {0xf94f, 0, 0, 0, f(No, false, "累")}, - {0xf950, 0, 0, 0, f(No, false, "縷")}, - {0xf951, 0, 0, 0, f(No, false, "陋")}, - {0xf952, 0, 0, 0, f(No, false, "勒")}, - {0xf953, 0, 0, 0, f(No, false, "肋")}, - {0xf954, 0, 0, 0, f(No, false, "凜")}, - {0xf955, 0, 0, 0, f(No, false, "凌")}, - {0xf956, 0, 0, 0, f(No, false, "稜")}, - {0xf957, 0, 0, 0, f(No, false, "綾")}, - {0xf958, 0, 0, 0, f(No, false, "菱")}, - {0xf959, 0, 0, 0, f(No, false, "陵")}, - {0xf95a, 0, 0, 0, f(No, false, "讀")}, - {0xf95b, 0, 0, 0, f(No, false, "拏")}, - {0xf95c, 0, 0, 0, f(No, false, "樂")}, - {0xf95d, 0, 0, 0, f(No, false, "諾")}, - {0xf95e, 0, 0, 0, f(No, false, "丹")}, - {0xf95f, 0, 0, 0, f(No, false, "寧")}, - {0xf960, 0, 0, 0, f(No, false, "怒")}, - {0xf961, 0, 0, 0, f(No, false, "率")}, - {0xf962, 0, 0, 0, f(No, false, "異")}, - {0xf963, 0, 0, 0, f(No, false, "北")}, - {0xf964, 0, 0, 0, f(No, false, "磻")}, - {0xf965, 0, 0, 0, f(No, false, "便")}, - {0xf966, 0, 0, 0, f(No, false, "復")}, - {0xf967, 0, 0, 0, f(No, false, "不")}, - {0xf968, 0, 0, 0, f(No, false, "泌")}, - {0xf969, 0, 0, 0, f(No, false, "數")}, - {0xf96a, 0, 0, 0, f(No, false, "索")}, - {0xf96b, 0, 0, 0, f(No, false, "參")}, - {0xf96c, 0, 0, 0, f(No, false, "塞")}, - {0xf96d, 0, 0, 0, f(No, false, "省")}, - {0xf96e, 0, 0, 0, f(No, false, "葉")}, - {0xf96f, 0, 0, 0, f(No, false, "說")}, - {0xf970, 0, 0, 0, f(No, false, "殺")}, - {0xf971, 0, 0, 0, f(No, false, "辰")}, - {0xf972, 0, 0, 0, f(No, false, "沈")}, - {0xf973, 0, 0, 0, f(No, false, "拾")}, - {0xf974, 0, 0, 0, f(No, false, "若")}, - {0xf975, 0, 0, 0, f(No, false, "掠")}, - {0xf976, 0, 0, 0, f(No, false, "略")}, - {0xf977, 0, 0, 0, f(No, false, "亮")}, - {0xf978, 0, 0, 0, f(No, false, "兩")}, - {0xf979, 0, 0, 0, f(No, false, "凉")}, - {0xf97a, 0, 0, 0, f(No, false, "梁")}, - {0xf97b, 0, 0, 0, f(No, false, "糧")}, - {0xf97c, 0, 0, 0, f(No, false, "良")}, - {0xf97d, 0, 0, 0, f(No, false, "諒")}, - {0xf97e, 0, 0, 0, f(No, false, "量")}, - {0xf97f, 0, 0, 0, f(No, false, "勵")}, - {0xf980, 0, 0, 0, f(No, false, "呂")}, - {0xf981, 0, 0, 0, f(No, false, "女")}, - {0xf982, 0, 0, 0, f(No, false, "廬")}, - {0xf983, 0, 0, 0, f(No, false, "旅")}, - {0xf984, 0, 0, 0, f(No, false, "濾")}, - {0xf985, 0, 0, 0, f(No, false, "礪")}, - {0xf986, 0, 0, 0, f(No, false, "閭")}, - {0xf987, 0, 0, 0, f(No, false, "驪")}, - {0xf988, 0, 0, 0, f(No, false, "麗")}, - {0xf989, 0, 0, 0, f(No, false, "黎")}, - {0xf98a, 0, 0, 0, f(No, false, "力")}, - {0xf98b, 0, 0, 0, f(No, false, "曆")}, - {0xf98c, 0, 0, 0, f(No, false, "歷")}, - {0xf98d, 0, 0, 0, f(No, false, "轢")}, - {0xf98e, 0, 0, 0, f(No, false, "年")}, - {0xf98f, 0, 0, 0, f(No, false, "憐")}, - {0xf990, 0, 0, 0, f(No, false, "戀")}, - {0xf991, 0, 0, 0, f(No, false, "撚")}, - {0xf992, 0, 0, 0, f(No, false, "漣")}, - {0xf993, 0, 0, 0, f(No, false, "煉")}, - {0xf994, 0, 0, 0, f(No, false, "璉")}, - {0xf995, 0, 0, 0, f(No, false, "秊")}, - {0xf996, 0, 0, 0, f(No, false, "練")}, - {0xf997, 0, 0, 0, f(No, false, "聯")}, - {0xf998, 0, 0, 0, f(No, false, "輦")}, - {0xf999, 0, 0, 0, f(No, false, "蓮")}, - {0xf99a, 0, 0, 0, f(No, false, "連")}, - {0xf99b, 0, 0, 0, f(No, false, "鍊")}, - {0xf99c, 0, 0, 0, f(No, false, "列")}, - {0xf99d, 0, 0, 0, f(No, false, "劣")}, - {0xf99e, 0, 0, 0, f(No, false, "咽")}, - {0xf99f, 0, 0, 0, f(No, false, "烈")}, - {0xf9a0, 0, 0, 0, f(No, false, "裂")}, - {0xf9a1, 0, 0, 0, f(No, false, "說")}, - {0xf9a2, 0, 0, 0, f(No, false, "廉")}, - {0xf9a3, 0, 0, 0, f(No, false, "念")}, - {0xf9a4, 0, 0, 0, f(No, false, "捻")}, - {0xf9a5, 0, 0, 0, f(No, false, "殮")}, - {0xf9a6, 0, 0, 0, f(No, false, "簾")}, - {0xf9a7, 0, 0, 0, f(No, false, "獵")}, - {0xf9a8, 0, 0, 0, f(No, false, "令")}, - {0xf9a9, 0, 0, 0, f(No, false, "囹")}, - {0xf9aa, 0, 0, 0, f(No, false, "寧")}, - {0xf9ab, 0, 0, 0, f(No, false, "嶺")}, - {0xf9ac, 0, 0, 0, f(No, false, "怜")}, - {0xf9ad, 0, 0, 0, f(No, false, "玲")}, - {0xf9ae, 0, 0, 0, f(No, false, "瑩")}, - {0xf9af, 0, 0, 0, f(No, false, "羚")}, - {0xf9b0, 0, 0, 0, f(No, false, "聆")}, - {0xf9b1, 0, 0, 0, f(No, false, "鈴")}, - {0xf9b2, 0, 0, 0, f(No, false, "零")}, - {0xf9b3, 0, 0, 0, f(No, false, "靈")}, - {0xf9b4, 0, 0, 0, f(No, false, "領")}, - {0xf9b5, 0, 0, 0, f(No, false, "例")}, - {0xf9b6, 0, 0, 0, f(No, false, "禮")}, - {0xf9b7, 0, 0, 0, f(No, false, "醴")}, - {0xf9b8, 0, 0, 0, f(No, false, "隸")}, - {0xf9b9, 0, 0, 0, f(No, false, "惡")}, - {0xf9ba, 0, 0, 0, f(No, false, "了")}, - {0xf9bb, 0, 0, 0, f(No, false, "僚")}, - {0xf9bc, 0, 0, 0, f(No, false, "寮")}, - {0xf9bd, 0, 0, 0, f(No, false, "尿")}, - {0xf9be, 0, 0, 0, f(No, false, "料")}, - {0xf9bf, 0, 0, 0, f(No, false, "樂")}, - {0xf9c0, 0, 0, 0, f(No, false, "燎")}, - {0xf9c1, 0, 0, 0, f(No, false, "療")}, - {0xf9c2, 0, 0, 0, f(No, false, "蓼")}, - {0xf9c3, 0, 0, 0, f(No, false, "遼")}, - {0xf9c4, 0, 0, 0, f(No, false, "龍")}, - {0xf9c5, 0, 0, 0, f(No, false, "暈")}, - {0xf9c6, 0, 0, 0, f(No, false, "阮")}, - {0xf9c7, 0, 0, 0, f(No, false, "劉")}, - {0xf9c8, 0, 0, 0, f(No, false, "杻")}, - {0xf9c9, 0, 0, 0, f(No, false, "柳")}, - {0xf9ca, 0, 0, 0, f(No, false, "流")}, - {0xf9cb, 0, 0, 0, f(No, false, "溜")}, - {0xf9cc, 0, 0, 0, f(No, false, "琉")}, - {0xf9cd, 0, 0, 0, f(No, false, "留")}, - {0xf9ce, 0, 0, 0, f(No, false, "硫")}, - {0xf9cf, 0, 0, 0, f(No, false, "紐")}, - {0xf9d0, 0, 0, 0, f(No, false, "類")}, - {0xf9d1, 0, 0, 0, f(No, false, "六")}, - {0xf9d2, 0, 0, 0, f(No, false, "戮")}, - {0xf9d3, 0, 0, 0, f(No, false, "陸")}, - {0xf9d4, 0, 0, 0, f(No, false, "倫")}, - {0xf9d5, 0, 0, 0, f(No, false, "崙")}, - {0xf9d6, 0, 0, 0, f(No, false, "淪")}, - {0xf9d7, 0, 0, 0, f(No, false, "輪")}, - {0xf9d8, 0, 0, 0, f(No, false, "律")}, - {0xf9d9, 0, 0, 0, f(No, false, "慄")}, - {0xf9da, 0, 0, 0, f(No, false, "栗")}, - {0xf9db, 0, 0, 0, f(No, false, "率")}, - {0xf9dc, 0, 0, 0, f(No, false, "隆")}, - {0xf9dd, 0, 0, 0, f(No, false, "利")}, - {0xf9de, 0, 0, 0, f(No, false, "吏")}, - {0xf9df, 0, 0, 0, f(No, false, "履")}, - {0xf9e0, 0, 0, 0, f(No, false, "易")}, - {0xf9e1, 0, 0, 0, f(No, false, "李")}, - {0xf9e2, 0, 0, 0, f(No, false, "梨")}, - {0xf9e3, 0, 0, 0, f(No, false, "泥")}, - {0xf9e4, 0, 0, 0, f(No, false, "理")}, - {0xf9e5, 0, 0, 0, f(No, false, "痢")}, - {0xf9e6, 0, 0, 0, f(No, false, "罹")}, - {0xf9e7, 0, 0, 0, f(No, false, "裏")}, - {0xf9e8, 0, 0, 0, f(No, false, "裡")}, - {0xf9e9, 0, 0, 0, f(No, false, "里")}, - {0xf9ea, 0, 0, 0, f(No, false, "離")}, - {0xf9eb, 0, 0, 0, f(No, false, "匿")}, - {0xf9ec, 0, 0, 0, f(No, false, "溺")}, - {0xf9ed, 0, 0, 0, f(No, false, "吝")}, - {0xf9ee, 0, 0, 0, f(No, false, "燐")}, - {0xf9ef, 0, 0, 0, f(No, false, "璘")}, - {0xf9f0, 0, 0, 0, f(No, false, "藺")}, - {0xf9f1, 0, 0, 0, f(No, false, "隣")}, - {0xf9f2, 0, 0, 0, f(No, false, "鱗")}, - {0xf9f3, 0, 0, 0, f(No, false, "麟")}, - {0xf9f4, 0, 0, 0, f(No, false, "林")}, - {0xf9f5, 0, 0, 0, f(No, false, "淋")}, - {0xf9f6, 0, 0, 0, f(No, false, "臨")}, - {0xf9f7, 0, 0, 0, f(No, false, "立")}, - {0xf9f8, 0, 0, 0, f(No, false, "笠")}, - {0xf9f9, 0, 0, 0, f(No, false, "粒")}, - {0xf9fa, 0, 0, 0, f(No, false, "狀")}, - {0xf9fb, 0, 0, 0, f(No, false, "炙")}, - {0xf9fc, 0, 0, 0, f(No, false, "識")}, - {0xf9fd, 0, 0, 0, f(No, false, "什")}, - {0xf9fe, 0, 0, 0, f(No, false, "茶")}, - {0xf9ff, 0, 0, 0, f(No, false, "刺")}, - {0xfa00, 0, 0, 0, f(No, false, "切")}, - {0xfa01, 0, 0, 0, f(No, false, "度")}, - {0xfa02, 0, 0, 0, f(No, false, "拓")}, - {0xfa03, 0, 0, 0, f(No, false, "糖")}, - {0xfa04, 0, 0, 0, f(No, false, "宅")}, - {0xfa05, 0, 0, 0, f(No, false, "洞")}, - {0xfa06, 0, 0, 0, f(No, false, "暴")}, - {0xfa07, 0, 0, 0, f(No, false, "輻")}, - {0xfa08, 0, 0, 0, f(No, false, "行")}, - {0xfa09, 0, 0, 0, f(No, false, "降")}, - {0xfa0a, 0, 0, 0, f(No, false, "見")}, - {0xfa0b, 0, 0, 0, f(No, false, "廓")}, - {0xfa0c, 0, 0, 0, f(No, false, "兀")}, - {0xfa0d, 0, 0, 0, f(No, false, "嗀")}, - {0xfa0e, 0, 0, 0, f(Yes, false, "")}, - {0xfa10, 0, 0, 0, f(No, false, "塚")}, - {0xfa11, 0, 0, 0, f(Yes, false, "")}, - {0xfa12, 0, 0, 0, f(No, false, "晴")}, - {0xfa13, 0, 0, 0, f(Yes, false, "")}, - {0xfa15, 0, 0, 0, f(No, false, "凞")}, - {0xfa16, 0, 0, 0, f(No, false, "猪")}, - {0xfa17, 0, 0, 0, f(No, false, "益")}, - {0xfa18, 0, 0, 0, f(No, false, "礼")}, - {0xfa19, 0, 0, 0, f(No, false, "神")}, - {0xfa1a, 0, 0, 0, f(No, false, "祥")}, - {0xfa1b, 0, 0, 0, f(No, false, "福")}, - {0xfa1c, 0, 0, 0, f(No, false, "靖")}, - {0xfa1d, 0, 0, 0, f(No, false, "精")}, - {0xfa1e, 0, 0, 0, f(No, false, "羽")}, - {0xfa1f, 0, 0, 0, f(Yes, false, "")}, - {0xfa20, 0, 0, 0, f(No, false, "蘒")}, - {0xfa21, 0, 0, 0, f(Yes, false, "")}, - {0xfa22, 0, 0, 0, f(No, false, "諸")}, - {0xfa23, 0, 0, 0, f(Yes, false, "")}, - {0xfa25, 0, 0, 0, f(No, false, "逸")}, - {0xfa26, 0, 0, 0, f(No, false, "都")}, - {0xfa27, 0, 0, 0, f(Yes, false, "")}, - {0xfa2a, 0, 0, 0, f(No, false, "飯")}, - {0xfa2b, 0, 0, 0, f(No, false, "飼")}, - {0xfa2c, 0, 0, 0, f(No, false, "館")}, - {0xfa2d, 0, 0, 0, f(No, false, "鶴")}, - {0xfa2e, 0, 0, 0, f(No, false, "郞")}, - {0xfa2f, 0, 0, 0, f(No, false, "隷")}, - {0xfa30, 0, 0, 0, f(No, false, "侮")}, - {0xfa31, 0, 0, 0, f(No, false, "僧")}, - {0xfa32, 0, 0, 0, f(No, false, "免")}, - {0xfa33, 0, 0, 0, f(No, false, "勉")}, - {0xfa34, 0, 0, 0, f(No, false, "勤")}, - {0xfa35, 0, 0, 0, f(No, false, "卑")}, - {0xfa36, 0, 0, 0, f(No, false, "喝")}, - {0xfa37, 0, 0, 0, f(No, false, "嘆")}, - {0xfa38, 0, 0, 0, f(No, false, "器")}, - {0xfa39, 0, 0, 0, f(No, false, "塀")}, - {0xfa3a, 0, 0, 0, f(No, false, "墨")}, - {0xfa3b, 0, 0, 0, f(No, false, "層")}, - {0xfa3c, 0, 0, 0, f(No, false, "屮")}, - {0xfa3d, 0, 0, 0, f(No, false, "悔")}, - {0xfa3e, 0, 0, 0, f(No, false, "慨")}, - {0xfa3f, 0, 0, 0, f(No, false, "憎")}, - {0xfa40, 0, 0, 0, f(No, false, "懲")}, - {0xfa41, 0, 0, 0, f(No, false, "敏")}, - {0xfa42, 0, 0, 0, f(No, false, "既")}, - {0xfa43, 0, 0, 0, f(No, false, "暑")}, - {0xfa44, 0, 0, 0, f(No, false, "梅")}, - {0xfa45, 0, 0, 0, f(No, false, "海")}, - {0xfa46, 0, 0, 0, f(No, false, "渚")}, - {0xfa47, 0, 0, 0, f(No, false, "漢")}, - {0xfa48, 0, 0, 0, f(No, false, "煮")}, - {0xfa49, 0, 0, 0, f(No, false, "爫")}, - {0xfa4a, 0, 0, 0, f(No, false, "琢")}, - {0xfa4b, 0, 0, 0, f(No, false, "碑")}, - {0xfa4c, 0, 0, 0, f(No, false, "社")}, - {0xfa4d, 0, 0, 0, f(No, false, "祉")}, - {0xfa4e, 0, 0, 0, f(No, false, "祈")}, - {0xfa4f, 0, 0, 0, f(No, false, "祐")}, - {0xfa50, 0, 0, 0, f(No, false, "祖")}, - {0xfa51, 0, 0, 0, f(No, false, "祝")}, - {0xfa52, 0, 0, 0, f(No, false, "禍")}, - {0xfa53, 0, 0, 0, f(No, false, "禎")}, - {0xfa54, 0, 0, 0, f(No, false, "穀")}, - {0xfa55, 0, 0, 0, f(No, false, "突")}, - {0xfa56, 0, 0, 0, f(No, false, "節")}, - {0xfa57, 0, 0, 0, f(No, false, "練")}, - {0xfa58, 0, 0, 0, f(No, false, "縉")}, - {0xfa59, 0, 0, 0, f(No, false, "繁")}, - {0xfa5a, 0, 0, 0, f(No, false, "署")}, - {0xfa5b, 0, 0, 0, f(No, false, "者")}, - {0xfa5c, 0, 0, 0, f(No, false, "臭")}, - {0xfa5d, 0, 0, 0, f(No, false, "艹")}, - {0xfa5f, 0, 0, 0, f(No, false, "著")}, - {0xfa60, 0, 0, 0, f(No, false, "褐")}, - {0xfa61, 0, 0, 0, f(No, false, "視")}, - {0xfa62, 0, 0, 0, f(No, false, "謁")}, - {0xfa63, 0, 0, 0, f(No, false, "謹")}, - {0xfa64, 0, 0, 0, f(No, false, "賓")}, - {0xfa65, 0, 0, 0, f(No, false, "贈")}, - {0xfa66, 0, 0, 0, f(No, false, "辶")}, - {0xfa67, 0, 0, 0, f(No, false, "逸")}, - {0xfa68, 0, 0, 0, f(No, false, "難")}, - {0xfa69, 0, 0, 0, f(No, false, "響")}, - {0xfa6a, 0, 0, 0, f(No, false, "頻")}, - {0xfa6b, 0, 0, 0, f(No, false, "恵")}, - {0xfa6c, 0, 0, 0, f(No, false, "𤋮")}, - {0xfa6d, 0, 0, 0, f(No, false, "舘")}, - {0xfa6e, 0, 0, 0, f(Yes, false, "")}, - {0xfa70, 0, 0, 0, f(No, false, "並")}, - {0xfa71, 0, 0, 0, f(No, false, "况")}, - {0xfa72, 0, 0, 0, f(No, false, "全")}, - {0xfa73, 0, 0, 0, f(No, false, "侀")}, - {0xfa74, 0, 0, 0, f(No, false, "充")}, - {0xfa75, 0, 0, 0, f(No, false, "冀")}, - {0xfa76, 0, 0, 0, f(No, false, "勇")}, - {0xfa77, 0, 0, 0, f(No, false, "勺")}, - {0xfa78, 0, 0, 0, f(No, false, "喝")}, - {0xfa79, 0, 0, 0, f(No, false, "啕")}, - {0xfa7a, 0, 0, 0, f(No, false, "喙")}, - {0xfa7b, 0, 0, 0, f(No, false, "嗢")}, - {0xfa7c, 0, 0, 0, f(No, false, "塚")}, - {0xfa7d, 0, 0, 0, f(No, false, "墳")}, - {0xfa7e, 0, 0, 0, f(No, false, "奄")}, - {0xfa7f, 0, 0, 0, f(No, false, "奔")}, - {0xfa80, 0, 0, 0, f(No, false, "婢")}, - {0xfa81, 0, 0, 0, f(No, false, "嬨")}, - {0xfa82, 0, 0, 0, f(No, false, "廒")}, - {0xfa83, 0, 0, 0, f(No, false, "廙")}, - {0xfa84, 0, 0, 0, f(No, false, "彩")}, - {0xfa85, 0, 0, 0, f(No, false, "徭")}, - {0xfa86, 0, 0, 0, f(No, false, "惘")}, - {0xfa87, 0, 0, 0, f(No, false, "慎")}, - {0xfa88, 0, 0, 0, f(No, false, "愈")}, - {0xfa89, 0, 0, 0, f(No, false, "憎")}, - {0xfa8a, 0, 0, 0, f(No, false, "慠")}, - {0xfa8b, 0, 0, 0, f(No, false, "懲")}, - {0xfa8c, 0, 0, 0, f(No, false, "戴")}, - {0xfa8d, 0, 0, 0, f(No, false, "揄")}, - {0xfa8e, 0, 0, 0, f(No, false, "搜")}, - {0xfa8f, 0, 0, 0, f(No, false, "摒")}, - {0xfa90, 0, 0, 0, f(No, false, "敖")}, - {0xfa91, 0, 0, 0, f(No, false, "晴")}, - {0xfa92, 0, 0, 0, f(No, false, "朗")}, - {0xfa93, 0, 0, 0, f(No, false, "望")}, - {0xfa94, 0, 0, 0, f(No, false, "杖")}, - {0xfa95, 0, 0, 0, f(No, false, "歹")}, - {0xfa96, 0, 0, 0, f(No, false, "殺")}, - {0xfa97, 0, 0, 0, f(No, false, "流")}, - {0xfa98, 0, 0, 0, f(No, false, "滛")}, - {0xfa99, 0, 0, 0, f(No, false, "滋")}, - {0xfa9a, 0, 0, 0, f(No, false, "漢")}, - {0xfa9b, 0, 0, 0, f(No, false, "瀞")}, - {0xfa9c, 0, 0, 0, f(No, false, "煮")}, - {0xfa9d, 0, 0, 0, f(No, false, "瞧")}, - {0xfa9e, 0, 0, 0, f(No, false, "爵")}, - {0xfa9f, 0, 0, 0, f(No, false, "犯")}, - {0xfaa0, 0, 0, 0, f(No, false, "猪")}, - {0xfaa1, 0, 0, 0, f(No, false, "瑱")}, - {0xfaa2, 0, 0, 0, f(No, false, "甆")}, - {0xfaa3, 0, 0, 0, f(No, false, "画")}, - {0xfaa4, 0, 0, 0, f(No, false, "瘝")}, - {0xfaa5, 0, 0, 0, f(No, false, "瘟")}, - {0xfaa6, 0, 0, 0, f(No, false, "益")}, - {0xfaa7, 0, 0, 0, f(No, false, "盛")}, - {0xfaa8, 0, 0, 0, f(No, false, "直")}, - {0xfaa9, 0, 0, 0, f(No, false, "睊")}, - {0xfaaa, 0, 0, 0, f(No, false, "着")}, - {0xfaab, 0, 0, 0, f(No, false, "磌")}, - {0xfaac, 0, 0, 0, f(No, false, "窱")}, - {0xfaad, 0, 0, 0, f(No, false, "節")}, - {0xfaae, 0, 0, 0, f(No, false, "类")}, - {0xfaaf, 0, 0, 0, f(No, false, "絛")}, - {0xfab0, 0, 0, 0, f(No, false, "練")}, - {0xfab1, 0, 0, 0, f(No, false, "缾")}, - {0xfab2, 0, 0, 0, f(No, false, "者")}, - {0xfab3, 0, 0, 0, f(No, false, "荒")}, - {0xfab4, 0, 0, 0, f(No, false, "華")}, - {0xfab5, 0, 0, 0, f(No, false, "蝹")}, - {0xfab6, 0, 0, 0, f(No, false, "襁")}, - {0xfab7, 0, 0, 0, f(No, false, "覆")}, - {0xfab8, 0, 0, 0, f(No, false, "視")}, - {0xfab9, 0, 0, 0, f(No, false, "調")}, - {0xfaba, 0, 0, 0, f(No, false, "諸")}, - {0xfabb, 0, 0, 0, f(No, false, "請")}, - {0xfabc, 0, 0, 0, f(No, false, "謁")}, - {0xfabd, 0, 0, 0, f(No, false, "諾")}, - {0xfabe, 0, 0, 0, f(No, false, "諭")}, - {0xfabf, 0, 0, 0, f(No, false, "謹")}, - {0xfac0, 0, 0, 0, f(No, false, "變")}, - {0xfac1, 0, 0, 0, f(No, false, "贈")}, - {0xfac2, 0, 0, 0, f(No, false, "輸")}, - {0xfac3, 0, 0, 0, f(No, false, "遲")}, - {0xfac4, 0, 0, 0, f(No, false, "醙")}, - {0xfac5, 0, 0, 0, f(No, false, "鉶")}, - {0xfac6, 0, 0, 0, f(No, false, "陼")}, - {0xfac7, 0, 0, 0, f(No, false, "難")}, - {0xfac8, 0, 0, 0, f(No, false, "靖")}, - {0xfac9, 0, 0, 0, f(No, false, "韛")}, - {0xfaca, 0, 0, 0, f(No, false, "響")}, - {0xfacb, 0, 0, 0, f(No, false, "頋")}, - {0xfacc, 0, 0, 0, f(No, false, "頻")}, - {0xfacd, 0, 0, 0, f(No, false, "鬒")}, - {0xface, 0, 0, 0, f(No, false, "龜")}, - {0xfacf, 0, 0, 0, f(No, false, "𢡊")}, - {0xfad0, 0, 0, 0, f(No, false, "𢡄")}, - {0xfad1, 0, 0, 0, f(No, false, "𣏕")}, - {0xfad2, 0, 0, 0, f(No, false, "㮝")}, - {0xfad3, 0, 0, 0, f(No, false, "䀘")}, - {0xfad4, 0, 0, 0, f(No, false, "䀹")}, - {0xfad5, 0, 0, 0, f(No, false, "𥉉")}, - {0xfad6, 0, 0, 0, f(No, false, "𥳐")}, - {0xfad7, 0, 0, 0, f(No, false, "𧻓")}, - {0xfad8, 0, 0, 0, f(No, false, "齃")}, - {0xfad9, 0, 0, 0, f(No, false, "龎")}, - {0xfada, 0, 0, 0, f(Yes, false, "")}, - {0xfb00, 0, 0, 0, g(Yes, No, false, false, "", "ff")}, - {0xfb01, 0, 0, 0, g(Yes, No, false, false, "", "fi")}, - {0xfb02, 0, 0, 0, g(Yes, No, false, false, "", "fl")}, - {0xfb03, 0, 0, 0, g(Yes, No, false, false, "", "ffi")}, - {0xfb04, 0, 0, 0, g(Yes, No, false, false, "", "ffl")}, - {0xfb05, 0, 0, 0, g(Yes, No, false, false, "", "st")}, - {0xfb07, 0, 0, 0, f(Yes, false, "")}, - {0xfb13, 0, 0, 0, g(Yes, No, false, false, "", "մն")}, - {0xfb14, 0, 0, 0, g(Yes, No, false, false, "", "մե")}, - {0xfb15, 0, 0, 0, g(Yes, No, false, false, "", "մի")}, - {0xfb16, 0, 0, 0, g(Yes, No, false, false, "", "վն")}, - {0xfb17, 0, 0, 0, g(Yes, No, false, false, "", "մխ")}, - {0xfb18, 0, 0, 0, f(Yes, false, "")}, - {0xfb1d, 0, 0, 1, f(No, false, "יִ")}, - {0xfb1e, 26, 1, 1, f(Yes, false, "")}, - {0xfb1f, 0, 0, 1, f(No, false, "ײַ")}, - {0xfb20, 0, 0, 0, g(Yes, No, false, false, "", "ע")}, - {0xfb21, 0, 0, 0, g(Yes, No, false, false, "", "א")}, - {0xfb22, 0, 0, 0, g(Yes, No, false, false, "", "ד")}, - {0xfb23, 0, 0, 0, g(Yes, No, false, false, "", "ה")}, - {0xfb24, 0, 0, 0, g(Yes, No, false, false, "", "כ")}, - {0xfb25, 0, 0, 0, g(Yes, No, false, false, "", "ל")}, - {0xfb26, 0, 0, 0, g(Yes, No, false, false, "", "ם")}, - {0xfb27, 0, 0, 0, g(Yes, No, false, false, "", "ר")}, - {0xfb28, 0, 0, 0, g(Yes, No, false, false, "", "ת")}, - {0xfb29, 0, 0, 0, g(Yes, No, false, false, "", "+")}, - {0xfb2a, 0, 0, 1, f(No, false, "שׁ")}, - {0xfb2b, 0, 0, 1, f(No, false, "שׂ")}, - {0xfb2c, 0, 0, 2, f(No, false, "שּׁ")}, - {0xfb2d, 0, 0, 2, f(No, false, "שּׂ")}, - {0xfb2e, 0, 0, 1, f(No, false, "אַ")}, - {0xfb2f, 0, 0, 1, f(No, false, "אָ")}, - {0xfb30, 0, 0, 1, f(No, false, "אּ")}, - {0xfb31, 0, 0, 1, f(No, false, "בּ")}, - {0xfb32, 0, 0, 1, f(No, false, "גּ")}, - {0xfb33, 0, 0, 1, f(No, false, "דּ")}, - {0xfb34, 0, 0, 1, f(No, false, "הּ")}, - {0xfb35, 0, 0, 1, f(No, false, "וּ")}, - {0xfb36, 0, 0, 1, f(No, false, "זּ")}, - {0xfb37, 0, 0, 0, f(Yes, false, "")}, - {0xfb38, 0, 0, 1, f(No, false, "טּ")}, - {0xfb39, 0, 0, 1, f(No, false, "יּ")}, - {0xfb3a, 0, 0, 1, f(No, false, "ךּ")}, - {0xfb3b, 0, 0, 1, f(No, false, "כּ")}, - {0xfb3c, 0, 0, 1, f(No, false, "לּ")}, - {0xfb3d, 0, 0, 0, f(Yes, false, "")}, - {0xfb3e, 0, 0, 1, f(No, false, "מּ")}, - {0xfb3f, 0, 0, 0, f(Yes, false, "")}, - {0xfb40, 0, 0, 1, f(No, false, "נּ")}, - {0xfb41, 0, 0, 1, f(No, false, "סּ")}, - {0xfb42, 0, 0, 0, f(Yes, false, "")}, - {0xfb43, 0, 0, 1, f(No, false, "ףּ")}, - {0xfb44, 0, 0, 1, f(No, false, "פּ")}, - {0xfb45, 0, 0, 0, f(Yes, false, "")}, - {0xfb46, 0, 0, 1, f(No, false, "צּ")}, - {0xfb47, 0, 0, 1, f(No, false, "קּ")}, - {0xfb48, 0, 0, 1, f(No, false, "רּ")}, - {0xfb49, 0, 0, 1, f(No, false, "שּ")}, - {0xfb4a, 0, 0, 1, f(No, false, "תּ")}, - {0xfb4b, 0, 0, 1, f(No, false, "וֹ")}, - {0xfb4c, 0, 0, 1, f(No, false, "בֿ")}, - {0xfb4d, 0, 0, 1, f(No, false, "כֿ")}, - {0xfb4e, 0, 0, 1, f(No, false, "פֿ")}, - {0xfb4f, 0, 0, 0, g(Yes, No, false, false, "", "אל")}, - {0xfb50, 0, 0, 0, g(Yes, No, false, false, "", "ٱ")}, - {0xfb52, 0, 0, 0, g(Yes, No, false, false, "", "ٻ")}, - {0xfb56, 0, 0, 0, g(Yes, No, false, false, "", "پ")}, - {0xfb5a, 0, 0, 0, g(Yes, No, false, false, "", "ڀ")}, - {0xfb5e, 0, 0, 0, g(Yes, No, false, false, "", "ٺ")}, - {0xfb62, 0, 0, 0, g(Yes, No, false, false, "", "ٿ")}, - {0xfb66, 0, 0, 0, g(Yes, No, false, false, "", "ٹ")}, - {0xfb6a, 0, 0, 0, g(Yes, No, false, false, "", "ڤ")}, - {0xfb6e, 0, 0, 0, g(Yes, No, false, false, "", "ڦ")}, - {0xfb72, 0, 0, 0, g(Yes, No, false, false, "", "ڄ")}, - {0xfb76, 0, 0, 0, g(Yes, No, false, false, "", "ڃ")}, - {0xfb7a, 0, 0, 0, g(Yes, No, false, false, "", "چ")}, - {0xfb7e, 0, 0, 0, g(Yes, No, false, false, "", "ڇ")}, - {0xfb82, 0, 0, 0, g(Yes, No, false, false, "", "ڍ")}, - {0xfb84, 0, 0, 0, g(Yes, No, false, false, "", "ڌ")}, - {0xfb86, 0, 0, 0, g(Yes, No, false, false, "", "ڎ")}, - {0xfb88, 0, 0, 0, g(Yes, No, false, false, "", "ڈ")}, - {0xfb8a, 0, 0, 0, g(Yes, No, false, false, "", "ژ")}, - {0xfb8c, 0, 0, 0, g(Yes, No, false, false, "", "ڑ")}, - {0xfb8e, 0, 0, 0, g(Yes, No, false, false, "", "ک")}, - {0xfb92, 0, 0, 0, g(Yes, No, false, false, "", "گ")}, - {0xfb96, 0, 0, 0, g(Yes, No, false, false, "", "ڳ")}, - {0xfb9a, 0, 0, 0, g(Yes, No, false, false, "", "ڱ")}, - {0xfb9e, 0, 0, 0, g(Yes, No, false, false, "", "ں")}, - {0xfba0, 0, 0, 0, g(Yes, No, false, false, "", "ڻ")}, - {0xfba4, 0, 0, 1, g(Yes, No, false, false, "", "ۀ")}, - {0xfba6, 0, 0, 0, g(Yes, No, false, false, "", "ہ")}, - {0xfbaa, 0, 0, 0, g(Yes, No, false, false, "", "ھ")}, - {0xfbae, 0, 0, 0, g(Yes, No, false, false, "", "ے")}, - {0xfbb0, 0, 0, 1, g(Yes, No, false, false, "", "ۓ")}, - {0xfbb2, 0, 0, 0, f(Yes, false, "")}, - {0xfbd3, 0, 0, 0, g(Yes, No, false, false, "", "ڭ")}, - {0xfbd7, 0, 0, 0, g(Yes, No, false, false, "", "ۇ")}, - {0xfbd9, 0, 0, 0, g(Yes, No, false, false, "", "ۆ")}, - {0xfbdb, 0, 0, 0, g(Yes, No, false, false, "", "ۈ")}, - {0xfbdd, 0, 0, 0, g(Yes, No, false, false, "", "ۇٴ")}, - {0xfbde, 0, 0, 0, g(Yes, No, false, false, "", "ۋ")}, - {0xfbe0, 0, 0, 0, g(Yes, No, false, false, "", "ۅ")}, - {0xfbe2, 0, 0, 0, g(Yes, No, false, false, "", "ۉ")}, - {0xfbe4, 0, 0, 0, g(Yes, No, false, false, "", "ې")}, - {0xfbe8, 0, 0, 0, g(Yes, No, false, false, "", "ى")}, - {0xfbea, 0, 0, 0, g(Yes, No, false, false, "", "ئا")}, - {0xfbec, 0, 0, 0, g(Yes, No, false, false, "", "ئە")}, - {0xfbee, 0, 0, 0, g(Yes, No, false, false, "", "ئو")}, - {0xfbf0, 0, 0, 0, g(Yes, No, false, false, "", "ئۇ")}, - {0xfbf2, 0, 0, 0, g(Yes, No, false, false, "", "ئۆ")}, - {0xfbf4, 0, 0, 0, g(Yes, No, false, false, "", "ئۈ")}, - {0xfbf6, 0, 0, 0, g(Yes, No, false, false, "", "ئې")}, - {0xfbf9, 0, 0, 0, g(Yes, No, false, false, "", "ئى")}, - {0xfbfc, 0, 0, 0, g(Yes, No, false, false, "", "ی")}, - {0xfc00, 0, 0, 0, g(Yes, No, false, false, "", "ئج")}, - {0xfc01, 0, 0, 0, g(Yes, No, false, false, "", "ئح")}, - {0xfc02, 0, 0, 0, g(Yes, No, false, false, "", "ئم")}, - {0xfc03, 0, 0, 0, g(Yes, No, false, false, "", "ئى")}, - {0xfc04, 0, 0, 0, g(Yes, No, false, false, "", "ئي")}, - {0xfc05, 0, 0, 0, g(Yes, No, false, false, "", "بج")}, - {0xfc06, 0, 0, 0, g(Yes, No, false, false, "", "بح")}, - {0xfc07, 0, 0, 0, g(Yes, No, false, false, "", "بخ")}, - {0xfc08, 0, 0, 0, g(Yes, No, false, false, "", "بم")}, - {0xfc09, 0, 0, 0, g(Yes, No, false, false, "", "بى")}, - {0xfc0a, 0, 0, 0, g(Yes, No, false, false, "", "بي")}, - {0xfc0b, 0, 0, 0, g(Yes, No, false, false, "", "تج")}, - {0xfc0c, 0, 0, 0, g(Yes, No, false, false, "", "تح")}, - {0xfc0d, 0, 0, 0, g(Yes, No, false, false, "", "تخ")}, - {0xfc0e, 0, 0, 0, g(Yes, No, false, false, "", "تم")}, - {0xfc0f, 0, 0, 0, g(Yes, No, false, false, "", "تى")}, - {0xfc10, 0, 0, 0, g(Yes, No, false, false, "", "تي")}, - {0xfc11, 0, 0, 0, g(Yes, No, false, false, "", "ثج")}, - {0xfc12, 0, 0, 0, g(Yes, No, false, false, "", "ثم")}, - {0xfc13, 0, 0, 0, g(Yes, No, false, false, "", "ثى")}, - {0xfc14, 0, 0, 0, g(Yes, No, false, false, "", "ثي")}, - {0xfc15, 0, 0, 0, g(Yes, No, false, false, "", "جح")}, - {0xfc16, 0, 0, 0, g(Yes, No, false, false, "", "جم")}, - {0xfc17, 0, 0, 0, g(Yes, No, false, false, "", "حج")}, - {0xfc18, 0, 0, 0, g(Yes, No, false, false, "", "حم")}, - {0xfc19, 0, 0, 0, g(Yes, No, false, false, "", "خج")}, - {0xfc1a, 0, 0, 0, g(Yes, No, false, false, "", "خح")}, - {0xfc1b, 0, 0, 0, g(Yes, No, false, false, "", "خم")}, - {0xfc1c, 0, 0, 0, g(Yes, No, false, false, "", "سج")}, - {0xfc1d, 0, 0, 0, g(Yes, No, false, false, "", "سح")}, - {0xfc1e, 0, 0, 0, g(Yes, No, false, false, "", "سخ")}, - {0xfc1f, 0, 0, 0, g(Yes, No, false, false, "", "سم")}, - {0xfc20, 0, 0, 0, g(Yes, No, false, false, "", "صح")}, - {0xfc21, 0, 0, 0, g(Yes, No, false, false, "", "صم")}, - {0xfc22, 0, 0, 0, g(Yes, No, false, false, "", "ضج")}, - {0xfc23, 0, 0, 0, g(Yes, No, false, false, "", "ضح")}, - {0xfc24, 0, 0, 0, g(Yes, No, false, false, "", "ضخ")}, - {0xfc25, 0, 0, 0, g(Yes, No, false, false, "", "ضم")}, - {0xfc26, 0, 0, 0, g(Yes, No, false, false, "", "طح")}, - {0xfc27, 0, 0, 0, g(Yes, No, false, false, "", "طم")}, - {0xfc28, 0, 0, 0, g(Yes, No, false, false, "", "ظم")}, - {0xfc29, 0, 0, 0, g(Yes, No, false, false, "", "عج")}, - {0xfc2a, 0, 0, 0, g(Yes, No, false, false, "", "عم")}, - {0xfc2b, 0, 0, 0, g(Yes, No, false, false, "", "غج")}, - {0xfc2c, 0, 0, 0, g(Yes, No, false, false, "", "غم")}, - {0xfc2d, 0, 0, 0, g(Yes, No, false, false, "", "فج")}, - {0xfc2e, 0, 0, 0, g(Yes, No, false, false, "", "فح")}, - {0xfc2f, 0, 0, 0, g(Yes, No, false, false, "", "فخ")}, - {0xfc30, 0, 0, 0, g(Yes, No, false, false, "", "فم")}, - {0xfc31, 0, 0, 0, g(Yes, No, false, false, "", "فى")}, - {0xfc32, 0, 0, 0, g(Yes, No, false, false, "", "في")}, - {0xfc33, 0, 0, 0, g(Yes, No, false, false, "", "قح")}, - {0xfc34, 0, 0, 0, g(Yes, No, false, false, "", "قم")}, - {0xfc35, 0, 0, 0, g(Yes, No, false, false, "", "قى")}, - {0xfc36, 0, 0, 0, g(Yes, No, false, false, "", "قي")}, - {0xfc37, 0, 0, 0, g(Yes, No, false, false, "", "كا")}, - {0xfc38, 0, 0, 0, g(Yes, No, false, false, "", "كج")}, - {0xfc39, 0, 0, 0, g(Yes, No, false, false, "", "كح")}, - {0xfc3a, 0, 0, 0, g(Yes, No, false, false, "", "كخ")}, - {0xfc3b, 0, 0, 0, g(Yes, No, false, false, "", "كل")}, - {0xfc3c, 0, 0, 0, g(Yes, No, false, false, "", "كم")}, - {0xfc3d, 0, 0, 0, g(Yes, No, false, false, "", "كى")}, - {0xfc3e, 0, 0, 0, g(Yes, No, false, false, "", "كي")}, - {0xfc3f, 0, 0, 0, g(Yes, No, false, false, "", "لج")}, - {0xfc40, 0, 0, 0, g(Yes, No, false, false, "", "لح")}, - {0xfc41, 0, 0, 0, g(Yes, No, false, false, "", "لخ")}, - {0xfc42, 0, 0, 0, g(Yes, No, false, false, "", "لم")}, - {0xfc43, 0, 0, 0, g(Yes, No, false, false, "", "لى")}, - {0xfc44, 0, 0, 0, g(Yes, No, false, false, "", "لي")}, - {0xfc45, 0, 0, 0, g(Yes, No, false, false, "", "مج")}, - {0xfc46, 0, 0, 0, g(Yes, No, false, false, "", "مح")}, - {0xfc47, 0, 0, 0, g(Yes, No, false, false, "", "مخ")}, - {0xfc48, 0, 0, 0, g(Yes, No, false, false, "", "مم")}, - {0xfc49, 0, 0, 0, g(Yes, No, false, false, "", "مى")}, - {0xfc4a, 0, 0, 0, g(Yes, No, false, false, "", "مي")}, - {0xfc4b, 0, 0, 0, g(Yes, No, false, false, "", "نج")}, - {0xfc4c, 0, 0, 0, g(Yes, No, false, false, "", "نح")}, - {0xfc4d, 0, 0, 0, g(Yes, No, false, false, "", "نخ")}, - {0xfc4e, 0, 0, 0, g(Yes, No, false, false, "", "نم")}, - {0xfc4f, 0, 0, 0, g(Yes, No, false, false, "", "نى")}, - {0xfc50, 0, 0, 0, g(Yes, No, false, false, "", "ني")}, - {0xfc51, 0, 0, 0, g(Yes, No, false, false, "", "هج")}, - {0xfc52, 0, 0, 0, g(Yes, No, false, false, "", "هم")}, - {0xfc53, 0, 0, 0, g(Yes, No, false, false, "", "هى")}, - {0xfc54, 0, 0, 0, g(Yes, No, false, false, "", "هي")}, - {0xfc55, 0, 0, 0, g(Yes, No, false, false, "", "يج")}, - {0xfc56, 0, 0, 0, g(Yes, No, false, false, "", "يح")}, - {0xfc57, 0, 0, 0, g(Yes, No, false, false, "", "يخ")}, - {0xfc58, 0, 0, 0, g(Yes, No, false, false, "", "يم")}, - {0xfc59, 0, 0, 0, g(Yes, No, false, false, "", "يى")}, - {0xfc5a, 0, 0, 0, g(Yes, No, false, false, "", "يي")}, - {0xfc5b, 0, 0, 1, g(Yes, No, false, false, "", "ذٰ")}, - {0xfc5c, 0, 0, 1, g(Yes, No, false, false, "", "رٰ")}, - {0xfc5d, 0, 0, 1, g(Yes, No, false, false, "", "ىٰ")}, - {0xfc5e, 0, 0, 2, g(Yes, No, false, false, "", " ٌّ")}, - {0xfc5f, 0, 0, 2, g(Yes, No, false, false, "", " ٍّ")}, - {0xfc60, 0, 0, 2, g(Yes, No, false, false, "", " َّ")}, - {0xfc61, 0, 0, 2, g(Yes, No, false, false, "", " ُّ")}, - {0xfc62, 0, 0, 2, g(Yes, No, false, false, "", " ِّ")}, - {0xfc63, 0, 0, 2, g(Yes, No, false, false, "", " ّٰ")}, - {0xfc64, 0, 0, 0, g(Yes, No, false, false, "", "ئر")}, - {0xfc65, 0, 0, 0, g(Yes, No, false, false, "", "ئز")}, - {0xfc66, 0, 0, 0, g(Yes, No, false, false, "", "ئم")}, - {0xfc67, 0, 0, 0, g(Yes, No, false, false, "", "ئن")}, - {0xfc68, 0, 0, 0, g(Yes, No, false, false, "", "ئى")}, - {0xfc69, 0, 0, 0, g(Yes, No, false, false, "", "ئي")}, - {0xfc6a, 0, 0, 0, g(Yes, No, false, false, "", "بر")}, - {0xfc6b, 0, 0, 0, g(Yes, No, false, false, "", "بز")}, - {0xfc6c, 0, 0, 0, g(Yes, No, false, false, "", "بم")}, - {0xfc6d, 0, 0, 0, g(Yes, No, false, false, "", "بن")}, - {0xfc6e, 0, 0, 0, g(Yes, No, false, false, "", "بى")}, - {0xfc6f, 0, 0, 0, g(Yes, No, false, false, "", "بي")}, - {0xfc70, 0, 0, 0, g(Yes, No, false, false, "", "تر")}, - {0xfc71, 0, 0, 0, g(Yes, No, false, false, "", "تز")}, - {0xfc72, 0, 0, 0, g(Yes, No, false, false, "", "تم")}, - {0xfc73, 0, 0, 0, g(Yes, No, false, false, "", "تن")}, - {0xfc74, 0, 0, 0, g(Yes, No, false, false, "", "تى")}, - {0xfc75, 0, 0, 0, g(Yes, No, false, false, "", "تي")}, - {0xfc76, 0, 0, 0, g(Yes, No, false, false, "", "ثر")}, - {0xfc77, 0, 0, 0, g(Yes, No, false, false, "", "ثز")}, - {0xfc78, 0, 0, 0, g(Yes, No, false, false, "", "ثم")}, - {0xfc79, 0, 0, 0, g(Yes, No, false, false, "", "ثن")}, - {0xfc7a, 0, 0, 0, g(Yes, No, false, false, "", "ثى")}, - {0xfc7b, 0, 0, 0, g(Yes, No, false, false, "", "ثي")}, - {0xfc7c, 0, 0, 0, g(Yes, No, false, false, "", "فى")}, - {0xfc7d, 0, 0, 0, g(Yes, No, false, false, "", "في")}, - {0xfc7e, 0, 0, 0, g(Yes, No, false, false, "", "قى")}, - {0xfc7f, 0, 0, 0, g(Yes, No, false, false, "", "قي")}, - {0xfc80, 0, 0, 0, g(Yes, No, false, false, "", "كا")}, - {0xfc81, 0, 0, 0, g(Yes, No, false, false, "", "كل")}, - {0xfc82, 0, 0, 0, g(Yes, No, false, false, "", "كم")}, - {0xfc83, 0, 0, 0, g(Yes, No, false, false, "", "كى")}, - {0xfc84, 0, 0, 0, g(Yes, No, false, false, "", "كي")}, - {0xfc85, 0, 0, 0, g(Yes, No, false, false, "", "لم")}, - {0xfc86, 0, 0, 0, g(Yes, No, false, false, "", "لى")}, - {0xfc87, 0, 0, 0, g(Yes, No, false, false, "", "لي")}, - {0xfc88, 0, 0, 0, g(Yes, No, false, false, "", "ما")}, - {0xfc89, 0, 0, 0, g(Yes, No, false, false, "", "مم")}, - {0xfc8a, 0, 0, 0, g(Yes, No, false, false, "", "نر")}, - {0xfc8b, 0, 0, 0, g(Yes, No, false, false, "", "نز")}, - {0xfc8c, 0, 0, 0, g(Yes, No, false, false, "", "نم")}, - {0xfc8d, 0, 0, 0, g(Yes, No, false, false, "", "نن")}, - {0xfc8e, 0, 0, 0, g(Yes, No, false, false, "", "نى")}, - {0xfc8f, 0, 0, 0, g(Yes, No, false, false, "", "ني")}, - {0xfc90, 0, 0, 1, g(Yes, No, false, false, "", "ىٰ")}, - {0xfc91, 0, 0, 0, g(Yes, No, false, false, "", "ير")}, - {0xfc92, 0, 0, 0, g(Yes, No, false, false, "", "يز")}, - {0xfc93, 0, 0, 0, g(Yes, No, false, false, "", "يم")}, - {0xfc94, 0, 0, 0, g(Yes, No, false, false, "", "ين")}, - {0xfc95, 0, 0, 0, g(Yes, No, false, false, "", "يى")}, - {0xfc96, 0, 0, 0, g(Yes, No, false, false, "", "يي")}, - {0xfc97, 0, 0, 0, g(Yes, No, false, false, "", "ئج")}, - {0xfc98, 0, 0, 0, g(Yes, No, false, false, "", "ئح")}, - {0xfc99, 0, 0, 0, g(Yes, No, false, false, "", "ئخ")}, - {0xfc9a, 0, 0, 0, g(Yes, No, false, false, "", "ئم")}, - {0xfc9b, 0, 0, 0, g(Yes, No, false, false, "", "ئه")}, - {0xfc9c, 0, 0, 0, g(Yes, No, false, false, "", "بج")}, - {0xfc9d, 0, 0, 0, g(Yes, No, false, false, "", "بح")}, - {0xfc9e, 0, 0, 0, g(Yes, No, false, false, "", "بخ")}, - {0xfc9f, 0, 0, 0, g(Yes, No, false, false, "", "بم")}, - {0xfca0, 0, 0, 0, g(Yes, No, false, false, "", "به")}, - {0xfca1, 0, 0, 0, g(Yes, No, false, false, "", "تج")}, - {0xfca2, 0, 0, 0, g(Yes, No, false, false, "", "تح")}, - {0xfca3, 0, 0, 0, g(Yes, No, false, false, "", "تخ")}, - {0xfca4, 0, 0, 0, g(Yes, No, false, false, "", "تم")}, - {0xfca5, 0, 0, 0, g(Yes, No, false, false, "", "ته")}, - {0xfca6, 0, 0, 0, g(Yes, No, false, false, "", "ثم")}, - {0xfca7, 0, 0, 0, g(Yes, No, false, false, "", "جح")}, - {0xfca8, 0, 0, 0, g(Yes, No, false, false, "", "جم")}, - {0xfca9, 0, 0, 0, g(Yes, No, false, false, "", "حج")}, - {0xfcaa, 0, 0, 0, g(Yes, No, false, false, "", "حم")}, - {0xfcab, 0, 0, 0, g(Yes, No, false, false, "", "خج")}, - {0xfcac, 0, 0, 0, g(Yes, No, false, false, "", "خم")}, - {0xfcad, 0, 0, 0, g(Yes, No, false, false, "", "سج")}, - {0xfcae, 0, 0, 0, g(Yes, No, false, false, "", "سح")}, - {0xfcaf, 0, 0, 0, g(Yes, No, false, false, "", "سخ")}, - {0xfcb0, 0, 0, 0, g(Yes, No, false, false, "", "سم")}, - {0xfcb1, 0, 0, 0, g(Yes, No, false, false, "", "صح")}, - {0xfcb2, 0, 0, 0, g(Yes, No, false, false, "", "صخ")}, - {0xfcb3, 0, 0, 0, g(Yes, No, false, false, "", "صم")}, - {0xfcb4, 0, 0, 0, g(Yes, No, false, false, "", "ضج")}, - {0xfcb5, 0, 0, 0, g(Yes, No, false, false, "", "ضح")}, - {0xfcb6, 0, 0, 0, g(Yes, No, false, false, "", "ضخ")}, - {0xfcb7, 0, 0, 0, g(Yes, No, false, false, "", "ضم")}, - {0xfcb8, 0, 0, 0, g(Yes, No, false, false, "", "طح")}, - {0xfcb9, 0, 0, 0, g(Yes, No, false, false, "", "ظم")}, - {0xfcba, 0, 0, 0, g(Yes, No, false, false, "", "عج")}, - {0xfcbb, 0, 0, 0, g(Yes, No, false, false, "", "عم")}, - {0xfcbc, 0, 0, 0, g(Yes, No, false, false, "", "غج")}, - {0xfcbd, 0, 0, 0, g(Yes, No, false, false, "", "غم")}, - {0xfcbe, 0, 0, 0, g(Yes, No, false, false, "", "فج")}, - {0xfcbf, 0, 0, 0, g(Yes, No, false, false, "", "فح")}, - {0xfcc0, 0, 0, 0, g(Yes, No, false, false, "", "فخ")}, - {0xfcc1, 0, 0, 0, g(Yes, No, false, false, "", "فم")}, - {0xfcc2, 0, 0, 0, g(Yes, No, false, false, "", "قح")}, - {0xfcc3, 0, 0, 0, g(Yes, No, false, false, "", "قم")}, - {0xfcc4, 0, 0, 0, g(Yes, No, false, false, "", "كج")}, - {0xfcc5, 0, 0, 0, g(Yes, No, false, false, "", "كح")}, - {0xfcc6, 0, 0, 0, g(Yes, No, false, false, "", "كخ")}, - {0xfcc7, 0, 0, 0, g(Yes, No, false, false, "", "كل")}, - {0xfcc8, 0, 0, 0, g(Yes, No, false, false, "", "كم")}, - {0xfcc9, 0, 0, 0, g(Yes, No, false, false, "", "لج")}, - {0xfcca, 0, 0, 0, g(Yes, No, false, false, "", "لح")}, - {0xfccb, 0, 0, 0, g(Yes, No, false, false, "", "لخ")}, - {0xfccc, 0, 0, 0, g(Yes, No, false, false, "", "لم")}, - {0xfccd, 0, 0, 0, g(Yes, No, false, false, "", "له")}, - {0xfcce, 0, 0, 0, g(Yes, No, false, false, "", "مج")}, - {0xfccf, 0, 0, 0, g(Yes, No, false, false, "", "مح")}, - {0xfcd0, 0, 0, 0, g(Yes, No, false, false, "", "مخ")}, - {0xfcd1, 0, 0, 0, g(Yes, No, false, false, "", "مم")}, - {0xfcd2, 0, 0, 0, g(Yes, No, false, false, "", "نج")}, - {0xfcd3, 0, 0, 0, g(Yes, No, false, false, "", "نح")}, - {0xfcd4, 0, 0, 0, g(Yes, No, false, false, "", "نخ")}, - {0xfcd5, 0, 0, 0, g(Yes, No, false, false, "", "نم")}, - {0xfcd6, 0, 0, 0, g(Yes, No, false, false, "", "نه")}, - {0xfcd7, 0, 0, 0, g(Yes, No, false, false, "", "هج")}, - {0xfcd8, 0, 0, 0, g(Yes, No, false, false, "", "هم")}, - {0xfcd9, 0, 0, 1, g(Yes, No, false, false, "", "هٰ")}, - {0xfcda, 0, 0, 0, g(Yes, No, false, false, "", "يج")}, - {0xfcdb, 0, 0, 0, g(Yes, No, false, false, "", "يح")}, - {0xfcdc, 0, 0, 0, g(Yes, No, false, false, "", "يخ")}, - {0xfcdd, 0, 0, 0, g(Yes, No, false, false, "", "يم")}, - {0xfcde, 0, 0, 0, g(Yes, No, false, false, "", "يه")}, - {0xfcdf, 0, 0, 0, g(Yes, No, false, false, "", "ئم")}, - {0xfce0, 0, 0, 0, g(Yes, No, false, false, "", "ئه")}, - {0xfce1, 0, 0, 0, g(Yes, No, false, false, "", "بم")}, - {0xfce2, 0, 0, 0, g(Yes, No, false, false, "", "به")}, - {0xfce3, 0, 0, 0, g(Yes, No, false, false, "", "تم")}, - {0xfce4, 0, 0, 0, g(Yes, No, false, false, "", "ته")}, - {0xfce5, 0, 0, 0, g(Yes, No, false, false, "", "ثم")}, - {0xfce6, 0, 0, 0, g(Yes, No, false, false, "", "ثه")}, - {0xfce7, 0, 0, 0, g(Yes, No, false, false, "", "سم")}, - {0xfce8, 0, 0, 0, g(Yes, No, false, false, "", "سه")}, - {0xfce9, 0, 0, 0, g(Yes, No, false, false, "", "شم")}, - {0xfcea, 0, 0, 0, g(Yes, No, false, false, "", "شه")}, - {0xfceb, 0, 0, 0, g(Yes, No, false, false, "", "كل")}, - {0xfcec, 0, 0, 0, g(Yes, No, false, false, "", "كم")}, - {0xfced, 0, 0, 0, g(Yes, No, false, false, "", "لم")}, - {0xfcee, 0, 0, 0, g(Yes, No, false, false, "", "نم")}, - {0xfcef, 0, 0, 0, g(Yes, No, false, false, "", "نه")}, - {0xfcf0, 0, 0, 0, g(Yes, No, false, false, "", "يم")}, - {0xfcf1, 0, 0, 0, g(Yes, No, false, false, "", "يه")}, - {0xfcf2, 0, 0, 2, g(Yes, No, false, false, "", "ـَّ")}, - {0xfcf3, 0, 0, 2, g(Yes, No, false, false, "", "ـُّ")}, - {0xfcf4, 0, 0, 2, g(Yes, No, false, false, "", "ـِّ")}, - {0xfcf5, 0, 0, 0, g(Yes, No, false, false, "", "طى")}, - {0xfcf6, 0, 0, 0, g(Yes, No, false, false, "", "طي")}, - {0xfcf7, 0, 0, 0, g(Yes, No, false, false, "", "عى")}, - {0xfcf8, 0, 0, 0, g(Yes, No, false, false, "", "عي")}, - {0xfcf9, 0, 0, 0, g(Yes, No, false, false, "", "غى")}, - {0xfcfa, 0, 0, 0, g(Yes, No, false, false, "", "غي")}, - {0xfcfb, 0, 0, 0, g(Yes, No, false, false, "", "سى")}, - {0xfcfc, 0, 0, 0, g(Yes, No, false, false, "", "سي")}, - {0xfcfd, 0, 0, 0, g(Yes, No, false, false, "", "شى")}, - {0xfcfe, 0, 0, 0, g(Yes, No, false, false, "", "شي")}, - {0xfcff, 0, 0, 0, g(Yes, No, false, false, "", "حى")}, - {0xfd00, 0, 0, 0, g(Yes, No, false, false, "", "حي")}, - {0xfd01, 0, 0, 0, g(Yes, No, false, false, "", "جى")}, - {0xfd02, 0, 0, 0, g(Yes, No, false, false, "", "جي")}, - {0xfd03, 0, 0, 0, g(Yes, No, false, false, "", "خى")}, - {0xfd04, 0, 0, 0, g(Yes, No, false, false, "", "خي")}, - {0xfd05, 0, 0, 0, g(Yes, No, false, false, "", "صى")}, - {0xfd06, 0, 0, 0, g(Yes, No, false, false, "", "صي")}, - {0xfd07, 0, 0, 0, g(Yes, No, false, false, "", "ضى")}, - {0xfd08, 0, 0, 0, g(Yes, No, false, false, "", "ضي")}, - {0xfd09, 0, 0, 0, g(Yes, No, false, false, "", "شج")}, - {0xfd0a, 0, 0, 0, g(Yes, No, false, false, "", "شح")}, - {0xfd0b, 0, 0, 0, g(Yes, No, false, false, "", "شخ")}, - {0xfd0c, 0, 0, 0, g(Yes, No, false, false, "", "شم")}, - {0xfd0d, 0, 0, 0, g(Yes, No, false, false, "", "شر")}, - {0xfd0e, 0, 0, 0, g(Yes, No, false, false, "", "سر")}, - {0xfd0f, 0, 0, 0, g(Yes, No, false, false, "", "صر")}, - {0xfd10, 0, 0, 0, g(Yes, No, false, false, "", "ضر")}, - {0xfd11, 0, 0, 0, g(Yes, No, false, false, "", "طى")}, - {0xfd12, 0, 0, 0, g(Yes, No, false, false, "", "طي")}, - {0xfd13, 0, 0, 0, g(Yes, No, false, false, "", "عى")}, - {0xfd14, 0, 0, 0, g(Yes, No, false, false, "", "عي")}, - {0xfd15, 0, 0, 0, g(Yes, No, false, false, "", "غى")}, - {0xfd16, 0, 0, 0, g(Yes, No, false, false, "", "غي")}, - {0xfd17, 0, 0, 0, g(Yes, No, false, false, "", "سى")}, - {0xfd18, 0, 0, 0, g(Yes, No, false, false, "", "سي")}, - {0xfd19, 0, 0, 0, g(Yes, No, false, false, "", "شى")}, - {0xfd1a, 0, 0, 0, g(Yes, No, false, false, "", "شي")}, - {0xfd1b, 0, 0, 0, g(Yes, No, false, false, "", "حى")}, - {0xfd1c, 0, 0, 0, g(Yes, No, false, false, "", "حي")}, - {0xfd1d, 0, 0, 0, g(Yes, No, false, false, "", "جى")}, - {0xfd1e, 0, 0, 0, g(Yes, No, false, false, "", "جي")}, - {0xfd1f, 0, 0, 0, g(Yes, No, false, false, "", "خى")}, - {0xfd20, 0, 0, 0, g(Yes, No, false, false, "", "خي")}, - {0xfd21, 0, 0, 0, g(Yes, No, false, false, "", "صى")}, - {0xfd22, 0, 0, 0, g(Yes, No, false, false, "", "صي")}, - {0xfd23, 0, 0, 0, g(Yes, No, false, false, "", "ضى")}, - {0xfd24, 0, 0, 0, g(Yes, No, false, false, "", "ضي")}, - {0xfd25, 0, 0, 0, g(Yes, No, false, false, "", "شج")}, - {0xfd26, 0, 0, 0, g(Yes, No, false, false, "", "شح")}, - {0xfd27, 0, 0, 0, g(Yes, No, false, false, "", "شخ")}, - {0xfd28, 0, 0, 0, g(Yes, No, false, false, "", "شم")}, - {0xfd29, 0, 0, 0, g(Yes, No, false, false, "", "شر")}, - {0xfd2a, 0, 0, 0, g(Yes, No, false, false, "", "سر")}, - {0xfd2b, 0, 0, 0, g(Yes, No, false, false, "", "صر")}, - {0xfd2c, 0, 0, 0, g(Yes, No, false, false, "", "ضر")}, - {0xfd2d, 0, 0, 0, g(Yes, No, false, false, "", "شج")}, - {0xfd2e, 0, 0, 0, g(Yes, No, false, false, "", "شح")}, - {0xfd2f, 0, 0, 0, g(Yes, No, false, false, "", "شخ")}, - {0xfd30, 0, 0, 0, g(Yes, No, false, false, "", "شم")}, - {0xfd31, 0, 0, 0, g(Yes, No, false, false, "", "سه")}, - {0xfd32, 0, 0, 0, g(Yes, No, false, false, "", "شه")}, - {0xfd33, 0, 0, 0, g(Yes, No, false, false, "", "طم")}, - {0xfd34, 0, 0, 0, g(Yes, No, false, false, "", "سج")}, - {0xfd35, 0, 0, 0, g(Yes, No, false, false, "", "سح")}, - {0xfd36, 0, 0, 0, g(Yes, No, false, false, "", "سخ")}, - {0xfd37, 0, 0, 0, g(Yes, No, false, false, "", "شج")}, - {0xfd38, 0, 0, 0, g(Yes, No, false, false, "", "شح")}, - {0xfd39, 0, 0, 0, g(Yes, No, false, false, "", "شخ")}, - {0xfd3a, 0, 0, 0, g(Yes, No, false, false, "", "طم")}, - {0xfd3b, 0, 0, 0, g(Yes, No, false, false, "", "ظم")}, - {0xfd3c, 0, 0, 1, g(Yes, No, false, false, "", "اً")}, - {0xfd3e, 0, 0, 0, f(Yes, false, "")}, - {0xfd50, 0, 0, 0, g(Yes, No, false, false, "", "تجم")}, - {0xfd51, 0, 0, 0, g(Yes, No, false, false, "", "تحج")}, - {0xfd53, 0, 0, 0, g(Yes, No, false, false, "", "تحم")}, - {0xfd54, 0, 0, 0, g(Yes, No, false, false, "", "تخم")}, - {0xfd55, 0, 0, 0, g(Yes, No, false, false, "", "تمج")}, - {0xfd56, 0, 0, 0, g(Yes, No, false, false, "", "تمح")}, - {0xfd57, 0, 0, 0, g(Yes, No, false, false, "", "تمخ")}, - {0xfd58, 0, 0, 0, g(Yes, No, false, false, "", "جمح")}, - {0xfd5a, 0, 0, 0, g(Yes, No, false, false, "", "حمي")}, - {0xfd5b, 0, 0, 0, g(Yes, No, false, false, "", "حمى")}, - {0xfd5c, 0, 0, 0, g(Yes, No, false, false, "", "سحج")}, - {0xfd5d, 0, 0, 0, g(Yes, No, false, false, "", "سجح")}, - {0xfd5e, 0, 0, 0, g(Yes, No, false, false, "", "سجى")}, - {0xfd5f, 0, 0, 0, g(Yes, No, false, false, "", "سمح")}, - {0xfd61, 0, 0, 0, g(Yes, No, false, false, "", "سمج")}, - {0xfd62, 0, 0, 0, g(Yes, No, false, false, "", "سمم")}, - {0xfd64, 0, 0, 0, g(Yes, No, false, false, "", "صحح")}, - {0xfd66, 0, 0, 0, g(Yes, No, false, false, "", "صمم")}, - {0xfd67, 0, 0, 0, g(Yes, No, false, false, "", "شحم")}, - {0xfd69, 0, 0, 0, g(Yes, No, false, false, "", "شجي")}, - {0xfd6a, 0, 0, 0, g(Yes, No, false, false, "", "شمخ")}, - {0xfd6c, 0, 0, 0, g(Yes, No, false, false, "", "شمم")}, - {0xfd6e, 0, 0, 0, g(Yes, No, false, false, "", "ضحى")}, - {0xfd6f, 0, 0, 0, g(Yes, No, false, false, "", "ضخم")}, - {0xfd71, 0, 0, 0, g(Yes, No, false, false, "", "طمح")}, - {0xfd73, 0, 0, 0, g(Yes, No, false, false, "", "طمم")}, - {0xfd74, 0, 0, 0, g(Yes, No, false, false, "", "طمي")}, - {0xfd75, 0, 0, 0, g(Yes, No, false, false, "", "عجم")}, - {0xfd76, 0, 0, 0, g(Yes, No, false, false, "", "عمم")}, - {0xfd78, 0, 0, 0, g(Yes, No, false, false, "", "عمى")}, - {0xfd79, 0, 0, 0, g(Yes, No, false, false, "", "غمم")}, - {0xfd7a, 0, 0, 0, g(Yes, No, false, false, "", "غمي")}, - {0xfd7b, 0, 0, 0, g(Yes, No, false, false, "", "غمى")}, - {0xfd7c, 0, 0, 0, g(Yes, No, false, false, "", "فخم")}, - {0xfd7e, 0, 0, 0, g(Yes, No, false, false, "", "قمح")}, - {0xfd7f, 0, 0, 0, g(Yes, No, false, false, "", "قمم")}, - {0xfd80, 0, 0, 0, g(Yes, No, false, false, "", "لحم")}, - {0xfd81, 0, 0, 0, g(Yes, No, false, false, "", "لحي")}, - {0xfd82, 0, 0, 0, g(Yes, No, false, false, "", "لحى")}, - {0xfd83, 0, 0, 0, g(Yes, No, false, false, "", "لجج")}, - {0xfd85, 0, 0, 0, g(Yes, No, false, false, "", "لخم")}, - {0xfd87, 0, 0, 0, g(Yes, No, false, false, "", "لمح")}, - {0xfd89, 0, 0, 0, g(Yes, No, false, false, "", "محج")}, - {0xfd8a, 0, 0, 0, g(Yes, No, false, false, "", "محم")}, - {0xfd8b, 0, 0, 0, g(Yes, No, false, false, "", "محي")}, - {0xfd8c, 0, 0, 0, g(Yes, No, false, false, "", "مجح")}, - {0xfd8d, 0, 0, 0, g(Yes, No, false, false, "", "مجم")}, - {0xfd8e, 0, 0, 0, g(Yes, No, false, false, "", "مخج")}, - {0xfd8f, 0, 0, 0, g(Yes, No, false, false, "", "مخم")}, - {0xfd90, 0, 0, 0, f(Yes, false, "")}, - {0xfd92, 0, 0, 0, g(Yes, No, false, false, "", "مجخ")}, - {0xfd93, 0, 0, 0, g(Yes, No, false, false, "", "همج")}, - {0xfd94, 0, 0, 0, g(Yes, No, false, false, "", "همم")}, - {0xfd95, 0, 0, 0, g(Yes, No, false, false, "", "نحم")}, - {0xfd96, 0, 0, 0, g(Yes, No, false, false, "", "نحى")}, - {0xfd97, 0, 0, 0, g(Yes, No, false, false, "", "نجم")}, - {0xfd99, 0, 0, 0, g(Yes, No, false, false, "", "نجى")}, - {0xfd9a, 0, 0, 0, g(Yes, No, false, false, "", "نمي")}, - {0xfd9b, 0, 0, 0, g(Yes, No, false, false, "", "نمى")}, - {0xfd9c, 0, 0, 0, g(Yes, No, false, false, "", "يمم")}, - {0xfd9e, 0, 0, 0, g(Yes, No, false, false, "", "بخي")}, - {0xfd9f, 0, 0, 0, g(Yes, No, false, false, "", "تجي")}, - {0xfda0, 0, 0, 0, g(Yes, No, false, false, "", "تجى")}, - {0xfda1, 0, 0, 0, g(Yes, No, false, false, "", "تخي")}, - {0xfda2, 0, 0, 0, g(Yes, No, false, false, "", "تخى")}, - {0xfda3, 0, 0, 0, g(Yes, No, false, false, "", "تمي")}, - {0xfda4, 0, 0, 0, g(Yes, No, false, false, "", "تمى")}, - {0xfda5, 0, 0, 0, g(Yes, No, false, false, "", "جمي")}, - {0xfda6, 0, 0, 0, g(Yes, No, false, false, "", "جحى")}, - {0xfda7, 0, 0, 0, g(Yes, No, false, false, "", "جمى")}, - {0xfda8, 0, 0, 0, g(Yes, No, false, false, "", "سخى")}, - {0xfda9, 0, 0, 0, g(Yes, No, false, false, "", "صحي")}, - {0xfdaa, 0, 0, 0, g(Yes, No, false, false, "", "شحي")}, - {0xfdab, 0, 0, 0, g(Yes, No, false, false, "", "ضحي")}, - {0xfdac, 0, 0, 0, g(Yes, No, false, false, "", "لجي")}, - {0xfdad, 0, 0, 0, g(Yes, No, false, false, "", "لمي")}, - {0xfdae, 0, 0, 0, g(Yes, No, false, false, "", "يحي")}, - {0xfdaf, 0, 0, 0, g(Yes, No, false, false, "", "يجي")}, - {0xfdb0, 0, 0, 0, g(Yes, No, false, false, "", "يمي")}, - {0xfdb1, 0, 0, 0, g(Yes, No, false, false, "", "ممي")}, - {0xfdb2, 0, 0, 0, g(Yes, No, false, false, "", "قمي")}, - {0xfdb3, 0, 0, 0, g(Yes, No, false, false, "", "نحي")}, - {0xfdb4, 0, 0, 0, g(Yes, No, false, false, "", "قمح")}, - {0xfdb5, 0, 0, 0, g(Yes, No, false, false, "", "لحم")}, - {0xfdb6, 0, 0, 0, g(Yes, No, false, false, "", "عمي")}, - {0xfdb7, 0, 0, 0, g(Yes, No, false, false, "", "كمي")}, - {0xfdb8, 0, 0, 0, g(Yes, No, false, false, "", "نجح")}, - {0xfdb9, 0, 0, 0, g(Yes, No, false, false, "", "مخي")}, - {0xfdba, 0, 0, 0, g(Yes, No, false, false, "", "لجم")}, - {0xfdbb, 0, 0, 0, g(Yes, No, false, false, "", "كمم")}, - {0xfdbc, 0, 0, 0, g(Yes, No, false, false, "", "لجم")}, - {0xfdbd, 0, 0, 0, g(Yes, No, false, false, "", "نجح")}, - {0xfdbe, 0, 0, 0, g(Yes, No, false, false, "", "جحي")}, - {0xfdbf, 0, 0, 0, g(Yes, No, false, false, "", "حجي")}, - {0xfdc0, 0, 0, 0, g(Yes, No, false, false, "", "مجي")}, - {0xfdc1, 0, 0, 0, g(Yes, No, false, false, "", "فمي")}, - {0xfdc2, 0, 0, 0, g(Yes, No, false, false, "", "بحي")}, - {0xfdc3, 0, 0, 0, g(Yes, No, false, false, "", "كمم")}, - {0xfdc4, 0, 0, 0, g(Yes, No, false, false, "", "عجم")}, - {0xfdc5, 0, 0, 0, g(Yes, No, false, false, "", "صمم")}, - {0xfdc6, 0, 0, 0, g(Yes, No, false, false, "", "سخي")}, - {0xfdc7, 0, 0, 0, g(Yes, No, false, false, "", "نجي")}, - {0xfdc8, 0, 0, 0, f(Yes, false, "")}, - {0xfdf0, 0, 0, 0, g(Yes, No, false, false, "", "صلے")}, - {0xfdf1, 0, 0, 0, g(Yes, No, false, false, "", "قلے")}, - {0xfdf2, 0, 0, 0, g(Yes, No, false, false, "", "الله")}, - {0xfdf3, 0, 0, 0, g(Yes, No, false, false, "", "اكبر")}, - {0xfdf4, 0, 0, 0, g(Yes, No, false, false, "", "محمد")}, - {0xfdf5, 0, 0, 0, g(Yes, No, false, false, "", "صلعم")}, - {0xfdf6, 0, 0, 0, g(Yes, No, false, false, "", "رسول")}, - {0xfdf7, 0, 0, 0, g(Yes, No, false, false, "", "عليه")}, - {0xfdf8, 0, 0, 0, g(Yes, No, false, false, "", "وسلم")}, - {0xfdf9, 0, 0, 0, g(Yes, No, false, false, "", "صلى")}, - {0xfdfa, 0, 0, 0, g(Yes, No, false, false, "", "صلى الله عليه وسلم")}, - {0xfdfb, 0, 0, 0, g(Yes, No, false, false, "", "جل جلاله")}, - {0xfdfc, 0, 0, 0, g(Yes, No, false, false, "", "ریال")}, - {0xfdfd, 0, 0, 0, f(Yes, false, "")}, - {0xfe10, 0, 0, 0, g(Yes, No, false, false, "", ",")}, - {0xfe11, 0, 0, 0, g(Yes, No, false, false, "", "、")}, - {0xfe12, 0, 0, 0, g(Yes, No, false, false, "", "。")}, - {0xfe13, 0, 0, 0, g(Yes, No, false, false, "", ":")}, - {0xfe14, 0, 0, 0, g(Yes, No, false, false, "", ";")}, - {0xfe15, 0, 0, 0, g(Yes, No, false, false, "", "!")}, - {0xfe16, 0, 0, 0, g(Yes, No, false, false, "", "?")}, - {0xfe17, 0, 0, 0, g(Yes, No, false, false, "", "〖")}, - {0xfe18, 0, 0, 0, g(Yes, No, false, false, "", "〗")}, - {0xfe19, 0, 0, 0, g(Yes, No, false, false, "", "...")}, - {0xfe1a, 0, 0, 0, f(Yes, false, "")}, - {0xfe20, 230, 1, 1, f(Yes, false, "")}, - {0xfe27, 220, 1, 1, f(Yes, false, "")}, - {0xfe2e, 230, 1, 1, f(Yes, false, "")}, - {0xfe30, 0, 0, 0, g(Yes, No, false, false, "", "..")}, - {0xfe31, 0, 0, 0, g(Yes, No, false, false, "", "—")}, - {0xfe32, 0, 0, 0, g(Yes, No, false, false, "", "–")}, - {0xfe33, 0, 0, 0, g(Yes, No, false, false, "", "_")}, - {0xfe35, 0, 0, 0, g(Yes, No, false, false, "", "(")}, - {0xfe36, 0, 0, 0, g(Yes, No, false, false, "", ")")}, - {0xfe37, 0, 0, 0, g(Yes, No, false, false, "", "{")}, - {0xfe38, 0, 0, 0, g(Yes, No, false, false, "", "}")}, - {0xfe39, 0, 0, 0, g(Yes, No, false, false, "", "〔")}, - {0xfe3a, 0, 0, 0, g(Yes, No, false, false, "", "〕")}, - {0xfe3b, 0, 0, 0, g(Yes, No, false, false, "", "【")}, - {0xfe3c, 0, 0, 0, g(Yes, No, false, false, "", "】")}, - {0xfe3d, 0, 0, 0, g(Yes, No, false, false, "", "《")}, - {0xfe3e, 0, 0, 0, g(Yes, No, false, false, "", "》")}, - {0xfe3f, 0, 0, 0, g(Yes, No, false, false, "", "〈")}, - {0xfe40, 0, 0, 0, g(Yes, No, false, false, "", "〉")}, - {0xfe41, 0, 0, 0, g(Yes, No, false, false, "", "「")}, - {0xfe42, 0, 0, 0, g(Yes, No, false, false, "", "」")}, - {0xfe43, 0, 0, 0, g(Yes, No, false, false, "", "『")}, - {0xfe44, 0, 0, 0, g(Yes, No, false, false, "", "』")}, - {0xfe45, 0, 0, 0, f(Yes, false, "")}, - {0xfe47, 0, 0, 0, g(Yes, No, false, false, "", "[")}, - {0xfe48, 0, 0, 0, g(Yes, No, false, false, "", "]")}, - {0xfe49, 0, 0, 1, g(Yes, No, false, false, "", " ̅")}, - {0xfe4d, 0, 0, 0, g(Yes, No, false, false, "", "_")}, - {0xfe50, 0, 0, 0, g(Yes, No, false, false, "", ",")}, - {0xfe51, 0, 0, 0, g(Yes, No, false, false, "", "、")}, - {0xfe52, 0, 0, 0, g(Yes, No, false, false, "", ".")}, - {0xfe53, 0, 0, 0, f(Yes, false, "")}, - {0xfe54, 0, 0, 0, g(Yes, No, false, false, "", ";")}, - {0xfe55, 0, 0, 0, g(Yes, No, false, false, "", ":")}, - {0xfe56, 0, 0, 0, g(Yes, No, false, false, "", "?")}, - {0xfe57, 0, 0, 0, g(Yes, No, false, false, "", "!")}, - {0xfe58, 0, 0, 0, g(Yes, No, false, false, "", "—")}, - {0xfe59, 0, 0, 0, g(Yes, No, false, false, "", "(")}, - {0xfe5a, 0, 0, 0, g(Yes, No, false, false, "", ")")}, - {0xfe5b, 0, 0, 0, g(Yes, No, false, false, "", "{")}, - {0xfe5c, 0, 0, 0, g(Yes, No, false, false, "", "}")}, - {0xfe5d, 0, 0, 0, g(Yes, No, false, false, "", "〔")}, - {0xfe5e, 0, 0, 0, g(Yes, No, false, false, "", "〕")}, - {0xfe5f, 0, 0, 0, g(Yes, No, false, false, "", "#")}, - {0xfe60, 0, 0, 0, g(Yes, No, false, false, "", "&")}, - {0xfe61, 0, 0, 0, g(Yes, No, false, false, "", "*")}, - {0xfe62, 0, 0, 0, g(Yes, No, false, false, "", "+")}, - {0xfe63, 0, 0, 0, g(Yes, No, false, false, "", "-")}, - {0xfe64, 0, 0, 0, g(Yes, No, false, false, "", "<")}, - {0xfe65, 0, 0, 0, g(Yes, No, false, false, "", ">")}, - {0xfe66, 0, 0, 0, g(Yes, No, false, false, "", "=")}, - {0xfe67, 0, 0, 0, f(Yes, false, "")}, - {0xfe68, 0, 0, 0, g(Yes, No, false, false, "", "\\")}, - {0xfe69, 0, 0, 0, g(Yes, No, false, false, "", "$")}, - {0xfe6a, 0, 0, 0, g(Yes, No, false, false, "", "%")}, - {0xfe6b, 0, 0, 0, g(Yes, No, false, false, "", "@")}, - {0xfe6c, 0, 0, 0, f(Yes, false, "")}, - {0xfe70, 0, 0, 1, g(Yes, No, false, false, "", " ً")}, - {0xfe71, 0, 0, 1, g(Yes, No, false, false, "", "ـً")}, - {0xfe72, 0, 0, 1, g(Yes, No, false, false, "", " ٌ")}, - {0xfe73, 0, 0, 0, f(Yes, false, "")}, - {0xfe74, 0, 0, 1, g(Yes, No, false, false, "", " ٍ")}, - {0xfe75, 0, 0, 0, f(Yes, false, "")}, - {0xfe76, 0, 0, 1, g(Yes, No, false, false, "", " َ")}, - {0xfe77, 0, 0, 1, g(Yes, No, false, false, "", "ـَ")}, - {0xfe78, 0, 0, 1, g(Yes, No, false, false, "", " ُ")}, - {0xfe79, 0, 0, 1, g(Yes, No, false, false, "", "ـُ")}, - {0xfe7a, 0, 0, 1, g(Yes, No, false, false, "", " ِ")}, - {0xfe7b, 0, 0, 1, g(Yes, No, false, false, "", "ـِ")}, - {0xfe7c, 0, 0, 1, g(Yes, No, false, false, "", " ّ")}, - {0xfe7d, 0, 0, 1, g(Yes, No, false, false, "", "ـّ")}, - {0xfe7e, 0, 0, 1, g(Yes, No, false, false, "", " ْ")}, - {0xfe7f, 0, 0, 1, g(Yes, No, false, false, "", "ـْ")}, - {0xfe80, 0, 0, 0, g(Yes, No, false, false, "", "ء")}, - {0xfe81, 0, 0, 1, g(Yes, No, false, false, "", "آ")}, - {0xfe83, 0, 0, 1, g(Yes, No, false, false, "", "أ")}, - {0xfe85, 0, 0, 1, g(Yes, No, false, false, "", "ؤ")}, - {0xfe87, 0, 0, 1, g(Yes, No, false, false, "", "إ")}, - {0xfe89, 0, 0, 1, g(Yes, No, false, false, "", "ئ")}, - {0xfe8d, 0, 0, 0, g(Yes, No, false, false, "", "ا")}, - {0xfe8f, 0, 0, 0, g(Yes, No, false, false, "", "ب")}, - {0xfe93, 0, 0, 0, g(Yes, No, false, false, "", "ة")}, - {0xfe95, 0, 0, 0, g(Yes, No, false, false, "", "ت")}, - {0xfe99, 0, 0, 0, g(Yes, No, false, false, "", "ث")}, - {0xfe9d, 0, 0, 0, g(Yes, No, false, false, "", "ج")}, - {0xfea1, 0, 0, 0, g(Yes, No, false, false, "", "ح")}, - {0xfea5, 0, 0, 0, g(Yes, No, false, false, "", "خ")}, - {0xfea9, 0, 0, 0, g(Yes, No, false, false, "", "د")}, - {0xfeab, 0, 0, 0, g(Yes, No, false, false, "", "ذ")}, - {0xfead, 0, 0, 0, g(Yes, No, false, false, "", "ر")}, - {0xfeaf, 0, 0, 0, g(Yes, No, false, false, "", "ز")}, - {0xfeb1, 0, 0, 0, g(Yes, No, false, false, "", "س")}, - {0xfeb5, 0, 0, 0, g(Yes, No, false, false, "", "ش")}, - {0xfeb9, 0, 0, 0, g(Yes, No, false, false, "", "ص")}, - {0xfebd, 0, 0, 0, g(Yes, No, false, false, "", "ض")}, - {0xfec1, 0, 0, 0, g(Yes, No, false, false, "", "ط")}, - {0xfec5, 0, 0, 0, g(Yes, No, false, false, "", "ظ")}, - {0xfec9, 0, 0, 0, g(Yes, No, false, false, "", "ع")}, - {0xfecd, 0, 0, 0, g(Yes, No, false, false, "", "غ")}, - {0xfed1, 0, 0, 0, g(Yes, No, false, false, "", "ف")}, - {0xfed5, 0, 0, 0, g(Yes, No, false, false, "", "ق")}, - {0xfed9, 0, 0, 0, g(Yes, No, false, false, "", "ك")}, - {0xfedd, 0, 0, 0, g(Yes, No, false, false, "", "ل")}, - {0xfee1, 0, 0, 0, g(Yes, No, false, false, "", "م")}, - {0xfee5, 0, 0, 0, g(Yes, No, false, false, "", "ن")}, - {0xfee9, 0, 0, 0, g(Yes, No, false, false, "", "ه")}, - {0xfeed, 0, 0, 0, g(Yes, No, false, false, "", "و")}, - {0xfeef, 0, 0, 0, g(Yes, No, false, false, "", "ى")}, - {0xfef1, 0, 0, 0, g(Yes, No, false, false, "", "ي")}, - {0xfef5, 0, 0, 1, g(Yes, No, false, false, "", "لآ")}, - {0xfef7, 0, 0, 1, g(Yes, No, false, false, "", "لأ")}, - {0xfef9, 0, 0, 1, g(Yes, No, false, false, "", "لإ")}, - {0xfefb, 0, 0, 0, g(Yes, No, false, false, "", "لا")}, - {0xfefd, 0, 0, 0, f(Yes, false, "")}, - {0xff01, 0, 0, 0, g(Yes, No, false, false, "", "!")}, - {0xff02, 0, 0, 0, g(Yes, No, false, false, "", "\"")}, - {0xff03, 0, 0, 0, g(Yes, No, false, false, "", "#")}, - {0xff04, 0, 0, 0, g(Yes, No, false, false, "", "$")}, - {0xff05, 0, 0, 0, g(Yes, No, false, false, "", "%")}, - {0xff06, 0, 0, 0, g(Yes, No, false, false, "", "&")}, - {0xff07, 0, 0, 0, g(Yes, No, false, false, "", "'")}, - {0xff08, 0, 0, 0, g(Yes, No, false, false, "", "(")}, - {0xff09, 0, 0, 0, g(Yes, No, false, false, "", ")")}, - {0xff0a, 0, 0, 0, g(Yes, No, false, false, "", "*")}, - {0xff0b, 0, 0, 0, g(Yes, No, false, false, "", "+")}, - {0xff0c, 0, 0, 0, g(Yes, No, false, false, "", ",")}, - {0xff0d, 0, 0, 0, g(Yes, No, false, false, "", "-")}, - {0xff0e, 0, 0, 0, g(Yes, No, false, false, "", ".")}, - {0xff0f, 0, 0, 0, g(Yes, No, false, false, "", "/")}, - {0xff10, 0, 0, 0, g(Yes, No, false, false, "", "0")}, - {0xff11, 0, 0, 0, g(Yes, No, false, false, "", "1")}, - {0xff12, 0, 0, 0, g(Yes, No, false, false, "", "2")}, - {0xff13, 0, 0, 0, g(Yes, No, false, false, "", "3")}, - {0xff14, 0, 0, 0, g(Yes, No, false, false, "", "4")}, - {0xff15, 0, 0, 0, g(Yes, No, false, false, "", "5")}, - {0xff16, 0, 0, 0, g(Yes, No, false, false, "", "6")}, - {0xff17, 0, 0, 0, g(Yes, No, false, false, "", "7")}, - {0xff18, 0, 0, 0, g(Yes, No, false, false, "", "8")}, - {0xff19, 0, 0, 0, g(Yes, No, false, false, "", "9")}, - {0xff1a, 0, 0, 0, g(Yes, No, false, false, "", ":")}, - {0xff1b, 0, 0, 0, g(Yes, No, false, false, "", ";")}, - {0xff1c, 0, 0, 0, g(Yes, No, false, false, "", "<")}, - {0xff1d, 0, 0, 0, g(Yes, No, false, false, "", "=")}, - {0xff1e, 0, 0, 0, g(Yes, No, false, false, "", ">")}, - {0xff1f, 0, 0, 0, g(Yes, No, false, false, "", "?")}, - {0xff20, 0, 0, 0, g(Yes, No, false, false, "", "@")}, - {0xff21, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0xff22, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0xff23, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0xff24, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0xff25, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0xff26, 0, 0, 0, g(Yes, No, false, false, "", "F")}, - {0xff27, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0xff28, 0, 0, 0, g(Yes, No, false, false, "", "H")}, - {0xff29, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0xff2a, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0xff2b, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0xff2c, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0xff2d, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0xff2e, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0xff2f, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0xff30, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0xff31, 0, 0, 0, g(Yes, No, false, false, "", "Q")}, - {0xff32, 0, 0, 0, g(Yes, No, false, false, "", "R")}, - {0xff33, 0, 0, 0, g(Yes, No, false, false, "", "S")}, - {0xff34, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0xff35, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0xff36, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0xff37, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0xff38, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0xff39, 0, 0, 0, g(Yes, No, false, false, "", "Y")}, - {0xff3a, 0, 0, 0, g(Yes, No, false, false, "", "Z")}, - {0xff3b, 0, 0, 0, g(Yes, No, false, false, "", "[")}, - {0xff3c, 0, 0, 0, g(Yes, No, false, false, "", "\\")}, - {0xff3d, 0, 0, 0, g(Yes, No, false, false, "", "]")}, - {0xff3e, 0, 0, 0, g(Yes, No, false, false, "", "^")}, - {0xff3f, 0, 0, 0, g(Yes, No, false, false, "", "_")}, - {0xff40, 0, 0, 0, g(Yes, No, false, false, "", "`")}, - {0xff41, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0xff42, 0, 0, 0, g(Yes, No, false, false, "", "b")}, - {0xff43, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0xff44, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0xff45, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0xff46, 0, 0, 0, g(Yes, No, false, false, "", "f")}, - {0xff47, 0, 0, 0, g(Yes, No, false, false, "", "g")}, - {0xff48, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0xff49, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0xff4a, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0xff4b, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0xff4c, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0xff4d, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0xff4e, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0xff4f, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0xff50, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0xff51, 0, 0, 0, g(Yes, No, false, false, "", "q")}, - {0xff52, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0xff53, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0xff54, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0xff55, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0xff56, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0xff57, 0, 0, 0, g(Yes, No, false, false, "", "w")}, - {0xff58, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0xff59, 0, 0, 0, g(Yes, No, false, false, "", "y")}, - {0xff5a, 0, 0, 0, g(Yes, No, false, false, "", "z")}, - {0xff5b, 0, 0, 0, g(Yes, No, false, false, "", "{")}, - {0xff5c, 0, 0, 0, g(Yes, No, false, false, "", "|")}, - {0xff5d, 0, 0, 0, g(Yes, No, false, false, "", "}")}, - {0xff5e, 0, 0, 0, g(Yes, No, false, false, "", "~")}, - {0xff5f, 0, 0, 0, g(Yes, No, false, false, "", "⦅")}, - {0xff60, 0, 0, 0, g(Yes, No, false, false, "", "⦆")}, - {0xff61, 0, 0, 0, g(Yes, No, false, false, "", "。")}, - {0xff62, 0, 0, 0, g(Yes, No, false, false, "", "「")}, - {0xff63, 0, 0, 0, g(Yes, No, false, false, "", "」")}, - {0xff64, 0, 0, 0, g(Yes, No, false, false, "", "、")}, - {0xff65, 0, 0, 0, g(Yes, No, false, false, "", "・")}, - {0xff66, 0, 0, 0, g(Yes, No, false, false, "", "ヲ")}, - {0xff67, 0, 0, 0, g(Yes, No, false, false, "", "ァ")}, - {0xff68, 0, 0, 0, g(Yes, No, false, false, "", "ィ")}, - {0xff69, 0, 0, 0, g(Yes, No, false, false, "", "ゥ")}, - {0xff6a, 0, 0, 0, g(Yes, No, false, false, "", "ェ")}, - {0xff6b, 0, 0, 0, g(Yes, No, false, false, "", "ォ")}, - {0xff6c, 0, 0, 0, g(Yes, No, false, false, "", "ャ")}, - {0xff6d, 0, 0, 0, g(Yes, No, false, false, "", "ュ")}, - {0xff6e, 0, 0, 0, g(Yes, No, false, false, "", "ョ")}, - {0xff6f, 0, 0, 0, g(Yes, No, false, false, "", "ッ")}, - {0xff70, 0, 0, 0, g(Yes, No, false, false, "", "ー")}, - {0xff71, 0, 0, 0, g(Yes, No, false, false, "", "ア")}, - {0xff72, 0, 0, 0, g(Yes, No, false, false, "", "イ")}, - {0xff73, 0, 0, 0, g(Yes, No, false, false, "", "ウ")}, - {0xff74, 0, 0, 0, g(Yes, No, false, false, "", "エ")}, - {0xff75, 0, 0, 0, g(Yes, No, false, false, "", "オ")}, - {0xff76, 0, 0, 0, g(Yes, No, false, false, "", "カ")}, - {0xff77, 0, 0, 0, g(Yes, No, false, false, "", "キ")}, - {0xff78, 0, 0, 0, g(Yes, No, false, false, "", "ク")}, - {0xff79, 0, 0, 0, g(Yes, No, false, false, "", "ケ")}, - {0xff7a, 0, 0, 0, g(Yes, No, false, false, "", "コ")}, - {0xff7b, 0, 0, 0, g(Yes, No, false, false, "", "サ")}, - {0xff7c, 0, 0, 0, g(Yes, No, false, false, "", "シ")}, - {0xff7d, 0, 0, 0, g(Yes, No, false, false, "", "ス")}, - {0xff7e, 0, 0, 0, g(Yes, No, false, false, "", "セ")}, - {0xff7f, 0, 0, 0, g(Yes, No, false, false, "", "ソ")}, - {0xff80, 0, 0, 0, g(Yes, No, false, false, "", "タ")}, - {0xff81, 0, 0, 0, g(Yes, No, false, false, "", "チ")}, - {0xff82, 0, 0, 0, g(Yes, No, false, false, "", "ツ")}, - {0xff83, 0, 0, 0, g(Yes, No, false, false, "", "テ")}, - {0xff84, 0, 0, 0, g(Yes, No, false, false, "", "ト")}, - {0xff85, 0, 0, 0, g(Yes, No, false, false, "", "ナ")}, - {0xff86, 0, 0, 0, g(Yes, No, false, false, "", "ニ")}, - {0xff87, 0, 0, 0, g(Yes, No, false, false, "", "ヌ")}, - {0xff88, 0, 0, 0, g(Yes, No, false, false, "", "ネ")}, - {0xff89, 0, 0, 0, g(Yes, No, false, false, "", "ノ")}, - {0xff8a, 0, 0, 0, g(Yes, No, false, false, "", "ハ")}, - {0xff8b, 0, 0, 0, g(Yes, No, false, false, "", "ヒ")}, - {0xff8c, 0, 0, 0, g(Yes, No, false, false, "", "フ")}, - {0xff8d, 0, 0, 0, g(Yes, No, false, false, "", "ヘ")}, - {0xff8e, 0, 0, 0, g(Yes, No, false, false, "", "ホ")}, - {0xff8f, 0, 0, 0, g(Yes, No, false, false, "", "マ")}, - {0xff90, 0, 0, 0, g(Yes, No, false, false, "", "ミ")}, - {0xff91, 0, 0, 0, g(Yes, No, false, false, "", "ム")}, - {0xff92, 0, 0, 0, g(Yes, No, false, false, "", "メ")}, - {0xff93, 0, 0, 0, g(Yes, No, false, false, "", "モ")}, - {0xff94, 0, 0, 0, g(Yes, No, false, false, "", "ヤ")}, - {0xff95, 0, 0, 0, g(Yes, No, false, false, "", "ユ")}, - {0xff96, 0, 0, 0, g(Yes, No, false, false, "", "ヨ")}, - {0xff97, 0, 0, 0, g(Yes, No, false, false, "", "ラ")}, - {0xff98, 0, 0, 0, g(Yes, No, false, false, "", "リ")}, - {0xff99, 0, 0, 0, g(Yes, No, false, false, "", "ル")}, - {0xff9a, 0, 0, 0, g(Yes, No, false, false, "", "レ")}, - {0xff9b, 0, 0, 0, g(Yes, No, false, false, "", "ロ")}, - {0xff9c, 0, 0, 0, g(Yes, No, false, false, "", "ワ")}, - {0xff9d, 0, 0, 0, g(Yes, No, false, false, "", "ン")}, - {0xff9e, 0, 1, 1, g(Yes, No, false, false, "", "゙")}, - {0xff9f, 0, 1, 1, g(Yes, No, false, false, "", "゚")}, - {0xffa0, 0, 0, 0, g(Yes, No, false, false, "", "ᅠ")}, - {0xffa1, 0, 0, 0, g(Yes, No, false, false, "", "ᄀ")}, - {0xffa2, 0, 0, 0, g(Yes, No, false, false, "", "ᄁ")}, - {0xffa3, 0, 1, 1, g(Yes, No, false, false, "", "ᆪ")}, - {0xffa4, 0, 0, 0, g(Yes, No, false, false, "", "ᄂ")}, - {0xffa5, 0, 1, 1, g(Yes, No, false, false, "", "ᆬ")}, - {0xffa6, 0, 1, 1, g(Yes, No, false, false, "", "ᆭ")}, - {0xffa7, 0, 0, 0, g(Yes, No, false, false, "", "ᄃ")}, - {0xffa8, 0, 0, 0, g(Yes, No, false, false, "", "ᄄ")}, - {0xffa9, 0, 0, 0, g(Yes, No, false, false, "", "ᄅ")}, - {0xffaa, 0, 1, 1, g(Yes, No, false, false, "", "ᆰ")}, - {0xffab, 0, 1, 1, g(Yes, No, false, false, "", "ᆱ")}, - {0xffac, 0, 1, 1, g(Yes, No, false, false, "", "ᆲ")}, - {0xffad, 0, 1, 1, g(Yes, No, false, false, "", "ᆳ")}, - {0xffae, 0, 1, 1, g(Yes, No, false, false, "", "ᆴ")}, - {0xffaf, 0, 1, 1, g(Yes, No, false, false, "", "ᆵ")}, - {0xffb0, 0, 0, 0, g(Yes, No, false, false, "", "ᄚ")}, - {0xffb1, 0, 0, 0, g(Yes, No, false, false, "", "ᄆ")}, - {0xffb2, 0, 0, 0, g(Yes, No, false, false, "", "ᄇ")}, - {0xffb3, 0, 0, 0, g(Yes, No, false, false, "", "ᄈ")}, - {0xffb4, 0, 0, 0, g(Yes, No, false, false, "", "ᄡ")}, - {0xffb5, 0, 0, 0, g(Yes, No, false, false, "", "ᄉ")}, - {0xffb6, 0, 0, 0, g(Yes, No, false, false, "", "ᄊ")}, - {0xffb7, 0, 0, 0, g(Yes, No, false, false, "", "ᄋ")}, - {0xffb8, 0, 0, 0, g(Yes, No, false, false, "", "ᄌ")}, - {0xffb9, 0, 0, 0, g(Yes, No, false, false, "", "ᄍ")}, - {0xffba, 0, 0, 0, g(Yes, No, false, false, "", "ᄎ")}, - {0xffbb, 0, 0, 0, g(Yes, No, false, false, "", "ᄏ")}, - {0xffbc, 0, 0, 0, g(Yes, No, false, false, "", "ᄐ")}, - {0xffbd, 0, 0, 0, g(Yes, No, false, false, "", "ᄑ")}, - {0xffbe, 0, 0, 0, g(Yes, No, false, false, "", "ᄒ")}, - {0xffbf, 0, 0, 0, f(Yes, false, "")}, - {0xffc2, 0, 1, 1, g(Yes, No, false, false, "", "ᅡ")}, - {0xffc3, 0, 1, 1, g(Yes, No, false, false, "", "ᅢ")}, - {0xffc4, 0, 1, 1, g(Yes, No, false, false, "", "ᅣ")}, - {0xffc5, 0, 1, 1, g(Yes, No, false, false, "", "ᅤ")}, - {0xffc6, 0, 1, 1, g(Yes, No, false, false, "", "ᅥ")}, - {0xffc7, 0, 1, 1, g(Yes, No, false, false, "", "ᅦ")}, - {0xffc8, 0, 0, 0, f(Yes, false, "")}, - {0xffca, 0, 1, 1, g(Yes, No, false, false, "", "ᅧ")}, - {0xffcb, 0, 1, 1, g(Yes, No, false, false, "", "ᅨ")}, - {0xffcc, 0, 1, 1, g(Yes, No, false, false, "", "ᅩ")}, - {0xffcd, 0, 1, 1, g(Yes, No, false, false, "", "ᅪ")}, - {0xffce, 0, 1, 1, g(Yes, No, false, false, "", "ᅫ")}, - {0xffcf, 0, 1, 1, g(Yes, No, false, false, "", "ᅬ")}, - {0xffd0, 0, 0, 0, f(Yes, false, "")}, - {0xffd2, 0, 1, 1, g(Yes, No, false, false, "", "ᅭ")}, - {0xffd3, 0, 1, 1, g(Yes, No, false, false, "", "ᅮ")}, - {0xffd4, 0, 1, 1, g(Yes, No, false, false, "", "ᅯ")}, - {0xffd5, 0, 1, 1, g(Yes, No, false, false, "", "ᅰ")}, - {0xffd6, 0, 1, 1, g(Yes, No, false, false, "", "ᅱ")}, - {0xffd7, 0, 1, 1, g(Yes, No, false, false, "", "ᅲ")}, - {0xffd8, 0, 0, 0, f(Yes, false, "")}, - {0xffda, 0, 1, 1, g(Yes, No, false, false, "", "ᅳ")}, - {0xffdb, 0, 1, 1, g(Yes, No, false, false, "", "ᅴ")}, - {0xffdc, 0, 1, 1, g(Yes, No, false, false, "", "ᅵ")}, - {0xffdd, 0, 0, 0, f(Yes, false, "")}, - {0xffe0, 0, 0, 0, g(Yes, No, false, false, "", "¢")}, - {0xffe1, 0, 0, 0, g(Yes, No, false, false, "", "£")}, - {0xffe2, 0, 0, 0, g(Yes, No, false, false, "", "¬")}, - {0xffe3, 0, 0, 1, g(Yes, No, false, false, "", " ̄")}, - {0xffe4, 0, 0, 0, g(Yes, No, false, false, "", "¦")}, - {0xffe5, 0, 0, 0, g(Yes, No, false, false, "", "¥")}, - {0xffe6, 0, 0, 0, g(Yes, No, false, false, "", "₩")}, - {0xffe7, 0, 0, 0, f(Yes, false, "")}, - {0xffe8, 0, 0, 0, g(Yes, No, false, false, "", "│")}, - {0xffe9, 0, 0, 0, g(Yes, No, false, false, "", "←")}, - {0xffea, 0, 0, 0, g(Yes, No, false, false, "", "↑")}, - {0xffeb, 0, 0, 0, g(Yes, No, false, false, "", "→")}, - {0xffec, 0, 0, 0, g(Yes, No, false, false, "", "↓")}, - {0xffed, 0, 0, 0, g(Yes, No, false, false, "", "■")}, - {0xffee, 0, 0, 0, g(Yes, No, false, false, "", "○")}, - {0xffef, 0, 0, 0, f(Yes, false, "")}, - {0x101fd, 220, 1, 1, f(Yes, false, "")}, - {0x101fe, 0, 0, 0, f(Yes, false, "")}, - {0x102e0, 220, 1, 1, f(Yes, false, "")}, - {0x102e1, 0, 0, 0, f(Yes, false, "")}, - {0x10376, 230, 1, 1, f(Yes, false, "")}, - {0x1037b, 0, 0, 0, f(Yes, false, "")}, - {0x10a0d, 220, 1, 1, f(Yes, false, "")}, - {0x10a0e, 0, 0, 0, f(Yes, false, "")}, - {0x10a0f, 230, 1, 1, f(Yes, false, "")}, - {0x10a10, 0, 0, 0, f(Yes, false, "")}, - {0x10a38, 230, 1, 1, f(Yes, false, "")}, - {0x10a39, 1, 1, 1, f(Yes, false, "")}, - {0x10a3a, 220, 1, 1, f(Yes, false, "")}, - {0x10a3b, 0, 0, 0, f(Yes, false, "")}, - {0x10a3f, 9, 1, 1, f(Yes, false, "")}, - {0x10a40, 0, 0, 0, f(Yes, false, "")}, - {0x10ae5, 230, 1, 1, f(Yes, false, "")}, - {0x10ae6, 220, 1, 1, f(Yes, false, "")}, - {0x10ae7, 0, 0, 0, f(Yes, false, "")}, - {0x11046, 9, 1, 1, f(Yes, false, "")}, - {0x11047, 0, 0, 0, f(Yes, false, "")}, - {0x1107f, 9, 1, 1, f(Yes, false, "")}, - {0x11080, 0, 0, 0, f(Yes, false, "")}, - {0x11099, 0, 0, 0, f(Yes, true, "")}, - {0x1109a, 0, 0, 1, f(Yes, false, "𑂚")}, - {0x1109b, 0, 0, 0, f(Yes, true, "")}, - {0x1109c, 0, 0, 1, f(Yes, false, "𑂜")}, - {0x1109d, 0, 0, 0, f(Yes, false, "")}, - {0x110a5, 0, 0, 0, f(Yes, true, "")}, - {0x110a6, 0, 0, 0, f(Yes, false, "")}, - {0x110ab, 0, 0, 1, f(Yes, false, "𑂫")}, - {0x110ac, 0, 0, 0, f(Yes, false, "")}, - {0x110b9, 9, 1, 1, f(Yes, false, "")}, - {0x110ba, 7, 1, 1, f(Maybe, false, "")}, - {0x110bb, 0, 0, 0, f(Yes, false, "")}, - {0x11100, 230, 1, 1, f(Yes, false, "")}, - {0x11103, 0, 0, 0, f(Yes, false, "")}, - {0x11127, 0, 1, 1, f(Maybe, false, "")}, - {0x11128, 0, 0, 0, f(Yes, false, "")}, - {0x1112e, 0, 0, 1, f(Yes, false, "𑄮")}, - {0x1112f, 0, 0, 1, f(Yes, false, "𑄯")}, - {0x11130, 0, 0, 0, f(Yes, false, "")}, - {0x11131, 0, 0, 0, f(Yes, true, "")}, - {0x11133, 9, 1, 1, f(Yes, false, "")}, - {0x11135, 0, 0, 0, f(Yes, false, "")}, - {0x11173, 7, 1, 1, f(Yes, false, "")}, - {0x11174, 0, 0, 0, f(Yes, false, "")}, - {0x111c0, 9, 1, 1, f(Yes, false, "")}, - {0x111c1, 0, 0, 0, f(Yes, false, "")}, - {0x111ca, 7, 1, 1, f(Yes, false, "")}, - {0x111cb, 0, 0, 0, f(Yes, false, "")}, - {0x11235, 9, 1, 1, f(Yes, false, "")}, - {0x11236, 7, 1, 1, f(Yes, false, "")}, - {0x11237, 0, 0, 0, f(Yes, false, "")}, - {0x112e9, 7, 1, 1, f(Yes, false, "")}, - {0x112ea, 9, 1, 1, f(Yes, false, "")}, - {0x112eb, 0, 0, 0, f(Yes, false, "")}, - {0x1133c, 7, 1, 1, f(Yes, false, "")}, - {0x1133d, 0, 0, 0, f(Yes, false, "")}, - {0x1133e, 0, 1, 1, f(Maybe, false, "")}, - {0x1133f, 0, 0, 0, f(Yes, false, "")}, - {0x11347, 0, 0, 0, f(Yes, true, "")}, - {0x11348, 0, 0, 0, f(Yes, false, "")}, - {0x1134b, 0, 0, 1, f(Yes, false, "𑍋")}, - {0x1134c, 0, 0, 1, f(Yes, false, "𑍌")}, - {0x1134d, 9, 1, 1, f(Yes, false, "")}, - {0x1134e, 0, 0, 0, f(Yes, false, "")}, - {0x11357, 0, 1, 1, f(Maybe, false, "")}, - {0x11358, 0, 0, 0, f(Yes, false, "")}, - {0x11366, 230, 1, 1, f(Yes, false, "")}, - {0x1136d, 0, 0, 0, f(Yes, false, "")}, - {0x11370, 230, 1, 1, f(Yes, false, "")}, - {0x11375, 0, 0, 0, f(Yes, false, "")}, - {0x11442, 9, 1, 1, f(Yes, false, "")}, - {0x11443, 0, 0, 0, f(Yes, false, "")}, - {0x11446, 7, 1, 1, f(Yes, false, "")}, - {0x11447, 0, 0, 0, f(Yes, false, "")}, - {0x114b0, 0, 1, 1, f(Maybe, false, "")}, - {0x114b1, 0, 0, 0, f(Yes, false, "")}, - {0x114b9, 0, 0, 0, f(Yes, true, "")}, - {0x114ba, 0, 1, 1, f(Maybe, false, "")}, - {0x114bb, 0, 0, 1, f(Yes, false, "𑒻")}, - {0x114bc, 0, 0, 1, f(Yes, false, "𑒼")}, - {0x114bd, 0, 1, 1, f(Maybe, false, "")}, - {0x114be, 0, 0, 1, f(Yes, false, "𑒾")}, - {0x114bf, 0, 0, 0, f(Yes, false, "")}, - {0x114c2, 9, 1, 1, f(Yes, false, "")}, - {0x114c3, 7, 1, 1, f(Yes, false, "")}, - {0x114c4, 0, 0, 0, f(Yes, false, "")}, - {0x115af, 0, 1, 1, f(Maybe, false, "")}, - {0x115b0, 0, 0, 0, f(Yes, false, "")}, - {0x115b8, 0, 0, 0, f(Yes, true, "")}, - {0x115ba, 0, 0, 1, f(Yes, false, "𑖺")}, - {0x115bb, 0, 0, 1, f(Yes, false, "𑖻")}, - {0x115bc, 0, 0, 0, f(Yes, false, "")}, - {0x115bf, 9, 1, 1, f(Yes, false, "")}, - {0x115c0, 7, 1, 1, f(Yes, false, "")}, - {0x115c1, 0, 0, 0, f(Yes, false, "")}, - {0x1163f, 9, 1, 1, f(Yes, false, "")}, - {0x11640, 0, 0, 0, f(Yes, false, "")}, - {0x116b6, 9, 1, 1, f(Yes, false, "")}, - {0x116b7, 7, 1, 1, f(Yes, false, "")}, - {0x116b8, 0, 0, 0, f(Yes, false, "")}, - {0x1172b, 9, 1, 1, f(Yes, false, "")}, - {0x1172c, 0, 0, 0, f(Yes, false, "")}, - {0x11c3f, 9, 1, 1, f(Yes, false, "")}, - {0x11c40, 0, 0, 0, f(Yes, false, "")}, - {0x16af0, 1, 1, 1, f(Yes, false, "")}, - {0x16af5, 0, 0, 0, f(Yes, false, "")}, - {0x16b30, 230, 1, 1, f(Yes, false, "")}, - {0x16b37, 0, 0, 0, f(Yes, false, "")}, - {0x1bc9e, 1, 1, 1, f(Yes, false, "")}, - {0x1bc9f, 0, 0, 0, f(Yes, false, "")}, - {0x1d15e, 0, 0, 1, f(No, false, "𝅗𝅥")}, - {0x1d15f, 0, 0, 1, f(No, false, "𝅘𝅥")}, - {0x1d160, 0, 0, 2, f(No, false, "𝅘𝅥𝅮")}, - {0x1d161, 0, 0, 2, f(No, false, "𝅘𝅥𝅯")}, - {0x1d162, 0, 0, 2, f(No, false, "𝅘𝅥𝅰")}, - {0x1d163, 0, 0, 2, f(No, false, "𝅘𝅥𝅱")}, - {0x1d164, 0, 0, 2, f(No, false, "𝅘𝅥𝅲")}, - {0x1d165, 216, 1, 1, f(Yes, false, "")}, - {0x1d167, 1, 1, 1, f(Yes, false, "")}, - {0x1d16a, 0, 0, 0, f(Yes, false, "")}, - {0x1d16d, 226, 1, 1, f(Yes, false, "")}, - {0x1d16e, 216, 1, 1, f(Yes, false, "")}, - {0x1d173, 0, 0, 0, f(Yes, false, "")}, - {0x1d17b, 220, 1, 1, f(Yes, false, "")}, - {0x1d183, 0, 0, 0, f(Yes, false, "")}, - {0x1d185, 230, 1, 1, f(Yes, false, "")}, - {0x1d18a, 220, 1, 1, f(Yes, false, "")}, - {0x1d18c, 0, 0, 0, f(Yes, false, "")}, - {0x1d1aa, 230, 1, 1, f(Yes, false, "")}, - {0x1d1ae, 0, 0, 0, f(Yes, false, "")}, - {0x1d1bb, 0, 0, 1, f(No, false, "𝆹𝅥")}, - {0x1d1bc, 0, 0, 1, f(No, false, "𝆺𝅥")}, - {0x1d1bd, 0, 0, 2, f(No, false, "𝆹𝅥𝅮")}, - {0x1d1be, 0, 0, 2, f(No, false, "𝆺𝅥𝅮")}, - {0x1d1bf, 0, 0, 2, f(No, false, "𝆹𝅥𝅯")}, - {0x1d1c0, 0, 0, 2, f(No, false, "𝆺𝅥𝅯")}, - {0x1d1c1, 0, 0, 0, f(Yes, false, "")}, - {0x1d242, 230, 1, 1, f(Yes, false, "")}, - {0x1d245, 0, 0, 0, f(Yes, false, "")}, - {0x1d400, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0x1d401, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0x1d402, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x1d403, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x1d404, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0x1d405, 0, 0, 0, g(Yes, No, false, false, "", "F")}, - {0x1d406, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0x1d407, 0, 0, 0, g(Yes, No, false, false, "", "H")}, - {0x1d408, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0x1d409, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0x1d40a, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0x1d40b, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x1d40c, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x1d40d, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0x1d40e, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0x1d40f, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0x1d410, 0, 0, 0, g(Yes, No, false, false, "", "Q")}, - {0x1d411, 0, 0, 0, g(Yes, No, false, false, "", "R")}, - {0x1d412, 0, 0, 0, g(Yes, No, false, false, "", "S")}, - {0x1d413, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0x1d414, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0x1d415, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x1d416, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0x1d417, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0x1d418, 0, 0, 0, g(Yes, No, false, false, "", "Y")}, - {0x1d419, 0, 0, 0, g(Yes, No, false, false, "", "Z")}, - {0x1d41a, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0x1d41b, 0, 0, 0, g(Yes, No, false, false, "", "b")}, - {0x1d41c, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0x1d41d, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x1d41e, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x1d41f, 0, 0, 0, g(Yes, No, false, false, "", "f")}, - {0x1d420, 0, 0, 0, g(Yes, No, false, false, "", "g")}, - {0x1d421, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0x1d422, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x1d423, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x1d424, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0x1d425, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x1d426, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x1d427, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0x1d428, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0x1d429, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0x1d42a, 0, 0, 0, g(Yes, No, false, false, "", "q")}, - {0x1d42b, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0x1d42c, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0x1d42d, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0x1d42e, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0x1d42f, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x1d430, 0, 0, 0, g(Yes, No, false, false, "", "w")}, - {0x1d431, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x1d432, 0, 0, 0, g(Yes, No, false, false, "", "y")}, - {0x1d433, 0, 0, 0, g(Yes, No, false, false, "", "z")}, - {0x1d434, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0x1d435, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0x1d436, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x1d437, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x1d438, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0x1d439, 0, 0, 0, g(Yes, No, false, false, "", "F")}, - {0x1d43a, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0x1d43b, 0, 0, 0, g(Yes, No, false, false, "", "H")}, - {0x1d43c, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0x1d43d, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0x1d43e, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0x1d43f, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x1d440, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x1d441, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0x1d442, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0x1d443, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0x1d444, 0, 0, 0, g(Yes, No, false, false, "", "Q")}, - {0x1d445, 0, 0, 0, g(Yes, No, false, false, "", "R")}, - {0x1d446, 0, 0, 0, g(Yes, No, false, false, "", "S")}, - {0x1d447, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0x1d448, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0x1d449, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x1d44a, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0x1d44b, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0x1d44c, 0, 0, 0, g(Yes, No, false, false, "", "Y")}, - {0x1d44d, 0, 0, 0, g(Yes, No, false, false, "", "Z")}, - {0x1d44e, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0x1d44f, 0, 0, 0, g(Yes, No, false, false, "", "b")}, - {0x1d450, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0x1d451, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x1d452, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x1d453, 0, 0, 0, g(Yes, No, false, false, "", "f")}, - {0x1d454, 0, 0, 0, g(Yes, No, false, false, "", "g")}, - {0x1d455, 0, 0, 0, f(Yes, false, "")}, - {0x1d456, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x1d457, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x1d458, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0x1d459, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x1d45a, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x1d45b, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0x1d45c, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0x1d45d, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0x1d45e, 0, 0, 0, g(Yes, No, false, false, "", "q")}, - {0x1d45f, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0x1d460, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0x1d461, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0x1d462, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0x1d463, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x1d464, 0, 0, 0, g(Yes, No, false, false, "", "w")}, - {0x1d465, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x1d466, 0, 0, 0, g(Yes, No, false, false, "", "y")}, - {0x1d467, 0, 0, 0, g(Yes, No, false, false, "", "z")}, - {0x1d468, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0x1d469, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0x1d46a, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x1d46b, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x1d46c, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0x1d46d, 0, 0, 0, g(Yes, No, false, false, "", "F")}, - {0x1d46e, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0x1d46f, 0, 0, 0, g(Yes, No, false, false, "", "H")}, - {0x1d470, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0x1d471, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0x1d472, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0x1d473, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x1d474, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x1d475, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0x1d476, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0x1d477, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0x1d478, 0, 0, 0, g(Yes, No, false, false, "", "Q")}, - {0x1d479, 0, 0, 0, g(Yes, No, false, false, "", "R")}, - {0x1d47a, 0, 0, 0, g(Yes, No, false, false, "", "S")}, - {0x1d47b, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0x1d47c, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0x1d47d, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x1d47e, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0x1d47f, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0x1d480, 0, 0, 0, g(Yes, No, false, false, "", "Y")}, - {0x1d481, 0, 0, 0, g(Yes, No, false, false, "", "Z")}, - {0x1d482, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0x1d483, 0, 0, 0, g(Yes, No, false, false, "", "b")}, - {0x1d484, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0x1d485, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x1d486, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x1d487, 0, 0, 0, g(Yes, No, false, false, "", "f")}, - {0x1d488, 0, 0, 0, g(Yes, No, false, false, "", "g")}, - {0x1d489, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0x1d48a, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x1d48b, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x1d48c, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0x1d48d, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x1d48e, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x1d48f, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0x1d490, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0x1d491, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0x1d492, 0, 0, 0, g(Yes, No, false, false, "", "q")}, - {0x1d493, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0x1d494, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0x1d495, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0x1d496, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0x1d497, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x1d498, 0, 0, 0, g(Yes, No, false, false, "", "w")}, - {0x1d499, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x1d49a, 0, 0, 0, g(Yes, No, false, false, "", "y")}, - {0x1d49b, 0, 0, 0, g(Yes, No, false, false, "", "z")}, - {0x1d49c, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0x1d49d, 0, 0, 0, f(Yes, false, "")}, - {0x1d49e, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x1d49f, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x1d4a0, 0, 0, 0, f(Yes, false, "")}, - {0x1d4a2, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0x1d4a3, 0, 0, 0, f(Yes, false, "")}, - {0x1d4a5, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0x1d4a6, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0x1d4a7, 0, 0, 0, f(Yes, false, "")}, - {0x1d4a9, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0x1d4aa, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0x1d4ab, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0x1d4ac, 0, 0, 0, g(Yes, No, false, false, "", "Q")}, - {0x1d4ad, 0, 0, 0, f(Yes, false, "")}, - {0x1d4ae, 0, 0, 0, g(Yes, No, false, false, "", "S")}, - {0x1d4af, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0x1d4b0, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0x1d4b1, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x1d4b2, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0x1d4b3, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0x1d4b4, 0, 0, 0, g(Yes, No, false, false, "", "Y")}, - {0x1d4b5, 0, 0, 0, g(Yes, No, false, false, "", "Z")}, - {0x1d4b6, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0x1d4b7, 0, 0, 0, g(Yes, No, false, false, "", "b")}, - {0x1d4b8, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0x1d4b9, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x1d4ba, 0, 0, 0, f(Yes, false, "")}, - {0x1d4bb, 0, 0, 0, g(Yes, No, false, false, "", "f")}, - {0x1d4bc, 0, 0, 0, f(Yes, false, "")}, - {0x1d4bd, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0x1d4be, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x1d4bf, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x1d4c0, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0x1d4c1, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x1d4c2, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x1d4c3, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0x1d4c4, 0, 0, 0, f(Yes, false, "")}, - {0x1d4c5, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0x1d4c6, 0, 0, 0, g(Yes, No, false, false, "", "q")}, - {0x1d4c7, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0x1d4c8, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0x1d4c9, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0x1d4ca, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0x1d4cb, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x1d4cc, 0, 0, 0, g(Yes, No, false, false, "", "w")}, - {0x1d4cd, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x1d4ce, 0, 0, 0, g(Yes, No, false, false, "", "y")}, - {0x1d4cf, 0, 0, 0, g(Yes, No, false, false, "", "z")}, - {0x1d4d0, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0x1d4d1, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0x1d4d2, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x1d4d3, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x1d4d4, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0x1d4d5, 0, 0, 0, g(Yes, No, false, false, "", "F")}, - {0x1d4d6, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0x1d4d7, 0, 0, 0, g(Yes, No, false, false, "", "H")}, - {0x1d4d8, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0x1d4d9, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0x1d4da, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0x1d4db, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x1d4dc, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x1d4dd, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0x1d4de, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0x1d4df, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0x1d4e0, 0, 0, 0, g(Yes, No, false, false, "", "Q")}, - {0x1d4e1, 0, 0, 0, g(Yes, No, false, false, "", "R")}, - {0x1d4e2, 0, 0, 0, g(Yes, No, false, false, "", "S")}, - {0x1d4e3, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0x1d4e4, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0x1d4e5, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x1d4e6, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0x1d4e7, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0x1d4e8, 0, 0, 0, g(Yes, No, false, false, "", "Y")}, - {0x1d4e9, 0, 0, 0, g(Yes, No, false, false, "", "Z")}, - {0x1d4ea, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0x1d4eb, 0, 0, 0, g(Yes, No, false, false, "", "b")}, - {0x1d4ec, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0x1d4ed, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x1d4ee, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x1d4ef, 0, 0, 0, g(Yes, No, false, false, "", "f")}, - {0x1d4f0, 0, 0, 0, g(Yes, No, false, false, "", "g")}, - {0x1d4f1, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0x1d4f2, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x1d4f3, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x1d4f4, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0x1d4f5, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x1d4f6, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x1d4f7, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0x1d4f8, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0x1d4f9, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0x1d4fa, 0, 0, 0, g(Yes, No, false, false, "", "q")}, - {0x1d4fb, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0x1d4fc, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0x1d4fd, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0x1d4fe, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0x1d4ff, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x1d500, 0, 0, 0, g(Yes, No, false, false, "", "w")}, - {0x1d501, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x1d502, 0, 0, 0, g(Yes, No, false, false, "", "y")}, - {0x1d503, 0, 0, 0, g(Yes, No, false, false, "", "z")}, - {0x1d504, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0x1d505, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0x1d506, 0, 0, 0, f(Yes, false, "")}, - {0x1d507, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x1d508, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0x1d509, 0, 0, 0, g(Yes, No, false, false, "", "F")}, - {0x1d50a, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0x1d50b, 0, 0, 0, f(Yes, false, "")}, - {0x1d50d, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0x1d50e, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0x1d50f, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x1d510, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x1d511, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0x1d512, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0x1d513, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0x1d514, 0, 0, 0, g(Yes, No, false, false, "", "Q")}, - {0x1d515, 0, 0, 0, f(Yes, false, "")}, - {0x1d516, 0, 0, 0, g(Yes, No, false, false, "", "S")}, - {0x1d517, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0x1d518, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0x1d519, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x1d51a, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0x1d51b, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0x1d51c, 0, 0, 0, g(Yes, No, false, false, "", "Y")}, - {0x1d51d, 0, 0, 0, f(Yes, false, "")}, - {0x1d51e, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0x1d51f, 0, 0, 0, g(Yes, No, false, false, "", "b")}, - {0x1d520, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0x1d521, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x1d522, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x1d523, 0, 0, 0, g(Yes, No, false, false, "", "f")}, - {0x1d524, 0, 0, 0, g(Yes, No, false, false, "", "g")}, - {0x1d525, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0x1d526, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x1d527, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x1d528, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0x1d529, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x1d52a, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x1d52b, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0x1d52c, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0x1d52d, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0x1d52e, 0, 0, 0, g(Yes, No, false, false, "", "q")}, - {0x1d52f, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0x1d530, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0x1d531, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0x1d532, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0x1d533, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x1d534, 0, 0, 0, g(Yes, No, false, false, "", "w")}, - {0x1d535, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x1d536, 0, 0, 0, g(Yes, No, false, false, "", "y")}, - {0x1d537, 0, 0, 0, g(Yes, No, false, false, "", "z")}, - {0x1d538, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0x1d539, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0x1d53a, 0, 0, 0, f(Yes, false, "")}, - {0x1d53b, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x1d53c, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0x1d53d, 0, 0, 0, g(Yes, No, false, false, "", "F")}, - {0x1d53e, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0x1d53f, 0, 0, 0, f(Yes, false, "")}, - {0x1d540, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0x1d541, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0x1d542, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0x1d543, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x1d544, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x1d545, 0, 0, 0, f(Yes, false, "")}, - {0x1d546, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0x1d547, 0, 0, 0, f(Yes, false, "")}, - {0x1d54a, 0, 0, 0, g(Yes, No, false, false, "", "S")}, - {0x1d54b, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0x1d54c, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0x1d54d, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x1d54e, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0x1d54f, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0x1d550, 0, 0, 0, g(Yes, No, false, false, "", "Y")}, - {0x1d551, 0, 0, 0, f(Yes, false, "")}, - {0x1d552, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0x1d553, 0, 0, 0, g(Yes, No, false, false, "", "b")}, - {0x1d554, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0x1d555, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x1d556, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x1d557, 0, 0, 0, g(Yes, No, false, false, "", "f")}, - {0x1d558, 0, 0, 0, g(Yes, No, false, false, "", "g")}, - {0x1d559, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0x1d55a, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x1d55b, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x1d55c, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0x1d55d, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x1d55e, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x1d55f, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0x1d560, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0x1d561, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0x1d562, 0, 0, 0, g(Yes, No, false, false, "", "q")}, - {0x1d563, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0x1d564, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0x1d565, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0x1d566, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0x1d567, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x1d568, 0, 0, 0, g(Yes, No, false, false, "", "w")}, - {0x1d569, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x1d56a, 0, 0, 0, g(Yes, No, false, false, "", "y")}, - {0x1d56b, 0, 0, 0, g(Yes, No, false, false, "", "z")}, - {0x1d56c, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0x1d56d, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0x1d56e, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x1d56f, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x1d570, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0x1d571, 0, 0, 0, g(Yes, No, false, false, "", "F")}, - {0x1d572, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0x1d573, 0, 0, 0, g(Yes, No, false, false, "", "H")}, - {0x1d574, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0x1d575, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0x1d576, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0x1d577, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x1d578, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x1d579, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0x1d57a, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0x1d57b, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0x1d57c, 0, 0, 0, g(Yes, No, false, false, "", "Q")}, - {0x1d57d, 0, 0, 0, g(Yes, No, false, false, "", "R")}, - {0x1d57e, 0, 0, 0, g(Yes, No, false, false, "", "S")}, - {0x1d57f, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0x1d580, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0x1d581, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x1d582, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0x1d583, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0x1d584, 0, 0, 0, g(Yes, No, false, false, "", "Y")}, - {0x1d585, 0, 0, 0, g(Yes, No, false, false, "", "Z")}, - {0x1d586, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0x1d587, 0, 0, 0, g(Yes, No, false, false, "", "b")}, - {0x1d588, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0x1d589, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x1d58a, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x1d58b, 0, 0, 0, g(Yes, No, false, false, "", "f")}, - {0x1d58c, 0, 0, 0, g(Yes, No, false, false, "", "g")}, - {0x1d58d, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0x1d58e, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x1d58f, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x1d590, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0x1d591, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x1d592, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x1d593, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0x1d594, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0x1d595, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0x1d596, 0, 0, 0, g(Yes, No, false, false, "", "q")}, - {0x1d597, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0x1d598, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0x1d599, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0x1d59a, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0x1d59b, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x1d59c, 0, 0, 0, g(Yes, No, false, false, "", "w")}, - {0x1d59d, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x1d59e, 0, 0, 0, g(Yes, No, false, false, "", "y")}, - {0x1d59f, 0, 0, 0, g(Yes, No, false, false, "", "z")}, - {0x1d5a0, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0x1d5a1, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0x1d5a2, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x1d5a3, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x1d5a4, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0x1d5a5, 0, 0, 0, g(Yes, No, false, false, "", "F")}, - {0x1d5a6, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0x1d5a7, 0, 0, 0, g(Yes, No, false, false, "", "H")}, - {0x1d5a8, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0x1d5a9, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0x1d5aa, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0x1d5ab, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x1d5ac, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x1d5ad, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0x1d5ae, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0x1d5af, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0x1d5b0, 0, 0, 0, g(Yes, No, false, false, "", "Q")}, - {0x1d5b1, 0, 0, 0, g(Yes, No, false, false, "", "R")}, - {0x1d5b2, 0, 0, 0, g(Yes, No, false, false, "", "S")}, - {0x1d5b3, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0x1d5b4, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0x1d5b5, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x1d5b6, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0x1d5b7, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0x1d5b8, 0, 0, 0, g(Yes, No, false, false, "", "Y")}, - {0x1d5b9, 0, 0, 0, g(Yes, No, false, false, "", "Z")}, - {0x1d5ba, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0x1d5bb, 0, 0, 0, g(Yes, No, false, false, "", "b")}, - {0x1d5bc, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0x1d5bd, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x1d5be, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x1d5bf, 0, 0, 0, g(Yes, No, false, false, "", "f")}, - {0x1d5c0, 0, 0, 0, g(Yes, No, false, false, "", "g")}, - {0x1d5c1, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0x1d5c2, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x1d5c3, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x1d5c4, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0x1d5c5, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x1d5c6, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x1d5c7, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0x1d5c8, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0x1d5c9, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0x1d5ca, 0, 0, 0, g(Yes, No, false, false, "", "q")}, - {0x1d5cb, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0x1d5cc, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0x1d5cd, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0x1d5ce, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0x1d5cf, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x1d5d0, 0, 0, 0, g(Yes, No, false, false, "", "w")}, - {0x1d5d1, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x1d5d2, 0, 0, 0, g(Yes, No, false, false, "", "y")}, - {0x1d5d3, 0, 0, 0, g(Yes, No, false, false, "", "z")}, - {0x1d5d4, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0x1d5d5, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0x1d5d6, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x1d5d7, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x1d5d8, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0x1d5d9, 0, 0, 0, g(Yes, No, false, false, "", "F")}, - {0x1d5da, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0x1d5db, 0, 0, 0, g(Yes, No, false, false, "", "H")}, - {0x1d5dc, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0x1d5dd, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0x1d5de, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0x1d5df, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x1d5e0, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x1d5e1, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0x1d5e2, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0x1d5e3, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0x1d5e4, 0, 0, 0, g(Yes, No, false, false, "", "Q")}, - {0x1d5e5, 0, 0, 0, g(Yes, No, false, false, "", "R")}, - {0x1d5e6, 0, 0, 0, g(Yes, No, false, false, "", "S")}, - {0x1d5e7, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0x1d5e8, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0x1d5e9, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x1d5ea, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0x1d5eb, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0x1d5ec, 0, 0, 0, g(Yes, No, false, false, "", "Y")}, - {0x1d5ed, 0, 0, 0, g(Yes, No, false, false, "", "Z")}, - {0x1d5ee, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0x1d5ef, 0, 0, 0, g(Yes, No, false, false, "", "b")}, - {0x1d5f0, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0x1d5f1, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x1d5f2, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x1d5f3, 0, 0, 0, g(Yes, No, false, false, "", "f")}, - {0x1d5f4, 0, 0, 0, g(Yes, No, false, false, "", "g")}, - {0x1d5f5, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0x1d5f6, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x1d5f7, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x1d5f8, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0x1d5f9, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x1d5fa, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x1d5fb, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0x1d5fc, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0x1d5fd, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0x1d5fe, 0, 0, 0, g(Yes, No, false, false, "", "q")}, - {0x1d5ff, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0x1d600, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0x1d601, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0x1d602, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0x1d603, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x1d604, 0, 0, 0, g(Yes, No, false, false, "", "w")}, - {0x1d605, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x1d606, 0, 0, 0, g(Yes, No, false, false, "", "y")}, - {0x1d607, 0, 0, 0, g(Yes, No, false, false, "", "z")}, - {0x1d608, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0x1d609, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0x1d60a, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x1d60b, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x1d60c, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0x1d60d, 0, 0, 0, g(Yes, No, false, false, "", "F")}, - {0x1d60e, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0x1d60f, 0, 0, 0, g(Yes, No, false, false, "", "H")}, - {0x1d610, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0x1d611, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0x1d612, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0x1d613, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x1d614, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x1d615, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0x1d616, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0x1d617, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0x1d618, 0, 0, 0, g(Yes, No, false, false, "", "Q")}, - {0x1d619, 0, 0, 0, g(Yes, No, false, false, "", "R")}, - {0x1d61a, 0, 0, 0, g(Yes, No, false, false, "", "S")}, - {0x1d61b, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0x1d61c, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0x1d61d, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x1d61e, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0x1d61f, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0x1d620, 0, 0, 0, g(Yes, No, false, false, "", "Y")}, - {0x1d621, 0, 0, 0, g(Yes, No, false, false, "", "Z")}, - {0x1d622, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0x1d623, 0, 0, 0, g(Yes, No, false, false, "", "b")}, - {0x1d624, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0x1d625, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x1d626, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x1d627, 0, 0, 0, g(Yes, No, false, false, "", "f")}, - {0x1d628, 0, 0, 0, g(Yes, No, false, false, "", "g")}, - {0x1d629, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0x1d62a, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x1d62b, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x1d62c, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0x1d62d, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x1d62e, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x1d62f, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0x1d630, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0x1d631, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0x1d632, 0, 0, 0, g(Yes, No, false, false, "", "q")}, - {0x1d633, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0x1d634, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0x1d635, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0x1d636, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0x1d637, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x1d638, 0, 0, 0, g(Yes, No, false, false, "", "w")}, - {0x1d639, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x1d63a, 0, 0, 0, g(Yes, No, false, false, "", "y")}, - {0x1d63b, 0, 0, 0, g(Yes, No, false, false, "", "z")}, - {0x1d63c, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0x1d63d, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0x1d63e, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x1d63f, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x1d640, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0x1d641, 0, 0, 0, g(Yes, No, false, false, "", "F")}, - {0x1d642, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0x1d643, 0, 0, 0, g(Yes, No, false, false, "", "H")}, - {0x1d644, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0x1d645, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0x1d646, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0x1d647, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x1d648, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x1d649, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0x1d64a, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0x1d64b, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0x1d64c, 0, 0, 0, g(Yes, No, false, false, "", "Q")}, - {0x1d64d, 0, 0, 0, g(Yes, No, false, false, "", "R")}, - {0x1d64e, 0, 0, 0, g(Yes, No, false, false, "", "S")}, - {0x1d64f, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0x1d650, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0x1d651, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x1d652, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0x1d653, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0x1d654, 0, 0, 0, g(Yes, No, false, false, "", "Y")}, - {0x1d655, 0, 0, 0, g(Yes, No, false, false, "", "Z")}, - {0x1d656, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0x1d657, 0, 0, 0, g(Yes, No, false, false, "", "b")}, - {0x1d658, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0x1d659, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x1d65a, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x1d65b, 0, 0, 0, g(Yes, No, false, false, "", "f")}, - {0x1d65c, 0, 0, 0, g(Yes, No, false, false, "", "g")}, - {0x1d65d, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0x1d65e, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x1d65f, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x1d660, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0x1d661, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x1d662, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x1d663, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0x1d664, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0x1d665, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0x1d666, 0, 0, 0, g(Yes, No, false, false, "", "q")}, - {0x1d667, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0x1d668, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0x1d669, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0x1d66a, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0x1d66b, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x1d66c, 0, 0, 0, g(Yes, No, false, false, "", "w")}, - {0x1d66d, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x1d66e, 0, 0, 0, g(Yes, No, false, false, "", "y")}, - {0x1d66f, 0, 0, 0, g(Yes, No, false, false, "", "z")}, - {0x1d670, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0x1d671, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0x1d672, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x1d673, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x1d674, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0x1d675, 0, 0, 0, g(Yes, No, false, false, "", "F")}, - {0x1d676, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0x1d677, 0, 0, 0, g(Yes, No, false, false, "", "H")}, - {0x1d678, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0x1d679, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0x1d67a, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0x1d67b, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x1d67c, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x1d67d, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0x1d67e, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0x1d67f, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0x1d680, 0, 0, 0, g(Yes, No, false, false, "", "Q")}, - {0x1d681, 0, 0, 0, g(Yes, No, false, false, "", "R")}, - {0x1d682, 0, 0, 0, g(Yes, No, false, false, "", "S")}, - {0x1d683, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0x1d684, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0x1d685, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x1d686, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0x1d687, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0x1d688, 0, 0, 0, g(Yes, No, false, false, "", "Y")}, - {0x1d689, 0, 0, 0, g(Yes, No, false, false, "", "Z")}, - {0x1d68a, 0, 0, 0, g(Yes, No, false, false, "", "a")}, - {0x1d68b, 0, 0, 0, g(Yes, No, false, false, "", "b")}, - {0x1d68c, 0, 0, 0, g(Yes, No, false, false, "", "c")}, - {0x1d68d, 0, 0, 0, g(Yes, No, false, false, "", "d")}, - {0x1d68e, 0, 0, 0, g(Yes, No, false, false, "", "e")}, - {0x1d68f, 0, 0, 0, g(Yes, No, false, false, "", "f")}, - {0x1d690, 0, 0, 0, g(Yes, No, false, false, "", "g")}, - {0x1d691, 0, 0, 0, g(Yes, No, false, false, "", "h")}, - {0x1d692, 0, 0, 0, g(Yes, No, false, false, "", "i")}, - {0x1d693, 0, 0, 0, g(Yes, No, false, false, "", "j")}, - {0x1d694, 0, 0, 0, g(Yes, No, false, false, "", "k")}, - {0x1d695, 0, 0, 0, g(Yes, No, false, false, "", "l")}, - {0x1d696, 0, 0, 0, g(Yes, No, false, false, "", "m")}, - {0x1d697, 0, 0, 0, g(Yes, No, false, false, "", "n")}, - {0x1d698, 0, 0, 0, g(Yes, No, false, false, "", "o")}, - {0x1d699, 0, 0, 0, g(Yes, No, false, false, "", "p")}, - {0x1d69a, 0, 0, 0, g(Yes, No, false, false, "", "q")}, - {0x1d69b, 0, 0, 0, g(Yes, No, false, false, "", "r")}, - {0x1d69c, 0, 0, 0, g(Yes, No, false, false, "", "s")}, - {0x1d69d, 0, 0, 0, g(Yes, No, false, false, "", "t")}, - {0x1d69e, 0, 0, 0, g(Yes, No, false, false, "", "u")}, - {0x1d69f, 0, 0, 0, g(Yes, No, false, false, "", "v")}, - {0x1d6a0, 0, 0, 0, g(Yes, No, false, false, "", "w")}, - {0x1d6a1, 0, 0, 0, g(Yes, No, false, false, "", "x")}, - {0x1d6a2, 0, 0, 0, g(Yes, No, false, false, "", "y")}, - {0x1d6a3, 0, 0, 0, g(Yes, No, false, false, "", "z")}, - {0x1d6a4, 0, 0, 0, g(Yes, No, false, false, "", "ı")}, - {0x1d6a5, 0, 0, 0, g(Yes, No, false, false, "", "ȷ")}, - {0x1d6a6, 0, 0, 0, f(Yes, false, "")}, - {0x1d6a8, 0, 0, 0, g(Yes, No, false, false, "", "Α")}, - {0x1d6a9, 0, 0, 0, g(Yes, No, false, false, "", "Β")}, - {0x1d6aa, 0, 0, 0, g(Yes, No, false, false, "", "Γ")}, - {0x1d6ab, 0, 0, 0, g(Yes, No, false, false, "", "Δ")}, - {0x1d6ac, 0, 0, 0, g(Yes, No, false, false, "", "Ε")}, - {0x1d6ad, 0, 0, 0, g(Yes, No, false, false, "", "Ζ")}, - {0x1d6ae, 0, 0, 0, g(Yes, No, false, false, "", "Η")}, - {0x1d6af, 0, 0, 0, g(Yes, No, false, false, "", "Θ")}, - {0x1d6b0, 0, 0, 0, g(Yes, No, false, false, "", "Ι")}, - {0x1d6b1, 0, 0, 0, g(Yes, No, false, false, "", "Κ")}, - {0x1d6b2, 0, 0, 0, g(Yes, No, false, false, "", "Λ")}, - {0x1d6b3, 0, 0, 0, g(Yes, No, false, false, "", "Μ")}, - {0x1d6b4, 0, 0, 0, g(Yes, No, false, false, "", "Ν")}, - {0x1d6b5, 0, 0, 0, g(Yes, No, false, false, "", "Ξ")}, - {0x1d6b6, 0, 0, 0, g(Yes, No, false, false, "", "Ο")}, - {0x1d6b7, 0, 0, 0, g(Yes, No, false, false, "", "Π")}, - {0x1d6b8, 0, 0, 0, g(Yes, No, false, false, "", "Ρ")}, - {0x1d6b9, 0, 0, 0, g(Yes, No, false, false, "", "Θ")}, - {0x1d6ba, 0, 0, 0, g(Yes, No, false, false, "", "Σ")}, - {0x1d6bb, 0, 0, 0, g(Yes, No, false, false, "", "Τ")}, - {0x1d6bc, 0, 0, 0, g(Yes, No, false, false, "", "Υ")}, - {0x1d6bd, 0, 0, 0, g(Yes, No, false, false, "", "Φ")}, - {0x1d6be, 0, 0, 0, g(Yes, No, false, false, "", "Χ")}, - {0x1d6bf, 0, 0, 0, g(Yes, No, false, false, "", "Ψ")}, - {0x1d6c0, 0, 0, 0, g(Yes, No, false, false, "", "Ω")}, - {0x1d6c1, 0, 0, 0, g(Yes, No, false, false, "", "∇")}, - {0x1d6c2, 0, 0, 0, g(Yes, No, false, false, "", "α")}, - {0x1d6c3, 0, 0, 0, g(Yes, No, false, false, "", "β")}, - {0x1d6c4, 0, 0, 0, g(Yes, No, false, false, "", "γ")}, - {0x1d6c5, 0, 0, 0, g(Yes, No, false, false, "", "δ")}, - {0x1d6c6, 0, 0, 0, g(Yes, No, false, false, "", "ε")}, - {0x1d6c7, 0, 0, 0, g(Yes, No, false, false, "", "ζ")}, - {0x1d6c8, 0, 0, 0, g(Yes, No, false, false, "", "η")}, - {0x1d6c9, 0, 0, 0, g(Yes, No, false, false, "", "θ")}, - {0x1d6ca, 0, 0, 0, g(Yes, No, false, false, "", "ι")}, - {0x1d6cb, 0, 0, 0, g(Yes, No, false, false, "", "κ")}, - {0x1d6cc, 0, 0, 0, g(Yes, No, false, false, "", "λ")}, - {0x1d6cd, 0, 0, 0, g(Yes, No, false, false, "", "μ")}, - {0x1d6ce, 0, 0, 0, g(Yes, No, false, false, "", "ν")}, - {0x1d6cf, 0, 0, 0, g(Yes, No, false, false, "", "ξ")}, - {0x1d6d0, 0, 0, 0, g(Yes, No, false, false, "", "ο")}, - {0x1d6d1, 0, 0, 0, g(Yes, No, false, false, "", "π")}, - {0x1d6d2, 0, 0, 0, g(Yes, No, false, false, "", "ρ")}, - {0x1d6d3, 0, 0, 0, g(Yes, No, false, false, "", "ς")}, - {0x1d6d4, 0, 0, 0, g(Yes, No, false, false, "", "σ")}, - {0x1d6d5, 0, 0, 0, g(Yes, No, false, false, "", "τ")}, - {0x1d6d6, 0, 0, 0, g(Yes, No, false, false, "", "υ")}, - {0x1d6d7, 0, 0, 0, g(Yes, No, false, false, "", "φ")}, - {0x1d6d8, 0, 0, 0, g(Yes, No, false, false, "", "χ")}, - {0x1d6d9, 0, 0, 0, g(Yes, No, false, false, "", "ψ")}, - {0x1d6da, 0, 0, 0, g(Yes, No, false, false, "", "ω")}, - {0x1d6db, 0, 0, 0, g(Yes, No, false, false, "", "∂")}, - {0x1d6dc, 0, 0, 0, g(Yes, No, false, false, "", "ε")}, - {0x1d6dd, 0, 0, 0, g(Yes, No, false, false, "", "θ")}, - {0x1d6de, 0, 0, 0, g(Yes, No, false, false, "", "κ")}, - {0x1d6df, 0, 0, 0, g(Yes, No, false, false, "", "φ")}, - {0x1d6e0, 0, 0, 0, g(Yes, No, false, false, "", "ρ")}, - {0x1d6e1, 0, 0, 0, g(Yes, No, false, false, "", "π")}, - {0x1d6e2, 0, 0, 0, g(Yes, No, false, false, "", "Α")}, - {0x1d6e3, 0, 0, 0, g(Yes, No, false, false, "", "Β")}, - {0x1d6e4, 0, 0, 0, g(Yes, No, false, false, "", "Γ")}, - {0x1d6e5, 0, 0, 0, g(Yes, No, false, false, "", "Δ")}, - {0x1d6e6, 0, 0, 0, g(Yes, No, false, false, "", "Ε")}, - {0x1d6e7, 0, 0, 0, g(Yes, No, false, false, "", "Ζ")}, - {0x1d6e8, 0, 0, 0, g(Yes, No, false, false, "", "Η")}, - {0x1d6e9, 0, 0, 0, g(Yes, No, false, false, "", "Θ")}, - {0x1d6ea, 0, 0, 0, g(Yes, No, false, false, "", "Ι")}, - {0x1d6eb, 0, 0, 0, g(Yes, No, false, false, "", "Κ")}, - {0x1d6ec, 0, 0, 0, g(Yes, No, false, false, "", "Λ")}, - {0x1d6ed, 0, 0, 0, g(Yes, No, false, false, "", "Μ")}, - {0x1d6ee, 0, 0, 0, g(Yes, No, false, false, "", "Ν")}, - {0x1d6ef, 0, 0, 0, g(Yes, No, false, false, "", "Ξ")}, - {0x1d6f0, 0, 0, 0, g(Yes, No, false, false, "", "Ο")}, - {0x1d6f1, 0, 0, 0, g(Yes, No, false, false, "", "Π")}, - {0x1d6f2, 0, 0, 0, g(Yes, No, false, false, "", "Ρ")}, - {0x1d6f3, 0, 0, 0, g(Yes, No, false, false, "", "Θ")}, - {0x1d6f4, 0, 0, 0, g(Yes, No, false, false, "", "Σ")}, - {0x1d6f5, 0, 0, 0, g(Yes, No, false, false, "", "Τ")}, - {0x1d6f6, 0, 0, 0, g(Yes, No, false, false, "", "Υ")}, - {0x1d6f7, 0, 0, 0, g(Yes, No, false, false, "", "Φ")}, - {0x1d6f8, 0, 0, 0, g(Yes, No, false, false, "", "Χ")}, - {0x1d6f9, 0, 0, 0, g(Yes, No, false, false, "", "Ψ")}, - {0x1d6fa, 0, 0, 0, g(Yes, No, false, false, "", "Ω")}, - {0x1d6fb, 0, 0, 0, g(Yes, No, false, false, "", "∇")}, - {0x1d6fc, 0, 0, 0, g(Yes, No, false, false, "", "α")}, - {0x1d6fd, 0, 0, 0, g(Yes, No, false, false, "", "β")}, - {0x1d6fe, 0, 0, 0, g(Yes, No, false, false, "", "γ")}, - {0x1d6ff, 0, 0, 0, g(Yes, No, false, false, "", "δ")}, - {0x1d700, 0, 0, 0, g(Yes, No, false, false, "", "ε")}, - {0x1d701, 0, 0, 0, g(Yes, No, false, false, "", "ζ")}, - {0x1d702, 0, 0, 0, g(Yes, No, false, false, "", "η")}, - {0x1d703, 0, 0, 0, g(Yes, No, false, false, "", "θ")}, - {0x1d704, 0, 0, 0, g(Yes, No, false, false, "", "ι")}, - {0x1d705, 0, 0, 0, g(Yes, No, false, false, "", "κ")}, - {0x1d706, 0, 0, 0, g(Yes, No, false, false, "", "λ")}, - {0x1d707, 0, 0, 0, g(Yes, No, false, false, "", "μ")}, - {0x1d708, 0, 0, 0, g(Yes, No, false, false, "", "ν")}, - {0x1d709, 0, 0, 0, g(Yes, No, false, false, "", "ξ")}, - {0x1d70a, 0, 0, 0, g(Yes, No, false, false, "", "ο")}, - {0x1d70b, 0, 0, 0, g(Yes, No, false, false, "", "π")}, - {0x1d70c, 0, 0, 0, g(Yes, No, false, false, "", "ρ")}, - {0x1d70d, 0, 0, 0, g(Yes, No, false, false, "", "ς")}, - {0x1d70e, 0, 0, 0, g(Yes, No, false, false, "", "σ")}, - {0x1d70f, 0, 0, 0, g(Yes, No, false, false, "", "τ")}, - {0x1d710, 0, 0, 0, g(Yes, No, false, false, "", "υ")}, - {0x1d711, 0, 0, 0, g(Yes, No, false, false, "", "φ")}, - {0x1d712, 0, 0, 0, g(Yes, No, false, false, "", "χ")}, - {0x1d713, 0, 0, 0, g(Yes, No, false, false, "", "ψ")}, - {0x1d714, 0, 0, 0, g(Yes, No, false, false, "", "ω")}, - {0x1d715, 0, 0, 0, g(Yes, No, false, false, "", "∂")}, - {0x1d716, 0, 0, 0, g(Yes, No, false, false, "", "ε")}, - {0x1d717, 0, 0, 0, g(Yes, No, false, false, "", "θ")}, - {0x1d718, 0, 0, 0, g(Yes, No, false, false, "", "κ")}, - {0x1d719, 0, 0, 0, g(Yes, No, false, false, "", "φ")}, - {0x1d71a, 0, 0, 0, g(Yes, No, false, false, "", "ρ")}, - {0x1d71b, 0, 0, 0, g(Yes, No, false, false, "", "π")}, - {0x1d71c, 0, 0, 0, g(Yes, No, false, false, "", "Α")}, - {0x1d71d, 0, 0, 0, g(Yes, No, false, false, "", "Β")}, - {0x1d71e, 0, 0, 0, g(Yes, No, false, false, "", "Γ")}, - {0x1d71f, 0, 0, 0, g(Yes, No, false, false, "", "Δ")}, - {0x1d720, 0, 0, 0, g(Yes, No, false, false, "", "Ε")}, - {0x1d721, 0, 0, 0, g(Yes, No, false, false, "", "Ζ")}, - {0x1d722, 0, 0, 0, g(Yes, No, false, false, "", "Η")}, - {0x1d723, 0, 0, 0, g(Yes, No, false, false, "", "Θ")}, - {0x1d724, 0, 0, 0, g(Yes, No, false, false, "", "Ι")}, - {0x1d725, 0, 0, 0, g(Yes, No, false, false, "", "Κ")}, - {0x1d726, 0, 0, 0, g(Yes, No, false, false, "", "Λ")}, - {0x1d727, 0, 0, 0, g(Yes, No, false, false, "", "Μ")}, - {0x1d728, 0, 0, 0, g(Yes, No, false, false, "", "Ν")}, - {0x1d729, 0, 0, 0, g(Yes, No, false, false, "", "Ξ")}, - {0x1d72a, 0, 0, 0, g(Yes, No, false, false, "", "Ο")}, - {0x1d72b, 0, 0, 0, g(Yes, No, false, false, "", "Π")}, - {0x1d72c, 0, 0, 0, g(Yes, No, false, false, "", "Ρ")}, - {0x1d72d, 0, 0, 0, g(Yes, No, false, false, "", "Θ")}, - {0x1d72e, 0, 0, 0, g(Yes, No, false, false, "", "Σ")}, - {0x1d72f, 0, 0, 0, g(Yes, No, false, false, "", "Τ")}, - {0x1d730, 0, 0, 0, g(Yes, No, false, false, "", "Υ")}, - {0x1d731, 0, 0, 0, g(Yes, No, false, false, "", "Φ")}, - {0x1d732, 0, 0, 0, g(Yes, No, false, false, "", "Χ")}, - {0x1d733, 0, 0, 0, g(Yes, No, false, false, "", "Ψ")}, - {0x1d734, 0, 0, 0, g(Yes, No, false, false, "", "Ω")}, - {0x1d735, 0, 0, 0, g(Yes, No, false, false, "", "∇")}, - {0x1d736, 0, 0, 0, g(Yes, No, false, false, "", "α")}, - {0x1d737, 0, 0, 0, g(Yes, No, false, false, "", "β")}, - {0x1d738, 0, 0, 0, g(Yes, No, false, false, "", "γ")}, - {0x1d739, 0, 0, 0, g(Yes, No, false, false, "", "δ")}, - {0x1d73a, 0, 0, 0, g(Yes, No, false, false, "", "ε")}, - {0x1d73b, 0, 0, 0, g(Yes, No, false, false, "", "ζ")}, - {0x1d73c, 0, 0, 0, g(Yes, No, false, false, "", "η")}, - {0x1d73d, 0, 0, 0, g(Yes, No, false, false, "", "θ")}, - {0x1d73e, 0, 0, 0, g(Yes, No, false, false, "", "ι")}, - {0x1d73f, 0, 0, 0, g(Yes, No, false, false, "", "κ")}, - {0x1d740, 0, 0, 0, g(Yes, No, false, false, "", "λ")}, - {0x1d741, 0, 0, 0, g(Yes, No, false, false, "", "μ")}, - {0x1d742, 0, 0, 0, g(Yes, No, false, false, "", "ν")}, - {0x1d743, 0, 0, 0, g(Yes, No, false, false, "", "ξ")}, - {0x1d744, 0, 0, 0, g(Yes, No, false, false, "", "ο")}, - {0x1d745, 0, 0, 0, g(Yes, No, false, false, "", "π")}, - {0x1d746, 0, 0, 0, g(Yes, No, false, false, "", "ρ")}, - {0x1d747, 0, 0, 0, g(Yes, No, false, false, "", "ς")}, - {0x1d748, 0, 0, 0, g(Yes, No, false, false, "", "σ")}, - {0x1d749, 0, 0, 0, g(Yes, No, false, false, "", "τ")}, - {0x1d74a, 0, 0, 0, g(Yes, No, false, false, "", "υ")}, - {0x1d74b, 0, 0, 0, g(Yes, No, false, false, "", "φ")}, - {0x1d74c, 0, 0, 0, g(Yes, No, false, false, "", "χ")}, - {0x1d74d, 0, 0, 0, g(Yes, No, false, false, "", "ψ")}, - {0x1d74e, 0, 0, 0, g(Yes, No, false, false, "", "ω")}, - {0x1d74f, 0, 0, 0, g(Yes, No, false, false, "", "∂")}, - {0x1d750, 0, 0, 0, g(Yes, No, false, false, "", "ε")}, - {0x1d751, 0, 0, 0, g(Yes, No, false, false, "", "θ")}, - {0x1d752, 0, 0, 0, g(Yes, No, false, false, "", "κ")}, - {0x1d753, 0, 0, 0, g(Yes, No, false, false, "", "φ")}, - {0x1d754, 0, 0, 0, g(Yes, No, false, false, "", "ρ")}, - {0x1d755, 0, 0, 0, g(Yes, No, false, false, "", "π")}, - {0x1d756, 0, 0, 0, g(Yes, No, false, false, "", "Α")}, - {0x1d757, 0, 0, 0, g(Yes, No, false, false, "", "Β")}, - {0x1d758, 0, 0, 0, g(Yes, No, false, false, "", "Γ")}, - {0x1d759, 0, 0, 0, g(Yes, No, false, false, "", "Δ")}, - {0x1d75a, 0, 0, 0, g(Yes, No, false, false, "", "Ε")}, - {0x1d75b, 0, 0, 0, g(Yes, No, false, false, "", "Ζ")}, - {0x1d75c, 0, 0, 0, g(Yes, No, false, false, "", "Η")}, - {0x1d75d, 0, 0, 0, g(Yes, No, false, false, "", "Θ")}, - {0x1d75e, 0, 0, 0, g(Yes, No, false, false, "", "Ι")}, - {0x1d75f, 0, 0, 0, g(Yes, No, false, false, "", "Κ")}, - {0x1d760, 0, 0, 0, g(Yes, No, false, false, "", "Λ")}, - {0x1d761, 0, 0, 0, g(Yes, No, false, false, "", "Μ")}, - {0x1d762, 0, 0, 0, g(Yes, No, false, false, "", "Ν")}, - {0x1d763, 0, 0, 0, g(Yes, No, false, false, "", "Ξ")}, - {0x1d764, 0, 0, 0, g(Yes, No, false, false, "", "Ο")}, - {0x1d765, 0, 0, 0, g(Yes, No, false, false, "", "Π")}, - {0x1d766, 0, 0, 0, g(Yes, No, false, false, "", "Ρ")}, - {0x1d767, 0, 0, 0, g(Yes, No, false, false, "", "Θ")}, - {0x1d768, 0, 0, 0, g(Yes, No, false, false, "", "Σ")}, - {0x1d769, 0, 0, 0, g(Yes, No, false, false, "", "Τ")}, - {0x1d76a, 0, 0, 0, g(Yes, No, false, false, "", "Υ")}, - {0x1d76b, 0, 0, 0, g(Yes, No, false, false, "", "Φ")}, - {0x1d76c, 0, 0, 0, g(Yes, No, false, false, "", "Χ")}, - {0x1d76d, 0, 0, 0, g(Yes, No, false, false, "", "Ψ")}, - {0x1d76e, 0, 0, 0, g(Yes, No, false, false, "", "Ω")}, - {0x1d76f, 0, 0, 0, g(Yes, No, false, false, "", "∇")}, - {0x1d770, 0, 0, 0, g(Yes, No, false, false, "", "α")}, - {0x1d771, 0, 0, 0, g(Yes, No, false, false, "", "β")}, - {0x1d772, 0, 0, 0, g(Yes, No, false, false, "", "γ")}, - {0x1d773, 0, 0, 0, g(Yes, No, false, false, "", "δ")}, - {0x1d774, 0, 0, 0, g(Yes, No, false, false, "", "ε")}, - {0x1d775, 0, 0, 0, g(Yes, No, false, false, "", "ζ")}, - {0x1d776, 0, 0, 0, g(Yes, No, false, false, "", "η")}, - {0x1d777, 0, 0, 0, g(Yes, No, false, false, "", "θ")}, - {0x1d778, 0, 0, 0, g(Yes, No, false, false, "", "ι")}, - {0x1d779, 0, 0, 0, g(Yes, No, false, false, "", "κ")}, - {0x1d77a, 0, 0, 0, g(Yes, No, false, false, "", "λ")}, - {0x1d77b, 0, 0, 0, g(Yes, No, false, false, "", "μ")}, - {0x1d77c, 0, 0, 0, g(Yes, No, false, false, "", "ν")}, - {0x1d77d, 0, 0, 0, g(Yes, No, false, false, "", "ξ")}, - {0x1d77e, 0, 0, 0, g(Yes, No, false, false, "", "ο")}, - {0x1d77f, 0, 0, 0, g(Yes, No, false, false, "", "π")}, - {0x1d780, 0, 0, 0, g(Yes, No, false, false, "", "ρ")}, - {0x1d781, 0, 0, 0, g(Yes, No, false, false, "", "ς")}, - {0x1d782, 0, 0, 0, g(Yes, No, false, false, "", "σ")}, - {0x1d783, 0, 0, 0, g(Yes, No, false, false, "", "τ")}, - {0x1d784, 0, 0, 0, g(Yes, No, false, false, "", "υ")}, - {0x1d785, 0, 0, 0, g(Yes, No, false, false, "", "φ")}, - {0x1d786, 0, 0, 0, g(Yes, No, false, false, "", "χ")}, - {0x1d787, 0, 0, 0, g(Yes, No, false, false, "", "ψ")}, - {0x1d788, 0, 0, 0, g(Yes, No, false, false, "", "ω")}, - {0x1d789, 0, 0, 0, g(Yes, No, false, false, "", "∂")}, - {0x1d78a, 0, 0, 0, g(Yes, No, false, false, "", "ε")}, - {0x1d78b, 0, 0, 0, g(Yes, No, false, false, "", "θ")}, - {0x1d78c, 0, 0, 0, g(Yes, No, false, false, "", "κ")}, - {0x1d78d, 0, 0, 0, g(Yes, No, false, false, "", "φ")}, - {0x1d78e, 0, 0, 0, g(Yes, No, false, false, "", "ρ")}, - {0x1d78f, 0, 0, 0, g(Yes, No, false, false, "", "π")}, - {0x1d790, 0, 0, 0, g(Yes, No, false, false, "", "Α")}, - {0x1d791, 0, 0, 0, g(Yes, No, false, false, "", "Β")}, - {0x1d792, 0, 0, 0, g(Yes, No, false, false, "", "Γ")}, - {0x1d793, 0, 0, 0, g(Yes, No, false, false, "", "Δ")}, - {0x1d794, 0, 0, 0, g(Yes, No, false, false, "", "Ε")}, - {0x1d795, 0, 0, 0, g(Yes, No, false, false, "", "Ζ")}, - {0x1d796, 0, 0, 0, g(Yes, No, false, false, "", "Η")}, - {0x1d797, 0, 0, 0, g(Yes, No, false, false, "", "Θ")}, - {0x1d798, 0, 0, 0, g(Yes, No, false, false, "", "Ι")}, - {0x1d799, 0, 0, 0, g(Yes, No, false, false, "", "Κ")}, - {0x1d79a, 0, 0, 0, g(Yes, No, false, false, "", "Λ")}, - {0x1d79b, 0, 0, 0, g(Yes, No, false, false, "", "Μ")}, - {0x1d79c, 0, 0, 0, g(Yes, No, false, false, "", "Ν")}, - {0x1d79d, 0, 0, 0, g(Yes, No, false, false, "", "Ξ")}, - {0x1d79e, 0, 0, 0, g(Yes, No, false, false, "", "Ο")}, - {0x1d79f, 0, 0, 0, g(Yes, No, false, false, "", "Π")}, - {0x1d7a0, 0, 0, 0, g(Yes, No, false, false, "", "Ρ")}, - {0x1d7a1, 0, 0, 0, g(Yes, No, false, false, "", "Θ")}, - {0x1d7a2, 0, 0, 0, g(Yes, No, false, false, "", "Σ")}, - {0x1d7a3, 0, 0, 0, g(Yes, No, false, false, "", "Τ")}, - {0x1d7a4, 0, 0, 0, g(Yes, No, false, false, "", "Υ")}, - {0x1d7a5, 0, 0, 0, g(Yes, No, false, false, "", "Φ")}, - {0x1d7a6, 0, 0, 0, g(Yes, No, false, false, "", "Χ")}, - {0x1d7a7, 0, 0, 0, g(Yes, No, false, false, "", "Ψ")}, - {0x1d7a8, 0, 0, 0, g(Yes, No, false, false, "", "Ω")}, - {0x1d7a9, 0, 0, 0, g(Yes, No, false, false, "", "∇")}, - {0x1d7aa, 0, 0, 0, g(Yes, No, false, false, "", "α")}, - {0x1d7ab, 0, 0, 0, g(Yes, No, false, false, "", "β")}, - {0x1d7ac, 0, 0, 0, g(Yes, No, false, false, "", "γ")}, - {0x1d7ad, 0, 0, 0, g(Yes, No, false, false, "", "δ")}, - {0x1d7ae, 0, 0, 0, g(Yes, No, false, false, "", "ε")}, - {0x1d7af, 0, 0, 0, g(Yes, No, false, false, "", "ζ")}, - {0x1d7b0, 0, 0, 0, g(Yes, No, false, false, "", "η")}, - {0x1d7b1, 0, 0, 0, g(Yes, No, false, false, "", "θ")}, - {0x1d7b2, 0, 0, 0, g(Yes, No, false, false, "", "ι")}, - {0x1d7b3, 0, 0, 0, g(Yes, No, false, false, "", "κ")}, - {0x1d7b4, 0, 0, 0, g(Yes, No, false, false, "", "λ")}, - {0x1d7b5, 0, 0, 0, g(Yes, No, false, false, "", "μ")}, - {0x1d7b6, 0, 0, 0, g(Yes, No, false, false, "", "ν")}, - {0x1d7b7, 0, 0, 0, g(Yes, No, false, false, "", "ξ")}, - {0x1d7b8, 0, 0, 0, g(Yes, No, false, false, "", "ο")}, - {0x1d7b9, 0, 0, 0, g(Yes, No, false, false, "", "π")}, - {0x1d7ba, 0, 0, 0, g(Yes, No, false, false, "", "ρ")}, - {0x1d7bb, 0, 0, 0, g(Yes, No, false, false, "", "ς")}, - {0x1d7bc, 0, 0, 0, g(Yes, No, false, false, "", "σ")}, - {0x1d7bd, 0, 0, 0, g(Yes, No, false, false, "", "τ")}, - {0x1d7be, 0, 0, 0, g(Yes, No, false, false, "", "υ")}, - {0x1d7bf, 0, 0, 0, g(Yes, No, false, false, "", "φ")}, - {0x1d7c0, 0, 0, 0, g(Yes, No, false, false, "", "χ")}, - {0x1d7c1, 0, 0, 0, g(Yes, No, false, false, "", "ψ")}, - {0x1d7c2, 0, 0, 0, g(Yes, No, false, false, "", "ω")}, - {0x1d7c3, 0, 0, 0, g(Yes, No, false, false, "", "∂")}, - {0x1d7c4, 0, 0, 0, g(Yes, No, false, false, "", "ε")}, - {0x1d7c5, 0, 0, 0, g(Yes, No, false, false, "", "θ")}, - {0x1d7c6, 0, 0, 0, g(Yes, No, false, false, "", "κ")}, - {0x1d7c7, 0, 0, 0, g(Yes, No, false, false, "", "φ")}, - {0x1d7c8, 0, 0, 0, g(Yes, No, false, false, "", "ρ")}, - {0x1d7c9, 0, 0, 0, g(Yes, No, false, false, "", "π")}, - {0x1d7ca, 0, 0, 0, g(Yes, No, false, false, "", "Ϝ")}, - {0x1d7cb, 0, 0, 0, g(Yes, No, false, false, "", "ϝ")}, - {0x1d7cc, 0, 0, 0, f(Yes, false, "")}, - {0x1d7ce, 0, 0, 0, g(Yes, No, false, false, "", "0")}, - {0x1d7cf, 0, 0, 0, g(Yes, No, false, false, "", "1")}, - {0x1d7d0, 0, 0, 0, g(Yes, No, false, false, "", "2")}, - {0x1d7d1, 0, 0, 0, g(Yes, No, false, false, "", "3")}, - {0x1d7d2, 0, 0, 0, g(Yes, No, false, false, "", "4")}, - {0x1d7d3, 0, 0, 0, g(Yes, No, false, false, "", "5")}, - {0x1d7d4, 0, 0, 0, g(Yes, No, false, false, "", "6")}, - {0x1d7d5, 0, 0, 0, g(Yes, No, false, false, "", "7")}, - {0x1d7d6, 0, 0, 0, g(Yes, No, false, false, "", "8")}, - {0x1d7d7, 0, 0, 0, g(Yes, No, false, false, "", "9")}, - {0x1d7d8, 0, 0, 0, g(Yes, No, false, false, "", "0")}, - {0x1d7d9, 0, 0, 0, g(Yes, No, false, false, "", "1")}, - {0x1d7da, 0, 0, 0, g(Yes, No, false, false, "", "2")}, - {0x1d7db, 0, 0, 0, g(Yes, No, false, false, "", "3")}, - {0x1d7dc, 0, 0, 0, g(Yes, No, false, false, "", "4")}, - {0x1d7dd, 0, 0, 0, g(Yes, No, false, false, "", "5")}, - {0x1d7de, 0, 0, 0, g(Yes, No, false, false, "", "6")}, - {0x1d7df, 0, 0, 0, g(Yes, No, false, false, "", "7")}, - {0x1d7e0, 0, 0, 0, g(Yes, No, false, false, "", "8")}, - {0x1d7e1, 0, 0, 0, g(Yes, No, false, false, "", "9")}, - {0x1d7e2, 0, 0, 0, g(Yes, No, false, false, "", "0")}, - {0x1d7e3, 0, 0, 0, g(Yes, No, false, false, "", "1")}, - {0x1d7e4, 0, 0, 0, g(Yes, No, false, false, "", "2")}, - {0x1d7e5, 0, 0, 0, g(Yes, No, false, false, "", "3")}, - {0x1d7e6, 0, 0, 0, g(Yes, No, false, false, "", "4")}, - {0x1d7e7, 0, 0, 0, g(Yes, No, false, false, "", "5")}, - {0x1d7e8, 0, 0, 0, g(Yes, No, false, false, "", "6")}, - {0x1d7e9, 0, 0, 0, g(Yes, No, false, false, "", "7")}, - {0x1d7ea, 0, 0, 0, g(Yes, No, false, false, "", "8")}, - {0x1d7eb, 0, 0, 0, g(Yes, No, false, false, "", "9")}, - {0x1d7ec, 0, 0, 0, g(Yes, No, false, false, "", "0")}, - {0x1d7ed, 0, 0, 0, g(Yes, No, false, false, "", "1")}, - {0x1d7ee, 0, 0, 0, g(Yes, No, false, false, "", "2")}, - {0x1d7ef, 0, 0, 0, g(Yes, No, false, false, "", "3")}, - {0x1d7f0, 0, 0, 0, g(Yes, No, false, false, "", "4")}, - {0x1d7f1, 0, 0, 0, g(Yes, No, false, false, "", "5")}, - {0x1d7f2, 0, 0, 0, g(Yes, No, false, false, "", "6")}, - {0x1d7f3, 0, 0, 0, g(Yes, No, false, false, "", "7")}, - {0x1d7f4, 0, 0, 0, g(Yes, No, false, false, "", "8")}, - {0x1d7f5, 0, 0, 0, g(Yes, No, false, false, "", "9")}, - {0x1d7f6, 0, 0, 0, g(Yes, No, false, false, "", "0")}, - {0x1d7f7, 0, 0, 0, g(Yes, No, false, false, "", "1")}, - {0x1d7f8, 0, 0, 0, g(Yes, No, false, false, "", "2")}, - {0x1d7f9, 0, 0, 0, g(Yes, No, false, false, "", "3")}, - {0x1d7fa, 0, 0, 0, g(Yes, No, false, false, "", "4")}, - {0x1d7fb, 0, 0, 0, g(Yes, No, false, false, "", "5")}, - {0x1d7fc, 0, 0, 0, g(Yes, No, false, false, "", "6")}, - {0x1d7fd, 0, 0, 0, g(Yes, No, false, false, "", "7")}, - {0x1d7fe, 0, 0, 0, g(Yes, No, false, false, "", "8")}, - {0x1d7ff, 0, 0, 0, g(Yes, No, false, false, "", "9")}, - {0x1d800, 0, 0, 0, f(Yes, false, "")}, - {0x1e000, 230, 1, 1, f(Yes, false, "")}, - {0x1e007, 0, 0, 0, f(Yes, false, "")}, - {0x1e008, 230, 1, 1, f(Yes, false, "")}, - {0x1e019, 0, 0, 0, f(Yes, false, "")}, - {0x1e01b, 230, 1, 1, f(Yes, false, "")}, - {0x1e022, 0, 0, 0, f(Yes, false, "")}, - {0x1e023, 230, 1, 1, f(Yes, false, "")}, - {0x1e025, 0, 0, 0, f(Yes, false, "")}, - {0x1e026, 230, 1, 1, f(Yes, false, "")}, - {0x1e02b, 0, 0, 0, f(Yes, false, "")}, - {0x1e8d0, 220, 1, 1, f(Yes, false, "")}, - {0x1e8d7, 0, 0, 0, f(Yes, false, "")}, - {0x1e944, 230, 1, 1, f(Yes, false, "")}, - {0x1e94a, 7, 1, 1, f(Yes, false, "")}, - {0x1e94b, 0, 0, 0, f(Yes, false, "")}, - {0x1ee00, 0, 0, 0, g(Yes, No, false, false, "", "ا")}, - {0x1ee01, 0, 0, 0, g(Yes, No, false, false, "", "ب")}, - {0x1ee02, 0, 0, 0, g(Yes, No, false, false, "", "ج")}, - {0x1ee03, 0, 0, 0, g(Yes, No, false, false, "", "د")}, - {0x1ee04, 0, 0, 0, f(Yes, false, "")}, - {0x1ee05, 0, 0, 0, g(Yes, No, false, false, "", "و")}, - {0x1ee06, 0, 0, 0, g(Yes, No, false, false, "", "ز")}, - {0x1ee07, 0, 0, 0, g(Yes, No, false, false, "", "ح")}, - {0x1ee08, 0, 0, 0, g(Yes, No, false, false, "", "ط")}, - {0x1ee09, 0, 0, 0, g(Yes, No, false, false, "", "ي")}, - {0x1ee0a, 0, 0, 0, g(Yes, No, false, false, "", "ك")}, - {0x1ee0b, 0, 0, 0, g(Yes, No, false, false, "", "ل")}, - {0x1ee0c, 0, 0, 0, g(Yes, No, false, false, "", "م")}, - {0x1ee0d, 0, 0, 0, g(Yes, No, false, false, "", "ن")}, - {0x1ee0e, 0, 0, 0, g(Yes, No, false, false, "", "س")}, - {0x1ee0f, 0, 0, 0, g(Yes, No, false, false, "", "ع")}, - {0x1ee10, 0, 0, 0, g(Yes, No, false, false, "", "ف")}, - {0x1ee11, 0, 0, 0, g(Yes, No, false, false, "", "ص")}, - {0x1ee12, 0, 0, 0, g(Yes, No, false, false, "", "ق")}, - {0x1ee13, 0, 0, 0, g(Yes, No, false, false, "", "ر")}, - {0x1ee14, 0, 0, 0, g(Yes, No, false, false, "", "ش")}, - {0x1ee15, 0, 0, 0, g(Yes, No, false, false, "", "ت")}, - {0x1ee16, 0, 0, 0, g(Yes, No, false, false, "", "ث")}, - {0x1ee17, 0, 0, 0, g(Yes, No, false, false, "", "خ")}, - {0x1ee18, 0, 0, 0, g(Yes, No, false, false, "", "ذ")}, - {0x1ee19, 0, 0, 0, g(Yes, No, false, false, "", "ض")}, - {0x1ee1a, 0, 0, 0, g(Yes, No, false, false, "", "ظ")}, - {0x1ee1b, 0, 0, 0, g(Yes, No, false, false, "", "غ")}, - {0x1ee1c, 0, 0, 0, g(Yes, No, false, false, "", "ٮ")}, - {0x1ee1d, 0, 0, 0, g(Yes, No, false, false, "", "ں")}, - {0x1ee1e, 0, 0, 0, g(Yes, No, false, false, "", "ڡ")}, - {0x1ee1f, 0, 0, 0, g(Yes, No, false, false, "", "ٯ")}, - {0x1ee20, 0, 0, 0, f(Yes, false, "")}, - {0x1ee21, 0, 0, 0, g(Yes, No, false, false, "", "ب")}, - {0x1ee22, 0, 0, 0, g(Yes, No, false, false, "", "ج")}, - {0x1ee23, 0, 0, 0, f(Yes, false, "")}, - {0x1ee24, 0, 0, 0, g(Yes, No, false, false, "", "ه")}, - {0x1ee25, 0, 0, 0, f(Yes, false, "")}, - {0x1ee27, 0, 0, 0, g(Yes, No, false, false, "", "ح")}, - {0x1ee28, 0, 0, 0, f(Yes, false, "")}, - {0x1ee29, 0, 0, 0, g(Yes, No, false, false, "", "ي")}, - {0x1ee2a, 0, 0, 0, g(Yes, No, false, false, "", "ك")}, - {0x1ee2b, 0, 0, 0, g(Yes, No, false, false, "", "ل")}, - {0x1ee2c, 0, 0, 0, g(Yes, No, false, false, "", "م")}, - {0x1ee2d, 0, 0, 0, g(Yes, No, false, false, "", "ن")}, - {0x1ee2e, 0, 0, 0, g(Yes, No, false, false, "", "س")}, - {0x1ee2f, 0, 0, 0, g(Yes, No, false, false, "", "ع")}, - {0x1ee30, 0, 0, 0, g(Yes, No, false, false, "", "ف")}, - {0x1ee31, 0, 0, 0, g(Yes, No, false, false, "", "ص")}, - {0x1ee32, 0, 0, 0, g(Yes, No, false, false, "", "ق")}, - {0x1ee33, 0, 0, 0, f(Yes, false, "")}, - {0x1ee34, 0, 0, 0, g(Yes, No, false, false, "", "ش")}, - {0x1ee35, 0, 0, 0, g(Yes, No, false, false, "", "ت")}, - {0x1ee36, 0, 0, 0, g(Yes, No, false, false, "", "ث")}, - {0x1ee37, 0, 0, 0, g(Yes, No, false, false, "", "خ")}, - {0x1ee38, 0, 0, 0, f(Yes, false, "")}, - {0x1ee39, 0, 0, 0, g(Yes, No, false, false, "", "ض")}, - {0x1ee3a, 0, 0, 0, f(Yes, false, "")}, - {0x1ee3b, 0, 0, 0, g(Yes, No, false, false, "", "غ")}, - {0x1ee3c, 0, 0, 0, f(Yes, false, "")}, - {0x1ee42, 0, 0, 0, g(Yes, No, false, false, "", "ج")}, - {0x1ee43, 0, 0, 0, f(Yes, false, "")}, - {0x1ee47, 0, 0, 0, g(Yes, No, false, false, "", "ح")}, - {0x1ee48, 0, 0, 0, f(Yes, false, "")}, - {0x1ee49, 0, 0, 0, g(Yes, No, false, false, "", "ي")}, - {0x1ee4a, 0, 0, 0, f(Yes, false, "")}, - {0x1ee4b, 0, 0, 0, g(Yes, No, false, false, "", "ل")}, - {0x1ee4c, 0, 0, 0, f(Yes, false, "")}, - {0x1ee4d, 0, 0, 0, g(Yes, No, false, false, "", "ن")}, - {0x1ee4e, 0, 0, 0, g(Yes, No, false, false, "", "س")}, - {0x1ee4f, 0, 0, 0, g(Yes, No, false, false, "", "ع")}, - {0x1ee50, 0, 0, 0, f(Yes, false, "")}, - {0x1ee51, 0, 0, 0, g(Yes, No, false, false, "", "ص")}, - {0x1ee52, 0, 0, 0, g(Yes, No, false, false, "", "ق")}, - {0x1ee53, 0, 0, 0, f(Yes, false, "")}, - {0x1ee54, 0, 0, 0, g(Yes, No, false, false, "", "ش")}, - {0x1ee55, 0, 0, 0, f(Yes, false, "")}, - {0x1ee57, 0, 0, 0, g(Yes, No, false, false, "", "خ")}, - {0x1ee58, 0, 0, 0, f(Yes, false, "")}, - {0x1ee59, 0, 0, 0, g(Yes, No, false, false, "", "ض")}, - {0x1ee5a, 0, 0, 0, f(Yes, false, "")}, - {0x1ee5b, 0, 0, 0, g(Yes, No, false, false, "", "غ")}, - {0x1ee5c, 0, 0, 0, f(Yes, false, "")}, - {0x1ee5d, 0, 0, 0, g(Yes, No, false, false, "", "ں")}, - {0x1ee5e, 0, 0, 0, f(Yes, false, "")}, - {0x1ee5f, 0, 0, 0, g(Yes, No, false, false, "", "ٯ")}, - {0x1ee60, 0, 0, 0, f(Yes, false, "")}, - {0x1ee61, 0, 0, 0, g(Yes, No, false, false, "", "ب")}, - {0x1ee62, 0, 0, 0, g(Yes, No, false, false, "", "ج")}, - {0x1ee63, 0, 0, 0, f(Yes, false, "")}, - {0x1ee64, 0, 0, 0, g(Yes, No, false, false, "", "ه")}, - {0x1ee65, 0, 0, 0, f(Yes, false, "")}, - {0x1ee67, 0, 0, 0, g(Yes, No, false, false, "", "ح")}, - {0x1ee68, 0, 0, 0, g(Yes, No, false, false, "", "ط")}, - {0x1ee69, 0, 0, 0, g(Yes, No, false, false, "", "ي")}, - {0x1ee6a, 0, 0, 0, g(Yes, No, false, false, "", "ك")}, - {0x1ee6b, 0, 0, 0, f(Yes, false, "")}, - {0x1ee6c, 0, 0, 0, g(Yes, No, false, false, "", "م")}, - {0x1ee6d, 0, 0, 0, g(Yes, No, false, false, "", "ن")}, - {0x1ee6e, 0, 0, 0, g(Yes, No, false, false, "", "س")}, - {0x1ee6f, 0, 0, 0, g(Yes, No, false, false, "", "ع")}, - {0x1ee70, 0, 0, 0, g(Yes, No, false, false, "", "ف")}, - {0x1ee71, 0, 0, 0, g(Yes, No, false, false, "", "ص")}, - {0x1ee72, 0, 0, 0, g(Yes, No, false, false, "", "ق")}, - {0x1ee73, 0, 0, 0, f(Yes, false, "")}, - {0x1ee74, 0, 0, 0, g(Yes, No, false, false, "", "ش")}, - {0x1ee75, 0, 0, 0, g(Yes, No, false, false, "", "ت")}, - {0x1ee76, 0, 0, 0, g(Yes, No, false, false, "", "ث")}, - {0x1ee77, 0, 0, 0, g(Yes, No, false, false, "", "خ")}, - {0x1ee78, 0, 0, 0, f(Yes, false, "")}, - {0x1ee79, 0, 0, 0, g(Yes, No, false, false, "", "ض")}, - {0x1ee7a, 0, 0, 0, g(Yes, No, false, false, "", "ظ")}, - {0x1ee7b, 0, 0, 0, g(Yes, No, false, false, "", "غ")}, - {0x1ee7c, 0, 0, 0, g(Yes, No, false, false, "", "ٮ")}, - {0x1ee7d, 0, 0, 0, f(Yes, false, "")}, - {0x1ee7e, 0, 0, 0, g(Yes, No, false, false, "", "ڡ")}, - {0x1ee7f, 0, 0, 0, f(Yes, false, "")}, - {0x1ee80, 0, 0, 0, g(Yes, No, false, false, "", "ا")}, - {0x1ee81, 0, 0, 0, g(Yes, No, false, false, "", "ب")}, - {0x1ee82, 0, 0, 0, g(Yes, No, false, false, "", "ج")}, - {0x1ee83, 0, 0, 0, g(Yes, No, false, false, "", "د")}, - {0x1ee84, 0, 0, 0, g(Yes, No, false, false, "", "ه")}, - {0x1ee85, 0, 0, 0, g(Yes, No, false, false, "", "و")}, - {0x1ee86, 0, 0, 0, g(Yes, No, false, false, "", "ز")}, - {0x1ee87, 0, 0, 0, g(Yes, No, false, false, "", "ح")}, - {0x1ee88, 0, 0, 0, g(Yes, No, false, false, "", "ط")}, - {0x1ee89, 0, 0, 0, g(Yes, No, false, false, "", "ي")}, - {0x1ee8a, 0, 0, 0, f(Yes, false, "")}, - {0x1ee8b, 0, 0, 0, g(Yes, No, false, false, "", "ل")}, - {0x1ee8c, 0, 0, 0, g(Yes, No, false, false, "", "م")}, - {0x1ee8d, 0, 0, 0, g(Yes, No, false, false, "", "ن")}, - {0x1ee8e, 0, 0, 0, g(Yes, No, false, false, "", "س")}, - {0x1ee8f, 0, 0, 0, g(Yes, No, false, false, "", "ع")}, - {0x1ee90, 0, 0, 0, g(Yes, No, false, false, "", "ف")}, - {0x1ee91, 0, 0, 0, g(Yes, No, false, false, "", "ص")}, - {0x1ee92, 0, 0, 0, g(Yes, No, false, false, "", "ق")}, - {0x1ee93, 0, 0, 0, g(Yes, No, false, false, "", "ر")}, - {0x1ee94, 0, 0, 0, g(Yes, No, false, false, "", "ش")}, - {0x1ee95, 0, 0, 0, g(Yes, No, false, false, "", "ت")}, - {0x1ee96, 0, 0, 0, g(Yes, No, false, false, "", "ث")}, - {0x1ee97, 0, 0, 0, g(Yes, No, false, false, "", "خ")}, - {0x1ee98, 0, 0, 0, g(Yes, No, false, false, "", "ذ")}, - {0x1ee99, 0, 0, 0, g(Yes, No, false, false, "", "ض")}, - {0x1ee9a, 0, 0, 0, g(Yes, No, false, false, "", "ظ")}, - {0x1ee9b, 0, 0, 0, g(Yes, No, false, false, "", "غ")}, - {0x1ee9c, 0, 0, 0, f(Yes, false, "")}, - {0x1eea1, 0, 0, 0, g(Yes, No, false, false, "", "ب")}, - {0x1eea2, 0, 0, 0, g(Yes, No, false, false, "", "ج")}, - {0x1eea3, 0, 0, 0, g(Yes, No, false, false, "", "د")}, - {0x1eea4, 0, 0, 0, f(Yes, false, "")}, - {0x1eea5, 0, 0, 0, g(Yes, No, false, false, "", "و")}, - {0x1eea6, 0, 0, 0, g(Yes, No, false, false, "", "ز")}, - {0x1eea7, 0, 0, 0, g(Yes, No, false, false, "", "ح")}, - {0x1eea8, 0, 0, 0, g(Yes, No, false, false, "", "ط")}, - {0x1eea9, 0, 0, 0, g(Yes, No, false, false, "", "ي")}, - {0x1eeaa, 0, 0, 0, f(Yes, false, "")}, - {0x1eeab, 0, 0, 0, g(Yes, No, false, false, "", "ل")}, - {0x1eeac, 0, 0, 0, g(Yes, No, false, false, "", "م")}, - {0x1eead, 0, 0, 0, g(Yes, No, false, false, "", "ن")}, - {0x1eeae, 0, 0, 0, g(Yes, No, false, false, "", "س")}, - {0x1eeaf, 0, 0, 0, g(Yes, No, false, false, "", "ع")}, - {0x1eeb0, 0, 0, 0, g(Yes, No, false, false, "", "ف")}, - {0x1eeb1, 0, 0, 0, g(Yes, No, false, false, "", "ص")}, - {0x1eeb2, 0, 0, 0, g(Yes, No, false, false, "", "ق")}, - {0x1eeb3, 0, 0, 0, g(Yes, No, false, false, "", "ر")}, - {0x1eeb4, 0, 0, 0, g(Yes, No, false, false, "", "ش")}, - {0x1eeb5, 0, 0, 0, g(Yes, No, false, false, "", "ت")}, - {0x1eeb6, 0, 0, 0, g(Yes, No, false, false, "", "ث")}, - {0x1eeb7, 0, 0, 0, g(Yes, No, false, false, "", "خ")}, - {0x1eeb8, 0, 0, 0, g(Yes, No, false, false, "", "ذ")}, - {0x1eeb9, 0, 0, 0, g(Yes, No, false, false, "", "ض")}, - {0x1eeba, 0, 0, 0, g(Yes, No, false, false, "", "ظ")}, - {0x1eebb, 0, 0, 0, g(Yes, No, false, false, "", "غ")}, - {0x1eebc, 0, 0, 0, f(Yes, false, "")}, - {0x1f100, 0, 0, 0, g(Yes, No, false, false, "", "0.")}, - {0x1f101, 0, 0, 0, g(Yes, No, false, false, "", "0,")}, - {0x1f102, 0, 0, 0, g(Yes, No, false, false, "", "1,")}, - {0x1f103, 0, 0, 0, g(Yes, No, false, false, "", "2,")}, - {0x1f104, 0, 0, 0, g(Yes, No, false, false, "", "3,")}, - {0x1f105, 0, 0, 0, g(Yes, No, false, false, "", "4,")}, - {0x1f106, 0, 0, 0, g(Yes, No, false, false, "", "5,")}, - {0x1f107, 0, 0, 0, g(Yes, No, false, false, "", "6,")}, - {0x1f108, 0, 0, 0, g(Yes, No, false, false, "", "7,")}, - {0x1f109, 0, 0, 0, g(Yes, No, false, false, "", "8,")}, - {0x1f10a, 0, 0, 0, g(Yes, No, false, false, "", "9,")}, - {0x1f10b, 0, 0, 0, f(Yes, false, "")}, - {0x1f110, 0, 0, 0, g(Yes, No, false, false, "", "(A)")}, - {0x1f111, 0, 0, 0, g(Yes, No, false, false, "", "(B)")}, - {0x1f112, 0, 0, 0, g(Yes, No, false, false, "", "(C)")}, - {0x1f113, 0, 0, 0, g(Yes, No, false, false, "", "(D)")}, - {0x1f114, 0, 0, 0, g(Yes, No, false, false, "", "(E)")}, - {0x1f115, 0, 0, 0, g(Yes, No, false, false, "", "(F)")}, - {0x1f116, 0, 0, 0, g(Yes, No, false, false, "", "(G)")}, - {0x1f117, 0, 0, 0, g(Yes, No, false, false, "", "(H)")}, - {0x1f118, 0, 0, 0, g(Yes, No, false, false, "", "(I)")}, - {0x1f119, 0, 0, 0, g(Yes, No, false, false, "", "(J)")}, - {0x1f11a, 0, 0, 0, g(Yes, No, false, false, "", "(K)")}, - {0x1f11b, 0, 0, 0, g(Yes, No, false, false, "", "(L)")}, - {0x1f11c, 0, 0, 0, g(Yes, No, false, false, "", "(M)")}, - {0x1f11d, 0, 0, 0, g(Yes, No, false, false, "", "(N)")}, - {0x1f11e, 0, 0, 0, g(Yes, No, false, false, "", "(O)")}, - {0x1f11f, 0, 0, 0, g(Yes, No, false, false, "", "(P)")}, - {0x1f120, 0, 0, 0, g(Yes, No, false, false, "", "(Q)")}, - {0x1f121, 0, 0, 0, g(Yes, No, false, false, "", "(R)")}, - {0x1f122, 0, 0, 0, g(Yes, No, false, false, "", "(S)")}, - {0x1f123, 0, 0, 0, g(Yes, No, false, false, "", "(T)")}, - {0x1f124, 0, 0, 0, g(Yes, No, false, false, "", "(U)")}, - {0x1f125, 0, 0, 0, g(Yes, No, false, false, "", "(V)")}, - {0x1f126, 0, 0, 0, g(Yes, No, false, false, "", "(W)")}, - {0x1f127, 0, 0, 0, g(Yes, No, false, false, "", "(X)")}, - {0x1f128, 0, 0, 0, g(Yes, No, false, false, "", "(Y)")}, - {0x1f129, 0, 0, 0, g(Yes, No, false, false, "", "(Z)")}, - {0x1f12a, 0, 0, 0, g(Yes, No, false, false, "", "〔S〕")}, - {0x1f12b, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x1f12c, 0, 0, 0, g(Yes, No, false, false, "", "R")}, - {0x1f12d, 0, 0, 0, g(Yes, No, false, false, "", "CD")}, - {0x1f12e, 0, 0, 0, g(Yes, No, false, false, "", "WZ")}, - {0x1f12f, 0, 0, 0, f(Yes, false, "")}, - {0x1f130, 0, 0, 0, g(Yes, No, false, false, "", "A")}, - {0x1f131, 0, 0, 0, g(Yes, No, false, false, "", "B")}, - {0x1f132, 0, 0, 0, g(Yes, No, false, false, "", "C")}, - {0x1f133, 0, 0, 0, g(Yes, No, false, false, "", "D")}, - {0x1f134, 0, 0, 0, g(Yes, No, false, false, "", "E")}, - {0x1f135, 0, 0, 0, g(Yes, No, false, false, "", "F")}, - {0x1f136, 0, 0, 0, g(Yes, No, false, false, "", "G")}, - {0x1f137, 0, 0, 0, g(Yes, No, false, false, "", "H")}, - {0x1f138, 0, 0, 0, g(Yes, No, false, false, "", "I")}, - {0x1f139, 0, 0, 0, g(Yes, No, false, false, "", "J")}, - {0x1f13a, 0, 0, 0, g(Yes, No, false, false, "", "K")}, - {0x1f13b, 0, 0, 0, g(Yes, No, false, false, "", "L")}, - {0x1f13c, 0, 0, 0, g(Yes, No, false, false, "", "M")}, - {0x1f13d, 0, 0, 0, g(Yes, No, false, false, "", "N")}, - {0x1f13e, 0, 0, 0, g(Yes, No, false, false, "", "O")}, - {0x1f13f, 0, 0, 0, g(Yes, No, false, false, "", "P")}, - {0x1f140, 0, 0, 0, g(Yes, No, false, false, "", "Q")}, - {0x1f141, 0, 0, 0, g(Yes, No, false, false, "", "R")}, - {0x1f142, 0, 0, 0, g(Yes, No, false, false, "", "S")}, - {0x1f143, 0, 0, 0, g(Yes, No, false, false, "", "T")}, - {0x1f144, 0, 0, 0, g(Yes, No, false, false, "", "U")}, - {0x1f145, 0, 0, 0, g(Yes, No, false, false, "", "V")}, - {0x1f146, 0, 0, 0, g(Yes, No, false, false, "", "W")}, - {0x1f147, 0, 0, 0, g(Yes, No, false, false, "", "X")}, - {0x1f148, 0, 0, 0, g(Yes, No, false, false, "", "Y")}, - {0x1f149, 0, 0, 0, g(Yes, No, false, false, "", "Z")}, - {0x1f14a, 0, 0, 0, g(Yes, No, false, false, "", "HV")}, - {0x1f14b, 0, 0, 0, g(Yes, No, false, false, "", "MV")}, - {0x1f14c, 0, 0, 0, g(Yes, No, false, false, "", "SD")}, - {0x1f14d, 0, 0, 0, g(Yes, No, false, false, "", "SS")}, - {0x1f14e, 0, 0, 0, g(Yes, No, false, false, "", "PPV")}, - {0x1f14f, 0, 0, 0, g(Yes, No, false, false, "", "WC")}, - {0x1f150, 0, 0, 0, f(Yes, false, "")}, - {0x1f16a, 0, 0, 0, g(Yes, No, false, false, "", "MC")}, - {0x1f16b, 0, 0, 0, g(Yes, No, false, false, "", "MD")}, - {0x1f16c, 0, 0, 0, f(Yes, false, "")}, - {0x1f190, 0, 0, 0, g(Yes, No, false, false, "", "DJ")}, - {0x1f191, 0, 0, 0, f(Yes, false, "")}, - {0x1f200, 0, 0, 0, g(Yes, No, false, false, "", "ほか")}, - {0x1f201, 0, 0, 0, g(Yes, No, false, false, "", "ココ")}, - {0x1f202, 0, 0, 0, g(Yes, No, false, false, "", "サ")}, - {0x1f203, 0, 0, 0, f(Yes, false, "")}, - {0x1f210, 0, 0, 0, g(Yes, No, false, false, "", "手")}, - {0x1f211, 0, 0, 0, g(Yes, No, false, false, "", "字")}, - {0x1f212, 0, 0, 0, g(Yes, No, false, false, "", "双")}, - {0x1f213, 0, 0, 1, g(Yes, No, false, false, "", "デ")}, - {0x1f214, 0, 0, 0, g(Yes, No, false, false, "", "二")}, - {0x1f215, 0, 0, 0, g(Yes, No, false, false, "", "多")}, - {0x1f216, 0, 0, 0, g(Yes, No, false, false, "", "解")}, - {0x1f217, 0, 0, 0, g(Yes, No, false, false, "", "天")}, - {0x1f218, 0, 0, 0, g(Yes, No, false, false, "", "交")}, - {0x1f219, 0, 0, 0, g(Yes, No, false, false, "", "映")}, - {0x1f21a, 0, 0, 0, g(Yes, No, false, false, "", "無")}, - {0x1f21b, 0, 0, 0, g(Yes, No, false, false, "", "料")}, - {0x1f21c, 0, 0, 0, g(Yes, No, false, false, "", "前")}, - {0x1f21d, 0, 0, 0, g(Yes, No, false, false, "", "後")}, - {0x1f21e, 0, 0, 0, g(Yes, No, false, false, "", "再")}, - {0x1f21f, 0, 0, 0, g(Yes, No, false, false, "", "新")}, - {0x1f220, 0, 0, 0, g(Yes, No, false, false, "", "初")}, - {0x1f221, 0, 0, 0, g(Yes, No, false, false, "", "終")}, - {0x1f222, 0, 0, 0, g(Yes, No, false, false, "", "生")}, - {0x1f223, 0, 0, 0, g(Yes, No, false, false, "", "販")}, - {0x1f224, 0, 0, 0, g(Yes, No, false, false, "", "声")}, - {0x1f225, 0, 0, 0, g(Yes, No, false, false, "", "吹")}, - {0x1f226, 0, 0, 0, g(Yes, No, false, false, "", "演")}, - {0x1f227, 0, 0, 0, g(Yes, No, false, false, "", "投")}, - {0x1f228, 0, 0, 0, g(Yes, No, false, false, "", "捕")}, - {0x1f229, 0, 0, 0, g(Yes, No, false, false, "", "一")}, - {0x1f22a, 0, 0, 0, g(Yes, No, false, false, "", "三")}, - {0x1f22b, 0, 0, 0, g(Yes, No, false, false, "", "遊")}, - {0x1f22c, 0, 0, 0, g(Yes, No, false, false, "", "左")}, - {0x1f22d, 0, 0, 0, g(Yes, No, false, false, "", "中")}, - {0x1f22e, 0, 0, 0, g(Yes, No, false, false, "", "右")}, - {0x1f22f, 0, 0, 0, g(Yes, No, false, false, "", "指")}, - {0x1f230, 0, 0, 0, g(Yes, No, false, false, "", "走")}, - {0x1f231, 0, 0, 0, g(Yes, No, false, false, "", "打")}, - {0x1f232, 0, 0, 0, g(Yes, No, false, false, "", "禁")}, - {0x1f233, 0, 0, 0, g(Yes, No, false, false, "", "空")}, - {0x1f234, 0, 0, 0, g(Yes, No, false, false, "", "合")}, - {0x1f235, 0, 0, 0, g(Yes, No, false, false, "", "満")}, - {0x1f236, 0, 0, 0, g(Yes, No, false, false, "", "有")}, - {0x1f237, 0, 0, 0, g(Yes, No, false, false, "", "月")}, - {0x1f238, 0, 0, 0, g(Yes, No, false, false, "", "申")}, - {0x1f239, 0, 0, 0, g(Yes, No, false, false, "", "割")}, - {0x1f23a, 0, 0, 0, g(Yes, No, false, false, "", "営")}, - {0x1f23b, 0, 0, 0, g(Yes, No, false, false, "", "配")}, - {0x1f23c, 0, 0, 0, f(Yes, false, "")}, - {0x1f240, 0, 0, 0, g(Yes, No, false, false, "", "〔本〕")}, - {0x1f241, 0, 0, 0, g(Yes, No, false, false, "", "〔三〕")}, - {0x1f242, 0, 0, 0, g(Yes, No, false, false, "", "〔二〕")}, - {0x1f243, 0, 0, 0, g(Yes, No, false, false, "", "〔安〕")}, - {0x1f244, 0, 0, 0, g(Yes, No, false, false, "", "〔点〕")}, - {0x1f245, 0, 0, 0, g(Yes, No, false, false, "", "〔打〕")}, - {0x1f246, 0, 0, 0, g(Yes, No, false, false, "", "〔盗〕")}, - {0x1f247, 0, 0, 0, g(Yes, No, false, false, "", "〔勝〕")}, - {0x1f248, 0, 0, 0, g(Yes, No, false, false, "", "〔敗〕")}, - {0x1f249, 0, 0, 0, f(Yes, false, "")}, - {0x1f250, 0, 0, 0, g(Yes, No, false, false, "", "得")}, - {0x1f251, 0, 0, 0, g(Yes, No, false, false, "", "可")}, - {0x1f252, 0, 0, 0, f(Yes, false, "")}, - {0x2f800, 0, 0, 0, f(No, false, "丽")}, - {0x2f801, 0, 0, 0, f(No, false, "丸")}, - {0x2f802, 0, 0, 0, f(No, false, "乁")}, - {0x2f803, 0, 0, 0, f(No, false, "𠄢")}, - {0x2f804, 0, 0, 0, f(No, false, "你")}, - {0x2f805, 0, 0, 0, f(No, false, "侮")}, - {0x2f806, 0, 0, 0, f(No, false, "侻")}, - {0x2f807, 0, 0, 0, f(No, false, "倂")}, - {0x2f808, 0, 0, 0, f(No, false, "偺")}, - {0x2f809, 0, 0, 0, f(No, false, "備")}, - {0x2f80a, 0, 0, 0, f(No, false, "僧")}, - {0x2f80b, 0, 0, 0, f(No, false, "像")}, - {0x2f80c, 0, 0, 0, f(No, false, "㒞")}, - {0x2f80d, 0, 0, 0, f(No, false, "𠘺")}, - {0x2f80e, 0, 0, 0, f(No, false, "免")}, - {0x2f80f, 0, 0, 0, f(No, false, "兔")}, - {0x2f810, 0, 0, 0, f(No, false, "兤")}, - {0x2f811, 0, 0, 0, f(No, false, "具")}, - {0x2f812, 0, 0, 0, f(No, false, "𠔜")}, - {0x2f813, 0, 0, 0, f(No, false, "㒹")}, - {0x2f814, 0, 0, 0, f(No, false, "內")}, - {0x2f815, 0, 0, 0, f(No, false, "再")}, - {0x2f816, 0, 0, 0, f(No, false, "𠕋")}, - {0x2f817, 0, 0, 0, f(No, false, "冗")}, - {0x2f818, 0, 0, 0, f(No, false, "冤")}, - {0x2f819, 0, 0, 0, f(No, false, "仌")}, - {0x2f81a, 0, 0, 0, f(No, false, "冬")}, - {0x2f81b, 0, 0, 0, f(No, false, "况")}, - {0x2f81c, 0, 0, 0, f(No, false, "𩇟")}, - {0x2f81d, 0, 0, 0, f(No, false, "凵")}, - {0x2f81e, 0, 0, 0, f(No, false, "刃")}, - {0x2f81f, 0, 0, 0, f(No, false, "㓟")}, - {0x2f820, 0, 0, 0, f(No, false, "刻")}, - {0x2f821, 0, 0, 0, f(No, false, "剆")}, - {0x2f822, 0, 0, 0, f(No, false, "割")}, - {0x2f823, 0, 0, 0, f(No, false, "剷")}, - {0x2f824, 0, 0, 0, f(No, false, "㔕")}, - {0x2f825, 0, 0, 0, f(No, false, "勇")}, - {0x2f826, 0, 0, 0, f(No, false, "勉")}, - {0x2f827, 0, 0, 0, f(No, false, "勤")}, - {0x2f828, 0, 0, 0, f(No, false, "勺")}, - {0x2f829, 0, 0, 0, f(No, false, "包")}, - {0x2f82a, 0, 0, 0, f(No, false, "匆")}, - {0x2f82b, 0, 0, 0, f(No, false, "北")}, - {0x2f82c, 0, 0, 0, f(No, false, "卉")}, - {0x2f82d, 0, 0, 0, f(No, false, "卑")}, - {0x2f82e, 0, 0, 0, f(No, false, "博")}, - {0x2f82f, 0, 0, 0, f(No, false, "即")}, - {0x2f830, 0, 0, 0, f(No, false, "卽")}, - {0x2f831, 0, 0, 0, f(No, false, "卿")}, - {0x2f834, 0, 0, 0, f(No, false, "𠨬")}, - {0x2f835, 0, 0, 0, f(No, false, "灰")}, - {0x2f836, 0, 0, 0, f(No, false, "及")}, - {0x2f837, 0, 0, 0, f(No, false, "叟")}, - {0x2f838, 0, 0, 0, f(No, false, "𠭣")}, - {0x2f839, 0, 0, 0, f(No, false, "叫")}, - {0x2f83a, 0, 0, 0, f(No, false, "叱")}, - {0x2f83b, 0, 0, 0, f(No, false, "吆")}, - {0x2f83c, 0, 0, 0, f(No, false, "咞")}, - {0x2f83d, 0, 0, 0, f(No, false, "吸")}, - {0x2f83e, 0, 0, 0, f(No, false, "呈")}, - {0x2f83f, 0, 0, 0, f(No, false, "周")}, - {0x2f840, 0, 0, 0, f(No, false, "咢")}, - {0x2f841, 0, 0, 0, f(No, false, "哶")}, - {0x2f842, 0, 0, 0, f(No, false, "唐")}, - {0x2f843, 0, 0, 0, f(No, false, "啓")}, - {0x2f844, 0, 0, 0, f(No, false, "啣")}, - {0x2f845, 0, 0, 0, f(No, false, "善")}, - {0x2f847, 0, 0, 0, f(No, false, "喙")}, - {0x2f848, 0, 0, 0, f(No, false, "喫")}, - {0x2f849, 0, 0, 0, f(No, false, "喳")}, - {0x2f84a, 0, 0, 0, f(No, false, "嗂")}, - {0x2f84b, 0, 0, 0, f(No, false, "圖")}, - {0x2f84c, 0, 0, 0, f(No, false, "嘆")}, - {0x2f84d, 0, 0, 0, f(No, false, "圗")}, - {0x2f84e, 0, 0, 0, f(No, false, "噑")}, - {0x2f84f, 0, 0, 0, f(No, false, "噴")}, - {0x2f850, 0, 0, 0, f(No, false, "切")}, - {0x2f851, 0, 0, 0, f(No, false, "壮")}, - {0x2f852, 0, 0, 0, f(No, false, "城")}, - {0x2f853, 0, 0, 0, f(No, false, "埴")}, - {0x2f854, 0, 0, 0, f(No, false, "堍")}, - {0x2f855, 0, 0, 0, f(No, false, "型")}, - {0x2f856, 0, 0, 0, f(No, false, "堲")}, - {0x2f857, 0, 0, 0, f(No, false, "報")}, - {0x2f858, 0, 0, 0, f(No, false, "墬")}, - {0x2f859, 0, 0, 0, f(No, false, "𡓤")}, - {0x2f85a, 0, 0, 0, f(No, false, "売")}, - {0x2f85b, 0, 0, 0, f(No, false, "壷")}, - {0x2f85c, 0, 0, 0, f(No, false, "夆")}, - {0x2f85d, 0, 0, 0, f(No, false, "多")}, - {0x2f85e, 0, 0, 0, f(No, false, "夢")}, - {0x2f85f, 0, 0, 0, f(No, false, "奢")}, - {0x2f860, 0, 0, 0, f(No, false, "𡚨")}, - {0x2f861, 0, 0, 0, f(No, false, "𡛪")}, - {0x2f862, 0, 0, 0, f(No, false, "姬")}, - {0x2f863, 0, 0, 0, f(No, false, "娛")}, - {0x2f864, 0, 0, 0, f(No, false, "娧")}, - {0x2f865, 0, 0, 0, f(No, false, "姘")}, - {0x2f866, 0, 0, 0, f(No, false, "婦")}, - {0x2f867, 0, 0, 0, f(No, false, "㛮")}, - {0x2f868, 0, 0, 0, f(No, false, "㛼")}, - {0x2f869, 0, 0, 0, f(No, false, "嬈")}, - {0x2f86a, 0, 0, 0, f(No, false, "嬾")}, - {0x2f86c, 0, 0, 0, f(No, false, "𡧈")}, - {0x2f86d, 0, 0, 0, f(No, false, "寃")}, - {0x2f86e, 0, 0, 0, f(No, false, "寘")}, - {0x2f86f, 0, 0, 0, f(No, false, "寧")}, - {0x2f870, 0, 0, 0, f(No, false, "寳")}, - {0x2f871, 0, 0, 0, f(No, false, "𡬘")}, - {0x2f872, 0, 0, 0, f(No, false, "寿")}, - {0x2f873, 0, 0, 0, f(No, false, "将")}, - {0x2f874, 0, 0, 0, f(No, false, "当")}, - {0x2f875, 0, 0, 0, f(No, false, "尢")}, - {0x2f876, 0, 0, 0, f(No, false, "㞁")}, - {0x2f877, 0, 0, 0, f(No, false, "屠")}, - {0x2f878, 0, 0, 0, f(No, false, "屮")}, - {0x2f879, 0, 0, 0, f(No, false, "峀")}, - {0x2f87a, 0, 0, 0, f(No, false, "岍")}, - {0x2f87b, 0, 0, 0, f(No, false, "𡷤")}, - {0x2f87c, 0, 0, 0, f(No, false, "嵃")}, - {0x2f87d, 0, 0, 0, f(No, false, "𡷦")}, - {0x2f87e, 0, 0, 0, f(No, false, "嵮")}, - {0x2f87f, 0, 0, 0, f(No, false, "嵫")}, - {0x2f880, 0, 0, 0, f(No, false, "嵼")}, - {0x2f881, 0, 0, 0, f(No, false, "巡")}, - {0x2f882, 0, 0, 0, f(No, false, "巢")}, - {0x2f883, 0, 0, 0, f(No, false, "㠯")}, - {0x2f884, 0, 0, 0, f(No, false, "巽")}, - {0x2f885, 0, 0, 0, f(No, false, "帨")}, - {0x2f886, 0, 0, 0, f(No, false, "帽")}, - {0x2f887, 0, 0, 0, f(No, false, "幩")}, - {0x2f888, 0, 0, 0, f(No, false, "㡢")}, - {0x2f889, 0, 0, 0, f(No, false, "𢆃")}, - {0x2f88a, 0, 0, 0, f(No, false, "㡼")}, - {0x2f88b, 0, 0, 0, f(No, false, "庰")}, - {0x2f88c, 0, 0, 0, f(No, false, "庳")}, - {0x2f88d, 0, 0, 0, f(No, false, "庶")}, - {0x2f88e, 0, 0, 0, f(No, false, "廊")}, - {0x2f88f, 0, 0, 0, f(No, false, "𪎒")}, - {0x2f890, 0, 0, 0, f(No, false, "廾")}, - {0x2f891, 0, 0, 0, f(No, false, "𢌱")}, - {0x2f893, 0, 0, 0, f(No, false, "舁")}, - {0x2f894, 0, 0, 0, f(No, false, "弢")}, - {0x2f896, 0, 0, 0, f(No, false, "㣇")}, - {0x2f897, 0, 0, 0, f(No, false, "𣊸")}, - {0x2f898, 0, 0, 0, f(No, false, "𦇚")}, - {0x2f899, 0, 0, 0, f(No, false, "形")}, - {0x2f89a, 0, 0, 0, f(No, false, "彫")}, - {0x2f89b, 0, 0, 0, f(No, false, "㣣")}, - {0x2f89c, 0, 0, 0, f(No, false, "徚")}, - {0x2f89d, 0, 0, 0, f(No, false, "忍")}, - {0x2f89e, 0, 0, 0, f(No, false, "志")}, - {0x2f89f, 0, 0, 0, f(No, false, "忹")}, - {0x2f8a0, 0, 0, 0, f(No, false, "悁")}, - {0x2f8a1, 0, 0, 0, f(No, false, "㤺")}, - {0x2f8a2, 0, 0, 0, f(No, false, "㤜")}, - {0x2f8a3, 0, 0, 0, f(No, false, "悔")}, - {0x2f8a4, 0, 0, 0, f(No, false, "𢛔")}, - {0x2f8a5, 0, 0, 0, f(No, false, "惇")}, - {0x2f8a6, 0, 0, 0, f(No, false, "慈")}, - {0x2f8a7, 0, 0, 0, f(No, false, "慌")}, - {0x2f8a8, 0, 0, 0, f(No, false, "慎")}, - {0x2f8a9, 0, 0, 0, f(No, false, "慌")}, - {0x2f8aa, 0, 0, 0, f(No, false, "慺")}, - {0x2f8ab, 0, 0, 0, f(No, false, "憎")}, - {0x2f8ac, 0, 0, 0, f(No, false, "憲")}, - {0x2f8ad, 0, 0, 0, f(No, false, "憤")}, - {0x2f8ae, 0, 0, 0, f(No, false, "憯")}, - {0x2f8af, 0, 0, 0, f(No, false, "懞")}, - {0x2f8b0, 0, 0, 0, f(No, false, "懲")}, - {0x2f8b1, 0, 0, 0, f(No, false, "懶")}, - {0x2f8b2, 0, 0, 0, f(No, false, "成")}, - {0x2f8b3, 0, 0, 0, f(No, false, "戛")}, - {0x2f8b4, 0, 0, 0, f(No, false, "扝")}, - {0x2f8b5, 0, 0, 0, f(No, false, "抱")}, - {0x2f8b6, 0, 0, 0, f(No, false, "拔")}, - {0x2f8b7, 0, 0, 0, f(No, false, "捐")}, - {0x2f8b8, 0, 0, 0, f(No, false, "𢬌")}, - {0x2f8b9, 0, 0, 0, f(No, false, "挽")}, - {0x2f8ba, 0, 0, 0, f(No, false, "拼")}, - {0x2f8bb, 0, 0, 0, f(No, false, "捨")}, - {0x2f8bc, 0, 0, 0, f(No, false, "掃")}, - {0x2f8bd, 0, 0, 0, f(No, false, "揤")}, - {0x2f8be, 0, 0, 0, f(No, false, "𢯱")}, - {0x2f8bf, 0, 0, 0, f(No, false, "搢")}, - {0x2f8c0, 0, 0, 0, f(No, false, "揅")}, - {0x2f8c1, 0, 0, 0, f(No, false, "掩")}, - {0x2f8c2, 0, 0, 0, f(No, false, "㨮")}, - {0x2f8c3, 0, 0, 0, f(No, false, "摩")}, - {0x2f8c4, 0, 0, 0, f(No, false, "摾")}, - {0x2f8c5, 0, 0, 0, f(No, false, "撝")}, - {0x2f8c6, 0, 0, 0, f(No, false, "摷")}, - {0x2f8c7, 0, 0, 0, f(No, false, "㩬")}, - {0x2f8c8, 0, 0, 0, f(No, false, "敏")}, - {0x2f8c9, 0, 0, 0, f(No, false, "敬")}, - {0x2f8ca, 0, 0, 0, f(No, false, "𣀊")}, - {0x2f8cb, 0, 0, 0, f(No, false, "旣")}, - {0x2f8cc, 0, 0, 0, f(No, false, "書")}, - {0x2f8cd, 0, 0, 0, f(No, false, "晉")}, - {0x2f8ce, 0, 0, 0, f(No, false, "㬙")}, - {0x2f8cf, 0, 0, 0, f(No, false, "暑")}, - {0x2f8d0, 0, 0, 0, f(No, false, "㬈")}, - {0x2f8d1, 0, 0, 0, f(No, false, "㫤")}, - {0x2f8d2, 0, 0, 0, f(No, false, "冒")}, - {0x2f8d3, 0, 0, 0, f(No, false, "冕")}, - {0x2f8d4, 0, 0, 0, f(No, false, "最")}, - {0x2f8d5, 0, 0, 0, f(No, false, "暜")}, - {0x2f8d6, 0, 0, 0, f(No, false, "肭")}, - {0x2f8d7, 0, 0, 0, f(No, false, "䏙")}, - {0x2f8d8, 0, 0, 0, f(No, false, "朗")}, - {0x2f8d9, 0, 0, 0, f(No, false, "望")}, - {0x2f8da, 0, 0, 0, f(No, false, "朡")}, - {0x2f8db, 0, 0, 0, f(No, false, "杞")}, - {0x2f8dc, 0, 0, 0, f(No, false, "杓")}, - {0x2f8dd, 0, 0, 0, f(No, false, "𣏃")}, - {0x2f8de, 0, 0, 0, f(No, false, "㭉")}, - {0x2f8df, 0, 0, 0, f(No, false, "柺")}, - {0x2f8e0, 0, 0, 0, f(No, false, "枅")}, - {0x2f8e1, 0, 0, 0, f(No, false, "桒")}, - {0x2f8e2, 0, 0, 0, f(No, false, "梅")}, - {0x2f8e3, 0, 0, 0, f(No, false, "𣑭")}, - {0x2f8e4, 0, 0, 0, f(No, false, "梎")}, - {0x2f8e5, 0, 0, 0, f(No, false, "栟")}, - {0x2f8e6, 0, 0, 0, f(No, false, "椔")}, - {0x2f8e7, 0, 0, 0, f(No, false, "㮝")}, - {0x2f8e8, 0, 0, 0, f(No, false, "楂")}, - {0x2f8e9, 0, 0, 0, f(No, false, "榣")}, - {0x2f8ea, 0, 0, 0, f(No, false, "槪")}, - {0x2f8eb, 0, 0, 0, f(No, false, "檨")}, - {0x2f8ec, 0, 0, 0, f(No, false, "𣚣")}, - {0x2f8ed, 0, 0, 0, f(No, false, "櫛")}, - {0x2f8ee, 0, 0, 0, f(No, false, "㰘")}, - {0x2f8ef, 0, 0, 0, f(No, false, "次")}, - {0x2f8f0, 0, 0, 0, f(No, false, "𣢧")}, - {0x2f8f1, 0, 0, 0, f(No, false, "歔")}, - {0x2f8f2, 0, 0, 0, f(No, false, "㱎")}, - {0x2f8f3, 0, 0, 0, f(No, false, "歲")}, - {0x2f8f4, 0, 0, 0, f(No, false, "殟")}, - {0x2f8f5, 0, 0, 0, f(No, false, "殺")}, - {0x2f8f6, 0, 0, 0, f(No, false, "殻")}, - {0x2f8f7, 0, 0, 0, f(No, false, "𣪍")}, - {0x2f8f8, 0, 0, 0, f(No, false, "𡴋")}, - {0x2f8f9, 0, 0, 0, f(No, false, "𣫺")}, - {0x2f8fa, 0, 0, 0, f(No, false, "汎")}, - {0x2f8fb, 0, 0, 0, f(No, false, "𣲼")}, - {0x2f8fc, 0, 0, 0, f(No, false, "沿")}, - {0x2f8fd, 0, 0, 0, f(No, false, "泍")}, - {0x2f8fe, 0, 0, 0, f(No, false, "汧")}, - {0x2f8ff, 0, 0, 0, f(No, false, "洖")}, - {0x2f900, 0, 0, 0, f(No, false, "派")}, - {0x2f901, 0, 0, 0, f(No, false, "海")}, - {0x2f902, 0, 0, 0, f(No, false, "流")}, - {0x2f903, 0, 0, 0, f(No, false, "浩")}, - {0x2f904, 0, 0, 0, f(No, false, "浸")}, - {0x2f905, 0, 0, 0, f(No, false, "涅")}, - {0x2f906, 0, 0, 0, f(No, false, "𣴞")}, - {0x2f907, 0, 0, 0, f(No, false, "洴")}, - {0x2f908, 0, 0, 0, f(No, false, "港")}, - {0x2f909, 0, 0, 0, f(No, false, "湮")}, - {0x2f90a, 0, 0, 0, f(No, false, "㴳")}, - {0x2f90b, 0, 0, 0, f(No, false, "滋")}, - {0x2f90c, 0, 0, 0, f(No, false, "滇")}, - {0x2f90d, 0, 0, 0, f(No, false, "𣻑")}, - {0x2f90e, 0, 0, 0, f(No, false, "淹")}, - {0x2f90f, 0, 0, 0, f(No, false, "潮")}, - {0x2f910, 0, 0, 0, f(No, false, "𣽞")}, - {0x2f911, 0, 0, 0, f(No, false, "𣾎")}, - {0x2f912, 0, 0, 0, f(No, false, "濆")}, - {0x2f913, 0, 0, 0, f(No, false, "瀹")}, - {0x2f914, 0, 0, 0, f(No, false, "瀞")}, - {0x2f915, 0, 0, 0, f(No, false, "瀛")}, - {0x2f916, 0, 0, 0, f(No, false, "㶖")}, - {0x2f917, 0, 0, 0, f(No, false, "灊")}, - {0x2f918, 0, 0, 0, f(No, false, "災")}, - {0x2f919, 0, 0, 0, f(No, false, "灷")}, - {0x2f91a, 0, 0, 0, f(No, false, "炭")}, - {0x2f91b, 0, 0, 0, f(No, false, "𠔥")}, - {0x2f91c, 0, 0, 0, f(No, false, "煅")}, - {0x2f91d, 0, 0, 0, f(No, false, "𤉣")}, - {0x2f91e, 0, 0, 0, f(No, false, "熜")}, - {0x2f91f, 0, 0, 0, f(No, false, "𤎫")}, - {0x2f920, 0, 0, 0, f(No, false, "爨")}, - {0x2f921, 0, 0, 0, f(No, false, "爵")}, - {0x2f922, 0, 0, 0, f(No, false, "牐")}, - {0x2f923, 0, 0, 0, f(No, false, "𤘈")}, - {0x2f924, 0, 0, 0, f(No, false, "犀")}, - {0x2f925, 0, 0, 0, f(No, false, "犕")}, - {0x2f926, 0, 0, 0, f(No, false, "𤜵")}, - {0x2f927, 0, 0, 0, f(No, false, "𤠔")}, - {0x2f928, 0, 0, 0, f(No, false, "獺")}, - {0x2f929, 0, 0, 0, f(No, false, "王")}, - {0x2f92a, 0, 0, 0, f(No, false, "㺬")}, - {0x2f92b, 0, 0, 0, f(No, false, "玥")}, - {0x2f92c, 0, 0, 0, f(No, false, "㺸")}, - {0x2f92e, 0, 0, 0, f(No, false, "瑇")}, - {0x2f92f, 0, 0, 0, f(No, false, "瑜")}, - {0x2f930, 0, 0, 0, f(No, false, "瑱")}, - {0x2f931, 0, 0, 0, f(No, false, "璅")}, - {0x2f932, 0, 0, 0, f(No, false, "瓊")}, - {0x2f933, 0, 0, 0, f(No, false, "㼛")}, - {0x2f934, 0, 0, 0, f(No, false, "甤")}, - {0x2f935, 0, 0, 0, f(No, false, "𤰶")}, - {0x2f936, 0, 0, 0, f(No, false, "甾")}, - {0x2f937, 0, 0, 0, f(No, false, "𤲒")}, - {0x2f938, 0, 0, 0, f(No, false, "異")}, - {0x2f939, 0, 0, 0, f(No, false, "𢆟")}, - {0x2f93a, 0, 0, 0, f(No, false, "瘐")}, - {0x2f93b, 0, 0, 0, f(No, false, "𤾡")}, - {0x2f93c, 0, 0, 0, f(No, false, "𤾸")}, - {0x2f93d, 0, 0, 0, f(No, false, "𥁄")}, - {0x2f93e, 0, 0, 0, f(No, false, "㿼")}, - {0x2f93f, 0, 0, 0, f(No, false, "䀈")}, - {0x2f940, 0, 0, 0, f(No, false, "直")}, - {0x2f941, 0, 0, 0, f(No, false, "𥃳")}, - {0x2f942, 0, 0, 0, f(No, false, "𥃲")}, - {0x2f943, 0, 0, 0, f(No, false, "𥄙")}, - {0x2f944, 0, 0, 0, f(No, false, "𥄳")}, - {0x2f945, 0, 0, 0, f(No, false, "眞")}, - {0x2f946, 0, 0, 0, f(No, false, "真")}, - {0x2f948, 0, 0, 0, f(No, false, "睊")}, - {0x2f949, 0, 0, 0, f(No, false, "䀹")}, - {0x2f94a, 0, 0, 0, f(No, false, "瞋")}, - {0x2f94b, 0, 0, 0, f(No, false, "䁆")}, - {0x2f94c, 0, 0, 0, f(No, false, "䂖")}, - {0x2f94d, 0, 0, 0, f(No, false, "𥐝")}, - {0x2f94e, 0, 0, 0, f(No, false, "硎")}, - {0x2f94f, 0, 0, 0, f(No, false, "碌")}, - {0x2f950, 0, 0, 0, f(No, false, "磌")}, - {0x2f951, 0, 0, 0, f(No, false, "䃣")}, - {0x2f952, 0, 0, 0, f(No, false, "𥘦")}, - {0x2f953, 0, 0, 0, f(No, false, "祖")}, - {0x2f954, 0, 0, 0, f(No, false, "𥚚")}, - {0x2f955, 0, 0, 0, f(No, false, "𥛅")}, - {0x2f956, 0, 0, 0, f(No, false, "福")}, - {0x2f957, 0, 0, 0, f(No, false, "秫")}, - {0x2f958, 0, 0, 0, f(No, false, "䄯")}, - {0x2f959, 0, 0, 0, f(No, false, "穀")}, - {0x2f95a, 0, 0, 0, f(No, false, "穊")}, - {0x2f95b, 0, 0, 0, f(No, false, "穏")}, - {0x2f95c, 0, 0, 0, f(No, false, "𥥼")}, - {0x2f95d, 0, 0, 0, f(No, false, "𥪧")}, - {0x2f95f, 0, 0, 0, f(No, false, "竮")}, - {0x2f960, 0, 0, 0, f(No, false, "䈂")}, - {0x2f961, 0, 0, 0, f(No, false, "𥮫")}, - {0x2f962, 0, 0, 0, f(No, false, "篆")}, - {0x2f963, 0, 0, 0, f(No, false, "築")}, - {0x2f964, 0, 0, 0, f(No, false, "䈧")}, - {0x2f965, 0, 0, 0, f(No, false, "𥲀")}, - {0x2f966, 0, 0, 0, f(No, false, "糒")}, - {0x2f967, 0, 0, 0, f(No, false, "䊠")}, - {0x2f968, 0, 0, 0, f(No, false, "糨")}, - {0x2f969, 0, 0, 0, f(No, false, "糣")}, - {0x2f96a, 0, 0, 0, f(No, false, "紀")}, - {0x2f96b, 0, 0, 0, f(No, false, "𥾆")}, - {0x2f96c, 0, 0, 0, f(No, false, "絣")}, - {0x2f96d, 0, 0, 0, f(No, false, "䌁")}, - {0x2f96e, 0, 0, 0, f(No, false, "緇")}, - {0x2f96f, 0, 0, 0, f(No, false, "縂")}, - {0x2f970, 0, 0, 0, f(No, false, "繅")}, - {0x2f971, 0, 0, 0, f(No, false, "䌴")}, - {0x2f972, 0, 0, 0, f(No, false, "𦈨")}, - {0x2f973, 0, 0, 0, f(No, false, "𦉇")}, - {0x2f974, 0, 0, 0, f(No, false, "䍙")}, - {0x2f975, 0, 0, 0, f(No, false, "𦋙")}, - {0x2f976, 0, 0, 0, f(No, false, "罺")}, - {0x2f977, 0, 0, 0, f(No, false, "𦌾")}, - {0x2f978, 0, 0, 0, f(No, false, "羕")}, - {0x2f979, 0, 0, 0, f(No, false, "翺")}, - {0x2f97a, 0, 0, 0, f(No, false, "者")}, - {0x2f97b, 0, 0, 0, f(No, false, "𦓚")}, - {0x2f97c, 0, 0, 0, f(No, false, "𦔣")}, - {0x2f97d, 0, 0, 0, f(No, false, "聠")}, - {0x2f97e, 0, 0, 0, f(No, false, "𦖨")}, - {0x2f97f, 0, 0, 0, f(No, false, "聰")}, - {0x2f980, 0, 0, 0, f(No, false, "𣍟")}, - {0x2f981, 0, 0, 0, f(No, false, "䏕")}, - {0x2f982, 0, 0, 0, f(No, false, "育")}, - {0x2f983, 0, 0, 0, f(No, false, "脃")}, - {0x2f984, 0, 0, 0, f(No, false, "䐋")}, - {0x2f985, 0, 0, 0, f(No, false, "脾")}, - {0x2f986, 0, 0, 0, f(No, false, "媵")}, - {0x2f987, 0, 0, 0, f(No, false, "𦞧")}, - {0x2f988, 0, 0, 0, f(No, false, "𦞵")}, - {0x2f989, 0, 0, 0, f(No, false, "𣎓")}, - {0x2f98a, 0, 0, 0, f(No, false, "𣎜")}, - {0x2f98b, 0, 0, 0, f(No, false, "舁")}, - {0x2f98c, 0, 0, 0, f(No, false, "舄")}, - {0x2f98d, 0, 0, 0, f(No, false, "辞")}, - {0x2f98e, 0, 0, 0, f(No, false, "䑫")}, - {0x2f98f, 0, 0, 0, f(No, false, "芑")}, - {0x2f990, 0, 0, 0, f(No, false, "芋")}, - {0x2f991, 0, 0, 0, f(No, false, "芝")}, - {0x2f992, 0, 0, 0, f(No, false, "劳")}, - {0x2f993, 0, 0, 0, f(No, false, "花")}, - {0x2f994, 0, 0, 0, f(No, false, "芳")}, - {0x2f995, 0, 0, 0, f(No, false, "芽")}, - {0x2f996, 0, 0, 0, f(No, false, "苦")}, - {0x2f997, 0, 0, 0, f(No, false, "𦬼")}, - {0x2f998, 0, 0, 0, f(No, false, "若")}, - {0x2f999, 0, 0, 0, f(No, false, "茝")}, - {0x2f99a, 0, 0, 0, f(No, false, "荣")}, - {0x2f99b, 0, 0, 0, f(No, false, "莭")}, - {0x2f99c, 0, 0, 0, f(No, false, "茣")}, - {0x2f99d, 0, 0, 0, f(No, false, "莽")}, - {0x2f99e, 0, 0, 0, f(No, false, "菧")}, - {0x2f99f, 0, 0, 0, f(No, false, "著")}, - {0x2f9a0, 0, 0, 0, f(No, false, "荓")}, - {0x2f9a1, 0, 0, 0, f(No, false, "菊")}, - {0x2f9a2, 0, 0, 0, f(No, false, "菌")}, - {0x2f9a3, 0, 0, 0, f(No, false, "菜")}, - {0x2f9a4, 0, 0, 0, f(No, false, "𦰶")}, - {0x2f9a5, 0, 0, 0, f(No, false, "𦵫")}, - {0x2f9a6, 0, 0, 0, f(No, false, "𦳕")}, - {0x2f9a7, 0, 0, 0, f(No, false, "䔫")}, - {0x2f9a8, 0, 0, 0, f(No, false, "蓱")}, - {0x2f9a9, 0, 0, 0, f(No, false, "蓳")}, - {0x2f9aa, 0, 0, 0, f(No, false, "蔖")}, - {0x2f9ab, 0, 0, 0, f(No, false, "𧏊")}, - {0x2f9ac, 0, 0, 0, f(No, false, "蕤")}, - {0x2f9ad, 0, 0, 0, f(No, false, "𦼬")}, - {0x2f9ae, 0, 0, 0, f(No, false, "䕝")}, - {0x2f9af, 0, 0, 0, f(No, false, "䕡")}, - {0x2f9b0, 0, 0, 0, f(No, false, "𦾱")}, - {0x2f9b1, 0, 0, 0, f(No, false, "𧃒")}, - {0x2f9b2, 0, 0, 0, f(No, false, "䕫")}, - {0x2f9b3, 0, 0, 0, f(No, false, "虐")}, - {0x2f9b4, 0, 0, 0, f(No, false, "虜")}, - {0x2f9b5, 0, 0, 0, f(No, false, "虧")}, - {0x2f9b6, 0, 0, 0, f(No, false, "虩")}, - {0x2f9b7, 0, 0, 0, f(No, false, "蚩")}, - {0x2f9b8, 0, 0, 0, f(No, false, "蚈")}, - {0x2f9b9, 0, 0, 0, f(No, false, "蜎")}, - {0x2f9ba, 0, 0, 0, f(No, false, "蛢")}, - {0x2f9bb, 0, 0, 0, f(No, false, "蝹")}, - {0x2f9bc, 0, 0, 0, f(No, false, "蜨")}, - {0x2f9bd, 0, 0, 0, f(No, false, "蝫")}, - {0x2f9be, 0, 0, 0, f(No, false, "螆")}, - {0x2f9bf, 0, 0, 0, f(No, false, "䗗")}, - {0x2f9c0, 0, 0, 0, f(No, false, "蟡")}, - {0x2f9c1, 0, 0, 0, f(No, false, "蠁")}, - {0x2f9c2, 0, 0, 0, f(No, false, "䗹")}, - {0x2f9c3, 0, 0, 0, f(No, false, "衠")}, - {0x2f9c4, 0, 0, 0, f(No, false, "衣")}, - {0x2f9c5, 0, 0, 0, f(No, false, "𧙧")}, - {0x2f9c6, 0, 0, 0, f(No, false, "裗")}, - {0x2f9c7, 0, 0, 0, f(No, false, "裞")}, - {0x2f9c8, 0, 0, 0, f(No, false, "䘵")}, - {0x2f9c9, 0, 0, 0, f(No, false, "裺")}, - {0x2f9ca, 0, 0, 0, f(No, false, "㒻")}, - {0x2f9cb, 0, 0, 0, f(No, false, "𧢮")}, - {0x2f9cc, 0, 0, 0, f(No, false, "𧥦")}, - {0x2f9cd, 0, 0, 0, f(No, false, "䚾")}, - {0x2f9ce, 0, 0, 0, f(No, false, "䛇")}, - {0x2f9cf, 0, 0, 0, f(No, false, "誠")}, - {0x2f9d0, 0, 0, 0, f(No, false, "諭")}, - {0x2f9d1, 0, 0, 0, f(No, false, "變")}, - {0x2f9d2, 0, 0, 0, f(No, false, "豕")}, - {0x2f9d3, 0, 0, 0, f(No, false, "𧲨")}, - {0x2f9d4, 0, 0, 0, f(No, false, "貫")}, - {0x2f9d5, 0, 0, 0, f(No, false, "賁")}, - {0x2f9d6, 0, 0, 0, f(No, false, "贛")}, - {0x2f9d7, 0, 0, 0, f(No, false, "起")}, - {0x2f9d8, 0, 0, 0, f(No, false, "𧼯")}, - {0x2f9d9, 0, 0, 0, f(No, false, "𠠄")}, - {0x2f9da, 0, 0, 0, f(No, false, "跋")}, - {0x2f9db, 0, 0, 0, f(No, false, "趼")}, - {0x2f9dc, 0, 0, 0, f(No, false, "跰")}, - {0x2f9dd, 0, 0, 0, f(No, false, "𠣞")}, - {0x2f9de, 0, 0, 0, f(No, false, "軔")}, - {0x2f9df, 0, 0, 0, f(No, false, "輸")}, - {0x2f9e0, 0, 0, 0, f(No, false, "𨗒")}, - {0x2f9e1, 0, 0, 0, f(No, false, "𨗭")}, - {0x2f9e2, 0, 0, 0, f(No, false, "邔")}, - {0x2f9e3, 0, 0, 0, f(No, false, "郱")}, - {0x2f9e4, 0, 0, 0, f(No, false, "鄑")}, - {0x2f9e5, 0, 0, 0, f(No, false, "𨜮")}, - {0x2f9e6, 0, 0, 0, f(No, false, "鄛")}, - {0x2f9e7, 0, 0, 0, f(No, false, "鈸")}, - {0x2f9e8, 0, 0, 0, f(No, false, "鋗")}, - {0x2f9e9, 0, 0, 0, f(No, false, "鋘")}, - {0x2f9ea, 0, 0, 0, f(No, false, "鉼")}, - {0x2f9eb, 0, 0, 0, f(No, false, "鏹")}, - {0x2f9ec, 0, 0, 0, f(No, false, "鐕")}, - {0x2f9ed, 0, 0, 0, f(No, false, "𨯺")}, - {0x2f9ee, 0, 0, 0, f(No, false, "開")}, - {0x2f9ef, 0, 0, 0, f(No, false, "䦕")}, - {0x2f9f0, 0, 0, 0, f(No, false, "閷")}, - {0x2f9f1, 0, 0, 0, f(No, false, "𨵷")}, - {0x2f9f2, 0, 0, 0, f(No, false, "䧦")}, - {0x2f9f3, 0, 0, 0, f(No, false, "雃")}, - {0x2f9f4, 0, 0, 0, f(No, false, "嶲")}, - {0x2f9f5, 0, 0, 0, f(No, false, "霣")}, - {0x2f9f6, 0, 0, 0, f(No, false, "𩅅")}, - {0x2f9f7, 0, 0, 0, f(No, false, "𩈚")}, - {0x2f9f8, 0, 0, 0, f(No, false, "䩮")}, - {0x2f9f9, 0, 0, 0, f(No, false, "䩶")}, - {0x2f9fa, 0, 0, 0, f(No, false, "韠")}, - {0x2f9fb, 0, 0, 0, f(No, false, "𩐊")}, - {0x2f9fc, 0, 0, 0, f(No, false, "䪲")}, - {0x2f9fd, 0, 0, 0, f(No, false, "𩒖")}, - {0x2f9fe, 0, 0, 0, f(No, false, "頋")}, - {0x2fa00, 0, 0, 0, f(No, false, "頩")}, - {0x2fa01, 0, 0, 0, f(No, false, "𩖶")}, - {0x2fa02, 0, 0, 0, f(No, false, "飢")}, - {0x2fa03, 0, 0, 0, f(No, false, "䬳")}, - {0x2fa04, 0, 0, 0, f(No, false, "餩")}, - {0x2fa05, 0, 0, 0, f(No, false, "馧")}, - {0x2fa06, 0, 0, 0, f(No, false, "駂")}, - {0x2fa07, 0, 0, 0, f(No, false, "駾")}, - {0x2fa08, 0, 0, 0, f(No, false, "䯎")}, - {0x2fa09, 0, 0, 0, f(No, false, "𩬰")}, - {0x2fa0a, 0, 0, 0, f(No, false, "鬒")}, - {0x2fa0b, 0, 0, 0, f(No, false, "鱀")}, - {0x2fa0c, 0, 0, 0, f(No, false, "鳽")}, - {0x2fa0d, 0, 0, 0, f(No, false, "䳎")}, - {0x2fa0e, 0, 0, 0, f(No, false, "䳭")}, - {0x2fa0f, 0, 0, 0, f(No, false, "鵧")}, - {0x2fa10, 0, 0, 0, f(No, false, "𪃎")}, - {0x2fa11, 0, 0, 0, f(No, false, "䳸")}, - {0x2fa12, 0, 0, 0, f(No, false, "𪄅")}, - {0x2fa13, 0, 0, 0, f(No, false, "𪈎")}, - {0x2fa14, 0, 0, 0, f(No, false, "𪊑")}, - {0x2fa15, 0, 0, 0, f(No, false, "麻")}, - {0x2fa16, 0, 0, 0, f(No, false, "䵖")}, - {0x2fa17, 0, 0, 0, f(No, false, "黹")}, - {0x2fa18, 0, 0, 0, f(No, false, "黾")}, - {0x2fa19, 0, 0, 0, f(No, false, "鼅")}, - {0x2fa1a, 0, 0, 0, f(No, false, "鼏")}, - {0x2fa1b, 0, 0, 0, f(No, false, "鼖")}, - {0x2fa1c, 0, 0, 0, f(No, false, "鼻")}, - {0x2fa1d, 0, 0, 0, f(No, false, "𪘀")}, - {0x2fa1e, 0, 0, 0, f(Yes, false, "")}, -} diff --git a/vendor/golang.org/x/text/unicode/norm/example_iter_test.go b/vendor/golang.org/x/text/unicode/norm/example_iter_test.go deleted file mode 100644 index 82df89c7..00000000 --- a/vendor/golang.org/x/text/unicode/norm/example_iter_test.go +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package norm_test - -import ( - "bytes" - "fmt" - "unicode/utf8" - - "golang.org/x/text/unicode/norm" -) - -// EqualSimple uses a norm.Iter to compare two non-normalized -// strings for equivalence. -func EqualSimple(a, b string) bool { - var ia, ib norm.Iter - ia.InitString(norm.NFKD, a) - ib.InitString(norm.NFKD, b) - for !ia.Done() && !ib.Done() { - if !bytes.Equal(ia.Next(), ib.Next()) { - return false - } - } - return ia.Done() && ib.Done() -} - -// FindPrefix finds the longest common prefix of ASCII characters -// of a and b. -func FindPrefix(a, b string) int { - i := 0 - for ; i < len(a) && i < len(b) && a[i] < utf8.RuneSelf && a[i] == b[i]; i++ { - } - return i -} - -// EqualOpt is like EqualSimple, but optimizes the special -// case for ASCII characters. -func EqualOpt(a, b string) bool { - n := FindPrefix(a, b) - a, b = a[n:], b[n:] - var ia, ib norm.Iter - ia.InitString(norm.NFKD, a) - ib.InitString(norm.NFKD, b) - for !ia.Done() && !ib.Done() { - if !bytes.Equal(ia.Next(), ib.Next()) { - return false - } - if n := int64(FindPrefix(a[ia.Pos():], b[ib.Pos():])); n != 0 { - ia.Seek(n, 1) - ib.Seek(n, 1) - } - } - return ia.Done() && ib.Done() -} - -var compareTests = []struct{ a, b string }{ - {"aaa", "aaa"}, - {"aaa", "aab"}, - {"a\u0300a", "\u00E0a"}, - {"a\u0300\u0320b", "a\u0320\u0300b"}, - {"\u1E0A\u0323", "\x44\u0323\u0307"}, - // A character that decomposes into multiple segments - // spans several iterations. - {"\u3304", "\u30A4\u30CB\u30F3\u30AF\u3099"}, -} - -func ExampleIter() { - for i, t := range compareTests { - r0 := EqualSimple(t.a, t.b) - r1 := EqualOpt(t.a, t.b) - fmt.Printf("%d: %v %v\n", i, r0, r1) - } - // Output: - // 0: true true - // 1: false false - // 2: true true - // 3: true true - // 4: true true - // 5: true true -} diff --git a/vendor/golang.org/x/text/unicode/norm/example_test.go b/vendor/golang.org/x/text/unicode/norm/example_test.go deleted file mode 100644 index 8f3b1565..00000000 --- a/vendor/golang.org/x/text/unicode/norm/example_test.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package norm_test - -import ( - "fmt" - - "golang.org/x/text/unicode/norm" -) - -func ExampleForm_NextBoundary() { - s := norm.NFD.String("Mêlée") - - for i := 0; i < len(s); { - d := norm.NFC.NextBoundaryInString(s[i:], true) - fmt.Printf("%[1]s: %+[1]q\n", s[i:i+d]) - i += d - } - // Output: - // M: "M" - // ê: "e\u0302" - // l: "l" - // é: "e\u0301" - // e: "e" -} diff --git a/vendor/golang.org/x/text/unicode/norm/forminfo_test.go b/vendor/golang.org/x/text/unicode/norm/forminfo_test.go deleted file mode 100644 index e15ba9be..00000000 --- a/vendor/golang.org/x/text/unicode/norm/forminfo_test.go +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build test - -package norm - -import "testing" - -func TestProperties(t *testing.T) { - var d runeData - CK := [2]string{"C", "K"} - for k, r := 1, rune(0); r < 0x2ffff; r++ { - if k < len(testData) && r == testData[k].r { - d = testData[k] - k++ - } - s := string(r) - for j, p := range []Properties{NFC.PropertiesString(s), NFKC.PropertiesString(s)} { - f := d.f[j] - if p.CCC() != d.ccc { - t.Errorf("%U: ccc(%s): was %d; want %d %X", r, CK[j], p.CCC(), d.ccc, p.index) - } - if p.isYesC() != (f.qc == Yes) { - t.Errorf("%U: YesC(%s): was %v; want %v", r, CK[j], p.isYesC(), f.qc == Yes) - } - if p.combinesBackward() != (f.qc == Maybe) { - t.Errorf("%U: combines backwards(%s): was %v; want %v", r, CK[j], p.combinesBackward(), f.qc == Maybe) - } - if p.nLeadingNonStarters() != d.nLead { - t.Errorf("%U: nLead(%s): was %d; want %d %#v %#v", r, CK[j], p.nLeadingNonStarters(), d.nLead, p, d) - } - if p.nTrailingNonStarters() != d.nTrail { - t.Errorf("%U: nTrail(%s): was %d; want %d %#v %#v", r, CK[j], p.nTrailingNonStarters(), d.nTrail, p, d) - } - if p.combinesForward() != f.combinesForward { - t.Errorf("%U: combines forward(%s): was %v; want %v %#v", r, CK[j], p.combinesForward(), f.combinesForward, p) - } - // Skip Hangul as it is algorithmically computed. - if r >= hangulBase && r < hangulEnd { - continue - } - if p.hasDecomposition() { - if has := f.decomposition != ""; !has { - t.Errorf("%U: hasDecomposition(%s): was %v; want %v", r, CK[j], p.hasDecomposition(), has) - } - if string(p.Decomposition()) != f.decomposition { - t.Errorf("%U: decomp(%s): was %+q; want %+q", r, CK[j], p.Decomposition(), f.decomposition) - } - } - } - } -} diff --git a/vendor/golang.org/x/text/unicode/norm/iter_test.go b/vendor/golang.org/x/text/unicode/norm/iter_test.go deleted file mode 100644 index d95aa304..00000000 --- a/vendor/golang.org/x/text/unicode/norm/iter_test.go +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package norm - -import ( - "strings" - "testing" -) - -func doIterNorm(f Form, s string) []byte { - acc := []byte{} - i := Iter{} - i.InitString(f, s) - for !i.Done() { - acc = append(acc, i.Next()...) - } - return acc -} - -func TestIterNext(t *testing.T) { - runNormTests(t, "IterNext", func(f Form, out []byte, s string) []byte { - return doIterNorm(f, string(append(out, s...))) - }) -} - -type SegmentTest struct { - in string - out []string -} - -var segmentTests = []SegmentTest{ - {"\u1E0A\u0323a", []string{"\x44\u0323\u0307", "a", ""}}, - {rep('a', segSize), append(strings.Split(rep('a', segSize), ""), "")}, - {rep('a', segSize+2), append(strings.Split(rep('a', segSize+2), ""), "")}, - {rep('a', segSize) + "\u0300aa", - append(strings.Split(rep('a', segSize-1), ""), "a\u0300", "a", "a", "")}, - - // U+0f73 is NOT treated as a starter as it is a modifier - {"a" + grave(29) + "\u0f73", []string{"a" + grave(29), cgj + "\u0f73"}}, - {"a\u0f73", []string{"a\u0f73"}}, - - // U+ff9e is treated as a non-starter. - // TODO: should we? Note that this will only affect iteration, as whether - // or not we do so does not affect the normalization output and will either - // way result in consistent iteration output. - {"a" + grave(30) + "\uff9e", []string{"a" + grave(30), cgj + "\uff9e"}}, - {"a\uff9e", []string{"a\uff9e"}}, -} - -var segmentTestsK = []SegmentTest{ - {"\u3332", []string{"\u30D5", "\u30A1", "\u30E9", "\u30C3", "\u30C8\u3099", ""}}, - // last segment of multi-segment decomposition needs normalization - {"\u3332\u093C", []string{"\u30D5", "\u30A1", "\u30E9", "\u30C3", "\u30C8\u093C\u3099", ""}}, - {"\u320E", []string{"\x28", "\uAC00", "\x29"}}, - - // last segment should be copied to start of buffer. - {"\ufdfa", []string{"\u0635", "\u0644", "\u0649", " ", "\u0627", "\u0644", "\u0644", "\u0647", " ", "\u0639", "\u0644", "\u064a", "\u0647", " ", "\u0648", "\u0633", "\u0644", "\u0645", ""}}, - {"\ufdfa" + grave(30), []string{"\u0635", "\u0644", "\u0649", " ", "\u0627", "\u0644", "\u0644", "\u0647", " ", "\u0639", "\u0644", "\u064a", "\u0647", " ", "\u0648", "\u0633", "\u0644", "\u0645" + grave(30), ""}}, - {"\uFDFA" + grave(64), []string{"\u0635", "\u0644", "\u0649", " ", "\u0627", "\u0644", "\u0644", "\u0647", " ", "\u0639", "\u0644", "\u064a", "\u0647", " ", "\u0648", "\u0633", "\u0644", "\u0645" + grave(30), cgj + grave(30), cgj + grave(4), ""}}, - - // Hangul and Jamo are grouped together. - {"\uAC00", []string{"\u1100\u1161", ""}}, - {"\uAC01", []string{"\u1100\u1161\u11A8", ""}}, - {"\u1100\u1161", []string{"\u1100\u1161", ""}}, -} - -// Note that, by design, segmentation is equal for composing and decomposing forms. -func TestIterSegmentation(t *testing.T) { - segmentTest(t, "SegmentTestD", NFD, segmentTests) - segmentTest(t, "SegmentTestC", NFC, segmentTests) - segmentTest(t, "SegmentTestKD", NFKD, segmentTestsK) - segmentTest(t, "SegmentTestKC", NFKC, segmentTestsK) -} - -func segmentTest(t *testing.T, name string, f Form, tests []SegmentTest) { - iter := Iter{} - for i, tt := range tests { - iter.InitString(f, tt.in) - for j, seg := range tt.out { - if seg == "" { - if !iter.Done() { - res := string(iter.Next()) - t.Errorf(`%s:%d:%d: expected Done()==true, found segment %+q`, name, i, j, res) - } - continue - } - if iter.Done() { - t.Errorf("%s:%d:%d: Done()==true, want false", name, i, j) - } - seg = f.String(seg) - if res := string(iter.Next()); res != seg { - t.Errorf(`%s:%d:%d" segment was %+q (%d); want %+q (%d)`, name, i, j, pc(res), len(res), pc(seg), len(seg)) - } - } - } -} diff --git a/vendor/golang.org/x/text/unicode/norm/normalize_test.go b/vendor/golang.org/x/text/unicode/norm/normalize_test.go deleted file mode 100644 index e3c0ac73..00000000 --- a/vendor/golang.org/x/text/unicode/norm/normalize_test.go +++ /dev/null @@ -1,1287 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package norm - -import ( - "bytes" - "flag" - "fmt" - "io" - "log" - "strings" - "testing" - "unicode/utf8" - - "golang.org/x/text/internal/testtext" - "golang.org/x/text/transform" -) - -var ( - testn = flag.Int("testn", -1, "specific test number to run or -1 for all") -) - -// pc replaces any rune r that is repeated n times, for n > 1, with r{n}. -func pc(s string) []byte { - b := bytes.NewBuffer(make([]byte, 0, len(s))) - for i := 0; i < len(s); { - r, sz := utf8.DecodeRuneInString(s[i:]) - n := 0 - if sz == 1 { - // Special-case one-byte case to handle repetition for invalid UTF-8. - for c := s[i]; i+n < len(s) && s[i+n] == c; n++ { - } - } else { - for _, r2 := range s[i:] { - if r2 != r { - break - } - n++ - } - } - b.WriteString(s[i : i+sz]) - if n > 1 { - fmt.Fprintf(b, "{%d}", n) - } - i += sz * n - } - return b.Bytes() -} - -// pidx finds the index from which two strings start to differ, plus context. -// It returns the index and ellipsis if the index is greater than 0. -func pidx(a, b string) (i int, prefix string) { - for ; i < len(a) && i < len(b) && a[i] == b[i]; i++ { - } - if i < 8 { - return 0, "" - } - i -= 3 // ensure taking at least one full rune before the difference. - for k := i - 7; i > k && !utf8.RuneStart(a[i]); i-- { - } - return i, "..." -} - -type PositionTest struct { - input string - pos int - buffer string // expected contents of reorderBuffer, if applicable -} - -type positionFunc func(rb *reorderBuffer, s string) (int, []byte) - -func runPosTests(t *testing.T, name string, f Form, fn positionFunc, tests []PositionTest) { - rb := reorderBuffer{} - rb.init(f, nil) - for i, test := range tests { - rb.reset() - rb.src = inputString(test.input) - rb.nsrc = len(test.input) - pos, out := fn(&rb, test.input) - if pos != test.pos { - t.Errorf("%s:%d: position is %d; want %d", name, i, pos, test.pos) - } - if outs := string(out); outs != test.buffer { - k, pfx := pidx(outs, test.buffer) - t.Errorf("%s:%d: buffer \nwas %s%+q; \nwant %s%+q", name, i, pfx, pc(outs[k:]), pfx, pc(test.buffer[k:])) - } - } -} - -func grave(n int) string { - return rep(0x0300, n) -} - -func rep(r rune, n int) string { - return strings.Repeat(string(r), n) -} - -const segSize = maxByteBufferSize - -var cgj = GraphemeJoiner - -var decomposeSegmentTests = []PositionTest{ - // illegal runes - {"\xC2", 0, ""}, - {"\xC0", 1, "\xC0"}, - {"\u00E0\x80", 2, "\u0061\u0300"}, - // starter - {"a", 1, "a"}, - {"ab", 1, "a"}, - // starter + composing - {"a\u0300", 3, "a\u0300"}, - {"a\u0300b", 3, "a\u0300"}, - // with decomposition - {"\u00C0", 2, "A\u0300"}, - {"\u00C0b", 2, "A\u0300"}, - // long - {grave(31), 60, grave(30) + cgj}, - {"a" + grave(31), 61, "a" + grave(30) + cgj}, - - // Stability tests: see http://www.unicode.org/review/pr-29.html. - // U+0300 COMBINING GRAVE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING GRAVE;;;; - // U+0B47 ORIYA VOWEL SIGN E;Mc;0;L;;;;;N;;;;; - // U+0B3E ORIYA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; - // U+1100 HANGUL CHOSEONG KIYEOK;Lo;0;L;;;;;N;;;;; - // U+1161 HANGUL JUNGSEONG A;Lo;0;L;;;;;N;;;;; - {"\u0B47\u0300\u0B3E", 8, "\u0B47\u0300\u0B3E"}, - {"\u1100\u0300\u1161", 8, "\u1100\u0300\u1161"}, - {"\u0B47\u0B3E", 6, "\u0B47\u0B3E"}, - {"\u1100\u1161", 6, "\u1100\u1161"}, - - // U+04DA MALAYALAM VOWEL SIGN O;Mc;0;L;0D46 0D3E;;;;N;;;;; - // Sequence of decomposing characters that are starters and modifiers. - {"\u0d4a" + strings.Repeat("\u0d3e", 31), 90, "\u0d46" + strings.Repeat("\u0d3e", 30) + cgj}, - - {grave(30), 60, grave(30)}, - // U+FF9E is a starter, but decomposes to U+3099, which is not. - {grave(30) + "\uff9e", 60, grave(30) + cgj}, - // ends with incomplete UTF-8 encoding - {"\xCC", 0, ""}, - {"\u0300\xCC", 2, "\u0300"}, -} - -func decomposeSegmentF(rb *reorderBuffer, s string) (int, []byte) { - rb.initString(NFD, s) - rb.setFlusher(nil, appendFlush) - p := decomposeSegment(rb, 0, true) - return p, rb.out -} - -func TestDecomposeSegment(t *testing.T) { - runPosTests(t, "TestDecomposeSegment", NFC, decomposeSegmentF, decomposeSegmentTests) -} - -var firstBoundaryTests = []PositionTest{ - // no boundary - {"", -1, ""}, - {"\u0300", -1, ""}, - {"\x80\x80", -1, ""}, - // illegal runes - {"\xff", 0, ""}, - {"\u0300\xff", 2, ""}, - {"\u0300\xc0\x80\x80", 2, ""}, - // boundaries - {"a", 0, ""}, - {"\u0300a", 2, ""}, - // Hangul - {"\u1103\u1161", 0, ""}, - {"\u110B\u1173\u11B7", 0, ""}, - {"\u1161\u110B\u1173\u11B7", 3, ""}, - {"\u1173\u11B7\u1103\u1161", 6, ""}, - // too many combining characters. - {grave(maxNonStarters - 1), -1, ""}, - {grave(maxNonStarters), 60, ""}, - {grave(maxNonStarters + 1), 60, ""}, -} - -func firstBoundaryF(rb *reorderBuffer, s string) (int, []byte) { - return rb.f.form.FirstBoundary([]byte(s)), nil -} - -func firstBoundaryStringF(rb *reorderBuffer, s string) (int, []byte) { - return rb.f.form.FirstBoundaryInString(s), nil -} - -func TestFirstBoundary(t *testing.T) { - runPosTests(t, "TestFirstBoundary", NFC, firstBoundaryF, firstBoundaryTests) - runPosTests(t, "TestFirstBoundaryInString", NFC, firstBoundaryStringF, firstBoundaryTests) -} - -func TestNextBoundary(t *testing.T) { - testCases := []struct { - input string - atEOF bool - want int - }{ - // no boundary - {"", true, 0}, - {"", false, -1}, - {"\u0300", true, 2}, - {"\u0300", false, -1}, - {"\x80\x80", true, 1}, - {"\x80\x80", false, 1}, - // illegal runes - {"\xff", false, 1}, - {"\u0300\xff", false, 2}, - {"\u0300\xc0\x80\x80", false, 2}, - {"\xc2\x80\x80", false, 2}, - {"\xc2", false, -1}, - {"\xc2", true, 1}, - {"a\u0300\xc2", false, -1}, - {"a\u0300\xc2", true, 3}, - // boundaries - {"a", true, 1}, - {"a", false, -1}, - {"aa", false, 1}, - {"\u0300", true, 2}, - {"\u0300", false, -1}, - {"\u0300a", false, 2}, - // Hangul - {"\u1103\u1161", true, 6}, - {"\u1103\u1161", false, -1}, - {"\u110B\u1173\u11B7", false, -1}, - {"\u110B\u1173\u11B7\u110B\u1173\u11B7", false, 9}, - {"\u1161\u110B\u1173\u11B7", false, 3}, - {"\u1173\u11B7\u1103\u1161", false, 6}, - // too many combining characters. - {grave(maxNonStarters - 1), false, -1}, - {grave(maxNonStarters), false, 60}, - {grave(maxNonStarters + 1), false, 60}, - } - - for _, tc := range testCases { - if got := NFC.NextBoundary([]byte(tc.input), tc.atEOF); got != tc.want { - t.Errorf("NextBoundary(%+q, %v) = %d; want %d", tc.input, tc.atEOF, got, tc.want) - } - if got := NFC.NextBoundaryInString(tc.input, tc.atEOF); got != tc.want { - t.Errorf("NextBoundaryInString(%+q, %v) = %d; want %d", tc.input, tc.atEOF, got, tc.want) - } - } -} - -var decomposeToLastTests = []PositionTest{ - // ends with inert character - {"Hello!", 6, ""}, - {"\u0632", 2, ""}, - {"a\u0301\u0635", 5, ""}, - // ends with non-inert starter - {"a", 0, "a"}, - {"a\u0301a", 3, "a"}, - {"a\u0301\u03B9", 3, "\u03B9"}, - {"a\u0327", 0, "a\u0327"}, - // illegal runes - {"\xFF", 1, ""}, - {"aa\xFF", 3, ""}, - {"\xC0\x80\x80", 3, ""}, - {"\xCC\x80\x80", 3, ""}, - // ends with incomplete UTF-8 encoding - {"a\xCC", 2, ""}, - // ends with combining characters - {"\u0300\u0301", 0, "\u0300\u0301"}, - {"a\u0300\u0301", 0, "a\u0300\u0301"}, - {"a\u0301\u0308", 0, "a\u0301\u0308"}, - {"a\u0308\u0301", 0, "a\u0308\u0301"}, - {"aaaa\u0300\u0301", 3, "a\u0300\u0301"}, - {"\u0300a\u0300\u0301", 2, "a\u0300\u0301"}, - {"\u00C0", 0, "A\u0300"}, - {"a\u00C0", 1, "A\u0300"}, - // decomposing - {"a\u0300\u00E0", 3, "a\u0300"}, - // multisegment decompositions (flushes leading segments) - {"a\u0300\uFDC0", 7, "\u064A"}, - {"\uFDC0" + grave(29), 4, "\u064A" + grave(29)}, - {"\uFDC0" + grave(30), 4, "\u064A" + grave(30)}, - {"\uFDC0" + grave(31), 5, grave(30)}, - {"\uFDFA" + grave(14), 31, "\u0645" + grave(14)}, - // Overflow - {"\u00E0" + grave(29), 0, "a" + grave(30)}, - {"\u00E0" + grave(30), 2, grave(30)}, - // Hangul - {"a\u1103", 1, "\u1103"}, - {"a\u110B", 1, "\u110B"}, - {"a\u110B\u1173", 1, "\u110B\u1173"}, - // See comment in composition.go:compBoundaryAfter. - {"a\u110B\u1173\u11B7", 1, "\u110B\u1173\u11B7"}, - {"a\uC73C", 1, "\u110B\u1173"}, - {"다음", 3, "\u110B\u1173\u11B7"}, - {"다", 0, "\u1103\u1161"}, - {"\u1103\u1161\u110B\u1173\u11B7", 6, "\u110B\u1173\u11B7"}, - {"\u110B\u1173\u11B7\u1103\u1161", 9, "\u1103\u1161"}, - {"다음음", 6, "\u110B\u1173\u11B7"}, - {"음다다", 6, "\u1103\u1161"}, - // maximized buffer - {"a" + grave(30), 0, "a" + grave(30)}, - // Buffer overflow - {"a" + grave(31), 3, grave(30)}, - // weird UTF-8 - {"a\u0300\u11B7", 0, "a\u0300\u11B7"}, -} - -func decomposeToLast(rb *reorderBuffer, s string) (int, []byte) { - rb.setFlusher([]byte(s), appendFlush) - decomposeToLastBoundary(rb) - buf := rb.flush(nil) - return len(rb.out), buf -} - -func TestDecomposeToLastBoundary(t *testing.T) { - runPosTests(t, "TestDecomposeToLastBoundary", NFKC, decomposeToLast, decomposeToLastTests) -} - -var lastBoundaryTests = []PositionTest{ - // ends with inert character - {"Hello!", 6, ""}, - {"\u0632", 2, ""}, - // ends with non-inert starter - {"a", 0, ""}, - // illegal runes - {"\xff", 1, ""}, - {"aa\xff", 3, ""}, - {"a\xff\u0300", 1, ""}, // TODO: should probably be 2. - {"\xc0\x80\x80", 3, ""}, - {"\xc0\x80\x80\u0300", 3, ""}, - // ends with incomplete UTF-8 encoding - {"\xCC", -1, ""}, - {"\xE0\x80", -1, ""}, - {"\xF0\x80\x80", -1, ""}, - {"a\xCC", 0, ""}, - {"\x80\xCC", 1, ""}, - {"\xCC\xCC", 1, ""}, - // ends with combining characters - {"a\u0300\u0301", 0, ""}, - {"aaaa\u0300\u0301", 3, ""}, - {"\u0300a\u0300\u0301", 2, ""}, - {"\u00C2", 0, ""}, - {"a\u00C2", 1, ""}, - // decomposition may recombine - {"\u0226", 0, ""}, - // no boundary - {"", -1, ""}, - {"\u0300\u0301", -1, ""}, - {"\u0300", -1, ""}, - {"\x80\x80", -1, ""}, - {"\x80\x80\u0301", -1, ""}, - // Hangul - {"다음", 3, ""}, - {"다", 0, ""}, - {"\u1103\u1161\u110B\u1173\u11B7", 6, ""}, - {"\u110B\u1173\u11B7\u1103\u1161", 9, ""}, - // too many combining characters. - {grave(maxNonStarters - 1), -1, ""}, - // May still be preceded with a non-starter. - {grave(maxNonStarters), -1, ""}, - // May still need to insert a cgj after the last combiner. - {grave(maxNonStarters + 1), 2, ""}, - {grave(maxNonStarters + 2), 4, ""}, - - {"a" + grave(maxNonStarters-1), 0, ""}, - {"a" + grave(maxNonStarters), 0, ""}, - // May still need to insert a cgj after the last combiner. - {"a" + grave(maxNonStarters+1), 3, ""}, - {"a" + grave(maxNonStarters+2), 5, ""}, -} - -func lastBoundaryF(rb *reorderBuffer, s string) (int, []byte) { - return rb.f.form.LastBoundary([]byte(s)), nil -} - -func TestLastBoundary(t *testing.T) { - runPosTests(t, "TestLastBoundary", NFC, lastBoundaryF, lastBoundaryTests) -} - -type spanTest struct { - input string - atEOF bool - n int - err error -} - -var quickSpanTests = []spanTest{ - {"", true, 0, nil}, - // starters - {"a", true, 1, nil}, - {"abc", true, 3, nil}, - {"\u043Eb", true, 3, nil}, - // incomplete last rune. - {"\xCC", true, 1, nil}, - {"\xCC", false, 0, transform.ErrShortSrc}, - {"a\xCC", true, 2, nil}, - {"a\xCC", false, 0, transform.ErrShortSrc}, // TODO: could be 1 for NFD - // incorrectly ordered combining characters - {"\u0300\u0316", true, 0, transform.ErrEndOfSpan}, - {"\u0300\u0316", false, 0, transform.ErrEndOfSpan}, - {"\u0300\u0316cd", true, 0, transform.ErrEndOfSpan}, - {"\u0300\u0316cd", false, 0, transform.ErrEndOfSpan}, - // have a maximum number of combining characters. - {rep(0x035D, 30) + "\u035B", true, 0, transform.ErrEndOfSpan}, - {"a" + rep(0x035D, 30) + "\u035B", true, 0, transform.ErrEndOfSpan}, - {"Ɵ" + rep(0x035D, 30) + "\u035B", true, 0, transform.ErrEndOfSpan}, - {"aa" + rep(0x035D, 30) + "\u035B", true, 1, transform.ErrEndOfSpan}, - {rep(0x035D, 30) + cgj + "\u035B", true, 64, nil}, - {"a" + rep(0x035D, 30) + cgj + "\u035B", true, 65, nil}, - {"Ɵ" + rep(0x035D, 30) + cgj + "\u035B", true, 66, nil}, - {"aa" + rep(0x035D, 30) + cgj + "\u035B", true, 66, nil}, - - {"a" + rep(0x035D, 30) + cgj + "\u035B", false, 61, transform.ErrShortSrc}, - {"Ɵ" + rep(0x035D, 30) + cgj + "\u035B", false, 62, transform.ErrShortSrc}, - {"aa" + rep(0x035D, 30) + cgj + "\u035B", false, 62, transform.ErrShortSrc}, -} - -var quickSpanNFDTests = []spanTest{ - // needs decomposing - {"\u00C0", true, 0, transform.ErrEndOfSpan}, - {"abc\u00C0", true, 3, transform.ErrEndOfSpan}, - // correctly ordered combining characters - {"\u0300", true, 2, nil}, - {"ab\u0300", true, 4, nil}, - {"ab\u0300cd", true, 6, nil}, - {"\u0300cd", true, 4, nil}, - {"\u0316\u0300", true, 4, nil}, - {"ab\u0316\u0300", true, 6, nil}, - {"ab\u0316\u0300cd", true, 8, nil}, - {"ab\u0316\u0300\u00C0", true, 6, transform.ErrEndOfSpan}, - {"\u0316\u0300cd", true, 6, nil}, - {"\u043E\u0308b", true, 5, nil}, - // incorrectly ordered combining characters - {"ab\u0300\u0316", true, 1, transform.ErrEndOfSpan}, // TODO: we could skip 'b' as well. - {"ab\u0300\u0316cd", true, 1, transform.ErrEndOfSpan}, - // Hangul - {"같은", true, 0, transform.ErrEndOfSpan}, -} - -var quickSpanNFCTests = []spanTest{ - // okay composed - {"\u00C0", true, 2, nil}, - {"abc\u00C0", true, 5, nil}, - // correctly ordered combining characters - // TODO: b may combine with modifiers, which is why this fails. We could - // make a more precise test that that actually checks whether last - // characters combines. Probably not worth it. - {"ab\u0300", true, 1, transform.ErrEndOfSpan}, - {"ab\u0300cd", true, 1, transform.ErrEndOfSpan}, - {"ab\u0316\u0300", true, 1, transform.ErrEndOfSpan}, - {"ab\u0316\u0300cd", true, 1, transform.ErrEndOfSpan}, - {"\u00C0\u035D", true, 4, nil}, - // we do not special case leading combining characters - {"\u0300cd", true, 0, transform.ErrEndOfSpan}, - {"\u0300", true, 0, transform.ErrEndOfSpan}, - {"\u0316\u0300", true, 0, transform.ErrEndOfSpan}, - {"\u0316\u0300cd", true, 0, transform.ErrEndOfSpan}, - // incorrectly ordered combining characters - {"ab\u0300\u0316", true, 1, transform.ErrEndOfSpan}, - {"ab\u0300\u0316cd", true, 1, transform.ErrEndOfSpan}, - // Hangul - {"같은", true, 6, nil}, - {"같은", false, 3, transform.ErrShortSrc}, - // We return the start of the violating segment in case of overflow. - {grave(30) + "\uff9e", true, 0, transform.ErrEndOfSpan}, - {grave(30), true, 0, transform.ErrEndOfSpan}, -} - -func runSpanTests(t *testing.T, name string, f Form, testCases []spanTest) { - for i, tc := range testCases { - s := fmt.Sprintf("Bytes/%s/%d=%+q/atEOF=%v", name, i, pc(tc.input), tc.atEOF) - ok := testtext.Run(t, s, func(t *testing.T) { - n, err := f.Span([]byte(tc.input), tc.atEOF) - if n != tc.n || err != tc.err { - t.Errorf("\n got %d, %v;\nwant %d, %v", n, err, tc.n, tc.err) - } - }) - if !ok { - continue // Don't do the String variant if the Bytes variant failed. - } - s = fmt.Sprintf("String/%s/%d=%+q/atEOF=%v", name, i, pc(tc.input), tc.atEOF) - testtext.Run(t, s, func(t *testing.T) { - n, err := f.SpanString(tc.input, tc.atEOF) - if n != tc.n || err != tc.err { - t.Errorf("\n got %d, %v;\nwant %d, %v", n, err, tc.n, tc.err) - } - }) - } -} - -func TestSpan(t *testing.T) { - runSpanTests(t, "NFD", NFD, quickSpanTests) - runSpanTests(t, "NFD", NFD, quickSpanNFDTests) - runSpanTests(t, "NFC", NFC, quickSpanTests) - runSpanTests(t, "NFC", NFC, quickSpanNFCTests) -} - -var isNormalTests = []PositionTest{ - {"", 1, ""}, - // illegal runes - {"\xff", 1, ""}, - // starters - {"a", 1, ""}, - {"abc", 1, ""}, - {"\u043Eb", 1, ""}, - // incorrectly ordered combining characters - {"\u0300\u0316", 0, ""}, - {"ab\u0300\u0316", 0, ""}, - {"ab\u0300\u0316cd", 0, ""}, - {"\u0300\u0316cd", 0, ""}, -} -var isNormalNFDTests = []PositionTest{ - // needs decomposing - {"\u00C0", 0, ""}, - {"abc\u00C0", 0, ""}, - // correctly ordered combining characters - {"\u0300", 1, ""}, - {"ab\u0300", 1, ""}, - {"ab\u0300cd", 1, ""}, - {"\u0300cd", 1, ""}, - {"\u0316\u0300", 1, ""}, - {"ab\u0316\u0300", 1, ""}, - {"ab\u0316\u0300cd", 1, ""}, - {"\u0316\u0300cd", 1, ""}, - {"\u043E\u0308b", 1, ""}, - // Hangul - {"같은", 0, ""}, -} -var isNormalNFCTests = []PositionTest{ - // okay composed - {"\u00C0", 1, ""}, - {"abc\u00C0", 1, ""}, - // need reordering - {"a\u0300", 0, ""}, - {"a\u0300cd", 0, ""}, - {"a\u0316\u0300", 0, ""}, - {"a\u0316\u0300cd", 0, ""}, - // correctly ordered combining characters - {"ab\u0300", 1, ""}, - {"ab\u0300cd", 1, ""}, - {"ab\u0316\u0300", 1, ""}, - {"ab\u0316\u0300cd", 1, ""}, - {"\u00C0\u035D", 1, ""}, - {"\u0300", 1, ""}, - {"\u0316\u0300cd", 1, ""}, - // Hangul - {"같은", 1, ""}, -} - -var isNormalNFKXTests = []PositionTest{ - // Special case. - {"\u00BC", 0, ""}, -} - -func isNormalF(rb *reorderBuffer, s string) (int, []byte) { - if rb.f.form.IsNormal([]byte(s)) { - return 1, nil - } - return 0, nil -} - -func isNormalStringF(rb *reorderBuffer, s string) (int, []byte) { - if rb.f.form.IsNormalString(s) { - return 1, nil - } - return 0, nil -} - -func TestIsNormal(t *testing.T) { - runPosTests(t, "TestIsNormalNFD1", NFD, isNormalF, isNormalTests) - runPosTests(t, "TestIsNormalNFD2", NFD, isNormalF, isNormalNFDTests) - runPosTests(t, "TestIsNormalNFC1", NFC, isNormalF, isNormalTests) - runPosTests(t, "TestIsNormalNFC2", NFC, isNormalF, isNormalNFCTests) - runPosTests(t, "TestIsNormalNFKD1", NFKD, isNormalF, isNormalTests) - runPosTests(t, "TestIsNormalNFKD2", NFKD, isNormalF, isNormalNFDTests) - runPosTests(t, "TestIsNormalNFKD3", NFKD, isNormalF, isNormalNFKXTests) - runPosTests(t, "TestIsNormalNFKC1", NFKC, isNormalF, isNormalTests) - runPosTests(t, "TestIsNormalNFKC2", NFKC, isNormalF, isNormalNFCTests) - runPosTests(t, "TestIsNormalNFKC3", NFKC, isNormalF, isNormalNFKXTests) -} - -func TestIsNormalString(t *testing.T) { - runPosTests(t, "TestIsNormalNFD1", NFD, isNormalStringF, isNormalTests) - runPosTests(t, "TestIsNormalNFD2", NFD, isNormalStringF, isNormalNFDTests) - runPosTests(t, "TestIsNormalNFC1", NFC, isNormalStringF, isNormalTests) - runPosTests(t, "TestIsNormalNFC2", NFC, isNormalStringF, isNormalNFCTests) -} - -type AppendTest struct { - left string - right string - out string -} - -type appendFunc func(f Form, out []byte, s string) []byte - -var fstr = []string{"NFC", "NFD", "NFKC", "NFKD"} - -func runNormTests(t *testing.T, name string, fn appendFunc) { - for f := NFC; f <= NFKD; f++ { - runAppendTests(t, name, f, fn, normTests[f]) - } -} - -func runAppendTests(t *testing.T, name string, f Form, fn appendFunc, tests []AppendTest) { - for i, test := range tests { - t.Run(fmt.Sprintf("%s/%d", fstr[f], i), func(t *testing.T) { - id := pc(test.left + test.right) - if *testn >= 0 && i != *testn { - return - } - t.Run("fn", func(t *testing.T) { - out := []byte(test.left) - have := string(fn(f, out, test.right)) - if len(have) != len(test.out) { - t.Errorf("%+q: length is %d; want %d (%+q vs %+q)", id, len(have), len(test.out), pc(have), pc(test.out)) - } - if have != test.out { - k, pf := pidx(have, test.out) - t.Errorf("%+q:\nwas %s%+q; \nwant %s%+q", id, pf, pc(have[k:]), pf, pc(test.out[k:])) - } - }) - - // Bootstrap by normalizing input. Ensures that the various variants - // behave the same. - for g := NFC; g <= NFKD; g++ { - if f == g { - continue - } - t.Run(fstr[g], func(t *testing.T) { - want := g.String(test.left + test.right) - have := string(fn(g, g.AppendString(nil, test.left), test.right)) - if len(have) != len(want) { - t.Errorf("%+q: length is %d; want %d (%+q vs %+q)", id, len(have), len(want), pc(have), pc(want)) - } - if have != want { - k, pf := pidx(have, want) - t.Errorf("%+q:\nwas %s%+q; \nwant %s%+q", id, pf, pc(have[k:]), pf, pc(want[k:])) - } - }) - } - }) - } -} - -var normTests = [][]AppendTest{ - appendTestsNFC, - appendTestsNFD, - appendTestsNFKC, - appendTestsNFKD, -} - -var appendTestsNFC = []AppendTest{ - {"", ascii, ascii}, - {"", txt_all, txt_all}, - {"\uff9e", grave(30), "\uff9e" + grave(29) + cgj + grave(1)}, - {grave(30), "\uff9e", grave(30) + cgj + "\uff9e"}, - - // Tests designed for Iter. - { // ordering of non-composing combining characters - "", - "\u0305\u0316", - "\u0316\u0305", - }, - { // segment overflow - "", - "a" + rep(0x0305, maxNonStarters+4) + "\u0316", - "a" + rep(0x0305, maxNonStarters) + cgj + "\u0316" + rep(0x305, 4), - }, - - { // Combine across non-blocking non-starters. - // U+0327 COMBINING CEDILLA;Mn;202;NSM;;;;;N;NON-SPACING CEDILLA;;;; - // U+0325 COMBINING RING BELOW;Mn;220;NSM;;;;;N;NON-SPACING RING BELOW;;;; - "", "a\u0327\u0325", "\u1e01\u0327", - }, - - { // Jamo V+T does not combine. - "", - "\u1161\u11a8", - "\u1161\u11a8", - }, - - // Stability tests: see http://www.unicode.org/review/pr-29.html. - {"", "\u0b47\u0300\u0b3e", "\u0b47\u0300\u0b3e"}, - {"", "\u1100\u0300\u1161", "\u1100\u0300\u1161"}, - {"", "\u0b47\u0b3e", "\u0b4b"}, - {"", "\u1100\u1161", "\uac00"}, - - // U+04DA MALAYALAM VOWEL SIGN O;Mc;0;L;0D46 0D3E;;;;N;;;;; - { // 0d4a starts a new segment. - "", - "\u0d4a" + strings.Repeat("\u0d3e", 15) + "\u0d4a" + strings.Repeat("\u0d3e", 15), - "\u0d4a" + strings.Repeat("\u0d3e", 15) + "\u0d4a" + strings.Repeat("\u0d3e", 15), - }, - - { // Split combining characters. - // TODO: don't insert CGJ before starters. - "", - "\u0d46" + strings.Repeat("\u0d3e", 31), - "\u0d4a" + strings.Repeat("\u0d3e", 29) + cgj + "\u0d3e", - }, - - { // Split combining characters. - "", - "\u0d4a" + strings.Repeat("\u0d3e", 30), - "\u0d4a" + strings.Repeat("\u0d3e", 29) + cgj + "\u0d3e", - }, - - { // https://golang.org/issues/20079 - "", - "\xeb\u0344", - "\xeb\u0308\u0301", - }, - - { // https://golang.org/issues/20079 - "", - "\uac00" + strings.Repeat("\u0300", 30), - "\uac00" + strings.Repeat("\u0300", 29) + "\u034f\u0300", - }, - - { // https://golang.org/issues/20079 - "", - "\xeb" + strings.Repeat("\u0300", 31), - "\xeb" + strings.Repeat("\u0300", 30) + "\u034f\u0300", - }, -} - -var appendTestsNFD = []AppendTest{ - // TODO: Move some of the tests here. -} - -var appendTestsNFKC = []AppendTest{ - // empty buffers - {"", "", ""}, - {"a", "", "a"}, - {"", "a", "a"}, - {"", "\u0041\u0307\u0304", "\u01E0"}, - // segment split across buffers - {"", "a\u0300b", "\u00E0b"}, - {"a", "\u0300b", "\u00E0b"}, - {"a", "\u0300\u0316", "\u00E0\u0316"}, - {"a", "\u0316\u0300", "\u00E0\u0316"}, - {"a", "\u0300a\u0300", "\u00E0\u00E0"}, - {"a", "\u0300a\u0300a\u0300", "\u00E0\u00E0\u00E0"}, - {"a", "\u0300aaa\u0300aaa\u0300", "\u00E0aa\u00E0aa\u00E0"}, - {"a\u0300", "\u0327", "\u00E0\u0327"}, - {"a\u0327", "\u0300", "\u00E0\u0327"}, - {"a\u0316", "\u0300", "\u00E0\u0316"}, - {"\u0041\u0307", "\u0304", "\u01E0"}, - // Hangul - {"", "\u110B\u1173", "\uC73C"}, - {"", "\u1103\u1161", "\uB2E4"}, - {"", "\u110B\u1173\u11B7", "\uC74C"}, - {"", "\u320E", "\x28\uAC00\x29"}, - {"", "\x28\u1100\u1161\x29", "\x28\uAC00\x29"}, - {"\u1103", "\u1161", "\uB2E4"}, - {"\u110B", "\u1173\u11B7", "\uC74C"}, - {"\u110B\u1173", "\u11B7", "\uC74C"}, - {"\uC73C", "\u11B7", "\uC74C"}, - // UTF-8 encoding split across buffers - {"a\xCC", "\x80", "\u00E0"}, - {"a\xCC", "\x80b", "\u00E0b"}, - {"a\xCC", "\x80a\u0300", "\u00E0\u00E0"}, - {"a\xCC", "\x80\x80", "\u00E0\x80"}, - {"a\xCC", "\x80\xCC", "\u00E0\xCC"}, - {"a\u0316\xCC", "\x80a\u0316\u0300", "\u00E0\u0316\u00E0\u0316"}, - // ending in incomplete UTF-8 encoding - {"", "\xCC", "\xCC"}, - {"a", "\xCC", "a\xCC"}, - {"a", "b\xCC", "ab\xCC"}, - {"\u0226", "\xCC", "\u0226\xCC"}, - // illegal runes - {"", "\x80", "\x80"}, - {"", "\x80\x80\x80", "\x80\x80\x80"}, - {"", "\xCC\x80\x80\x80", "\xCC\x80\x80\x80"}, - {"", "a\x80", "a\x80"}, - {"", "a\x80\x80\x80", "a\x80\x80\x80"}, - {"", "a\x80\x80\x80\x80\x80\x80", "a\x80\x80\x80\x80\x80\x80"}, - {"a", "\x80\x80\x80", "a\x80\x80\x80"}, - // overflow - {"", strings.Repeat("\x80", 33), strings.Repeat("\x80", 33)}, - {strings.Repeat("\x80", 33), "", strings.Repeat("\x80", 33)}, - {strings.Repeat("\x80", 33), strings.Repeat("\x80", 33), strings.Repeat("\x80", 66)}, - // overflow of combining characters - {"", grave(34), grave(30) + cgj + grave(4)}, - {"", grave(36), grave(30) + cgj + grave(6)}, - {grave(29), grave(5), grave(30) + cgj + grave(4)}, - {grave(30), grave(4), grave(30) + cgj + grave(4)}, - {grave(30), grave(3), grave(30) + cgj + grave(3)}, - {grave(30) + "\xCC", "\x80", grave(30) + cgj + grave(1)}, - {"", "\uFDFA" + grave(14), "\u0635\u0644\u0649 \u0627\u0644\u0644\u0647 \u0639\u0644\u064a\u0647 \u0648\u0633\u0644\u0645" + grave(14)}, - {"", "\uFDFA" + grave(28) + "\u0316", "\u0635\u0644\u0649 \u0627\u0644\u0644\u0647 \u0639\u0644\u064a\u0647 \u0648\u0633\u0644\u0645\u0316" + grave(28)}, - // - First rune has a trailing non-starter. - {"\u00d5", grave(30), "\u00d5" + grave(29) + cgj + grave(1)}, - // - U+FF9E decomposes into a non-starter in compatibility mode. A CGJ must be - // inserted even when FF9E starts a new segment. - {"\uff9e", grave(30), "\u3099" + grave(29) + cgj + grave(1)}, - {grave(30), "\uff9e", grave(30) + cgj + "\u3099"}, - // - Many non-starter decompositions in a row causing overflow. - {"", rep(0x340, 31), rep(0x300, 30) + cgj + "\u0300"}, - {"", rep(0xFF9E, 31), rep(0x3099, 30) + cgj + "\u3099"}, - - {"", "\u0644\u0625" + rep(0x300, 31), "\u0644\u0625" + rep(0x300, 29) + cgj + "\u0300\u0300"}, - {"", "\ufef9" + rep(0x300, 31), "\u0644\u0625" + rep(0x300, 29) + cgj + rep(0x0300, 2)}, - {"", "\ufef9" + rep(0x300, 31), "\u0644\u0625" + rep(0x300, 29) + cgj + rep(0x0300, 2)}, - - // U+0F81 TIBETAN VOWEL SIGN REVERSED II splits into two modifiers. - {"", "\u0f7f" + rep(0xf71, 29) + "\u0f81", "\u0f7f" + rep(0xf71, 29) + cgj + "\u0f71\u0f80"}, - {"", "\u0f7f" + rep(0xf71, 28) + "\u0f81", "\u0f7f" + rep(0xf71, 29) + "\u0f80"}, - {"", "\u0f7f" + rep(0xf81, 16), "\u0f7f" + rep(0xf71, 15) + rep(0xf80, 15) + cgj + "\u0f71\u0f80"}, - - // weird UTF-8 - {"\u00E0\xE1", "\x86", "\u00E0\xE1\x86"}, - {"a\u0300\u11B7", "\u0300", "\u00E0\u11B7\u0300"}, - {"a\u0300\u11B7\u0300", "\u0300", "\u00E0\u11B7\u0300\u0300"}, - {"\u0300", "\xF8\x80\x80\x80\x80\u0300", "\u0300\xF8\x80\x80\x80\x80\u0300"}, - {"\u0300", "\xFC\x80\x80\x80\x80\x80\u0300", "\u0300\xFC\x80\x80\x80\x80\x80\u0300"}, - {"\xF8\x80\x80\x80\x80\u0300", "\u0300", "\xF8\x80\x80\x80\x80\u0300\u0300"}, - {"\xFC\x80\x80\x80\x80\x80\u0300", "\u0300", "\xFC\x80\x80\x80\x80\x80\u0300\u0300"}, - {"\xF8\x80\x80\x80", "\x80\u0300\u0300", "\xF8\x80\x80\x80\x80\u0300\u0300"}, - - {"", strings.Repeat("a\u0316\u0300", 6), strings.Repeat("\u00E0\u0316", 6)}, - // large input. - {"", strings.Repeat("a\u0300\u0316", 31), strings.Repeat("\u00E0\u0316", 31)}, - {"", strings.Repeat("a\u0300\u0316", 4000), strings.Repeat("\u00E0\u0316", 4000)}, - {"", strings.Repeat("\x80\x80", 4000), strings.Repeat("\x80\x80", 4000)}, - {"", "\u0041\u0307\u0304", "\u01E0"}, -} - -var appendTestsNFKD = []AppendTest{ - {"", "a" + grave(64), "a" + grave(30) + cgj + grave(30) + cgj + grave(4)}, - - { // segment overflow on unchanged character - "", - "a" + grave(64) + "\u0316", - "a" + grave(30) + cgj + grave(30) + cgj + "\u0316" + grave(4), - }, - { // segment overflow on unchanged character + start value - "", - "a" + grave(98) + "\u0316", - "a" + grave(30) + cgj + grave(30) + cgj + grave(30) + cgj + "\u0316" + grave(8), - }, - { // segment overflow on decomposition. (U+0340 decomposes to U+0300.) - "", - "a" + grave(59) + "\u0340", - "a" + grave(30) + cgj + grave(30), - }, - { // segment overflow on non-starter decomposition - "", - "a" + grave(33) + "\u0340" + grave(30) + "\u0320", - "a" + grave(30) + cgj + grave(30) + cgj + "\u0320" + grave(4), - }, - { // start value after ASCII overflow - "", - rep('a', segSize) + grave(32) + "\u0320", - rep('a', segSize) + grave(30) + cgj + "\u0320" + grave(2), - }, - { // Jamo overflow - "", - "\u1100\u1161" + grave(30) + "\u0320" + grave(2), - "\u1100\u1161" + grave(29) + cgj + "\u0320" + grave(3), - }, - { // Hangul - "", - "\uac00", - "\u1100\u1161", - }, - { // Hangul overflow - "", - "\uac00" + grave(32) + "\u0320", - "\u1100\u1161" + grave(29) + cgj + "\u0320" + grave(3), - }, - { // Hangul overflow in Hangul mode. - "", - "\uac00\uac00" + grave(32) + "\u0320", - "\u1100\u1161\u1100\u1161" + grave(29) + cgj + "\u0320" + grave(3), - }, - { // Hangul overflow in Hangul mode. - "", - strings.Repeat("\uac00", 3) + grave(32) + "\u0320", - strings.Repeat("\u1100\u1161", 3) + grave(29) + cgj + "\u0320" + grave(3), - }, - { // start value after cc=0 - "", - "您您" + grave(34) + "\u0320", - "您您" + grave(30) + cgj + "\u0320" + grave(4), - }, - { // start value after normalization - "", - "\u0300\u0320a" + grave(34) + "\u0320", - "\u0320\u0300a" + grave(30) + cgj + "\u0320" + grave(4), - }, - { - // U+0F81 TIBETAN VOWEL SIGN REVERSED II splits into two modifiers. - "", - "a\u0f7f" + rep(0xf71, 29) + "\u0f81", - "a\u0f7f" + rep(0xf71, 29) + cgj + "\u0f71\u0f80", - }, -} - -func TestAppend(t *testing.T) { - runNormTests(t, "Append", func(f Form, out []byte, s string) []byte { - return f.Append(out, []byte(s)...) - }) -} - -func TestAppendString(t *testing.T) { - runNormTests(t, "AppendString", func(f Form, out []byte, s string) []byte { - return f.AppendString(out, s) - }) -} - -func TestBytes(t *testing.T) { - runNormTests(t, "Bytes", func(f Form, out []byte, s string) []byte { - buf := []byte{} - buf = append(buf, out...) - buf = append(buf, s...) - return f.Bytes(buf) - }) -} - -func TestString(t *testing.T) { - runNormTests(t, "String", func(f Form, out []byte, s string) []byte { - outs := string(out) + s - return []byte(f.String(outs)) - }) -} - -func TestLinking(t *testing.T) { - const prog = ` - package main - import "fmt" - import "golang.org/x/text/unicode/norm" - func main() { fmt.Println(norm.%s) } - ` - baseline, errB := testtext.CodeSize(fmt.Sprintf(prog, "MaxSegmentSize")) - withTables, errT := testtext.CodeSize(fmt.Sprintf(prog, `NFC.String("")`)) - if errB != nil || errT != nil { - t.Skipf("code size failed: %v and %v", errB, errT) - } - // Tables are at least 50K - if d := withTables - baseline; d < 50*1024 { - t.Errorf("tables appear not to be dropped: %d - %d = %d", - withTables, baseline, d) - } -} - -func appendBench(f Form, in []byte) func() { - buf := make([]byte, 0, 4*len(in)) - return func() { - f.Append(buf, in...) - } -} - -func bytesBench(f Form, in []byte) func() { - return func() { - f.Bytes(in) - } -} - -func iterBench(f Form, in []byte) func() { - iter := Iter{} - return func() { - iter.Init(f, in) - for !iter.Done() { - iter.Next() - } - } -} - -func transformBench(f Form, in []byte) func() { - buf := make([]byte, 4*len(in)) - return func() { - if _, n, err := f.Transform(buf, in, true); err != nil || len(in) != n { - log.Panic(n, len(in), err) - } - } -} - -func readerBench(f Form, in []byte) func() { - buf := make([]byte, 4*len(in)) - return func() { - r := f.Reader(bytes.NewReader(in)) - var err error - for err == nil { - _, err = r.Read(buf) - } - if err != io.EOF { - panic("") - } - } -} - -func writerBench(f Form, in []byte) func() { - buf := make([]byte, 0, 4*len(in)) - return func() { - r := f.Writer(bytes.NewBuffer(buf)) - if _, err := r.Write(in); err != nil { - panic("") - } - } -} - -func appendBenchmarks(bm []func(), f Form, in []byte) []func() { - bm = append(bm, appendBench(f, in)) - bm = append(bm, iterBench(f, in)) - bm = append(bm, transformBench(f, in)) - bm = append(bm, readerBench(f, in)) - bm = append(bm, writerBench(f, in)) - return bm -} - -func doFormBenchmark(b *testing.B, inf, f Form, s string) { - b.StopTimer() - in := inf.Bytes([]byte(s)) - bm := appendBenchmarks(nil, f, in) - b.SetBytes(int64(len(in) * len(bm))) - b.StartTimer() - for i := 0; i < b.N; i++ { - for _, fn := range bm { - fn() - } - } -} - -func doSingle(b *testing.B, f func(Form, []byte) func(), s []byte) { - b.StopTimer() - fn := f(NFC, s) - b.SetBytes(int64(len(s))) - b.StartTimer() - for i := 0; i < b.N; i++ { - fn() - } -} - -var ( - smallNoChange = []byte("nörmalization") - smallChange = []byte("No\u0308rmalization") - ascii = strings.Repeat("There is nothing to change here! ", 500) -) - -func lowerBench(f Form, in []byte) func() { - // Use package strings instead of bytes as it doesn't allocate memory - // if there aren't any changes. - s := string(in) - return func() { - strings.ToLower(s) - } -} - -func BenchmarkLowerCaseNoChange(b *testing.B) { - doSingle(b, lowerBench, smallNoChange) -} -func BenchmarkLowerCaseChange(b *testing.B) { - doSingle(b, lowerBench, smallChange) -} - -func quickSpanBench(f Form, in []byte) func() { - return func() { - f.QuickSpan(in) - } -} - -func BenchmarkQuickSpanChangeNFC(b *testing.B) { - doSingle(b, quickSpanBench, smallNoChange) -} - -func BenchmarkBytesNoChangeNFC(b *testing.B) { - doSingle(b, bytesBench, smallNoChange) -} -func BenchmarkBytesChangeNFC(b *testing.B) { - doSingle(b, bytesBench, smallChange) -} - -func BenchmarkAppendNoChangeNFC(b *testing.B) { - doSingle(b, appendBench, smallNoChange) -} -func BenchmarkAppendChangeNFC(b *testing.B) { - doSingle(b, appendBench, smallChange) -} -func BenchmarkAppendLargeNFC(b *testing.B) { - doSingle(b, appendBench, txt_all_bytes) -} - -func BenchmarkIterNoChangeNFC(b *testing.B) { - doSingle(b, iterBench, smallNoChange) -} -func BenchmarkIterChangeNFC(b *testing.B) { - doSingle(b, iterBench, smallChange) -} -func BenchmarkIterLargeNFC(b *testing.B) { - doSingle(b, iterBench, txt_all_bytes) -} - -func BenchmarkTransformNoChangeNFC(b *testing.B) { - doSingle(b, transformBench, smallNoChange) -} -func BenchmarkTransformChangeNFC(b *testing.B) { - doSingle(b, transformBench, smallChange) -} -func BenchmarkTransformLargeNFC(b *testing.B) { - doSingle(b, transformBench, txt_all_bytes) -} - -func BenchmarkNormalizeAsciiNFC(b *testing.B) { - doFormBenchmark(b, NFC, NFC, ascii) -} -func BenchmarkNormalizeAsciiNFD(b *testing.B) { - doFormBenchmark(b, NFC, NFD, ascii) -} -func BenchmarkNormalizeAsciiNFKC(b *testing.B) { - doFormBenchmark(b, NFC, NFKC, ascii) -} -func BenchmarkNormalizeAsciiNFKD(b *testing.B) { - doFormBenchmark(b, NFC, NFKD, ascii) -} - -func BenchmarkNormalizeNFC2NFC(b *testing.B) { - doFormBenchmark(b, NFC, NFC, txt_all) -} -func BenchmarkNormalizeNFC2NFD(b *testing.B) { - doFormBenchmark(b, NFC, NFD, txt_all) -} -func BenchmarkNormalizeNFD2NFC(b *testing.B) { - doFormBenchmark(b, NFD, NFC, txt_all) -} -func BenchmarkNormalizeNFD2NFD(b *testing.B) { - doFormBenchmark(b, NFD, NFD, txt_all) -} - -// Hangul is often special-cased, so we test it separately. -func BenchmarkNormalizeHangulNFC2NFC(b *testing.B) { - doFormBenchmark(b, NFC, NFC, txt_kr) -} -func BenchmarkNormalizeHangulNFC2NFD(b *testing.B) { - doFormBenchmark(b, NFC, NFD, txt_kr) -} -func BenchmarkNormalizeHangulNFD2NFC(b *testing.B) { - doFormBenchmark(b, NFD, NFC, txt_kr) -} -func BenchmarkNormalizeHangulNFD2NFD(b *testing.B) { - doFormBenchmark(b, NFD, NFD, txt_kr) -} - -var forms = []Form{NFC, NFD, NFKC, NFKD} - -func doTextBenchmark(b *testing.B, s string) { - b.StopTimer() - in := []byte(s) - bm := []func(){} - for _, f := range forms { - bm = appendBenchmarks(bm, f, in) - } - b.SetBytes(int64(len(s) * len(bm))) - b.StartTimer() - for i := 0; i < b.N; i++ { - for _, f := range bm { - f() - } - } -} - -func BenchmarkCanonicalOrdering(b *testing.B) { - doTextBenchmark(b, txt_canon) -} -func BenchmarkExtendedLatin(b *testing.B) { - doTextBenchmark(b, txt_vn) -} -func BenchmarkMiscTwoByteUtf8(b *testing.B) { - doTextBenchmark(b, twoByteUtf8) -} -func BenchmarkMiscThreeByteUtf8(b *testing.B) { - doTextBenchmark(b, threeByteUtf8) -} -func BenchmarkHangul(b *testing.B) { - doTextBenchmark(b, txt_kr) -} -func BenchmarkJapanese(b *testing.B) { - doTextBenchmark(b, txt_jp) -} -func BenchmarkChinese(b *testing.B) { - doTextBenchmark(b, txt_cn) -} -func BenchmarkOverflow(b *testing.B) { - doTextBenchmark(b, overflow) -} - -var overflow = string(bytes.Repeat([]byte("\u035D"), 4096)) + "\u035B" - -// Tests sampled from the Canonical ordering tests (Part 2) of -// http://unicode.org/Public/UNIDATA/NormalizationTest.txt -const txt_canon = `\u0061\u0315\u0300\u05AE\u0300\u0062 \u0061\u0300\u0315\u0300\u05AE\u0062 -\u0061\u0302\u0315\u0300\u05AE\u0062 \u0061\u0307\u0315\u0300\u05AE\u0062 -\u0061\u0315\u0300\u05AE\u030A\u0062 \u0061\u059A\u0316\u302A\u031C\u0062 -\u0061\u032E\u059A\u0316\u302A\u0062 \u0061\u0338\u093C\u0334\u0062 -\u0061\u059A\u0316\u302A\u0339 \u0061\u0341\u0315\u0300\u05AE\u0062 -\u0061\u0348\u059A\u0316\u302A\u0062 \u0061\u0361\u0345\u035D\u035C\u0062 -\u0061\u0366\u0315\u0300\u05AE\u0062 \u0061\u0315\u0300\u05AE\u0486\u0062 -\u0061\u05A4\u059A\u0316\u302A\u0062 \u0061\u0315\u0300\u05AE\u0613\u0062 -\u0061\u0315\u0300\u05AE\u0615\u0062 \u0061\u0617\u0315\u0300\u05AE\u0062 -\u0061\u0619\u0618\u064D\u064E\u0062 \u0061\u0315\u0300\u05AE\u0654\u0062 -\u0061\u0315\u0300\u05AE\u06DC\u0062 \u0061\u0733\u0315\u0300\u05AE\u0062 -\u0061\u0744\u059A\u0316\u302A\u0062 \u0061\u0315\u0300\u05AE\u0745\u0062 -\u0061\u09CD\u05B0\u094D\u3099\u0062 \u0061\u0E38\u0E48\u0E38\u0C56\u0062 -\u0061\u0EB8\u0E48\u0E38\u0E49\u0062 \u0061\u0F72\u0F71\u0EC8\u0F71\u0062 -\u0061\u1039\u05B0\u094D\u3099\u0062 \u0061\u05B0\u094D\u3099\u1A60\u0062 -\u0061\u3099\u093C\u0334\u1BE6\u0062 \u0061\u3099\u093C\u0334\u1C37\u0062 -\u0061\u1CD9\u059A\u0316\u302A\u0062 \u0061\u2DED\u0315\u0300\u05AE\u0062 -\u0061\u2DEF\u0315\u0300\u05AE\u0062 \u0061\u302D\u302E\u059A\u0316\u0062` - -// Taken from http://creativecommons.org/licenses/by-sa/3.0/vn/ -const txt_vn = `Với các điều kiện sau: Ghi nhận công của tác giả. -Nếu bạn sử dụng, chuyển đổi, hoặc xây dựng dự án từ -nội dung được chia sẻ này, bạn phải áp dụng giấy phép này hoặc -một giấy phép khác có các điều khoản tương tự như giấy phép này -cho dự án của bạn. Hiểu rằng: Miễn — Bất kỳ các điều kiện nào -trên đây cũng có thể được miễn bỏ nếu bạn được sự cho phép của -người sở hữu bản quyền. Phạm vi công chúng — Khi tác phẩm hoặc -bất kỳ chương nào của tác phẩm đã trong vùng dành cho công -chúng theo quy định của pháp luật thì tình trạng của nó không -bị ảnh hưởng bởi giấy phép trong bất kỳ trường hợp nào.` - -// Taken from http://creativecommons.org/licenses/by-sa/1.0/deed.ru -const txt_ru = `При обязательном соблюдении следующих условий: -Attribution — Вы должны атрибутировать произведение (указывать -автора и источник) в порядке, предусмотренном автором или -лицензиаром (но только так, чтобы никоим образом не подразумевалось, -что они поддерживают вас или использование вами данного произведения). -Υπό τις ακόλουθες προϋποθέσεις:` - -// Taken from http://creativecommons.org/licenses/by-sa/3.0/gr/ -const txt_gr = `Αναφορά Δημιουργού — Θα πρέπει να κάνετε την αναφορά στο έργο με τον -τρόπο που έχει οριστεί από το δημιουργό ή το χορηγούντο την άδεια -(χωρίς όμως να εννοείται με οποιονδήποτε τρόπο ότι εγκρίνουν εσάς ή -τη χρήση του έργου από εσάς). Παρόμοια Διανομή — Εάν αλλοιώσετε, -τροποποιήσετε ή δημιουργήσετε περαιτέρω βασισμένοι στο έργο θα -μπορείτε να διανέμετε το έργο που θα προκύψει μόνο με την ίδια ή -παρόμοια άδεια.` - -// Taken from http://creativecommons.org/licenses/by-sa/3.0/deed.ar -const txt_ar = `بموجب الشروط التالية نسب المصنف — يجب عليك أن -تنسب العمل بالطريقة التي تحددها المؤلف أو المرخص (ولكن ليس بأي حال من -الأحوال أن توحي وتقترح بتحول أو استخدامك للعمل). -المشاركة على قدم المساواة — إذا كنت يعدل ، والتغيير ، أو الاستفادة -من هذا العمل ، قد ينتج عن توزيع العمل إلا في ظل تشابه او تطابق فى واحد -لهذا الترخيص.` - -// Taken from http://creativecommons.org/licenses/by-sa/1.0/il/ -const txt_il = `בכפוף לתנאים הבאים: ייחוס — עליך לייחס את היצירה (לתת קרדיט) באופן -המצויין על-ידי היוצר או מעניק הרישיון (אך לא בשום אופן המרמז על כך -שהם תומכים בך או בשימוש שלך ביצירה). שיתוף זהה — אם תחליט/י לשנות, -לעבד או ליצור יצירה נגזרת בהסתמך על יצירה זו, תוכל/י להפיץ את יצירתך -החדשה רק תחת אותו הרישיון או רישיון דומה לרישיון זה.` - -const twoByteUtf8 = txt_ru + txt_gr + txt_ar + txt_il - -// Taken from http://creativecommons.org/licenses/by-sa/2.0/kr/ -const txt_kr = `다음과 같은 조건을 따라야 합니다: 저작자표시 -(Attribution) — 저작자나 이용허락자가 정한 방법으로 저작물의 -원저작자를 표시하여야 합니다(그러나 원저작자가 이용자나 이용자의 -이용을 보증하거나 추천한다는 의미로 표시해서는 안됩니다). -동일조건변경허락 — 이 저작물을 이용하여 만든 이차적 저작물에는 본 -라이선스와 동일한 라이선스를 적용해야 합니다.` - -// Taken from http://creativecommons.org/licenses/by-sa/3.0/th/ -const txt_th = `ภายใต้เงื่อนไข ดังต่อไปนี้ : แสดงที่มา — คุณต้องแสดงที่ -มาของงานดังกล่าว ตามรูปแบบที่ผู้สร้างสรรค์หรือผู้อนุญาตกำหนด (แต่ -ไม่ใช่ในลักษณะที่ว่า พวกเขาสนับสนุนคุณหรือสนับสนุนการที่ -คุณนำงานไปใช้) อนุญาตแบบเดียวกัน — หากคุณดัดแปลง เปลี่ยนรูป หรื -อต่อเติมงานนี้ คุณต้องใช้สัญญาอนุญาตแบบเดียวกันหรือแบบที่เหมื -อนกับสัญญาอนุญาตที่ใช้กับงานนี้เท่านั้น` - -const threeByteUtf8 = txt_th - -// Taken from http://creativecommons.org/licenses/by-sa/2.0/jp/ -const txt_jp = `あなたの従うべき条件は以下の通りです。 -表示 — あなたは原著作者のクレジットを表示しなければなりません。 -継承 — もしあなたがこの作品を改変、変形または加工した場合、 -あなたはその結果生じた作品をこの作品と同一の許諾条件の下でのみ -頒布することができます。` - -// http://creativecommons.org/licenses/by-sa/2.5/cn/ -const txt_cn = `您可以自由: 复制、发行、展览、表演、放映、 -广播或通过信息网络传播本作品 创作演绎作品 -对本作品进行商业性使用 惟须遵守下列条件: -署名 — 您必须按照作者或者许可人指定的方式对作品进行署名。 -相同方式共享 — 如果您改变、转换本作品或者以本作品为基础进行创作, -您只能采用与本协议相同的许可协议发布基于本作品的演绎作品。` - -const txt_cjk = txt_cn + txt_jp + txt_kr -const txt_all = txt_vn + twoByteUtf8 + threeByteUtf8 + txt_cjk - -var txt_all_bytes = []byte(txt_all) diff --git a/vendor/golang.org/x/text/unicode/norm/readwriter_test.go b/vendor/golang.org/x/text/unicode/norm/readwriter_test.go deleted file mode 100644 index b7756ba2..00000000 --- a/vendor/golang.org/x/text/unicode/norm/readwriter_test.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package norm - -import ( - "bytes" - "fmt" - "testing" -) - -var bufSizes = []int{1, 2, 3, 4, 5, 6, 7, 8, 100, 101, 102, 103, 4000, 4001, 4002, 4003} - -func readFunc(size int) appendFunc { - return func(f Form, out []byte, s string) []byte { - out = append(out, s...) - r := f.Reader(bytes.NewBuffer(out)) - buf := make([]byte, size) - result := []byte{} - for n, err := 0, error(nil); err == nil; { - n, err = r.Read(buf) - result = append(result, buf[:n]...) - } - return result - } -} - -func TestReader(t *testing.T) { - for _, s := range bufSizes { - name := fmt.Sprintf("TestReader%d", s) - runNormTests(t, name, readFunc(s)) - } -} - -func writeFunc(size int) appendFunc { - return func(f Form, out []byte, s string) []byte { - in := append(out, s...) - result := new(bytes.Buffer) - w := f.Writer(result) - buf := make([]byte, size) - for n := 0; len(in) > 0; in = in[n:] { - n = copy(buf, in) - _, _ = w.Write(buf[:n]) - } - w.Close() - return result.Bytes() - } -} - -func TestWriter(t *testing.T) { - for _, s := range bufSizes { - name := fmt.Sprintf("TestWriter%d", s) - runNormTests(t, name, writeFunc(s)) - } -} diff --git a/vendor/golang.org/x/text/unicode/norm/transform_test.go b/vendor/golang.org/x/text/unicode/norm/transform_test.go deleted file mode 100644 index d596ff3d..00000000 --- a/vendor/golang.org/x/text/unicode/norm/transform_test.go +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package norm - -import ( - "fmt" - "testing" - - "golang.org/x/text/transform" -) - -func TestTransform(t *testing.T) { - tests := []struct { - f Form - in, out string - eof bool - dstSize int - err error - }{ - {NFC, "ab", "ab", true, 2, nil}, - {NFC, "qx", "qx", true, 2, nil}, - {NFD, "qx", "qx", true, 2, nil}, - {NFC, "", "", true, 1, nil}, - {NFD, "", "", true, 1, nil}, - {NFC, "", "", false, 1, nil}, - {NFD, "", "", false, 1, nil}, - - // Normalized segment does not fit in destination. - {NFD, "ö", "", true, 1, transform.ErrShortDst}, - {NFD, "ö", "", true, 2, transform.ErrShortDst}, - - // As an artifact of the algorithm, only full segments are written. - // This is not strictly required, and some bytes could be written. - // In practice, for Transform to not block, the destination buffer - // should be at least MaxSegmentSize to work anyway and these edge - // conditions will be relatively rare. - {NFC, "ab", "", true, 1, transform.ErrShortDst}, - // This is even true for inert runes. - {NFC, "qx", "", true, 1, transform.ErrShortDst}, - {NFC, "a\u0300abc", "\u00e0a", true, 4, transform.ErrShortDst}, - - // We cannot write a segment if successive runes could still change the result. - {NFD, "ö", "", false, 3, transform.ErrShortSrc}, - {NFC, "a\u0300", "", false, 4, transform.ErrShortSrc}, - {NFD, "a\u0300", "", false, 4, transform.ErrShortSrc}, - {NFC, "ö", "", false, 3, transform.ErrShortSrc}, - - {NFC, "a\u0300", "", true, 1, transform.ErrShortDst}, - // Theoretically could fit, but won't due to simplified checks. - {NFC, "a\u0300", "", true, 2, transform.ErrShortDst}, - {NFC, "a\u0300", "", true, 3, transform.ErrShortDst}, - {NFC, "a\u0300", "\u00e0", true, 4, nil}, - - {NFD, "öa\u0300", "o\u0308", false, 8, transform.ErrShortSrc}, - {NFD, "öa\u0300ö", "o\u0308a\u0300", true, 8, transform.ErrShortDst}, - {NFD, "öa\u0300ö", "o\u0308a\u0300", false, 12, transform.ErrShortSrc}, - - // Illegal input is copied verbatim. - {NFD, "\xbd\xb2=\xbc ", "\xbd\xb2=\xbc ", true, 8, nil}, - } - b := make([]byte, 100) - for i, tt := range tests { - nDst, _, err := tt.f.Transform(b[:tt.dstSize], []byte(tt.in), tt.eof) - out := string(b[:nDst]) - if out != tt.out || err != tt.err { - t.Errorf("%d: was %+q (%v); want %+q (%v)", i, out, err, tt.out, tt.err) - } - if want := tt.f.String(tt.in)[:nDst]; want != out { - t.Errorf("%d: incorrect normalization: was %+q; want %+q", i, out, want) - } - } -} - -var transBufSizes = []int{ - MaxTransformChunkSize, - 3 * MaxTransformChunkSize / 2, - 2 * MaxTransformChunkSize, - 3 * MaxTransformChunkSize, - 100 * MaxTransformChunkSize, -} - -func doTransNorm(f Form, buf []byte, b []byte) []byte { - acc := []byte{} - for p := 0; p < len(b); { - nd, ns, _ := f.Transform(buf[:], b[p:], true) - p += ns - acc = append(acc, buf[:nd]...) - } - return acc -} - -func TestTransformNorm(t *testing.T) { - for _, sz := range transBufSizes { - buf := make([]byte, sz) - runNormTests(t, fmt.Sprintf("Transform:%d", sz), func(f Form, out []byte, s string) []byte { - return doTransNorm(f, buf, append(out, s...)) - }) - } -} diff --git a/vendor/golang.org/x/text/unicode/norm/ucd_test.go b/vendor/golang.org/x/text/unicode/norm/ucd_test.go deleted file mode 100644 index 29205a6a..00000000 --- a/vendor/golang.org/x/text/unicode/norm/ucd_test.go +++ /dev/null @@ -1,275 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package norm - -import ( - "bufio" - "bytes" - "fmt" - "regexp" - "runtime" - "strconv" - "strings" - "sync" - "testing" - "time" - "unicode/utf8" - - "golang.org/x/text/internal/gen" - "golang.org/x/text/internal/testtext" -) - -var once sync.Once - -func skipShort(t *testing.T) { - testtext.SkipIfNotLong(t) - - once.Do(func() { loadTestData(t) }) -} - -// This regression test runs the test set in NormalizationTest.txt -// (taken from http://www.unicode.org/Public//ucd/). -// -// NormalizationTest.txt has form: -// @Part0 # Specific cases -// # -// 1E0A;1E0A;0044 0307;1E0A;0044 0307; # (Ḋ; Ḋ; D◌̇; Ḋ; D◌̇; ) LATIN CAPITAL LETTER D WITH DOT ABOVE -// 1E0C;1E0C;0044 0323;1E0C;0044 0323; # (Ḍ; Ḍ; D◌̣; Ḍ; D◌̣; ) LATIN CAPITAL LETTER D WITH DOT BELOW -// -// Each test has 5 columns (c1, c2, c3, c4, c5), where -// (c1, c2, c3, c4, c5) == (c1, NFC(c1), NFD(c1), NFKC(c1), NFKD(c1)) -// -// CONFORMANCE: -// 1. The following invariants must be true for all conformant implementations -// -// NFC -// c2 == NFC(c1) == NFC(c2) == NFC(c3) -// c4 == NFC(c4) == NFC(c5) -// -// NFD -// c3 == NFD(c1) == NFD(c2) == NFD(c3) -// c5 == NFD(c4) == NFD(c5) -// -// NFKC -// c4 == NFKC(c1) == NFKC(c2) == NFKC(c3) == NFKC(c4) == NFKC(c5) -// -// NFKD -// c5 == NFKD(c1) == NFKD(c2) == NFKD(c3) == NFKD(c4) == NFKD(c5) -// -// 2. For every code point X assigned in this version of Unicode that is not -// specifically listed in Part 1, the following invariants must be true -// for all conformant implementations: -// -// X == NFC(X) == NFD(X) == NFKC(X) == NFKD(X) -// - -// Column types. -const ( - cRaw = iota - cNFC - cNFD - cNFKC - cNFKD - cMaxColumns -) - -// Holds data from NormalizationTest.txt -var part []Part - -type Part struct { - name string - number int - tests []Test -} - -type Test struct { - name string - partnr int - number int - r rune // used for character by character test - cols [cMaxColumns]string // Each has 5 entries, see below. -} - -func (t Test) Name() string { - if t.number < 0 { - return part[t.partnr].name - } - return fmt.Sprintf("%s:%d", part[t.partnr].name, t.number) -} - -var partRe = regexp.MustCompile(`@Part(\d) # (.*)$`) -var testRe = regexp.MustCompile(`^` + strings.Repeat(`([\dA-F ]+);`, 5) + ` # (.*)$`) - -var counter int - -// Load the data form NormalizationTest.txt -func loadTestData(t *testing.T) { - f := gen.OpenUCDFile("NormalizationTest.txt") - defer f.Close() - scanner := bufio.NewScanner(f) - for scanner.Scan() { - line := scanner.Text() - if len(line) == 0 || line[0] == '#' { - continue - } - m := partRe.FindStringSubmatch(line) - if m != nil { - if len(m) < 3 { - t.Fatal("Failed to parse Part: ", line) - } - i, err := strconv.Atoi(m[1]) - if err != nil { - t.Fatal(err) - } - name := m[2] - part = append(part, Part{name: name[:len(name)-1], number: i}) - continue - } - m = testRe.FindStringSubmatch(line) - if m == nil || len(m) < 7 { - t.Fatalf(`Failed to parse: "%s" result: %#v`, line, m) - } - test := Test{name: m[6], partnr: len(part) - 1, number: counter} - counter++ - for j := 1; j < len(m)-1; j++ { - for _, split := range strings.Split(m[j], " ") { - r, err := strconv.ParseUint(split, 16, 64) - if err != nil { - t.Fatal(err) - } - if test.r == 0 { - // save for CharacterByCharacterTests - test.r = rune(r) - } - var buf [utf8.UTFMax]byte - sz := utf8.EncodeRune(buf[:], rune(r)) - test.cols[j-1] += string(buf[:sz]) - } - } - part := &part[len(part)-1] - part.tests = append(part.tests, test) - } - if scanner.Err() != nil { - t.Fatal(scanner.Err()) - } -} - -func cmpResult(t *testing.T, tc *Test, name string, f Form, gold, test, result string) { - if gold != result { - t.Errorf("%s:%s: %s(%+q)=%+q; want %+q: %s", - tc.Name(), name, fstr[f], test, result, gold, tc.name) - } -} - -func cmpIsNormal(t *testing.T, tc *Test, name string, f Form, test string, result, want bool) { - if result != want { - t.Errorf("%s:%s: %s(%+q)=%v; want %v", tc.Name(), name, fstr[f], test, result, want) - } -} - -func doTest(t *testing.T, tc *Test, f Form, gold, test string) { - testb := []byte(test) - result := f.Bytes(testb) - cmpResult(t, tc, "Bytes", f, gold, test, string(result)) - - sresult := f.String(test) - cmpResult(t, tc, "String", f, gold, test, sresult) - - acc := []byte{} - i := Iter{} - i.InitString(f, test) - for !i.Done() { - acc = append(acc, i.Next()...) - } - cmpResult(t, tc, "Iter.Next", f, gold, test, string(acc)) - - buf := make([]byte, 128) - acc = nil - for p := 0; p < len(testb); { - nDst, nSrc, _ := f.Transform(buf, testb[p:], true) - acc = append(acc, buf[:nDst]...) - p += nSrc - } - cmpResult(t, tc, "Transform", f, gold, test, string(acc)) - - for i := range test { - out := f.Append(f.Bytes([]byte(test[:i])), []byte(test[i:])...) - cmpResult(t, tc, fmt.Sprintf(":Append:%d", i), f, gold, test, string(out)) - } - cmpIsNormal(t, tc, "IsNormal", f, test, f.IsNormal([]byte(test)), test == gold) - cmpIsNormal(t, tc, "IsNormalString", f, test, f.IsNormalString(test), test == gold) -} - -func doConformanceTests(t *testing.T, tc *Test, partn int) { - for i := 0; i <= 2; i++ { - doTest(t, tc, NFC, tc.cols[1], tc.cols[i]) - doTest(t, tc, NFD, tc.cols[2], tc.cols[i]) - doTest(t, tc, NFKC, tc.cols[3], tc.cols[i]) - doTest(t, tc, NFKD, tc.cols[4], tc.cols[i]) - } - for i := 3; i <= 4; i++ { - doTest(t, tc, NFC, tc.cols[3], tc.cols[i]) - doTest(t, tc, NFD, tc.cols[4], tc.cols[i]) - doTest(t, tc, NFKC, tc.cols[3], tc.cols[i]) - doTest(t, tc, NFKD, tc.cols[4], tc.cols[i]) - } -} - -func TestCharacterByCharacter(t *testing.T) { - skipShort(t) - tests := part[1].tests - var last rune = 0 - for i := 0; i <= len(tests); i++ { // last one is special case - var r rune - if i == len(tests) { - r = 0x2FA1E // Don't have to go to 0x10FFFF - } else { - r = tests[i].r - } - for last++; last < r; last++ { - // Check all characters that were not explicitly listed in the test. - tc := &Test{partnr: 1, number: -1} - char := string(last) - doTest(t, tc, NFC, char, char) - doTest(t, tc, NFD, char, char) - doTest(t, tc, NFKC, char, char) - doTest(t, tc, NFKD, char, char) - } - if i < len(tests) { - doConformanceTests(t, &tests[i], 1) - } - } -} - -func TestStandardTests(t *testing.T) { - skipShort(t) - for _, j := range []int{0, 2, 3} { - for _, test := range part[j].tests { - doConformanceTests(t, &test, j) - } - } -} - -// TestPerformance verifies that normalization is O(n). If any of the -// code does not properly check for maxCombiningChars, normalization -// may exhibit O(n**2) behavior. -func TestPerformance(t *testing.T) { - skipShort(t) - runtime.GOMAXPROCS(2) - success := make(chan bool, 1) - go func() { - buf := bytes.Repeat([]byte("\u035D"), 1024*1024) - buf = append(buf, "\u035B"...) - NFC.Append(nil, buf...) - success <- true - }() - timeout := time.After(1 * time.Second) - select { - case <-success: - // test completed before the timeout - case <-timeout: - t.Errorf(`unexpectedly long time to complete PerformanceTest`) - } -} diff --git a/vendor/golang.org/x/text/unicode/rangetable/merge_test.go b/vendor/golang.org/x/text/unicode/rangetable/merge_test.go deleted file mode 100644 index 93ed0fca..00000000 --- a/vendor/golang.org/x/text/unicode/rangetable/merge_test.go +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package rangetable - -import ( - "testing" - "unicode" -) - -var ( - maxRuneTable = &unicode.RangeTable{ - R32: []unicode.Range32{ - {unicode.MaxRune, unicode.MaxRune, 1}, - }, - } - - overlap1 = &unicode.RangeTable{ - R16: []unicode.Range16{ - {0x100, 0xfffc, 4}, - }, - R32: []unicode.Range32{ - {0x100000, 0x10fffc, 4}, - }, - } - - overlap2 = &unicode.RangeTable{ - R16: []unicode.Range16{ - {0x101, 0xfffd, 4}, - }, - R32: []unicode.Range32{ - {0x100001, 0x10fffd, 3}, - }, - } - - // The following table should be compacted into two entries for R16 and R32. - optimize = &unicode.RangeTable{ - R16: []unicode.Range16{ - {0x1, 0x1, 1}, - {0x2, 0x2, 1}, - {0x3, 0x3, 1}, - {0x5, 0x5, 1}, - {0x7, 0x7, 1}, - {0x9, 0x9, 1}, - {0xb, 0xf, 2}, - }, - R32: []unicode.Range32{ - {0x10001, 0x10001, 1}, - {0x10002, 0x10002, 1}, - {0x10003, 0x10003, 1}, - {0x10005, 0x10005, 1}, - {0x10007, 0x10007, 1}, - {0x10009, 0x10009, 1}, - {0x1000b, 0x1000f, 2}, - }, - } -) - -func TestMerge(t *testing.T) { - for i, tt := range [][]*unicode.RangeTable{ - {unicode.Cc, unicode.Cf}, - {unicode.L, unicode.Ll}, - {unicode.L, unicode.Ll, unicode.Lu}, - {unicode.Ll, unicode.Lu}, - {unicode.M}, - unicode.GraphicRanges, - cased, - - // Merge R16 only and R32 only and vice versa. - {unicode.Khmer, unicode.Khudawadi}, - {unicode.Imperial_Aramaic, unicode.Radical}, - - // Merge with empty. - {&unicode.RangeTable{}}, - {&unicode.RangeTable{}, &unicode.RangeTable{}}, - {&unicode.RangeTable{}, &unicode.RangeTable{}, &unicode.RangeTable{}}, - {&unicode.RangeTable{}, unicode.Hiragana}, - {unicode.Inherited, &unicode.RangeTable{}}, - {&unicode.RangeTable{}, unicode.Hanunoo, &unicode.RangeTable{}}, - - // Hypothetical tables. - {maxRuneTable}, - {overlap1, overlap2}, - - // Optimization - {optimize}, - } { - rt := Merge(tt...) - for r := rune(0); r <= unicode.MaxRune; r++ { - if got, want := unicode.Is(rt, r), unicode.In(r, tt...); got != want { - t.Fatalf("%d:%U: got %v; want %v", i, r, got, want) - } - } - // Test optimization and correctness for R16. - for k := 0; k < len(rt.R16)-1; k++ { - if lo, hi := rt.R16[k].Lo, rt.R16[k].Hi; lo > hi { - t.Errorf("%d: Lo (%x) > Hi (%x)", i, lo, hi) - } - if hi, lo := rt.R16[k].Hi, rt.R16[k+1].Lo; hi >= lo { - t.Errorf("%d: Hi (%x) >= next Lo (%x)", i, hi, lo) - } - if rt.R16[k].Hi+rt.R16[k].Stride == rt.R16[k+1].Lo { - t.Errorf("%d: missed optimization for R16 at %d between %X and %x", - i, k, rt.R16[k], rt.R16[k+1]) - } - } - // Test optimization and correctness for R32. - for k := 0; k < len(rt.R32)-1; k++ { - if lo, hi := rt.R32[k].Lo, rt.R32[k].Hi; lo > hi { - t.Errorf("%d: Lo (%x) > Hi (%x)", i, lo, hi) - } - if hi, lo := rt.R32[k].Hi, rt.R32[k+1].Lo; hi >= lo { - t.Errorf("%d: Hi (%x) >= next Lo (%x)", i, hi, lo) - } - if rt.R32[k].Hi+rt.R32[k].Stride == rt.R32[k+1].Lo { - t.Errorf("%d: missed optimization for R32 at %d between %X and %X", - i, k, rt.R32[k], rt.R32[k+1]) - } - } - } -} - -const runes = "Hello World in 2015!,\U0010fffd" - -func BenchmarkNotMerged(t *testing.B) { - for i := 0; i < t.N; i++ { - for _, r := range runes { - unicode.In(r, unicode.GraphicRanges...) - } - } -} - -func BenchmarkMerged(t *testing.B) { - rt := Merge(unicode.GraphicRanges...) - - for i := 0; i < t.N; i++ { - for _, r := range runes { - unicode.Is(rt, r) - } - } -} - -var cased = []*unicode.RangeTable{ - unicode.Lower, - unicode.Upper, - unicode.Title, - unicode.Other_Lowercase, - unicode.Other_Uppercase, -} - -func BenchmarkNotMergedCased(t *testing.B) { - for i := 0; i < t.N; i++ { - for _, r := range runes { - unicode.In(r, cased...) - } - } -} - -func BenchmarkMergedCased(t *testing.B) { - // This reduces len(R16) from 243 to 82 and len(R32) from 65 to 35 for - // Unicode 7.0.0. - rt := Merge(cased...) - - for i := 0; i < t.N; i++ { - for _, r := range runes { - unicode.Is(rt, r) - } - } -} - -func BenchmarkInit(t *testing.B) { - for i := 0; i < t.N; i++ { - Merge(cased...) - Merge(unicode.GraphicRanges...) - } -} - -func BenchmarkInit2(t *testing.B) { - // Hypothetical near-worst-case performance. - for i := 0; i < t.N; i++ { - Merge(overlap1, overlap2) - } -} diff --git a/vendor/golang.org/x/text/unicode/rangetable/rangetable_test.go b/vendor/golang.org/x/text/unicode/rangetable/rangetable_test.go deleted file mode 100644 index 5a355aa3..00000000 --- a/vendor/golang.org/x/text/unicode/rangetable/rangetable_test.go +++ /dev/null @@ -1,55 +0,0 @@ -package rangetable - -import ( - "reflect" - "testing" - "unicode" -) - -var ( - empty = &unicode.RangeTable{} - many = &unicode.RangeTable{ - R16: []unicode.Range16{{0, 0xffff, 5}}, - R32: []unicode.Range32{{0x10004, 0x10009, 5}}, - LatinOffset: 0, - } -) - -func TestVisit(t *testing.T) { - Visit(empty, func(got rune) { - t.Error("call from empty RangeTable") - }) - - var want rune - Visit(many, func(got rune) { - if got != want { - t.Errorf("got %U; want %U", got, want) - } - want += 5 - }) - if want -= 5; want != 0x10009 { - t.Errorf("last run was %U; want U+10009", want) - } -} - -func TestNew(t *testing.T) { - for i, rt := range []*unicode.RangeTable{ - empty, - unicode.Co, - unicode.Letter, - unicode.ASCII_Hex_Digit, - many, - maxRuneTable, - } { - var got, want []rune - Visit(rt, func(r rune) { - want = append(want, r) - }) - Visit(New(want...), func(r rune) { - got = append(got, r) - }) - if !reflect.DeepEqual(got, want) { - t.Errorf("%d:\ngot %v;\nwant %v", i, got, want) - } - } -} diff --git a/vendor/google.golang.org/api/CONTRIBUTING.md b/vendor/google.golang.org/api/CONTRIBUTING.md deleted file mode 100644 index e4d36da3..00000000 --- a/vendor/google.golang.org/api/CONTRIBUTING.md +++ /dev/null @@ -1,484 +0,0 @@ -# Contributing to the Google API Go Client - -## Master git repo - -Our master git repo is https://code.googlesource.com/google-api-go-client - -## Pull Requests - -We do **NOT** use Github pull requests. We use Gerrit instead -with the same workflow as Go. See below. - -## The source tree - -Most of this project is auto-generated. - -The notable directories which are not auto-generated: - -``` - google-api-go-generator/ -- the generator itself - googleapi/ -- shared common code, used by auto-generated code - examples/ -- sample code -``` - -# Contribution Guidelines - -## Introduction - -This document explains how to contribute changes to the google-api-go-client project. - -## Testing redux - -You've written and tested your code, but -before sending code out for review, run all the tests for the whole -tree to make sure the changes don't break other packages or programs: - -``` -$ make cached -$ go test ./... -... -ok google.golang.org/api/google-api-go-generator 0.226s -ok google.golang.org/api/googleapi 0.015s -... -``` - -Ideally, you will add unit tests to one of the above directories to -demonstrate the changes you are making and include the tests with your -code review. - -## Code review - -Changes to google-api-go-client must be reviewed before they are submitted, -no matter who makes the change. -A custom git command called `git-codereview`, -discussed below, helps manage the code review process through a Google-hosted -[instance](https://code-review.googlesource.com/) of the code review -system called [Gerrit](https://code.google.com/p/gerrit/). - -### Set up authentication for code review - -The Git code hosting server and Gerrit code review server both use a Google -Account to authenticate. You therefore need a Google Account to proceed. -(If you can use the account to -[sign in at google.com](https://www.google.com/accounts/Login), -you can use it to sign in to the code review server.) -The email address you use with the code review system -needs to be added to the [`CONTRIBUTORS`](/CONTRIBUTORS) file -with your first code review. -You can [create a Google Account](https://www.google.com/accounts/NewAccount) -associated with any address where you receive email. - -Visit the site [code.googlesource.com](https://code.googlesource.com) -and log in using your Google Account. -Click on the "Generate Password" link that appears at the top of the page. - -Click the radio button that says "Only `code.googlesource.com`" -to use this authentication token only for the google-api-go-client project. - -Further down the page is a box containing commands to install -the authentication cookie in file called `.gitcookies` in your home -directory. -Copy the text for the commands into a Unix shell window to execute it. -That will install the authentication token. - -(If you are on a Windows computer, you should instead follow the instructions -in the yellow box to run the command.) - -### Register with Gerrit - -Now that you have a Google account and the authentication token, -you need to register your account with Gerrit, the code review system. -To do this, visit [golang.org/cl](https://golang.org/cl) -and log in using the same Google Account you used above. -That is all that is required. - -### Install the git-codereview command - -Now install the `git-codereview` command by running, - -``` -go get -u golang.org/x/review/git-codereview -``` - -Make sure `git-codereview` is installed in your shell path, so that the -`git` command can find it. Check that - -``` -$ git codereview help -``` - -prints help text, not an error. - -Note to Git aficionados: The `git-codereview` command is not required to -upload and manage Gerrit code reviews. For those who prefer plain Git, the text -below gives the Git equivalent of each git-codereview command. If you do use plain -Git, note that you still need the commit hooks that the git-codereview command -configures; those hooks add a Gerrit `Change-Id` line to the commit -message and check that all Go source files have been formatted with gofmt. Even -if you intend to use plain Git for daily work, install the hooks in a new Git -checkout by running `git-codereview hooks`. - -### Set up git aliases - -The `git-codereview` command can be run directly from the shell -by typing, for instance, - -``` -$ git codereview sync -``` - -but it is more convenient to set up aliases for `git-codereview`'s own -subcommands, so that the above becomes, - -``` -$ git sync -``` - -The `git-codereview` subcommands have been chosen to be distinct from -Git's own, so it's safe to do so. - -The aliases are optional, but in the rest of this document we will assume -they are installed. -To install them, copy this text into your Git configuration file -(usually `.gitconfig` in your home directory): - -``` -[alias] - change = codereview change - gofmt = codereview gofmt - mail = codereview mail - pending = codereview pending - submit = codereview submit - sync = codereview sync -``` - -### Understanding the git-codereview command - -After installing the `git-codereview` command, you can run - -``` -$ git codereview help -``` - -to learn more about its commands. -You can also read the [command documentation](https://godoc.org/golang.org/x/review/git-codereview). - -### Switch to the master branch - -New changes should -only be made based on the master branch. -Before making a change, make sure you start on the master branch: - -``` -$ git checkout master -$ git sync -```` - -(In Git terms, `git sync` runs -`git pull -r`.) - -### Make a change - -The entire checked-out tree is writable. -Once you have edited files, you must tell Git that they have been modified. -You must also tell Git about any files that are added, removed, or renamed files. -These operations are done with the usual Git commands, -`git add`, -`git rm`, -and -`git mv`. - -If you wish to checkpoint your work, or are ready to send the code out for review, run - -``` -$ git change -``` - -from any directory in your google-api-go-client repository to commit the changes so far. -The name `` is an arbitrary one you choose to identify the -local branch containing your changes. - -(In Git terms, `git change ` -runs `git checkout -b branch`, -then `git branch --set-upstream-to origin/master`, -then `git commit`.) - -Git will open a change description file in your editor. -(It uses the editor named by the `$EDITOR` environment variable, -`vi` by default.) -The file will look like: - -``` -# Please enter the commit message for your changes. Lines starting -# with '#' will be ignored, and an empty message aborts the commit. -# On branch foo -# Changes not staged for commit: -# modified: editedfile.go -# -``` - -At the beginning of this file is a blank line; replace it -with a thorough description of your change. -The first line of the change description is conventionally a one-line -summary of the change, prefixed by `google-api-go-client:`, -and is used as the subject for code review mail. -The rest of the -description elaborates and should provide context for the -change and explain what it does. -If there is a helpful reference, mention it here. - -After editing, the template might now read: - -``` -math: improved Sin, Cos and Tan precision for very large arguments - -The existing implementation has poor numerical properties for -large arguments, so use the McGillicutty algorithm to improve -accuracy above 1e10. - -The algorithm is described at http://wikipedia.org/wiki/McGillicutty_Algorithm - -Fixes #54 - -# Please enter the commit message for your changes. Lines starting -# with '#' will be ignored, and an empty message aborts the commit. -# On branch foo -# Changes not staged for commit: -# modified: editedfile.go -# -``` - -The commented section of the file lists all the modified files in your client. -It is best to keep unrelated changes in different change lists, -so if you see a file listed that should not be included, abort -the command and move that file to a different branch. - -The special notation "Fixes #54" associates the change with issue 54 in the -[google-api-go-client issue tracker](https://github.com/google/google-api-go-client/issues/54). -When this change is eventually submitted, the issue -tracker will automatically mark the issue as fixed. -(There are several such conventions, described in detail in the -[GitHub Issue Tracker documentation](https://help.github.com/articles/closing-issues-via-commit-messages/).) - -Once you have finished writing the commit message, -save the file and exit the editor. - -If you wish to do more editing, re-stage your changes using -`git add`, and then run - -``` -$ git change -``` - -to update the change description and incorporate the staged changes. The -change description contains a `Change-Id` line near the bottom, -added by a Git commit hook during the initial -`git change`. -That line is used by Gerrit to match successive uploads of the same change. -Do not edit or delete it. - -(In Git terms, `git change` with no branch name -runs `git commit --amend`.) - -### Mail the change for review - -Once the change is ready, mail it out for review: - -``` -$ git mail -``` - -You can specify a reviewer or CC interested parties -using the `-r` or `-cc` options. -Both accept a comma-separated list of email addresses: - -``` -$ git mail -r joe@golang.org -cc mabel@example.com,math-nuts@swtch.com -``` - -Unless explicitly told otherwise, such as in the discussion leading -up to sending in the change list, please specify -`bradfitz@golang.org`, `gmlewis@google.com`, or -`mcgreevy@golang.org` as a reviewer. - -(In Git terms, `git mail` pushes the local committed -changes to Gerrit using `git push origin HEAD:refs/for/master`.) - -If your change relates to an open issue, please add a comment to the issue -announcing your proposed fix, including a link to your CL. - -The code review server assigns your change an issue number and URL, -which `git mail` will print, something like: - -``` -remote: New Changes: -remote: https://code-review.googlesource.com/99999 math: improved Sin, Cos and Tan precision for very large arguments -``` - -### Reviewing code - -Running `git mail` will send an email to you and the -reviewers asking them to visit the issue's URL and make comments on the change. -When done, the reviewer adds comments through the Gerrit user interface -and clicks "Reply" to send comments back. -You will receive a mail notification when this happens. -You must reply through the web interface. - -### Revise and upload - -You must respond to review comments through the web interface. - -When you have revised the code and are ready for another round of review, -stage those changes and use `git change` to update the -commit. -To send the update change list for another round of review, -run `git mail` again. - -The reviewer can comment on the new copy, and the process repeats. -The reviewer approves the change by giving it a positive score -(+1 or +2) and replying `LGTM`: looks good to me. - -You can see a list of your pending changes by running -`git pending`, and switch between change branches with -`git change `. - -### Synchronize your client - -While you were working, others might have submitted changes to the repository. -To update your local branch, run - -``` -$ git sync -``` - -(In git terms, `git sync` runs -`git pull -r`.) - -If files you were editing have changed, Git does its best to merge the -remote changes into your local changes. -It may leave some files to merge by hand. - -For example, suppose you have edited `sin.go` but -someone else has committed an independent change. -When you run `git sync`, -you will get the (scary-looking) output: - -``` -$ git sync -Failed to merge in the changes. -Patch failed at 0023 math: improved Sin, Cos and Tan precision for very large arguments -The copy of the patch that failed is found in: - /home/you/repo/.git/rebase-apply/patch - -When you have resolved this problem, run "git rebase --continue". -If you prefer to skip this patch, run "git rebase --skip" instead. -To check out the original branch and stop rebasing, run "git rebase --abort". -``` - - -If this happens, run - -``` -$ git status -``` - -to see which files failed to merge. -The output will look something like this: - -``` -rebase in progress; onto a24c3eb -You are currently rebasing branch 'mcgillicutty' on 'a24c3eb'. - (fix conflicts and then run "git rebase --continue") - (use "git rebase --skip" to skip this patch) - (use "git rebase --abort" to check out the original branch) - -Unmerged paths: - (use "git reset HEAD ..." to unstage) - (use "git add ..." to mark resolution) - - _both modified: sin.go_ -``` - - -The only important part in that transcript is the italicized "both modified" -line: Git failed to merge your changes with the conflicting change. -When this happens, Git leaves both sets of edits in the file, -with conflicts marked by `<<<<<<<` and -`>>>>>>>`. -It is now your job to edit the file to combine them. -Continuing the example, searching for those strings in `sin.go` -might turn up: - -``` - arg = scale(arg) -<<<<<<< HEAD - if arg > 1e9 { -======= - if arg > 1e10 { ->>>>>>> mcgillicutty - largeReduce(arg) -``` - -Git doesn't show it, but suppose the original text that both edits -started with was 1e8; you changed it to 1e10 and the other change to 1e9, -so the correct answer might now be 1e10. First, edit the section -to remove the markers and leave the correct code: - -``` - arg = scale(arg) - if arg > 1e10 { - largeReduce(arg) -``` - -Then tell Git that the conflict is resolved by running - -``` -$ git add sin.go -``` - -If you had been editing the file, say for debugging, but do not -care to preserve your changes, you can run -`git reset HEAD sin.go` -to abandon your changes. -Then run `git rebase --continue` to -restore the change commit. - -### Reviewing code by others - -You can import a change proposed by someone else into your local Git repository. -On the Gerrit review page, click the "Download ▼" link in the upper right -corner, copy the "Checkout" command and run it from your local Git repo. -It should look something like this: - -``` -$ git fetch https://code.googlesource.com/review refs/changes/21/1221/1 && git checkout FETCH_HEAD -``` - -To revert, change back to the branch you were working in. - -### Submit the change after the review - -After the code has been `LGTM`'ed, an approver may -submit it to the master branch using the Gerrit UI. -There is a "Submit" button on the web page for the change -that appears once the change is approved (marked +2). - -This checks the change into the repository. -The change description will include a link to the code review, -and the code review will be updated with a link to the change -in the repository. -Since the method used to integrate the changes is "Cherry Pick", -the commit hashes in the repository will be changed by -the submit operation. - -### More information - -In addition to the information here, the Go community maintains a [CodeReview](https://golang.org/wiki/CodeReview) wiki page. -Feel free to contribute to this page as you learn the review process. - -## Contributors - -Files in the google-api-go-client repository don't list author names, -both to avoid clutter and to avoid having to keep the lists up to date. -Instead, please add your name to the [`CONTRIBUTORS`](/CONTRIBUTORS) -file as your first code review, keeping the names in sorted order. diff --git a/vendor/google.golang.org/api/GettingStarted.md b/vendor/google.golang.org/api/GettingStarted.md deleted file mode 100644 index 72855cda..00000000 --- a/vendor/google.golang.org/api/GettingStarted.md +++ /dev/null @@ -1,146 +0,0 @@ -# Getting Started with the Google APIs for Go - -## Getting Started - -This is a quick walk-through of how to get started with the Google APIs for Go. - -## Background - -The first thing to understand is that the Google API libraries are auto-generated for -each language, including Go, so they may not feel like 100% natural for any language. -The Go versions are pretty natural, but please forgive any small non-idiomatic things. -(Suggestions welcome, though!) - -## Installing - -Pick an API and a version of that API to install. -You can find the complete list by looking at the -[directories here](https://github.com/google/google-api-go-client/tree/master/). - -For example, let's install the -[urlshortener's version 1 API](https://godoc.org/google.golang.org/api/urlshortener/v1): - -``` -$ go get -u google.golang.org/api/urlshortener/v1 -``` - -Now it's ready for use in your code. - -## Using - -Once you've installed a library, you import it like this: - -```go -package main - -import ( - "context" - "golang.org/x/oauth2" - "golang.org/x/oauth2/google" - "google.golang.org/api/urlshortener/v1" -) -``` - -The package name, if you don't override it on your import line, is the name of the -API without the version number. In the case above, just `urlshortener`. - -## Instantiating - -Each API has a `New` function taking an `*http.Client` and returning an API-specific `*Service`. - -You create the service like: - -```go - svc, err := urlshortener.New(httpClient) -``` - -## OAuth HTTP Client - -The HTTP client you pass in to the service must be one that automatically adds -Google-supported Authorization information to the requests. - -There are several ways to do authentication. They will all involve the package -[golang.org/x/oauth2](https://godoc.org/golang.org/x/oauth2) in some way. - -### 3-legged OAuth - -For 3-legged OAuth (your application redirecting a user through a website to get a -token giving your application access to that user's resources), you will need to -create an oauth2.Config, - - -```go - var config = &oauth2.Config{ - ClientID: "", // from https://console.developers.google.com/project//apiui/credential - ClientSecret: "", // from https://console.developers.google.com/project//apiui/credential - Endpoint: google.Endpoint, - Scopes: []string{urlshortener.UrlshortenerScope}, - } -``` - -... and then use the AuthCodeURL, Exchange, and Client methods on it. -For an example, see: https://godoc.org/golang.org/x/oauth2#example-Config - -For the redirect URL, see -https://developers.google.com/identity/protocols/OAuth2InstalledApp#choosingredirecturi - -### Service Accounts - -To use a Google service account, or the GCE metadata service, see -the [golang.org/x/oauth2/google](https://godoc.org/golang.org/x/oauth2/google) package. -In particular, see [google.DefaultClient](https://godoc.org/golang.org/x/oauth2/google#DefaultClient). - -### Using API Keys - -Some APIs require passing API keys from your application. -To do this, you can use -[transport.APIKey](https://godoc.org/google.golang.org/api/googleapi/transport#APIKey): - -```go - ctx := context.WithValue(context.Background(), oauth2.HTTPClient, &http.Client{ - Transport: &transport.APIKey{Key: developerKey}, - }) - oauthConfig := &oauth2.Config{ .... } - var token *oauth2.Token = .... // via cache, or oauthConfig.Exchange - httpClient := oauthConfig.Client(ctx, token) - svc, err := urlshortener.New(httpClient) - ... -``` - -## Using the Service - -Each service contains zero or more methods and zero or more sub-services. -The sub-services related to a specific type of "Resource". - -Those sub-services then contain their own methods. - -For instance, the urlshortener API has just the "Url" sub-service: - -```go - url, err := svc.Url.Get(shortURL).Do() - if err != nil { - ... - } - fmt.Printf("The URL %s goes to %s\n", shortURL, url.LongUrl) -``` - -For a more complete example, see -[urlshortener.go](https://github.com/google/google-api-go-client/tree/master/examples/urlshortener.go) -in the [examples directory](https://github.com/google/google-api-go-client/tree/master/examples/). -(the examples use some functions in `main.go` in the same directory) - -## Error Handling - -Most errors returned by the `Do` methods of these clients will be of type -[`googleapi.Error`](https://godoc.org/google.golang.org/api/googleapi#Error). -Use a type assertion to obtain the HTTP status code and other properties of the -error: - -```go - url, err := svc.Url.Get(shortURL).Do() - if err != nil { - if e, ok := err.(*googleapi.Error); ok && e.Code == http.StatusNotFound { - ... - } - } -``` diff --git a/vendor/google.golang.org/api/NOTES b/vendor/google.golang.org/api/NOTES deleted file mode 100644 index 571f6ec7..00000000 --- a/vendor/google.golang.org/api/NOTES +++ /dev/null @@ -1,13 +0,0 @@ -Discovery Service: -https://developers.google.com/discovery/ -https://developers.google.com/discovery/v1/reference/ - -The "type" key: -http://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.1 - -The "format" key: -http://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.23 -https://developers.google.com/discovery/v1/type-format - -Google JSON format docs: -http://google-styleguide.googlecode.com/svn/trunk/jsoncstyleguide.xml diff --git a/vendor/google.golang.org/api/README.md b/vendor/google.golang.org/api/README.md deleted file mode 100644 index cd938c19..00000000 --- a/vendor/google.golang.org/api/README.md +++ /dev/null @@ -1,104 +0,0 @@ -# Google APIs Client Library for Go - -## Getting Started - -``` -$ go get google.golang.org/api/tasks/v1 -$ go get google.golang.org/api/moderator/v1 -$ go get google.golang.org/api/urlshortener/v1 -... etc ... -``` - -and using: - -```go -package main - -import ( - "net/http" - - "google.golang.org/api/urlshortener/v1" -) - -func main() { - svc, err := urlshortener.New(http.DefaultClient) - // ... -} -``` - -* For a longer tutorial, see the [Getting Started guide](https://github.com/google/google-api-go-client/blob/master/GettingStarted.md). -* For examples, see the [examples directory](https://github.com/google/google-api-go-client/tree/master/examples). -* For support, use the [golang-nuts](https://groups.google.com/group/golang-nuts) mailing list. -* The code review instance may be found [here](https://code-review.googlesource.com). - -## Status -[![GoDoc](https://godoc.org/google.golang.org/api?status.svg)](https://godoc.org/google.golang.org/api) - -These are auto-generated Go libraries from the Google Discovery Service's JSON description files of the available "new style" Google APIs. - -Due to the auto-generated nature of this collection of libraries, complete APIs or specific versions can appear or go away without notice. -As a result, you should always locally vendor any API(s) that your code relies upon. - -These client libraries are officially supported by Google. However, the libraries are considered complete and are in maintenance mode. This means that we will address critical bugs and security issues but will not add any new features. - -If you're working with Google Cloud Platform APIs such as Datastore or Pub/Sub, -consider using the -[Cloud Client Libraries for Go](https://github.com/googleapis/google-cloud-go) -instead. These are the new and -idiomatic Go libraries targeted specifically at Google Cloud Platform Services. - -The generator itself and the code it produces are beta. Some APIs are -alpha/beta, and indicated as such in the import path (e.g., -"google.golang.org/api/someapi/v1alpha"). - -## Application Default Credentials Example - -Application Default Credentials provide a simplified way to obtain credentials -for authenticating with Google APIs. - -The Application Default Credentials authenticate as the application itself, -which make them great for working with Google Cloud APIs like Storage or -Datastore. They are the recommended form of authentication when building -applications that run on Google Compute Engine or Google App Engine. - -Default credentials are provided by the `golang.org/x/oauth2/google` package. To use them, add the following import: - -```go -import "golang.org/x/oauth2/google" -``` - -Some credentials types require you to specify scopes, and service entry points may not inject them. If you encounter this situation you may need to specify scopes as follows: - -```go -import ( - "context" - "golang.org/x/oauth2/google" - "google.golang.org/api/compute/v1" -) - -func main() { - // Use oauth2.NoContext if there isn't a good context to pass in. - ctx := context.Background() - - client, err := google.DefaultClient(ctx, compute.ComputeScope) - if err != nil { - //... - } - computeService, err := compute.New(client) - if err != nil { - //... - } -} -``` - -If you need a `oauth2.TokenSource`, use the `DefaultTokenSource` function: - -```go -ts, err := google.DefaultTokenSource(ctx, scope1, scope2, ...) -if err != nil { - //... -} -client := oauth2.NewClient(ctx, ts) -``` - -See also: [golang.org/x/oauth2/google](https://godoc.org/golang.org/x/oauth2/google) package documentation. diff --git a/vendor/google.golang.org/api/TODO b/vendor/google.golang.org/api/TODO deleted file mode 100644 index de2467c3..00000000 --- a/vendor/google.golang.org/api/TODO +++ /dev/null @@ -1,2 +0,0 @@ -Moved to: -https://github.com/google/google-api-go-client/issues diff --git a/vendor/google.golang.org/api/api-list.json b/vendor/google.golang.org/api/api-list.json deleted file mode 100644 index f643fae7..00000000 --- a/vendor/google.golang.org/api/api-list.json +++ /dev/null @@ -1,3419 +0,0 @@ -{ - "kind": "discovery#directoryList", - "discoveryVersion": "v1", - "items": [ - { - "kind": "discovery#directoryItem", - "id": "abusiveexperiencereport:v1", - "name": "abusiveexperiencereport", - "version": "v1", - "title": "Abusive Experience Report API", - "description": "Views Abusive Experience Report data, and gets a list of sites that have a significant number of abusive experiences.", - "discoveryRestUrl": "https://abusiveexperiencereport.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/abusive-experience-report/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "acceleratedmobilepageurl:v1", - "name": "acceleratedmobilepageurl", - "version": "v1", - "title": "Accelerated Mobile Pages (AMP) URL API", - "description": "This API contains a single method, batchGet. Call this method to retrieve the AMP URL (and equivalent AMP Cache URL) for given public URL(s).", - "discoveryRestUrl": "https://acceleratedmobilepageurl.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/amp/cache/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "accesscontextmanager:v1beta", - "name": "accesscontextmanager", - "version": "v1beta", - "title": "Access Context Manager API", - "description": "An API for setting attribute based access control to requests to GCP services.", - "discoveryRestUrl": "https://accesscontextmanager.googleapis.com/$discovery/rest?version=v1beta", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/access-context-manager/docs/reference/rest/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "adexchangebuyer:v1.2", - "name": "adexchangebuyer", - "version": "v1.2", - "title": "Ad Exchange Buyer API", - "description": "Accesses your bidding-account information, submits creatives for validation, finds available direct deals, and retrieves performance reports.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/adexchangebuyer/v1.2/rest", - "discoveryLink": "./apis/adexchangebuyer/v1.2/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/doubleclick-16.gif", - "x32": "https://www.google.com/images/icons/product/doubleclick-32.gif" - }, - "documentationLink": "https://developers.google.com/ad-exchange/buyer-rest", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "adexchangebuyer:v1.3", - "name": "adexchangebuyer", - "version": "v1.3", - "title": "Ad Exchange Buyer API", - "description": "Accesses your bidding-account information, submits creatives for validation, finds available direct deals, and retrieves performance reports.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/adexchangebuyer/v1.3/rest", - "discoveryLink": "./apis/adexchangebuyer/v1.3/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/doubleclick-16.gif", - "x32": "https://www.google.com/images/icons/product/doubleclick-32.gif" - }, - "documentationLink": "https://developers.google.com/ad-exchange/buyer-rest", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "adexchangebuyer:v1.4", - "name": "adexchangebuyer", - "version": "v1.4", - "title": "Ad Exchange Buyer API", - "description": "Accesses your bidding-account information, submits creatives for validation, finds available direct deals, and retrieves performance reports.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/adexchangebuyer/v1.4/rest", - "discoveryLink": "./apis/adexchangebuyer/v1.4/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/doubleclick-16.gif", - "x32": "https://www.google.com/images/icons/product/doubleclick-32.gif" - }, - "documentationLink": "https://developers.google.com/ad-exchange/buyer-rest", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "adexchangebuyer2:v2beta1", - "name": "adexchangebuyer2", - "version": "v2beta1", - "title": "Ad Exchange Buyer API II", - "description": "Accesses the latest features for managing Ad Exchange accounts, Real-Time Bidding configurations and auction metrics, and Marketplace programmatic deals.", - "discoveryRestUrl": "https://adexchangebuyer.googleapis.com/$discovery/rest?version=v2beta1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/ad-exchange/buyer-rest/reference/rest/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "adexperiencereport:v1", - "name": "adexperiencereport", - "version": "v1", - "title": "Ad Experience Report API", - "description": "Views Ad Experience Report data, and gets a list of sites that have a significant number of annoying ads.", - "discoveryRestUrl": "https://adexperiencereport.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/ad-experience-report/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "admin:datatransfer_v1", - "name": "admin", - "version": "datatransfer_v1", - "title": "Admin Data Transfer API", - "description": "Transfers user data from one user to another.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/admin/datatransfer_v1/rest", - "discoveryLink": "./apis/admin/datatransfer_v1/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/admin-sdk/data-transfer/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "admin:directory_v1", - "name": "admin", - "version": "directory_v1", - "title": "Admin Directory API", - "description": "Manages enterprise resources such as users and groups, administrative notifications, security features, and more.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/admin/directory_v1/rest", - "discoveryLink": "./apis/admin/directory_v1/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/admin-sdk/directory/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "admin:reports_v1", - "name": "admin", - "version": "reports_v1", - "title": "Admin Reports API", - "description": "Fetches reports for the administrators of G Suite customers about the usage, collaboration, security, and risk for their users.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/admin/reports_v1/rest", - "discoveryLink": "./apis/admin/reports_v1/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/admin-sdk/reports/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "adsense:v1.4", - "name": "adsense", - "version": "v1.4", - "title": "AdSense Management API", - "description": "Accesses AdSense publishers' inventory and generates performance reports.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/adsense/v1.4/rest", - "discoveryLink": "./apis/adsense/v1.4/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/adsense-16.png", - "x32": "https://www.google.com/images/icons/product/adsense-32.png" - }, - "documentationLink": "https://developers.google.com/adsense/management/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "adsensehost:v4.1", - "name": "adsensehost", - "version": "v4.1", - "title": "AdSense Host API", - "description": "Generates performance reports, generates ad codes, and provides publisher management capabilities for AdSense Hosts.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/adsensehost/v4.1/rest", - "discoveryLink": "./apis/adsensehost/v4.1/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/adsense-16.png", - "x32": "https://www.google.com/images/icons/product/adsense-32.png" - }, - "documentationLink": "https://developers.google.com/adsense/host/", - "labels": [ - "limited_availability" - ], - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "alertcenter:v1beta1", - "name": "alertcenter", - "version": "v1beta1", - "title": "G Suite Alert Center API", - "description": "Manages alerts on issues affecting your domain.", - "discoveryRestUrl": "https://alertcenter.googleapis.com/$discovery/rest?version=v1beta1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/admin-sdk/alertcenter/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "analytics:v2.4", - "name": "analytics", - "version": "v2.4", - "title": "Google Analytics API", - "description": "Views and manages your Google Analytics data.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/analytics/v2.4/rest", - "discoveryLink": "./apis/analytics/v2.4/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/analytics-16.png", - "x32": "https://www.google.com/images/icons/product/analytics-32.png" - }, - "documentationLink": "https://developers.google.com/analytics/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "analytics:v3", - "name": "analytics", - "version": "v3", - "title": "Google Analytics API", - "description": "Views and manages your Google Analytics data.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/analytics/v3/rest", - "discoveryLink": "./apis/analytics/v3/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/analytics-16.png", - "x32": "https://www.google.com/images/icons/product/analytics-32.png" - }, - "documentationLink": "https://developers.google.com/analytics/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "analyticsreporting:v4", - "name": "analyticsreporting", - "version": "v4", - "title": "Google Analytics Reporting API", - "description": "Accesses Analytics report data.", - "discoveryRestUrl": "https://analyticsreporting.googleapis.com/$discovery/rest?version=v4", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/analytics/devguides/reporting/core/v4/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "androiddeviceprovisioning:v1", - "name": "androiddeviceprovisioning", - "version": "v1", - "title": "Android Device Provisioning Partner API", - "description": "Automates Android zero-touch enrollment for device resellers, customers, and EMMs.", - "discoveryRestUrl": "https://androiddeviceprovisioning.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/zero-touch/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "androidenterprise:v1", - "name": "androidenterprise", - "version": "v1", - "title": "Google Play EMM API", - "description": "Manages the deployment of apps to Android for Work users.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/androidenterprise/v1/rest", - "discoveryLink": "./apis/androidenterprise/v1/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/android-16.png", - "x32": "https://www.google.com/images/icons/product/android-32.png" - }, - "documentationLink": "https://developers.google.com/android/work/play/emm-api", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "androidmanagement:v1", - "name": "androidmanagement", - "version": "v1", - "title": "Android Management API", - "description": "The Android Management API provides remote enterprise management of Android devices and apps.", - "discoveryRestUrl": "https://androidmanagement.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/android/management", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "androidpublisher:v1", - "name": "androidpublisher", - "version": "v1", - "title": "Google Play Developer API", - "description": "Accesses Android application developers' Google Play accounts.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/androidpublisher/v1/rest", - "discoveryLink": "./apis/androidpublisher/v1/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/android-16.png", - "x32": "https://www.google.com/images/icons/product/android-32.png" - }, - "documentationLink": "https://developers.google.com/android-publisher", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "androidpublisher:v1.1", - "name": "androidpublisher", - "version": "v1.1", - "title": "Google Play Developer API", - "description": "Accesses Android application developers' Google Play accounts.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/androidpublisher/v1.1/rest", - "discoveryLink": "./apis/androidpublisher/v1.1/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/android-16.png", - "x32": "https://www.google.com/images/icons/product/android-32.png" - }, - "documentationLink": "https://developers.google.com/android-publisher", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "androidpublisher:v2", - "name": "androidpublisher", - "version": "v2", - "title": "Google Play Developer API", - "description": "Accesses Android application developers' Google Play accounts.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/androidpublisher/v2/rest", - "discoveryLink": "./apis/androidpublisher/v2/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/android-16.png", - "x32": "https://www.google.com/images/icons/product/android-32.png" - }, - "documentationLink": "https://developers.google.com/android-publisher", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "androidpublisher:v3", - "name": "androidpublisher", - "version": "v3", - "title": "Google Play Developer API", - "description": "Accesses Android application developers' Google Play accounts.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/androidpublisher/v3/rest", - "discoveryLink": "./apis/androidpublisher/v3/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/android-16.png", - "x32": "https://www.google.com/images/icons/product/android-32.png" - }, - "documentationLink": "https://developers.google.com/android-publisher", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "appengine:v1alpha", - "name": "appengine", - "version": "v1alpha", - "title": "App Engine Admin API", - "description": "Provisions and manages developers' App Engine applications.", - "discoveryRestUrl": "https://appengine.googleapis.com/$discovery/rest?version=v1alpha", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/appengine/docs/admin-api/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "appengine:v1beta", - "name": "appengine", - "version": "v1beta", - "title": "App Engine Admin API", - "description": "Provisions and manages developers' App Engine applications.", - "discoveryRestUrl": "https://appengine.googleapis.com/$discovery/rest?version=v1beta", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/appengine/docs/admin-api/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "appengine:v1", - "name": "appengine", - "version": "v1", - "title": "App Engine Admin API", - "description": "Provisions and manages developers' App Engine applications.", - "discoveryRestUrl": "https://appengine.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/appengine/docs/admin-api/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "appengine:v1beta4", - "name": "appengine", - "version": "v1beta4", - "title": "App Engine Admin API", - "description": "Provisions and manages developers' App Engine applications.", - "discoveryRestUrl": "https://appengine.googleapis.com/$discovery/rest?version=v1beta4", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/appengine/docs/admin-api/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "appengine:v1beta5", - "name": "appengine", - "version": "v1beta5", - "title": "App Engine Admin API", - "description": "Provisions and manages developers' App Engine applications.", - "discoveryRestUrl": "https://appengine.googleapis.com/$discovery/rest?version=v1beta5", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/appengine/docs/admin-api/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "appsactivity:v1", - "name": "appsactivity", - "version": "v1", - "title": "Drive Activity API", - "description": "Provides a historical view of activity.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/appsactivity/v1/rest", - "discoveryLink": "./apis/appsactivity/v1/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/google-apps/activity/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "appstate:v1", - "name": "appstate", - "version": "v1", - "title": "Google App State API", - "description": "The Google App State API.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/appstate/v1/rest", - "discoveryLink": "./apis/appstate/v1/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/games/services/web/api/states", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "bigquery:v2", - "name": "bigquery", - "version": "v2", - "title": "BigQuery API", - "description": "A data platform for customers to create, manage, share and query data.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/bigquery/v2/rest", - "discoveryLink": "./apis/bigquery/v2/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/search-16.gif", - "x32": "https://www.google.com/images/icons/product/search-32.gif" - }, - "documentationLink": "https://cloud.google.com/bigquery/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "bigquerydatatransfer:v1", - "name": "bigquerydatatransfer", - "version": "v1", - "title": "BigQuery Data Transfer API", - "description": "Transfers data from partner SaaS applications to Google BigQuery on a scheduled, managed basis.", - "discoveryRestUrl": "https://bigquerydatatransfer.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/bigquery/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "bigtableadmin:v2", - "name": "bigtableadmin", - "version": "v2", - "title": "Cloud Bigtable Admin API", - "description": "", - "discoveryRestUrl": "https://bigtableadmin.googleapis.com/$discovery/rest?version=v2", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/bigtable/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "binaryauthorization:v1beta1", - "name": "binaryauthorization", - "version": "v1beta1", - "title": "Binary Authorization API", - "description": "The management interface for Binary Authorization, a system providing policy control for images deployed to Kubernetes Engine clusters.", - "discoveryRestUrl": "https://binaryauthorization.googleapis.com/$discovery/rest?version=v1beta1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/binary-authorization/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "blogger:v2", - "name": "blogger", - "version": "v2", - "title": "Blogger API", - "description": "API for access to the data within Blogger.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/blogger/v2/rest", - "discoveryLink": "./apis/blogger/v2/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/blogger-16.png", - "x32": "https://www.google.com/images/icons/product/blogger-32.png" - }, - "documentationLink": "https://developers.google.com/blogger/docs/2.0/json/getting_started", - "labels": [ - "limited_availability" - ], - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "blogger:v3", - "name": "blogger", - "version": "v3", - "title": "Blogger API", - "description": "API for access to the data within Blogger.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/blogger/v3/rest", - "discoveryLink": "./apis/blogger/v3/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/blogger-16.png", - "x32": "https://www.google.com/images/icons/product/blogger-32.png" - }, - "documentationLink": "https://developers.google.com/blogger/docs/3.0/getting_started", - "labels": [ - "limited_availability" - ], - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "books:v1", - "name": "books", - "version": "v1", - "title": "Books API", - "description": "Searches for books and manages your Google Books library.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/books/v1/rest", - "discoveryLink": "./apis/books/v1/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/ebooks-16.png", - "x32": "https://www.google.com/images/icons/product/ebooks-32.png" - }, - "documentationLink": "https://developers.google.com/books/docs/v1/getting_started", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "calendar:v3", - "name": "calendar", - "version": "v3", - "title": "Calendar API", - "description": "Manipulates events and other calendar data.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest", - "discoveryLink": "./apis/calendar/v3/rest", - "icons": { - "x16": "http://www.google.com/images/icons/product/calendar-16.png", - "x32": "http://www.google.com/images/icons/product/calendar-32.png" - }, - "documentationLink": "https://developers.google.com/google-apps/calendar/firstapp", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "chat:v1", - "name": "chat", - "version": "v1", - "title": "Hangouts Chat API", - "description": "Create bots and extend the new Hangouts Chat.", - "discoveryRestUrl": "https://chat.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/hangouts/chat", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "civicinfo:v2", - "name": "civicinfo", - "version": "v2", - "title": "Google Civic Information API", - "description": "Provides polling places, early vote locations, contest data, election officials, and government representatives for U.S. residential addresses.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/civicinfo/v2/rest", - "discoveryLink": "./apis/civicinfo/v2/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/civic-information", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "classroom:v1", - "name": "classroom", - "version": "v1", - "title": "Google Classroom API", - "description": "Manages classes, rosters, and invitations in Google Classroom.", - "discoveryRestUrl": "https://classroom.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/classroom", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "cloudasset:v1beta1", - "name": "cloudasset", - "version": "v1beta1", - "title": "Cloud Asset API", - "description": "The cloud asset API manages the history and inventory of cloud resources.", - "discoveryRestUrl": "https://cloudasset.googleapis.com/$discovery/rest?version=v1beta1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://console.cloud.google.com/apis/api/cloudasset.googleapis.com/overview", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "cloudbilling:v1", - "name": "cloudbilling", - "version": "v1", - "title": "Cloud Billing API", - "description": "Allows developers to manage billing for their Google Cloud Platform projects programmatically.", - "discoveryRestUrl": "https://cloudbilling.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/billing/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "cloudbuild:v1alpha1", - "name": "cloudbuild", - "version": "v1alpha1", - "title": "Cloud Build API", - "description": "Creates and manages builds on Google Cloud Platform.", - "discoveryRestUrl": "https://cloudbuild.googleapis.com/$discovery/rest?version=v1alpha1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/cloud-build/docs/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "cloudbuild:v1", - "name": "cloudbuild", - "version": "v1", - "title": "Cloud Build API", - "description": "Creates and manages builds on Google Cloud Platform.", - "discoveryRestUrl": "https://cloudbuild.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/cloud-build/docs/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "clouddebugger:v2", - "name": "clouddebugger", - "version": "v2", - "title": "Stackdriver Debugger API", - "description": "Examines the call stack and variables of a running application without stopping or slowing it down.", - "discoveryRestUrl": "https://clouddebugger.googleapis.com/$discovery/rest?version=v2", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/debugger", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "clouderrorreporting:v1beta1", - "name": "clouderrorreporting", - "version": "v1beta1", - "title": "Stackdriver Error Reporting API", - "description": "Groups and counts similar errors from cloud services and applications, reports new errors, and provides access to error groups and their associated errors.", - "discoveryRestUrl": "https://clouderrorreporting.googleapis.com/$discovery/rest?version=v1beta1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/error-reporting/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "cloudfunctions:v1", - "name": "cloudfunctions", - "version": "v1", - "title": "Cloud Functions API", - "description": "Manages lightweight user-provided functions executed in response to events.", - "discoveryRestUrl": "https://cloudfunctions.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/functions", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "cloudfunctions:v1beta2", - "name": "cloudfunctions", - "version": "v1beta2", - "title": "Cloud Functions API", - "description": "Manages lightweight user-provided functions executed in response to events.", - "discoveryRestUrl": "https://cloudfunctions.googleapis.com/$discovery/rest?version=v1beta2", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/functions", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "cloudidentity:v1", - "name": "cloudidentity", - "version": "v1", - "title": "Cloud Identity API", - "description": "API for provisioning and managing identity resources.", - "discoveryRestUrl": "https://cloudidentity.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/identity/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "cloudidentity:v1beta1", - "name": "cloudidentity", - "version": "v1beta1", - "title": "Cloud Identity API", - "description": "API for provisioning and managing identity resources.", - "discoveryRestUrl": "https://cloudidentity.googleapis.com/$discovery/rest?version=v1beta1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/identity/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "cloudiot:v1", - "name": "cloudiot", - "version": "v1", - "title": "Cloud IoT API", - "description": "Registers and manages IoT (Internet of Things) devices that connect to the Google Cloud Platform.", - "discoveryRestUrl": "https://cloudiot.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/iot", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "cloudkms:v1", - "name": "cloudkms", - "version": "v1", - "title": "Cloud Key Management Service (KMS) API", - "description": "Manages keys and performs cryptographic operations in a central cloud service, for direct use by other cloud resources and applications.", - "discoveryRestUrl": "https://cloudkms.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/kms/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "cloudprofiler:v2", - "name": "cloudprofiler", - "version": "v2", - "title": "Stackdriver Profiler API", - "description": "Manages continuous profiling information.", - "discoveryRestUrl": "https://cloudprofiler.googleapis.com/$discovery/rest?version=v2", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/profiler/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "cloudresourcemanager:v1", - "name": "cloudresourcemanager", - "version": "v1", - "title": "Cloud Resource Manager API", - "description": "Creates, reads, and updates metadata for Google Cloud Platform resource containers.", - "discoveryRestUrl": "https://cloudresourcemanager.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/resource-manager", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "cloudresourcemanager:v1beta1", - "name": "cloudresourcemanager", - "version": "v1beta1", - "title": "Cloud Resource Manager API", - "description": "Creates, reads, and updates metadata for Google Cloud Platform resource containers.", - "discoveryRestUrl": "https://cloudresourcemanager.googleapis.com/$discovery/rest?version=v1beta1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/resource-manager", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "cloudresourcemanager:v2", - "name": "cloudresourcemanager", - "version": "v2", - "title": "Cloud Resource Manager API", - "description": "Creates, reads, and updates metadata for Google Cloud Platform resource containers.", - "discoveryRestUrl": "https://cloudresourcemanager.googleapis.com/$discovery/rest?version=v2", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/resource-manager", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "cloudresourcemanager:v2beta1", - "name": "cloudresourcemanager", - "version": "v2beta1", - "title": "Cloud Resource Manager API", - "description": "Creates, reads, and updates metadata for Google Cloud Platform resource containers.", - "discoveryRestUrl": "https://cloudresourcemanager.googleapis.com/$discovery/rest?version=v2beta1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/resource-manager", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "cloudscheduler:v1beta1", - "name": "cloudscheduler", - "version": "v1beta1", - "title": "Cloud Scheduler API", - "description": "Creates and manages jobs run on a regular recurring schedule.", - "discoveryRestUrl": "https://cloudscheduler.googleapis.com/$discovery/rest?version=v1beta1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/scheduler/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "cloudsearch:v1", - "name": "cloudsearch", - "version": "v1", - "title": "Cloud Search API", - "description": "Cloud Search provides cloud-based search capabilities over G Suite data. The Cloud Search API allows indexing of non-G Suite data into Cloud Search.", - "discoveryRestUrl": "https://cloudsearch.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://gsuite.google.com/products/cloud-search/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "cloudshell:v1alpha1", - "name": "cloudshell", - "version": "v1alpha1", - "title": "Cloud Shell API", - "description": "Allows users to start, configure, and connect to interactive shell sessions running in the cloud.", - "discoveryRestUrl": "https://cloudshell.googleapis.com/$discovery/rest?version=v1alpha1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/shell/docs/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "cloudshell:v1", - "name": "cloudshell", - "version": "v1", - "title": "Cloud Shell API", - "description": "Allows users to start, configure, and connect to interactive shell sessions running in the cloud.", - "discoveryRestUrl": "https://cloudshell.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/shell/docs/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "cloudtasks:v2beta2", - "name": "cloudtasks", - "version": "v2beta2", - "title": "Cloud Tasks API", - "description": "Manages the execution of large numbers of distributed requests.", - "discoveryRestUrl": "https://cloudtasks.googleapis.com/$discovery/rest?version=v2beta2", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/tasks/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "cloudtasks:v2beta3", - "name": "cloudtasks", - "version": "v2beta3", - "title": "Cloud Tasks API", - "description": "Manages the execution of large numbers of distributed requests.", - "discoveryRestUrl": "https://cloudtasks.googleapis.com/$discovery/rest?version=v2beta3", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/tasks/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "cloudtrace:v2alpha1", - "name": "cloudtrace", - "version": "v2alpha1", - "title": "Stackdriver Trace API", - "description": "Sends application trace data to Stackdriver Trace for viewing. Trace data is collected for all App Engine applications by default. Trace data from other applications can be provided using this API. This library is used to interact with the Trace API directly. If you are looking to instrument your application for Stackdriver Trace, we recommend using OpenCensus.", - "discoveryRestUrl": "https://cloudtrace.googleapis.com/$discovery/rest?version=v2alpha1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/trace", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "cloudtrace:v1", - "name": "cloudtrace", - "version": "v1", - "title": "Stackdriver Trace API", - "description": "Sends application trace data to Stackdriver Trace for viewing. Trace data is collected for all App Engine applications by default. Trace data from other applications can be provided using this API. This library is used to interact with the Trace API directly. If you are looking to instrument your application for Stackdriver Trace, we recommend using OpenCensus.", - "discoveryRestUrl": "https://cloudtrace.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/trace", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "cloudtrace:v2", - "name": "cloudtrace", - "version": "v2", - "title": "Stackdriver Trace API", - "description": "Sends application trace data to Stackdriver Trace for viewing. Trace data is collected for all App Engine applications by default. Trace data from other applications can be provided using this API. This library is used to interact with the Trace API directly. If you are looking to instrument your application for Stackdriver Trace, we recommend using OpenCensus.", - "discoveryRestUrl": "https://cloudtrace.googleapis.com/$discovery/rest?version=v2", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/trace", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "composer:v1", - "name": "composer", - "version": "v1", - "title": "Cloud Composer API", - "description": "Manages Apache Airflow environments on Google Cloud Platform.", - "discoveryRestUrl": "https://composer.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/composer/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "composer:v1beta1", - "name": "composer", - "version": "v1beta1", - "title": "Cloud Composer API", - "description": "Manages Apache Airflow environments on Google Cloud Platform.", - "discoveryRestUrl": "https://composer.googleapis.com/$discovery/rest?version=v1beta1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/composer/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "compute:alpha", - "name": "compute", - "version": "alpha", - "title": "Compute Engine API", - "description": "Creates and runs virtual machines on Google Cloud Platform.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/compute/alpha/rest", - "discoveryLink": "./apis/compute/alpha/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/compute_engine-16.png", - "x32": "https://www.google.com/images/icons/product/compute_engine-32.png" - }, - "documentationLink": "https://developers.google.com/compute/docs/reference/latest/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "compute:beta", - "name": "compute", - "version": "beta", - "title": "Compute Engine API", - "description": "Creates and runs virtual machines on Google Cloud Platform.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/compute/beta/rest", - "discoveryLink": "./apis/compute/beta/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/compute_engine-16.png", - "x32": "https://www.google.com/images/icons/product/compute_engine-32.png" - }, - "documentationLink": "https://developers.google.com/compute/docs/reference/latest/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "compute:v1", - "name": "compute", - "version": "v1", - "title": "Compute Engine API", - "description": "Creates and runs virtual machines on Google Cloud Platform.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/compute/v1/rest", - "discoveryLink": "./apis/compute/v1/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/compute_engine-16.png", - "x32": "https://www.google.com/images/icons/product/compute_engine-32.png" - }, - "documentationLink": "https://developers.google.com/compute/docs/reference/latest/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "container:v1", - "name": "container", - "version": "v1", - "title": "Kubernetes Engine API", - "description": "Builds and manages container-based applications, powered by the open source Kubernetes technology.", - "discoveryRestUrl": "https://container.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/container-engine/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "container:v1beta1", - "name": "container", - "version": "v1beta1", - "title": "Kubernetes Engine API", - "description": "Builds and manages container-based applications, powered by the open source Kubernetes technology.", - "discoveryRestUrl": "https://container.googleapis.com/$discovery/rest?version=v1beta1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/container-engine/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "content:v2", - "name": "content", - "version": "v2", - "title": "Content API for Shopping", - "description": "Manages product items, inventory, and Merchant Center accounts for Google Shopping.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/content/v2/rest", - "discoveryLink": "./apis/content/v2/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/shopping-content", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "content:v2.1", - "name": "content", - "version": "v2.1", - "title": "Content API for Shopping", - "description": "Manages product items, inventory, and Merchant Center accounts for Google Shopping.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/content/v2.1/rest", - "discoveryLink": "./apis/content/v2.1/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/shopping-content", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "customsearch:v1", - "name": "customsearch", - "version": "v1", - "title": "CustomSearch API", - "description": "Searches over a website or collection of websites", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/customsearch/v1/rest", - "discoveryLink": "./apis/customsearch/v1/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/custom-search/v1/using_rest", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "dataflow:v1b3", - "name": "dataflow", - "version": "v1b3", - "title": "Dataflow API", - "description": "Manages Google Cloud Dataflow projects on Google Cloud Platform.", - "discoveryRestUrl": "https://dataflow.googleapis.com/$discovery/rest?version=v1b3", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/dataflow", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "dataproc:v1", - "name": "dataproc", - "version": "v1", - "title": "Cloud Dataproc API", - "description": "Manages Hadoop-based clusters and jobs on Google Cloud Platform.", - "discoveryRestUrl": "https://dataproc.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/dataproc/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "dataproc:v1beta2", - "name": "dataproc", - "version": "v1beta2", - "title": "Cloud Dataproc API", - "description": "Manages Hadoop-based clusters and jobs on Google Cloud Platform.", - "discoveryRestUrl": "https://dataproc.googleapis.com/$discovery/rest?version=v1beta2", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/dataproc/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "datastore:v1", - "name": "datastore", - "version": "v1", - "title": "Cloud Datastore API", - "description": "Accesses the schemaless NoSQL database to provide fully managed, robust, scalable storage for your application.", - "discoveryRestUrl": "https://datastore.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/datastore/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "datastore:v1beta1", - "name": "datastore", - "version": "v1beta1", - "title": "Cloud Datastore API", - "description": "Accesses the schemaless NoSQL database to provide fully managed, robust, scalable storage for your application.", - "discoveryRestUrl": "https://datastore.googleapis.com/$discovery/rest?version=v1beta1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/datastore/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "datastore:v1beta3", - "name": "datastore", - "version": "v1beta3", - "title": "Cloud Datastore API", - "description": "Accesses the schemaless NoSQL database to provide fully managed, robust, scalable storage for your application.", - "discoveryRestUrl": "https://datastore.googleapis.com/$discovery/rest?version=v1beta3", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/datastore/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "deploymentmanager:alpha", - "name": "deploymentmanager", - "version": "alpha", - "title": "Google Cloud Deployment Manager Alpha API", - "description": "The Deployment Manager API allows users to declaratively configure, deploy and run complex solutions on the Google Cloud Platform.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/deploymentmanager/alpha/rest", - "discoveryLink": "./apis/deploymentmanager/alpha/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/deployment-manager/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "deploymentmanager:v2beta", - "name": "deploymentmanager", - "version": "v2beta", - "title": "Google Cloud Deployment Manager API V2Beta Methods", - "description": "The Deployment Manager API allows users to declaratively configure, deploy and run complex solutions on the Google Cloud Platform.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/deploymentmanager/v2beta/rest", - "discoveryLink": "./apis/deploymentmanager/v2beta/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/deployment-manager/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "deploymentmanager:v2", - "name": "deploymentmanager", - "version": "v2", - "title": "Google Cloud Deployment Manager API", - "description": "Declares, configures, and deploys complex solutions on Google Cloud Platform.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/deploymentmanager/v2/rest", - "discoveryLink": "./apis/deploymentmanager/v2/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/deployment-manager/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "dfareporting:v3.1", - "name": "dfareporting", - "version": "v3.1", - "title": "DCM/DFA Reporting And Trafficking API", - "description": "Manages your DoubleClick Campaign Manager ad campaigns and reports.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/dfareporting/v3.1/rest", - "discoveryLink": "./apis/dfareporting/v3.1/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/doubleclick-16.gif", - "x32": "https://www.google.com/images/icons/product/doubleclick-32.gif" - }, - "documentationLink": "https://developers.google.com/doubleclick-advertisers/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "dfareporting:v3.2", - "name": "dfareporting", - "version": "v3.2", - "title": "DCM/DFA Reporting And Trafficking API", - "description": "Manages your DoubleClick Campaign Manager ad campaigns and reports.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/dfareporting/v3.2/rest", - "discoveryLink": "./apis/dfareporting/v3.2/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/doubleclick-16.gif", - "x32": "https://www.google.com/images/icons/product/doubleclick-32.gif" - }, - "documentationLink": "https://developers.google.com/doubleclick-advertisers/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "dialogflow:v2", - "name": "dialogflow", - "version": "v2", - "title": "Dialogflow API", - "description": "Builds conversational interfaces (for example, chatbots, and voice-powered apps and devices).", - "discoveryRestUrl": "https://dialogflow.googleapis.com/$discovery/rest?version=v2", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/dialogflow-enterprise/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "dialogflow:v2beta1", - "name": "dialogflow", - "version": "v2beta1", - "title": "Dialogflow API", - "description": "Builds conversational interfaces (for example, chatbots, and voice-powered apps and devices).", - "discoveryRestUrl": "https://dialogflow.googleapis.com/$discovery/rest?version=v2beta1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/dialogflow-enterprise/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "digitalassetlinks:v1", - "name": "digitalassetlinks", - "version": "v1", - "title": "Digital Asset Links API", - "description": "Discovers relationships between online assets such as websites or mobile apps.", - "discoveryRestUrl": "https://digitalassetlinks.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/digital-asset-links/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "discovery:v1", - "name": "discovery", - "version": "v1", - "title": "APIs Discovery Service", - "description": "Provides information about other Google APIs, such as what APIs are available, the resource, and method details for each API.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/discovery/v1/rest", - "discoveryLink": "./apis/discovery/v1/rest", - "icons": { - "x16": "http://www.google.com/images/icons/feature/filing_cabinet_search-g16.png", - "x32": "http://www.google.com/images/icons/feature/filing_cabinet_search-g32.png" - }, - "documentationLink": "https://developers.google.com/discovery/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "dlp:v2", - "name": "dlp", - "version": "v2", - "title": "Cloud Data Loss Prevention (DLP) API", - "description": "Provides methods for detection, risk analysis, and de-identification of privacy-sensitive fragments in text, images, and Google Cloud Platform storage repositories.", - "discoveryRestUrl": "https://dlp.googleapis.com/$discovery/rest?version=v2", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/dlp/docs/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "dns:v1", - "name": "dns", - "version": "v1", - "title": "Google Cloud DNS API", - "description": "Configures and serves authoritative DNS records.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/dns/v1/rest", - "discoveryLink": "./apis/dns/v1/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/cloud-dns", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "dns:v1beta2", - "name": "dns", - "version": "v1beta2", - "title": "Google Cloud DNS API", - "description": "Configures and serves authoritative DNS records.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/dns/v1beta2/rest", - "discoveryLink": "./apis/dns/v1beta2/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/cloud-dns", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "dns:v2beta1", - "name": "dns", - "version": "v2beta1", - "title": "Google Cloud DNS API", - "description": "Configures and serves authoritative DNS records.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/dns/v2beta1/rest", - "discoveryLink": "./apis/dns/v2beta1/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/cloud-dns", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "doubleclickbidmanager:v1", - "name": "doubleclickbidmanager", - "version": "v1", - "title": "DoubleClick Bid Manager API", - "description": "API for viewing and managing your reports in DoubleClick Bid Manager.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/doubleclickbidmanager/v1/rest", - "discoveryLink": "./apis/doubleclickbidmanager/v1/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/bid-manager/", - "labels": [ - "limited_availability" - ], - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "doubleclicksearch:v2", - "name": "doubleclicksearch", - "version": "v2", - "title": "DoubleClick Search API", - "description": "Reports and modifies your advertising data in DoubleClick Search (for example, campaigns, ad groups, keywords, and conversions).", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/doubleclicksearch/v2/rest", - "discoveryLink": "./apis/doubleclicksearch/v2/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/doubleclick-search/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "drive:v2", - "name": "drive", - "version": "v2", - "title": "Drive API", - "description": "Manages files in Drive including uploading, downloading, searching, detecting changes, and updating sharing permissions.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/drive/v2/rest", - "discoveryLink": "./apis/drive/v2/rest", - "icons": { - "x16": "https://ssl.gstatic.com/docs/doclist/images/drive_icon_16.png", - "x32": "https://ssl.gstatic.com/docs/doclist/images/drive_icon_32.png" - }, - "documentationLink": "https://developers.google.com/drive/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "drive:v3", - "name": "drive", - "version": "v3", - "title": "Drive API", - "description": "Manages files in Drive including uploading, downloading, searching, detecting changes, and updating sharing permissions.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/drive/v3/rest", - "discoveryLink": "./apis/drive/v3/rest", - "icons": { - "x16": "https://ssl.gstatic.com/docs/doclist/images/drive_icon_16.png", - "x32": "https://ssl.gstatic.com/docs/doclist/images/drive_icon_32.png" - }, - "documentationLink": "https://developers.google.com/drive/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "driveactivity:v2", - "name": "driveactivity", - "version": "v2", - "title": "Drive Activity API", - "description": "Provides a historical view of activity in Google Drive.", - "discoveryRestUrl": "https://driveactivity.googleapis.com/$discovery/rest?version=v2", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/drive/activity/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "file:v1beta1", - "name": "file", - "version": "v1beta1", - "title": "Cloud Filestore API", - "description": "The Cloud Filestore API is used for creating and managing cloud file servers.", - "discoveryRestUrl": "https://file.googleapis.com/$discovery/rest?version=v1beta1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/filestore/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "firebasedynamiclinks:v1", - "name": "firebasedynamiclinks", - "version": "v1", - "title": "Firebase Dynamic Links API", - "description": "Programmatically creates and manages Firebase Dynamic Links.", - "discoveryRestUrl": "https://firebasedynamiclinks.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://firebase.google.com/docs/dynamic-links/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "firebasehosting:v1beta1", - "name": "firebasehosting", - "version": "v1beta1", - "title": "Firebase Hosting API", - "description": "", - "discoveryRestUrl": "https://firebasehosting.googleapis.com/$discovery/rest?version=v1beta1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://firebase.google.com/docs/hosting/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "firebaserules:v1", - "name": "firebaserules", - "version": "v1", - "title": "Firebase Rules API", - "description": "Creates and manages rules that determine when a Firebase Rules-enabled service should permit a request.", - "discoveryRestUrl": "https://firebaserules.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://firebase.google.com/docs/storage/security", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "firestore:v1", - "name": "firestore", - "version": "v1", - "title": "Cloud Firestore API", - "description": "Accesses the NoSQL document database built for automatic scaling, high performance, and ease of application development.", - "discoveryRestUrl": "https://firestore.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/firestore", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "firestore:v1beta1", - "name": "firestore", - "version": "v1beta1", - "title": "Cloud Firestore API", - "description": "Accesses the NoSQL document database built for automatic scaling, high performance, and ease of application development.", - "discoveryRestUrl": "https://firestore.googleapis.com/$discovery/rest?version=v1beta1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/firestore", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "firestore:v1beta2", - "name": "firestore", - "version": "v1beta2", - "title": "Cloud Firestore API", - "description": "Accesses the NoSQL document database built for automatic scaling, high performance, and ease of application development.", - "discoveryRestUrl": "https://firestore.googleapis.com/$discovery/rest?version=v1beta2", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/firestore", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "fitness:v1", - "name": "fitness", - "version": "v1", - "title": "Fitness", - "description": "Stores and accesses user data in the fitness store from apps on any platform.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/fitness/v1/rest", - "discoveryLink": "./apis/fitness/v1/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/fit/rest/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "fusiontables:v1", - "name": "fusiontables", - "version": "v1", - "title": "Fusion Tables API", - "description": "API for working with Fusion Tables data.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/fusiontables/v1/rest", - "discoveryLink": "./apis/fusiontables/v1/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/fusiontables", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "fusiontables:v2", - "name": "fusiontables", - "version": "v2", - "title": "Fusion Tables API", - "description": "API for working with Fusion Tables data.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/fusiontables/v2/rest", - "discoveryLink": "./apis/fusiontables/v2/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/fusiontables", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "games:v1", - "name": "games", - "version": "v1", - "title": "Google Play Game Services API", - "description": "The API for Google Play Game Services.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/games/v1/rest", - "discoveryLink": "./apis/games/v1/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/games/services/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "gamesConfiguration:v1configuration", - "name": "gamesConfiguration", - "version": "v1configuration", - "title": "Google Play Game Services Publishing API", - "description": "The Publishing API for Google Play Game Services.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/gamesConfiguration/v1configuration/rest", - "discoveryLink": "./apis/gamesConfiguration/v1configuration/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/games/services", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "gamesManagement:v1management", - "name": "gamesManagement", - "version": "v1management", - "title": "Google Play Game Services Management API", - "description": "The Management API for Google Play Game Services.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/gamesManagement/v1management/rest", - "discoveryLink": "./apis/gamesManagement/v1management/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/games/services", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "genomics:v1alpha2", - "name": "genomics", - "version": "v1alpha2", - "title": "Genomics API", - "description": "Uploads, processes, queries, and searches Genomics data in the cloud.", - "discoveryRestUrl": "https://genomics.googleapis.com/$discovery/rest?version=v1alpha2", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/genomics", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "genomics:v2alpha1", - "name": "genomics", - "version": "v2alpha1", - "title": "Genomics API", - "description": "Uploads, processes, queries, and searches Genomics data in the cloud.", - "discoveryRestUrl": "https://genomics.googleapis.com/$discovery/rest?version=v2alpha1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/genomics", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "genomics:v1", - "name": "genomics", - "version": "v1", - "title": "Genomics API", - "description": "Uploads, processes, queries, and searches Genomics data in the cloud.", - "discoveryRestUrl": "https://genomics.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/genomics", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "gmail:v1", - "name": "gmail", - "version": "v1", - "title": "Gmail API", - "description": "Access Gmail mailboxes including sending user email.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/gmail/v1/rest", - "discoveryLink": "./apis/gmail/v1/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/googlemail-16.png", - "x32": "https://www.google.com/images/icons/product/googlemail-32.png" - }, - "documentationLink": "https://developers.google.com/gmail/api/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "groupsmigration:v1", - "name": "groupsmigration", - "version": "v1", - "title": "Groups Migration API", - "description": "Groups Migration Api.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/groupsmigration/v1/rest", - "discoveryLink": "./apis/groupsmigration/v1/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/discussions-16.gif", - "x32": "https://www.google.com/images/icons/product/discussions-32.gif" - }, - "documentationLink": "https://developers.google.com/google-apps/groups-migration/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "groupssettings:v1", - "name": "groupssettings", - "version": "v1", - "title": "Groups Settings API", - "description": "Lets you manage permission levels and related settings of a group.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/groupssettings/v1/rest", - "discoveryLink": "./apis/groupssettings/v1/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/google-apps/groups-settings/get_started", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "iam:v1", - "name": "iam", - "version": "v1", - "title": "Identity and Access Management (IAM) API", - "description": "Manages identity and access control for Google Cloud Platform resources, including the creation of service accounts, which you can use to authenticate to Google and make API calls.", - "discoveryRestUrl": "https://iam.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/iam/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "iamcredentials:v1", - "name": "iamcredentials", - "version": "v1", - "title": "IAM Service Account Credentials API", - "description": "Creates short-lived, limited-privilege credentials for IAM service accounts.", - "discoveryRestUrl": "https://iamcredentials.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/iam/docs/creating-short-lived-service-account-credentials", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "iap:v1", - "name": "iap", - "version": "v1", - "title": "Cloud Identity-Aware Proxy API", - "description": "Controls access to cloud applications running on Google Cloud Platform.", - "discoveryRestUrl": "https://iap.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/iap", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "iap:v1beta1", - "name": "iap", - "version": "v1beta1", - "title": "Cloud Identity-Aware Proxy API", - "description": "Controls access to cloud applications running on Google Cloud Platform.", - "discoveryRestUrl": "https://iap.googleapis.com/$discovery/rest?version=v1beta1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/iap", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "identitytoolkit:v3", - "name": "identitytoolkit", - "version": "v3", - "title": "Google Identity Toolkit API", - "description": "Help the third party sites to implement federated login.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/identitytoolkit/v3/rest", - "discoveryLink": "./apis/identitytoolkit/v3/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/identity-toolkit/v3/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "indexing:v3", - "name": "indexing", - "version": "v3", - "title": "Indexing API", - "description": "Notifies Google when your web pages change.", - "discoveryRestUrl": "https://indexing.googleapis.com/$discovery/rest?version=v3", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/search/apis/indexing-api/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "jobs:v3p1beta1", - "name": "jobs", - "version": "v3p1beta1", - "title": "Cloud Talent Solution API", - "description": "Cloud Talent Solution provides the capability to create, read, update, and delete job postings, as well as search jobs based on keywords and filters.", - "discoveryRestUrl": "https://jobs.googleapis.com/$discovery/rest?version=v3p1beta1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/talent-solution/job-search/docs/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "jobs:v2", - "name": "jobs", - "version": "v2", - "title": "Cloud Talent Solution API", - "description": "Cloud Talent Solution provides the capability to create, read, update, and delete job postings, as well as search jobs based on keywords and filters.", - "discoveryRestUrl": "https://jobs.googleapis.com/$discovery/rest?version=v2", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/talent-solution/job-search/docs/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "jobs:v3", - "name": "jobs", - "version": "v3", - "title": "Cloud Talent Solution API", - "description": "Cloud Talent Solution provides the capability to create, read, update, and delete job postings, as well as search jobs based on keywords and filters.", - "discoveryRestUrl": "https://jobs.googleapis.com/$discovery/rest?version=v3", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/talent-solution/job-search/docs/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "kgsearch:v1", - "name": "kgsearch", - "version": "v1", - "title": "Knowledge Graph Search API", - "description": "Searches the Google Knowledge Graph for entities.", - "discoveryRestUrl": "https://kgsearch.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/knowledge-graph/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "language:v1", - "name": "language", - "version": "v1", - "title": "Cloud Natural Language API", - "description": "Provides natural language understanding technologies, such as sentiment analysis, entity recognition, entity sentiment analysis, and other text annotations, to developers.", - "discoveryRestUrl": "https://language.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/natural-language/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "language:v1beta1", - "name": "language", - "version": "v1beta1", - "title": "Cloud Natural Language API", - "description": "Provides natural language understanding technologies, such as sentiment analysis, entity recognition, entity sentiment analysis, and other text annotations, to developers.", - "discoveryRestUrl": "https://language.googleapis.com/$discovery/rest?version=v1beta1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/natural-language/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "language:v1beta2", - "name": "language", - "version": "v1beta2", - "title": "Cloud Natural Language API", - "description": "Provides natural language understanding technologies, such as sentiment analysis, entity recognition, entity sentiment analysis, and other text annotations, to developers.", - "discoveryRestUrl": "https://language.googleapis.com/$discovery/rest?version=v1beta2", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/natural-language/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "licensing:v1", - "name": "licensing", - "version": "v1", - "title": "Enterprise License Manager API", - "description": "Views and manages licenses for your domain.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/licensing/v1/rest", - "discoveryLink": "./apis/licensing/v1/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/google-apps/licensing/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "logging:v2", - "name": "logging", - "version": "v2", - "title": "Stackdriver Logging API", - "description": "Writes log entries and manages your Logging configuration.", - "discoveryRestUrl": "https://logging.googleapis.com/$discovery/rest?version=v2", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/logging/docs/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "logging:v2beta1", - "name": "logging", - "version": "v2beta1", - "title": "Stackdriver Logging API", - "description": "Writes log entries and manages your Logging configuration.", - "discoveryRestUrl": "https://logging.googleapis.com/$discovery/rest?version=v2beta1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/logging/docs/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "manufacturers:v1", - "name": "manufacturers", - "version": "v1", - "title": "Manufacturer Center API", - "description": "Public API for managing Manufacturer Center related data.", - "discoveryRestUrl": "https://manufacturers.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/manufacturers/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "mirror:v1", - "name": "mirror", - "version": "v1", - "title": "Google Mirror API", - "description": "Interacts with Glass users via the timeline.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/mirror/v1/rest", - "discoveryLink": "./apis/mirror/v1/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/glass", - "labels": [ - "limited_availability" - ], - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "ml:v1", - "name": "ml", - "version": "v1", - "title": "Cloud Machine Learning Engine", - "description": "An API to enable creating and using machine learning models.", - "discoveryRestUrl": "https://ml.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/ml/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "monitoring:v1", - "name": "monitoring", - "version": "v1", - "title": "Stackdriver Monitoring API", - "description": "Manages your Stackdriver Monitoring data and configurations. Most projects must be associated with a Stackdriver account, with a few exceptions as noted on the individual method pages.", - "discoveryRestUrl": "https://monitoring.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/monitoring/api/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "monitoring:v3", - "name": "monitoring", - "version": "v3", - "title": "Stackdriver Monitoring API", - "description": "Manages your Stackdriver Monitoring data and configurations. Most projects must be associated with a Stackdriver account, with a few exceptions as noted on the individual method pages.", - "discoveryRestUrl": "https://monitoring.googleapis.com/$discovery/rest?version=v3", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/monitoring/api/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "oauth2:v1", - "name": "oauth2", - "version": "v1", - "title": "Google OAuth2 API", - "description": "Obtains end-user authorization grants for use with other Google APIs.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/oauth2/v1/rest", - "discoveryLink": "./apis/oauth2/v1/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/accounts/docs/OAuth2", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "oauth2:v2", - "name": "oauth2", - "version": "v2", - "title": "Google OAuth2 API", - "description": "Obtains end-user authorization grants for use with other Google APIs.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/oauth2/v2/rest", - "discoveryLink": "./apis/oauth2/v2/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/accounts/docs/OAuth2", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "oslogin:v1alpha", - "name": "oslogin", - "version": "v1alpha", - "title": "Cloud OS Login API", - "description": "Manages OS login configuration for Google account users.", - "discoveryRestUrl": "https://oslogin.googleapis.com/$discovery/rest?version=v1alpha", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/compute/docs/oslogin/rest/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "oslogin:v1beta", - "name": "oslogin", - "version": "v1beta", - "title": "Cloud OS Login API", - "description": "Manages OS login configuration for Google account users.", - "discoveryRestUrl": "https://oslogin.googleapis.com/$discovery/rest?version=v1beta", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/compute/docs/oslogin/rest/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "oslogin:v1", - "name": "oslogin", - "version": "v1", - "title": "Cloud OS Login API", - "description": "Manages OS login configuration for Google account users.", - "discoveryRestUrl": "https://oslogin.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/compute/docs/oslogin/rest/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "pagespeedonline:v1", - "name": "pagespeedonline", - "version": "v1", - "title": "PageSpeed Insights API", - "description": "Analyzes the performance of a web page and provides tailored suggestions to make that page faster.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/pagespeedonline/v1/rest", - "discoveryLink": "./apis/pagespeedonline/v1/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/pagespeed-16.png", - "x32": "https://www.google.com/images/icons/product/pagespeed-32.png" - }, - "documentationLink": "https://developers.google.com/speed/docs/insights/v1/getting_started", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "pagespeedonline:v2", - "name": "pagespeedonline", - "version": "v2", - "title": "PageSpeed Insights API", - "description": "Analyzes the performance of a web page and provides tailored suggestions to make that page faster.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/pagespeedonline/v2/rest", - "discoveryLink": "./apis/pagespeedonline/v2/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/pagespeed-16.png", - "x32": "https://www.google.com/images/icons/product/pagespeed-32.png" - }, - "documentationLink": "https://developers.google.com/speed/docs/insights/v2/getting-started", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "pagespeedonline:v4", - "name": "pagespeedonline", - "version": "v4", - "title": "PageSpeed Insights API", - "description": "Analyzes the performance of a web page and provides tailored suggestions to make that page faster.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/pagespeedonline/v4/rest", - "discoveryLink": "./apis/pagespeedonline/v4/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/pagespeed-16.png", - "x32": "https://www.google.com/images/icons/product/pagespeed-32.png" - }, - "documentationLink": "https://developers.google.com/speed/docs/insights/v4/getting-started", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "pagespeedonline:v5", - "name": "pagespeedonline", - "version": "v5", - "title": "PageSpeed Insights API", - "description": "Analyzes the performance of a web page and provides tailored suggestions to make that page faster.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/pagespeedonline/v5/rest", - "discoveryLink": "./apis/pagespeedonline/v5/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/pagespeed-16.png", - "x32": "https://www.google.com/images/icons/product/pagespeed-32.png" - }, - "documentationLink": "https://developers.google.com/speed/docs/insights/v5/get-started", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "partners:v2", - "name": "partners", - "version": "v2", - "title": "Google Partners API", - "description": "Searches certified companies and creates contact leads with them, and also audits the usage of clients.", - "discoveryRestUrl": "https://partners.googleapis.com/$discovery/rest?version=v2", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/partners/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "people:v1", - "name": "people", - "version": "v1", - "title": "People API", - "description": "Provides access to information about profiles and contacts.", - "discoveryRestUrl": "https://people.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/people/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "playcustomapp:v1", - "name": "playcustomapp", - "version": "v1", - "title": "Google Play Custom App Publishing API", - "description": "An API to publish custom Android apps.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/playcustomapp/v1/rest", - "discoveryLink": "./apis/playcustomapp/v1/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/android/work/play/custom-app-api", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "plus:v1", - "name": "plus", - "version": "v1", - "title": "Google+ API", - "description": "Builds on top of the Google+ platform.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/plus/v1/rest", - "discoveryLink": "./apis/plus/v1/rest", - "icons": { - "x16": "http://www.google.com/images/icons/product/gplus-16.png", - "x32": "http://www.google.com/images/icons/product/gplus-32.png" - }, - "documentationLink": "https://developers.google.com/+/api/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "plusDomains:v1", - "name": "plusDomains", - "version": "v1", - "title": "Google+ Domains API", - "description": "Builds on top of the Google+ platform for Google Apps Domains.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/plusDomains/v1/rest", - "discoveryLink": "./apis/plusDomains/v1/rest", - "icons": { - "x16": "http://www.google.com/images/icons/product/gplus-16.png", - "x32": "http://www.google.com/images/icons/product/gplus-32.png" - }, - "documentationLink": "https://developers.google.com/+/domains/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "poly:v1", - "name": "poly", - "version": "v1", - "title": "Poly API", - "description": "The Poly API provides read access to assets hosted on poly.google.com to all, and upload access to poly.google.com for whitelisted accounts.", - "discoveryRestUrl": "https://poly.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/poly/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "proximitybeacon:v1beta1", - "name": "proximitybeacon", - "version": "v1beta1", - "title": "Proximity Beacon API", - "description": "Registers, manages, indexes, and searches beacons.", - "discoveryRestUrl": "https://proximitybeacon.googleapis.com/$discovery/rest?version=v1beta1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/beacons/proximity/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "pubsub:v1beta1a", - "name": "pubsub", - "version": "v1beta1a", - "title": "Cloud Pub/Sub API", - "description": "Provides reliable, many-to-many, asynchronous messaging between applications.", - "discoveryRestUrl": "https://pubsub.googleapis.com/$discovery/rest?version=v1beta1a", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/pubsub/docs", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "pubsub:v1", - "name": "pubsub", - "version": "v1", - "title": "Cloud Pub/Sub API", - "description": "Provides reliable, many-to-many, asynchronous messaging between applications.", - "discoveryRestUrl": "https://pubsub.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/pubsub/docs", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "pubsub:v1beta2", - "name": "pubsub", - "version": "v1beta2", - "title": "Cloud Pub/Sub API", - "description": "Provides reliable, many-to-many, asynchronous messaging between applications.", - "discoveryRestUrl": "https://pubsub.googleapis.com/$discovery/rest?version=v1beta2", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/pubsub/docs", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "redis:v1", - "name": "redis", - "version": "v1", - "title": "Google Cloud Memorystore for Redis API", - "description": "Creates and manages Redis instances on the Google Cloud Platform.", - "discoveryRestUrl": "https://redis.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/memorystore/docs/redis/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "redis:v1beta1", - "name": "redis", - "version": "v1beta1", - "title": "Google Cloud Memorystore for Redis API", - "description": "Creates and manages Redis instances on the Google Cloud Platform.", - "discoveryRestUrl": "https://redis.googleapis.com/$discovery/rest?version=v1beta1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/memorystore/docs/redis/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "replicapool:v1beta1", - "name": "replicapool", - "version": "v1beta1", - "title": "Replica Pool API", - "description": "The Replica Pool API allows users to declaratively provision and manage groups of Google Compute Engine instances based on a common template.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/replicapool/v1beta1/rest", - "discoveryLink": "./apis/replicapool/v1beta1/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/compute/docs/replica-pool/", - "labels": [ - "limited_availability" - ], - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "reseller:v1", - "name": "reseller", - "version": "v1", - "title": "Enterprise Apps Reseller API", - "description": "Creates and manages your customers and their subscriptions.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/reseller/v1/rest", - "discoveryLink": "./apis/reseller/v1/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/google-apps/reseller/", - "labels": [ - "limited_availability" - ], - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "runtimeconfig:v1", - "name": "runtimeconfig", - "version": "v1", - "title": "Cloud Runtime Configuration API", - "description": "The Runtime Configurator allows you to dynamically configure and expose variables through Google Cloud Platform. In addition, you can also set Watchers and Waiters that will watch for changes to your data and return based on certain conditions.", - "discoveryRestUrl": "https://runtimeconfig.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/deployment-manager/runtime-configurator/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "runtimeconfig:v1beta1", - "name": "runtimeconfig", - "version": "v1beta1", - "title": "Cloud Runtime Configuration API", - "description": "The Runtime Configurator allows you to dynamically configure and expose variables through Google Cloud Platform. In addition, you can also set Watchers and Waiters that will watch for changes to your data and return based on certain conditions.", - "discoveryRestUrl": "https://runtimeconfig.googleapis.com/$discovery/rest?version=v1beta1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/deployment-manager/runtime-configurator/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "safebrowsing:v4", - "name": "safebrowsing", - "version": "v4", - "title": "Safe Browsing API", - "description": "Enables client applications to check web resources (most commonly URLs) against Google-generated lists of unsafe web resources.", - "discoveryRestUrl": "https://safebrowsing.googleapis.com/$discovery/rest?version=v4", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/safe-browsing/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "script:v1", - "name": "script", - "version": "v1", - "title": "Apps Script API", - "description": "Manages and executes Google Apps Script projects.", - "discoveryRestUrl": "https://script.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/apps-script/api/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "searchconsole:v1", - "name": "searchconsole", - "version": "v1", - "title": "Google Search Console URL Testing Tools API", - "description": "Provides tools for running validation tests against single URLs", - "discoveryRestUrl": "https://searchconsole.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/webmaster-tools/search-console-api/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "servicebroker:v1alpha1", - "name": "servicebroker", - "version": "v1alpha1", - "title": "Service Broker API", - "description": "The Google Cloud Platform Service Broker API provides Google hosted implementation of the Open Service Broker API (https://www.openservicebrokerapi.org/).", - "discoveryRestUrl": "https://servicebroker.googleapis.com/$discovery/rest?version=v1alpha1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/kubernetes-engine/docs/concepts/add-on/service-broker", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "servicebroker:v1", - "name": "servicebroker", - "version": "v1", - "title": "Service Broker API", - "description": "The Google Cloud Platform Service Broker API provides Google hosted implementation of the Open Service Broker API (https://www.openservicebrokerapi.org/).", - "discoveryRestUrl": "https://servicebroker.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/kubernetes-engine/docs/concepts/add-on/service-broker", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "servicebroker:v1beta1", - "name": "servicebroker", - "version": "v1beta1", - "title": "Service Broker API", - "description": "The Google Cloud Platform Service Broker API provides Google hosted implementation of the Open Service Broker API (https://www.openservicebrokerapi.org/).", - "discoveryRestUrl": "https://servicebroker.googleapis.com/$discovery/rest?version=v1beta1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/kubernetes-engine/docs/concepts/add-on/service-broker", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "serviceconsumermanagement:v1", - "name": "serviceconsumermanagement", - "version": "v1", - "title": "Service Consumer Management API", - "description": "Manages the service consumers of a Service Infrastructure service.", - "discoveryRestUrl": "https://serviceconsumermanagement.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/service-consumer-management/docs/overview", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "servicecontrol:v1", - "name": "servicecontrol", - "version": "v1", - "title": "Service Control API", - "description": "Provides control plane functionality to managed services, such as logging, monitoring, and status checks.", - "discoveryRestUrl": "https://servicecontrol.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/service-control/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "servicemanagement:v1", - "name": "servicemanagement", - "version": "v1", - "title": "Service Management API", - "description": "Google Service Management allows service producers to publish their services on Google Cloud Platform so that they can be discovered and used by service consumers.", - "discoveryRestUrl": "https://servicemanagement.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/service-management/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "servicenetworking:v1beta", - "name": "servicenetworking", - "version": "v1beta", - "title": "Service Networking API", - "description": "Provides automatic management of network configurations necessary for certain services.", - "discoveryRestUrl": "https://servicenetworking.googleapis.com/$discovery/rest?version=v1beta", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/service-infrastructure/docs/service-networking/getting-started", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "serviceusage:v1", - "name": "serviceusage", - "version": "v1", - "title": "Service Usage API", - "description": "Enables services that service consumers want to use on Google Cloud Platform, lists the available or enabled services, or disables services that service consumers no longer use.", - "discoveryRestUrl": "https://serviceusage.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/service-usage/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "serviceusage:v1beta1", - "name": "serviceusage", - "version": "v1beta1", - "title": "Service Usage API", - "description": "Enables services that service consumers want to use on Google Cloud Platform, lists the available or enabled services, or disables services that service consumers no longer use.", - "discoveryRestUrl": "https://serviceusage.googleapis.com/$discovery/rest?version=v1beta1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/service-usage/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "sheets:v4", - "name": "sheets", - "version": "v4", - "title": "Google Sheets API", - "description": "Reads and writes Google Sheets.", - "discoveryRestUrl": "https://sheets.googleapis.com/$discovery/rest?version=v4", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/sheets/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "siteVerification:v1", - "name": "siteVerification", - "version": "v1", - "title": "Google Site Verification API", - "description": "Verifies ownership of websites or domains with Google.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/siteVerification/v1/rest", - "discoveryLink": "./apis/siteVerification/v1/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/site-verification/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "slides:v1", - "name": "slides", - "version": "v1", - "title": "Google Slides API", - "description": "Reads and writes Google Slides presentations.", - "discoveryRestUrl": "https://slides.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/slides/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "sourcerepo:v1", - "name": "sourcerepo", - "version": "v1", - "title": "Cloud Source Repositories API", - "description": "Accesses source code repositories hosted by Google.", - "discoveryRestUrl": "https://sourcerepo.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/source-repositories/docs/apis", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "spanner:v1", - "name": "spanner", - "version": "v1", - "title": "Cloud Spanner API", - "description": "Cloud Spanner is a managed, mission-critical, globally consistent and scalable relational database service.", - "discoveryRestUrl": "https://spanner.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/spanner/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "speech:v1p1beta1", - "name": "speech", - "version": "v1p1beta1", - "title": "Cloud Speech API", - "description": "Converts audio to text by applying powerful neural network models.", - "discoveryRestUrl": "https://speech.googleapis.com/$discovery/rest?version=v1p1beta1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/speech-to-text/docs/quickstart-protocol", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "speech:v1", - "name": "speech", - "version": "v1", - "title": "Cloud Speech API", - "description": "Converts audio to text by applying powerful neural network models.", - "discoveryRestUrl": "https://speech.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/speech-to-text/docs/quickstart-protocol", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "sqladmin:v1beta4", - "name": "sqladmin", - "version": "v1beta4", - "title": "Cloud SQL Admin API", - "description": "Creates and manages Cloud SQL instances, which provide fully managed MySQL or PostgreSQL databases.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/sqladmin/v1beta4/rest", - "discoveryLink": "./apis/sqladmin/v1beta4/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/sql/docs/reference/latest", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "storage:v1", - "name": "storage", - "version": "v1", - "title": "Cloud Storage JSON API", - "description": "Stores and retrieves potentially large, immutable data objects.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/storage/v1/rest", - "discoveryLink": "./apis/storage/v1/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/cloud_storage-16.png", - "x32": "https://www.google.com/images/icons/product/cloud_storage-32.png" - }, - "documentationLink": "https://developers.google.com/storage/docs/json_api/", - "labels": [ - "labs" - ], - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "storage:v1beta1", - "name": "storage", - "version": "v1beta1", - "title": "Cloud Storage JSON API", - "description": "Lets you store and retrieve potentially-large, immutable data objects.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/storage/v1beta1/rest", - "discoveryLink": "./apis/storage/v1beta1/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/cloud_storage-16.png", - "x32": "https://www.google.com/images/icons/product/cloud_storage-32.png" - }, - "documentationLink": "https://developers.google.com/storage/docs/json_api/", - "labels": [ - "labs" - ], - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "storage:v1beta2", - "name": "storage", - "version": "v1beta2", - "title": "Cloud Storage JSON API", - "description": "Lets you store and retrieve potentially-large, immutable data objects.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/storage/v1beta2/rest", - "discoveryLink": "./apis/storage/v1beta2/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/cloud_storage-16.png", - "x32": "https://www.google.com/images/icons/product/cloud_storage-32.png" - }, - "documentationLink": "https://developers.google.com/storage/docs/json_api/", - "labels": [ - "labs" - ], - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "storagetransfer:v1", - "name": "storagetransfer", - "version": "v1", - "title": "Storage Transfer API", - "description": "Transfers data from external data sources to a Google Cloud Storage bucket or between Google Cloud Storage buckets.", - "discoveryRestUrl": "https://storagetransfer.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/storage/transfer", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "streetviewpublish:v1", - "name": "streetviewpublish", - "version": "v1", - "title": "Street View Publish API", - "description": "Publishes 360 photos to Google Maps, along with position, orientation, and connectivity metadata. Apps can offer an interface for positioning, connecting, and uploading user-generated Street View images.", - "discoveryRestUrl": "https://streetviewpublish.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/streetview/publish/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "surveys:v2", - "name": "surveys", - "version": "v2", - "title": "Surveys API", - "description": "Creates and conducts surveys, lists the surveys that an authenticated user owns, and retrieves survey results and information about specified surveys.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/surveys/v2/rest", - "discoveryLink": "./apis/surveys/v2/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "tagmanager:v1", - "name": "tagmanager", - "version": "v1", - "title": "Tag Manager API", - "description": "Accesses Tag Manager accounts and containers.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/tagmanager/v1/rest", - "discoveryLink": "./apis/tagmanager/v1/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/tag-manager/api/v1/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "tagmanager:v2", - "name": "tagmanager", - "version": "v2", - "title": "Tag Manager API", - "description": "Accesses Tag Manager accounts and containers.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/tagmanager/v2/rest", - "discoveryLink": "./apis/tagmanager/v2/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/tag-manager/api/v2/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "tasks:v1", - "name": "tasks", - "version": "v1", - "title": "Tasks API", - "description": "Lets you manage your tasks and task lists.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/tasks/v1/rest", - "discoveryLink": "./apis/tasks/v1/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/tasks-16.png", - "x32": "https://www.google.com/images/icons/product/tasks-32.png" - }, - "documentationLink": "https://developers.google.com/google-apps/tasks/firstapp", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "testing:v1", - "name": "testing", - "version": "v1", - "title": "Cloud Testing API", - "description": "Allows developers to run automated tests for their mobile applications on Google infrastructure.", - "discoveryRestUrl": "https://testing.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/cloud-test-lab/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "texttospeech:v1", - "name": "texttospeech", - "version": "v1", - "title": "Cloud Text-to-Speech API", - "description": "Synthesizes natural-sounding speech by applying powerful neural network models.", - "discoveryRestUrl": "https://texttospeech.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/text-to-speech/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "texttospeech:v1beta1", - "name": "texttospeech", - "version": "v1beta1", - "title": "Cloud Text-to-Speech API", - "description": "Synthesizes natural-sounding speech by applying powerful neural network models.", - "discoveryRestUrl": "https://texttospeech.googleapis.com/$discovery/rest?version=v1beta1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/text-to-speech/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "toolresults:v1beta3", - "name": "toolresults", - "version": "v1beta3", - "title": "Cloud Tool Results API", - "description": "Reads and publishes results from Firebase Test Lab.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/toolresults/v1beta3/rest", - "discoveryLink": "./apis/toolresults/v1beta3/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://firebase.google.com/docs/test-lab/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "tpu:v1alpha1", - "name": "tpu", - "version": "v1alpha1", - "title": "Cloud TPU API", - "description": "TPU API provides customers with access to Google TPU technology.", - "discoveryRestUrl": "https://tpu.googleapis.com/$discovery/rest?version=v1alpha1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/tpu/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "tpu:v1", - "name": "tpu", - "version": "v1", - "title": "Cloud TPU API", - "description": "TPU API provides customers with access to Google TPU technology.", - "discoveryRestUrl": "https://tpu.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/tpu/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "translate:v2", - "name": "translate", - "version": "v2", - "title": "Cloud Translation API", - "description": "Integrates text translation into your website or application.", - "discoveryRestUrl": "https://translation.googleapis.com/$discovery/rest?version=v2", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://code.google.com/apis/language/translate/v2/getting_started.html", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "urlshortener:v1", - "name": "urlshortener", - "version": "v1", - "title": "URL Shortener API", - "description": "Lets you create, inspect, and manage goo.gl short URLs", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/urlshortener/v1/rest", - "discoveryLink": "./apis/urlshortener/v1/rest", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/url-shortener/v1/getting_started", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "vault:v1", - "name": "vault", - "version": "v1", - "title": "G Suite Vault API", - "description": "Archiving and eDiscovery for G Suite.", - "discoveryRestUrl": "https://vault.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/vault", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "videointelligence:v1p1beta1", - "name": "videointelligence", - "version": "v1p1beta1", - "title": "Cloud Video Intelligence API", - "description": "Detects objects, explicit content, and scene changes in videos. It also specifies the region for annotation and transcribes speech to text.", - "discoveryRestUrl": "https://videointelligence.googleapis.com/$discovery/rest?version=v1p1beta1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/video-intelligence/docs/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "videointelligence:v1", - "name": "videointelligence", - "version": "v1", - "title": "Cloud Video Intelligence API", - "description": "Detects objects, explicit content, and scene changes in videos. It also specifies the region for annotation and transcribes speech to text.", - "discoveryRestUrl": "https://videointelligence.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/video-intelligence/docs/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "videointelligence:v1beta2", - "name": "videointelligence", - "version": "v1beta2", - "title": "Cloud Video Intelligence API", - "description": "Detects objects, explicit content, and scene changes in videos. It also specifies the region for annotation and transcribes speech to text.", - "discoveryRestUrl": "https://videointelligence.googleapis.com/$discovery/rest?version=v1beta2", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/video-intelligence/docs/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "vision:v1p1beta1", - "name": "vision", - "version": "v1p1beta1", - "title": "Cloud Vision API", - "description": "Integrates Google Vision features, including image labeling, face, logo, and landmark detection, optical character recognition (OCR), and detection of explicit content, into applications.", - "discoveryRestUrl": "https://vision.googleapis.com/$discovery/rest?version=v1p1beta1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/vision/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "vision:v1p2beta1", - "name": "vision", - "version": "v1p2beta1", - "title": "Cloud Vision API", - "description": "Integrates Google Vision features, including image labeling, face, logo, and landmark detection, optical character recognition (OCR), and detection of explicit content, into applications.", - "discoveryRestUrl": "https://vision.googleapis.com/$discovery/rest?version=v1p2beta1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/vision/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "vision:v1", - "name": "vision", - "version": "v1", - "title": "Cloud Vision API", - "description": "Integrates Google Vision features, including image labeling, face, logo, and landmark detection, optical character recognition (OCR), and detection of explicit content, into applications.", - "discoveryRestUrl": "https://vision.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/vision/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "webfonts:v1", - "name": "webfonts", - "version": "v1", - "title": "Google Fonts Developer API", - "description": "Accesses the metadata for all families served by Google Fonts, providing a list of families currently available (including available styles and a list of supported script subsets).", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/webfonts/v1/rest", - "discoveryLink": "./apis/webfonts/v1/rest", - "icons": { - "x16": "https://www.google.com/images/icons/feature/font_api-16.png", - "x32": "https://www.google.com/images/icons/feature/font_api-32.gif" - }, - "documentationLink": "https://developers.google.com/fonts/docs/developer_api", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "webmasters:v3", - "name": "webmasters", - "version": "v3", - "title": "Search Console API", - "description": "View Google Search Console data for your verified sites.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/webmasters/v3/rest", - "discoveryLink": "./apis/webmasters/v3/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/webmaster_tools-16.png", - "x32": "https://www.google.com/images/icons/product/webmaster_tools-32.png" - }, - "documentationLink": "https://developers.google.com/webmaster-tools/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "websecurityscanner:v1alpha", - "name": "websecurityscanner", - "version": "v1alpha", - "title": "Web Security Scanner API", - "description": "Scans your Compute and App Engine apps for common web vulnerabilities.", - "discoveryRestUrl": "https://websecurityscanner.googleapis.com/$discovery/rest?version=v1alpha", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/security-scanner/", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "websecurityscanner:v1beta", - "name": "websecurityscanner", - "version": "v1beta", - "title": "Web Security Scanner API", - "description": "Scans your Compute and App Engine apps for common web vulnerabilities.", - "discoveryRestUrl": "https://websecurityscanner.googleapis.com/$discovery/rest?version=v1beta", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://cloud.google.com/security-scanner/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "youtube:v3", - "name": "youtube", - "version": "v3", - "title": "YouTube Data API", - "description": "Supports core YouTube features, such as uploading videos, creating and managing playlists, searching for content, and much more.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/youtube/v3/rest", - "discoveryLink": "./apis/youtube/v3/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/youtube-16.png", - "x32": "https://www.google.com/images/icons/product/youtube-32.png" - }, - "documentationLink": "https://developers.google.com/youtube/v3", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "youtubeAnalytics:v1", - "name": "youtubeAnalytics", - "version": "v1", - "title": "YouTube Analytics API", - "description": "Retrieves your YouTube Analytics data.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/youtubeAnalytics/v1/rest", - "discoveryLink": "./apis/youtubeAnalytics/v1/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/youtube-16.png", - "x32": "https://www.google.com/images/icons/product/youtube-32.png" - }, - "documentationLink": "http://developers.google.com/youtube/analytics/", - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "youtubeAnalytics:v1beta1", - "name": "youtubeAnalytics", - "version": "v1beta1", - "title": "YouTube Analytics API", - "description": "Retrieves your YouTube Analytics data.", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/youtubeAnalytics/v1beta1/rest", - "discoveryLink": "./apis/youtubeAnalytics/v1beta1/rest", - "icons": { - "x16": "https://www.google.com/images/icons/product/youtube-16.png", - "x32": "https://www.google.com/images/icons/product/youtube-32.png" - }, - "documentationLink": "http://developers.google.com/youtube/analytics/", - "labels": [ - "deprecated" - ], - "preferred": false - }, - { - "kind": "discovery#directoryItem", - "id": "youtubeAnalytics:v2", - "name": "youtubeAnalytics", - "version": "v2", - "title": "YouTube Analytics API", - "description": "Retrieves your YouTube Analytics data.", - "discoveryRestUrl": "https://youtubeanalytics.googleapis.com/$discovery/rest?version=v2", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/youtube/analytics", - "preferred": true - }, - { - "kind": "discovery#directoryItem", - "id": "youtubereporting:v1", - "name": "youtubereporting", - "version": "v1", - "title": "YouTube Reporting API", - "description": "Schedules reporting jobs containing your YouTube Analytics data and downloads the resulting bulk data reports in the form of CSV files.", - "discoveryRestUrl": "https://youtubereporting.googleapis.com/$discovery/rest?version=v1", - "icons": { - "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", - "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" - }, - "documentationLink": "https://developers.google.com/youtube/reporting/v1/reports/", - "preferred": true - } - ] -} diff --git a/vendor/google.golang.org/api/go.mod b/vendor/google.golang.org/api/go.mod deleted file mode 100644 index eec4bb3e..00000000 --- a/vendor/google.golang.org/api/go.mod +++ /dev/null @@ -1,11 +0,0 @@ -module google.golang.org/api - -require ( - github.com/google/go-cmp v0.2.0 - go.opencensus.io v0.18.0 - golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890 - golang.org/x/sync v0.0.0-20181108010431-42b317875d0f - google.golang.org/appengine v1.3.0 - google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898 - google.golang.org/grpc v1.17.0 -) diff --git a/vendor/google.golang.org/api/go.sum b/vendor/google.golang.org/api/go.sum deleted file mode 100644 index c1840133..00000000 --- a/vendor/google.golang.org/api/go.sum +++ /dev/null @@ -1,58 +0,0 @@ -cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ= -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= -github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -go.opencensus.io v0.18.0 h1:Mk5rgZcggtbvtAun5aJzAtjKKN/t0R3jJPlWILlv938= -go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= -golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181106065722-10aee1819953 h1:LuZIitY8waaxUfNIdtajyE/YzA/zyf0YxXG27VpLrkg= -golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890 h1:uESlIz09WIHT2I+pasSXcpLYqYK8wHcdCetU3VuMBJE= -golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f h1:Bl/8QSvNqXvPGPGXa2z5xUTmV7VDcZyvRZ+QQXkXTZQ= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.3.0 h1:FBSsiFRMz3LBeXIomRnVzrQwSDj4ibvcRexLG0LZGQk= -google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898 h1:yvw+zsSmSM02Z5H3ZdEV7B7Ql7eFrjQTnmByJvK+3J8= -google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= -google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= -google.golang.org/grpc v1.17.0 h1:TRJYBgMclJvGYn2rIMjj+h9KtMt5r1Ij7ODVRIZkwhk= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/vendor/google.golang.org/api/googleapi/internal/uritemplates/LICENSE b/vendor/google.golang.org/api/googleapi/internal/uritemplates/LICENSE new file mode 100644 index 00000000..de9c88cb --- /dev/null +++ b/vendor/google.golang.org/api/googleapi/internal/uritemplates/LICENSE @@ -0,0 +1,18 @@ +Copyright (c) 2013 Joshua Tacoma + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/google.golang.org/api/key.json.enc b/vendor/google.golang.org/api/key.json.enc deleted file mode 100644 index 1286368010e083568344f647654071f7ceb8b97b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2432 zcmV-`34iv1%C6-HLz|k4h;vcrNKKz7QY$uvqLZrA#+ENMaijsr2O^{nlC~UeXsauO zyYC8hS)d;K)UHb-QtlD#IKYdJ?g}fxv6g?6vTk#!0L=Vf3fPH)eBOm5U~8RID32xj z!lLCp_&HFw`%U#Tys4(-#FgY|R$>uPJ7w;orm0Oc>(uZqL>UM3789vKL;ynRdAMh6;6TW5aMs+{3tB^Yc6w*{Cl{GH4Czv@r>GO`DSp!3dzo zR3uepj;3ZqnWfD}rNkoyWgz@_1lrhU1G(&G0UfzeBANC#d?Gj z8$uhd=K|SSFC=S8TgPPvJpv{j?Vy-vE+5n5t-cG!$*~5~6^&c5sD%R-7!QlkDU40Z zlD@Y9kS}fnbJ24Mma6v1r6*9qwXW>;C6%b~>gdgTBGG?+scG)OC>M$E5BNXbUW8;7 zc8i3cDaOc1Y6LhRvBw6JbT80Fhi$HaYini#G)kk~!E#LlsRQq=16HTHM-_CfBzToM zj8%ZqYnlH)fdWV1#41R67OFrpWD)_=MLFQqOokkW4o7BuG`Knp&36oWYIqQVEe?4I ztncN^cxebyD-z=9CzXhhf;iu+2tl-DQRIXuze*rO0=7oD7RPu+bICNWzdY}qc;R?1 zkyR18aH*LL^y@!jQpHA4x)sB8f6zdHm6G+cFY(69HgC?Uj=t^G;D<0(EC=QU{+5qU z?fsf>_9Av!U8ZP8%@okz;q%TE?z}&CiRf;dT7_aFrtVWH!jAAoguht{Uhj!S(sz$f z*%7NLG)!%&kGW{+(HUW{Q&8J(d}V!<=^8>+lsS3FkBYLHG*(h|?DW2TJ{)byUFA1C znor2|5@&ZN@Sg{bFA=;R0xzJr#J6*+bqHwYL0AG5%M&GlFhq2V%wj0b6HEk{Lyd+M zcMiac2axL@)s?BrEnoCdqK<-@P~J3LQqhFU94)8iZB&S2c<@KnZfLAm zNCWRle&_F~{0J|scVj=y=sS8USPOlRAUgiu1d#2qOH?IXrV`34*c}c%fW$G4Jzhf> zGvbqKd=144q$(kRH#OSM{5OyGZgSV;+@UvFdJ3)+PGEKlGB-l1Hnbz4UI0ii> zXN)^d`DiU(TgWx;L191Le9)veY+s~Drx8- zpyY_kxT0mLv9&V8Dn8YsvWf@4e7Kd;Gaid|=+))CiiRty{5@B~%ABJSP#7L; zMz07@PP9bY$uKt0^xDVV9GU!xUEIt1AQ5wEJd(kzrAKE{-dt+s&Cni~eWGw}kX0zMWYSj#!?Bc2PT6+;RU}RkzgPbqlLu4h4J9z*$Sj{&V?*FS ziRI(AY=-x6Hp6wYo&v+7gAwHs)eeiP;Jx?_8i_T5(WyTD+z0lvBLrJz=>g4*_cM@?U#t(GCvmsYeKlA&RON^GQ~U_W{$dp+|-R zoU21CG7kyafD0Ga>!q>G51XtnMu^O8726k|O2H|>iamt~oWAREElPma?xBU)7$s|9 z<=Jj+*Kj8ZI^lGK7Jh2(kPi7M8tgiTGi}m!qG13zB$^TIKyX|EPrnayRWF=uw{%c# z@kXpI-e~J3(qA?4o(4L?_fw+7mkt1>WU_E_=i=(!jc;ep=2iX2|4S`}PWTU-8_?$o zn~w9Hw!YVezofK)d->quDBY)~__2rv2dD6H4hNMgzk8GiTdl`1kIYt!Puj4)usus( z^w8HQcU-k&)W^py)N{Oa2KPnetpmbJTi2sBWYp3%rLU9bN**|Qvsm44Y|EhQT-$w6 z>h%&u5S%oMku+El8pC(CE64QgZ`I@$tJn!JdM$O!LmZK1*bU?iwGHb`EYRh3fUY}s zbu?f~HG#eXk-Q!0yU=;@ut;L`zA603{4g51>h(HfMriPid>X@?Xgi{vlNPq*7M-T@ yw(pSQU{u||=+p-tA;gzyD6))#<~f@qU4sSK<16G359nTZ3^o2G67!Z^Xw-)Qqq7VE diff --git a/vendor/google.golang.org/api/support/bundler/bundler_test.go b/vendor/google.golang.org/api/support/bundler/bundler_test.go deleted file mode 100644 index ec23ad3e..00000000 --- a/vendor/google.golang.org/api/support/bundler/bundler_test.go +++ /dev/null @@ -1,366 +0,0 @@ -// Copyright 2016 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package bundler - -import ( - "context" - "fmt" - "reflect" - "sync" - "testing" - "time" -) - -func TestBundlerCount1(t *testing.T) { - // Unbundled case: one item per bundle. - handler := &testHandler{} - b := NewBundler(int(0), handler.handle) - b.BundleCountThreshold = 1 - b.DelayThreshold = time.Second - - for i := 0; i < 3; i++ { - if err := b.Add(i, 1); err != nil { - t.Fatal(err) - } - } - b.Flush() - got := handler.bundles() - want := [][]int{{0}, {1}, {2}} - if !reflect.DeepEqual(got, want) { - t.Errorf("bundles: got %v, want %v", got, want) - } - // All bundles should have been handled "immediately": much less - // than the delay threshold of 1s. - tgot := quantizeTimes(handler.times(), 100*time.Millisecond) - twant := []int{0, 0, 0} - if !reflect.DeepEqual(tgot, twant) { - t.Errorf("times: got %v, want %v", tgot, twant) - } -} - -func TestBundlerCount3(t *testing.T) { - handler := &testHandler{} - b := NewBundler(int(0), handler.handle) - b.BundleCountThreshold = 3 - b.DelayThreshold = 100 * time.Millisecond - // Add 8 items. - // The first two bundles of 3 should both be handled quickly. - // The third bundle of 2 should not be handled for about DelayThreshold ms. - for i := 0; i < 8; i++ { - if err := b.Add(i, 1); err != nil { - t.Fatal(err) - } - } - time.Sleep(5 * b.DelayThreshold) - // We should not need to close the bundler. - - bgot := handler.bundles() - bwant := [][]int{{0, 1, 2}, {3, 4, 5}, {6, 7}} - if !reflect.DeepEqual(bgot, bwant) { - t.Errorf("bundles: got %v, want %v", bgot, bwant) - } - - tgot := quantizeTimes(handler.times(), b.DelayThreshold) - if len(tgot) != 3 || tgot[0] != 0 || tgot[1] != 0 || tgot[2] == 0 { - t.Errorf("times: got %v, want [0, 0, non-zero]", tgot) - } -} - -func TestBundlerByteThreshold(t *testing.T) { - handler := &testHandler{} - b := NewBundler(int(0), handler.handle) - b.BundleCountThreshold = 10 - b.BundleByteThreshold = 3 - add := func(i interface{}, s int) { - if err := b.Add(i, s); err != nil { - t.Fatal(err) - } - } - - add(1, 1) - add(2, 2) - // Hit byte threshold: bundle = 1, 2 - add(3, 1) - add(4, 1) - add(5, 2) - // Passed byte threshold, but not limit: bundle = 3, 4, 5 - add(6, 1) - b.Flush() - bgot := handler.bundles() - bwant := [][]int{{1, 2}, {3, 4, 5}, {6}} - if !reflect.DeepEqual(bgot, bwant) { - t.Errorf("bundles: got %v, want %v", bgot, bwant) - } - tgot := quantizeTimes(handler.times(), b.DelayThreshold) - twant := []int{0, 0, 0} - if !reflect.DeepEqual(tgot, twant) { - t.Errorf("times: got %v, want %v", tgot, twant) - } -} - -func TestBundlerLimit(t *testing.T) { - handler := &testHandler{} - b := NewBundler(int(0), handler.handle) - b.BundleCountThreshold = 10 - b.BundleByteLimit = 3 - add := func(i interface{}, s int) { - if err := b.Add(i, s); err != nil { - t.Fatal(err) - } - } - - add(1, 1) - add(2, 2) - // Hit byte limit: bundle = 1, 2 - add(3, 1) - add(4, 1) - add(5, 2) - // Exceeded byte limit: bundle = 3, 4 - add(6, 2) - // Exceeded byte limit: bundle = 5 - b.Flush() - bgot := handler.bundles() - bwant := [][]int{{1, 2}, {3, 4}, {5}, {6}} - if !reflect.DeepEqual(bgot, bwant) { - t.Errorf("bundles: got %v, want %v", bgot, bwant) - } - tgot := quantizeTimes(handler.times(), b.DelayThreshold) - twant := []int{0, 0, 0, 0} - if !reflect.DeepEqual(tgot, twant) { - t.Errorf("times: got %v, want %v", tgot, twant) - } -} - -func TestAddWait(t *testing.T) { - var ( - mu sync.Mutex - events []string - ) - event := func(s string) { - mu.Lock() - events = append(events, s) - mu.Unlock() - } - - handlec := make(chan int) - done := make(chan struct{}) - b := NewBundler(int(0), func(interface{}) { - <-handlec - event("handle") - }) - b.BufferedByteLimit = 3 - addw := func(sz int) { - if err := b.AddWait(context.Background(), 0, sz); err != nil { - t.Fatal(err) - } - event(fmt.Sprintf("addw(%d)", sz)) - } - - addw(2) - go func() { - addw(3) // blocks until first bundle is handled - close(done) - }() - // Give addw(3) a chance to finish - time.Sleep(100 * time.Millisecond) - handlec <- 1 // handle the first bundle - select { - case <-time.After(time.Second): - t.Fatal("timed out") - case <-done: - } - want := []string{"addw(2)", "handle", "addw(3)"} - if !reflect.DeepEqual(events, want) { - t.Errorf("got %v\nwant%v", events, want) - } -} - -func TestAddWaitCancel(t *testing.T) { - b := NewBundler(int(0), func(interface{}) {}) - b.BufferedByteLimit = 3 - ctx, cancel := context.WithCancel(context.Background()) - go func() { - time.Sleep(100 * time.Millisecond) - cancel() - }() - err := b.AddWait(ctx, 0, 4) - if want := context.Canceled; err != want { - t.Fatalf("got %v, want %v", err, want) - } -} - -func TestBundlerErrors(t *testing.T) { - // Use a handler that blocks forever, to force the bundler to run out of - // memory. - b := NewBundler(int(0), func(interface{}) { select {} }) - b.BundleByteLimit = 3 - b.BufferedByteLimit = 10 - - if got, want := b.Add(1, 4), ErrOversizedItem; got != want { - t.Fatalf("got %v, want %v", got, want) - } - - for i := 0; i < 5; i++ { - if err := b.Add(i, 2); err != nil { - t.Fatal(err) - } - } - if got, want := b.Add(5, 1), ErrOverflow; got != want { - t.Fatalf("got %v, want %v", got, want) - } -} - -// Check that no more than HandlerLimit handlers are active at once. -func TestConcurrentHandlersMax(t *testing.T) { - const handlerLimit = 10 - var ( - mu sync.Mutex - active int - maxHandlers int - ) - b := NewBundler(int(0), func(s interface{}) { - mu.Lock() - active++ - if active > maxHandlers { - maxHandlers = active - } - if maxHandlers > handlerLimit { - t.Errorf("too many handlers running (got %d; want %d)", maxHandlers, handlerLimit) - } - mu.Unlock() - time.Sleep(1 * time.Millisecond) // let the scheduler work - mu.Lock() - active-- - mu.Unlock() - }) - b.BundleCountThreshold = 5 - b.HandlerLimit = 10 - defer b.Flush() - - more := 0 // extra iterations past saturation - for i := 0; more == 0 || i < more; i++ { - mu.Lock() - m := maxHandlers - mu.Unlock() - if m >= handlerLimit && more == 0 { - // Run past saturation to check that we don't exceed the max. - more = 2 * i - } - b.Add(i, 1) - } -} - -// Check that Flush doesn't return until all prior items have been handled. -func TestConcurrentFlush(t *testing.T) { - var ( - mu sync.Mutex - items = make(map[int]bool) - ) - b := NewBundler(int(0), func(s interface{}) { - mu.Lock() - for _, i := range s.([]int) { - items[i] = true - } - mu.Unlock() - time.Sleep(10 * time.Millisecond) - }) - b.BundleCountThreshold = 5 - b.HandlerLimit = 10 - defer b.Flush() - - var wg sync.WaitGroup - defer wg.Wait() - for i := 0; i < 50; i++ { - b.Add(i, 1) - if i%100 == 0 { - i := i - wg.Add(1) - go func() { - defer wg.Done() - b.Flush() - mu.Lock() - defer mu.Unlock() - for j := 0; j <= i; j++ { - if !items[j] { - // Cannot use Fatal, since we're in a non-test goroutine. - t.Errorf("flush(%d): item %d not handled", i, j) - break - } - } - }() - } - } -} - -type testHandler struct { - mu sync.Mutex - b [][]int - t []time.Time -} - -func (t *testHandler) bundles() [][]int { - t.mu.Lock() - defer t.mu.Unlock() - return t.b -} - -func (t *testHandler) times() []time.Time { - t.mu.Lock() - defer t.mu.Unlock() - return t.t -} - -func (t *testHandler) handle(b interface{}) { - t.mu.Lock() - defer t.mu.Unlock() - t.b = append(t.b, b.([]int)) - t.t = append(t.t, time.Now()) -} - -// Round times to the nearest q and express them as the number of q -// since the first time. -// E.g. if q is 100ms, then a time within 50ms of the first time -// will be represented as 0, a time 150 to 250ms of the first time -// we be represented as 1, etc. -func quantizeTimes(times []time.Time, q time.Duration) []int { - var rs []int - for _, t := range times { - d := t.Sub(times[0]) - r := int((d + q/2) / q) - rs = append(rs, r) - } - return rs -} - -func TestQuantizeTimes(t *testing.T) { - quantum := 100 * time.Millisecond - for _, test := range []struct { - millis []int // times in milliseconds - want []int - }{ - {[]int{10, 20, 30}, []int{0, 0, 0}}, - {[]int{0, 49, 50, 90}, []int{0, 0, 1, 1}}, - {[]int{0, 95, 170, 315}, []int{0, 1, 2, 3}}, - } { - var times []time.Time - for _, ms := range test.millis { - times = append(times, time.Unix(0, int64(ms*1e6))) - } - got := quantizeTimes(times, quantum) - if !reflect.DeepEqual(got, test.want) { - t.Errorf("%v: got %v, want %v", test.millis, got, test.want) - } - } -} diff --git a/vendor/google.golang.org/appengine/CONTRIBUTING.md b/vendor/google.golang.org/appengine/CONTRIBUTING.md deleted file mode 100644 index ffc29852..00000000 --- a/vendor/google.golang.org/appengine/CONTRIBUTING.md +++ /dev/null @@ -1,90 +0,0 @@ -# Contributing - -1. Sign one of the contributor license agreements below. -1. Get the package: - - `go get -d google.golang.org/appengine` -1. Change into the checked out source: - - `cd $GOPATH/src/google.golang.org/appengine` -1. Fork the repo. -1. Set your fork as a remote: - - `git remote add fork git@github.com:GITHUB_USERNAME/appengine.git` -1. Make changes, commit to your fork. -1. Send a pull request with your changes. - The first line of your commit message is conventionally a one-line summary of the change, prefixed by the primary affected package, and is used as the title of your pull request. - -# Testing - -## Running system tests - -Download and install the [Go App Engine SDK](https://cloud.google.com/appengine/docs/go/download). Make sure the `go_appengine` dir is in your `PATH`. - -Set the `APPENGINE_DEV_APPSERVER` environment variable to `/path/to/go_appengine/dev_appserver.py`. - -Run tests with `goapp test`: - -``` -goapp test -v google.golang.org/appengine/... -``` - -## Contributor License Agreements - -Before we can accept your pull requests you'll need to sign a Contributor -License Agreement (CLA): - -- **If you are an individual writing original source code** and **you own the -intellectual property**, then you'll need to sign an [individual CLA][indvcla]. -- **If you work for a company that wants to allow you to contribute your work**, -then you'll need to sign a [corporate CLA][corpcla]. - -You can sign these electronically (just scroll to the bottom). After that, -we'll be able to accept your pull requests. - -## Contributor Code of Conduct - -As contributors and maintainers of this project, -and in the interest of fostering an open and welcoming community, -we pledge to respect all people who contribute through reporting issues, -posting feature requests, updating documentation, -submitting pull requests or patches, and other activities. - -We are committed to making participation in this project -a harassment-free experience for everyone, -regardless of level of experience, gender, gender identity and expression, -sexual orientation, disability, personal appearance, -body size, race, ethnicity, age, religion, or nationality. - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery -* Personal attacks -* Trolling or insulting/derogatory comments -* Public or private harassment -* Publishing other's private information, -such as physical or electronic -addresses, without explicit permission -* Other unethical or unprofessional conduct. - -Project maintainers have the right and responsibility to remove, edit, or reject -comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct. -By adopting this Code of Conduct, -project maintainers commit themselves to fairly and consistently -applying these principles to every aspect of managing this project. -Project maintainers who do not follow or enforce the Code of Conduct -may be permanently removed from the project team. - -This code of conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. - -Instances of abusive, harassing, or otherwise unacceptable behavior -may be reported by opening an issue -or contacting one or more of the project maintainers. - -This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, -available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/) - -[indvcla]: https://developers.google.com/open-source/cla/individual -[corpcla]: https://developers.google.com/open-source/cla/corporate diff --git a/vendor/google.golang.org/appengine/README.md b/vendor/google.golang.org/appengine/README.md deleted file mode 100644 index d86768a2..00000000 --- a/vendor/google.golang.org/appengine/README.md +++ /dev/null @@ -1,73 +0,0 @@ -# Go App Engine packages - -[![Build Status](https://travis-ci.org/golang/appengine.svg)](https://travis-ci.org/golang/appengine) - -This repository supports the Go runtime on *App Engine standard*. -It provides APIs for interacting with App Engine services. -Its canonical import path is `google.golang.org/appengine`. - -See https://cloud.google.com/appengine/docs/go/ -for more information. - -File issue reports and feature requests on the [GitHub's issue -tracker](https://github.com/golang/appengine/issues). - -## Upgrading an App Engine app to the flexible environment - -This package does not work on *App Engine flexible*. - -There are many differences between the App Engine standard environment and -the flexible environment. - -See the [documentation on upgrading to the flexible environment](https://cloud.google.com/appengine/docs/flexible/go/upgrading). - -## Directory structure - -The top level directory of this repository is the `appengine` package. It -contains the -basic APIs (e.g. `appengine.NewContext`) that apply across APIs. Specific API -packages are in subdirectories (e.g. `datastore`). - -There is an `internal` subdirectory that contains service protocol buffers, -plus packages required for connectivity to make API calls. App Engine apps -should not directly import any package under `internal`. - -## Updating from legacy (`import "appengine"`) packages - -If you're currently using the bare `appengine` packages -(that is, not these ones, imported via `google.golang.org/appengine`), -then you can use the `aefix` tool to help automate an upgrade to these packages. - -Run `go get google.golang.org/appengine/cmd/aefix` to install it. - -### 1. Update import paths - -The import paths for App Engine packages are now fully qualified, based at `google.golang.org/appengine`. -You will need to update your code to use import paths starting with that; for instance, -code importing `appengine/datastore` will now need to import `google.golang.org/appengine/datastore`. - -### 2. Update code using deprecated, removed or modified APIs - -Most App Engine services are available with exactly the same API. -A few APIs were cleaned up, and there are some differences: - -* `appengine.Context` has been replaced with the `Context` type from `golang.org/x/net/context`. -* Logging methods that were on `appengine.Context` are now functions in `google.golang.org/appengine/log`. -* `appengine.Timeout` has been removed. Use `context.WithTimeout` instead. -* `appengine.Datacenter` now takes a `context.Context` argument. -* `datastore.PropertyLoadSaver` has been simplified to use slices in place of channels. -* `delay.Call` now returns an error. -* `search.FieldLoadSaver` now handles document metadata. -* `urlfetch.Transport` no longer has a Deadline field; set a deadline on the - `context.Context` instead. -* `aetest` no longer declares its own Context type, and uses the standard one instead. -* `taskqueue.QueueStats` no longer takes a maxTasks argument. That argument has been - deprecated and unused for a long time. -* `appengine.BackendHostname` and `appengine.BackendInstance` were for the deprecated backends feature. - Use `appengine.ModuleHostname`and `appengine.ModuleName` instead. -* Most of `appengine/file` and parts of `appengine/blobstore` are deprecated. - Use [Google Cloud Storage](https://godoc.org/cloud.google.com/go/storage) if the - feature you require is not present in the new - [blobstore package](https://google.golang.org/appengine/blobstore). -* `appengine/socket` is not required on App Engine flexible environment / Managed VMs. - Use the standard `net` package instead. diff --git a/vendor/google.golang.org/appengine/appengine.go b/vendor/google.golang.org/appengine/appengine.go deleted file mode 100644 index 79525454..00000000 --- a/vendor/google.golang.org/appengine/appengine.go +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright 2011 Google Inc. All rights reserved. -// Use of this source code is governed by the Apache 2.0 -// license that can be found in the LICENSE file. - -// Package appengine provides basic functionality for Google App Engine. -// -// For more information on how to write Go apps for Google App Engine, see: -// https://cloud.google.com/appengine/docs/go/ -package appengine // import "google.golang.org/appengine" - -import ( - "net/http" - - "github.com/golang/protobuf/proto" - "golang.org/x/net/context" - - "google.golang.org/appengine/internal" -) - -// The gophers party all night; the rabbits provide the beats. - -// Main is the principal entry point for an app running in App Engine. -// -// On App Engine Flexible it installs a trivial health checker if one isn't -// already registered, and starts listening on port 8080 (overridden by the -// $PORT environment variable). -// -// See https://cloud.google.com/appengine/docs/flexible/custom-runtimes#health_check_requests -// for details on how to do your own health checking. -// -// On App Engine Standard it ensures the server has started and is prepared to -// receive requests. -// -// Main never returns. -// -// Main is designed so that the app's main package looks like this: -// -// package main -// -// import ( -// "google.golang.org/appengine" -// -// _ "myapp/package0" -// _ "myapp/package1" -// ) -// -// func main() { -// appengine.Main() -// } -// -// The "myapp/packageX" packages are expected to register HTTP handlers -// in their init functions. -func Main() { - internal.Main() -} - -// IsDevAppServer reports whether the App Engine app is running in the -// development App Server. -func IsDevAppServer() bool { - return internal.IsDevAppServer() -} - -// IsStandard reports whether the App Engine app is running in the standard -// environment. This includes both the first generation runtimes (<= Go 1.9) -// and the second generation runtimes (>= Go 1.11). -func IsStandard() bool { - return internal.IsStandard() -} - -// IsFlex reports whether the App Engine app is running in the flexible environment. -func IsFlex() bool { - return internal.IsFlex() -} - -// IsAppEngine reports whether the App Engine app is running on App Engine, in either -// the standard or flexible environment. -func IsAppEngine() bool { - return internal.IsAppEngine() -} - -// NewContext returns a context for an in-flight HTTP request. -// This function is cheap. -func NewContext(req *http.Request) context.Context { - return internal.ReqContext(req) -} - -// WithContext returns a copy of the parent context -// and associates it with an in-flight HTTP request. -// This function is cheap. -func WithContext(parent context.Context, req *http.Request) context.Context { - return internal.WithContext(parent, req) -} - -// TODO(dsymonds): Add a Call function here? Otherwise other packages can't access internal.Call. - -// BlobKey is a key for a blobstore blob. -// -// Conceptually, this type belongs in the blobstore package, but it lives in -// the appengine package to avoid a circular dependency: blobstore depends on -// datastore, and datastore needs to refer to the BlobKey type. -type BlobKey string - -// GeoPoint represents a location as latitude/longitude in degrees. -type GeoPoint struct { - Lat, Lng float64 -} - -// Valid returns whether a GeoPoint is within [-90, 90] latitude and [-180, 180] longitude. -func (g GeoPoint) Valid() bool { - return -90 <= g.Lat && g.Lat <= 90 && -180 <= g.Lng && g.Lng <= 180 -} - -// APICallFunc defines a function type for handling an API call. -// See WithCallOverride. -type APICallFunc func(ctx context.Context, service, method string, in, out proto.Message) error - -// WithAPICallFunc returns a copy of the parent context -// that will cause API calls to invoke f instead of their normal operation. -// -// This is intended for advanced users only. -func WithAPICallFunc(ctx context.Context, f APICallFunc) context.Context { - return internal.WithCallOverride(ctx, internal.CallOverrideFunc(f)) -} - -// APICall performs an API call. -// -// This is not intended for general use; it is exported for use in conjunction -// with WithAPICallFunc. -func APICall(ctx context.Context, service, method string, in, out proto.Message) error { - return internal.Call(ctx, service, method, in, out) -} diff --git a/vendor/google.golang.org/appengine/appengine_test.go b/vendor/google.golang.org/appengine/appengine_test.go deleted file mode 100644 index f1cf0a1b..00000000 --- a/vendor/google.golang.org/appengine/appengine_test.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2014 Google Inc. All rights reserved. -// Use of this source code is governed by the Apache 2.0 -// license that can be found in the LICENSE file. - -package appengine - -import ( - "testing" -) - -func TestValidGeoPoint(t *testing.T) { - testCases := []struct { - desc string - pt GeoPoint - want bool - }{ - { - "valid", - GeoPoint{67.21, 13.37}, - true, - }, - { - "high lat", - GeoPoint{-90.01, 13.37}, - false, - }, - { - "low lat", - GeoPoint{90.01, 13.37}, - false, - }, - { - "high lng", - GeoPoint{67.21, 182}, - false, - }, - { - "low lng", - GeoPoint{67.21, -181}, - false, - }, - } - - for _, tc := range testCases { - if got := tc.pt.Valid(); got != tc.want { - t.Errorf("%s: got %v, want %v", tc.desc, got, tc.want) - } - } -} diff --git a/vendor/google.golang.org/appengine/appengine_vm.go b/vendor/google.golang.org/appengine/appengine_vm.go deleted file mode 100644 index f4b645aa..00000000 --- a/vendor/google.golang.org/appengine/appengine_vm.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2015 Google Inc. All rights reserved. -// Use of this source code is governed by the Apache 2.0 -// license that can be found in the LICENSE file. - -// +build !appengine - -package appengine - -import ( - "golang.org/x/net/context" - - "google.golang.org/appengine/internal" -) - -// BackgroundContext returns a context not associated with a request. -// This should only be used when not servicing a request. -// This only works in App Engine "flexible environment". -func BackgroundContext() context.Context { - return internal.BackgroundContext() -} diff --git a/vendor/google.golang.org/appengine/errors.go b/vendor/google.golang.org/appengine/errors.go deleted file mode 100644 index 16d0772e..00000000 --- a/vendor/google.golang.org/appengine/errors.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2011 Google Inc. All rights reserved. -// Use of this source code is governed by the Apache 2.0 -// license that can be found in the LICENSE file. - -// This file provides error functions for common API failure modes. - -package appengine - -import ( - "fmt" - - "google.golang.org/appengine/internal" -) - -// IsOverQuota reports whether err represents an API call failure -// due to insufficient available quota. -func IsOverQuota(err error) bool { - callErr, ok := err.(*internal.CallError) - return ok && callErr.Code == 4 -} - -// MultiError is returned by batch operations when there are errors with -// particular elements. Errors will be in a one-to-one correspondence with -// the input elements; successful elements will have a nil entry. -type MultiError []error - -func (m MultiError) Error() string { - s, n := "", 0 - for _, e := range m { - if e != nil { - if n == 0 { - s = e.Error() - } - n++ - } - } - switch n { - case 0: - return "(0 errors)" - case 1: - return s - case 2: - return s + " (and 1 other error)" - } - return fmt.Sprintf("%s (and %d other errors)", s, n-1) -} diff --git a/vendor/google.golang.org/appengine/go.mod b/vendor/google.golang.org/appengine/go.mod deleted file mode 100644 index f449359d..00000000 --- a/vendor/google.golang.org/appengine/go.mod +++ /dev/null @@ -1,7 +0,0 @@ -module google.golang.org/appengine - -require ( - github.com/golang/protobuf v1.2.0 - golang.org/x/net v0.0.0-20180724234803-3673e40ba225 - golang.org/x/text v0.3.0 -) diff --git a/vendor/google.golang.org/appengine/go.sum b/vendor/google.golang.org/appengine/go.sum deleted file mode 100644 index 1a221c08..00000000 --- a/vendor/google.golang.org/appengine/go.sum +++ /dev/null @@ -1,6 +0,0 @@ -github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225 h1:kNX+jCowfMYzvlSvJu5pQWEmyWFrBXJ3PBy10xKMXK8= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/vendor/google.golang.org/appengine/identity.go b/vendor/google.golang.org/appengine/identity.go deleted file mode 100644 index b8dcf8f3..00000000 --- a/vendor/google.golang.org/appengine/identity.go +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright 2011 Google Inc. All rights reserved. -// Use of this source code is governed by the Apache 2.0 -// license that can be found in the LICENSE file. - -package appengine - -import ( - "time" - - "golang.org/x/net/context" - - "google.golang.org/appengine/internal" - pb "google.golang.org/appengine/internal/app_identity" - modpb "google.golang.org/appengine/internal/modules" -) - -// AppID returns the application ID for the current application. -// The string will be a plain application ID (e.g. "appid"), with a -// domain prefix for custom domain deployments (e.g. "example.com:appid"). -func AppID(c context.Context) string { return internal.AppID(c) } - -// DefaultVersionHostname returns the standard hostname of the default version -// of the current application (e.g. "my-app.appspot.com"). This is suitable for -// use in constructing URLs. -func DefaultVersionHostname(c context.Context) string { - return internal.DefaultVersionHostname(c) -} - -// ModuleName returns the module name of the current instance. -func ModuleName(c context.Context) string { - return internal.ModuleName(c) -} - -// ModuleHostname returns a hostname of a module instance. -// If module is the empty string, it refers to the module of the current instance. -// If version is empty, it refers to the version of the current instance if valid, -// or the default version of the module of the current instance. -// If instance is empty, ModuleHostname returns the load-balancing hostname. -func ModuleHostname(c context.Context, module, version, instance string) (string, error) { - req := &modpb.GetHostnameRequest{} - if module != "" { - req.Module = &module - } - if version != "" { - req.Version = &version - } - if instance != "" { - req.Instance = &instance - } - res := &modpb.GetHostnameResponse{} - if err := internal.Call(c, "modules", "GetHostname", req, res); err != nil { - return "", err - } - return *res.Hostname, nil -} - -// VersionID returns the version ID for the current application. -// It will be of the form "X.Y", where X is specified in app.yaml, -// and Y is a number generated when each version of the app is uploaded. -// It does not include a module name. -func VersionID(c context.Context) string { return internal.VersionID(c) } - -// InstanceID returns a mostly-unique identifier for this instance. -func InstanceID() string { return internal.InstanceID() } - -// Datacenter returns an identifier for the datacenter that the instance is running in. -func Datacenter(c context.Context) string { return internal.Datacenter(c) } - -// ServerSoftware returns the App Engine release version. -// In production, it looks like "Google App Engine/X.Y.Z". -// In the development appserver, it looks like "Development/X.Y". -func ServerSoftware() string { return internal.ServerSoftware() } - -// RequestID returns a string that uniquely identifies the request. -func RequestID(c context.Context) string { return internal.RequestID(c) } - -// AccessToken generates an OAuth2 access token for the specified scopes on -// behalf of service account of this application. This token will expire after -// the returned time. -func AccessToken(c context.Context, scopes ...string) (token string, expiry time.Time, err error) { - req := &pb.GetAccessTokenRequest{Scope: scopes} - res := &pb.GetAccessTokenResponse{} - - err = internal.Call(c, "app_identity_service", "GetAccessToken", req, res) - if err != nil { - return "", time.Time{}, err - } - return res.GetAccessToken(), time.Unix(res.GetExpirationTime(), 0), nil -} - -// Certificate represents a public certificate for the app. -type Certificate struct { - KeyName string - Data []byte // PEM-encoded X.509 certificate -} - -// PublicCertificates retrieves the public certificates for the app. -// They can be used to verify a signature returned by SignBytes. -func PublicCertificates(c context.Context) ([]Certificate, error) { - req := &pb.GetPublicCertificateForAppRequest{} - res := &pb.GetPublicCertificateForAppResponse{} - if err := internal.Call(c, "app_identity_service", "GetPublicCertificatesForApp", req, res); err != nil { - return nil, err - } - var cs []Certificate - for _, pc := range res.PublicCertificateList { - cs = append(cs, Certificate{ - KeyName: pc.GetKeyName(), - Data: []byte(pc.GetX509CertificatePem()), - }) - } - return cs, nil -} - -// ServiceAccount returns a string representing the service account name, in -// the form of an email address (typically app_id@appspot.gserviceaccount.com). -func ServiceAccount(c context.Context) (string, error) { - req := &pb.GetServiceAccountNameRequest{} - res := &pb.GetServiceAccountNameResponse{} - - err := internal.Call(c, "app_identity_service", "GetServiceAccountName", req, res) - if err != nil { - return "", err - } - return res.GetServiceAccountName(), err -} - -// SignBytes signs bytes using a private key unique to your application. -func SignBytes(c context.Context, bytes []byte) (keyName string, signature []byte, err error) { - req := &pb.SignForAppRequest{BytesToSign: bytes} - res := &pb.SignForAppResponse{} - - if err := internal.Call(c, "app_identity_service", "SignForApp", req, res); err != nil { - return "", nil, err - } - return res.GetKeyName(), res.GetSignatureBytes(), nil -} - -func init() { - internal.RegisterErrorCodeMap("app_identity_service", pb.AppIdentityServiceError_ErrorCode_name) - internal.RegisterErrorCodeMap("modules", modpb.ModulesServiceError_ErrorCode_name) -} diff --git a/vendor/google.golang.org/appengine/namespace.go b/vendor/google.golang.org/appengine/namespace.go deleted file mode 100644 index 21860ca0..00000000 --- a/vendor/google.golang.org/appengine/namespace.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 Google Inc. All rights reserved. -// Use of this source code is governed by the Apache 2.0 -// license that can be found in the LICENSE file. - -package appengine - -import ( - "fmt" - "regexp" - - "golang.org/x/net/context" - - "google.golang.org/appengine/internal" -) - -// Namespace returns a replacement context that operates within the given namespace. -func Namespace(c context.Context, namespace string) (context.Context, error) { - if !validNamespace.MatchString(namespace) { - return nil, fmt.Errorf("appengine: namespace %q does not match /%s/", namespace, validNamespace) - } - return internal.NamespacedContext(c, namespace), nil -} - -// validNamespace matches valid namespace names. -var validNamespace = regexp.MustCompile(`^[0-9A-Za-z._-]{0,100}$`) diff --git a/vendor/google.golang.org/appengine/namespace_test.go b/vendor/google.golang.org/appengine/namespace_test.go deleted file mode 100644 index 847f640b..00000000 --- a/vendor/google.golang.org/appengine/namespace_test.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2014 Google Inc. All rights reserved. -// Use of this source code is governed by the Apache 2.0 -// license that can be found in the LICENSE file. - -package appengine - -import ( - "testing" - - "golang.org/x/net/context" -) - -func TestNamespaceValidity(t *testing.T) { - testCases := []struct { - namespace string - ok bool - }{ - // data from Python's namespace_manager_test.py - {"", true}, - {"__a.namespace.123__", true}, - {"-_A....NAMESPACE-_", true}, - {"-", true}, - {".", true}, - {".-", true}, - - {"?", false}, - {"+", false}, - {"!", false}, - {" ", false}, - } - for _, tc := range testCases { - _, err := Namespace(context.Background(), tc.namespace) - if err == nil && !tc.ok { - t.Errorf("Namespace %q should be rejected, but wasn't", tc.namespace) - } else if err != nil && tc.ok { - t.Errorf("Namespace %q should be accepted, but wasn't", tc.namespace) - } - } -} diff --git a/vendor/google.golang.org/appengine/timeout.go b/vendor/google.golang.org/appengine/timeout.go deleted file mode 100644 index 05642a99..00000000 --- a/vendor/google.golang.org/appengine/timeout.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2013 Google Inc. All rights reserved. -// Use of this source code is governed by the Apache 2.0 -// license that can be found in the LICENSE file. - -package appengine - -import "golang.org/x/net/context" - -// IsTimeoutError reports whether err is a timeout error. -func IsTimeoutError(err error) bool { - if err == context.DeadlineExceeded { - return true - } - if t, ok := err.(interface { - IsTimeout() bool - }); ok { - return t.IsTimeout() - } - return false -} diff --git a/vendor/google.golang.org/appengine/travis_install.sh b/vendor/google.golang.org/appengine/travis_install.sh deleted file mode 100755 index 785b62f4..00000000 --- a/vendor/google.golang.org/appengine/travis_install.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -set -e - -if [[ $GO111MODULE == "on" ]]; then - go get . -else - go get -u -v $(go list -f '{{join .Imports "\n"}}{{"\n"}}{{join .TestImports "\n"}}' ./... | sort | uniq | grep -v appengine) -fi - -if [[ $GOAPP == "true" ]]; then - mkdir /tmp/sdk - curl -o /tmp/sdk.zip "https://storage.googleapis.com/appengine-sdks/featured/go_appengine_sdk_linux_amd64-1.9.68.zip" - unzip -q /tmp/sdk.zip -d /tmp/sdk - # NOTE: Set the following env vars in the test script: - # export PATH="$PATH:/tmp/sdk/go_appengine" - # export APPENGINE_DEV_APPSERVER=/tmp/sdk/go_appengine/dev_appserver.py -fi - diff --git a/vendor/google.golang.org/appengine/travis_test.sh b/vendor/google.golang.org/appengine/travis_test.sh deleted file mode 100755 index d4390f04..00000000 --- a/vendor/google.golang.org/appengine/travis_test.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -set -e - -go version -go test -v google.golang.org/appengine/... -go test -v -race google.golang.org/appengine/... -if [[ $GOAPP == "true" ]]; then - export PATH="$PATH:/tmp/sdk/go_appengine" - export APPENGINE_DEV_APPSERVER=/tmp/sdk/go_appengine/dev_appserver.py - goapp version - goapp test -v google.golang.org/appengine/... -fi diff --git a/vendor/google.golang.org/genproto/CONTRIBUTING.md b/vendor/google.golang.org/genproto/CONTRIBUTING.md deleted file mode 100644 index 2827b7d3..00000000 --- a/vendor/google.golang.org/genproto/CONTRIBUTING.md +++ /dev/null @@ -1,27 +0,0 @@ -Want to contribute? Great! First, read this page (including the small print at the end). - -### Before you contribute -Before we can use your code, you must sign the -[Google Individual Contributor License Agreement] -(https://cla.developers.google.com/about/google-individual) -(CLA), which you can do online. The CLA is necessary mainly because you own the -copyright to your changes, even after your contribution becomes part of our -codebase, so we need your permission to use and distribute your code. We also -need to be sure of various other things—for instance that you'll tell us if you -know that your code infringes on other people's patents. You don't have to sign -the CLA until after you've submitted your code for review and a member has -approved it, but you must do it before we can put your code into our codebase. -Before you start working on a larger contribution, you should get in touch with -us first through the issue tracker with your idea so that we can help out and -possibly guide you. Coordinating up front makes it much easier to avoid -frustration later on. - -### Code reviews -All submissions, including submissions by project members, require review. We -use Github pull requests for this purpose. - -### The small print -Contributions made by corporations are covered by a different agreement than -the one above, the -[Software Grant and Corporate Contributor License Agreement] -(https://cla.developers.google.com/about/google-corporate). diff --git a/vendor/google.golang.org/genproto/README.md b/vendor/google.golang.org/genproto/README.md deleted file mode 100644 index 52e084b6..00000000 --- a/vendor/google.golang.org/genproto/README.md +++ /dev/null @@ -1,31 +0,0 @@ -Go generated proto packages -=========================== - -[![GoDoc](https://godoc.org/google.golang.org/genproto?status.svg)](https://godoc.org/google.golang.org/genproto) - -``` -go get google.golang.org/genproto -``` - -> **IMPORTANT** This repository is currently experimental. The structure -> of the contained packages is subject to change. Please see the original -> source repositories (listed below) to find out the status of the each -> protocol buffer's associated service. - -This repository contains the generated Go packages for common protocol buffer -types, and the generated [gRPC][1] code necessary for interacting with Google's gRPC -APIs. - -There are two sources for the proto files used in this repository: - -1. [google/protobuf][2]: the code in the `protobuf` and `ptypes` subdirectories - is derived from this repo. The messages in `protobuf` are used to describe - protocol buffer messages themselves. The messages under `ptypes` define the - common well-known types. -2. [googleapis/googleapis][3]: the code in the `googleapis` is derived from this - repo. The packages here contain types specifically for interacting with Google - APIs. - -[1]: http://grpc.io -[2]: https://github.com/google/protobuf/ -[3]: https://github.com/googleapis/googleapis/ diff --git a/vendor/google.golang.org/genproto/go.mod b/vendor/google.golang.org/genproto/go.mod deleted file mode 100644 index d81a7c32..00000000 --- a/vendor/google.golang.org/genproto/go.mod +++ /dev/null @@ -1,7 +0,0 @@ -module google.golang.org/genproto - -require ( - github.com/golang/protobuf v1.2.0 - golang.org/x/net v0.0.0-20181106065722-10aee1819953 - google.golang.org/grpc v1.16.0 -) diff --git a/vendor/google.golang.org/genproto/go.sum b/vendor/google.golang.org/genproto/go.sum deleted file mode 100644 index 623d8f8f..00000000 --- a/vendor/google.golang.org/genproto/go.sum +++ /dev/null @@ -1,26 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181106065722-10aee1819953 h1:LuZIitY8waaxUfNIdtajyE/YzA/zyf0YxXG27VpLrkg= -golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522 h1:Ve1ORMCxvRmSXBwJK+t3Oy+V2vRW2OetUQBq4rJIkZE= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/grpc v1.16.0 h1:dz5IJGuC2BB7qXR5AyHNwAUBhZscK2xVez7mznh72sY= -google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/vendor/google.golang.org/genproto/regen.go b/vendor/google.golang.org/genproto/regen.go deleted file mode 100644 index 53779b92..00000000 --- a/vendor/google.golang.org/genproto/regen.go +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright 2016 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// +build ignore - -// Regen.go regenerates the genproto repository. -// -// Regen.go recursively walks through each directory named by given arguments, -// looking for all .proto files. (Symlinks are not followed.) -// If the pkg_prefix flag is not an empty string, -// any proto file without `go_package` option -// or whose option does not begin with the prefix is ignored. -// If multiple roots contain files with the same name, -// eg "root1/path/to/file" and "root2/path/to/file", -// only the first file is processed; the rest are ignored. -// Protoc is executed on remaining files, -// one invocation per set of files declaring the same Go package. -package main - -import ( - "flag" - "fmt" - "io/ioutil" - "log" - "os" - "os/exec" - "path/filepath" - "regexp" - "strconv" - "strings" -) - -var goPkgOptRe = regexp.MustCompile(`(?m)^option go_package = (.*);`) - -func usage() { - fmt.Fprintln(os.Stderr, `usage: go run regen.go -go_out=path/to/output [-pkg_prefix=pkg/prefix] roots... - -Most users will not need to run this file directly. -To regenerate this repository, run regen.sh instead.`) - flag.PrintDefaults() -} - -func main() { - goOutDir := flag.String("go_out", "", "go_out argument to pass to protoc-gen-go") - pkgPrefix := flag.String("pkg_prefix", "", "only include proto files with go_package starting with this prefix") - flag.Usage = usage - flag.Parse() - - if *goOutDir == "" { - log.Fatal("need go_out flag") - } - - seenFiles := make(map[string]bool) - pkgFiles := make(map[string][]string) - for _, root := range flag.Args() { - walkFn := func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - if !info.Mode().IsRegular() || !strings.HasSuffix(path, ".proto") { - return nil - } - - switch rel, err := filepath.Rel(root, path); { - case err != nil: - return err - case seenFiles[rel]: - return nil - default: - seenFiles[rel] = true - } - - pkg, err := goPkg(path) - if err != nil { - return err - } - pkgFiles[pkg] = append(pkgFiles[pkg], path) - return nil - } - if err := filepath.Walk(root, walkFn); err != nil { - log.Fatal(err) - } - } - for pkg, fnames := range pkgFiles { - if !strings.HasPrefix(pkg, *pkgPrefix) { - continue - } - if out, err := protoc(*goOutDir, flag.Args(), fnames); err != nil { - log.Fatalf("error executing protoc: %s\n%s", err, out) - } - } -} - -// goPkg reports the import path declared in the given file's -// `go_package` option. If the option is missing, goPkg returns empty string. -func goPkg(fname string) (string, error) { - content, err := ioutil.ReadFile(fname) - if err != nil { - return "", err - } - - var pkgName string - if match := goPkgOptRe.FindSubmatch(content); len(match) > 0 { - pn, err := strconv.Unquote(string(match[1])) - if err != nil { - return "", err - } - pkgName = pn - } - if p := strings.IndexRune(pkgName, ';'); p > 0 { - pkgName = pkgName[:p] - } - return pkgName, nil -} - -// protoc executes the "protoc" command on files named in fnames, -// passing go_out and include flags specified in goOut and includes respectively. -// protoc returns combined output from stdout and stderr. -func protoc(goOut string, includes, fnames []string) ([]byte, error) { - args := []string{"--go_out=plugins=grpc:" + goOut} - for _, inc := range includes { - args = append(args, "-I", inc) - } - args = append(args, fnames...) - return exec.Command("protoc", args...).CombinedOutput() -} diff --git a/vendor/google.golang.org/genproto/regen.sh b/vendor/google.golang.org/genproto/regen.sh deleted file mode 100755 index 53e00fc3..00000000 --- a/vendor/google.golang.org/genproto/regen.sh +++ /dev/null @@ -1,86 +0,0 @@ -#!/bin/bash -# -# Copyright 2016 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This script rebuilds the generated code for the protocol buffers. -# To run this you will need protoc and goprotobuf installed; -# see https://github.com/golang/protobuf for instructions. -# You also need Go and Git installed. - -set -e - -PKG=google.golang.org/genproto -PROTO_REPO=https://github.com/google/protobuf -PROTO_SUBDIR=src/google/protobuf -GOOGLEAPIS_REPO=https://github.com/googleapis/googleapis -API_COMMON_REPO=https://github.com/googleapis/api-common-protos.git - -function die() { - echo 1>&2 $* - exit 1 -} - -# Sanity check that the right tools are accessible. -for tool in go git protoc protoc-gen-go; do - q=$(which $tool) || die "didn't find $tool" - echo 1>&2 "$tool: $q" -done - -root=$(go list -f '{{.Root}}' $PKG/... | head -n1) -if [ -z "$root" ]; then - die "cannot find root of $PKG" -fi - -remove_dirs= -trap 'rm -rf $remove_dirs' EXIT - -if [ -z "$PROTOBUF" ]; then - proto_repo_dir=$(mktemp -d -t regen-cds-proto.XXXXXX) - git clone -q $PROTO_REPO $proto_repo_dir & - remove_dirs="$proto_repo_dir" - # The protoc include directory is actually the "src" directory of the repo. - protodir="$proto_repo_dir/src" -else - protodir="$PROTOBUF/src" -fi - -if [ -z "$GOOGLEAPIS" ]; then - apidir=$(mktemp -d -t regen-cds-api.XXXXXX) - git clone -q $GOOGLEAPIS_REPO $apidir & - remove_dirs="$remove_dirs $apidir" -else - apidir="$GOOGLEAPIS" -fi - -if [ -z "$COMMONPROTOS" ]; then - commondir=$(mktemp -d -t regen-cds-common.XXXXXX) - git clone -q $API_COMMON_REPO $commondir & - remove_dirs="$remove_dirs $commondir" -else - commondir="$COMMONPROTOS" -fi - -wait - -# Nuke everything, we'll generate them back -rm -r googleapis/ protobuf/ - -go run regen.go -go_out "$root/src" -pkg_prefix "$PKG" "$commondir" "$apidir" "$protodir" - -# Sanity check the build. -echo 1>&2 "Checking that the libraries build..." -go build -v ./... - -echo 1>&2 "All done!" diff --git a/vendor/google.golang.org/grpc/CONTRIBUTING.md b/vendor/google.golang.org/grpc/CONTRIBUTING.md deleted file mode 100644 index 0863eb26..00000000 --- a/vendor/google.golang.org/grpc/CONTRIBUTING.md +++ /dev/null @@ -1,36 +0,0 @@ -# How to contribute - -We definitely welcome your patches and contributions to gRPC! - -If you are new to github, please start by reading [Pull Request howto](https://help.github.com/articles/about-pull-requests/) - -## Legal requirements - -In order to protect both you and ourselves, you will need to sign the -[Contributor License Agreement](https://identity.linuxfoundation.org/projects/cncf). - -## Guidelines for Pull Requests -How to get your contributions merged smoothly and quickly. - -- Create **small PRs** that are narrowly focused on **addressing a single concern**. We often times receive PRs that are trying to fix several things at a time, but only one fix is considered acceptable, nothing gets merged and both author's & review's time is wasted. Create more PRs to address different concerns and everyone will be happy. - -- For speculative changes, consider opening an issue and discussing it first. If you are suggesting a behavioral or API change, consider starting with a [gRFC proposal](https://github.com/grpc/proposal). - -- Provide a good **PR description** as a record of **what** change is being made and **why** it was made. Link to a github issue if it exists. - -- Don't fix code style and formatting unless you are already changing that line to address an issue. PRs with irrelevant changes won't be merged. If you do want to fix formatting or style, do that in a separate PR. - -- Unless your PR is trivial, you should expect there will be reviewer comments that you'll need to address before merging. We expect you to be reasonably responsive to those comments, otherwise the PR will be closed after 2-3 weeks of inactivity. - -- Maintain **clean commit history** and use **meaningful commit messages**. PRs with messy commit history are difficult to review and won't be merged. Use `rebase -i upstream/master` to curate your commit history and/or to bring in latest changes from master (but avoid rebasing in the middle of a code review). - -- Keep your PR up to date with upstream/master (if there are merge conflicts, we can't really merge your change). - -- **All tests need to be passing** before your change can be merged. We recommend you **run tests locally** before creating your PR to catch breakages early on. - - `make all` to test everything, OR - - `make vet` to catch vet errors - - `make test` to run the tests - - `make testrace` to run tests in race mode - -- Exceptions to the rules can be made if there's a compelling reason for doing so. - diff --git a/vendor/google.golang.org/grpc/Makefile b/vendor/google.golang.org/grpc/Makefile deleted file mode 100644 index 41a754f9..00000000 --- a/vendor/google.golang.org/grpc/Makefile +++ /dev/null @@ -1,60 +0,0 @@ -all: vet test testrace testappengine - -build: deps - go build google.golang.org/grpc/... - -clean: - go clean -i google.golang.org/grpc/... - -deps: - go get -d -v google.golang.org/grpc/... - -proto: - @ if ! which protoc > /dev/null; then \ - echo "error: protoc not installed" >&2; \ - exit 1; \ - fi - go generate google.golang.org/grpc/... - -test: testdeps - go test -cpu 1,4 -timeout 7m google.golang.org/grpc/... - -testappengine: testappenginedeps - goapp test -cpu 1,4 -timeout 7m google.golang.org/grpc/... - -testappenginedeps: - goapp get -d -v -t -tags 'appengine appenginevm' google.golang.org/grpc/... - -testdeps: - go get -d -v -t google.golang.org/grpc/... - -testrace: testdeps - go test -race -cpu 1,4 -timeout 7m google.golang.org/grpc/... - -updatedeps: - go get -d -v -u -f google.golang.org/grpc/... - -updatetestdeps: - go get -d -v -t -u -f google.golang.org/grpc/... - -vet: vetdeps - ./vet.sh - -vetdeps: - ./vet.sh -install - -.PHONY: \ - all \ - build \ - clean \ - deps \ - proto \ - test \ - testappengine \ - testappenginedeps \ - testdeps \ - testrace \ - updatedeps \ - updatetestdeps \ - vet \ - vetdeps diff --git a/vendor/google.golang.org/grpc/README.md b/vendor/google.golang.org/grpc/README.md deleted file mode 100644 index e3fb3c75..00000000 --- a/vendor/google.golang.org/grpc/README.md +++ /dev/null @@ -1,67 +0,0 @@ -# gRPC-Go - -[![Build Status](https://travis-ci.org/grpc/grpc-go.svg)](https://travis-ci.org/grpc/grpc-go) [![GoDoc](https://godoc.org/google.golang.org/grpc?status.svg)](https://godoc.org/google.golang.org/grpc) [![GoReportCard](https://goreportcard.com/badge/grpc/grpc-go)](https://goreportcard.com/report/github.com/grpc/grpc-go) - -The Go implementation of [gRPC](https://grpc.io/): A high performance, open source, general RPC framework that puts mobile and HTTP/2 first. For more information see the [gRPC Quick Start: Go](https://grpc.io/docs/quickstart/go.html) guide. - -Installation ------------- - -To install this package, you need to install Go and setup your Go workspace on your computer. The simplest way to install the library is to run: - -``` -$ go get -u google.golang.org/grpc -``` - -Prerequisites -------------- - -gRPC-Go requires Go 1.9 or later. - -Constraints ------------ -The grpc package should only depend on standard Go packages and a small number of exceptions. If your contribution introduces new dependencies which are NOT in the [list](http://godoc.org/google.golang.org/grpc?imports), you need a discussion with gRPC-Go authors and consultants. - -Documentation -------------- -See [API documentation](https://godoc.org/google.golang.org/grpc) for package and API descriptions and find examples in the [examples directory](examples/). - -Performance ------------ -See the current benchmarks for some of the languages supported in [this dashboard](https://performance-dot-grpc-testing.appspot.com/explore?dashboard=5652536396611584&widget=490377658&container=1286539696). - -Status ------- -General Availability [Google Cloud Platform Launch Stages](https://cloud.google.com/terms/launch-stages). - -FAQ ---- - -#### Compiling error, undefined: grpc.SupportPackageIsVersion - -Please update proto package, gRPC package and rebuild the proto files: - - `go get -u github.com/golang/protobuf/{proto,protoc-gen-go}` - - `go get -u google.golang.org/grpc` - - `protoc --go_out=plugins=grpc:. *.proto` - -#### How to turn on logging - -The default logger is controlled by the environment variables. Turn everything -on by setting: - -``` -GRPC_GO_LOG_VERBOSITY_LEVEL=99 GRPC_GO_LOG_SEVERITY_LEVEL=info -``` - -#### The RPC failed with error `"code = Unavailable desc = transport is closing"` - -This error means the connection the RPC is using was closed, and there are many -possible reasons, including: - 1. mis-configured transport credentials, connection failed on handshaking - 1. bytes disrupted, possibly by a proxy in between - 1. server shutdown - -It can be tricky to debug this because the error happens on the client side but -the root cause of the connection being closed is on the server side. Turn on -logging on __both client and server__, and see if there are any transport -errors. diff --git a/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin_test.go b/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin_test.go deleted file mode 100644 index 80c4e2b6..00000000 --- a/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin_test.go +++ /dev/null @@ -1,477 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package roundrobin_test - -import ( - "context" - "fmt" - "net" - "sync" - "testing" - "time" - - "google.golang.org/grpc" - "google.golang.org/grpc/balancer/roundrobin" - "google.golang.org/grpc/codes" - _ "google.golang.org/grpc/grpclog/glogger" - "google.golang.org/grpc/internal/leakcheck" - "google.golang.org/grpc/peer" - "google.golang.org/grpc/resolver" - "google.golang.org/grpc/resolver/manual" - "google.golang.org/grpc/status" - testpb "google.golang.org/grpc/test/grpc_testing" -) - -type testServer struct { - testpb.TestServiceServer -} - -func (s *testServer) EmptyCall(ctx context.Context, in *testpb.Empty) (*testpb.Empty, error) { - return &testpb.Empty{}, nil -} - -func (s *testServer) FullDuplexCall(stream testpb.TestService_FullDuplexCallServer) error { - return nil -} - -type test struct { - servers []*grpc.Server - addresses []string -} - -func (t *test) cleanup() { - for _, s := range t.servers { - s.Stop() - } -} - -func startTestServers(count int) (_ *test, err error) { - t := &test{} - - defer func() { - if err != nil { - for _, s := range t.servers { - s.Stop() - } - } - }() - for i := 0; i < count; i++ { - lis, err := net.Listen("tcp", "localhost:0") - if err != nil { - return nil, fmt.Errorf("Failed to listen %v", err) - } - - s := grpc.NewServer() - testpb.RegisterTestServiceServer(s, &testServer{}) - t.servers = append(t.servers, s) - t.addresses = append(t.addresses, lis.Addr().String()) - - go func(s *grpc.Server, l net.Listener) { - s.Serve(l) - }(s, lis) - } - - return t, nil -} - -func TestOneBackend(t *testing.T) { - defer leakcheck.Check(t) - r, cleanup := manual.GenerateAndRegisterManualResolver() - defer cleanup() - - test, err := startTestServers(1) - if err != nil { - t.Fatalf("failed to start servers: %v", err) - } - defer test.cleanup() - - cc, err := grpc.Dial(r.Scheme()+":///test.server", grpc.WithInsecure(), grpc.WithBalancerName(roundrobin.Name)) - if err != nil { - t.Fatalf("failed to dial: %v", err) - } - defer cc.Close() - testc := testpb.NewTestServiceClient(cc) - // The first RPC should fail because there's no address. - ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond) - defer cancel() - if _, err := testc.EmptyCall(ctx, &testpb.Empty{}); err == nil || status.Code(err) != codes.DeadlineExceeded { - t.Fatalf("EmptyCall() = _, %v, want _, DeadlineExceeded", err) - } - - r.NewAddress([]resolver.Address{{Addr: test.addresses[0]}}) - // The second RPC should succeed. - if _, err := testc.EmptyCall(context.Background(), &testpb.Empty{}); err != nil { - t.Fatalf("EmptyCall() = _, %v, want _, ", err) - } -} - -func TestBackendsRoundRobin(t *testing.T) { - defer leakcheck.Check(t) - r, cleanup := manual.GenerateAndRegisterManualResolver() - defer cleanup() - - backendCount := 5 - test, err := startTestServers(backendCount) - if err != nil { - t.Fatalf("failed to start servers: %v", err) - } - defer test.cleanup() - - cc, err := grpc.Dial(r.Scheme()+":///test.server", grpc.WithInsecure(), grpc.WithBalancerName(roundrobin.Name)) - if err != nil { - t.Fatalf("failed to dial: %v", err) - } - defer cc.Close() - testc := testpb.NewTestServiceClient(cc) - // The first RPC should fail because there's no address. - ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond) - defer cancel() - if _, err := testc.EmptyCall(ctx, &testpb.Empty{}); err == nil || status.Code(err) != codes.DeadlineExceeded { - t.Fatalf("EmptyCall() = _, %v, want _, DeadlineExceeded", err) - } - - var resolvedAddrs []resolver.Address - for i := 0; i < backendCount; i++ { - resolvedAddrs = append(resolvedAddrs, resolver.Address{Addr: test.addresses[i]}) - } - - r.NewAddress(resolvedAddrs) - var p peer.Peer - // Make sure connections to all servers are up. - for si := 0; si < backendCount; si++ { - var connected bool - for i := 0; i < 1000; i++ { - if _, err := testc.EmptyCall(context.Background(), &testpb.Empty{}, grpc.Peer(&p)); err != nil { - t.Fatalf("EmptyCall() = _, %v, want _, ", err) - } - if p.Addr.String() == test.addresses[si] { - connected = true - break - } - time.Sleep(time.Millisecond) - } - if !connected { - t.Fatalf("Connection to %v was not up after more than 1 second", test.addresses[si]) - } - } - - for i := 0; i < 3*backendCount; i++ { - if _, err := testc.EmptyCall(context.Background(), &testpb.Empty{}, grpc.Peer(&p)); err != nil { - t.Fatalf("EmptyCall() = _, %v, want _, ", err) - } - if p.Addr.String() != test.addresses[i%backendCount] { - t.Fatalf("Index %d: want peer %v, got peer %v", i, test.addresses[i%backendCount], p.Addr.String()) - } - } -} - -func TestAddressesRemoved(t *testing.T) { - defer leakcheck.Check(t) - r, cleanup := manual.GenerateAndRegisterManualResolver() - defer cleanup() - - test, err := startTestServers(1) - if err != nil { - t.Fatalf("failed to start servers: %v", err) - } - defer test.cleanup() - - cc, err := grpc.Dial(r.Scheme()+":///test.server", grpc.WithInsecure(), grpc.WithBalancerName(roundrobin.Name)) - if err != nil { - t.Fatalf("failed to dial: %v", err) - } - defer cc.Close() - testc := testpb.NewTestServiceClient(cc) - // The first RPC should fail because there's no address. - ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond) - defer cancel() - if _, err := testc.EmptyCall(ctx, &testpb.Empty{}); err == nil || status.Code(err) != codes.DeadlineExceeded { - t.Fatalf("EmptyCall() = _, %v, want _, DeadlineExceeded", err) - } - - r.NewAddress([]resolver.Address{{Addr: test.addresses[0]}}) - // The second RPC should succeed. - if _, err := testc.EmptyCall(context.Background(), &testpb.Empty{}); err != nil { - t.Fatalf("EmptyCall() = _, %v, want _, ", err) - } - - r.NewAddress([]resolver.Address{}) - for i := 0; i < 1000; i++ { - ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond) - defer cancel() - if _, err := testc.EmptyCall(ctx, &testpb.Empty{}, grpc.FailFast(false)); status.Code(err) == codes.DeadlineExceeded { - return - } - time.Sleep(time.Millisecond) - } - t.Fatalf("No RPC failed after removing all addresses, want RPC to fail with DeadlineExceeded") -} - -func TestCloseWithPendingRPC(t *testing.T) { - defer leakcheck.Check(t) - r, cleanup := manual.GenerateAndRegisterManualResolver() - defer cleanup() - - test, err := startTestServers(1) - if err != nil { - t.Fatalf("failed to start servers: %v", err) - } - defer test.cleanup() - - cc, err := grpc.Dial(r.Scheme()+":///test.server", grpc.WithInsecure(), grpc.WithBalancerName(roundrobin.Name)) - if err != nil { - t.Fatalf("failed to dial: %v", err) - } - testc := testpb.NewTestServiceClient(cc) - - var wg sync.WaitGroup - for i := 0; i < 3; i++ { - wg.Add(1) - go func() { - defer wg.Done() - // This RPC blocks until cc is closed. - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - if _, err := testc.EmptyCall(ctx, &testpb.Empty{}); status.Code(err) == codes.DeadlineExceeded { - t.Errorf("RPC failed because of deadline after cc is closed; want error the client connection is closing") - } - cancel() - }() - } - cc.Close() - wg.Wait() -} - -func TestNewAddressWhileBlocking(t *testing.T) { - defer leakcheck.Check(t) - r, cleanup := manual.GenerateAndRegisterManualResolver() - defer cleanup() - - test, err := startTestServers(1) - if err != nil { - t.Fatalf("failed to start servers: %v", err) - } - defer test.cleanup() - - cc, err := grpc.Dial(r.Scheme()+":///test.server", grpc.WithInsecure(), grpc.WithBalancerName(roundrobin.Name)) - if err != nil { - t.Fatalf("failed to dial: %v", err) - } - defer cc.Close() - testc := testpb.NewTestServiceClient(cc) - // The first RPC should fail because there's no address. - ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond) - defer cancel() - if _, err := testc.EmptyCall(ctx, &testpb.Empty{}); err == nil || status.Code(err) != codes.DeadlineExceeded { - t.Fatalf("EmptyCall() = _, %v, want _, DeadlineExceeded", err) - } - - r.NewAddress([]resolver.Address{{Addr: test.addresses[0]}}) - // The second RPC should succeed. - ctx, cancel = context.WithTimeout(context.Background(), 2*time.Second) - defer cancel() - if _, err := testc.EmptyCall(ctx, &testpb.Empty{}); err != nil { - t.Fatalf("EmptyCall() = _, %v, want _, nil", err) - } - - r.NewAddress([]resolver.Address{}) - - var wg sync.WaitGroup - for i := 0; i < 3; i++ { - wg.Add(1) - go func() { - defer wg.Done() - // This RPC blocks until NewAddress is called. - testc.EmptyCall(context.Background(), &testpb.Empty{}) - }() - } - time.Sleep(50 * time.Millisecond) - r.NewAddress([]resolver.Address{{Addr: test.addresses[0]}}) - wg.Wait() -} - -func TestOneServerDown(t *testing.T) { - defer leakcheck.Check(t) - r, cleanup := manual.GenerateAndRegisterManualResolver() - defer cleanup() - - backendCount := 3 - test, err := startTestServers(backendCount) - if err != nil { - t.Fatalf("failed to start servers: %v", err) - } - defer test.cleanup() - - cc, err := grpc.Dial(r.Scheme()+":///test.server", grpc.WithInsecure(), grpc.WithBalancerName(roundrobin.Name), grpc.WithWaitForHandshake()) - if err != nil { - t.Fatalf("failed to dial: %v", err) - } - defer cc.Close() - testc := testpb.NewTestServiceClient(cc) - // The first RPC should fail because there's no address. - ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond) - defer cancel() - if _, err := testc.EmptyCall(ctx, &testpb.Empty{}); err == nil || status.Code(err) != codes.DeadlineExceeded { - t.Fatalf("EmptyCall() = _, %v, want _, DeadlineExceeded", err) - } - - var resolvedAddrs []resolver.Address - for i := 0; i < backendCount; i++ { - resolvedAddrs = append(resolvedAddrs, resolver.Address{Addr: test.addresses[i]}) - } - - r.NewAddress(resolvedAddrs) - var p peer.Peer - // Make sure connections to all servers are up. - for si := 0; si < backendCount; si++ { - var connected bool - for i := 0; i < 1000; i++ { - if _, err := testc.EmptyCall(context.Background(), &testpb.Empty{}, grpc.Peer(&p)); err != nil { - t.Fatalf("EmptyCall() = _, %v, want _, ", err) - } - if p.Addr.String() == test.addresses[si] { - connected = true - break - } - time.Sleep(time.Millisecond) - } - if !connected { - t.Fatalf("Connection to %v was not up after more than 1 second", test.addresses[si]) - } - } - - for i := 0; i < 3*backendCount; i++ { - if _, err := testc.EmptyCall(context.Background(), &testpb.Empty{}, grpc.Peer(&p)); err != nil { - t.Fatalf("EmptyCall() = _, %v, want _, ", err) - } - if p.Addr.String() != test.addresses[i%backendCount] { - t.Fatalf("Index %d: want peer %v, got peer %v", i, test.addresses[i%backendCount], p.Addr.String()) - } - } - - // Stop one server, RPCs should roundrobin among the remaining servers. - backendCount-- - test.servers[backendCount].Stop() - // Loop until see server[backendCount-1] twice without seeing server[backendCount]. - var targetSeen int - for i := 0; i < 1000; i++ { - if _, err := testc.EmptyCall(context.Background(), &testpb.Empty{}, grpc.Peer(&p)); err != nil { - targetSeen = 0 - t.Logf("EmptyCall() = _, %v, want _, ", err) - // Due to a race, this RPC could possibly get the connection that - // was closing, and this RPC may fail. Keep trying when this - // happens. - continue - } - switch p.Addr.String() { - case test.addresses[backendCount-1]: - targetSeen++ - case test.addresses[backendCount]: - // Reset targetSeen if peer is server[backendCount]. - targetSeen = 0 - } - // Break to make sure the last picked address is server[-1], so the following for loop won't be flaky. - if targetSeen >= 2 { - break - } - } - if targetSeen != 2 { - t.Fatal("Failed to see server[backendCount-1] twice without seeing server[backendCount]") - } - for i := 0; i < 3*backendCount; i++ { - if _, err := testc.EmptyCall(context.Background(), &testpb.Empty{}, grpc.Peer(&p)); err != nil { - t.Fatalf("EmptyCall() = _, %v, want _, ", err) - } - if p.Addr.String() != test.addresses[i%backendCount] { - t.Errorf("Index %d: want peer %v, got peer %v", i, test.addresses[i%backendCount], p.Addr.String()) - } - } -} - -func TestAllServersDown(t *testing.T) { - defer leakcheck.Check(t) - r, cleanup := manual.GenerateAndRegisterManualResolver() - defer cleanup() - - backendCount := 3 - test, err := startTestServers(backendCount) - if err != nil { - t.Fatalf("failed to start servers: %v", err) - } - defer test.cleanup() - - cc, err := grpc.Dial(r.Scheme()+":///test.server", grpc.WithInsecure(), grpc.WithBalancerName(roundrobin.Name), grpc.WithWaitForHandshake()) - if err != nil { - t.Fatalf("failed to dial: %v", err) - } - defer cc.Close() - testc := testpb.NewTestServiceClient(cc) - // The first RPC should fail because there's no address. - ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond) - defer cancel() - if _, err := testc.EmptyCall(ctx, &testpb.Empty{}); err == nil || status.Code(err) != codes.DeadlineExceeded { - t.Fatalf("EmptyCall() = _, %v, want _, DeadlineExceeded", err) - } - - var resolvedAddrs []resolver.Address - for i := 0; i < backendCount; i++ { - resolvedAddrs = append(resolvedAddrs, resolver.Address{Addr: test.addresses[i]}) - } - - r.NewAddress(resolvedAddrs) - var p peer.Peer - // Make sure connections to all servers are up. - for si := 0; si < backendCount; si++ { - var connected bool - for i := 0; i < 1000; i++ { - if _, err := testc.EmptyCall(context.Background(), &testpb.Empty{}, grpc.Peer(&p)); err != nil { - t.Fatalf("EmptyCall() = _, %v, want _, ", err) - } - if p.Addr.String() == test.addresses[si] { - connected = true - break - } - time.Sleep(time.Millisecond) - } - if !connected { - t.Fatalf("Connection to %v was not up after more than 1 second", test.addresses[si]) - } - } - - for i := 0; i < 3*backendCount; i++ { - if _, err := testc.EmptyCall(context.Background(), &testpb.Empty{}, grpc.Peer(&p)); err != nil { - t.Fatalf("EmptyCall() = _, %v, want _, ", err) - } - if p.Addr.String() != test.addresses[i%backendCount] { - t.Fatalf("Index %d: want peer %v, got peer %v", i, test.addresses[i%backendCount], p.Addr.String()) - } - } - - // All servers are stopped, failfast RPC should fail with unavailable. - for i := 0; i < backendCount; i++ { - test.servers[i].Stop() - } - time.Sleep(100 * time.Millisecond) - for i := 0; i < 1000; i++ { - if _, err := testc.EmptyCall(context.Background(), &testpb.Empty{}); status.Code(err) == codes.Unavailable { - return - } - time.Sleep(time.Millisecond) - } - t.Fatalf("Failfast RPCs didn't fail with Unavailable after all servers are stopped") -} diff --git a/vendor/google.golang.org/grpc/balancer_switching_test.go b/vendor/google.golang.org/grpc/balancer_switching_test.go deleted file mode 100644 index d36c8e96..00000000 --- a/vendor/google.golang.org/grpc/balancer_switching_test.go +++ /dev/null @@ -1,469 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package grpc - -import ( - "context" - "fmt" - "math" - "testing" - "time" - - "google.golang.org/grpc/balancer" - "google.golang.org/grpc/balancer/roundrobin" - "google.golang.org/grpc/connectivity" - _ "google.golang.org/grpc/grpclog/glogger" - "google.golang.org/grpc/internal/leakcheck" - "google.golang.org/grpc/resolver" - "google.golang.org/grpc/resolver/manual" -) - -var _ balancer.Builder = &magicalLB{} -var _ balancer.Balancer = &magicalLB{} - -// magicalLB is a ringer for grpclb. It is used to avoid circular dependencies on the grpclb package -type magicalLB struct{} - -func (b *magicalLB) Name() string { - return "grpclb" -} - -func (b *magicalLB) Build(cc balancer.ClientConn, opts balancer.BuildOptions) balancer.Balancer { - return b -} - -func (b *magicalLB) HandleSubConnStateChange(balancer.SubConn, connectivity.State) {} - -func (b *magicalLB) HandleResolvedAddrs([]resolver.Address, error) {} - -func (b *magicalLB) Close() {} - -func init() { - balancer.Register(&magicalLB{}) -} - -func checkPickFirst(cc *ClientConn, servers []*server) error { - var ( - req = "port" - reply string - err error - ) - connected := false - for i := 0; i < 5000; i++ { - if err = cc.Invoke(context.Background(), "/foo/bar", &req, &reply); errorDesc(err) == servers[0].port { - if connected { - // connected is set to false if peer is not server[0]. So if - // connected is true here, this is the second time we saw - // server[0] in a row. Break because pickfirst is in effect. - break - } - connected = true - } else { - connected = false - } - time.Sleep(time.Millisecond) - } - if !connected { - return fmt.Errorf("pickfirst is not in effect after 5 second, EmptyCall() = _, %v, want _, %v", err, servers[0].port) - } - // The following RPCs should all succeed with the first server. - for i := 0; i < 3; i++ { - err = cc.Invoke(context.Background(), "/foo/bar", &req, &reply) - if errorDesc(err) != servers[0].port { - return fmt.Errorf("Index %d: want peer %v, got peer %v", i, servers[0].port, err) - } - } - return nil -} - -func checkRoundRobin(cc *ClientConn, servers []*server) error { - var ( - req = "port" - reply string - err error - ) - - // Make sure connections to all servers are up. - for i := 0; i < 2; i++ { - // Do this check twice, otherwise the first RPC's transport may still be - // picked by the closing pickfirst balancer, and the test becomes flaky. - for _, s := range servers { - var up bool - for i := 0; i < 5000; i++ { - if err = cc.Invoke(context.Background(), "/foo/bar", &req, &reply); errorDesc(err) == s.port { - up = true - break - } - time.Sleep(time.Millisecond) - } - if !up { - return fmt.Errorf("server %v is not up within 5 second", s.port) - } - } - } - - serverCount := len(servers) - for i := 0; i < 3*serverCount; i++ { - err = cc.Invoke(context.Background(), "/foo/bar", &req, &reply) - if errorDesc(err) != servers[i%serverCount].port { - return fmt.Errorf("Index %d: want peer %v, got peer %v", i, servers[i%serverCount].port, err) - } - } - return nil -} - -func TestSwitchBalancer(t *testing.T) { - defer leakcheck.Check(t) - r, rcleanup := manual.GenerateAndRegisterManualResolver() - defer rcleanup() - - numServers := 2 - servers, _, scleanup := startServers(t, numServers, math.MaxInt32) - defer scleanup() - - cc, err := Dial(r.Scheme()+":///test.server", WithInsecure(), WithCodec(testCodec{})) - if err != nil { - t.Fatalf("failed to dial: %v", err) - } - defer cc.Close() - r.NewAddress([]resolver.Address{{Addr: servers[0].addr}, {Addr: servers[1].addr}}) - // The default balancer is pickfirst. - if err := checkPickFirst(cc, servers); err != nil { - t.Fatalf("check pickfirst returned non-nil error: %v", err) - } - // Switch to roundrobin. - cc.handleServiceConfig(`{"loadBalancingPolicy": "round_robin"}`) - if err := checkRoundRobin(cc, servers); err != nil { - t.Fatalf("check roundrobin returned non-nil error: %v", err) - } - // Switch to pickfirst. - cc.handleServiceConfig(`{"loadBalancingPolicy": "pick_first"}`) - if err := checkPickFirst(cc, servers); err != nil { - t.Fatalf("check pickfirst returned non-nil error: %v", err) - } -} - -// Test that balancer specified by dial option will not be overridden. -func TestBalancerDialOption(t *testing.T) { - defer leakcheck.Check(t) - r, rcleanup := manual.GenerateAndRegisterManualResolver() - defer rcleanup() - - numServers := 2 - servers, _, scleanup := startServers(t, numServers, math.MaxInt32) - defer scleanup() - - cc, err := Dial(r.Scheme()+":///test.server", WithInsecure(), WithCodec(testCodec{}), WithBalancerName(roundrobin.Name)) - if err != nil { - t.Fatalf("failed to dial: %v", err) - } - defer cc.Close() - r.NewAddress([]resolver.Address{{Addr: servers[0].addr}, {Addr: servers[1].addr}}) - // The init balancer is roundrobin. - if err := checkRoundRobin(cc, servers); err != nil { - t.Fatalf("check roundrobin returned non-nil error: %v", err) - } - // Switch to pickfirst. - cc.handleServiceConfig(`{"loadBalancingPolicy": "pick_first"}`) - // Balancer is still roundrobin. - if err := checkRoundRobin(cc, servers); err != nil { - t.Fatalf("check roundrobin returned non-nil error: %v", err) - } -} - -// First addr update contains grpclb. -func TestSwitchBalancerGRPCLBFirst(t *testing.T) { - defer leakcheck.Check(t) - r, rcleanup := manual.GenerateAndRegisterManualResolver() - defer rcleanup() - - cc, err := Dial(r.Scheme()+":///test.server", WithInsecure(), WithCodec(testCodec{})) - if err != nil { - t.Fatalf("failed to dial: %v", err) - } - defer cc.Close() - - // ClientConn will switch balancer to grpclb when receives an address of - // type GRPCLB. - r.NewAddress([]resolver.Address{{Addr: "backend"}, {Addr: "grpclb", Type: resolver.GRPCLB}}) - var isGRPCLB bool - for i := 0; i < 5000; i++ { - cc.mu.Lock() - isGRPCLB = cc.curBalancerName == "grpclb" - cc.mu.Unlock() - if isGRPCLB { - break - } - time.Sleep(time.Millisecond) - } - if !isGRPCLB { - t.Fatalf("after 5 second, cc.balancer is of type %v, not grpclb", cc.curBalancerName) - } - - // New update containing new backend and new grpclb. Should not switch - // balancer. - r.NewAddress([]resolver.Address{{Addr: "backend2"}, {Addr: "grpclb2", Type: resolver.GRPCLB}}) - for i := 0; i < 200; i++ { - cc.mu.Lock() - isGRPCLB = cc.curBalancerName == "grpclb" - cc.mu.Unlock() - if !isGRPCLB { - break - } - time.Sleep(time.Millisecond) - } - if !isGRPCLB { - t.Fatalf("within 200 ms, cc.balancer switched to !grpclb, want grpclb") - } - - var isPickFirst bool - // Switch balancer to pickfirst. - r.NewAddress([]resolver.Address{{Addr: "backend"}}) - for i := 0; i < 5000; i++ { - cc.mu.Lock() - isPickFirst = cc.curBalancerName == PickFirstBalancerName - cc.mu.Unlock() - if isPickFirst { - break - } - time.Sleep(time.Millisecond) - } - if !isPickFirst { - t.Fatalf("after 5 second, cc.balancer is of type %v, not pick_first", cc.curBalancerName) - } -} - -// First addr update does not contain grpclb. -func TestSwitchBalancerGRPCLBSecond(t *testing.T) { - defer leakcheck.Check(t) - r, rcleanup := manual.GenerateAndRegisterManualResolver() - defer rcleanup() - - cc, err := Dial(r.Scheme()+":///test.server", WithInsecure(), WithCodec(testCodec{})) - if err != nil { - t.Fatalf("failed to dial: %v", err) - } - defer cc.Close() - - r.NewAddress([]resolver.Address{{Addr: "backend"}}) - var isPickFirst bool - for i := 0; i < 5000; i++ { - cc.mu.Lock() - isPickFirst = cc.curBalancerName == PickFirstBalancerName - cc.mu.Unlock() - if isPickFirst { - break - } - time.Sleep(time.Millisecond) - } - if !isPickFirst { - t.Fatalf("after 5 second, cc.balancer is of type %v, not pick_first", cc.curBalancerName) - } - - // ClientConn will switch balancer to grpclb when receives an address of - // type GRPCLB. - r.NewAddress([]resolver.Address{{Addr: "backend"}, {Addr: "grpclb", Type: resolver.GRPCLB}}) - var isGRPCLB bool - for i := 0; i < 5000; i++ { - cc.mu.Lock() - isGRPCLB = cc.curBalancerName == "grpclb" - cc.mu.Unlock() - if isGRPCLB { - break - } - time.Sleep(time.Millisecond) - } - if !isGRPCLB { - t.Fatalf("after 5 second, cc.balancer is of type %v, not grpclb", cc.curBalancerName) - } - - // New update containing new backend and new grpclb. Should not switch - // balancer. - r.NewAddress([]resolver.Address{{Addr: "backend2"}, {Addr: "grpclb2", Type: resolver.GRPCLB}}) - for i := 0; i < 200; i++ { - cc.mu.Lock() - isGRPCLB = cc.curBalancerName == "grpclb" - cc.mu.Unlock() - if !isGRPCLB { - break - } - time.Sleep(time.Millisecond) - } - if !isGRPCLB { - t.Fatalf("within 200 ms, cc.balancer switched to !grpclb, want grpclb") - } - - // Switch balancer back. - r.NewAddress([]resolver.Address{{Addr: "backend"}}) - for i := 0; i < 5000; i++ { - cc.mu.Lock() - isPickFirst = cc.curBalancerName == PickFirstBalancerName - cc.mu.Unlock() - if isPickFirst { - break - } - time.Sleep(time.Millisecond) - } - if !isPickFirst { - t.Fatalf("after 5 second, cc.balancer is of type %v, not pick_first", cc.curBalancerName) - } -} - -// Test that if the current balancer is roundrobin, after switching to grpclb, -// when the resolved address doesn't contain grpclb addresses, balancer will be -// switched back to roundrobin. -func TestSwitchBalancerGRPCLBRoundRobin(t *testing.T) { - defer leakcheck.Check(t) - r, rcleanup := manual.GenerateAndRegisterManualResolver() - defer rcleanup() - - cc, err := Dial(r.Scheme()+":///test.server", WithInsecure(), WithCodec(testCodec{})) - if err != nil { - t.Fatalf("failed to dial: %v", err) - } - defer cc.Close() - - r.NewServiceConfig(`{"loadBalancingPolicy": "round_robin"}`) - - r.NewAddress([]resolver.Address{{Addr: "backend"}}) - var isRoundRobin bool - for i := 0; i < 5000; i++ { - cc.mu.Lock() - isRoundRobin = cc.curBalancerName == "round_robin" - cc.mu.Unlock() - if isRoundRobin { - break - } - time.Sleep(time.Millisecond) - } - if !isRoundRobin { - t.Fatalf("after 5 second, cc.balancer is of type %v, not round_robin", cc.curBalancerName) - } - - // ClientConn will switch balancer to grpclb when receives an address of - // type GRPCLB. - r.NewAddress([]resolver.Address{{Addr: "grpclb", Type: resolver.GRPCLB}}) - var isGRPCLB bool - for i := 0; i < 5000; i++ { - cc.mu.Lock() - isGRPCLB = cc.curBalancerName == "grpclb" - cc.mu.Unlock() - if isGRPCLB { - break - } - time.Sleep(time.Millisecond) - } - if !isGRPCLB { - t.Fatalf("after 5 second, cc.balancer is of type %v, not grpclb", cc.curBalancerName) - } - - // Switch balancer back. - r.NewAddress([]resolver.Address{{Addr: "backend"}}) - for i := 0; i < 5000; i++ { - cc.mu.Lock() - isRoundRobin = cc.curBalancerName == "round_robin" - cc.mu.Unlock() - if isRoundRobin { - break - } - time.Sleep(time.Millisecond) - } - if !isRoundRobin { - t.Fatalf("after 5 second, cc.balancer is of type %v, not round_robin", cc.curBalancerName) - } -} - -// Test that if resolved address list contains grpclb, the balancer option in -// service config won't take effect. But when there's no grpclb address in a new -// resolved address list, balancer will be switched to the new one. -func TestSwitchBalancerGRPCLBServiceConfig(t *testing.T) { - defer leakcheck.Check(t) - r, rcleanup := manual.GenerateAndRegisterManualResolver() - defer rcleanup() - - cc, err := Dial(r.Scheme()+":///test.server", WithInsecure(), WithCodec(testCodec{})) - if err != nil { - t.Fatalf("failed to dial: %v", err) - } - defer cc.Close() - - r.NewAddress([]resolver.Address{{Addr: "backend"}}) - var isPickFirst bool - for i := 0; i < 5000; i++ { - cc.mu.Lock() - isPickFirst = cc.curBalancerName == PickFirstBalancerName - cc.mu.Unlock() - if isPickFirst { - break - } - time.Sleep(time.Millisecond) - } - if !isPickFirst { - t.Fatalf("after 5 second, cc.balancer is of type %v, not pick_first", cc.curBalancerName) - } - - // ClientConn will switch balancer to grpclb when receives an address of - // type GRPCLB. - r.NewAddress([]resolver.Address{{Addr: "grpclb", Type: resolver.GRPCLB}}) - var isGRPCLB bool - for i := 0; i < 5000; i++ { - cc.mu.Lock() - isGRPCLB = cc.curBalancerName == "grpclb" - cc.mu.Unlock() - if isGRPCLB { - break - } - time.Sleep(time.Millisecond) - } - if !isGRPCLB { - t.Fatalf("after 5 second, cc.balancer is of type %v, not grpclb", cc.curBalancerName) - } - - r.NewServiceConfig(`{"loadBalancingPolicy": "round_robin"}`) - var isRoundRobin bool - for i := 0; i < 200; i++ { - cc.mu.Lock() - isRoundRobin = cc.curBalancerName == "round_robin" - cc.mu.Unlock() - if isRoundRobin { - break - } - time.Sleep(time.Millisecond) - } - // Balancer should NOT switch to round_robin because resolved list contains - // grpclb. - if isRoundRobin { - t.Fatalf("within 200 ms, cc.balancer switched to round_robin, want grpclb") - } - - // Switch balancer back. - r.NewAddress([]resolver.Address{{Addr: "backend"}}) - for i := 0; i < 5000; i++ { - cc.mu.Lock() - isRoundRobin = cc.curBalancerName == "round_robin" - cc.mu.Unlock() - if isRoundRobin { - break - } - time.Sleep(time.Millisecond) - } - if !isRoundRobin { - t.Fatalf("after 5 second, cc.balancer is of type %v, not round_robin", cc.curBalancerName) - } -} diff --git a/vendor/google.golang.org/grpc/balancer_test.go b/vendor/google.golang.org/grpc/balancer_test.go deleted file mode 100644 index 219dcaca..00000000 --- a/vendor/google.golang.org/grpc/balancer_test.go +++ /dev/null @@ -1,808 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package grpc - -import ( - "context" - "fmt" - "math" - "strconv" - "sync" - "testing" - "time" - - "google.golang.org/grpc/codes" - _ "google.golang.org/grpc/grpclog/glogger" - "google.golang.org/grpc/internal/leakcheck" - "google.golang.org/grpc/naming" - "google.golang.org/grpc/status" - - // V1 balancer tests use passthrough resolver instead of dns. - // TODO(bar) remove this when removing v1 balaner entirely. - - _ "google.golang.org/grpc/resolver/passthrough" -) - -func pickFirstBalancerV1(r naming.Resolver) Balancer { - return &pickFirst{&roundRobin{r: r}} -} - -type testWatcher struct { - // the channel to receives name resolution updates - update chan *naming.Update - // the side channel to get to know how many updates in a batch - side chan int - // the channel to notify update injector that the update reading is done - readDone chan int -} - -func (w *testWatcher) Next() (updates []*naming.Update, err error) { - n := <-w.side - if n == 0 { - return nil, fmt.Errorf("w.side is closed") - } - for i := 0; i < n; i++ { - u := <-w.update - if u != nil { - updates = append(updates, u) - } - } - w.readDone <- 0 - return -} - -func (w *testWatcher) Close() { - close(w.side) -} - -// Inject naming resolution updates to the testWatcher. -func (w *testWatcher) inject(updates []*naming.Update) { - w.side <- len(updates) - for _, u := range updates { - w.update <- u - } - <-w.readDone -} - -type testNameResolver struct { - w *testWatcher - addr string -} - -func (r *testNameResolver) Resolve(target string) (naming.Watcher, error) { - r.w = &testWatcher{ - update: make(chan *naming.Update, 1), - side: make(chan int, 1), - readDone: make(chan int), - } - r.w.side <- 1 - r.w.update <- &naming.Update{ - Op: naming.Add, - Addr: r.addr, - } - go func() { - <-r.w.readDone - }() - return r.w, nil -} - -func startServers(t *testing.T, numServers int, maxStreams uint32) ([]*server, *testNameResolver, func()) { - var servers []*server - for i := 0; i < numServers; i++ { - s := newTestServer() - servers = append(servers, s) - go s.start(t, 0, maxStreams) - s.wait(t, 2*time.Second) - } - // Point to server[0] - addr := "localhost:" + servers[0].port - return servers, &testNameResolver{ - addr: addr, - }, func() { - for i := 0; i < numServers; i++ { - servers[i].stop() - } - } -} - -func TestNameDiscovery(t *testing.T) { - defer leakcheck.Check(t) - // Start 2 servers on 2 ports. - numServers := 2 - servers, r, cleanup := startServers(t, numServers, math.MaxUint32) - defer cleanup() - cc, err := Dial("passthrough:///foo.bar.com", WithBalancer(RoundRobin(r)), WithBlock(), WithInsecure(), WithCodec(testCodec{})) - if err != nil { - t.Fatalf("Failed to create ClientConn: %v", err) - } - defer cc.Close() - req := "port" - var reply string - if err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err == nil || errorDesc(err) != servers[0].port { - t.Fatalf("grpc.Invoke(_, _, _, _, _) = %v, want %s", err, servers[0].port) - } - // Inject the name resolution change to remove servers[0] and add servers[1]. - var updates []*naming.Update - updates = append(updates, &naming.Update{ - Op: naming.Delete, - Addr: "localhost:" + servers[0].port, - }) - updates = append(updates, &naming.Update{ - Op: naming.Add, - Addr: "localhost:" + servers[1].port, - }) - r.w.inject(updates) - // Loop until the rpcs in flight talks to servers[1]. - for { - if err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err != nil && errorDesc(err) == servers[1].port { - break - } - time.Sleep(10 * time.Millisecond) - } -} - -func TestEmptyAddrs(t *testing.T) { - defer leakcheck.Check(t) - servers, r, cleanup := startServers(t, 1, math.MaxUint32) - defer cleanup() - cc, err := Dial("passthrough:///foo.bar.com", WithBalancer(RoundRobin(r)), WithBlock(), WithInsecure(), WithCodec(testCodec{})) - if err != nil { - t.Fatalf("Failed to create ClientConn: %v", err) - } - defer cc.Close() - var reply string - if err := cc.Invoke(context.Background(), "/foo/bar", &expectedRequest, &reply); err != nil || reply != expectedResponse { - t.Fatalf("grpc.Invoke(_, _, _, _, _) = %v, reply = %q, want %q, ", err, reply, expectedResponse) - } - // Inject name resolution change to remove the server so that there is no address - // available after that. - u := &naming.Update{ - Op: naming.Delete, - Addr: "localhost:" + servers[0].port, - } - r.w.inject([]*naming.Update{u}) - // Loop until the above updates apply. - for { - time.Sleep(10 * time.Millisecond) - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Millisecond) - if err := cc.Invoke(ctx, "/foo/bar", &expectedRequest, &reply); err != nil { - cancel() - break - } - cancel() - } -} - -func TestRoundRobin(t *testing.T) { - defer leakcheck.Check(t) - // Start 3 servers on 3 ports. - numServers := 3 - servers, r, cleanup := startServers(t, numServers, math.MaxUint32) - defer cleanup() - cc, err := Dial("passthrough:///foo.bar.com", WithBalancer(RoundRobin(r)), WithBlock(), WithInsecure(), WithCodec(testCodec{})) - if err != nil { - t.Fatalf("Failed to create ClientConn: %v", err) - } - defer cc.Close() - // Add servers[1] to the service discovery. - u := &naming.Update{ - Op: naming.Add, - Addr: "localhost:" + servers[1].port, - } - r.w.inject([]*naming.Update{u}) - req := "port" - var reply string - // Loop until servers[1] is up - for { - if err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err != nil && errorDesc(err) == servers[1].port { - break - } - time.Sleep(10 * time.Millisecond) - } - // Add server2[2] to the service discovery. - u = &naming.Update{ - Op: naming.Add, - Addr: "localhost:" + servers[2].port, - } - r.w.inject([]*naming.Update{u}) - // Loop until both servers[2] are up. - for { - if err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err != nil && errorDesc(err) == servers[2].port { - break - } - time.Sleep(10 * time.Millisecond) - } - // Check the incoming RPCs served in a round-robin manner. - for i := 0; i < 10; i++ { - if err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err == nil || errorDesc(err) != servers[i%numServers].port { - t.Fatalf("Index %d: Invoke(_, _, _, _, _) = %v, want %s", i, err, servers[i%numServers].port) - } - } -} - -func TestCloseWithPendingRPC(t *testing.T) { - defer leakcheck.Check(t) - servers, r, cleanup := startServers(t, 1, math.MaxUint32) - defer cleanup() - cc, err := Dial("passthrough:///foo.bar.com", WithBalancer(RoundRobin(r)), WithBlock(), WithInsecure(), WithCodec(testCodec{})) - if err != nil { - t.Fatalf("Failed to create ClientConn: %v", err) - } - defer cc.Close() - var reply string - if err := cc.Invoke(context.Background(), "/foo/bar", &expectedRequest, &reply, FailFast(false)); err != nil { - t.Fatalf("grpc.Invoke(_, _, _, _, _) = %v, want %s", err, servers[0].port) - } - // Remove the server. - updates := []*naming.Update{{ - Op: naming.Delete, - Addr: "localhost:" + servers[0].port, - }} - r.w.inject(updates) - // Loop until the above update applies. - for { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Millisecond) - if err := cc.Invoke(ctx, "/foo/bar", &expectedRequest, &reply, FailFast(false)); status.Code(err) == codes.DeadlineExceeded { - cancel() - break - } - time.Sleep(10 * time.Millisecond) - cancel() - } - // Issue 2 RPCs which should be completed with error status once cc is closed. - var wg sync.WaitGroup - wg.Add(2) - go func() { - defer wg.Done() - var reply string - if err := cc.Invoke(context.Background(), "/foo/bar", &expectedRequest, &reply, FailFast(false)); err == nil { - t.Errorf("grpc.Invoke(_, _, _, _, _) = %v, want not nil", err) - } - }() - go func() { - defer wg.Done() - var reply string - time.Sleep(5 * time.Millisecond) - if err := cc.Invoke(context.Background(), "/foo/bar", &expectedRequest, &reply, FailFast(false)); err == nil { - t.Errorf("grpc.Invoke(_, _, _, _, _) = %v, want not nil", err) - } - }() - time.Sleep(5 * time.Millisecond) - cc.Close() - wg.Wait() -} - -func TestGetOnWaitChannel(t *testing.T) { - defer leakcheck.Check(t) - servers, r, cleanup := startServers(t, 1, math.MaxUint32) - defer cleanup() - cc, err := Dial("passthrough:///foo.bar.com", WithBalancer(RoundRobin(r)), WithBlock(), WithInsecure(), WithCodec(testCodec{})) - if err != nil { - t.Fatalf("Failed to create ClientConn: %v", err) - } - defer cc.Close() - // Remove all servers so that all upcoming RPCs will block on waitCh. - updates := []*naming.Update{{ - Op: naming.Delete, - Addr: "localhost:" + servers[0].port, - }} - r.w.inject(updates) - for { - var reply string - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Millisecond) - if err := cc.Invoke(ctx, "/foo/bar", &expectedRequest, &reply, FailFast(false)); status.Code(err) == codes.DeadlineExceeded { - cancel() - break - } - cancel() - time.Sleep(10 * time.Millisecond) - } - var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() - var reply string - if err := cc.Invoke(context.Background(), "/foo/bar", &expectedRequest, &reply, FailFast(false)); err != nil { - t.Errorf("grpc.Invoke(_, _, _, _, _) = %v, want ", err) - } - }() - // Add a connected server to get the above RPC through. - updates = []*naming.Update{{ - Op: naming.Add, - Addr: "localhost:" + servers[0].port, - }} - r.w.inject(updates) - // Wait until the above RPC succeeds. - wg.Wait() -} - -func TestOneServerDown(t *testing.T) { - defer leakcheck.Check(t) - // Start 2 servers. - numServers := 2 - servers, r, cleanup := startServers(t, numServers, math.MaxUint32) - defer cleanup() - cc, err := Dial("passthrough:///foo.bar.com", WithBalancer(RoundRobin(r)), WithBlock(), WithInsecure(), WithCodec(testCodec{}), WithWaitForHandshake()) - if err != nil { - t.Fatalf("Failed to create ClientConn: %v", err) - } - defer cc.Close() - // Add servers[1] to the service discovery. - var updates []*naming.Update - updates = append(updates, &naming.Update{ - Op: naming.Add, - Addr: "localhost:" + servers[1].port, - }) - r.w.inject(updates) - req := "port" - var reply string - // Loop until servers[1] is up - for { - if err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err != nil && errorDesc(err) == servers[1].port { - break - } - time.Sleep(10 * time.Millisecond) - } - - var wg sync.WaitGroup - numRPC := 100 - sleepDuration := 10 * time.Millisecond - wg.Add(1) - go func() { - time.Sleep(sleepDuration) - // After sleepDuration, kill server[0]. - servers[0].stop() - wg.Done() - }() - - // All non-failfast RPCs should not block because there's at least one connection available. - for i := 0; i < numRPC; i++ { - wg.Add(1) - go func() { - time.Sleep(sleepDuration) - // After sleepDuration, invoke RPC. - // server[0] is killed around the same time to make it racy between balancer and gRPC internals. - cc.Invoke(context.Background(), "/foo/bar", &req, &reply, FailFast(false)) - wg.Done() - }() - } - wg.Wait() -} - -func TestOneAddressRemoval(t *testing.T) { - defer leakcheck.Check(t) - // Start 2 servers. - numServers := 2 - servers, r, cleanup := startServers(t, numServers, math.MaxUint32) - defer cleanup() - cc, err := Dial("passthrough:///foo.bar.com", WithBalancer(RoundRobin(r)), WithBlock(), WithInsecure(), WithCodec(testCodec{})) - if err != nil { - t.Fatalf("Failed to create ClientConn: %v", err) - } - defer cc.Close() - // Add servers[1] to the service discovery. - var updates []*naming.Update - updates = append(updates, &naming.Update{ - Op: naming.Add, - Addr: "localhost:" + servers[1].port, - }) - r.w.inject(updates) - req := "port" - var reply string - // Loop until servers[1] is up - for { - if err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err != nil && errorDesc(err) == servers[1].port { - break - } - time.Sleep(10 * time.Millisecond) - } - - var wg sync.WaitGroup - numRPC := 100 - sleepDuration := 10 * time.Millisecond - wg.Add(1) - go func() { - time.Sleep(sleepDuration) - // After sleepDuration, delete server[0]. - var updates []*naming.Update - updates = append(updates, &naming.Update{ - Op: naming.Delete, - Addr: "localhost:" + servers[0].port, - }) - r.w.inject(updates) - wg.Done() - }() - - // All non-failfast RPCs should not fail because there's at least one connection available. - for i := 0; i < numRPC; i++ { - wg.Add(1) - go func() { - var reply string - time.Sleep(sleepDuration) - // After sleepDuration, invoke RPC. - // server[0] is removed around the same time to make it racy between balancer and gRPC internals. - if err := cc.Invoke(context.Background(), "/foo/bar", &expectedRequest, &reply, FailFast(false)); err != nil { - t.Errorf("grpc.Invoke(_, _, _, _, _) = %v, want nil", err) - } - wg.Done() - }() - } - wg.Wait() -} - -func checkServerUp(t *testing.T, currentServer *server) { - req := "port" - port := currentServer.port - cc, err := Dial("passthrough:///localhost:"+port, WithBlock(), WithInsecure(), WithCodec(testCodec{})) - if err != nil { - t.Fatalf("Failed to create ClientConn: %v", err) - } - defer cc.Close() - var reply string - for { - if err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err != nil && errorDesc(err) == port { - break - } - time.Sleep(10 * time.Millisecond) - } -} - -func TestPickFirstEmptyAddrs(t *testing.T) { - defer leakcheck.Check(t) - servers, r, cleanup := startServers(t, 1, math.MaxUint32) - defer cleanup() - cc, err := Dial("passthrough:///foo.bar.com", WithBalancer(pickFirstBalancerV1(r)), WithBlock(), WithInsecure(), WithCodec(testCodec{})) - if err != nil { - t.Fatalf("Failed to create ClientConn: %v", err) - } - defer cc.Close() - var reply string - if err := cc.Invoke(context.Background(), "/foo/bar", &expectedRequest, &reply); err != nil || reply != expectedResponse { - t.Fatalf("grpc.Invoke(_, _, _, _, _) = %v, reply = %q, want %q, ", err, reply, expectedResponse) - } - // Inject name resolution change to remove the server so that there is no address - // available after that. - u := &naming.Update{ - Op: naming.Delete, - Addr: "localhost:" + servers[0].port, - } - r.w.inject([]*naming.Update{u}) - // Loop until the above updates apply. - for { - time.Sleep(10 * time.Millisecond) - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Millisecond) - if err := cc.Invoke(ctx, "/foo/bar", &expectedRequest, &reply); err != nil { - cancel() - break - } - cancel() - } -} - -func TestPickFirstCloseWithPendingRPC(t *testing.T) { - defer leakcheck.Check(t) - servers, r, cleanup := startServers(t, 1, math.MaxUint32) - defer cleanup() - cc, err := Dial("passthrough:///foo.bar.com", WithBalancer(pickFirstBalancerV1(r)), WithBlock(), WithInsecure(), WithCodec(testCodec{})) - if err != nil { - t.Fatalf("Failed to create ClientConn: %v", err) - } - defer cc.Close() - var reply string - if err := cc.Invoke(context.Background(), "/foo/bar", &expectedRequest, &reply, FailFast(false)); err != nil { - t.Fatalf("grpc.Invoke(_, _, _, _, _) = %v, want %s", err, servers[0].port) - } - // Remove the server. - updates := []*naming.Update{{ - Op: naming.Delete, - Addr: "localhost:" + servers[0].port, - }} - r.w.inject(updates) - // Loop until the above update applies. - for { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Millisecond) - if err := cc.Invoke(ctx, "/foo/bar", &expectedRequest, &reply, FailFast(false)); status.Code(err) == codes.DeadlineExceeded { - cancel() - break - } - time.Sleep(10 * time.Millisecond) - cancel() - } - // Issue 2 RPCs which should be completed with error status once cc is closed. - var wg sync.WaitGroup - wg.Add(2) - go func() { - defer wg.Done() - var reply string - if err := cc.Invoke(context.Background(), "/foo/bar", &expectedRequest, &reply, FailFast(false)); err == nil { - t.Errorf("grpc.Invoke(_, _, _, _, _) = %v, want not nil", err) - } - }() - go func() { - defer wg.Done() - var reply string - time.Sleep(5 * time.Millisecond) - if err := cc.Invoke(context.Background(), "/foo/bar", &expectedRequest, &reply, FailFast(false)); err == nil { - t.Errorf("grpc.Invoke(_, _, _, _, _) = %v, want not nil", err) - } - }() - time.Sleep(5 * time.Millisecond) - cc.Close() - wg.Wait() -} - -func TestPickFirstOrderAllServerUp(t *testing.T) { - defer leakcheck.Check(t) - // Start 3 servers on 3 ports. - numServers := 3 - servers, r, cleanup := startServers(t, numServers, math.MaxUint32) - defer cleanup() - cc, err := Dial("passthrough:///foo.bar.com", WithBalancer(pickFirstBalancerV1(r)), WithBlock(), WithInsecure(), WithCodec(testCodec{})) - if err != nil { - t.Fatalf("Failed to create ClientConn: %v", err) - } - defer cc.Close() - // Add servers[1] and [2] to the service discovery. - u := &naming.Update{ - Op: naming.Add, - Addr: "localhost:" + servers[1].port, - } - r.w.inject([]*naming.Update{u}) - - u = &naming.Update{ - Op: naming.Add, - Addr: "localhost:" + servers[2].port, - } - r.w.inject([]*naming.Update{u}) - - // Loop until all 3 servers are up - checkServerUp(t, servers[0]) - checkServerUp(t, servers[1]) - checkServerUp(t, servers[2]) - - // Check the incoming RPCs served in server[0] - req := "port" - var reply string - for i := 0; i < 20; i++ { - if err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err == nil || errorDesc(err) != servers[0].port { - t.Fatalf("Index %d: Invoke(_, _, _, _, _) = %v, want %s", 0, err, servers[0].port) - } - time.Sleep(10 * time.Millisecond) - } - - // Delete server[0] in the balancer, the incoming RPCs served in server[1] - // For test addrconn, close server[0] instead - u = &naming.Update{ - Op: naming.Delete, - Addr: "localhost:" + servers[0].port, - } - r.w.inject([]*naming.Update{u}) - // Loop until it changes to server[1] - for { - if err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err != nil && errorDesc(err) == servers[1].port { - break - } - time.Sleep(10 * time.Millisecond) - } - for i := 0; i < 20; i++ { - if err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err == nil || errorDesc(err) != servers[1].port { - t.Fatalf("Index %d: Invoke(_, _, _, _, _) = %v, want %s", 1, err, servers[1].port) - } - time.Sleep(10 * time.Millisecond) - } - - // Add server[0] back to the balancer, the incoming RPCs served in server[1] - // Add is append operation, the order of Notify now is {server[1].port server[2].port server[0].port} - u = &naming.Update{ - Op: naming.Add, - Addr: "localhost:" + servers[0].port, - } - r.w.inject([]*naming.Update{u}) - for i := 0; i < 20; i++ { - if err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err == nil || errorDesc(err) != servers[1].port { - t.Fatalf("Index %d: Invoke(_, _, _, _, _) = %v, want %s", 1, err, servers[1].port) - } - time.Sleep(10 * time.Millisecond) - } - - // Delete server[1] in the balancer, the incoming RPCs served in server[2] - u = &naming.Update{ - Op: naming.Delete, - Addr: "localhost:" + servers[1].port, - } - r.w.inject([]*naming.Update{u}) - for { - if err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err != nil && errorDesc(err) == servers[2].port { - break - } - time.Sleep(1 * time.Second) - } - for i := 0; i < 20; i++ { - if err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err == nil || errorDesc(err) != servers[2].port { - t.Fatalf("Index %d: Invoke(_, _, _, _, _) = %v, want %s", 2, err, servers[2].port) - } - time.Sleep(10 * time.Millisecond) - } - - // Delete server[2] in the balancer, the incoming RPCs served in server[0] - u = &naming.Update{ - Op: naming.Delete, - Addr: "localhost:" + servers[2].port, - } - r.w.inject([]*naming.Update{u}) - for { - if err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err != nil && errorDesc(err) == servers[0].port { - break - } - time.Sleep(1 * time.Second) - } - for i := 0; i < 20; i++ { - if err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err == nil || errorDesc(err) != servers[0].port { - t.Fatalf("Index %d: Invoke(_, _, _, _, _) = %v, want %s", 0, err, servers[0].port) - } - time.Sleep(10 * time.Millisecond) - } -} - -func TestPickFirstOrderOneServerDown(t *testing.T) { - defer leakcheck.Check(t) - // Start 3 servers on 3 ports. - numServers := 3 - servers, r, cleanup := startServers(t, numServers, math.MaxUint32) - defer cleanup() - cc, err := Dial("passthrough:///foo.bar.com", WithBalancer(pickFirstBalancerV1(r)), WithBlock(), WithInsecure(), WithCodec(testCodec{}), WithWaitForHandshake()) - if err != nil { - t.Fatalf("Failed to create ClientConn: %v", err) - } - defer cc.Close() - // Add servers[1] and [2] to the service discovery. - u := &naming.Update{ - Op: naming.Add, - Addr: "localhost:" + servers[1].port, - } - r.w.inject([]*naming.Update{u}) - - u = &naming.Update{ - Op: naming.Add, - Addr: "localhost:" + servers[2].port, - } - r.w.inject([]*naming.Update{u}) - - // Loop until all 3 servers are up - checkServerUp(t, servers[0]) - checkServerUp(t, servers[1]) - checkServerUp(t, servers[2]) - - // Check the incoming RPCs served in server[0] - req := "port" - var reply string - for i := 0; i < 20; i++ { - if err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err == nil || errorDesc(err) != servers[0].port { - t.Fatalf("Index %d: Invoke(_, _, _, _, _) = %v, want %s", 0, err, servers[0].port) - } - time.Sleep(10 * time.Millisecond) - } - - // server[0] down, incoming RPCs served in server[1], but the order of Notify still remains - // {server[0] server[1] server[2]} - servers[0].stop() - // Loop until it changes to server[1] - for { - if err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err != nil && errorDesc(err) == servers[1].port { - break - } - time.Sleep(10 * time.Millisecond) - } - for i := 0; i < 20; i++ { - if err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err == nil || errorDesc(err) != servers[1].port { - t.Fatalf("Index %d: Invoke(_, _, _, _, _) = %v, want %s", 1, err, servers[1].port) - } - time.Sleep(10 * time.Millisecond) - } - - // up the server[0] back, the incoming RPCs served in server[1] - p, _ := strconv.Atoi(servers[0].port) - servers[0] = newTestServer() - go servers[0].start(t, p, math.MaxUint32) - defer servers[0].stop() - servers[0].wait(t, 2*time.Second) - checkServerUp(t, servers[0]) - - for i := 0; i < 20; i++ { - if err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err == nil || errorDesc(err) != servers[1].port { - t.Fatalf("Index %d: Invoke(_, _, _, _, _) = %v, want %s", 1, err, servers[1].port) - } - time.Sleep(10 * time.Millisecond) - } - - // Delete server[1] in the balancer, the incoming RPCs served in server[0] - u = &naming.Update{ - Op: naming.Delete, - Addr: "localhost:" + servers[1].port, - } - r.w.inject([]*naming.Update{u}) - for { - if err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err != nil && errorDesc(err) == servers[0].port { - break - } - time.Sleep(1 * time.Second) - } - for i := 0; i < 20; i++ { - if err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err == nil || errorDesc(err) != servers[0].port { - t.Fatalf("Index %d: Invoke(_, _, _, _, _) = %v, want %s", 0, err, servers[0].port) - } - time.Sleep(10 * time.Millisecond) - } -} - -func TestPickFirstOneAddressRemoval(t *testing.T) { - defer leakcheck.Check(t) - // Start 2 servers. - numServers := 2 - servers, r, cleanup := startServers(t, numServers, math.MaxUint32) - defer cleanup() - cc, err := Dial("passthrough:///localhost:"+servers[0].port, WithBalancer(pickFirstBalancerV1(r)), WithBlock(), WithInsecure(), WithCodec(testCodec{})) - if err != nil { - t.Fatalf("Failed to create ClientConn: %v", err) - } - defer cc.Close() - // Add servers[1] to the service discovery. - var updates []*naming.Update - updates = append(updates, &naming.Update{ - Op: naming.Add, - Addr: "localhost:" + servers[1].port, - }) - r.w.inject(updates) - - // Create a new cc to Loop until servers[1] is up - checkServerUp(t, servers[0]) - checkServerUp(t, servers[1]) - - var wg sync.WaitGroup - numRPC := 100 - sleepDuration := 10 * time.Millisecond - wg.Add(1) - go func() { - time.Sleep(sleepDuration) - // After sleepDuration, delete server[0]. - var updates []*naming.Update - updates = append(updates, &naming.Update{ - Op: naming.Delete, - Addr: "localhost:" + servers[0].port, - }) - r.w.inject(updates) - wg.Done() - }() - - // All non-failfast RPCs should not fail because there's at least one connection available. - for i := 0; i < numRPC; i++ { - wg.Add(1) - go func() { - var reply string - time.Sleep(sleepDuration) - // After sleepDuration, invoke RPC. - // server[0] is removed around the same time to make it racy between balancer and gRPC internals. - if err := cc.Invoke(context.Background(), "/foo/bar", &expectedRequest, &reply, FailFast(false)); err != nil { - t.Errorf("grpc.Invoke(_, _, _, _, _) = %v, want nil", err) - } - wg.Done() - }() - } - wg.Wait() -} diff --git a/vendor/google.golang.org/grpc/call_test.go b/vendor/google.golang.org/grpc/call_test.go deleted file mode 100644 index 7800c5d8..00000000 --- a/vendor/google.golang.org/grpc/call_test.go +++ /dev/null @@ -1,293 +0,0 @@ -/* - * - * Copyright 2014 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package grpc - -import ( - "context" - "fmt" - "io" - "math" - "net" - "strconv" - "strings" - "sync" - "testing" - "time" - - "google.golang.org/grpc/codes" - "google.golang.org/grpc/internal/leakcheck" - "google.golang.org/grpc/internal/transport" - "google.golang.org/grpc/status" -) - -var ( - expectedRequest = "ping" - expectedResponse = "pong" - weirdError = "format verbs: %v%s" - sizeLargeErr = 1024 * 1024 - canceled = 0 -) - -type testCodec struct { -} - -func (testCodec) Marshal(v interface{}) ([]byte, error) { - return []byte(*(v.(*string))), nil -} - -func (testCodec) Unmarshal(data []byte, v interface{}) error { - *(v.(*string)) = string(data) - return nil -} - -func (testCodec) String() string { - return "test" -} - -type testStreamHandler struct { - port string - t transport.ServerTransport -} - -func (h *testStreamHandler) handleStream(t *testing.T, s *transport.Stream) { - p := &parser{r: s} - for { - pf, req, err := p.recvMsg(math.MaxInt32) - if err == io.EOF { - break - } - if err != nil { - return - } - if pf != compressionNone { - t.Errorf("Received the mistaken message format %d, want %d", pf, compressionNone) - return - } - var v string - codec := testCodec{} - if err := codec.Unmarshal(req, &v); err != nil { - t.Errorf("Failed to unmarshal the received message: %v", err) - return - } - if v == "weird error" { - h.t.WriteStatus(s, status.New(codes.Internal, weirdError)) - return - } - if v == "canceled" { - canceled++ - h.t.WriteStatus(s, status.New(codes.Internal, "")) - return - } - if v == "port" { - h.t.WriteStatus(s, status.New(codes.Internal, h.port)) - return - } - - if v != expectedRequest { - h.t.WriteStatus(s, status.New(codes.Internal, strings.Repeat("A", sizeLargeErr))) - return - } - } - // send a response back to end the stream. - data, err := encode(testCodec{}, &expectedResponse) - if err != nil { - t.Errorf("Failed to encode the response: %v", err) - return - } - hdr, payload := msgHeader(data, nil) - h.t.Write(s, hdr, payload, &transport.Options{}) - h.t.WriteStatus(s, status.New(codes.OK, "")) -} - -type server struct { - lis net.Listener - port string - addr string - startedErr chan error // sent nil or an error after server starts - mu sync.Mutex - conns map[transport.ServerTransport]bool -} - -func newTestServer() *server { - return &server{startedErr: make(chan error, 1)} -} - -// start starts server. Other goroutines should block on s.startedErr for further operations. -func (s *server) start(t *testing.T, port int, maxStreams uint32) { - var err error - if port == 0 { - s.lis, err = net.Listen("tcp", "localhost:0") - } else { - s.lis, err = net.Listen("tcp", "localhost:"+strconv.Itoa(port)) - } - if err != nil { - s.startedErr <- fmt.Errorf("failed to listen: %v", err) - return - } - s.addr = s.lis.Addr().String() - _, p, err := net.SplitHostPort(s.addr) - if err != nil { - s.startedErr <- fmt.Errorf("failed to parse listener address: %v", err) - return - } - s.port = p - s.conns = make(map[transport.ServerTransport]bool) - s.startedErr <- nil - for { - conn, err := s.lis.Accept() - if err != nil { - return - } - config := &transport.ServerConfig{ - MaxStreams: maxStreams, - } - st, err := transport.NewServerTransport("http2", conn, config) - if err != nil { - continue - } - s.mu.Lock() - if s.conns == nil { - s.mu.Unlock() - st.Close() - return - } - s.conns[st] = true - s.mu.Unlock() - h := &testStreamHandler{ - port: s.port, - t: st, - } - go st.HandleStreams(func(s *transport.Stream) { - go h.handleStream(t, s) - }, func(ctx context.Context, method string) context.Context { - return ctx - }) - } -} - -func (s *server) wait(t *testing.T, timeout time.Duration) { - select { - case err := <-s.startedErr: - if err != nil { - t.Fatal(err) - } - case <-time.After(timeout): - t.Fatalf("Timed out after %v waiting for server to be ready", timeout) - } -} - -func (s *server) stop() { - s.lis.Close() - s.mu.Lock() - for c := range s.conns { - c.Close() - } - s.conns = nil - s.mu.Unlock() -} - -func setUp(t *testing.T, port int, maxStreams uint32) (*server, *ClientConn) { - server := newTestServer() - go server.start(t, port, maxStreams) - server.wait(t, 2*time.Second) - addr := "localhost:" + server.port - cc, err := Dial(addr, WithBlock(), WithInsecure(), WithCodec(testCodec{})) - if err != nil { - t.Fatalf("Failed to create ClientConn: %v", err) - } - return server, cc -} - -func TestInvoke(t *testing.T) { - defer leakcheck.Check(t) - server, cc := setUp(t, 0, math.MaxUint32) - var reply string - if err := cc.Invoke(context.Background(), "/foo/bar", &expectedRequest, &reply); err != nil || reply != expectedResponse { - t.Fatalf("grpc.Invoke(_, _, _, _, _) = %v, want ", err) - } - cc.Close() - server.stop() -} - -func TestInvokeLargeErr(t *testing.T) { - defer leakcheck.Check(t) - server, cc := setUp(t, 0, math.MaxUint32) - var reply string - req := "hello" - err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply) - if _, ok := status.FromError(err); !ok { - t.Fatalf("grpc.Invoke(_, _, _, _, _) receives non rpc error.") - } - if status.Code(err) != codes.Internal || len(errorDesc(err)) != sizeLargeErr { - t.Fatalf("grpc.Invoke(_, _, _, _, _) = %v, want an error of code %d and desc size %d", err, codes.Internal, sizeLargeErr) - } - cc.Close() - server.stop() -} - -// TestInvokeErrorSpecialChars checks that error messages don't get mangled. -func TestInvokeErrorSpecialChars(t *testing.T) { - defer leakcheck.Check(t) - server, cc := setUp(t, 0, math.MaxUint32) - var reply string - req := "weird error" - err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply) - if _, ok := status.FromError(err); !ok { - t.Fatalf("grpc.Invoke(_, _, _, _, _) receives non rpc error.") - } - if got, want := errorDesc(err), weirdError; got != want { - t.Fatalf("grpc.Invoke(_, _, _, _, _) error = %q, want %q", got, want) - } - cc.Close() - server.stop() -} - -// TestInvokeCancel checks that an Invoke with a canceled context is not sent. -func TestInvokeCancel(t *testing.T) { - defer leakcheck.Check(t) - server, cc := setUp(t, 0, math.MaxUint32) - var reply string - req := "canceled" - for i := 0; i < 100; i++ { - ctx, cancel := context.WithCancel(context.Background()) - cancel() - cc.Invoke(ctx, "/foo/bar", &req, &reply) - } - if canceled != 0 { - t.Fatalf("received %d of 100 canceled requests", canceled) - } - cc.Close() - server.stop() -} - -// TestInvokeCancelClosedNonFail checks that a canceled non-failfast RPC -// on a closed client will terminate. -func TestInvokeCancelClosedNonFailFast(t *testing.T) { - defer leakcheck.Check(t) - server, cc := setUp(t, 0, math.MaxUint32) - var reply string - cc.Close() - req := "hello" - ctx, cancel := context.WithCancel(context.Background()) - cancel() - if err := cc.Invoke(ctx, "/foo/bar", &req, &reply, FailFast(false)); err == nil { - t.Fatalf("canceled invoke on closed connection should fail") - } - server.stop() -} diff --git a/vendor/google.golang.org/grpc/clientconn_state_transition_test.go b/vendor/google.golang.org/grpc/clientconn_state_transition_test.go deleted file mode 100644 index bf5bbd88..00000000 --- a/vendor/google.golang.org/grpc/clientconn_state_transition_test.go +++ /dev/null @@ -1,515 +0,0 @@ -/* - * - * Copyright 2018 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package grpc - -import ( - "context" - "net" - "sync" - "sync/atomic" - "testing" - "time" - - "golang.org/x/net/http2" - "google.golang.org/grpc/balancer" - "google.golang.org/grpc/connectivity" - "google.golang.org/grpc/internal/leakcheck" - "google.golang.org/grpc/internal/testutils" - "google.golang.org/grpc/resolver" - "google.golang.org/grpc/resolver/manual" -) - -const stateRecordingBalancerName = "state_recoding_balancer" - -var testBalancer = &stateRecordingBalancer{} - -func init() { - balancer.Register(testBalancer) -} - -// These tests use a pipeListener. This listener is similar to net.Listener except that it is unbuffered, so each read -// and write will wait for the other side's corresponding write or read. -func TestStateTransitions_SingleAddress(t *testing.T) { - defer leakcheck.Check(t) - - mctBkp := getMinConnectTimeout() - defer func() { - atomic.StoreInt64((*int64)(&mutableMinConnectTimeout), int64(mctBkp)) - }() - atomic.StoreInt64((*int64)(&mutableMinConnectTimeout), int64(time.Millisecond)*100) - - for _, test := range []struct { - desc string - want []connectivity.State - server func(net.Listener) net.Conn - }{ - { - desc: "When the server returns server preface, the client enters READY.", - want: []connectivity.State{ - connectivity.Connecting, - connectivity.Ready, - }, - server: func(lis net.Listener) net.Conn { - conn, err := lis.Accept() - if err != nil { - t.Error(err) - return nil - } - - go keepReading(conn) - - framer := http2.NewFramer(conn, conn) - if err := framer.WriteSettings(http2.Setting{}); err != nil { - t.Errorf("Error while writing settings frame. %v", err) - return nil - } - - return conn - }, - }, - { - desc: "When the connection is closed, the client enters TRANSIENT FAILURE.", - want: []connectivity.State{ - connectivity.Connecting, - connectivity.TransientFailure, - }, - server: func(lis net.Listener) net.Conn { - conn, err := lis.Accept() - if err != nil { - t.Error(err) - return nil - } - - conn.Close() - return nil - }, - }, - { - desc: `When the server sends its connection preface, but the connection dies before the client can write its -connection preface, the client enters TRANSIENT FAILURE.`, - want: []connectivity.State{ - connectivity.Connecting, - connectivity.TransientFailure, - }, - server: func(lis net.Listener) net.Conn { - conn, err := lis.Accept() - if err != nil { - t.Error(err) - return nil - } - - framer := http2.NewFramer(conn, conn) - if err := framer.WriteSettings(http2.Setting{}); err != nil { - t.Errorf("Error while writing settings frame. %v", err) - return nil - } - - conn.Close() - return nil - }, - }, - { - desc: `When the server reads the client connection preface but does not send its connection preface, the -client enters TRANSIENT FAILURE.`, - want: []connectivity.State{ - connectivity.Connecting, - connectivity.TransientFailure, - }, - server: func(lis net.Listener) net.Conn { - conn, err := lis.Accept() - if err != nil { - t.Error(err) - return nil - } - - go keepReading(conn) - - return conn - }, - }, - } { - t.Log(test.desc) - testStateTransitionSingleAddress(t, test.want, test.server) - } -} - -func testStateTransitionSingleAddress(t *testing.T, want []connectivity.State, server func(net.Listener) net.Conn) { - defer leakcheck.Check(t) - - stateNotifications := make(chan connectivity.State, len(want)) - testBalancer.ResetNotifier(stateNotifications) - - ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) - defer cancel() - - pl := testutils.NewPipeListener() - defer pl.Close() - - // Launch the server. - var conn net.Conn - var connMu sync.Mutex - go func() { - connMu.Lock() - conn = server(pl) - connMu.Unlock() - }() - - client, err := DialContext(ctx, "", WithWaitForHandshake(), WithInsecure(), - WithBalancerName(stateRecordingBalancerName), WithDialer(pl.Dialer()), withBackoff(noBackoff{})) - if err != nil { - t.Fatal(err) - } - defer client.Close() - - timeout := time.After(5 * time.Second) - - for i := 0; i < len(want); i++ { - select { - case <-timeout: - t.Fatalf("timed out waiting for state %d (%v) in flow %v", i, want[i], want) - case seen := <-stateNotifications: - if seen != want[i] { - t.Fatalf("expected to see %v at position %d in flow %v, got %v", want[i], i, want, seen) - } - } - } - - connMu.Lock() - defer connMu.Unlock() - if conn != nil { - err = conn.Close() - if err != nil { - t.Fatal(err) - } - } -} - -// When a READY connection is closed, the client enters TRANSIENT FAILURE before CONNECTING. -func TestStateTransition_ReadyToTransientFailure(t *testing.T) { - defer leakcheck.Check(t) - - want := []connectivity.State{ - connectivity.Connecting, - connectivity.Ready, - connectivity.TransientFailure, - connectivity.Connecting, - } - - stateNotifications := make(chan connectivity.State, len(want)) - testBalancer.ResetNotifier(stateNotifications) - - ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) - defer cancel() - - lis, err := net.Listen("tcp", "localhost:0") - if err != nil { - t.Fatalf("Error while listening. Err: %v", err) - } - defer lis.Close() - - sawReady := make(chan struct{}) - - // Launch the server. - go func() { - conn, err := lis.Accept() - if err != nil { - t.Error(err) - return - } - - go keepReading(conn) - - framer := http2.NewFramer(conn, conn) - if err := framer.WriteSettings(http2.Setting{}); err != nil { - t.Errorf("Error while writing settings frame. %v", err) - return - } - - // Prevents race between onPrefaceReceipt and onClose. - <-sawReady - - conn.Close() - }() - - client, err := DialContext(ctx, lis.Addr().String(), WithWaitForHandshake(), WithInsecure(), WithBalancerName(stateRecordingBalancerName)) - if err != nil { - t.Fatal(err) - } - defer client.Close() - - timeout := time.After(5 * time.Second) - - for i := 0; i < len(want); i++ { - select { - case <-timeout: - t.Fatalf("timed out waiting for state %d (%v) in flow %v", i, want[i], want) - case seen := <-stateNotifications: - if seen == connectivity.Ready { - close(sawReady) - } - if seen != want[i] { - t.Fatalf("expected to see %v at position %d in flow %v, got %v", want[i], i, want, seen) - } - } - } -} - -// When the first connection is closed, the client enters stays in CONNECTING until it tries the second -// address (which succeeds, and then it enters READY). -func TestStateTransitions_TriesAllAddrsBeforeTransientFailure(t *testing.T) { - defer leakcheck.Check(t) - - want := []connectivity.State{ - connectivity.Connecting, - connectivity.Ready, - } - - stateNotifications := make(chan connectivity.State, len(want)) - testBalancer.ResetNotifier(stateNotifications) - - ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) - defer cancel() - - lis1, err := net.Listen("tcp", "localhost:0") - if err != nil { - t.Fatalf("Error while listening. Err: %v", err) - } - defer lis1.Close() - - lis2, err := net.Listen("tcp", "localhost:0") - if err != nil { - t.Fatalf("Error while listening. Err: %v", err) - } - defer lis2.Close() - - server1Done := make(chan struct{}) - server2Done := make(chan struct{}) - - // Launch server 1. - go func() { - conn, err := lis1.Accept() - if err != nil { - t.Error(err) - return - } - - conn.Close() - close(server1Done) - }() - // Launch server 2. - go func() { - conn, err := lis2.Accept() - if err != nil { - t.Error(err) - return - } - - go keepReading(conn) - - framer := http2.NewFramer(conn, conn) - if err := framer.WriteSettings(http2.Setting{}); err != nil { - t.Errorf("Error while writing settings frame. %v", err) - return - } - - close(server2Done) - }() - - rb := manual.NewBuilderWithScheme("whatever") - rb.InitialAddrs([]resolver.Address{ - {Addr: lis1.Addr().String()}, - {Addr: lis2.Addr().String()}, - }) - client, err := DialContext(ctx, "this-gets-overwritten", WithInsecure(), WithWaitForHandshake(), WithBalancerName(stateRecordingBalancerName), withResolverBuilder(rb)) - if err != nil { - t.Fatal(err) - } - defer client.Close() - - timeout := time.After(5 * time.Second) - - for i := 0; i < len(want); i++ { - select { - case <-timeout: - t.Fatalf("timed out waiting for state %d (%v) in flow %v", i, want[i], want) - case seen := <-stateNotifications: - if seen != want[i] { - t.Fatalf("expected to see %v at position %d in flow %v, got %v", want[i], i, want, seen) - } - } - } - select { - case <-timeout: - t.Fatal("saw the correct state transitions, but timed out waiting for client to finish interactions with server 1") - case <-server1Done: - } - select { - case <-timeout: - t.Fatal("saw the correct state transitions, but timed out waiting for client to finish interactions with server 2") - case <-server2Done: - } -} - -// When there are multiple addresses, and we enter READY on one of them, a later closure should cause -// the client to enter TRANSIENT FAILURE before it re-enters CONNECTING. -func TestStateTransitions_MultipleAddrsEntersReady(t *testing.T) { - defer leakcheck.Check(t) - - want := []connectivity.State{ - connectivity.Connecting, - connectivity.Ready, - connectivity.TransientFailure, - connectivity.Connecting, - } - - stateNotifications := make(chan connectivity.State, len(want)) - testBalancer.ResetNotifier(stateNotifications) - - ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) - defer cancel() - - lis1, err := net.Listen("tcp", "localhost:0") - if err != nil { - t.Fatalf("Error while listening. Err: %v", err) - } - defer lis1.Close() - - // Never actually gets used; we just want it to be alive so that the resolver has two addresses to target. - lis2, err := net.Listen("tcp", "localhost:0") - if err != nil { - t.Fatalf("Error while listening. Err: %v", err) - } - defer lis2.Close() - - server1Done := make(chan struct{}) - sawReady := make(chan struct{}) - - // Launch server 1. - go func() { - conn, err := lis1.Accept() - if err != nil { - t.Error(err) - return - } - - go keepReading(conn) - - framer := http2.NewFramer(conn, conn) - if err := framer.WriteSettings(http2.Setting{}); err != nil { - t.Errorf("Error while writing settings frame. %v", err) - return - } - - <-sawReady - - conn.Close() - - _, err = lis1.Accept() - if err != nil { - t.Error(err) - return - } - - close(server1Done) - }() - - rb := manual.NewBuilderWithScheme("whatever") - rb.InitialAddrs([]resolver.Address{ - {Addr: lis1.Addr().String()}, - {Addr: lis2.Addr().String()}, - }) - client, err := DialContext(ctx, "this-gets-overwritten", WithInsecure(), WithWaitForHandshake(), WithBalancerName(stateRecordingBalancerName), withResolverBuilder(rb)) - if err != nil { - t.Fatal(err) - } - defer client.Close() - - timeout := time.After(2 * time.Second) - - for i := 0; i < len(want); i++ { - select { - case <-timeout: - t.Fatalf("timed out waiting for state %d (%v) in flow %v", i, want[i], want) - case seen := <-stateNotifications: - if seen == connectivity.Ready { - close(sawReady) - } - if seen != want[i] { - t.Fatalf("expected to see %v at position %d in flow %v, got %v", want[i], i, want, seen) - } - } - } - select { - case <-timeout: - t.Fatal("saw the correct state transitions, but timed out waiting for client to finish interactions with server 1") - case <-server1Done: - } -} - -type stateRecordingBalancer struct { - mu sync.Mutex - notifier chan<- connectivity.State - - balancer.Balancer -} - -func (b *stateRecordingBalancer) HandleSubConnStateChange(sc balancer.SubConn, s connectivity.State) { - b.mu.Lock() - b.notifier <- s - b.mu.Unlock() - - b.Balancer.HandleSubConnStateChange(sc, s) -} - -func (b *stateRecordingBalancer) ResetNotifier(r chan<- connectivity.State) { - b.mu.Lock() - defer b.mu.Unlock() - b.notifier = r -} - -func (b *stateRecordingBalancer) Close() { - b.mu.Lock() - u := b.Balancer - b.mu.Unlock() - u.Close() -} - -func (b *stateRecordingBalancer) Name() string { - return stateRecordingBalancerName -} - -func (b *stateRecordingBalancer) Build(cc balancer.ClientConn, opts balancer.BuildOptions) balancer.Balancer { - b.mu.Lock() - b.Balancer = balancer.Get(PickFirstBalancerName).Build(cc, opts) - b.mu.Unlock() - return b -} - -type noBackoff struct{} - -func (b noBackoff) Backoff(int) time.Duration { return time.Duration(0) } - -// Keep reading until something causes the connection to die (EOF, server closed, etc). Useful -// as a tool for mindlessly keeping the connection healthy, since the client will error if -// things like client prefaces are not accepted in a timely fashion. -func keepReading(conn net.Conn) { - buf := make([]byte, 1024) - for _, err := conn.Read(buf); err == nil; _, err = conn.Read(buf) { - } -} diff --git a/vendor/google.golang.org/grpc/clientconn_test.go b/vendor/google.golang.org/grpc/clientconn_test.go deleted file mode 100644 index 467e2ef5..00000000 --- a/vendor/google.golang.org/grpc/clientconn_test.go +++ /dev/null @@ -1,1022 +0,0 @@ -/* - * - * Copyright 2014 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package grpc - -import ( - "context" - "errors" - "fmt" - "math" - "net" - "sync/atomic" - "testing" - "time" - - "golang.org/x/net/http2" - "google.golang.org/grpc/connectivity" - "google.golang.org/grpc/credentials" - "google.golang.org/grpc/internal/backoff" - "google.golang.org/grpc/internal/envconfig" - "google.golang.org/grpc/internal/leakcheck" - "google.golang.org/grpc/internal/transport" - "google.golang.org/grpc/keepalive" - "google.golang.org/grpc/naming" - "google.golang.org/grpc/resolver" - "google.golang.org/grpc/resolver/manual" - _ "google.golang.org/grpc/resolver/passthrough" - "google.golang.org/grpc/testdata" -) - -var ( - mutableMinConnectTimeout = time.Second * 20 -) - -func init() { - getMinConnectTimeout = func() time.Duration { - return time.Duration(atomic.LoadInt64((*int64)(&mutableMinConnectTimeout))) - } -} - -func assertState(wantState connectivity.State, cc *ClientConn) (connectivity.State, bool) { - ctx, cancel := context.WithTimeout(context.Background(), time.Second) - defer cancel() - var state connectivity.State - for state = cc.GetState(); state != wantState && cc.WaitForStateChange(ctx, state); state = cc.GetState() { - } - return state, state == wantState -} - -func TestDialWithMultipleBackendsNotSendingServerPreface(t *testing.T) { - defer leakcheck.Check(t) - numServers := 2 - servers := make([]net.Listener, numServers) - var err error - for i := 0; i < numServers; i++ { - servers[i], err = net.Listen("tcp", "localhost:0") - if err != nil { - t.Fatalf("Error while listening. Err: %v", err) - } - } - dones := make([]chan struct{}, numServers) - for i := 0; i < numServers; i++ { - dones[i] = make(chan struct{}) - } - for i := 0; i < numServers; i++ { - go func(i int) { - defer func() { - close(dones[i]) - }() - conn, err := servers[i].Accept() - if err != nil { - t.Errorf("Error while accepting. Err: %v", err) - return - } - defer conn.Close() - switch i { - case 0: // 1st server accepts the connection and immediately closes it. - case 1: // 2nd server accepts the connection and sends settings frames. - framer := http2.NewFramer(conn, conn) - if err := framer.WriteSettings(http2.Setting{}); err != nil { - t.Errorf("Error while writing settings frame. %v", err) - return - } - conn.SetDeadline(time.Now().Add(time.Second)) - buf := make([]byte, 1024) - for { // Make sure the connection stays healthy. - _, err = conn.Read(buf) - if err == nil { - continue - } - if nerr, ok := err.(net.Error); !ok || !nerr.Timeout() { - t.Errorf("Server expected the conn.Read(_) to timeout instead got error: %v", err) - } - return - } - } - }(i) - } - r, cleanup := manual.GenerateAndRegisterManualResolver() - defer cleanup() - resolvedAddrs := make([]resolver.Address, numServers) - for i := 0; i < numServers; i++ { - resolvedAddrs[i] = resolver.Address{Addr: servers[i].Addr().String()} - } - r.InitialAddrs(resolvedAddrs) - client, err := Dial(r.Scheme()+":///test.server", WithInsecure()) - if err != nil { - t.Errorf("Dial failed. Err: %v", err) - } else { - defer client.Close() - } - time.Sleep(time.Second) // Close the servers after a second for cleanup. - for _, s := range servers { - s.Close() - } - for _, done := range dones { - <-done - } -} - -var allReqHSSettings = []envconfig.RequireHandshakeSetting{ - envconfig.RequireHandshakeOff, - envconfig.RequireHandshakeOn, - envconfig.RequireHandshakeHybrid, -} -var reqNoHSSettings = []envconfig.RequireHandshakeSetting{ - envconfig.RequireHandshakeOff, - envconfig.RequireHandshakeHybrid, -} -var reqHSBeforeSuccess = []envconfig.RequireHandshakeSetting{ - envconfig.RequireHandshakeOn, - envconfig.RequireHandshakeHybrid, -} - -func TestDialWaitsForServerSettings(t *testing.T) { - // Restore current setting after test. - old := envconfig.RequireHandshake - defer func() { envconfig.RequireHandshake = old }() - - defer leakcheck.Check(t) - - // Test with all environment variable settings, which should not impact the - // test case since WithWaitForHandshake has higher priority. - for _, setting := range allReqHSSettings { - envconfig.RequireHandshake = setting - lis, err := net.Listen("tcp", "localhost:0") - if err != nil { - t.Fatalf("Error while listening. Err: %v", err) - } - defer lis.Close() - done := make(chan struct{}) - sent := make(chan struct{}) - dialDone := make(chan struct{}) - go func() { // Launch the server. - defer func() { - close(done) - }() - conn, err := lis.Accept() - if err != nil { - t.Errorf("Error while accepting. Err: %v", err) - return - } - defer conn.Close() - // Sleep for a little bit to make sure that Dial on client - // side blocks until settings are received. - time.Sleep(100 * time.Millisecond) - framer := http2.NewFramer(conn, conn) - close(sent) - if err := framer.WriteSettings(http2.Setting{}); err != nil { - t.Errorf("Error while writing settings. Err: %v", err) - return - } - <-dialDone // Close conn only after dial returns. - }() - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - client, err := DialContext(ctx, lis.Addr().String(), WithInsecure(), WithWaitForHandshake(), WithBlock()) - close(dialDone) - if err != nil { - t.Fatalf("Error while dialing. Err: %v", err) - } - defer client.Close() - select { - case <-sent: - default: - t.Fatalf("Dial returned before server settings were sent") - } - <-done - } -} - -func TestDialWaitsForServerSettingsViaEnv(t *testing.T) { - // Set default behavior and restore current setting after test. - old := envconfig.RequireHandshake - envconfig.RequireHandshake = envconfig.RequireHandshakeOn - defer func() { envconfig.RequireHandshake = old }() - - defer leakcheck.Check(t) - - lis, err := net.Listen("tcp", "localhost:0") - if err != nil { - t.Fatalf("Error while listening. Err: %v", err) - } - defer lis.Close() - done := make(chan struct{}) - sent := make(chan struct{}) - dialDone := make(chan struct{}) - go func() { // Launch the server. - defer func() { - close(done) - }() - conn, err := lis.Accept() - if err != nil { - t.Errorf("Error while accepting. Err: %v", err) - return - } - defer conn.Close() - // Sleep for a little bit to make sure that Dial on client - // side blocks until settings are received. - time.Sleep(100 * time.Millisecond) - framer := http2.NewFramer(conn, conn) - close(sent) - if err := framer.WriteSettings(http2.Setting{}); err != nil { - t.Errorf("Error while writing settings. Err: %v", err) - return - } - <-dialDone // Close conn only after dial returns. - }() - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - client, err := DialContext(ctx, lis.Addr().String(), WithInsecure(), WithBlock()) - close(dialDone) - if err != nil { - t.Fatalf("Error while dialing. Err: %v", err) - } - defer client.Close() - select { - case <-sent: - default: - t.Fatalf("Dial returned before server settings were sent") - } - <-done -} - -func TestDialWaitsForServerSettingsAndFails(t *testing.T) { - // Restore current setting after test. - old := envconfig.RequireHandshake - defer func() { envconfig.RequireHandshake = old }() - - defer leakcheck.Check(t) - - for _, setting := range allReqHSSettings { - envconfig.RequireHandshake = setting - lis, err := net.Listen("tcp", "localhost:0") - if err != nil { - t.Fatalf("Error while listening. Err: %v", err) - } - done := make(chan struct{}) - numConns := 0 - go func() { // Launch the server. - defer func() { - close(done) - }() - for { - conn, err := lis.Accept() - if err != nil { - break - } - numConns++ - defer conn.Close() - } - }() - getMinConnectTimeout = func() time.Duration { return time.Second / 4 } - ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) - defer cancel() - client, err := DialContext(ctx, lis.Addr().String(), WithInsecure(), WithWaitForHandshake(), WithBlock(), withBackoff(noBackoff{})) - lis.Close() - if err == nil { - client.Close() - t.Fatalf("Unexpected success (err=nil) while dialing") - } - if err != context.DeadlineExceeded { - t.Fatalf("DialContext(_) = %v; want context.DeadlineExceeded", err) - } - if numConns < 2 { - t.Fatalf("dial attempts: %v; want > 1", numConns) - } - <-done - } -} - -func TestDialWaitsForServerSettingsViaEnvAndFails(t *testing.T) { - // Set default behavior and restore current setting after test. - old := envconfig.RequireHandshake - envconfig.RequireHandshake = envconfig.RequireHandshakeOn - defer func() { envconfig.RequireHandshake = old }() - - defer leakcheck.Check(t) - - lis, err := net.Listen("tcp", "localhost:0") - if err != nil { - t.Fatalf("Error while listening. Err: %v", err) - } - done := make(chan struct{}) - numConns := 0 - go func() { // Launch the server. - defer func() { - close(done) - }() - for { - conn, err := lis.Accept() - if err != nil { - break - } - numConns++ - defer conn.Close() - } - }() - getMinConnectTimeout = func() time.Duration { return time.Second / 4 } - ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) - defer cancel() - client, err := DialContext(ctx, lis.Addr().String(), WithInsecure(), WithBlock(), withBackoff(noBackoff{})) - lis.Close() - if err == nil { - client.Close() - t.Fatalf("Unexpected success (err=nil) while dialing") - } - if err != context.DeadlineExceeded { - t.Fatalf("DialContext(_) = %v; want context.DeadlineExceeded", err) - } - if numConns < 2 { - t.Fatalf("dial attempts: %v; want > 1", numConns) - } - <-done -} - -func TestDialDoesNotWaitForServerSettings(t *testing.T) { - // Restore current setting after test. - old := envconfig.RequireHandshake - defer func() { envconfig.RequireHandshake = old }() - - defer leakcheck.Check(t) - - // Test with "off" and "hybrid". - for _, setting := range reqNoHSSettings { - envconfig.RequireHandshake = setting - lis, err := net.Listen("tcp", "localhost:0") - if err != nil { - t.Fatalf("Error while listening. Err: %v", err) - } - defer lis.Close() - done := make(chan struct{}) - dialDone := make(chan struct{}) - go func() { // Launch the server. - defer func() { - close(done) - }() - conn, err := lis.Accept() - if err != nil { - t.Errorf("Error while accepting. Err: %v", err) - return - } - defer conn.Close() - <-dialDone // Close conn only after dial returns. - }() - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - client, err := DialContext(ctx, lis.Addr().String(), WithInsecure(), WithBlock()) - - if err != nil { - t.Fatalf("DialContext returned err =%v; want nil", err) - } - defer client.Close() - - if state := client.GetState(); state != connectivity.Ready { - t.Fatalf("client.GetState() = %v; want connectivity.Ready", state) - } - close(dialDone) - <-done - } -} - -func TestCloseConnectionWhenServerPrefaceNotReceived(t *testing.T) { - // Restore current setting after test. - old := envconfig.RequireHandshake - defer func() { envconfig.RequireHandshake = old }() - - // 1. Client connects to a server that doesn't send preface. - // 2. After minConnectTimeout(500 ms here), client disconnects and retries. - // 3. The new server sends its preface. - // 4. Client doesn't kill the connection this time. - mctBkp := getMinConnectTimeout() - defer func() { - atomic.StoreInt64((*int64)(&mutableMinConnectTimeout), int64(mctBkp)) - }() - defer leakcheck.Check(t) - atomic.StoreInt64((*int64)(&mutableMinConnectTimeout), int64(time.Millisecond)*500) - - // Test with "on" and "hybrid". - for _, setting := range reqHSBeforeSuccess { - envconfig.RequireHandshake = setting - - lis, err := net.Listen("tcp", "localhost:0") - if err != nil { - t.Fatalf("Error while listening. Err: %v", err) - } - var ( - conn2 net.Conn - over uint32 - ) - defer func() { - lis.Close() - // conn2 shouldn't be closed until the client has - // observed a successful test. - if conn2 != nil { - conn2.Close() - } - }() - done := make(chan struct{}) - accepted := make(chan struct{}) - go func() { // Launch the server. - defer close(done) - conn1, err := lis.Accept() - if err != nil { - t.Errorf("Error while accepting. Err: %v", err) - return - } - defer conn1.Close() - // Don't send server settings and the client should close the connection and try again. - conn2, err = lis.Accept() // Accept a reconnection request from client. - if err != nil { - t.Errorf("Error while accepting. Err: %v", err) - return - } - close(accepted) - framer := http2.NewFramer(conn2, conn2) - if err = framer.WriteSettings(http2.Setting{}); err != nil { - t.Errorf("Error while writing settings. Err: %v", err) - return - } - b := make([]byte, 8) - for { - _, err = conn2.Read(b) - if err == nil { - continue - } - if atomic.LoadUint32(&over) == 1 { - // The connection stayed alive for the timer. - // Success. - return - } - t.Errorf("Unexpected error while reading. Err: %v, want timeout error", err) - break - } - }() - client, err := Dial(lis.Addr().String(), WithInsecure()) - if err != nil { - t.Fatalf("Error while dialing. Err: %v", err) - } - // wait for connection to be accepted on the server. - timer := time.NewTimer(time.Second * 10) - select { - case <-accepted: - case <-timer.C: - t.Fatalf("Client didn't make another connection request in time.") - } - // Make sure the connection stays alive for sometime. - time.Sleep(time.Second) - atomic.StoreUint32(&over, 1) - client.Close() - <-done - } -} - -func TestBackoffWhenNoServerPrefaceReceived(t *testing.T) { - defer leakcheck.Check(t) - lis, err := net.Listen("tcp", "localhost:0") - if err != nil { - t.Fatalf("Error while listening. Err: %v", err) - } - defer lis.Close() - done := make(chan struct{}) - go func() { // Launch the server. - defer func() { - close(done) - }() - conn, err := lis.Accept() // Accept the connection only to close it immediately. - if err != nil { - t.Errorf("Error while accepting. Err: %v", err) - return - } - prevAt := time.Now() - conn.Close() - var prevDuration time.Duration - // Make sure the retry attempts are backed off properly. - for i := 0; i < 3; i++ { - conn, err := lis.Accept() - if err != nil { - t.Errorf("Error while accepting. Err: %v", err) - return - } - meow := time.Now() - conn.Close() - dr := meow.Sub(prevAt) - if dr <= prevDuration { - t.Errorf("Client backoff did not increase with retries. Previous duration: %v, current duration: %v", prevDuration, dr) - return - } - prevDuration = dr - prevAt = meow - } - }() - client, err := Dial(lis.Addr().String(), WithInsecure()) - if err != nil { - t.Fatalf("Error while dialing. Err: %v", err) - } - defer client.Close() - <-done - -} - -func TestConnectivityStates(t *testing.T) { - defer leakcheck.Check(t) - servers, resolver, cleanup := startServers(t, 2, math.MaxUint32) - defer cleanup() - cc, err := Dial("passthrough:///foo.bar.com", WithBalancer(RoundRobin(resolver)), WithInsecure()) - if err != nil { - t.Fatalf("Dial(\"foo.bar.com\", WithBalancer(_)) = _, %v, want _ ", err) - } - defer cc.Close() - wantState := connectivity.Ready - if state, ok := assertState(wantState, cc); !ok { - t.Fatalf("asserState(%s) = %s, false, want %s, true", wantState, state, wantState) - } - // Send an update to delete the server connection (tearDown addrConn). - update := []*naming.Update{ - { - Op: naming.Delete, - Addr: "localhost:" + servers[0].port, - }, - } - resolver.w.inject(update) - wantState = connectivity.TransientFailure - if state, ok := assertState(wantState, cc); !ok { - t.Fatalf("asserState(%s) = %s, false, want %s, true", wantState, state, wantState) - } - update[0] = &naming.Update{ - Op: naming.Add, - Addr: "localhost:" + servers[1].port, - } - resolver.w.inject(update) - wantState = connectivity.Ready - if state, ok := assertState(wantState, cc); !ok { - t.Fatalf("asserState(%s) = %s, false, want %s, true", wantState, state, wantState) - } - -} - -func TestWithTimeout(t *testing.T) { - defer leakcheck.Check(t) - conn, err := Dial("passthrough:///Non-Existent.Server:80", WithTimeout(time.Millisecond), WithBlock(), WithInsecure()) - if err == nil { - conn.Close() - } - if err != context.DeadlineExceeded { - t.Fatalf("Dial(_, _) = %v, %v, want %v", conn, err, context.DeadlineExceeded) - } -} - -func TestWithTransportCredentialsTLS(t *testing.T) { - ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond) - defer cancel() - defer leakcheck.Check(t) - creds, err := credentials.NewClientTLSFromFile(testdata.Path("ca.pem"), "x.test.youtube.com") - if err != nil { - t.Fatalf("Failed to create credentials %v", err) - } - conn, err := DialContext(ctx, "passthrough:///Non-Existent.Server:80", WithTransportCredentials(creds), WithBlock()) - if err == nil { - conn.Close() - } - if err != context.DeadlineExceeded { - t.Fatalf("Dial(_, _) = %v, %v, want %v", conn, err, context.DeadlineExceeded) - } -} - -func TestDefaultAuthority(t *testing.T) { - defer leakcheck.Check(t) - target := "Non-Existent.Server:8080" - conn, err := Dial(target, WithInsecure()) - if err != nil { - t.Fatalf("Dial(_, _) = _, %v, want _, ", err) - } - defer conn.Close() - if conn.authority != target { - t.Fatalf("%v.authority = %v, want %v", conn, conn.authority, target) - } -} - -func TestTLSServerNameOverwrite(t *testing.T) { - defer leakcheck.Check(t) - overwriteServerName := "over.write.server.name" - creds, err := credentials.NewClientTLSFromFile(testdata.Path("ca.pem"), overwriteServerName) - if err != nil { - t.Fatalf("Failed to create credentials %v", err) - } - conn, err := Dial("passthrough:///Non-Existent.Server:80", WithTransportCredentials(creds)) - if err != nil { - t.Fatalf("Dial(_, _) = _, %v, want _, ", err) - } - defer conn.Close() - if conn.authority != overwriteServerName { - t.Fatalf("%v.authority = %v, want %v", conn, conn.authority, overwriteServerName) - } -} - -func TestWithAuthority(t *testing.T) { - defer leakcheck.Check(t) - overwriteServerName := "over.write.server.name" - conn, err := Dial("passthrough:///Non-Existent.Server:80", WithInsecure(), WithAuthority(overwriteServerName)) - if err != nil { - t.Fatalf("Dial(_, _) = _, %v, want _, ", err) - } - defer conn.Close() - if conn.authority != overwriteServerName { - t.Fatalf("%v.authority = %v, want %v", conn, conn.authority, overwriteServerName) - } -} - -func TestWithAuthorityAndTLS(t *testing.T) { - defer leakcheck.Check(t) - overwriteServerName := "over.write.server.name" - creds, err := credentials.NewClientTLSFromFile(testdata.Path("ca.pem"), overwriteServerName) - if err != nil { - t.Fatalf("Failed to create credentials %v", err) - } - conn, err := Dial("passthrough:///Non-Existent.Server:80", WithTransportCredentials(creds), WithAuthority("no.effect.authority")) - if err != nil { - t.Fatalf("Dial(_, _) = _, %v, want _, ", err) - } - defer conn.Close() - if conn.authority != overwriteServerName { - t.Fatalf("%v.authority = %v, want %v", conn, conn.authority, overwriteServerName) - } -} - -func TestDialContextCancel(t *testing.T) { - defer leakcheck.Check(t) - ctx, cancel := context.WithCancel(context.Background()) - cancel() - if _, err := DialContext(ctx, "Non-Existent.Server:80", WithBlock(), WithInsecure()); err != context.Canceled { - t.Fatalf("DialContext(%v, _) = _, %v, want _, %v", ctx, err, context.Canceled) - } -} - -type failFastError struct{} - -func (failFastError) Error() string { return "failfast" } -func (failFastError) Temporary() bool { return false } - -func TestDialContextFailFast(t *testing.T) { - defer leakcheck.Check(t) - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - failErr := failFastError{} - dialer := func(string, time.Duration) (net.Conn, error) { - return nil, failErr - } - - _, err := DialContext(ctx, "Non-Existent.Server:80", WithBlock(), WithInsecure(), WithDialer(dialer), FailOnNonTempDialError(true)) - if terr, ok := err.(transport.ConnectionError); !ok || terr.Origin() != failErr { - t.Fatalf("DialContext() = _, %v, want _, %v", err, failErr) - } -} - -// blockingBalancer mimics the behavior of balancers whose initialization takes a long time. -// In this test, reading from blockingBalancer.Notify() blocks forever. -type blockingBalancer struct { - ch chan []Address -} - -func newBlockingBalancer() Balancer { - return &blockingBalancer{ch: make(chan []Address)} -} -func (b *blockingBalancer) Start(target string, config BalancerConfig) error { - return nil -} -func (b *blockingBalancer) Up(addr Address) func(error) { - return nil -} -func (b *blockingBalancer) Get(ctx context.Context, opts BalancerGetOptions) (addr Address, put func(), err error) { - return Address{}, nil, nil -} -func (b *blockingBalancer) Notify() <-chan []Address { - return b.ch -} -func (b *blockingBalancer) Close() error { - close(b.ch) - return nil -} - -func TestDialWithBlockingBalancer(t *testing.T) { - defer leakcheck.Check(t) - ctx, cancel := context.WithCancel(context.Background()) - dialDone := make(chan struct{}) - go func() { - DialContext(ctx, "Non-Existent.Server:80", WithBlock(), WithInsecure(), WithBalancer(newBlockingBalancer())) - close(dialDone) - }() - cancel() - <-dialDone -} - -// securePerRPCCredentials always requires transport security. -type securePerRPCCredentials struct{} - -func (c securePerRPCCredentials) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { - return nil, nil -} - -func (c securePerRPCCredentials) RequireTransportSecurity() bool { - return true -} - -func TestCredentialsMisuse(t *testing.T) { - defer leakcheck.Check(t) - tlsCreds, err := credentials.NewClientTLSFromFile(testdata.Path("ca.pem"), "x.test.youtube.com") - if err != nil { - t.Fatalf("Failed to create authenticator %v", err) - } - // Two conflicting credential configurations - if _, err := Dial("passthrough:///Non-Existent.Server:80", WithTransportCredentials(tlsCreds), WithBlock(), WithInsecure()); err != errCredentialsConflict { - t.Fatalf("Dial(_, _) = _, %v, want _, %v", err, errCredentialsConflict) - } - // security info on insecure connection - if _, err := Dial("passthrough:///Non-Existent.Server:80", WithPerRPCCredentials(securePerRPCCredentials{}), WithBlock(), WithInsecure()); err != errTransportCredentialsMissing { - t.Fatalf("Dial(_, _) = _, %v, want _, %v", err, errTransportCredentialsMissing) - } -} - -func TestWithBackoffConfigDefault(t *testing.T) { - defer leakcheck.Check(t) - testBackoffConfigSet(t, &DefaultBackoffConfig) -} - -func TestWithBackoffConfig(t *testing.T) { - defer leakcheck.Check(t) - b := BackoffConfig{MaxDelay: DefaultBackoffConfig.MaxDelay / 2} - expected := b - testBackoffConfigSet(t, &expected, WithBackoffConfig(b)) -} - -func TestWithBackoffMaxDelay(t *testing.T) { - defer leakcheck.Check(t) - md := DefaultBackoffConfig.MaxDelay / 2 - expected := BackoffConfig{MaxDelay: md} - testBackoffConfigSet(t, &expected, WithBackoffMaxDelay(md)) -} - -func testBackoffConfigSet(t *testing.T, expected *BackoffConfig, opts ...DialOption) { - opts = append(opts, WithInsecure()) - conn, err := Dial("passthrough:///foo:80", opts...) - if err != nil { - t.Fatalf("unexpected error dialing connection: %v", err) - } - defer conn.Close() - - if conn.dopts.bs == nil { - t.Fatalf("backoff config not set") - } - - actual, ok := conn.dopts.bs.(backoff.Exponential) - if !ok { - t.Fatalf("unexpected type of backoff config: %#v", conn.dopts.bs) - } - - expectedValue := backoff.Exponential{ - MaxDelay: expected.MaxDelay, - } - if actual != expectedValue { - t.Fatalf("unexpected backoff config on connection: %v, want %v", actual, expected) - } -} - -// emptyBalancer returns an empty set of servers. -type emptyBalancer struct { - ch chan []Address -} - -func newEmptyBalancer() Balancer { - return &emptyBalancer{ch: make(chan []Address, 1)} -} -func (b *emptyBalancer) Start(_ string, _ BalancerConfig) error { - b.ch <- nil - return nil -} -func (b *emptyBalancer) Up(_ Address) func(error) { - return nil -} -func (b *emptyBalancer) Get(_ context.Context, _ BalancerGetOptions) (Address, func(), error) { - return Address{}, nil, nil -} -func (b *emptyBalancer) Notify() <-chan []Address { - return b.ch -} -func (b *emptyBalancer) Close() error { - close(b.ch) - return nil -} - -func TestNonblockingDialWithEmptyBalancer(t *testing.T) { - defer leakcheck.Check(t) - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - dialDone := make(chan error) - go func() { - dialDone <- func() error { - conn, err := DialContext(ctx, "Non-Existent.Server:80", WithInsecure(), WithBalancer(newEmptyBalancer())) - if err != nil { - return err - } - return conn.Close() - }() - }() - if err := <-dialDone; err != nil { - t.Fatalf("unexpected error dialing connection: %s", err) - } -} - -func TestResolverServiceConfigBeforeAddressNotPanic(t *testing.T) { - defer leakcheck.Check(t) - r, rcleanup := manual.GenerateAndRegisterManualResolver() - defer rcleanup() - - cc, err := Dial(r.Scheme()+":///test.server", WithInsecure()) - if err != nil { - t.Fatalf("failed to dial: %v", err) - } - defer cc.Close() - - // SwitchBalancer before NewAddress. There was no balancer created, this - // makes sure we don't call close on nil balancerWrapper. - r.NewServiceConfig(`{"loadBalancingPolicy": "round_robin"}`) // This should not panic. - - time.Sleep(time.Second) // Sleep to make sure the service config is handled by ClientConn. -} - -func TestResolverServiceConfigWhileClosingNotPanic(t *testing.T) { - defer leakcheck.Check(t) - for i := 0; i < 10; i++ { // Run this multiple times to make sure it doesn't panic. - r, rcleanup := manual.GenerateAndRegisterManualResolver() - defer rcleanup() - - cc, err := Dial(r.Scheme()+":///test.server", WithInsecure()) - if err != nil { - t.Fatalf("failed to dial: %v", err) - } - // Send a new service config while closing the ClientConn. - go cc.Close() - go r.NewServiceConfig(`{"loadBalancingPolicy": "round_robin"}`) // This should not panic. - } -} - -func TestResolverEmptyUpdateNotPanic(t *testing.T) { - defer leakcheck.Check(t) - r, rcleanup := manual.GenerateAndRegisterManualResolver() - defer rcleanup() - - cc, err := Dial(r.Scheme()+":///test.server", WithInsecure()) - if err != nil { - t.Fatalf("failed to dial: %v", err) - } - defer cc.Close() - - // This make sure we don't create addrConn with empty address list. - r.NewAddress([]resolver.Address{}) // This should not panic. - - time.Sleep(time.Second) // Sleep to make sure the service config is handled by ClientConn. -} - -func TestClientUpdatesParamsAfterGoAway(t *testing.T) { - defer leakcheck.Check(t) - lis, err := net.Listen("tcp", "localhost:0") - if err != nil { - t.Fatalf("Failed to listen. Err: %v", err) - } - defer lis.Close() - addr := lis.Addr().String() - s := NewServer() - go s.Serve(lis) - defer s.Stop() - cc, err := Dial(addr, WithBlock(), WithInsecure(), WithKeepaliveParams(keepalive.ClientParameters{ - Time: 50 * time.Millisecond, - Timeout: 100 * time.Millisecond, - PermitWithoutStream: true, - })) - if err != nil { - t.Fatalf("Dial(%s, _) = _, %v, want _, ", addr, err) - } - defer cc.Close() - time.Sleep(time.Second) - cc.mu.RLock() - defer cc.mu.RUnlock() - v := cc.mkp.Time - if v < 100*time.Millisecond { - t.Fatalf("cc.dopts.copts.Keepalive.Time = %v , want 100ms", v) - } -} - -func TestDisableServiceConfigOption(t *testing.T) { - r, cleanup := manual.GenerateAndRegisterManualResolver() - defer cleanup() - addr := r.Scheme() + ":///non.existent" - cc, err := Dial(addr, WithInsecure(), WithDisableServiceConfig()) - if err != nil { - t.Fatalf("Dial(%s, _) = _, %v, want _, ", addr, err) - } - defer cc.Close() - r.NewServiceConfig(`{ - "methodConfig": [ - { - "name": [ - { - "service": "foo", - "method": "Bar" - } - ], - "waitForReady": true - } - ] -}`) - time.Sleep(time.Second) - m := cc.GetMethodConfig("/foo/Bar") - if m.WaitForReady != nil { - t.Fatalf("want: method (\"/foo/bar/\") config to be empty, got: %v", m) - } -} - -func TestGetClientConnTarget(t *testing.T) { - addr := "nonexist:///non.existent" - cc, err := Dial(addr, WithInsecure()) - if err != nil { - t.Fatalf("Dial(%s, _) = _, %v, want _, ", addr, err) - } - defer cc.Close() - if cc.Target() != addr { - t.Fatalf("Target() = %s, want %s", cc.Target(), addr) - } -} - -type backoffForever struct{} - -func (b backoffForever) Backoff(int) time.Duration { return time.Duration(math.MaxInt64) } - -func TestResetConnectBackoff(t *testing.T) { - defer leakcheck.Check(t) - dials := make(chan struct{}) - defer func() { // If we fail, let the http2client break out of dialing. - select { - case <-dials: - default: - } - }() - dialer := func(string, time.Duration) (net.Conn, error) { - dials <- struct{}{} - return nil, errors.New("failed to fake dial") - } - cc, err := Dial("any", WithInsecure(), WithDialer(dialer), withBackoff(backoffForever{})) - if err != nil { - t.Fatalf("Dial() = _, %v; want _, nil", err) - } - defer cc.Close() - select { - case <-dials: - case <-time.NewTimer(10 * time.Second).C: - t.Fatal("Failed to call dial within 10s") - } - - select { - case <-dials: - t.Fatal("Dial called unexpectedly before resetting backoff") - case <-time.NewTimer(100 * time.Millisecond).C: - } - - cc.ResetConnectBackoff() - - select { - case <-dials: - case <-time.NewTimer(10 * time.Second).C: - t.Fatal("Failed to call dial within 10s after resetting backoff") - } -} - -func TestBackoffCancel(t *testing.T) { - defer leakcheck.Check(t) - dialStrCh := make(chan string) - cc, err := Dial("any", WithInsecure(), WithDialer(func(t string, _ time.Duration) (net.Conn, error) { - dialStrCh <- t - return nil, fmt.Errorf("test dialer, always error") - })) - if err != nil { - t.Fatalf("Failed to create ClientConn: %v", err) - } - <-dialStrCh - cc.Close() - // Should not leak. May need -count 5000 to exercise. -} diff --git a/vendor/google.golang.org/grpc/codec_test.go b/vendor/google.golang.org/grpc/codec_test.go deleted file mode 100644 index 3fda708e..00000000 --- a/vendor/google.golang.org/grpc/codec_test.go +++ /dev/null @@ -1,32 +0,0 @@ -/* - * - * Copyright 2014 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package grpc - -import ( - "testing" - - "google.golang.org/grpc/encoding" - "google.golang.org/grpc/encoding/proto" -) - -func TestGetCodecForProtoIsNotNil(t *testing.T) { - if encoding.GetCodec(proto.Name) == nil { - t.Fatalf("encoding.GetCodec(%q) must not be nil by default", proto.Name) - } -} diff --git a/vendor/google.golang.org/grpc/codegen.sh b/vendor/google.golang.org/grpc/codegen.sh deleted file mode 100755 index 4cdc6ba7..00000000 --- a/vendor/google.golang.org/grpc/codegen.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash - -# This script serves as an example to demonstrate how to generate the gRPC-Go -# interface and the related messages from .proto file. -# -# It assumes the installation of i) Google proto buffer compiler at -# https://github.com/google/protobuf (after v2.6.1) and ii) the Go codegen -# plugin at https://github.com/golang/protobuf (after 2015-02-20). If you have -# not, please install them first. -# -# We recommend running this script at $GOPATH/src. -# -# If this is not what you need, feel free to make your own scripts. Again, this -# script is for demonstration purpose. -# -proto=$1 -protoc --go_out=plugins=grpc:. $proto diff --git a/vendor/google.golang.org/grpc/codes/codes_test.go b/vendor/google.golang.org/grpc/codes/codes_test.go deleted file mode 100644 index d3e32d22..00000000 --- a/vendor/google.golang.org/grpc/codes/codes_test.go +++ /dev/null @@ -1,84 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package codes - -import ( - "encoding/json" - "reflect" - "testing" - - cpb "google.golang.org/genproto/googleapis/rpc/code" -) - -func TestUnmarshalJSON(t *testing.T) { - for s, v := range cpb.Code_value { - want := Code(v) - var got Code - if err := got.UnmarshalJSON([]byte(`"` + s + `"`)); err != nil || got != want { - t.Errorf("got.UnmarshalJSON(%q) = %v; want . got=%v; want %v", s, err, got, want) - } - } -} - -func TestJSONUnmarshal(t *testing.T) { - var got []Code - want := []Code{OK, NotFound, Internal, Canceled} - in := `["OK", "NOT_FOUND", "INTERNAL", "CANCELLED"]` - err := json.Unmarshal([]byte(in), &got) - if err != nil || !reflect.DeepEqual(got, want) { - t.Fatalf("json.Unmarshal(%q, &got) = %v; want . got=%v; want %v", in, err, got, want) - } -} - -func TestUnmarshalJSON_NilReceiver(t *testing.T) { - var got *Code - in := OK.String() - if err := got.UnmarshalJSON([]byte(in)); err == nil { - t.Errorf("got.UnmarshalJSON(%q) = nil; want . got=%v", in, got) - } -} - -func TestUnmarshalJSON_UnknownInput(t *testing.T) { - var got Code - for _, in := range [][]byte{[]byte(""), []byte("xxx"), []byte("Code(17)"), nil} { - if err := got.UnmarshalJSON([]byte(in)); err == nil { - t.Errorf("got.UnmarshalJSON(%q) = nil; want . got=%v", in, got) - } - } -} - -func TestUnmarshalJSON_MarshalUnmarshal(t *testing.T) { - for i := 0; i < _maxCode; i++ { - var cUnMarshaled Code - c := Code(i) - - cJSON, err := json.Marshal(c) - if err != nil { - t.Errorf("marshalling %q failed: %v", c, err) - } - - if err := json.Unmarshal(cJSON, &cUnMarshaled); err != nil { - t.Errorf("unmarshalling code failed: %s", err) - } - - if c != cUnMarshaled { - t.Errorf("code is %q after marshalling/unmarshalling, expected %q", cUnMarshaled, c) - } - } -} diff --git a/vendor/google.golang.org/grpc/credentials/credentials_test.go b/vendor/google.golang.org/grpc/credentials/credentials_test.go deleted file mode 100644 index cb091de0..00000000 --- a/vendor/google.golang.org/grpc/credentials/credentials_test.go +++ /dev/null @@ -1,206 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package credentials - -import ( - "context" - "crypto/tls" - "net" - "testing" - - "google.golang.org/grpc/testdata" -) - -func TestTLSOverrideServerName(t *testing.T) { - expectedServerName := "server.name" - c := NewTLS(nil) - c.OverrideServerName(expectedServerName) - if c.Info().ServerName != expectedServerName { - t.Fatalf("c.Info().ServerName = %v, want %v", c.Info().ServerName, expectedServerName) - } -} - -func TestTLSClone(t *testing.T) { - expectedServerName := "server.name" - c := NewTLS(nil) - c.OverrideServerName(expectedServerName) - cc := c.Clone() - if cc.Info().ServerName != expectedServerName { - t.Fatalf("cc.Info().ServerName = %v, want %v", cc.Info().ServerName, expectedServerName) - } - cc.OverrideServerName("") - if c.Info().ServerName != expectedServerName { - t.Fatalf("Change in clone should not affect the original, c.Info().ServerName = %v, want %v", c.Info().ServerName, expectedServerName) - } - -} - -type serverHandshake func(net.Conn) (AuthInfo, error) - -func TestClientHandshakeReturnsAuthInfo(t *testing.T) { - done := make(chan AuthInfo, 1) - lis := launchServer(t, tlsServerHandshake, done) - defer lis.Close() - lisAddr := lis.Addr().String() - clientAuthInfo := clientHandle(t, gRPCClientHandshake, lisAddr) - // wait until server sends serverAuthInfo or fails. - serverAuthInfo, ok := <-done - if !ok { - t.Fatalf("Error at server-side") - } - if !compare(clientAuthInfo, serverAuthInfo) { - t.Fatalf("c.ClientHandshake(_, %v, _) = %v, want %v.", lisAddr, clientAuthInfo, serverAuthInfo) - } -} - -func TestServerHandshakeReturnsAuthInfo(t *testing.T) { - done := make(chan AuthInfo, 1) - lis := launchServer(t, gRPCServerHandshake, done) - defer lis.Close() - clientAuthInfo := clientHandle(t, tlsClientHandshake, lis.Addr().String()) - // wait until server sends serverAuthInfo or fails. - serverAuthInfo, ok := <-done - if !ok { - t.Fatalf("Error at server-side") - } - if !compare(clientAuthInfo, serverAuthInfo) { - t.Fatalf("ServerHandshake(_) = %v, want %v.", serverAuthInfo, clientAuthInfo) - } -} - -func TestServerAndClientHandshake(t *testing.T) { - done := make(chan AuthInfo, 1) - lis := launchServer(t, gRPCServerHandshake, done) - defer lis.Close() - clientAuthInfo := clientHandle(t, gRPCClientHandshake, lis.Addr().String()) - // wait until server sends serverAuthInfo or fails. - serverAuthInfo, ok := <-done - if !ok { - t.Fatalf("Error at server-side") - } - if !compare(clientAuthInfo, serverAuthInfo) { - t.Fatalf("AuthInfo returned by server: %v and client: %v aren't same", serverAuthInfo, clientAuthInfo) - } -} - -func compare(a1, a2 AuthInfo) bool { - if a1.AuthType() != a2.AuthType() { - return false - } - switch a1.AuthType() { - case "tls": - state1 := a1.(TLSInfo).State - state2 := a2.(TLSInfo).State - if state1.Version == state2.Version && - state1.HandshakeComplete == state2.HandshakeComplete && - state1.CipherSuite == state2.CipherSuite && - state1.NegotiatedProtocol == state2.NegotiatedProtocol { - return true - } - return false - default: - return false - } -} - -func launchServer(t *testing.T, hs serverHandshake, done chan AuthInfo) net.Listener { - lis, err := net.Listen("tcp", "localhost:0") - if err != nil { - t.Fatalf("Failed to listen: %v", err) - } - go serverHandle(t, hs, done, lis) - return lis -} - -// Is run in a separate goroutine. -func serverHandle(t *testing.T, hs serverHandshake, done chan AuthInfo, lis net.Listener) { - serverRawConn, err := lis.Accept() - if err != nil { - t.Errorf("Server failed to accept connection: %v", err) - close(done) - return - } - serverAuthInfo, err := hs(serverRawConn) - if err != nil { - t.Errorf("Server failed while handshake. Error: %v", err) - serverRawConn.Close() - close(done) - return - } - done <- serverAuthInfo -} - -func clientHandle(t *testing.T, hs func(net.Conn, string) (AuthInfo, error), lisAddr string) AuthInfo { - conn, err := net.Dial("tcp", lisAddr) - if err != nil { - t.Fatalf("Client failed to connect to %s. Error: %v", lisAddr, err) - } - defer conn.Close() - clientAuthInfo, err := hs(conn, lisAddr) - if err != nil { - t.Fatalf("Error on client while handshake. Error: %v", err) - } - return clientAuthInfo -} - -// Server handshake implementation in gRPC. -func gRPCServerHandshake(conn net.Conn) (AuthInfo, error) { - serverTLS, err := NewServerTLSFromFile(testdata.Path("server1.pem"), testdata.Path("server1.key")) - if err != nil { - return nil, err - } - _, serverAuthInfo, err := serverTLS.ServerHandshake(conn) - if err != nil { - return nil, err - } - return serverAuthInfo, nil -} - -// Client handshake implementation in gRPC. -func gRPCClientHandshake(conn net.Conn, lisAddr string) (AuthInfo, error) { - clientTLS := NewTLS(&tls.Config{InsecureSkipVerify: true}) - _, authInfo, err := clientTLS.ClientHandshake(context.Background(), lisAddr, conn) - if err != nil { - return nil, err - } - return authInfo, nil -} - -func tlsServerHandshake(conn net.Conn) (AuthInfo, error) { - cert, err := tls.LoadX509KeyPair(testdata.Path("server1.pem"), testdata.Path("server1.key")) - if err != nil { - return nil, err - } - serverTLSConfig := &tls.Config{Certificates: []tls.Certificate{cert}} - serverConn := tls.Server(conn, serverTLSConfig) - err = serverConn.Handshake() - if err != nil { - return nil, err - } - return TLSInfo{State: serverConn.ConnectionState()}, nil -} - -func tlsClientHandshake(conn net.Conn, _ string) (AuthInfo, error) { - clientTLSConfig := &tls.Config{InsecureSkipVerify: true} - clientConn := tls.Client(conn, clientTLSConfig) - if err := clientConn.Handshake(); err != nil { - return nil, err - } - return TLSInfo{State: clientConn.ConnectionState()}, nil -} diff --git a/vendor/google.golang.org/grpc/credentials/internal/syscallconn_test.go b/vendor/google.golang.org/grpc/credentials/internal/syscallconn_test.go deleted file mode 100644 index 74567132..00000000 --- a/vendor/google.golang.org/grpc/credentials/internal/syscallconn_test.go +++ /dev/null @@ -1,64 +0,0 @@ -// +build !appengine - -/* - * - * Copyright 2018 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package internal_test - -import ( - "net" - "syscall" - "testing" - - "google.golang.org/grpc/credentials/internal" -) - -type syscallConn struct { - net.Conn -} - -func (*syscallConn) SyscallConn() (syscall.RawConn, error) { - return nil, nil -} - -type nonSyscallConn struct { - net.Conn -} - -func TestWrapSyscallConn(t *testing.T) { - sc := &syscallConn{} - nsc := &nonSyscallConn{} - - wrapConn := internal.WrapSyscallConn(sc, nsc) - if _, ok := wrapConn.(syscall.Conn); !ok { - t.Errorf("returned conn (type %T) doesn't implement syscall.Conn, want implement", wrapConn) - } -} - -func TestWrapSyscallConnNoWrap(t *testing.T) { - nscRaw := &nonSyscallConn{} - nsc := &nonSyscallConn{} - - wrapConn := internal.WrapSyscallConn(nscRaw, nsc) - if _, ok := wrapConn.(syscall.Conn); ok { - t.Errorf("returned conn (type %T) implements syscall.Conn, want not implement", wrapConn) - } - if wrapConn != nsc { - t.Errorf("returned conn is %p, want %p (the passed-in newConn)", wrapConn, nsc) - } -} diff --git a/vendor/google.golang.org/grpc/encoding/proto/proto_benchmark_test.go b/vendor/google.golang.org/grpc/encoding/proto/proto_benchmark_test.go deleted file mode 100644 index 7d481985..00000000 --- a/vendor/google.golang.org/grpc/encoding/proto/proto_benchmark_test.go +++ /dev/null @@ -1,98 +0,0 @@ -/* - * - * Copyright 2014 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package proto - -import ( - "fmt" - "testing" - - "github.com/golang/protobuf/proto" - "google.golang.org/grpc/encoding" - "google.golang.org/grpc/test/codec_perf" -) - -func setupBenchmarkProtoCodecInputs(payloadBaseSize uint32) []proto.Message { - payloadBase := make([]byte, payloadBaseSize) - // arbitrary byte slices - payloadSuffixes := [][]byte{ - []byte("one"), - []byte("two"), - []byte("three"), - []byte("four"), - []byte("five"), - } - protoStructs := make([]proto.Message, 0) - - for _, p := range payloadSuffixes { - ps := &codec_perf.Buffer{} - ps.Body = append(payloadBase, p...) - protoStructs = append(protoStructs, ps) - } - - return protoStructs -} - -// The possible use of certain protobuf APIs like the proto.Buffer API potentially involves caching -// on our side. This can add checks around memory allocations and possible contention. -// Example run: go test -v -run=^$ -bench=BenchmarkProtoCodec -benchmem -func BenchmarkProtoCodec(b *testing.B) { - // range of message sizes - payloadBaseSizes := make([]uint32, 0) - for i := uint32(0); i <= 12; i += 4 { - payloadBaseSizes = append(payloadBaseSizes, 1<", md, err) - } - if err := grpc.SetTrailer(ctx, testTrailerMetadata); err != nil { - return nil, status.Errorf(status.Code(err), "grpc.SetTrailer(_, %v) = %v, want ", testTrailerMetadata, err) - } - } - - if in.Id == errorID { - return nil, fmt.Errorf("got error id: %v", in.Id) - } - - return &testpb.SimpleResponse{Id: in.Id}, nil -} - -func (s *testServer) FullDuplexCall(stream testpb.TestService_FullDuplexCallServer) error { - md, ok := metadata.FromIncomingContext(stream.Context()) - if ok { - if err := stream.SendHeader(md); err != nil { - return status.Errorf(status.Code(err), "stream.SendHeader(%v) = %v, want %v", md, err, nil) - } - stream.SetTrailer(testTrailerMetadata) - } - for { - in, err := stream.Recv() - if err == io.EOF { - // read done. - return nil - } - if err != nil { - return err - } - - if in.Id == errorID { - return fmt.Errorf("got error id: %v", in.Id) - } - - if err := stream.Send(&testpb.SimpleResponse{Id: in.Id}); err != nil { - return err - } - } -} - -func (s *testServer) ClientStreamCall(stream testpb.TestService_ClientStreamCallServer) error { - md, ok := metadata.FromIncomingContext(stream.Context()) - if ok { - if err := stream.SendHeader(md); err != nil { - return status.Errorf(status.Code(err), "stream.SendHeader(%v) = %v, want %v", md, err, nil) - } - stream.SetTrailer(testTrailerMetadata) - } - for { - in, err := stream.Recv() - if err == io.EOF { - // read done. - return stream.SendAndClose(&testpb.SimpleResponse{Id: int32(0)}) - } - if err != nil { - return err - } - - if in.Id == errorID { - return fmt.Errorf("got error id: %v", in.Id) - } - } -} - -func (s *testServer) ServerStreamCall(in *testpb.SimpleRequest, stream testpb.TestService_ServerStreamCallServer) error { - md, ok := metadata.FromIncomingContext(stream.Context()) - if ok { - if err := stream.SendHeader(md); err != nil { - return status.Errorf(status.Code(err), "stream.SendHeader(%v) = %v, want %v", md, err, nil) - } - stream.SetTrailer(testTrailerMetadata) - } - - if in.Id == errorID { - return fmt.Errorf("got error id: %v", in.Id) - } - - for i := 0; i < 5; i++ { - if err := stream.Send(&testpb.SimpleResponse{Id: in.Id}); err != nil { - return err - } - } - return nil -} - -// test is an end-to-end test. It should be created with the newTest -// func, modified as needed, and then started with its startServer method. -// It should be cleaned up with the tearDown method. -type test struct { - t *testing.T - - testServer testpb.TestServiceServer // nil means none - // srv and srvAddr are set once startServer is called. - srv *grpc.Server - srvAddr string // Server IP without port. - srvIP net.IP - srvPort int - - cc *grpc.ClientConn // nil until requested via clientConn - - // Fields for client address. Set by the service handler. - clientAddrMu sync.Mutex - clientIP net.IP - clientPort int -} - -func (te *test) tearDown() { - if te.cc != nil { - te.cc.Close() - te.cc = nil - } - te.srv.Stop() -} - -type testConfig struct { -} - -// newTest returns a new test using the provided testing.T and -// environment. It is returned with default values. Tests should -// modify it before calling its startServer and clientConn methods. -func newTest(t *testing.T, tc *testConfig) *test { - te := &test{ - t: t, - } - return te -} - -type listenerWrapper struct { - net.Listener - te *test -} - -func (lw *listenerWrapper) Accept() (net.Conn, error) { - conn, err := lw.Listener.Accept() - if err != nil { - return nil, err - } - lw.te.clientAddrMu.Lock() - lw.te.clientIP = conn.RemoteAddr().(*net.TCPAddr).IP - lw.te.clientPort = conn.RemoteAddr().(*net.TCPAddr).Port - lw.te.clientAddrMu.Unlock() - return conn, nil -} - -// startServer starts a gRPC server listening. Callers should defer a -// call to te.tearDown to clean up. -func (te *test) startServer(ts testpb.TestServiceServer) { - te.testServer = ts - lis, err := net.Listen("tcp", "localhost:0") - - lis = &listenerWrapper{ - Listener: lis, - te: te, - } - - if err != nil { - te.t.Fatalf("Failed to listen: %v", err) - } - var opts []grpc.ServerOption - s := grpc.NewServer(opts...) - te.srv = s - if te.testServer != nil { - testpb.RegisterTestServiceServer(s, te.testServer) - } - - go s.Serve(lis) - te.srvAddr = lis.Addr().String() - te.srvIP = lis.Addr().(*net.TCPAddr).IP - te.srvPort = lis.Addr().(*net.TCPAddr).Port -} - -func (te *test) clientConn() *grpc.ClientConn { - if te.cc != nil { - return te.cc - } - opts := []grpc.DialOption{grpc.WithInsecure(), grpc.WithBlock()} - - var err error - te.cc, err = grpc.Dial(te.srvAddr, opts...) - if err != nil { - te.t.Fatalf("Dial(%q) = %v", te.srvAddr, err) - } - return te.cc -} - -type rpcType int - -const ( - unaryRPC rpcType = iota - clientStreamRPC - serverStreamRPC - fullDuplexStreamRPC - cancelRPC -) - -type rpcConfig struct { - count int // Number of requests and responses for streaming RPCs. - success bool // Whether the RPC should succeed or return error. - callType rpcType // Type of RPC. -} - -func (te *test) doUnaryCall(c *rpcConfig) (*testpb.SimpleRequest, *testpb.SimpleResponse, error) { - var ( - resp *testpb.SimpleResponse - req *testpb.SimpleRequest - err error - ) - tc := testpb.NewTestServiceClient(te.clientConn()) - if c.success { - req = &testpb.SimpleRequest{Id: errorID + 1} - } else { - req = &testpb.SimpleRequest{Id: errorID} - } - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - ctx = metadata.NewOutgoingContext(ctx, testMetadata) - - resp, err = tc.UnaryCall(ctx, req) - return req, resp, err -} - -func (te *test) doFullDuplexCallRoundtrip(c *rpcConfig) ([]*testpb.SimpleRequest, []*testpb.SimpleResponse, error) { - var ( - reqs []*testpb.SimpleRequest - resps []*testpb.SimpleResponse - err error - ) - tc := testpb.NewTestServiceClient(te.clientConn()) - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - ctx = metadata.NewOutgoingContext(ctx, testMetadata) - - stream, err := tc.FullDuplexCall(ctx) - if err != nil { - return reqs, resps, err - } - - if c.callType == cancelRPC { - cancel() - return reqs, resps, context.Canceled - } - - var startID int32 - if !c.success { - startID = errorID - } - for i := 0; i < c.count; i++ { - req := &testpb.SimpleRequest{ - Id: int32(i) + startID, - } - reqs = append(reqs, req) - if err = stream.Send(req); err != nil { - return reqs, resps, err - } - var resp *testpb.SimpleResponse - if resp, err = stream.Recv(); err != nil { - return reqs, resps, err - } - resps = append(resps, resp) - } - if err = stream.CloseSend(); err != nil && err != io.EOF { - return reqs, resps, err - } - if _, err = stream.Recv(); err != io.EOF { - return reqs, resps, err - } - - return reqs, resps, nil -} - -func (te *test) doClientStreamCall(c *rpcConfig) ([]*testpb.SimpleRequest, *testpb.SimpleResponse, error) { - var ( - reqs []*testpb.SimpleRequest - resp *testpb.SimpleResponse - err error - ) - tc := testpb.NewTestServiceClient(te.clientConn()) - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - ctx = metadata.NewOutgoingContext(ctx, testMetadata) - - stream, err := tc.ClientStreamCall(ctx) - if err != nil { - return reqs, resp, err - } - var startID int32 - if !c.success { - startID = errorID - } - for i := 0; i < c.count; i++ { - req := &testpb.SimpleRequest{ - Id: int32(i) + startID, - } - reqs = append(reqs, req) - if err = stream.Send(req); err != nil { - return reqs, resp, err - } - } - resp, err = stream.CloseAndRecv() - return reqs, resp, err -} - -func (te *test) doServerStreamCall(c *rpcConfig) (*testpb.SimpleRequest, []*testpb.SimpleResponse, error) { - var ( - req *testpb.SimpleRequest - resps []*testpb.SimpleResponse - err error - ) - - tc := testpb.NewTestServiceClient(te.clientConn()) - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - ctx = metadata.NewOutgoingContext(ctx, testMetadata) - - var startID int32 - if !c.success { - startID = errorID - } - req = &testpb.SimpleRequest{Id: startID} - stream, err := tc.ServerStreamCall(ctx, req) - if err != nil { - return req, resps, err - } - for { - var resp *testpb.SimpleResponse - resp, err := stream.Recv() - if err == io.EOF { - return req, resps, nil - } else if err != nil { - return req, resps, err - } - resps = append(resps, resp) - } -} - -type expectedData struct { - te *test - cc *rpcConfig - - method string - requests []*testpb.SimpleRequest - responses []*testpb.SimpleResponse - err error -} - -func (ed *expectedData) newClientHeaderEntry(client bool, rpcID, inRPCID uint64) *pb.GrpcLogEntry { - logger := pb.GrpcLogEntry_LOGGER_CLIENT - var peer *pb.Address - if !client { - logger = pb.GrpcLogEntry_LOGGER_SERVER - ed.te.clientAddrMu.Lock() - peer = &pb.Address{ - Address: ed.te.clientIP.String(), - IpPort: uint32(ed.te.clientPort), - } - if ed.te.clientIP.To4() != nil { - peer.Type = pb.Address_TYPE_IPV4 - } else { - peer.Type = pb.Address_TYPE_IPV6 - } - ed.te.clientAddrMu.Unlock() - } - return &pb.GrpcLogEntry{ - Timestamp: nil, - CallId: rpcID, - SequenceIdWithinCall: inRPCID, - Type: pb.GrpcLogEntry_EVENT_TYPE_CLIENT_HEADER, - Logger: logger, - Payload: &pb.GrpcLogEntry_ClientHeader{ - ClientHeader: &pb.ClientHeader{ - Metadata: binarylog.MdToMetadataProto(testMetadata), - MethodName: ed.method, - Authority: ed.te.srvAddr, - }, - }, - Peer: peer, - } -} - -func (ed *expectedData) newServerHeaderEntry(client bool, rpcID, inRPCID uint64) *pb.GrpcLogEntry { - logger := pb.GrpcLogEntry_LOGGER_SERVER - var peer *pb.Address - if client { - logger = pb.GrpcLogEntry_LOGGER_CLIENT - peer = &pb.Address{ - Address: ed.te.srvIP.String(), - IpPort: uint32(ed.te.srvPort), - } - if ed.te.srvIP.To4() != nil { - peer.Type = pb.Address_TYPE_IPV4 - } else { - peer.Type = pb.Address_TYPE_IPV6 - } - } - return &pb.GrpcLogEntry{ - Timestamp: nil, - CallId: rpcID, - SequenceIdWithinCall: inRPCID, - Type: pb.GrpcLogEntry_EVENT_TYPE_SERVER_HEADER, - Logger: logger, - Payload: &pb.GrpcLogEntry_ServerHeader{ - ServerHeader: &pb.ServerHeader{ - Metadata: binarylog.MdToMetadataProto(testMetadata), - }, - }, - Peer: peer, - } -} - -func (ed *expectedData) newClientMessageEntry(client bool, rpcID, inRPCID uint64, msg *testpb.SimpleRequest) *pb.GrpcLogEntry { - logger := pb.GrpcLogEntry_LOGGER_CLIENT - if !client { - logger = pb.GrpcLogEntry_LOGGER_SERVER - } - data, err := proto.Marshal(msg) - if err != nil { - grpclog.Infof("binarylogging_testing: failed to marshal proto message: %v", err) - } - return &pb.GrpcLogEntry{ - Timestamp: nil, - CallId: rpcID, - SequenceIdWithinCall: inRPCID, - Type: pb.GrpcLogEntry_EVENT_TYPE_CLIENT_MESSAGE, - Logger: logger, - Payload: &pb.GrpcLogEntry_Message{ - Message: &pb.Message{ - Length: uint32(len(data)), - Data: data, - }, - }, - } -} - -func (ed *expectedData) newServerMessageEntry(client bool, rpcID, inRPCID uint64, msg *testpb.SimpleResponse) *pb.GrpcLogEntry { - logger := pb.GrpcLogEntry_LOGGER_CLIENT - if !client { - logger = pb.GrpcLogEntry_LOGGER_SERVER - } - data, err := proto.Marshal(msg) - if err != nil { - grpclog.Infof("binarylogging_testing: failed to marshal proto message: %v", err) - } - return &pb.GrpcLogEntry{ - Timestamp: nil, - CallId: rpcID, - SequenceIdWithinCall: inRPCID, - Type: pb.GrpcLogEntry_EVENT_TYPE_SERVER_MESSAGE, - Logger: logger, - Payload: &pb.GrpcLogEntry_Message{ - Message: &pb.Message{ - Length: uint32(len(data)), - Data: data, - }, - }, - } -} - -func (ed *expectedData) newHalfCloseEntry(client bool, rpcID, inRPCID uint64) *pb.GrpcLogEntry { - logger := pb.GrpcLogEntry_LOGGER_CLIENT - if !client { - logger = pb.GrpcLogEntry_LOGGER_SERVER - } - return &pb.GrpcLogEntry{ - Timestamp: nil, - CallId: rpcID, - SequenceIdWithinCall: inRPCID, - Type: pb.GrpcLogEntry_EVENT_TYPE_CLIENT_HALF_CLOSE, - Payload: nil, // No payload here. - Logger: logger, - } -} - -func (ed *expectedData) newServerTrailerEntry(client bool, rpcID, inRPCID uint64, stErr error) *pb.GrpcLogEntry { - logger := pb.GrpcLogEntry_LOGGER_SERVER - var peer *pb.Address - if client { - logger = pb.GrpcLogEntry_LOGGER_CLIENT - peer = &pb.Address{ - Address: ed.te.srvIP.String(), - IpPort: uint32(ed.te.srvPort), - } - if ed.te.srvIP.To4() != nil { - peer.Type = pb.Address_TYPE_IPV4 - } else { - peer.Type = pb.Address_TYPE_IPV6 - } - } - st, ok := status.FromError(stErr) - if !ok { - grpclog.Info("binarylogging: error in trailer is not a status error") - } - stProto := st.Proto() - var ( - detailsBytes []byte - err error - ) - if stProto != nil && len(stProto.Details) != 0 { - detailsBytes, err = proto.Marshal(stProto) - if err != nil { - grpclog.Infof("binarylogging: failed to marshal status proto: %v", err) - } - } - return &pb.GrpcLogEntry{ - Timestamp: nil, - CallId: rpcID, - SequenceIdWithinCall: inRPCID, - Type: pb.GrpcLogEntry_EVENT_TYPE_SERVER_TRAILER, - Logger: logger, - Payload: &pb.GrpcLogEntry_Trailer{ - Trailer: &pb.Trailer{ - Metadata: binarylog.MdToMetadataProto(testTrailerMetadata), - // st will be nil if err was not a status error, but nil is ok. - StatusCode: uint32(st.Code()), - StatusMessage: st.Message(), - StatusDetails: detailsBytes, - }, - }, - Peer: peer, - } -} - -func (ed *expectedData) newCancelEntry(rpcID, inRPCID uint64) *pb.GrpcLogEntry { - return &pb.GrpcLogEntry{ - Timestamp: nil, - CallId: rpcID, - SequenceIdWithinCall: inRPCID, - Type: pb.GrpcLogEntry_EVENT_TYPE_CANCEL, - Logger: pb.GrpcLogEntry_LOGGER_CLIENT, - Payload: nil, - } -} - -func (ed *expectedData) toClientLogEntries() []*pb.GrpcLogEntry { - var ( - ret []*pb.GrpcLogEntry - idInRPC uint64 = 1 - ) - ret = append(ret, ed.newClientHeaderEntry(true, globalRPCID, idInRPC)) - idInRPC++ - - switch ed.cc.callType { - case unaryRPC, fullDuplexStreamRPC: - for i := 0; i < len(ed.requests); i++ { - ret = append(ret, ed.newClientMessageEntry(true, globalRPCID, idInRPC, ed.requests[i])) - idInRPC++ - if i == 0 { - // First message, append ServerHeader. - ret = append(ret, ed.newServerHeaderEntry(true, globalRPCID, idInRPC)) - idInRPC++ - } - if !ed.cc.success { - // There is no response in the RPC error case. - continue - } - ret = append(ret, ed.newServerMessageEntry(true, globalRPCID, idInRPC, ed.responses[i])) - idInRPC++ - } - if ed.cc.success && ed.cc.callType == fullDuplexStreamRPC { - ret = append(ret, ed.newHalfCloseEntry(true, globalRPCID, idInRPC)) - idInRPC++ - } - case clientStreamRPC, serverStreamRPC: - for i := 0; i < len(ed.requests); i++ { - ret = append(ret, ed.newClientMessageEntry(true, globalRPCID, idInRPC, ed.requests[i])) - idInRPC++ - } - if ed.cc.callType == clientStreamRPC { - ret = append(ret, ed.newHalfCloseEntry(true, globalRPCID, idInRPC)) - idInRPC++ - } - ret = append(ret, ed.newServerHeaderEntry(true, globalRPCID, idInRPC)) - idInRPC++ - if ed.cc.success { - for i := 0; i < len(ed.responses); i++ { - ret = append(ret, ed.newServerMessageEntry(true, globalRPCID, idInRPC, ed.responses[0])) - idInRPC++ - } - } - } - - if ed.cc.callType == cancelRPC { - ret = append(ret, ed.newCancelEntry(globalRPCID, idInRPC)) - idInRPC++ - } else { - ret = append(ret, ed.newServerTrailerEntry(true, globalRPCID, idInRPC, ed.err)) - idInRPC++ - } - return ret -} - -func (ed *expectedData) toServerLogEntries() []*pb.GrpcLogEntry { - var ( - ret []*pb.GrpcLogEntry - idInRPC uint64 = 1 - ) - ret = append(ret, ed.newClientHeaderEntry(false, globalRPCID, idInRPC)) - idInRPC++ - - switch ed.cc.callType { - case unaryRPC: - ret = append(ret, ed.newClientMessageEntry(false, globalRPCID, idInRPC, ed.requests[0])) - idInRPC++ - ret = append(ret, ed.newServerHeaderEntry(false, globalRPCID, idInRPC)) - idInRPC++ - if ed.cc.success { - ret = append(ret, ed.newServerMessageEntry(false, globalRPCID, idInRPC, ed.responses[0])) - idInRPC++ - } - case fullDuplexStreamRPC: - ret = append(ret, ed.newServerHeaderEntry(false, globalRPCID, idInRPC)) - idInRPC++ - for i := 0; i < len(ed.requests); i++ { - ret = append(ret, ed.newClientMessageEntry(false, globalRPCID, idInRPC, ed.requests[i])) - idInRPC++ - if !ed.cc.success { - // There is no response in the RPC error case. - continue - } - ret = append(ret, ed.newServerMessageEntry(false, globalRPCID, idInRPC, ed.responses[i])) - idInRPC++ - } - - if ed.cc.success && ed.cc.callType == fullDuplexStreamRPC { - ret = append(ret, ed.newHalfCloseEntry(false, globalRPCID, idInRPC)) - idInRPC++ - } - case clientStreamRPC: - ret = append(ret, ed.newServerHeaderEntry(false, globalRPCID, idInRPC)) - idInRPC++ - for i := 0; i < len(ed.requests); i++ { - ret = append(ret, ed.newClientMessageEntry(false, globalRPCID, idInRPC, ed.requests[i])) - idInRPC++ - } - if ed.cc.success { - ret = append(ret, ed.newHalfCloseEntry(false, globalRPCID, idInRPC)) - idInRPC++ - ret = append(ret, ed.newServerMessageEntry(false, globalRPCID, idInRPC, ed.responses[0])) - idInRPC++ - } - case serverStreamRPC: - ret = append(ret, ed.newClientMessageEntry(false, globalRPCID, idInRPC, ed.requests[0])) - idInRPC++ - ret = append(ret, ed.newServerHeaderEntry(false, globalRPCID, idInRPC)) - idInRPC++ - for i := 0; i < len(ed.responses); i++ { - ret = append(ret, ed.newServerMessageEntry(false, globalRPCID, idInRPC, ed.responses[0])) - idInRPC++ - } - } - - ret = append(ret, ed.newServerTrailerEntry(false, globalRPCID, idInRPC, ed.err)) - idInRPC++ - - return ret -} - -func runRPCs(t *testing.T, tc *testConfig, cc *rpcConfig) *expectedData { - te := newTest(t, tc) - te.startServer(&testServer{te: te}) - defer te.tearDown() - - expect := &expectedData{ - te: te, - cc: cc, - } - - switch cc.callType { - case unaryRPC: - expect.method = "/grpc.testing.TestService/UnaryCall" - req, resp, err := te.doUnaryCall(cc) - expect.requests = []*testpb.SimpleRequest{req} - expect.responses = []*testpb.SimpleResponse{resp} - expect.err = err - case clientStreamRPC: - expect.method = "/grpc.testing.TestService/ClientStreamCall" - reqs, resp, err := te.doClientStreamCall(cc) - expect.requests = reqs - expect.responses = []*testpb.SimpleResponse{resp} - expect.err = err - case serverStreamRPC: - expect.method = "/grpc.testing.TestService/ServerStreamCall" - req, resps, err := te.doServerStreamCall(cc) - expect.responses = resps - expect.requests = []*testpb.SimpleRequest{req} - expect.err = err - case fullDuplexStreamRPC, cancelRPC: - expect.method = "/grpc.testing.TestService/FullDuplexCall" - expect.requests, expect.responses, expect.err = te.doFullDuplexCallRoundtrip(cc) - } - if cc.success != (expect.err == nil) { - t.Fatalf("cc.success: %v, got error: %v", cc.success, expect.err) - } - te.cc.Close() - te.srv.GracefulStop() // Wait for the server to stop. - - return expect -} - -// equalLogEntry sorts the metadata entries by key (to compare metadata). -// -// This function is typically called with only two entries. It's written in this -// way so the code can be put in a for loop instead of copied twice. -func equalLogEntry(entries ...*pb.GrpcLogEntry) (equal bool) { - for i, e := range entries { - // Clear out some fields we don't compare. - e.Timestamp = nil - e.CallId = 0 // CallID is global to the binary, hard to compare. - if h := e.GetClientHeader(); h != nil { - h.Timeout = nil - tmp := h.Metadata.Entry[:0] - for _, e := range h.Metadata.Entry { - tmp = append(tmp, e) - } - h.Metadata.Entry = tmp - sort.Slice(h.Metadata.Entry, func(i, j int) bool { return h.Metadata.Entry[i].Key < h.Metadata.Entry[j].Key }) - } - if h := e.GetServerHeader(); h != nil { - tmp := h.Metadata.Entry[:0] - for _, e := range h.Metadata.Entry { - tmp = append(tmp, e) - } - h.Metadata.Entry = tmp - sort.Slice(h.Metadata.Entry, func(i, j int) bool { return h.Metadata.Entry[i].Key < h.Metadata.Entry[j].Key }) - } - if h := e.GetTrailer(); h != nil { - sort.Slice(h.Metadata.Entry, func(i, j int) bool { return h.Metadata.Entry[i].Key < h.Metadata.Entry[j].Key }) - } - - if i > 0 && !proto.Equal(e, entries[i-1]) { - return false - } - } - return true -} - -func testClientBinaryLog(t *testing.T, c *rpcConfig) error { - defer testSink.clear() - expect := runRPCs(t, &testConfig{}, c) - want := expect.toClientLogEntries() - var got []*pb.GrpcLogEntry - // In racy cases, some entries are not logged when the RPC is finished (e.g. - // context.Cancel). - // - // Check 10 times, with a sleep of 1/100 seconds between each check. Makes - // it an 1-second wait in total. - for i := 0; i < 10; i++ { - got = testSink.logEntries(true) // all client entries. - if len(want) == len(got) { - break - } - time.Sleep(100 * time.Millisecond) - } - if len(want) != len(got) { - for i, e := range want { - t.Errorf("in want: %d, %s", i, e.GetType()) - } - for i, e := range got { - t.Errorf("in got: %d, %s", i, e.GetType()) - } - return fmt.Errorf("didn't get same amount of log entries, want: %d, got: %d", len(want), len(got)) - } - var errored bool - for i := 0; i < len(got); i++ { - if !equalLogEntry(want[i], got[i]) { - t.Errorf("entry: %d, want %+v, got %+v", i, want[i], got[i]) - errored = true - } - } - if errored { - return fmt.Errorf("test failed") - } - return nil -} - -func TestClientBinaryLogUnaryRPC(t *testing.T) { - if err := testClientBinaryLog(t, &rpcConfig{success: true, callType: unaryRPC}); err != nil { - t.Fatal(err) - } -} - -func TestClientBinaryLogUnaryRPCError(t *testing.T) { - if err := testClientBinaryLog(t, &rpcConfig{success: false, callType: unaryRPC}); err != nil { - t.Fatal(err) - } -} - -func TestClientBinaryLogClientStreamRPC(t *testing.T) { - count := 5 - if err := testClientBinaryLog(t, &rpcConfig{count: count, success: true, callType: clientStreamRPC}); err != nil { - t.Fatal(err) - } -} - -func TestClientBinaryLogClientStreamRPCError(t *testing.T) { - count := 1 - if err := testClientBinaryLog(t, &rpcConfig{count: count, success: false, callType: clientStreamRPC}); err != nil { - t.Fatal(err) - } -} - -func TestClientBinaryLogServerStreamRPC(t *testing.T) { - count := 5 - if err := testClientBinaryLog(t, &rpcConfig{count: count, success: true, callType: serverStreamRPC}); err != nil { - t.Fatal(err) - } -} - -func TestClientBinaryLogServerStreamRPCError(t *testing.T) { - count := 5 - if err := testClientBinaryLog(t, &rpcConfig{count: count, success: false, callType: serverStreamRPC}); err != nil { - t.Fatal(err) - } -} - -func TestClientBinaryLogFullDuplexRPC(t *testing.T) { - count := 5 - if err := testClientBinaryLog(t, &rpcConfig{count: count, success: true, callType: fullDuplexStreamRPC}); err != nil { - t.Fatal(err) - } -} - -func TestClientBinaryLogFullDuplexRPCError(t *testing.T) { - count := 5 - if err := testClientBinaryLog(t, &rpcConfig{count: count, success: false, callType: fullDuplexStreamRPC}); err != nil { - t.Fatal(err) - } -} - -func TestClientBinaryLogCancel(t *testing.T) { - count := 5 - if err := testClientBinaryLog(t, &rpcConfig{count: count, success: false, callType: cancelRPC}); err != nil { - t.Fatal(err) - } -} - -func testServerBinaryLog(t *testing.T, c *rpcConfig) error { - defer testSink.clear() - expect := runRPCs(t, &testConfig{}, c) - want := expect.toServerLogEntries() - var got []*pb.GrpcLogEntry - // In racy cases, some entries are not logged when the RPC is finished (e.g. - // context.Cancel). This is unlikely to happen on server side, but it does - // no harm to retry. - // - // Check 10 times, with a sleep of 1/100 seconds between each check. Makes - // it an 1-second wait in total. - for i := 0; i < 10; i++ { - got = testSink.logEntries(false) // all server entries. - if len(want) == len(got) { - break - } - time.Sleep(100 * time.Millisecond) - } - - if len(want) != len(got) { - for i, e := range want { - t.Errorf("in want: %d, %s", i, e.GetType()) - } - for i, e := range got { - t.Errorf("in got: %d, %s", i, e.GetType()) - } - return fmt.Errorf("didn't get same amount of log entries, want: %d, got: %d", len(want), len(got)) - } - var errored bool - for i := 0; i < len(got); i++ { - if !equalLogEntry(want[i], got[i]) { - t.Errorf("entry: %d, want %+v, got %+v", i, want[i], got[i]) - errored = true - } - } - if errored { - return fmt.Errorf("test failed") - } - return nil -} - -func TestServerBinaryLogUnaryRPC(t *testing.T) { - if err := testServerBinaryLog(t, &rpcConfig{success: true, callType: unaryRPC}); err != nil { - t.Fatal(err) - } -} - -func TestServerBinaryLogUnaryRPCError(t *testing.T) { - if err := testServerBinaryLog(t, &rpcConfig{success: false, callType: unaryRPC}); err != nil { - t.Fatal(err) - } -} - -func TestServerBinaryLogClientStreamRPC(t *testing.T) { - count := 5 - if err := testServerBinaryLog(t, &rpcConfig{count: count, success: true, callType: clientStreamRPC}); err != nil { - t.Fatal(err) - } -} - -func TestServerBinaryLogClientStreamRPCError(t *testing.T) { - count := 1 - if err := testServerBinaryLog(t, &rpcConfig{count: count, success: false, callType: clientStreamRPC}); err != nil { - t.Fatal(err) - } -} - -func TestServerBinaryLogServerStreamRPC(t *testing.T) { - count := 5 - if err := testServerBinaryLog(t, &rpcConfig{count: count, success: true, callType: serverStreamRPC}); err != nil { - t.Fatal(err) - } -} - -func TestServerBinaryLogServerStreamRPCError(t *testing.T) { - count := 5 - if err := testServerBinaryLog(t, &rpcConfig{count: count, success: false, callType: serverStreamRPC}); err != nil { - t.Fatal(err) - } -} - -func TestServerBinaryLogFullDuplex(t *testing.T) { - count := 5 - if err := testServerBinaryLog(t, &rpcConfig{count: count, success: true, callType: fullDuplexStreamRPC}); err != nil { - t.Fatal(err) - } -} - -func TestServerBinaryLogFullDuplexError(t *testing.T) { - count := 5 - if err := testServerBinaryLog(t, &rpcConfig{count: count, success: false, callType: fullDuplexStreamRPC}); err != nil { - t.Fatal(err) - } -} diff --git a/vendor/google.golang.org/grpc/internal/binarylog/binarylog_test.go b/vendor/google.golang.org/grpc/internal/binarylog/binarylog_test.go deleted file mode 100644 index 62500a8d..00000000 --- a/vendor/google.golang.org/grpc/internal/binarylog/binarylog_test.go +++ /dev/null @@ -1,147 +0,0 @@ -/* - * - * Copyright 2018 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package binarylog - -import ( - "testing" -) - -// Test that get method logger returns the one with the most exact match. -func TestGetMethodLogger(t *testing.T) { - testCases := []struct { - in string - method string - hdr, msg uint64 - }{ - // Global. - { - in: "*{h:12;m:23}", - method: "/s/m", - hdr: 12, msg: 23, - }, - // service/*. - { - in: "*,s/*{h:12;m:23}", - method: "/s/m", - hdr: 12, msg: 23, - }, - // Service/method. - { - in: "*{h;m},s/m{h:12;m:23}", - method: "/s/m", - hdr: 12, msg: 23, - }, - { - in: "*{h;m},s/*{h:314;m},s/m{h:12;m:23}", - method: "/s/m", - hdr: 12, msg: 23, - }, - { - in: "*{h;m},s/*{h:12;m:23},s/m", - method: "/s/m", - hdr: maxUInt, msg: maxUInt, - }, - - // service/*. - { - in: "*{h;m},s/*{h:12;m:23},s/m1", - method: "/s/m", - hdr: 12, msg: 23, - }, - { - in: "*{h;m},s1/*,s/m{h:12;m:23}", - method: "/s/m", - hdr: 12, msg: 23, - }, - - // With black list. - { - in: "*{h:12;m:23},-s/m1", - method: "/s/m", - hdr: 12, msg: 23, - }, - } - for _, tc := range testCases { - l := NewLoggerFromConfigString(tc.in) - if l == nil { - t.Errorf("in: %q, failed to create logger from config string", tc.in) - continue - } - ml := l.getMethodLogger(tc.method) - if ml == nil { - t.Errorf("in: %q, method logger is nil, want non-nil", tc.in) - continue - } - - if ml.headerMaxLen != tc.hdr || ml.messageMaxLen != tc.msg { - t.Errorf("in: %q, want header: %v, message: %v, got header: %v, message: %v", tc.in, tc.hdr, tc.msg, ml.headerMaxLen, ml.messageMaxLen) - } - } -} - -// expect method logger to be nil -func TestGetMethodLoggerOff(t *testing.T) { - testCases := []struct { - in string - method string - }{ - // method not specified. - { - in: "s1/m", - method: "/s/m", - }, - { - in: "s/m1", - method: "/s/m", - }, - { - in: "s1/*", - method: "/s/m", - }, - { - in: "s1/*,s/m1", - method: "/s/m", - }, - - // blacklisted. - { - in: "*,-s/m", - method: "/s/m", - }, - { - in: "s/*,-s/m", - method: "/s/m", - }, - { - in: "-s/m,s/*", - method: "/s/m", - }, - } - for _, tc := range testCases { - l := NewLoggerFromConfigString(tc.in) - if l == nil { - t.Errorf("in: %q, failed to create logger from config string", tc.in) - continue - } - ml := l.getMethodLogger(tc.method) - if ml != nil { - t.Errorf("in: %q, method logger is non-nil, want nil", tc.in) - } - } -} diff --git a/vendor/google.golang.org/grpc/internal/binarylog/env_config_test.go b/vendor/google.golang.org/grpc/internal/binarylog/env_config_test.go deleted file mode 100644 index aced5d55..00000000 --- a/vendor/google.golang.org/grpc/internal/binarylog/env_config_test.go +++ /dev/null @@ -1,478 +0,0 @@ -/* - * - * Copyright 2018 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package binarylog - -import ( - "fmt" - "testing" -) - -// This tests that when multiple configs are specified, all methods loggers will -// be set correctly. Correctness of each logger is covered by other unit tests. -func TestNewLoggerFromConfigString(t *testing.T) { - const ( - s1 = "s1" - m1 = "m1" - m2 = "m2" - fullM1 = s1 + "/" + m1 - fullM2 = s1 + "/" + m2 - ) - c := fmt.Sprintf("*{h:1;m:2},%s{h},%s{m},%s{h;m}", s1+"/*", fullM1, fullM2) - l := NewLoggerFromConfigString(c).(*logger) - - if l.all.hdr != 1 || l.all.msg != 2 { - t.Errorf("l.all = %#v, want headerLen: 1, messageLen: 2", l.all) - } - - if ml, ok := l.services[s1]; ok { - if ml.hdr != maxUInt || ml.msg != 0 { - t.Errorf("want maxUInt header, 0 message, got header: %v, message: %v", ml.hdr, ml.msg) - } - } else { - t.Errorf("service/* is not set") - } - - if ml, ok := l.methods[fullM1]; ok { - if ml.hdr != 0 || ml.msg != maxUInt { - t.Errorf("want 0 header, maxUInt message, got header: %v, message: %v", ml.hdr, ml.msg) - } - } else { - t.Errorf("service/method{h} is not set") - } - - if ml, ok := l.methods[fullM2]; ok { - if ml.hdr != maxUInt || ml.msg != maxUInt { - t.Errorf("want maxUInt header, maxUInt message, got header: %v, message: %v", ml.hdr, ml.msg) - } - } else { - t.Errorf("service/method{h;m} is not set") - } -} - -func TestNewLoggerFromConfigStringInvalid(t *testing.T) { - testCases := []string{ - "", - "*{}", - "s/m,*{}", - "s/m,s/m{a}", - - // Duplciate rules. - "s/m,-s/m", - "-s/m,s/m", - "s/m,s/m", - "s/m,s/m{h:1;m:1}", - "s/m{h:1;m:1},s/m", - "-s/m,-s/m", - "s/*,s/*{h:1;m:1}", - "*,*{h:1;m:1}", - } - for _, tc := range testCases { - l := NewLoggerFromConfigString(tc) - if l != nil { - t.Errorf("With config %q, want logger %v, got %v", tc, nil, l) - } - } -} - -func TestParseMethodConfigAndSuffix(t *testing.T) { - testCases := []struct { - in, service, method, suffix string - }{ - { - in: "p.s/m", - service: "p.s", method: "m", suffix: "", - }, - { - in: "p.s/m{h,m}", - service: "p.s", method: "m", suffix: "{h,m}", - }, - { - in: "p.s/*", - service: "p.s", method: "*", suffix: "", - }, - { - in: "p.s/*{h,m}", - service: "p.s", method: "*", suffix: "{h,m}", - }, - - // invalid suffix will be detected by another function. - { - in: "p.s/m{invalidsuffix}", - service: "p.s", method: "m", suffix: "{invalidsuffix}", - }, - { - in: "p.s/*{invalidsuffix}", - service: "p.s", method: "*", suffix: "{invalidsuffix}", - }, - { - in: "s/m*", - service: "s", method: "m", suffix: "*", - }, - { - in: "s/*m", - service: "s", method: "*", suffix: "m", - }, - { - in: "s/**", - service: "s", method: "*", suffix: "*", - }, - } - for _, tc := range testCases { - t.Logf("testing parseMethodConfigAndSuffix(%q)", tc.in) - s, m, suffix, err := parseMethodConfigAndSuffix(tc.in) - if err != nil { - t.Errorf("returned error %v, want nil", err) - continue - } - if s != tc.service { - t.Errorf("service = %q, want %q", s, tc.service) - } - if m != tc.method { - t.Errorf("method = %q, want %q", m, tc.method) - } - if suffix != tc.suffix { - t.Errorf("suffix = %q, want %q", suffix, tc.suffix) - } - } -} - -func TestParseMethodConfigAndSuffixInvalid(t *testing.T) { - testCases := []string{ - "*/m", - "*/m{}", - } - for _, tc := range testCases { - s, m, suffix, err := parseMethodConfigAndSuffix(tc) - if err == nil { - t.Errorf("Parsing %q got nil error with %q, %q, %q, want non-nil error", tc, s, m, suffix) - } - } -} - -func TestParseHeaderMessageLengthConfig(t *testing.T) { - testCases := []struct { - in string - hdr, msg uint64 - }{ - { - in: "", - hdr: maxUInt, msg: maxUInt, - }, - { - in: "{h}", - hdr: maxUInt, msg: 0, - }, - { - in: "{h:314}", - hdr: 314, msg: 0, - }, - { - in: "{m}", - hdr: 0, msg: maxUInt, - }, - { - in: "{m:213}", - hdr: 0, msg: 213, - }, - { - in: "{h;m}", - hdr: maxUInt, msg: maxUInt, - }, - { - in: "{h:314;m}", - hdr: 314, msg: maxUInt, - }, - { - in: "{h;m:213}", - hdr: maxUInt, msg: 213, - }, - { - in: "{h:314;m:213}", - hdr: 314, msg: 213, - }, - } - for _, tc := range testCases { - t.Logf("testing parseHeaderMessageLengthConfig(%q)", tc.in) - hdr, msg, err := parseHeaderMessageLengthConfig(tc.in) - if err != nil { - t.Errorf("returned error %v, want nil", err) - continue - } - if hdr != tc.hdr { - t.Errorf("header length = %v, want %v", hdr, tc.hdr) - } - if msg != tc.msg { - t.Errorf("message length = %v, want %v", msg, tc.msg) - } - } -} -func TestParseHeaderMessageLengthConfigInvalid(t *testing.T) { - testCases := []string{ - "{}", - "{h;a}", - "{h;m;b}", - } - for _, tc := range testCases { - _, _, err := parseHeaderMessageLengthConfig(tc) - if err == nil { - t.Errorf("Parsing %q got nil error, want non-nil error", tc) - } - } -} - -func TestFillMethodLoggerWithConfigStringBlacklist(t *testing.T) { - testCases := []string{ - "p.s/m", - "service/method", - } - for _, tc := range testCases { - c := "-" + tc - t.Logf("testing fillMethodLoggerWithConfigString(%q)", c) - l := newEmptyLogger() - if err := l.fillMethodLoggerWithConfigString(c); err != nil { - t.Errorf("returned err %v, want nil", err) - continue - } - _, ok := l.blacklist[tc] - if !ok { - t.Errorf("blacklist[%q] is not set", tc) - } - } -} - -func TestFillMethodLoggerWithConfigStringGlobal(t *testing.T) { - testCases := []struct { - in string - hdr, msg uint64 - }{ - { - in: "", - hdr: maxUInt, msg: maxUInt, - }, - { - in: "{h}", - hdr: maxUInt, msg: 0, - }, - { - in: "{h:314}", - hdr: 314, msg: 0, - }, - { - in: "{m}", - hdr: 0, msg: maxUInt, - }, - { - in: "{m:213}", - hdr: 0, msg: 213, - }, - { - in: "{h;m}", - hdr: maxUInt, msg: maxUInt, - }, - { - in: "{h:314;m}", - hdr: 314, msg: maxUInt, - }, - { - in: "{h;m:213}", - hdr: maxUInt, msg: 213, - }, - { - in: "{h:314;m:213}", - hdr: 314, msg: 213, - }, - } - for _, tc := range testCases { - c := "*" + tc.in - t.Logf("testing fillMethodLoggerWithConfigString(%q)", c) - l := newEmptyLogger() - if err := l.fillMethodLoggerWithConfigString(c); err != nil { - t.Errorf("returned err %v, want nil", err) - continue - } - if l.all == nil { - t.Errorf("l.all is not set") - continue - } - if hdr := l.all.hdr; hdr != tc.hdr { - t.Errorf("header length = %v, want %v", hdr, tc.hdr) - - } - if msg := l.all.msg; msg != tc.msg { - t.Errorf("message length = %v, want %v", msg, tc.msg) - } - } -} - -func TestFillMethodLoggerWithConfigStringPerService(t *testing.T) { - testCases := []struct { - in string - hdr, msg uint64 - }{ - { - in: "", - hdr: maxUInt, msg: maxUInt, - }, - { - in: "{h}", - hdr: maxUInt, msg: 0, - }, - { - in: "{h:314}", - hdr: 314, msg: 0, - }, - { - in: "{m}", - hdr: 0, msg: maxUInt, - }, - { - in: "{m:213}", - hdr: 0, msg: 213, - }, - { - in: "{h;m}", - hdr: maxUInt, msg: maxUInt, - }, - { - in: "{h:314;m}", - hdr: 314, msg: maxUInt, - }, - { - in: "{h;m:213}", - hdr: maxUInt, msg: 213, - }, - { - in: "{h:314;m:213}", - hdr: 314, msg: 213, - }, - } - const serviceName = "service" - for _, tc := range testCases { - c := serviceName + "/*" + tc.in - t.Logf("testing fillMethodLoggerWithConfigString(%q)", c) - l := newEmptyLogger() - if err := l.fillMethodLoggerWithConfigString(c); err != nil { - t.Errorf("returned err %v, want nil", err) - continue - } - ml, ok := l.services[serviceName] - if !ok { - t.Errorf("l.service[%q] is not set", serviceName) - continue - } - if hdr := ml.hdr; hdr != tc.hdr { - t.Errorf("header length = %v, want %v", hdr, tc.hdr) - - } - if msg := ml.msg; msg != tc.msg { - t.Errorf("message length = %v, want %v", msg, tc.msg) - } - } -} - -func TestFillMethodLoggerWithConfigStringPerMethod(t *testing.T) { - testCases := []struct { - in string - hdr, msg uint64 - }{ - { - in: "", - hdr: maxUInt, msg: maxUInt, - }, - { - in: "{h}", - hdr: maxUInt, msg: 0, - }, - { - in: "{h:314}", - hdr: 314, msg: 0, - }, - { - in: "{m}", - hdr: 0, msg: maxUInt, - }, - { - in: "{m:213}", - hdr: 0, msg: 213, - }, - { - in: "{h;m}", - hdr: maxUInt, msg: maxUInt, - }, - { - in: "{h:314;m}", - hdr: 314, msg: maxUInt, - }, - { - in: "{h;m:213}", - hdr: maxUInt, msg: 213, - }, - { - in: "{h:314;m:213}", - hdr: 314, msg: 213, - }, - } - const ( - serviceName = "service" - methodName = "method" - fullMethodName = serviceName + "/" + methodName - ) - for _, tc := range testCases { - c := fullMethodName + tc.in - t.Logf("testing fillMethodLoggerWithConfigString(%q)", c) - l := newEmptyLogger() - if err := l.fillMethodLoggerWithConfigString(c); err != nil { - t.Errorf("returned err %v, want nil", err) - continue - } - ml, ok := l.methods[fullMethodName] - if !ok { - t.Errorf("l.methods[%q] is not set", fullMethodName) - continue - } - if hdr := ml.hdr; hdr != tc.hdr { - t.Errorf("header length = %v, want %v", hdr, tc.hdr) - - } - if msg := ml.msg; msg != tc.msg { - t.Errorf("message length = %v, want %v", msg, tc.msg) - } - } -} - -func TestFillMethodLoggerWithConfigStringInvalid(t *testing.T) { - testCases := []string{ - "", - "{}", - "p.s/m{}", - "p.s/m{a}", - "p.s/m*", - "p.s/**", - "*/m", - - "-p.s/*", - "-p.s/m{h}", - } - l := &logger{} - for _, tc := range testCases { - if err := l.fillMethodLoggerWithConfigString(tc); err == nil { - t.Errorf("fillMethodLoggerWithConfigString(%q) returned nil error, want non-nil", tc) - } - } -} diff --git a/vendor/google.golang.org/grpc/internal/binarylog/method_logger_test.go b/vendor/google.golang.org/grpc/internal/binarylog/method_logger_test.go deleted file mode 100644 index 177adb6a..00000000 --- a/vendor/google.golang.org/grpc/internal/binarylog/method_logger_test.go +++ /dev/null @@ -1,542 +0,0 @@ -/* - * - * Copyright 2018 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package binarylog - -import ( - "bytes" - "fmt" - "net" - "testing" - "time" - - "github.com/golang/protobuf/proto" - dpb "github.com/golang/protobuf/ptypes/duration" - pb "google.golang.org/grpc/binarylog/grpc_binarylog_v1" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" -) - -func TestLog(t *testing.T) { - idGen.reset() - ml := newMethodLogger(10, 10) - // Set sink to testing buffer. - buf := bytes.NewBuffer(nil) - ml.sink = newWriterSink(buf) - - addr := "1.2.3.4" - port := 790 - tcpAddr, _ := net.ResolveTCPAddr("tcp", fmt.Sprintf("%v:%d", addr, port)) - addr6 := "2001:1db8:85a3::8a2e:1370:7334" - port6 := 796 - tcpAddr6, _ := net.ResolveTCPAddr("tcp", fmt.Sprintf("[%v]:%d", addr6, port6)) - - testProtoMsg := &pb.Message{ - Length: 1, - Data: []byte{'a'}, - } - testProtoBytes, _ := proto.Marshal(testProtoMsg) - - testCases := []struct { - config LogEntryConfig - want *pb.GrpcLogEntry - }{ - { - config: &ClientHeader{ - OnClientSide: false, - Header: map[string][]string{ - "a": {"b", "bb"}, - }, - MethodName: "testservice/testmethod", - Authority: "test.service.io", - Timeout: 2*time.Second + 3*time.Nanosecond, - PeerAddr: tcpAddr, - }, - want: &pb.GrpcLogEntry{ - Timestamp: nil, - CallId: 1, - SequenceIdWithinCall: 0, - Type: pb.GrpcLogEntry_EVENT_TYPE_CLIENT_HEADER, - Logger: pb.GrpcLogEntry_LOGGER_SERVER, - Payload: &pb.GrpcLogEntry_ClientHeader{ - ClientHeader: &pb.ClientHeader{ - Metadata: &pb.Metadata{ - Entry: []*pb.MetadataEntry{ - {Key: "a", Value: []byte{'b'}}, - {Key: "a", Value: []byte{'b', 'b'}}, - }, - }, - MethodName: "testservice/testmethod", - Authority: "test.service.io", - Timeout: &dpb.Duration{ - Seconds: 2, - Nanos: 3, - }, - }, - }, - PayloadTruncated: false, - Peer: &pb.Address{ - Type: pb.Address_TYPE_IPV4, - Address: addr, - IpPort: uint32(port), - }, - }, - }, - { - config: &ClientHeader{ - OnClientSide: false, - MethodName: "testservice/testmethod", - Authority: "test.service.io", - }, - want: &pb.GrpcLogEntry{ - Timestamp: nil, - CallId: 1, - SequenceIdWithinCall: 0, - Type: pb.GrpcLogEntry_EVENT_TYPE_CLIENT_HEADER, - Logger: pb.GrpcLogEntry_LOGGER_SERVER, - Payload: &pb.GrpcLogEntry_ClientHeader{ - ClientHeader: &pb.ClientHeader{ - Metadata: &pb.Metadata{}, - MethodName: "testservice/testmethod", - Authority: "test.service.io", - }, - }, - PayloadTruncated: false, - }, - }, - { - config: &ServerHeader{ - OnClientSide: true, - Header: map[string][]string{ - "a": {"b", "bb"}, - }, - PeerAddr: tcpAddr6, - }, - want: &pb.GrpcLogEntry{ - Timestamp: nil, - CallId: 1, - SequenceIdWithinCall: 0, - Type: pb.GrpcLogEntry_EVENT_TYPE_SERVER_HEADER, - Logger: pb.GrpcLogEntry_LOGGER_CLIENT, - Payload: &pb.GrpcLogEntry_ServerHeader{ - ServerHeader: &pb.ServerHeader{ - Metadata: &pb.Metadata{ - Entry: []*pb.MetadataEntry{ - {Key: "a", Value: []byte{'b'}}, - {Key: "a", Value: []byte{'b', 'b'}}, - }, - }, - }, - }, - PayloadTruncated: false, - Peer: &pb.Address{ - Type: pb.Address_TYPE_IPV6, - Address: addr6, - IpPort: uint32(port6), - }, - }, - }, - { - config: &ClientMessage{ - OnClientSide: true, - Message: testProtoMsg, - }, - want: &pb.GrpcLogEntry{ - Timestamp: nil, - CallId: 1, - SequenceIdWithinCall: 0, - Type: pb.GrpcLogEntry_EVENT_TYPE_CLIENT_MESSAGE, - Logger: pb.GrpcLogEntry_LOGGER_CLIENT, - Payload: &pb.GrpcLogEntry_Message{ - Message: &pb.Message{ - Length: uint32(len(testProtoBytes)), - Data: testProtoBytes, - }, - }, - PayloadTruncated: false, - Peer: nil, - }, - }, - { - config: &ServerMessage{ - OnClientSide: false, - Message: testProtoMsg, - }, - want: &pb.GrpcLogEntry{ - Timestamp: nil, - CallId: 1, - SequenceIdWithinCall: 0, - Type: pb.GrpcLogEntry_EVENT_TYPE_SERVER_MESSAGE, - Logger: pb.GrpcLogEntry_LOGGER_SERVER, - Payload: &pb.GrpcLogEntry_Message{ - Message: &pb.Message{ - Length: uint32(len(testProtoBytes)), - Data: testProtoBytes, - }, - }, - PayloadTruncated: false, - Peer: nil, - }, - }, - { - config: &ClientHalfClose{ - OnClientSide: false, - }, - want: &pb.GrpcLogEntry{ - Timestamp: nil, - CallId: 1, - SequenceIdWithinCall: 0, - Type: pb.GrpcLogEntry_EVENT_TYPE_CLIENT_HALF_CLOSE, - Logger: pb.GrpcLogEntry_LOGGER_SERVER, - Payload: nil, - PayloadTruncated: false, - Peer: nil, - }, - }, - { - config: &ServerTrailer{ - OnClientSide: true, - Err: status.Errorf(codes.Unavailable, "test"), - PeerAddr: tcpAddr, - }, - want: &pb.GrpcLogEntry{ - Timestamp: nil, - CallId: 1, - SequenceIdWithinCall: 0, - Type: pb.GrpcLogEntry_EVENT_TYPE_SERVER_TRAILER, - Logger: pb.GrpcLogEntry_LOGGER_CLIENT, - Payload: &pb.GrpcLogEntry_Trailer{ - Trailer: &pb.Trailer{ - Metadata: &pb.Metadata{}, - StatusCode: uint32(codes.Unavailable), - StatusMessage: "test", - StatusDetails: nil, - }, - }, - PayloadTruncated: false, - Peer: &pb.Address{ - Type: pb.Address_TYPE_IPV4, - Address: addr, - IpPort: uint32(port), - }, - }, - }, - { // Err is nil, Log OK status. - config: &ServerTrailer{ - OnClientSide: true, - }, - want: &pb.GrpcLogEntry{ - Timestamp: nil, - CallId: 1, - SequenceIdWithinCall: 0, - Type: pb.GrpcLogEntry_EVENT_TYPE_SERVER_TRAILER, - Logger: pb.GrpcLogEntry_LOGGER_CLIENT, - Payload: &pb.GrpcLogEntry_Trailer{ - Trailer: &pb.Trailer{ - Metadata: &pb.Metadata{}, - StatusCode: uint32(codes.OK), - StatusMessage: "", - StatusDetails: nil, - }, - }, - PayloadTruncated: false, - Peer: nil, - }, - }, - { - config: &Cancel{ - OnClientSide: true, - }, - want: &pb.GrpcLogEntry{ - Timestamp: nil, - CallId: 1, - SequenceIdWithinCall: 0, - Type: pb.GrpcLogEntry_EVENT_TYPE_CANCEL, - Logger: pb.GrpcLogEntry_LOGGER_CLIENT, - Payload: nil, - PayloadTruncated: false, - Peer: nil, - }, - }, - - // gRPC headers should be omitted. - { - config: &ClientHeader{ - OnClientSide: false, - Header: map[string][]string{ - "grpc-reserved": {"to be omitted"}, - ":authority": {"to be omitted"}, - "a": {"b", "bb"}, - }, - }, - want: &pb.GrpcLogEntry{ - Timestamp: nil, - CallId: 1, - SequenceIdWithinCall: 0, - Type: pb.GrpcLogEntry_EVENT_TYPE_CLIENT_HEADER, - Logger: pb.GrpcLogEntry_LOGGER_SERVER, - Payload: &pb.GrpcLogEntry_ClientHeader{ - ClientHeader: &pb.ClientHeader{ - Metadata: &pb.Metadata{ - Entry: []*pb.MetadataEntry{ - {Key: "a", Value: []byte{'b'}}, - {Key: "a", Value: []byte{'b', 'b'}}, - }, - }, - }, - }, - PayloadTruncated: false, - }, - }, - { - config: &ServerHeader{ - OnClientSide: true, - Header: map[string][]string{ - "grpc-reserved": {"to be omitted"}, - ":authority": {"to be omitted"}, - "a": {"b", "bb"}, - }, - }, - want: &pb.GrpcLogEntry{ - Timestamp: nil, - CallId: 1, - SequenceIdWithinCall: 0, - Type: pb.GrpcLogEntry_EVENT_TYPE_SERVER_HEADER, - Logger: pb.GrpcLogEntry_LOGGER_CLIENT, - Payload: &pb.GrpcLogEntry_ServerHeader{ - ServerHeader: &pb.ServerHeader{ - Metadata: &pb.Metadata{ - Entry: []*pb.MetadataEntry{ - {Key: "a", Value: []byte{'b'}}, - {Key: "a", Value: []byte{'b', 'b'}}, - }, - }, - }, - }, - PayloadTruncated: false, - }, - }, - } - for i, tc := range testCases { - buf.Reset() - tc.want.SequenceIdWithinCall = uint64(i + 1) - ml.Log(tc.config) - inSink := new(pb.GrpcLogEntry) - if err := proto.Unmarshal(buf.Bytes()[4:], inSink); err != nil { - t.Errorf("failed to unmarshal bytes in sink to proto: %v", err) - continue - } - inSink.Timestamp = nil // Strip timestamp before comparing. - if !proto.Equal(inSink, tc.want) { - t.Errorf("Log(%+v), in sink: %+v, want %+v", tc.config, inSink, tc.want) - } - } -} - -func TestTruncateMetadataNotTruncated(t *testing.T) { - testCases := []struct { - ml *MethodLogger - mpPb *pb.Metadata - }{ - { - ml: newMethodLogger(maxUInt, maxUInt), - mpPb: &pb.Metadata{ - Entry: []*pb.MetadataEntry{ - {Key: "", Value: []byte{1}}, - }, - }, - }, - { - ml: newMethodLogger(2, maxUInt), - mpPb: &pb.Metadata{ - Entry: []*pb.MetadataEntry{ - {Key: "", Value: []byte{1}}, - }, - }, - }, - { - ml: newMethodLogger(1, maxUInt), - mpPb: &pb.Metadata{ - Entry: []*pb.MetadataEntry{ - {Key: "", Value: nil}, - }, - }, - }, - { - ml: newMethodLogger(2, maxUInt), - mpPb: &pb.Metadata{ - Entry: []*pb.MetadataEntry{ - {Key: "", Value: []byte{1, 1}}, - }, - }, - }, - { - ml: newMethodLogger(2, maxUInt), - mpPb: &pb.Metadata{ - Entry: []*pb.MetadataEntry{ - {Key: "", Value: []byte{1}}, - {Key: "", Value: []byte{1}}, - }, - }, - }, - // "grpc-trace-bin" is kept in log but not counted towards the size - // limit. - { - ml: newMethodLogger(1, maxUInt), - mpPb: &pb.Metadata{ - Entry: []*pb.MetadataEntry{ - {Key: "", Value: []byte{1}}, - {Key: "grpc-trace-bin", Value: []byte("some.trace.key")}, - }, - }, - }, - } - - for i, tc := range testCases { - truncated := tc.ml.truncateMetadata(tc.mpPb) - if truncated { - t.Errorf("test case %v, returned truncated, want not truncated", i) - } - } -} - -func TestTruncateMetadataTruncated(t *testing.T) { - testCases := []struct { - ml *MethodLogger - mpPb *pb.Metadata - - entryLen int - }{ - { - ml: newMethodLogger(2, maxUInt), - mpPb: &pb.Metadata{ - Entry: []*pb.MetadataEntry{ - {Key: "", Value: []byte{1, 1, 1}}, - }, - }, - entryLen: 0, - }, - { - ml: newMethodLogger(2, maxUInt), - mpPb: &pb.Metadata{ - Entry: []*pb.MetadataEntry{ - {Key: "", Value: []byte{1}}, - {Key: "", Value: []byte{1}}, - {Key: "", Value: []byte{1}}, - }, - }, - entryLen: 2, - }, - { - ml: newMethodLogger(2, maxUInt), - mpPb: &pb.Metadata{ - Entry: []*pb.MetadataEntry{ - {Key: "", Value: []byte{1, 1}}, - {Key: "", Value: []byte{1}}, - }, - }, - entryLen: 1, - }, - { - ml: newMethodLogger(2, maxUInt), - mpPb: &pb.Metadata{ - Entry: []*pb.MetadataEntry{ - {Key: "", Value: []byte{1}}, - {Key: "", Value: []byte{1, 1}}, - }, - }, - entryLen: 1, - }, - } - - for i, tc := range testCases { - truncated := tc.ml.truncateMetadata(tc.mpPb) - if !truncated { - t.Errorf("test case %v, returned not truncated, want truncated", i) - continue - } - if len(tc.mpPb.Entry) != tc.entryLen { - t.Errorf("test case %v, entry length: %v, want: %v", i, len(tc.mpPb.Entry), tc.entryLen) - } - } -} - -func TestTruncateMessageNotTruncated(t *testing.T) { - testCases := []struct { - ml *MethodLogger - msgPb *pb.Message - }{ - { - ml: newMethodLogger(maxUInt, maxUInt), - msgPb: &pb.Message{ - Data: []byte{1}, - }, - }, - { - ml: newMethodLogger(maxUInt, 3), - msgPb: &pb.Message{ - Data: []byte{1, 1}, - }, - }, - { - ml: newMethodLogger(maxUInt, 2), - msgPb: &pb.Message{ - Data: []byte{1, 1}, - }, - }, - } - - for i, tc := range testCases { - truncated := tc.ml.truncateMessage(tc.msgPb) - if truncated { - t.Errorf("test case %v, returned truncated, want not truncated", i) - } - } -} - -func TestTruncateMessageTruncated(t *testing.T) { - testCases := []struct { - ml *MethodLogger - msgPb *pb.Message - - oldLength uint32 - }{ - { - ml: newMethodLogger(maxUInt, 2), - msgPb: &pb.Message{ - Length: 3, - Data: []byte{1, 1, 1}, - }, - oldLength: 3, - }, - } - - for i, tc := range testCases { - truncated := tc.ml.truncateMessage(tc.msgPb) - if !truncated { - t.Errorf("test case %v, returned not truncated, want truncated", i) - continue - } - if len(tc.msgPb.Data) != int(tc.ml.messageMaxLen) { - t.Errorf("test case %v, message length: %v, want: %v", i, len(tc.msgPb.Data), tc.ml.messageMaxLen) - } - if tc.msgPb.Length != tc.oldLength { - t.Errorf("test case %v, message.Length field: %v, want: %v", i, tc.msgPb.Length, tc.oldLength) - } - } -} diff --git a/vendor/google.golang.org/grpc/internal/binarylog/regenerate.sh b/vendor/google.golang.org/grpc/internal/binarylog/regenerate.sh deleted file mode 100755 index 113d40cb..00000000 --- a/vendor/google.golang.org/grpc/internal/binarylog/regenerate.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash -# Copyright 2018 gRPC authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -set -eux -o pipefail - -TMP=$(mktemp -d) - -function finish { - rm -rf "$TMP" -} -trap finish EXIT - -pushd "$TMP" -mkdir -p grpc/binarylog/grpc_binarylog_v1 -curl https://raw.githubusercontent.com/grpc/grpc-proto/master/grpc/binlog/v1/binarylog.proto > grpc/binarylog/grpc_binarylog_v1/binarylog.proto - -protoc --go_out=plugins=grpc,paths=source_relative:. -I. grpc/binarylog/grpc_binarylog_v1/*.proto -popd -rm -f ./grpc_binarylog_v1/*.pb.go -cp "$TMP"/grpc/binarylog/grpc_binarylog_v1/*.pb.go ../../binarylog/grpc_binarylog_v1/ - diff --git a/vendor/google.golang.org/grpc/internal/binarylog/regexp_test.go b/vendor/google.golang.org/grpc/internal/binarylog/regexp_test.go deleted file mode 100644 index 8806a5aa..00000000 --- a/vendor/google.golang.org/grpc/internal/binarylog/regexp_test.go +++ /dev/null @@ -1,179 +0,0 @@ -/* - * - * Copyright 2018 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package binarylog - -import ( - "reflect" - "testing" -) - -func TestLongMethodConfigRegexp(t *testing.T) { - testCases := []struct { - in string - out []string - }{ - {in: "", out: nil}, - {in: "*/m", out: nil}, - - { - in: "p.s/m{}", - out: []string{"p.s/m{}", "p.s", "m", "{}"}, - }, - - { - in: "p.s/m", - out: []string{"p.s/m", "p.s", "m", ""}, - }, - { - in: "p.s/m{h}", - out: []string{"p.s/m{h}", "p.s", "m", "{h}"}, - }, - { - in: "p.s/m{m}", - out: []string{"p.s/m{m}", "p.s", "m", "{m}"}, - }, - { - in: "p.s/m{h:123}", - out: []string{"p.s/m{h:123}", "p.s", "m", "{h:123}"}, - }, - { - in: "p.s/m{m:123}", - out: []string{"p.s/m{m:123}", "p.s", "m", "{m:123}"}, - }, - { - in: "p.s/m{h:123,m:123}", - out: []string{"p.s/m{h:123,m:123}", "p.s", "m", "{h:123,m:123}"}, - }, - - { - in: "p.s/*", - out: []string{"p.s/*", "p.s", "*", ""}, - }, - { - in: "p.s/*{h}", - out: []string{"p.s/*{h}", "p.s", "*", "{h}"}, - }, - - { - in: "s/m*", - out: []string{"s/m*", "s", "m", "*"}, - }, - { - in: "s/**", - out: []string{"s/**", "s", "*", "*"}, - }, - } - for _, tc := range testCases { - match := longMethodConfigRegexp.FindStringSubmatch(tc.in) - if !reflect.DeepEqual(match, tc.out) { - t.Errorf("in: %q, out: %q, want: %q", tc.in, match, tc.out) - } - } -} - -func TestHeaderConfigRegexp(t *testing.T) { - testCases := []struct { - in string - out []string - }{ - {in: "{}", out: nil}, - {in: "{a:b}", out: nil}, - {in: "{m:123}", out: nil}, - {in: "{h:123;m:123}", out: nil}, - - { - in: "{h}", - out: []string{"{h}", ""}, - }, - { - in: "{h:123}", - out: []string{"{h:123}", "123"}, - }, - } - for _, tc := range testCases { - match := headerConfigRegexp.FindStringSubmatch(tc.in) - if !reflect.DeepEqual(match, tc.out) { - t.Errorf("in: %q, out: %q, want: %q", tc.in, match, tc.out) - } - } -} - -func TestMessageConfigRegexp(t *testing.T) { - testCases := []struct { - in string - out []string - }{ - {in: "{}", out: nil}, - {in: "{a:b}", out: nil}, - {in: "{h:123}", out: nil}, - {in: "{h:123;m:123}", out: nil}, - - { - in: "{m}", - out: []string{"{m}", ""}, - }, - { - in: "{m:123}", - out: []string{"{m:123}", "123"}, - }, - } - for _, tc := range testCases { - match := messageConfigRegexp.FindStringSubmatch(tc.in) - if !reflect.DeepEqual(match, tc.out) { - t.Errorf("in: %q, out: %q, want: %q", tc.in, match, tc.out) - } - } -} - -func TestHeaderMessageConfigRegexp(t *testing.T) { - testCases := []struct { - in string - out []string - }{ - {in: "{}", out: nil}, - {in: "{a:b}", out: nil}, - {in: "{h}", out: nil}, - {in: "{h:123}", out: nil}, - {in: "{m}", out: nil}, - {in: "{m:123}", out: nil}, - - { - in: "{h;m}", - out: []string{"{h;m}", "", ""}, - }, - { - in: "{h:123;m}", - out: []string{"{h:123;m}", "123", ""}, - }, - { - in: "{h;m:123}", - out: []string{"{h;m:123}", "", "123"}, - }, - { - in: "{h:123;m:123}", - out: []string{"{h:123;m:123}", "123", "123"}, - }, - } - for _, tc := range testCases { - match := headerMessageConfigRegexp.FindStringSubmatch(tc.in) - if !reflect.DeepEqual(match, tc.out) { - t.Errorf("in: %q, out: %q, want: %q", tc.in, match, tc.out) - } - } -} diff --git a/vendor/google.golang.org/grpc/internal/binarylog/util_test.go b/vendor/google.golang.org/grpc/internal/binarylog/util_test.go deleted file mode 100644 index 3454f029..00000000 --- a/vendor/google.golang.org/grpc/internal/binarylog/util_test.go +++ /dev/null @@ -1,59 +0,0 @@ -/* - * - * Copyright 2018 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package binarylog - -import "testing" - -func TestParseMethodName(t *testing.T) { - testCases := []struct { - methodName string - service, method string - }{ - {methodName: "/s/m", service: "s", method: "m"}, - {methodName: "/p.s/m", service: "p.s", method: "m"}, - {methodName: "/p/s/m", service: "p/s", method: "m"}, - } - for _, tc := range testCases { - s, m, err := parseMethodName(tc.methodName) - if err != nil { - t.Errorf("Parsing %q got error %v, want nil", tc.methodName, err) - continue - } - if s != tc.service || m != tc.method { - t.Errorf("Parseing %q got service %q, method %q, want service %q, method %q", - tc.methodName, s, m, tc.service, tc.method, - ) - } - } -} - -func TestParseMethodNameInvalid(t *testing.T) { - testCases := []string{ - "/", - "/sm", - "", - "sm", - } - for _, tc := range testCases { - _, _, err := parseMethodName(tc) - if err == nil { - t.Errorf("Parsing %q got nil error, want non-nil error", tc) - } - } -} diff --git a/vendor/google.golang.org/grpc/internal/channelz/util_test.go b/vendor/google.golang.org/grpc/internal/channelz/util_test.go deleted file mode 100644 index 6091e1a3..00000000 --- a/vendor/google.golang.org/grpc/internal/channelz/util_test.go +++ /dev/null @@ -1,90 +0,0 @@ -// +build linux,go1.10,!appengine - -/* - * - * Copyright 2018 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// The test in this file should be run in an environment that has go1.10 or later, -// as the function SyscallConn() (required to get socket option) was introduced -// to net.TCPListener in go1.10. - -package channelz_test - -import ( - "net" - "reflect" - "syscall" - "testing" - - "golang.org/x/sys/unix" - "google.golang.org/grpc/internal/channelz" -) - -func TestGetSocketOpt(t *testing.T) { - network, addr := "tcp", ":0" - ln, err := net.Listen(network, addr) - if err != nil { - t.Fatalf("net.Listen(%s,%s) failed with err: %v", network, addr, err) - } - defer ln.Close() - go func() { - ln.Accept() - }() - conn, _ := net.Dial(network, ln.Addr().String()) - defer conn.Close() - tcpc := conn.(*net.TCPConn) - raw, err := tcpc.SyscallConn() - if err != nil { - t.Fatalf("SyscallConn() failed due to %v", err) - } - - l := &unix.Linger{Onoff: 1, Linger: 5} - recvTimout := &unix.Timeval{Sec: 100} - sendTimeout := &unix.Timeval{Sec: 8888} - raw.Control(func(fd uintptr) { - err := unix.SetsockoptLinger(int(fd), syscall.SOL_SOCKET, syscall.SO_LINGER, l) - if err != nil { - t.Fatalf("failed to SetsockoptLinger(%v,%v,%v,%v) due to %v", int(fd), syscall.SOL_SOCKET, syscall.SO_LINGER, l, err) - } - err = unix.SetsockoptTimeval(int(fd), syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, recvTimout) - if err != nil { - t.Fatalf("failed to SetsockoptTimeval(%v,%v,%v,%v) due to %v", int(fd), syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, recvTimout, err) - } - err = unix.SetsockoptTimeval(int(fd), syscall.SOL_SOCKET, syscall.SO_SNDTIMEO, sendTimeout) - if err != nil { - t.Fatalf("failed to SetsockoptTimeval(%v,%v,%v,%v) due to %v", int(fd), syscall.SOL_SOCKET, syscall.SO_SNDTIMEO, sendTimeout, err) - } - }) - sktopt := channelz.GetSocketOption(conn) - if !reflect.DeepEqual(sktopt.Linger, l) { - t.Fatalf("get socket option linger, want: %v, got %v", l, sktopt.Linger) - } - if !reflect.DeepEqual(sktopt.RecvTimeout, recvTimout) { - t.Logf("get socket option recv timeout, want: %v, got %v, may be caused by system allowing non or partial setting of this value", recvTimout, sktopt.RecvTimeout) - } - if !reflect.DeepEqual(sktopt.SendTimeout, sendTimeout) { - t.Logf("get socket option send timeout, want: %v, got %v, may be caused by system allowing non or partial setting of this value", sendTimeout, sktopt.SendTimeout) - } - if sktopt == nil || sktopt.TCPInfo != nil && sktopt.TCPInfo.State != 1 { - t.Fatalf("TCPInfo.State want 1 (TCP_ESTABLISHED), got %v", sktopt) - } - - sktopt = channelz.GetSocketOption(ln) - if sktopt == nil || sktopt.TCPInfo == nil || sktopt.TCPInfo.State != 10 { - t.Fatalf("TCPInfo.State want 10 (TCP_LISTEN), got %v", sktopt) - } -} diff --git a/vendor/google.golang.org/grpc/internal/grpcsync/event_test.go b/vendor/google.golang.org/grpc/internal/grpcsync/event_test.go deleted file mode 100644 index af64d183..00000000 --- a/vendor/google.golang.org/grpc/internal/grpcsync/event_test.go +++ /dev/null @@ -1,69 +0,0 @@ -/* - * - * Copyright 2018 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package grpcsync - -import "testing" - -func TestEventHasFired(t *testing.T) { - e := NewEvent() - if e.HasFired() { - t.Fatal("e.HasFired() = true; want false") - } - if !e.Fire() { - t.Fatal("e.Fire() = false; want true") - } - if !e.HasFired() { - t.Fatal("e.HasFired() = false; want true") - } -} - -func TestEventDoneChannel(t *testing.T) { - e := NewEvent() - select { - case <-e.Done(): - t.Fatal("e.HasFired() = true; want false") - default: - } - if !e.Fire() { - t.Fatal("e.Fire() = false; want true") - } - select { - case <-e.Done(): - default: - t.Fatal("e.HasFired() = false; want true") - } -} - -func TestEventMultipleFires(t *testing.T) { - e := NewEvent() - if e.HasFired() { - t.Fatal("e.HasFired() = true; want false") - } - if !e.Fire() { - t.Fatal("e.Fire() = false; want true") - } - for i := 0; i < 3; i++ { - if !e.HasFired() { - t.Fatal("e.HasFired() = false; want true") - } - if e.Fire() { - t.Fatal("e.Fire() = true; want false") - } - } -} diff --git a/vendor/google.golang.org/grpc/internal/transport/handler_server_test.go b/vendor/google.golang.org/grpc/internal/transport/handler_server_test.go deleted file mode 100644 index cf989c76..00000000 --- a/vendor/google.golang.org/grpc/internal/transport/handler_server_test.go +++ /dev/null @@ -1,481 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package transport - -import ( - "context" - "errors" - "fmt" - "io" - "net/http" - "net/http/httptest" - "net/url" - "reflect" - "sync" - "testing" - "time" - - "github.com/golang/protobuf/proto" - dpb "github.com/golang/protobuf/ptypes/duration" - epb "google.golang.org/genproto/googleapis/rpc/errdetails" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/metadata" - "google.golang.org/grpc/status" -) - -func TestHandlerTransport_NewServerHandlerTransport(t *testing.T) { - type testCase struct { - name string - req *http.Request - wantErr string - modrw func(http.ResponseWriter) http.ResponseWriter - check func(*serverHandlerTransport, *testCase) error - } - tests := []testCase{ - { - name: "http/1.1", - req: &http.Request{ - ProtoMajor: 1, - ProtoMinor: 1, - }, - wantErr: "gRPC requires HTTP/2", - }, - { - name: "bad method", - req: &http.Request{ - ProtoMajor: 2, - Method: "GET", - Header: http.Header{}, - RequestURI: "/", - }, - wantErr: "invalid gRPC request method", - }, - { - name: "bad content type", - req: &http.Request{ - ProtoMajor: 2, - Method: "POST", - Header: http.Header{ - "Content-Type": {"application/foo"}, - }, - RequestURI: "/service/foo.bar", - }, - wantErr: "invalid gRPC request content-type", - }, - { - name: "not flusher", - req: &http.Request{ - ProtoMajor: 2, - Method: "POST", - Header: http.Header{ - "Content-Type": {"application/grpc"}, - }, - RequestURI: "/service/foo.bar", - }, - modrw: func(w http.ResponseWriter) http.ResponseWriter { - // Return w without its Flush method - type onlyCloseNotifier interface { - http.ResponseWriter - http.CloseNotifier - } - return struct{ onlyCloseNotifier }{w.(onlyCloseNotifier)} - }, - wantErr: "gRPC requires a ResponseWriter supporting http.Flusher", - }, - { - name: "not closenotifier", - req: &http.Request{ - ProtoMajor: 2, - Method: "POST", - Header: http.Header{ - "Content-Type": {"application/grpc"}, - }, - RequestURI: "/service/foo.bar", - }, - modrw: func(w http.ResponseWriter) http.ResponseWriter { - // Return w without its CloseNotify method - type onlyFlusher interface { - http.ResponseWriter - http.Flusher - } - return struct{ onlyFlusher }{w.(onlyFlusher)} - }, - wantErr: "gRPC requires a ResponseWriter supporting http.CloseNotifier", - }, - { - name: "valid", - req: &http.Request{ - ProtoMajor: 2, - Method: "POST", - Header: http.Header{ - "Content-Type": {"application/grpc"}, - }, - URL: &url.URL{ - Path: "/service/foo.bar", - }, - RequestURI: "/service/foo.bar", - }, - check: func(t *serverHandlerTransport, tt *testCase) error { - if t.req != tt.req { - return fmt.Errorf("t.req = %p; want %p", t.req, tt.req) - } - if t.rw == nil { - return errors.New("t.rw = nil; want non-nil") - } - return nil - }, - }, - { - name: "with timeout", - req: &http.Request{ - ProtoMajor: 2, - Method: "POST", - Header: http.Header{ - "Content-Type": []string{"application/grpc"}, - "Grpc-Timeout": {"200m"}, - }, - URL: &url.URL{ - Path: "/service/foo.bar", - }, - RequestURI: "/service/foo.bar", - }, - check: func(t *serverHandlerTransport, tt *testCase) error { - if !t.timeoutSet { - return errors.New("timeout not set") - } - if want := 200 * time.Millisecond; t.timeout != want { - return fmt.Errorf("timeout = %v; want %v", t.timeout, want) - } - return nil - }, - }, - { - name: "with bad timeout", - req: &http.Request{ - ProtoMajor: 2, - Method: "POST", - Header: http.Header{ - "Content-Type": []string{"application/grpc"}, - "Grpc-Timeout": {"tomorrow"}, - }, - URL: &url.URL{ - Path: "/service/foo.bar", - }, - RequestURI: "/service/foo.bar", - }, - wantErr: `rpc error: code = Internal desc = malformed time-out: transport: timeout unit is not recognized: "tomorrow"`, - }, - { - name: "with metadata", - req: &http.Request{ - ProtoMajor: 2, - Method: "POST", - Header: http.Header{ - "Content-Type": []string{"application/grpc"}, - "meta-foo": {"foo-val"}, - "meta-bar": {"bar-val1", "bar-val2"}, - "user-agent": {"x/y a/b"}, - }, - URL: &url.URL{ - Path: "/service/foo.bar", - }, - RequestURI: "/service/foo.bar", - }, - check: func(ht *serverHandlerTransport, tt *testCase) error { - want := metadata.MD{ - "meta-bar": {"bar-val1", "bar-val2"}, - "user-agent": {"x/y a/b"}, - "meta-foo": {"foo-val"}, - "content-type": {"application/grpc"}, - } - - if !reflect.DeepEqual(ht.headerMD, want) { - return fmt.Errorf("metdata = %#v; want %#v", ht.headerMD, want) - } - return nil - }, - }, - } - - for _, tt := range tests { - rw := newTestHandlerResponseWriter() - if tt.modrw != nil { - rw = tt.modrw(rw) - } - got, gotErr := NewServerHandlerTransport(rw, tt.req, nil) - if (gotErr != nil) != (tt.wantErr != "") || (gotErr != nil && gotErr.Error() != tt.wantErr) { - t.Errorf("%s: error = %q; want %q", tt.name, gotErr.Error(), tt.wantErr) - continue - } - if gotErr != nil { - continue - } - if tt.check != nil { - if err := tt.check(got.(*serverHandlerTransport), &tt); err != nil { - t.Errorf("%s: %v", tt.name, err) - } - } - } -} - -type testHandlerResponseWriter struct { - *httptest.ResponseRecorder - closeNotify chan bool -} - -func (w testHandlerResponseWriter) CloseNotify() <-chan bool { return w.closeNotify } -func (w testHandlerResponseWriter) Flush() {} - -func newTestHandlerResponseWriter() http.ResponseWriter { - return testHandlerResponseWriter{ - ResponseRecorder: httptest.NewRecorder(), - closeNotify: make(chan bool, 1), - } -} - -type handleStreamTest struct { - t *testing.T - bodyw *io.PipeWriter - rw testHandlerResponseWriter - ht *serverHandlerTransport -} - -func newHandleStreamTest(t *testing.T) *handleStreamTest { - bodyr, bodyw := io.Pipe() - req := &http.Request{ - ProtoMajor: 2, - Method: "POST", - Header: http.Header{ - "Content-Type": {"application/grpc"}, - }, - URL: &url.URL{ - Path: "/service/foo.bar", - }, - RequestURI: "/service/foo.bar", - Body: bodyr, - } - rw := newTestHandlerResponseWriter().(testHandlerResponseWriter) - ht, err := NewServerHandlerTransport(rw, req, nil) - if err != nil { - t.Fatal(err) - } - return &handleStreamTest{ - t: t, - bodyw: bodyw, - ht: ht.(*serverHandlerTransport), - rw: rw, - } -} - -func TestHandlerTransport_HandleStreams(t *testing.T) { - st := newHandleStreamTest(t) - handleStream := func(s *Stream) { - if want := "/service/foo.bar"; s.method != want { - t.Errorf("stream method = %q; want %q", s.method, want) - } - st.bodyw.Close() // no body - st.ht.WriteStatus(s, status.New(codes.OK, "")) - } - st.ht.HandleStreams( - func(s *Stream) { go handleStream(s) }, - func(ctx context.Context, method string) context.Context { return ctx }, - ) - wantHeader := http.Header{ - "Date": nil, - "Content-Type": {"application/grpc"}, - "Trailer": {"Grpc-Status", "Grpc-Message", "Grpc-Status-Details-Bin"}, - "Grpc-Status": {"0"}, - } - if !reflect.DeepEqual(st.rw.HeaderMap, wantHeader) { - t.Errorf("Header+Trailer Map: %#v; want %#v", st.rw.HeaderMap, wantHeader) - } -} - -// Tests that codes.Unimplemented will close the body, per comment in handler_server.go. -func TestHandlerTransport_HandleStreams_Unimplemented(t *testing.T) { - handleStreamCloseBodyTest(t, codes.Unimplemented, "thingy is unimplemented") -} - -// Tests that codes.InvalidArgument will close the body, per comment in handler_server.go. -func TestHandlerTransport_HandleStreams_InvalidArgument(t *testing.T) { - handleStreamCloseBodyTest(t, codes.InvalidArgument, "bad arg") -} - -func handleStreamCloseBodyTest(t *testing.T, statusCode codes.Code, msg string) { - st := newHandleStreamTest(t) - - handleStream := func(s *Stream) { - st.ht.WriteStatus(s, status.New(statusCode, msg)) - } - st.ht.HandleStreams( - func(s *Stream) { go handleStream(s) }, - func(ctx context.Context, method string) context.Context { return ctx }, - ) - wantHeader := http.Header{ - "Date": nil, - "Content-Type": {"application/grpc"}, - "Trailer": {"Grpc-Status", "Grpc-Message", "Grpc-Status-Details-Bin"}, - "Grpc-Status": {fmt.Sprint(uint32(statusCode))}, - "Grpc-Message": {encodeGrpcMessage(msg)}, - } - - if !reflect.DeepEqual(st.rw.HeaderMap, wantHeader) { - t.Errorf("Header+Trailer mismatch.\n got: %#v\nwant: %#v", st.rw.HeaderMap, wantHeader) - } -} - -func TestHandlerTransport_HandleStreams_Timeout(t *testing.T) { - bodyr, bodyw := io.Pipe() - req := &http.Request{ - ProtoMajor: 2, - Method: "POST", - Header: http.Header{ - "Content-Type": {"application/grpc"}, - "Grpc-Timeout": {"200m"}, - }, - URL: &url.URL{ - Path: "/service/foo.bar", - }, - RequestURI: "/service/foo.bar", - Body: bodyr, - } - rw := newTestHandlerResponseWriter().(testHandlerResponseWriter) - ht, err := NewServerHandlerTransport(rw, req, nil) - if err != nil { - t.Fatal(err) - } - runStream := func(s *Stream) { - defer bodyw.Close() - select { - case <-s.ctx.Done(): - case <-time.After(5 * time.Second): - t.Errorf("timeout waiting for ctx.Done") - return - } - err := s.ctx.Err() - if err != context.DeadlineExceeded { - t.Errorf("ctx.Err = %v; want %v", err, context.DeadlineExceeded) - return - } - ht.WriteStatus(s, status.New(codes.DeadlineExceeded, "too slow")) - } - ht.HandleStreams( - func(s *Stream) { go runStream(s) }, - func(ctx context.Context, method string) context.Context { return ctx }, - ) - wantHeader := http.Header{ - "Date": nil, - "Content-Type": {"application/grpc"}, - "Trailer": {"Grpc-Status", "Grpc-Message", "Grpc-Status-Details-Bin"}, - "Grpc-Status": {"4"}, - "Grpc-Message": {encodeGrpcMessage("too slow")}, - } - if !reflect.DeepEqual(rw.HeaderMap, wantHeader) { - t.Errorf("Header+Trailer Map mismatch.\n got: %#v\nwant: %#v", rw.HeaderMap, wantHeader) - } -} - -// TestHandlerTransport_HandleStreams_MultiWriteStatus ensures that -// concurrent "WriteStatus"s do not panic writing to closed "writes" channel. -func TestHandlerTransport_HandleStreams_MultiWriteStatus(t *testing.T) { - testHandlerTransportHandleStreams(t, func(st *handleStreamTest, s *Stream) { - if want := "/service/foo.bar"; s.method != want { - t.Errorf("stream method = %q; want %q", s.method, want) - } - st.bodyw.Close() // no body - - var wg sync.WaitGroup - wg.Add(5) - for i := 0; i < 5; i++ { - go func() { - defer wg.Done() - st.ht.WriteStatus(s, status.New(codes.OK, "")) - }() - } - wg.Wait() - }) -} - -// TestHandlerTransport_HandleStreams_WriteStatusWrite ensures that "Write" -// following "WriteStatus" does not panic writing to closed "writes" channel. -func TestHandlerTransport_HandleStreams_WriteStatusWrite(t *testing.T) { - testHandlerTransportHandleStreams(t, func(st *handleStreamTest, s *Stream) { - if want := "/service/foo.bar"; s.method != want { - t.Errorf("stream method = %q; want %q", s.method, want) - } - st.bodyw.Close() // no body - - st.ht.WriteStatus(s, status.New(codes.OK, "")) - st.ht.Write(s, []byte("hdr"), []byte("data"), &Options{}) - }) -} - -func testHandlerTransportHandleStreams(t *testing.T, handleStream func(st *handleStreamTest, s *Stream)) { - st := newHandleStreamTest(t) - st.ht.HandleStreams( - func(s *Stream) { go handleStream(st, s) }, - func(ctx context.Context, method string) context.Context { return ctx }, - ) -} - -func TestHandlerTransport_HandleStreams_ErrDetails(t *testing.T) { - errDetails := []proto.Message{ - &epb.RetryInfo{ - RetryDelay: &dpb.Duration{Seconds: 60}, - }, - &epb.ResourceInfo{ - ResourceType: "foo bar", - ResourceName: "service.foo.bar", - Owner: "User", - }, - } - - statusCode := codes.ResourceExhausted - msg := "you are being throttled" - st, err := status.New(statusCode, msg).WithDetails(errDetails...) - if err != nil { - t.Fatal(err) - } - - stBytes, err := proto.Marshal(st.Proto()) - if err != nil { - t.Fatal(err) - } - - hst := newHandleStreamTest(t) - handleStream := func(s *Stream) { - hst.ht.WriteStatus(s, st) - } - hst.ht.HandleStreams( - func(s *Stream) { go handleStream(s) }, - func(ctx context.Context, method string) context.Context { return ctx }, - ) - wantHeader := http.Header{ - "Date": nil, - "Content-Type": {"application/grpc"}, - "Trailer": {"Grpc-Status", "Grpc-Message", "Grpc-Status-Details-Bin"}, - "Grpc-Status": {fmt.Sprint(uint32(statusCode))}, - "Grpc-Message": {encodeGrpcMessage(msg)}, - "Grpc-Status-Details-Bin": {encodeBinHeader(stBytes)}, - } - - if !reflect.DeepEqual(hst.rw.HeaderMap, wantHeader) { - t.Errorf("Header+Trailer mismatch.\n got: %#v\nwant: %#v", hst.rw.HeaderMap, wantHeader) - } -} diff --git a/vendor/google.golang.org/grpc/internal/transport/http_util_test.go b/vendor/google.golang.org/grpc/internal/transport/http_util_test.go deleted file mode 100644 index 44169b65..00000000 --- a/vendor/google.golang.org/grpc/internal/transport/http_util_test.go +++ /dev/null @@ -1,237 +0,0 @@ -/* - * - * Copyright 2014 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package transport - -import ( - "fmt" - "reflect" - "testing" - "time" -) - -func TestTimeoutEncode(t *testing.T) { - for _, test := range []struct { - in string - out string - }{ - {"12345678ns", "12345678n"}, - {"123456789ns", "123457u"}, - {"12345678us", "12345678u"}, - {"123456789us", "123457m"}, - {"12345678ms", "12345678m"}, - {"123456789ms", "123457S"}, - {"12345678s", "12345678S"}, - {"123456789s", "2057614M"}, - {"12345678m", "12345678M"}, - {"123456789m", "2057614H"}, - } { - d, err := time.ParseDuration(test.in) - if err != nil { - t.Fatalf("failed to parse duration string %s: %v", test.in, err) - } - out := encodeTimeout(d) - if out != test.out { - t.Fatalf("timeoutEncode(%s) = %s, want %s", test.in, out, test.out) - } - } -} - -func TestTimeoutDecode(t *testing.T) { - for _, test := range []struct { - // input - s string - // output - d time.Duration - err error - }{ - {"1234S", time.Second * 1234, nil}, - {"1234x", 0, fmt.Errorf("transport: timeout unit is not recognized: %q", "1234x")}, - {"1", 0, fmt.Errorf("transport: timeout string is too short: %q", "1")}, - {"", 0, fmt.Errorf("transport: timeout string is too short: %q", "")}, - } { - d, err := decodeTimeout(test.s) - if d != test.d || fmt.Sprint(err) != fmt.Sprint(test.err) { - t.Fatalf("timeoutDecode(%q) = %d, %v, want %d, %v", test.s, int64(d), err, int64(test.d), test.err) - } - } -} - -func TestContentSubtype(t *testing.T) { - tests := []struct { - contentType string - want string - wantValid bool - }{ - {"application/grpc", "", true}, - {"application/grpc+", "", true}, - {"application/grpc+blah", "blah", true}, - {"application/grpc;", "", true}, - {"application/grpc;blah", "blah", true}, - {"application/grpcd", "", false}, - {"application/grpd", "", false}, - {"application/grp", "", false}, - } - for _, tt := range tests { - got, gotValid := contentSubtype(tt.contentType) - if got != tt.want || gotValid != tt.wantValid { - t.Errorf("contentSubtype(%q) = (%v, %v); want (%v, %v)", tt.contentType, got, gotValid, tt.want, tt.wantValid) - } - } -} - -func TestEncodeGrpcMessage(t *testing.T) { - for _, tt := range []struct { - input string - expected string - }{ - {"", ""}, - {"Hello", "Hello"}, - {"\u0000", "%00"}, - {"%", "%25"}, - {"系统", "%E7%B3%BB%E7%BB%9F"}, - {string([]byte{0xff, 0xfe, 0xfd}), "%EF%BF%BD%EF%BF%BD%EF%BF%BD"}, - } { - actual := encodeGrpcMessage(tt.input) - if tt.expected != actual { - t.Errorf("encodeGrpcMessage(%q) = %q, want %q", tt.input, actual, tt.expected) - } - } - - // make sure that all the visible ASCII chars except '%' are not percent encoded. - for i := ' '; i <= '~' && i != '%'; i++ { - output := encodeGrpcMessage(string(i)) - if output != string(i) { - t.Errorf("encodeGrpcMessage(%v) = %v, want %v", string(i), output, string(i)) - } - } - - // make sure that all the invisible ASCII chars and '%' are percent encoded. - for i := rune(0); i == '%' || (i >= rune(0) && i < ' ') || (i > '~' && i <= rune(127)); i++ { - output := encodeGrpcMessage(string(i)) - expected := fmt.Sprintf("%%%02X", i) - if output != expected { - t.Errorf("encodeGrpcMessage(%v) = %v, want %v", string(i), output, expected) - } - } -} - -func TestDecodeGrpcMessage(t *testing.T) { - for _, tt := range []struct { - input string - expected string - }{ - {"", ""}, - {"Hello", "Hello"}, - {"H%61o", "Hao"}, - {"H%6", "H%6"}, - {"%G0", "%G0"}, - {"%E7%B3%BB%E7%BB%9F", "系统"}, - {"%EF%BF%BD", "�"}, - } { - actual := decodeGrpcMessage(tt.input) - if tt.expected != actual { - t.Errorf("decodeGrpcMessage(%q) = %q, want %q", tt.input, actual, tt.expected) - } - } - - // make sure that all the visible ASCII chars except '%' are not percent decoded. - for i := ' '; i <= '~' && i != '%'; i++ { - output := decodeGrpcMessage(string(i)) - if output != string(i) { - t.Errorf("decodeGrpcMessage(%v) = %v, want %v", string(i), output, string(i)) - } - } - - // make sure that all the invisible ASCII chars and '%' are percent decoded. - for i := rune(0); i == '%' || (i >= rune(0) && i < ' ') || (i > '~' && i <= rune(127)); i++ { - output := decodeGrpcMessage(fmt.Sprintf("%%%02X", i)) - if output != string(i) { - t.Errorf("decodeGrpcMessage(%v) = %v, want %v", fmt.Sprintf("%%%02X", i), output, string(i)) - } - } -} - -// Decode an encoded string should get the same thing back, except for invalid -// utf8 chars. -func TestDecodeEncodeGrpcMessage(t *testing.T) { - testCases := []struct { - orig string - want string - }{ - {"", ""}, - {"hello", "hello"}, - {"h%6", "h%6"}, - {"%G0", "%G0"}, - {"系统", "系统"}, - {"Hello, 世界", "Hello, 世界"}, - - {string([]byte{0xff, 0xfe, 0xfd}), "���"}, - {string([]byte{0xff}) + "Hello" + string([]byte{0xfe}) + "世界" + string([]byte{0xfd}), "�Hello�世界�"}, - } - for _, tC := range testCases { - got := decodeGrpcMessage(encodeGrpcMessage(tC.orig)) - if got != tC.want { - t.Errorf("decodeGrpcMessage(encodeGrpcMessage(%q)) = %q, want %q", tC.orig, got, tC.want) - } - } -} - -const binaryValue = string(128) - -func TestEncodeMetadataHeader(t *testing.T) { - for _, test := range []struct { - // input - kin string - vin string - // output - vout string - }{ - {"key", "abc", "abc"}, - {"KEY", "abc", "abc"}, - {"key-bin", "abc", "YWJj"}, - {"key-bin", binaryValue, "woA"}, - } { - v := encodeMetadataHeader(test.kin, test.vin) - if !reflect.DeepEqual(v, test.vout) { - t.Fatalf("encodeMetadataHeader(%q, %q) = %q, want %q", test.kin, test.vin, v, test.vout) - } - } -} - -func TestDecodeMetadataHeader(t *testing.T) { - for _, test := range []struct { - // input - kin string - vin string - // output - vout string - err error - }{ - {"a", "abc", "abc", nil}, - {"key-bin", "Zm9vAGJhcg==", "foo\x00bar", nil}, - {"key-bin", "Zm9vAGJhcg", "foo\x00bar", nil}, - {"key-bin", "woA=", binaryValue, nil}, - {"a", "abc,efg", "abc,efg", nil}, - } { - v, err := decodeMetadataHeader(test.kin, test.vin) - if !reflect.DeepEqual(v, test.vout) || !reflect.DeepEqual(err, test.err) { - t.Fatalf("decodeMetadataHeader(%q, %q) = %q, %v, want %q, %v", test.kin, test.vin, v, err, test.vout, test.err) - } - } -} diff --git a/vendor/google.golang.org/grpc/internal/transport/transport_test.go b/vendor/google.golang.org/grpc/internal/transport/transport_test.go deleted file mode 100644 index 91b6b95f..00000000 --- a/vendor/google.golang.org/grpc/internal/transport/transport_test.go +++ /dev/null @@ -1,2375 +0,0 @@ -/* - * - * Copyright 2014 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package transport - -import ( - "bufio" - "bytes" - "context" - "encoding/binary" - "errors" - "fmt" - "io" - "math" - "net" - "net/http" - "reflect" - "runtime" - "strconv" - "strings" - "sync" - "testing" - "time" - - "golang.org/x/net/http2" - "golang.org/x/net/http2/hpack" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/internal/leakcheck" - "google.golang.org/grpc/internal/syscall" - "google.golang.org/grpc/keepalive" - "google.golang.org/grpc/status" -) - -type server struct { - lis net.Listener - port string - startedErr chan error // error (or nil) with server start value - mu sync.Mutex - conns map[ServerTransport]bool - h *testStreamHandler - ready chan struct{} -} - -var ( - expectedRequest = []byte("ping") - expectedResponse = []byte("pong") - expectedRequestLarge = make([]byte, initialWindowSize*2) - expectedResponseLarge = make([]byte, initialWindowSize*2) - expectedInvalidHeaderField = "invalid/content-type" -) - -type testStreamHandler struct { - t *http2Server - notify chan struct{} - getNotified chan struct{} -} - -type hType int - -const ( - normal hType = iota - suspended - notifyCall - misbehaved - encodingRequiredStatus - invalidHeaderField - delayRead - pingpong -) - -func (h *testStreamHandler) handleStreamAndNotify(s *Stream) { - if h.notify == nil { - return - } - go func() { - select { - case <-h.notify: - default: - close(h.notify) - } - }() -} - -func (h *testStreamHandler) handleStream(t *testing.T, s *Stream) { - req := expectedRequest - resp := expectedResponse - if s.Method() == "foo.Large" { - req = expectedRequestLarge - resp = expectedResponseLarge - } - p := make([]byte, len(req)) - _, err := s.Read(p) - if err != nil { - return - } - if !bytes.Equal(p, req) { - t.Fatalf("handleStream got %v, want %v", p, req) - } - // send a response back to the client. - h.t.Write(s, nil, resp, &Options{}) - // send the trailer to end the stream. - h.t.WriteStatus(s, status.New(codes.OK, "")) -} - -func (h *testStreamHandler) handleStreamPingPong(t *testing.T, s *Stream) { - header := make([]byte, 5) - for { - if _, err := s.Read(header); err != nil { - if err == io.EOF { - h.t.WriteStatus(s, status.New(codes.OK, "")) - return - } - t.Fatalf("Error on server while reading data header: %v", err) - } - sz := binary.BigEndian.Uint32(header[1:]) - msg := make([]byte, int(sz)) - if _, err := s.Read(msg); err != nil { - t.Fatalf("Error on server while reading message: %v", err) - } - buf := make([]byte, sz+5) - buf[0] = byte(0) - binary.BigEndian.PutUint32(buf[1:], uint32(sz)) - copy(buf[5:], msg) - h.t.Write(s, nil, buf, &Options{}) - } -} - -func (h *testStreamHandler) handleStreamMisbehave(t *testing.T, s *Stream) { - conn, ok := s.st.(*http2Server) - if !ok { - t.Fatalf("Failed to convert %v to *http2Server", s.st) - } - var sent int - p := make([]byte, http2MaxFrameLen) - for sent < initialWindowSize { - n := initialWindowSize - sent - // The last message may be smaller than http2MaxFrameLen - if n <= http2MaxFrameLen { - if s.Method() == "foo.Connection" { - // Violate connection level flow control window of client but do not - // violate any stream level windows. - p = make([]byte, n) - } else { - // Violate stream level flow control window of client. - p = make([]byte, n+1) - } - } - conn.controlBuf.put(&dataFrame{ - streamID: s.id, - h: nil, - d: p, - onEachWrite: func() {}, - }) - sent += len(p) - } -} - -func (h *testStreamHandler) handleStreamEncodingRequiredStatus(t *testing.T, s *Stream) { - // raw newline is not accepted by http2 framer so it must be encoded. - h.t.WriteStatus(s, encodingTestStatus) -} - -func (h *testStreamHandler) handleStreamInvalidHeaderField(t *testing.T, s *Stream) { - headerFields := []hpack.HeaderField{} - headerFields = append(headerFields, hpack.HeaderField{Name: "content-type", Value: expectedInvalidHeaderField}) - h.t.controlBuf.put(&headerFrame{ - streamID: s.id, - hf: headerFields, - endStream: false, - }) -} - -// handleStreamDelayRead delays reads so that the other side has to halt on -// stream-level flow control. -// This handler assumes dynamic flow control is turned off and assumes window -// sizes to be set to defaultWindowSize. -func (h *testStreamHandler) handleStreamDelayRead(t *testing.T, s *Stream) { - req := expectedRequest - resp := expectedResponse - if s.Method() == "foo.Large" { - req = expectedRequestLarge - resp = expectedResponseLarge - } - var ( - mu sync.Mutex - total int - ) - s.wq.replenish = func(n int) { - mu.Lock() - total += n - mu.Unlock() - s.wq.realReplenish(n) - } - getTotal := func() int { - mu.Lock() - defer mu.Unlock() - return total - } - done := make(chan struct{}) - defer close(done) - go func() { - for { - select { - // Prevent goroutine from leaking. - case <-done: - return - default: - } - if getTotal() == defaultWindowSize { - // Signal the client to start reading and - // thereby send window update. - close(h.notify) - return - } - runtime.Gosched() - } - }() - p := make([]byte, len(req)) - - // Let the other side run out of stream-level window before - // starting to read and thereby sending a window update. - timer := time.NewTimer(time.Second * 10) - select { - case <-h.getNotified: - timer.Stop() - case <-timer.C: - t.Errorf("Server timed-out.") - return - } - _, err := s.Read(p) - if err != nil { - t.Errorf("s.Read(_) = _, %v, want _, ", err) - return - } - - if !bytes.Equal(p, req) { - t.Errorf("handleStream got %v, want %v", p, req) - return - } - // This write will cause server to run out of stream level, - // flow control and the other side won't send a window update - // until that happens. - if err := h.t.Write(s, nil, resp, &Options{}); err != nil { - t.Errorf("server Write got %v, want ", err) - return - } - // Read one more time to ensure that everything remains fine and - // that the goroutine, that we launched earlier to signal client - // to read, gets enough time to process. - _, err = s.Read(p) - if err != nil { - t.Errorf("s.Read(_) = _, %v, want _, nil", err) - return - } - // send the trailer to end the stream. - if err := h.t.WriteStatus(s, status.New(codes.OK, "")); err != nil { - t.Errorf("server WriteStatus got %v, want ", err) - return - } -} - -// start starts server. Other goroutines should block on s.readyChan for further operations. -func (s *server) start(t *testing.T, port int, serverConfig *ServerConfig, ht hType) { - var err error - if port == 0 { - s.lis, err = net.Listen("tcp", "localhost:0") - } else { - s.lis, err = net.Listen("tcp", "localhost:"+strconv.Itoa(port)) - } - if err != nil { - s.startedErr <- fmt.Errorf("failed to listen: %v", err) - return - } - _, p, err := net.SplitHostPort(s.lis.Addr().String()) - if err != nil { - s.startedErr <- fmt.Errorf("failed to parse listener address: %v", err) - return - } - s.port = p - s.conns = make(map[ServerTransport]bool) - s.startedErr <- nil - for { - conn, err := s.lis.Accept() - if err != nil { - return - } - transport, err := NewServerTransport("http2", conn, serverConfig) - if err != nil { - return - } - s.mu.Lock() - if s.conns == nil { - s.mu.Unlock() - transport.Close() - return - } - s.conns[transport] = true - h := &testStreamHandler{t: transport.(*http2Server)} - s.h = h - s.mu.Unlock() - switch ht { - case notifyCall: - go transport.HandleStreams(h.handleStreamAndNotify, - func(ctx context.Context, _ string) context.Context { - return ctx - }) - case suspended: - go transport.HandleStreams(func(*Stream) {}, // Do nothing to handle the stream. - func(ctx context.Context, method string) context.Context { - return ctx - }) - case misbehaved: - go transport.HandleStreams(func(s *Stream) { - go h.handleStreamMisbehave(t, s) - }, func(ctx context.Context, method string) context.Context { - return ctx - }) - case encodingRequiredStatus: - go transport.HandleStreams(func(s *Stream) { - go h.handleStreamEncodingRequiredStatus(t, s) - }, func(ctx context.Context, method string) context.Context { - return ctx - }) - case invalidHeaderField: - go transport.HandleStreams(func(s *Stream) { - go h.handleStreamInvalidHeaderField(t, s) - }, func(ctx context.Context, method string) context.Context { - return ctx - }) - case delayRead: - h.notify = make(chan struct{}) - h.getNotified = make(chan struct{}) - s.mu.Lock() - close(s.ready) - s.mu.Unlock() - go transport.HandleStreams(func(s *Stream) { - go h.handleStreamDelayRead(t, s) - }, func(ctx context.Context, method string) context.Context { - return ctx - }) - case pingpong: - go transport.HandleStreams(func(s *Stream) { - go h.handleStreamPingPong(t, s) - }, func(ctx context.Context, method string) context.Context { - return ctx - }) - default: - go transport.HandleStreams(func(s *Stream) { - go h.handleStream(t, s) - }, func(ctx context.Context, method string) context.Context { - return ctx - }) - } - } -} - -func (s *server) wait(t *testing.T, timeout time.Duration) { - select { - case err := <-s.startedErr: - if err != nil { - t.Fatal(err) - } - case <-time.After(timeout): - t.Fatalf("Timed out after %v waiting for server to be ready", timeout) - } -} - -func (s *server) stop() { - s.lis.Close() - s.mu.Lock() - for c := range s.conns { - c.Close() - } - s.conns = nil - s.mu.Unlock() -} - -func setUpServerOnly(t *testing.T, port int, serverConfig *ServerConfig, ht hType) *server { - server := &server{startedErr: make(chan error, 1), ready: make(chan struct{})} - go server.start(t, port, serverConfig, ht) - server.wait(t, 2*time.Second) - return server -} - -func setUp(t *testing.T, port int, maxStreams uint32, ht hType) (*server, *http2Client, func()) { - return setUpWithOptions(t, port, &ServerConfig{MaxStreams: maxStreams}, ht, ConnectOptions{}) -} - -func setUpWithOptions(t *testing.T, port int, serverConfig *ServerConfig, ht hType, copts ConnectOptions) (*server, *http2Client, func()) { - server := setUpServerOnly(t, port, serverConfig, ht) - addr := "localhost:" + server.port - target := TargetInfo{ - Addr: addr, - } - connectCtx, cancel := context.WithDeadline(context.Background(), time.Now().Add(2*time.Second)) - ct, connErr := NewClientTransport(connectCtx, context.Background(), target, copts, func() {}, func(GoAwayReason) {}, func() {}) - if connErr != nil { - cancel() // Do not cancel in success path. - t.Fatalf("failed to create transport: %v", connErr) - } - return server, ct.(*http2Client), cancel -} - -func setUpWithNoPingServer(t *testing.T, copts ConnectOptions, done chan net.Conn) (*http2Client, func()) { - lis, err := net.Listen("tcp", "localhost:0") - if err != nil { - t.Fatalf("Failed to listen: %v", err) - } - // Launch a non responsive server. - go func() { - defer lis.Close() - conn, err := lis.Accept() - if err != nil { - t.Errorf("Error at server-side while accepting: %v", err) - close(done) - return - } - done <- conn - }() - connectCtx, cancel := context.WithDeadline(context.Background(), time.Now().Add(2*time.Second)) - tr, err := NewClientTransport(connectCtx, context.Background(), TargetInfo{Addr: lis.Addr().String()}, copts, func() {}, func(GoAwayReason) {}, func() {}) - if err != nil { - cancel() // Do not cancel in success path. - // Server clean-up. - lis.Close() - if conn, ok := <-done; ok { - conn.Close() - } - t.Fatalf("Failed to dial: %v", err) - } - return tr.(*http2Client), cancel -} - -// TestInflightStreamClosing ensures that closing in-flight stream -// sends status error to concurrent stream reader. -func TestInflightStreamClosing(t *testing.T) { - serverConfig := &ServerConfig{} - server, client, cancel := setUpWithOptions(t, 0, serverConfig, suspended, ConnectOptions{}) - defer cancel() - defer server.stop() - defer client.Close() - - stream, err := client.NewStream(context.Background(), &CallHdr{}) - if err != nil { - t.Fatalf("Client failed to create RPC request: %v", err) - } - - donec := make(chan struct{}) - serr := status.Error(codes.Internal, "client connection is closing") - go func() { - defer close(donec) - if _, err := stream.Read(make([]byte, defaultWindowSize)); err != serr { - t.Errorf("unexpected Stream error %v, expected %v", err, serr) - } - }() - - // should unblock concurrent stream.Read - client.CloseStream(stream, serr) - - // wait for stream.Read error - timeout := time.NewTimer(5 * time.Second) - select { - case <-donec: - if !timeout.Stop() { - <-timeout.C - } - case <-timeout.C: - t.Fatalf("Test timed out, expected a status error.") - } -} - -// TestMaxConnectionIdle tests that a server will send GoAway to a idle client. -// An idle client is one who doesn't make any RPC calls for a duration of -// MaxConnectionIdle time. -func TestMaxConnectionIdle(t *testing.T) { - serverConfig := &ServerConfig{ - KeepaliveParams: keepalive.ServerParameters{ - MaxConnectionIdle: 2 * time.Second, - }, - } - server, client, cancel := setUpWithOptions(t, 0, serverConfig, suspended, ConnectOptions{}) - defer cancel() - defer server.stop() - defer client.Close() - stream, err := client.NewStream(context.Background(), &CallHdr{}) - if err != nil { - t.Fatalf("Client failed to create RPC request: %v", err) - } - client.closeStream(stream, io.EOF, true, http2.ErrCodeCancel, nil, nil, false) - // wait for server to see that closed stream and max-age logic to send goaway after no new RPCs are mode - timeout := time.NewTimer(time.Second * 4) - select { - case <-client.GoAway(): - if !timeout.Stop() { - <-timeout.C - } - case <-timeout.C: - t.Fatalf("Test timed out, expected a GoAway from the server.") - } -} - -// TestMaxConenctionIdleNegative tests that a server will not send GoAway to a non-idle(busy) client. -func TestMaxConnectionIdleNegative(t *testing.T) { - serverConfig := &ServerConfig{ - KeepaliveParams: keepalive.ServerParameters{ - MaxConnectionIdle: 2 * time.Second, - }, - } - server, client, cancel := setUpWithOptions(t, 0, serverConfig, suspended, ConnectOptions{}) - defer cancel() - defer server.stop() - defer client.Close() - _, err := client.NewStream(context.Background(), &CallHdr{}) - if err != nil { - t.Fatalf("Client failed to create RPC request: %v", err) - } - timeout := time.NewTimer(time.Second * 4) - select { - case <-client.GoAway(): - if !timeout.Stop() { - <-timeout.C - } - t.Fatalf("A non-idle client received a GoAway.") - case <-timeout.C: - } - -} - -// TestMaxConnectionAge tests that a server will send GoAway after a duration of MaxConnectionAge. -func TestMaxConnectionAge(t *testing.T) { - serverConfig := &ServerConfig{ - KeepaliveParams: keepalive.ServerParameters{ - MaxConnectionAge: 2 * time.Second, - }, - } - server, client, cancel := setUpWithOptions(t, 0, serverConfig, suspended, ConnectOptions{}) - defer cancel() - defer server.stop() - defer client.Close() - _, err := client.NewStream(context.Background(), &CallHdr{}) - if err != nil { - t.Fatalf("Client failed to create stream: %v", err) - } - // Wait for max-age logic to send GoAway. - timeout := time.NewTimer(4 * time.Second) - select { - case <-client.GoAway(): - if !timeout.Stop() { - <-timeout.C - } - case <-timeout.C: - t.Fatalf("Test timer out, expected a GoAway from the server.") - } -} - -const ( - defaultWriteBufSize = 32 * 1024 - defaultReadBufSize = 32 * 1024 -) - -// TestKeepaliveServer tests that a server closes connection with a client that doesn't respond to keepalive pings. -func TestKeepaliveServer(t *testing.T) { - serverConfig := &ServerConfig{ - KeepaliveParams: keepalive.ServerParameters{ - Time: 2 * time.Second, - Timeout: 1 * time.Second, - }, - } - server, c, cancel := setUpWithOptions(t, 0, serverConfig, suspended, ConnectOptions{}) - defer cancel() - defer server.stop() - defer c.Close() - client, err := net.Dial("tcp", server.lis.Addr().String()) - if err != nil { - t.Fatalf("Failed to dial: %v", err) - } - defer client.Close() - - // Set read deadline on client conn so that it doesn't block forever in errorsome cases. - client.SetDeadline(time.Now().Add(10 * time.Second)) - - if n, err := client.Write(clientPreface); err != nil || n != len(clientPreface) { - t.Fatalf("Error writing client preface; n=%v, err=%v", n, err) - } - framer := newFramer(client, defaultWriteBufSize, defaultReadBufSize, 0) - if err := framer.fr.WriteSettings(http2.Setting{}); err != nil { - t.Fatal("Error writing settings frame:", err) - } - framer.writer.Flush() - // Wait for keepalive logic to close the connection. - time.Sleep(4 * time.Second) - b := make([]byte, 24) - for { - _, err = client.Read(b) - if err == nil { - continue - } - if err != io.EOF { - t.Fatalf("client.Read(_) = _,%v, want io.EOF", err) - } - break - } -} - -// TestKeepaliveServerNegative tests that a server doesn't close connection with a client that responds to keepalive pings. -func TestKeepaliveServerNegative(t *testing.T) { - serverConfig := &ServerConfig{ - KeepaliveParams: keepalive.ServerParameters{ - Time: 2 * time.Second, - Timeout: 1 * time.Second, - }, - } - server, client, cancel := setUpWithOptions(t, 0, serverConfig, suspended, ConnectOptions{}) - defer cancel() - defer server.stop() - defer client.Close() - // Give keepalive logic some time by sleeping. - time.Sleep(4 * time.Second) - // Assert that client is still active. - client.mu.Lock() - defer client.mu.Unlock() - if client.state != reachable { - t.Fatalf("Test failed: Expected server-client connection to be healthy.") - } -} - -func TestKeepaliveClientClosesIdleTransport(t *testing.T) { - done := make(chan net.Conn, 1) - tr, cancel := setUpWithNoPingServer(t, ConnectOptions{KeepaliveParams: keepalive.ClientParameters{ - Time: 2 * time.Second, // Keepalive time = 2 sec. - Timeout: 1 * time.Second, // Keepalive timeout = 1 sec. - PermitWithoutStream: true, // Run keepalive even with no RPCs. - }}, done) - defer cancel() - defer tr.Close() - conn, ok := <-done - if !ok { - t.Fatalf("Server didn't return connection object") - } - defer conn.Close() - // Sleep for keepalive to close the connection. - time.Sleep(4 * time.Second) - // Assert that the connection was closed. - tr.mu.Lock() - defer tr.mu.Unlock() - if tr.state == reachable { - t.Fatalf("Test Failed: Expected client transport to have closed.") - } -} - -func TestKeepaliveClientStaysHealthyOnIdleTransport(t *testing.T) { - done := make(chan net.Conn, 1) - tr, cancel := setUpWithNoPingServer(t, ConnectOptions{KeepaliveParams: keepalive.ClientParameters{ - Time: 2 * time.Second, // Keepalive time = 2 sec. - Timeout: 1 * time.Second, // Keepalive timeout = 1 sec. - }}, done) - defer cancel() - defer tr.Close() - conn, ok := <-done - if !ok { - t.Fatalf("server didn't reutrn connection object") - } - defer conn.Close() - // Give keepalive some time. - time.Sleep(4 * time.Second) - // Assert that connections is still healthy. - tr.mu.Lock() - defer tr.mu.Unlock() - if tr.state != reachable { - t.Fatalf("Test failed: Expected client transport to be healthy.") - } -} - -func TestKeepaliveClientClosesWithActiveStreams(t *testing.T) { - done := make(chan net.Conn, 1) - tr, cancel := setUpWithNoPingServer(t, ConnectOptions{KeepaliveParams: keepalive.ClientParameters{ - Time: 2 * time.Second, // Keepalive time = 2 sec. - Timeout: 1 * time.Second, // Keepalive timeout = 1 sec. - }}, done) - defer cancel() - defer tr.Close() - conn, ok := <-done - if !ok { - t.Fatalf("Server didn't return connection object") - } - defer conn.Close() - // Create a stream. - _, err := tr.NewStream(context.Background(), &CallHdr{}) - if err != nil { - t.Fatalf("Failed to create a new stream: %v", err) - } - // Give keepalive some time. - time.Sleep(4 * time.Second) - // Assert that transport was closed. - tr.mu.Lock() - defer tr.mu.Unlock() - if tr.state == reachable { - t.Fatalf("Test failed: Expected client transport to have closed.") - } -} - -func TestKeepaliveClientStaysHealthyWithResponsiveServer(t *testing.T) { - s, tr, cancel := setUpWithOptions(t, 0, &ServerConfig{MaxStreams: math.MaxUint32}, normal, ConnectOptions{KeepaliveParams: keepalive.ClientParameters{ - Time: 2 * time.Second, // Keepalive time = 2 sec. - Timeout: 1 * time.Second, // Keepalive timeout = 1 sec. - PermitWithoutStream: true, // Run keepalive even with no RPCs. - }}) - defer cancel() - defer s.stop() - defer tr.Close() - // Give keep alive some time. - time.Sleep(4 * time.Second) - // Assert that transport is healthy. - tr.mu.Lock() - defer tr.mu.Unlock() - if tr.state != reachable { - t.Fatalf("Test failed: Expected client transport to be healthy.") - } -} - -func TestKeepaliveServerEnforcementWithAbusiveClientNoRPC(t *testing.T) { - serverConfig := &ServerConfig{ - KeepalivePolicy: keepalive.EnforcementPolicy{ - MinTime: 2 * time.Second, - }, - } - clientOptions := ConnectOptions{ - KeepaliveParams: keepalive.ClientParameters{ - Time: 50 * time.Millisecond, - Timeout: 1 * time.Second, - PermitWithoutStream: true, - }, - } - server, client, cancel := setUpWithOptions(t, 0, serverConfig, normal, clientOptions) - defer cancel() - defer server.stop() - defer client.Close() - - timeout := time.NewTimer(10 * time.Second) - select { - case <-client.GoAway(): - if !timeout.Stop() { - <-timeout.C - } - case <-timeout.C: - t.Fatalf("Test failed: Expected a GoAway from server.") - } - time.Sleep(500 * time.Millisecond) - client.mu.Lock() - defer client.mu.Unlock() - if client.state == reachable { - t.Fatalf("Test failed: Expected the connection to be closed.") - } -} - -func TestKeepaliveServerEnforcementWithAbusiveClientWithRPC(t *testing.T) { - serverConfig := &ServerConfig{ - KeepalivePolicy: keepalive.EnforcementPolicy{ - MinTime: 2 * time.Second, - }, - } - clientOptions := ConnectOptions{ - KeepaliveParams: keepalive.ClientParameters{ - Time: 50 * time.Millisecond, - Timeout: 1 * time.Second, - }, - } - server, client, cancel := setUpWithOptions(t, 0, serverConfig, suspended, clientOptions) - defer cancel() - defer server.stop() - defer client.Close() - - if _, err := client.NewStream(context.Background(), &CallHdr{}); err != nil { - t.Fatalf("Client failed to create stream.") - } - timeout := time.NewTimer(10 * time.Second) - select { - case <-client.GoAway(): - if !timeout.Stop() { - <-timeout.C - } - case <-timeout.C: - t.Fatalf("Test failed: Expected a GoAway from server.") - } - time.Sleep(500 * time.Millisecond) - client.mu.Lock() - defer client.mu.Unlock() - if client.state == reachable { - t.Fatalf("Test failed: Expected the connection to be closed.") - } -} - -func TestKeepaliveServerEnforcementWithObeyingClientNoRPC(t *testing.T) { - serverConfig := &ServerConfig{ - KeepalivePolicy: keepalive.EnforcementPolicy{ - MinTime: 100 * time.Millisecond, - PermitWithoutStream: true, - }, - } - clientOptions := ConnectOptions{ - KeepaliveParams: keepalive.ClientParameters{ - Time: 101 * time.Millisecond, - Timeout: 1 * time.Second, - PermitWithoutStream: true, - }, - } - server, client, cancel := setUpWithOptions(t, 0, serverConfig, normal, clientOptions) - defer cancel() - defer server.stop() - defer client.Close() - - // Give keepalive enough time. - time.Sleep(3 * time.Second) - // Assert that connection is healthy. - client.mu.Lock() - defer client.mu.Unlock() - if client.state != reachable { - t.Fatalf("Test failed: Expected connection to be healthy.") - } -} - -func TestKeepaliveServerEnforcementWithObeyingClientWithRPC(t *testing.T) { - serverConfig := &ServerConfig{ - KeepalivePolicy: keepalive.EnforcementPolicy{ - MinTime: 100 * time.Millisecond, - }, - } - clientOptions := ConnectOptions{ - KeepaliveParams: keepalive.ClientParameters{ - Time: 101 * time.Millisecond, - Timeout: 1 * time.Second, - }, - } - server, client, cancel := setUpWithOptions(t, 0, serverConfig, suspended, clientOptions) - defer cancel() - defer server.stop() - defer client.Close() - - if _, err := client.NewStream(context.Background(), &CallHdr{}); err != nil { - t.Fatalf("Client failed to create stream.") - } - - // Give keepalive enough time. - time.Sleep(3 * time.Second) - // Assert that connection is healthy. - client.mu.Lock() - defer client.mu.Unlock() - if client.state != reachable { - t.Fatalf("Test failed: Expected connection to be healthy.") - } -} - -func TestClientSendAndReceive(t *testing.T) { - server, ct, cancel := setUp(t, 0, math.MaxUint32, normal) - defer cancel() - callHdr := &CallHdr{ - Host: "localhost", - Method: "foo.Small", - } - s1, err1 := ct.NewStream(context.Background(), callHdr) - if err1 != nil { - t.Fatalf("failed to open stream: %v", err1) - } - if s1.id != 1 { - t.Fatalf("wrong stream id: %d", s1.id) - } - s2, err2 := ct.NewStream(context.Background(), callHdr) - if err2 != nil { - t.Fatalf("failed to open stream: %v", err2) - } - if s2.id != 3 { - t.Fatalf("wrong stream id: %d", s2.id) - } - opts := Options{Last: true} - if err := ct.Write(s1, nil, expectedRequest, &opts); err != nil && err != io.EOF { - t.Fatalf("failed to send data: %v", err) - } - p := make([]byte, len(expectedResponse)) - _, recvErr := s1.Read(p) - if recvErr != nil || !bytes.Equal(p, expectedResponse) { - t.Fatalf("Error: %v, want ; Result: %v, want %v", recvErr, p, expectedResponse) - } - _, recvErr = s1.Read(p) - if recvErr != io.EOF { - t.Fatalf("Error: %v; want ", recvErr) - } - ct.Close() - server.stop() -} - -func TestClientErrorNotify(t *testing.T) { - server, ct, cancel := setUp(t, 0, math.MaxUint32, normal) - defer cancel() - go server.stop() - // ct.reader should detect the error and activate ct.Error(). - <-ct.Error() - ct.Close() -} - -func performOneRPC(ct ClientTransport) { - callHdr := &CallHdr{ - Host: "localhost", - Method: "foo.Small", - } - s, err := ct.NewStream(context.Background(), callHdr) - if err != nil { - return - } - opts := Options{Last: true} - if err := ct.Write(s, []byte{}, expectedRequest, &opts); err == nil || err == io.EOF { - time.Sleep(5 * time.Millisecond) - // The following s.Recv()'s could error out because the - // underlying transport is gone. - // - // Read response - p := make([]byte, len(expectedResponse)) - s.Read(p) - // Read io.EOF - s.Read(p) - } -} - -func TestClientMix(t *testing.T) { - s, ct, cancel := setUp(t, 0, math.MaxUint32, normal) - defer cancel() - go func(s *server) { - time.Sleep(5 * time.Second) - s.stop() - }(s) - go func(ct ClientTransport) { - <-ct.Error() - ct.Close() - }(ct) - for i := 0; i < 1000; i++ { - time.Sleep(10 * time.Millisecond) - go performOneRPC(ct) - } -} - -func TestLargeMessage(t *testing.T) { - server, ct, cancel := setUp(t, 0, math.MaxUint32, normal) - defer cancel() - callHdr := &CallHdr{ - Host: "localhost", - Method: "foo.Large", - } - var wg sync.WaitGroup - for i := 0; i < 2; i++ { - wg.Add(1) - go func() { - defer wg.Done() - s, err := ct.NewStream(context.Background(), callHdr) - if err != nil { - t.Errorf("%v.NewStream(_, _) = _, %v, want _, ", ct, err) - } - if err := ct.Write(s, []byte{}, expectedRequestLarge, &Options{Last: true}); err != nil && err != io.EOF { - t.Errorf("%v.Write(_, _, _) = %v, want ", ct, err) - } - p := make([]byte, len(expectedResponseLarge)) - if _, err := s.Read(p); err != nil || !bytes.Equal(p, expectedResponseLarge) { - t.Errorf("s.Read(%v) = _, %v, want %v, ", err, p, expectedResponse) - } - if _, err = s.Read(p); err != io.EOF { - t.Errorf("Failed to complete the stream %v; want ", err) - } - }() - } - wg.Wait() - ct.Close() - server.stop() -} - -func TestLargeMessageWithDelayRead(t *testing.T) { - // Disable dynamic flow control. - sc := &ServerConfig{ - InitialWindowSize: defaultWindowSize, - InitialConnWindowSize: defaultWindowSize, - } - co := ConnectOptions{ - InitialWindowSize: defaultWindowSize, - InitialConnWindowSize: defaultWindowSize, - } - server, ct, cancel := setUpWithOptions(t, 0, sc, delayRead, co) - defer cancel() - defer server.stop() - defer ct.Close() - server.mu.Lock() - ready := server.ready - server.mu.Unlock() - callHdr := &CallHdr{ - Host: "localhost", - Method: "foo.Large", - } - ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(time.Second*10)) - defer cancel() - s, err := ct.NewStream(ctx, callHdr) - if err != nil { - t.Fatalf("%v.NewStream(_, _) = _, %v, want _, ", ct, err) - return - } - // Wait for server's handerler to be initialized - select { - case <-ready: - case <-ctx.Done(): - t.Fatalf("Client timed out waiting for server handler to be initialized.") - } - server.mu.Lock() - serviceHandler := server.h - server.mu.Unlock() - var ( - mu sync.Mutex - total int - ) - s.wq.replenish = func(n int) { - mu.Lock() - total += n - mu.Unlock() - s.wq.realReplenish(n) - } - getTotal := func() int { - mu.Lock() - defer mu.Unlock() - return total - } - done := make(chan struct{}) - defer close(done) - go func() { - for { - select { - // Prevent goroutine from leaking in case of error. - case <-done: - return - default: - } - if getTotal() == defaultWindowSize { - // unblock server to be able to read and - // thereby send stream level window update. - close(serviceHandler.getNotified) - return - } - runtime.Gosched() - } - }() - // This write will cause client to run out of stream level, - // flow control and the other side won't send a window update - // until that happens. - if err := ct.Write(s, []byte{}, expectedRequestLarge, &Options{}); err != nil { - t.Fatalf("write(_, _, _) = %v, want ", err) - } - p := make([]byte, len(expectedResponseLarge)) - - // Wait for the other side to run out of stream level flow control before - // reading and thereby sending a window update. - select { - case <-serviceHandler.notify: - case <-ctx.Done(): - t.Fatalf("Client timed out") - } - if _, err := s.Read(p); err != nil || !bytes.Equal(p, expectedResponseLarge) { - t.Fatalf("s.Read(_) = _, %v, want _, ", err) - } - if err := ct.Write(s, []byte{}, expectedRequestLarge, &Options{Last: true}); err != nil { - t.Fatalf("Write(_, _, _) = %v, want ", err) - } - if _, err = s.Read(p); err != io.EOF { - t.Fatalf("Failed to complete the stream %v; want ", err) - } -} - -func TestGracefulClose(t *testing.T) { - server, ct, cancel := setUp(t, 0, math.MaxUint32, pingpong) - defer cancel() - defer func() { - // Stop the server's listener to make the server's goroutines terminate - // (after the last active stream is done). - server.lis.Close() - // Check for goroutine leaks (i.e. GracefulClose with an active stream - // doesn't eventually close the connection when that stream completes). - leakcheck.Check(t) - // Correctly clean up the server - server.stop() - }() - ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(time.Second*10)) - defer cancel() - s, err := ct.NewStream(ctx, &CallHdr{}) - if err != nil { - t.Fatalf("NewStream(_, _) = _, %v, want _, ", err) - } - msg := make([]byte, 1024) - outgoingHeader := make([]byte, 5) - outgoingHeader[0] = byte(0) - binary.BigEndian.PutUint32(outgoingHeader[1:], uint32(len(msg))) - incomingHeader := make([]byte, 5) - if err := ct.Write(s, outgoingHeader, msg, &Options{}); err != nil { - t.Fatalf("Error while writing: %v", err) - } - if _, err := s.Read(incomingHeader); err != nil { - t.Fatalf("Error while reading: %v", err) - } - sz := binary.BigEndian.Uint32(incomingHeader[1:]) - recvMsg := make([]byte, int(sz)) - if _, err := s.Read(recvMsg); err != nil { - t.Fatalf("Error while reading: %v", err) - } - if err = ct.GracefulClose(); err != nil { - t.Fatalf("GracefulClose() = %v, want ", err) - } - var wg sync.WaitGroup - // Expect the failure for all the follow-up streams because ct has been closed gracefully. - for i := 0; i < 200; i++ { - wg.Add(1) - go func() { - defer wg.Done() - str, err := ct.NewStream(context.Background(), &CallHdr{}) - if err == ErrConnClosing { - return - } else if err != nil { - t.Errorf("_.NewStream(_, _) = _, %v, want _, %v", err, ErrConnClosing) - return - } - ct.Write(str, nil, nil, &Options{Last: true}) - if _, err := str.Read(make([]byte, 8)); err != errStreamDrain && err != ErrConnClosing { - t.Errorf("_.Read(_) = _, %v, want _, %v or %v", err, errStreamDrain, ErrConnClosing) - } - }() - } - ct.Write(s, nil, nil, &Options{Last: true}) - if _, err := s.Read(incomingHeader); err != io.EOF { - t.Fatalf("Client expected EOF from the server. Got: %v", err) - } - // The stream which was created before graceful close can still proceed. - wg.Wait() -} - -func TestLargeMessageSuspension(t *testing.T) { - server, ct, cancel := setUp(t, 0, math.MaxUint32, suspended) - defer cancel() - callHdr := &CallHdr{ - Host: "localhost", - Method: "foo.Large", - } - // Set a long enough timeout for writing a large message out. - ctx, cancel := context.WithTimeout(context.Background(), time.Second) - defer cancel() - s, err := ct.NewStream(ctx, callHdr) - if err != nil { - t.Fatalf("failed to open stream: %v", err) - } - // Launch a goroutine simillar to the stream monitoring goroutine in - // stream.go to keep track of context timeout and call CloseStream. - go func() { - <-ctx.Done() - ct.CloseStream(s, ContextErr(ctx.Err())) - }() - // Write should not be done successfully due to flow control. - msg := make([]byte, initialWindowSize*8) - ct.Write(s, nil, msg, &Options{}) - err = ct.Write(s, nil, msg, &Options{Last: true}) - if err != errStreamDone { - t.Fatalf("Write got %v, want io.EOF", err) - } - expectedErr := status.Error(codes.DeadlineExceeded, context.DeadlineExceeded.Error()) - if _, err := s.Read(make([]byte, 8)); err.Error() != expectedErr.Error() { - t.Fatalf("Read got %v of type %T, want %v", err, err, expectedErr) - } - ct.Close() - server.stop() -} - -func TestMaxStreams(t *testing.T) { - serverConfig := &ServerConfig{ - MaxStreams: 1, - } - server, ct, cancel := setUpWithOptions(t, 0, serverConfig, suspended, ConnectOptions{}) - defer cancel() - defer ct.Close() - defer server.stop() - callHdr := &CallHdr{ - Host: "localhost", - Method: "foo.Large", - } - s, err := ct.NewStream(context.Background(), callHdr) - if err != nil { - t.Fatalf("Failed to open stream: %v", err) - } - // Keep creating streams until one fails with deadline exceeded, marking the application - // of server settings on client. - slist := []*Stream{} - pctx, cancel := context.WithCancel(context.Background()) - defer cancel() - timer := time.NewTimer(time.Second * 10) - expectedErr := status.Error(codes.DeadlineExceeded, context.DeadlineExceeded.Error()) - for { - select { - case <-timer.C: - t.Fatalf("Test timeout: client didn't receive server settings.") - default: - } - ctx, cancel := context.WithDeadline(pctx, time.Now().Add(time.Second)) - // This is only to get rid of govet. All these context are based on a base - // context which is canceled at the end of the test. - defer cancel() - if str, err := ct.NewStream(ctx, callHdr); err == nil { - slist = append(slist, str) - continue - } else if err.Error() != expectedErr.Error() { - t.Fatalf("ct.NewStream(_,_) = _, %v, want _, %v", err, expectedErr) - } - timer.Stop() - break - } - done := make(chan struct{}) - // Try and create a new stream. - go func() { - defer close(done) - ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(time.Second*10)) - defer cancel() - if _, err := ct.NewStream(ctx, callHdr); err != nil { - t.Errorf("Failed to open stream: %v", err) - } - }() - // Close all the extra streams created and make sure the new stream is not created. - for _, str := range slist { - ct.CloseStream(str, nil) - } - select { - case <-done: - t.Fatalf("Test failed: didn't expect new stream to be created just yet.") - default: - } - // Close the first stream created so that the new stream can finally be created. - ct.CloseStream(s, nil) - <-done - ct.Close() - <-ct.writerDone - if ct.maxConcurrentStreams != 1 { - t.Fatalf("ct.maxConcurrentStreams: %d, want 1", ct.maxConcurrentStreams) - } -} - -func TestServerContextCanceledOnClosedConnection(t *testing.T) { - server, ct, cancel := setUp(t, 0, math.MaxUint32, suspended) - defer cancel() - callHdr := &CallHdr{ - Host: "localhost", - Method: "foo", - } - var sc *http2Server - // Wait until the server transport is setup. - for { - server.mu.Lock() - if len(server.conns) == 0 { - server.mu.Unlock() - time.Sleep(time.Millisecond) - continue - } - for k := range server.conns { - var ok bool - sc, ok = k.(*http2Server) - if !ok { - t.Fatalf("Failed to convert %v to *http2Server", k) - } - } - server.mu.Unlock() - break - } - s, err := ct.NewStream(context.Background(), callHdr) - if err != nil { - t.Fatalf("Failed to open stream: %v", err) - } - ct.controlBuf.put(&dataFrame{ - streamID: s.id, - endStream: false, - h: nil, - d: make([]byte, http2MaxFrameLen), - onEachWrite: func() {}, - }) - // Loop until the server side stream is created. - var ss *Stream - for { - time.Sleep(time.Second) - sc.mu.Lock() - if len(sc.activeStreams) == 0 { - sc.mu.Unlock() - continue - } - ss = sc.activeStreams[s.id] - sc.mu.Unlock() - break - } - ct.Close() - select { - case <-ss.Context().Done(): - if ss.Context().Err() != context.Canceled { - t.Fatalf("ss.Context().Err() got %v, want %v", ss.Context().Err(), context.Canceled) - } - case <-time.After(5 * time.Second): - t.Fatalf("Failed to cancel the context of the sever side stream.") - } - server.stop() -} - -func TestClientConnDecoupledFromApplicationRead(t *testing.T) { - connectOptions := ConnectOptions{ - InitialWindowSize: defaultWindowSize, - InitialConnWindowSize: defaultWindowSize, - } - server, client, cancel := setUpWithOptions(t, 0, &ServerConfig{}, notifyCall, connectOptions) - defer cancel() - defer server.stop() - defer client.Close() - - waitWhileTrue(t, func() (bool, error) { - server.mu.Lock() - defer server.mu.Unlock() - - if len(server.conns) == 0 { - return true, fmt.Errorf("timed-out while waiting for connection to be created on the server") - } - return false, nil - }) - - var st *http2Server - server.mu.Lock() - for k := range server.conns { - st = k.(*http2Server) - } - notifyChan := make(chan struct{}) - server.h.notify = notifyChan - server.mu.Unlock() - cstream1, err := client.NewStream(context.Background(), &CallHdr{}) - if err != nil { - t.Fatalf("Client failed to create first stream. Err: %v", err) - } - - <-notifyChan - var sstream1 *Stream - // Access stream on the server. - st.mu.Lock() - for _, v := range st.activeStreams { - if v.id == cstream1.id { - sstream1 = v - } - } - st.mu.Unlock() - if sstream1 == nil { - t.Fatalf("Didn't find stream corresponding to client cstream.id: %v on the server", cstream1.id) - } - // Exhaust client's connection window. - if err := st.Write(sstream1, []byte{}, make([]byte, defaultWindowSize), &Options{}); err != nil { - t.Fatalf("Server failed to write data. Err: %v", err) - } - notifyChan = make(chan struct{}) - server.mu.Lock() - server.h.notify = notifyChan - server.mu.Unlock() - // Create another stream on client. - cstream2, err := client.NewStream(context.Background(), &CallHdr{}) - if err != nil { - t.Fatalf("Client failed to create second stream. Err: %v", err) - } - <-notifyChan - var sstream2 *Stream - st.mu.Lock() - for _, v := range st.activeStreams { - if v.id == cstream2.id { - sstream2 = v - } - } - st.mu.Unlock() - if sstream2 == nil { - t.Fatalf("Didn't find stream corresponding to client cstream.id: %v on the server", cstream2.id) - } - // Server should be able to send data on the new stream, even though the client hasn't read anything on the first stream. - if err := st.Write(sstream2, []byte{}, make([]byte, defaultWindowSize), &Options{}); err != nil { - t.Fatalf("Server failed to write data. Err: %v", err) - } - - // Client should be able to read data on second stream. - if _, err := cstream2.Read(make([]byte, defaultWindowSize)); err != nil { - t.Fatalf("_.Read(_) = _, %v, want _, ", err) - } - - // Client should be able to read data on first stream. - if _, err := cstream1.Read(make([]byte, defaultWindowSize)); err != nil { - t.Fatalf("_.Read(_) = _, %v, want _, ", err) - } -} - -func TestServerConnDecoupledFromApplicationRead(t *testing.T) { - serverConfig := &ServerConfig{ - InitialWindowSize: defaultWindowSize, - InitialConnWindowSize: defaultWindowSize, - } - server, client, cancel := setUpWithOptions(t, 0, serverConfig, suspended, ConnectOptions{}) - defer cancel() - defer server.stop() - defer client.Close() - waitWhileTrue(t, func() (bool, error) { - server.mu.Lock() - defer server.mu.Unlock() - - if len(server.conns) == 0 { - return true, fmt.Errorf("timed-out while waiting for connection to be created on the server") - } - return false, nil - }) - var st *http2Server - server.mu.Lock() - for k := range server.conns { - st = k.(*http2Server) - } - server.mu.Unlock() - cstream1, err := client.NewStream(context.Background(), &CallHdr{}) - if err != nil { - t.Fatalf("Failed to create 1st stream. Err: %v", err) - } - // Exhaust server's connection window. - if err := client.Write(cstream1, nil, make([]byte, defaultWindowSize), &Options{Last: true}); err != nil { - t.Fatalf("Client failed to write data. Err: %v", err) - } - //Client should be able to create another stream and send data on it. - cstream2, err := client.NewStream(context.Background(), &CallHdr{}) - if err != nil { - t.Fatalf("Failed to create 2nd stream. Err: %v", err) - } - if err := client.Write(cstream2, nil, make([]byte, defaultWindowSize), &Options{}); err != nil { - t.Fatalf("Client failed to write data. Err: %v", err) - } - // Get the streams on server. - waitWhileTrue(t, func() (bool, error) { - st.mu.Lock() - defer st.mu.Unlock() - - if len(st.activeStreams) != 2 { - return true, fmt.Errorf("timed-out while waiting for server to have created the streams") - } - return false, nil - }) - var sstream1 *Stream - st.mu.Lock() - for _, v := range st.activeStreams { - if v.id == 1 { - sstream1 = v - } - } - st.mu.Unlock() - // Reading from the stream on server should succeed. - if _, err := sstream1.Read(make([]byte, defaultWindowSize)); err != nil { - t.Fatalf("_.Read(_) = %v, want ", err) - } - - if _, err := sstream1.Read(make([]byte, 1)); err != io.EOF { - t.Fatalf("_.Read(_) = %v, want io.EOF", err) - } - -} - -func TestServerWithMisbehavedClient(t *testing.T) { - server := setUpServerOnly(t, 0, &ServerConfig{}, suspended) - defer server.stop() - // Create a client that can override server stream quota. - mconn, err := net.Dial("tcp", server.lis.Addr().String()) - if err != nil { - t.Fatalf("Clent failed to dial:%v", err) - } - defer mconn.Close() - if err := mconn.SetWriteDeadline(time.Now().Add(time.Second * 10)); err != nil { - t.Fatalf("Failed to set write deadline: %v", err) - } - if n, err := mconn.Write(clientPreface); err != nil || n != len(clientPreface) { - t.Fatalf("mconn.Write(clientPreface) = %d, %v, want %d, ", n, err, len(clientPreface)) - } - // success chan indicates that reader received a RSTStream from server. - success := make(chan struct{}) - var mu sync.Mutex - framer := http2.NewFramer(mconn, mconn) - if err := framer.WriteSettings(); err != nil { - t.Fatalf("Error while writing settings: %v", err) - } - go func() { // Launch a reader for this misbehaving client. - for { - frame, err := framer.ReadFrame() - if err != nil { - return - } - switch frame := frame.(type) { - case *http2.PingFrame: - // Write ping ack back so that server's BDP estimation works right. - mu.Lock() - framer.WritePing(true, frame.Data) - mu.Unlock() - case *http2.RSTStreamFrame: - if frame.Header().StreamID != 1 || http2.ErrCode(frame.ErrCode) != http2.ErrCodeFlowControl { - t.Errorf("RST stream received with streamID: %d and code: %v, want streamID: 1 and code: http2.ErrCodeFlowControl", frame.Header().StreamID, http2.ErrCode(frame.ErrCode)) - } - close(success) - return - default: - // Do nothing. - } - - } - }() - // Create a stream. - var buf bytes.Buffer - henc := hpack.NewEncoder(&buf) - // TODO(mmukhi): Remove unnecessary fields. - if err := henc.WriteField(hpack.HeaderField{Name: ":method", Value: "POST"}); err != nil { - t.Fatalf("Error while encoding header: %v", err) - } - if err := henc.WriteField(hpack.HeaderField{Name: ":path", Value: "foo"}); err != nil { - t.Fatalf("Error while encoding header: %v", err) - } - if err := henc.WriteField(hpack.HeaderField{Name: ":authority", Value: "localhost"}); err != nil { - t.Fatalf("Error while encoding header: %v", err) - } - if err := henc.WriteField(hpack.HeaderField{Name: "content-type", Value: "application/grpc"}); err != nil { - t.Fatalf("Error while encoding header: %v", err) - } - mu.Lock() - if err := framer.WriteHeaders(http2.HeadersFrameParam{StreamID: 1, BlockFragment: buf.Bytes(), EndHeaders: true}); err != nil { - mu.Unlock() - t.Fatalf("Error while writing headers: %v", err) - } - mu.Unlock() - - // Test server behavior for violation of stream flow control window size restriction. - timer := time.NewTimer(time.Second * 5) - dbuf := make([]byte, http2MaxFrameLen) - for { - select { - case <-timer.C: - t.Fatalf("Test timed out.") - case <-success: - return - default: - } - mu.Lock() - if err := framer.WriteData(1, false, dbuf); err != nil { - mu.Unlock() - // Error here means the server could have closed the connection due to flow control - // violation. Make sure that is the case by waiting for success chan to be closed. - select { - case <-timer.C: - t.Fatalf("Error while writing data: %v", err) - case <-success: - return - } - } - mu.Unlock() - // This for loop is capable of hogging the CPU and cause starvation - // in Go versions prior to 1.9, - // in single CPU environment. Explicitly relinquish processor. - runtime.Gosched() - } -} - -func TestClientWithMisbehavedServer(t *testing.T) { - // Create a misbehaving server. - lis, err := net.Listen("tcp", "localhost:0") - if err != nil { - t.Fatalf("Error while listening: %v", err) - } - defer lis.Close() - // success chan indicates that the server received - // RSTStream from the client. - success := make(chan struct{}) - go func() { // Launch the misbehaving server. - sconn, err := lis.Accept() - if err != nil { - t.Errorf("Error while accepting: %v", err) - return - } - defer sconn.Close() - if _, err := io.ReadFull(sconn, make([]byte, len(clientPreface))); err != nil { - t.Errorf("Error while reading clieng preface: %v", err) - return - } - sfr := http2.NewFramer(sconn, sconn) - if err := sfr.WriteSettingsAck(); err != nil { - t.Errorf("Error while writing settings: %v", err) - return - } - var mu sync.Mutex - for { - frame, err := sfr.ReadFrame() - if err != nil { - return - } - switch frame := frame.(type) { - case *http2.HeadersFrame: - // When the client creates a stream, violate the stream flow control. - go func() { - buf := make([]byte, http2MaxFrameLen) - for { - mu.Lock() - if err := sfr.WriteData(1, false, buf); err != nil { - mu.Unlock() - return - } - mu.Unlock() - // This for loop is capable of hogging the CPU and cause starvation - // in Go versions prior to 1.9, - // in single CPU environment. Explicitly relinquish processor. - runtime.Gosched() - } - }() - case *http2.RSTStreamFrame: - if frame.Header().StreamID != 1 || http2.ErrCode(frame.ErrCode) != http2.ErrCodeFlowControl { - t.Errorf("RST stream received with streamID: %d and code: %v, want streamID: 1 and code: http2.ErrCodeFlowControl", frame.Header().StreamID, http2.ErrCode(frame.ErrCode)) - } - close(success) - return - case *http2.PingFrame: - mu.Lock() - sfr.WritePing(true, frame.Data) - mu.Unlock() - default: - } - } - }() - connectCtx, cancel := context.WithDeadline(context.Background(), time.Now().Add(2*time.Second)) - defer cancel() - ct, err := NewClientTransport(connectCtx, context.Background(), TargetInfo{Addr: lis.Addr().String()}, ConnectOptions{}, func() {}, func(GoAwayReason) {}, func() {}) - if err != nil { - t.Fatalf("Error while creating client transport: %v", err) - } - defer ct.Close() - str, err := ct.NewStream(context.Background(), &CallHdr{}) - if err != nil { - t.Fatalf("Error while creating stream: %v", err) - } - timer := time.NewTimer(time.Second * 5) - go func() { // This go routine mimics the one in stream.go to call CloseStream. - <-str.Done() - ct.CloseStream(str, nil) - }() - select { - case <-timer.C: - t.Fatalf("Test timed-out.") - case <-success: - } -} - -var encodingTestStatus = status.New(codes.Internal, "\n") - -func TestEncodingRequiredStatus(t *testing.T) { - server, ct, cancel := setUp(t, 0, math.MaxUint32, encodingRequiredStatus) - defer cancel() - callHdr := &CallHdr{ - Host: "localhost", - Method: "foo", - } - s, err := ct.NewStream(context.Background(), callHdr) - if err != nil { - return - } - opts := Options{Last: true} - if err := ct.Write(s, nil, expectedRequest, &opts); err != nil && err != errStreamDone { - t.Fatalf("Failed to write the request: %v", err) - } - p := make([]byte, http2MaxFrameLen) - if _, err := s.trReader.(*transportReader).Read(p); err != io.EOF { - t.Fatalf("Read got error %v, want %v", err, io.EOF) - } - if !reflect.DeepEqual(s.Status(), encodingTestStatus) { - t.Fatalf("stream with status %v, want %v", s.Status(), encodingTestStatus) - } - ct.Close() - server.stop() -} - -func TestInvalidHeaderField(t *testing.T) { - server, ct, cancel := setUp(t, 0, math.MaxUint32, invalidHeaderField) - defer cancel() - callHdr := &CallHdr{ - Host: "localhost", - Method: "foo", - } - s, err := ct.NewStream(context.Background(), callHdr) - if err != nil { - return - } - p := make([]byte, http2MaxFrameLen) - _, err = s.trReader.(*transportReader).Read(p) - if se, ok := status.FromError(err); !ok || se.Code() != codes.Internal || !strings.Contains(err.Error(), expectedInvalidHeaderField) { - t.Fatalf("Read got error %v, want error with code %s and contains %q", err, codes.Internal, expectedInvalidHeaderField) - } - ct.Close() - server.stop() -} - -func TestIsReservedHeader(t *testing.T) { - tests := []struct { - h string - want bool - }{ - {"", false}, // but should be rejected earlier - {"foo", false}, - {"content-type", true}, - {"user-agent", true}, - {":anything", true}, - {"grpc-message-type", true}, - {"grpc-encoding", true}, - {"grpc-message", true}, - {"grpc-status", true}, - {"grpc-timeout", true}, - {"te", true}, - } - for _, tt := range tests { - got := isReservedHeader(tt.h) - if got != tt.want { - t.Errorf("isReservedHeader(%q) = %v; want %v", tt.h, got, tt.want) - } - } -} - -func TestContextErr(t *testing.T) { - for _, test := range []struct { - // input - errIn error - // outputs - errOut error - }{ - {context.DeadlineExceeded, status.Error(codes.DeadlineExceeded, context.DeadlineExceeded.Error())}, - {context.Canceled, status.Error(codes.Canceled, context.Canceled.Error())}, - } { - err := ContextErr(test.errIn) - if err.Error() != test.errOut.Error() { - t.Fatalf("ContextErr{%v} = %v \nwant %v", test.errIn, err, test.errOut) - } - } -} - -type windowSizeConfig struct { - serverStream int32 - serverConn int32 - clientStream int32 - clientConn int32 -} - -func TestAccountCheckWindowSizeWithLargeWindow(t *testing.T) { - wc := windowSizeConfig{ - serverStream: 10 * 1024 * 1024, - serverConn: 12 * 1024 * 1024, - clientStream: 6 * 1024 * 1024, - clientConn: 8 * 1024 * 1024, - } - testFlowControlAccountCheck(t, 1024*1024, wc) -} - -func TestAccountCheckWindowSizeWithSmallWindow(t *testing.T) { - wc := windowSizeConfig{ - serverStream: defaultWindowSize, - // Note this is smaller than initialConnWindowSize which is the current default. - serverConn: defaultWindowSize, - clientStream: defaultWindowSize, - clientConn: defaultWindowSize, - } - testFlowControlAccountCheck(t, 1024*1024, wc) -} - -func TestAccountCheckDynamicWindowSmallMessage(t *testing.T) { - testFlowControlAccountCheck(t, 1024, windowSizeConfig{}) -} - -func TestAccountCheckDynamicWindowLargeMessage(t *testing.T) { - testFlowControlAccountCheck(t, 1024*1024, windowSizeConfig{}) -} - -func testFlowControlAccountCheck(t *testing.T, msgSize int, wc windowSizeConfig) { - sc := &ServerConfig{ - InitialWindowSize: wc.serverStream, - InitialConnWindowSize: wc.serverConn, - } - co := ConnectOptions{ - InitialWindowSize: wc.clientStream, - InitialConnWindowSize: wc.clientConn, - } - server, client, cancel := setUpWithOptions(t, 0, sc, pingpong, co) - defer cancel() - defer server.stop() - defer client.Close() - waitWhileTrue(t, func() (bool, error) { - server.mu.Lock() - defer server.mu.Unlock() - if len(server.conns) == 0 { - return true, fmt.Errorf("timed out while waiting for server transport to be created") - } - return false, nil - }) - var st *http2Server - server.mu.Lock() - for k := range server.conns { - st = k.(*http2Server) - } - server.mu.Unlock() - const numStreams = 10 - clientStreams := make([]*Stream, numStreams) - for i := 0; i < numStreams; i++ { - var err error - clientStreams[i], err = client.NewStream(context.Background(), &CallHdr{}) - if err != nil { - t.Fatalf("Failed to create stream. Err: %v", err) - } - } - var wg sync.WaitGroup - // For each stream send pingpong messages to the server. - for _, stream := range clientStreams { - wg.Add(1) - go func(stream *Stream) { - defer wg.Done() - buf := make([]byte, msgSize+5) - buf[0] = byte(0) - binary.BigEndian.PutUint32(buf[1:], uint32(msgSize)) - opts := Options{} - header := make([]byte, 5) - for i := 1; i <= 10; i++ { - if err := client.Write(stream, nil, buf, &opts); err != nil { - t.Errorf("Error on client while writing message: %v", err) - return - } - if _, err := stream.Read(header); err != nil { - t.Errorf("Error on client while reading data frame header: %v", err) - return - } - sz := binary.BigEndian.Uint32(header[1:]) - recvMsg := make([]byte, int(sz)) - if _, err := stream.Read(recvMsg); err != nil { - t.Errorf("Error on client while reading data: %v", err) - return - } - if len(recvMsg) != msgSize { - t.Errorf("Length of message received by client: %v, want: %v", len(recvMsg), msgSize) - return - } - } - }(stream) - } - wg.Wait() - serverStreams := map[uint32]*Stream{} - loopyClientStreams := map[uint32]*outStream{} - loopyServerStreams := map[uint32]*outStream{} - // Get all the streams from server reader and writer and client writer. - st.mu.Lock() - for _, stream := range clientStreams { - id := stream.id - serverStreams[id] = st.activeStreams[id] - loopyServerStreams[id] = st.loopy.estdStreams[id] - loopyClientStreams[id] = client.loopy.estdStreams[id] - - } - st.mu.Unlock() - // Close all streams - for _, stream := range clientStreams { - client.Write(stream, nil, nil, &Options{Last: true}) - if _, err := stream.Read(make([]byte, 5)); err != io.EOF { - t.Fatalf("Client expected an EOF from the server. Got: %v", err) - } - } - // Close down both server and client so that their internals can be read without data - // races. - client.Close() - st.Close() - <-st.readerDone - <-st.writerDone - <-client.readerDone - <-client.writerDone - for _, cstream := range clientStreams { - id := cstream.id - sstream := serverStreams[id] - loopyServerStream := loopyServerStreams[id] - loopyClientStream := loopyClientStreams[id] - // Check stream flow control. - if int(cstream.fc.limit+cstream.fc.delta-cstream.fc.pendingData-cstream.fc.pendingUpdate) != int(st.loopy.oiws)-loopyServerStream.bytesOutStanding { - t.Fatalf("Account mismatch: client stream inflow limit(%d) + delta(%d) - pendingData(%d) - pendingUpdate(%d) != server outgoing InitialWindowSize(%d) - outgoingStream.bytesOutStanding(%d)", cstream.fc.limit, cstream.fc.delta, cstream.fc.pendingData, cstream.fc.pendingUpdate, st.loopy.oiws, loopyServerStream.bytesOutStanding) - } - if int(sstream.fc.limit+sstream.fc.delta-sstream.fc.pendingData-sstream.fc.pendingUpdate) != int(client.loopy.oiws)-loopyClientStream.bytesOutStanding { - t.Fatalf("Account mismatch: server stream inflow limit(%d) + delta(%d) - pendingData(%d) - pendingUpdate(%d) != client outgoing InitialWindowSize(%d) - outgoingStream.bytesOutStanding(%d)", sstream.fc.limit, sstream.fc.delta, sstream.fc.pendingData, sstream.fc.pendingUpdate, client.loopy.oiws, loopyClientStream.bytesOutStanding) - } - } - // Check transport flow control. - if client.fc.limit != client.fc.unacked+st.loopy.sendQuota { - t.Fatalf("Account mismatch: client transport inflow(%d) != client unacked(%d) + server sendQuota(%d)", client.fc.limit, client.fc.unacked, st.loopy.sendQuota) - } - if st.fc.limit != st.fc.unacked+client.loopy.sendQuota { - t.Fatalf("Account mismatch: server transport inflow(%d) != server unacked(%d) + client sendQuota(%d)", st.fc.limit, st.fc.unacked, client.loopy.sendQuota) - } -} - -func waitWhileTrue(t *testing.T, condition func() (bool, error)) { - var ( - wait bool - err error - ) - timer := time.NewTimer(time.Second * 5) - for { - wait, err = condition() - if wait { - select { - case <-timer.C: - t.Fatalf(err.Error()) - default: - time.Sleep(50 * time.Millisecond) - continue - } - } - if !timer.Stop() { - <-timer.C - } - break - } -} - -// A function of type writeHeaders writes out -// http status with the given stream ID using the given framer. -type writeHeaders func(*http2.Framer, uint32, int) error - -func writeOneHeader(framer *http2.Framer, sid uint32, httpStatus int) error { - var buf bytes.Buffer - henc := hpack.NewEncoder(&buf) - henc.WriteField(hpack.HeaderField{Name: ":status", Value: fmt.Sprint(httpStatus)}) - return framer.WriteHeaders(http2.HeadersFrameParam{ - StreamID: sid, - BlockFragment: buf.Bytes(), - EndStream: true, - EndHeaders: true, - }) -} - -func writeTwoHeaders(framer *http2.Framer, sid uint32, httpStatus int) error { - var buf bytes.Buffer - henc := hpack.NewEncoder(&buf) - henc.WriteField(hpack.HeaderField{ - Name: ":status", - Value: fmt.Sprint(http.StatusOK), - }) - if err := framer.WriteHeaders(http2.HeadersFrameParam{ - StreamID: sid, - BlockFragment: buf.Bytes(), - EndHeaders: true, - }); err != nil { - return err - } - buf.Reset() - henc.WriteField(hpack.HeaderField{ - Name: ":status", - Value: fmt.Sprint(httpStatus), - }) - return framer.WriteHeaders(http2.HeadersFrameParam{ - StreamID: sid, - BlockFragment: buf.Bytes(), - EndStream: true, - EndHeaders: true, - }) -} - -type httpServer struct { - httpStatus int - wh writeHeaders -} - -func (s *httpServer) start(t *testing.T, lis net.Listener) { - // Launch an HTTP server to send back header with httpStatus. - go func() { - conn, err := lis.Accept() - if err != nil { - t.Errorf("Error accepting connection: %v", err) - return - } - defer conn.Close() - // Read preface sent by client. - if _, err = io.ReadFull(conn, make([]byte, len(http2.ClientPreface))); err != nil { - t.Errorf("Error at server-side while reading preface from client. Err: %v", err) - return - } - reader := bufio.NewReaderSize(conn, defaultWriteBufSize) - writer := bufio.NewWriterSize(conn, defaultReadBufSize) - framer := http2.NewFramer(writer, reader) - if err = framer.WriteSettingsAck(); err != nil { - t.Errorf("Error at server-side while sending Settings ack. Err: %v", err) - return - } - var sid uint32 - // Read frames until a header is received. - for { - frame, err := framer.ReadFrame() - if err != nil { - t.Errorf("Error at server-side while reading frame. Err: %v", err) - return - } - if hframe, ok := frame.(*http2.HeadersFrame); ok { - sid = hframe.Header().StreamID - break - } - } - if err = s.wh(framer, sid, s.httpStatus); err != nil { - t.Errorf("Error at server-side while writing headers. Err: %v", err) - return - } - writer.Flush() - }() -} - -func setUpHTTPStatusTest(t *testing.T, httpStatus int, wh writeHeaders) (*Stream, func()) { - lis, err := net.Listen("tcp", "localhost:0") - if err != nil { - t.Fatalf("Failed to listen. Err: %v", err) - } - server := &httpServer{ - httpStatus: httpStatus, - wh: wh, - } - server.start(t, lis) - connectCtx, cancel := context.WithDeadline(context.Background(), time.Now().Add(2*time.Second)) - defer cancel() - client, err := newHTTP2Client(connectCtx, context.Background(), TargetInfo{Addr: lis.Addr().String()}, ConnectOptions{}, func() {}, func(GoAwayReason) {}, func() {}) - if err != nil { - lis.Close() - t.Fatalf("Error creating client. Err: %v", err) - } - stream, err := client.NewStream(context.Background(), &CallHdr{Method: "bogus/method"}) - if err != nil { - client.Close() - lis.Close() - t.Fatalf("Error creating stream at client-side. Err: %v", err) - } - return stream, func() { - client.Close() - lis.Close() - } -} - -func TestHTTPToGRPCStatusMapping(t *testing.T) { - for k := range httpStatusConvTab { - testHTTPToGRPCStatusMapping(t, k, writeOneHeader) - } -} - -func testHTTPToGRPCStatusMapping(t *testing.T, httpStatus int, wh writeHeaders) { - stream, cleanUp := setUpHTTPStatusTest(t, httpStatus, wh) - defer cleanUp() - want := httpStatusConvTab[httpStatus] - buf := make([]byte, 8) - _, err := stream.Read(buf) - if err == nil { - t.Fatalf("Stream.Read(_) unexpectedly returned no error. Expected stream error with code %v", want) - } - serr, ok := status.FromError(err) - if !ok { - t.Fatalf("err.(Type) = %T, want status error", err) - } - if want != serr.Code() { - t.Fatalf("Want error code: %v, got: %v", want, serr.Code()) - } -} - -func TestHTTPStatusOKAndMissingGRPCStatus(t *testing.T) { - stream, cleanUp := setUpHTTPStatusTest(t, http.StatusOK, writeOneHeader) - defer cleanUp() - buf := make([]byte, 8) - _, err := stream.Read(buf) - if err != io.EOF { - t.Fatalf("stream.Read(_) = _, %v, want _, io.EOF", err) - } - want := codes.Unknown - if stream.status.Code() != want { - t.Fatalf("Status code of stream: %v, want: %v", stream.status.Code(), want) - } -} - -func TestHTTPStatusNottOKAndMissingGRPCStatusInSecondHeader(t *testing.T) { - testHTTPToGRPCStatusMapping(t, http.StatusUnauthorized, writeTwoHeaders) -} - -// If any error occurs on a call to Stream.Read, future calls -// should continue to return that same error. -func TestReadGivesSameErrorAfterAnyErrorOccurs(t *testing.T) { - testRecvBuffer := newRecvBuffer() - s := &Stream{ - ctx: context.Background(), - buf: testRecvBuffer, - requestRead: func(int) {}, - } - s.trReader = &transportReader{ - reader: &recvBufferReader{ - ctx: s.ctx, - ctxDone: s.ctx.Done(), - recv: s.buf, - }, - windowHandler: func(int) {}, - } - testData := make([]byte, 1) - testData[0] = 5 - testErr := errors.New("test error") - s.write(recvMsg{data: testData, err: testErr}) - - inBuf := make([]byte, 1) - actualCount, actualErr := s.Read(inBuf) - if actualCount != 0 { - t.Errorf("actualCount, _ := s.Read(_) differs; want 0; got %v", actualCount) - } - if actualErr.Error() != testErr.Error() { - t.Errorf("_ , actualErr := s.Read(_) differs; want actualErr.Error() to be %v; got %v", testErr.Error(), actualErr.Error()) - } - - s.write(recvMsg{data: testData, err: nil}) - s.write(recvMsg{data: testData, err: errors.New("different error from first")}) - - for i := 0; i < 2; i++ { - inBuf := make([]byte, 1) - actualCount, actualErr := s.Read(inBuf) - if actualCount != 0 { - t.Errorf("actualCount, _ := s.Read(_) differs; want %v; got %v", 0, actualCount) - } - if actualErr.Error() != testErr.Error() { - t.Errorf("_ , actualErr := s.Read(_) differs; want actualErr.Error() to be %v; got %v", testErr.Error(), actualErr.Error()) - } - } -} - -func TestPingPong1B(t *testing.T) { - runPingPongTest(t, 1) -} - -func TestPingPong1KB(t *testing.T) { - runPingPongTest(t, 1024) -} - -func TestPingPong64KB(t *testing.T) { - runPingPongTest(t, 65536) -} - -func TestPingPong1MB(t *testing.T) { - runPingPongTest(t, 1048576) -} - -//This is a stress-test of flow control logic. -func runPingPongTest(t *testing.T, msgSize int) { - server, client, cancel := setUp(t, 0, 0, pingpong) - defer cancel() - defer server.stop() - defer client.Close() - waitWhileTrue(t, func() (bool, error) { - server.mu.Lock() - defer server.mu.Unlock() - if len(server.conns) == 0 { - return true, fmt.Errorf("timed out while waiting for server transport to be created") - } - return false, nil - }) - stream, err := client.NewStream(context.Background(), &CallHdr{}) - if err != nil { - t.Fatalf("Failed to create stream. Err: %v", err) - } - msg := make([]byte, msgSize) - outgoingHeader := make([]byte, 5) - outgoingHeader[0] = byte(0) - binary.BigEndian.PutUint32(outgoingHeader[1:], uint32(msgSize)) - opts := &Options{} - incomingHeader := make([]byte, 5) - done := make(chan struct{}) - go func() { - timer := time.NewTimer(time.Second * 5) - <-timer.C - close(done) - }() - for { - select { - case <-done: - client.Write(stream, nil, nil, &Options{Last: true}) - if _, err := stream.Read(incomingHeader); err != io.EOF { - t.Fatalf("Client expected EOF from the server. Got: %v", err) - } - return - default: - if err := client.Write(stream, outgoingHeader, msg, opts); err != nil { - t.Fatalf("Error on client while writing message. Err: %v", err) - } - if _, err := stream.Read(incomingHeader); err != nil { - t.Fatalf("Error on client while reading data header. Err: %v", err) - } - sz := binary.BigEndian.Uint32(incomingHeader[1:]) - recvMsg := make([]byte, int(sz)) - if _, err := stream.Read(recvMsg); err != nil { - t.Fatalf("Error on client while reading data. Err: %v", err) - } - } - } -} - -type tableSizeLimit struct { - mu sync.Mutex - limits []uint32 -} - -func (t *tableSizeLimit) add(limit uint32) { - t.mu.Lock() - t.limits = append(t.limits, limit) - t.mu.Unlock() -} - -func (t *tableSizeLimit) getLen() int { - t.mu.Lock() - defer t.mu.Unlock() - return len(t.limits) -} - -func (t *tableSizeLimit) getIndex(i int) uint32 { - t.mu.Lock() - defer t.mu.Unlock() - return t.limits[i] -} - -func TestHeaderTblSize(t *testing.T) { - limits := &tableSizeLimit{} - updateHeaderTblSize = func(e *hpack.Encoder, v uint32) { - e.SetMaxDynamicTableSizeLimit(v) - limits.add(v) - } - defer func() { - updateHeaderTblSize = func(e *hpack.Encoder, v uint32) { - e.SetMaxDynamicTableSizeLimit(v) - } - }() - - server, ct, cancel := setUp(t, 0, math.MaxUint32, normal) - defer cancel() - defer ct.Close() - defer server.stop() - _, err := ct.NewStream(context.Background(), &CallHdr{}) - if err != nil { - t.Fatalf("failed to open stream: %v", err) - } - - var svrTransport ServerTransport - var i int - for i = 0; i < 1000; i++ { - server.mu.Lock() - if len(server.conns) != 0 { - server.mu.Unlock() - break - } - server.mu.Unlock() - time.Sleep(10 * time.Millisecond) - continue - } - if i == 1000 { - t.Fatalf("unable to create any server transport after 10s") - } - - for st := range server.conns { - svrTransport = st - break - } - svrTransport.(*http2Server).controlBuf.put(&outgoingSettings{ - ss: []http2.Setting{ - { - ID: http2.SettingHeaderTableSize, - Val: uint32(100), - }, - }, - }) - - for i = 0; i < 1000; i++ { - if limits.getLen() != 1 { - time.Sleep(10 * time.Millisecond) - continue - } - if val := limits.getIndex(0); val != uint32(100) { - t.Fatalf("expected limits[0] = 100, got %d", val) - } - break - } - if i == 1000 { - t.Fatalf("expected len(limits) = 1 within 10s, got != 1") - } - - ct.controlBuf.put(&outgoingSettings{ - ss: []http2.Setting{ - { - ID: http2.SettingHeaderTableSize, - Val: uint32(200), - }, - }, - }) - - for i := 0; i < 1000; i++ { - if limits.getLen() != 2 { - time.Sleep(10 * time.Millisecond) - continue - } - if val := limits.getIndex(1); val != uint32(200) { - t.Fatalf("expected limits[1] = 200, got %d", val) - } - break - } - if i == 1000 { - t.Fatalf("expected len(limits) = 2 within 10s, got != 2") - } -} - -// TestTCPUserTimeout tests that the TCP_USER_TIMEOUT socket option is set to the -// keepalive timeout, as detailed in proposal A18 -func TestTCPUserTimeout(t *testing.T) { - tests := []struct { - time time.Duration - timeout time.Duration - }{ - { - 10 * time.Second, - 10 * time.Second, - }, - { - 0, - 0, - }, - } - for _, tt := range tests { - server, client, cancel := setUpWithOptions( - t, - 0, - &ServerConfig{ - KeepaliveParams: keepalive.ServerParameters{ - Time: tt.timeout, - Timeout: tt.timeout, - }, - }, - normal, - ConnectOptions{ - KeepaliveParams: keepalive.ClientParameters{ - Time: tt.time, - Timeout: tt.timeout, - }, - }, - ) - defer cancel() - defer server.stop() - defer client.Close() - - stream, err := client.NewStream(context.Background(), &CallHdr{}) - if err != nil { - t.Fatalf("Client failed to create RPC request: %v", err) - } - client.closeStream(stream, io.EOF, true, http2.ErrCodeCancel, nil, nil, false) - - opt, err := syscall.GetTCPUserTimeout(client.conn) - if err != nil { - t.Fatalf("GetTCPUserTimeout error: %v", err) - } - if opt < 0 { - t.Skipf("skipping test on unsupported environment") - } - if timeoutMS := int(tt.timeout / time.Millisecond); timeoutMS != opt { - t.Fatalf("wrong TCP_USER_TIMEOUT set on conn. expected %d. got %d", - timeoutMS, opt) - } - } -} diff --git a/vendor/google.golang.org/grpc/metadata/metadata_test.go b/vendor/google.golang.org/grpc/metadata/metadata_test.go deleted file mode 100644 index f166ffaf..00000000 --- a/vendor/google.golang.org/grpc/metadata/metadata_test.go +++ /dev/null @@ -1,250 +0,0 @@ -/* - * - * Copyright 2014 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package metadata - -import ( - "context" - "reflect" - "strconv" - "testing" -) - -func TestPairsMD(t *testing.T) { - for _, test := range []struct { - // input - kv []string - // output - md MD - }{ - {[]string{}, MD{}}, - {[]string{"k1", "v1", "k1", "v2"}, MD{"k1": []string{"v1", "v2"}}}, - } { - md := Pairs(test.kv...) - if !reflect.DeepEqual(md, test.md) { - t.Fatalf("Pairs(%v) = %v, want %v", test.kv, md, test.md) - } - } -} - -func TestCopy(t *testing.T) { - const key, val = "key", "val" - orig := Pairs(key, val) - cpy := orig.Copy() - if !reflect.DeepEqual(orig, cpy) { - t.Errorf("copied value not equal to the original, got %v, want %v", cpy, orig) - } - orig[key][0] = "foo" - if v := cpy[key][0]; v != val { - t.Errorf("change in original should not affect copy, got %q, want %q", v, val) - } -} - -func TestJoin(t *testing.T) { - for _, test := range []struct { - mds []MD - want MD - }{ - {[]MD{}, MD{}}, - {[]MD{Pairs("foo", "bar")}, Pairs("foo", "bar")}, - {[]MD{Pairs("foo", "bar"), Pairs("foo", "baz")}, Pairs("foo", "bar", "foo", "baz")}, - {[]MD{Pairs("foo", "bar"), Pairs("foo", "baz"), Pairs("zip", "zap")}, Pairs("foo", "bar", "foo", "baz", "zip", "zap")}, - } { - md := Join(test.mds...) - if !reflect.DeepEqual(md, test.want) { - t.Errorf("context's metadata is %v, want %v", md, test.want) - } - } -} - -func TestGet(t *testing.T) { - for _, test := range []struct { - md MD - key string - wantVals []string - }{ - {md: Pairs("My-Optional-Header", "42"), key: "My-Optional-Header", wantVals: []string{"42"}}, - {md: Pairs("Header", "42", "Header", "43", "Header", "44", "other", "1"), key: "HEADER", wantVals: []string{"42", "43", "44"}}, - {md: Pairs("HEADER", "10"), key: "HEADER", wantVals: []string{"10"}}, - } { - vals := test.md.Get(test.key) - if !reflect.DeepEqual(vals, test.wantVals) { - t.Errorf("value of metadata %v is %v, want %v", test.key, vals, test.wantVals) - } - } -} - -func TestSet(t *testing.T) { - for _, test := range []struct { - md MD - setKey string - setVals []string - want MD - }{ - { - md: Pairs("My-Optional-Header", "42", "other-key", "999"), - setKey: "Other-Key", - setVals: []string{"1"}, - want: Pairs("my-optional-header", "42", "other-key", "1"), - }, - { - md: Pairs("My-Optional-Header", "42"), - setKey: "Other-Key", - setVals: []string{"1", "2", "3"}, - want: Pairs("my-optional-header", "42", "other-key", "1", "other-key", "2", "other-key", "3"), - }, - { - md: Pairs("My-Optional-Header", "42"), - setKey: "Other-Key", - setVals: []string{}, - want: Pairs("my-optional-header", "42"), - }, - } { - test.md.Set(test.setKey, test.setVals...) - if !reflect.DeepEqual(test.md, test.want) { - t.Errorf("value of metadata is %v, want %v", test.md, test.want) - } - } -} - -func TestAppend(t *testing.T) { - for _, test := range []struct { - md MD - appendKey string - appendVals []string - want MD - }{ - { - md: Pairs("My-Optional-Header", "42"), - appendKey: "Other-Key", - appendVals: []string{"1"}, - want: Pairs("my-optional-header", "42", "other-key", "1"), - }, - { - md: Pairs("My-Optional-Header", "42"), - appendKey: "my-OptIoNal-HeAder", - appendVals: []string{"1", "2", "3"}, - want: Pairs("my-optional-header", "42", "my-optional-header", "1", - "my-optional-header", "2", "my-optional-header", "3"), - }, - { - md: Pairs("My-Optional-Header", "42"), - appendKey: "my-OptIoNal-HeAder", - appendVals: []string{}, - want: Pairs("my-optional-header", "42"), - }, - } { - test.md.Append(test.appendKey, test.appendVals...) - if !reflect.DeepEqual(test.md, test.want) { - t.Errorf("value of metadata is %v, want %v", test.md, test.want) - } - } -} - -func TestAppendToOutgoingContext(t *testing.T) { - // Pre-existing metadata - ctx := NewOutgoingContext(context.Background(), Pairs("k1", "v1", "k2", "v2")) - ctx = AppendToOutgoingContext(ctx, "k1", "v3") - ctx = AppendToOutgoingContext(ctx, "k1", "v4") - md, ok := FromOutgoingContext(ctx) - if !ok { - t.Errorf("Expected MD to exist in ctx, but got none") - } - want := Pairs("k1", "v1", "k1", "v3", "k1", "v4", "k2", "v2") - if !reflect.DeepEqual(md, want) { - t.Errorf("context's metadata is %v, want %v", md, want) - } - - // No existing metadata - ctx = AppendToOutgoingContext(context.Background(), "k1", "v1") - md, ok = FromOutgoingContext(ctx) - if !ok { - t.Errorf("Expected MD to exist in ctx, but got none") - } - want = Pairs("k1", "v1") - if !reflect.DeepEqual(md, want) { - t.Errorf("context's metadata is %v, want %v", md, want) - } -} - -func TestAppendToOutgoingContext_Repeated(t *testing.T) { - ctx := context.Background() - - for i := 0; i < 100; i = i + 2 { - ctx1 := AppendToOutgoingContext(ctx, "k", strconv.Itoa(i)) - ctx2 := AppendToOutgoingContext(ctx, "k", strconv.Itoa(i+1)) - - md1, _ := FromOutgoingContext(ctx1) - md2, _ := FromOutgoingContext(ctx2) - - if reflect.DeepEqual(md1, md2) { - t.Fatalf("md1, md2 = %v, %v; should not be equal", md1, md2) - } - - ctx = ctx1 - } -} - -func TestAppendToOutgoingContext_FromKVSlice(t *testing.T) { - const k, v = "a", "b" - kv := []string{k, v} - ctx := AppendToOutgoingContext(context.Background(), kv...) - md, _ := FromOutgoingContext(ctx) - if md[k][0] != v { - t.Fatalf("md[%q] = %q; want %q", k, md[k], v) - } - kv[1] = "xxx" - md, _ = FromOutgoingContext(ctx) - if md[k][0] != v { - t.Fatalf("md[%q] = %q; want %q", k, md[k], v) - } -} - -// Old/slow approach to adding metadata to context -func Benchmark_AddingMetadata_ContextManipulationApproach(b *testing.B) { - // TODO: Add in N=1-100 tests once Go1.6 support is removed. - const num = 10 - for n := 0; n < b.N; n++ { - ctx := context.Background() - for i := 0; i < num; i++ { - md, _ := FromOutgoingContext(ctx) - NewOutgoingContext(ctx, Join(Pairs("k1", "v1", "k2", "v2"), md)) - } - } -} - -// Newer/faster approach to adding metadata to context -func BenchmarkAppendToOutgoingContext(b *testing.B) { - const num = 10 - for n := 0; n < b.N; n++ { - ctx := context.Background() - for i := 0; i < num; i++ { - ctx = AppendToOutgoingContext(ctx, "k1", "v1", "k2", "v2") - } - } -} - -func BenchmarkFromOutgoingContext(b *testing.B) { - ctx := context.Background() - ctx = NewOutgoingContext(ctx, MD{"k3": {"v3", "v4"}}) - ctx = AppendToOutgoingContext(ctx, "k1", "v1", "k2", "v2") - - for n := 0; n < b.N; n++ { - FromOutgoingContext(ctx) - } -} diff --git a/vendor/google.golang.org/grpc/naming/dns_resolver_test.go b/vendor/google.golang.org/grpc/naming/dns_resolver_test.go deleted file mode 100644 index 42868a5d..00000000 --- a/vendor/google.golang.org/grpc/naming/dns_resolver_test.go +++ /dev/null @@ -1,331 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package naming - -import ( - "context" - "fmt" - "net" - "reflect" - "sync" - "testing" - "time" -) - -func newUpdateWithMD(op Operation, addr, lb string) *Update { - return &Update{ - Op: op, - Addr: addr, - Metadata: AddrMetadataGRPCLB{AddrType: GRPCLB, ServerName: lb}, - } -} - -func toMap(u []*Update) map[string]*Update { - m := make(map[string]*Update) - for _, v := range u { - m[v.Addr] = v - } - return m -} - -func TestCompileUpdate(t *testing.T) { - tests := []struct { - oldAddrs []string - newAddrs []string - want []*Update - }{ - { - []string{}, - []string{"1.0.0.1"}, - []*Update{{Op: Add, Addr: "1.0.0.1"}}, - }, - { - []string{"1.0.0.1"}, - []string{"1.0.0.1"}, - []*Update{}, - }, - { - []string{"1.0.0.0"}, - []string{"1.0.0.1"}, - []*Update{{Op: Delete, Addr: "1.0.0.0"}, {Op: Add, Addr: "1.0.0.1"}}, - }, - { - []string{"1.0.0.1"}, - []string{"1.0.0.0"}, - []*Update{{Op: Add, Addr: "1.0.0.0"}, {Op: Delete, Addr: "1.0.0.1"}}, - }, - { - []string{"1.0.0.1"}, - []string{"1.0.0.1", "1.0.0.2", "1.0.0.3"}, - []*Update{{Op: Add, Addr: "1.0.0.2"}, {Op: Add, Addr: "1.0.0.3"}}, - }, - { - []string{"1.0.0.1", "1.0.0.2", "1.0.0.3"}, - []string{"1.0.0.0"}, - []*Update{{Op: Add, Addr: "1.0.0.0"}, {Op: Delete, Addr: "1.0.0.1"}, {Op: Delete, Addr: "1.0.0.2"}, {Op: Delete, Addr: "1.0.0.3"}}, - }, - { - []string{"1.0.0.1", "1.0.0.3", "1.0.0.5"}, - []string{"1.0.0.2", "1.0.0.3", "1.0.0.6"}, - []*Update{{Op: Delete, Addr: "1.0.0.1"}, {Op: Add, Addr: "1.0.0.2"}, {Op: Delete, Addr: "1.0.0.5"}, {Op: Add, Addr: "1.0.0.6"}}, - }, - { - []string{"1.0.0.1", "1.0.0.1", "1.0.0.2"}, - []string{"1.0.0.1"}, - []*Update{{Op: Delete, Addr: "1.0.0.2"}}, - }, - } - - var w dnsWatcher - for _, c := range tests { - w.curAddrs = make(map[string]*Update) - newUpdates := make(map[string]*Update) - for _, a := range c.oldAddrs { - w.curAddrs[a] = &Update{Addr: a} - } - for _, a := range c.newAddrs { - newUpdates[a] = &Update{Addr: a} - } - r := w.compileUpdate(newUpdates) - if !reflect.DeepEqual(toMap(c.want), toMap(r)) { - t.Errorf("w(%+v).compileUpdate(%+v) = %+v, want %+v", c.oldAddrs, c.newAddrs, updatesToSlice(r), updatesToSlice(c.want)) - } - } -} - -func TestResolveFunc(t *testing.T) { - tests := []struct { - addr string - want error - }{ - // TODO(yuxuanli): More false cases? - {"www.google.com", nil}, - {"foo.bar:12345", nil}, - {"127.0.0.1", nil}, - {"127.0.0.1:12345", nil}, - {"[::1]:80", nil}, - {"[2001:db8:a0b:12f0::1]:21", nil}, - {":80", nil}, - {"127.0.0...1:12345", nil}, - {"[fe80::1%lo0]:80", nil}, - {"golang.org:http", nil}, - {"[2001:db8::1]:http", nil}, - {":", nil}, - {"", errMissingAddr}, - {"[2001:db8:a0b:12f0::1", fmt.Errorf("invalid target address %v", "[2001:db8:a0b:12f0::1")}, - } - - r, err := NewDNSResolver() - if err != nil { - t.Errorf("%v", err) - } - for _, v := range tests { - _, err := r.Resolve(v.addr) - if !reflect.DeepEqual(err, v.want) { - t.Errorf("Resolve(%q) = %v, want %v", v.addr, err, v.want) - } - } -} - -var hostLookupTbl = map[string][]string{ - "foo.bar.com": {"1.2.3.4", "5.6.7.8"}, - "ipv4.single.fake": {"1.2.3.4"}, - "ipv4.multi.fake": {"1.2.3.4", "5.6.7.8", "9.10.11.12"}, - "ipv6.single.fake": {"2607:f8b0:400a:801::1001"}, - "ipv6.multi.fake": {"2607:f8b0:400a:801::1001", "2607:f8b0:400a:801::1002", "2607:f8b0:400a:801::1003"}, -} - -func hostLookup(host string) ([]string, error) { - if addrs, ok := hostLookupTbl[host]; ok { - return addrs, nil - } - return nil, fmt.Errorf("failed to lookup host:%s resolution in hostLookupTbl", host) -} - -var srvLookupTbl = map[string][]*net.SRV{ - "_grpclb._tcp.srv.ipv4.single.fake": {&net.SRV{Target: "ipv4.single.fake", Port: 1234}}, - "_grpclb._tcp.srv.ipv4.multi.fake": {&net.SRV{Target: "ipv4.multi.fake", Port: 1234}}, - "_grpclb._tcp.srv.ipv6.single.fake": {&net.SRV{Target: "ipv6.single.fake", Port: 1234}}, - "_grpclb._tcp.srv.ipv6.multi.fake": {&net.SRV{Target: "ipv6.multi.fake", Port: 1234}}, -} - -func srvLookup(service, proto, name string) (string, []*net.SRV, error) { - cname := "_" + service + "._" + proto + "." + name - if srvs, ok := srvLookupTbl[cname]; ok { - return cname, srvs, nil - } - return "", nil, fmt.Errorf("failed to lookup srv record for %s in srvLookupTbl", cname) -} - -func updatesToSlice(updates []*Update) []Update { - res := make([]Update, len(updates)) - for i, u := range updates { - res[i] = *u - } - return res -} - -func testResolver(t *testing.T, freq time.Duration, slp time.Duration) { - tests := []struct { - target string - want []*Update - }{ - { - "foo.bar.com", - []*Update{{Op: Add, Addr: "1.2.3.4" + colonDefaultPort}, {Op: Add, Addr: "5.6.7.8" + colonDefaultPort}}, - }, - { - "foo.bar.com:1234", - []*Update{{Op: Add, Addr: "1.2.3.4:1234"}, {Op: Add, Addr: "5.6.7.8:1234"}}, - }, - { - "srv.ipv4.single.fake", - []*Update{newUpdateWithMD(Add, "1.2.3.4:1234", "ipv4.single.fake")}, - }, - { - "srv.ipv4.multi.fake", - []*Update{ - newUpdateWithMD(Add, "1.2.3.4:1234", "ipv4.multi.fake"), - newUpdateWithMD(Add, "5.6.7.8:1234", "ipv4.multi.fake"), - newUpdateWithMD(Add, "9.10.11.12:1234", "ipv4.multi.fake")}, - }, - { - "srv.ipv6.single.fake", - []*Update{newUpdateWithMD(Add, "[2607:f8b0:400a:801::1001]:1234", "ipv6.single.fake")}, - }, - { - "srv.ipv6.multi.fake", - []*Update{ - newUpdateWithMD(Add, "[2607:f8b0:400a:801::1001]:1234", "ipv6.multi.fake"), - newUpdateWithMD(Add, "[2607:f8b0:400a:801::1002]:1234", "ipv6.multi.fake"), - newUpdateWithMD(Add, "[2607:f8b0:400a:801::1003]:1234", "ipv6.multi.fake"), - }, - }, - } - - for _, a := range tests { - r, err := NewDNSResolverWithFreq(freq) - if err != nil { - t.Fatalf("%v\n", err) - } - w, err := r.Resolve(a.target) - if err != nil { - t.Fatalf("%v\n", err) - } - updates, err := w.Next() - if err != nil { - t.Fatalf("%v\n", err) - } - if !reflect.DeepEqual(toMap(a.want), toMap(updates)) { - t.Errorf("Resolve(%q) = %+v, want %+v\n", a.target, updatesToSlice(updates), updatesToSlice(a.want)) - } - var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() - for { - _, err := w.Next() - if err != nil { - return - } - t.Error("Execution shouldn't reach here, since w.Next() should be blocked until close happen.") - } - }() - // Sleep for sometime to let watcher do more than one lookup - time.Sleep(slp) - w.Close() - wg.Wait() - } -} - -func replaceNetFunc() func() { - oldLookupHost := lookupHost - oldLookupSRV := lookupSRV - lookupHost = func(ctx context.Context, host string) ([]string, error) { - return hostLookup(host) - } - lookupSRV = func(ctx context.Context, service, proto, name string) (string, []*net.SRV, error) { - return srvLookup(service, proto, name) - } - return func() { - lookupHost = oldLookupHost - lookupSRV = oldLookupSRV - } -} - -func TestResolve(t *testing.T) { - defer replaceNetFunc()() - testResolver(t, time.Millisecond*5, time.Millisecond*10) -} - -const colonDefaultPort = ":" + defaultPort - -func TestIPWatcher(t *testing.T) { - tests := []struct { - target string - want []*Update - }{ - {"127.0.0.1", []*Update{{Op: Add, Addr: "127.0.0.1" + colonDefaultPort}}}, - {"127.0.0.1:12345", []*Update{{Op: Add, Addr: "127.0.0.1:12345"}}}, - {"::1", []*Update{{Op: Add, Addr: "[::1]" + colonDefaultPort}}}, - {"[::1]:12345", []*Update{{Op: Add, Addr: "[::1]:12345"}}}, - {"[::1]:", []*Update{{Op: Add, Addr: "[::1]:443"}}}, - {"2001:db8:85a3::8a2e:370:7334", []*Update{{Op: Add, Addr: "[2001:db8:85a3::8a2e:370:7334]" + colonDefaultPort}}}, - {"[2001:db8:85a3::8a2e:370:7334]", []*Update{{Op: Add, Addr: "[2001:db8:85a3::8a2e:370:7334]" + colonDefaultPort}}}, - {"[2001:db8:85a3::8a2e:370:7334]:12345", []*Update{{Op: Add, Addr: "[2001:db8:85a3::8a2e:370:7334]:12345"}}}, - {"[2001:db8::1]:http", []*Update{{Op: Add, Addr: "[2001:db8::1]:http"}}}, - // TODO(yuxuanli): zone support? - } - - for _, v := range tests { - r, err := NewDNSResolverWithFreq(time.Millisecond * 5) - if err != nil { - t.Fatalf("%v\n", err) - } - w, err := r.Resolve(v.target) - if err != nil { - t.Fatalf("%v\n", err) - } - var updates []*Update - var wg sync.WaitGroup - wg.Add(1) - count := 0 - go func() { - defer wg.Done() - for { - u, err := w.Next() - if err != nil { - return - } - updates = u - count++ - } - }() - // Sleep for sometime to let watcher do more than one lookup - time.Sleep(time.Millisecond * 10) - w.Close() - wg.Wait() - if !reflect.DeepEqual(v.want, updates) { - t.Errorf("Resolve(%q) = %v, want %+v\n", v.target, updatesToSlice(updates), updatesToSlice(v.want)) - } - if count != 1 { - t.Errorf("IPWatcher Next() should return only once, not %d times\n", count) - } - } -} diff --git a/vendor/google.golang.org/grpc/picker_wrapper_test.go b/vendor/google.golang.org/grpc/picker_wrapper_test.go deleted file mode 100644 index 36653b12..00000000 --- a/vendor/google.golang.org/grpc/picker_wrapper_test.go +++ /dev/null @@ -1,160 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package grpc - -import ( - "context" - "fmt" - "sync/atomic" - "testing" - "time" - - "google.golang.org/grpc/balancer" - "google.golang.org/grpc/connectivity" - _ "google.golang.org/grpc/grpclog/glogger" - "google.golang.org/grpc/internal/leakcheck" - "google.golang.org/grpc/internal/transport" -) - -const goroutineCount = 5 - -var ( - testT = &testTransport{} - testSC = &acBalancerWrapper{ac: &addrConn{ - state: connectivity.Ready, - transport: testT, - }} - testSCNotReady = &acBalancerWrapper{ac: &addrConn{ - state: connectivity.TransientFailure, - }} -) - -type testTransport struct { - transport.ClientTransport -} - -type testingPicker struct { - err error - sc balancer.SubConn - maxCalled int64 -} - -func (p *testingPicker) Pick(ctx context.Context, opts balancer.PickOptions) (balancer.SubConn, func(balancer.DoneInfo), error) { - if atomic.AddInt64(&p.maxCalled, -1) < 0 { - return nil, nil, fmt.Errorf("Pick called to many times (> goroutineCount)") - } - if p.err != nil { - return nil, nil, p.err - } - return p.sc, nil, nil -} - -func TestBlockingPickTimeout(t *testing.T) { - defer leakcheck.Check(t) - bp := newPickerWrapper() - ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond) - defer cancel() - if _, _, err := bp.pick(ctx, true, balancer.PickOptions{}); err != context.DeadlineExceeded { - t.Errorf("bp.pick returned error %v, want DeadlineExceeded", err) - } -} - -func TestBlockingPick(t *testing.T) { - defer leakcheck.Check(t) - bp := newPickerWrapper() - // All goroutines should block because picker is nil in bp. - var finishedCount uint64 - for i := goroutineCount; i > 0; i-- { - go func() { - if tr, _, err := bp.pick(context.Background(), true, balancer.PickOptions{}); err != nil || tr != testT { - t.Errorf("bp.pick returned non-nil error: %v", err) - } - atomic.AddUint64(&finishedCount, 1) - }() - } - time.Sleep(50 * time.Millisecond) - if c := atomic.LoadUint64(&finishedCount); c != 0 { - t.Errorf("finished goroutines count: %v, want 0", c) - } - bp.updatePicker(&testingPicker{sc: testSC, maxCalled: goroutineCount}) -} - -func TestBlockingPickNoSubAvailable(t *testing.T) { - defer leakcheck.Check(t) - bp := newPickerWrapper() - var finishedCount uint64 - bp.updatePicker(&testingPicker{err: balancer.ErrNoSubConnAvailable, maxCalled: goroutineCount}) - // All goroutines should block because picker returns no sc available. - for i := goroutineCount; i > 0; i-- { - go func() { - if tr, _, err := bp.pick(context.Background(), true, balancer.PickOptions{}); err != nil || tr != testT { - t.Errorf("bp.pick returned non-nil error: %v", err) - } - atomic.AddUint64(&finishedCount, 1) - }() - } - time.Sleep(50 * time.Millisecond) - if c := atomic.LoadUint64(&finishedCount); c != 0 { - t.Errorf("finished goroutines count: %v, want 0", c) - } - bp.updatePicker(&testingPicker{sc: testSC, maxCalled: goroutineCount}) -} - -func TestBlockingPickTransientWaitforready(t *testing.T) { - defer leakcheck.Check(t) - bp := newPickerWrapper() - bp.updatePicker(&testingPicker{err: balancer.ErrTransientFailure, maxCalled: goroutineCount}) - var finishedCount uint64 - // All goroutines should block because picker returns transientFailure and - // picks are not failfast. - for i := goroutineCount; i > 0; i-- { - go func() { - if tr, _, err := bp.pick(context.Background(), false, balancer.PickOptions{}); err != nil || tr != testT { - t.Errorf("bp.pick returned non-nil error: %v", err) - } - atomic.AddUint64(&finishedCount, 1) - }() - } - time.Sleep(time.Millisecond) - if c := atomic.LoadUint64(&finishedCount); c != 0 { - t.Errorf("finished goroutines count: %v, want 0", c) - } - bp.updatePicker(&testingPicker{sc: testSC, maxCalled: goroutineCount}) -} - -func TestBlockingPickSCNotReady(t *testing.T) { - defer leakcheck.Check(t) - bp := newPickerWrapper() - bp.updatePicker(&testingPicker{sc: testSCNotReady, maxCalled: goroutineCount}) - var finishedCount uint64 - // All goroutines should block because sc is not ready. - for i := goroutineCount; i > 0; i-- { - go func() { - if tr, _, err := bp.pick(context.Background(), true, balancer.PickOptions{}); err != nil || tr != testT { - t.Errorf("bp.pick returned non-nil error: %v", err) - } - atomic.AddUint64(&finishedCount, 1) - }() - } - time.Sleep(time.Millisecond) - if c := atomic.LoadUint64(&finishedCount); c != 0 { - t.Errorf("finished goroutines count: %v, want 0", c) - } - bp.updatePicker(&testingPicker{sc: testSC, maxCalled: goroutineCount}) -} diff --git a/vendor/google.golang.org/grpc/pickfirst_test.go b/vendor/google.golang.org/grpc/pickfirst_test.go deleted file mode 100644 index 675067fd..00000000 --- a/vendor/google.golang.org/grpc/pickfirst_test.go +++ /dev/null @@ -1,360 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package grpc - -import ( - "context" - "math" - "sync" - "testing" - "time" - - "google.golang.org/grpc/codes" - "google.golang.org/grpc/internal/leakcheck" - "google.golang.org/grpc/resolver" - "google.golang.org/grpc/resolver/manual" - "google.golang.org/grpc/status" -) - -func errorDesc(err error) string { - if s, ok := status.FromError(err); ok { - return s.Message() - } - return err.Error() -} - -func TestOneBackendPickfirst(t *testing.T) { - defer leakcheck.Check(t) - r, rcleanup := manual.GenerateAndRegisterManualResolver() - defer rcleanup() - - numServers := 1 - servers, _, scleanup := startServers(t, numServers, math.MaxInt32) - defer scleanup() - - cc, err := Dial(r.Scheme()+":///test.server", WithInsecure(), WithCodec(testCodec{})) - if err != nil { - t.Fatalf("failed to dial: %v", err) - } - defer cc.Close() - // The first RPC should fail because there's no address. - ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond) - defer cancel() - req := "port" - var reply string - if err := cc.Invoke(ctx, "/foo/bar", &req, &reply); err == nil || status.Code(err) != codes.DeadlineExceeded { - t.Fatalf("EmptyCall() = _, %v, want _, DeadlineExceeded", err) - } - - r.NewAddress([]resolver.Address{{Addr: servers[0].addr}}) - // The second RPC should succeed. - for i := 0; i < 1000; i++ { - if err = cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err != nil && errorDesc(err) == servers[0].port { - return - } - time.Sleep(time.Millisecond) - } - t.Fatalf("EmptyCall() = _, %v, want _, %v", err, servers[0].port) -} - -func TestBackendsPickfirst(t *testing.T) { - defer leakcheck.Check(t) - r, rcleanup := manual.GenerateAndRegisterManualResolver() - defer rcleanup() - - numServers := 2 - servers, _, scleanup := startServers(t, numServers, math.MaxInt32) - defer scleanup() - - cc, err := Dial(r.Scheme()+":///test.server", WithInsecure(), WithCodec(testCodec{})) - if err != nil { - t.Fatalf("failed to dial: %v", err) - } - defer cc.Close() - // The first RPC should fail because there's no address. - ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond) - defer cancel() - req := "port" - var reply string - if err := cc.Invoke(ctx, "/foo/bar", &req, &reply); err == nil || status.Code(err) != codes.DeadlineExceeded { - t.Fatalf("EmptyCall() = _, %v, want _, DeadlineExceeded", err) - } - - r.NewAddress([]resolver.Address{{Addr: servers[0].addr}, {Addr: servers[1].addr}}) - // The second RPC should succeed with the first server. - for i := 0; i < 1000; i++ { - if err = cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err != nil && errorDesc(err) == servers[0].port { - return - } - time.Sleep(time.Millisecond) - } - t.Fatalf("EmptyCall() = _, %v, want _, %v", err, servers[0].port) -} - -func TestNewAddressWhileBlockingPickfirst(t *testing.T) { - defer leakcheck.Check(t) - r, rcleanup := manual.GenerateAndRegisterManualResolver() - defer rcleanup() - - numServers := 1 - servers, _, scleanup := startServers(t, numServers, math.MaxInt32) - defer scleanup() - - cc, err := Dial(r.Scheme()+":///test.server", WithInsecure(), WithCodec(testCodec{})) - if err != nil { - t.Fatalf("failed to dial: %v", err) - } - defer cc.Close() - // The first RPC should fail because there's no address. - ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond) - defer cancel() - req := "port" - var reply string - if err := cc.Invoke(ctx, "/foo/bar", &req, &reply); err == nil || status.Code(err) != codes.DeadlineExceeded { - t.Fatalf("EmptyCall() = _, %v, want _, DeadlineExceeded", err) - } - - var wg sync.WaitGroup - for i := 0; i < 3; i++ { - wg.Add(1) - go func() { - defer wg.Done() - // This RPC blocks until NewAddress is called. - cc.Invoke(context.Background(), "/foo/bar", &req, &reply) - }() - } - time.Sleep(50 * time.Millisecond) - r.NewAddress([]resolver.Address{{Addr: servers[0].addr}}) - wg.Wait() -} - -func TestCloseWithPendingRPCPickfirst(t *testing.T) { - defer leakcheck.Check(t) - r, rcleanup := manual.GenerateAndRegisterManualResolver() - defer rcleanup() - - numServers := 1 - _, _, scleanup := startServers(t, numServers, math.MaxInt32) - defer scleanup() - - cc, err := Dial(r.Scheme()+":///test.server", WithInsecure(), WithCodec(testCodec{})) - if err != nil { - t.Fatalf("failed to dial: %v", err) - } - defer cc.Close() - // The first RPC should fail because there's no address. - ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond) - defer cancel() - req := "port" - var reply string - if err := cc.Invoke(ctx, "/foo/bar", &req, &reply); err == nil || status.Code(err) != codes.DeadlineExceeded { - t.Fatalf("EmptyCall() = _, %v, want _, DeadlineExceeded", err) - } - - var wg sync.WaitGroup - for i := 0; i < 3; i++ { - wg.Add(1) - go func() { - defer wg.Done() - // This RPC blocks until NewAddress is called. - cc.Invoke(context.Background(), "/foo/bar", &req, &reply) - }() - } - time.Sleep(50 * time.Millisecond) - cc.Close() - wg.Wait() -} - -func TestOneServerDownPickfirst(t *testing.T) { - defer leakcheck.Check(t) - r, rcleanup := manual.GenerateAndRegisterManualResolver() - defer rcleanup() - - numServers := 2 - servers, _, scleanup := startServers(t, numServers, math.MaxInt32) - defer scleanup() - - cc, err := Dial(r.Scheme()+":///test.server", WithInsecure(), WithCodec(testCodec{}), WithWaitForHandshake()) - if err != nil { - t.Fatalf("failed to dial: %v", err) - } - defer cc.Close() - // The first RPC should fail because there's no address. - ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond) - defer cancel() - req := "port" - var reply string - if err := cc.Invoke(ctx, "/foo/bar", &req, &reply); err == nil || status.Code(err) != codes.DeadlineExceeded { - t.Fatalf("EmptyCall() = _, %v, want _, DeadlineExceeded", err) - } - - r.NewAddress([]resolver.Address{{Addr: servers[0].addr}, {Addr: servers[1].addr}}) - // The second RPC should succeed with the first server. - for i := 0; i < 1000; i++ { - if err = cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err != nil && errorDesc(err) == servers[0].port { - break - } - time.Sleep(time.Millisecond) - } - - servers[0].stop() - for i := 0; i < 1000; i++ { - if err = cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err != nil && errorDesc(err) == servers[1].port { - return - } - time.Sleep(time.Millisecond) - } - t.Fatalf("EmptyCall() = _, %v, want _, %v", err, servers[0].port) -} - -func TestAllServersDownPickfirst(t *testing.T) { - defer leakcheck.Check(t) - r, rcleanup := manual.GenerateAndRegisterManualResolver() - defer rcleanup() - - numServers := 2 - servers, _, scleanup := startServers(t, numServers, math.MaxInt32) - defer scleanup() - - cc, err := Dial(r.Scheme()+":///test.server", WithInsecure(), WithCodec(testCodec{}), WithWaitForHandshake()) - if err != nil { - t.Fatalf("failed to dial: %v", err) - } - defer cc.Close() - // The first RPC should fail because there's no address. - ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond) - defer cancel() - req := "port" - var reply string - if err := cc.Invoke(ctx, "/foo/bar", &req, &reply); err == nil || status.Code(err) != codes.DeadlineExceeded { - t.Fatalf("EmptyCall() = _, %v, want _, DeadlineExceeded", err) - } - - r.NewAddress([]resolver.Address{{Addr: servers[0].addr}, {Addr: servers[1].addr}}) - // The second RPC should succeed with the first server. - for i := 0; i < 1000; i++ { - if err = cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err != nil && errorDesc(err) == servers[0].port { - break - } - time.Sleep(time.Millisecond) - } - - for i := 0; i < numServers; i++ { - servers[i].stop() - } - for i := 0; i < 1000; i++ { - if err = cc.Invoke(context.Background(), "/foo/bar", &req, &reply); status.Code(err) == codes.Unavailable { - return - } - time.Sleep(time.Millisecond) - } - t.Fatalf("EmptyCall() = _, %v, want _, error with code unavailable", err) -} - -func TestAddressesRemovedPickfirst(t *testing.T) { - defer leakcheck.Check(t) - r, rcleanup := manual.GenerateAndRegisterManualResolver() - defer rcleanup() - - numServers := 3 - servers, _, scleanup := startServers(t, numServers, math.MaxInt32) - defer scleanup() - - cc, err := Dial(r.Scheme()+":///test.server", WithInsecure(), WithCodec(testCodec{})) - if err != nil { - t.Fatalf("failed to dial: %v", err) - } - defer cc.Close() - // The first RPC should fail because there's no address. - ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond) - defer cancel() - req := "port" - var reply string - if err := cc.Invoke(ctx, "/foo/bar", &req, &reply); err == nil || status.Code(err) != codes.DeadlineExceeded { - t.Fatalf("EmptyCall() = _, %v, want _, DeadlineExceeded", err) - } - - r.NewAddress([]resolver.Address{{Addr: servers[0].addr}, {Addr: servers[1].addr}, {Addr: servers[2].addr}}) - for i := 0; i < 1000; i++ { - if err = cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err != nil && errorDesc(err) == servers[0].port { - break - } - time.Sleep(time.Millisecond) - } - for i := 0; i < 20; i++ { - if err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err == nil || errorDesc(err) != servers[0].port { - t.Fatalf("Index %d: Invoke(_, _, _, _, _) = %v, want %s", 0, err, servers[0].port) - } - time.Sleep(10 * time.Millisecond) - } - - // Remove server[0]. - r.NewAddress([]resolver.Address{{Addr: servers[1].addr}, {Addr: servers[2].addr}}) - for i := 0; i < 1000; i++ { - if err = cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err != nil && errorDesc(err) == servers[1].port { - break - } - time.Sleep(time.Millisecond) - } - for i := 0; i < 20; i++ { - if err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err == nil || errorDesc(err) != servers[1].port { - t.Fatalf("Index %d: Invoke(_, _, _, _, _) = %v, want %s", 1, err, servers[1].port) - } - time.Sleep(10 * time.Millisecond) - } - - // Append server[0], nothing should change. - r.NewAddress([]resolver.Address{{Addr: servers[1].addr}, {Addr: servers[2].addr}, {Addr: servers[0].addr}}) - for i := 0; i < 20; i++ { - if err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err == nil || errorDesc(err) != servers[1].port { - t.Fatalf("Index %d: Invoke(_, _, _, _, _) = %v, want %s", 1, err, servers[1].port) - } - time.Sleep(10 * time.Millisecond) - } - - // Remove server[1]. - r.NewAddress([]resolver.Address{{Addr: servers[2].addr}, {Addr: servers[0].addr}}) - for i := 0; i < 1000; i++ { - if err = cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err != nil && errorDesc(err) == servers[2].port { - break - } - time.Sleep(time.Millisecond) - } - for i := 0; i < 20; i++ { - if err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err == nil || errorDesc(err) != servers[2].port { - t.Fatalf("Index %d: Invoke(_, _, _, _, _) = %v, want %s", 2, err, servers[2].port) - } - time.Sleep(10 * time.Millisecond) - } - - // Remove server[2]. - r.NewAddress([]resolver.Address{{Addr: servers[0].addr}}) - for i := 0; i < 1000; i++ { - if err = cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err != nil && errorDesc(err) == servers[0].port { - break - } - time.Sleep(time.Millisecond) - } - for i := 0; i < 20; i++ { - if err := cc.Invoke(context.Background(), "/foo/bar", &req, &reply); err == nil || errorDesc(err) != servers[0].port { - t.Fatalf("Index %d: Invoke(_, _, _, _, _) = %v, want %s", 0, err, servers[0].port) - } - time.Sleep(10 * time.Millisecond) - } -} diff --git a/vendor/google.golang.org/grpc/proxy_test.go b/vendor/google.golang.org/grpc/proxy_test.go deleted file mode 100644 index 9ab72cb8..00000000 --- a/vendor/google.golang.org/grpc/proxy_test.go +++ /dev/null @@ -1,235 +0,0 @@ -// +build !race - -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package grpc - -import ( - "bufio" - "context" - "encoding/base64" - "fmt" - "io" - "net" - "net/http" - "net/url" - "testing" - "time" - - "google.golang.org/grpc/internal/leakcheck" -) - -const ( - envTestAddr = "1.2.3.4:8080" - envProxyAddr = "2.3.4.5:7687" -) - -// overwriteAndRestore overwrite function httpProxyFromEnvironment and -// returns a function to restore the default values. -func overwrite(hpfe func(req *http.Request) (*url.URL, error)) func() { - backHPFE := httpProxyFromEnvironment - httpProxyFromEnvironment = hpfe - return func() { - httpProxyFromEnvironment = backHPFE - } -} - -type proxyServer struct { - t *testing.T - lis net.Listener - in net.Conn - out net.Conn - - requestCheck func(*http.Request) error -} - -func (p *proxyServer) run() { - in, err := p.lis.Accept() - if err != nil { - return - } - p.in = in - - req, err := http.ReadRequest(bufio.NewReader(in)) - if err != nil { - p.t.Errorf("failed to read CONNECT req: %v", err) - return - } - if err := p.requestCheck(req); err != nil { - resp := http.Response{StatusCode: http.StatusMethodNotAllowed} - resp.Write(p.in) - p.in.Close() - p.t.Errorf("get wrong CONNECT req: %+v, error: %v", req, err) - return - } - - out, err := net.Dial("tcp", req.URL.Host) - if err != nil { - p.t.Errorf("failed to dial to server: %v", err) - return - } - resp := http.Response{StatusCode: http.StatusOK, Proto: "HTTP/1.0"} - resp.Write(p.in) - p.out = out - go io.Copy(p.in, p.out) - go io.Copy(p.out, p.in) -} - -func (p *proxyServer) stop() { - p.lis.Close() - if p.in != nil { - p.in.Close() - } - if p.out != nil { - p.out.Close() - } -} - -func testHTTPConnect(t *testing.T, proxyURLModify func(*url.URL) *url.URL, proxyReqCheck func(*http.Request) error) { - defer leakcheck.Check(t) - plis, err := net.Listen("tcp", "localhost:0") - if err != nil { - t.Fatalf("failed to listen: %v", err) - } - p := &proxyServer{ - t: t, - lis: plis, - requestCheck: proxyReqCheck, - } - go p.run() - defer p.stop() - - blis, err := net.Listen("tcp", "localhost:0") - if err != nil { - t.Fatalf("failed to listen: %v", err) - } - - msg := []byte{4, 3, 5, 2} - recvBuf := make([]byte, len(msg)) - done := make(chan struct{}) - go func() { - in, err := blis.Accept() - if err != nil { - t.Errorf("failed to accept: %v", err) - return - } - defer in.Close() - in.Read(recvBuf) - close(done) - }() - - // Overwrite the function in the test and restore them in defer. - hpfe := func(req *http.Request) (*url.URL, error) { - return proxyURLModify(&url.URL{Host: plis.Addr().String()}), nil - } - defer overwrite(hpfe)() - - // Dial to proxy server. - dialer := newProxyDialer(func(ctx context.Context, addr string) (net.Conn, error) { - if deadline, ok := ctx.Deadline(); ok { - return net.DialTimeout("tcp", addr, deadline.Sub(time.Now())) - } - return net.Dial("tcp", addr) - }) - ctx, cancel := context.WithTimeout(context.Background(), time.Second) - defer cancel() - c, err := dialer(ctx, blis.Addr().String()) - if err != nil { - t.Fatalf("http connect Dial failed: %v", err) - } - defer c.Close() - - // Send msg on the connection. - c.Write(msg) - <-done - - // Check received msg. - if string(recvBuf) != string(msg) { - t.Fatalf("received msg: %v, want %v", recvBuf, msg) - } -} - -func TestHTTPConnect(t *testing.T) { - testHTTPConnect(t, - func(in *url.URL) *url.URL { - return in - }, - func(req *http.Request) error { - if req.Method != http.MethodConnect { - return fmt.Errorf("unexpected Method %q, want %q", req.Method, http.MethodConnect) - } - if req.UserAgent() != grpcUA { - return fmt.Errorf("unexpect user agent %q, want %q", req.UserAgent(), grpcUA) - } - return nil - }, - ) -} - -func TestHTTPConnectBasicAuth(t *testing.T) { - const ( - user = "notAUser" - password = "notAPassword" - ) - testHTTPConnect(t, - func(in *url.URL) *url.URL { - in.User = url.UserPassword(user, password) - return in - }, - func(req *http.Request) error { - if req.Method != http.MethodConnect { - return fmt.Errorf("unexpected Method %q, want %q", req.Method, http.MethodConnect) - } - if req.UserAgent() != grpcUA { - return fmt.Errorf("unexpect user agent %q, want %q", req.UserAgent(), grpcUA) - } - wantProxyAuthStr := "Basic " + base64.StdEncoding.EncodeToString([]byte(user+":"+password)) - if got := req.Header.Get(proxyAuthHeaderKey); got != wantProxyAuthStr { - gotDecoded, _ := base64.StdEncoding.DecodeString(got) - wantDecoded, _ := base64.StdEncoding.DecodeString(wantProxyAuthStr) - return fmt.Errorf("unexpected auth %q (%q), want %q (%q)", got, gotDecoded, wantProxyAuthStr, wantDecoded) - } - return nil - }, - ) -} - -func TestMapAddressEnv(t *testing.T) { - defer leakcheck.Check(t) - // Overwrite the function in the test and restore them in defer. - hpfe := func(req *http.Request) (*url.URL, error) { - if req.URL.Host == envTestAddr { - return &url.URL{ - Scheme: "https", - Host: envProxyAddr, - }, nil - } - return nil, nil - } - defer overwrite(hpfe)() - - // envTestAddr should be handled by ProxyFromEnvironment. - got, err := mapAddress(context.Background(), envTestAddr) - if err != nil { - t.Error(err) - } - if got.Host != envProxyAddr { - t.Errorf("want %v, got %v", envProxyAddr, got) - } -} diff --git a/vendor/google.golang.org/grpc/resolver/dns/dns_resolver_test.go b/vendor/google.golang.org/grpc/resolver/dns/dns_resolver_test.go deleted file mode 100644 index 07673d0d..00000000 --- a/vendor/google.golang.org/grpc/resolver/dns/dns_resolver_test.go +++ /dev/null @@ -1,1124 +0,0 @@ -/* - * - * Copyright 2018 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package dns - -import ( - "context" - "errors" - "fmt" - "net" - "os" - "reflect" - "sync" - "testing" - "time" - - "google.golang.org/grpc/internal/leakcheck" - "google.golang.org/grpc/resolver" -) - -func TestMain(m *testing.M) { - cleanup := replaceNetFunc() - code := m.Run() - cleanup() - os.Exit(code) -} - -const ( - txtBytesLimit = 255 -) - -type testClientConn struct { - target string - m1 sync.Mutex - addrs []resolver.Address - a int // how many times NewAddress() has been called - m2 sync.Mutex - sc string - s int -} - -func (t *testClientConn) NewAddress(addresses []resolver.Address) { - t.m1.Lock() - defer t.m1.Unlock() - t.addrs = addresses - t.a++ -} - -func (t *testClientConn) getAddress() ([]resolver.Address, int) { - t.m1.Lock() - defer t.m1.Unlock() - return t.addrs, t.a -} - -func (t *testClientConn) NewServiceConfig(serviceConfig string) { - t.m2.Lock() - defer t.m2.Unlock() - t.sc = serviceConfig - t.s++ -} - -func (t *testClientConn) getSc() (string, int) { - t.m2.Lock() - defer t.m2.Unlock() - return t.sc, t.s -} - -type testResolver struct { -} - -func (*testResolver) LookupHost(ctx context.Context, host string) ([]string, error) { - return hostLookup(host) -} - -func (*testResolver) LookupSRV(ctx context.Context, service, proto, name string) (string, []*net.SRV, error) { - return srvLookup(service, proto, name) -} - -func (*testResolver) LookupTXT(ctx context.Context, host string) ([]string, error) { - return txtLookup(host) -} - -func replaceNetFunc() func() { - oldResolver := defaultResolver - defaultResolver = &testResolver{} - - return func() { - defaultResolver = oldResolver - } -} - -var hostLookupTbl = struct { - sync.Mutex - tbl map[string][]string -}{ - tbl: map[string][]string{ - "foo.bar.com": {"1.2.3.4", "5.6.7.8"}, - "ipv4.single.fake": {"1.2.3.4"}, - "srv.ipv4.single.fake": {"2.4.6.8"}, - "ipv4.multi.fake": {"1.2.3.4", "5.6.7.8", "9.10.11.12"}, - "ipv6.single.fake": {"2607:f8b0:400a:801::1001"}, - "ipv6.multi.fake": {"2607:f8b0:400a:801::1001", "2607:f8b0:400a:801::1002", "2607:f8b0:400a:801::1003"}, - }, -} - -func hostLookup(host string) ([]string, error) { - hostLookupTbl.Lock() - defer hostLookupTbl.Unlock() - if addrs, cnt := hostLookupTbl.tbl[host]; cnt { - return addrs, nil - } - return nil, fmt.Errorf("failed to lookup host:%s resolution in hostLookupTbl", host) -} - -var srvLookupTbl = struct { - sync.Mutex - tbl map[string][]*net.SRV -}{ - tbl: map[string][]*net.SRV{ - "_grpclb._tcp.srv.ipv4.single.fake": {&net.SRV{Target: "ipv4.single.fake", Port: 1234}}, - "_grpclb._tcp.srv.ipv4.multi.fake": {&net.SRV{Target: "ipv4.multi.fake", Port: 1234}}, - "_grpclb._tcp.srv.ipv6.single.fake": {&net.SRV{Target: "ipv6.single.fake", Port: 1234}}, - "_grpclb._tcp.srv.ipv6.multi.fake": {&net.SRV{Target: "ipv6.multi.fake", Port: 1234}}, - }, -} - -func srvLookup(service, proto, name string) (string, []*net.SRV, error) { - cname := "_" + service + "._" + proto + "." + name - srvLookupTbl.Lock() - defer srvLookupTbl.Unlock() - if srvs, cnt := srvLookupTbl.tbl[cname]; cnt { - return cname, srvs, nil - } - return "", nil, fmt.Errorf("failed to lookup srv record for %s in srvLookupTbl", cname) -} - -// div divides a byte slice into a slice of strings, each of which is of maximum -// 255 bytes length, which is the length limit per TXT record in DNS. -func div(b []byte) []string { - var r []string - for i := 0; i < len(b); i += txtBytesLimit { - if i+txtBytesLimit > len(b) { - r = append(r, string(b[i:])) - } else { - r = append(r, string(b[i:i+txtBytesLimit])) - } - } - return r -} - -// scfs contains an array of service config file string in JSON format. -// Notes about the scfs contents and usage: -// scfs contains 4 service config file JSON strings for testing. Inside each -// service config file, there are multiple choices. scfs[0:3] each contains 5 -// choices, and first 3 choices are nonmatching choices based on canarying rule, -// while the last two are matched choices. scfs[3] only contains 3 choices, and -// all of them are nonmatching based on canarying rule. For each of scfs[0:3], -// the eventually returned service config, which is from the first of the two -// matched choices, is stored in the corresponding scs element (e.g. -// scfs[0]->scs[0]). scfs and scs elements are used in pair to test the dns -// resolver functionality, with scfs as the input and scs used for validation of -// the output. For scfs[3], it corresponds to empty service config, since there -// isn't a matched choice. -var scfs = []string{ - `[ - { - "clientLanguage": [ - "CPP", - "JAVA" - ], - "serviceConfig": { - "loadBalancingPolicy": "grpclb", - "methodConfig": [ - { - "name": [ - { - "service": "all" - } - ], - "timeout": "1s" - } - ] - } - }, - { - "percentage": 0, - "serviceConfig": { - "loadBalancingPolicy": "grpclb", - "methodConfig": [ - { - "name": [ - { - "service": "all" - } - ], - "timeout": "1s" - } - ] - } - }, - { - "clientHostName": [ - "localhost" - ], - "serviceConfig": { - "loadBalancingPolicy": "grpclb", - "methodConfig": [ - { - "name": [ - { - "service": "all" - } - ], - "timeout": "1s" - } - ] - } - }, - { - "clientLanguage": [ - "GO" - ], - "percentage": 100, - "serviceConfig": { - "methodConfig": [ - { - "name": [ - { - "method": "bar" - } - ], - "maxRequestMessageBytes": 1024, - "maxResponseMessageBytes": 1024 - } - ] - } - }, - { - "serviceConfig": { - "loadBalancingPolicy": "round_robin", - "methodConfig": [ - { - "name": [ - { - "service": "foo", - "method": "bar" - } - ], - "waitForReady": true - } - ] - } - } -]`, - `[ - { - "clientLanguage": [ - "CPP", - "JAVA" - ], - "serviceConfig": { - "loadBalancingPolicy": "grpclb", - "methodConfig": [ - { - "name": [ - { - "service": "all" - } - ], - "timeout": "1s" - } - ] - } - }, - { - "percentage": 0, - "serviceConfig": { - "loadBalancingPolicy": "grpclb", - "methodConfig": [ - { - "name": [ - { - "service": "all" - } - ], - "timeout": "1s" - } - ] - } - }, - { - "clientHostName": [ - "localhost" - ], - "serviceConfig": { - "loadBalancingPolicy": "grpclb", - "methodConfig": [ - { - "name": [ - { - "service": "all" - } - ], - "timeout": "1s" - } - ] - } - }, - { - "clientLanguage": [ - "GO" - ], - "percentage": 100, - "serviceConfig": { - "methodConfig": [ - { - "name": [ - { - "service": "foo", - "method": "bar" - } - ], - "waitForReady": true, - "timeout": "1s", - "maxRequestMessageBytes": 1024, - "maxResponseMessageBytes": 1024 - } - ] - } - }, - { - "serviceConfig": { - "loadBalancingPolicy": "round_robin", - "methodConfig": [ - { - "name": [ - { - "service": "foo", - "method": "bar" - } - ], - "waitForReady": true - } - ] - } - } -]`, - `[ - { - "clientLanguage": [ - "CPP", - "JAVA" - ], - "serviceConfig": { - "loadBalancingPolicy": "grpclb", - "methodConfig": [ - { - "name": [ - { - "service": "all" - } - ], - "timeout": "1s" - } - ] - } - }, - { - "percentage": 0, - "serviceConfig": { - "loadBalancingPolicy": "grpclb", - "methodConfig": [ - { - "name": [ - { - "service": "all" - } - ], - "timeout": "1s" - } - ] - } - }, - { - "clientHostName": [ - "localhost" - ], - "serviceConfig": { - "loadBalancingPolicy": "grpclb", - "methodConfig": [ - { - "name": [ - { - "service": "all" - } - ], - "timeout": "1s" - } - ] - } - }, - { - "clientLanguage": [ - "GO" - ], - "percentage": 100, - "serviceConfig": { - "loadBalancingPolicy": "round_robin", - "methodConfig": [ - { - "name": [ - { - "service": "foo" - } - ], - "waitForReady": true, - "timeout": "1s" - }, - { - "name": [ - { - "service": "bar" - } - ], - "waitForReady": false - } - ] - } - }, - { - "serviceConfig": { - "loadBalancingPolicy": "round_robin", - "methodConfig": [ - { - "name": [ - { - "service": "foo", - "method": "bar" - } - ], - "waitForReady": true - } - ] - } - } -]`, - `[ - { - "clientLanguage": [ - "CPP", - "JAVA" - ], - "serviceConfig": { - "loadBalancingPolicy": "grpclb", - "methodConfig": [ - { - "name": [ - { - "service": "all" - } - ], - "timeout": "1s" - } - ] - } - }, - { - "percentage": 0, - "serviceConfig": { - "loadBalancingPolicy": "grpclb", - "methodConfig": [ - { - "name": [ - { - "service": "all" - } - ], - "timeout": "1s" - } - ] - } - }, - { - "clientHostName": [ - "localhost" - ], - "serviceConfig": { - "loadBalancingPolicy": "grpclb", - "methodConfig": [ - { - "name": [ - { - "service": "all" - } - ], - "timeout": "1s" - } - ] - } - } -]`, -} - -// scs contains an array of service config string in JSON format. -var scs = []string{ - `{ - "methodConfig": [ - { - "name": [ - { - "method": "bar" - } - ], - "maxRequestMessageBytes": 1024, - "maxResponseMessageBytes": 1024 - } - ] - }`, - `{ - "methodConfig": [ - { - "name": [ - { - "service": "foo", - "method": "bar" - } - ], - "waitForReady": true, - "timeout": "1s", - "maxRequestMessageBytes": 1024, - "maxResponseMessageBytes": 1024 - } - ] - }`, - `{ - "loadBalancingPolicy": "round_robin", - "methodConfig": [ - { - "name": [ - { - "service": "foo" - } - ], - "waitForReady": true, - "timeout": "1s" - }, - { - "name": [ - { - "service": "bar" - } - ], - "waitForReady": false - } - ] - }`, -} - -// scLookupTbl is a set, which contains targets that have service config. Target -// not in this set should not have service config. -var scLookupTbl = map[string]bool{ - "foo.bar.com": true, - "srv.ipv4.single.fake": true, - "srv.ipv4.multi.fake": true, - "no.attribute": true, -} - -// generateSCF generates a slice of strings (aggregately representing a single -// service config file) for the input name, which mocks the result from a real -// DNS TXT record lookup. -func generateSCF(name string) []string { - var b []byte - switch name { - case "foo.bar.com": - b = []byte(scfs[0]) - case "srv.ipv4.single.fake": - b = []byte(scfs[1]) - case "srv.ipv4.multi.fake": - b = []byte(scfs[2]) - default: - b = []byte(scfs[3]) - } - if name == "no.attribute" { - return div(b) - } - return div(append([]byte(txtAttribute), b...)) -} - -// generateSC returns a service config string in JSON format for the input name. -func generateSC(name string) string { - _, cnt := scLookupTbl[name] - if !cnt || name == "no.attribute" { - return "" - } - switch name { - case "foo.bar.com": - return scs[0] - case "srv.ipv4.single.fake": - return scs[1] - case "srv.ipv4.multi.fake": - return scs[2] - default: - return "" - } -} - -var txtLookupTbl = struct { - sync.Mutex - tbl map[string][]string -}{ - tbl: map[string][]string{ - "foo.bar.com": generateSCF("foo.bar.com"), - "srv.ipv4.single.fake": generateSCF("srv.ipv4.single.fake"), - "srv.ipv4.multi.fake": generateSCF("srv.ipv4.multi.fake"), - "srv.ipv6.single.fake": generateSCF("srv.ipv6.single.fake"), - "srv.ipv6.multi.fake": generateSCF("srv.ipv6.multi.fake"), - "no.attribute": generateSCF("no.attribute"), - }, -} - -func txtLookup(host string) ([]string, error) { - txtLookupTbl.Lock() - defer txtLookupTbl.Unlock() - if scs, cnt := txtLookupTbl.tbl[host]; cnt { - return scs, nil - } - return nil, fmt.Errorf("failed to lookup TXT:%s resolution in txtLookupTbl", host) -} - -func TestResolve(t *testing.T) { - testDNSResolver(t) - testDNSResolveNow(t) - testIPResolver(t) -} - -func testDNSResolver(t *testing.T) { - defer leakcheck.Check(t) - tests := []struct { - target string - addrWant []resolver.Address - scWant string - }{ - { - "foo.bar.com", - []resolver.Address{{Addr: "1.2.3.4" + colonDefaultPort}, {Addr: "5.6.7.8" + colonDefaultPort}}, - generateSC("foo.bar.com"), - }, - { - "foo.bar.com:1234", - []resolver.Address{{Addr: "1.2.3.4:1234"}, {Addr: "5.6.7.8:1234"}}, - generateSC("foo.bar.com"), - }, - { - "srv.ipv4.single.fake", - []resolver.Address{{Addr: "1.2.3.4:1234", Type: resolver.GRPCLB, ServerName: "ipv4.single.fake"}, {Addr: "2.4.6.8" + colonDefaultPort}}, - generateSC("srv.ipv4.single.fake"), - }, - { - "srv.ipv4.multi.fake", - []resolver.Address{ - {Addr: "1.2.3.4:1234", Type: resolver.GRPCLB, ServerName: "ipv4.multi.fake"}, - {Addr: "5.6.7.8:1234", Type: resolver.GRPCLB, ServerName: "ipv4.multi.fake"}, - {Addr: "9.10.11.12:1234", Type: resolver.GRPCLB, ServerName: "ipv4.multi.fake"}, - }, - generateSC("srv.ipv4.multi.fake"), - }, - { - "srv.ipv6.single.fake", - []resolver.Address{{Addr: "[2607:f8b0:400a:801::1001]:1234", Type: resolver.GRPCLB, ServerName: "ipv6.single.fake"}}, - generateSC("srv.ipv6.single.fake"), - }, - { - "srv.ipv6.multi.fake", - []resolver.Address{ - {Addr: "[2607:f8b0:400a:801::1001]:1234", Type: resolver.GRPCLB, ServerName: "ipv6.multi.fake"}, - {Addr: "[2607:f8b0:400a:801::1002]:1234", Type: resolver.GRPCLB, ServerName: "ipv6.multi.fake"}, - {Addr: "[2607:f8b0:400a:801::1003]:1234", Type: resolver.GRPCLB, ServerName: "ipv6.multi.fake"}, - }, - generateSC("srv.ipv6.multi.fake"), - }, - { - "no.attribute", - nil, - generateSC("no.attribute"), - }, - } - - for _, a := range tests { - b := NewBuilder() - cc := &testClientConn{target: a.target} - r, err := b.Build(resolver.Target{Endpoint: a.target}, cc, resolver.BuildOption{}) - if err != nil { - t.Fatalf("%v\n", err) - } - var addrs []resolver.Address - var cnt int - for { - addrs, cnt = cc.getAddress() - if cnt > 0 { - break - } - time.Sleep(time.Millisecond) - } - var sc string - for { - sc, cnt = cc.getSc() - if cnt > 0 { - break - } - time.Sleep(time.Millisecond) - } - if !reflect.DeepEqual(a.addrWant, addrs) { - t.Errorf("Resolved addresses of target: %q = %+v, want %+v\n", a.target, addrs, a.addrWant) - } - if !reflect.DeepEqual(a.scWant, sc) { - t.Errorf("Resolved service config of target: %q = %+v, want %+v\n", a.target, sc, a.scWant) - } - r.Close() - } -} - -func mutateTbl(target string) func() { - hostLookupTbl.Lock() - oldHostTblEntry := hostLookupTbl.tbl[target] - hostLookupTbl.tbl[target] = hostLookupTbl.tbl[target][:len(oldHostTblEntry)-1] - hostLookupTbl.Unlock() - txtLookupTbl.Lock() - oldTxtTblEntry := txtLookupTbl.tbl[target] - txtLookupTbl.tbl[target] = []string{""} - txtLookupTbl.Unlock() - - return func() { - hostLookupTbl.Lock() - hostLookupTbl.tbl[target] = oldHostTblEntry - hostLookupTbl.Unlock() - txtLookupTbl.Lock() - txtLookupTbl.tbl[target] = oldTxtTblEntry - txtLookupTbl.Unlock() - } -} - -func testDNSResolveNow(t *testing.T) { - defer leakcheck.Check(t) - tests := []struct { - target string - addrWant []resolver.Address - addrNext []resolver.Address - scWant string - scNext string - }{ - { - "foo.bar.com", - []resolver.Address{{Addr: "1.2.3.4" + colonDefaultPort}, {Addr: "5.6.7.8" + colonDefaultPort}}, - []resolver.Address{{Addr: "1.2.3.4" + colonDefaultPort}}, - generateSC("foo.bar.com"), - "", - }, - } - - for _, a := range tests { - b := NewBuilder() - cc := &testClientConn{target: a.target} - r, err := b.Build(resolver.Target{Endpoint: a.target}, cc, resolver.BuildOption{}) - if err != nil { - t.Fatalf("%v\n", err) - } - var addrs []resolver.Address - var cnt int - for { - addrs, cnt = cc.getAddress() - if cnt > 0 { - break - } - time.Sleep(time.Millisecond) - } - var sc string - for { - sc, cnt = cc.getSc() - if cnt > 0 { - break - } - time.Sleep(time.Millisecond) - } - if !reflect.DeepEqual(a.addrWant, addrs) { - t.Errorf("Resolved addresses of target: %q = %+v, want %+v\n", a.target, addrs, a.addrWant) - } - if !reflect.DeepEqual(a.scWant, sc) { - t.Errorf("Resolved service config of target: %q = %+v, want %+v\n", a.target, sc, a.scWant) - } - revertTbl := mutateTbl(a.target) - r.ResolveNow(resolver.ResolveNowOption{}) - for { - addrs, cnt = cc.getAddress() - if cnt == 2 { - break - } - time.Sleep(time.Millisecond) - } - for { - sc, cnt = cc.getSc() - if cnt == 2 { - break - } - time.Sleep(time.Millisecond) - } - if !reflect.DeepEqual(a.addrNext, addrs) { - t.Errorf("Resolved addresses of target: %q = %+v, want %+v\n", a.target, addrs, a.addrNext) - } - if !reflect.DeepEqual(a.scNext, sc) { - t.Errorf("Resolved service config of target: %q = %+v, want %+v\n", a.target, sc, a.scNext) - } - revertTbl() - r.Close() - } -} - -const colonDefaultPort = ":" + defaultPort - -func testIPResolver(t *testing.T) { - defer leakcheck.Check(t) - tests := []struct { - target string - want []resolver.Address - }{ - {"127.0.0.1", []resolver.Address{{Addr: "127.0.0.1" + colonDefaultPort}}}, - {"127.0.0.1:12345", []resolver.Address{{Addr: "127.0.0.1:12345"}}}, - {"::1", []resolver.Address{{Addr: "[::1]" + colonDefaultPort}}}, - {"[::1]:12345", []resolver.Address{{Addr: "[::1]:12345"}}}, - {"[::1]", []resolver.Address{{Addr: "[::1]:443"}}}, - {"2001:db8:85a3::8a2e:370:7334", []resolver.Address{{Addr: "[2001:db8:85a3::8a2e:370:7334]" + colonDefaultPort}}}, - {"[2001:db8:85a3::8a2e:370:7334]", []resolver.Address{{Addr: "[2001:db8:85a3::8a2e:370:7334]" + colonDefaultPort}}}, - {"[2001:db8:85a3::8a2e:370:7334]:12345", []resolver.Address{{Addr: "[2001:db8:85a3::8a2e:370:7334]:12345"}}}, - {"[2001:db8::1]:http", []resolver.Address{{Addr: "[2001:db8::1]:http"}}}, - // TODO(yuxuanli): zone support? - } - - for _, v := range tests { - b := NewBuilder() - cc := &testClientConn{target: v.target} - r, err := b.Build(resolver.Target{Endpoint: v.target}, cc, resolver.BuildOption{}) - if err != nil { - t.Fatalf("%v\n", err) - } - var addrs []resolver.Address - var cnt int - for { - addrs, cnt = cc.getAddress() - if cnt > 0 { - break - } - time.Sleep(time.Millisecond) - } - if !reflect.DeepEqual(v.want, addrs) { - t.Errorf("Resolved addresses of target: %q = %+v, want %+v\n", v.target, addrs, v.want) - } - r.ResolveNow(resolver.ResolveNowOption{}) - for { - addrs, cnt = cc.getAddress() - if cnt == 2 { - break - } - time.Sleep(time.Millisecond) - } - if !reflect.DeepEqual(v.want, addrs) { - t.Errorf("Resolved addresses of target: %q = %+v, want %+v\n", v.target, addrs, v.want) - } - r.Close() - } -} - -func TestResolveFunc(t *testing.T) { - defer leakcheck.Check(t) - tests := []struct { - addr string - want error - }{ - // TODO(yuxuanli): More false cases? - {"www.google.com", nil}, - {"foo.bar:12345", nil}, - {"127.0.0.1", nil}, - {"::", nil}, - {"127.0.0.1:12345", nil}, - {"[::1]:80", nil}, - {"[2001:db8:a0b:12f0::1]:21", nil}, - {":80", nil}, - {"127.0.0...1:12345", nil}, - {"[fe80::1%lo0]:80", nil}, - {"golang.org:http", nil}, - {"[2001:db8::1]:http", nil}, - {"[2001:db8::1]:", errEndsWithColon}, - {":", errEndsWithColon}, - {"", errMissingAddr}, - {"[2001:db8:a0b:12f0::1", fmt.Errorf("invalid target address [2001:db8:a0b:12f0::1, error info: address [2001:db8:a0b:12f0::1:443: missing ']' in address")}, - } - - b := NewBuilder() - for _, v := range tests { - cc := &testClientConn{target: v.addr} - r, err := b.Build(resolver.Target{Endpoint: v.addr}, cc, resolver.BuildOption{}) - if err == nil { - r.Close() - } - if !reflect.DeepEqual(err, v.want) { - t.Errorf("Build(%q, cc, resolver.BuildOption{}) = %v, want %v", v.addr, err, v.want) - } - } -} - -func TestDisableServiceConfig(t *testing.T) { - defer leakcheck.Check(t) - tests := []struct { - target string - scWant string - disableServiceConfig bool - }{ - { - "foo.bar.com", - generateSC("foo.bar.com"), - false, - }, - { - "foo.bar.com", - "", - true, - }, - } - - for _, a := range tests { - b := NewBuilder() - cc := &testClientConn{target: a.target} - r, err := b.Build(resolver.Target{Endpoint: a.target}, cc, resolver.BuildOption{DisableServiceConfig: a.disableServiceConfig}) - if err != nil { - t.Fatalf("%v\n", err) - } - var cnt int - var sc string - for { - sc, cnt = cc.getSc() - if cnt > 0 { - break - } - time.Sleep(time.Millisecond) - } - if !reflect.DeepEqual(a.scWant, sc) { - t.Errorf("Resolved service config of target: %q = %+v, want %+v\n", a.target, sc, a.scWant) - } - r.Close() - } -} - -func TestDNSResolverRetry(t *testing.T) { - b := NewBuilder() - target := "ipv4.single.fake" - cc := &testClientConn{target: target} - r, err := b.Build(resolver.Target{Endpoint: target}, cc, resolver.BuildOption{}) - if err != nil { - t.Fatalf("%v\n", err) - } - var addrs []resolver.Address - for { - addrs, _ = cc.getAddress() - if len(addrs) == 1 { - break - } - time.Sleep(time.Millisecond) - } - want := []resolver.Address{{Addr: "1.2.3.4" + colonDefaultPort}} - if !reflect.DeepEqual(want, addrs) { - t.Errorf("Resolved addresses of target: %q = %+v, want %+v\n", target, addrs, want) - } - // mutate the host lookup table so the target has 0 address returned. - revertTbl := mutateTbl(target) - // trigger a resolve that will get empty address list - r.ResolveNow(resolver.ResolveNowOption{}) - for { - addrs, _ = cc.getAddress() - if len(addrs) == 0 { - break - } - time.Sleep(time.Millisecond) - } - revertTbl() - // wait for the retry to happen in two seconds. - timer := time.NewTimer(2 * time.Second) - for { - b := false - select { - case <-timer.C: - b = true - default: - addrs, _ = cc.getAddress() - if len(addrs) == 1 { - b = true - break - } - time.Sleep(time.Millisecond) - } - if b { - break - } - } - if !reflect.DeepEqual(want, addrs) { - t.Errorf("Resolved addresses of target: %q = %+v, want %+v\n", target, addrs, want) - } - r.Close() -} - -func TestCustomAuthority(t *testing.T) { - defer leakcheck.Check(t) - - tests := []struct { - authority string - authorityWant string - expectError bool - }{ - { - "4.3.2.1:" + defaultDNSSvrPort, - "4.3.2.1:" + defaultDNSSvrPort, - false, - }, - { - "4.3.2.1:123", - "4.3.2.1:123", - false, - }, - { - "4.3.2.1", - "4.3.2.1:" + defaultDNSSvrPort, - false, - }, - { - "::1", - "[::1]:" + defaultDNSSvrPort, - false, - }, - { - "[::1]", - "[::1]:" + defaultDNSSvrPort, - false, - }, - { - "[::1]:123", - "[::1]:123", - false, - }, - { - "dnsserver.com", - "dnsserver.com:" + defaultDNSSvrPort, - false, - }, - { - ":123", - "localhost:123", - false, - }, - { - ":", - "", - true, - }, - { - "[::1]:", - "", - true, - }, - { - "dnsserver.com:", - "", - true, - }, - } - oldCustomAuthorityDialler := customAuthorityDialler - defer func() { - customAuthorityDialler = oldCustomAuthorityDialler - }() - - for _, a := range tests { - errChan := make(chan error, 1) - customAuthorityDialler = func(authority string) func(ctx context.Context, network, address string) (net.Conn, error) { - if authority != a.authorityWant { - errChan <- fmt.Errorf("wrong custom authority passed to resolver. input: %s expected: %s actual: %s", a.authority, a.authorityWant, authority) - } else { - errChan <- nil - } - return func(ctx context.Context, network, address string) (net.Conn, error) { - return nil, errors.New("no need to dial") - } - } - - b := NewBuilder() - cc := &testClientConn{target: "foo.bar.com"} - r, err := b.Build(resolver.Target{Endpoint: "foo.bar.com", Authority: a.authority}, cc, resolver.BuildOption{}) - - if err == nil { - r.Close() - - err = <-errChan - if err != nil { - t.Errorf(err.Error()) - } - - if a.expectError { - t.Errorf("custom authority should have caused an error: %s", a.authority) - } - } else if !a.expectError { - t.Errorf("unexpected error using custom authority %s: %s", a.authority, err) - } - } -} diff --git a/vendor/google.golang.org/grpc/resolver_conn_wrapper_test.go b/vendor/google.golang.org/grpc/resolver_conn_wrapper_test.go deleted file mode 100644 index e87b9420..00000000 --- a/vendor/google.golang.org/grpc/resolver_conn_wrapper_test.go +++ /dev/null @@ -1,116 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package grpc - -import ( - "fmt" - "net" - "testing" - "time" - - "google.golang.org/grpc/resolver" -) - -func TestParseTarget(t *testing.T) { - for _, test := range []resolver.Target{ - {Scheme: "dns", Authority: "", Endpoint: "google.com"}, - {Scheme: "dns", Authority: "a.server.com", Endpoint: "google.com"}, - {Scheme: "dns", Authority: "a.server.com", Endpoint: "google.com/?a=b"}, - {Scheme: "passthrough", Authority: "", Endpoint: "/unix/socket/address"}, - } { - str := test.Scheme + "://" + test.Authority + "/" + test.Endpoint - got := parseTarget(str) - if got != test { - t.Errorf("parseTarget(%q) = %+v, want %+v", str, got, test) - } - } -} - -func TestParseTargetString(t *testing.T) { - for _, test := range []struct { - targetStr string - want resolver.Target - }{ - {targetStr: "", want: resolver.Target{Scheme: "", Authority: "", Endpoint: ""}}, - {targetStr: ":///", want: resolver.Target{Scheme: "", Authority: "", Endpoint: ""}}, - {targetStr: "a:///", want: resolver.Target{Scheme: "a", Authority: "", Endpoint: ""}}, - {targetStr: "://a/", want: resolver.Target{Scheme: "", Authority: "a", Endpoint: ""}}, - {targetStr: ":///a", want: resolver.Target{Scheme: "", Authority: "", Endpoint: "a"}}, - {targetStr: "a://b/", want: resolver.Target{Scheme: "a", Authority: "b", Endpoint: ""}}, - {targetStr: "a:///b", want: resolver.Target{Scheme: "a", Authority: "", Endpoint: "b"}}, - {targetStr: "://a/b", want: resolver.Target{Scheme: "", Authority: "a", Endpoint: "b"}}, - {targetStr: "a://b/c", want: resolver.Target{Scheme: "a", Authority: "b", Endpoint: "c"}}, - {targetStr: "dns:///google.com", want: resolver.Target{Scheme: "dns", Authority: "", Endpoint: "google.com"}}, - {targetStr: "dns://a.server.com/google.com", want: resolver.Target{Scheme: "dns", Authority: "a.server.com", Endpoint: "google.com"}}, - {targetStr: "dns://a.server.com/google.com/?a=b", want: resolver.Target{Scheme: "dns", Authority: "a.server.com", Endpoint: "google.com/?a=b"}}, - - {targetStr: "/", want: resolver.Target{Scheme: "", Authority: "", Endpoint: "/"}}, - {targetStr: "google.com", want: resolver.Target{Scheme: "", Authority: "", Endpoint: "google.com"}}, - {targetStr: "google.com/?a=b", want: resolver.Target{Scheme: "", Authority: "", Endpoint: "google.com/?a=b"}}, - {targetStr: "/unix/socket/address", want: resolver.Target{Scheme: "", Authority: "", Endpoint: "/unix/socket/address"}}, - - // If we can only parse part of the target. - {targetStr: "://", want: resolver.Target{Scheme: "", Authority: "", Endpoint: "://"}}, - {targetStr: "unix://domain", want: resolver.Target{Scheme: "", Authority: "", Endpoint: "unix://domain"}}, - {targetStr: "a:b", want: resolver.Target{Scheme: "", Authority: "", Endpoint: "a:b"}}, - {targetStr: "a/b", want: resolver.Target{Scheme: "", Authority: "", Endpoint: "a/b"}}, - {targetStr: "a:/b", want: resolver.Target{Scheme: "", Authority: "", Endpoint: "a:/b"}}, - {targetStr: "a//b", want: resolver.Target{Scheme: "", Authority: "", Endpoint: "a//b"}}, - {targetStr: "a://b", want: resolver.Target{Scheme: "", Authority: "", Endpoint: "a://b"}}, - } { - got := parseTarget(test.targetStr) - if got != test.want { - t.Errorf("parseTarget(%q) = %+v, want %+v", test.targetStr, got, test.want) - } - } -} - -// The target string with unknown scheme should be kept unchanged and passed to -// the dialer. -func TestDialParseTargetUnknownScheme(t *testing.T) { - for _, test := range []struct { - targetStr string - want string - }{ - {"/unix/socket/address", "/unix/socket/address"}, - - // Special test for "unix:///". - {"unix:///unix/socket/address", "unix:///unix/socket/address"}, - - // For known scheme. - {"passthrough://a.server.com/google.com", "google.com"}, - } { - dialStrCh := make(chan string, 1) - cc, err := Dial(test.targetStr, WithInsecure(), WithDialer(func(addr string, _ time.Duration) (net.Conn, error) { - select { - case dialStrCh <- addr: - default: - } - return nil, fmt.Errorf("test dialer, always error") - })) - if err != nil { - t.Fatalf("Failed to create ClientConn: %v", err) - } - got := <-dialStrCh - cc.Close() - if got != test.want { - t.Errorf("Dial(%q), dialer got %q, want %q", test.targetStr, got, test.want) - } - } -} diff --git a/vendor/google.golang.org/grpc/rpc_util_test.go b/vendor/google.golang.org/grpc/rpc_util_test.go deleted file mode 100644 index 0335fc7d..00000000 --- a/vendor/google.golang.org/grpc/rpc_util_test.go +++ /dev/null @@ -1,288 +0,0 @@ -/* - * - * Copyright 2014 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package grpc - -import ( - "bytes" - "compress/gzip" - "io" - "math" - "reflect" - "testing" - - "github.com/golang/protobuf/proto" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/encoding" - protoenc "google.golang.org/grpc/encoding/proto" - "google.golang.org/grpc/internal/transport" - "google.golang.org/grpc/status" - perfpb "google.golang.org/grpc/test/codec_perf" -) - -type fullReader struct { - reader io.Reader -} - -func (f fullReader) Read(p []byte) (int, error) { - return io.ReadFull(f.reader, p) -} - -var _ CallOption = EmptyCallOption{} // ensure EmptyCallOption implements the interface - -func TestSimpleParsing(t *testing.T) { - bigMsg := bytes.Repeat([]byte{'x'}, 1<<24) - for _, test := range []struct { - // input - p []byte - // outputs - err error - b []byte - pt payloadFormat - }{ - {nil, io.EOF, nil, compressionNone}, - {[]byte{0, 0, 0, 0, 0}, nil, nil, compressionNone}, - {[]byte{0, 0, 0, 0, 1, 'a'}, nil, []byte{'a'}, compressionNone}, - {[]byte{1, 0}, io.ErrUnexpectedEOF, nil, compressionNone}, - {[]byte{0, 0, 0, 0, 10, 'a'}, io.ErrUnexpectedEOF, nil, compressionNone}, - // Check that messages with length >= 2^24 are parsed. - {append([]byte{0, 1, 0, 0, 0}, bigMsg...), nil, bigMsg, compressionNone}, - } { - buf := fullReader{bytes.NewReader(test.p)} - parser := &parser{r: buf} - pt, b, err := parser.recvMsg(math.MaxInt32) - if err != test.err || !bytes.Equal(b, test.b) || pt != test.pt { - t.Fatalf("parser{%v}.recvMsg(_) = %v, %v, %v\nwant %v, %v, %v", test.p, pt, b, err, test.pt, test.b, test.err) - } - } -} - -func TestMultipleParsing(t *testing.T) { - // Set a byte stream consists of 3 messages with their headers. - p := []byte{0, 0, 0, 0, 1, 'a', 0, 0, 0, 0, 2, 'b', 'c', 0, 0, 0, 0, 1, 'd'} - b := fullReader{bytes.NewReader(p)} - parser := &parser{r: b} - - wantRecvs := []struct { - pt payloadFormat - data []byte - }{ - {compressionNone, []byte("a")}, - {compressionNone, []byte("bc")}, - {compressionNone, []byte("d")}, - } - for i, want := range wantRecvs { - pt, data, err := parser.recvMsg(math.MaxInt32) - if err != nil || pt != want.pt || !reflect.DeepEqual(data, want.data) { - t.Fatalf("after %d calls, parser{%v}.recvMsg(_) = %v, %v, %v\nwant %v, %v, ", - i, p, pt, data, err, want.pt, want.data) - } - } - - pt, data, err := parser.recvMsg(math.MaxInt32) - if err != io.EOF { - t.Fatalf("after %d recvMsgs calls, parser{%v}.recvMsg(_) = %v, %v, %v\nwant _, _, %v", - len(wantRecvs), p, pt, data, err, io.EOF) - } -} - -func TestEncode(t *testing.T) { - for _, test := range []struct { - // input - msg proto.Message - // outputs - hdr []byte - data []byte - err error - }{ - {nil, []byte{0, 0, 0, 0, 0}, []byte{}, nil}, - } { - data, err := encode(encoding.GetCodec(protoenc.Name), test.msg) - if err != test.err || !bytes.Equal(data, test.data) { - t.Errorf("encode(_, %v) = %v, %v; want %v, %v", test.msg, data, err, test.data, test.err) - continue - } - if hdr, _ := msgHeader(data, nil); !bytes.Equal(hdr, test.hdr) { - t.Errorf("msgHeader(%v, false) = %v; want %v", data, hdr, test.hdr) - } - } -} - -func TestCompress(t *testing.T) { - bestCompressor, err := NewGZIPCompressorWithLevel(gzip.BestCompression) - if err != nil { - t.Fatalf("Could not initialize gzip compressor with best compression.") - } - bestSpeedCompressor, err := NewGZIPCompressorWithLevel(gzip.BestSpeed) - if err != nil { - t.Fatalf("Could not initialize gzip compressor with best speed compression.") - } - - defaultCompressor, err := NewGZIPCompressorWithLevel(gzip.BestSpeed) - if err != nil { - t.Fatalf("Could not initialize gzip compressor with default compression.") - } - - level5, err := NewGZIPCompressorWithLevel(5) - if err != nil { - t.Fatalf("Could not initialize gzip compressor with level 5 compression.") - } - - for _, test := range []struct { - // input - data []byte - cp Compressor - dc Decompressor - // outputs - err error - }{ - {make([]byte, 1024), NewGZIPCompressor(), NewGZIPDecompressor(), nil}, - {make([]byte, 1024), bestCompressor, NewGZIPDecompressor(), nil}, - {make([]byte, 1024), bestSpeedCompressor, NewGZIPDecompressor(), nil}, - {make([]byte, 1024), defaultCompressor, NewGZIPDecompressor(), nil}, - {make([]byte, 1024), level5, NewGZIPDecompressor(), nil}, - } { - b := new(bytes.Buffer) - if err := test.cp.Do(b, test.data); err != test.err { - t.Fatalf("Compressor.Do(_, %v) = %v, want %v", test.data, err, test.err) - } - if b.Len() >= len(test.data) { - t.Fatalf("The compressor fails to compress data.") - } - if p, err := test.dc.Do(b); err != nil || !bytes.Equal(test.data, p) { - t.Fatalf("Decompressor.Do(%v) = %v, %v, want %v, ", b, p, err, test.data) - } - } -} - -func TestToRPCErr(t *testing.T) { - for _, test := range []struct { - // input - errIn error - // outputs - errOut error - }{ - {transport.ErrConnClosing, status.Error(codes.Unavailable, transport.ErrConnClosing.Desc)}, - {io.ErrUnexpectedEOF, status.Error(codes.Internal, io.ErrUnexpectedEOF.Error())}, - } { - err := toRPCErr(test.errIn) - if _, ok := status.FromError(err); !ok { - t.Fatalf("toRPCErr{%v} returned type %T, want %T", test.errIn, err, status.Error(codes.Unknown, "")) - } - if !reflect.DeepEqual(err, test.errOut) { - t.Fatalf("toRPCErr{%v} = %v \nwant %v", test.errIn, err, test.errOut) - } - } -} - -func TestParseDialTarget(t *testing.T) { - for _, test := range []struct { - target, wantNet, wantAddr string - }{ - {"unix:etcd:0", "unix", "etcd:0"}, - {"unix:///tmp/unix-3", "unix", "/tmp/unix-3"}, - {"unix://domain", "unix", "domain"}, - {"unix://etcd:0", "unix", "etcd:0"}, - {"unix:///etcd:0", "unix", "/etcd:0"}, - {"passthrough://unix://domain", "tcp", "passthrough://unix://domain"}, - {"https://google.com:443", "tcp", "https://google.com:443"}, - {"dns:///google.com", "tcp", "dns:///google.com"}, - {"/unix/socket/address", "tcp", "/unix/socket/address"}, - } { - gotNet, gotAddr := parseDialTarget(test.target) - if gotNet != test.wantNet || gotAddr != test.wantAddr { - t.Errorf("parseDialTarget(%q) = %s, %s want %s, %s", test.target, gotNet, gotAddr, test.wantNet, test.wantAddr) - } - } -} - -// bmEncode benchmarks encoding a Protocol Buffer message containing mSize -// bytes. -func bmEncode(b *testing.B, mSize int) { - cdc := encoding.GetCodec(protoenc.Name) - msg := &perfpb.Buffer{Body: make([]byte, mSize)} - encodeData, _ := encode(cdc, msg) - encodedSz := int64(len(encodeData)) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - encode(cdc, msg) - } - b.SetBytes(encodedSz) -} - -func BenchmarkEncode1B(b *testing.B) { - bmEncode(b, 1) -} - -func BenchmarkEncode1KiB(b *testing.B) { - bmEncode(b, 1024) -} - -func BenchmarkEncode8KiB(b *testing.B) { - bmEncode(b, 8*1024) -} - -func BenchmarkEncode64KiB(b *testing.B) { - bmEncode(b, 64*1024) -} - -func BenchmarkEncode512KiB(b *testing.B) { - bmEncode(b, 512*1024) -} - -func BenchmarkEncode1MiB(b *testing.B) { - bmEncode(b, 1024*1024) -} - -// bmCompressor benchmarks a compressor of a Protocol Buffer message containing -// mSize bytes. -func bmCompressor(b *testing.B, mSize int, cp Compressor) { - payload := make([]byte, mSize) - cBuf := bytes.NewBuffer(make([]byte, mSize)) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - cp.Do(cBuf, payload) - cBuf.Reset() - } -} - -func BenchmarkGZIPCompressor1B(b *testing.B) { - bmCompressor(b, 1, NewGZIPCompressor()) -} - -func BenchmarkGZIPCompressor1KiB(b *testing.B) { - bmCompressor(b, 1024, NewGZIPCompressor()) -} - -func BenchmarkGZIPCompressor8KiB(b *testing.B) { - bmCompressor(b, 8*1024, NewGZIPCompressor()) -} - -func BenchmarkGZIPCompressor64KiB(b *testing.B) { - bmCompressor(b, 64*1024, NewGZIPCompressor()) -} - -func BenchmarkGZIPCompressor512KiB(b *testing.B) { - bmCompressor(b, 512*1024, NewGZIPCompressor()) -} - -func BenchmarkGZIPCompressor1MiB(b *testing.B) { - bmCompressor(b, 1024*1024, NewGZIPCompressor()) -} diff --git a/vendor/google.golang.org/grpc/server_test.go b/vendor/google.golang.org/grpc/server_test.go deleted file mode 100644 index 125be01c..00000000 --- a/vendor/google.golang.org/grpc/server_test.go +++ /dev/null @@ -1,136 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package grpc - -import ( - "context" - "net" - "reflect" - "strings" - "testing" - "time" - - "google.golang.org/grpc/internal/leakcheck" - "google.golang.org/grpc/internal/transport" -) - -type emptyServiceServer interface{} - -type testServer struct{} - -func TestStopBeforeServe(t *testing.T) { - defer leakcheck.Check(t) - lis, err := net.Listen("tcp", "localhost:0") - if err != nil { - t.Fatalf("failed to create listener: %v", err) - } - - server := NewServer() - server.Stop() - err = server.Serve(lis) - if err != ErrServerStopped { - t.Fatalf("server.Serve() error = %v, want %v", err, ErrServerStopped) - } - - // server.Serve is responsible for closing the listener, even if the - // server was already stopped. - err = lis.Close() - if got, want := errorDesc(err), "use of closed"; !strings.Contains(got, want) { - t.Errorf("Close() error = %q, want %q", got, want) - } -} - -func TestGracefulStop(t *testing.T) { - defer leakcheck.Check(t) - - lis, err := net.Listen("tcp", "localhost:0") - if err != nil { - t.Fatalf("failed to create listener: %v", err) - } - - server := NewServer() - go func() { - // make sure Serve() is called - time.Sleep(time.Millisecond * 500) - server.GracefulStop() - }() - - err = server.Serve(lis) - if err != nil { - t.Fatalf("Serve() returned non-nil error on GracefulStop: %v", err) - } -} - -func TestGetServiceInfo(t *testing.T) { - defer leakcheck.Check(t) - testSd := ServiceDesc{ - ServiceName: "grpc.testing.EmptyService", - HandlerType: (*emptyServiceServer)(nil), - Methods: []MethodDesc{ - { - MethodName: "EmptyCall", - Handler: nil, - }, - }, - Streams: []StreamDesc{ - { - StreamName: "EmptyStream", - Handler: nil, - ServerStreams: false, - ClientStreams: true, - }, - }, - Metadata: []int{0, 2, 1, 3}, - } - - server := NewServer() - server.RegisterService(&testSd, &testServer{}) - - info := server.GetServiceInfo() - want := map[string]ServiceInfo{ - "grpc.testing.EmptyService": { - Methods: []MethodInfo{ - { - Name: "EmptyCall", - IsClientStream: false, - IsServerStream: false, - }, - { - Name: "EmptyStream", - IsClientStream: true, - IsServerStream: false, - }}, - Metadata: []int{0, 2, 1, 3}, - }, - } - - if !reflect.DeepEqual(info, want) { - t.Errorf("GetServiceInfo() = %+v, want %+v", info, want) - } -} - -func TestStreamContext(t *testing.T) { - expectedStream := &transport.Stream{} - ctx := NewContextWithServerTransportStream(context.Background(), expectedStream) - s := ServerTransportStreamFromContext(ctx) - stream, ok := s.(*transport.Stream) - if !ok || expectedStream != stream { - t.Fatalf("GetStreamFromContext(%v) = %v, %t, want: %v, true", ctx, stream, ok, expectedStream) - } -} diff --git a/vendor/google.golang.org/grpc/service_config_test.go b/vendor/google.golang.org/grpc/service_config_test.go deleted file mode 100644 index 8301a506..00000000 --- a/vendor/google.golang.org/grpc/service_config_test.go +++ /dev/null @@ -1,386 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package grpc - -import ( - "fmt" - "math" - "reflect" - "testing" - "time" -) - -func TestParseLoadBalancer(t *testing.T) { - testcases := []struct { - scjs string - wantSC ServiceConfig - wantErr bool - }{ - { - `{ - "loadBalancingPolicy": "round_robin", - "methodConfig": [ - { - "name": [ - { - "service": "foo", - "method": "Bar" - } - ], - "waitForReady": true - } - ] -}`, - ServiceConfig{ - LB: newString("round_robin"), - Methods: map[string]MethodConfig{ - "/foo/Bar": { - WaitForReady: newBool(true), - }, - }, - }, - false, - }, - { - `{ - "loadBalancingPolicy": 1, - "methodConfig": [ - { - "name": [ - { - "service": "foo", - "method": "Bar" - } - ], - "waitForReady": false - } - ] -}`, - ServiceConfig{}, - true, - }, - } - - for _, c := range testcases { - sc, err := parseServiceConfig(c.scjs) - if c.wantErr != (err != nil) || !reflect.DeepEqual(sc, c.wantSC) { - t.Fatalf("parseServiceConfig(%s) = %+v, %v, want %+v, %v", c.scjs, sc, err, c.wantSC, c.wantErr) - } - } -} - -func TestParseWaitForReady(t *testing.T) { - testcases := []struct { - scjs string - wantSC ServiceConfig - wantErr bool - }{ - { - `{ - "methodConfig": [ - { - "name": [ - { - "service": "foo", - "method": "Bar" - } - ], - "waitForReady": true - } - ] -}`, - ServiceConfig{ - Methods: map[string]MethodConfig{ - "/foo/Bar": { - WaitForReady: newBool(true), - }, - }, - }, - false, - }, - { - `{ - "methodConfig": [ - { - "name": [ - { - "service": "foo", - "method": "Bar" - } - ], - "waitForReady": false - } - ] -}`, - ServiceConfig{ - Methods: map[string]MethodConfig{ - "/foo/Bar": { - WaitForReady: newBool(false), - }, - }, - }, - false, - }, - { - `{ - "methodConfig": [ - { - "name": [ - { - "service": "foo", - "method": "Bar" - } - ], - "waitForReady": fall - }, - { - "name": [ - { - "service": "foo", - "method": "Bar" - } - ], - "waitForReady": true - } - ] -}`, - ServiceConfig{}, - true, - }, - } - - for _, c := range testcases { - sc, err := parseServiceConfig(c.scjs) - if c.wantErr != (err != nil) || !reflect.DeepEqual(sc, c.wantSC) { - t.Fatalf("parseServiceConfig(%s) = %+v, %v, want %+v, %v", c.scjs, sc, err, c.wantSC, c.wantErr) - } - } -} - -func TestPraseTimeOut(t *testing.T) { - testcases := []struct { - scjs string - wantSC ServiceConfig - wantErr bool - }{ - { - `{ - "methodConfig": [ - { - "name": [ - { - "service": "foo", - "method": "Bar" - } - ], - "timeout": "1s" - } - ] -}`, - ServiceConfig{ - Methods: map[string]MethodConfig{ - "/foo/Bar": { - Timeout: newDuration(time.Second), - }, - }, - }, - false, - }, - { - `{ - "methodConfig": [ - { - "name": [ - { - "service": "foo", - "method": "Bar" - } - ], - "timeout": "3c" - } - ] -}`, - ServiceConfig{}, - true, - }, - { - `{ - "methodConfig": [ - { - "name": [ - { - "service": "foo", - "method": "Bar" - } - ], - "timeout": "3c" - }, - { - "name": [ - { - "service": "foo", - "method": "Bar" - } - ], - "timeout": "1s" - } - ] -}`, - ServiceConfig{}, - true, - }, - } - - for _, c := range testcases { - sc, err := parseServiceConfig(c.scjs) - if c.wantErr != (err != nil) || !reflect.DeepEqual(sc, c.wantSC) { - t.Fatalf("parseServiceConfig(%s) = %+v, %v, want %+v, %v", c.scjs, sc, err, c.wantSC, c.wantErr) - } - } -} - -func TestPraseMsgSize(t *testing.T) { - testcases := []struct { - scjs string - wantSC ServiceConfig - wantErr bool - }{ - { - `{ - "methodConfig": [ - { - "name": [ - { - "service": "foo", - "method": "Bar" - } - ], - "maxRequestMessageBytes": 1024, - "maxResponseMessageBytes": 2048 - } - ] -}`, - ServiceConfig{ - Methods: map[string]MethodConfig{ - "/foo/Bar": { - MaxReqSize: newInt(1024), - MaxRespSize: newInt(2048), - }, - }, - }, - false, - }, - { - `{ - "methodConfig": [ - { - "name": [ - { - "service": "foo", - "method": "Bar" - } - ], - "maxRequestMessageBytes": "1024", - "maxResponseMessageBytes": "2048" - }, - { - "name": [ - { - "service": "foo", - "method": "Bar" - } - ], - "maxRequestMessageBytes": 1024, - "maxResponseMessageBytes": 2048 - } - ] -}`, - ServiceConfig{}, - true, - }, - } - - for _, c := range testcases { - sc, err := parseServiceConfig(c.scjs) - if c.wantErr != (err != nil) || !reflect.DeepEqual(sc, c.wantSC) { - t.Fatalf("parseServiceConfig(%s) = %+v, %v, want %+v, %v", c.scjs, sc, err, c.wantSC, c.wantErr) - } - } -} - -func TestParseDuration(t *testing.T) { - testCases := []struct { - s *string - want *time.Duration - err bool - }{ - {s: nil, want: nil}, - {s: newString("1s"), want: newDuration(time.Second)}, - {s: newString("-1s"), want: newDuration(-time.Second)}, - {s: newString("1.1s"), want: newDuration(1100 * time.Millisecond)}, - {s: newString("1.s"), want: newDuration(time.Second)}, - {s: newString("1.0s"), want: newDuration(time.Second)}, - {s: newString(".002s"), want: newDuration(2 * time.Millisecond)}, - {s: newString(".002000s"), want: newDuration(2 * time.Millisecond)}, - {s: newString("0.003s"), want: newDuration(3 * time.Millisecond)}, - {s: newString("0.000004s"), want: newDuration(4 * time.Microsecond)}, - {s: newString("5000.000000009s"), want: newDuration(5000*time.Second + 9*time.Nanosecond)}, - {s: newString("4999.999999999s"), want: newDuration(5000*time.Second - time.Nanosecond)}, - {s: newString("1"), err: true}, - {s: newString("s"), err: true}, - {s: newString(".s"), err: true}, - {s: newString("1 s"), err: true}, - {s: newString(" 1s"), err: true}, - {s: newString("1ms"), err: true}, - {s: newString("1.1.1s"), err: true}, - {s: newString("Xs"), err: true}, - {s: newString("as"), err: true}, - {s: newString(".0000000001s"), err: true}, - {s: newString(fmt.Sprint(math.MaxInt32) + "s"), want: newDuration(math.MaxInt32 * time.Second)}, - {s: newString(fmt.Sprint(int64(math.MaxInt32)+1) + "s"), err: true}, - } - for _, tc := range testCases { - got, err := parseDuration(tc.s) - if tc.err != (err != nil) || - (got == nil) != (tc.want == nil) || - (got != nil && *got != *tc.want) { - wantErr := "" - if tc.err { - wantErr = "" - } - s := "" - if tc.s != nil { - s = `&"` + *tc.s + `"` - } - t.Errorf("parseDuration(%v) = %v, %v; want %v, %v", s, got, err, tc.want, wantErr) - } - } -} - -func newBool(b bool) *bool { - return &b -} - -func newDuration(b time.Duration) *time.Duration { - return &b -} - -func newString(b string) *string { - return &b -} diff --git a/vendor/google.golang.org/grpc/stats/stats_test.go b/vendor/google.golang.org/grpc/stats/stats_test.go deleted file mode 100644 index 008d684c..00000000 --- a/vendor/google.golang.org/grpc/stats/stats_test.go +++ /dev/null @@ -1,1255 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package stats_test - -import ( - "context" - "fmt" - "io" - "net" - "reflect" - "sync" - "testing" - "time" - - "github.com/golang/protobuf/proto" - "google.golang.org/grpc" - "google.golang.org/grpc/metadata" - "google.golang.org/grpc/stats" - testpb "google.golang.org/grpc/stats/grpc_testing" - "google.golang.org/grpc/status" -) - -func init() { - grpc.EnableTracing = false -} - -type connCtxKey struct{} -type rpcCtxKey struct{} - -var ( - // For headers: - testMetadata = metadata.MD{ - "key1": []string{"value1"}, - "key2": []string{"value2"}, - } - // For trailers: - testTrailerMetadata = metadata.MD{ - "tkey1": []string{"trailerValue1"}, - "tkey2": []string{"trailerValue2"}, - } - // The id for which the service handler should return error. - errorID int32 = 32202 -) - -type testServer struct{} - -func (s *testServer) UnaryCall(ctx context.Context, in *testpb.SimpleRequest) (*testpb.SimpleResponse, error) { - md, ok := metadata.FromIncomingContext(ctx) - if ok { - if err := grpc.SendHeader(ctx, md); err != nil { - return nil, status.Errorf(status.Code(err), "grpc.SendHeader(_, %v) = %v, want ", md, err) - } - if err := grpc.SetTrailer(ctx, testTrailerMetadata); err != nil { - return nil, status.Errorf(status.Code(err), "grpc.SetTrailer(_, %v) = %v, want ", testTrailerMetadata, err) - } - } - - if in.Id == errorID { - return nil, fmt.Errorf("got error id: %v", in.Id) - } - - return &testpb.SimpleResponse{Id: in.Id}, nil -} - -func (s *testServer) FullDuplexCall(stream testpb.TestService_FullDuplexCallServer) error { - md, ok := metadata.FromIncomingContext(stream.Context()) - if ok { - if err := stream.SendHeader(md); err != nil { - return status.Errorf(status.Code(err), "%v.SendHeader(%v) = %v, want %v", stream, md, err, nil) - } - stream.SetTrailer(testTrailerMetadata) - } - for { - in, err := stream.Recv() - if err == io.EOF { - // read done. - return nil - } - if err != nil { - return err - } - - if in.Id == errorID { - return fmt.Errorf("got error id: %v", in.Id) - } - - if err := stream.Send(&testpb.SimpleResponse{Id: in.Id}); err != nil { - return err - } - } -} - -func (s *testServer) ClientStreamCall(stream testpb.TestService_ClientStreamCallServer) error { - md, ok := metadata.FromIncomingContext(stream.Context()) - if ok { - if err := stream.SendHeader(md); err != nil { - return status.Errorf(status.Code(err), "%v.SendHeader(%v) = %v, want %v", stream, md, err, nil) - } - stream.SetTrailer(testTrailerMetadata) - } - for { - in, err := stream.Recv() - if err == io.EOF { - // read done. - return stream.SendAndClose(&testpb.SimpleResponse{Id: int32(0)}) - } - if err != nil { - return err - } - - if in.Id == errorID { - return fmt.Errorf("got error id: %v", in.Id) - } - } -} - -func (s *testServer) ServerStreamCall(in *testpb.SimpleRequest, stream testpb.TestService_ServerStreamCallServer) error { - md, ok := metadata.FromIncomingContext(stream.Context()) - if ok { - if err := stream.SendHeader(md); err != nil { - return status.Errorf(status.Code(err), "%v.SendHeader(%v) = %v, want %v", stream, md, err, nil) - } - stream.SetTrailer(testTrailerMetadata) - } - - if in.Id == errorID { - return fmt.Errorf("got error id: %v", in.Id) - } - - for i := 0; i < 5; i++ { - if err := stream.Send(&testpb.SimpleResponse{Id: in.Id}); err != nil { - return err - } - } - return nil -} - -// test is an end-to-end test. It should be created with the newTest -// func, modified as needed, and then started with its startServer method. -// It should be cleaned up with the tearDown method. -type test struct { - t *testing.T - compress string - clientStatsHandler stats.Handler - serverStatsHandler stats.Handler - - testServer testpb.TestServiceServer // nil means none - // srv and srvAddr are set once startServer is called. - srv *grpc.Server - srvAddr string - - cc *grpc.ClientConn // nil until requested via clientConn -} - -func (te *test) tearDown() { - if te.cc != nil { - te.cc.Close() - te.cc = nil - } - te.srv.Stop() -} - -type testConfig struct { - compress string -} - -// newTest returns a new test using the provided testing.T and -// environment. It is returned with default values. Tests should -// modify it before calling its startServer and clientConn methods. -func newTest(t *testing.T, tc *testConfig, ch stats.Handler, sh stats.Handler) *test { - te := &test{ - t: t, - compress: tc.compress, - clientStatsHandler: ch, - serverStatsHandler: sh, - } - return te -} - -// startServer starts a gRPC server listening. Callers should defer a -// call to te.tearDown to clean up. -func (te *test) startServer(ts testpb.TestServiceServer) { - te.testServer = ts - lis, err := net.Listen("tcp", "localhost:0") - if err != nil { - te.t.Fatalf("Failed to listen: %v", err) - } - var opts []grpc.ServerOption - if te.compress == "gzip" { - opts = append(opts, - grpc.RPCCompressor(grpc.NewGZIPCompressor()), - grpc.RPCDecompressor(grpc.NewGZIPDecompressor()), - ) - } - if te.serverStatsHandler != nil { - opts = append(opts, grpc.StatsHandler(te.serverStatsHandler)) - } - s := grpc.NewServer(opts...) - te.srv = s - if te.testServer != nil { - testpb.RegisterTestServiceServer(s, te.testServer) - } - - go s.Serve(lis) - te.srvAddr = lis.Addr().String() -} - -func (te *test) clientConn() *grpc.ClientConn { - if te.cc != nil { - return te.cc - } - opts := []grpc.DialOption{grpc.WithInsecure(), grpc.WithBlock()} - if te.compress == "gzip" { - opts = append(opts, - grpc.WithCompressor(grpc.NewGZIPCompressor()), - grpc.WithDecompressor(grpc.NewGZIPDecompressor()), - ) - } - if te.clientStatsHandler != nil { - opts = append(opts, grpc.WithStatsHandler(te.clientStatsHandler)) - } - - var err error - te.cc, err = grpc.Dial(te.srvAddr, opts...) - if err != nil { - te.t.Fatalf("Dial(%q) = %v", te.srvAddr, err) - } - return te.cc -} - -type rpcType int - -const ( - unaryRPC rpcType = iota - clientStreamRPC - serverStreamRPC - fullDuplexStreamRPC -) - -type rpcConfig struct { - count int // Number of requests and responses for streaming RPCs. - success bool // Whether the RPC should succeed or return error. - failfast bool - callType rpcType // Type of RPC. -} - -func (te *test) doUnaryCall(c *rpcConfig) (*testpb.SimpleRequest, *testpb.SimpleResponse, error) { - var ( - resp *testpb.SimpleResponse - req *testpb.SimpleRequest - err error - ) - tc := testpb.NewTestServiceClient(te.clientConn()) - if c.success { - req = &testpb.SimpleRequest{Id: errorID + 1} - } else { - req = &testpb.SimpleRequest{Id: errorID} - } - ctx := metadata.NewOutgoingContext(context.Background(), testMetadata) - - resp, err = tc.UnaryCall(ctx, req, grpc.FailFast(c.failfast)) - return req, resp, err -} - -func (te *test) doFullDuplexCallRoundtrip(c *rpcConfig) ([]*testpb.SimpleRequest, []*testpb.SimpleResponse, error) { - var ( - reqs []*testpb.SimpleRequest - resps []*testpb.SimpleResponse - err error - ) - tc := testpb.NewTestServiceClient(te.clientConn()) - stream, err := tc.FullDuplexCall(metadata.NewOutgoingContext(context.Background(), testMetadata), grpc.FailFast(c.failfast)) - if err != nil { - return reqs, resps, err - } - var startID int32 - if !c.success { - startID = errorID - } - for i := 0; i < c.count; i++ { - req := &testpb.SimpleRequest{ - Id: int32(i) + startID, - } - reqs = append(reqs, req) - if err = stream.Send(req); err != nil { - return reqs, resps, err - } - var resp *testpb.SimpleResponse - if resp, err = stream.Recv(); err != nil { - return reqs, resps, err - } - resps = append(resps, resp) - } - if err = stream.CloseSend(); err != nil && err != io.EOF { - return reqs, resps, err - } - if _, err = stream.Recv(); err != io.EOF { - return reqs, resps, err - } - - return reqs, resps, nil -} - -func (te *test) doClientStreamCall(c *rpcConfig) ([]*testpb.SimpleRequest, *testpb.SimpleResponse, error) { - var ( - reqs []*testpb.SimpleRequest - resp *testpb.SimpleResponse - err error - ) - tc := testpb.NewTestServiceClient(te.clientConn()) - stream, err := tc.ClientStreamCall(metadata.NewOutgoingContext(context.Background(), testMetadata), grpc.FailFast(c.failfast)) - if err != nil { - return reqs, resp, err - } - var startID int32 - if !c.success { - startID = errorID - } - for i := 0; i < c.count; i++ { - req := &testpb.SimpleRequest{ - Id: int32(i) + startID, - } - reqs = append(reqs, req) - if err = stream.Send(req); err != nil { - return reqs, resp, err - } - } - resp, err = stream.CloseAndRecv() - return reqs, resp, err -} - -func (te *test) doServerStreamCall(c *rpcConfig) (*testpb.SimpleRequest, []*testpb.SimpleResponse, error) { - var ( - req *testpb.SimpleRequest - resps []*testpb.SimpleResponse - err error - ) - - tc := testpb.NewTestServiceClient(te.clientConn()) - - var startID int32 - if !c.success { - startID = errorID - } - req = &testpb.SimpleRequest{Id: startID} - stream, err := tc.ServerStreamCall(metadata.NewOutgoingContext(context.Background(), testMetadata), req, grpc.FailFast(c.failfast)) - if err != nil { - return req, resps, err - } - for { - var resp *testpb.SimpleResponse - resp, err := stream.Recv() - if err == io.EOF { - return req, resps, nil - } else if err != nil { - return req, resps, err - } - resps = append(resps, resp) - } -} - -type expectedData struct { - method string - serverAddr string - compression string - reqIdx int - requests []*testpb.SimpleRequest - respIdx int - responses []*testpb.SimpleResponse - err error - failfast bool -} - -type gotData struct { - ctx context.Context - client bool - s interface{} // This could be RPCStats or ConnStats. -} - -const ( - begin int = iota - end - inPayload - inHeader - inTrailer - outPayload - outHeader - // TODO: test outTrailer ? - connbegin - connend -) - -func checkBegin(t *testing.T, d *gotData, e *expectedData) { - var ( - ok bool - st *stats.Begin - ) - if st, ok = d.s.(*stats.Begin); !ok { - t.Fatalf("got %T, want Begin", d.s) - } - if d.ctx == nil { - t.Fatalf("d.ctx = nil, want ") - } - if st.BeginTime.IsZero() { - t.Fatalf("st.BeginTime = %v, want ", st.BeginTime) - } - if d.client { - if st.FailFast != e.failfast { - t.Fatalf("st.FailFast = %v, want %v", st.FailFast, e.failfast) - } - } -} - -func checkInHeader(t *testing.T, d *gotData, e *expectedData) { - var ( - ok bool - st *stats.InHeader - ) - if st, ok = d.s.(*stats.InHeader); !ok { - t.Fatalf("got %T, want InHeader", d.s) - } - if d.ctx == nil { - t.Fatalf("d.ctx = nil, want ") - } - if !d.client { - if st.FullMethod != e.method { - t.Fatalf("st.FullMethod = %s, want %v", st.FullMethod, e.method) - } - if st.LocalAddr.String() != e.serverAddr { - t.Fatalf("st.LocalAddr = %v, want %v", st.LocalAddr, e.serverAddr) - } - if st.Compression != e.compression { - t.Fatalf("st.Compression = %v, want %v", st.Compression, e.compression) - } - - if connInfo, ok := d.ctx.Value(connCtxKey{}).(*stats.ConnTagInfo); ok { - if connInfo.RemoteAddr != st.RemoteAddr { - t.Fatalf("connInfo.RemoteAddr = %v, want %v", connInfo.RemoteAddr, st.RemoteAddr) - } - if connInfo.LocalAddr != st.LocalAddr { - t.Fatalf("connInfo.LocalAddr = %v, want %v", connInfo.LocalAddr, st.LocalAddr) - } - } else { - t.Fatalf("got context %v, want one with connCtxKey", d.ctx) - } - if rpcInfo, ok := d.ctx.Value(rpcCtxKey{}).(*stats.RPCTagInfo); ok { - if rpcInfo.FullMethodName != st.FullMethod { - t.Fatalf("rpcInfo.FullMethod = %s, want %v", rpcInfo.FullMethodName, st.FullMethod) - } - } else { - t.Fatalf("got context %v, want one with rpcCtxKey", d.ctx) - } - } -} - -func checkInPayload(t *testing.T, d *gotData, e *expectedData) { - var ( - ok bool - st *stats.InPayload - ) - if st, ok = d.s.(*stats.InPayload); !ok { - t.Fatalf("got %T, want InPayload", d.s) - } - if d.ctx == nil { - t.Fatalf("d.ctx = nil, want ") - } - if d.client { - b, err := proto.Marshal(e.responses[e.respIdx]) - if err != nil { - t.Fatalf("failed to marshal message: %v", err) - } - if reflect.TypeOf(st.Payload) != reflect.TypeOf(e.responses[e.respIdx]) { - t.Fatalf("st.Payload = %T, want %T", st.Payload, e.responses[e.respIdx]) - } - e.respIdx++ - if string(st.Data) != string(b) { - t.Fatalf("st.Data = %v, want %v", st.Data, b) - } - if st.Length != len(b) { - t.Fatalf("st.Lenght = %v, want %v", st.Length, len(b)) - } - } else { - b, err := proto.Marshal(e.requests[e.reqIdx]) - if err != nil { - t.Fatalf("failed to marshal message: %v", err) - } - if reflect.TypeOf(st.Payload) != reflect.TypeOf(e.requests[e.reqIdx]) { - t.Fatalf("st.Payload = %T, want %T", st.Payload, e.requests[e.reqIdx]) - } - e.reqIdx++ - if string(st.Data) != string(b) { - t.Fatalf("st.Data = %v, want %v", st.Data, b) - } - if st.Length != len(b) { - t.Fatalf("st.Lenght = %v, want %v", st.Length, len(b)) - } - } - // TODO check WireLength and ReceivedTime. - if st.RecvTime.IsZero() { - t.Fatalf("st.ReceivedTime = %v, want ", st.RecvTime) - } -} - -func checkInTrailer(t *testing.T, d *gotData, e *expectedData) { - var ( - ok bool - ) - if _, ok = d.s.(*stats.InTrailer); !ok { - t.Fatalf("got %T, want InTrailer", d.s) - } - if d.ctx == nil { - t.Fatalf("d.ctx = nil, want ") - } -} - -func checkOutHeader(t *testing.T, d *gotData, e *expectedData) { - var ( - ok bool - st *stats.OutHeader - ) - if st, ok = d.s.(*stats.OutHeader); !ok { - t.Fatalf("got %T, want OutHeader", d.s) - } - if d.ctx == nil { - t.Fatalf("d.ctx = nil, want ") - } - if d.client { - if st.FullMethod != e.method { - t.Fatalf("st.FullMethod = %s, want %v", st.FullMethod, e.method) - } - if st.RemoteAddr.String() != e.serverAddr { - t.Fatalf("st.RemoteAddr = %v, want %v", st.RemoteAddr, e.serverAddr) - } - if st.Compression != e.compression { - t.Fatalf("st.Compression = %v, want %v", st.Compression, e.compression) - } - - if rpcInfo, ok := d.ctx.Value(rpcCtxKey{}).(*stats.RPCTagInfo); ok { - if rpcInfo.FullMethodName != st.FullMethod { - t.Fatalf("rpcInfo.FullMethod = %s, want %v", rpcInfo.FullMethodName, st.FullMethod) - } - } else { - t.Fatalf("got context %v, want one with rpcCtxKey", d.ctx) - } - } -} - -func checkOutPayload(t *testing.T, d *gotData, e *expectedData) { - var ( - ok bool - st *stats.OutPayload - ) - if st, ok = d.s.(*stats.OutPayload); !ok { - t.Fatalf("got %T, want OutPayload", d.s) - } - if d.ctx == nil { - t.Fatalf("d.ctx = nil, want ") - } - if d.client { - b, err := proto.Marshal(e.requests[e.reqIdx]) - if err != nil { - t.Fatalf("failed to marshal message: %v", err) - } - if reflect.TypeOf(st.Payload) != reflect.TypeOf(e.requests[e.reqIdx]) { - t.Fatalf("st.Payload = %T, want %T", st.Payload, e.requests[e.reqIdx]) - } - e.reqIdx++ - if string(st.Data) != string(b) { - t.Fatalf("st.Data = %v, want %v", st.Data, b) - } - if st.Length != len(b) { - t.Fatalf("st.Lenght = %v, want %v", st.Length, len(b)) - } - } else { - b, err := proto.Marshal(e.responses[e.respIdx]) - if err != nil { - t.Fatalf("failed to marshal message: %v", err) - } - if reflect.TypeOf(st.Payload) != reflect.TypeOf(e.responses[e.respIdx]) { - t.Fatalf("st.Payload = %T, want %T", st.Payload, e.responses[e.respIdx]) - } - e.respIdx++ - if string(st.Data) != string(b) { - t.Fatalf("st.Data = %v, want %v", st.Data, b) - } - if st.Length != len(b) { - t.Fatalf("st.Lenght = %v, want %v", st.Length, len(b)) - } - } - // TODO check WireLength and ReceivedTime. - if st.SentTime.IsZero() { - t.Fatalf("st.SentTime = %v, want ", st.SentTime) - } -} - -func checkOutTrailer(t *testing.T, d *gotData, e *expectedData) { - var ( - ok bool - st *stats.OutTrailer - ) - if st, ok = d.s.(*stats.OutTrailer); !ok { - t.Fatalf("got %T, want OutTrailer", d.s) - } - if d.ctx == nil { - t.Fatalf("d.ctx = nil, want ") - } - if st.Client { - t.Fatalf("st IsClient = true, want false") - } -} - -func checkEnd(t *testing.T, d *gotData, e *expectedData) { - var ( - ok bool - st *stats.End - ) - if st, ok = d.s.(*stats.End); !ok { - t.Fatalf("got %T, want End", d.s) - } - if d.ctx == nil { - t.Fatalf("d.ctx = nil, want ") - } - if st.BeginTime.IsZero() { - t.Fatalf("st.BeginTime = %v, want ", st.BeginTime) - } - if st.EndTime.IsZero() { - t.Fatalf("st.EndTime = %v, want ", st.EndTime) - } - - actual, ok := status.FromError(st.Error) - if !ok { - t.Fatalf("expected st.Error to be a statusError, got %v (type %T)", st.Error, st.Error) - } - - expectedStatus, _ := status.FromError(e.err) - if actual.Code() != expectedStatus.Code() || actual.Message() != expectedStatus.Message() { - t.Fatalf("st.Error = %v, want %v", st.Error, e.err) - } -} - -func checkConnBegin(t *testing.T, d *gotData, e *expectedData) { - var ( - ok bool - st *stats.ConnBegin - ) - if st, ok = d.s.(*stats.ConnBegin); !ok { - t.Fatalf("got %T, want ConnBegin", d.s) - } - if d.ctx == nil { - t.Fatalf("d.ctx = nil, want ") - } - st.IsClient() // TODO remove this. -} - -func checkConnEnd(t *testing.T, d *gotData, e *expectedData) { - var ( - ok bool - st *stats.ConnEnd - ) - if st, ok = d.s.(*stats.ConnEnd); !ok { - t.Fatalf("got %T, want ConnEnd", d.s) - } - if d.ctx == nil { - t.Fatalf("d.ctx = nil, want ") - } - st.IsClient() // TODO remove this. -} - -type statshandler struct { - mu sync.Mutex - gotRPC []*gotData - gotConn []*gotData -} - -func (h *statshandler) TagConn(ctx context.Context, info *stats.ConnTagInfo) context.Context { - return context.WithValue(ctx, connCtxKey{}, info) -} - -func (h *statshandler) TagRPC(ctx context.Context, info *stats.RPCTagInfo) context.Context { - return context.WithValue(ctx, rpcCtxKey{}, info) -} - -func (h *statshandler) HandleConn(ctx context.Context, s stats.ConnStats) { - h.mu.Lock() - defer h.mu.Unlock() - h.gotConn = append(h.gotConn, &gotData{ctx, s.IsClient(), s}) -} - -func (h *statshandler) HandleRPC(ctx context.Context, s stats.RPCStats) { - h.mu.Lock() - defer h.mu.Unlock() - h.gotRPC = append(h.gotRPC, &gotData{ctx, s.IsClient(), s}) -} - -func checkConnStats(t *testing.T, got []*gotData) { - if len(got) <= 0 || len(got)%2 != 0 { - for i, g := range got { - t.Errorf(" - %v, %T = %+v, ctx: %v", i, g.s, g.s, g.ctx) - } - t.Fatalf("got %v stats, want even positive number", len(got)) - } - // The first conn stats must be a ConnBegin. - checkConnBegin(t, got[0], nil) - // The last conn stats must be a ConnEnd. - checkConnEnd(t, got[len(got)-1], nil) -} - -func checkServerStats(t *testing.T, got []*gotData, expect *expectedData, checkFuncs []func(t *testing.T, d *gotData, e *expectedData)) { - if len(got) != len(checkFuncs) { - for i, g := range got { - t.Errorf(" - %v, %T", i, g.s) - } - t.Fatalf("got %v stats, want %v stats", len(got), len(checkFuncs)) - } - - var rpcctx context.Context - for i := 0; i < len(got); i++ { - if _, ok := got[i].s.(stats.RPCStats); ok { - if rpcctx != nil && got[i].ctx != rpcctx { - t.Fatalf("got different contexts with stats %T", got[i].s) - } - rpcctx = got[i].ctx - } - } - - for i, f := range checkFuncs { - f(t, got[i], expect) - } -} - -func testServerStats(t *testing.T, tc *testConfig, cc *rpcConfig, checkFuncs []func(t *testing.T, d *gotData, e *expectedData)) { - h := &statshandler{} - te := newTest(t, tc, nil, h) - te.startServer(&testServer{}) - defer te.tearDown() - - var ( - reqs []*testpb.SimpleRequest - resps []*testpb.SimpleResponse - err error - method string - - req *testpb.SimpleRequest - resp *testpb.SimpleResponse - e error - ) - - switch cc.callType { - case unaryRPC: - method = "/grpc.testing.TestService/UnaryCall" - req, resp, e = te.doUnaryCall(cc) - reqs = []*testpb.SimpleRequest{req} - resps = []*testpb.SimpleResponse{resp} - err = e - case clientStreamRPC: - method = "/grpc.testing.TestService/ClientStreamCall" - reqs, resp, e = te.doClientStreamCall(cc) - resps = []*testpb.SimpleResponse{resp} - err = e - case serverStreamRPC: - method = "/grpc.testing.TestService/ServerStreamCall" - req, resps, e = te.doServerStreamCall(cc) - reqs = []*testpb.SimpleRequest{req} - err = e - case fullDuplexStreamRPC: - method = "/grpc.testing.TestService/FullDuplexCall" - reqs, resps, err = te.doFullDuplexCallRoundtrip(cc) - } - if cc.success != (err == nil) { - t.Fatalf("cc.success: %v, got error: %v", cc.success, err) - } - te.cc.Close() - te.srv.GracefulStop() // Wait for the server to stop. - - for { - h.mu.Lock() - if len(h.gotRPC) >= len(checkFuncs) { - h.mu.Unlock() - break - } - h.mu.Unlock() - time.Sleep(10 * time.Millisecond) - } - - for { - h.mu.Lock() - if _, ok := h.gotConn[len(h.gotConn)-1].s.(*stats.ConnEnd); ok { - h.mu.Unlock() - break - } - h.mu.Unlock() - time.Sleep(10 * time.Millisecond) - } - - expect := &expectedData{ - serverAddr: te.srvAddr, - compression: tc.compress, - method: method, - requests: reqs, - responses: resps, - err: err, - } - - h.mu.Lock() - checkConnStats(t, h.gotConn) - h.mu.Unlock() - checkServerStats(t, h.gotRPC, expect, checkFuncs) -} - -func TestServerStatsUnaryRPC(t *testing.T) { - testServerStats(t, &testConfig{compress: ""}, &rpcConfig{success: true, callType: unaryRPC}, []func(t *testing.T, d *gotData, e *expectedData){ - checkInHeader, - checkBegin, - checkInPayload, - checkOutHeader, - checkOutPayload, - checkOutTrailer, - checkEnd, - }) -} - -func TestServerStatsUnaryRPCError(t *testing.T) { - testServerStats(t, &testConfig{compress: ""}, &rpcConfig{success: false, callType: unaryRPC}, []func(t *testing.T, d *gotData, e *expectedData){ - checkInHeader, - checkBegin, - checkInPayload, - checkOutHeader, - checkOutTrailer, - checkEnd, - }) -} - -func TestServerStatsClientStreamRPC(t *testing.T) { - count := 5 - checkFuncs := []func(t *testing.T, d *gotData, e *expectedData){ - checkInHeader, - checkBegin, - checkOutHeader, - } - ioPayFuncs := []func(t *testing.T, d *gotData, e *expectedData){ - checkInPayload, - } - for i := 0; i < count; i++ { - checkFuncs = append(checkFuncs, ioPayFuncs...) - } - checkFuncs = append(checkFuncs, - checkOutPayload, - checkOutTrailer, - checkEnd, - ) - testServerStats(t, &testConfig{compress: "gzip"}, &rpcConfig{count: count, success: true, callType: clientStreamRPC}, checkFuncs) -} - -func TestServerStatsClientStreamRPCError(t *testing.T) { - count := 1 - testServerStats(t, &testConfig{compress: "gzip"}, &rpcConfig{count: count, success: false, callType: clientStreamRPC}, []func(t *testing.T, d *gotData, e *expectedData){ - checkInHeader, - checkBegin, - checkOutHeader, - checkInPayload, - checkOutTrailer, - checkEnd, - }) -} - -func TestServerStatsServerStreamRPC(t *testing.T) { - count := 5 - checkFuncs := []func(t *testing.T, d *gotData, e *expectedData){ - checkInHeader, - checkBegin, - checkInPayload, - checkOutHeader, - } - ioPayFuncs := []func(t *testing.T, d *gotData, e *expectedData){ - checkOutPayload, - } - for i := 0; i < count; i++ { - checkFuncs = append(checkFuncs, ioPayFuncs...) - } - checkFuncs = append(checkFuncs, - checkOutTrailer, - checkEnd, - ) - testServerStats(t, &testConfig{compress: "gzip"}, &rpcConfig{count: count, success: true, callType: serverStreamRPC}, checkFuncs) -} - -func TestServerStatsServerStreamRPCError(t *testing.T) { - count := 5 - testServerStats(t, &testConfig{compress: "gzip"}, &rpcConfig{count: count, success: false, callType: serverStreamRPC}, []func(t *testing.T, d *gotData, e *expectedData){ - checkInHeader, - checkBegin, - checkInPayload, - checkOutHeader, - checkOutTrailer, - checkEnd, - }) -} - -func TestServerStatsFullDuplexRPC(t *testing.T) { - count := 5 - checkFuncs := []func(t *testing.T, d *gotData, e *expectedData){ - checkInHeader, - checkBegin, - checkOutHeader, - } - ioPayFuncs := []func(t *testing.T, d *gotData, e *expectedData){ - checkInPayload, - checkOutPayload, - } - for i := 0; i < count; i++ { - checkFuncs = append(checkFuncs, ioPayFuncs...) - } - checkFuncs = append(checkFuncs, - checkOutTrailer, - checkEnd, - ) - testServerStats(t, &testConfig{compress: "gzip"}, &rpcConfig{count: count, success: true, callType: fullDuplexStreamRPC}, checkFuncs) -} - -func TestServerStatsFullDuplexRPCError(t *testing.T) { - count := 5 - testServerStats(t, &testConfig{compress: "gzip"}, &rpcConfig{count: count, success: false, callType: fullDuplexStreamRPC}, []func(t *testing.T, d *gotData, e *expectedData){ - checkInHeader, - checkBegin, - checkOutHeader, - checkInPayload, - checkOutTrailer, - checkEnd, - }) -} - -type checkFuncWithCount struct { - f func(t *testing.T, d *gotData, e *expectedData) - c int // expected count -} - -func checkClientStats(t *testing.T, got []*gotData, expect *expectedData, checkFuncs map[int]*checkFuncWithCount) { - var expectLen int - for _, v := range checkFuncs { - expectLen += v.c - } - if len(got) != expectLen { - for i, g := range got { - t.Errorf(" - %v, %T", i, g.s) - } - t.Fatalf("got %v stats, want %v stats", len(got), expectLen) - } - - var tagInfoInCtx *stats.RPCTagInfo - for i := 0; i < len(got); i++ { - if _, ok := got[i].s.(stats.RPCStats); ok { - tagInfoInCtxNew, _ := got[i].ctx.Value(rpcCtxKey{}).(*stats.RPCTagInfo) - if tagInfoInCtx != nil && tagInfoInCtx != tagInfoInCtxNew { - t.Fatalf("got context containing different tagInfo with stats %T", got[i].s) - } - tagInfoInCtx = tagInfoInCtxNew - } - } - - for _, s := range got { - switch s.s.(type) { - case *stats.Begin: - if checkFuncs[begin].c <= 0 { - t.Fatalf("unexpected stats: %T", s.s) - } - checkFuncs[begin].f(t, s, expect) - checkFuncs[begin].c-- - case *stats.OutHeader: - if checkFuncs[outHeader].c <= 0 { - t.Fatalf("unexpected stats: %T", s.s) - } - checkFuncs[outHeader].f(t, s, expect) - checkFuncs[outHeader].c-- - case *stats.OutPayload: - if checkFuncs[outPayload].c <= 0 { - t.Fatalf("unexpected stats: %T", s.s) - } - checkFuncs[outPayload].f(t, s, expect) - checkFuncs[outPayload].c-- - case *stats.InHeader: - if checkFuncs[inHeader].c <= 0 { - t.Fatalf("unexpected stats: %T", s.s) - } - checkFuncs[inHeader].f(t, s, expect) - checkFuncs[inHeader].c-- - case *stats.InPayload: - if checkFuncs[inPayload].c <= 0 { - t.Fatalf("unexpected stats: %T", s.s) - } - checkFuncs[inPayload].f(t, s, expect) - checkFuncs[inPayload].c-- - case *stats.InTrailer: - if checkFuncs[inTrailer].c <= 0 { - t.Fatalf("unexpected stats: %T", s.s) - } - checkFuncs[inTrailer].f(t, s, expect) - checkFuncs[inTrailer].c-- - case *stats.End: - if checkFuncs[end].c <= 0 { - t.Fatalf("unexpected stats: %T", s.s) - } - checkFuncs[end].f(t, s, expect) - checkFuncs[end].c-- - case *stats.ConnBegin: - if checkFuncs[connbegin].c <= 0 { - t.Fatalf("unexpected stats: %T", s.s) - } - checkFuncs[connbegin].f(t, s, expect) - checkFuncs[connbegin].c-- - case *stats.ConnEnd: - if checkFuncs[connend].c <= 0 { - t.Fatalf("unexpected stats: %T", s.s) - } - checkFuncs[connend].f(t, s, expect) - checkFuncs[connend].c-- - default: - t.Fatalf("unexpected stats: %T", s.s) - } - } -} - -func testClientStats(t *testing.T, tc *testConfig, cc *rpcConfig, checkFuncs map[int]*checkFuncWithCount) { - h := &statshandler{} - te := newTest(t, tc, h, nil) - te.startServer(&testServer{}) - defer te.tearDown() - - var ( - reqs []*testpb.SimpleRequest - resps []*testpb.SimpleResponse - method string - err error - - req *testpb.SimpleRequest - resp *testpb.SimpleResponse - e error - ) - switch cc.callType { - case unaryRPC: - method = "/grpc.testing.TestService/UnaryCall" - req, resp, e = te.doUnaryCall(cc) - reqs = []*testpb.SimpleRequest{req} - resps = []*testpb.SimpleResponse{resp} - err = e - case clientStreamRPC: - method = "/grpc.testing.TestService/ClientStreamCall" - reqs, resp, e = te.doClientStreamCall(cc) - resps = []*testpb.SimpleResponse{resp} - err = e - case serverStreamRPC: - method = "/grpc.testing.TestService/ServerStreamCall" - req, resps, e = te.doServerStreamCall(cc) - reqs = []*testpb.SimpleRequest{req} - err = e - case fullDuplexStreamRPC: - method = "/grpc.testing.TestService/FullDuplexCall" - reqs, resps, err = te.doFullDuplexCallRoundtrip(cc) - } - if cc.success != (err == nil) { - t.Fatalf("cc.success: %v, got error: %v", cc.success, err) - } - te.cc.Close() - te.srv.GracefulStop() // Wait for the server to stop. - - lenRPCStats := 0 - for _, v := range checkFuncs { - lenRPCStats += v.c - } - for { - h.mu.Lock() - if len(h.gotRPC) >= lenRPCStats { - h.mu.Unlock() - break - } - h.mu.Unlock() - time.Sleep(10 * time.Millisecond) - } - - for { - h.mu.Lock() - if _, ok := h.gotConn[len(h.gotConn)-1].s.(*stats.ConnEnd); ok { - h.mu.Unlock() - break - } - h.mu.Unlock() - time.Sleep(10 * time.Millisecond) - } - - expect := &expectedData{ - serverAddr: te.srvAddr, - compression: tc.compress, - method: method, - requests: reqs, - responses: resps, - failfast: cc.failfast, - err: err, - } - - h.mu.Lock() - checkConnStats(t, h.gotConn) - h.mu.Unlock() - checkClientStats(t, h.gotRPC, expect, checkFuncs) -} - -func TestClientStatsUnaryRPC(t *testing.T) { - testClientStats(t, &testConfig{compress: ""}, &rpcConfig{success: true, failfast: false, callType: unaryRPC}, map[int]*checkFuncWithCount{ - begin: {checkBegin, 1}, - outHeader: {checkOutHeader, 1}, - outPayload: {checkOutPayload, 1}, - inHeader: {checkInHeader, 1}, - inPayload: {checkInPayload, 1}, - inTrailer: {checkInTrailer, 1}, - end: {checkEnd, 1}, - }) -} - -func TestClientStatsUnaryRPCError(t *testing.T) { - testClientStats(t, &testConfig{compress: ""}, &rpcConfig{success: false, failfast: false, callType: unaryRPC}, map[int]*checkFuncWithCount{ - begin: {checkBegin, 1}, - outHeader: {checkOutHeader, 1}, - outPayload: {checkOutPayload, 1}, - inHeader: {checkInHeader, 1}, - inTrailer: {checkInTrailer, 1}, - end: {checkEnd, 1}, - }) -} - -func TestClientStatsClientStreamRPC(t *testing.T) { - count := 5 - testClientStats(t, &testConfig{compress: "gzip"}, &rpcConfig{count: count, success: true, failfast: false, callType: clientStreamRPC}, map[int]*checkFuncWithCount{ - begin: {checkBegin, 1}, - outHeader: {checkOutHeader, 1}, - inHeader: {checkInHeader, 1}, - outPayload: {checkOutPayload, count}, - inTrailer: {checkInTrailer, 1}, - inPayload: {checkInPayload, 1}, - end: {checkEnd, 1}, - }) -} - -func TestClientStatsClientStreamRPCError(t *testing.T) { - count := 1 - testClientStats(t, &testConfig{compress: "gzip"}, &rpcConfig{count: count, success: false, failfast: false, callType: clientStreamRPC}, map[int]*checkFuncWithCount{ - begin: {checkBegin, 1}, - outHeader: {checkOutHeader, 1}, - inHeader: {checkInHeader, 1}, - outPayload: {checkOutPayload, 1}, - inTrailer: {checkInTrailer, 1}, - end: {checkEnd, 1}, - }) -} - -func TestClientStatsServerStreamRPC(t *testing.T) { - count := 5 - testClientStats(t, &testConfig{compress: "gzip"}, &rpcConfig{count: count, success: true, failfast: false, callType: serverStreamRPC}, map[int]*checkFuncWithCount{ - begin: {checkBegin, 1}, - outHeader: {checkOutHeader, 1}, - outPayload: {checkOutPayload, 1}, - inHeader: {checkInHeader, 1}, - inPayload: {checkInPayload, count}, - inTrailer: {checkInTrailer, 1}, - end: {checkEnd, 1}, - }) -} - -func TestClientStatsServerStreamRPCError(t *testing.T) { - count := 5 - testClientStats(t, &testConfig{compress: "gzip"}, &rpcConfig{count: count, success: false, failfast: false, callType: serverStreamRPC}, map[int]*checkFuncWithCount{ - begin: {checkBegin, 1}, - outHeader: {checkOutHeader, 1}, - outPayload: {checkOutPayload, 1}, - inHeader: {checkInHeader, 1}, - inTrailer: {checkInTrailer, 1}, - end: {checkEnd, 1}, - }) -} - -func TestClientStatsFullDuplexRPC(t *testing.T) { - count := 5 - testClientStats(t, &testConfig{compress: "gzip"}, &rpcConfig{count: count, success: true, failfast: false, callType: fullDuplexStreamRPC}, map[int]*checkFuncWithCount{ - begin: {checkBegin, 1}, - outHeader: {checkOutHeader, 1}, - outPayload: {checkOutPayload, count}, - inHeader: {checkInHeader, 1}, - inPayload: {checkInPayload, count}, - inTrailer: {checkInTrailer, 1}, - end: {checkEnd, 1}, - }) -} - -func TestClientStatsFullDuplexRPCError(t *testing.T) { - count := 5 - testClientStats(t, &testConfig{compress: "gzip"}, &rpcConfig{count: count, success: false, failfast: false, callType: fullDuplexStreamRPC}, map[int]*checkFuncWithCount{ - begin: {checkBegin, 1}, - outHeader: {checkOutHeader, 1}, - outPayload: {checkOutPayload, 1}, - inHeader: {checkInHeader, 1}, - inTrailer: {checkInTrailer, 1}, - end: {checkEnd, 1}, - }) -} - -func TestTags(t *testing.T) { - b := []byte{5, 2, 4, 3, 1} - ctx := stats.SetTags(context.Background(), b) - if tg := stats.OutgoingTags(ctx); !reflect.DeepEqual(tg, b) { - t.Errorf("OutgoingTags(%v) = %v; want %v", ctx, tg, b) - } - if tg := stats.Tags(ctx); tg != nil { - t.Errorf("Tags(%v) = %v; want nil", ctx, tg) - } - - ctx = stats.SetIncomingTags(context.Background(), b) - if tg := stats.Tags(ctx); !reflect.DeepEqual(tg, b) { - t.Errorf("Tags(%v) = %v; want %v", ctx, tg, b) - } - if tg := stats.OutgoingTags(ctx); tg != nil { - t.Errorf("OutgoingTags(%v) = %v; want nil", ctx, tg) - } -} - -func TestTrace(t *testing.T) { - b := []byte{5, 2, 4, 3, 1} - ctx := stats.SetTrace(context.Background(), b) - if tr := stats.OutgoingTrace(ctx); !reflect.DeepEqual(tr, b) { - t.Errorf("OutgoingTrace(%v) = %v; want %v", ctx, tr, b) - } - if tr := stats.Trace(ctx); tr != nil { - t.Errorf("Trace(%v) = %v; want nil", ctx, tr) - } - - ctx = stats.SetIncomingTrace(context.Background(), b) - if tr := stats.Trace(ctx); !reflect.DeepEqual(tr, b) { - t.Errorf("Trace(%v) = %v; want %v", ctx, tr, b) - } - if tr := stats.OutgoingTrace(ctx); tr != nil { - t.Errorf("OutgoingTrace(%v) = %v; want nil", ctx, tr) - } -} diff --git a/vendor/google.golang.org/grpc/status/status_test.go b/vendor/google.golang.org/grpc/status/status_test.go deleted file mode 100644 index 011cb0ae..00000000 --- a/vendor/google.golang.org/grpc/status/status_test.go +++ /dev/null @@ -1,348 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package status - -import ( - "context" - "errors" - "fmt" - "reflect" - "testing" - - "github.com/golang/protobuf/proto" - "github.com/golang/protobuf/ptypes" - apb "github.com/golang/protobuf/ptypes/any" - dpb "github.com/golang/protobuf/ptypes/duration" - cpb "google.golang.org/genproto/googleapis/rpc/code" - epb "google.golang.org/genproto/googleapis/rpc/errdetails" - spb "google.golang.org/genproto/googleapis/rpc/status" - "google.golang.org/grpc/codes" -) - -func TestErrorsWithSameParameters(t *testing.T) { - const description = "some description" - e1 := Errorf(codes.AlreadyExists, description) - e2 := Errorf(codes.AlreadyExists, description) - if e1 == e2 || !reflect.DeepEqual(e1, e2) { - t.Fatalf("Errors should be equivalent but unique - e1: %v, %v e2: %p, %v", e1.(*statusError), e1, e2.(*statusError), e2) - } -} - -func TestFromToProto(t *testing.T) { - s := &spb.Status{ - Code: int32(codes.Internal), - Message: "test test test", - Details: []*apb.Any{{TypeUrl: "foo", Value: []byte{3, 2, 1}}}, - } - - err := FromProto(s) - if got := err.Proto(); !proto.Equal(s, got) { - t.Fatalf("Expected errors to be identical - s: %v got: %v", s, got) - } -} - -func TestFromNilProto(t *testing.T) { - tests := []*Status{nil, FromProto(nil)} - for _, s := range tests { - if c := s.Code(); c != codes.OK { - t.Errorf("s: %v - Expected s.Code() = OK; got %v", s, c) - } - if m := s.Message(); m != "" { - t.Errorf("s: %v - Expected s.Message() = \"\"; got %q", s, m) - } - if p := s.Proto(); p != nil { - t.Errorf("s: %v - Expected s.Proto() = nil; got %q", s, p) - } - if e := s.Err(); e != nil { - t.Errorf("s: %v - Expected s.Err() = nil; got %v", s, e) - } - } -} - -func TestError(t *testing.T) { - err := Error(codes.Internal, "test description") - if got, want := err.Error(), "rpc error: code = Internal desc = test description"; got != want { - t.Fatalf("err.Error() = %q; want %q", got, want) - } - s, _ := FromError(err) - if got, want := s.Code(), codes.Internal; got != want { - t.Fatalf("err.Code() = %s; want %s", got, want) - } - if got, want := s.Message(), "test description"; got != want { - t.Fatalf("err.Message() = %s; want %s", got, want) - } -} - -func TestErrorOK(t *testing.T) { - err := Error(codes.OK, "foo") - if err != nil { - t.Fatalf("Error(codes.OK, _) = %p; want nil", err.(*statusError)) - } -} - -func TestErrorProtoOK(t *testing.T) { - s := &spb.Status{Code: int32(codes.OK)} - if got := ErrorProto(s); got != nil { - t.Fatalf("ErrorProto(%v) = %v; want nil", s, got) - } -} - -func TestFromError(t *testing.T) { - code, message := codes.Internal, "test description" - err := Error(code, message) - s, ok := FromError(err) - if !ok || s.Code() != code || s.Message() != message || s.Err() == nil { - t.Fatalf("FromError(%v) = %v, %v; want , true", err, s, ok, code, message) - } -} - -func TestFromErrorOK(t *testing.T) { - code, message := codes.OK, "" - s, ok := FromError(nil) - if !ok || s.Code() != code || s.Message() != message || s.Err() != nil { - t.Fatalf("FromError(nil) = %v, %v; want , true", s, ok, code, message) - } -} - -type customError struct { - Code codes.Code - Message string - Details []*apb.Any -} - -func (c customError) Error() string { - return fmt.Sprintf("rpc error: code = %s desc = %s", c.Code, c.Message) -} - -func (c customError) GRPCStatus() *Status { - return &Status{ - s: &spb.Status{ - Code: int32(c.Code), - Message: c.Message, - Details: c.Details, - }, - } -} - -func TestFromErrorImplementsInterface(t *testing.T) { - code, message := codes.Internal, "test description" - details := []*apb.Any{{ - TypeUrl: "testUrl", - Value: []byte("testValue"), - }} - err := customError{ - Code: code, - Message: message, - Details: details, - } - s, ok := FromError(err) - if !ok || s.Code() != code || s.Message() != message || s.Err() == nil { - t.Fatalf("FromError(%v) = %v, %v; want , true", err, s, ok, code, message) - } - pd := s.Proto().GetDetails() - if len(pd) != 1 || !reflect.DeepEqual(pd[0], details[0]) { - t.Fatalf("s.Proto.GetDetails() = %v; want ", pd, details) - } -} - -func TestFromErrorUnknownError(t *testing.T) { - code, message := codes.Unknown, "unknown error" - err := errors.New("unknown error") - s, ok := FromError(err) - if ok || s.Code() != code || s.Message() != message { - t.Fatalf("FromError(%v) = %v, %v; want , false", err, s, ok, code, message) - } -} - -func TestConvertKnownError(t *testing.T) { - code, message := codes.Internal, "test description" - err := Error(code, message) - s := Convert(err) - if s.Code() != code || s.Message() != message { - t.Fatalf("Convert(%v) = %v; want ", err, s, code, message) - } -} - -func TestConvertUnknownError(t *testing.T) { - code, message := codes.Unknown, "unknown error" - err := errors.New("unknown error") - s := Convert(err) - if s.Code() != code || s.Message() != message { - t.Fatalf("Convert(%v) = %v; want ", err, s, code, message) - } -} - -func TestStatus_ErrorDetails(t *testing.T) { - tests := []struct { - code codes.Code - details []proto.Message - }{ - { - code: codes.NotFound, - details: nil, - }, - { - code: codes.NotFound, - details: []proto.Message{ - &epb.ResourceInfo{ - ResourceType: "book", - ResourceName: "projects/1234/books/5678", - Owner: "User", - }, - }, - }, - { - code: codes.Internal, - details: []proto.Message{ - &epb.DebugInfo{ - StackEntries: []string{ - "first stack", - "second stack", - }, - }, - }, - }, - { - code: codes.Unavailable, - details: []proto.Message{ - &epb.RetryInfo{ - RetryDelay: &dpb.Duration{Seconds: 60}, - }, - &epb.ResourceInfo{ - ResourceType: "book", - ResourceName: "projects/1234/books/5678", - Owner: "User", - }, - }, - }, - } - - for _, tc := range tests { - s, err := New(tc.code, "").WithDetails(tc.details...) - if err != nil { - t.Fatalf("(%v).WithDetails(%+v) failed: %v", str(s), tc.details, err) - } - details := s.Details() - for i := range details { - if !proto.Equal(details[i].(proto.Message), tc.details[i]) { - t.Fatalf("(%v).Details()[%d] = %+v, want %+v", str(s), i, details[i], tc.details[i]) - } - } - } -} - -func TestStatus_WithDetails_Fail(t *testing.T) { - tests := []*Status{ - nil, - FromProto(nil), - New(codes.OK, ""), - } - for _, s := range tests { - if s, err := s.WithDetails(); err == nil || s != nil { - t.Fatalf("(%v).WithDetails(%+v) = %v, %v; want nil, non-nil", str(s), []proto.Message{}, s, err) - } - } -} - -func TestStatus_ErrorDetails_Fail(t *testing.T) { - tests := []struct { - s *Status - i []interface{} - }{ - { - nil, - nil, - }, - { - FromProto(nil), - nil, - }, - { - New(codes.OK, ""), - []interface{}{}, - }, - { - FromProto(&spb.Status{ - Code: int32(cpb.Code_CANCELLED), - Details: []*apb.Any{ - { - TypeUrl: "", - Value: []byte{}, - }, - mustMarshalAny(&epb.ResourceInfo{ - ResourceType: "book", - ResourceName: "projects/1234/books/5678", - Owner: "User", - }), - }, - }), - []interface{}{ - errors.New(`message type url "" is invalid`), - &epb.ResourceInfo{ - ResourceType: "book", - ResourceName: "projects/1234/books/5678", - Owner: "User", - }, - }, - }, - } - for _, tc := range tests { - got := tc.s.Details() - if !reflect.DeepEqual(got, tc.i) { - t.Errorf("(%v).Details() = %+v, want %+v", str(tc.s), got, tc.i) - } - } -} - -func str(s *Status) string { - if s == nil { - return "nil" - } - if s.s == nil { - return "" - } - return fmt.Sprintf("", codes.Code(s.s.GetCode()), s.s.GetMessage(), s.s.GetDetails()) -} - -// mustMarshalAny converts a protobuf message to an any. -func mustMarshalAny(msg proto.Message) *apb.Any { - any, err := ptypes.MarshalAny(msg) - if err != nil { - panic(fmt.Sprintf("ptypes.MarshalAny(%+v) failed: %v", msg, err)) - } - return any -} - -func TestFromContextError(t *testing.T) { - testCases := []struct { - in error - want *Status - }{ - {in: nil, want: New(codes.OK, "")}, - {in: context.DeadlineExceeded, want: New(codes.DeadlineExceeded, context.DeadlineExceeded.Error())}, - {in: context.Canceled, want: New(codes.Canceled, context.Canceled.Error())}, - {in: errors.New("other"), want: New(codes.Unknown, "other")}, - } - for _, tc := range testCases { - got := FromContextError(tc.in) - if got.Code() != tc.want.Code() || got.Message() != tc.want.Message() { - t.Errorf("FromContextError(%v) = %v; want %v", tc.in, got, tc.want) - } - } -} diff --git a/vendor/google.golang.org/grpc/vet.sh b/vendor/google.golang.org/grpc/vet.sh deleted file mode 100755 index 94d3d54e..00000000 --- a/vendor/google.golang.org/grpc/vet.sh +++ /dev/null @@ -1,136 +0,0 @@ -#!/bin/bash - -if [[ `uname -a` = *"Darwin"* ]]; then - echo "It seems you are running on Mac. This script does not work on Mac. See https://github.com/grpc/grpc-go/issues/2047" - exit 1 -fi - -set -ex # Exit on error; debugging enabled. -set -o pipefail # Fail a pipe if any sub-command fails. - -die() { - echo "$@" >&2 - exit 1 -} - -# Check to make sure it's safe to modify the user's git repo. -if git status --porcelain | read; then - die "Uncommitted or untracked files found; commit changes first" -fi - -if [[ -d "${GOPATH}/src" ]]; then - die "\${GOPATH}/src (${GOPATH}/src) exists; this script will delete it." -fi - -# Undo any edits made by this script. -cleanup() { - rm -rf "${GOPATH}/src" - git reset --hard HEAD -} -trap cleanup EXIT - -fail_on_output() { - tee /dev/stderr | (! read) -} - -PATH="${GOPATH}/bin:${GOROOT}/bin:${PATH}" - -if [[ "$1" = "-install" ]]; then - # Check for module support - if go help mod >& /dev/null; then - go install \ - golang.org/x/lint/golint \ - golang.org/x/tools/cmd/goimports \ - honnef.co/go/tools/cmd/staticcheck \ - github.com/client9/misspell/cmd/misspell \ - github.com/golang/protobuf/protoc-gen-go - else - # Ye olde `go get` incantation. - # Note: this gets the latest version of all tools (vs. the pinned versions - # with Go modules). - go get -u \ - golang.org/x/lint/golint \ - golang.org/x/tools/cmd/goimports \ - honnef.co/go/tools/cmd/staticcheck \ - github.com/client9/misspell/cmd/misspell \ - github.com/golang/protobuf/protoc-gen-go - fi - if [[ -z "${VET_SKIP_PROTO}" ]]; then - if [[ "${TRAVIS}" = "true" ]]; then - PROTOBUF_VERSION=3.3.0 - PROTOC_FILENAME=protoc-${PROTOBUF_VERSION}-linux-x86_64.zip - pushd /home/travis - wget https://github.com/google/protobuf/releases/download/v${PROTOBUF_VERSION}/${PROTOC_FILENAME} - unzip ${PROTOC_FILENAME} - bin/protoc --version - popd - elif ! which protoc > /dev/null; then - die "Please install protoc into your path" - fi - fi - exit 0 -elif [[ "$#" -ne 0 ]]; then - die "Unknown argument(s): $*" -fi - -# - Ensure all source files contain a copyright message. -git ls-files "*.go" | xargs grep -L "\(Copyright [0-9]\{4,\} gRPC authors\)\|DO NOT EDIT" 2>&1 | fail_on_output - -# - Do not import math/rand for real library code. Use internal/grpcrand for -# thread safety. -git ls-files "*.go" | xargs grep -l '"math/rand"' 2>&1 | (! grep -v '^examples\|^stress\|grpcrand') - -# - Ensure all ptypes proto packages are renamed when importing. -git ls-files "*.go" | (! xargs grep "\(import \|^\s*\)\"github.com/golang/protobuf/ptypes/") - -# - Check imports that are illegal in appengine (until Go 1.11). -# TODO: Remove when we drop Go 1.10 support -go list -f {{.Dir}} ./... | xargs go run test/go_vet/vet.go - -# - gofmt, goimports, golint (with exceptions for generated code), go vet. -gofmt -s -d -l . 2>&1 | fail_on_output -goimports -l . 2>&1 | fail_on_output -golint ./... 2>&1 | (! grep -vE "(_mock|\.pb)\.go:") -go tool vet -all . - -# - Check that generated proto files are up to date. -if [[ -z "${VET_SKIP_PROTO}" ]]; then - PATH="/home/travis/bin:${PATH}" make proto && \ - git status --porcelain 2>&1 | fail_on_output || \ - (git status; git --no-pager diff; exit 1) -fi - -# - Check that our module is tidy. -if go help mod >& /dev/null; then - go mod tidy && \ - git status --porcelain 2>&1 | fail_on_output || \ - (git status; git --no-pager diff; exit 1) -fi - -# - Collection of static analysis checks -### HACK HACK HACK: Remove once staticcheck works with modules. -# Make a symlink in ${GOPATH}/src to its ${GOPATH}/pkg/mod equivalent for every package we use. -for x in $(find "${GOPATH}/pkg/mod" -name '*@*' | grep -v \/mod\/cache\/); do - pkg="$(echo ${x#"${GOPATH}/pkg/mod/"} | cut -f1 -d@)"; - # If multiple versions exist, just use the existing one. - if [[ -L "${GOPATH}/src/${pkg}" ]]; then continue; fi - mkdir -p "$(dirname "${GOPATH}/src/${pkg}")"; - ln -s $x "${GOPATH}/src/${pkg}"; -done -### END HACK HACK HACK - -# TODO(menghanl): fix errors in transport_test. -staticcheck -ignore ' -balancer.go:SA1019 -balancer_test.go:SA1019 -clientconn_test.go:SA1019 -balancer/roundrobin/roundrobin_test.go:SA1019 -benchmark/benchmain/main.go:SA1019 -internal/transport/handler_server.go:SA1019 -internal/transport/handler_server_test.go:SA1019 -internal/transport/transport_test.go:SA2002 -stats/stats_test.go:SA1019 -test/channelz_test.go:SA1019 -test/end2end_test.go:SA1019 -' ./... -misspell -error .