<commit_before>#lang at-exp racket/base

(require net/ftp tests/eli-tester
         racket/tcp racket/port racket/file racket/match)

(define (tcp-serve dest text)
  (define listener (tcp-listen 0))
  (define the-port (let-values ([(_1 p _2 _3) (tcp-addresses listener #t)]) p))
  (define (feed in out)
    (if (input-port? in) (copy-port in out) (display in out))
    (flush-output out))
  (define (feeder)
    (define-values [ip op] (tcp-accept listener))
    (for-each thread-wait
              (list (thread (λ () (feed text op) (close-output-port op)))
                    (thread (λ () (feed ip dest) (close-input-port ip))))))
  (values (thread feeder) the-port))

(define (port->splitstr n)
  (let-values ([(q r) (quotient/remainder n 256)]) (format "~a,~a" q r)))
(define (tcp-serve* dest text)
  (define-values [thd port] (tcp-serve dest text))
  (values thd (port->splitstr port)))

(define ((progress-proc dir) get-count)
  (thread
   (lambda ()
     (let loop ()
       (define-values (count changed-evt) (get-count))
       (printf "~a bytes ~aloaded\n" count dir)
       (sync changed-evt)
       (loop)))))

(provide tests)
(module+ main (tests))
(define (tests)
  (define cop (open-output-string))
  (define-values [pasv1-thd pasv1-port] (tcp-serve* (current-output-port) DIRLIST))
  (define-values [pasv2-thd pasv2-port] (tcp-serve* (current-output-port) TEXT-FILE))
  (define-values [pasv3-thd pasv3-port] (tcp-serve* (open-output-nowhere) TEXT-FILE))
  (define-values [main-thd main-port] (tcp-serve cop (SERVER-OUTPUT pasv1-port pasv2-port pasv3-port)))
  (define server "127.0.0.1")
  (define port main-port)
  (define user "anonymous")
  (define passwd "<PASSWORD>")
  (define conn #f)
  (define pth "=README-about-.diff-files")
  (define tmp-dir (make-temporary-file "racket-ftp-test-~a" 'directory))
  (test (port->splitstr 18291) => "71,115"
        (ftp-connection? 1) => #f
        (set! conn (ftp-establish-connection server port user passwd))
        (ftp-connection? conn)
        (when (ftp-connection? conn)
          (test (ftp-cd conn "gnu")
                (for ([f (in-list (ftp-directory-list conn))])
                  (match-define (list* type ftp-date name ?size) f)
                  (test (ftp-make-file-seconds ftp-date)))
                (ftp-download-file conn tmp-dir pth #:progress (progress-proc "down"))
                (ftp-upload-file conn (path->string (build-path tmp-dir pth)) #:progress (progress-proc "up"))
                (ftp-delete-file conn "3dldf/test.file")
                (ftp-make-directory conn "test")
                (ftp-delete-directory conn "test")
                (ftp-rename-file conn "test1" "test2")
                (ftp-close-connection conn)
                (delete-file (build-path tmp-dir pth))
                (delete-directory/files tmp-dir)
                (thread-wait pasv1-thd)
                (thread-wait pasv2-thd)
                (thread-wait pasv3-thd)
                (thread-wait main-thd)
                (get-output-string cop) => EXPECTED-USER-OUTPUT<commit_msg>Avoid output in ftp tests.<commit_after>#lang at-exp racket/base

(require net/ftp tests/eli-tester
         racket/tcp racket/port racket/file racket/match)

(define (tcp-serve dest text)
  (define listener (tcp-listen 0))
  (define the-port (let-values ([(_1 p _2 _3) (tcp-addresses listener #t)]) p))
  (define (feed in out)
    (if (input-port? in) (copy-port in out) (display in out))
    (flush-output out))
  (define (feeder)
    (define-values [ip op] (tcp-accept listener))
    (for-each thread-wait
              (list (thread (λ () (feed text op) (close-output-port op)))
                    (thread (λ () (feed ip dest) (close-input-port ip))))))
  (values (thread feeder) the-port))

(define (port->splitstr n)
  (let-values ([(q r) (quotient/remainder n 256)]) (format "~a,~a" q r)))
(define (tcp-serve* dest text)
  (define-values [thd port] (tcp-serve dest text))
  (values thd (port->splitstr port)))

(define ((progress-proc output dir) get-count)
  (thread
   (lambda ()
     (let loop ()
       (define-values [count changed-evt] (get-count))
       (fprintf output "~a bytes ~aloaded\n" count dir)
       (sync changed-evt)
       (loop)))))

(provide tests)
(module+ main (tests))
(define (tests)
  (define cop (open-output-string))
  (define-values [pasv1-thd pasv1-port] (tcp-serve* (current-output-port) DIRLIST))
  (define-values [pasv2-thd pasv2-port] (tcp-serve* (current-output-port) TEXT-FILE))
  (define-values [pasv3-thd pasv3-port] (tcp-serve* (open-output-nowhere) TEXT-FILE))
  (define-values [main-thd main-port] (tcp-serve cop (SERVER-OUTPUT pasv1-port pasv2-port pasv3-port)))
  (define server "127.0.0.1")
  (define port main-port)
  (define user "anonymous")
  (define passwd "<PASSWORD>")
  (define conn #f)
  (define pth "=README-about-.diff-files")
  (define tmp-dir (make-temporary-file "racket-ftp-test-~a" 'directory))
  (test (port->splitstr 18291) => "71,115"
        (ftp-connection? 1) => #f
        (set! conn (ftp-establish-connection server port user passwd))
        (ftp-connection? conn)
        (when (ftp-connection? conn)
          (define output (open-output-bytes))
          (test (ftp-cd conn "gnu")
                (for ([f (in-list (ftp-directory-list conn))])
                  (match-define (list* type ftp-date name ?size) f)
                  (test (ftp-make-file-seconds ftp-date)))
                (ftp-download-file conn tmp-dir pth
                                   #:progress (progress-proc output "down"))
                ;; Note: It would be nice to test the output but there is no
                ;; easy way that I see to wait for the progress thread to
                ;; finish (it stays alive after the transfer), and it's
                ;; probably a bad idea to make a test that expects a specific
                ;; output
                ;; (get-output-bytes output #t) => #"0 bytes downloaded\n"
                ;; (get-output-bytes output #t) => #"744 bytes uploaded\n"
                (ftp-upload-file conn (path->string (build-path tmp-dir pth))
                                 #:progress (progress-proc output "up"))
                ;; (get-output-bytes output #t) => #"744 bytes uploaded\n"
                (ftp-delete-file conn "3dldf/test.file")
                (ftp-make-directory conn "test")
                (ftp-delete-directory conn "test")
                (ftp-rename-file conn "test1" "test2")
                (ftp-close-connection conn)
                (delete-file (build-path tmp-dir pth))
                (delete-directory/files tmp-dir)
                (thread-wait pasv1-thd)
                (thread-wait pasv2-thd)
                (thread-wait pasv3-thd)
                (thread-wait main-thd)
                (get-output-string cop) => EXPECTED-USER-OUTPUT
{'fraction_non_alphanumeric': 0.15016114854966306, 'fraction_numerical': 0.012452387928508644, 'mean_word_length': 2.3237585199610518, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 22, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 5, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1329638', 'n_tokens_mistral': 2346, 'n_tokens_neox': 2204, 'n_words': 607}