| /* |
| Copyright 2017 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 main |
| |
| import ( |
| "flag" |
| "fmt" |
| "log" |
| "os" |
| "path/filepath" |
| "time" |
| |
| "github.com/maps-booking-v3/api" |
| "github.com/maps-booking-v3/utils" |
| |
| mpb "github.com/maps-booking-v3/v3" |
| ) |
| |
| const logFile = "http_test_client_log_" |
| |
| var ( |
| serverAddr = flag.String("server_addr", "example.com:80", "Your http server's address in the format of host:port") |
| credentialsFile = flag.String("credentials_file", "", "File containing credentials for your server. Leave blank to bypass authentication. File should have exactly one line of the form 'username:password'.") |
| testSlots = flag.Int("num_test_slots", 10, "Maximum number of slots to test from availability_feed. Slots will be selected randomly") |
| allFlows = flag.Bool("all_tests", false, "Whether to test all endpoints syncronously, including ListOrders flow.") |
| healthFlow = flag.Bool("health_check_test", false, "Whether to test the Health endpoint.") |
| checkFlow = flag.Bool("check_order_test", false, "Whether to test the CheckOrderFulfillability endpoint.") |
| orderFlow = flag.Bool("create_order_test", false, "Whether to test the CreateOrder endpoint.") |
| serviceFeed = flag.String("service_feed", "", "Absolute path to service feed required for all tests except health. Feeds can be in either json or pb3 format") |
| availabilityFeed = flag.String("availability_feed", "", "Absolute path to availability feed required for all tests except health. Feeds can be in either json or pb3 format") |
| outputDir = flag.String("output_dir", "", "Absolute path of dir to dump log file.") |
| caFile = flag.String("ca_file", "", "Absolute path to your server's Certificate Authority root cert. Downloading all roots currently recommended by the Google Internet Authority is a suitable alternative https://pki.google.com/roots.pem. Leave blank to connect using http rather than https.") |
| fullServerName = flag.String("full_server_name", "", "Fully qualified domain name. Same name used to sign CN. Only necessary if ca_file is specified and the base URL differs from the server address.") |
| ) |
| |
| type counters struct { |
| TotalSlotsProcessed int |
| HealthCheckSuccess bool |
| CheckOrderFulfillabilitySuccess int |
| CheckOrderFulfillabilityErrors int |
| CreateOrderSuccess int |
| CreateOrderErrors int |
| ListOrdersSuccess bool |
| } |
| |
| func createLogFile() (*os.File, error) { |
| var err error |
| outPath := *outputDir |
| if outPath == "" { |
| outPath, err = os.Getwd() |
| if err != nil { |
| return nil, err |
| } |
| } |
| |
| now := time.Now().UTC() |
| nowString := fmt.Sprintf("%d-%02d-%02d_%02d-%02d-%02d", now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second()) |
| outFile := filepath.Join(outPath, fmt.Sprintf("%s%s", logFile, nowString)) |
| |
| return os.Create(outFile) |
| } |
| |
| func logStats(stats counters) { |
| log.Println("\n************* Begin Stats *************\n") |
| var totalErrors int |
| if *healthFlow || *allFlows { |
| if stats.HealthCheckSuccess { |
| log.Println("HealthCheck Succeeded") |
| } else { |
| totalErrors++ |
| log.Println("HealthCheck Failed") |
| } |
| } |
| if *checkFlow || *allFlows { |
| totalErrors += stats.CheckOrderFulfillabilityErrors |
| log.Printf("CheckOrderFulfillability Errors: %d/%d", stats.CheckOrderFulfillabilityErrors, stats.CheckOrderFulfillabilityErrors+stats.CheckOrderFulfillabilitySuccess) |
| } |
| if *orderFlow || *allFlows { |
| totalErrors += stats.CreateOrderErrors |
| log.Printf("CreateOrder Errors: %d/%d", stats.CreateOrderErrors, stats.CreateOrderErrors+stats.CreateOrderSuccess) |
| } |
| if *allFlows { |
| if stats.ListOrdersSuccess { |
| log.Println("ListOrders Succeeded") |
| } else { |
| totalErrors++ |
| log.Println("ListOrders Failed") |
| } |
| } |
| if *checkFlow || *orderFlow || *allFlows { |
| log.Printf("Total Slots Processed: %d", stats.TotalSlotsProcessed) |
| } |
| |
| log.Println("\n\n\n") |
| if totalErrors == 0 { |
| log.Println("All Tests Pass!") |
| } else { |
| log.Printf("Found %d Errors", totalErrors) |
| } |
| |
| log.Println("\n************* End Stats *************\n") |
| os.Exit(0) |
| } |
| |
| func main() { |
| flag.Parse() |
| var stats counters |
| |
| // Set up logging before continuing with flows |
| f, err := createLogFile() |
| if err != nil { |
| log.Fatalf("Failed to create log file %v", err) |
| } |
| defer f.Close() |
| log.SetOutput(f) |
| |
| conn, err := api.InitHTTPConnection(*serverAddr, *credentialsFile, *caFile, *fullServerName) |
| if err != nil { |
| log.Fatalf("Failed to init http connection %v", err) |
| } |
| |
| // HealthCheck Flow |
| if *healthFlow || *allFlows { |
| stats.HealthCheckSuccess = true |
| if err := api.HealthCheck(conn); err != nil { |
| stats.HealthCheckSuccess = false |
| log.Println(err.Error()) |
| } |
| if !*allFlows && !*checkFlow && !*orderFlow { |
| logStats(stats) |
| } |
| } |
| |
| if *availabilityFeed == "" || *serviceFeed == "" { |
| log.Fatal("please set both availability_feed and service_feed flags") |
| } |
| |
| testInventory, err := utils.MerchantLineItemMapFrom(*serviceFeed, *availabilityFeed, *testSlots) |
| if err != nil { |
| log.Fatal(err.Error()) |
| } |
| |
| // CheckOrderFulfillability Flow |
| if *checkFlow || *allFlows { |
| utils.LogFlow("CheckOrderFulfillability", "Start") |
| for _, value := range testInventory { |
| stats.TotalSlotsProcessed += len(value) |
| } |
| |
| i := 0 |
| for merchantID, lineItems := range testInventory { |
| if err = api.CheckOrderFulfillability(merchantID, lineItems, conn); err != nil { |
| log.Printf("%s. skipping slots %d-%d/%d", err.Error(), i, i+len(lineItems)-1, stats.TotalSlotsProcessed) |
| stats.CheckOrderFulfillabilityErrors += len(lineItems) |
| delete(testInventory, merchantID) |
| i += len(lineItems) |
| continue |
| } |
| stats.CheckOrderFulfillabilitySuccess += len(lineItems) |
| i += len(lineItems) |
| } |
| utils.LogFlow("CheckOrderFulfillability", "End") |
| } |
| // CreateOrder Flow. |
| var orders []*mpb.Order |
| if *orderFlow || *allFlows { |
| utils.LogFlow("CreateOrder", "Start") |
| if stats.TotalSlotsProcessed == 0 { |
| for _, value := range testInventory { |
| stats.TotalSlotsProcessed += len(value) |
| } |
| } |
| |
| i := 0 |
| for merchantID, lineItems := range testInventory { |
| order, err := api.CreateOrder(merchantID, lineItems, conn) |
| if err != nil { |
| log.Printf("%s. skipping slot %d-%d/%d", err.Error(), i, i+len(lineItems)-1, stats.TotalSlotsProcessed) |
| stats.CreateOrderErrors += len(lineItems) |
| delete(testInventory, merchantID) |
| i += len(lineItems) |
| continue |
| } |
| orders = append(orders, order) |
| stats.CreateOrderSuccess += len(lineItems) |
| i += len(lineItems) |
| } |
| utils.LogFlow("CreateOrder", "End") |
| } |
| // ListOrders Flow |
| if *allFlows { |
| utils.LogFlow("ListOrders", "Start") |
| stats.ListOrdersSuccess = true |
| if err = api.ListOrders(orders, conn); err != nil { |
| stats.ListOrdersSuccess = false |
| log.Println(err.Error()) |
| } |
| utils.LogFlow("ListOrders", "End") |
| } |
| |
| logStats(stats) |
| } |