| /* |
| 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) |
| } |