snmp_table_viewer 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,296 @@
1
+ module SNMPTableViewer
2
+
3
+ # Converter for the interface table.
4
+ # Replaces type with "number (meaning)"
5
+ # Replaces admin state with "number (meaning)"
6
+ # Replaces oper state with "number (meaning)"
7
+ # Replaces last change with "Timeticks: (number) D days, H:M:S.ms"
8
+ class Converter::IfTable < Converter
9
+ def self.convert(data)
10
+ admin_states = ['up', 'down', 'testing']
11
+ oper_states = ['up', 'down', 'testing', 'unknown', 'dormant', 'notPresent', 'lowerLayerDown']
12
+ types = {
13
+ 1 => 'other',
14
+ 2 => 'regular1822',
15
+ 3 => 'hdh1822',
16
+ 4 => 'ddnX25',
17
+ 5 => 'rfc877x25',
18
+ 6 => 'ethernetCsmacd',
19
+ 7 => 'iso88023Csmacd',
20
+ 8 => 'iso88024TokenBus',
21
+ 9 => 'iso88025TokenRing',
22
+ 10 => 'iso88026Man',
23
+ 11 => 'starLan',
24
+ 12 => 'proteon10Mbit',
25
+ 13 => 'proteon80Mbit',
26
+ 14 => 'hyperchannel',
27
+ 15 => 'fddi',
28
+ 16 => 'lapb',
29
+ 17 => 'sdlc',
30
+ 18 => 'ds1',
31
+ 19 => 'e1',
32
+ 20 => 'basicISDN',
33
+ 21 => 'primaryISDN',
34
+ 22 => 'propPointToPointSerial',
35
+ 23 => 'ppp',
36
+ 24 => 'softwareLoopback',
37
+ 25 => 'eon',
38
+ 26 => 'ethernet3Mbit',
39
+ 27 => 'nsip',
40
+ 28 => 'slip',
41
+ 29 => 'ultra',
42
+ 30 => 'ds3',
43
+ 31 => 'sip',
44
+ 32 => 'frameRelay',
45
+ 33 => 'rs232',
46
+ 34 => 'para',
47
+ 35 => 'arcnet',
48
+ 36 => 'arcnetPlus',
49
+ 37 => 'atm',
50
+ 38 => 'miox25',
51
+ 39 => 'sonet',
52
+ 40 => 'x25ple',
53
+ 41 => 'iso88022llc',
54
+ 42 => 'localTalk',
55
+ 43 => 'smdsDxi',
56
+ 44 => 'frameRelayService',
57
+ 45 => 'v35',
58
+ 46 => 'hssi',
59
+ 47 => 'hippi',
60
+ 48 => 'modem',
61
+ 49 => 'aal5',
62
+ 50 => 'sonetPath',
63
+ 51 => 'sonetVT',
64
+ 52 => 'smdsIcip',
65
+ 53 => 'propVirtual',
66
+ 54 => 'propMultiplexor',
67
+ 55 => 'ieee80212',
68
+ 56 => 'fibreChannel',
69
+ 57 => 'hippiInterface',
70
+ 58 => 'frameRelayInterconnect',
71
+ 59 => 'aflane8023',
72
+ 60 => 'aflane8025',
73
+ 61 => 'cctEmul',
74
+ 62 => 'fastEther',
75
+ 63 => 'isdn',
76
+ 64 => 'v11',
77
+ 65 => 'v36',
78
+ 66 => 'g703at64k',
79
+ 67 => 'g703at2mb',
80
+ 68 => 'qllc',
81
+ 69 => 'fastEtherFX',
82
+ 70 => 'channel',
83
+ 71 => 'ieee80211',
84
+ 72 => 'ibm370parChan',
85
+ 73 => 'escon',
86
+ 74 => 'dlsw',
87
+ 75 => 'isdns',
88
+ 76 => 'isdnu',
89
+ 77 => 'lapd',
90
+ 78 => 'ipSwitch',
91
+ 79 => 'rsrb',
92
+ 80 => 'atmLogical',
93
+ 81 => 'ds0',
94
+ 82 => 'ds0Bundle',
95
+ 83 => 'bsc',
96
+ 84 => 'async',
97
+ 85 => 'cnr',
98
+ 86 => 'iso88025Dtr',
99
+ 87 => 'eplrs',
100
+ 88 => 'arap',
101
+ 89 => 'propCnls',
102
+ 90 => 'hostPad',
103
+ 91 => 'termPad',
104
+ 92 => 'frameRelayMPI',
105
+ 93 => 'x213',
106
+ 94 => 'adsl',
107
+ 95 => 'radsl',
108
+ 96 => 'sdsl',
109
+ 97 => 'vdsl',
110
+ 98 => 'iso88025CRFPInt',
111
+ 99 => 'myrinet',
112
+ 100 => 'voiceEM',
113
+ 101 => 'voiceFXO',
114
+ 102 => 'voiceFXS',
115
+ 103 => 'voiceEncap',
116
+ 104 => 'voiceOverIp',
117
+ 105 => 'atmDxi',
118
+ 106 => 'atmFuni',
119
+ 107 => 'atmIma',
120
+ 108 => 'pppMultilinkBundle',
121
+ 109 => 'ipOverCdlc',
122
+ 110 => 'ipOverClaw',
123
+ 111 => 'stackToStack',
124
+ 112 => 'virtualIpAddress',
125
+ 113 => 'mpc',
126
+ 114 => 'ipOverAtm',
127
+ 115 => 'iso88025Fiber',
128
+ 116 => 'tdlc',
129
+ 117 => 'gigabitEthernet',
130
+ 118 => 'hdlc',
131
+ 119 => 'lapf',
132
+ 120 => 'v37',
133
+ 121 => 'x25mlp',
134
+ 122 => 'x25huntGroup',
135
+ 123 => 'transpHdlc',
136
+ 124 => 'interleave',
137
+ 125 => 'fast',
138
+ 126 => 'ip',
139
+ 127 => 'docsCableMaclayer',
140
+ 128 => 'docsCableDownstream',
141
+ 129 => 'docsCableUpstream',
142
+ 130 => 'a12MppSwitch',
143
+ 131 => 'tunnel',
144
+ 132 => 'coffee',
145
+ 133 => 'ces',
146
+ 134 => 'atmSubInterface',
147
+ 135 => 'l2vlan',
148
+ 136 => 'l3ipvlan',
149
+ 137 => 'l3ipxvlan',
150
+ 138 => 'digitalPowerline',
151
+ 139 => 'mediaMailOverIp',
152
+ 140 => 'dtm',
153
+ 141 => 'dcn',
154
+ 142 => 'ipForward',
155
+ 143 => 'msdsl',
156
+ 144 => 'ieee1394',
157
+ 145 => 'if-gsn',
158
+ 146 => 'dvbRccMacLayer',
159
+ 147 => 'dvbRccDownstream',
160
+ 148 => 'dvbRccUpstream',
161
+ 149 => 'atmVirtual',
162
+ 150 => 'mplsTunnel',
163
+ 151 => 'srp',
164
+ 152 => 'voiceOverAtm',
165
+ 153 => 'voiceOverFrameRelay',
166
+ 154 => 'idsl',
167
+ 155 => 'compositeLink',
168
+ 156 => 'ss7SigLink',
169
+ 157 => 'propWirelessP2P',
170
+ 158 => 'frForward',
171
+ 159 => 'rfc1483',
172
+ 160 => 'usb',
173
+ 161 => 'ieee8023adLag',
174
+ 162 => 'bgppolicyaccounting',
175
+ 163 => 'frf16MfrBundle',
176
+ 164 => 'h323Gatekeeper',
177
+ 165 => 'h323Proxy',
178
+ 166 => 'mpls',
179
+ 167 => 'mfSigLink',
180
+ 168 => 'hdsl2',
181
+ 169 => 'shdsl',
182
+ 170 => 'ds1FDL',
183
+ 171 => 'pos',
184
+ 172 => 'dvbAsiIn',
185
+ 173 => 'dvbAsiOut',
186
+ 174 => 'plc',
187
+ 175 => 'nfas',
188
+ 176 => 'tr008',
189
+ 177 => 'gr303RDT',
190
+ 178 => 'gr303IDT',
191
+ 179 => 'isup',
192
+ 180 => 'propDocsWirelessMaclayer',
193
+ 181 => 'propDocsWirelessDownstream',
194
+ 182 => 'propDocsWirelessUpstream',
195
+ 183 => 'hiperlan2',
196
+ 184 => 'propBWAp2Mp',
197
+ 185 => 'sonetOverheadChannel',
198
+ 186 => 'digitalWrapperOverheadChannel',
199
+ 187 => 'aal2',
200
+ 188 => 'radioMAC',
201
+ 189 => 'atmRadio',
202
+ 190 => 'imt',
203
+ 191 => 'mvl',
204
+ 192 => 'reachDSL',
205
+ 193 => 'frDlciEndPt',
206
+ 194 => 'atmVciEndPt',
207
+ 195 => 'opticalChannel',
208
+ 196 => 'opticalTransport',
209
+ 197 => 'propAtm',
210
+ 198 => 'voiceOverCable',
211
+ 199 => 'infiniband',
212
+ 200 => 'teLink',
213
+ 201 => 'q2931',
214
+ 202 => 'virtualTg',
215
+ 203 => 'sipTg',
216
+ 204 => 'sipSig',
217
+ 205 => 'docsCableUpstreamChannel',
218
+ 206 => 'econet',
219
+ 207 => 'pon155',
220
+ 208 => 'pon622',
221
+ 209 => 'bridge',
222
+ 210 => 'linegroup',
223
+ 211 => 'voiceEMFGD',
224
+ 212 => 'voiceFGDEANA',
225
+ 213 => 'voiceDID',
226
+ 214 => 'mpegTransport',
227
+ 215 => 'sixToFour',
228
+ 216 => 'gtp',
229
+ 217 => 'pdnEtherLoop1',
230
+ 218 => 'pdnEtherLoop2',
231
+ 219 => 'opticalChannelGroup',
232
+ 220 => 'homepna',
233
+ 221 => 'gfp',
234
+ 222 => 'ciscoISLvlan',
235
+ 223 => 'actelisMetaLOOP',
236
+ 224 => 'fcipLink',
237
+ 225 => 'rpr',
238
+ 226 => 'qam',
239
+ 227 => 'lmp',
240
+ 228 => 'cblVectaStar',
241
+ 229 => 'docsCableMCmtsDownstream',
242
+ 230 => 'adsl2',
243
+ 231 => 'macSecControlledIF',
244
+ 232 => 'macSecUncontrolledIF',
245
+ 233 => 'aviciOpticalEther',
246
+ 234 => 'atmbond',
247
+ 235 => 'voiceFGDOS',
248
+ 236 => 'mocaVersion1',
249
+ 237 => 'ieee80216WMAN',
250
+ 238 => 'adsl2plus',
251
+ 239 => 'dvbRcsMacLayer',
252
+ 240 => 'dvbTdm',
253
+ 241 => 'dvbRcsTdma',
254
+ 242 => 'x86Laps',
255
+ 243 => 'wwanPP',
256
+ 244 => 'wwanPP2',
257
+ 245 => 'voiceEBS',
258
+ 246 => 'ifPwType',
259
+ 247 => 'ilan',
260
+ 248 => 'pip',
261
+ 249 => 'aluELP',
262
+ 250 => 'gpon',
263
+ 251 => 'vdsl2',
264
+ 252 => 'capwapDot11Profile',
265
+ 253 => 'capwapDot11Bss',
266
+ 254 => 'capwapWtpVirtualRadio',
267
+ 255 => 'bits',
268
+ 256 => 'docsCableUpstreamRfPort',
269
+ 257 => 'cableDownstreamRfPort',
270
+ 258 => 'vmwareVirtualNic',
271
+ 259 => 'ieee802154',
272
+ 260 => 'otnOdu',
273
+ 261 => 'otnOtu',
274
+ 262 => 'ifVfiType',
275
+ 263 => 'g9981',
276
+ 264 => 'g9982',
277
+ 265 => 'g9983',
278
+ 266 => 'aluEpon',
279
+ 267 => 'aluEponOnu',
280
+ 268 => 'aluEponPhysicalUni',
281
+ 269 => 'aluEponLogicalLink',
282
+ 270 => 'aluGponOnu',
283
+ 271 => 'aluGponPhysicalUni',
284
+ 272 => 'vmwareNicTeam',
285
+ }
286
+ data.map do |item|
287
+ item[2] = "#{item[2]} (#{types[item[2]]})"
288
+ item[6] = "#{item[6]} (#{admin_states[item[6]-1]})"
289
+ item[7] = "#{item[7]} (#{oper_states[item[7]-1]})"
290
+ item[8] = item[8].to_s # Timeticks for last change
291
+ item
292
+ end
293
+ end
294
+ end # IfTable Converter
295
+
296
+ end # module SNMPTableViewer
@@ -0,0 +1,8 @@
1
+ module SNMPTableViewer
2
+
3
+ # Parent class for converters. Which take data and perform sometranslations/conversions to it..
4
+ # @abstract
5
+ class Converter
6
+ end # Converter base class
7
+
8
+ end # module SNMPTableViewer
@@ -0,0 +1,24 @@
1
+ module SNMPTableViewer
2
+
3
+ # Class to fetch the information from an SNMP host.
4
+ class Fetcher
5
+
6
+ # Fetch the data using SNMP.
7
+ # @param base_oid [String] The OID to start the SNMP walk from
8
+ # @param **snmp_options [Hash] The options to pass to NETSNMP::Client.new
9
+ # @return [Array<Array<#to_s>>] A two dimensional array containing objects in each cell (at 'address' data[row][col])
10
+ def self.from_snmp(base_oid:, **snmp_options)
11
+ data = Array.new
12
+ NETSNMP::Client.new(snmp_options) do |manager|
13
+ manager.walk(oid: base_oid).each do |oid, value|
14
+ col, row = oid.split('.')[-2..-1].map{ |i| i.to_i - 1}
15
+ data[row] ||= []
16
+ data[row][col] = value
17
+ end
18
+ end
19
+ data
20
+ end
21
+
22
+ end # class Fetcher
23
+
24
+ end # module SNMPTableViewer
@@ -0,0 +1,12 @@
1
+ module SNMPTableViewer
2
+
3
+ # Formatting class for CSV output.
4
+ class Formatter::CSV < Formatter
5
+ # Output the data (and headings if provided).
6
+ # @return [String] the CSV data
7
+ def output()
8
+ data_with_headings.map(&:to_csv).join
9
+ end
10
+ end # CSV Formatter
11
+
12
+ end # module SNMPTableViewer
@@ -0,0 +1,17 @@
1
+ module SNMPTableViewer
2
+
3
+ # Formatting class for JSON output
4
+ class Formatter::JSON < Formatter
5
+ # Output the data. If no headings are provided you'll get an Array or Arrays. If headings are provided you'll get an Array of Hashes.
6
+ # @return [String] the JSON data
7
+ def output()
8
+ data = @data
9
+ if @headings.size > 0
10
+ # Convert inner arrays to hashes
11
+ data = data.map{ |row| Hash[row.map.with_index{ |value, index| [@headings[index] || '', value] }] }
12
+ end
13
+ ::JSON.generate(data)
14
+ end
15
+ end # JSON Formatter
16
+
17
+ end # module SNMPTableViewer
@@ -0,0 +1,12 @@
1
+ module SNMPTableViewer
2
+
3
+ # Formatting class for raw output.
4
+ class Formatter::Raw < Formatter
5
+ # Output the data (and headings if provided).
6
+ # @return [String] the raw data
7
+ def output()
8
+ data_with_headings.inspect
9
+ end
10
+ end # Raw Fromatter
11
+
12
+ end # module SNMPTableViewer
@@ -0,0 +1,30 @@
1
+ module SNMPTableViewer
2
+
3
+ # Formatting class for Table output.
4
+ class Formatter::Table < Formatter
5
+ # Output the data (and headings if provided) as a table which can be displayed in the terminal.
6
+ # @param transpose [Boolean] Whether to swap rows and columns - useful for displaying a wide and short table
7
+ # @return [String] the text to display in order to draw the table
8
+ def output(transpose: false)
9
+ use_headings = @headings.size > 0
10
+ data = @data
11
+
12
+ if transpose
13
+ # transpose the data
14
+ if use_headings
15
+ data = [@headings, *data].transpose
16
+ use_headings = false # Don't add headings twice
17
+ else
18
+ data = data.transpose
19
+ end
20
+ end
21
+
22
+ if use_headings
23
+ Terminal::Table.new(rows: data, headings: @headings).to_s
24
+ else
25
+ Terminal::Table.new(rows: data).to_s
26
+ end
27
+ end
28
+ end # Table Formatter
29
+
30
+ end # module SNMPTableViewer
@@ -0,0 +1,30 @@
1
+ module SNMPTableViewer
2
+
3
+ # Parent class for formatters. Which take data and headings and output it in a given format.
4
+ # @abstract
5
+ class Formatter
6
+
7
+ # Create a new instance of Formatter.
8
+ # @param data [Array<Array<#to_s>>] A two dimensional array containing objects in each cell (at 'address' data[row][col])
9
+ # @param headings [Array<String, #to_s>] An array of headings for each column
10
+ # @return [Formatter]
11
+ def initialize(data:, headings: [])
12
+ @headings = headings
13
+ @data = data
14
+ end
15
+
16
+ private
17
+ # Get a two dimensioan array of headings prepended to the data or just the data (if no headings were provided).
18
+ # @return Array<Array<#to_s>>
19
+ def data_with_headings
20
+ has_headings? ? [@headings, *@data] : @data
21
+ end
22
+ # Determine if headings were passed.
23
+ # @return [Boolean]
24
+ def has_headings?
25
+ @headings.is_a?(Array) && @headings.size > 0
26
+ end
27
+
28
+ end # Formatter base class
29
+
30
+ end # module SNMPTableViewer
@@ -0,0 +1,14 @@
1
+ # Require gems
2
+ require 'netsnmp'
3
+ require 'terminal-table'
4
+
5
+ # Require from standard ruby libraries
6
+ require 'csv'
7
+ require 'json'
8
+
9
+ # Load the other files in the lib directory
10
+ require_relative '../version'
11
+ Dir["#{File.dirname(__FILE__)}/**/*.rb"].select{ |f| f != __FILE__}.sort.each { |f| load(f) }
12
+
13
+ module SNMPTableViewer
14
+ end # module SNMPTableViewer
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require File.join(File.dirname(__FILE__), 'version')
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "snmp_table_viewer"
7
+ s.license = 'BSD 3 clause'
8
+ s.version = SNMPTableViewer::VERSION
9
+ s.authors = ['Robert Gauld']
10
+ s.email = ['robert@robertgauld.co.uk']
11
+ s.homepage = 'https://github.com/robertgauld/snmp-table-viewer'
12
+ s.summary = %q{Easily view SNMP tables.}
13
+ s.description = %q{Easily view SNMP tables in a variety of different formats including as a table in the terminal, json or csv.}
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ s.add_runtime_dependency 'netsnmp', '~> 0.1.3'
21
+ s.add_runtime_dependency 'terminal-table', '~> 1.8.0'
22
+
23
+ s.add_development_dependency 'rake', '~> 12.0'
24
+ s.add_development_dependency 'rspec', '>= 2.14.1', '< 4'
25
+ s.add_development_dependency 'guard-rspec', '~> 4.2', '>= 4.2.5'
26
+ s.add_development_dependency 'rb-inotify', '~> 0.9'
27
+ s.add_development_dependency 'coveralls', '~> 0.7'
28
+ s.add_development_dependency 'simplecov', '~> 0.7'
29
+
30
+ end
@@ -0,0 +1,36 @@
1
+ describe SNMPTableViewer::Converter::IfTable do
2
+
3
+ describe '#convert' do
4
+
5
+ before :each do
6
+ @input = [[1, "lo", 24, 65536, nil, "", 1, 2, NETSNMP::Timetick.new(100), 18985, 220, 0, 0, 0, 0, 18985, 220, 0, 0, 0, nil, "0.0"]]
7
+ end
8
+
9
+ it 'Converts type' do
10
+ output = described_class.convert(@input)[0]
11
+ expect(output[2]).to eq '24 (softwareLoopback)'
12
+ end
13
+
14
+ it 'Converts admin state' do
15
+ output = described_class.convert(@input)[0]
16
+ expect(output[6]).to eq '1 (up)'
17
+ end
18
+
19
+ it 'Converts oper state' do
20
+ output = described_class.convert(@input)[0]
21
+ expect(output[7]).to eq '2 (down)'
22
+ end
23
+
24
+ it 'Converts last change' do
25
+ output = described_class.convert(@input)[0]
26
+ expect(output[8]).to eq 'Timeticks: (100) 0 days, 0:0:1.0'
27
+ end
28
+
29
+ end # describe #convert
30
+
31
+ end
32
+
33
+
34
+
35
+
36
+ # [1, "lo", 24, 65536, nil, "", 1, 1, NETSNMP::Timetick.new(100), 18985, 220, 0, 0, 0, 0, 18985, 220, 0, 0, 0, nil, "0.0"]
@@ -0,0 +1,2 @@
1
+ describe SNMPTableViewer::Converter do
2
+ end
@@ -0,0 +1,23 @@
1
+ describe SNMPTableViewer::Fetcher do
2
+
3
+ it 'Fetches' do
4
+ snmp_options = {opt_a: :a}
5
+ manager = double("manager")
6
+ expect(manager).to receive(:walk).with(oid: '1.2.3.4.5').once.and_return([
7
+ ['1.2.3.4.5.0.1.1', 1],
8
+ ['1.2.3.4.5.0.1.2', 2],
9
+ ['1.2.3.4.5.0.2.1', 'a'],
10
+ ['1.2.3.4.5.0.2.2', 'b'],
11
+ ['1.2.3.4.5.0.3.1', 'A'],
12
+ ['1.2.3.4.5.0.3.2', 'B'],
13
+ ]) # Array returned by manager doing the SNMP walk
14
+ expect(NETSNMP::Client).to receive(:new).with(snmp_options).once do |&block|
15
+ block.call(manager)
16
+ end # expect block
17
+ expect(described_class.from_snmp(base_oid: '1.2.3.4.5', **snmp_options)).to eq [
18
+ [1, 'a', 'A'],
19
+ [2, 'b', 'B']
20
+ ]
21
+ end
22
+
23
+ end
@@ -0,0 +1,26 @@
1
+ describe SNMPTableViewer::Formatter::CSV do
2
+
3
+ describe '#output' do
4
+
5
+ it 'With headings' do
6
+ headings = ['heading1', 'heading2', 'heading3']
7
+ data = [
8
+ ['row1col1', 'row1col2', 'a,b'],
9
+ ['row2col1', 'row2col2', 'b,c']
10
+ ]
11
+ formatter = described_class.new(data: data, headings: headings)
12
+ expect(formatter.output).to eq "heading1,heading2,heading3\nrow1col1,row1col2,\"a,b\"\nrow2col1,row2col2,\"b,c\"\n"
13
+ end
14
+
15
+ it 'Without headings' do
16
+ data = [
17
+ ['row1col1', 'row1col2', 'a,b'],
18
+ ['row2col1', 'row2col2', 'b,c']
19
+ ]
20
+ formatter = described_class.new(data: data)
21
+ expect(formatter.output).to eq "row1col1,row1col2,\"a,b\"\nrow2col1,row2col2,\"b,c\"\n"
22
+ end
23
+
24
+ end # describe #output
25
+
26
+ end
@@ -0,0 +1,26 @@
1
+ describe SNMPTableViewer::Formatter::JSON do
2
+
3
+ describe '#output' do
4
+
5
+ it 'With headings' do
6
+ headings = ['heading1', 'heading2', 'heading3']
7
+ data = [
8
+ ['row1col1', 'row1col2', 'a,b'],
9
+ ['row2col1', 'row2col2', 'b,c']
10
+ ]
11
+ formatter = described_class.new(data: data, headings: headings)
12
+ expect(formatter.output).to eq '[{"heading1":"row1col1","heading2":"row1col2","heading3":"a,b"},{"heading1":"row2col1","heading2":"row2col2","heading3":"b,c"}]'
13
+ end
14
+
15
+ it 'Without headings' do
16
+ data = [
17
+ ['row1col1', 'row1col2', 'a,b'],
18
+ ['row2col1', 'row2col2', 'b,c']
19
+ ]
20
+ formatter = described_class.new(data: data)
21
+ expect(formatter.output).to eq '[["row1col1","row1col2","a,b"],["row2col1","row2col2","b,c"]]'
22
+ end
23
+
24
+ end # describe #output
25
+
26
+ end
@@ -0,0 +1,26 @@
1
+ describe SNMPTableViewer::Formatter::Raw do
2
+
3
+ describe '#output' do
4
+
5
+ it 'With headings' do
6
+ headings = ['heading1', 'heading2', 'heading3']
7
+ data = [
8
+ ['row1col1', 'row1col2', 'a,b'],
9
+ ['row2col1', 'row2col2', 'b,c']
10
+ ]
11
+ formatter = described_class.new(data: data, headings: headings)
12
+ expect(formatter.output).to eq '[["heading1", "heading2", "heading3"], ["row1col1", "row1col2", "a,b"], ["row2col1", "row2col2", "b,c"]]'
13
+ end
14
+
15
+ it 'Without headings' do
16
+ data = [
17
+ ['row1col1', 'row1col2', 'a,b'],
18
+ ['row2col1', 'row2col2', 'b,c']
19
+ ]
20
+ formatter = described_class.new(data: data)
21
+ expect(formatter.output).to eq '[["row1col1", "row1col2", "a,b"], ["row2col1", "row2col2", "b,c"]]'
22
+ end
23
+
24
+ end # describe #output
25
+
26
+ end