ooni-probe-cli/internal/database/actions_test.go

425 lines
8.8 KiB
Go
Raw Normal View History

package database
import (
"database/sql"
"encoding/json"
"fmt"
"io/ioutil"
"os"
"testing"
2018-09-07 14:06:08 +02:00
"github.com/upper/db/v4"
)
type locationInfo struct {
asn uint
countryCode string
ip string
networkName string
resolverIP string
}
func (lp *locationInfo) ProbeASN() uint {
return lp.asn
}
func (lp *locationInfo) ProbeASNString() string {
return fmt.Sprintf("AS%d", lp.asn)
}
func (lp *locationInfo) ProbeCC() string {
return lp.countryCode
}
func (lp *locationInfo) ProbeIP() string {
return lp.ip
}
func (lp *locationInfo) ProbeNetworkName() string {
return lp.networkName
}
func (lp *locationInfo) ResolverIP() string {
return lp.resolverIP
}
func TestNewDatabase(t *testing.T) {
t.Run("with empty path", func(t *testing.T) {
dbpath := ""
database, err := Open(dbpath)
if database != nil {
t.Fatal("unexpected database instance")
}
if err.Error() != "Expecting file:// connection scheme." {
t.Fatal(err)
}
})
t.Run("with valid path", func(t *testing.T) {
tmpfile, err := ioutil.TempFile("", "dbtest")
if err != nil {
t.Fatal(err)
}
defer os.Remove(tmpfile.Name())
_, err = Open(tmpfile.Name())
if err != nil {
t.Fatal(err)
}
})
}
func TestMeasurementWorkflow(t *testing.T) {
tmpfile, err := ioutil.TempFile("", "dbtest")
if err != nil {
t.Fatal(err)
}
defer os.Remove(tmpfile.Name())
tmpdir, err := ioutil.TempDir("", "oonitest")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpdir)
database, err := Open(tmpfile.Name())
if err != nil {
t.Fatal(err)
}
2018-09-07 14:06:08 +02:00
location := locationInfo{
asn: 0,
countryCode: "IT",
networkName: "Unknown",
2018-09-07 14:06:08 +02:00
}
sess := database.Session()
network, err := database.CreateNetwork(&location)
2018-09-07 14:06:08 +02:00
if err != nil {
t.Fatal(err)
}
result, err := database.CreateResult(tmpdir, "websites", network.ID)
if err != nil {
t.Fatal(err)
}
reportID := sql.NullString{String: "", Valid: false}
testName := "antani"
resultID := result.ID
2020-01-28 12:08:09 +01:00
msmtFilePath := tmpdir
urlID := sql.NullInt64{Int64: 0, Valid: false}
m1, err := database.CreateMeasurement(reportID, testName, msmtFilePath, 0, resultID, urlID)
if err != nil {
t.Fatal(err)
}
m1.IsUploaded = true
m1.IsAnomaly = sql.NullBool{Valid: true, Bool: false}
err = sess.Collection("measurements").Find("measurement_id", m1.ID).Update(m1)
if err != nil {
t.Fatal(err)
}
m2, err := database.CreateMeasurement(reportID, testName, msmtFilePath, 0, resultID, urlID)
if err != nil {
t.Fatal(err)
}
m2.IsUploaded = false
m2.IsAnomaly = sql.NullBool{Valid: true, Bool: true}
err = sess.Collection("measurements").Find("measurement_id", m2.ID).Update(m2)
if err != nil {
t.Fatal(err)
}
if m2.ResultID != m1.ResultID {
t.Error("result_id mismatch")
}
err = database.UpdateUploadedStatus(result)
if err != nil {
t.Fatal(err)
}
result.Finished(sess)
var r Result
err = sess.Collection("measurements").Find("result_id", result.ID).One(&r)
if err != nil {
t.Fatal(err)
}
if r.IsUploaded == true {
t.Error("result should be marked as not uploaded")
}
done, incomplete, err := database.ListResults()
if err != nil {
t.Fatal(err)
}
if len(incomplete) != 0 {
t.Error("there should be 0 incomplete result")
}
if len(done) != 1 {
t.Error("there should be 1 done result")
}
if done[0].TotalCount != 2 {
t.Error("there should be a total of 2 measurements in the result")
}
if done[0].AnomalyCount != 1 {
t.Error("there should be a total of 1 anomalies in the result")
}
msmts, err := database.ListMeasurements(resultID)
if err != nil {
t.Fatal(err)
}
if msmts[0].Network.NetworkType != "wifi" {
t.Error("network_type should be wifi")
}
}
2018-09-17 17:30:29 +02:00
func TestDeleteResult(t *testing.T) {
tmpfile, err := ioutil.TempFile("", "dbtest")
if err != nil {
t.Fatal(err)
}
2018-09-17 17:35:57 +02:00
defer os.Remove(tmpfile.Name())
2018-09-17 17:30:29 +02:00
tmpdir, err := ioutil.TempDir("", "oonitest")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpdir)
database, err := Open(tmpfile.Name())
2018-09-17 17:30:29 +02:00
if err != nil {
t.Fatal(err)
}
location := locationInfo{
asn: 0,
countryCode: "IT",
networkName: "Unknown",
2018-09-17 17:30:29 +02:00
}
sess := database.Session()
network, err := database.CreateNetwork(&location)
2018-09-17 17:30:29 +02:00
if err != nil {
t.Fatal(err)
}
result, err := database.CreateResult(tmpdir, "websites", network.ID)
2018-09-17 17:30:29 +02:00
if err != nil {
t.Fatal(err)
}
reportID := sql.NullString{String: "", Valid: false}
testName := "antani"
resultID := result.ID
2020-01-28 12:08:09 +01:00
msmtFilePath := tmpdir
2018-09-17 17:30:29 +02:00
urlID := sql.NullInt64{Int64: 0, Valid: false}
m1, err := database.CreateMeasurement(reportID, testName, msmtFilePath, 0, resultID, urlID)
2018-09-17 17:30:29 +02:00
if err != nil {
t.Fatal(err)
}
var m2 Measurement
err = sess.Collection("measurements").Find("measurement_id", m1.ID).One(&m2)
if err != nil {
t.Fatal(err)
}
2018-09-17 17:30:29 +02:00
if m2.ResultID != m1.ResultID {
t.Error("result_id mismatch")
}
err = database.DeleteResult(resultID)
2018-09-17 17:30:29 +02:00
if err != nil {
t.Fatal(err)
}
totalResults, err := sess.Collection("results").Find().Count()
if err != nil {
t.Fatal(err)
}
totalMeasurements, err := sess.Collection("measurements").Find().Count()
if err != nil {
t.Fatal(err)
}
if totalResults != 0 {
t.Fatal("results should be zero")
}
if totalMeasurements != 0 {
t.Fatal("measurements should be zero")
}
2018-09-18 09:54:27 +02:00
err = database.DeleteResult(20)
2018-09-18 09:54:27 +02:00
if err != db.ErrNoMoreRows {
t.Fatal(err)
}
2018-09-17 17:30:29 +02:00
}
2018-09-10 12:41:28 +02:00
func TestNetworkCreate(t *testing.T) {
tmpfile, err := ioutil.TempFile("", "dbtest")
if err != nil {
t.Fatal(err)
}
defer os.Remove(tmpfile.Name())
database, err := Open(tmpfile.Name())
if err != nil {
t.Fatal(err)
}
2018-09-10 12:41:28 +02:00
l1 := locationInfo{
asn: 2,
countryCode: "IT",
networkName: "Antaninet",
2018-09-10 12:41:28 +02:00
}
l2 := locationInfo{
asn: 3,
countryCode: "IT",
networkName: "Fufnet",
2018-09-10 12:41:28 +02:00
}
_, err = database.CreateNetwork(&l1)
2018-09-10 12:41:28 +02:00
if err != nil {
t.Fatal(err)
}
_, err = database.CreateNetwork(&l2)
2018-09-10 12:41:28 +02:00
if err != nil {
t.Fatal(err)
}
}
func TestURLCreation(t *testing.T) {
tmpfile, err := ioutil.TempFile("", "dbtest")
if err != nil {
t.Fatal(err)
}
defer os.Remove(tmpfile.Name())
database, err := Open(tmpfile.Name())
if err != nil {
t.Fatal(err)
}
newID1, err := database.CreateOrUpdateURL("https://google.com", "GMB", "XX")
if err != nil {
t.Fatal(err)
}
newID2, err := database.CreateOrUpdateURL("https://google.com", "SRCH", "XX")
if err != nil {
t.Fatal(err)
}
newID3, err := database.CreateOrUpdateURL("https://facebook.com", "GRP", "XX")
if err != nil {
t.Fatal(err)
}
newID4, err := database.CreateOrUpdateURL("https://facebook.com", "GMP", "XX")
if err != nil {
t.Fatal(err)
}
newID5, err := database.CreateOrUpdateURL("https://google.com", "SRCH", "XX")
if err != nil {
t.Fatal(err)
}
if newID2 != newID1 {
t.Error("inserting the same URL with different category code should produce the same result")
}
if newID3 == newID1 {
t.Error("inserting different URL should produce different ids")
}
if newID4 != newID3 {
t.Error("inserting the same URL with different category code should produce the same result")
}
if newID5 != newID1 {
t.Error("the ID of google should still be the same")
}
}
func TestPerformanceTestKeys(t *testing.T) {
var tk PerformanceTestKeys
ndtS := "{\"download\":100.0,\"upload\":20.0,\"ping\":2.2}"
dashS := "{\"median_bitrate\":102.0}"
if err := json.Unmarshal([]byte(ndtS), &tk); err != nil {
t.Fatal("failed to parse ndtS")
}
if err := json.Unmarshal([]byte(dashS), &tk); err != nil {
t.Fatal("failed to parse dashS")
}
if tk.Bitrate != 102.0 {
t.Fatalf("error Bitrate %f", tk.Bitrate)
}
if tk.Download != 100.0 {
t.Fatalf("error Download %f", tk.Download)
}
}
func TestGetMeasurementJSON(t *testing.T) {
tmpfile, err := ioutil.TempFile("", "dbtest")
if err != nil {
t.Fatal(err)
}
defer os.Remove(tmpfile.Name())
tmpdir, err := ioutil.TempDir("", "oonitest")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpdir)
database, err := Open(tmpfile.Name())
if err != nil {
t.Fatal(err)
}
sess := database.Session()
location := locationInfo{
asn: 0,
countryCode: "IT",
networkName: "Unknown",
}
network, err := database.CreateNetwork(&location)
if err != nil {
t.Fatal(err)
}
result, err := database.CreateResult(tmpdir, "websites", network.ID)
if err != nil {
t.Fatal(err)
}
reportID := sql.NullString{String: "20210111T085144Z_ndt_RU_3216_n1_qMVnP0PTX7ObUSmD", Valid: true}
testName := "antani"
resultID := result.ID
msmtFilePath := tmpdir
urlID := sql.NullInt64{Int64: 0, Valid: false}
msmt, err := database.CreateMeasurement(reportID, testName, msmtFilePath, 0, resultID, urlID)
if err != nil {
t.Fatal(err)
}
msmt.IsUploaded = true
err = sess.Collection("measurements").Find("measurement_id", msmt.ID).Update(msmt)
if err != nil {
t.Fatal(err)
}
tk, err := database.GetMeasurementJSON(msmt.ID)
if err != nil {
t.Fatal(err)
}
if tk["probe_asn"] != "AS3216" {
t.Error("inconsistent measurement downloaded")
}
}