💾 Archived View for source.community › ckaznocha › gemini › raw › main › response_test.go captured on 2022-06-03 at 23:43:31.

View Raw

More Information

⬅️ Previous capture (2021-12-17)

-=-=-=-=-=-=-

package gemini_test

import (
	"context"
	"crypto/tls"
	"fmt"
	"io"
	"mime"
	"net"
	"strings"
	"testing"
	"time"

	"source.community/ckaznocha/gemini"
	"source.community/ckaznocha/gemini/geminitest"
)

func Test_response_Input(t *testing.T) {
	t.Parallel()

	type args struct {
		prompt      string
		isSensitive bool
	}

	tests := []struct {
		name string
		want string
		args args
	}{
		{
			name: "",
			args: args{
				prompt: "Hello",
			},
			want: "10 Hello\r\n",
		},
		{
			name: "",
			args: args{
				prompt:      "Hello",
				isSensitive: true,
			},
			want: "11 Hello\r\n",
		},
	}

	for _, tt := range tests {
		tt := tt
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()

			s := geminitest.NewServer(t, gemini.HandlerFunc(func(ctx context.Context, w gemini.ResponseWriter, r *gemini.Request) {
				w.Input(ctx, tt.args.prompt, tt.args.isSensitive)
			}))

			defer s.Close()

			conn, err := tls.DialWithDialer(
				&net.Dialer{Timeout: 1 * time.Second},
				"tcp",
				s.Addr,
				&tls.Config{
					InsecureSkipVerify: true,
				},
			)
			if err != nil {
				t.Fatalf("Unable to dial: error = %v", err)
			}

			if _, err = fmt.Fprint(conn, "gemini://localhost.com/\r\n"); err != nil {
				t.Fatalf("Unable to write request: error = %v", err)
			}

			got, err := io.ReadAll(conn)
			if err != nil {
				t.Fatalf("Unable to read response: error = %v", err)
			}

			if string(got) != tt.want {
				t.Fatalf("*response.Input(%s, %t) = %s, want %s", tt.args.prompt, tt.args.isSensitive, string(got), tt.want)
			}
		})
	}
}

func Test_response_Redirect(t *testing.T) {
	t.Parallel()

	type args struct {
		redirectURL string
		isPermanant bool
	}

	tests := []struct {
		name string
		want string
		args args
	}{
		{
			name: "",
			args: args{
				redirectURL: "gemini://foo.bar",
				isPermanant: false,
			},
			want: "30 gemini://foo.bar\r\n",
		},
		{
			name: "",
			args: args{
				redirectURL: "gemini://foo.bar",
				isPermanant: true,
			},
			want: "31 gemini://foo.bar\r\n",
		},
	}

	for _, tt := range tests {
		tt := tt
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()

			s := geminitest.NewServer(t, gemini.HandlerFunc(func(ctx context.Context, w gemini.ResponseWriter, r *gemini.Request) {
				w.Redirect(ctx, tt.args.redirectURL, tt.args.isPermanant)
			}))

			defer s.Close()

			conn, err := tls.DialWithDialer(
				&net.Dialer{Timeout: 1 * time.Second},
				"tcp",
				s.Addr,
				&tls.Config{
					InsecureSkipVerify: true,
				},
			)
			if err != nil {
				t.Fatalf("Unable to dial: error = %v", err)
			}

			if _, err = fmt.Fprint(conn, "gemini://localhost.com/\r\n"); err != nil {
				t.Fatalf("Unable to write request: error = %v", err)
			}

			got, err := io.ReadAll(conn)
			if err != nil {
				t.Fatalf("Unable to read response: error = %v", err)
			}

			if string(got) != tt.want {
				t.Fatalf("*response.Redirect(%s, %t) = %s, want %s", tt.args.redirectURL, tt.args.isPermanant, string(got), tt.want)
			}
		})
	}
}

func Test_response_Success(t *testing.T) {
	t.Parallel()

	type args struct {
		body     io.Reader
		mimeType string
	}

	tests := []struct {
		name string
		args args
		want string
	}{
		{
			name: "With mime type and body",
			args: args{
				mimeType: mime.FormatMediaType("text/gemini", map[string]string{"charset": "utf-8", "lang": "en"}),
				body:     strings.NewReader("Hello, Gemini!"),
			},
			want: "20 text/gemini; charset=utf-8; lang=en\r\nHello, Gemini!",
		},
		{
			name: "With body only",
			args: args{
				mimeType: "",
				body:     strings.NewReader("Hello, Gemini!"),
			},
			want: "20 \r\nHello, Gemini!",
		},
		{
			name: "With mime type only",
			args: args{
				mimeType: mime.FormatMediaType("text/gemini", map[string]string{"charset": "utf-8", "lang": "en"}),
				body:     nil,
			},
			want: "20 text/gemini; charset=utf-8; lang=en\r\n",
		},
		{
			name: "With no mime type or body",
			args: args{
				mimeType: "",
				body:     nil,
			},
			want: "20 \r\n",
		},
	}

	for _, tt := range tests {
		tt := tt
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()

			s := geminitest.NewServer(t, gemini.HandlerFunc(func(ctx context.Context, w gemini.ResponseWriter, r *gemini.Request) {
				gotWriter := w.Success(ctx, tt.args.mimeType)

				if tt.args.body != nil {
					_, err := io.Copy(gotWriter, tt.args.body)
					if err != nil {
						t.Fatal(err)
					}
				}
			}))

			defer s.Close()

			conn, err := tls.DialWithDialer(
				&net.Dialer{Timeout: 1 * time.Second},
				"tcp",
				s.Addr,
				&tls.Config{
					InsecureSkipVerify: true,
				},
			)
			if err != nil {
				t.Fatalf("Unable to dial: error = %v", err)
			}

			if _, err = fmt.Fprint(conn, "gemini://localhost.com/\r\n"); err != nil {
				t.Fatalf("Unable to write request: error = %v", err)
			}

			got, err := io.ReadAll(conn)
			if err != nil {
				t.Fatalf("Unable to read response: error = %v", err)
			}

			if string(got) != tt.want {
				t.Fatalf("*response.Success(%s) = %s, want %s", tt.args.mimeType, string(got), tt.want)
			}
		})
	}
}

func Test_response_Failure(t *testing.T) {
	t.Parallel()

	type args struct {
		msg  string
		code gemini.StatusCode
	}

	tests := []struct {
		name string
		args args
		want string
	}{
		{
			name: "",
			args: args{
				code: gemini.StatusTemporaryFailure,
				msg:  "oops",
			},
			want: "40 oops\r\n",
		},
		{
			name: "",
			args: args{
				code: gemini.StatusPermanentFailure,
				msg:  "oops",
			},
			want: "50 oops\r\n",
		},
		{
			name: "",
			args: args{
				code: gemini.StatusTemporaryRedirect,
				msg:  "oops",
			},
			want: "50 oops\r\n",
		},
	}

	for _, tt := range tests {
		tt := tt
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()

			s := geminitest.NewServer(t, gemini.HandlerFunc(func(ctx context.Context, w gemini.ResponseWriter, r *gemini.Request) {
				w.Failure(ctx, tt.args.code, tt.args.msg)
			}))

			defer s.Close()

			conn, err := tls.DialWithDialer(
				&net.Dialer{Timeout: 1 * time.Second},
				"tcp",
				s.Addr,
				&tls.Config{
					InsecureSkipVerify: true,
				},
			)
			if err != nil {
				t.Fatalf("Unable to dial: error = %v", err)
			}

			if _, err = fmt.Fprint(conn, "gemini://localhost.com/\r\n"); err != nil {
				t.Fatalf("Unable to write request: error = %v", err)
			}

			got, err := io.ReadAll(conn)
			if err != nil {
				t.Fatalf("Unable to read response: error = %v", err)
			}

			if string(got) != tt.want {
				t.Fatalf("*response.Failure(%d, %s) = %s, want %s", tt.args.code, tt.args.msg, string(got), tt.want)
			}
		})
	}
}