83440cf110
The legacy part for now is internal/errorsx. It will stay there until I figure out whether it also needs some extra bug fixing. The good part is now in internal/netxlite/errorsx and contains all the logic for mapping errors. We need to further improve upon this logic by writing more thorough integration tests for QUIC. We also need to copy the various dialer, conn, etc adapters that set errors. We will put them inside netxlite and we will generate errors in a way that is less crazy with respect to the major operation. (The idea is to always wrap, given that now we measure in an incremental way and we don't measure every operation together.) Part of https://github.com/ooni/probe/issues/1591
363 lines
9.8 KiB
Go
363 lines
9.8 KiB
Go
package fbmessenger_test
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
"testing"
|
|
|
|
"github.com/apex/log"
|
|
engine "github.com/ooni/probe-cli/v3/internal/engine"
|
|
"github.com/ooni/probe-cli/v3/internal/engine/experiment/fbmessenger"
|
|
"github.com/ooni/probe-cli/v3/internal/engine/experiment/urlgetter"
|
|
"github.com/ooni/probe-cli/v3/internal/engine/mockable"
|
|
"github.com/ooni/probe-cli/v3/internal/engine/model"
|
|
"github.com/ooni/probe-cli/v3/internal/engine/netx/archival"
|
|
"github.com/ooni/probe-cli/v3/internal/netxlite/errorsx"
|
|
)
|
|
|
|
func TestNewExperimentMeasurer(t *testing.T) {
|
|
measurer := fbmessenger.NewExperimentMeasurer(fbmessenger.Config{})
|
|
if measurer.ExperimentName() != "facebook_messenger" {
|
|
t.Fatal("unexpected name")
|
|
}
|
|
if measurer.ExperimentVersion() != "0.2.0" {
|
|
t.Fatal("unexpected version")
|
|
}
|
|
}
|
|
|
|
func TestSuccess(t *testing.T) {
|
|
if testing.Short() {
|
|
t.Skip("skip test in short mode")
|
|
}
|
|
measurer := fbmessenger.NewExperimentMeasurer(fbmessenger.Config{})
|
|
ctx := context.Background()
|
|
// we need a real session because we need the ASN database
|
|
sess := newsession(t)
|
|
measurement := new(model.Measurement)
|
|
callbacks := model.NewPrinterCallbacks(log.Log)
|
|
err := measurer.Run(ctx, sess, measurement, callbacks)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
tk := measurement.TestKeys.(*fbmessenger.TestKeys)
|
|
if *tk.FacebookBAPIDNSConsistent != true {
|
|
t.Fatal("invalid FacebookBAPIDNSConsistent")
|
|
}
|
|
if *tk.FacebookBAPIReachable != true {
|
|
t.Fatal("invalid FacebookBAPIReachable")
|
|
}
|
|
if *tk.FacebookBGraphDNSConsistent != true {
|
|
t.Fatal("invalid FacebookBGraphDNSConsistent")
|
|
}
|
|
if *tk.FacebookBGraphReachable != true {
|
|
t.Fatal("invalid FacebookBGraphReachable")
|
|
}
|
|
if *tk.FacebookEdgeDNSConsistent != true {
|
|
t.Fatal("invalid FacebookEdgeDNSConsistent")
|
|
}
|
|
if *tk.FacebookEdgeReachable != true {
|
|
t.Fatal("invalid FacebookEdgeReachable")
|
|
}
|
|
if *tk.FacebookExternalCDNDNSConsistent != true {
|
|
t.Fatal("invalid FacebookExternalCDNDNSConsistent")
|
|
}
|
|
if *tk.FacebookExternalCDNReachable != true {
|
|
t.Fatal("invalid FacebookExternalCDNReachable")
|
|
}
|
|
if *tk.FacebookScontentCDNDNSConsistent != true {
|
|
t.Fatal("invalid FacebookScontentCDNDNSConsistent")
|
|
}
|
|
if *tk.FacebookScontentCDNReachable != true {
|
|
t.Fatal("invalid FacebookScontentCDNReachable")
|
|
}
|
|
if *tk.FacebookStarDNSConsistent != true {
|
|
t.Fatal("invalid FacebookStarDNSConsistent")
|
|
}
|
|
if *tk.FacebookStarReachable != true {
|
|
t.Fatal("invalid FacebookStarReachable")
|
|
}
|
|
if *tk.FacebookSTUNDNSConsistent != true {
|
|
t.Fatal("invalid FacebookSTUNDNSConsistent")
|
|
}
|
|
if tk.FacebookSTUNReachable != nil {
|
|
t.Fatal("invalid FacebookSTUNReachable")
|
|
}
|
|
if *tk.FacebookDNSBlocking != false {
|
|
t.Fatal("invalid FacebookDNSBlocking")
|
|
}
|
|
if *tk.FacebookTCPBlocking != false {
|
|
t.Fatal("invalid FacebookTCPBlocking")
|
|
}
|
|
}
|
|
|
|
func TestWithCancelledContext(t *testing.T) {
|
|
measurer := fbmessenger.NewExperimentMeasurer(fbmessenger.Config{})
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
cancel() // so we fail immediately
|
|
sess := &mockable.Session{MockableLogger: log.Log}
|
|
measurement := new(model.Measurement)
|
|
callbacks := model.NewPrinterCallbacks(log.Log)
|
|
err := measurer.Run(ctx, sess, measurement, callbacks)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
tk := measurement.TestKeys.(*fbmessenger.TestKeys)
|
|
if *tk.FacebookBAPIDNSConsistent != false {
|
|
t.Fatal("invalid FacebookBAPIDNSConsistent")
|
|
}
|
|
if tk.FacebookBAPIReachable != nil {
|
|
t.Fatal("invalid FacebookBAPIReachable")
|
|
}
|
|
if *tk.FacebookBGraphDNSConsistent != false {
|
|
t.Fatal("invalid FacebookBGraphDNSConsistent")
|
|
}
|
|
if tk.FacebookBGraphReachable != nil {
|
|
t.Fatal("invalid FacebookBGraphReachable")
|
|
}
|
|
if *tk.FacebookEdgeDNSConsistent != false {
|
|
t.Fatal("invalid FacebookEdgeDNSConsistent")
|
|
}
|
|
if tk.FacebookEdgeReachable != nil {
|
|
t.Fatal("invalid FacebookEdgeReachable")
|
|
}
|
|
if *tk.FacebookExternalCDNDNSConsistent != false {
|
|
t.Fatal("invalid FacebookExternalCDNDNSConsistent")
|
|
}
|
|
if tk.FacebookExternalCDNReachable != nil {
|
|
t.Fatal("invalid FacebookExternalCDNReachable")
|
|
}
|
|
if *tk.FacebookScontentCDNDNSConsistent != false {
|
|
t.Fatal("invalid FacebookScontentCDNDNSConsistent")
|
|
}
|
|
if tk.FacebookScontentCDNReachable != nil {
|
|
t.Fatal("invalid FacebookScontentCDNReachable")
|
|
}
|
|
if *tk.FacebookStarDNSConsistent != false {
|
|
t.Fatal("invalid FacebookStarDNSConsistent")
|
|
}
|
|
if tk.FacebookStarReachable != nil {
|
|
t.Fatal("invalid FacebookStarReachable")
|
|
}
|
|
if *tk.FacebookSTUNDNSConsistent != false {
|
|
t.Fatal("invalid FacebookSTUNDNSConsistent")
|
|
}
|
|
if tk.FacebookSTUNReachable != nil {
|
|
t.Fatal("invalid FacebookSTUNReachable")
|
|
}
|
|
if *tk.FacebookDNSBlocking != true {
|
|
t.Fatal("invalid FacebookDNSBlocking")
|
|
}
|
|
// no TCP blocking because we didn't ever reach TCP connect
|
|
if *tk.FacebookTCPBlocking != false {
|
|
t.Fatal("invalid FacebookTCPBlocking")
|
|
}
|
|
sk, err := measurer.GetSummaryKeys(measurement)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, ok := sk.(fbmessenger.SummaryKeys); !ok {
|
|
t.Fatal("invalid type for summary keys")
|
|
}
|
|
}
|
|
|
|
func TestComputeEndpointStatsTCPBlocking(t *testing.T) {
|
|
failure := io.EOF.Error()
|
|
operation := errorsx.ConnectOperation
|
|
tk := fbmessenger.TestKeys{}
|
|
tk.Update(urlgetter.MultiOutput{
|
|
Input: urlgetter.MultiInput{Target: fbmessenger.ServiceEdge},
|
|
TestKeys: urlgetter.TestKeys{
|
|
Failure: &failure,
|
|
FailedOperation: &operation,
|
|
Queries: []archival.DNSQueryEntry{{
|
|
Answers: []archival.DNSAnswerEntry{{
|
|
ASN: fbmessenger.FacebookASN,
|
|
}},
|
|
}},
|
|
},
|
|
})
|
|
if *tk.FacebookEdgeDNSConsistent != true {
|
|
t.Fatal("invalid FacebookEdgeDNSConsistent")
|
|
}
|
|
if *tk.FacebookEdgeReachable != false {
|
|
t.Fatal("invalid FacebookEdgeReachable")
|
|
}
|
|
if tk.FacebookDNSBlocking != nil { // meaning: not determined yet
|
|
t.Fatal("invalid FacebookDNSBlocking")
|
|
}
|
|
if *tk.FacebookTCPBlocking != true {
|
|
t.Fatal("invalid FacebookTCPBlocking")
|
|
}
|
|
}
|
|
|
|
func TestComputeEndpointStatsDNSIsLying(t *testing.T) {
|
|
failure := io.EOF.Error()
|
|
operation := errorsx.ConnectOperation
|
|
tk := fbmessenger.TestKeys{}
|
|
tk.Update(urlgetter.MultiOutput{
|
|
Input: urlgetter.MultiInput{Target: fbmessenger.ServiceEdge},
|
|
TestKeys: urlgetter.TestKeys{
|
|
Failure: &failure,
|
|
FailedOperation: &operation,
|
|
Queries: []archival.DNSQueryEntry{{
|
|
Answers: []archival.DNSAnswerEntry{{
|
|
ASN: 0,
|
|
}},
|
|
}},
|
|
},
|
|
})
|
|
if *tk.FacebookEdgeDNSConsistent != false {
|
|
t.Fatal("invalid FacebookEdgeDNSConsistent")
|
|
}
|
|
if tk.FacebookEdgeReachable != nil {
|
|
t.Fatal("invalid FacebookEdgeReachable")
|
|
}
|
|
if *tk.FacebookDNSBlocking != true {
|
|
t.Fatal("invalid FacebookDNSBlocking")
|
|
}
|
|
if tk.FacebookTCPBlocking != nil { // meaning: not determined yet
|
|
t.Fatal("invalid FacebookTCPBlocking")
|
|
}
|
|
}
|
|
|
|
func newsession(t *testing.T) model.ExperimentSession {
|
|
sess, err := engine.NewSession(context.Background(), engine.SessionConfig{
|
|
AvailableProbeServices: []model.Service{{
|
|
Address: "https://ams-pg-test.ooni.org",
|
|
Type: "https",
|
|
}},
|
|
Logger: log.Log,
|
|
SoftwareName: "ooniprobe-engine",
|
|
SoftwareVersion: "0.0.1",
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := sess.MaybeLookupLocation(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return sess
|
|
}
|
|
|
|
func TestSummaryKeysInvalidType(t *testing.T) {
|
|
measurement := new(model.Measurement)
|
|
m := &fbmessenger.Measurer{}
|
|
_, err := m.GetSummaryKeys(measurement)
|
|
if err.Error() != "invalid test keys type" {
|
|
t.Fatal("not the error we expected")
|
|
}
|
|
}
|
|
|
|
func TestSummaryKeysWithNils(t *testing.T) {
|
|
measurement := &model.Measurement{TestKeys: &fbmessenger.TestKeys{}}
|
|
m := &fbmessenger.Measurer{}
|
|
osk, err := m.GetSummaryKeys(measurement)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
sk := osk.(fbmessenger.SummaryKeys)
|
|
if sk.DNSBlocking {
|
|
t.Fatal("invalid dnsBlocking")
|
|
}
|
|
if sk.TCPBlocking {
|
|
t.Fatal("invalid tcpBlocking")
|
|
}
|
|
if sk.IsAnomaly {
|
|
t.Fatal("invalid isAnomaly")
|
|
}
|
|
}
|
|
|
|
func TestSummaryKeysWithFalseFalse(t *testing.T) {
|
|
falsy := false
|
|
measurement := &model.Measurement{TestKeys: &fbmessenger.TestKeys{
|
|
FacebookTCPBlocking: &falsy,
|
|
FacebookDNSBlocking: &falsy,
|
|
}}
|
|
m := &fbmessenger.Measurer{}
|
|
osk, err := m.GetSummaryKeys(measurement)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
sk := osk.(fbmessenger.SummaryKeys)
|
|
if sk.DNSBlocking {
|
|
t.Fatal("invalid dnsBlocking")
|
|
}
|
|
if sk.TCPBlocking {
|
|
t.Fatal("invalid tcpBlocking")
|
|
}
|
|
if sk.IsAnomaly {
|
|
t.Fatal("invalid isAnomaly")
|
|
}
|
|
}
|
|
|
|
func TestSummaryKeysWithFalseTrue(t *testing.T) {
|
|
falsy := false
|
|
truy := true
|
|
measurement := &model.Measurement{TestKeys: &fbmessenger.TestKeys{
|
|
FacebookTCPBlocking: &falsy,
|
|
FacebookDNSBlocking: &truy,
|
|
}}
|
|
m := &fbmessenger.Measurer{}
|
|
osk, err := m.GetSummaryKeys(measurement)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
sk := osk.(fbmessenger.SummaryKeys)
|
|
if sk.DNSBlocking == false {
|
|
t.Fatal("invalid dnsBlocking")
|
|
}
|
|
if sk.TCPBlocking {
|
|
t.Fatal("invalid tcpBlocking")
|
|
}
|
|
if sk.IsAnomaly == false {
|
|
t.Fatal("invalid isAnomaly")
|
|
}
|
|
}
|
|
|
|
func TestSummaryKeysWithTrueFalse(t *testing.T) {
|
|
falsy := false
|
|
truy := true
|
|
measurement := &model.Measurement{TestKeys: &fbmessenger.TestKeys{
|
|
FacebookTCPBlocking: &truy,
|
|
FacebookDNSBlocking: &falsy,
|
|
}}
|
|
m := &fbmessenger.Measurer{}
|
|
osk, err := m.GetSummaryKeys(measurement)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
sk := osk.(fbmessenger.SummaryKeys)
|
|
if sk.DNSBlocking {
|
|
t.Fatal("invalid dnsBlocking")
|
|
}
|
|
if sk.TCPBlocking == false {
|
|
t.Fatal("invalid tcpBlocking")
|
|
}
|
|
if sk.IsAnomaly == false {
|
|
t.Fatal("invalid isAnomaly")
|
|
}
|
|
}
|
|
|
|
func TestSummaryKeysWithTrueTrue(t *testing.T) {
|
|
truy := true
|
|
measurement := &model.Measurement{TestKeys: &fbmessenger.TestKeys{
|
|
FacebookTCPBlocking: &truy,
|
|
FacebookDNSBlocking: &truy,
|
|
}}
|
|
m := &fbmessenger.Measurer{}
|
|
osk, err := m.GetSummaryKeys(measurement)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
sk := osk.(fbmessenger.SummaryKeys)
|
|
if sk.DNSBlocking == false {
|
|
t.Fatal("invalid dnsBlocking")
|
|
}
|
|
if sk.TCPBlocking == false {
|
|
t.Fatal("invalid tcpBlocking")
|
|
}
|
|
if sk.IsAnomaly == false {
|
|
t.Fatal("invalid isAnomaly")
|
|
}
|
|
}
|