Пример #1
0
func TestRetryLimit(t *testing.T) {
	is := is.New(t)
	err := try.Do(func(attempt int) (bool, error) {
		return true, errors.New("nope")
	})
	is.OK(err)
	is.Equal(try.IsMaxRetries(err), true)
}
Пример #2
0
func TestTryDoSuccessful(t *testing.T) {
	is := is.New(t)
	callCount := 0
	err := try.Do(func(attempt int) (bool, error) {
		callCount++
		return attempt < 5, nil
	})
	is.NoErr(err)
	is.Equal(callCount, 1)
}
Пример #3
0
func TestTryDoFailed(t *testing.T) {
	is := is.New(t)
	theErr := errors.New("something went wrong")
	callCount := 0
	err := try.Do(func(attempt int) (bool, error) {
		callCount++
		return attempt < 5, theErr
	})
	is.Equal(err, theErr)
	is.Equal(callCount, 5)
}
Пример #4
0
func TestTryExample(t *testing.T) {
	try.MaxRetries = 20
	SomeFunction := func() (string, error) {
		return "", nil
	}
	var value string
	err := try.Do(func(attempt int) (bool, error) {
		var err error
		value, err = SomeFunction()
		return attempt < 5, err // try 5 times
	})
	if err != nil {
		log.Fatalln("error:", err)
	}
}
Пример #5
0
func openInputFile(input string) (*os.File, bool) {
	var r *os.File
	if input == "" {
		r = os.Stdin
	} else {
		err := try.Do(func(attempt int) (bool, error) {
			var err error
			r, err = os.Open(input)
			return attempt < 5, err
		})
		if err != nil {
			Error.Println(err)
			return nil, false
		}
	}
	return r, true
}
Пример #6
0
func TestTryExamplePanic(t *testing.T) {
	SomeFunction := func() (string, error) {
		panic("something went badly wrong")
	}
	var value string
	err := try.Do(func(attempt int) (retry bool, err error) {
		retry = attempt < 5 // try 5 times
		defer func() {
			if r := recover(); r != nil {
				err = errors.New(fmt.Sprintf("panic: %v", r))
			}
		}()
		value, err = SomeFunction()
		return
	})
	if err != nil {
		//log.Fatalln("error:", err)
	}
}
Пример #7
0
func openOutputFile(output string) (*os.File, bool) {
	var w *os.File
	if output == "" {
		w = os.Stdout
	} else {
		if err := os.MkdirAll(path.Dir(output), 0777); err != nil {
			Error.Println(err)
			return nil, false
		}
		err := try.Do(func(attempt int) (bool, error) {
			var err error
			w, err = os.OpenFile(output, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666)
			return attempt < 5, err
		})
		if err != nil {
			Error.Println(err)
			return nil, false
		}
	}
	return w, true
}
Пример #8
0
func TestTryPanics(t *testing.T) {
	is := is.New(t)
	theErr := errors.New("something went wrong")
	callCount := 0
	err := try.Do(func(attempt int) (retry bool, err error) {
		retry = attempt < 5
		defer func() {
			if r := recover(); r != nil {
				err = errors.New(fmt.Sprintf("panic: %v", r))
			}
		}()
		callCount++
		if attempt > 2 {
			panic("I don't like three")
		}
		err = theErr
		return
	})
	is.Equal(err.Error(), "panic: I don't like three")
	is.Equal(callCount, 5)
}
Пример #9
0
func main() {
	user, pass := getCredentials()

	cookieJar, _ := cookiejar.New(nil)
	client := &http.Client{Jar: cookieJar}

	log.Println("Grabbing XSRF Token")
	resp, err := client.Get("https://www.hipchat.com/sign_in")
	if err != nil {
		log.Fatal(err)
	}
	gq := mustParseResponse(resp)

	xsrf, exists := gq.Find("input[name=xsrf_token]").Attr("value")
	if !exists {
		log.Fatal("Can't find xsrf_token")
	}

	log.Println("Logging in")
	resp, err = client.PostForm("https://www.hipchat.com/sign_in", url.Values{
		"xsrf_token":     {xsrf},
		"email":          {user},
		"password":       {pass},
		"stay_signed_in": {"1"},
		"signin":         {"log in"},
	})
	if err != nil {
		log.Fatal(err)
	}

	gq = mustParseResponse(resp)
	if gq.Find("div.aui-page-header-main h1").Size() != 1 {
		log.Fatal("Couldn't find welcome header")
	}

	uid, created, err := extractProfileMetadata(gq)
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("Found user %s created %s", uid, created)

	domain := resp.Request.URL.Host

	log.Println("Listing people")

	// Get first page
	resp, err = client.Get("https://" + domain + "/people")
	if err != nil {
		log.Fatal(err)
	}
	gq = mustParseResponse(resp)

	people := make([]person, 0)

	// Figure out how many pages there are (the next/prev are links in aui-nav, but page 1 is not a link so just subtract one)
	pages := gq.Find("ol.aui-nav a").Size() - 1

	longestName := 0
	for page := 1; page <= pages; page++ {
		gq.Find("a.name").Each(func(i int, s *goquery.Selection) {
			attr, exists := s.Attr("href")
			name := strings.TrimSpace(s.Text())
			signup := parseSignupDate(strings.TrimSpace(s.Parent().Parent().SiblingsFiltered("[headers=date-joined]").Text()))

			if !exists {
				log.Println("Can't find the href for this item")
				return
			}

			longestName = maxInt(longestName, len(name))

			people = append(people, person{
				Name:   name,
				ID:     strings.TrimPrefix(attr, "/people/show/"),
				Joined: signup,
			})
		})

		if page < pages {
			log.Printf("Getting people page %d", page+1)
			resp, err = client.Get("https://" + domain + "/people?p=" + strconv.Itoa(page+1))
			if err != nil {
				log.Fatal(err)
			}
			gq = mustParseResponse(resp)
		}
	}

	// Doesn't seem to on windows
	width, _, _ := terminal.GetSize(0)
	peopleDigits := len(strconv.Itoa(len(people)))

	columns := width / (longestName + peopleDigits + 6)
	if columns < 1 {
		columns = 1
	}

	peopleDigitsString := strconv.Itoa(peopleDigits)
	for i, person := range people {
		index := i + 1 // offset by 1 for input
		padding := strings.Repeat(".", longestName-len(person.Name))
		fmt.Printf("%"+peopleDigitsString+"d:%s%s    ", index, padding, person.Name)
		if index%columns == 0 {
			fmt.Println("")
		}
	}

	// extra newline for when the columns don't line up
	if len(people)%columns != 0 {
		fmt.Println("")
	}

	historiesToDelete := promptPeople(len(people))

	for _, index := range historiesToDelete {
		var currentPerson person
		switch t := index.(type) {
		case int:
			currentPerson = people[t]
		case string:
			log.Printf("Resolving %s to a user", t)
			err = func() error {
				resp, err = client.Get("https://" + domain + "/people/show/" + t)
				if err != nil {
					return fmt.Errorf("Can't lookup %s: %s", t, err)
				}

				gq, err := goquery.NewDocumentFromResponse(resp)
				if err != nil {
					return fmt.Errorf("Can't parse %s: %s", t, err)
				}

				name := gq.Find("div.aui-item h2").Text()
				if name == "" {
					return fmt.Errorf("Can't find name for %s", t)
				}

				_, joined, err := extractProfileMetadata(gq)
				if err != nil {
					return err
				}

				currentPerson = person{
					Name:   name,
					Joined: joined,
					ID:     t,
				}
				return nil
			}()
			if err != nil {
				log.Printf("ERR: %s", err)
				continue
			}
		}
		endDate := created.Add(-1 * 24 * time.Hour)
		if endDate.Before(currentPerson.Joined) {
			endDate = currentPerson.Joined
		}

		for working := time.Now(); working.After(endDate); working = working.Add(-1 * 24 * time.Hour) {
			log.Printf("Checking %s @ %s", currentPerson.Name, working.Format("2006-01-02"))

			err := try.Do(func(attempt int) (bool, error) {
				if attempt > 1 {
					time.Sleep(retryInterval * time.Duration(attempt-1) * time.Second)
				}
				resp, err = client.Get("https://" + domain + "/history/member/" + currentPerson.ID + working.Format("/2006/01/02"))
				if err != nil {
					return attempt < retryLimit, err
				}
				doc, err := goquery.NewDocumentFromResponse(resp)
				if err != nil {
					return attempt < retryLimit, err
				}
				forms := doc.Find("div.delete form")

				if forms.Size() > 0 {
					log.Printf("Found %d entries, deleting...", forms.Size())
				}

				forms.Each(func(i int, form *goquery.Selection) {
					delurl, exists := form.Attr("action")
					if !exists {
						log.Fatal("Can't find action for the delete form")
					}

					values := url.Values{}
					form.Find("input").Each(func(i int, input *goquery.Selection) {
						name, nameExists := input.Attr("name")
						value, valueExists := input.Attr("value")
						if nameExists && valueExists {
							values.Set(name, value)
						}
					})
					err := try.Do(func(attempt int) (bool, error) {
						if attempt > 1 {
							time.Sleep(retryInterval * time.Duration(attempt-1) * time.Second)
						}
						_, err := client.PostForm(delurl, values)
						return attempt < retryLimit, err
					})
					if err != nil {
						log.Fatalln("Tried", retryLimit, "times to delete post:", err)
					}
				})
				return attempt < retryLimit, err
			})

			if err != nil {
				log.Fatalln("Tried", retryLimit, "times to pull day:", err)
			}

		}
	}

}