<commit_before>package main

import (
	"github.com/go-kit/kit/log"
	"github.com/piotrkowalczuk/charon"
	"github.com/piotrkowalczuk/mnemosyne"
	"golang.org/x/net/context"
	"google.golang.org/grpc/metadata"
	"google.golang.org/grpc/peer"
)

type rpcServer struct {
	meta               metadata.MD
	logger             log.Logger
	monitor            monitoring
	session            mnemosyne.Mnemosyne
	passwordHasher     charon.PasswordHasher
	permissionRegistry PermissionRegistry
	repository         repositories
}

type actor struct {
	user        *userEntity
	session     *mnemosyne.Session
	permissions charon.Permissions
	isLocal     bool
}

func (rs *rpcServer) loggerBackground(ctx context.Context, keyval ...interface{}) log.Logger {
	l := log.NewContext(rs.logger).With(keyval...)
	if md, ok := metadata.FromContext(ctx); ok {
		if rid, ok := md["request_id"]; ok && len(rid) < 1 {
			l = l.With("request_id", rid[0])
		}
	}

	if p, ok := peer.FromContext(ctx); ok {
		l = l.With("peer_address", p.Addr.String())
	}

	return l
}

// Context create new context based on given metadata and instance metadata.
func (rs *rpcServer) Context(md metadata.MD) context.Context {
	if md.Len() == 0 {
		md = rs.meta
	} else {
		md = rs.metadata(md)
	}

	return metadata.NewContext(context.Background(), md)
}

func (rs *rpcServer) metadata(md metadata.MD) metadata.MD {
	for key, value := range rs.meta {
		if _, ok := md[key]; !ok {
			md[key] = value
		}
	}

	return md
}

// Login implements charon.RPCServer interface.
func (rs *rpcServer) Login(ctx context.Context, req *charon.LoginRequest) (*charon.LoginResponse, error) {
	h := &loginHandler{
		handler: newHandler(rs, ctx, "login"),
		hasher:  rs.passwordHasher,
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "subject has been logged in")

	return resp, err
}

// Logout implements charon.RPCServer interface.
func (rs *rpcServer) Logout(ctx context.Context, req *charon.LogoutRequest) (*charon.LogoutResponse, error) {
	h := &logoutHandler{
		handler: newHandler(rs, ctx, "logout"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "subject has been logged out")

	return resp, err
}

// IsAuthenticated implements charon.RPCServer interface.
func (rs *rpcServer) IsAuthenticated(ctx context.Context, req *charon.IsAuthenticatedRequest) (*charon.IsAuthenticatedResponse, error) {
	h := &isAuthenticatedHandler{
		handler: newHandler(rs, ctx, "is_authenticated"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "subject has been logged out")

	return resp, err
}

// Subject implements charon.RPCServer interface.
func (rs *rpcServer) Subject(ctx context.Context, req *charon.SubjectRequest) (*charon.SubjectResponse, error) {
	h := &subjectHandler{
		handler: newHandler(rs, ctx, "subject"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "subject has been retrieved")

	return resp, err
}

// IsGranted implements charon.RPCServer interface.
func (rs *rpcServer) IsGranted(ctx context.Context, req *charon.IsGrantedRequest) (*charon.IsGrantedResponse, error) {
	h := &isGrantedHandler{
		handler: newHandler(rs, ctx, "is_granted"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "permission has been checked")

	return resp, err
}

// BelongsTo implements charon.RPCServer interface.
func (rs *rpcServer) BelongsTo(ctx context.Context, req *charon.BelongsToRequest) (*charon.BelongsToResponse, error) {
	h := &belongsToHandler{
		handler: newHandler(rs, ctx, "belongs_to"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "belonging to the group has been checked")

	return resp, err
}

// CreateGroup implements charon.RPCServer interface.
func (rs *rpcServer) CreateGroup(ctx context.Context, req *charon.CreateGroupRequest) (*charon.CreateGroupResponse, error) {
	h := &createGroupHandler{
		handler: newHandler(rs, ctx, "create_group"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "group has been created")

	return resp, err
}

// ModifyGroup implements charon.RPCServer interface.
func (rs *rpcServer) ModifyGroup(ctx context.Context, req *charon.ModifyGroupRequest) (*charon.ModifyGroupResponse, error) {
	h := &modifyGroupHandler{
		handler: newHandler(rs, ctx, "modify_group"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "group has been created")

	return resp, err
}

// DeleteGroup implements charon.RPCServer interface.
func (rs *rpcServer) DeleteGroup(ctx context.Context, req *charon.DeleteGroupRequest) (*charon.DeleteGroupResponse, error) {
	h := &deleteGroupHandler{
		handler: newHandler(rs, ctx, "delete_group"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "group has been deleted")

	return resp, err
}

// GetGroup implements charon.RPCServer interface.
func (rs *rpcServer) GetGroup(ctx context.Context, req *charon.GetGroupRequest) (*charon.GetGroupResponse, error) {
	h := &getGroupHandler{
		handler: newHandler(rs, ctx, "get_group"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "group has been retrieved")

	return resp, err
}

// ListGroups implements charon.RPCServer interface.
func (rs *rpcServer) ListGroups(ctx context.Context, req *charon.ListGroupsRequest) (*charon.ListGroupsResponse, error) {
	h := &listGroupsHandler{
		handler: newHandler(rs, ctx, "list_groups"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "list of groups has been retrieved")

	return resp, err
}

// ListGroupPermissions implements charon.RPCServer interface.
func (rs *rpcServer) ListGroupPermissions(ctx context.Context, req *charon.ListGroupPermissionsRequest) (*charon.ListGroupPermissionsResponse, error) {
	h := &listGroupPermissionsHandler{
		handler: newHandler(rs, ctx, "list_group_permissions"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "list of group permissions has been retrieved")

	return resp, err
}

// SetGroupPermissions implements charon.RPCServer interface.
func (rs *rpcServer) SetGroupPermissions(ctx context.Context, req *charon.SetGroupPermissionsRequest) (*charon.SetGroupPermissionsResponse, error) {
	h := &setGroupPermissionsHandler{
		handler: newHandler(rs, ctx, "set_group_permissions"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "group permissions has been set")

	return resp, err
}

// GetPermission implements charon.RPCServer interface.
func (rs *rpcServer) GetPermission(ctx context.Context, req *charon.GetPermissionRequest) (*charon.GetPermissionResponse, error) {
	h := &getPermissionHandler{
		handler: newHandler(rs, ctx, "get_permission"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "permission has been retrieved")

	return resp, err
}

// RegisterPermissions implements charon.RPCServer interface.
func (rs *rpcServer) RegisterPermissions(ctx context.Context, req *charon.RegisterPermissionsRequest) (*charon.RegisterPermissionsResponse, error) {
	h := &registerPermissionsHandler{
		handler:  newHandler(rs, ctx, "register_permissions"),
		registry: rs.permissionRegistry,
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "permissions has been registered")

	return resp, err
}

// ListPermissions implements charon.RPCServer interface.
func (rs *rpcServer) ListPermissions(ctx context.Context, req *charon.ListPermissionsRequest) (*charon.ListPermissionsResponse, error) {
	h := &listPermissionsHandler{
		handler: newHandler(rs, ctx, "list_permissions"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "list of permissions has been retrieved")

	return resp, err
}

// CreateUser implements charon.RPCServer interface.
func (rs *rpcServer) CreateUser(ctx context.Context, req *charon.CreateUserRequest) (*charon.CreateUserResponse, error) {
	h := &createUserHandler{
		handler: newHandler(rs, ctx, "create_user"),
		hasher:  rs.passwordHasher,
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "user has been created")

	return resp, err
}

// ModifyUser implements charon.RPCServer interface.
func (rs *rpcServer) ModifyUser(ctx context.Context, req *charon.ModifyUserRequest) (*charon.ModifyUserResponse, error) {
	h := &modifyUserHandler{
		handler: newHandler(rs, ctx, "modify_user"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "user has been modified")

	return resp, err
}

// GetUser implements charon.RPCServer interface.
func (rs *rpcServer) GetUser(ctx context.Context, req *charon.GetUserRequest) (*charon.GetUserResponse, error) {
	h := &getUserHandler{
		handler: newHandler(rs, ctx, "get_user"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "user has been retrieved")

	return resp, err
}

// ListUsers implements charon.RPCServer interface.
func (rs *rpcServer) ListUsers(ctx context.Context, req *charon.ListUsersRequest) (*charon.ListUsersResponse, error) {
	h := &listUsersHandler{
		handler: newHandler(rs, ctx, "list_users"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "list of users has been retrieved")

	return resp, err
}

// DeleteUser implements charon.RPCServer interface.
func (rs *rpcServer) DeleteUser(ctx context.Context, req *charon.DeleteUserRequest) (*charon.DeleteUserResponse, error) {
	h := &deleteUserHandler{
		handler: newHandler(rs, ctx, "delete_user"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "user has been deleted")

	return resp, err
}

// SetUserGroups implements charon.RPCServer interface.
func (rs *rpcServer) SetUserGroups(ctx context.Context, req *charon.SetUserGroupsRequest) (*charon.SetUserGroupsResponse, error) {
	h := &setUserGroupsHandler{
		handler: newHandler(rs, ctx, "set_user_groups"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "user groups has been set")

	return resp, err
}

// ListUserGroups implements charon.RPCServer interface.
func (rs *rpcServer) ListUserGroups(ctx context.Context, req *charon.ListUserGroupsRequest) (*charon.ListUserGroupsResponse, error) {
	h := &listUserGroupsHandler{
		handler: newHandler(rs, ctx, "list_user_groups"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "list of user groups has been retrieved")

	return resp, err
}

// SetUserPermissions implements charon.RPCServer interface.
func (rs *rpcServer) SetUserPermissions(ctx context.Context, req *charon.SetUserPermissionsRequest) (*charon.SetUserPermissionsResponse, error) {
	h := &setUserPermissionsHandler{
		handler: newHandler(rs, ctx, "set_user_permissions"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "user permissions has been set")

	return resp, err
}

// ListUserPermissions implements charon.RPCServer interface.
func (rs *rpcServer) ListUserPermissions(ctx context.Context, req *charon.ListUserPermissionsRequest) (*charon.ListUserPermissionsResponse, error) {
	h := &listUserPermissionsHandler{
		handler: newHandler(rs, ctx, "list_user_permissions"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "list of user permissions has been retrieved")

	return resp, err
}
<commit_msg>log message fix<commit_after>package main

import (
	"github.com/go-kit/kit/log"
	"github.com/piotrkowalczuk/charon"
	"github.com/piotrkowalczuk/mnemosyne"
	"golang.org/x/net/context"
	"google.golang.org/grpc/metadata"
	"google.golang.org/grpc/peer"
)

type rpcServer struct {
	meta               metadata.MD
	logger             log.Logger
	monitor            monitoring
	session            mnemosyne.Mnemosyne
	passwordHasher     charon.PasswordHasher
	permissionRegistry PermissionRegistry
	repository         repositories
}

type actor struct {
	user        *userEntity
	session     *mnemosyne.Session
	permissions charon.Permissions
	isLocal     bool
}

func (rs *rpcServer) loggerBackground(ctx context.Context, keyval ...interface{}) log.Logger {
	l := log.NewContext(rs.logger).With(keyval...)
	if md, ok := metadata.FromContext(ctx); ok {
		if rid, ok := md["request_id"]; ok && len(rid) < 1 {
			l = l.With("request_id", rid[0])
		}
	}

	if p, ok := peer.FromContext(ctx); ok {
		l = l.With("peer_address", p.Addr.String())
	}

	return l
}

// Context create new context based on given metadata and instance metadata.
func (rs *rpcServer) Context(md metadata.MD) context.Context {
	if md.Len() == 0 {
		md = rs.meta
	} else {
		md = rs.metadata(md)
	}

	return metadata.NewContext(context.Background(), md)
}

func (rs *rpcServer) metadata(md metadata.MD) metadata.MD {
	for key, value := range rs.meta {
		if _, ok := md[key]; !ok {
			md[key] = value
		}
	}

	return md
}

// Login implements charon.RPCServer interface.
func (rs *rpcServer) Login(ctx context.Context, req *charon.LoginRequest) (*charon.LoginResponse, error) {
	h := &loginHandler{
		handler: newHandler(rs, ctx, "login"),
		hasher:  rs.passwordHasher,
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "subject has been logged in")

	return resp, err
}

// Logout implements charon.RPCServer interface.
func (rs *rpcServer) Logout(ctx context.Context, req *charon.LogoutRequest) (*charon.LogoutResponse, error) {
	h := &logoutHandler{
		handler: newHandler(rs, ctx, "logout"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "subject has been logged out")

	return resp, err
}

// IsAuthenticated implements charon.RPCServer interface.
func (rs *rpcServer) IsAuthenticated(ctx context.Context, req *charon.IsAuthenticatedRequest) (*charon.IsAuthenticatedResponse, error) {
	h := &isAuthenticatedHandler{
		handler: newHandler(rs, ctx, "is_authenticated"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "subject authentication status has been checked")

	return resp, err
}

// Subject implements charon.RPCServer interface.
func (rs *rpcServer) Subject(ctx context.Context, req *charon.SubjectRequest) (*charon.SubjectResponse, error) {
	h := &subjectHandler{
		handler: newHandler(rs, ctx, "subject"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "subject has been retrieved")

	return resp, err
}

// IsGranted implements charon.RPCServer interface.
func (rs *rpcServer) IsGranted(ctx context.Context, req *charon.IsGrantedRequest) (*charon.IsGrantedResponse, error) {
	h := &isGrantedHandler{
		handler: newHandler(rs, ctx, "is_granted"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "permission has been checked")

	return resp, err
}

// BelongsTo implements charon.RPCServer interface.
func (rs *rpcServer) BelongsTo(ctx context.Context, req *charon.BelongsToRequest) (*charon.BelongsToResponse, error) {
	h := &belongsToHandler{
		handler: newHandler(rs, ctx, "belongs_to"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "belonging to the group has been checked")

	return resp, err
}

// CreateGroup implements charon.RPCServer interface.
func (rs *rpcServer) CreateGroup(ctx context.Context, req *charon.CreateGroupRequest) (*charon.CreateGroupResponse, error) {
	h := &createGroupHandler{
		handler: newHandler(rs, ctx, "create_group"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "group has been created")

	return resp, err
}

// ModifyGroup implements charon.RPCServer interface.
func (rs *rpcServer) ModifyGroup(ctx context.Context, req *charon.ModifyGroupRequest) (*charon.ModifyGroupResponse, error) {
	h := &modifyGroupHandler{
		handler: newHandler(rs, ctx, "modify_group"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "group has been created")

	return resp, err
}

// DeleteGroup implements charon.RPCServer interface.
func (rs *rpcServer) DeleteGroup(ctx context.Context, req *charon.DeleteGroupRequest) (*charon.DeleteGroupResponse, error) {
	h := &deleteGroupHandler{
		handler: newHandler(rs, ctx, "delete_group"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "group has been deleted")

	return resp, err
}

// GetGroup implements charon.RPCServer interface.
func (rs *rpcServer) GetGroup(ctx context.Context, req *charon.GetGroupRequest) (*charon.GetGroupResponse, error) {
	h := &getGroupHandler{
		handler: newHandler(rs, ctx, "get_group"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "group has been retrieved")

	return resp, err
}

// ListGroups implements charon.RPCServer interface.
func (rs *rpcServer) ListGroups(ctx context.Context, req *charon.ListGroupsRequest) (*charon.ListGroupsResponse, error) {
	h := &listGroupsHandler{
		handler: newHandler(rs, ctx, "list_groups"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "list of groups has been retrieved")

	return resp, err
}

// ListGroupPermissions implements charon.RPCServer interface.
func (rs *rpcServer) ListGroupPermissions(ctx context.Context, req *charon.ListGroupPermissionsRequest) (*charon.ListGroupPermissionsResponse, error) {
	h := &listGroupPermissionsHandler{
		handler: newHandler(rs, ctx, "list_group_permissions"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "list of group permissions has been retrieved")

	return resp, err
}

// SetGroupPermissions implements charon.RPCServer interface.
func (rs *rpcServer) SetGroupPermissions(ctx context.Context, req *charon.SetGroupPermissionsRequest) (*charon.SetGroupPermissionsResponse, error) {
	h := &setGroupPermissionsHandler{
		handler: newHandler(rs, ctx, "set_group_permissions"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "group permissions has been set")

	return resp, err
}

// GetPermission implements charon.RPCServer interface.
func (rs *rpcServer) GetPermission(ctx context.Context, req *charon.GetPermissionRequest) (*charon.GetPermissionResponse, error) {
	h := &getPermissionHandler{
		handler: newHandler(rs, ctx, "get_permission"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "permission has been retrieved")

	return resp, err
}

// RegisterPermissions implements charon.RPCServer interface.
func (rs *rpcServer) RegisterPermissions(ctx context.Context, req *charon.RegisterPermissionsRequest) (*charon.RegisterPermissionsResponse, error) {
	h := &registerPermissionsHandler{
		handler:  newHandler(rs, ctx, "register_permissions"),
		registry: rs.permissionRegistry,
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "permissions has been registered")

	return resp, err
}

// ListPermissions implements charon.RPCServer interface.
func (rs *rpcServer) ListPermissions(ctx context.Context, req *charon.ListPermissionsRequest) (*charon.ListPermissionsResponse, error) {
	h := &listPermissionsHandler{
		handler: newHandler(rs, ctx, "list_permissions"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "list of permissions has been retrieved")

	return resp, err
}

// CreateUser implements charon.RPCServer interface.
func (rs *rpcServer) CreateUser(ctx context.Context, req *charon.CreateUserRequest) (*charon.CreateUserResponse, error) {
	h := &createUserHandler{
		handler: newHandler(rs, ctx, "create_user"),
		hasher:  rs.passwordHasher,
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "user has been created")

	return resp, err
}

// ModifyUser implements charon.RPCServer interface.
func (rs *rpcServer) ModifyUser(ctx context.Context, req *charon.ModifyUserRequest) (*charon.ModifyUserResponse, error) {
	h := &modifyUserHandler{
		handler: newHandler(rs, ctx, "modify_user"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "user has been modified")

	return resp, err
}

// GetUser implements charon.RPCServer interface.
func (rs *rpcServer) GetUser(ctx context.Context, req *charon.GetUserRequest) (*charon.GetUserResponse, error) {
	h := &getUserHandler{
		handler: newHandler(rs, ctx, "get_user"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "user has been retrieved")

	return resp, err
}

// ListUsers implements charon.RPCServer interface.
func (rs *rpcServer) ListUsers(ctx context.Context, req *charon.ListUsersRequest) (*charon.ListUsersResponse, error) {
	h := &listUsersHandler{
		handler: newHandler(rs, ctx, "list_users"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "list of users has been retrieved")

	return resp, err
}

// DeleteUser implements charon.RPCServer interface.
func (rs *rpcServer) DeleteUser(ctx context.Context, req *charon.DeleteUserRequest) (*charon.DeleteUserResponse, error) {
	h := &deleteUserHandler{
		handler: newHandler(rs, ctx, "delete_user"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "user has been deleted")

	return resp, err
}

// SetUserGroups implements charon.RPCServer interface.
func (rs *rpcServer) SetUserGroups(ctx context.Context, req *charon.SetUserGroupsRequest) (*charon.SetUserGroupsResponse, error) {
	h := &setUserGroupsHandler{
		handler: newHandler(rs, ctx, "set_user_groups"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "user groups has been set")

	return resp, err
}

// ListUserGroups implements charon.RPCServer interface.
func (rs *rpcServer) ListUserGroups(ctx context.Context, req *charon.ListUserGroupsRequest) (*charon.ListUserGroupsResponse, error) {
	h := &listUserGroupsHandler{
		handler: newHandler(rs, ctx, "list_user_groups"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "list of user groups has been retrieved")

	return resp, err
}

// SetUserPermissions implements charon.RPCServer interface.
func (rs *rpcServer) SetUserPermissions(ctx context.Context, req *charon.SetUserPermissionsRequest) (*charon.SetUserPermissionsResponse, error) {
	h := &setUserPermissionsHandler{
		handler: newHandler(rs, ctx, "set_user_permissions"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "user permissions has been set")

	return resp, err
}

// ListUserPermissions implements charon.RPCServer interface.
func (rs *rpcServer) ListUserPermissions(ctx context.Context, req *charon.ListUserPermissionsRequest) (*charon.ListUserPermissionsResponse, error) {
	h := &listUserPermissionsHandler{
		handler: newHandler(rs, ctx, "list_user_permissions"),
	}
	h.addRequest(1)

	resp, err := h.handle(ctx, req)
	h.handler.handle(err, "list of user permissions has been retrieved")

	return resp, err
}
<|endoftext|>


<commit_before>// Copyright 2016 Yahoo Inc.
// Licensed under the terms of the Apache license. Please see LICENSE.md file distributed with this work for terms.

package utils

import (
	"fmt"
	"github.com/ardielle/ardielle-go/rdl"
	"io"
	"os"
	"strings"
	"text/template"
	"unicode"
)

func JavaGenerationHeader(banner string) string {
	return fmt.Sprintf("%s// Please DO NOT edit directly; changes could be overwritten.\n//", javaGenerationBanner(banner))
}

func JavaGenerationOrigHeader(banner string) string {
	return fmt.Sprintf("%s// WILL NOT be auto-generated if file has already existed.\n//", javaGenerationBanner(banner));
}

func javaGenerationBanner(banner string) string {
	return fmt.Sprintf("//\n// This file is generated by %s\n", banner)
}

func JavaGenerationPackage(schema *rdl.Schema, namespace string) string {
	return JavaGenerationOrigPackage(schema, namespace) + ".parsec_generated"
}

func JavaGenerationOrigPackage(schema *rdl.Schema, namespace string) string {
	if namespace != "" {
		return namespace
	}
	return string(schema.Namespace)
}

func camelSnakeToKebab(name string) string {
	s := strings.Replace(name, "_", "-", -1)
	result := make([]rune, 0)
	wasLower := false
	for _, c := range s {
		if unicode.IsUpper(c) {
			if wasLower {
				result = append(result, '-')
			}
			result = append(result, unicode.ToLower(c))
			wasLower = false
		} else {
			result = append(result, c)
			wasLower = true
		}
	}
	return string(result)
}

func JavaGenerationRootPath(schema *rdl.Schema, basePath string) string {
	if basePath != "" {
		if schema.Version != nil {
			if basePath != "/" {
				return fmt.Sprintf("%s/v%d", basePath, *schema.Version)
			}
			return fmt.Sprintf("/v%d", *schema.Version)
		}
		return basePath
	} else if schema.Name != "" {
		n := camelSnakeToKebab(string(schema.Name))
		if schema.Version != nil {
			return fmt.Sprintf("/%s/v%d", n, *schema.Version)
		} else {
			return fmt.Sprintf("/%s", n)
		}
	}

	return "/"
}

func JavaGenerationDir(outdir string, schema *rdl.Schema, namespace string) (string, error) {
        return _javaGenerationDir(outdir, schema, "./target/generated-sources/java", JavaGenerationPackage(schema, namespace))
}

func JavaGenerationSourceDir(schema *rdl.Schema, namespace string) (string, error) {
        return _javaGenerationDir("", schema, "./src/main/java", JavaGenerationOrigPackage(schema, namespace))
}

func _javaGenerationDir(outdir string, schema *rdl.Schema, defaultDir string, pack string) (string, error) {
	dir := outdir
	if dir == "" {
		dir = defaultDir
	}
	//pack := javaGenerationPackage(schema)
	if pack != "" {
		dir += "/" + strings.Replace(pack, ".", "/", -1)
	}
	_, err := os.Stat(dir)
	if err != nil {
		err = os.MkdirAll(dir, 0755)
	}
	return dir, err
}

func JavaGenerateResourceError(schema *rdl.Schema, writer io.Writer, namespace string) error {
	return _javaGenerateTemplate(schema, writer, javaResourceErrorTemplate, namespace)
}

func JavaGenerateParsecResourceError(schema *rdl.Schema, writer io.Writer, namespace string) error {
	return _javaGenerateTemplate(schema, writer, javaParsecResourceErrorTemplate, namespace)
}

func JavaGenerateParsecErrorBody(schema *rdl.Schema, writer io.Writer, namespace string) error {
	return _javaGenerateTemplate(schema, writer, javaParsecErrorBodyTemplate, namespace)
}

func JavaGenerateParsecErrorDetail(schema *rdl.Schema, writer io.Writer, namespace string) error {
	return _javaGenerateTemplate(schema, writer, javaParsecErrorDetailTemplate, namespace)
}

func _javaGenerateTemplate(schema *rdl.Schema, writer io.Writer, content string, namespace string) error {
	funcMap := template.FuncMap{
		"package": func() string {
			s := JavaGenerationPackage(schema, namespace)
			if s == "" {
				return s
			}
			return "package " + s + ";\n"
		},
	}
	t := template.Must(template.New("util").Funcs(funcMap).Parse(content))
	return t.Execute(writer, schema)
}

const javaResourceErrorTemplate = `{{package}}
public class ResourceError {

    public int code;
    public String message;

    public ResourceError code(int code) {
        this.code = code;
        return this;
    }

    public ResourceError message(String message) {
        this.message = message;
        return this;
    }

    public String toString() {
        return "{code: " + code + ", message: \"" + message + "\"}";
    }

}
`

const javaParsecResourceErrorTemplate = `{{package}}
public final class ParsecResourceError implements java.io.Serializable {

    private ParsecErrorBody error;

    public ParsecResourceError() { }

    public ParsecErrorBody getError() { return error; }

    public ParsecResourceError setError(ParsecErrorBody error) { this.error = error; return this; }
}
`

const javaParsecErrorBodyTemplate = `{{package}}
import java.util.List;

public final class ParsecErrorBody implements java.io.Serializable {

    private Integer code;
    private String message;

    private List<ParsecErrorDetail> detail;

    public ParsecErrorBody() { }

    public Integer getCode() { return code; }

    public String getMessage() { return message; }

    public List<ParsecErrorDetail> getDetail() { return detail; }

    public ParsecErrorBody setCode(Integer code) { this.code = code; return this; }

    public ParsecErrorBody setMessage(String message) { this.message = message; return this; }

    public ParsecErrorBody setDetail(List<ParsecErrorDetail> detail) { this.detail = detail; return this; }
}
`

const javaParsecErrorDetailTemplate = `{{package}}
public final class ParsecErrorDetail implements java.io.Serializable {

    private String message;

    private String invalidValue;

    public ParsecErrorDetail() { }

    public String getMessage() { return message; }

    public String getInvalidValue() { return invalidValue; }

    public ParsecErrorDetail setMessage(String message) { this.message = message; return this; }

    public ParsecErrorDetail setInvalidValue(String invalidValue) { this.invalidValue = invalidValue; return this; }
}
`

func JavaGenerateResourceException(schema *rdl.Schema, writer io.Writer, namespace string) error {
	return _javaGenerateTemplate(schema, writer, javaResourceExceptionTemplate, namespace)
}

const javaResourceExceptionTemplate = `{{package}}
public class ResourceException extends RuntimeException {
    public final static int OK = 200;
    public final static int CREATED = 201;
    public final static int ACCEPTED = 202;
    public final static int NO_CONTENT = 204;
    public final static int MOVED_PERMANENTLY = 301;
    public final static int FOUND = 302;
    public final static int SEE_OTHER = 303;
    public final static int NOT_MODIFIED = 304;
    public final static int TEMPORARY_REDIRECT = 307;
    public final static int BAD_REQUEST = 400;
    public final static int UNAUTHORIZED = 401;
    public final static int FORBIDDEN = 403;
    public final static int NOT_FOUND = 404;
    public final static int CONFLICT = 409;
    public final static int GONE = 410;
    public final static int PRECONDITION_FAILED = 412;
    public final static int REQUEST_ENTITY_TOO_LARGE = 413;
    public final static int UNSUPPORTED_MEDIA_TYPE = 415;
    public final static int MISDIRECTED_REQUEST = 421;
    public final static int PRECONDITION_REQUIRED = 428;
    public final static int TOO_MANY_REQUESTS = 429;

    public final static int INTERNAL_SERVER_ERROR = 500;
    public final static int NOT_IMPLEMENTED = 501;

    public final static int SERVICE_UNAVAILABLE = 503;

    public static String codeToString(int code) {
        switch (code) {
        case OK: return "OK";
        case CREATED: return "Created";
        case ACCEPTED: return "Accepted";
        case NO_CONTENT: return "No Content";
        case MOVED_PERMANENTLY: return "Moved Permanently";
        case FOUND: return "Found";
        case SEE_OTHER: return "See Other";
        case NOT_MODIFIED: return "Not Modified";
        case TEMPORARY_REDIRECT: return "Temporary Redirect";
        case BAD_REQUEST: return "Bad Request";
        case UNAUTHORIZED: return "Unauthorized";
        case FORBIDDEN: return "Forbidden";
        case NOT_FOUND: return "Not Found";
        case CONFLICT: return "Conflict";
        case GONE: return "Gone";
        case PRECONDITION_FAILED: return "Precondition Failed";
        case UNSUPPORTED_MEDIA_TYPE: return "Unsupported Media Type";
        case INTERNAL_SERVER_ERROR: return "Internal Server Error";
        case NOT_IMPLEMENTED: return "Not Implemented";
        case MISDIRECTED_REQUEST : return "Misdirected Request";
        case PRECONDITION_REQUIRED: return "Precondition Required";
        case TOO_MANY_REQUESTS: return "Too Many Requests";
        case REQUEST_ENTITY_TOO_LARGE: return "Request Entity Too Large";
        default: return "" + code;
        }
    }

    int code;
    Object data;

    public ResourceException(int code) {
        this(code, new ResourceError().code(code).message(codeToString(code)));
    }

    public ResourceException(int code, Object data) {
        super("ResourceException (" + code + "): " + data);
        this.code = code;
        this.data = data;
    }

    public int getCode() {
        return code;
    }

    public Object getData() {
        return data;
    }

    public <T> T getData(Class<T> cl) {
        return cl.cast(data);
    }

}
`
func GetUserDefinedTypeAnnotations(userDefinedType rdl.TypeRef, schemaTypes []*rdl.Type) map[rdl.ExtendedAnnotation]string {
	for _, schemaType := range schemaTypes {
		switch schemaType.Variant {
		case rdl.TypeVariantStructTypeDef:
			if string(userDefinedType) == string(schemaType.StructTypeDef.Name) {
				return schemaType.StructTypeDef.Annotations
			}
		case rdl.TypeVariantStringTypeDef:
			if string(userDefinedType) == string(schemaType.StringTypeDef.Name) {
				return schemaType.StringTypeDef.Annotations
			}
		case rdl.TypeVariantMapTypeDef:
			if string(userDefinedType) == string(schemaType.MapTypeDef.Name) {
				return schemaType.MapTypeDef.Annotations
			}
		case rdl.TypeVariantArrayTypeDef:
			if string(userDefinedType) == string(schemaType.ArrayTypeDef.Name) {
				return schemaType.ArrayTypeDef.Annotations
			}
		case rdl.TypeVariantBytesTypeDef:
			if string(userDefinedType) == string(schemaType.BytesTypeDef.Name) {
				return schemaType.BytesTypeDef.Annotations
			}
		case rdl.TypeVariantNumberTypeDef:
			if string(userDefinedType) == string(schemaType.NumberTypeDef.Name) {
				return schemaType.NumberTypeDef.Annotations
			}
		case rdl.TypeVariantUnionTypeDef:
			if string(userDefinedType) == string(schemaType.UnionTypeDef.Name) {
				return schemaType.UnionTypeDef.Annotations
			}
		}
	}
	return make(map[rdl.ExtendedAnnotation]string, 0)
}

func JavaType(reg rdl.TypeRegistry, rdlType rdl.TypeRef, optional bool, items rdl.TypeRef, keys rdl.TypeRef) string {
	t := reg.FindType(rdlType)
	if t == nil || t.Variant == 0 {
		panic("Cannot find type '" + rdlType + "'")
	}
	bt := reg.BaseType(t)
	switch bt {
	case rdl.BaseTypeAny:
		return "Object"
	case rdl.BaseTypeString:
		return "String"
	case rdl.BaseTypeSymbol, rdl.BaseTypeTimestamp, rdl.BaseTypeUUID:
		return "String"
	case rdl.BaseTypeBool:
		if optional {
			return "Boolean"
		}
		return "boolean"
	case rdl.BaseTypeInt8:
		if optional {
			return "Byte"
		}
		return "byte"
	case rdl.BaseTypeInt16:
		if optional {
			return "Short"
		}
		return "short"
	case rdl.BaseTypeInt32:
		if optional {
			return "Integer"
		}
		return "int"
	case rdl.BaseTypeInt64:
		if optional {
			return "Long"
		}
		return "long"
	case rdl.BaseTypeFloat32:
		if optional {
			return "Float"
		}
		return "float"
	case rdl.BaseTypeFloat64:
		if optional {
			return "Double"
		}
		return "double"
	case rdl.BaseTypeArray:
		i := rdl.TypeRef("Any")
		switch t.Variant {
		case rdl.TypeVariantArrayTypeDef:
			i = t.ArrayTypeDef.Items
		default:
			if items != "" && items != "Any" {
				i = items
			}
		}
		gitems := JavaType(reg, i, false, "", "")
		//return gitems + "[]" //if arrays, not lists
		return "List<" + gitems + ">"
	case rdl.BaseTypeMap:
		k := rdl.TypeRef("Any")
		i := rdl.TypeRef("Any")
		switch t.Variant {
		case rdl.TypeVariantMapTypeDef:
			k = t.MapTypeDef.Keys
			i = t.MapTypeDef.Items
		default:
			if keys != "" && keys != "Any" {
				k = keys
			}
			if items != "" && keys != "Any" {
				i = items
			}
		}
		gkeys := JavaType(reg, k, false, "", "")
		gitems := JavaType(reg, i, false, "", "")
		return "Map<" + gkeys + "," + gitems + ">"
	case rdl.BaseTypeStruct:
		switch t.Variant {
		case rdl.TypeVariantStructTypeDef:
			if t.StructTypeDef.Name == "Struct" {
				return "Object"
			}
		}
		return string(rdlType)
	default:
		return string(rdlType)
	}
}
<commit_msg>remove camelSnakeToKebab<commit_after>// Copyright 2016 Yahoo Inc.
// Licensed under the terms of the Apache license. Please see LICENSE.md file distributed with this work for terms.

package utils

import (
	"fmt"
	"github.com/ardielle/ardielle-go/rdl"
	"io"
	"os"
	"strings"
	"text/template"
)

func JavaGenerationHeader(banner string) string {
	return fmt.Sprintf("%s// Please DO NOT edit directly; changes could be overwritten.\n//", javaGenerationBanner(banner))
}

func JavaGenerationOrigHeader(banner string) string {
	return fmt.Sprintf("%s// WILL NOT be auto-generated if file has already existed.\n//", javaGenerationBanner(banner));
}

func javaGenerationBanner(banner string) string {
	return fmt.Sprintf("//\n// This file is generated by %s\n", banner)
}

func JavaGenerationPackage(schema *rdl.Schema, namespace string) string {
	return JavaGenerationOrigPackage(schema, namespace) + ".parsec_generated"
}

func JavaGenerationOrigPackage(schema *rdl.Schema, namespace string) string {
	if namespace != "" {
		return namespace
	}
	return string(schema.Namespace)
}

func JavaGenerationRootPath(schema *rdl.Schema, basePath string) string {
	if basePath != "" {
		if schema.Version != nil {
			if basePath != "/" {
				return fmt.Sprintf("%s/v%d", basePath, *schema.Version)
			}
			return fmt.Sprintf("/v%d", *schema.Version)
		}
		return basePath
	} else if schema.Name != "" {
		if schema.Version != nil {
			return fmt.Sprintf("/%s/v%d", string(schema.Name), *schema.Version)
		} else {
			return fmt.Sprintf("/%s", string(schema.Name))
		}
	}

	return "/"
}

func JavaGenerationDir(outdir string, schema *rdl.Schema, namespace string) (string, error) {
        return _javaGenerationDir(outdir, schema, "./target/generated-sources/java", JavaGenerationPackage(schema, namespace))
}

func JavaGenerationSourceDir(schema *rdl.Schema, namespace string) (string, error) {
        return _javaGenerationDir("", schema, "./src/main/java", JavaGenerationOrigPackage(schema, namespace))
}

func _javaGenerationDir(outdir string, schema *rdl.Schema, defaultDir string, pack string) (string, error) {
	dir := outdir
	if dir == "" {
		dir = defaultDir
	}
	//pack := javaGenerationPackage(schema)
	if pack != "" {
		dir += "/" + strings.Replace(pack, ".", "/", -1)
	}
	_, err := os.Stat(dir)
	if err != nil {
		err = os.MkdirAll(dir, 0755)
	}
	return dir, err
}

func JavaGenerateResourceError(schema *rdl.Schema, writer io.Writer, namespace string) error {
	return _javaGenerateTemplate(schema, writer, javaResourceErrorTemplate, namespace)
}

func JavaGenerateParsecResourceError(schema *rdl.Schema, writer io.Writer, namespace string) error {
	return _javaGenerateTemplate(schema, writer, javaParsecResourceErrorTemplate, namespace)
}

func JavaGenerateParsecErrorBody(schema *rdl.Schema, writer io.Writer, namespace string) error {
	return _javaGenerateTemplate(schema, writer, javaParsecErrorBodyTemplate, namespace)
}

func JavaGenerateParsecErrorDetail(schema *rdl.Schema, writer io.Writer, namespace string) error {
	return _javaGenerateTemplate(schema, writer, javaParsecErrorDetailTemplate, namespace)
}

func _javaGenerateTemplate(schema *rdl.Schema, writer io.Writer, content string, namespace string) error {
	funcMap := template.FuncMap{
		"package": func() string {
			s := JavaGenerationPackage(schema, namespace)
			if s == "" {
				return s
			}
			return "package " + s + ";\n"
		},
	}
	t := template.Must(template.New("util").Funcs(funcMap).Parse(content))
	return t.Execute(writer, schema)
}

const javaResourceErrorTemplate = `{{package}}
public class ResourceError {

    public int code;
    public String message;

    public ResourceError code(int code) {
        this.code = code;
        return this;
    }

    public ResourceError message(String message) {
        this.message = message;
        return this;
    }

    public String toString() {
        return "{code: " + code + ", message: \"" + message + "\"}";
    }

}
`

const javaParsecResourceErrorTemplate = `{{package}}
public final class ParsecResourceError implements java.io.Serializable {

    private ParsecErrorBody error;

    public ParsecResourceError() { }

    public ParsecErrorBody getError() { return error; }

    public ParsecResourceError setError(ParsecErrorBody error) { this.error = error; return this; }
}
`

const javaParsecErrorBodyTemplate = `{{package}}
import java.util.List;

public final class ParsecErrorBody implements java.io.Serializable {

    private Integer code;
    private String message;

    private List<ParsecErrorDetail> detail;

    public ParsecErrorBody() { }

    public Integer getCode() { return code; }

    public String getMessage() { return message; }

    public List<ParsecErrorDetail> getDetail() { return detail; }

    public ParsecErrorBody setCode(Integer code) { this.code = code; return this; }

    public ParsecErrorBody setMessage(String message) { this.message = message; return this; }

    public ParsecErrorBody setDetail(List<ParsecErrorDetail> detail) { this.detail = detail; return this; }
}
`

const javaParsecErrorDetailTemplate = `{{package}}
public final class ParsecErrorDetail implements java.io.Serializable {

    private String message;

    private String invalidValue;

    public ParsecErrorDetail() { }

    public String getMessage() { return message; }

    public String getInvalidValue() { return invalidValue; }

    public ParsecErrorDetail setMessage(String message) { this.message = message; return this; }

    public ParsecErrorDetail setInvalidValue(String invalidValue) { this.invalidValue = invalidValue; return this; }
}
`

func JavaGenerateResourceException(schema *rdl.Schema, writer io.Writer, namespace string) error {
	return _javaGenerateTemplate(schema, writer, javaResourceExceptionTemplate, namespace)
}

const javaResourceExceptionTemplate = `{{package}}
public class ResourceException extends RuntimeException {
    public final static int OK = 200;
    public final static int CREATED = 201;
    public final static int ACCEPTED = 202;
    public final static int NO_CONTENT = 204;
    public final static int MOVED_PERMANENTLY = 301;
    public final static int FOUND = 302;
    public final static int SEE_OTHER = 303;
    public final static int NOT_MODIFIED = 304;
    public final static int TEMPORARY_REDIRECT = 307;
    public final static int BAD_REQUEST = 400;
    public final static int UNAUTHORIZED = 401;
    public final static int FORBIDDEN = 403;
    public final static int NOT_FOUND = 404;
    public final static int CONFLICT = 409;
    public final static int GONE = 410;
    public final static int PRECONDITION_FAILED = 412;
    public final static int REQUEST_ENTITY_TOO_LARGE = 413;
    public final static int UNSUPPORTED_MEDIA_TYPE = 415;
    public final static int MISDIRECTED_REQUEST = 421;
    public final static int PRECONDITION_REQUIRED = 428;
    public final static int TOO_MANY_REQUESTS = 429;

    public final static int INTERNAL_SERVER_ERROR = 500;
    public final static int NOT_IMPLEMENTED = 501;

    public final static int SERVICE_UNAVAILABLE = 503;

    public static String codeToString(int code) {
        switch (code) {
        case OK: return "OK";
        case CREATED: return "Created";
        case ACCEPTED: return "Accepted";
        case NO_CONTENT: return "No Content";
        case MOVED_PERMANENTLY: return "Moved Permanently";
        case FOUND: return "Found";
        case SEE_OTHER: return "See Other";
        case NOT_MODIFIED: return "Not Modified";
        case TEMPORARY_REDIRECT: return "Temporary Redirect";
        case BAD_REQUEST: return "Bad Request";
        case UNAUTHORIZED: return "Unauthorized";
        case FORBIDDEN: return "Forbidden";
        case NOT_FOUND: return "Not Found";
        case CONFLICT: return "Conflict";
        case GONE: return "Gone";
        case PRECONDITION_FAILED: return "Precondition Failed";
        case UNSUPPORTED_MEDIA_TYPE: return "Unsupported Media Type";
        case INTERNAL_SERVER_ERROR: return "Internal Server Error";
        case NOT_IMPLEMENTED: return "Not Implemented";
        case MISDIRECTED_REQUEST : return "Misdirected Request";
        case PRECONDITION_REQUIRED: return "Precondition Required";
        case TOO_MANY_REQUESTS: return "Too Many Requests";
        case REQUEST_ENTITY_TOO_LARGE: return "Request Entity Too Large";
        default: return "" + code;
        }
    }

    int code;
    Object data;

    public ResourceException(int code) {
        this(code, new ResourceError().code(code).message(codeToString(code)));
    }

    public ResourceException(int code, Object data) {
        super("ResourceException (" + code + "): " + data);
        this.code = code;
        this.data = data;
    }

    public int getCode() {
        return code;
    }

    public Object getData() {
        return data;
    }

    public <T> T getData(Class<T> cl) {
        return cl.cast(data);
    }

}
`
func GetUserDefinedTypeAnnotations(userDefinedType rdl.TypeRef, schemaTypes []*rdl.Type) map[rdl.ExtendedAnnotation]string {
	for _, schemaType := range schemaTypes {
		switch schemaType.Variant {
		case rdl.TypeVariantStructTypeDef:
			if string(userDefinedType) == string(schemaType.StructTypeDef.Name) {
				return schemaType.StructTypeDef.Annotations
			}
		case rdl.TypeVariantStringTypeDef:
			if string(userDefinedType) == string(schemaType.StringTypeDef.Name) {
				return schemaType.StringTypeDef.Annotations
			}
		case rdl.TypeVariantMapTypeDef:
			if string(userDefinedType) == string(schemaType.MapTypeDef.Name) {
				return schemaType.MapTypeDef.Annotations
			}
		case rdl.TypeVariantArrayTypeDef:
			if string(userDefinedType) == string(schemaType.ArrayTypeDef.Name) {
				return schemaType.ArrayTypeDef.Annotations
			}
		case rdl.TypeVariantBytesTypeDef:
			if string(userDefinedType) == string(schemaType.BytesTypeDef.Name) {
				return schemaType.BytesTypeDef.Annotations
			}
		case rdl.TypeVariantNumberTypeDef:
			if string(userDefinedType) == string(schemaType.NumberTypeDef.Name) {
				return schemaType.NumberTypeDef.Annotations
			}
		case rdl.TypeVariantUnionTypeDef:
			if string(userDefinedType) == string(schemaType.UnionTypeDef.Name) {
				return schemaType.UnionTypeDef.Annotations
			}
		}
	}
	return make(map[rdl.ExtendedAnnotation]string, 0)
}

func JavaType(reg rdl.TypeRegistry, rdlType rdl.TypeRef, optional bool, items rdl.TypeRef, keys rdl.TypeRef) string {
	t := reg.FindType(rdlType)
	if t == nil || t.Variant == 0 {
		panic("Cannot find type '" + rdlType + "'")
	}
	bt := reg.BaseType(t)
	switch bt {
	case rdl.BaseTypeAny:
		return "Object"
	case rdl.BaseTypeString:
		return "String"
	case rdl.BaseTypeSymbol, rdl.BaseTypeTimestamp, rdl.BaseTypeUUID:
		return "String"
	case rdl.BaseTypeBool:
		if optional {
			return "Boolean"
		}
		return "boolean"
	case rdl.BaseTypeInt8:
		if optional {
			return "Byte"
		}
		return "byte"
	case rdl.BaseTypeInt16:
		if optional {
			return "Short"
		}
		return "short"
	case rdl.BaseTypeInt32:
		if optional {
			return "Integer"
		}
		return "int"
	case rdl.BaseTypeInt64:
		if optional {
			return "Long"
		}
		return "long"
	case rdl.BaseTypeFloat32:
		if optional {
			return "Float"
		}
		return "float"
	case rdl.BaseTypeFloat64:
		if optional {
			return "Double"
		}
		return "double"
	case rdl.BaseTypeArray:
		i := rdl.TypeRef("Any")
		switch t.Variant {
		case rdl.TypeVariantArrayTypeDef:
			i = t.ArrayTypeDef.Items
		default:
			if items != "" && items != "Any" {
				i = items
			}
		}
		gitems := JavaType(reg, i, false, "", "")
		//return gitems + "[]" //if arrays, not lists
		return "List<" + gitems + ">"
	case rdl.BaseTypeMap:
		k := rdl.TypeRef("Any")
		i := rdl.TypeRef("Any")
		switch t.Variant {
		case rdl.TypeVariantMapTypeDef:
			k = t.MapTypeDef.Keys
			i = t.MapTypeDef.Items
		default:
			if keys != "" && keys != "Any" {
				k = keys
			}
			if items != "" && keys != "Any" {
				i = items
			}
		}
		gkeys := JavaType(reg, k, false, "", "")
		gitems := JavaType(reg, i, false, "", "")
		return "Map<" + gkeys + "," + gitems + ">"
	case rdl.BaseTypeStruct:
		switch t.Variant {
		case rdl.TypeVariantStructTypeDef:
			if t.StructTypeDef.Name == "Struct" {
				return "Object"
			}
		}
		return string(rdlType)
	default:
		return string(rdlType)
	}
}
<|endoftext|>


<commit_before>package printer

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"io/ioutil"
	"strconv"

	"github.com/davyxu/tabtoy/v2/i18n"
	"github.com/davyxu/tabtoy/v2/model"
	"os"
	"path/filepath"
)

type Stream struct {
	buf bytes.Buffer
}

func (self *Stream) Len() int {
	return self.buf.Len()
}

func (self *Stream) Buffer() *bytes.Buffer {
	return &self.buf
}

func (self *Stream) WriteBytes(b []byte) {
	self.buf.Write(b)
}

func (self *Stream) Printf(format string, args ...interface{}) {
	self.buf.WriteString(fmt.Sprintf(format, args...))
}

func (self *Stream) WriteFile(outfile string) error {

	// 自动创建目录
	os.MkdirAll(filepath.Dir(outfile), 666)

	err := ioutil.WriteFile(outfile, self.buf.Bytes(), 0666)
	if err != nil {
		log.Errorf("%s, %v", i18n.String(i18n.Printer_OpenWriteOutputFileFailed), err.Error())
		return err
	}

	return nil
}

func (self *Stream) WriteInt32(v int32) {

	binary.Write(&self.buf, binary.LittleEndian, v)
}

func (self *Stream) WriteString(v string) {
	rawStr := []byte(v)

	binary.Write(&self.buf, binary.LittleEndian, int32(len(rawStr)))

	binary.Write(&self.buf, binary.LittleEndian, rawStr)
}

func (self *Stream) WriteNodeValue(ft model.FieldType, value *model.Node) {

	switch ft {
	case model.FieldType_Int32:
		v, _ := strconv.ParseInt(value.Value, 10, 32)
		binary.Write(&self.buf, binary.LittleEndian, int32(v))
	case model.FieldType_UInt32:
		v, _ := strconv.ParseUint(value.Value, 10, 32)

		binary.Write(&self.buf, binary.LittleEndian, uint32(v))
	case model.FieldType_Int64:
		v, _ := strconv.ParseInt(value.Value, 10, 64)

		binary.Write(&self.buf, binary.LittleEndian, int64(v))
	case model.FieldType_UInt64:
		v, _ := strconv.ParseUint(value.Value, 10, 64)

		binary.Write(&self.buf, binary.LittleEndian, uint64(v))
	case model.FieldType_Float:
		v, _ := strconv.ParseFloat(value.Value, 32)

		binary.Write(&self.buf, binary.LittleEndian, float32(v))
	case model.FieldType_Bool:
		v, _ := strconv.ParseBool(value.Value)
		boolByte := []byte{0}
		if v {
			boolByte = []byte{1}
		}
		binary.Write(&self.buf, binary.LittleEndian, boolByte)
	case model.FieldType_String:
		self.WriteString(value.Value)
	case model.FieldType_Enum:
		binary.Write(&self.buf, binary.LittleEndian, value.EnumValue)
	default:
		panic("unsupport type" + model.FieldTypeToString(ft))
	}

}

func NewStream() *Stream {
	return &Stream{}
}
<commit_msg>修改: 自动生成目录的权限<commit_after>package printer

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"io/ioutil"
	"strconv"

	"github.com/davyxu/tabtoy/v2/i18n"
	"github.com/davyxu/tabtoy/v2/model"
	"os"
	"path/filepath"
)

type Stream struct {
	buf bytes.Buffer
}

func (self *Stream) Len() int {
	return self.buf.Len()
}

func (self *Stream) Buffer() *bytes.Buffer {
	return &self.buf
}

func (self *Stream) WriteBytes(b []byte) {
	self.buf.Write(b)
}

func (self *Stream) Printf(format string, args ...interface{}) {
	self.buf.WriteString(fmt.Sprintf(format, args...))
}

func (self *Stream) WriteFile(outfile string) error {

	// 自动创建目录
	os.MkdirAll(filepath.Dir(outfile), 0755)

	err := ioutil.WriteFile(outfile, self.buf.Bytes(), 0666)
	if err != nil {
		log.Errorf("%s, %v", i18n.String(i18n.Printer_OpenWriteOutputFileFailed), err.Error())
		return err
	}

	return nil
}

func (self *Stream) WriteInt32(v int32) {

	binary.Write(&self.buf, binary.LittleEndian, v)
}

func (self *Stream) WriteString(v string) {
	rawStr := []byte(v)

	binary.Write(&self.buf, binary.LittleEndian, int32(len(rawStr)))

	binary.Write(&self.buf, binary.LittleEndian, rawStr)
}

func (self *Stream) WriteNodeValue(ft model.FieldType, value *model.Node) {

	switch ft {
	case model.FieldType_Int32:
		v, _ := strconv.ParseInt(value.Value, 10, 32)
		binary.Write(&self.buf, binary.LittleEndian, int32(v))
	case model.FieldType_UInt32:
		v, _ := strconv.ParseUint(value.Value, 10, 32)

		binary.Write(&self.buf, binary.LittleEndian, uint32(v))
	case model.FieldType_Int64:
		v, _ := strconv.ParseInt(value.Value, 10, 64)

		binary.Write(&self.buf, binary.LittleEndian, int64(v))
	case model.FieldType_UInt64:
		v, _ := strconv.ParseUint(value.Value, 10, 64)

		binary.Write(&self.buf, binary.LittleEndian, uint64(v))
	case model.FieldType_Float:
		v, _ := strconv.ParseFloat(value.Value, 32)

		binary.Write(&self.buf, binary.LittleEndian, float32(v))
	case model.FieldType_Bool:
		v, _ := strconv.ParseBool(value.Value)
		boolByte := []byte{0}
		if v {
			boolByte = []byte{1}
		}
		binary.Write(&self.buf, binary.LittleEndian, boolByte)
	case model.FieldType_String:
		self.WriteString(value.Value)
	case model.FieldType_Enum:
		binary.Write(&self.buf, binary.LittleEndian, value.EnumValue)
	default:
		panic("unsupport type" + model.FieldTypeToString(ft))
	}

}

func NewStream() *Stream {
	return &Stream{}
}
<|endoftext|>


<commit_before>// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package tail implements "tail -F" functionality following rotated logs
package tail

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"sync"
	"time"

	"github.com/golang/glog"
	"golang.org/x/exp/inotify"
)

const (
	readerStateOpening = 1 << iota
	readerStateOpened
	readerStateError
)

type Tail struct {
	reader      *bufio.Reader
	readerState int
	readerLock  sync.Mutex
	filename    string
	file        *os.File
	stop        chan bool
	watcher     *inotify.Watcher
}

const retryOpenInterval = time.Second
const maxOpenAttempts = 3

// NewTail starts opens the given file and watches it for deletion/rotation
func NewTail(filename string) (*Tail, error) {
	t := &Tail{
		filename: filename,
	}
	var err error
	t.stop = make(chan bool)
	t.watcher, err = inotify.NewWatcher()
	if err != nil {
		return nil, fmt.Errorf("inotify init failed on %s: %v", t.filename, err)
	}
	t.readerState = readerStateOpening
	go t.watchLoop()
	return t, nil
}

// Read implements the io.Reader interface for Tail
func (t *Tail) Read(p []byte) (int, error) {
	t.readerLock.Lock()
	defer t.readerLock.Unlock()
	if t.reader == nil {
		if t.readerState == readerStateOpening {
			return 0, nil
		}
		return 0, fmt.Errorf("can't open log file %s", t.filename)
	}
	return t.reader.Read(p)
}

var _ io.Reader = &Tail{}

// Close stops watching and closes the file
func (t *Tail) Close() {
	close(t.stop)
}

func isEvent(event *inotify.Event, flag uint32) bool {
	return event.Mask&flag == flag
}

func (t *Tail) fileChanged() error {
	for {
		select {
		case event := <-t.watcher.Event:
			// We don't get IN_DELETE because we are holding the file open
			if isEvent(event, inotify.IN_ATTRIB) || isEvent(event, inotify.IN_MOVE_SELF) {
				return nil
			}
		case <-t.stop:
			return fmt.Errorf("watch was cancelled")
		}
	}
}

func (t *Tail) attemptOpen() (err error) {
	t.readerLock.Lock()
	defer t.readerLock.Unlock()
	for attempt := 1; attempt <= maxOpenAttempts; attempt++ {
		glog.V(4).Infof("Opening %s (attempt %d of %d)", t.filename, attempt, maxOpenAttempts)
		t.file, err = os.Open(t.filename)
		if err == nil {
			// TODO: not interested in old events?
			//t.file.Seek(0, os.SEEK_END)
			t.reader = bufio.NewReader(t.file)
			t.readerState = readerStateOpened
			return nil
		}
		select {
		case <-time.After(retryOpenInterval):
		case <-t.stop:
			t.readerState = readerStateError
			return fmt.Errorf("watch was cancelled")
		}
	}
	t.readerState = readerStateError
	return err
}

func (t *Tail) watchLoop() {
	for {
		err := t.watchFile()
		if err != nil {
			glog.Errorf("Tail failed on %s: %v", t.filename, err)
			break
		}
	}
}

func (t *Tail) watchFile() error {
	err := t.attemptOpen()
	if err != nil {
		return err
	}
	defer t.file.Close()
	err = t.watcher.Watch(t.filename)
	if err != nil {
		return err
	}
	defer t.watcher.RemoveWatch(t.filename)
	err = t.fileChanged()
	if err != nil {
		return err
	}
	glog.V(4).Infof("Log file %s moved/deleted", t.filename)
	t.readerLock.Lock()
	defer t.readerLock.Unlock()
	t.readerState = readerStateOpening
	return nil
}
<commit_msg>Cleanup tail util from #1264<commit_after>// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package tail implements "tail -F" functionality following rotated logs
package tail

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"sync"
	"time"

	"github.com/golang/glog"
	"golang.org/x/exp/inotify"
)

type Tail struct {
	reader     *bufio.Reader
	readerErr  error
	readerLock sync.RWMutex
	filename   string
	file       *os.File
	stop       chan bool
	watcher    *inotify.Watcher
}

const retryOpenInterval = time.Second
const maxOpenAttempts = 3

// NewTail starts opens the given file and watches it for deletion/rotation
func NewTail(filename string) (*Tail, error) {
	t := &Tail{
		filename: filename,
	}
	var err error
	t.stop = make(chan bool)
	t.watcher, err = inotify.NewWatcher()
	if err != nil {
		return nil, fmt.Errorf("inotify init failed on %s: %v", t.filename, err)
	}
	go t.watchLoop()
	return t, nil
}

// Read implements the io.Reader interface for Tail
func (t *Tail) Read(p []byte) (int, error) {
	t.readerLock.RLock()
	defer t.readerLock.RUnlock()
	if t.reader == nil || t.readerErr != nil {
		return 0, t.readerErr
	}
	return t.reader.Read(p)
}

var _ io.Reader = &Tail{}

// Close stops watching and closes the file
func (t *Tail) Close() {
	close(t.stop)
}

func isEvent(event *inotify.Event, flag uint32) bool {
	return event.Mask&flag == flag
}

func (t *Tail) fileChanged() error {
	for {
		select {
		case event := <-t.watcher.Event:
			// We don't get IN_DELETE because we are holding the file open
			if isEvent(event, inotify.IN_ATTRIB) || isEvent(event, inotify.IN_MOVE_SELF) {
				return nil
			}
		case <-t.stop:
			return fmt.Errorf("watch was cancelled")
		}
	}
}

func (t *Tail) attemptOpen() error {
	t.readerLock.Lock()
	defer t.readerLock.Unlock()
	t.reader = nil
	t.readerErr = nil
	for attempt := 1; attempt <= maxOpenAttempts; attempt++ {
		glog.V(4).Infof("Opening %s (attempt %d of %d)", t.filename, attempt, maxOpenAttempts)
		var err error
		t.file, err = os.Open(t.filename)
		if err == nil {
			// TODO: not interested in old events?
			//t.file.Seek(0, os.SEEK_END)
			t.reader = bufio.NewReader(t.file)
			return nil
		}
		select {
		case <-time.After(retryOpenInterval):
		case <-t.stop:
			t.readerErr = io.EOF
			return fmt.Errorf("watch was cancelled")
		}
	}
	err := fmt.Errorf("can't open log file %s", t.filename)
	t.readerErr = err
	return err
}

func (t *Tail) watchLoop() {
	for {
		err := t.watchFile()
		if err != nil {
			glog.Errorf("Tail failed on %s: %v", t.filename, err)
			break
		}
	}
}

func (t *Tail) watchFile() error {
	err := t.attemptOpen()
	if err != nil {
		return err
	}
	defer t.file.Close()
	err = t.watcher.Watch(t.filename)
	if err != nil {
		return err
	}
	defer t.watcher.RemoveWatch(t.filename)
	err = t.fileChanged()
	if err != nil {
		return err
	}
	glog.V(4).Infof("Log file %s moved/deleted", t.filename)
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"delay"
	"fmt"
	"rtos"

	"display/eve"
	"display/eve/ft80"

	"stm32/evedci"

	"stm32/hal/dma"
	"stm32/hal/exti"
	"stm32/hal/gpio"
	"stm32/hal/irq"
	"stm32/hal/spi"
	"stm32/hal/system"
	"stm32/hal/system/timer/systick"
)

var dci *evedci.SPI

func init() {
	system.Setup80(0, 0)
	systick.Setup(2e6)

	// GPIO

	gpio.A.EnableClock(true)
	spiport, sck, miso, mosi := gpio.A, gpio.Pin5, gpio.Pin6, gpio.Pin7
	pdn := gpio.A.Pin(9)

	gpio.B.EnableClock(true)
	csn := gpio.B.Pin(6)

	gpio.C.EnableClock(true)
	irqn := gpio.C.Pin(7)

	// EVE SPI

	spiport.Setup(sck|mosi, &gpio.Config{Mode: gpio.Alt, Speed: gpio.High})
	spiport.Setup(miso, &gpio.Config{Mode: gpio.AltIn})
	spiport.SetAltFunc(sck|miso|mosi, gpio.SPI1)
	d := dma.DMA1
	d.EnableClock(true)
	rxdc, txdc := d.Channel(2, 0), d.Channel(3, 0)
	rxdc.SetRequest(dma.DMA1_SPI1)
	txdc.SetRequest(dma.DMA1_SPI1)
	spidrv := spi.NewDriver(spi.SPI1, rxdc, txdc)
	spidrv.P.EnableClock(true)
	rtos.IRQ(irq.SPI1).Enable()
	rtos.IRQ(irq.DMA1_Channel2).Enable()
	rtos.IRQ(irq.DMA1_Channel3).Enable()

	// EVE control lines

	cfg := gpio.Config{Mode: gpio.Out, Speed: gpio.High}
	pdn.Setup(&cfg)
	csn.Setup(&cfg)
	irqn.Setup(&gpio.Config{Mode: gpio.In})
	irqline := exti.Lines(irqn.Mask())
	irqline.Connect(irqn.Port())
	//rtos.IRQ(irq.EXTI9_5).Enable()

	dci = evedci.NewSPI(spidrv, csn, pdn, irqline)
}

const (
	lcdWidth   = 480 // Active width of LCD display
	lcdHeight  = 272 // Active height of LCD display
	lcdHcycle  = 548 // Total number of clocks per line
	lcdHoffset = 43  // Start of active line
	lcdHsync0  = 0   // Start of horizontal sync pulse
	lcdHsync1  = 41  // End of horizontal sync pulse
	lcdVcycle  = 292 // Total number of lines per screen
	lcdVoffset = 12  // Start of active screen
	lcdVsync0  = 0   // Start of vertical sync pulse
	lcdVsync1  = 10  // End of vertical sync pulse
	lcdPclk    = 5   // Pixel Clock
	lcdPclkpol = 1   // Define active edge of PCLK
)

func main() {
	delay.Millisec(200)
	spibus := dci.SPI().P.Bus()
	baudrate := dci.SPI().P.Baudrate(dci.SPI().P.Conf())
	fmt.Printf(
		"\nSPI on %s (%d MHz).\nSPI speed: %d bps.\n",
		spibus, spibus.Clock()/1e6, baudrate,
	)

	// Wakeup from POWERDOWN to STANDBY (PDN must be low min. 20 ms).
	dci.PDN().Set()
	delay.Millisec(20) // Wait 20 ms for internal oscilator and PLL.

	lcd := eve.NewDriver(dci, 32)

	fmt.Print("Init... ")

	// Wakeup from STANDBY to ACTIVE.
	lcd.Cmd(ft80.ACTIVE, 0)

	// Select external 12 MHz oscilator as clock source.
	lcd.Cmd(ft80.CLKEXT, 0)

	if lcd.Reader(ft80.REG_ID).ReadByte() != 0x7c {
		fmt.Printf("Not EVE controller.\n")
		return
	}
	if lcd.Reader(ft80.ROM_CHIPID).ReadWord32() != 0x10008 {
		fmt.Printf("Not FT800 controller.\n")
		return
	}

	check(lcd.Err(false))

	fmt.Print("Configure WQVGA (480x272) display...")

	lcd.Writer(ft80.REG_PWM_DUTY).Write32(0)

	lcd.Writer(ft80.REG_PCLK_POL).Write32(
		lcdPclkpol, // REG_PCLK_POL
		0,          // REG_PCLK
	)

	lcd.Writer(ft80.REG_HCYCLE).Write32(
		lcdHcycle,  // REG_HCYCLE
		lcdHoffset, // REG_HOFFSET
		lcdWidth,   // REG_HSIZE
		lcdHsync0,  // REG_HSYNC0
		lcdHsync1,  // REG_HSYNC1
		lcdVcycle,  // REG_VCYCLE
		lcdVoffset, // REG_VOFFSET
		lcdHeight,  // REG_VSIZE
		lcdVsync0,  // REG_VSYNC0
		lcdVsync1,  // REG_VSYNC1
	)

	check(lcd.Err(false))

	fmt.Print("Write initial display list and enable display...")

	dl := lcd.DL(ft80.RAM_DL)
	dl.ClearColorRGB(0, 0, 0)
	dl.Clear(eve.CST)
	dl.Display()

	// Alternative, method:
	//
	//  lcd.Writer(ft80.RAM_DL).Write32(
	//  	eve.CLEAR_COLOR_RGB,
	//  	eve.CLEAR|eve.CST,
	//  	eve.DISPLAY,
	//  )

	lcd.Writer(ft80.REG_DLSWAP).Write32(eve.DLSWAP_FRAME)

	gpio := lcd.Reader(ft80.REG_GPIO).ReadWord32()
	lcd.Writer(ft80.REG_GPIO).Write32(gpio | 0x80)
	lcd.Writer(ft80.REG_PCLK).Write32(lcdPclk)

	check(lcd.Err(false))

	dci.SPI().P.SetConf(dci.SPI().P.Conf()&^spi.BR256 | dci.SPI().P.BR(30e6))
	fmt.Printf("SPI set to %d Hz\n", dci.SPI().P.Baudrate(dci.SPI().P.Conf()))

	lcd.Writer(ft80.REG_PWM_DUTY).Write32(100)

	fmt.Print("Testing DL...")

	dl = lcd.DL(ft80.RAM_DL)
	dl.ClearColorRGB(0, 0, 0)
	dl.Clear(eve.CST)
	dl.Begin(eve.POINTS)
	dl.ColorRGB(161, 244, 97)
	dl.PointSize(100 * 16)
	dl.Vertex2F(200*16, 100*16)
	dl.ColorRGB(255, 0, 255)
	dl.PointSize(50 * 16)
	dl.Vertex2F(300*16, 200*16)
	dl.Display()

	for {
		lcd.Writer(ft80.REG_DLSWAP).Write32(eve.DLSWAP_FRAME)
		check(lcd.Err(false))
		delay.Millisec(500)
	}
}

func check(err error) {
	if err == nil {
		fmt.Printf(" OK\n")
		return
	}
	fmt.Printf(" %v\n", err)
	for {
	}
}

func lcdSPIISR() {
	dci.SPI().ISR()
}

func lcdRxDMAISR() {
	dci.SPI().DMAISR(dci.SPI().RxDMA)
}

func lcdTxDMAISR() {
	dci.SPI().DMAISR(dci.SPI().TxDMA)
}

//emgo:const
//c:__attribute__((section(".ISRs")))
var ISRs = [...]func(){
	irq.SPI1:          lcdSPIISR,
	irq.DMA1_Channel2: lcdRxDMAISR,
	irq.DMA1_Channel3: lcdTxDMAISR,
}
<commit_msg>examples/nucleo-l476rg/ft800: Test pixmaps.<commit_after>package main

import (
	"delay"
	"fmt"
	"math/rand"
	"rtos"

	"display/eve"
	"display/eve/ft80"

	"stm32/evedci"

	"stm32/hal/dma"
	"stm32/hal/exti"
	"stm32/hal/gpio"
	"stm32/hal/irq"
	"stm32/hal/spi"
	"stm32/hal/system"
	"stm32/hal/system/timer/systick"
)

var dci *evedci.SPI

func init() {
	system.Setup80(0, 0)
	systick.Setup(2e6)

	// GPIO

	gpio.A.EnableClock(true)
	spiport, sck, miso, mosi := gpio.A, gpio.Pin5, gpio.Pin6, gpio.Pin7
	pdn := gpio.A.Pin(9)

	gpio.B.EnableClock(true)
	csn := gpio.B.Pin(6)

	gpio.C.EnableClock(true)
	irqn := gpio.C.Pin(7)

	// EVE SPI

	spiport.Setup(sck|mosi, &gpio.Config{Mode: gpio.Alt, Speed: gpio.High})
	spiport.Setup(miso, &gpio.Config{Mode: gpio.AltIn})
	spiport.SetAltFunc(sck|miso|mosi, gpio.SPI1)
	d := dma.DMA1
	d.EnableClock(true)
	rxdc, txdc := d.Channel(2, 0), d.Channel(3, 0)
	rxdc.SetRequest(dma.DMA1_SPI1)
	txdc.SetRequest(dma.DMA1_SPI1)
	spidrv := spi.NewDriver(spi.SPI1, rxdc, txdc)
	spidrv.P.EnableClock(true)
	rtos.IRQ(irq.SPI1).Enable()
	rtos.IRQ(irq.DMA1_Channel2).Enable()
	rtos.IRQ(irq.DMA1_Channel3).Enable()

	// EVE control lines

	cfg := gpio.Config{Mode: gpio.Out, Speed: gpio.High}
	pdn.Setup(&cfg)
	csn.Setup(&cfg)
	irqn.Setup(&gpio.Config{Mode: gpio.In})
	irqline := exti.Lines(irqn.Mask())
	irqline.Connect(irqn.Port())
	//rtos.IRQ(irq.EXTI9_5).Enable()

	dci = evedci.NewSPI(spidrv, csn, pdn, irqline)
}

const (
	lcdWidth   = 480 // Active width of LCD display
	lcdHeight  = 272 // Active height of LCD display
	lcdHcycle  = 548 // Total number of clocks per line
	lcdHoffset = 43  // Start of active line
	lcdHsync0  = 0   // Start of horizontal sync pulse
	lcdHsync1  = 41  // End of horizontal sync pulse
	lcdVcycle  = 292 // Total number of lines per screen
	lcdVoffset = 12  // Start of active screen
	lcdVsync0  = 0   // Start of vertical sync pulse
	lcdVsync1  = 10  // End of vertical sync pulse
	lcdPclk    = 5   // Pixel Clock
	lcdPclkpol = 1   // Define active edge of PCLK
)

func main() {
	delay.Millisec(200)
	spibus := dci.SPI().P.Bus()
	baudrate := dci.SPI().P.Baudrate(dci.SPI().P.Conf())
	fmt.Printf(
		"\nSPI on %s (%d MHz).\nSPI speed: %d bps.\n",
		spibus, spibus.Clock()/1e6, baudrate,
	)

	// Wakeup from POWERDOWN to STANDBY (PDN must be low min. 20 ms).
	dci.PDN().Set()
	delay.Millisec(20) // Wait 20 ms for internal oscilator and PLL.

	lcd := eve.NewDriver(dci, 32)

	fmt.Print("Init... ")

	// Wakeup from STANDBY to ACTIVE.
	lcd.Cmd(ft80.ACTIVE, 0)

	// Select external 12 MHz oscilator as clock source.
	lcd.Cmd(ft80.CLKEXT, 0)

	if lcd.Reader(ft80.REG_ID).ReadByte() != 0x7c {
		fmt.Printf("Not EVE controller.\n")
		return
	}
	if lcd.Reader(ft80.ROM_CHIPID).ReadWord32() != 0x10008 {
		fmt.Printf("Not FT800 controller.\n")
		return
	}

	check(lcd.Err(false))

	fmt.Print("Configure WQVGA (480x272) display...")

	lcd.Writer(ft80.REG_PWM_DUTY).Write32(0)

	lcd.Writer(ft80.REG_PCLK_POL).Write32(
		lcdPclkpol, // REG_PCLK_POL
		0,          // REG_PCLK
	)

	lcd.Writer(ft80.REG_HCYCLE).Write32(
		lcdHcycle,  // REG_HCYCLE
		lcdHoffset, // REG_HOFFSET
		lcdWidth,   // REG_HSIZE
		lcdHsync0,  // REG_HSYNC0
		lcdHsync1,  // REG_HSYNC1
		lcdVcycle,  // REG_VCYCLE
		lcdVoffset, // REG_VOFFSET
		lcdHeight,  // REG_VSIZE
		lcdVsync0,  // REG_VSYNC0
		lcdVsync1,  // REG_VSYNC1
	)

	check(lcd.Err(false))

	fmt.Print("Write initial display list and enable display...")

	dl := lcd.DL(ft80.RAM_DL)
	dl.ClearColorRGB(0, 0, 0)
	dl.Clear(eve.CST)
	dl.Display()

	// Alternative, method:
	//
	//  lcd.Writer(ft80.RAM_DL).Write32(
	//  	eve.CLEAR_COLOR_RGB,
	//  	eve.CLEAR|eve.CST,
	//  	eve.DISPLAY,
	//  )

	lcd.Writer(ft80.REG_DLSWAP).Write32(eve.DLSWAP_FRAME)

	gpio := lcd.Reader(ft80.REG_GPIO).ReadWord32()
	lcd.Writer(ft80.REG_GPIO).Write32(gpio | 0x80)
	lcd.Writer(ft80.REG_PCLK).Write32(lcdPclk)

	check(lcd.Err(false))

	delay.Millisec(20) // Clock switching is synchronised to VSYNC.

	dci.SPI().P.SetConf(dci.SPI().P.Conf()&^spi.BR256 | dci.SPI().P.BR(30e6))
	fmt.Printf("SPI set to %d Hz\n", dci.SPI().P.Baudrate(dci.SPI().P.Conf()))

	lcd.Writer(ft80.REG_PWM_DUTY).Write32(100)

	fmt.Print("Testing DL...")

	w := lcd.Writer(ft80.RAM_G)
	img := &Tomato_DXT1_C0_Data_Raw
	for i := 0; i < len(img); i += 4 {
		w.Write32(
			uint32(img[i]) | uint32(img[i+1])<<8 |
				uint32(img[i+2])<<16 | uint32(img[i+3])<<24,
		)
	}

	dl = lcd.DL(ft80.RAM_DL)

	dl.BitmapHandle(1)
	dl.BitmapSource(ft80.RAM_G)
	dl.BitmapLayout(eve.RGB565, 64, 32)
	dl.BitmapSize(0, 32, 32)

	dl.ClearColorRGB(0, 0, 0)
	dl.Clear(eve.CST)

	dl.Begin(eve.POINTS)
	dl.ColorRGB(161, 244, 97)
	dl.PointSize(100 * 16)
	dl.Vertex2F(200*16, 100*16)
	dl.ColorRGB(255, 0, 255)
	dl.PointSize(50 * 16)
	dl.Vertex2F(300*16, 200*16)

	dl.Begin(eve.BITMAPS)
	dl.ColorA(150)
	dl.BitmapHandle(1)

	var rnd rand.XorShift64
	rnd.Seed(1)
	for i := 0; i < 100; i++ {
		v := rnd.Uint64()
		vl := uint32(v)
		vh := uint32(v >> 32)
		dl.Vertex2F(int(vl%(480-32)*16), int(vh%(272-32)*16))
	}
	dl.Display()

	lcd.Writer(ft80.REG_DLSWAP).Write32(eve.DLSWAP_FRAME)
	check(lcd.Err(false))
}

func check(err error) {
	if err == nil {
		fmt.Printf(" OK\n")
		return
	}
	fmt.Printf(" %v\n", err)
	for {
	}
}

func lcdSPIISR() {
	dci.SPI().ISR()
}

func lcdRxDMAISR() {
	dci.SPI().DMAISR(dci.SPI().RxDMA)
}

func lcdTxDMAISR() {
	dci.SPI().DMAISR(dci.SPI().TxDMA)
}

//emgo:const
//c:__attribute__((section(".ISRs")))
var ISRs = [...]func(){
	irq.SPI1:          lcdSPIISR,
	irq.DMA1_Channel2: lcdRxDMAISR,
	irq.DMA1_Channel3: lcdTxDMAISR,
}
<|endoftext|>


<commit_before>// Copyright 2016 The Gosl Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package chk

import (
	"fmt"
	"testing"
)

func Test_IntAssert(tst *testing.T) {

	//Verbose = true
	defer func() {
		if err := recover(); err != nil {
			if Verbose {
				fmt.Printf("OK, caught the following message:\n\n\t%v\n", err)
			}
		} else {
			tst.Errorf("\n\tTEST FAILED. Assert should have panicked\n")
		}
	}()

	PrintTitle("IntAssert")

	PrintOk("the next error message is")
	IntAssert(2, 1)
}

func Test_DblAssert(tst *testing.T) {

	//Verbose = true
	defer func() {
		if err := recover(); err != nil {
			if Verbose {
				fmt.Printf("OK, caught the following message:\n\n\t%v\n", err)
			}
		} else {
			tst.Errorf("\n\tTEST FAILED. Assert should have panicked\n")
		}
	}()

	PrintTitle("DblAssert")

	PrintOk("the next error message is")
	DblAssert(2, 1)
}

func Test_IntAssertLessthan(tst *testing.T) {

	//Verbose = true
	defer func() {
		if err := recover(); err != nil {
			if Verbose {
				fmt.Printf("OK, caught the following message:\n\n\t%v\n", err)
			}
		} else {
			tst.Errorf("\n\tTEST FAILED. Assert should have panicked\n")
		}
	}()

	PrintTitle("IntAssertLessthan")

	PrintOk("the next error message is")
	IntAssertLessThan(1, 1)
}

func Test_IntAssertLessthanOrEqualTo(tst *testing.T) {

	//Verbose = true
	defer func() {
		if err := recover(); err != nil {
			if Verbose {
				fmt.Printf("OK, caught the following message:\n\n\t%v\n", err)
			}
		} else {
			tst.Errorf("\n\tTEST FAILED. Assert should have panicked\n")
		}
	}()

	PrintTitle("IntAssertLessthanOrEqualTo")

	PrintOk("the next error message is")
	IntAssertLessThanOrEqualTo(2, 1)
}

func Test_StrAssert(tst *testing.T) {

	//Verbose = true
	defer func() {
		if err := recover(); err != nil {
			if Verbose {
				fmt.Printf("OK, caught the following message:\n\n\t%v\n", err)
			}
		} else {
			tst.Errorf("\n\tTEST FAILED. Assert should have panicked\n")
		}
	}()

	PrintTitle("StrAssert")

	PrintOk("the next error message is")
	StrAssert("rambo", "terminator")
}

func myfunction() {}

func Test_FcnName(tst *testing.T) {

	//Verbose = true
	PrintTitle("FcnName")

	name := GetFunctionName(myfunction)
	if Verbose {
		fmt.Printf("name = %v\n", name)
	}
	if name != "github.com/cpmech/gosl/chk.myfunction" {
		tst.Errorf("function name is incorrect\n")
	}

	fcn := func() {}
	name = GetFunctionName(fcn)
	if Verbose {
		fmt.Printf("name = %v\n", name)
	}
	//if !strings.HasPrefix(name, "github.com/cpmech/gosl/chk.Test_FcnName.func") {
	//tst.Errorf("function name is incorrect\n")
	//}
}
<commit_msg>Disable test that checks for function name: it does not work on MacOS<commit_after>// Copyright 2016 The Gosl Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package chk

import (
	"fmt"
	"testing"
)

func Test_IntAssert(tst *testing.T) {

	//Verbose = true
	defer func() {
		if err := recover(); err != nil {
			if Verbose {
				fmt.Printf("OK, caught the following message:\n\n\t%v\n", err)
			}
		} else {
			tst.Errorf("\n\tTEST FAILED. Assert should have panicked\n")
		}
	}()

	PrintTitle("IntAssert")

	PrintOk("the next error message is")
	IntAssert(2, 1)
}

func Test_DblAssert(tst *testing.T) {

	//Verbose = true
	defer func() {
		if err := recover(); err != nil {
			if Verbose {
				fmt.Printf("OK, caught the following message:\n\n\t%v\n", err)
			}
		} else {
			tst.Errorf("\n\tTEST FAILED. Assert should have panicked\n")
		}
	}()

	PrintTitle("DblAssert")

	PrintOk("the next error message is")
	DblAssert(2, 1)
}

func Test_IntAssertLessthan(tst *testing.T) {

	//Verbose = true
	defer func() {
		if err := recover(); err != nil {
			if Verbose {
				fmt.Printf("OK, caught the following message:\n\n\t%v\n", err)
			}
		} else {
			tst.Errorf("\n\tTEST FAILED. Assert should have panicked\n")
		}
	}()

	PrintTitle("IntAssertLessthan")

	PrintOk("the next error message is")
	IntAssertLessThan(1, 1)
}

func Test_IntAssertLessthanOrEqualTo(tst *testing.T) {

	//Verbose = true
	defer func() {
		if err := recover(); err != nil {
			if Verbose {
				fmt.Printf("OK, caught the following message:\n\n\t%v\n", err)
			}
		} else {
			tst.Errorf("\n\tTEST FAILED. Assert should have panicked\n")
		}
	}()

	PrintTitle("IntAssertLessthanOrEqualTo")

	PrintOk("the next error message is")
	IntAssertLessThanOrEqualTo(2, 1)
}

func Test_StrAssert(tst *testing.T) {

	//Verbose = true
	defer func() {
		if err := recover(); err != nil {
			if Verbose {
				fmt.Printf("OK, caught the following message:\n\n\t%v\n", err)
			}
		} else {
			tst.Errorf("\n\tTEST FAILED. Assert should have panicked\n")
		}
	}()

	PrintTitle("StrAssert")

	PrintOk("the next error message is")
	StrAssert("rambo", "terminator")
}

func myfunction() {}

// TODO: this test doesn't work on MacOS
func test_FcnName(tst *testing.T) {

	//Verbose = true
	PrintTitle("FcnName")

	name := GetFunctionName(myfunction)
	if Verbose {
		fmt.Printf("name = %v\n", name)
	}
	if name != "github.com/cpmech/gosl/chk.myfunction" {
		tst.Errorf("function name is incorrect\n")
	}

	fcn := func() {}
	name = GetFunctionName(fcn)
	if Verbose {
		fmt.Printf("name = %v\n", name)
	}
	//if !strings.HasPrefix(name, "github.com/cpmech/gosl/chk.Test_FcnName.func") {
	//tst.Errorf("function name is incorrect\n")
	//}
}
<|endoftext|>


<commit_before>// This file was generated by counterfeiter
package fakes

import (
	"sync"

	"github.com/concourse/fly/eventstream"
	"github.com/concourse/turbine/event"
)

type FakeEventStream struct {
	NextEventStub        func() (event.Event, error)
	nextEventMutex       sync.RWMutex
	nextEventArgsForCall []struct{}
	nextEventReturns struct {
		result1 event.Event
		result2 error
	}
}

func (fake *FakeEventStream) NextEvent() (event.Event, error) {
	fake.nextEventMutex.Lock()
	defer fake.nextEventMutex.Unlock()
	fake.nextEventArgsForCall = append(fake.nextEventArgsForCall, struct{}{})
	if fake.NextEventStub != nil {
		return fake.NextEventStub()
	} else {
		return fake.nextEventReturns.result1, fake.nextEventReturns.result2
	}
}

func (fake *FakeEventStream) NextEventCallCount() int {
	fake.nextEventMutex.RLock()
	defer fake.nextEventMutex.RUnlock()
	return len(fake.nextEventArgsForCall)
}

func (fake *FakeEventStream) NextEventReturns(result1 event.Event, result2 error) {
	fake.NextEventStub = nil
	fake.nextEventReturns = struct {
		result1 event.Event
		result2 error
	}{result1, result2}
}

var _ eventstream.EventStream = new(FakeEventStream)
<commit_msg>go fmt ./...<commit_after>// This file was generated by counterfeiter
package fakes

import (
	"sync"

	"github.com/concourse/fly/eventstream"
	"github.com/concourse/turbine/event"
)

type FakeEventStream struct {
	NextEventStub        func() (event.Event, error)
	nextEventMutex       sync.RWMutex
	nextEventArgsForCall []struct{}
	nextEventReturns     struct {
		result1 event.Event
		result2 error
	}
}

func (fake *FakeEventStream) NextEvent() (event.Event, error) {
	fake.nextEventMutex.Lock()
	defer fake.nextEventMutex.Unlock()
	fake.nextEventArgsForCall = append(fake.nextEventArgsForCall, struct{}{})
	if fake.NextEventStub != nil {
		return fake.NextEventStub()
	} else {
		return fake.nextEventReturns.result1, fake.nextEventReturns.result2
	}
}

func (fake *FakeEventStream) NextEventCallCount() int {
	fake.nextEventMutex.RLock()
	defer fake.nextEventMutex.RUnlock()
	return len(fake.nextEventArgsForCall)
}

func (fake *FakeEventStream) NextEventReturns(result1 event.Event, result2 error) {
	fake.NextEventStub = nil
	fake.nextEventReturns = struct {
		result1 event.Event
		result2 error
	}{result1, result2}
}

var _ eventstream.EventStream = new(FakeEventStream)
<|endoftext|>


<commit_before>package examples

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"testing"

	"github.com/pachyderm/pachyderm/src/client"
	pfsclient "github.com/pachyderm/pachyderm/src/client/pfs"
	"github.com/pachyderm/pachyderm/src/client/pkg/require"
)

func getPachClient(t testing.TB) *client.APIClient {
	client, err := client.NewFromAddress("0.0.0.0:30650")
	require.NoError(t, err)
	return client
}

func TestExampleTensorFlow(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping integration tests in short mode")
	}

	c := getPachClient(t)
	t.Parallel()

	cwd, err := os.Getwd()
	require.NoError(t, err)
	exampleDir := filepath.Join(cwd, "../../../doc/examples/tensor_flow")
	cmd := exec.Command("make", "test")
	cmd.Dir = exampleDir
	_, err = cmd.CombinedOutput()
	require.NoError(t, err)

	commitInfos, err := c.ListCommit(
		[]*pfsclient.Commit{{
			Repo: &pfsclient.Repo{"GoT_scripts"},
		}},
		nil,
		client.CommitTypeRead,
		client.CommitStatusAll,
		false,
	)
	require.NoError(t, err)
	fmt.Printf("commits: %v\n", commitInfos)
	require.Equal(t, 1, len(commitInfos))
	inputCommitID := commitInfos[0].Commit.ID

	// Wait until the GoT_generate job has finished
	commitInfos, err = c.FlushCommit([]*pfsclient.Commit{client.NewCommit("GoT_scripts", inputCommitID)}, nil)
	require.NoError(t, err)
	require.Equal(t, 3, len(commitInfos))

	repos := []interface{}{"GoT_train", "GoT_generate", "GoT_scripts"}
	var generateCommitID string
	for _, commitInfo := range commitInfos {
		require.EqualOneOf(t, repos, commitInfo.Commit.Repo.Name)
		if commitInfo.Commit.Repo.Name == "GoT_generate" {
			generateCommitID = commitInfo.Commit.ID
		}
	}

	// Make sure the final output is non zero
	var buffer bytes.Buffer
	require.NoError(t, c.GetFile("GoT_generate", generateCommitID, "new_script.txt", 0, 0, "", false, nil, &buffer))
	if buffer.Len() < 100 {
		t.Fatalf("Output GoT script is too small (has len=%v)", buffer.Len())
	}
	require.NoError(t, c.DeleteRepo("GoT_generate", false))
	require.NoError(t, c.DeleteRepo("GoT_train", false))
	require.NoError(t, c.DeleteRepo("GoT_scripts", false))
}

func TestWordCount(t *testing.T) {

	if testing.Short() {
		t.Skip("Skipping integration tests in short mode")
	}

	c := getPachClient(t)

	// Should stay in sync with examples/word_count/README.md
	inputPipelineManifest := `
{
  "pipeline": {
    "name": "wordcount_input"
  },
  "transform": {
    "image": "pachyderm/job-shim:latest",
    "cmd": [ "wget",
        "-e", "robots=off",
        "--recursive",
        "--level", "1",
        "--adjust-extension",
        "--no-check-certificate",
        "--no-directories",
        "--directory-prefix",
        "/pfs/out",
        "https://en.wikipedia.org/wiki/Main_Page"
    ],
    "acceptReturnCode": [4,5,6,7,8]
  },
  "parallelism_spec": {
       "strategy" : "CONSTANT",
       "constant" : 1
  }
}
`
	exampleDir := "../../examples/word_count"
	cmd := exec.Command("pachctl", "create-pipeline")
	cmd.Stdin = strings.NewReader(inputPipelineManifest)
	cmd.Dir = exampleDir
	raw, err := cmd.CombinedOutput()
	fmt.Printf("create pipeline output: %v\n", string(raw))
	require.NoError(t, err)

	cmd = exec.Command("pachctl", "run-pipeline", "wordcount_input")
	cmd.Dir = exampleDir
	_, err = cmd.Output()
	require.NoError(t, err)

	cmd = exec.Command("docker", "build", "-t", "wordcount-map", ".")
	cmd.Dir = exampleDir
	_, err = cmd.CombinedOutput()
	require.NoError(t, err)

	// Should stay in sync with examples/word_count/README.md
	wordcountMapPipelineManifest := `
{
  "pipeline": {
    "name": "wordcount_map"
  },
  "transform": {
    "image": "wordcount-map:latest",
    "cmd": ["/map", "/pfs/wordcount_input", "/pfs/out"]
  },
  "inputs": [
    {
      "repo": {
        "name": "wordcount_input"
      }
    }
  ]
}
`
	cmd = exec.Command("pachctl", "create-pipeline")
	cmd.Stdin = strings.NewReader(wordcountMapPipelineManifest)
	cmd.Dir = exampleDir
	_, err = cmd.Output()
	require.NoError(t, err)

	commitInfos, err := c.ListCommit([]string{"wordcount_map"}, nil, client.CommitTypeRead, false, client.CommitStatusAll, nil)
	require.NoError(t, err)
	require.Equal(t, 1, len(commitInfos))

	var buffer bytes.Buffer
	require.NoError(t, c.GetFile(commitInfos[0].Commit.Repo.Name, commitInfos[0].Commit.ID, "morning", 0, 0, "", false, nil, &buffer))
	lines := strings.Split(buffer.String(), "\n")
	// Should see # lines output == # pods running job ... not sure what this is on CI?
	require.Equal(t, 3, len(lines))

	// Should stay in sync with examples/word_count/README.md
	wordcountReducePipelineManifest := `
{
  "pipeline": {
    "name": "wordcount_reduce"
  },
  "transform": {
    "image": "pachyderm/job-shim:latest",
    "cmd": ["sh"],
    "stdin": [
        "find /pfs/wordcount_map -name '*' | while read count; do cat $count | awk '{ sum+=$1} END {print sum}' >/tmp/count; mv /tmp/count /pfs/out/` + "`basename $count`" + `; done"
    ]
  },
  "inputs": [
    {
      "repo": {
        "name": "wordcount_map"
      },
	  "method": "reduce"
    }
  ]
}
`

	cmd = exec.Command("pachctl", "create-pipeline")
	cmd.Stdin = strings.NewReader(wordcountReducePipelineManifest)
	cmd.Dir = exampleDir
	_, err = cmd.Output()
	require.NoError(t, err)

	commitInfos, err = c.ListCommit([]string{"wordcount_reduce"}, nil, client.CommitTypeRead, false, client.CommitStatusAll, nil)
	require.NoError(t, err)
	require.Equal(t, 1, len(commitInfos))
	buffer.Reset()
	require.NoError(t, c.GetFile("wordcount_reduce", commitInfos[0].Commit.ID, "morning", 0, 0, "", false, nil, &buffer))
	lines = strings.Split(buffer.String(), "\n")
	require.Equal(t, 1, len(lines))

	fileInfos, err := c.ListFile("wordcount_reduce", commitInfos[0].Commit.ID, "", "", false, nil, false)
	require.NoError(t, err)

	if len(fileInfos) < 100 {
		t.Fatalf("Word count result is too small. Should have counted a bunch of words. Only counted %v:\n%v\n", len(fileInfos), fileInfos)
	}
}
<commit_msg>Handle polling for output of pipeline w no inputs<commit_after>package examples

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"testing"
	"time"

	"github.com/pachyderm/pachyderm/src/client"
	pfsclient "github.com/pachyderm/pachyderm/src/client/pfs"
	"github.com/pachyderm/pachyderm/src/client/pkg/require"
)

func getPachClient(t testing.TB) *client.APIClient {
	client, err := client.NewFromAddress("0.0.0.0:30650")
	require.NoError(t, err)
	return client
}

func TestExampleTensorFlow(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping integration tests in short mode")
	}

	c := getPachClient(t)
	t.Parallel()

	cwd, err := os.Getwd()
	require.NoError(t, err)
	exampleDir := filepath.Join(cwd, "../../../doc/examples/tensor_flow")
	cmd := exec.Command("make", "test")
	cmd.Dir = exampleDir
	_, err = cmd.CombinedOutput()
	require.NoError(t, err)

	commitInfos, err := c.ListCommit(
		[]*pfsclient.Commit{{
			Repo: &pfsclient.Repo{"GoT_scripts"},
		}},
		nil,
		client.CommitTypeRead,
		client.CommitStatusAll,
		false,
	)
	require.NoError(t, err)
	fmt.Printf("commits: %v\n", commitInfos)
	require.Equal(t, 1, len(commitInfos))
	inputCommitID := commitInfos[0].Commit.ID

	// Wait until the GoT_generate job has finished
	commitInfos, err = c.FlushCommit([]*pfsclient.Commit{client.NewCommit("GoT_scripts", inputCommitID)}, nil)
	require.NoError(t, err)
	require.Equal(t, 3, len(commitInfos))

	repos := []interface{}{"GoT_train", "GoT_generate", "GoT_scripts"}
	var generateCommitID string
	for _, commitInfo := range commitInfos {
		require.EqualOneOf(t, repos, commitInfo.Commit.Repo.Name)
		if commitInfo.Commit.Repo.Name == "GoT_generate" {
			generateCommitID = commitInfo.Commit.ID
		}
	}

	// Make sure the final output is non zero
	var buffer bytes.Buffer
	require.NoError(t, c.GetFile("GoT_generate", generateCommitID, "new_script.txt", 0, 0, "", false, nil, &buffer))
	if buffer.Len() < 100 {
		t.Fatalf("Output GoT script is too small (has len=%v)", buffer.Len())
	}
	require.NoError(t, c.DeleteRepo("GoT_generate", false))
	require.NoError(t, c.DeleteRepo("GoT_train", false))
	require.NoError(t, c.DeleteRepo("GoT_scripts", false))
}

func TestWordCount(t *testing.T) {

	if testing.Short() {
		t.Skip("Skipping integration tests in short mode")
	}

	c := getPachClient(t)

	// Should stay in sync with doc/examples/word_count/README.md
	inputPipelineManifest := `
{
  "pipeline": {
    "name": "wordcount_input"
  },
  "transform": {
    "image": "pachyderm/job-shim:latest",
    "cmd": [ "wget",
        "-e", "robots=off",
        "--recursive",
        "--level", "1",
        "--adjust-extension",
        "--no-check-certificate",
        "--no-directories",
        "--directory-prefix",
        "/pfs/out",
        "https://en.wikipedia.org/wiki/Main_Page"
    ],
    "acceptReturnCode": [4,5,6,7,8]
  },
  "parallelism_spec": {
       "strategy" : "CONSTANT",
       "constant" : 1
  }
}
`
	exampleDir := "../../../doc/examples/word_count"
	cmd := exec.Command("pachctl", "create-pipeline")
	cmd.Stdin = strings.NewReader(inputPipelineManifest)
	cmd.Dir = exampleDir
	raw, err := cmd.CombinedOutput()
	fmt.Printf("create pipeline output: %v\n", string(raw))
	require.NoError(t, err)

	cmd = exec.Command("pachctl", "run-pipeline", "wordcount_input")
	cmd.Dir = exampleDir
	_, err = cmd.Output()
	require.NoError(t, err)

	cmd = exec.Command("docker", "build", "-t", "wordcount-map", ".")
	cmd.Dir = exampleDir
	_, err = cmd.CombinedOutput()
	require.NoError(t, err)

	// Should stay in sync with doc/examples/word_count/README.md
	wordcountMapPipelineManifest := `
{
  "pipeline": {
    "name": "wordcount_map"
  },
  "transform": {
    "image": "wordcount-map:latest",
    "cmd": ["/map", "/pfs/wordcount_input", "/pfs/out"]
  },
  "inputs": [
    {
      "repo": {
        "name": "wordcount_input"
      }
    }
  ]
}
`
	cmd = exec.Command("pachctl", "create-pipeline")
	cmd.Stdin = strings.NewReader(wordcountMapPipelineManifest)
	cmd.Dir = exampleDir
	_, err = cmd.Output()
	require.NoError(t, err)

	// Flush Commit can't help us here since there are no inputs
	// So we poll wordcount_input until it has a commit
	tries := 10
	sleepAmount := 10

	var commitInfos []*pfsclient.CommitInfo
	for tries != 0 {
		commitInfos, err = c.ListCommit(
			[]*pfsclient.Commit{{
				Repo: &pfsclient.Repo{"wordcount_input"},
			}},
			nil,
			client.CommitTypeRead,
			client.CommitStatusAll,
			false,
		)
		require.NoError(t, err)
		if len(commitInfos) == 1 {
			break
		}
		time.Sleep(sleepAmount)
		tries--
	}

	commitInfos, err = c.FlushCommit([]*pfsclient.Commit{commitInfos[0].Commit}, nil)
	require.NoError(t, err)
	require.Equal(t, 3, len(commitInfos))

	commitInfos, err = c.ListCommit(
		[]*pfsclient.Commit{{
			Repo: &pfsclient.Repo{"wordcount_map"},
		}},
		nil,
		client.CommitTypeRead,
		client.CommitStatusNormal,
		false,
	)
	require.NoError(t, err)
	require.Equal(t, 1, len(commitInfos))

	var buffer bytes.Buffer
	require.NoError(t, c.GetFile(commitInfos[0].Commit.Repo.Name, commitInfos[0].Commit.ID, "morning", 0, 0, "", false, nil, &buffer))
	lines := strings.Split(buffer.String(), "\n")
	// Should see # lines output == # pods running job ... not sure what this is on CI?
	require.Equal(t, 3, len(lines))

	// Should stay in sync with doc/examples/word_count/README.md
	wordcountReducePipelineManifest := `
{
  "pipeline": {
    "name": "wordcount_reduce"
  },
  "transform": {
    "image": "pachyderm/job-shim:latest",
    "cmd": ["sh"],
    "stdin": [
        "find /pfs/wordcount_map -name '*' | while read count; do cat $count | awk '{ sum+=$1} END {print sum}' >/tmp/count; mv /tmp/count /pfs/out/` + "`basename $count`" + `; done"
    ]
  },
  "inputs": [
    {
      "repo": {
        "name": "wordcount_map"
      },
	  "method": "reduce"
    }
  ]
}
`

	cmd = exec.Command("pachctl", "create-pipeline")
	cmd.Stdin = strings.NewReader(wordcountReducePipelineManifest)
	cmd.Dir = exampleDir
	_, err = cmd.Output()
	require.NoError(t, err)

	commitInfos, err = c.ListCommit(
		[]*pfsclient.Commit{{
			Repo: &pfsclient.Repo{"wordcount_reduce"},
		}},
		nil,
		client.CommitTypeRead,
		client.CommitStatusNormal,
		false,
	)
	require.NoError(t, err)
	require.Equal(t, 1, len(commitInfos))
	buffer.Reset()
	require.NoError(t, c.GetFile("wordcount_reduce", commitInfos[0].Commit.ID, "morning", 0, 0, "", false, nil, &buffer))
	lines = strings.Split(buffer.String(), "\n")
	require.Equal(t, 1, len(lines))

	fileInfos, err := c.ListFile("wordcount_reduce", commitInfos[0].Commit.ID, "", "", false, nil, false)
	require.NoError(t, err)

	if len(fileInfos) < 100 {
		t.Fatalf("Word count result is too small. Should have counted a bunch of words. Only counted %v:\n%v\n", len(fileInfos), fileInfos)
	}
}
<|endoftext|>