mesa_test 1.0.1 → 1.1.0

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.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/bin/mesa_test +2 -1
  3. data/lib/mesa_test.rb +220 -27
  4. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4400ba9260e7fb896e1ae980fb7a8795b5efeaec672fcea5ce108eed8ae8a355
4
- data.tar.gz: 60c95a170bfbdbafa537dc99bf7dc23822ea6a5dbea1093ede0d46e6d7ae19aa
3
+ metadata.gz: 2c6b3c8632cb3efbbabbcbd9534f5519a317a0f80d991227dde9c7acc1257946
4
+ data.tar.gz: 81ac0670ba6f3e7799bd3f07ea571f9cee317a8cb2cc230fe8d7b2fa96837622
5
5
  SHA512:
6
- metadata.gz: 938faed6625333b5890428d47495b0039b5a17bdaf09cdc703d38a4d07a1403c9f28d8a9fb98b360f9b9d5d32d48510d367b8c64381ef723ec58eb23550e72c7
7
- data.tar.gz: b401ff50c34c01cda33f43fa5e3c5b88808f80ed6aaabd2300f2af15d7ac364dfb71f5880cf02ee9512f78e0967b34447ea98de304106eea2558bd0d8891e687
6
+ metadata.gz: f23b4cb696c153072d2890d4c6ec1c412ed6e9ce723568367ae731ca8b4189ada86dfcaca27d04899f14ec175971beafe2e15c91488ac777181200de8bf54f0a
7
+ data.tar.gz: 5d4c7559f31733ad12c88bec794663ac873b36fa2166129ceac9d17cb29ac8db019110f853360b0b60a6067a9ca469b3c26e35e1e44581b16be514df8297a544
data/bin/mesa_test CHANGED
@@ -138,7 +138,8 @@ class MesaTest < Thor
138
138
  m.check_installation
139
139
  rescue MesaDirError
140
140
  shell.say %q{This MESA installation doesn't seem to be compiled } \
141
- 'properly. Submitting a compilation failure to MESATestHub.', :red
141
+ 'properly. Attempting to submit a compilation failure to '\
142
+ 'MESATestHub.', :red
142
143
  empty = true
143
144
  ensure
144
145
  # submit all tests
data/lib/mesa_test.rb CHANGED
@@ -7,6 +7,7 @@ require 'net/http'
7
7
  require 'net/https'
8
8
  require 'thor'
9
9
  require 'json'
10
+ require 'base64'
10
11
 
11
12
  MesaDirError = Class.new(StandardError)
12
13
  TestCaseDirError = Class.new(StandardError)
@@ -48,9 +49,14 @@ e-mail and password will be stored in plain text.'
48
49
  "#{s.email} (required)? (#{s.password})", :blue
49
50
  s.password = response unless response.empty?
50
51
 
52
+ # Get API key for submitting failure logs
53
+ response = shell.ask 'What is the logs submission API token associated '\
54
+ "with the email #{s.email} (required)? (#{s.logs_token})", :blue
55
+ s.logs_token = response unless response.empty?
56
+
51
57
  # Determine if we'll use ssh or https to access github
52
58
  response = shell.ask 'When accessing GitHub, which protocol do you '\
53
- 'want to use? ', :blue, limited_to: %w[ssh https]
59
+ 'want to use?', :blue, limited_to: %w[ssh https]
54
60
  s.github_protocol = response.strip.downcase.to_sym
55
61
 
56
62
  # Get location of source MESA repo (the mirror)
@@ -75,10 +81,12 @@ e-mail and password will be stored in plain text.'
75
81
  "Ubuntu 16.04)? (#{s.platform_version}):", :blue
76
82
  s.platform_version = response unless response.empty?
77
83
 
78
- # Confirm save location
79
- response = shell.ask "This will be saved in #{s.config_file}. Press " \
80
- 'enter to accept or enter a new location:', :blue, path: true
81
- s.config_file = response unless response.empty?
84
+ # we are powerless to do change the location for now, so stop asking
85
+ # about it
86
+ # # Confirm save location
87
+ # response = shell.ask "This will be saved in #{s.config_file}. Press " \
88
+ # 'enter to accept or enter a new location:', :blue, path: true
89
+ # s.config_file = response unless response.empty?
82
90
  end
83
91
 
84
92
  # Confirm data. If not confirmed, restart whole wizard.
@@ -108,7 +116,7 @@ e-mail and password will be stored in plain text.'
108
116
 
109
117
  attr_accessor :computer_name, :user_name, :email, :password, :platform,
110
118
  :mesa_mirror, :mesa_work, :platform_version, :processor,
111
- :config_file, :base_uri, :last_tested, :github_protocol
119
+ :config_file, :base_uri, :github_protocol, :logs_token
112
120
 
113
121
  attr_reader :shell
114
122
 
@@ -116,7 +124,7 @@ e-mail and password will be stored in plain text.'
116
124
  def initialize(
117
125
  computer_name: nil, user_name: nil, email: nil, github_protocol: nil,
118
126
  mesa_mirror: nil, platform: nil, platform_version: nil, processor: nil,
119
- config_file: nil, base_uri: nil, last_tested: nil
127
+ config_file: nil, base_uri: nil, logs_token: nil
120
128
  )
121
129
  @computer_name = computer_name || Socket.gethostname.scan(/^[^\.]+\.?/)[0]
122
130
  @computer_name.chomp!('.') if @computer_name
@@ -144,6 +152,7 @@ e-mail and password will be stored in plain text.'
144
152
  @config_file = config_file || File.join(ENV['HOME'], '.mesa_test',
145
153
  'config.yml')
146
154
  @base_uri = base_uri
155
+ @logs_token = logs_token || ENV['MESA_LOGS_TOKEN']
147
156
 
148
157
  # set up thor-proof way to get responses from user. Thor hijacks the
149
158
  # gets command, so we have to use its built-in "ask" method, which is
@@ -164,11 +173,12 @@ e-mail and password will be stored in plain text.'
164
173
  puts "Computer Name #{computer_name}"
165
174
  puts "User email #{email}"
166
175
  puts 'Password ***********'
176
+ puts "logs API token #{logs_token}"
167
177
  puts "GitHub Protocol #{github_protocol}"
168
178
  puts "MESA Mirror Location #{mesa_mirror}"
169
179
  puts "MESA Work Location #{mesa_work}"
170
180
  puts "Platform #{platform} #{platform_version}"
171
- puts "Config location #{config_file}"
181
+ # puts "Config location #{config_file}"
172
182
  puts '-------------------------------------------------------'
173
183
  puts ''
174
184
  response = shell.ask 'Is this correct? (y/Y = Yes, anything else = No):'
@@ -186,6 +196,7 @@ e-mail and password will be stored in plain text.'
186
196
  'computer_name' => computer_name,
187
197
  'email' => email,
188
198
  'password' => password,
199
+ 'logs_token' => logs_token,
189
200
  'github_protocol' => github_protocol,
190
201
  'mesa_mirror' => mesa_mirror,
191
202
  'mesa_work' => mesa_work,
@@ -204,6 +215,7 @@ e-mail and password will be stored in plain text.'
204
215
  @computer_name = data_hash['computer_name']
205
216
  @email = data_hash['email']
206
217
  @password = data_hash['password']
218
+ @logs_token = data_hash['logs_token']
207
219
  @github_protocol = data_hash['github_protocol'].to_sym
208
220
  @mesa_mirror = data_hash['mesa_mirror']
209
221
  @mesa_work = data_hash['mesa_work']
@@ -271,6 +283,28 @@ e-mail and password will be stored in plain text.'
271
283
  res
272
284
  end
273
285
 
286
+ # Parameters for reporting a failed compilation to the logs server
287
+ def build_log_params(mesa)
288
+ {
289
+ 'computer_name' => computer_name,
290
+ 'commit' => mesa.sha,
291
+ 'build.log' => mesa.build_log_64
292
+ }
293
+ end
294
+
295
+ # Parameters for reporting a failed test to the logs server
296
+ def test_log_params(test_case)
297
+ res = {
298
+ 'computer_name' => computer_name,
299
+ 'commit' => test_case.mesa.sha,
300
+ 'test_case' => test_case.test_name
301
+ }
302
+ res['mk.txt'] = test_case.mk_64 unless test_case.mk_64.empty?
303
+ res['out.txt'] = test_case.out_64 unless test_case.out_64.empty?
304
+ res['err.txt'] = test_case.err_64 unless test_case.err_64.empty?
305
+ res
306
+ end
307
+
274
308
  # Parameters for a single test case. +mesa+ is an instance of +Mesa+, and
275
309
  # +test_case+ is an instance of MesaTestCase representing the test case to
276
310
  # be submitted
@@ -287,7 +321,7 @@ e-mail and password will be stored in plain text.'
287
321
  https.use_ssl = base_uri.include? 'https'
288
322
 
289
323
  request = Net::HTTP::Post.new(
290
- uri, initheader = { 'Content-Type' => 'application/json' }
324
+ uri, initheader = { 'Accept' => 'application/json', 'Content-Type' => 'application/json' }
291
325
  )
292
326
  request.body = {
293
327
  email: email,
@@ -300,20 +334,26 @@ e-mail and password will be stored in plain text.'
300
334
  # submit entire commit's worth of test cases, OR submit compilation status
301
335
  # and NO test cases
302
336
  def submit_commit(mesa, empty: false)
337
+ unless mesa.install_attempted?
338
+ raise MesaDirError, 'No testhub.yml file found in installation; '\
339
+ 'must attempt to install before subitting.'
340
+ end
303
341
  uri = URI.parse(base_uri + '/submissions/create.json')
304
342
  https = Net::HTTP.new(uri.hostname, uri.port)
305
343
  https.use_ssl = true if base_uri.include? 'https'
306
344
 
307
345
  request = Net::HTTP::Post.new(
308
346
  uri,
309
- initheader = { 'Content-Type' => 'application/json' }
347
+ initheader = { 'Accept' => 'application/json', 'Content-Type' => 'application/json' }
310
348
  )
311
349
 
312
350
  # create the request body for submission to the submissions API
313
351
  #
314
352
  # if we have an empty submission, then it is necessarily not entire.
315
353
  # Similarly, a non-empty submission is necessarily entire (otherwise one
316
- # would use +submit_instance+)
354
+ # would use +submit_instance+). Also, make a "nonempty" submission be
355
+ # empty if there was an overall build error
356
+ empty ||= !mesa.installed?
317
357
  request_data = {submitter: submitter_params,
318
358
  commit: commit_params(mesa, empty: empty, entire: !empty)}
319
359
  # don't need test instances if it's an empty submission or if compilation
@@ -332,20 +372,47 @@ e-mail and password will be stored in plain text.'
332
372
  false
333
373
  else
334
374
  shell.say "\nSuccessfully submitted commit #{mesa.sha}.", :green
335
- true
375
+ # commit submitted to testhub, now submit build log if compilation failed
376
+ # and exit
377
+ unless mesa.installed?
378
+ return submit_build_log(mesa)
379
+ end
380
+
381
+ # compilation succeded, so submit any logs for failing tests
382
+ res = true
383
+ unless empty
384
+ mesa.test_cases.each do |mod, test_case_hash|
385
+ test_case_hash.each do |tc_name, test_case|
386
+ # get at each individual test case, see if it failed, and if it
387
+ # did, submit its log files
388
+ unless test_case.passed?
389
+ res &&= submit_test_log(test_case)
390
+ end
391
+ end
392
+ end
393
+ end
394
+
395
+ # a true return value means that any and all log submission were
396
+ # successful
397
+ res
336
398
  end
337
399
  end
338
400
 
339
401
  # submit results for a single test case instance. Does *not* report overall
340
402
  # compilation status to testhub. Use an empty commit submission for that
341
403
  def submit_instance(mesa, test_case)
404
+ unless mesa.install_attempted?
405
+ raise MesaDirError, 'No testhub.yml file found in installation; '\
406
+ 'must attempt to install before subitting.'
407
+ end
408
+
342
409
  uri = URI.parse(base_uri + '/submissions/create.json')
343
410
  https = Net::HTTP.new(uri.hostname, uri.port)
344
411
  https.use_ssl = true if base_uri.include? 'https'
345
412
 
346
413
  request = Net::HTTP::Post.new(
347
414
  uri,
348
- initheader = { 'Content-Type' => 'application/json' }
415
+ initheader = { 'Accept' => 'application/json', 'Content-Type' => 'application/json' }
349
416
  )
350
417
 
351
418
  # create the request body for submission to the submissions API
@@ -367,9 +434,80 @@ e-mail and password will be stored in plain text.'
367
434
  else
368
435
  shell.say "\nSuccessfully submitted instance of #{test_case.test_name} "\
369
436
  "for commit #{mesa.sha}.", :green
437
+ # submit logs if test failed
438
+ return submit_test_log(test_case) unless test_case.passed?
439
+ true
440
+ end
441
+ end
442
+
443
+ # make generic request to LOGS server
444
+ # +params+ is a hash of data to be encoded as JSON and sent off
445
+ def submit_logs(params)
446
+ uri = URI('https://logs.mesastar.org/uploads')
447
+ https = Net::HTTP.new(uri.host, uri.port)
448
+ https.use_ssl = true
449
+ req = Net::HTTP::Post.new(uri.path, 'Content-Type' => 'application/json',
450
+ 'X-Api-Key' => logs_token)
451
+ req.body = params.to_json
452
+ https.request(req)
453
+ end
454
+
455
+ # send build log to the logs server
456
+ def submit_build_log(mesa)
457
+ # intercept and don't send if mesa was properly installed
458
+ return true if mesa.installed?
459
+
460
+ # don't even try unless we have a logs token set
461
+ unless logs_token
462
+ shell.say 'Cannot submit to logs server; need to set mesa_logs_token '\
463
+ 'in the mesa_test config file.'
464
+ return false
465
+ end
466
+
467
+ # do submission
468
+ res = submit_logs(build_log_params(mesa))
469
+
470
+ # report out results
471
+ if !res.is_a? Net::HTTPOK
472
+ shell.say "\nFailed to submit build.log to the LOGS server for commit "\
473
+ "#{mesa.sha}.", :red
474
+ false
475
+ else
476
+ shell.say "\nSuccessfully submitted build.log to the LOGS server for "\
477
+ "#{mesa.sha}.", :green
370
478
  true
371
479
  end
372
480
  end
481
+
482
+ # send build log to the logs server
483
+ def submit_test_log(test_case)
484
+ # skip submission if mesa was never installed or if the test passed
485
+ return true if !test_case.mesa.installed? || test_case.passed?
486
+
487
+ # don't even try unless we have a logs token set
488
+ unless logs_token
489
+ shell.say 'Cannot submit to logs server; need to set mesa_logs_token '\
490
+ 'in the mesa_test config file..'
491
+ return false
492
+ end
493
+
494
+ # do submission
495
+ res = submit_logs(test_log_params(test_case))
496
+
497
+ # report out results
498
+ if !res.is_a? Net::HTTPOK
499
+ shell.say "Failed to submit out.txt and mk.txt to the LOGS server for "\
500
+ "test case #{test_case.test_name} in commit "\
501
+ "#{test_case.mesa.sha}.", :red
502
+ false
503
+ else
504
+ shell.say "Successfully submitted out.txt and mk.txt to the LOGS "\
505
+ "server for test case #{test_case.test_name} in commit "\
506
+ "#{test_case.mesa.sha}.", :green
507
+ true
508
+ end
509
+ end
510
+
373
511
  end
374
512
 
375
513
  class Mesa
@@ -551,18 +689,29 @@ class Mesa
551
689
  'show a successful installation).'
552
690
  end
553
691
 
692
+ # base 64-encoded contents of build.log
693
+ def build_log_64
694
+ build_log = File.join(mesa_dir, 'build.log')
695
+ return '' unless File.exist?(build_log)
696
+
697
+ b64_file(build_log)
698
+ end
699
+
554
700
  # sourced from $MESA_DIR/testhub.yml, which should be created after
555
701
  # installation
556
702
  def compiler_hash
557
703
  data_file = File.join(mesa_dir, 'testhub.yml')
558
- unless File.exist? data_file
559
- raise(MesaDirError, "Could not find file testhub.yml in #{mesa_dir}.")
704
+ res = {
705
+ compiler: 'Unknown',
706
+ sdk_version: 'Unknown',
707
+ math_backend: 'Unknown'
708
+ }
709
+ if File.exist? data_file
710
+ res = res.merge(YAML.safe_load(File.read(data_file)) || {})
711
+ # currently version_number is reported, but we don't need that in Git land
712
+ res.delete('version_number') # returns the value, not the updated hash
713
+ res
560
714
  end
561
-
562
- res = YAML.safe_load(File.read(data_file))
563
- # currently version_number is reported, but we don't need that in Git land
564
- res.delete('version_number') # returns the value, not the updated hash
565
- res
566
715
  end
567
716
 
568
717
  ## TEST SUITE METHODS
@@ -600,12 +749,16 @@ class Mesa
600
749
  num, tc_name = line.strip.split
601
750
  @names_to_numbers[mod][tc_name.strip] = num.to_i
602
751
  @test_case_names[mod] << tc_name.strip
603
- @test_cases[mod][tc_name.strip] = MesaTestCase.new(
604
- test: tc_name.strip,
605
- mod: mod,
606
- position: num.to_i,
607
- mesa: self
608
- )
752
+ begin
753
+ @test_cases[mod][tc_name.strip] = MesaTestCase.new(
754
+ test: tc_name.strip,
755
+ mod: mod,
756
+ position: num.to_i,
757
+ mesa: self
758
+ )
759
+ rescue TestCaseDirError
760
+ shell.say "No such test case #{tc_name.strip}. Skipping loading it.", :red
761
+ end
609
762
  end
610
763
  end
611
764
  end
@@ -645,11 +798,16 @@ class Mesa
645
798
  def installed?
646
799
  # assume build log reflects installation status; does not account for
647
800
  # mucking with modules after the fact
648
- downloaded? && File.read(File.join(mesa_dir, 'build.log')).include?(
801
+ build_log = File.join(mesa_dir, 'build.log')
802
+ downloaded? && File.exist?(build_log) && File.read(build_log).include?(
649
803
  'MESA installation was successful'
650
804
  )
651
805
  end
652
806
 
807
+ def install_attempted?
808
+ File.exist? File.join(mesa_dir, 'testhub.yml')
809
+ end
810
+
653
811
  private
654
812
 
655
813
  # verify that mesa_dir is valid by checking for existence of test_suite
@@ -834,6 +992,36 @@ class MesaTestCase
834
992
  YAML.safe_load(File.read(testhub_file), [Symbol])
835
993
  end
836
994
 
995
+ # whether or not a test case has passed; only has meaning
996
+ # if we can load the results hash, though
997
+ def passed?
998
+ results_hash['outcome'] == :pass
999
+ end
1000
+
1001
+ # Base-64 encoded contents of mk.txt file
1002
+ def mk_64
1003
+ mk_file = File.join(test_case_dir, 'mk.txt')
1004
+ return '' unless File.exist?(mk_file)
1005
+
1006
+ b64_file(mk_file)
1007
+ end
1008
+
1009
+ # Base-64 encoded contents of err.txt file
1010
+ def err_64
1011
+ err_file = File.join(test_case_dir, 'err.txt')
1012
+ return '' unless File.exist?(err_file)
1013
+
1014
+ b64_file(err_file)
1015
+ end
1016
+
1017
+ # Base-64 encoded contents of out.txt file
1018
+ def out_64
1019
+ out_file = File.join(test_case_dir, 'out.txt')
1020
+ return '' unless File.exist?(out_file)
1021
+
1022
+ b64_file(out_file)
1023
+ end
1024
+
837
1025
  private
838
1026
 
839
1027
  # cd into the test case directory, do something in a block, then cd back
@@ -932,3 +1120,8 @@ end
932
1120
  def bashticks(command)
933
1121
  `bash -c "#{command}"`.chomp
934
1122
  end
1123
+
1124
+ # encode the contents of a file as base-64
1125
+ def b64_file(filename)
1126
+ Base64.encode64(File.open(filename).read)
1127
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mesa_test
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - William Wolf
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-12-17 00:00:00.000000000 Z
11
+ date: 2021-05-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -81,7 +81,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  requirements: []
84
- rubygems_version: 3.1.2
84
+ rubygems_version: 3.2.3
85
85
  signing_key:
86
86
  specification_version: 4
87
87
  summary: Command line tool for running and reporting the MESA test suites.