* mostly working api proxy gen * api: Consistent api names * fix docsgen * regenerate api struct * api: expand external interfaces * Add missing gen files * apigen: fix perm detection * api: Move perm tags to the interface * gofmt * worker perms * docsgen * docsgen: ignore tag comments * apigen: add codegen warning * gofmt * missing actor type * docsgen * make linter happy * fix lint * apigen: use directives for tags * docsgen * regen openrpc docs
		
			
				
	
	
		
			116 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			116 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package api
 | |
| 
 | |
| import (
 | |
| 	"encoding/json"
 | |
| 	"os"
 | |
| 	"os/exec"
 | |
| 	"path/filepath"
 | |
| 	"reflect"
 | |
| 	"runtime"
 | |
| 	"strings"
 | |
| 	"testing"
 | |
| 
 | |
| 	"github.com/stretchr/testify/require"
 | |
| )
 | |
| 
 | |
| func goCmd() string {
 | |
| 	var exeSuffix string
 | |
| 	if runtime.GOOS == "windows" {
 | |
| 		exeSuffix = ".exe"
 | |
| 	}
 | |
| 	path := filepath.Join(runtime.GOROOT(), "bin", "go"+exeSuffix)
 | |
| 	if _, err := os.Stat(path); err == nil {
 | |
| 		return path
 | |
| 	}
 | |
| 	return "go"
 | |
| }
 | |
| 
 | |
| func TestDoesntDependOnFFI(t *testing.T) {
 | |
| 	deps, err := exec.Command(goCmd(), "list", "-deps", "github.com/filecoin-project/lotus/api").Output()
 | |
| 	if err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 	for _, pkg := range strings.Fields(string(deps)) {
 | |
| 		if pkg == "github.com/filecoin-project/filecoin-ffi" {
 | |
| 			t.Fatal("api depends on filecoin-ffi")
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestDoesntDependOnBuild(t *testing.T) {
 | |
| 	deps, err := exec.Command(goCmd(), "list", "-deps", "github.com/filecoin-project/lotus/api").Output()
 | |
| 	if err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 	for _, pkg := range strings.Fields(string(deps)) {
 | |
| 		if pkg == "github.com/filecoin-project/build" {
 | |
| 			t.Fatal("api depends on filecoin-ffi")
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestReturnTypes(t *testing.T) {
 | |
| 	errType := reflect.TypeOf(new(error)).Elem()
 | |
| 	bareIface := reflect.TypeOf(new(interface{})).Elem()
 | |
| 	jmarsh := reflect.TypeOf(new(json.Marshaler)).Elem()
 | |
| 
 | |
| 	tst := func(api interface{}) func(t *testing.T) {
 | |
| 		return func(t *testing.T) {
 | |
| 			ra := reflect.TypeOf(api).Elem()
 | |
| 			for i := 0; i < ra.NumMethod(); i++ {
 | |
| 				m := ra.Method(i)
 | |
| 				switch m.Type.NumOut() {
 | |
| 				case 1: // if 1 return value, it must be an error
 | |
| 					require.Equal(t, errType, m.Type.Out(0), m.Name)
 | |
| 
 | |
| 				case 2: // if 2 return values, first cant be an interface/function, second must be an error
 | |
| 					seen := map[reflect.Type]struct{}{}
 | |
| 					todo := []reflect.Type{m.Type.Out(0)}
 | |
| 					for len(todo) > 0 {
 | |
| 						typ := todo[len(todo)-1]
 | |
| 						todo = todo[:len(todo)-1]
 | |
| 
 | |
| 						if _, ok := seen[typ]; ok {
 | |
| 							continue
 | |
| 						}
 | |
| 						seen[typ] = struct{}{}
 | |
| 
 | |
| 						if typ.Kind() == reflect.Interface && typ != bareIface && !typ.Implements(jmarsh) {
 | |
| 							t.Error("methods can't return interfaces", m.Name)
 | |
| 						}
 | |
| 
 | |
| 						switch typ.Kind() {
 | |
| 						case reflect.Ptr:
 | |
| 							fallthrough
 | |
| 						case reflect.Array:
 | |
| 							fallthrough
 | |
| 						case reflect.Slice:
 | |
| 							fallthrough
 | |
| 						case reflect.Chan:
 | |
| 							todo = append(todo, typ.Elem())
 | |
| 						case reflect.Map:
 | |
| 							todo = append(todo, typ.Elem())
 | |
| 							todo = append(todo, typ.Key())
 | |
| 						case reflect.Struct:
 | |
| 							for i := 0; i < typ.NumField(); i++ {
 | |
| 								todo = append(todo, typ.Field(i).Type)
 | |
| 							}
 | |
| 						}
 | |
| 					}
 | |
| 
 | |
| 					require.NotEqual(t, reflect.Func.String(), m.Type.Out(0).Kind().String(), m.Name)
 | |
| 					require.Equal(t, errType, m.Type.Out(1), m.Name)
 | |
| 
 | |
| 				default:
 | |
| 					t.Error("methods can only have 1 or 2 return values", m.Name)
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	t.Run("common", tst(new(Common)))
 | |
| 	t.Run("full", tst(new(FullNode)))
 | |
| 	t.Run("miner", tst(new(StorageMiner)))
 | |
| 	t.Run("worker", tst(new(Worker)))
 | |
| }
 |