package fritzbox import ( "context" "net/http" "net/http/httptest" "strings" "testing" ) const addonInfos = ` 81908 1467861996 1247413843 276345768940 3471580989011 ` const linkProperties = ` Cable 56710000 1150000000 ` const soapFault = ` s:ClientUPnPError 401Invalid Action ` // fakeIGD answers each action with the given body and status, and fails the // test on a request the box would reject. func fakeIGD(t *testing.T, answers map[string]string, status int) *Client { t.Helper() srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { action := r.Header.Get("SOAPACTION") if r.Method != http.MethodPost || r.URL.Path != igdControl { t.Errorf("%s %s", r.Method, r.URL.Path) } if !strings.HasPrefix(action, `"`+igdService+"#") || !strings.HasSuffix(action, `"`) { t.Errorf("SOAPACTION %s is not the quoted service#action", action) } name := strings.Trim(action[strings.Index(action, "#")+1:], `"`) w.WriteHeader(status) _, _ = w.Write([]byte(answers[name])) })) t.Cleanup(srv.Close) c := New("http://fritz.box", "", "") c.IGD = srv.URL return c } func TestWANPrefersThe64BitCounters(t *testing.T) { c := fakeIGD(t, map[string]string{"GetAddonInfos": addonInfos, "GetCommonLinkProperties": linkProperties}, http.StatusOK) w, err := c.WAN(context.Background()) if err != nil { t.Fatal(err) } want := WAN{ReceivedBytes: 3471580989011, SentBytes: 276345768940, DownstreamBps: 1150000000, UpstreamBps: 56710000} if w != want { t.Errorf("got %+v, want %+v", w, want) } } func TestWANFallsBackTo32BitCounters(t *testing.T) { old := strings.NewReplacer( "3471580989011", "", "276345768940", "").Replace(addonInfos) c := fakeIGD(t, map[string]string{"GetAddonInfos": old, "GetCommonLinkProperties": linkProperties}, http.StatusOK) w, err := c.WAN(context.Background()) if err != nil { t.Fatal(err) } if w.ReceivedBytes != 1247413843 || w.SentBytes != 1467861996 { t.Errorf("got %+v, want the 32 bit counters", w) } } func TestWANReportsTheFault(t *testing.T) { c := fakeIGD(t, map[string]string{"GetAddonInfos": soapFault}, http.StatusInternalServerError) _, err := c.WAN(context.Background()) if err == nil || !strings.Contains(err.Error(), "Invalid Action") { t.Errorf("err = %v, want the fault's description", err) } } func TestWANNamesTheUPnPSettingWhenOff(t *testing.T) { c := fakeIGD(t, nil, http.StatusNotFound) _, err := c.WAN(context.Background()) if err == nil || !strings.Contains(err.Error(), "UPnP") { t.Errorf("err = %v, want it to name the UPnP setting", err) } } func TestIGDBaseIsTheBoxHostOnPort49000(t *testing.T) { for in, want := range map[string]string{ "http://fritz.box": "http://fritz.box:49000", "https://192.168.178.1:443": "http://192.168.178.1:49000", "": "", } { if got := igdBase(in); got != want { t.Errorf("igdBase(%q) = %q, want %q", in, got, want) } } }