blob: b44ec05cec58bfaeaf305bb7deed24030de0e6e5 [file] [log] [blame]
/*
Copyright 2019 Google Inc.
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
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package booking contains test logic for booking related endpoints.
package booking
import (
"context"
"log"
"github.com/maps-booking-v3/api"
"github.com/maps-booking-v3/utils"
fpb "github.com/maps-booking-v3/feeds"
mpb "github.com/maps-booking-v3/v3"
)
// GenerateBookings creates bookings from an availability feed.
func GenerateBookings(ctx context.Context, logger *log.Logger, av []*fpb.Availability, stats *utils.TestSummary, conn *utils.HTTPConnection, config *utils.Config) api.Bookings {
logger.Println("no previous bookings to use, acquiring new inventory")
utils.LogFlow(logger, "Generate Fresh Inventory", "Start")
defer utils.LogFlow(logger, "Generate Fresh Inventory", "End")
var out api.Bookings
totalSlots := len(av)
for i, a := range av {
if config.BookingUseBal {
if err := api.BatchAvailabilityLookup(ctx, logger, []*fpb.Availability{a}, conn); err != nil {
logger.Printf("BAL error: %s. skipping slot %d/%d", err.Error(), i, totalSlots)
stats.BookingBatchAvailabilityLookupErrors++
continue
}
stats.BookingBatchAvailabilityLookupSuccess++
} else {
if err := api.CheckAvailability(ctx, logger, a, conn); err != nil {
logger.Printf("%s. skipping slot %d/%d", err.Error(), i, totalSlots)
stats.BookingCheckAvailabilityErrors++
continue
}
stats.BookingCheckAvailabilitySuccess++
}
booking, err := api.CreateBooking(ctx, logger, a, conn)
if err != nil {
logger.Printf("%s. skipping slot %d/%d", err.Error(), i, totalSlots)
stats.BookingCreateBookingErrors++
continue
}
out = append(out, booking)
stats.BookingCreateBookingSuccess++
}
return out
}
func logStats(stats *utils.TestSummary, logger *log.Logger, config *utils.Config) {
logger.Println("\n************* Begin Stats *************\n")
var totalErrors int
if config.BookingHealthFlow || config.BookingAllFlows {
if stats.BookingHealthCheckSuccess {
logger.Println("HealthCheck Succeeded")
} else {
totalErrors++
logger.Println("HealthCheck Failed")
}
}
if config.BookingCheckFlow || config.BookingAllFlows {
if config.BookingUseBal {
totalErrors += stats.BookingBatchAvailabilityLookupErrors
logger.Printf("BatchAvailabilityLookup Errors: %d/%d", stats.BookingBatchAvailabilityLookupErrors, stats.BookingBatchAvailabilityLookupErrors+stats.BookingBatchAvailabilityLookupSuccess)
} else {
totalErrors += stats.BookingCheckAvailabilityErrors
logger.Printf("CheckAvailability Errors: %d/%d", stats.BookingCheckAvailabilityErrors, stats.BookingCheckAvailabilityErrors+stats.BookingCheckAvailabilitySuccess)
}
}
if config.BookingBookFlow || config.BookingAllFlows {
totalErrors += stats.BookingCreateBookingErrors
logger.Printf("CreateBooking Errors: %d/%d", stats.BookingCreateBookingErrors, stats.BookingCreateBookingErrors+stats.BookingCreateBookingSuccess)
}
if config.BookingListFlow || config.BookingAllFlows || config.BookingCancelAllBookings {
if stats.BookingListBookingsSuccess {
logger.Println("ListBookings Succeeded")
} else {
totalErrors++
logger.Println("ListBookings Failed")
}
}
if config.BookingStatusFlow || config.BookingAllFlows {
totalErrors += stats.BookingGetBookingStatusErrors
logger.Printf("GetBookingStatus Errors: %d/%d", stats.BookingGetBookingStatusErrors, stats.BookingGetBookingStatusErrors+stats.BookingGetBookingStatusSuccess)
}
if config.BookingRescheduleFlow || config.BookingAllFlows {
if stats.BookingReschedulingSuccess {
logger.Println("Rescheduling Succeeded")
} else {
totalErrors++
logger.Println("Rescheduling Failed")
}
}
logger.Println("\n\n\n")
if totalErrors == 0 {
logger.Println("All Tests Pass!")
} else {
logger.Printf("Found %d Errors", totalErrors)
}
logger.Println("\n************* End Stats *************\n")
}
// RunTests runs booking tests.
func RunTests(ctx context.Context, logger *log.Logger, config *utils.Config, av []*fpb.Availability, avForRescheduling []*fpb.Availability, stats *utils.TestSummary) {
conn := config.Conn
// HealthCheck Flow
if config.BookingHealthFlow || config.BookingAllFlows {
stats.BookingHealthCheckSuccess = true
if err := api.HealthCheck(ctx, logger, conn); err != nil {
stats.BookingHealthCheckSuccess = false
logger.Println(err.Error())
}
stats.BookingHealthCheckCompleted = true
if !config.BookingAllFlows && !config.BookingCheckFlow && !config.BookingBookFlow &&
!config.BookingListFlow && !config.BookingStatusFlow && !config.BookingRescheduleFlow {
logStats(stats, logger, config)
return
}
}
if config.BookingCheckFlow || config.BookingAllFlows {
if config.BookingUseBal {
utils.LogFlow(logger, "Batch Availability Lookup", "Start")
for _, a := range utils.SplitAvailabilityByMerchant(av) {
if err := api.BatchAvailabilityLookup(ctx, logger, a, conn); err != nil {
logger.Printf("BatchAvailabilityLookup returned error: %v", err)
stats.BookingBatchAvailabilityLookupErrors++
} else {
stats.BookingBatchAvailabilityLookupSuccess++
}
}
utils.LogFlow(logger, "Batch Availability Lookup", "End")
stats.BookingBatchAvailabilityLookupCompleted = true
} else {
// AvailabilityCheck Flow
utils.LogFlow(logger, "Availability Check", "Start")
totalSlots := len(av)
for i, a := range av {
if err := api.CheckAvailability(ctx, logger, a, conn); err != nil {
logger.Printf("%s. skipping slot %d/%d", err.Error(), i, totalSlots)
stats.BookingCheckAvailabilityErrors++
continue
}
stats.BookingCheckAvailabilitySuccess++
}
utils.LogFlow(logger, "Availability Check", "End")
stats.BookingCheckAvailabilityCompleted = true
}
}
// CreateBooking Flow.
var b []*mpb.Booking
if config.BookingBookFlow || config.BookingAllFlows {
utils.LogFlow(logger, "Booking", "Start")
totalSlots := len(av)
logger.Printf("total slots %d", totalSlots)
for i, a := range av {
logger.Printf("creating booking")
booking, err := api.CreateBooking(ctx, logger, a, conn)
if err != nil {
logger.Printf("%s. skipping slot %d/%d", err.Error(), i, totalSlots)
stats.BookingCreateBookingErrors++
continue
}
b = append(b, booking)
stats.BookingCreateBookingSuccess++
}
utils.LogFlow(logger, "Booking", "End")
stats.BookingCreateBookingCompleted = true
}
// ListBookings Flow
if config.BookingListFlow || config.BookingAllFlows || config.BookingCancelAllBookings {
if len(b) == 0 && !config.BookingCancelAllBookings {
b = GenerateBookings(ctx, logger, av, stats, conn, config)
}
utils.LogFlow(logger, "List Bookings", "Start")
if len(b) > 0 || config.BookingCancelAllBookings {
var err error
b, err = api.ListBookings(ctx, logger, b, conn)
stats.BookingListBookingsSuccess = true
if err != nil {
stats.BookingListBookingsSuccess = false
logger.Println(err.Error())
}
} else {
logger.Println("Could not create bookings to test ListBookings flow with.")
stats.BookingListBookingsSuccess = false
}
utils.LogFlow(logger, "List Bookings", "End")
stats.BookingListBookingsCompleted = true
}
// GetBookingStatus Flow
if config.BookingStatusFlow || config.BookingAllFlows {
if len(b) == 0 {
b = GenerateBookings(ctx, logger, av, stats, conn, config)
}
utils.LogFlow(logger, "BookingStatus", "Start")
totalBookings := len(b)
if totalBookings > 0 {
j := 0
for i, booking := range b {
if err := api.GetBookingStatus(ctx, logger, booking, conn); err != nil {
logger.Printf("%s. abandoning booking %d/%d", err.Error(), i, totalBookings)
stats.BookingGetBookingStatusErrors++
continue
}
stats.BookingGetBookingStatusSuccess++
b[j] = booking
j++
}
b = b[:j]
} else {
logger.Println("Could not create bookings to test GetBookingStatus flow with.")
}
utils.LogFlow(logger, "BookingStatus", "End")
stats.BookingGetBookingStatusCompleted = true
}
// CancelBooking Flow
if len(b) > 0 {
utils.LogFlow(logger, "Cancel Booking", "Start")
for i, booking := range b {
if err := api.CancelBooking(ctx, logger, booking.GetBookingId(), conn); err != nil {
logger.Printf("%s. abandoning booking %d/%d", err.Error(), i, len(b))
stats.BookingCancelBookingsErrors++
continue
}
stats.BookingCancelBookingsSuccess++
}
utils.LogFlow(logger, "Cancel Booking", "End")
stats.BookingCancelBookingsCompleted = true
}
// Rescheduling is nuanced and can be isolated
// from the rest of the tests.
if config.BookingRescheduleFlow || config.BookingAllFlows {
utils.LogFlow(logger, "Rescheduling", "Start")
stats.BookingReschedulingSuccess = true
if err := api.Rescheduling(ctx, logger, avForRescheduling, conn); err != nil {
logger.Println(err.Error())
stats.BookingReschedulingSuccess = false
}
utils.LogFlow(logger, "Rescheduling", "End")
stats.BookingReschedulingCompleted = true
}
logStats(stats, logger, config)
}