Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions cmd/fdsn-quake-consumer/sc3ml_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"bytes"
"database/sql"
"fmt"
"io"
"os"
"reflect"
Expand Down Expand Up @@ -184,6 +185,75 @@ func TestEventUnmarshalSC12_13(t *testing.T) {
}
}

// test new event types in SC3ML 0.13 can be unmarshalled
func TestEventUnmarshalSC13_eventTypes(t *testing.T) {
for _, eventType := range []string{
"volcanic long-period",
"volcanic very-long-period",
"volcanic hybrid",
"volcanic tremor",
"tremor pulse",
"volcano-tectonic",
"volcanic rockfall",
"lahar",
"pyroclastic flow",
"volcanic eruption"} {

input := "2024p344188_0.13.xml"
b, err := os.ReadFile("etc/" + input)
if err != nil {
t.Fatal(err)
}
b = bytes.Replace(b, []byte("<type>other</type>"), []byte(fmt.Sprintf("<type>%s</type>", eventType)), -1)
var e event

if err = unmarshal(b, &e); err != nil {
t.Error(err)
}
if !strings.HasPrefix(e.Quakeml12Event, `<event publicID="smi:nz.org.geonet/2024p344188">`) {
t.Errorf("%s: quakeml fragment should start with <event...", input)
}

if !strings.HasSuffix(e.Quakeml12Event, `</event>`) {
t.Errorf("%s: quakeml fragment should end with </event>", input)
}

c := event{
PublicID: "2024p344188",
EventType: eventType,
Longitude: 176.2128674424493,
Latitude: -38.62063477317881,
Depth: 5.1162109375,
EvaluationMethod: "NonLinLoc",
EarthModel: "nz3drx",
EvaluationMode: "automatic",
EvaluationStatus: "",
UsedPhaseCount: 10,
UsedStationCount: 10,
OriginError: 0.13178423630674604,
AzimuthalGap: 76.05025526639076,
MinimumDistance: 0.0752301603770797,
Magnitude: 1.4089917745797527,
MagnitudeUncertainty: 0,
MagnitudeType: "M",
MagnitudeStationCount: 5,
Deleted: false,
Sc3ml: string(b),
}

c.ModificationTime, _ = time.Parse(time.RFC3339Nano, "2024-05-07T22:58:22.37962Z")
c.OriginTime, _ = time.Parse(time.RFC3339Nano, "2024-05-07T08:24:09.853066Z")

if c.Quakeml12Event, err = toQuakeMLEvent(b); err != nil {
t.Error(err)
}

if !reflect.DeepEqual(e, c) {
t.Errorf("c not equal to e, expected: %+v", e)
}
}
}

// TestEventType tests that the remapping of SC3ML event type to QuakeML is correct.
// The bug in the sc3ml_*_quakeml_1.2.xsl conversion (inserting "other" instead of "other event"
// has been fixed locally and reported upstream. GMC 12 Sept 2017
Expand Down
25 changes: 18 additions & 7 deletions cmd/fdsn-ws/fdsn_event_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ func TestLongitudeWrap180(t *testing.T) {
setup(t)
defer teardown()

// test data: one at 176.3257242 and another at -176.3257242
// test data at: 176.3257242, -176.3257242, 179.3257242
v := url.Values{}
v.Set("minlon", "177.0")
e, err := parseEventV1(v)
Expand All @@ -362,8 +362,8 @@ func TestLongitudeWrap180(t *testing.T) {
t.Error(err)
}

if c != 1 {
t.Errorf("expected 1 records got %d\n", c)
if c != 2 {
t.Errorf("expected 2 records got %d\n", c)
}

v = url.Values{}
Expand All @@ -379,8 +379,8 @@ func TestLongitudeWrap180(t *testing.T) {
t.Error(err)
}

if c != 2 {
t.Errorf("expected 2 records got %d\n", c)
if c != 3 {
t.Errorf("expected 3 records got %d\n", c)
}

v = url.Values{}
Expand All @@ -395,8 +395,8 @@ func TestLongitudeWrap180(t *testing.T) {
t.Error(err)
}

if c != 1 {
t.Errorf("expected 1 records got %d\n", c)
if c != 2 {
t.Errorf("expected 2 records got %d\n", c)
}

v = url.Values{}
Expand Down Expand Up @@ -432,6 +432,17 @@ func TestEventTypes(t *testing.T) {
{"experimental explosion", false, []interface{}{"experimental explosion"}},
{"e*,a*", false, []interface{}{"earthquake", "explosion", "anthropogenic event", "accidental explosion", "experimental explosion", "atmospheric event", "acoustic noise", "avalanche", "artillery strike", "atmospheric meteor explosion"}},
{"unknown", false, []interface{}{""}}, // specify "unknown" means query for empty value
//new event types
{"volcanic long-period", false, []interface{}{"volcanic long-period"}},
{"volcanic very-long-period", false, []interface{}{"volcanic very-long-period"}},
{"volcanic hybrid", false, []interface{}{"volcanic hybrid"}},
{"volcanic tremor", false, []interface{}{"volcanic tremor"}},
{"tremor pulse", false, []interface{}{"tremor pulse"}},
{"volcano-tectonic", false, []interface{}{"volcano-tectonic"}},
{"volcanic rockfall", false, []interface{}{"volcanic rockfall"}},
{"pyroclastic flow", false, []interface{}{"pyroclastic flow"}},
{"volcanic eruption", false, []interface{}{"volcanic eruption"}},
{"lahar", false, []interface{}{"lahar"}},
}
for _, c := range queryCases {
v := url.Values{}
Expand Down
4 changes: 4 additions & 0 deletions cmd/fdsn-ws/routes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ var routes = wt.Requests{
{ID: wt.L(), URL: "/fdsnws/event/1/catalogs", Content: "application/xml"},
{ID: wt.L(), URL: "/fdsnws/event/1/contributors", Content: "application/xml"},
{ID: wt.L(), URL: "/fdsnws/event/1/application.wadl", Content: "application/xml"},
//event type
{ID: wt.L(), URL: "/fdsnws/event/1/query?starttime=2015-01-01T00:00:00&endtime=2015-12-28T22:00:00&format=text&eventtype=volcanic%20long-period", Content: "text/plain"},
{ID: wt.L(), URL: "/fdsnws/event/1/query?starttime=2015-01-01T00:00:00&endtime=2015-12-28T22:00:00&format=text&eventtype=volcanic%20very-long-period", Content: "text/plain"},
{ID: wt.L(), URL: "/fdsnws/event/1/query?starttime=2015-01-01T00:00:00&endtime=2015-12-28T22:00:00&format=text&eventtype=other%20event", Content: "text/plain"},

// fdsn-ws-dataselect
{ID: wt.L(), URL: "/fdsnws/dataselect/1", Content: "text/html"},
Expand Down
20 changes: 17 additions & 3 deletions cmd/fdsn-ws/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func setup(t *testing.T) {
t.Fatal("ERROR: problem pinging DB")
}

_, err = db.Exec(`DELETE FROM fdsn.event WHERE publicid = '2015p768477' or publicid = '2015p768478'`)
_, err = db.Exec(`DELETE FROM fdsn.event WHERE publicid = '2015p768477' or publicid = '2015p768478' or publicid = '2015p768479'`)
if err != nil {
t.Log(err)
}
Expand All @@ -51,7 +51,7 @@ func setup(t *testing.T) {
usedphasecount, usedstationcount, originerror, azimuthalgap, minimumdistance,
magnitudeuncertainty, magnitudestationcount, quakeml12event, sc3ml)
VALUES ('2015p768477', timestamptz '2015-10-12 08:05:01.717692+00', timestamptz '2015-10-12 08:05:01.717692+00',
-40.57806609, 176.3257242, 23.28125, 2.3, 'magnitudetype', false, 'eventtype',
-40.57806609, 176.3257242, 23.28125, 2.3, 'magnitudetype', false, 'volcanic long-period',
'depthtype', 'evaluationmethod', 'earthmodel', 'evaluationmode', 'evaluationstatus',
0, 0, 0, 0, 0,
0, 0, 'quakeml12event', 'sc3ml')`)
Expand All @@ -65,14 +65,28 @@ func setup(t *testing.T) {
usedphasecount, usedstationcount, originerror, azimuthalgap, minimumdistance,
magnitudeuncertainty, magnitudestationcount, quakeml12event, sc3ml)
VALUES ('2015p768478', timestamptz '2015-10-12 08:05:02.717692+00', timestamptz '2015-10-12 08:05:02.717692+00',
-40.57806609, -176.3257242, 23.28125, 2.3, 'magnitudetype', false, 'eventtype',
-40.57806609, -176.3257242, 23.28125, 2.3, 'magnitudetype', false, 'volcanic very-long-period',
'depthtype', 'evaluationmethod', 'earthmodel', 'evaluationmode', 'evaluationstatus',
0, 0, 0, 0, 0,
0, 0, 'quakeml12event', 'sc3ml')`)
if err != nil {
t.Log(err)
}

_, err = db.Exec(`INSERT INTO fdsn.event (publicid, modificationtime, origintime,
latitude, longitude, depth, magnitude, magnitudetype, deleted, eventtype,
depthtype, evaluationmethod, earthmodel, evaluationmode, evaluationstatus,
usedphasecount, usedstationcount, originerror, azimuthalgap, minimumdistance,
magnitudeuncertainty, magnitudestationcount, quakeml12event, sc3ml)
VALUES ('2015p768479', timestamptz '2015-10-12 09:05:02.717692+00', timestamptz '2015-10-12 09:05:02.717692+00',
-23.57806609, 179.3257242, 33.28125, 2.3, 'magnitudetype', false, 'other event',
'depthtype', 'evaluationmethod', 'earthmodel', 'evaluationmode', 'evaluationstatus',
0, 0, 0, 0, 0,
0, 0, 'quakeml12event', 'sc3ml')`)
if err != nil {
t.Log(err)
}

ts = httptest.NewServer(mux)

// Silence the logging unless running with
Expand Down
7 changes: 4 additions & 3 deletions internal/fdsn/dataselect.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ var dataSelectNotSupported = map[string]bool{
"minuimumlength": true,
}

// nslcReg: FDSN spec allows all ascii, but we'll only allow alpha, number, _, ?, *, "," and "--" (exactly 2 hyphens only)
var nslcReg = regexp.MustCompile(`^([\w*?,]+|--)$`)
var eventTypeReg = regexp.MustCompile(`^([\w*?, ]+|--)$`) // space allowed
// nslcReg: FDSN spec allows all ascii, but we'll only allow alpha, number, _,-, ?, *, "," and "--" (exactly 2 hyphens only)
var nslcReg = regexp.MustCompile(`^([\w*?,]+(?:-[\w*?,]+)*|--)$`) // space not allowed
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This nslcReg is used to verify network/station/location/channel identifiers, is not for event type.
We don't have any identifiers containing -.

However, it's fine to add this since it's in FDSN specification.

var eventTypeReg = regexp.MustCompile(`^([\w*?, ]+(?:[ -][\w*?,]+)*|--)$`) // space allowed
Copy link
Contributor

@junghao junghao May 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure which cases are this change aim to deal with?

If it's for -, then I think adding a \- to existing regex is sufficient.
^([\w*?,\- ]+|--)$

Copy link
Contributor Author

@bpeng bpeng May 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is to allow - in the middle, and it needs to be multiple times, yes adding a - to existing regex is simpler, may be it doesn't matter if - is in the start, but it also allow more than 2 hyphens (---)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless the specification says "no hyphen at the start" (though people won't do it) otherwise we don't need to make sure it's in the middle.


// nslcRegPassPattern: This is beyond FDSN spec.
// Any NSLC regex string doesn't match this pattern we knew it won't generate any results.
Expand Down Expand Up @@ -306,6 +306,7 @@ func GenRegex(input []string, emptyDash bool, allowSpace bool) ([]string, error)
} else {
matched = nslcReg.MatchString(s)
}

if !matched {
return nil, fmt.Errorf("invalid parameter:'%s'", s)
}
Expand Down
Loading