Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8ac445bc69 |
@@ -24,15 +24,13 @@ jobs:
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Build Darabonba
|
||||
run: go build ./dara
|
||||
- name: Build Tea
|
||||
run: go build ./tea
|
||||
- name: Build Util
|
||||
run: go build ./utils
|
||||
|
||||
- name: Test
|
||||
run: go test -race -coverprofile=coverage.txt -covermode=atomic ./dara/... ./utils/... ./tea/...
|
||||
run: go test -race -coverprofile=coverage.txt -covermode=atomic ./tea/... ./utils/...
|
||||
|
||||
- name: CodeCov
|
||||
run: bash <(curl -s https://codecov.io/bash)
|
||||
|
||||
+1
-2
@@ -2,5 +2,4 @@ coverage.html
|
||||
coverage.txt
|
||||
coverage.out
|
||||
.DS_Store
|
||||
.history/
|
||||
vendor/
|
||||
.history/
|
||||
@@ -1,8 +1,8 @@
|
||||
all:
|
||||
|
||||
fmt:
|
||||
go fmt ./tea ./dara ./utils
|
||||
go fmt ./
|
||||
|
||||
test:
|
||||
go test -race -coverprofile=coverage.txt -covermode=atomic ./tea ./utils ./dara
|
||||
go test -race -coverprofile=coverage.txt -covermode=atomic ./tea ./utils
|
||||
go tool cover -html=coverage.txt -o coverage.html
|
||||
|
||||
-439
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
-1307
File diff suppressed because it is too large
Load Diff
-1508
File diff suppressed because it is too large
Load Diff
-162
@@ -1,162 +0,0 @@
|
||||
package dara
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Date struct {
|
||||
date time.Time
|
||||
}
|
||||
|
||||
func NewDate(dateInput string) (*Date, error) {
|
||||
var t time.Time
|
||||
var err error
|
||||
// 解析输入时间,如果输入格式不对,返回错误
|
||||
formats := []string{
|
||||
"2006-01-02 15:04:05",
|
||||
"2006-01-02 15:04:05.999999999 -0700 MST",
|
||||
"2006-01-02T15:04:05-07:00",
|
||||
"2006-01-02T15:04:05Z",
|
||||
}
|
||||
|
||||
for _, format := range formats {
|
||||
t, err = time.Parse(format, dateInput)
|
||||
if err == nil {
|
||||
return &Date{date: t}, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("unable to parse date: %v", dateInput)
|
||||
}
|
||||
|
||||
func (t *Date) Format(layout string) string {
|
||||
|
||||
layout = strings.Replace(layout, "yyyy", "2006", 1)
|
||||
layout = strings.Replace(layout, "MM", "01", 1)
|
||||
layout = strings.Replace(layout, "dd", "02", 1)
|
||||
// layout = strings.Replace(layout, "HH", "15", 1)
|
||||
layout = strings.Replace(layout, "hh", "15", 1)
|
||||
layout = strings.Replace(layout, "mm", "04", 1)
|
||||
layout = strings.Replace(layout, "ss", "05", 1)
|
||||
layout = strings.Replace(layout, "a", "PM", 1)
|
||||
layout = strings.Replace(layout, "EEEE", "Monday", 1)
|
||||
layout = strings.Replace(layout, "E", "Mon", 1)
|
||||
return t.date.Format(layout)
|
||||
}
|
||||
|
||||
func (t *Date) Unix() int64 {
|
||||
return t.date.Unix()
|
||||
}
|
||||
|
||||
func (t *Date) UTC() string {
|
||||
return t.date.UTC().Format("2006-01-02 15:04:05.000000000 -0700 MST")
|
||||
}
|
||||
|
||||
func (t *Date) Sub(amount int, unit string) *Date {
|
||||
var duration time.Duration
|
||||
switch unit {
|
||||
case "second", "seconds":
|
||||
duration = time.Duration(-amount) * time.Second
|
||||
case "minute", "minutes":
|
||||
duration = time.Duration(-amount) * time.Minute
|
||||
case "hour", "hours":
|
||||
duration = time.Duration(-amount) * time.Hour
|
||||
case "day", "days":
|
||||
duration = time.Duration(-amount) * 24 * time.Hour
|
||||
case "week", "weeks":
|
||||
duration = time.Duration(-amount) * 7 * 24 * time.Hour
|
||||
case "month", "months":
|
||||
return &Date{date: t.date.AddDate(0, -amount, 0)}
|
||||
case "year", "years":
|
||||
return &Date{date: t.date.AddDate(-amount, 0, 0)}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
newDate := t.date.Add(duration)
|
||||
return &Date{date: newDate}
|
||||
}
|
||||
|
||||
func (t *Date) Add(amount int, unit string) *Date {
|
||||
var duration time.Duration
|
||||
switch unit {
|
||||
case "second", "seconds":
|
||||
duration = time.Duration(amount) * time.Second
|
||||
case "minute", "minutes":
|
||||
duration = time.Duration(amount) * time.Minute
|
||||
case "hour", "hours":
|
||||
duration = time.Duration(amount) * time.Hour
|
||||
case "day", "days":
|
||||
duration = time.Duration(amount) * 24 * time.Hour
|
||||
case "week", "weeks":
|
||||
duration = time.Duration(amount) * 7 * 24 * time.Hour
|
||||
case "month", "months":
|
||||
return &Date{date: t.date.AddDate(0, amount, 0)}
|
||||
case "year", "years":
|
||||
return &Date{date: t.date.AddDate(amount, 0, 0)}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
||||
newDate := t.date.Add(duration)
|
||||
return &Date{date: newDate}
|
||||
}
|
||||
|
||||
func (t *Date) Diff(amount string, diffDate *Date) int64 {
|
||||
switch amount {
|
||||
case "second", "seconds":
|
||||
return int64(t.date.Sub(diffDate.date).Seconds())
|
||||
case "minute", "minutes":
|
||||
return int64(t.date.Sub(diffDate.date).Minutes())
|
||||
case "hour", "hours":
|
||||
return int64(t.date.Sub(diffDate.date).Hours())
|
||||
case "day", "days":
|
||||
return int64(t.date.Sub(diffDate.date).Hours() / 24)
|
||||
case "week", "weeks":
|
||||
return int64(t.date.Sub(diffDate.date).Hours() / (24 * 7))
|
||||
case "month", "months":
|
||||
return int64(diffDate.date.Year()*12 + int(diffDate.date.Month()) - (t.date.Year()*12 + int(t.date.Month())))
|
||||
case "year", "years":
|
||||
return int64(t.date.Year() - diffDate.date.Year())
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Date) Hour() int {
|
||||
return t.date.Hour()
|
||||
}
|
||||
|
||||
func (t *Date) Minute() int {
|
||||
return t.date.Minute()
|
||||
}
|
||||
|
||||
func (t *Date) Second() int {
|
||||
return t.date.Second()
|
||||
}
|
||||
|
||||
func (t *Date) Month() int {
|
||||
return int(t.date.Month())
|
||||
}
|
||||
|
||||
func (t *Date) Year() int {
|
||||
return t.date.Year()
|
||||
}
|
||||
|
||||
func (t *Date) DayOfMonth() int {
|
||||
return t.date.Day()
|
||||
}
|
||||
|
||||
func (t *Date) DayOfWeek() int {
|
||||
weekday := int(t.date.Weekday())
|
||||
if weekday == 0 {
|
||||
return 7 // Sunday
|
||||
}
|
||||
return weekday
|
||||
}
|
||||
|
||||
func (t *Date) WeekOfYear() int {
|
||||
_, week := t.date.ISOWeek()
|
||||
return week
|
||||
}
|
||||
@@ -1,160 +0,0 @@
|
||||
package dara
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestConstructWithNow(t *testing.T) {
|
||||
date := &Date{date: time.Now()}
|
||||
currentTime := time.Now()
|
||||
if currentTime.Format("2006-01-02 15:04:05") != date.Format("yyyy-MM-dd hh:mm:ss") {
|
||||
t.Errorf("Expected %v, got %v", currentTime.Format("2006-01-02 15:04:05"), date.Format("yyyy-MM-dd hh:mm:ss"))
|
||||
}
|
||||
}
|
||||
|
||||
func TestConstructWithDateTimeString(t *testing.T) {
|
||||
datetime := "2023-03-01T12:00:00Z" // Use RFC3339 format
|
||||
date, err := NewDate(datetime)
|
||||
if err != nil {
|
||||
t.Fatalf("Expected no error, got %v", err)
|
||||
}
|
||||
if datetime != date.Format("yyyy-MM-ddThh:mm:ssZ") {
|
||||
t.Errorf("Expected %v, got %v", datetime, date.Format("yyyy-MM-ddThh:mm:ssZ"))
|
||||
}
|
||||
}
|
||||
|
||||
func TestConstructWithWrongType(t *testing.T) {
|
||||
_, err := NewDate("20230301 12:00:00 +0000 UTC")
|
||||
if err == nil {
|
||||
t.Errorf("Expected error, but got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConstructWithUTC(t *testing.T) {
|
||||
datetimeUTC := "2023-03-01T12:00:00Z"
|
||||
dateWithUTC, err := NewDate(datetimeUTC)
|
||||
if err != nil {
|
||||
t.Fatalf("Expected no error, got %v", err)
|
||||
}
|
||||
|
||||
referenceDateTime, _ := time.Parse(time.RFC3339, datetimeUTC)
|
||||
if referenceDateTime.Unix() != dateWithUTC.Unix() {
|
||||
t.Errorf("Expected %v, got %v", referenceDateTime.Unix(), dateWithUTC.Unix())
|
||||
}
|
||||
|
||||
formattedDateTime := dateWithUTC.UTC()
|
||||
expectedFormattedDateTime := referenceDateTime.UTC().Format("2006-01-02 15:04:05.000000000 -0700 MST")
|
||||
if formattedDateTime != expectedFormattedDateTime {
|
||||
t.Errorf("Expected %v, got %v", expectedFormattedDateTime, formattedDateTime)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormat(t *testing.T) {
|
||||
datetime := "2023-03-01T12:00:00Z"
|
||||
date, _ := NewDate(datetime)
|
||||
expected := "2023-03-01 12:00 PM"
|
||||
if result := date.Format("yyyy-MM-dd hh:mm a"); result != expected {
|
||||
t.Errorf("Expected %v, got %v", expected, result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUTC(t *testing.T) {
|
||||
datetime := "2023-03-01T12:00:00+08:00"
|
||||
date, _ := NewDate(datetime)
|
||||
expected := "2023-03-01 04:00:00.000000000 +0000 UTC"
|
||||
if result := date.UTC(); result != expected {
|
||||
t.Errorf("Expected %v, got %v", expected, result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnix(t *testing.T) {
|
||||
datetime := "1970-01-01T00:00:00Z"
|
||||
date, _ := NewDate(datetime)
|
||||
if result := date.Unix(); result != 0 {
|
||||
t.Errorf("Expected 0, got %v", result)
|
||||
}
|
||||
|
||||
datetime = "2023-12-31T08:00:00+08:00"
|
||||
date, _ = NewDate(datetime)
|
||||
if result := date.Unix(); result != 1703980800 {
|
||||
t.Errorf("Expected 1703980800, got %v", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddSub(t *testing.T) {
|
||||
datetime := "2023-03-01T12:00:00Z"
|
||||
date, _ := NewDate(datetime)
|
||||
date = date.Add(1, "day")
|
||||
expectedDate := time.Date(2023, 3, 2, 12, 0, 0, 0, time.UTC)
|
||||
if date.date != expectedDate {
|
||||
t.Errorf("Expected %v, got %v", expectedDate, date.date)
|
||||
}
|
||||
date = date.Sub(1, "day") // Subtract 1 day
|
||||
expectedDate = time.Date(2023, 3, 1, 12, 0, 0, 0, time.UTC)
|
||||
if date.date != expectedDate {
|
||||
t.Errorf("Expected %v, got %v", expectedDate, date.date)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDiff(t *testing.T) {
|
||||
datetime1 := "2023-03-01T12:00:00Z"
|
||||
datetime2 := "2023-04-01T12:00:00Z"
|
||||
date1, _ := NewDate(datetime1)
|
||||
date2, _ := NewDate(datetime2)
|
||||
diffInSeconds := date1.Diff("seconds", date2)
|
||||
if diffInSeconds != -31*24*60*60 {
|
||||
t.Errorf("Expected %v, got %v", -31*24*60*60, diffInSeconds)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHourMinuteSecond(t *testing.T) {
|
||||
datetime := "2023-03-01T12:34:56Z"
|
||||
date, _ := NewDate(datetime)
|
||||
if result := date.Hour(); result != 12 {
|
||||
t.Errorf("Expected 12, got %d", result)
|
||||
}
|
||||
if result := date.Minute(); result != 34 {
|
||||
t.Errorf("Expected 34, got %d", result)
|
||||
}
|
||||
if result := date.Second(); result != 56 {
|
||||
t.Errorf("Expected 56, got %d", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMonthYearDay(t *testing.T) {
|
||||
datetime := "2023-03-01T12:00:00Z"
|
||||
date, _ := NewDate(datetime)
|
||||
if result := date.Month(); result != 3 {
|
||||
t.Errorf("Expected 3, got %d", result)
|
||||
}
|
||||
if result := date.Year(); result != 2023 {
|
||||
t.Errorf("Expected 2023, got %d", result)
|
||||
}
|
||||
if result := date.DayOfMonth(); result != 1 {
|
||||
t.Errorf("Expected 1, got %d", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDayOfWeekWeekOfYear(t *testing.T) {
|
||||
datetime := "2023-03-01 00:00:00"
|
||||
date, _ := NewDate(datetime)
|
||||
if result := date.DayOfWeek(); result != 3 {
|
||||
t.Errorf("Expected 3, got %d", result)
|
||||
}
|
||||
if result := date.WeekOfYear(); result != 9 {
|
||||
t.Errorf("Expected 9, got %d", result)
|
||||
}
|
||||
|
||||
datetime1 := "2023-12-31T12:00:00Z"
|
||||
date1, _ := NewDate(datetime1)
|
||||
if result := date1.DayOfMonth(); result != 31 {
|
||||
t.Errorf("Expected 31, got %d", result)
|
||||
}
|
||||
if result := date1.DayOfWeek(); result != 7 {
|
||||
t.Errorf("Expected 7, got %d", result)
|
||||
}
|
||||
if result := date1.WeekOfYear(); result != 52 {
|
||||
t.Errorf("Expected 52, got %d", result)
|
||||
}
|
||||
}
|
||||
-146
@@ -1,146 +0,0 @@
|
||||
package dara
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
// File struct to represent the file
|
||||
type DaraFile struct {
|
||||
path string
|
||||
fileInfo os.FileInfo
|
||||
file *os.File
|
||||
position int64
|
||||
}
|
||||
|
||||
// NewFile creates a new instance of File
|
||||
func NewDaraFile(path string) *DaraFile {
|
||||
return &DaraFile{
|
||||
path: path,
|
||||
position: 0,
|
||||
}
|
||||
}
|
||||
|
||||
// Path returns the path of the file
|
||||
func (tf *DaraFile) Path() string {
|
||||
return tf.path
|
||||
}
|
||||
|
||||
// CreateTime returns the creation time of the file
|
||||
func (tf *DaraFile) CreateTime() (*Date, error) {
|
||||
if tf.fileInfo == nil {
|
||||
var err error
|
||||
tf.fileInfo, err = os.Stat(tf.path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &Date{tf.fileInfo.ModTime()}, nil
|
||||
}
|
||||
|
||||
// ModifyTime returns the modification time of the file
|
||||
func (tf *DaraFile) ModifyTime() (*Date, error) {
|
||||
if tf.fileInfo == nil {
|
||||
var err error
|
||||
tf.fileInfo, err = os.Stat(tf.path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &Date{tf.fileInfo.ModTime()}, nil
|
||||
}
|
||||
|
||||
// Length returns the size of the file
|
||||
func (tf *DaraFile) Length() (int64, error) {
|
||||
if tf.fileInfo == nil {
|
||||
var err error
|
||||
tf.fileInfo, err = os.Stat(tf.path)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
return tf.fileInfo.Size(), nil
|
||||
}
|
||||
|
||||
// Read reads a specified number of bytes from the file
|
||||
func (tf *DaraFile) Read(size int) ([]byte, error) {
|
||||
if tf.file == nil {
|
||||
file, err := os.OpenFile(tf.path, os.O_RDWR|os.O_CREATE, 0755)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tf.file = file
|
||||
}
|
||||
|
||||
fileInfo, err := tf.file.Stat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 获取文件大小
|
||||
fileSize := fileInfo.Size()
|
||||
|
||||
// 计算可以读取的实际大小
|
||||
if tf.position >= fileSize {
|
||||
return nil, nil // End of file reached
|
||||
}
|
||||
|
||||
// 确保 size 不超过剩余文件大小
|
||||
actualSize := size
|
||||
if tf.position+int64(size) > fileSize {
|
||||
actualSize = int(fileSize - tf.position)
|
||||
}
|
||||
|
||||
buf := make([]byte, actualSize)
|
||||
bytesRead, err := tf.file.ReadAt(buf, tf.position)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tf.position += int64(bytesRead)
|
||||
return buf[:bytesRead], nil
|
||||
}
|
||||
|
||||
// Write writes data to the file
|
||||
func (tf *DaraFile) Write(data []byte) error {
|
||||
if tf.file == nil {
|
||||
file, err := os.OpenFile(tf.path, os.O_RDWR|os.O_CREATE, 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tf.file = file
|
||||
}
|
||||
|
||||
_, err := tf.file.Write(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tf.fileInfo, err = os.Stat(tf.path) // Update fileInfo after write
|
||||
return err
|
||||
}
|
||||
|
||||
// Close closes the file
|
||||
func (tf *DaraFile) Close() error {
|
||||
if tf.file == nil {
|
||||
return nil
|
||||
}
|
||||
return tf.file.Close()
|
||||
}
|
||||
|
||||
// Exists checks if the file exists
|
||||
func Exists(path string) (bool, error) {
|
||||
_, err := os.Stat(path)
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
return err == nil, err
|
||||
}
|
||||
|
||||
// CreateReadStream would typically return an os.File or similar
|
||||
func CreateReadStream(path string) (*os.File, error) {
|
||||
return os.Open(path)
|
||||
}
|
||||
|
||||
// CreateWriteStream would typically return an os.File or similar
|
||||
func CreateWriteStream(path string) (*os.File, error) {
|
||||
return os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755)
|
||||
}
|
||||
@@ -1,183 +0,0 @@
|
||||
package dara
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestNewDaraFile tests the NewDaraFile function
|
||||
func TestNewDaraFile(t *testing.T) {
|
||||
path := "testfile.txt"
|
||||
tf := NewDaraFile(path)
|
||||
if tf.Path() != path {
|
||||
t.Errorf("Expected path to be %s, got %s", path, tf.Path())
|
||||
}
|
||||
}
|
||||
|
||||
// TestCreateTime tests the CreateTime method
|
||||
func TestCreateTime(t *testing.T) {
|
||||
path := "testfile.txt"
|
||||
ioutil.WriteFile(path, []byte("test"), 0644) // 创建文件以确保它存在
|
||||
defer os.Remove(path)
|
||||
|
||||
tf := NewDaraFile(path)
|
||||
date, err := tf.CreateTime()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if date == nil {
|
||||
t.Error("expected a valid TeaDate, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
// TestModifyTime tests the ModifyTime method
|
||||
func TestModifyTime(t *testing.T) {
|
||||
path := "testfile.txt"
|
||||
ioutil.WriteFile(path, []byte("test"), 0644)
|
||||
defer os.Remove(path)
|
||||
|
||||
tf := NewDaraFile(path)
|
||||
date, err := tf.ModifyTime()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if date == nil {
|
||||
t.Error("expected a valid TeaDate, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
// TestLength tests the Length method
|
||||
func TestLength(t *testing.T) {
|
||||
path := "testfile.txt"
|
||||
content := []byte("Hello, World!")
|
||||
ioutil.WriteFile(path, content, 0644)
|
||||
defer os.Remove(path)
|
||||
|
||||
tf := NewDaraFile(path)
|
||||
length, err := tf.Length()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if length != int64(len(content)) {
|
||||
t.Errorf("expected length %d, got %d", len(content), length)
|
||||
}
|
||||
}
|
||||
|
||||
// TestRead tests the Read method
|
||||
func TestRead(t *testing.T) {
|
||||
path := "testfile.txt"
|
||||
content := []byte("Hello, World!")
|
||||
ioutil.WriteFile(path, content, 0644)
|
||||
defer os.Remove(path)
|
||||
|
||||
tf := NewDaraFile(path)
|
||||
data, err := tf.Read(5)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if string(data) != "Hello" {
|
||||
t.Errorf("expected 'Hello', got '%s'", string(data))
|
||||
}
|
||||
|
||||
// Read the rest of the file
|
||||
data, err = tf.Read(10)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if string(data) != ", World!" {
|
||||
t.Errorf("expected ', World!', got '%s'", string(data))
|
||||
}
|
||||
}
|
||||
|
||||
// TestWrite tests the Write method
|
||||
func TestWrite(t *testing.T) {
|
||||
path := "testfile.txt"
|
||||
tf := NewDaraFile(path)
|
||||
|
||||
data := []byte("Hello, Write Test!")
|
||||
err := tf.Write(data)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
// Validate the content of the file
|
||||
readData, _ := ioutil.ReadFile(path)
|
||||
if string(readData) != "Hello, Write Test!" {
|
||||
t.Errorf("expected file content to be %s, got %s", string(data), string(readData))
|
||||
}
|
||||
}
|
||||
|
||||
// TestClose tests the Close method
|
||||
func TestClose(t *testing.T) {
|
||||
path := "testfile.txt"
|
||||
tf := NewDaraFile(path)
|
||||
err := tf.Close()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestExists tests the Exists function
|
||||
func TestExists(t *testing.T) {
|
||||
path := "testfile.txt"
|
||||
ioutil.WriteFile(path, []byte("test"), 0644)
|
||||
defer os.Remove(path)
|
||||
|
||||
exists, err := Exists(path)
|
||||
if err != nil || !exists {
|
||||
t.Errorf("expected file to exist, got error: %v", err)
|
||||
}
|
||||
|
||||
exists, err = Exists("nonexistent.txt")
|
||||
if err != nil || exists {
|
||||
t.Errorf("expected file to not exist, got error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateReadWriteStream(t *testing.T) {
|
||||
tempDir, err := ioutil.TempDir("", "example")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(tempDir)
|
||||
testFile := filepath.Join(tempDir, "test.txt")
|
||||
testWFile := filepath.Join(tempDir, "test2.txt")
|
||||
|
||||
// Prepare the test file
|
||||
originalContent := "Hello, World!"
|
||||
if err := ioutil.WriteFile(testFile, []byte(originalContent), 0644); err != nil {
|
||||
t.Fatalf("failed to write test file: %v", err)
|
||||
}
|
||||
|
||||
// Test CreateReadStream
|
||||
rs, err := CreateReadStream(testFile)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create read stream: %v", err)
|
||||
}
|
||||
defer rs.Close()
|
||||
|
||||
// Test CreateWriteStream
|
||||
ws, err := CreateWriteStream(testWFile)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create write stream: %v", err)
|
||||
}
|
||||
defer ws.Close()
|
||||
|
||||
// Pipe data from read stream to write stream
|
||||
if _, err := io.Copy(ws, rs); err != nil {
|
||||
t.Fatalf("failed to copy data from read stream to write stream: %v", err)
|
||||
}
|
||||
|
||||
// Read back the content to check if it's correct
|
||||
data, err := ioutil.ReadFile(testWFile)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to read back test file: %v", err)
|
||||
}
|
||||
|
||||
if string(data) != originalContent {
|
||||
t.Fatalf("expected %q but got %q", originalContent, string(data))
|
||||
}
|
||||
}
|
||||
-177
@@ -1,177 +0,0 @@
|
||||
package dara
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/rand"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type FileField struct {
|
||||
Filename *string `json:"filename" xml:"filename" require:"true"`
|
||||
ContentType *string `json:"content-type" xml:"content-type" require:"true"`
|
||||
Content io.Reader `json:"content" xml:"content" require:"true"`
|
||||
}
|
||||
|
||||
func (s *FileField) SetFilename(v string) *FileField {
|
||||
s.Filename = &v
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *FileField) SetContentType(v string) *FileField {
|
||||
s.ContentType = &v
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *FileField) SetContent(v io.Reader) *FileField {
|
||||
s.Content = v
|
||||
return s
|
||||
}
|
||||
|
||||
type FileFormReader struct {
|
||||
formFiles []*formFile
|
||||
formField io.Reader
|
||||
index int
|
||||
streaming bool
|
||||
ifField bool
|
||||
}
|
||||
|
||||
type formFile struct {
|
||||
StartField io.Reader
|
||||
EndField io.Reader
|
||||
File io.Reader
|
||||
start bool
|
||||
end bool
|
||||
}
|
||||
|
||||
const numBytes = "1234567890"
|
||||
|
||||
func GetBoundary() string {
|
||||
b := make([]byte, 14)
|
||||
for i := range b {
|
||||
b[i] = numBytes[rand.Intn(len(numBytes))]
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func ToFileForm(body map[string]interface{}, boundary string) io.Reader {
|
||||
out := bytes.NewBuffer(nil)
|
||||
line := "--" + boundary + "\r\n"
|
||||
forms := make(map[string]string)
|
||||
files := make(map[string]map[string]interface{})
|
||||
for key, value := range body {
|
||||
switch value.(type) {
|
||||
case *FileField:
|
||||
if val, ok := value.(*FileField); ok {
|
||||
out := make(map[string]interface{})
|
||||
out["filename"] = StringValue(val.Filename)
|
||||
out["content-type"] = StringValue(val.ContentType)
|
||||
out["content"] = val.Content
|
||||
files[key] = out
|
||||
}
|
||||
case map[string]interface{}:
|
||||
if val, ok := value.(map[string]interface{}); ok {
|
||||
files[key] = val
|
||||
}
|
||||
default:
|
||||
forms[key] = fmt.Sprintf("%v", value)
|
||||
}
|
||||
}
|
||||
for key, value := range forms {
|
||||
if value != "" {
|
||||
out.Write([]byte(line))
|
||||
out.Write([]byte("Content-Disposition: form-data; name=\"" + key + "\"" + "\r\n\r\n"))
|
||||
out.Write([]byte(value + "\r\n"))
|
||||
}
|
||||
}
|
||||
formFiles := make([]*formFile, 0)
|
||||
for key, value := range files {
|
||||
var file io.Reader
|
||||
start := line
|
||||
start += "Content-Disposition: form-data; name=\"" + key + "\"; filename=\"" + value["filename"].(string) + "\"\r\n"
|
||||
start += "Content-Type: " + value["content-type"].(string) + "\r\n\r\n"
|
||||
if content, ok := value["content"].(io.Reader); ok {
|
||||
file = content
|
||||
} else {
|
||||
file = strings.NewReader("")
|
||||
}
|
||||
formFile := &formFile{
|
||||
File: file,
|
||||
start: true,
|
||||
StartField: strings.NewReader(start),
|
||||
}
|
||||
if len(files) == len(formFiles)+1 {
|
||||
end := "\r\n\r\n--" + boundary + "--\r\n"
|
||||
formFile.EndField = strings.NewReader(end)
|
||||
} else {
|
||||
formFile.EndField = strings.NewReader("\r\n\r\n")
|
||||
}
|
||||
formFiles = append(formFiles, formFile)
|
||||
}
|
||||
return &FileFormReader{
|
||||
formFiles: formFiles,
|
||||
formField: out,
|
||||
ifField: true,
|
||||
}
|
||||
}
|
||||
|
||||
func (f *FileFormReader) Read(p []byte) (n int, err error) {
|
||||
if f.ifField {
|
||||
n, err = f.formField.Read(p)
|
||||
if err != nil && err != io.EOF {
|
||||
return n, err
|
||||
} else if err == io.EOF {
|
||||
err = nil
|
||||
f.ifField = false
|
||||
f.streaming = true
|
||||
}
|
||||
} else if f.streaming {
|
||||
form := f.formFiles[f.index]
|
||||
if form.start {
|
||||
n, err = form.StartField.Read(p)
|
||||
if err != nil && err != io.EOF {
|
||||
return n, err
|
||||
} else if err == io.EOF {
|
||||
err = nil
|
||||
form.start = false
|
||||
}
|
||||
} else if form.end {
|
||||
n, err = form.EndField.Read(p)
|
||||
if err != nil && err != io.EOF {
|
||||
return n, err
|
||||
} else if err == io.EOF {
|
||||
f.index++
|
||||
form.end = false
|
||||
if f.index < len(f.formFiles) {
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
} else {
|
||||
n, err = form.File.Read(p)
|
||||
if err != nil && err != io.EOF {
|
||||
return n, err
|
||||
} else if err == io.EOF {
|
||||
err = nil
|
||||
form.end = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return n, err
|
||||
}
|
||||
|
||||
func ToFormString(a map[string]interface{}) string {
|
||||
if a == nil {
|
||||
return ""
|
||||
}
|
||||
res := ""
|
||||
urlEncoder := url.Values{}
|
||||
for key, value := range a {
|
||||
v := fmt.Sprintf("%v", value)
|
||||
urlEncoder.Add(key, v)
|
||||
}
|
||||
res = urlEncoder.Encode()
|
||||
return res
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
package dara
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/alibabacloud-go/tea/utils"
|
||||
)
|
||||
|
||||
func Test_ToFormString(t *testing.T) {
|
||||
str := ToFormString(nil)
|
||||
utils.AssertEqual(t, "", str)
|
||||
|
||||
a := map[string]interface{}{
|
||||
"key1": "value1",
|
||||
"key2": "value2",
|
||||
}
|
||||
str = ToFormString(a)
|
||||
utils.AssertEqual(t, str, "key1=value1&key2=value2")
|
||||
}
|
||||
|
||||
type TestForm struct {
|
||||
Ak *string `json:"ak"`
|
||||
File1 *FileField `json:"file1"`
|
||||
File2 *FileField `json:"file2"`
|
||||
}
|
||||
|
||||
func Test_ToFileForm(t *testing.T) {
|
||||
file1 := new(FileField).
|
||||
SetContent(strings.NewReader("ok")).
|
||||
SetContentType("jpg").
|
||||
SetFilename("a.jpg")
|
||||
body := map[string]interface{}{
|
||||
"ak": "accesskey",
|
||||
"file1": file1,
|
||||
}
|
||||
res := ToFileForm(ToMap(body), "28802961715230")
|
||||
byt, err := ioutil.ReadAll(res)
|
||||
utils.AssertNil(t, err)
|
||||
utils.AssertEqual(t, string(byt), "--28802961715230\r\nContent-Disposition: "+
|
||||
"form-data; name=\"ak\"\r\n\r\naccesskey\r\n--28802961715230\r\nContent-Disposition: "+
|
||||
"form-data; name=\"file1\"; filename=\"a.jpg\"\r\nContent-Type: jpg\r\n\r\nok\r\n\r\n--28802961715230--\r\n")
|
||||
|
||||
body1 := &TestForm{
|
||||
Ak: String("accesskey"),
|
||||
File1: &FileField{
|
||||
Filename: String("a.jpg"),
|
||||
ContentType: String("jpg"),
|
||||
Content: strings.NewReader("ok"),
|
||||
},
|
||||
}
|
||||
res = ToFileForm(ToMap(body1), "28802961715230")
|
||||
byt, err = ioutil.ReadAll(res)
|
||||
utils.AssertNil(t, err)
|
||||
utils.AssertEqual(t, string(byt), "--28802961715230\r\nContent-Disposition: form-data; "+
|
||||
"name=\"ak\"\r\n\r\naccesskey\r\n--28802961715230\r\nContent-Disposition: "+
|
||||
"form-data; name=\"file1\"; filename=\"a.jpg\"\r\nContent-Type: jpg\r\n\r\n\r\n\r\n--28802961715230--\r\n")
|
||||
}
|
||||
|
||||
func Test_GetBoundary(t *testing.T) {
|
||||
bound := GetBoundary()
|
||||
utils.AssertEqual(t, len(bound), 14)
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
-49
@@ -1,49 +0,0 @@
|
||||
package dara
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type Entry struct {
|
||||
Key string
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
// toFloat64 converts a numeric value to float64 for comparison
|
||||
func Entries(m interface{}) []*Entry {
|
||||
v := reflect.ValueOf(m)
|
||||
if v.Kind() != reflect.Map {
|
||||
panic("Entries: input must be a map")
|
||||
}
|
||||
|
||||
entries := make([]*Entry, 0, v.Len())
|
||||
for _, key := range v.MapKeys() {
|
||||
// 确保 Key 是字符串类型
|
||||
if key.Kind() != reflect.String {
|
||||
panic("Entries: map keys must be of type string")
|
||||
}
|
||||
|
||||
value := v.MapIndex(key)
|
||||
entries = append(entries, &Entry{
|
||||
Key: key.String(),
|
||||
Value: value.Interface(),
|
||||
})
|
||||
}
|
||||
return entries
|
||||
}
|
||||
|
||||
func KeySet(m interface{}) []string {
|
||||
v := reflect.ValueOf(m)
|
||||
if v.Kind() != reflect.Map {
|
||||
panic("KeySet: input must be a map")
|
||||
}
|
||||
|
||||
keys := make([]string, 0, v.Len())
|
||||
for _, key := range v.MapKeys() {
|
||||
if key.Kind() != reflect.String {
|
||||
panic("KeySet: map keys must be of type string")
|
||||
}
|
||||
keys = append(keys, key.String())
|
||||
}
|
||||
return keys
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
package dara
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type Person struct {
|
||||
Name string
|
||||
Age int
|
||||
}
|
||||
|
||||
func TestEntries(t *testing.T) {
|
||||
// 定义一个包含多种类型的 map
|
||||
type Person struct {
|
||||
Name string
|
||||
Age int
|
||||
}
|
||||
|
||||
testMap := map[string]interface{}{
|
||||
"one": 1,
|
||||
"two": "two",
|
||||
"three": &Person{Name: "Alice", Age: 30},
|
||||
}
|
||||
|
||||
entries := Entries(testMap)
|
||||
|
||||
if len(entries) != 3 {
|
||||
t.Errorf("expected %d entries, got %d", 3, len(entries))
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
if !reflect.DeepEqual(entry.Value, testMap[entry.Key]) {
|
||||
t.Errorf("expected entry %s to be %v, got %v", entry.Key, testMap[entry.Key], entry.Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestKeySet(t *testing.T) {
|
||||
testMap := map[string]interface{}{
|
||||
"one": 1,
|
||||
"two": "two",
|
||||
"three": &Person{Name: "Alice", Age: 30},
|
||||
}
|
||||
|
||||
keys := KeySet(testMap)
|
||||
str1, str2, str3 := "one", "two", "three"
|
||||
expectedKeys := []*string{&str1, &str2, &str3}
|
||||
|
||||
if len(keys) != len(expectedKeys) {
|
||||
t.Errorf("expected %d keys, got %d", len(expectedKeys), len(keys))
|
||||
}
|
||||
|
||||
for _, key := range keys {
|
||||
if !ArrContains(expectedKeys, key) {
|
||||
t.Errorf("expected key %s to be in the array %v, but not", key, expectedKeys)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package dara
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Number is an interface that can be implemented by any numeric type
|
||||
type Number interface{}
|
||||
|
||||
// toFloat64 converts a numeric value to float64 for comparison
|
||||
func toFloat64(n Number) float64 {
|
||||
v := reflect.ValueOf(n)
|
||||
switch v.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return float64(v.Int())
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
return float64(v.Uint())
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return v.Float()
|
||||
default:
|
||||
panic("unsupported type")
|
||||
}
|
||||
}
|
||||
|
||||
// Floor returns the largest integer less than or equal to the input number as int
|
||||
func Floor(n Number) int {
|
||||
v := toFloat64(n)
|
||||
floorValue := math.Floor(v)
|
||||
return int(floorValue)
|
||||
}
|
||||
|
||||
// Round returns the nearest integer to the input number as int
|
||||
func Round(n Number) int {
|
||||
v := toFloat64(n)
|
||||
roundValue := math.Round(v)
|
||||
return int(roundValue)
|
||||
}
|
||||
|
||||
func Random() float64 {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
return rand.Float64()
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package dara
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestRandom tests the Random function to ensure it returns a value in the range [0.0, 1.0)
|
||||
func TestRandom(t *testing.T) {
|
||||
for i := 0; i < 100; i++ {
|
||||
val := Random()
|
||||
if val < 0.0 || val >= 1.0 {
|
||||
t.Errorf("Random() = %v, want [0.0, 1.0)", val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestFloor tests the Floor function with various numeric inputs
|
||||
func TestFloor(t *testing.T) {
|
||||
tests := []struct {
|
||||
input Number
|
||||
expected int
|
||||
}{
|
||||
{3.7, 3},
|
||||
{-3.7, -4},
|
||||
{0.9, 0},
|
||||
{0.0, 0},
|
||||
{-0.9, -1},
|
||||
{int64(3), 3},
|
||||
{int32(-3), -3},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
result := Floor(tt.input)
|
||||
if result != tt.expected {
|
||||
t.Errorf("Floor(%v) = %v, want %v", tt.input, result, tt.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestRound tests the Round function with various numeric inputs
|
||||
func TestRound(t *testing.T) {
|
||||
tests := []struct {
|
||||
input Number
|
||||
expected int
|
||||
}{
|
||||
{3.7, 4},
|
||||
{-3.7, -4},
|
||||
{2.5, 3},
|
||||
{2.4, 2},
|
||||
{-2.5, -3},
|
||||
{0.0, 0},
|
||||
{int64(4), 4},
|
||||
{int32(-4), -4},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
result := Round(tt.input)
|
||||
if result != tt.expected {
|
||||
t.Errorf("Round(%v) = %v, want %v", tt.input, result, tt.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
-588
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
-373
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
-215
@@ -1,215 +0,0 @@
|
||||
package dara
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type SSEEvent struct {
|
||||
Id *string
|
||||
Event *string
|
||||
Data *string
|
||||
Retry *int
|
||||
}
|
||||
|
||||
func parseEvent(lines []string) *SSEEvent {
|
||||
event := &SSEEvent{}
|
||||
for _, line := range lines {
|
||||
if strings.HasPrefix(line, "data:") {
|
||||
var data string
|
||||
if strings.HasPrefix(line, "data: ") {
|
||||
data = strings.TrimPrefix(line, "data: ") + "\n"
|
||||
} else {
|
||||
data = strings.TrimPrefix(line, "data:") + "\n"
|
||||
}
|
||||
if event.Data == nil {
|
||||
event.Data = new(string)
|
||||
}
|
||||
*event.Data += data
|
||||
} else if strings.HasPrefix(line, "event:") {
|
||||
var eventName string
|
||||
if strings.HasPrefix(line, "event: ") {
|
||||
eventName = strings.TrimPrefix(line, "event: ")
|
||||
} else {
|
||||
eventName = strings.TrimPrefix(line, "event:")
|
||||
}
|
||||
event.Event = &eventName
|
||||
} else if strings.HasPrefix(line, "id:") {
|
||||
var id string
|
||||
if strings.HasPrefix(line, "id: ") {
|
||||
id = strings.TrimPrefix(line, "id: ")
|
||||
} else {
|
||||
id = strings.TrimPrefix(line, "id:")
|
||||
}
|
||||
event.Id = &id
|
||||
} else if strings.HasPrefix(line, "retry:") {
|
||||
var retryStr string
|
||||
if strings.HasPrefix(line, "retry: ") {
|
||||
retryStr = strings.TrimPrefix(line, "retry: ")
|
||||
} else {
|
||||
retryStr = strings.TrimPrefix(line, "retry:")
|
||||
}
|
||||
var retry int
|
||||
fmt.Sscanf(retryStr, "%d", &retry)
|
||||
event.Retry = &retry
|
||||
}
|
||||
}
|
||||
if event.Data != nil {
|
||||
data := strings.TrimRight(*event.Data, "\n")
|
||||
event.Data = &data
|
||||
}
|
||||
return event
|
||||
}
|
||||
|
||||
func ReadAsBytes(body io.Reader) ([]byte, error) {
|
||||
byt, err := ioutil.ReadAll(body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r, ok := body.(io.ReadCloser)
|
||||
if ok {
|
||||
r.Close()
|
||||
}
|
||||
return byt, nil
|
||||
}
|
||||
|
||||
func ReadAsJSON(body io.Reader) (result interface{}, err error) {
|
||||
byt, err := ioutil.ReadAll(body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if string(byt) == "" {
|
||||
return
|
||||
}
|
||||
r, ok := body.(io.ReadCloser)
|
||||
if ok {
|
||||
r.Close()
|
||||
}
|
||||
d := json.NewDecoder(bytes.NewReader(byt))
|
||||
d.UseNumber()
|
||||
err = d.Decode(&result)
|
||||
return
|
||||
}
|
||||
|
||||
func ReadAsString(body io.Reader) (string, error) {
|
||||
byt, err := ioutil.ReadAll(body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
r, ok := body.(io.ReadCloser)
|
||||
if ok {
|
||||
r.Close()
|
||||
}
|
||||
return string(byt), nil
|
||||
}
|
||||
|
||||
func ReadAsSSE(body io.ReadCloser, eventChannel chan *SSEEvent, errorChannel chan error) {
|
||||
|
||||
go func() {
|
||||
defer func() {
|
||||
body.Close()
|
||||
close(eventChannel)
|
||||
}()
|
||||
|
||||
reader := bufio.NewReader(body)
|
||||
var eventLines []string
|
||||
|
||||
for {
|
||||
line, err := reader.ReadString('\n')
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
// Handle the end of the stream and possibly pending event
|
||||
if len(eventLines) > 0 {
|
||||
event := parseEvent(eventLines)
|
||||
eventChannel <- event
|
||||
}
|
||||
errorChannel <- nil
|
||||
return
|
||||
}
|
||||
errorChannel <- err
|
||||
return
|
||||
}
|
||||
|
||||
line = strings.TrimRight(line, "\n")
|
||||
|
||||
if line == "" {
|
||||
// End of an SSE event
|
||||
if len(eventLines) > 0 {
|
||||
event := parseEvent(eventLines)
|
||||
eventChannel <- event
|
||||
eventLines = []string{} // Reset for the next event
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
eventLines = append(eventLines, line)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func ReadAsSSEWithContext(ctx context.Context, body io.ReadCloser, eventChannel chan *SSEEvent, errorChannel chan error) {
|
||||
|
||||
go func() {
|
||||
defer func() {
|
||||
body.Close()
|
||||
close(eventChannel)
|
||||
}()
|
||||
|
||||
reader := bufio.NewReader(body)
|
||||
var eventLines []string
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
errorChannel <- ctx.Err()
|
||||
return
|
||||
default:
|
||||
}
|
||||
|
||||
line, err := reader.ReadString('\n')
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
// Handle the end of the stream and possibly pending event
|
||||
if len(eventLines) > 0 {
|
||||
event := parseEvent(eventLines)
|
||||
select {
|
||||
case eventChannel <- event:
|
||||
case <-ctx.Done():
|
||||
errorChannel <- ctx.Err()
|
||||
return
|
||||
}
|
||||
}
|
||||
errorChannel <- nil
|
||||
return
|
||||
}
|
||||
errorChannel <- err
|
||||
return
|
||||
}
|
||||
|
||||
line = strings.TrimRight(line, "\n")
|
||||
|
||||
if line == "" {
|
||||
// End of an SSE event
|
||||
if len(eventLines) > 0 {
|
||||
event := parseEvent(eventLines)
|
||||
select {
|
||||
case eventChannel <- event:
|
||||
case <-ctx.Done():
|
||||
errorChannel <- ctx.Err()
|
||||
return
|
||||
}
|
||||
eventLines = []string{} // Reset for the next event
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
eventLines = append(eventLines, line)
|
||||
}
|
||||
}()
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
-491
File diff suppressed because it is too large
Load Diff
@@ -1,163 +0,0 @@
|
||||
package dara
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/alibabacloud-go/tea/utils"
|
||||
)
|
||||
|
||||
func Test_Trans(t *testing.T) {
|
||||
str := String("tea")
|
||||
strVal := StringValue(str)
|
||||
utils.AssertEqual(t, "tea", strVal)
|
||||
utils.AssertEqual(t, "", StringValue(nil))
|
||||
|
||||
strSlice := StringSlice([]string{"tea"})
|
||||
strSliceVal := StringSliceValue(strSlice)
|
||||
utils.AssertEqual(t, []string{"tea"}, strSliceVal)
|
||||
utils.AssertNil(t, StringSlice(nil))
|
||||
utils.AssertNil(t, StringSliceValue(nil))
|
||||
|
||||
b := Bool(true)
|
||||
bVal := BoolValue(b)
|
||||
utils.AssertEqual(t, true, bVal)
|
||||
utils.AssertEqual(t, false, BoolValue(nil))
|
||||
|
||||
bSlice := BoolSlice([]bool{false})
|
||||
bSliceVal := BoolSliceValue(bSlice)
|
||||
utils.AssertEqual(t, []bool{false}, bSliceVal)
|
||||
utils.AssertNil(t, BoolSlice(nil))
|
||||
utils.AssertNil(t, BoolSliceValue(nil))
|
||||
|
||||
f64 := Float64(2.00)
|
||||
f64Val := Float64Value(f64)
|
||||
utils.AssertEqual(t, float64(2.00), f64Val)
|
||||
utils.AssertEqual(t, float64(0), Float64Value(nil))
|
||||
|
||||
f32 := Float32(2.00)
|
||||
f32Val := Float32Value(f32)
|
||||
utils.AssertEqual(t, float32(2.00), f32Val)
|
||||
utils.AssertEqual(t, float32(0), Float32Value(nil))
|
||||
|
||||
f64Slice := Float64Slice([]float64{2.00})
|
||||
f64SliceVal := Float64ValueSlice(f64Slice)
|
||||
utils.AssertEqual(t, []float64{2.00}, f64SliceVal)
|
||||
utils.AssertNil(t, Float64Slice(nil))
|
||||
utils.AssertNil(t, Float64ValueSlice(nil))
|
||||
|
||||
f32Slice := Float32Slice([]float32{2.00})
|
||||
f32SliceVal := Float32ValueSlice(f32Slice)
|
||||
utils.AssertEqual(t, []float32{2.00}, f32SliceVal)
|
||||
utils.AssertNil(t, Float32Slice(nil))
|
||||
utils.AssertNil(t, Float32ValueSlice(nil))
|
||||
|
||||
i := Int(1)
|
||||
iVal := IntValue(i)
|
||||
utils.AssertEqual(t, 1, iVal)
|
||||
utils.AssertEqual(t, 0, IntValue(nil))
|
||||
|
||||
i8 := Int8(int8(1))
|
||||
i8Val := Int8Value(i8)
|
||||
utils.AssertEqual(t, int8(1), i8Val)
|
||||
utils.AssertEqual(t, int8(0), Int8Value(nil))
|
||||
|
||||
i16 := Int16(int16(1))
|
||||
i16Val := Int16Value(i16)
|
||||
utils.AssertEqual(t, int16(1), i16Val)
|
||||
utils.AssertEqual(t, int16(0), Int16Value(nil))
|
||||
|
||||
i32 := Int32(int32(1))
|
||||
i32Val := Int32Value(i32)
|
||||
utils.AssertEqual(t, int32(1), i32Val)
|
||||
utils.AssertEqual(t, int32(0), Int32Value(nil))
|
||||
|
||||
i64 := Int64(int64(1))
|
||||
i64Val := Int64Value(i64)
|
||||
utils.AssertEqual(t, int64(1), i64Val)
|
||||
utils.AssertEqual(t, int64(0), Int64Value(nil))
|
||||
|
||||
iSlice := IntSlice([]int{1})
|
||||
iSliceVal := IntValueSlice(iSlice)
|
||||
utils.AssertEqual(t, []int{1}, iSliceVal)
|
||||
utils.AssertNil(t, IntSlice(nil))
|
||||
utils.AssertNil(t, IntValueSlice(nil))
|
||||
|
||||
i8Slice := Int8Slice([]int8{1})
|
||||
i8ValSlice := Int8ValueSlice(i8Slice)
|
||||
utils.AssertEqual(t, []int8{1}, i8ValSlice)
|
||||
utils.AssertNil(t, Int8Slice(nil))
|
||||
utils.AssertNil(t, Int8ValueSlice(nil))
|
||||
|
||||
i16Slice := Int16Slice([]int16{1})
|
||||
i16ValSlice := Int16ValueSlice(i16Slice)
|
||||
utils.AssertEqual(t, []int16{1}, i16ValSlice)
|
||||
utils.AssertNil(t, Int16Slice(nil))
|
||||
utils.AssertNil(t, Int16ValueSlice(nil))
|
||||
|
||||
i32Slice := Int32Slice([]int32{1})
|
||||
i32ValSlice := Int32ValueSlice(i32Slice)
|
||||
utils.AssertEqual(t, []int32{1}, i32ValSlice)
|
||||
utils.AssertNil(t, Int32Slice(nil))
|
||||
utils.AssertNil(t, Int32ValueSlice(nil))
|
||||
|
||||
i64Slice := Int64Slice([]int64{1})
|
||||
i64ValSlice := Int64ValueSlice(i64Slice)
|
||||
utils.AssertEqual(t, []int64{1}, i64ValSlice)
|
||||
utils.AssertNil(t, Int64Slice(nil))
|
||||
utils.AssertNil(t, Int64ValueSlice(nil))
|
||||
|
||||
ui := Uint(1)
|
||||
uiVal := UintValue(ui)
|
||||
utils.AssertEqual(t, uint(1), uiVal)
|
||||
utils.AssertEqual(t, uint(0), UintValue(nil))
|
||||
|
||||
ui8 := Uint8(uint8(1))
|
||||
ui8Val := Uint8Value(ui8)
|
||||
utils.AssertEqual(t, uint8(1), ui8Val)
|
||||
utils.AssertEqual(t, uint8(0), Uint8Value(nil))
|
||||
|
||||
ui16 := Uint16(uint16(1))
|
||||
ui16Val := Uint16Value(ui16)
|
||||
utils.AssertEqual(t, uint16(1), ui16Val)
|
||||
utils.AssertEqual(t, uint16(0), Uint16Value(nil))
|
||||
|
||||
ui32 := Uint32(uint32(1))
|
||||
ui32Val := Uint32Value(ui32)
|
||||
utils.AssertEqual(t, uint32(1), ui32Val)
|
||||
utils.AssertEqual(t, uint32(0), Uint32Value(nil))
|
||||
|
||||
ui64 := Uint64(uint64(1))
|
||||
ui64Val := Uint64Value(ui64)
|
||||
utils.AssertEqual(t, uint64(1), ui64Val)
|
||||
utils.AssertEqual(t, uint64(0), Uint64Value(nil))
|
||||
|
||||
uiSlice := UintSlice([]uint{1})
|
||||
uiValSlice := UintValueSlice(uiSlice)
|
||||
utils.AssertEqual(t, []uint{1}, uiValSlice)
|
||||
utils.AssertNil(t, UintSlice(nil))
|
||||
utils.AssertNil(t, UintValueSlice(nil))
|
||||
|
||||
ui8Slice := Uint8Slice([]uint8{1})
|
||||
ui8ValSlice := Uint8ValueSlice(ui8Slice)
|
||||
utils.AssertEqual(t, []uint8{1}, ui8ValSlice)
|
||||
utils.AssertNil(t, Uint8Slice(nil))
|
||||
utils.AssertNil(t, Uint8ValueSlice(nil))
|
||||
|
||||
ui16Slice := Uint16Slice([]uint16{1})
|
||||
ui16ValSlice := Uint16ValueSlice(ui16Slice)
|
||||
utils.AssertEqual(t, []uint16{1}, ui16ValSlice)
|
||||
utils.AssertNil(t, Uint16Slice(nil))
|
||||
utils.AssertNil(t, Uint16ValueSlice(nil))
|
||||
|
||||
ui32Slice := Uint32Slice([]uint32{1})
|
||||
ui32ValSlice := Uint32ValueSlice(ui32Slice)
|
||||
utils.AssertEqual(t, []uint32{1}, ui32ValSlice)
|
||||
utils.AssertNil(t, Uint32Slice(nil))
|
||||
utils.AssertNil(t, Uint32ValueSlice(nil))
|
||||
|
||||
ui64Slice := Uint64Slice([]uint64{1})
|
||||
ui64ValSlice := Uint64ValueSlice(ui64Slice)
|
||||
utils.AssertEqual(t, []uint64{1}, ui64ValSlice)
|
||||
utils.AssertNil(t, Uint64Slice(nil))
|
||||
utils.AssertNil(t, Uint64ValueSlice(nil))
|
||||
}
|
||||
-149
@@ -1,149 +0,0 @@
|
||||
package dara
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// PortMap maps protocols to their corresponding ports.
|
||||
var portMap = map[string]string{
|
||||
"ftp": "21",
|
||||
"gopher": "70",
|
||||
"http": "80",
|
||||
"https": "443",
|
||||
"ws": "80",
|
||||
"wss": "443",
|
||||
}
|
||||
|
||||
// URL is a wrapper around the URL type.
|
||||
type URL struct {
|
||||
_url *url.URL
|
||||
}
|
||||
|
||||
// NewURL constructs a new URL from a string.
|
||||
func NewURL(str string) (*URL, error) {
|
||||
parsedURL, err := url.Parse(str)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &URL{_url: parsedURL}, nil
|
||||
}
|
||||
|
||||
// Path returns the path and query of the URL.
|
||||
func (t *URL) Path() string {
|
||||
if t._url.RawQuery == "" {
|
||||
return t._url.Path
|
||||
}
|
||||
return t._url.Path + "?" + t._url.RawQuery
|
||||
}
|
||||
|
||||
// Pathname returns the pathname of the URL.
|
||||
func (t *URL) Pathname() string {
|
||||
return t._url.Path
|
||||
}
|
||||
|
||||
// Protocol returns the protocol of the URL.
|
||||
func (t *URL) Protocol() string {
|
||||
return strings.TrimSuffix(t._url.Scheme, ":")
|
||||
}
|
||||
|
||||
// Hostname returns the hostname of the URL.
|
||||
func (t *URL) Hostname() string {
|
||||
return t._url.Hostname()
|
||||
}
|
||||
|
||||
// Host returns the host (host:port) of the URL.
|
||||
func (t *URL) Host() string {
|
||||
return t._url.Host
|
||||
}
|
||||
|
||||
// Port returns the port of the URL, or the default for the protocol if not specified.
|
||||
func (t *URL) Port() string {
|
||||
if p := t._url.Port(); p != "" {
|
||||
return p
|
||||
}
|
||||
return portMap[t.Protocol()]
|
||||
}
|
||||
|
||||
// Hash returns the hash of the URL without the #.
|
||||
func (t *URL) Hash() string {
|
||||
return strings.TrimPrefix(t._url.Fragment, "#")
|
||||
}
|
||||
|
||||
// Search returns the search part of the URL without the ?.
|
||||
func (t *URL) Search() string {
|
||||
return strings.TrimPrefix(t._url.RawQuery, "?")
|
||||
}
|
||||
|
||||
// Href returns the full URL.
|
||||
func (t *URL) Href() string {
|
||||
return t._url.String()
|
||||
}
|
||||
|
||||
// Auth returns the username and password of the URL.
|
||||
func (t *URL) Auth() string {
|
||||
password := getPassword(t._url.User)
|
||||
username := t._url.User.Username()
|
||||
if username == "" && password == "" {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("%s:%s", username, password)
|
||||
}
|
||||
|
||||
// getPassword retrieves the password from a URL.User.
|
||||
func getPassword(user *url.Userinfo) string {
|
||||
if password, ok := user.Password(); ok {
|
||||
return password
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Parse constructs a new URL from a string.
|
||||
func ParseURL(urlStr string) (*URL, error) {
|
||||
return NewURL(urlStr)
|
||||
}
|
||||
|
||||
// EncodeURL encodes a URL string.
|
||||
func EncodeURL(urlStr string) string {
|
||||
if urlStr == "" {
|
||||
return ""
|
||||
}
|
||||
strs := strings.Split(urlStr, "/")
|
||||
for i, v := range strs {
|
||||
strs[i] = url.QueryEscape(v)
|
||||
}
|
||||
urlStr = strings.Join(strs, "/")
|
||||
urlStr = strings.Replace(urlStr, "+", "%20", -1)
|
||||
urlStr = strings.Replace(urlStr, "*", "%2A", -1)
|
||||
urlStr = strings.Replace(urlStr, "%7E", "~", -1)
|
||||
return urlStr
|
||||
}
|
||||
|
||||
// PercentEncode encodes a string for use in URLs, replacing certain characters.
|
||||
func PercentEncode(uri string) string {
|
||||
if uri == "" {
|
||||
return ""
|
||||
}
|
||||
uri = url.QueryEscape(uri)
|
||||
uri = strings.Replace(uri, "+", "%20", -1)
|
||||
uri = strings.Replace(uri, "*", "%2A", -1)
|
||||
uri = strings.Replace(uri, "%7E", "~", -1)
|
||||
return uri
|
||||
}
|
||||
|
||||
// PathEncode encodes each segment of a path.
|
||||
func PathEncode(path string) string {
|
||||
if path == "" || path == "/" {
|
||||
return path
|
||||
}
|
||||
strs := strings.Split(path, "/")
|
||||
for i, v := range strs {
|
||||
strs[i] = url.QueryEscape(v)
|
||||
}
|
||||
path = strings.Join(strs, "/")
|
||||
path = strings.Replace(path, "+", "%20", -1)
|
||||
path = strings.Replace(path, "*", "%2A", -1)
|
||||
path = strings.Replace(path, "%7E", "~", -1)
|
||||
return path
|
||||
}
|
||||
@@ -1,255 +0,0 @@
|
||||
package dara
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNewURL(t *testing.T) {
|
||||
tests := []struct {
|
||||
urlString string
|
||||
wantErr bool
|
||||
}{
|
||||
{"http://example.com", false},
|
||||
{"ftp://user:pass@host:21/path", false},
|
||||
{"://example.com", true}, // Invalid URL
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
_, err := NewURL(tt.urlString)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("NewURL(%q) error = %v, wantErr %v", tt.urlString, err, tt.wantErr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDaraURL_Path(t *testing.T) {
|
||||
tests := []struct {
|
||||
urlString string
|
||||
want string
|
||||
}{
|
||||
{"http://example.com/path?query=1", "/path?query=1"},
|
||||
{"https://example.com/", "/"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tu, _ := NewURL(tt.urlString)
|
||||
if got := tu.Path(); got != tt.want {
|
||||
t.Errorf("DaraURL.Path() = %v, want %v", got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDaraURL_Pathname(t *testing.T) {
|
||||
tests := []struct {
|
||||
urlString string
|
||||
want string
|
||||
}{
|
||||
{"http://example.com/path?query=1", "/path"},
|
||||
{"https://example.com/another/path/", "/another/path/"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tu, _ := NewURL(tt.urlString)
|
||||
if got := tu.Pathname(); got != tt.want {
|
||||
t.Errorf("DaraURL.Pathname() = %v, want %v", got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDaraURL_Protocol(t *testing.T) {
|
||||
tests := []struct {
|
||||
urlString string
|
||||
want string
|
||||
}{
|
||||
{"http://example.com", "http"},
|
||||
{"ftp://example.com", "ftp"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tu, _ := NewURL(tt.urlString)
|
||||
if got := tu.Protocol(); got != tt.want {
|
||||
t.Errorf("DaraURL.Protocol() = %v, want %v", got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDaraURL_Hostname(t *testing.T) {
|
||||
tests := []struct {
|
||||
urlString string
|
||||
want string
|
||||
}{
|
||||
{"http://example.com", "example.com"},
|
||||
{"https://user@subdomain.example.com:443", "subdomain.example.com"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tu, _ := NewURL(tt.urlString)
|
||||
if got := tu.Hostname(); got != tt.want {
|
||||
t.Errorf("DaraURL.Hostname() = %v, want %v", got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDaraURL_Host(t *testing.T) {
|
||||
tests := []struct {
|
||||
urlString string
|
||||
want string
|
||||
}{
|
||||
{"http://example.com", "example.com"},
|
||||
{"http://example.com:8080", "example.com:8080"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tu, _ := NewURL(tt.urlString)
|
||||
if got := tu.Host(); got != tt.want {
|
||||
t.Errorf("DaraURL.Host() = %v, want %v", got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDaraURL_Port(t *testing.T) {
|
||||
tests := []struct {
|
||||
urlString string
|
||||
want string
|
||||
}{
|
||||
{"http://example.com", "80"},
|
||||
{"https://example.com", "443"},
|
||||
{"ftp://example.com:21", "21"},
|
||||
{"gopher://example.com", "70"},
|
||||
{"ws://example.com", "80"},
|
||||
{"wss://example.com", "443"},
|
||||
{"http://example.com:8080", "8080"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tu, _ := NewURL(tt.urlString)
|
||||
if got := tu.Port(); got != tt.want {
|
||||
t.Errorf("DaraURL.Port() = %v, want %v", got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDaraURL_Hash(t *testing.T) {
|
||||
tests := []struct {
|
||||
urlString string
|
||||
want string
|
||||
}{
|
||||
{"http://example.com#section", "section"},
|
||||
{"http://example.com", ""},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tu, _ := NewURL(tt.urlString)
|
||||
if got := tu.Hash(); got != tt.want {
|
||||
t.Errorf("DaraURL.Hash() = %v, want %v", got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDaraURL_Search(t *testing.T) {
|
||||
tests := []struct {
|
||||
urlString string
|
||||
want string
|
||||
}{
|
||||
{"http://example.com?query=1", "query=1"},
|
||||
{"http://example.com", ""},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tu, _ := NewURL(tt.urlString)
|
||||
if got := tu.Search(); got != tt.want {
|
||||
t.Errorf("DaraURL.Search() = %v, want %v", got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDaraURL_Href(t *testing.T) {
|
||||
tests := []struct {
|
||||
urlString string
|
||||
want string
|
||||
}{
|
||||
{"http://example.com", "http://example.com"},
|
||||
{"https://user:pass@host:443/path?query=1#section", "https://user:pass@host:443/path?query=1#section"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tu, _ := NewURL(tt.urlString)
|
||||
if got := tu.Href(); got != tt.want {
|
||||
t.Errorf("DaraURL.Href() = %v, want %v", got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDaraURL_Auth(t *testing.T) {
|
||||
tests := []struct {
|
||||
urlString string
|
||||
want string
|
||||
}{
|
||||
{"http://user:pass@example.com", "user:pass"},
|
||||
{"http://user@example.com", "user:"},
|
||||
{"http://example.com", ""},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tu, _ := NewURL(tt.urlString)
|
||||
if got := tu.Auth(); got != tt.want {
|
||||
t.Errorf("DaraURL.Auth() = %v, want %v", got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeURL(t *testing.T) {
|
||||
tests := []struct {
|
||||
urlString string
|
||||
want string
|
||||
}{
|
||||
{"hello world", "hello%20world"},
|
||||
{"test*abcd++", "test%2Aabcd%2B%2B"},
|
||||
{"", ""},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
got := EncodeURL(tt.urlString)
|
||||
if got != tt.want {
|
||||
t.Errorf("EncodeURL(%q) = %v, want %v", tt.urlString, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPercentEncode(t *testing.T) {
|
||||
tests := []struct {
|
||||
raw string
|
||||
want string
|
||||
}{
|
||||
{"hello world", "hello%20world"},
|
||||
{"hello*world", "hello%2Aworld"},
|
||||
{"hello~world", "hello~world"},
|
||||
{"", ""},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
got := PercentEncode(tt.raw)
|
||||
if got != tt.want {
|
||||
t.Errorf("PercentEncode(%q) = %v, want %v", tt.raw, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPathEncode(t *testing.T) {
|
||||
tests := []struct {
|
||||
path string
|
||||
want string
|
||||
}{
|
||||
{"hello/world", "hello/world"},
|
||||
{"hello world", "hello%20world"},
|
||||
{"", ""},
|
||||
{"/", "/"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
got := PathEncode(tt.path)
|
||||
if got != tt.want {
|
||||
t.Errorf("PathEncode(%q) = %v, want %v", tt.path, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
-1295
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user