|
8 | 8 | "github.com/google/go-cmp/cmp"
|
9 | 9 | "github.com/google/go-cmp/cmp/cmpopts"
|
10 | 10 | "github.com/ooni/probe-cli/v3/internal/model"
|
| 11 | + "github.com/ooni/probe-cli/v3/internal/netxlite" |
11 | 12 | "github.com/ooni/probe-cli/v3/internal/testingx"
|
12 | 13 | )
|
13 | 14 |
|
@@ -206,7 +207,7 @@ func TestArchivalBinaryData(t *testing.T) {
|
206 | 207 | err := json.Unmarshal(tc.input, &abd)
|
207 | 208 |
|
208 | 209 | t.Log("got this error", err)
|
209 |
| - t.Log("got this .Value filed", abd.Value) |
| 210 | + t.Log("got this .Value field", abd.Value) |
210 | 211 | t.Logf("converted to string: %s", string(abd.Value))
|
211 | 212 |
|
212 | 213 | // handle errors
|
@@ -565,3 +566,209 @@ func TestHTTPBody(t *testing.T) {
|
565 | 566 | t.Fatal(diff)
|
566 | 567 | }
|
567 | 568 | }
|
| 569 | + |
| 570 | +// This test ensures that ArchivalTLSOrQUICHandshakeResult is WAI |
| 571 | +func TestArchivalTLSOrQUICHandshakeResult(t *testing.T) { |
| 572 | + |
| 573 | + // This test ensures that we correctly serialize to JSON. |
| 574 | + t.Run("MarshalJSON", func(t *testing.T) { |
| 575 | + // testcase is a test case defined by this function |
| 576 | + type testcase struct { |
| 577 | + // name is the name of the test case |
| 578 | + name string |
| 579 | + |
| 580 | + // input is the input struct |
| 581 | + input model.ArchivalTLSOrQUICHandshakeResult |
| 582 | + |
| 583 | + // expectErr is the error we expect to see or nil |
| 584 | + expectErr error |
| 585 | + |
| 586 | + // expectData is the data we expect to see |
| 587 | + expectData []byte |
| 588 | + } |
| 589 | + |
| 590 | + cases := []testcase{{ |
| 591 | + name: "serialization of a successful TLS handshake", |
| 592 | + input: model.ArchivalTLSOrQUICHandshakeResult{ |
| 593 | + Network: "tcp", |
| 594 | + Address: "8.8.8.8:443", |
| 595 | + CipherSuite: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", |
| 596 | + Failure: nil, |
| 597 | + SoError: nil, |
| 598 | + NegotiatedProtocol: "http/1.1", |
| 599 | + NoTLSVerify: false, |
| 600 | + PeerCertificates: []model.ArchivalMaybeBinaryData{{ |
| 601 | + Value: string(archivalBinaryInput), |
| 602 | + }}, |
| 603 | + ServerName: "dns.google", |
| 604 | + T0: 1.0, |
| 605 | + T: 2.0, |
| 606 | + Tags: []string{"tls"}, |
| 607 | + TLSVersion: "TLSv1.3", |
| 608 | + TransactionID: 14, |
| 609 | + }, |
| 610 | + expectErr: nil, |
| 611 | + expectData: []byte(`{"network":"tcp","address":"8.8.8.8:443","cipher_suite":"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256","failure":null,"negotiated_protocol":"http/1.1","no_tls_verify":false,"peer_certificates":[{"data":"V+V5+6a7DbzOvaeguqR4eBJZ7mg5pAeYxT68Vcv+NDx+G1qzIp3BLW7KW/EQJUceROItYAjqsArMBUig9Xg48Ns/nZ8lb4kAlpOvQ6xNyawT2yK+en3ZJKJSadiJwdFXqgQrotixGfbVETm7gM+G+V+djKv1xXQkOqLUQE7XEB8=","format":"base64"}],"server_name":"dns.google","t0":1,"t":2,"tags":["tls"],"tls_version":"TLSv1.3","transaction_id":14}`), |
| 612 | + }, { |
| 613 | + name: "serialization of a failed TLS handshake", |
| 614 | + input: model.ArchivalTLSOrQUICHandshakeResult{ |
| 615 | + Network: "tcp", |
| 616 | + Address: "8.8.8.8:443", |
| 617 | + CipherSuite: "", |
| 618 | + Failure: (func() *string { |
| 619 | + s := netxlite.FailureConnectionReset |
| 620 | + return &s |
| 621 | + })(), |
| 622 | + SoError: (func() *string { |
| 623 | + s := "connection reset by peer" |
| 624 | + return &s |
| 625 | + })(), |
| 626 | + NegotiatedProtocol: "", |
| 627 | + NoTLSVerify: false, |
| 628 | + PeerCertificates: []model.ArchivalMaybeBinaryData{}, |
| 629 | + ServerName: "dns.google", |
| 630 | + T0: 1.0, |
| 631 | + T: 2.0, |
| 632 | + Tags: []string{"tls"}, |
| 633 | + TLSVersion: "", |
| 634 | + TransactionID: 4, |
| 635 | + }, |
| 636 | + expectErr: nil, |
| 637 | + expectData: []byte(`{"network":"tcp","address":"8.8.8.8:443","cipher_suite":"","failure":"connection_reset","so_error":"connection reset by peer","negotiated_protocol":"","no_tls_verify":false,"peer_certificates":[],"server_name":"dns.google","t0":1,"t":2,"tags":["tls"],"tls_version":"","transaction_id":4}`), |
| 638 | + }} |
| 639 | + |
| 640 | + for _, tc := range cases { |
| 641 | + t.Run(tc.name, func(t *testing.T) { |
| 642 | + // serialize to JSON |
| 643 | + data, err := json.Marshal(tc.input) |
| 644 | + |
| 645 | + t.Log("got this error", err) |
| 646 | + t.Log("got this raw data", data) |
| 647 | + t.Logf("converted to string: %s", string(data)) |
| 648 | + |
| 649 | + // handle errors |
| 650 | + switch { |
| 651 | + case err == nil && tc.expectErr != nil: |
| 652 | + t.Fatal("expected", tc.expectErr, "got", err) |
| 653 | + |
| 654 | + case err != nil && tc.expectErr == nil: |
| 655 | + t.Fatal("expected", tc.expectErr, "got", err) |
| 656 | + |
| 657 | + case err != nil && tc.expectErr != nil: |
| 658 | + if err.Error() != tc.expectErr.Error() { |
| 659 | + t.Fatal("expected", tc.expectErr, "got", err) |
| 660 | + } |
| 661 | + |
| 662 | + case err == nil && tc.expectErr == nil: |
| 663 | + // all good--fallthrough |
| 664 | + } |
| 665 | + |
| 666 | + // make sure the serialization is OK |
| 667 | + if diff := cmp.Diff(tc.expectData, data); diff != "" { |
| 668 | + t.Fatal(diff) |
| 669 | + } |
| 670 | + }) |
| 671 | + } |
| 672 | + }) |
| 673 | + |
| 674 | + // This test ensures that we can unmarshal from the JSON representation |
| 675 | + t.Run("UnmarshalJSON", func(t *testing.T) { |
| 676 | + // testcase is a test case defined by this function |
| 677 | + type testcase struct { |
| 678 | + // name is the name of the test case |
| 679 | + name string |
| 680 | + |
| 681 | + // input is the binary input |
| 682 | + input []byte |
| 683 | + |
| 684 | + // expectErr is the error we expect to see or nil |
| 685 | + expectErr error |
| 686 | + |
| 687 | + // expectStruct is the struct we expect to see |
| 688 | + expectStruct model.ArchivalTLSOrQUICHandshakeResult |
| 689 | + } |
| 690 | + |
| 691 | + cases := []testcase{{ |
| 692 | + name: "deserialization of a successful TLS handshake", |
| 693 | + expectErr: nil, |
| 694 | + input: []byte(`{"network":"tcp","address":"8.8.8.8:443","cipher_suite":"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256","failure":null,"negotiated_protocol":"http/1.1","no_tls_verify":false,"peer_certificates":[{"data":"V+V5+6a7DbzOvaeguqR4eBJZ7mg5pAeYxT68Vcv+NDx+G1qzIp3BLW7KW/EQJUceROItYAjqsArMBUig9Xg48Ns/nZ8lb4kAlpOvQ6xNyawT2yK+en3ZJKJSadiJwdFXqgQrotixGfbVETm7gM+G+V+djKv1xXQkOqLUQE7XEB8=","format":"base64"}],"server_name":"dns.google","t0":1,"t":2,"tags":["tls"],"tls_version":"TLSv1.3","transaction_id":14}`), |
| 695 | + expectStruct: model.ArchivalTLSOrQUICHandshakeResult{ |
| 696 | + Network: "tcp", |
| 697 | + Address: "8.8.8.8:443", |
| 698 | + CipherSuite: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", |
| 699 | + Failure: nil, |
| 700 | + SoError: nil, |
| 701 | + NegotiatedProtocol: "http/1.1", |
| 702 | + NoTLSVerify: false, |
| 703 | + PeerCertificates: []model.ArchivalMaybeBinaryData{{ |
| 704 | + Value: string(archivalBinaryInput), |
| 705 | + }}, |
| 706 | + ServerName: "dns.google", |
| 707 | + T0: 1.0, |
| 708 | + T: 2.0, |
| 709 | + Tags: []string{"tls"}, |
| 710 | + TLSVersion: "TLSv1.3", |
| 711 | + TransactionID: 14, |
| 712 | + }, |
| 713 | + }, { |
| 714 | + name: "deserialization of a failed TLS handshake", |
| 715 | + input: []byte(`{"network":"tcp","address":"8.8.8.8:443","cipher_suite":"","failure":"connection_reset","so_error":"connection reset by peer","negotiated_protocol":"","no_tls_verify":false,"peer_certificates":[],"server_name":"dns.google","t0":1,"t":2,"tags":["tls"],"tls_version":"","transaction_id":4}`), |
| 716 | + expectErr: nil, |
| 717 | + expectStruct: model.ArchivalTLSOrQUICHandshakeResult{ |
| 718 | + Network: "tcp", |
| 719 | + Address: "8.8.8.8:443", |
| 720 | + CipherSuite: "", |
| 721 | + Failure: (func() *string { |
| 722 | + s := netxlite.FailureConnectionReset |
| 723 | + return &s |
| 724 | + })(), |
| 725 | + SoError: (func() *string { |
| 726 | + s := "connection reset by peer" |
| 727 | + return &s |
| 728 | + })(), |
| 729 | + NegotiatedProtocol: "", |
| 730 | + NoTLSVerify: false, |
| 731 | + PeerCertificates: []model.ArchivalMaybeBinaryData{}, |
| 732 | + ServerName: "dns.google", |
| 733 | + T0: 1.0, |
| 734 | + T: 2.0, |
| 735 | + Tags: []string{"tls"}, |
| 736 | + TLSVersion: "", |
| 737 | + TransactionID: 4, |
| 738 | + }, |
| 739 | + }} |
| 740 | + |
| 741 | + for _, tc := range cases { |
| 742 | + t.Run(tc.name, func(t *testing.T) { |
| 743 | + // parse the JSON |
| 744 | + var data model.ArchivalTLSOrQUICHandshakeResult |
| 745 | + err := json.Unmarshal(tc.input, &data) |
| 746 | + |
| 747 | + t.Log("got this error", err) |
| 748 | + t.Logf("got this struct %+v", data) |
| 749 | + |
| 750 | + // handle errors |
| 751 | + switch { |
| 752 | + case err == nil && tc.expectErr != nil: |
| 753 | + t.Fatal("expected", tc.expectErr, "got", err) |
| 754 | + |
| 755 | + case err != nil && tc.expectErr == nil: |
| 756 | + t.Fatal("expected", tc.expectErr, "got", err) |
| 757 | + |
| 758 | + case err != nil && tc.expectErr != nil: |
| 759 | + if err.Error() != tc.expectErr.Error() { |
| 760 | + t.Fatal("expected", tc.expectErr, "got", err) |
| 761 | + } |
| 762 | + |
| 763 | + case err == nil && tc.expectErr == nil: |
| 764 | + // all good--fallthrough |
| 765 | + } |
| 766 | + |
| 767 | + // make sure the deserialization is OK |
| 768 | + if diff := cmp.Diff(tc.expectStruct, data); diff != "" { |
| 769 | + t.Fatal(diff) |
| 770 | + } |
| 771 | + }) |
| 772 | + } |
| 773 | + }) |
| 774 | +} |
0 commit comments