summary refs log tree commit diff stats
path: root/tests/dll/nimhcr_integration.nim
blob: 64f6bb7086cd058e05f3471c181a9d7e41e35550 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
discard """
  disabled: "macosx"
  output: '''
main: HELLO!
main: hasAnyModuleChanged? true
main: before
   0: after
main: after
              The answer is: 1000
main: hasAnyModuleChanged? false
              The answer is: 1000
main: hasAnyModuleChanged? true
   0: before
main: before
   1: print me once!
   1: 1
   1: 2
   1: 3
   1: 4
   1: 5
   1: 5
   1: 5
   1: Type1.a:42
1
bar
   0: after - improved!
main: after
              The answer is: 110
main: hasAnyModuleChanged? true
   0: before - improved!
main: before
   2: random string
max mutual recursion reached!
1
bar
   0: after - closure iterator: 0
   0: after - closure iterator: 1
main: after
              The answer is: 9
main: hasAnyModuleChanged? true
   2: before!
main: before
   2: after!
   0: after - closure iterator! after reload! does it remember? :2
   0: after - closure iterator! after reload! does it remember? :3
main: after
              The answer is: 1000
main: hasAnyModuleChanged? true
main: before
main: after
              The answer is: 42
done
'''
"""

## This is perhaps the most complex test in the nim test suite - calling the
## compiler on the file itself with the same set or arguments and reloading
## parts of the program at runtime! In the same folder there are a few modules
## with names such as `nimhcr_<number>.nim`. Each of them has a few versions which
## are in the format of `nimhcr_<number>_<version>.nim`. The below code uses the
## `update` proc to say which of the modules should bump its version (and that
## is done by copying `nimhcr_<number>_<version>.nim` onto `nimhcr_<number>.nim`).
## The files should refer to each other (when importing) without the versions.
## A few files can be updated by calling `update` for each of their indexes
## and after that with a single call to `compileReloadExecute` the new version
## of the program will be compiled, reloaded, and the only thing the main module
## calls from `nimhcr_0.nim` (the procedure `getInt` proc) is called for a result.
##
## This test is expected to be executed with arguments - the full nim compiler
## command used for building it - so it can rebuild iself the same way - example:
##
## compiling:
##                   nim c --hotCodeReloading:on --nimCache:<folder> <this_file>.nim
## executing:
##   <this_file>.exe nim c --hotCodeReloading:on --nimCache:<folder> <this_file>.nim

import os, osproc, strutils, hotcodereloading

import nimhcr_0 # getInt() - the only thing we continually call from the main module

proc compileReloadExecute() =
  # Remove the `--forceBuild` option - is there in the first place because:
  # - when `koch test` is ran for the first time the nimcache is empty
  # - when each of the variants are built (debug, release after that, different GCs)
  #   the main executable that gets built into the appropriate nimcache folder
  #   gets copied to the originally intended destination and is executed
  #   (this behaviour is only when the --hotCodeReloading option is used).
  # - when `koch test` is ran again and the nimcache is full the executable files
  #   in the nimcache folder aren't relinked and therefore aren't copied to the
  #   originally intended destination - so when the binary at the intended
  #   destination is executed - it is actually a remnant from a previous execution.
  #   That is a problem because it points to shared objects to load from its own
  #   nimcache folder - the one used for building it - a previous run! And when
  #   this test changes other modules it references but the main module (this file)
  #   remains intact - the binary isn't replaced. `--forceBuild` fixes this but has
  #   to be applied only for the main build - the one done from koch, but when this
  #   binary triggers rebuilding itself here it shouldn't rebuild the main module -
  #   that would lead to replacing the main binary executable which is running!
  let cmd = commandLineParams()[0..^1].join(" ").replace(" --forceBuild")
  let (stdout, exitcode) = execCmdEx(cmd)
  if exitcode != 0:
    echo "COMPILATION ERROR!"
    echo "COMMAND: ", cmd
    echo "STDOUT: ", stdout
    quit 1
  echo "main: hasAnyModuleChanged? ", hasAnyModuleChanged()
  performCodeReload()
  echo "              The answer is: ", getInt()

# there are 3 files and all of them start from their 1st version
var vers = [1, 1, 1]
proc update(file: int) =
  proc getfile(mid: string): string =
    let (path, _, _) = splitFile(currentSourcePath())
    return path & "/nimhcr_" & mid & ".nim"
  copyFile(getfile($file & "_" & $vers[file]), getfile($file))
  inc vers[file]

beforeCodeReload:
  echo "main: before"

afterCodeReload:
  echo "main: after"

echo "main: HELLO!"

update 0
compileReloadExecute() # versions are: 1 - -

compileReloadExecute() # no change

update 0
update 1
compileReloadExecute() # versions are: 2 1 -

update 0
update 2
compileReloadExecute() # versions are: 3 1 1

update 0
update 1
update 2
compileReloadExecute() # versions are: 4 2 2

update 0
compileReloadExecute() # versions are: 5 2 2

# final update so there are no git modifications left after everything
# (the last versions are like the first files without a version suffix)
update 0
update 1
update 2

echo "done"