blob: ffb91a9f52d585312db156ef5814fcae53b5d205 [file] [log] [blame]
Jeremy Ronquillo6df87812017-08-28 16:17:36 +00001# Copyright 2017 Open Networking Foundation (ONF)
2#
3# Please refer questions to either the onos test mailing list at <onos-test@onosproject.org>,
4# the System Testing Plans and Results wiki page at <https://wiki.onosproject.org/x/voMg>,
5# or the System Testing Guide page at <https://wiki.onosproject.org/x/WYQg>
6#
7# TestON is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation, either version 2 of the License, or
10# (at your option) any later version.
11#
12# TestON is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with TestON. If not, see <http://www.gnu.org/licenses/>.
19#
20# If you have any questions, or if you don't understand R,
Jeremy Ronquillob6268842017-10-03 13:02:58 -070021# please contact Jeremy Ronquillo: j_ronquillo@u.pacific.edu
Jeremy Ronquillo6df87812017-08-28 16:17:36 +000022
23# **********************************************************
Jeremy Ronquillo7673f802017-10-30 09:42:44 -070024# STEP 1: Data management.
Jeremy Ronquillo6df87812017-08-28 16:17:36 +000025# **********************************************************
Devin Lim0e967162017-11-03 15:59:53 -070026has_flow_obj = 1
27database_host = 2
28database_port = 3
29database_u_id = 4
30database_pw = 5
31test_name = 6
32branch_name = 7
33has_neighbors = 8
34old_flow = 9
35save_directory = 10
Jeremy Ronquillo6df87812017-08-28 16:17:36 +000036
Jeremy Ronquillo7673f802017-10-30 09:42:44 -070037print( "**********************************************************" )
38print( "STEP 1: Data management." )
39print( "**********************************************************" )
Jeremy Ronquillo6df87812017-08-28 16:17:36 +000040
Jeremy Ronquillob6268842017-10-03 13:02:58 -070041# Command line arguments are read.
Jeremy Ronquillo6df87812017-08-28 16:17:36 +000042print( "Reading commmand-line args." )
43args <- commandArgs( trailingOnly=TRUE )
44
Jeremy Ronquillo7673f802017-10-30 09:42:44 -070045# ----------------
46# Import Libraries
47# ----------------
48
Jeremy Ronquillo6df87812017-08-28 16:17:36 +000049print( "Importing libraries." )
50library( ggplot2 )
51library( reshape2 )
52library( RPostgreSQL ) # For databases
53
Jeremy Ronquillo7673f802017-10-30 09:42:44 -070054# -------------------
55# Check CLI Arguments
56# -------------------
57
58print( "Verifying CLI args." )
59
Devin Lim0e967162017-11-03 15:59:53 -070060if ( is.na( args[ save_directory ] ) ){
Jeremy Ronquillo7673f802017-10-30 09:42:44 -070061
62 print( paste( "Usage: Rscript SCPFflowTp1g.R",
63 "<has-flow-obj>",
64 "<database-host>",
65 "<database-port>",
66 "<database-user-id>",
67 "<database-password>",
68 "<test-name>",
69 "<branch-name>",
70 "<has-neighbors>",
Devin Lim0e967162017-11-03 15:59:53 -070071 "<using-old-flow>",
Jeremy Ronquillo7673f802017-10-30 09:42:44 -070072 "<directory-to-save-graphs>",
73 sep=" " ) )
74
Jeremy Ronquillo9ea85d02017-11-27 10:21:03 -080075 quit( status = 1 ) # basically exit(), but in R
Jeremy Ronquillo6df87812017-08-28 16:17:36 +000076}
77
Jeremy Ronquillo7673f802017-10-30 09:42:44 -070078# -----------------
79# Create File Names
80# -----------------
Jeremy Ronquillo6df87812017-08-28 16:17:36 +000081
Jeremy Ronquillo7673f802017-10-30 09:42:44 -070082print( "Creating filenames and title of graph." )
Jeremy Ronquillo6df87812017-08-28 16:17:36 +000083
Jeremy Ronquillo7673f802017-10-30 09:42:44 -070084chartTitle <- "Flow Throughput Test"
85fileNeighborsModifier <- "no"
Jeremy Ronquillo6df87812017-08-28 16:17:36 +000086commandNeighborModifier <- ""
Jeremy Ronquillo7673f802017-10-30 09:42:44 -070087fileFlowObjModifier <- ""
88sqlFlowObjModifier <- ""
Devin Lim0e967162017-11-03 15:59:53 -070089if ( args[ has_flow_obj ] == 'y' ){
Jeremy Ronquillo7673f802017-10-30 09:42:44 -070090 fileFlowObjModifier <- "_flowObj"
91 sqlFlowObjModifier <- "_fobj"
92 chartTitle <- paste( chartTitle, " with Flow Objectives", sep="" )
Jeremy Ronquillo6df87812017-08-28 16:17:36 +000093}
Jeremy Ronquillo7673f802017-10-30 09:42:44 -070094
95chartTitle <- paste( chartTitle, "\nNeighbors =", sep="" )
96
Devin Lim0e967162017-11-03 15:59:53 -070097fileOldFlowModifier <- ""
98if ( args[ has_neighbors ] == 'y' ){
Jeremy Ronquillo7673f802017-10-30 09:42:44 -070099 fileNeighborsModifier <- "all"
Jeremy Ronquillo2d2649d2017-09-14 12:53:06 -0700100 commandNeighborModifier <- "scale=1 OR NOT "
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700101 chartTitle <- paste( chartTitle, "Cluster Size - 1" )
102} else {
103 chartTitle <- paste( chartTitle, "0" )
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000104}
Devin Lim0e967162017-11-03 15:59:53 -0700105if ( args[ old_flow ] == 'y' ){
106 fileOldFlowModifier <- "_OldFlow"
Devin Lim1bba7622017-11-14 16:31:41 -0800107 chartTitle <- paste( chartTitle, "With Eventually Consistent Flow Rule Store", sep="\n" )
Devin Lim0e967162017-11-03 15:59:53 -0700108}
109errBarOutputFile <- paste( args[ save_directory ],
110 args[ test_name ],
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700111 "_",
Devin Lim0e967162017-11-03 15:59:53 -0700112 args[ branch_name ],
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700113 "_",
114 fileNeighborsModifier,
115 "-neighbors",
116 fileFlowObjModifier,
Devin Lim0e967162017-11-03 15:59:53 -0700117 fileOldFlowModifier,
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700118 "_graph.jpg",
119 sep="" )
120# ------------------
121# SQL Initialization
122# ------------------
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000123
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700124print( "Initializing SQL" )
125
126con <- dbConnect( dbDriver( "PostgreSQL" ),
127 dbname = "onostest",
Devin Lim0e967162017-11-03 15:59:53 -0700128 host = args[ database_host ],
129 port = strtoi( args[ database_port ] ),
130 user = args[ database_u_id ],
131 password = args[ database_pw ] )
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700132
133# ---------------------------
134# Flow Throughput SQL Command
135# ---------------------------
136
137print( "Generating Flow Throughput SQL command." )
138
139command <- paste( "SELECT scale, avg( avg ), avg( std ) FROM flow_tp",
140 sqlFlowObjModifier,
141 "_tests WHERE (",
142 commandNeighborModifier,
143 "neighbors = 0 ) AND branch = '",
Devin Lim0e967162017-11-03 15:59:53 -0700144 args[ branch_name ],
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700145 "' AND date IN ( SELECT max( date ) FROM flow_tp",
146 sqlFlowObjModifier,
147 "_tests WHERE branch='",
Devin Lim0e967162017-11-03 15:59:53 -0700148 args[ branch_name ],
149 "' AND ",
150 ( if( args[ old_flow ] == 'y' ) "" else "NOT " ),
151 "is_old_flow",
152 " ) GROUP BY scale ORDER BY scale",
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700153 sep="" )
154
155print( "Sending SQL command:" )
156print( command )
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000157
158fileData <- dbGetQuery( con, command )
159
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000160# **********************************************************
161# STEP 2: Organize data.
162# **********************************************************
163
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700164print( "**********************************************************" )
165print( "STEP 2: Organize Data." )
166print( "**********************************************************" )
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000167
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700168# ------------
169# Data Sorting
170# ------------
171
172print( "Sorting data for Flow Throughput." )
173
174colnames( fileData ) <- c( "scale",
175 "avg",
176 "std" )
177
Jeremy Ronquillo9ea85d02017-11-27 10:21:03 -0800178requiredColumns <- c( "avg" )
179
180tryCatch( avgs <- c( fileData[ requiredColumns] ),
181 error = function( e ) {
182 print( "[ERROR] One or more expected columns are missing from the data. Please check that the data and SQL command are valid, then try again." )
183 print( "Required columns: " )
184 print( requiredColumns )
185 print( "Actual columns: " )
186 print( names( fileData ) )
187 print( "Error dump:" )
188 print( e )
189 quit( status = 1 )
190 }
191 )
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000192
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700193
194# ----------------------------
195# Flow TP Construct Data Frame
196# ----------------------------
197
198print( "Constructing Flow TP data frame." )
199
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000200dataFrame <- melt( avgs ) # This is where reshape2 comes in. Avgs list is converted to data frame
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700201dataFrame$scale <- fileData$scale # Add node scaling to the data frame.
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000202dataFrame$std <- fileData$std
203
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700204colnames( dataFrame ) <- c( "throughput",
205 "type",
206 "scale",
207 "std" )
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000208
Jeremy Ronquillo2d2649d2017-09-14 12:53:06 -0700209dataFrame <- na.omit( dataFrame ) # Omit any data that doesn't exist
210
211print( "Data Frame Results:" )
212print( dataFrame )
213
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000214# **********************************************************
215# STEP 3: Generate graphs.
216# **********************************************************
217
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700218print( "**********************************************************" )
219print( "STEP 3: Generate Graph." )
220print( "**********************************************************" )
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000221
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700222# ------------------
223# Generate Main Plot
224# ------------------
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000225
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700226print( "Generating main plot." )
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000227# Create the primary plot here.
228# ggplot contains the following arguments:
229# - data: the data frame that the graph will be based off of
230# - aes: the asthetics of the graph which require:
231# - x: x-axis values (usually node scaling)
232# - y: y-axis values (usually time in milliseconds)
233# - fill: the category of the colored side-by-side bars (usually type)
Jeremy Ronquillo2d2649d2017-09-14 12:53:06 -0700234
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700235mainPlot <- ggplot( data = dataFrame, aes( x = scale,
236 y = throughput,
237 ymin = throughput,
238 ymax = throughput + std,
239 fill = type ) )
240# ------------------------------
241# Fundamental Variables Assigned
242# ------------------------------
Jeremy Ronquillo2d2649d2017-09-14 12:53:06 -0700243
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700244print( "Generating fundamental graph data." )
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000245
246# Formatting the plot
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700247theme_set( theme_grey( base_size = 22 ) ) # set the default text size of the graph.
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000248width <- 0.7 # Width of the bars.
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700249xScaleConfig <- scale_x_continuous( breaks = dataFrame$scale,
250 label = dataFrame$scale )
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000251xLabel <- xlab( "Scale" )
Jeremy Ronquillo1bdaae52017-09-22 11:39:48 -0700252yLabel <- ylab( "Throughput (,000 Flows/sec)" )
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000253fillLabel <- labs( fill="Type" )
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700254imageWidth <- 15
255imageHeight <- 10
256imageDPI <- 200
257errorBarColor <- rgb( 140, 140, 140, maxColorValue=255 )
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000258
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700259theme <- theme( plot.title = element_text( hjust = 0.5,
260 size = 32,
Jeremy Ronquillo94f99dd2018-01-05 11:11:27 -0800261 face = 'bold' ),
262 plot.subtitle = element_text( size=16, hjust=1.0 ) )
263
264subtitle <- paste( "Last Updated: ", format( Sys.time(), format = "%b %d, %Y at %I:%M %p %Z" ), sep="" )
265
266title <- labs( title = chartTitle, subtitle = subtitle )
Jeremy Ronquillo4363d092017-10-13 13:28:47 -0700267
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000268# Store plot configurations as 1 variable
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700269fundamentalGraphData <- mainPlot +
270 xScaleConfig +
271 xLabel +
272 yLabel +
273 fillLabel +
274 theme +
275 title
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000276
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700277# ---------------------------
278# Generating Bar Graph Format
279# ---------------------------
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000280
281# Create the stacked bar graph with error bars.
282# geom_bar contains:
283# - stat: data formatting (usually "identity")
284# - width: the width of the bar types (declared above)
285# geom_errorbar contains similar arguments as geom_bar.
286print( "Generating bar graph with error bars." )
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700287barGraphFormat <- geom_bar( stat = "identity",
288 width = width,
289 fill = "#FFAA3C" )
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000290
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700291errorBarFormat <- geom_errorbar( width = width,
292 position = position_dodge(),
293 color = errorBarColor )
294
295values <- geom_text( aes( x = dataFrame$scale,
296 y = dataFrame$throughput + 0.03 * max( dataFrame$throughput ),
297 label = format( dataFrame$throughput,
298 digits=3,
299 big.mark = ",",
300 scientific = FALSE ) ),
301 size = 7.0,
302 fontface = "bold" )
303
304result <- fundamentalGraphData +
305 barGraphFormat +
306 errorBarFormat +
307 values
308
309# -----------------------
310# Exporting Graph to File
311# -----------------------
312
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000313print( paste( "Saving bar chart with error bars to", errBarOutputFile ) )
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700314
Jeremy Ronquillo9ea85d02017-11-27 10:21:03 -0800315tryCatch( ggsave( errBarOutputFile,
316 width = imageWidth,
317 height = imageHeight,
318 dpi = imageDPI ),
319 error = function( e ){
320 print( "[ERROR] There was a problem saving the graph due to a graph formatting exception. Error dump:" )
321 print( e )
322 quit( status = 1 )
323 }
324 )
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700325
326print( paste( "[SUCCESS] Successfully wrote bar chart with error bars out to", errBarOutputFile ) )
Jeremy Ronquillo9ea85d02017-11-27 10:21:03 -0800327quit( status = 0 )