<commit_before>package scheduling

import (
	"context"
	"strings"

	g "github.com/onsi/ginkgo"
	o "github.com/onsi/gomega"
	configv1 "github.com/openshift/api/config/v1"
	e2e "k8s.io/kubernetes/test/e2e/framework"

	exutil "github.com/openshift/origin/test/extended/util"
	appsv1 "k8s.io/api/apps/v1"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// requirePodsOnDifferentNodesTest fails if any pods with the prefix in the
// namespace are scheduled to the same node
type requirePodsOnDifferentNodesTest struct {
	namespace  string
	deployment string
}

// getPodDeploymentName returns the name of the deployment associated with a
// given pod. To do that, it needs a list of all replicasets in the pod's
// namespace. If the Pod is not part of a Deployment, an empty string is
// returned
func getPodDeploymentName(pod *corev1.Pod, namespaceReplicaSets *appsv1.ReplicaSetList) string {
	podOwnerReplicaSetName := ""
	for _, owner := range pod.OwnerReferences {
		if owner.APIVersion == "apps/v1" && owner.Kind == "ReplicaSet" {
			podOwnerReplicaSetName = owner.Name
			break
		}
	}

	if podOwnerReplicaSetName == "" {
		// Pod is not owned by a replicaset, so it doesn't have a deployment
		// associated with it
		return ""
	}

	podOwnerReplicaSet := (*appsv1.ReplicaSet)(nil)
	for _, namespaceReplicaSet := range namespaceReplicaSets.Items {
		namespaceReplicaSet := namespaceReplicaSet
		if namespaceReplicaSet.Name == podOwnerReplicaSetName {
			podOwnerReplicaSet = &namespaceReplicaSet
			break
		}
	}

	if podOwnerReplicaSet == nil {
		e2e.Failf("Could not find ReplicaSet resource associated with the Pod ReplicaSet owner reference")
	}

	for _, replicaSetOwner := range podOwnerReplicaSet.OwnerReferences {
		if replicaSetOwner.APIVersion == "apps/v1" && replicaSetOwner.Kind == "Deployment" {
			return replicaSetOwner.Name
		}
	}

	// Pod is part of a ReplicaSet which is not owned by any deployment
	return ""
}

func (p requirePodsOnDifferentNodesTest) getDeploymentPods(oc *exutil.CLI) []*corev1.Pod {
	pods, err := oc.KubeFramework().ClientSet.CoreV1().Pods(p.namespace).List(context.Background(), metav1.ListOptions{})
	if err != nil {
		e2e.Failf("unable to list pods: %v", err)
	}

	replicaSets, err := oc.KubeFramework().ClientSet.AppsV1().ReplicaSets(p.namespace).List(context.Background(), metav1.ListOptions{})
	if err != nil {
		e2e.Failf("unable to list replicaSets: %v", err)
	}

	deploymentPods := make([]*corev1.Pod, 0, 2)
	for _, pod := range pods.Items {
		pod := pod
		podDeploymentName := getPodDeploymentName(&pod, replicaSets)

		if p.deployment == podDeploymentName {
			deploymentPods = append(deploymentPods, &pod)
		}
	}

	return deploymentPods
}

func (p requirePodsOnDifferentNodesTest) run(oc *exutil.CLI) {
	ctx := context.TODO()

	if clusterVersion, err := oc.AdminConfigClient().ConfigV1().ClusterVersions().Get(ctx, "version", metav1.GetOptions{}); err == nil && len(clusterVersion.Status.History) > 0 {
		// most recent is first.  Check the most recently installed version, if it is 4.10 or earlier, skip this test
		for _, releaseUpdate := range clusterVersion.Status.History {
			if releaseUpdate.State != configv1.CompletedUpdate {
				continue
			}
			switch {
			case strings.HasPrefix(releaseUpdate.Version, "4.0") ||
				strings.HasPrefix(releaseUpdate.Version, "4.1.") ||
				strings.HasPrefix(releaseUpdate.Version, "4.2.") ||
				strings.HasPrefix(releaseUpdate.Version, "4.3.") ||
				strings.HasPrefix(releaseUpdate.Version, "4.4.") ||
				strings.HasPrefix(releaseUpdate.Version, "4.5.") ||
				strings.HasPrefix(releaseUpdate.Version, "4.6") ||
				strings.HasPrefix(releaseUpdate.Version, "4.7") ||
				strings.HasPrefix(releaseUpdate.Version, "4.8") ||
				strings.HasPrefix(releaseUpdate.Version, "4.9") ||
				strings.HasPrefix(releaseUpdate.Version, "4.10"):
				return
			}
			// if we got here, then we're 4.11 or after, so we run the test.  skip the rest of the history.
			break
		}
	}

	deploymentPods := p.getDeploymentPods(oc)

	if len(deploymentPods) == 0 {
		// This is not a bug. Not all deployments are available all the time.
		// For example, the openshift-etcd/etcd-quorum-guard deployment is not
		// created for SingleReplica ControlPlaneTopology.
		return
	}

	nodeNameMap := map[string]string{}
	for _, pod := range deploymentPods {
		if podName, ok := nodeNameMap[pod.Spec.NodeName]; ok {
			e2e.Failf("ns/%s pod %s and pod %s are running on the same node: %s", p.namespace, pod.Name, podName, pod.Spec.NodeName)
		} else {
			nodeNameMap[pod.Spec.NodeName] = pod.Name
		}
	}
}

var _ = g.Describe("[sig-scheduling][Early]", func() {
	defer g.GinkgoRecover()

	oc := exutil.NewCLI("scheduling-pod-check")

	g.BeforeEach(func() {
		var err error
		_, err = exutil.WaitForRouterServiceIP(oc)
		o.Expect(err).NotTo(o.HaveOccurred())
	})

	g.Describe("The HAProxy router pods", func() {
		g.It("should be scheduled on different nodes", func() {
			requirePodsOnDifferentNodesTest{namespace: "openshift-ingress", deployment: "router-default"}.run(oc)
		})
	})

	g.Describe("The openshift-apiserver pods", func() {
		g.It("should be scheduled on different nodes", func() {
			requirePodsOnDifferentNodesTest{namespace: "openshift-apiserver", deployment: "apiserver"}.run(oc)
		})
	})

	g.Describe("The openshift-authentication pods", func() {
		g.It("should be scheduled on different nodes", func() {
			requirePodsOnDifferentNodesTest{namespace: "openshift-authentication", deployment: "oauth-openshift"}.run(oc)
		})
	})

	g.Describe("The openshift-console console pods", func() {
		g.It("should be scheduled on different nodes", func() {
			requirePodsOnDifferentNodesTest{namespace: "openshift-console", deployment: "console"}.run(oc)
		})
	})

	g.Describe("The openshift-console downloads pods", func() {
		g.It("should be scheduled on different nodes", func() {
			requirePodsOnDifferentNodesTest{namespace: "openshift-console", deployment: "downloads"}.run(oc)
		})
	})

	g.Describe("The openshift-etcd pods", func() {
		g.It("should be scheduled on different nodes", func() {
			requirePodsOnDifferentNodesTest{namespace: "openshift-etcd", deployment: "etcd-quorum-guard"}.run(oc)
		})
	})

	g.Describe("The openshift-image-registry pods", func() {
		g.It("should be scheduled on different nodes", func() {
			requirePodsOnDifferentNodesTest{namespace: "openshift-image-registry", deployment: "image-registry"}.run(oc)
		})
	})

	g.Describe("The openshift-monitoring prometheus-adapter pods", func() {
		g.It("should be scheduled on different nodes", func() {
			requirePodsOnDifferentNodesTest{namespace: "openshift-monitoring", deployment: "prometheus-adapter"}.run(oc)
		})
	})

	g.Describe("The openshift-monitoring thanos-querier pods", func() {
		g.It("should be scheduled on different nodes", func() {
			requirePodsOnDifferentNodesTest{namespace: "openshift-monitoring", deployment: "thanos-querier"}.run(oc)
		})
	})

	g.Describe("The openshift-oauth-apiserver pods", func() {
		g.It("should be scheduled on different nodes", func() {
			requirePodsOnDifferentNodesTest{namespace: "openshift-oauth-apiserver", deployment: "apiserver"}.run(oc)
		})
	})

	g.Describe("The openshift-operator-lifecycle-manager pods", func() {
		g.It("should be scheduled on different nodes", func() {
			requirePodsOnDifferentNodesTest{namespace: "openshift-operator-lifecycle-manager", deployment: "packageserver"}.run(oc)
		})
	})
})
<commit_msg>Remove checks for OCP <= 4.10 given the master HEAD is 4.12 now<commit_after>package scheduling

import (
	"context"

	g "github.com/onsi/ginkgo"
	o "github.com/onsi/gomega"
	e2e "k8s.io/kubernetes/test/e2e/framework"

	exutil "github.com/openshift/origin/test/extended/util"
	appsv1 "k8s.io/api/apps/v1"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// requirePodsOnDifferentNodesTest fails if any pods with the prefix in the
// namespace are scheduled to the same node
type requirePodsOnDifferentNodesTest struct {
	namespace  string
	deployment string
}

// getPodDeploymentName returns the name of the deployment associated with a
// given pod. To do that, it needs a list of all replicasets in the pod's
// namespace. If the Pod is not part of a Deployment, an empty string is
// returned
func getPodDeploymentName(pod *corev1.Pod, namespaceReplicaSets *appsv1.ReplicaSetList) string {
	podOwnerReplicaSetName := ""
	for _, owner := range pod.OwnerReferences {
		if owner.APIVersion == "apps/v1" && owner.Kind == "ReplicaSet" {
			podOwnerReplicaSetName = owner.Name
			break
		}
	}

	if podOwnerReplicaSetName == "" {
		// Pod is not owned by a replicaset, so it doesn't have a deployment
		// associated with it
		return ""
	}

	podOwnerReplicaSet := (*appsv1.ReplicaSet)(nil)
	for _, namespaceReplicaSet := range namespaceReplicaSets.Items {
		namespaceReplicaSet := namespaceReplicaSet
		if namespaceReplicaSet.Name == podOwnerReplicaSetName {
			podOwnerReplicaSet = &namespaceReplicaSet
			break
		}
	}

	if podOwnerReplicaSet == nil {
		e2e.Failf("Could not find ReplicaSet resource associated with the Pod ReplicaSet owner reference")
	}

	for _, replicaSetOwner := range podOwnerReplicaSet.OwnerReferences {
		if replicaSetOwner.APIVersion == "apps/v1" && replicaSetOwner.Kind == "Deployment" {
			return replicaSetOwner.Name
		}
	}

	// Pod is part of a ReplicaSet which is not owned by any deployment
	return ""
}

func (p requirePodsOnDifferentNodesTest) getDeploymentPods(oc *exutil.CLI) []*corev1.Pod {
	pods, err := oc.KubeFramework().ClientSet.CoreV1().Pods(p.namespace).List(context.Background(), metav1.ListOptions{})
	if err != nil {
		e2e.Failf("unable to list pods: %v", err)
	}

	replicaSets, err := oc.KubeFramework().ClientSet.AppsV1().ReplicaSets(p.namespace).List(context.Background(), metav1.ListOptions{})
	if err != nil {
		e2e.Failf("unable to list replicaSets: %v", err)
	}

	deploymentPods := make([]*corev1.Pod, 0, 2)
	for _, pod := range pods.Items {
		pod := pod
		podDeploymentName := getPodDeploymentName(&pod, replicaSets)

		if p.deployment == podDeploymentName {
			deploymentPods = append(deploymentPods, &pod)
		}
	}

	return deploymentPods
}

func (p requirePodsOnDifferentNodesTest) run(oc *exutil.CLI) {
	deploymentPods := p.getDeploymentPods(oc)

	if len(deploymentPods) == 0 {
		// This is not a bug. Not all deployments are available all the time.
		// For example, the openshift-etcd/etcd-quorum-guard deployment is not
		// created for SingleReplica ControlPlaneTopology.
		return
	}

	nodeNameMap := map[string]string{}
	for _, pod := range deploymentPods {
		if podName, ok := nodeNameMap[pod.Spec.NodeName]; ok {
			e2e.Failf("ns/%s pod %s and pod %s are running on the same node: %s", p.namespace, pod.Name, podName, pod.Spec.NodeName)
		} else {
			nodeNameMap[pod.Spec.NodeName] = pod.Name
		}
	}
}

var _ = g.Describe("[sig-scheduling][Early]", func() {
	defer g.GinkgoRecover()

	oc := exutil.NewCLI("scheduling-pod-check")

	g.BeforeEach(func() {
		var err error
		_, err = exutil.WaitForRouterServiceIP(oc)
		o.Expect(err).NotTo(o.HaveOccurred())
	})

	g.Describe("The HAProxy router pods", func() {
		g.It("should be scheduled on different nodes", func() {
			requirePodsOnDifferentNodesTest{namespace: "openshift-ingress", deployment: "router-default"}.run(oc)
		})
	})

	g.Describe("The openshift-apiserver pods", func() {
		g.It("should be scheduled on different nodes", func() {
			requirePodsOnDifferentNodesTest{namespace: "openshift-apiserver", deployment: "apiserver"}.run(oc)
		})
	})

	g.Describe("The openshift-authentication pods", func() {
		g.It("should be scheduled on different nodes", func() {
			requirePodsOnDifferentNodesTest{namespace: "openshift-authentication", deployment: "oauth-openshift"}.run(oc)
		})
	})

	g.Describe("The openshift-console console pods", func() {
		g.It("should be scheduled on different nodes", func() {
			requirePodsOnDifferentNodesTest{namespace: "openshift-console", deployment: "console"}.run(oc)
		})
	})

	g.Describe("The openshift-console downloads pods", func() {
		g.It("should be scheduled on different nodes", func() {
			requirePodsOnDifferentNodesTest{namespace: "openshift-console", deployment: "downloads"}.run(oc)
		})
	})

	g.Describe("The openshift-etcd pods", func() {
		g.It("should be scheduled on different nodes", func() {
			requirePodsOnDifferentNodesTest{namespace: "openshift-etcd", deployment: "etcd-quorum-guard"}.run(oc)
		})
	})

	g.Describe("The openshift-image-registry pods", func() {
		g.It("should be scheduled on different nodes", func() {
			requirePodsOnDifferentNodesTest{namespace: "openshift-image-registry", deployment: "image-registry"}.run(oc)
		})
	})

	g.Describe("The openshift-monitoring prometheus-adapter pods", func() {
		g.It("should be scheduled on different nodes", func() {
			requirePodsOnDifferentNodesTest{namespace: "openshift-monitoring", deployment: "prometheus-adapter"}.run(oc)
		})
	})

	g.Describe("The openshift-monitoring thanos-querier pods", func() {
		g.It("should be scheduled on different nodes", func() {
			requirePodsOnDifferentNodesTest{namespace: "openshift-monitoring", deployment: "thanos-querier"}.run(oc)
		})
	})

	g.Describe("The openshift-oauth-apiserver pods", func() {
		g.It("should be scheduled on different nodes", func() {
			requirePodsOnDifferentNodesTest{namespace: "openshift-oauth-apiserver", deployment: "apiserver"}.run(oc)
		})
	})

	g.Describe("The openshift-operator-lifecycle-manager pods", func() {
		g.It("should be scheduled on different nodes", func() {
			requirePodsOnDifferentNodesTest{namespace: "openshift-operator-lifecycle-manager", deployment: "packageserver"}.run(oc)
		})
	})
})
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/bwmarrin/discordgo"
	"net/http"

	"github.com/koffeinsource/go-imgur"
	"github.com/koffeinsource/go-klogger"

	"github.com/thehowl/go-osuapi"
)

// Variables used for Command line parameters
var (
	Token        string
	BotID        string
	ImgurID      string
	OsuID        string
	DataLocation string

	Servers         map[string]*ServerData
	AdminCommands   map[string]func(*discordgo.Session, MessageData, *ServerData)
	PruneCommands   map[string]func(*discordgo.Session, MessageData, *ServerData)
	DefaultCommands map[string]func(*discordgo.Session, MessageData, *ServerData)
	AlbumCache      map[string]*imgur.AlbumInfo

	osuClient osuapi.Client
	imgClient *imgur.Client
)

// ServerData is the data which is saved for every server the bot is in.
type ServerData struct {
	ID            string                  `json:"id"`
	Commanders    map[string]bool         `json:"commanders"`
	Channels      map[string]*ChannelData `json:"channels"`
	Commands      map[string]*CommandData `json:"commands"`
	meIrlCommands map[string]*MeIrlData   `json:"meIrlCommand"`
	Key           string                  `json:"Key"`
}

// ChannelData is the data which is saved for every channel
type ChannelData struct {
	ID     string   `json:"ID"`
	Albums []string `json:"albums"`
}

// MeIrlData is the data which is saved for every meIrlCommand
type MeIrlData struct {
	UserID   string `json:"id"`
	Nickname string `json:"nickname"`
	Content  string `json:"content"`
}

// CommandData is the data which is saved for every command
type CommandData struct {
	Name    string `json:"name"`
	Content string `json:"content"`
}

// MessageData is the parsed message, allows for easier access to arguments.
type MessageData struct {
	Key       string
	Command   string
	Content   []string
	MessageID string
	ChannelID string
	Mentions  []*discordgo.User
	Author    *discordgo.User
}

func setUp() {
	// Set up all the commands
	AdminCommands = map[string]func(*discordgo.Session, MessageData, *ServerData){
		"addcommand":   addCommandCommand,
		"delcommand":   delCommandCommand,
		"addcommander": addCommanderCommand,
		"delcommander": delCommanderCommand,
		"setkey":       setKeyCommand,
		"addalbum":     addAlbumCommand,
		"delalbum":     delAlbumCommand,
		"forcereload":  forceGetAlbumCommand,
		"addme_irl":    addMeIrlCommand,
		"delme_irl":    delMeIrlCommand,
		"lock":         lockChannelCommand,
		"unlock":       unlockChannelCommand,
	}

	PruneCommands = map[string]func(*discordgo.Session, MessageData, *ServerData){
		"pruneCommand": pruneCommand,
	}

	DefaultCommands = map[string]func(*discordgo.Session, MessageData, *ServerData){
		"i":           getImageCommand,
		"image":       getImageCommand,
		"meIrl":       meIrlCommand,
		"help":        helpCommand,
		"commandlist": commandListCommands,
	}

	// Set up the cache so we do not have to make multiple API calls for the same album.
	AlbumCache = make(map[string]*imgur.AlbumInfo)
}

func init() {
	flag.StringVar(&Token, "t", "", "Bot Token")
	flag.StringVar(&ImgurID, "i", "", "Imgur Token")
	flag.StringVar(&OsuID, "o", "", "Osu Token")
	flag.StringVar(&DataLocation, "d", "./data.json", "Data Location")
	flag.Parse()
}

func main() {
	imgClient = new(imgur.Client)
	imgClient.HTTPClient = new(http.Client)
	imgClient.Log = new(klogger.CLILogger)
	imgClient.ImgurClientID = ImgurID

	osuClient = *osuapi.NewClient(OsuID)

	// Create a new Discord session using the provided bot token.
	dg, err := discordgo.New("Bot " + Token)
	if err != nil {
		fmt.Println("error creating Discord session,", err)
		return
	}

	// Get the account information.
	u, err := dg.User("@me")
	if err != nil {
		fmt.Println("error obtaining account details,", err)
		return
	}

	// Store the account ID for later use.
	BotID = u.ID

	// Register messageCreate as a callback for the messageCreate events.
	dg.AddHandler(messageCreate)

	readServerData()
	setUp()

	// Open the websocket and begin listening.
	err = dg.Open()
	if err != nil {
		fmt.Println("error opening connection,", err)
		return
	}

	fmt.Println("Bot is now running.  Press CTRL-C to exit.")
	// Simple way to keep program running until CTRL-C is pressed.
	<-make(chan struct{})
	return
}

// This function will be called (due to AddHandler above) every time a new
// message is created on any channel that the autenticated bot has access to.
func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
	// Ignore all messages created by the bot itself
	if m.Author.ID == BotID || len(m.Content) < 1 {
		return
	}

	// Parse the command into a MessageData struct
	msg := parseCommand(m)

	// Retrieve the server data of the given server.
	serverData := getServerData(s, m.ChannelID)

	//Check for any beatmap links in message
	checkBeatmapLink(s, m)

	if serverData.Key != msg.Key {
		return
	}

	// Check if a Command is in one of the maps.
	if f, ok := AdminCommands[msg.Command]; ok {
		perm, _ := s.UserChannelPermissions(m.Author.ID, m.ChannelID)
		if isCommander, ok := serverData.Commanders[m.Author.ID]; isAdmin(perm) || (ok && isCommander) {
			f(s, msg, serverData)
		} else {
			s.ChannelMessageSend(m.ChannelID, "Insufficient permission to use **"+msg.Command+"**.")
		}
	} else if f, ok := PruneCommands[msg.Command]; ok {
		perm, _ := s.UserChannelPermissions(m.Author.ID, m.ChannelID)
		if isCommander, ok := serverData.Commanders[m.Author.ID]; isAllowedToPrune(perm) || (ok && isCommander) {
			f(s, msg, serverData)
		} else {
			s.ChannelMessageSend(m.ChannelID, "Insufficient permission to use **"+msg.Command+"**.")
		}
	} else if f, ok := DefaultCommands[msg.Command]; ok {
		f(s, msg, serverData)
	} else if cmd, ok := serverData.Commands[msg.Command]; ok {
		s.ChannelMessageSend(m.ChannelID, cmd.Content)
	}
}
<commit_msg>Fix the prune command<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/bwmarrin/discordgo"
	"net/http"

	"github.com/koffeinsource/go-imgur"
	"github.com/koffeinsource/go-klogger"

	"github.com/thehowl/go-osuapi"
)

// Variables used for Command line parameters
var (
	Token        string
	BotID        string
	ImgurID      string
	OsuID        string
	DataLocation string

	Servers         map[string]*ServerData
	AdminCommands   map[string]func(*discordgo.Session, MessageData, *ServerData)
	PruneCommands   map[string]func(*discordgo.Session, MessageData, *ServerData)
	DefaultCommands map[string]func(*discordgo.Session, MessageData, *ServerData)
	AlbumCache      map[string]*imgur.AlbumInfo

	osuClient osuapi.Client
	imgClient *imgur.Client
)

// ServerData is the data which is saved for every server the bot is in.
type ServerData struct {
	ID            string                  `json:"id"`
	Commanders    map[string]bool         `json:"commanders"`
	Channels      map[string]*ChannelData `json:"channels"`
	Commands      map[string]*CommandData `json:"commands"`
	meIrlCommands map[string]*MeIrlData   `json:"meIrlCommand"`
	Key           string                  `json:"Key"`
}

// ChannelData is the data which is saved for every channel
type ChannelData struct {
	ID     string   `json:"ID"`
	Albums []string `json:"albums"`
}

// MeIrlData is the data which is saved for every meIrlCommand
type MeIrlData struct {
	UserID   string `json:"id"`
	Nickname string `json:"nickname"`
	Content  string `json:"content"`
}

// CommandData is the data which is saved for every command
type CommandData struct {
	Name    string `json:"name"`
	Content string `json:"content"`
}

// MessageData is the parsed message, allows for easier access to arguments.
type MessageData struct {
	Key       string
	Command   string
	Content   []string
	MessageID string
	ChannelID string
	Mentions  []*discordgo.User
	Author    *discordgo.User
}

func setUp() {
	// Set up all the commands
	AdminCommands = map[string]func(*discordgo.Session, MessageData, *ServerData){
		"addcommand":   addCommandCommand,
		"delcommand":   delCommandCommand,
		"addcommander": addCommanderCommand,
		"delcommander": delCommanderCommand,
		"setkey":       setKeyCommand,
		"addalbum":     addAlbumCommand,
		"delalbum":     delAlbumCommand,
		"forcereload":  forceGetAlbumCommand,
		"addme_irl":    addMeIrlCommand,
		"delme_irl":    delMeIrlCommand,
		"lock":         lockChannelCommand,
		"unlock":       unlockChannelCommand,
	}

	PruneCommands = map[string]func(*discordgo.Session, MessageData, *ServerData){
		"prune": pruneCommand,
	}

	DefaultCommands = map[string]func(*discordgo.Session, MessageData, *ServerData){
		"i":           getImageCommand,
		"image":       getImageCommand,
		"meIrl":       meIrlCommand,
		"help":        helpCommand,
		"commandlist": commandListCommands,
	}

	// Set up the cache so we do not have to make multiple API calls for the same album.
	AlbumCache = make(map[string]*imgur.AlbumInfo)
}

func init() {
	flag.StringVar(&Token, "t", "", "Bot Token")
	flag.StringVar(&ImgurID, "i", "", "Imgur Token")
	flag.StringVar(&OsuID, "o", "", "Osu Token")
	flag.StringVar(&DataLocation, "d", "./data.json", "Data Location")
	flag.Parse()
}

func main() {
	imgClient = new(imgur.Client)
	imgClient.HTTPClient = new(http.Client)
	imgClient.Log = new(klogger.CLILogger)
	imgClient.ImgurClientID = ImgurID

	osuClient = *osuapi.NewClient(OsuID)

	// Create a new Discord session using the provided bot token.
	dg, err := discordgo.New("Bot " + Token)
	if err != nil {
		fmt.Println("error creating Discord session,", err)
		return
	}

	// Get the account information.
	u, err := dg.User("@me")
	if err != nil {
		fmt.Println("error obtaining account details,", err)
		return
	}

	// Store the account ID for later use.
	BotID = u.ID

	// Register messageCreate as a callback for the messageCreate events.
	dg.AddHandler(messageCreate)

	readServerData()
	setUp()

	// Open the websocket and begin listening.
	err = dg.Open()
	if err != nil {
		fmt.Println("error opening connection,", err)
		return
	}

	fmt.Println("Bot is now running.  Press CTRL-C to exit.")
	// Simple way to keep program running until CTRL-C is pressed.
	<-make(chan struct{})
	return
}

// This function will be called (due to AddHandler above) every time a new
// message is created on any channel that the autenticated bot has access to.
func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
	// Ignore all messages created by the bot itself
	if m.Author.ID == BotID || len(m.Content) < 1 {
		return
	}

	// Parse the command into a MessageData struct
	msg := parseCommand(m)

	// Retrieve the server data of the given server.
	serverData := getServerData(s, m.ChannelID)

	//Check for any beatmap links in message
	checkBeatmapLink(s, m)

	if serverData.Key != msg.Key {
		return
	}

	// Check if a Command is in one of the maps.
	if f, ok := AdminCommands[msg.Command]; ok {
		perm, _ := s.UserChannelPermissions(m.Author.ID, m.ChannelID)
		if isCommander, ok := serverData.Commanders[m.Author.ID]; isAdmin(perm) || (ok && isCommander) {
			f(s, msg, serverData)
		} else {
			s.ChannelMessageSend(m.ChannelID, "Insufficient permission to use **"+msg.Command+"**.")
		}
	} else if f, ok := PruneCommands[msg.Command]; ok {
		perm, _ := s.UserChannelPermissions(m.Author.ID, m.ChannelID)
		if isCommander, ok := serverData.Commanders[m.Author.ID]; isAllowedToPrune(perm) || (ok && isCommander) {
			f(s, msg, serverData)
		} else {
			s.ChannelMessageSend(m.ChannelID, "Insufficient permission to use **"+msg.Command+"**.")
		}
	} else if f, ok := DefaultCommands[msg.Command]; ok {
		f(s, msg, serverData)
	} else if cmd, ok := serverData.Commands[msg.Command]; ok {
		s.ChannelMessageSend(m.ChannelID, cmd.Content)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"math/big"
	"testing"
)

func sumOfPrimesBelow(x int64) int64 {
	var i int64
	var sum int64 = 0
	for i = 2; i < x; i++ {
		if i > 2 && i%2 == 0 {
			continue
		}

		j := big.NewInt(i)
		if !j.ProbablyPrime(10) {
			continue
		}
		sum += i

	}
	return sum
}

func TestSumOfPrimesBelow2M(t *testing.T) {
	x := sumOfPrimesBelow(2000000)
	var answer int64 = 142913828922
	if x != answer {
		t.Errorf("result = %v, want %v", x, answer)
	}

}
<commit_msg>Use a sieve for Prob 10<commit_after>package main

import (
	"testing"
)

func sumOfPrimesBelow(x int) int {
	sieve := make([]bool, x)
	for i:=0; i<x; i++ {
		sieve[i] = true
	}
	sieve[0] = false
	sieve[1] = false

	for i:=2; i<x; i++ {
		if sieve[i] == false {
			continue
		}
		for j:=2*i; j<x; j+=i {
			sieve[j] = false
		}

	}

	sum := 0
	for i:=2; i<x; i++ {
		if sieve[i] {
			sum += i;
		}
	}
	return sum
}

func TestSumOfPrimesBelow2M(t *testing.T) {
	x := sumOfPrimesBelow(2000000)
	answer := 142913828922
	if x != answer {
		t.Errorf("result = %v, want %v", x, answer)
	}

}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"sync"
	"unsafe"
)

/*
#cgo CFLAGS: -I/Users/preetam/git/Preetam/libab/src
#cgo LDFLAGS: -L/Users/preetam/git/Preetam/libab/build -lab

#include <stdlib.h>
#include "ab.h"
#include "callback.h"
*/
import "C"

var registeredNodesLock sync.RWMutex
var registrationCounter int
var registeredNodes = map[int]*Node{}

type Node struct {
	ptr             *C.ab_node_t
	callbacksNum    int
	callbackHandler CallbackHandler
	appendResult    chan int
}

type CallbackHandler interface {
	OnAppend(round uint64, data string)
	OnCommit(round uint64)
	GainedLeadership()
	LostLeadership()
	OnLeaderChange(leaderID uint64)
}

func NewNode(id uint64,
	listen string,
	callbackHandler CallbackHandler,
	clusterSize int) (*Node, error) {

	n := &Node{
		callbackHandler: callbackHandler,
	}
	cCallbacks := C.ab_callbacks_t{}
	C.set_callbacks(&cCallbacks)
	registeredNodesLock.Lock()
	defer registeredNodesLock.Unlock()
	registrationCounter++
	registeredNodes[registrationCounter] = n
	n.callbacksNum = registrationCounter
	ptr := C.ab_node_create(C.uint64_t(id), C.int(clusterSize), cCallbacks, unsafe.Pointer(&n.callbacksNum))
	listenStr := C.CString(listen)
	defer C.free(unsafe.Pointer(listenStr))
	ret := C.ab_listen(ptr, listenStr)
	if ret < 0 {
		C.ab_destroy(ptr)
		return nil, fmt.Errorf("error listening")
	}
	n.ptr = ptr
	return n, nil
}

func (n *Node) SetCommitted(commit uint64) {
	C.ab_set_committed(n.ptr, C.uint64_t(commit))
}

func (n *Node) Run() error {
	C.ab_run(n.ptr)
	return fmt.Errorf("failed")
}

func (n *Node) Append(data string) error {
	n.appendResult = make(chan int)
	cData := C.CString(data)
	defer C.free(unsafe.Pointer(cData))
	C.append_go_gateway(n.ptr, cData, C.int(len(data)), C.int(n.callbacksNum))
	result := <-n.appendResult
	n.appendResult = nil
	if result == 0 {
		return nil
	}
	return fmt.Errorf("append failed :(")
}

func (n *Node) ConfirmAppend(round uint64) {
	fmt.Println("confirm append")
	C.ab_confirm_append(n.ptr, C.uint64_t(round))
}

func (n *Node) AddPeer(address string) error {
	cAddr := C.CString(address)
	defer C.free(unsafe.Pointer(cAddr))
	ret := C.ab_connect_to_peer(n.ptr, cAddr)
	if ret < 0 {
		return fmt.Errorf("error adding peer")
	}
	return nil
}

//export on_append_go_cb
func on_append_go_cb(round C.uint64_t, str *C.char, length C.int, p unsafe.Pointer) {
	i := *(*int)(p)
	registeredNodesLock.RLock()
	defer registeredNodesLock.RUnlock()
	node := registeredNodes[i]
	node.callbackHandler.OnAppend(uint64(round), C.GoStringN(str, length))
}

//export on_commit_go_cb
func on_commit_go_cb(round C.uint64_t, p unsafe.Pointer) {
	i := *(*int)(p)
	registeredNodesLock.RLock()
	defer registeredNodesLock.RUnlock()
	node := registeredNodes[i]
	node.callbackHandler.OnCommit(uint64(round))
}

//export gained_leadership_go_cb
func gained_leadership_go_cb(p unsafe.Pointer) {
	i := *(*int)(p)
	registeredNodesLock.RLock()
	defer registeredNodesLock.RUnlock()
	node := registeredNodes[i]
	node.callbackHandler.GainedLeadership()
}

//export lost_leadership_go_cb
func lost_leadership_go_cb(p unsafe.Pointer) {
	i := *(*int)(p)
	registeredNodesLock.RLock()
	defer registeredNodesLock.RUnlock()
	node := registeredNodes[i]
	node.callbackHandler.LostLeadership()
}

//export on_leader_change_go_cb
func on_leader_change_go_cb(id C.uint64_t, p unsafe.Pointer) {
	i := *(*int)(p)
	registeredNodesLock.RLock()
	defer registeredNodesLock.RUnlock()
	node := registeredNodes[i]
	node.callbackHandler.OnLeaderChange(uint64(id))
}

//export append_go_cb
func append_go_cb(status C.int, p unsafe.Pointer) {
	i := *(*int)(p)
	C.free(p)
	registeredNodesLock.RLock()
	defer registeredNodesLock.RUnlock()
	node := registeredNodes[i]
	if node != nil && node.appendResult != nil {
		node.appendResult <- int(status)
	}
}
<commit_msg>relative paths for Go package<commit_after>package main

import (
	"fmt"
	"sync"
	"unsafe"
)

/*
#cgo CFLAGS: -I../src
#cgo LDFLAGS: -L../build -lab

#include <stdlib.h>
#include "ab.h"
#include "callback.h"
*/
import "C"

var registeredNodesLock sync.RWMutex
var registrationCounter int
var registeredNodes = map[int]*Node{}

type Node struct {
	ptr             *C.ab_node_t
	callbacksNum    int
	callbackHandler CallbackHandler
	appendResult    chan int
}

type CallbackHandler interface {
	OnAppend(round uint64, data string)
	OnCommit(round uint64)
	GainedLeadership()
	LostLeadership()
	OnLeaderChange(leaderID uint64)
}

func NewNode(id uint64,
	listen string,
	callbackHandler CallbackHandler,
	clusterSize int) (*Node, error) {

	n := &Node{
		callbackHandler: callbackHandler,
	}
	cCallbacks := C.ab_callbacks_t{}
	C.set_callbacks(&cCallbacks)
	registeredNodesLock.Lock()
	defer registeredNodesLock.Unlock()
	registrationCounter++
	registeredNodes[registrationCounter] = n
	n.callbacksNum = registrationCounter
	ptr := C.ab_node_create(C.uint64_t(id), C.int(clusterSize), cCallbacks, unsafe.Pointer(&n.callbacksNum))
	listenStr := C.CString(listen)
	defer C.free(unsafe.Pointer(listenStr))
	ret := C.ab_listen(ptr, listenStr)
	if ret < 0 {
		C.ab_destroy(ptr)
		return nil, fmt.Errorf("error listening")
	}
	n.ptr = ptr
	return n, nil
}

func (n *Node) SetCommitted(commit uint64) {
	C.ab_set_committed(n.ptr, C.uint64_t(commit))
}

func (n *Node) Run() error {
	C.ab_run(n.ptr)
	return fmt.Errorf("failed")
}

func (n *Node) Append(data string) error {
	n.appendResult = make(chan int)
	cData := C.CString(data)
	defer C.free(unsafe.Pointer(cData))
	C.append_go_gateway(n.ptr, cData, C.int(len(data)), C.int(n.callbacksNum))
	result := <-n.appendResult
	n.appendResult = nil
	if result == 0 {
		return nil
	}
	return fmt.Errorf("append failed :(")
}

func (n *Node) ConfirmAppend(round uint64) {
	fmt.Println("confirm append")
	C.ab_confirm_append(n.ptr, C.uint64_t(round))
}

func (n *Node) AddPeer(address string) error {
	cAddr := C.CString(address)
	defer C.free(unsafe.Pointer(cAddr))
	ret := C.ab_connect_to_peer(n.ptr, cAddr)
	if ret < 0 {
		return fmt.Errorf("error adding peer")
	}
	return nil
}

//export on_append_go_cb
func on_append_go_cb(round C.uint64_t, str *C.char, length C.int, p unsafe.Pointer) {
	i := *(*int)(p)
	registeredNodesLock.RLock()
	defer registeredNodesLock.RUnlock()
	node := registeredNodes[i]
	node.callbackHandler.OnAppend(uint64(round), C.GoStringN(str, length))
}

//export on_commit_go_cb
func on_commit_go_cb(round C.uint64_t, p unsafe.Pointer) {
	i := *(*int)(p)
	registeredNodesLock.RLock()
	defer registeredNodesLock.RUnlock()
	node := registeredNodes[i]
	node.callbackHandler.OnCommit(uint64(round))
}

//export gained_leadership_go_cb
func gained_leadership_go_cb(p unsafe.Pointer) {
	i := *(*int)(p)
	registeredNodesLock.RLock()
	defer registeredNodesLock.RUnlock()
	node := registeredNodes[i]
	node.callbackHandler.GainedLeadership()
}

//export lost_leadership_go_cb
func lost_leadership_go_cb(p unsafe.Pointer) {
	i := *(*int)(p)
	registeredNodesLock.RLock()
	defer registeredNodesLock.RUnlock()
	node := registeredNodes[i]
	node.callbackHandler.LostLeadership()
}

//export on_leader_change_go_cb
func on_leader_change_go_cb(id C.uint64_t, p unsafe.Pointer) {
	i := *(*int)(p)
	registeredNodesLock.RLock()
	defer registeredNodesLock.RUnlock()
	node := registeredNodes[i]
	node.callbackHandler.OnLeaderChange(uint64(id))
}

//export append_go_cb
func append_go_cb(status C.int, p unsafe.Pointer) {
	i := *(*int)(p)
	C.free(p)
	registeredNodesLock.RLock()
	defer registeredNodesLock.RUnlock()
	node := registeredNodes[i]
	if node != nil && node.appendResult != nil {
		node.appendResult <- int(status)
	}
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013 Matt Jibson <matt.jibson@gmail.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package goapp

import (
	"appengine"
	"encoding/json"
	"encoding/xml"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
	"sync"
	"time"

	"appengine/blobstore"
	"appengine/datastore"
	"appengine/taskqueue"
	"appengine/urlfetch"
	mpg "github.com/MiniProfiler/go/miniprofiler_gae"
	"github.com/mjibson/goon"
)

func ImportOpmlTask(c mpg.Context, w http.ResponseWriter, r *http.Request) {
	gn := goon.FromContext(c)
	userid := r.FormValue("user")
	bk := r.FormValue("key")
	fr := blobstore.NewReader(c, appengine.BlobKey(bk))
	data, err := ioutil.ReadAll(fr)
	if err != nil {
		return
	}

	var skip int
	if s, err := strconv.Atoi(r.FormValue("skip")); err == nil {
		skip = s
	}
	c.Debugf("reader import for %v, skip %v", userid, skip)

	var userOpml []*OpmlOutline
	remaining := skip

	var proc func(label string, outlines []*OpmlOutline)
	proc = func(label string, outlines []*OpmlOutline) {
		for _, o := range outlines {
			if o.XmlUrl != "" {
				if remaining > 0 {
					remaining--
				} else if len(userOpml) < IMPORT_LIMIT {
					userOpml = append(userOpml, &OpmlOutline{
						Title:   label,
						Outline: []*OpmlOutline{o},
					})
				}
			}

			if o.Title != "" && len(o.Outline) > 0 {
				proc(o.Title, o.Outline)
			}
		}
	}

	opml := Opml{}
	if err := xml.Unmarshal(data, &opml); err != nil {
		c.Errorf("opml error: %v", err.Error())
		return
	}
	proc("", opml.Outline)

	// todo: refactor below with similar from ImportReaderTask
	wg := sync.WaitGroup{}
	wg.Add(len(userOpml))
	for i := range userOpml {
		go func(i int) {
			o := userOpml[i].Outline[0]
			if err := addFeed(c, userid, userOpml[i]); err != nil {
				c.Warningf("opml import error: %v", err.Error())
				// todo: do something here?
			}
			c.Debugf("opml import: %s, %s", o.Title, o.XmlUrl)
			wg.Done()
		}(i)
	}
	wg.Wait()

	ud := UserData{Id: "data", Parent: gn.Key(&User{Id: userid})}
	if err := gn.RunInTransaction(func(gn *goon.Goon) error {
		gn.Get(&ud)
		mergeUserOpml(&ud, opml.Outline...)
		_, err := gn.Put(&ud)
		return err
	}, nil); err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		c.Errorf("ude update error: %v", err.Error())
		return
	}

	if len(userOpml) == IMPORT_LIMIT {
		task := taskqueue.NewPOSTTask(routeUrl("import-opml-task"), url.Values{
			"key":  {bk},
			"user": {userid},
			"skip": {strconv.Itoa(skip + IMPORT_LIMIT)},
		})
		taskqueue.Add(c, task, "import-reader")
	}
}

const IMPORT_LIMIT = 10

func ImportReaderTask(c mpg.Context, w http.ResponseWriter, r *http.Request) {
	gn := goon.FromContext(c)
	userid := r.FormValue("user")
	bk := r.FormValue("key")
	fr := blobstore.NewReader(c, appengine.BlobKey(bk))
	data, err := ioutil.ReadAll(fr)
	if err != nil {
		return
	}

	var skip int
	if s, err := strconv.Atoi(r.FormValue("skip")); err == nil {
		skip = s
	}

	v := struct {
		Subscriptions []struct {
			Id         string `json:"id"`
			Title      string `json:"title"`
			HtmlUrl    string `json:"htmlUrl"`
			Categories []struct {
				Id    string `json:"id"`
				Label string `json:"label"`
			} `json:"categories"`
		} `json:"subscriptions"`
	}{}
	json.Unmarshal(data, &v)
	c.Debugf("reader import for %v, skip %v, len %v", userid, skip, len(v.Subscriptions))

	end := skip + IMPORT_LIMIT
	if end > len(v.Subscriptions) {
		end = len(v.Subscriptions)
	}

	wg := sync.WaitGroup{}
	wg.Add(end - skip)
	userOpml := make([]*OpmlOutline, end-skip)

	for i := range v.Subscriptions[skip:end] {
		go func(i int) {
			sub := v.Subscriptions[skip+i]
			var label string
			if len(sub.Categories) > 0 {
				label = sub.Categories[0].Label
			}
			outline := &OpmlOutline{
				Title: label,
				Outline: []*OpmlOutline{
					&OpmlOutline{
						XmlUrl: sub.Id[5:],
						Title:  sub.Title,
					},
				},
			}
			userOpml[i] = outline
			if err := addFeed(c, userid, outline); err != nil {
				c.Warningf("reader import error: %v", err.Error())
				// todo: do something here?
			}
			c.Debugf("reader import: %s, %s", sub.Title, sub.Id)
			wg.Done()
		}(i)
	}
	wg.Wait()

	ud := UserData{Id: "data", Parent: gn.Key(&User{Id: userid})}
	if err := gn.RunInTransaction(func(gn *goon.Goon) error {
		gn.Get(&ud)
		mergeUserOpml(&ud, userOpml...)
		_, err := gn.Put(&ud)
		return err
	}, nil); err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		c.Errorf("ude update error: %v", err.Error())
		return
	}

	if end < len(v.Subscriptions) {
		task := taskqueue.NewPOSTTask(routeUrl("import-reader-task"), url.Values{
			"key":  {bk},
			"user": {userid},
			"skip": {strconv.Itoa(skip + IMPORT_LIMIT)},
		})
		taskqueue.Add(c, task, "import-reader")
	} else {
		blobstore.Delete(c, appengine.BlobKey(bk))
	}
}

func UpdateFeeds(c mpg.Context, w http.ResponseWriter, r *http.Request) {
	gn := goon.FromContext(c)
	q := datastore.NewQuery(gn.Key(&Feed{}).Kind()).KeysOnly()
	q = q.Filter("n <=", time.Now())
	retry, _ := strconv.Atoi(r.FormValue("retry"))
	c.Errorf("retry: %v", retry)

	//* iterator
	it := gn.Run(q)
	i := 0
	done := false
	for {
		k, err := it.Next(nil)
		if err == datastore.Done {
			done = true
			break
		} else if err != nil {
			c.Errorf("next error: %v", err.Error())
			break
		}
		t := taskqueue.NewPOSTTask(routeUrl("update-feed"), url.Values{
			"feed": {k.StringID()},
		})
		if _, err := taskqueue.Add(c, t, "update-feed"); err != nil {
			c.Errorf("taskqueue error: %v", err.Error())
		}
		i++
	}
	c.Infof("updating %d feeds", i)
	fmt.Fprintf(w, "updating %d feeds", i)
	if !done {
		time.Sleep(time.Second * time.Duration(i) / 50) // sleep about the time it'll take to process them
		t := taskqueue.NewPOSTTask("/tasks/update-feeds", url.Values{
			"retry": {strconv.Itoa(retry + 1)},
		})
		if _, err := taskqueue.Add(c, t, "update-feeds"); err != nil {
			c.Errorf("taskqueue update feeds error: %v", err.Error())
		}
		c.Errorf("ran update again")
		fmt.Fprintf(w, "\nran update again")
	}
	//*/

	/* get all
	q = q.Limit(1000)
	keys, _ := gn.GetAll(q, nil)
	for _, k := range keys {
		t := taskqueue.NewPOSTTask(routeUrl("update-feed"), url.Values{
			"feed": {k.StringID()},
		})
		if _, err := taskqueue.Add(c, t, "update-feed"); err != nil {
			c.Errorf("taskqueue error: %v", err.Error())
		}
	}
	c.Infof("updating %d feeds", len(keys))
	fmt.Fprintf(w, "updating %d feeds", len(keys))
	//*/
}

func fetchFeed(c mpg.Context, origUrl, fetchUrl string) (*Feed, []*Story) {
	u, err := url.Parse(fetchUrl)
	if err == nil && u.Scheme == "" {
		u.Scheme = "http"
		origUrl = u.String()
		fetchUrl = origUrl
	}

	cl := &http.Client{
		Transport: &urlfetch.Transport{
			Context:  c,
			Deadline: time.Minute,
		},
	}
	if resp, err := cl.Get(fetchUrl); err == nil && resp.StatusCode == http.StatusOK {
		defer resp.Body.Close()
		b, _ := ioutil.ReadAll(resp.Body)
		if autoUrl, err := Autodiscover(b); err == nil && origUrl == fetchUrl {
			if autoU, err := url.Parse(autoUrl); err == nil {
				if autoU.Scheme == "" {
					autoU.Scheme = u.Scheme
				}
				if autoU.Host == "" {
					autoU.Host = u.Host
				}
				autoUrl = autoU.String()
			}
			return fetchFeed(c, origUrl, autoUrl)
		}
		return ParseFeed(c, origUrl, b)
	} else if err != nil {
		c.Warningf("fetch feed error: %s", err.Error())
	} else {
		c.Warningf("fetch feed error: status code: %s", resp.Status)
	}
	return nil, nil
}

func updateFeed(c mpg.Context, url string, feed *Feed, stories []*Story) error {
	gn := goon.FromContext(c)
	f := Feed{Url: url}
	if err := gn.Get(&f); err != nil {
		return errors.New(fmt.Sprintf("feed not found: %s", url))
	}

	// Compare the feed's listed update to the story's update.
	// Note: these may not be accurate, hence, only compare them to each other,
	// since they should have the same relative error.
	storyDate := f.Updated

	hasUpdated := !feed.Updated.IsZero()
	isFeedUpdated := f.Updated == feed.Updated
	if !hasUpdated {
		feed.Updated = f.Updated
	}
	feed.Date = f.Date
	f = *feed

	if hasUpdated && isFeedUpdated {
		c.Infof("feed %s already updated to %v, putting", url, feed.Updated)
		f.Updated = time.Now()
		gn.Put(&f)
		return nil
	}

	c.Debugf("hasUpdate: %v, isFeedUpdated: %v, storyDate: %v", hasUpdated, isFeedUpdated, storyDate)

	var newStories []*Story
	for _, s := range stories {
		if s.Updated.IsZero() || !s.Updated.Before(storyDate) {
			newStories = append(newStories, s)
		}
	}
	c.Debugf("%v possible stories to update", len(newStories))

	puts := []interface{}{&f}

	// find non existant stories
	fk := gn.Key(&f)
	getStories := make([]*Story, len(newStories))
	for i, s := range newStories {
		getStories[i] = &Story{Id: s.Id, Parent: fk}
	}
	err := gn.GetMulti(getStories)
	var updateStories []*Story
	for i, s := range getStories {
		if goon.NotFound(err, i) {
			updateStories = append(updateStories, newStories[i])
		} else if !newStories[i].Updated.IsZero() && !newStories[i].Updated.Equal(s.Updated) {
			newStories[i].Created = s.Created
			newStories[i].Published = s.Published
			updateStories = append(updateStories, newStories[i])
		}
	}
	c.Debugf("%v update stories", len(updateStories))

	for _, s := range updateStories {
		puts = append(puts, s)
		gn.Put(&StoryContent{
			Id:      1,
			Parent:  gn.Key(s),
			Content: s.content,
		})
	}

	c.Debugf("putting %v entities", len(puts))
	if len(puts) > 1 {
		f.Date = time.Now()
		if !hasUpdated {
			f.Updated = f.Date
		}
	}
	gn.PutMulti(puts)

	return nil
}

func UpdateFeed(c mpg.Context, w http.ResponseWriter, r *http.Request) {
	gn := goon.FromContext(c)
	url := r.FormValue("feed")
	c.Debugf("update feed %s", url)
	f := Feed{Url: url}
	if err := gn.Get(&f); err == datastore.ErrNoSuchEntity {
		return
	} else if time.Now().Before(f.NextUpdate) {
		c.Infof("feed %v already updated", url)
		return
	}
	if feed, stories := fetchFeed(c, url, url); feed != nil {
		updateFeed(c, url, feed, stories)
	} else {
		f.Errors++
		v := f.Errors + 1
		const max = 24 * 7
		if v > max {
			v = max
		} else if f.Errors == 1 {
			v = 0
		}
		f.NextUpdate = time.Now().Add(time.Hour * time.Duration(v))
		gn.Put(&f)
		c.Warningf("error with %v (%v), bump next update to %v", url, f.Errors, f.NextUpdate)
	}
}
<commit_msg>Return an error if there is one<commit_after>/*
 * Copyright (c) 2013 Matt Jibson <matt.jibson@gmail.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package goapp

import (
	"appengine"
	"encoding/json"
	"encoding/xml"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
	"sync"
	"time"

	"appengine/blobstore"
	"appengine/datastore"
	"appengine/taskqueue"
	"appengine/urlfetch"
	mpg "github.com/MiniProfiler/go/miniprofiler_gae"
	"github.com/mjibson/goon"
)

func ImportOpmlTask(c mpg.Context, w http.ResponseWriter, r *http.Request) {
	gn := goon.FromContext(c)
	userid := r.FormValue("user")
	bk := r.FormValue("key")
	fr := blobstore.NewReader(c, appengine.BlobKey(bk))
	data, err := ioutil.ReadAll(fr)
	if err != nil {
		return
	}

	var skip int
	if s, err := strconv.Atoi(r.FormValue("skip")); err == nil {
		skip = s
	}
	c.Debugf("reader import for %v, skip %v", userid, skip)

	var userOpml []*OpmlOutline
	remaining := skip

	var proc func(label string, outlines []*OpmlOutline)
	proc = func(label string, outlines []*OpmlOutline) {
		for _, o := range outlines {
			if o.XmlUrl != "" {
				if remaining > 0 {
					remaining--
				} else if len(userOpml) < IMPORT_LIMIT {
					userOpml = append(userOpml, &OpmlOutline{
						Title:   label,
						Outline: []*OpmlOutline{o},
					})
				}
			}

			if o.Title != "" && len(o.Outline) > 0 {
				proc(o.Title, o.Outline)
			}
		}
	}

	opml := Opml{}
	if err := xml.Unmarshal(data, &opml); err != nil {
		c.Errorf("opml error: %v", err.Error())
		return
	}
	proc("", opml.Outline)

	// todo: refactor below with similar from ImportReaderTask
	wg := sync.WaitGroup{}
	wg.Add(len(userOpml))
	for i := range userOpml {
		go func(i int) {
			o := userOpml[i].Outline[0]
			if err := addFeed(c, userid, userOpml[i]); err != nil {
				c.Warningf("opml import error: %v", err.Error())
				// todo: do something here?
			}
			c.Debugf("opml import: %s, %s", o.Title, o.XmlUrl)
			wg.Done()
		}(i)
	}
	wg.Wait()

	ud := UserData{Id: "data", Parent: gn.Key(&User{Id: userid})}
	if err := gn.RunInTransaction(func(gn *goon.Goon) error {
		gn.Get(&ud)
		mergeUserOpml(&ud, opml.Outline...)
		_, err := gn.Put(&ud)
		return err
	}, nil); err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		c.Errorf("ude update error: %v", err.Error())
		return
	}

	if len(userOpml) == IMPORT_LIMIT {
		task := taskqueue.NewPOSTTask(routeUrl("import-opml-task"), url.Values{
			"key":  {bk},
			"user": {userid},
			"skip": {strconv.Itoa(skip + IMPORT_LIMIT)},
		})
		taskqueue.Add(c, task, "import-reader")
	}
}

const IMPORT_LIMIT = 10

func ImportReaderTask(c mpg.Context, w http.ResponseWriter, r *http.Request) {
	gn := goon.FromContext(c)
	userid := r.FormValue("user")
	bk := r.FormValue("key")
	fr := blobstore.NewReader(c, appengine.BlobKey(bk))
	data, err := ioutil.ReadAll(fr)
	if err != nil {
		return
	}

	var skip int
	if s, err := strconv.Atoi(r.FormValue("skip")); err == nil {
		skip = s
	}

	v := struct {
		Subscriptions []struct {
			Id         string `json:"id"`
			Title      string `json:"title"`
			HtmlUrl    string `json:"htmlUrl"`
			Categories []struct {
				Id    string `json:"id"`
				Label string `json:"label"`
			} `json:"categories"`
		} `json:"subscriptions"`
	}{}
	json.Unmarshal(data, &v)
	c.Debugf("reader import for %v, skip %v, len %v", userid, skip, len(v.Subscriptions))

	end := skip + IMPORT_LIMIT
	if end > len(v.Subscriptions) {
		end = len(v.Subscriptions)
	}

	wg := sync.WaitGroup{}
	wg.Add(end - skip)
	userOpml := make([]*OpmlOutline, end-skip)

	for i := range v.Subscriptions[skip:end] {
		go func(i int) {
			sub := v.Subscriptions[skip+i]
			var label string
			if len(sub.Categories) > 0 {
				label = sub.Categories[0].Label
			}
			outline := &OpmlOutline{
				Title: label,
				Outline: []*OpmlOutline{
					&OpmlOutline{
						XmlUrl: sub.Id[5:],
						Title:  sub.Title,
					},
				},
			}
			userOpml[i] = outline
			if err := addFeed(c, userid, outline); err != nil {
				c.Warningf("reader import error: %v", err.Error())
				// todo: do something here?
			}
			c.Debugf("reader import: %s, %s", sub.Title, sub.Id)
			wg.Done()
		}(i)
	}
	wg.Wait()

	ud := UserData{Id: "data", Parent: gn.Key(&User{Id: userid})}
	if err := gn.RunInTransaction(func(gn *goon.Goon) error {
		gn.Get(&ud)
		mergeUserOpml(&ud, userOpml...)
		_, err := gn.Put(&ud)
		return err
	}, nil); err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		c.Errorf("ude update error: %v", err.Error())
		return
	}

	if end < len(v.Subscriptions) {
		task := taskqueue.NewPOSTTask(routeUrl("import-reader-task"), url.Values{
			"key":  {bk},
			"user": {userid},
			"skip": {strconv.Itoa(skip + IMPORT_LIMIT)},
		})
		taskqueue.Add(c, task, "import-reader")
	} else {
		blobstore.Delete(c, appengine.BlobKey(bk))
	}
}

func UpdateFeeds(c mpg.Context, w http.ResponseWriter, r *http.Request) {
	gn := goon.FromContext(c)
	q := datastore.NewQuery(gn.Key(&Feed{}).Kind()).KeysOnly()
	q = q.Filter("n <=", time.Now())
	retry, _ := strconv.Atoi(r.FormValue("retry"))
	c.Errorf("retry: %v", retry)

	//* iterator
	it := gn.Run(q)
	i := 0
	done := false
	for {
		k, err := it.Next(nil)
		if err == datastore.Done {
			done = true
			break
		} else if err != nil {
			c.Errorf("next error: %v", err.Error())
			break
		}
		t := taskqueue.NewPOSTTask(routeUrl("update-feed"), url.Values{
			"feed": {k.StringID()},
		})
		if _, err := taskqueue.Add(c, t, "update-feed"); err != nil {
			c.Errorf("taskqueue error: %v", err.Error())
		}
		i++
	}
	c.Infof("updating %d feeds", i)
	fmt.Fprintf(w, "updating %d feeds", i)
	if !done {
		time.Sleep(time.Second * time.Duration(i) / 50) // sleep about the time it'll take to process them
		t := taskqueue.NewPOSTTask("/tasks/update-feeds", url.Values{
			"retry": {strconv.Itoa(retry + 1)},
		})
		if _, err := taskqueue.Add(c, t, "update-feeds"); err != nil {
			c.Errorf("taskqueue update feeds error: %v", err.Error())
		}
		c.Errorf("ran update again")
		fmt.Fprintf(w, "\nran update again")
	}
	//*/

	/* get all
	q = q.Limit(1000)
	keys, _ := gn.GetAll(q, nil)
	for _, k := range keys {
		t := taskqueue.NewPOSTTask(routeUrl("update-feed"), url.Values{
			"feed": {k.StringID()},
		})
		if _, err := taskqueue.Add(c, t, "update-feed"); err != nil {
			c.Errorf("taskqueue error: %v", err.Error())
		}
	}
	c.Infof("updating %d feeds", len(keys))
	fmt.Fprintf(w, "updating %d feeds", len(keys))
	//*/
}

func fetchFeed(c mpg.Context, origUrl, fetchUrl string) (*Feed, []*Story) {
	u, err := url.Parse(fetchUrl)
	if err == nil && u.Scheme == "" {
		u.Scheme = "http"
		origUrl = u.String()
		fetchUrl = origUrl
	}

	cl := &http.Client{
		Transport: &urlfetch.Transport{
			Context:  c,
			Deadline: time.Minute,
		},
	}
	if resp, err := cl.Get(fetchUrl); err == nil && resp.StatusCode == http.StatusOK {
		defer resp.Body.Close()
		b, _ := ioutil.ReadAll(resp.Body)
		if autoUrl, err := Autodiscover(b); err == nil && origUrl == fetchUrl {
			if autoU, err := url.Parse(autoUrl); err == nil {
				if autoU.Scheme == "" {
					autoU.Scheme = u.Scheme
				}
				if autoU.Host == "" {
					autoU.Host = u.Host
				}
				autoUrl = autoU.String()
			}
			return fetchFeed(c, origUrl, autoUrl)
		}
		return ParseFeed(c, origUrl, b)
	} else if err != nil {
		c.Warningf("fetch feed error: %s", err.Error())
	} else {
		c.Warningf("fetch feed error: status code: %s", resp.Status)
	}
	return nil, nil
}

func updateFeed(c mpg.Context, url string, feed *Feed, stories []*Story) error {
	gn := goon.FromContext(c)
	f := Feed{Url: url}
	if err := gn.Get(&f); err != nil {
		return errors.New(fmt.Sprintf("feed not found: %s", url))
	}

	// Compare the feed's listed update to the story's update.
	// Note: these may not be accurate, hence, only compare them to each other,
	// since they should have the same relative error.
	storyDate := f.Updated

	hasUpdated := !feed.Updated.IsZero()
	isFeedUpdated := f.Updated == feed.Updated
	if !hasUpdated {
		feed.Updated = f.Updated
	}
	feed.Date = f.Date
	f = *feed

	if hasUpdated && isFeedUpdated {
		c.Infof("feed %s already updated to %v, putting", url, feed.Updated)
		f.Updated = time.Now()
		gn.Put(&f)
		return nil
	}

	c.Debugf("hasUpdate: %v, isFeedUpdated: %v, storyDate: %v", hasUpdated, isFeedUpdated, storyDate)

	var newStories []*Story
	for _, s := range stories {
		if s.Updated.IsZero() || !s.Updated.Before(storyDate) {
			newStories = append(newStories, s)
		}
	}
	c.Debugf("%v possible stories to update", len(newStories))

	puts := []interface{}{&f}

	// find non existant stories
	fk := gn.Key(&f)
	getStories := make([]*Story, len(newStories))
	for i, s := range newStories {
		getStories[i] = &Story{Id: s.Id, Parent: fk}
	}
	err := gn.GetMulti(getStories)
	if _, ok := err.(appengine.MultiError); !ok {
		return err
	}
	var updateStories []*Story
	for i, s := range getStories {
		if goon.NotFound(err, i) {
			updateStories = append(updateStories, newStories[i])
		} else if !newStories[i].Updated.IsZero() && !newStories[i].Updated.Equal(s.Updated) {
			newStories[i].Created = s.Created
			newStories[i].Published = s.Published
			updateStories = append(updateStories, newStories[i])
		}
	}
	c.Debugf("%v update stories", len(updateStories))

	for _, s := range updateStories {
		puts = append(puts, s)
		gn.Put(&StoryContent{
			Id:      1,
			Parent:  gn.Key(s),
			Content: s.content,
		})
	}

	c.Debugf("putting %v entities", len(puts))
	if len(puts) > 1 {
		f.Date = time.Now()
		if !hasUpdated {
			f.Updated = f.Date
		}
	}
	gn.PutMulti(puts)

	return nil
}

func UpdateFeed(c mpg.Context, w http.ResponseWriter, r *http.Request) {
	gn := goon.FromContext(c)
	url := r.FormValue("feed")
	c.Debugf("update feed %s", url)
	f := Feed{Url: url}
	if err := gn.Get(&f); err == datastore.ErrNoSuchEntity {
		return
	} else if time.Now().Before(f.NextUpdate) {
		c.Infof("feed %v already updated", url)
		return
	}
	if feed, stories := fetchFeed(c, url, url); feed != nil {
		updateFeed(c, url, feed, stories)
	} else {
		f.Errors++
		v := f.Errors + 1
		const max = 24 * 7
		if v > max {
			v = max
		} else if f.Errors == 1 {
			v = 0
		}
		f.NextUpdate = time.Now().Add(time.Hour * time.Duration(v))
		gn.Put(&f)
		c.Warningf("error with %v (%v), bump next update to %v", url, f.Errors, f.NextUpdate)
	}
}
<|endoftext|>


<commit_before>// package name: libgodot
package godot

/*
#cgo CXXFLAGS: -I/usr/local/include -std=c11
#cgo LDFLAGS: -Wl,-unresolved-symbols=ignore-all
#include <stddef.h>
#include <stdlib.h>
#include <godot_nativescript.h>

// Type definitions for any function pointers. Some of these are not defined in
// the godot headers when they are part of a typedef struct.
typedef void (*create_func)(godot_object *, void *);
typedef void (*destroy_func)(godot_object *, void *, void *);
typedef void (*free_func)(void *);
typedef godot_variant (*method)(godot_object *, void *, void *, int, godot_variant **);

// Forward declarations of gateway functions defined in cgateway.go.
void *go_create_func_cgo(godot_object *, void *); // Forward declaration.
void *go_destroy_func_cgo(godot_object *, void *); // Forward declaration.
void *go_free_func_cgo(void *); // Forward declaration.
godot_variant go_method_func_cgo(godot_object *obj, void *method_data, void *user_data, int num_args, godot_variant **args);
*/
import "C"

import (
	"log"
	"reflect"
	"strings"
	"unsafe"
)

const (
	tagPrefix        = "godot"
	defaultBaseClass = "Node"
)

// Exposed is a base structure for any structure that will be exposed to Godot.
// You should embed this structure in your own custom structs.
type Exposed struct {
	GDParent string `godot:"_inherits"`
}

// ClassConstructor is any function that will build and return a class to be registered
// with Godot.
type ClassConstructor func() interface{}

// function signature for Godot classes
type gdMethod func(godotObject *C.godot_object, methodData unsafe.Pointer, userData unsafe.Pointer, numArgs C.int, args **C.godot_variant)

type Method func(godotObject *Object, methodData, userData interface{}, numArgs int, args []*Variant)

/** Library entry point **/
// godot_gdnative_init is the library entry point. When the library is loaded
// this method will be called by Godot.
//export godot_gdnative_init
func godot_gdnative_init(options *C.godot_gdnative_init_options) {
	log.SetFlags(log.LstdFlags | log.Lshortfile)
	log.SetOutput(Log)
	log.Println("Initializing Go library.")

	// Translate the C struct into a Go struct.
	goOptions := &GodotGDNativeInitOptions{
		InEditor:      bool(options.in_editor),
		CoreAPIHash:   uint64(options.core_api_hash),
		EditorAPIHash: uint64(options.editor_api_hash),
		NoAPIHash:     uint64(options.no_api_hash),
	}

	// Call user defined init if it was set.
	if godotGDNativeInit != nil {
		godotGDNativeInit(goOptions)
	}
}

/** Library de-initialization **/
// godot_gdnative_terminate is the library's de-initialization method. When
// Godot unloads the library, this method will be called.
//export godot_gdnative_terminate
func godot_gdnative_terminate(options *C.godot_gdnative_terminate_options) {
	log.Println("De-initializing Go library.")
}

/** Script entry (Registering all the classes and stuff) **/
// godot_nativescript_init is the script's entrypoint. It is called by Godot
// when a script is loaded. It is responsible for registering all the classes
// and stuff. The `unsafe.Pointer` type is used to represent a null C pointer.
//export godot_nativescript_init
func godot_nativescript_init(desc unsafe.Pointer) {
	log.Println("Initializing script")

	// Loop through our registered classes and register them with the Godot API.
	for _, constructor := range godotConstructorsToRegister {
		// Use the constructor to build a class to inspect the given structure.
		class := constructor()

		// Get the type of the given struct, and get its name as a string and C string.
		classType := reflect.TypeOf(class)
		classString := strings.Replace(classType.String(), "*main.", "", 1) // TODO: Just remove * instead.
		classCString := C.CString(classString)
		log.Println("Registering class:", classString)

		// Add the type to our internal type registry. This is used so the constructor
		// function can create the correct kind of struct.
		constructorRegistry[classString] = constructor
		typeRegistry[classString] = classType

		// Look at the struct tags for "_inherits" to get the base class.
		baseClass := defaultBaseClass
		classValuePtr := reflect.ValueOf(class)
		classValue := classValuePtr.Elem()
		log.Println("  Found", classValue.NumField(), "struct fields.")
		for i := 0; i < classValue.NumField(); i++ {
			// Get the struct field.
			field := classValue.Field(i)

			// Ignore fields that don't have the same type as a string
			if field.Type() != reflect.TypeOf("") {
				continue
			}

			// Check if the struct field tag is "inherits"
			fieldTag, _ := classValue.Type().Field(i).Tag.Lookup(tagPrefix)
			if fieldTag != "_inherits" {
				continue
			}

			baseClass = field.Interface().(string)
			log.Println("  Found inheritance in struct:", baseClass)
		}
		baseClassCString := C.CString(baseClass)
		log.Println("  Using Base Class:", baseClass)

		// TODO: Look at the struct tags for methods to register.
		// TODO: OR look for methods that follow the GodotMethod type.

		// Set up our create function C struct
		var createFunc C.godot_instance_create_func
		var destroyFunc C.godot_instance_destroy_func

		// *** CREATE FUNC ***
		// Use a pointer to our gateway function.
		// GDCALLINGCONV void *(*create_func)(godot_object *, void *);
		createFunc.create_func = (C.create_func)(unsafe.Pointer(C.go_create_func_cgo))
		// void *method_data;
		createFunc.method_data = unsafe.Pointer(classCString)
		// GDCALLINGCONV void (*free_func)(void *);
		createFunc.free_func = (C.free_func)(unsafe.Pointer(C.go_free_func_cgo))

		// *** DESTROY FUNC ***
		// GDCALLINGCONV void (*destroy_func)(godot_object *, void *, void *);
		destroyFunc.destroy_func = (C.destroy_func)(unsafe.Pointer(C.go_destroy_func_cgo))
		// void *method_data;
		destroyFunc.method_data = unsafe.Pointer(classCString)
		// GDCALLINGCONV void (*free_func)(void *);
		destroyFunc.free_func = (C.free_func)(unsafe.Pointer(C.go_free_func_cgo))

		// Register our class.
		C.godot_nativescript_register_class(desc, classCString, baseClassCString, createFunc, destroyFunc)

		// TODO: Register the methods of the class.
		// Loop through our class's methods that are attached to it.
		log.Println("  Looking at methods:")
		log.Println("    Found", classType.NumMethod(), "methods")
		for i := 0; i < classType.NumMethod(); i++ {
			classMethod := classType.Method(i)
			log.Println("  Found method:", classMethod.Name)

			// Check to see if the method's name is a special Godot method.
			methodString := classMethod.Name
			if methodName, ok := methodMap[classMethod.Name]; ok {
				log.Println("    Mapped method to:", methodName)
				methodString = methodName
			}

			// Set up registering a method
			var method C.godot_instance_method

			// *** METHOD STRUCTURE ***
			// GDCALLINGCONV godot_variant (*method)(godot_object *, void *, void *, int, godot_variant **);
			method.method = (C.method)(unsafe.Pointer(C.go_method_func_cgo))
			// void *method_data;
			method.method_data = unsafe.Pointer(classCString)
			// GDCALLINGCONV void (*free_func)(void *);
			method.free_func = (C.free_func)(unsafe.Pointer(C.go_free_func_cgo))

			// Set up the method attributes.
			var attr C.godot_method_attributes
			attr.rpc_type = C.GODOT_METHOD_RPC_MODE_DISABLED

			// Set up the method name
			methodCString := C.CString(methodString)

			// Register a method.
			C.godot_nativescript_register_method(desc, classCString, methodCString, attr, method)
		}

	}
}

// This is a native Go function that is callable from C. It is called by the
// gateway functions defined in cgateway.go.
//export go_create_func
func go_create_func(godotObject *C.godot_object, methodData unsafe.Pointer) {
	// Cast our pointer to a *char, so we can cast it to a Go string.
	str := (*C.char)(methodData)
	className := C.GoString(str)
	log.Println("Create function called for:", className)

	// Look up our class constructor by its class name in the registry.
	constructor := constructorRegistry[className]

	// Create a new instance of the object.
	class := constructor()
	log.Println("Created new object instance:", class)
}

// This is a native Go function that is callable from C. It is called by the
// gateway functions defined in cgateway.go.
//export go_destroy_func
func go_destroy_func(godotObject *C.godot_object, methodData unsafe.Pointer, userData unsafe.Pointer) {
	log.Println("Destroy function called!")
}

//export go_free_func
func go_free_func(methodData unsafe.Pointer) {
	log.Println("Free function called!")
}

//godot_variant go_method_func_cgo(godot_object *obj, void *method_data, void *user_data, int num_args, godot_variant **args)
//export go_method_func
func go_method_func(godotObject *C.godot_object, methodData unsafe.Pointer, userData unsafe.Pointer, numArgs C.int, args **C.godot_variant) C.godot_variant {
	log.Println("Method was called!")
	log.Println("  godotObject:", godotObject)
	log.Println("  methodData:", methodData)
	log.Println("  userData:", userData)
	log.Println("  numArgs:", int(numArgs))
	log.Println("  args:", args)

	if int(numArgs) > 500 {
		panic("Wtf, 500+ arguments?")
	}

	// Create a slice of godot_variant arguments
	argsSlice := []*C.godot_variant{}

	// Get the size of each godot_variant object pointer.
	size := unsafe.Sizeof(*args)

	// If we have arguments, append the first argument.
	if int(numArgs) > 0 {
		argsSlice = append(argsSlice, *args)

		// Loop through all our arguments.
		for i := 0; i < int(numArgs); i++ {
			// Convert the pointer into a uintptr so we can perform artithmetic on it.
			arrayPtr := uintptr(unsafe.Pointer(args))

			// Add the size of the godot_variant pointer to our array pointer to get the position
			// of the next argument.
			arg := (*C.godot_variant)(unsafe.Pointer(arrayPtr + size))

			// Check to see what type this variant is
			variantType := C.godot_variant_get_type(arg)
			log.Println("Argument variant type:", variantType)

			// Append the argument to our slice.
			argsSlice = append(argsSlice, arg)
		}
	}

	var ret C.godot_variant
	C.godot_variant_new_nil(&ret)

	return ret
}
<commit_msg>Continue work on implementing godot methods<commit_after>// package name: libgodot
package godot

/*
#cgo CXXFLAGS: -I/usr/local/include -std=c11
#cgo LDFLAGS: -Wl,-unresolved-symbols=ignore-all
#include <stddef.h>
#include <stdlib.h>
#include <godot_nativescript.h>

// Type definitions for any function pointers. Some of these are not defined in
// the godot headers when they are part of a typedef struct.
typedef void (*create_func)(godot_object *, void *);
typedef void (*destroy_func)(godot_object *, void *, void *);
typedef void (*free_func)(void *);
typedef godot_variant (*method)(godot_object *, void *, void *, int, godot_variant **);

// Forward declarations of gateway functions defined in cgateway.go.
void *go_create_func_cgo(godot_object *, void *); // Forward declaration.
void *go_destroy_func_cgo(godot_object *, void *); // Forward declaration.
void *go_free_func_cgo(void *); // Forward declaration.
godot_variant go_method_func_cgo(godot_object *obj, void *method_data, void *user_data, int num_args, godot_variant **args);
*/
import "C"

import (
	"fmt"
	"log"
	"reflect"
	"strings"
	"unsafe"
)

const (
	tagPrefix        = "godot"
	defaultBaseClass = "Node"
)

// Exposed is a base structure for any structure that will be exposed to Godot.
// You should embed this structure in your own custom structs.
type Exposed struct {
	GDParent string `godot:"_inherits"`
}

// ClassConstructor is any function that will build and return a class to be registered
// with Godot.
type ClassConstructor func() interface{}

// function signature for Godot classes
type gdMethod func(godotObject *C.godot_object, methodData unsafe.Pointer, userData unsafe.Pointer, numArgs C.int, args **C.godot_variant)

type Method func(godotObject *Object, methodData, userData interface{}, numArgs int, args []*Variant)

/** Library entry point **/
// godot_gdnative_init is the library entry point. When the library is loaded
// this method will be called by Godot.
//export godot_gdnative_init
func godot_gdnative_init(options *C.godot_gdnative_init_options) {
	log.SetFlags(log.LstdFlags | log.Lshortfile)
	log.SetOutput(Log)
	log.Println("Initializing Go library.")

	// Translate the C struct into a Go struct.
	goOptions := &GodotGDNativeInitOptions{
		InEditor:      bool(options.in_editor),
		CoreAPIHash:   uint64(options.core_api_hash),
		EditorAPIHash: uint64(options.editor_api_hash),
		NoAPIHash:     uint64(options.no_api_hash),
	}

	// Call user defined init if it was set.
	if godotGDNativeInit != nil {
		godotGDNativeInit(goOptions)
	}
}

/** Library de-initialization **/
// godot_gdnative_terminate is the library's de-initialization method. When
// Godot unloads the library, this method will be called.
//export godot_gdnative_terminate
func godot_gdnative_terminate(options *C.godot_gdnative_terminate_options) {
	log.Println("De-initializing Go library.")
}

/** Script entry (Registering all the classes and stuff) **/
// godot_nativescript_init is the script's entrypoint. It is called by Godot
// when a script is loaded. It is responsible for registering all the classes
// and stuff. The `unsafe.Pointer` type is used to represent a null C pointer.
//export godot_nativescript_init
func godot_nativescript_init(desc unsafe.Pointer) {
	log.Println("Initializing script")

	// Loop through our registered classes and register them with the Godot API.
	for _, constructor := range godotConstructorsToRegister {
		// Use the constructor to build a class to inspect the given structure.
		class := constructor()

		// Get the type of the given struct, and get its name as a string and C string.
		classType := reflect.TypeOf(class)
		classString := strings.Replace(classType.String(), "*main.", "", 1) // TODO: Just remove * instead.
		classCString := C.CString(classString)
		log.Println("Registering class:", classString)

		// Add the type to our internal type registry. This is used so the constructor
		// function can create the correct kind of struct.
		constructorRegistry[classString] = constructor
		typeRegistry[classString] = classType

		// Look at the struct tags for "_inherits" to get the base class.
		baseClass := defaultBaseClass
		classValuePtr := reflect.ValueOf(class)
		classValue := classValuePtr.Elem()
		log.Println("  Found", classValue.NumField(), "struct fields.")
		for i := 0; i < classValue.NumField(); i++ {
			// Get the struct field.
			field := classValue.Field(i)

			// Ignore fields that don't have the same type as a string
			if field.Type() != reflect.TypeOf("") {
				continue
			}

			// Check if the struct field tag is "inherits"
			fieldTag, _ := classValue.Type().Field(i).Tag.Lookup(tagPrefix)
			if fieldTag != "_inherits" {
				continue
			}

			baseClass = field.Interface().(string)
			log.Println("  Found inheritance in struct:", baseClass)
		}
		baseClassCString := C.CString(baseClass)
		log.Println("  Using Base Class:", baseClass)

		// TODO: Look at the struct tags for methods to register.
		// TODO: OR look for methods that follow the GodotMethod type.

		// Set up our create function C struct
		var createFunc C.godot_instance_create_func
		var destroyFunc C.godot_instance_destroy_func

		// *** CREATE FUNC ***
		// Use a pointer to our gateway function.
		// GDCALLINGCONV void *(*create_func)(godot_object *, void *);
		createFunc.create_func = (C.create_func)(unsafe.Pointer(C.go_create_func_cgo))
		// void *method_data;
		createFunc.method_data = unsafe.Pointer(classCString)
		// GDCALLINGCONV void (*free_func)(void *);
		createFunc.free_func = (C.free_func)(unsafe.Pointer(C.go_free_func_cgo))

		// *** DESTROY FUNC ***
		// GDCALLINGCONV void (*destroy_func)(godot_object *, void *, void *);
		destroyFunc.destroy_func = (C.destroy_func)(unsafe.Pointer(C.go_destroy_func_cgo))
		// void *method_data;
		destroyFunc.method_data = unsafe.Pointer(classCString)
		// GDCALLINGCONV void (*free_func)(void *);
		destroyFunc.free_func = (C.free_func)(unsafe.Pointer(C.go_free_func_cgo))

		// Register our class.
		C.godot_nativescript_register_class(desc, classCString, baseClassCString, createFunc, destroyFunc)

		// TODO: Register the methods of the class.
		// Loop through our class's methods that are attached to it.
		log.Println("  Looking at methods:")
		log.Println("    Found", classType.NumMethod(), "methods")
		for i := 0; i < classType.NumMethod(); i++ {
			classMethod := classType.Method(i)
			log.Println("  Found method:", classMethod.Name)

			// Check to see if the method's name is a special Godot method.
			methodString := classMethod.Name
			if methodName, ok := methodMap[classMethod.Name]; ok {
				log.Println("    Mapped method to:", methodName)
				methodString = methodName
			}

			// Set up registering a method
			var method C.godot_instance_method

			// *** METHOD STRUCTURE ***
			// GDCALLINGCONV godot_variant (*method)(godot_object *, void *, void *, int, godot_variant **);
			method.method = (C.method)(unsafe.Pointer(C.go_method_func_cgo))
			// void *method_data;
			method.method_data = unsafe.Pointer(classCString)
			// GDCALLINGCONV void (*free_func)(void *);
			method.free_func = (C.free_func)(unsafe.Pointer(C.go_free_func_cgo))

			// Set up the method attributes.
			var attr C.godot_method_attributes
			attr.rpc_type = C.GODOT_METHOD_RPC_MODE_DISABLED

			// Set up the method name
			methodCString := C.CString(methodString)

			// Register a method.
			C.godot_nativescript_register_method(desc, classCString, methodCString, attr, method)
		}

	}
}

// This is a native Go function that is callable from C. It is called by the
// gateway functions defined in cgateway.go.
//export go_create_func
func go_create_func(godotObject *C.godot_object, methodData unsafe.Pointer) {
	// Cast our pointer to a *char, so we can cast it to a Go string.
	str := (*C.char)(methodData)
	className := C.GoString(str)
	log.Println("Create function called for:", className)

	// Look up our class constructor by its class name in the registry.
	constructor := constructorRegistry[className]

	// Create a new instance of the object.
	class := constructor()
	instanceString := fmt.Sprintf("%p", &class)
	//instanceCString := C.CString(instanceString)
	log.Println("Created new object instance:", class, "with instance address:", instanceString)

	// TODO: Do we modify godotObject to point to our newly constructed class?
	//godotObject = (*C.godot_object)(unsafe.Pointer(instanceCString))
}

// This is a native Go function that is callable from C. It is called by the
// gateway functions defined in cgateway.go.
//export go_destroy_func
func go_destroy_func(godotObject *C.godot_object, methodData unsafe.Pointer, userData unsafe.Pointer) {
	log.Println("Destroy function called!")
}

//export go_free_func
func go_free_func(methodData unsafe.Pointer) {
	log.Println("Free function called!")
}

//godot_variant go_method_func_cgo(godot_object *obj, void *method_data, void *user_data, int num_args, godot_variant **args)
//export go_method_func
func go_method_func(godotObject *C.godot_object, methodData unsafe.Pointer, userData unsafe.Pointer, numArgs C.int, args **C.godot_variant) C.godot_variant {
	log.Println("Method was called!")
	log.Println("  godotObject:", godotObject)
	log.Println("  methodData:", methodData)
	log.Println("  userData:", userData)
	log.Println("  numArgs:", int(numArgs))
	log.Println("  args:", args)

	// TODO: Try and get the object instance?
	//goGodotObject := (*C.char)(unsafe.Pointer(godotObject))
	//log.Println("  Called from instance:", C.GoString(goGodotObject))

	// Create a slice of godot_variant arguments
	argsSlice := []*C.godot_variant{}

	// Get the size of each godot_variant object pointer.
	size := unsafe.Sizeof(*args)

	// Panic if something's wrong.
	if int(numArgs) > 500 {
		panic("Wtf, 500+ arguments?")
	}

	// If we have arguments, append the first argument.
	if int(numArgs) > 0 {
		argsSlice = append(argsSlice, *args)

		// Loop through all our arguments.
		for i := 0; i < int(numArgs); i++ {
			// Convert the pointer into a uintptr so we can perform artithmetic on it.
			arrayPtr := uintptr(unsafe.Pointer(args))

			// Add the size of the godot_variant pointer to our array pointer to get the position
			// of the next argument.
			arg := (*C.godot_variant)(unsafe.Pointer(arrayPtr + size))

			// Check to see what type this variant is
			variantType := C.godot_variant_get_type(arg)
			log.Println("Argument variant type:", variantType)

			// Append the argument to our slice.
			argsSlice = append(argsSlice, arg)
		}
	}

	var ret C.godot_variant
	C.godot_variant_new_nil(&ret)

	return ret
}
<|endoftext|>


<commit_before>package peco

import (
	"testing"
	"unicode/utf8"

	"github.com/mattn/go-runewidth"
	"github.com/nsf/termbox-go"
)

type dummyScreen struct {
	*interceptor
	width  int
	height int
}

func setDummyScreen() (*interceptor, func()) {
	i := newInterceptor()
	old := screen
	guard := func() { screen = old }
	screen = dummyScreen{
		i,
		100,
		100,
	}
	return i, guard
}

func (d dummyScreen) SetCell(x, y int, ch rune, fg, bg termbox.Attribute) {
	d.record("SetCell", interceptorArgs{x, y, ch, fg, bg})
}
func (d dummyScreen) Clear(fg, bg termbox.Attribute) error { return nil }
func (d dummyScreen) Flush() error {
	d.record("Flush", interceptorArgs{})
	return nil
}
func (d dummyScreen) PollEvent() chan termbox.Event { return nil }
func (d dummyScreen) Size() (int, int) {
	return d.width, d.height
}

func TestLayoutType(t *testing.T) {
	layouts := []struct {
		value    LayoutType
		expectOK bool
	}{
		{LayoutTypeTopDown, true},
		{LayoutTypeBottomUp, true},
		{"foobar", false},
	}
	for _, l := range layouts {
		valid := IsValidLayoutType(l.value)
		if valid != l.expectOK {
			t.Errorf("LayoutType %s, expected IsValidLayoutType to return %s, but got %s",
				l.value,
				l.expectOK,
				valid,
			)
		}
	}
}

func TestPrintScreen(t *testing.T) {
	i, guard := setDummyScreen()
	defer guard()

	makeVerifier := func(initX, initY int, fill bool) func(string) {
		return func(msg string) {
			i.reset()
			t.Logf("Checking printScreen(%d, %d, %s, %s)", initX, initY, msg, fill)
			width := utf8.RuneCountInString(msg)
			printScreen(initX, initY, termbox.ColorDefault, termbox.ColorDefault, msg, fill)
			events := i.events["SetCell"]
			if !fill {
				if len(events) != width {
					t.Errorf("Expected %d SetCell events, got %d",
						width,
						len(events),
					)
				}
				return
			}

			// fill == true
			w, _ := screen.Size()
			if rw := runewidth.StringWidth(msg); rw != width {
				w -= rw - width
			}
			if len(events) != w {
				t.Errorf("Expected %d SetCell events, got %d",
					w,
					len(events),
				)
				return
			}
		}
	}

	verify := makeVerifier(0, 0, false)
	verify("Hello, World!")
	verify("日本語")

	verify = makeVerifier(0, 0, true)
	verify("Hello, World!")
	verify("日本語")
}

func TestStatusBar(t *testing.T) {
	i, guard := setDummyScreen()
	defer guard()

	st := NewStatusBar(NewCtx(nil), AnchorBottom, 0)
	st.PrintStatus("Hello, World!", 0)

	events := i.events
	if l := len(events["Flush"]); l != 1 {
		t.Errorf("Expected 1 Flush event, got %d", l)
		return
	}
}
<commit_msg>use a real channel<commit_after>package peco

import (
	"testing"
	"unicode/utf8"

	"github.com/mattn/go-runewidth"
	"github.com/nsf/termbox-go"
)

type dummyScreen struct {
	*interceptor
	width  int
	height int
	pollCh chan termbox.Event
}

func (d *dummyScreen) SendEvent(e termbox.Event) {
	d.pollCh <- e
}

func setDummyScreen() (*interceptor, func()) {
	i := newInterceptor()
	old := screen
	guard := func() { screen = old }
	screen = dummyScreen{
		i,
		100,
		100,
		make(chan termbox.Event, 256), // chan has a biiiig buffer, so we avoid blocking
	}
	return i, guard
}

func (d dummyScreen) SetCell(x, y int, ch rune, fg, bg termbox.Attribute) {
	d.record("SetCell", interceptorArgs{x, y, ch, fg, bg})
}
func (d dummyScreen) Clear(fg, bg termbox.Attribute) error { return nil }
func (d dummyScreen) Flush() error {
	d.record("Flush", interceptorArgs{})
	return nil
}
func (d dummyScreen) PollEvent() chan termbox.Event {
	return d.pollCh
}
func (d dummyScreen) Size() (int, int) {
	return d.width, d.height
}

func TestLayoutType(t *testing.T) {
	layouts := []struct {
		value    LayoutType
		expectOK bool
	}{
		{LayoutTypeTopDown, true},
		{LayoutTypeBottomUp, true},
		{"foobar", false},
	}
	for _, l := range layouts {
		valid := IsValidLayoutType(l.value)
		if valid != l.expectOK {
			t.Errorf("LayoutType %s, expected IsValidLayoutType to return %s, but got %s",
				l.value,
				l.expectOK,
				valid,
			)
		}
	}
}

func TestPrintScreen(t *testing.T) {
	i, guard := setDummyScreen()
	defer guard()

	makeVerifier := func(initX, initY int, fill bool) func(string) {
		return func(msg string) {
			i.reset()
			t.Logf("Checking printScreen(%d, %d, %s, %s)", initX, initY, msg, fill)
			width := utf8.RuneCountInString(msg)
			printScreen(initX, initY, termbox.ColorDefault, termbox.ColorDefault, msg, fill)
			events := i.events["SetCell"]
			if !fill {
				if len(events) != width {
					t.Errorf("Expected %d SetCell events, got %d",
						width,
						len(events),
					)
				}
				return
			}

			// fill == true
			w, _ := screen.Size()
			if rw := runewidth.StringWidth(msg); rw != width {
				w -= rw - width
			}
			if len(events) != w {
				t.Errorf("Expected %d SetCell events, got %d",
					w,
					len(events),
				)
				return
			}
		}
	}

	verify := makeVerifier(0, 0, false)
	verify("Hello, World!")
	verify("日本語")

	verify = makeVerifier(0, 0, true)
	verify("Hello, World!")
	verify("日本語")
}

func TestStatusBar(t *testing.T) {
	i, guard := setDummyScreen()
	defer guard()

	st := NewStatusBar(NewCtx(nil), AnchorBottom, 0)
	st.PrintStatus("Hello, World!", 0)

	events := i.events
	if l := len(events["Flush"]); l != 1 {
		t.Errorf("Expected 1 Flush event, got %d", l)
		return
	}
}
<|endoftext|>


<commit_before>package gopher

import "testing"

func TestNewApp(t *testing.T) {
	app := initialize()
	if app == nil {
		t.Error("Expected to get a pointer to the container, but got nil instead")
	}
}
<commit_msg>Fixed test<commit_after>package gopher

import "testing"

func TestNewApp(t *testing.T) {
	app := Config()
	if app == nil {
		t.Error("Expected to get a pointer to the container, but got nil instead")
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Knative Authors

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.
*/

// This file contains functions which check resources until they
// get into the state desired by the caller or time out.

package duck

import (
	"time"

	k8serrors "k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/client-go/dynamic"
	"knative.dev/pkg/apis"
	duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1"

	"knative.dev/eventing/test/lib/resources"
)

const (
	interval = 1 * time.Second
	timeout  = 2 * time.Minute
)

// WaitForResourceReady polls the status of the MetaResource from client
// every interval until isResourceReady returns `true` indicating
// it is done, returns an error or timeout.
func WaitForResourceReady(dynamicClient dynamic.Interface, obj *resources.MetaResource) error {
	return wait.PollImmediate(interval, timeout, func() (bool, error) {
		untyped, err := GetGenericObject(dynamicClient, obj, &duckv1beta1.KResource{})
		return isResourceReady(untyped, err)
	})
}

// WaitForResourcesReady waits until all the specified resources in the given namespace are ready.
func WaitForResourcesReady(dynamicClient dynamic.Interface, objList *resources.MetaResourceList) error {
	return wait.PollImmediate(interval, timeout, func() (bool, error) {
		untypeds, err := GetGenericObjectList(dynamicClient, objList, &duckv1beta1.KResource{})
		for _, untyped := range untypeds {
			if isReady, err := isResourceReady(untyped, err); !isReady {
				return isReady, err
			}
		}
		return true, nil
	})
}

// isResourceReady leverage duck-type to check if the given MetaResource is in ready state
func isResourceReady(obj runtime.Object, err error) (bool, error) {
	if k8serrors.IsNotFound(err) {
		// Return false as we are not done yet.
		// We swallow the error to keep on polling.
		// It should only happen if we wait for the auto-created resources, like default Broker.
		return false, nil
	} else if err != nil {
		// Return error to stop the polling.
		return false, err
	}

	kr := obj.(*duckv1beta1.KResource)
	ready := kr.Status.GetCondition(apis.ConditionReady)
	return ready != nil && ready.IsTrue(), nil
}
<commit_msg>Use WaitForPodRunning instead of WaitForResourceReady on pods (#4093)<commit_after>/*
Copyright 2019 The Knative Authors

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.
*/

// This file contains functions which check resources until they
// get into the state desired by the caller or time out.

package duck

import (
	"time"

	corev1 "k8s.io/api/core/v1"
	k8serrors "k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/client-go/dynamic"
	"knative.dev/pkg/apis"
	duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1"

	"knative.dev/eventing/test/lib/resources"
)

const (
	interval = 1 * time.Second
	timeout  = 2 * time.Minute
)

// WaitForResourceReady polls the status of the MetaResource from client
// every interval until isResourceReady returns `true` indicating
// it is done, returns an error or timeout.
func WaitForResourceReady(dynamicClient dynamic.Interface, obj *resources.MetaResource) error {
	return wait.PollImmediate(interval, timeout, func() (bool, error) {
		untyped, err := GetGenericObject(dynamicClient, obj, &duckv1beta1.KResource{})
		return isResourceReady(untyped, err)
	})
}

// WaitForResourcesReady waits until all the specified resources in the given namespace are ready.
func WaitForResourcesReady(dynamicClient dynamic.Interface, objList *resources.MetaResourceList) error {
	return wait.PollImmediate(interval, timeout, func() (bool, error) {
		untypeds, err := GetGenericObjectList(dynamicClient, objList, &duckv1beta1.KResource{})
		for _, untyped := range untypeds {
			if isReady, err := isResourceReady(untyped, err); !isReady {
				return isReady, err
			}
		}
		return true, nil
	})
}

// isResourceReady leverage duck-type to check if the given obj is in ready state
func isResourceReady(obj runtime.Object, err error) (bool, error) {
	if k8serrors.IsNotFound(err) {
		// Return false as we are not done yet.
		// We swallow the error to keep on polling.
		// It should only happen if we wait for the auto-created resources, like default Broker.
		return false, nil
	} else if err != nil {
		// Return error to stop the polling.
		return false, err
	}

	if pod, isPod := obj.(*corev1.Pod); isPod {
		return isPodRunning(pod), nil
	}

	kr := obj.(*duckv1beta1.KResource)
	ready := kr.Status.GetCondition(apis.ConditionReady)
	return ready != nil && ready.IsTrue(), nil
}

// isPodRunning will check the status conditions of the pod and return true if it's Running or Succeeded.
func isPodRunning(pod *corev1.Pod) bool {
	return pod.Status.Phase == corev1.PodRunning || pod.Status.Phase == corev1.PodSucceeded
}
<|endoftext|>


<commit_before>// +build linux,amd64
// run -race

// Copyright 2020 The Go 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 main

import (
	"fmt"
	"testing"
	"unsafe"
)

var buf [2]byte
var x unsafe.Pointer = unsafe.Pointer(&buf[0])

func main() {
	n := testing.AllocsPerRun(1000, func() {
		x = unsafe.Pointer(uintptr(x) + 1)
		x = unsafe.Pointer(uintptr(x) - 1)
	})
	if n > 0 {
		panic(fmt.Sprintf("too many allocations; want 0 got %f", n))
	}
}
<commit_msg>test: disable test for #36516 when cgo is not enabled<commit_after>// +build cgo,linux,amd64
// run -race

// Copyright 2020 The Go 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 main

import (
	"fmt"
	"testing"
	"unsafe"
)

var buf [2]byte
var x unsafe.Pointer = unsafe.Pointer(&buf[0])

func main() {
	n := testing.AllocsPerRun(1000, func() {
		x = unsafe.Pointer(uintptr(x) + 1)
		x = unsafe.Pointer(uintptr(x) - 1)
	})
	if n > 0 {
		panic(fmt.Sprintf("too many allocations; want 0 got %f", n))
	}
}
<|endoftext|>