mesa_test 1.0.2 → 1.1.1

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 +10 -3
  3. data/lib/mesa_test.rb +213 -22
  4. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 56e31a9841e2aae7f051e81c87283288c30a760dbf86799f34e3c4106e05536a
4
- data.tar.gz: caef468ad982b2d508c56067c3b10e9f645f0a02cccb86f4d770b94ce3e190a8
3
+ metadata.gz: c75d606f1563b84b57b6eba19e52d67badc7c0aa0080e8a0079f2979081901b1
4
+ data.tar.gz: f22702d62513f2ebb8fb432a417ca7705311eba433eb92457258d1f6e8270484
5
5
  SHA512:
6
- metadata.gz: '09e0a052e5628e28ed6786811e5861548c02924153fe74c133e6a1265f5bdaa1e35cd479bae5181c14423ac04b5588d28223d441c8959f56629ebfbbc6f33b9f'
7
- data.tar.gz: bb40a700dc352a309191c90550d9ab598ad9d2a2f5d9e123590f1d89960962bcc54d1e32afa2e06916bf6cf886e8391b8a18f20efecd0fbcd68024dd755bad8b
6
+ metadata.gz: c8b788bccd4055590a40194cf4e58ac91386673d4db52e8ac2ebbc501b9e1bc10537082ecb92ecabb810edb8e3aa3f71fdb1f6856fb31b2bffa67e69856db7f5
7
+ data.tar.gz: 89fa655c7b861d47a7edbd42a5f27ec00377cd357394ba75fa1955d61a5265ee1c4d1db478c4905ddd22d2aa820b8a8bb5df1685912ba27fc1dbee64f63d0f75
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
@@ -209,8 +210,14 @@ class MesaTest < Thor
209
210
  github_protocol: s.github_protocol
210
211
  )
211
212
  end
212
- m.clean
213
- m.install
213
+ begin
214
+ m.clean
215
+ m.install
216
+ rescue MesaDirError
217
+ shell.say "\nFailed in compiling MESA.", :red
218
+ else
219
+ shell.say "\nSuccessfully compiled MESA commit #{m.sha}.", :green
220
+ end
214
221
  end
215
222
 
216
223
  desc 'install_and_test [SHA]', 'Install, test, and submit an entire commit.'
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)
@@ -110,7 +116,7 @@ e-mail and password will be stored in plain text.'
110
116
 
111
117
  attr_accessor :computer_name, :user_name, :email, :password, :platform,
112
118
  :mesa_mirror, :mesa_work, :platform_version, :processor,
113
- :config_file, :base_uri, :last_tested, :github_protocol
119
+ :config_file, :base_uri, :github_protocol, :logs_token
114
120
 
115
121
  attr_reader :shell
116
122
 
@@ -118,7 +124,7 @@ e-mail and password will be stored in plain text.'
118
124
  def initialize(
119
125
  computer_name: nil, user_name: nil, email: nil, github_protocol: nil,
120
126
  mesa_mirror: nil, platform: nil, platform_version: nil, processor: nil,
121
- config_file: nil, base_uri: nil, last_tested: nil
127
+ config_file: nil, base_uri: nil, logs_token: nil
122
128
  )
123
129
  @computer_name = computer_name || Socket.gethostname.scan(/^[^\.]+\.?/)[0]
124
130
  @computer_name.chomp!('.') if @computer_name
@@ -146,6 +152,7 @@ e-mail and password will be stored in plain text.'
146
152
  @config_file = config_file || File.join(ENV['HOME'], '.mesa_test',
147
153
  'config.yml')
148
154
  @base_uri = base_uri
155
+ @logs_token = logs_token || ENV['MESA_LOGS_TOKEN']
149
156
 
150
157
  # set up thor-proof way to get responses from user. Thor hijacks the
151
158
  # gets command, so we have to use its built-in "ask" method, which is
@@ -166,6 +173,7 @@ e-mail and password will be stored in plain text.'
166
173
  puts "Computer Name #{computer_name}"
167
174
  puts "User email #{email}"
168
175
  puts 'Password ***********'
176
+ puts "logs API token #{logs_token}"
169
177
  puts "GitHub Protocol #{github_protocol}"
170
178
  puts "MESA Mirror Location #{mesa_mirror}"
171
179
  puts "MESA Work Location #{mesa_work}"
@@ -188,6 +196,7 @@ e-mail and password will be stored in plain text.'
188
196
  'computer_name' => computer_name,
189
197
  'email' => email,
190
198
  'password' => password,
199
+ 'logs_token' => logs_token,
191
200
  'github_protocol' => github_protocol,
192
201
  'mesa_mirror' => mesa_mirror,
193
202
  'mesa_work' => mesa_work,
@@ -206,6 +215,7 @@ e-mail and password will be stored in plain text.'
206
215
  @computer_name = data_hash['computer_name']
207
216
  @email = data_hash['email']
208
217
  @password = data_hash['password']
218
+ @logs_token = data_hash['logs_token']
209
219
  @github_protocol = data_hash['github_protocol'].to_sym
210
220
  @mesa_mirror = data_hash['mesa_mirror']
211
221
  @mesa_work = data_hash['mesa_work']
@@ -273,6 +283,28 @@ e-mail and password will be stored in plain text.'
273
283
  res
274
284
  end
275
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
+
276
308
  # Parameters for a single test case. +mesa+ is an instance of +Mesa+, and
277
309
  # +test_case+ is an instance of MesaTestCase representing the test case to
278
310
  # be submitted
@@ -289,7 +321,7 @@ e-mail and password will be stored in plain text.'
289
321
  https.use_ssl = base_uri.include? 'https'
290
322
 
291
323
  request = Net::HTTP::Post.new(
292
- uri, initheader = { 'Content-Type' => 'application/json' }
324
+ uri, initheader = { 'Accept' => 'application/json', 'Content-Type' => 'application/json' }
293
325
  )
294
326
  request.body = {
295
327
  email: email,
@@ -302,20 +334,26 @@ e-mail and password will be stored in plain text.'
302
334
  # submit entire commit's worth of test cases, OR submit compilation status
303
335
  # and NO test cases
304
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
305
341
  uri = URI.parse(base_uri + '/submissions/create.json')
306
342
  https = Net::HTTP.new(uri.hostname, uri.port)
307
343
  https.use_ssl = true if base_uri.include? 'https'
308
344
 
309
345
  request = Net::HTTP::Post.new(
310
346
  uri,
311
- initheader = { 'Content-Type' => 'application/json' }
347
+ initheader = { 'Accept' => 'application/json', 'Content-Type' => 'application/json' }
312
348
  )
313
349
 
314
350
  # create the request body for submission to the submissions API
315
351
  #
316
352
  # if we have an empty submission, then it is necessarily not entire.
317
353
  # Similarly, a non-empty submission is necessarily entire (otherwise one
318
- # 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?
319
357
  request_data = {submitter: submitter_params,
320
358
  commit: commit_params(mesa, empty: empty, entire: !empty)}
321
359
  # don't need test instances if it's an empty submission or if compilation
@@ -334,20 +372,47 @@ e-mail and password will be stored in plain text.'
334
372
  false
335
373
  else
336
374
  shell.say "\nSuccessfully submitted commit #{mesa.sha}.", :green
337
- 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
338
398
  end
339
399
  end
340
400
 
341
401
  # submit results for a single test case instance. Does *not* report overall
342
402
  # compilation status to testhub. Use an empty commit submission for that
343
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
+
344
409
  uri = URI.parse(base_uri + '/submissions/create.json')
345
410
  https = Net::HTTP.new(uri.hostname, uri.port)
346
411
  https.use_ssl = true if base_uri.include? 'https'
347
412
 
348
413
  request = Net::HTTP::Post.new(
349
414
  uri,
350
- initheader = { 'Content-Type' => 'application/json' }
415
+ initheader = { 'Accept' => 'application/json', 'Content-Type' => 'application/json' }
351
416
  )
352
417
 
353
418
  # create the request body for submission to the submissions API
@@ -369,9 +434,80 @@ e-mail and password will be stored in plain text.'
369
434
  else
370
435
  shell.say "\nSuccessfully submitted instance of #{test_case.test_name} "\
371
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
372
478
  true
373
479
  end
374
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
+
375
511
  end
376
512
 
377
513
  class Mesa
@@ -553,18 +689,29 @@ class Mesa
553
689
  'show a successful installation).'
554
690
  end
555
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
+
556
700
  # sourced from $MESA_DIR/testhub.yml, which should be created after
557
701
  # installation
558
702
  def compiler_hash
559
703
  data_file = File.join(mesa_dir, 'testhub.yml')
560
- unless File.exist? data_file
561
- 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
562
714
  end
563
-
564
- res = YAML.safe_load(File.read(data_file))
565
- # currently version_number is reported, but we don't need that in Git land
566
- res.delete('version_number') # returns the value, not the updated hash
567
- res
568
715
  end
569
716
 
570
717
  ## TEST SUITE METHODS
@@ -602,12 +749,16 @@ class Mesa
602
749
  num, tc_name = line.strip.split
603
750
  @names_to_numbers[mod][tc_name.strip] = num.to_i
604
751
  @test_case_names[mod] << tc_name.strip
605
- @test_cases[mod][tc_name.strip] = MesaTestCase.new(
606
- test: tc_name.strip,
607
- mod: mod,
608
- position: num.to_i,
609
- mesa: self
610
- )
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
611
762
  end
612
763
  end
613
764
  end
@@ -647,11 +798,16 @@ class Mesa
647
798
  def installed?
648
799
  # assume build log reflects installation status; does not account for
649
800
  # mucking with modules after the fact
650
- 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?(
651
803
  'MESA installation was successful'
652
804
  )
653
805
  end
654
806
 
807
+ def install_attempted?
808
+ File.exist? File.join(mesa_dir, 'testhub.yml')
809
+ end
810
+
655
811
  private
656
812
 
657
813
  # verify that mesa_dir is valid by checking for existence of test_suite
@@ -836,6 +992,36 @@ class MesaTestCase
836
992
  YAML.safe_load(File.read(testhub_file), [Symbol])
837
993
  end
838
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
+
839
1025
  private
840
1026
 
841
1027
  # cd into the test case directory, do something in a block, then cd back
@@ -934,3 +1120,8 @@ end
934
1120
  def bashticks(command)
935
1121
  `bash -c "#{command}"`.chomp
936
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.2
4
+ version: 1.1.1
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-19 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.