diff options
18 files changed, 2093 insertions, 23 deletions
diff --git a/indra/viewer_components/manager/SL_Launcher b/indra/viewer_components/manager/SL_Launcher index ecf88a1105..1d4c19fa86 100755 --- a/indra/viewer_components/manager/SL_Launcher +++ b/indra/viewer_components/manager/SL_Launcher @@ -18,8 +18,11 @@  # Copyright (c) 2013, Linden Research, Inc.  import argparse +import collections  import InstallerUserMessage +import llsd  import os +import platform  import sys  import subprocess  import update_manager @@ -31,7 +34,88 @@ def after_frame(my_message, timeout = 10000):     #this is done before basic_message so that we aren't blocked by mainloop()     frame.after(timout, lambda: frame._delete_window)     frame.basic_message(message = my_message) +    +def get_cmd_line(): +   platform_name = platform.system() +   #find the parent of the logs and user_settings directories +   if (platform_name == 'mac'): +      settings_file = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'Resources/app_settings/cmd_line.xml') +   elif (platform_name == 'lnx'):  +      settings_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'app_settings/cmd_line.xml') +   #using list format of join is important here because the Windows pathsep in a string escapes the next char +   elif (platform_name == 'win'): +      settings_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'app_settings/cmd_line.xml') +   else: +      settings_dir = None +       +   try: +      cmd_line = llsd.parse((open(settings_file)).read()) +   except: +      cmd_line = None +    +   return cmd_line + +def get_settings(): +   #return the settings file parsed into a dict +   try: +      settings_file = os.path.abspath(os.path.join(parent_dir,'user_settings','settings.xml')) +      settings = llsd.parse((open(settings_file)).read()) +   except llsd.LLSDParseError as lpe: +      silent_write(log_file_handle, "Could not parse settings file %s" % lpe) +      return None +   return settings +    +def capture_vmp_args(arg_list = None, cmd_line = None): +   #expected input format: arg_list = ['--set', 'foo', 'bar', '-X', '-Y', 'qux'] +   #take a copy of the viewer parameters that are of interest to VMP. +   #the regex for a parameter is --<param> {opt1} {opt2} +   cli_overrides = {}    +   cmd_line = get_cmd_line() +    +   vmp_params = {'--channel':'channel', '--settings':'settings', '--update-service':'update-service', '--set':'set'} +   #the settings set with --set.  All such settings have only one argument. +   vmp_setters = ('UpdaterMaximumBandwidth', 'UpdaterServiceCheckPeriod', 'UpdaterServicePath', 'UpdaterServiceSetting', 'UpdaterServiceURL', 'UpdaterWillingToTest')    +    +   #Here turn the list into a queue, popping off the left as we go. Note that deque() makes a copy by value, not by reference +   #Because of the complexity introduced by the uncertainty of how many options a parameter can take, this is far less complicated code than the more +   #pythonic (x,y) = <some generator> since we will sometimes have (x), sometimes (x,y) and sometimes (x,y,z) +   #also, because the pop is destructive, we prevent ourselves from iterating back over list elements that iterator methods would peek ahead at +   vmp_queue = collections.deque(arg_list) +   while (len(vmp_queue)): +      param = vmp_queue.popleft() +      #if it is not one of ours, pop through args until we get to the next parameter +      if param in vmp_params.keys(): +         if param == '--set': +            setting_name = vmp_queue.popleft() +            setting_value = vmp_queue.popleft() +            if setting_name in vmp_setters: +               cli_overrides[vmp_params[param]] = (setting_name, setting_value) +         else: +            #find out how many args this parameter has +            count = cmd_line[param]['count'] +            param_args = [] +            if count: +               for argh in range(1,count): +                  param_args.append(vmp_queue.popleft()) +            #the parameter name is the key, the (possibly empty) list of args is the value +            cli_overrides[vmp_params[param]] = param_args +             +   #to prevent KeyErrors on missing keys, set the remainder to None +   for key in vmp_params: +      if key != '--set': +         try: +            cli_overrides[key] +         except KeyError: +            cli_overrides[key] = None +      else: +         for arg in vmp_setters: +            try: +               cli_overrides[key][arg] +            except KeyError: +               cli_overrides[key][arg] = None +   return cli_overrides +     cwd = os.path.dirname(os.path.realpath(__file__))  executable_name = "" @@ -58,11 +142,15 @@ viewer_binary = os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])),execu  parser = argparse.ArgumentParser()  args = parser.parse_known_args(sys.argv) +print args[1] +sys.exit() +#args[1] looks like ['./SL_Launcher', '--set', 'foo', 'bar', '-X', '-Y', 'qux'], dump the progname  args_list_to_pass = args[1][1:] +vmp_args = capture_vmp_args(args_list_to_pass)  #make a copy by value, not by reference  command = list(args_list_to_pass) -(success, state, condition) = update_manager.update_manager() +(success, state, condition) = update_manager.update_manager(cli_overrides)  # From update_manager:  #  (False, 'setup', None): error occurred before we knew what the update was (e.g., in setup or parsing)  #  (False, 'download', version): we failed to download the new version diff --git a/indra/viewer_components/manager/tests/data/settings.xml b/indra/viewer_components/manager/tests/data/settings.xml new file mode 100644 index 0000000000..07e420dcb3 --- /dev/null +++ b/indra/viewer_components/manager/tests/data/settings.xml @@ -0,0 +1,1184 @@ +<llsd> +    <map> +    <key>AllowMultipleViewers</key> +        <map> +        <key>Comment</key> +            <string>Allow multiple viewers.</string> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <integer>1</integer> +        </map> +    <key>AllowTapTapHoldRun</key> +        <map> +        <key>Comment</key> +            <string>Tapping a direction key twice and holding it down makes avatar run</string> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <integer>0</integer> +        </map> +    <key>AppearanceCameraMovement</key> +        <map> +        <key>Comment</key> +            <string>When entering appearance editing mode, camera zooms in on currently selected portion of avatar</string> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <integer>0</integer> +        </map> +    <key>AudioLevelMedia</key> +        <map> +        <key>Comment</key> +            <string>Audio level of Quicktime movies</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0.699999988079071044921875</real> +        </map> +    <key>AudioLevelMic</key> +        <map> +        <key>Comment</key> +            <string>Audio level of microphone input</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0.1749999970197677612304688</real> +        </map> +    <key>AudioLevelMusic</key> +        <map> +        <key>Comment</key> +            <string>Audio level of streaming music</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0</real> +        </map> +    <key>AudioLevelSFX</key> +        <map> +        <key>Comment</key> +            <string>Audio level of in-world sound effects</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0.699999988079071044921875</real> +        </map> +    <key>AudioLevelVoice</key> +        <map> +        <key>Comment</key> +            <string>Audio level of voice chat</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>1</real> +        </map> +    <key>AudioStreamingMedia</key> +        <map> +        <key>Comment</key> +            <string>Enable streaming</string> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <integer>0</integer> +        </map> +    <key>AvatarAxisDeadZone0</key> +        <map> +        <key>Comment</key> +            <string>Avatar axis 0 dead zone.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0.1000000014901161193847656</real> +        </map> +    <key>AvatarAxisDeadZone1</key> +        <map> +        <key>Comment</key> +            <string>Avatar axis 1 dead zone.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0.1000000014901161193847656</real> +        </map> +    <key>AvatarAxisDeadZone2</key> +        <map> +        <key>Comment</key> +            <string>Avatar axis 2 dead zone.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0.1000000014901161193847656</real> +        </map> +    <key>AvatarAxisDeadZone3</key> +        <map> +        <key>Comment</key> +            <string>Avatar axis 3 dead zone.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>1</real> +        </map> +    <key>AvatarAxisDeadZone4</key> +        <map> +        <key>Comment</key> +            <string>Avatar axis 4 dead zone.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0.01999999955296516418457031</real> +        </map> +    <key>AvatarAxisDeadZone5</key> +        <map> +        <key>Comment</key> +            <string>Avatar axis 5 dead zone.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0.009999999776482582092285156</real> +        </map> +    <key>AvatarAxisScale3</key> +        <map> +        <key>Comment</key> +            <string>Avatar axis 3 scaler.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0</real> +        </map> +    <key>AvatarAxisScale4</key> +        <map> +        <key>Comment</key> +            <string>Avatar axis 4 scaler.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>2</real> +        </map> +    <key>AvatarAxisScale5</key> +        <map> +        <key>Comment</key> +            <string>Avatar axis 5 scaler.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>2</real> +        </map> +    <key>AvatarFeathering</key> +        <map> +        <key>Comment</key> +            <string>Avatar feathering (less is softer)</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>6</real> +        </map> +    <key>AvatarFileName</key> +        <map> +        <key>Comment</key> +            <string>Alternative avatar file name</string> +        <key>Type</key> +            <string>String</string> +        <key>Value</key> +            <string>avatar_lad_tentacles.xml</string> +        </map> +    <key>BuildAxisDeadZone0</key> +        <map> +        <key>Comment</key> +            <string>Build axis 0 dead zone.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0.009999999776482582092285156</real> +        </map> +    <key>BuildAxisDeadZone1</key> +        <map> +        <key>Comment</key> +            <string>Build axis 1 dead zone.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0.009999999776482582092285156</real> +        </map> +    <key>BuildAxisDeadZone2</key> +        <map> +        <key>Comment</key> +            <string>Build axis 2 dead zone.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0.009999999776482582092285156</real> +        </map> +    <key>BuildAxisDeadZone3</key> +        <map> +        <key>Comment</key> +            <string>Build axis 3 dead zone.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0.009999999776482582092285156</real> +        </map> +    <key>BuildAxisDeadZone4</key> +        <map> +        <key>Comment</key> +            <string>Build axis 4 dead zone.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0.009999999776482582092285156</real> +        </map> +    <key>BuildAxisDeadZone5</key> +        <map> +        <key>Comment</key> +            <string>Build axis 5 dead zone.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0.009999999776482582092285156</real> +        </map> +    <key>BuildAxisScale0</key> +        <map> +        <key>Comment</key> +            <string>Build axis 0 scaler.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>6</real> +        </map> +    <key>BuildAxisScale1</key> +        <map> +        <key>Comment</key> +            <string>Build axis 1 scaler.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>6</real> +        </map> +    <key>BuildAxisScale2</key> +        <map> +        <key>Comment</key> +            <string>Build axis 2 scaler.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>6</real> +        </map> +    <key>BuildAxisScale3</key> +        <map> +        <key>Comment</key> +            <string>Build axis 3 scaler.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>6</real> +        </map> +    <key>BuildAxisScale4</key> +        <map> +        <key>Comment</key> +            <string>Build axis 4 scaler.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>6</real> +        </map> +    <key>BuildAxisScale5</key> +        <map> +        <key>Comment</key> +            <string>Build axis 5 scaler.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>6</real> +        </map> +    <key>BuildFeathering</key> +        <map> +        <key>Comment</key> +            <string>Build feathering (less is softer)</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>12</real> +        </map> +    <key>BulkChangeEveryoneCopy</key> +        <map> +        <key>Comment</key> +            <string>Bulk changed objects can be copied by everyone</string> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <boolean>1</boolean> +        </map> +    <key>BulkChangeNextOwnerCopy</key> +        <map> +        <key>Comment</key> +            <string>Bulk changed objects can be copied by next owner</string> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <boolean>1</boolean> +        </map> +    <key>BulkChangeNextOwnerModify</key> +        <map> +        <key>Comment</key> +            <string>Bulk changed objects can be modified by next owner</string> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <boolean>1</boolean> +        </map> +    <key>BulkChangeShareWithGroup</key> +        <map> +        <key>Comment</key> +            <string>Bulk changed objects are shared with the currently active group</string> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <boolean>1</boolean> +        </map> +    <key>CacheValidateCounter</key> +        <map> +        <key>Comment</key> +            <string>Used to distribute cache validation</string> +        <key>Type</key> +            <string>U32</string> +        <key>Value</key> +            <integer>122</integer> +        </map> +    <key>CameraPosOnLogout</key> +        <map> +        <key>Comment</key> +            <string>Camera position when last logged out (global coordinates)</string> +        <key>Type</key> +            <string>Vector3D</string> +        <key>Value</key> +            <array> +                <real>288290.4477181434631347656</real> +                <real>275988.5277819633483886719</real> +                <real>49.10921102762222290039062</real> +            </array> +        </map> +    <key>ClickToWalk</key> +        <map> +        <key>Comment</key> +            <string>Click in world to walk to location</string> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <boolean>0</boolean> +        </map> +    <key>ConversationSortOrder</key> +        <map> +        <key>Comment</key> +            <string>Specifies sort key for conversations</string> +        <key>Type</key> +            <string>U32</string> +        <key>Value</key> +            <integer>0</integer> +        </map> +    <key>CurrentGrid</key> +        <map> +        <key>Comment</key> +            <string>Currently Selected Grid</string> +        <key>Type</key> +            <string>String</string> +        <key>Value</key> +            <string>util.agni.lindenlab.com</string> +        </map> +    <key>Cursor3D</key> +        <map> +        <key>Comment</key> +            <string>Treat Joystick values as absolute positions (not deltas).</string> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <boolean>0</boolean> +        </map> +    <key>FirstLoginThisInstall</key> +        <map> +        <key>Comment</key> +            <string>Specifies that you have not logged in with the viewer since you performed a clean install</string> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <boolean>0</boolean> +        </map> +    <key>FirstRunThisInstall</key> +        <map> +        <key>Comment</key> +            <string>Specifies that you have not run the viewer since you performed a clean install</string> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <boolean>0</boolean> +        </map> +    <key>FlycamAxisDeadZone0</key> +        <map> +        <key>Comment</key> +            <string>Flycam axis 0 dead zone.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0.009999999776482582092285156</real> +        </map> +    <key>FlycamAxisDeadZone1</key> +        <map> +        <key>Comment</key> +            <string>Flycam axis 1 dead zone.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0.009999999776482582092285156</real> +        </map> +    <key>FlycamAxisDeadZone2</key> +        <map> +        <key>Comment</key> +            <string>Flycam axis 2 dead zone.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0.009999999776482582092285156</real> +        </map> +    <key>FlycamAxisDeadZone3</key> +        <map> +        <key>Comment</key> +            <string>Flycam axis 3 dead zone.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0.009999999776482582092285156</real> +        </map> +    <key>FlycamAxisDeadZone4</key> +        <map> +        <key>Comment</key> +            <string>Flycam axis 4 dead zone.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0.009999999776482582092285156</real> +        </map> +    <key>FlycamAxisDeadZone5</key> +        <map> +        <key>Comment</key> +            <string>Flycam axis 5 dead zone.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0.009999999776482582092285156</real> +        </map> +    <key>FlycamAxisDeadZone6</key> +        <map> +        <key>Comment</key> +            <string>Flycam axis 6 dead zone.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>1</real> +        </map> +    <key>FlycamAxisScale0</key> +        <map> +        <key>Comment</key> +            <string>Flycam axis 0 scaler.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>42</real> +        </map> +    <key>FlycamAxisScale1</key> +        <map> +        <key>Comment</key> +            <string>Flycam axis 1 scaler.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>40</real> +        </map> +    <key>FlycamAxisScale2</key> +        <map> +        <key>Comment</key> +            <string>Flycam axis 2 scaler.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>40</real> +        </map> +    <key>FlycamAxisScale3</key> +        <map> +        <key>Comment</key> +            <string>Flycam axis 3 scaler.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0</real> +        </map> +    <key>FlycamAxisScale4</key> +        <map> +        <key>Comment</key> +            <string>Flycam axis 4 scaler.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>2</real> +        </map> +    <key>FlycamAxisScale5</key> +        <map> +        <key>Comment</key> +            <string>Flycam axis 5 scaler.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>3</real> +        </map> +    <key>FlycamAxisScale6</key> +        <map> +        <key>Comment</key> +            <string>Flycam axis 6 scaler.</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0</real> +        </map> +    <key>FlycamFeathering</key> +        <map> +        <key>Comment</key> +            <string>Flycam feathering (less is softer)</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>5</real> +        </map> +    <key>FocusPosOnLogout</key> +        <map> +        <key>Comment</key> +            <string>Camera focus point when last logged out (global coordinates)</string> +        <key>Type</key> +            <string>Vector3D</string> +        <key>Value</key> +            <array> +                <real>288287.8830481640761718154</real> +                <real>275991.5973855691263452172</real> +                <real>47.96361158013021963597566</real> +            </array> +        </map> +    <key>ForceShowGrid</key> +        <map> +        <key>Comment</key> +            <string>Always show grid dropdown on login screen</string> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <integer>1</integer> +        </map> +    <key>HttpProxyType</key> +        <map> +        <key>Comment</key> +            <string>Proxy type to use for HTTP operations</string> +        <key>Type</key> +            <string>String</string> +        <key>Value</key> +            <string>None</string> +        </map> +    <key>JoystickInitialized</key> +        <map> +        <key>Comment</key> +            <string>Whether or not a joystick has been detected and initiailized.</string> +        <key>Type</key> +            <string>String</string> +        <key>Value</key> +            <string>UnknownDevice</string> +        </map> +    <key>LSLFindCaseInsensitivity</key> +        <map> +        <key>Comment</key> +            <string>Use case insensitivity when searching in LSL editor</string> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <integer>1</integer> +        </map> +    <key>LastFeatureVersion</key> +        <map> +        <key>Comment</key> +            <string>[DO NOT MODIFY] Feature Table Version number for tracking rendering system changes</string> +        <key>Type</key> +            <string>S32</string> +        <key>Value</key> +            <integer>37</integer> +        </map> +    <key>LastGPUString</key> +        <map> +        <key>Comment</key> +            <string>[DO NOT MODIFY] previous GPU id string for tracking hardware changes</string> +        <key>Type</key> +            <string>String</string> +        <key>Value</key> +            <string>NVIDIA Corporation NVIDIA GeForce GT 750M OpenGL Engine</string> +        </map> +    <key>LastPrefTab</key> +        <map> +        <key>Comment</key> +            <string>Last selected tab in preferences window</string> +        <key>Type</key> +            <string>S32</string> +        <key>Value</key> +            <integer>1</integer> +        </map> +    <key>LastRunVersion</key> +        <map> +        <key>Comment</key> +            <string>Version number of last instance of the viewer that you ran</string> +        <key>Type</key> +            <string>String</string> +        <key>Value</key> +            <string>Second Life Project Bento 5.0.0.315657</string> +        </map> +    <key>LocalCacheVersion</key> +        <map> +        <key>Comment</key> +            <string>Version number of cache</string> +        <key>Type</key> +            <string>S32</string> +        <key>Value</key> +            <integer>7</integer> +        </map> +    <key>LoginLocation</key> +        <map> +        <key>Comment</key> +            <string>Default Login location ('last', 'home') preference</string> +        <key>Type</key> +            <string>String</string> +        <key>Value</key> +            <string>home</string> +        </map> +    <key>MapScale</key> +        <map> +        <key>Comment</key> +            <string>World map zoom level (pixels per region)</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>256</real> +        </map> +    <key>MaxJointsPerMeshObject</key> +        <map> +        <key>Comment</key> +            <string>Maximum joints per rigged mesh object</string> +        <key>Type</key> +            <string>U32</string> +        <key>Value</key> +            <real>51</real> +        </map> +    <key>MediaEnablePopups</key> +        <map> +        <key>Comment</key> +            <string>If true, enable targeted links and javascript in media to open new media browser windows without a prompt.</string> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <boolean>1</boolean> +        </map> +    <key>MediaShowOnOthers</key> +        <map> +        <key>Comment</key> +            <string>Whether or not to show media on other avatars</string> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <integer>1</integer> +        </map> +    <key>MigrateCacheDirectory</key> +        <map> +        <key>Comment</key> +            <string>Check for old version of disk cache to migrate to current location</string> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <boolean>0</boolean> +        </map> +    <key>NavBarShowParcelProperties</key> +        <map> +        <key>Comment</key> +            <string>Show parcel property icons in navigation bar</string> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <boolean>0</boolean> +        </map> +    <key>NextLoginLocation</key> +        <map> +        <key>Comment</key> +            <string>Location to log into for this session - set from command line or the login panel, cleared following a successfull login.</string> +        <key>Type</key> +            <string>String</string> +        <key>Value</key> +            <string>home</string> +        </map> +    <key>NotificationConferenceIMOptions</key> +        <map> +        <key>Comment</key> +            <string> +        Specifies how the UI responds to Conference IM Notifications. +        Allowed values: [openconversations,toast,flash,noaction] +      </string> +        <key>Type</key> +            <string>String</string> +        <key>Value</key> +            <string>none</string> +        </map> +    <key>NotificationFriendIMOptions</key> +        <map> +        <key>Comment</key> +            <string> +        Specifies how the UI responds to Friend IM Notifications. +        Allowed values: [openconversations,toast,flash,noaction] +      </string> +        <key>Type</key> +            <string>String</string> +        <key>Value</key> +            <string>openconversations</string> +        </map> +    <key>NotificationGroupChatOptions</key> +        <map> +        <key>Comment</key> +            <string> +        Specifies how the UI responds to Group Chat Notifications. +        Allowed values: [openconversations,toast,flash,noaction] +      </string> +        <key>Type</key> +            <string>String</string> +        <key>Value</key> +            <string>none</string> +        </map> +    <key>NotificationNearbyChatOptions</key> +        <map> +        <key>Comment</key> +            <string> +        Specifies how the UI responds to Nearby Chat Notifications. +        Allowed values: [openconversations,toast,flash,noaction] +      </string> +        <key>Type</key> +            <string>String</string> +        <key>Value</key> +            <string>none</string> +        </map> +    <key>NotificationNonFriendIMOptions</key> +        <map> +        <key>Comment</key> +            <string> +        Specifies how the UI responds to Non Friend IM Notifications. +        Allowed values: [openconversations,toast,flash,noaction] +      </string> +        <key>Type</key> +            <string>String</string> +        <key>Value</key> +            <string>openconversations</string> +        </map> +    <key>NumSessions</key> +        <map> +        <key>Comment</key> +            <string>Number of successful logins to Second Life</string> +        <key>Type</key> +            <string>S32</string> +        <key>Value</key> +            <integer>1674</integer> +        </map> +    <key>PlayTypingAnim</key> +        <map> +        <key>Comment</key> +            <string>Your avatar plays the typing animation whenever you type in the chat bar</string> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <integer>0</integer> +        </map> +    <key>PoolSizeExpCache</key> +        <map> +        <key>Comment</key> +            <string>Coroutine Pool size for ExpCache</string> +        <key>Type</key> +            <string>U32</string> +        <key>Value</key> +            <integer>5</integer> +        </map> +    <key>PreferredBrowserBehavior</key> +        <map> +        <key>Comment</key> +            <string>Use system browser for any links (0), use builtin browser for SL links and system one for others (1) or use builtin browser only (2).</string> +        <key>Type</key> +            <string>U32</string> +        <key>Value</key> +            <string>0</string> +        </map> +    <key>PreferredMaturity</key> +        <map> +        <key>Comment</key> +            <string>Setting for the user's preferred maturity level (consts in indra_constants.h)</string> +        <key>Type</key> +            <string>U32</string> +        <key>Value</key> +            <integer>42</integer> +        </map> +    <key>PresetGraphicActive</key> +        <map> +        <key>Comment</key> +            <string>Name of currently selected preference</string> +        <key>Type</key> +            <string>String</string> +        <key>Value</key> +            <string>Default</string> +        </map> +    <key>ProbeHardwareOnStartup</key> +        <map> +        <key>Comment</key> +            <string>Query current hardware configuration on application startup</string> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <boolean>0</boolean> +        </map> +    <key>QAMode</key> +        <map> +        <key>Comment</key> +            <string>Enable Testing Features.</string> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <boolean>1</boolean> +        </map> +    <key>RenderAnisotropic</key> +        <map> +        <key>Comment</key> +            <string>Render textures using anisotropic filtering</string> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <boolean>1</boolean> +        </map> +    <key>RenderAvatarCloth</key> +        <map> +        <key>Comment</key> +            <string>Controls if avatars use wavy cloth</string> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <boolean>0</boolean> +        </map> +    <key>RenderAvatarLODFactor</key> +        <map> +        <key>Comment</key> +            <string>Controls level of detail of avatars (multiplier for current screen area when calculated level of detail)</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>1</real> +        </map> +    <key>RenderFSAASamples</key> +        <map> +        <key>Comment</key> +            <string>Number of samples to use for FSAA (0 = no AA).</string> +        <key>Type</key> +            <string>U32</string> +        <key>Value</key> +            <integer>2</integer> +        </map> +    <key>RenderFarClip</key> +        <map> +        <key>Comment</key> +            <string>Distance of far clip plane from camera (meters)</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>128</real> +        </map> +    <key>RenderMaxPartCount</key> +        <map> +        <key>Comment</key> +            <string>Maximum number of particles to display on screen</string> +        <key>Type</key> +            <string>S32</string> +        <key>Value</key> +            <real>2048</real> +        </map> +    <key>RenderQualityPerformance</key> +        <map> +        <key>Comment</key> +            <string>Which graphics settings you've chosen</string> +        <key>Type</key> +            <string>U32</string> +        <key>Value</key> +            <real>4</real> +        </map> +    <key>RenderReflectionDetail</key> +        <map> +        <key>Comment</key> +            <string>Detail of reflection render pass.</string> +        <key>Type</key> +            <string>S32</string> +        <key>Value</key> +            <integer>0</integer> +        </map> +    <key>RenderTerrainLODFactor</key> +        <map> +        <key>Comment</key> +            <string>Controls level of detail of terrain (multiplier for current screen area when calculated level of detail)</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>2</real> +        </map> +    <key>RenderVBOEnable</key> +        <map> +        <key>Comment</key> +            <string>Use GL Vertex Buffer Objects</string> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <boolean>0</boolean> +        </map> +    <key>RenderVolumeLODFactor</key> +        <map> +        <key>Comment</key> +            <string>Controls level of detail of primitives (multiplier for current screen area when calculated level of detail)</string> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>1.125</real> +        </map> +    <key>ShowAdvancedGraphicsSettings</key> +        <map> +        <key>Comment</key> +            <string>Show advanced graphics settings</string> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <integer>1</integer> +        </map> +    <key>ShowBanLines</key> +        <map> +        <key>Comment</key> +            <string>Show in-world ban/access borders</string> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <boolean>0</boolean> +        </map> +    <key>ShowStartLocation</key> +        <map> +        <key>Comment</key> +            <string>Display starting location menu on login screen</string> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <boolean>1</boolean> +        </map> +    <key>SkeletonFileName</key> +        <map> +        <key>Comment</key> +            <string>Alternative skeleton file name</string> +        <key>Type</key> +            <string>String</string> +        <key>Value</key> +            <string>avatar_skeleton_tentacles.xml</string> +        </map> +    <key>SkyPresetName</key> +        <map> +        <key>Comment</key> +            <string>Sky preset to use. May be superseded by region settings or by a day cycle (see DayCycleName).</string> +        <key>Type</key> +            <string>String</string> +        <key>Value</key> +            <string>Sunset</string> +        </map> +    <key>SnapshotConfigURL</key> +        <map> +        <key>Comment</key> +            <string>URL to fetch Snapshot Sharing configuration data from.</string> +        <key>Type</key> +            <string>String</string> +        <key>Value</key> +            <string>http://photos.apps.avatarsunited.com/viewer_config</string> +        </map> +    <key>SnapshotFormat</key> +        <map> +        <key>Comment</key> +            <string>Save snapshots in this format (0 = PNG, 1 = JPEG, 2 = BMP)</string> +        <key>Type</key> +            <string>S32</string> +        <key>Value</key> +            <integer>1</integer> +        </map> +    <key>SnapshotQuality</key> +        <map> +        <key>Comment</key> +            <string>Quality setting of postcard JPEGs (0 = worst, 100 = best)</string> +        <key>Type</key> +            <string>S32</string> +        <key>Value</key> +            <integer>100</integer> +        </map> +    <key>SpellCheck</key> +        <map> +        <key>Comment</key> +            <string>Enable spellchecking on line and text editors</string> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <integer>0</integer> +        </map> +    <key>SpellCheckDictionary</key> +        <map> +        <key>Comment</key> +            <string>Current primary and secondary dictionaries used for spell checking</string> +        <key>Type</key> +            <string>String</string> +        <key>Value</key> +            <string>English (United States)</string> +        </map> +    <key>TextureMemory</key> +        <map> +        <key>Comment</key> +            <string>Amount of memory to use for textures in MB (0 = autodetect)</string> +        <key>Type</key> +            <string>S32</string> +        <key>Value</key> +            <integer>256</integer> +        </map> +    <key>UseDayCycle</key> +        <map> +        <key>Comment</key> +            <string>Whether to use use a day cycle or a fixed sky.</string> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <boolean>0</boolean> +        </map> +    <key>UseDebugMenus</key> +        <map> +        <key>Comment</key> +            <string>Turns on "Debug" menu</string> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <boolean>1</boolean> +        </map> +    <key>UseEnvironmentFromRegion</key> +        <map> +        <key>Comment</key> +            <string>Choose whether to use the region's environment settings, or override them with the local settings.</string> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <boolean>0</boolean> +        </map> +    <key>VFSOldSize</key> +        <map> +        <key>Comment</key> +            <string>[DO NOT MODIFY] Controls resizing of local file cache</string> +        <key>Type</key> +            <string>U32</string> +        <key>Value</key> +            <integer>102</integer> +        </map> +    <key>VFSSalt</key> +        <map> +        <key>Comment</key> +            <string>[DO NOT MODIFY] Controls local file caching behavior</string> +        <key>Type</key> +            <string>U32</string> +        <key>Value</key> +            <integer>260093998</integer> +        </map> +    <key>VersionChannelName</key> +        <map> +        <key>Comment</key> +            <string>Version information generated by running the viewer</string> +        <key>Type</key> +            <string>String</string> +        <key>Value</key> +            <string>Second Life Release</string> +        </map> +    <key>VertexShaderEnable</key> +        <map> +        <key>Comment</key> +            <string>Enable/disable all GLSL shaders (debug)</string> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <boolean>1</boolean> +        </map> +    <key>VoiceInputAudioDevice</key> +        <map> +        <key>Comment</key> +            <string>Audio input device to use for voice</string> +        <key>Type</key> +            <string>String</string> +        <key>Value</key> +            <string>C-Media USB Audio Device</string> +        </map> +    <key>VoiceOutputAudioDevice</key> +        <map> +        <key>Comment</key> +            <string>Audio output device to use for voice</string> +        <key>Type</key> +            <string>String</string> +        <key>Value</key> +            <string>C-Media USB Audio Device</string> +        </map> +    <key>WLSkyDetail</key> +        <map> +        <key>Comment</key> +            <string>Controls vertex detail on the WindLight sky.  Lower numbers will give better performance and uglier skies.</string> +        <key>Type</key> +            <string>U32</string> +        <key>Value</key> +            <integer>48</integer> +        </map> +    <key>WebProfileFloaterRect</key> +        <map> +        <key>Comment</key> +            <string>Web profile floater dimensions</string> +        <key>Type</key> +            <string>Rect</string> +        <key>Value</key> +            <array> +                <integer>1189</integer> +                <integer>957</integer> +                <integer>1674</integer> +                <integer>277</integer> +            </array> +        </map> +    <key>WindowHeight</key> +        <map> +        <key>Comment</key> +            <string>SL viewer window height</string> +        <key>Type</key> +            <string>U32</string> +        <key>Value</key> +            <integer>1000</integer> +        </map> +    <key>WindowWidth</key> +        <map> +        <key>Comment</key> +            <string>SL viewer window width</string> +        <key>Type</key> +            <string>U32</string> +        <key>Value</key> +            <integer>1626</integer> +        </map> +    <key>WindowX</key> +        <map> +        <key>Comment</key> +            <string>X coordinate of upper left corner of SL viewer window, relative to upper left corner of primary display (pixels)</string> +        <key>Type</key> +            <string>S32</string> +        <key>Value</key> +            <integer>50</integer> +        </map> +    <key>WindowY</key> +        <map> +        <key>Comment</key> +            <string>Y coordinate of upper left corner of SL viewer window, relative to upper left corner of primary display (pixels)</string> +        <key>Type</key> +            <string>S32</string> +        <key>Value</key> +            <integer>50</integer> +        </map> +    </map> +</llsd> diff --git a/indra/viewer_components/manager/tests/summary.json b/indra/viewer_components/manager/tests/summary.json new file mode 100644 index 0000000000..b78859d427 --- /dev/null +++ b/indra/viewer_components/manager/tests/summary.json @@ -0,0 +1 @@ +{"Type":"viewer","Version":"4.0.5.315117","Channel":"Second Life Release"} diff --git a/indra/viewer_components/manager/tests/test_InstallerError.py b/indra/viewer_components/manager/tests/test_InstallerError.py new file mode 100644 index 0000000000..d722208b7f --- /dev/null +++ b/indra/viewer_components/manager/tests/test_InstallerError.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python + +# $LicenseInfo:firstyear=2016&license=internal$ +#  +# Copyright (c) 2016, Linden Research, Inc. +#  +# The following source code is PROPRIETARY AND CONFIDENTIAL. Use of +# this source code is governed by the Linden Lab Source Code Disclosure +# Agreement ("Agreement") previously entered between you and Linden +# Lab. By accessing, using, copying, modifying or distributing this +# software, you acknowledge that you have been informed of your +# obligations under the Agreement and agree to abide by those obligations. +#  +# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +# COMPLETENESS OR PERFORMANCE. +# $/LicenseInfo$ + +""" +@file   test_InstallerError.py +@author coyot +@date   2016-06-01 +""" + +from nose.tools import assert_equal + +import InstallerError +import os + +def test_InstallerError(): +    try: +        #try to make our own homedir, this will fail on all three platforms +        homedir = os.path.abspath(os.path.expanduser('~')) +        os.mkdir(homedir) +    except OSError, oe: +        ie = InstallerError.InstallerError(oe, "Installer failed to create a homedir that already exists.") + +    assert_equal( str(ie),  +        "[Errno [Errno 17] File exists: '%s'] Installer failed to create a homedir that already exists." % homedir) diff --git a/indra/viewer_components/manager/tests/test_check_for_completed_download.py b/indra/viewer_components/manager/tests/test_check_for_completed_download.py new file mode 100644 index 0000000000..388bc900e9 --- /dev/null +++ b/indra/viewer_components/manager/tests/test_check_for_completed_download.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python + +# $LicenseInfo:firstyear=2016&license=internal$ +#  +# Copyright (c) 2016, Linden Research, Inc. +#  +# The following source code is PROPRIETARY AND CONFIDENTIAL. Use of +# this source code is governed by the Linden Lab Source Code Disclosure +# Agreement ("Agreement") previously entered between you and Linden +# Lab. By accessing, using, copying, modifying or distributing this +# software, you acknowledge that you have been informed of your +# obligations under the Agreement and agree to abide by those obligations. +#  +# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +# COMPLETENESS OR PERFORMANCE. +# $/LicenseInfo$ + +""" +@file   test_check_for_completed_download.py +@author coyot +@date   2016-06-03 +""" + +from nose.tools import * +from nose import with_setup + +import os +import shutil +import tempfile +import update_manager +import with_setup_args + +def check_for_completed_download_setup(): +    tmpdir1 = tempfile.mkdtemp(prefix = 'test1') +    tmpdir2 = tempfile.mkdtemp(prefix = 'test2') +    tempfile.mkstemp(suffix = '.done', dir = tmpdir1) + +    return [tmpdir1,tmpdir2], {} + +def check_for_completed_download_teardown(tmpdir1,tmpdir2): +    shutil.rmtree(tmpdir1, ignore_errors = True) +    shutil.rmtree(tmpdir2, ignore_errors = True) + +@with_setup_args.with_setup_args(check_for_completed_download_setup, check_for_completed_download_teardown) +def test_completed_check_for_completed_download(tmpdir1,tmpdir2): +    assert_equal(update_manager.check_for_completed_download(tmpdir1), 'done'), "Failed to find completion marker" + +@with_setup_args.with_setup_args(check_for_completed_download_setup, check_for_completed_download_teardown) +def test_incomplete_check_for_completed_download(tmpdir1,tmpdir2): +    #should return False +    incomplete = not update_manager.check_for_completed_download(tmpdir2) +    assert incomplete, "False positive, should not mark complete without a marker"
\ No newline at end of file diff --git a/indra/viewer_components/manager/tests/test_convert_version_file_style.py b/indra/viewer_components/manager/tests/test_convert_version_file_style.py new file mode 100644 index 0000000000..d700f91b84 --- /dev/null +++ b/indra/viewer_components/manager/tests/test_convert_version_file_style.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python + +# $LicenseInfo:firstyear=2016&license=internal$ +#  +# Copyright (c) 2016, Linden Research, Inc. +#  +# The following source code is PROPRIETARY AND CONFIDENTIAL. Use of +# this source code is governed by the Linden Lab Source Code Disclosure +# Agreement ("Agreement") previously entered between you and Linden +# Lab. By accessing, using, copying, modifying or distributing this +# software, you acknowledge that you have been informed of your +# obligations under the Agreement and agree to abide by those obligations. +#  +# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +# COMPLETENESS OR PERFORMANCE. +# $/LicenseInfo$ + +""" +@file   test_convert_version_file_style.py +@author coyot +@date   2016-06-01 +""" + +from nose.tools import assert_equal + +import update_manager + +def test_normal_form(): +    version = '1.2.3.456789' +    golden = '1_2_3_456789' +    converted = update_manager.convert_version_file_style(version) +     +    assert_equal(golden, converted) + +def test_short_form(): +    version = '1.23' +    golden = '1_23' +    converted = update_manager.convert_version_file_style(version) +     +    assert_equal(golden, converted) + +def test_idempotent(): +    version = '123' +    golden = '123' +    converted = update_manager.convert_version_file_style(version) +     +    assert_equal(golden, converted) + +def test_none(): +    version = None +    golden = None +    converted = update_manager.convert_version_file_style(version) +     +    assert_equal(golden, converted)
\ No newline at end of file diff --git a/indra/viewer_components/manager/tests/test_get_filename.py b/indra/viewer_components/manager/tests/test_get_filename.py new file mode 100644 index 0000000000..95771d75dc --- /dev/null +++ b/indra/viewer_components/manager/tests/test_get_filename.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python + +# $LicenseInfo:firstyear=2016&license=internal$ +#  +# Copyright (c) 2016, Linden Research, Inc. +#  +# The following source code is PROPRIETARY AND CONFIDENTIAL. Use of +# this source code is governed by the Linden Lab Source Code Disclosure +# Agreement ("Agreement") previously entered between you and Linden +# Lab. By accessing, using, copying, modifying or distributing this +# software, you acknowledge that you have been informed of your +# obligations under the Agreement and agree to abide by those obligations. +#  +# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +# COMPLETENESS OR PERFORMANCE. +# $/LicenseInfo$ + +""" +@file   test_get_filename.py +@author coyot +@date   2016-06-30 +""" + +from nose.tools import * +from nose import with_setup + +import os +import shutil +import tempfile +import apply_update +import with_setup_args + +def get_filename_setup(): +    tmpdir1 = tempfile.mkdtemp(prefix = 'lnx') +    tmpdir2 = tempfile.mkdtemp(prefix = 'mac') +    tmpdir3 = tempfile.mkdtemp(prefix = 'win') +    tmpdir4 = tempfile.mkdtemp(prefix = 'bad') +    tempfile.mkstemp(suffix = '.bz2', dir = tmpdir1) +    tempfile.mkstemp(suffix = '.dmg', dir = tmpdir2) +    tempfile.mkstemp(suffix = '.exe', dir = tmpdir3) + +    return [tmpdir1,tmpdir2, tmpdir3, tmpdir4], {} + +def get_filename_teardown(tmpdir1,tmpdir2, tmpdir3, tmpdir4): +    shutil.rmtree(tmpdir1, ignore_errors = True) +    shutil.rmtree(tmpdir2, ignore_errors = True) +    shutil.rmtree(tmpdir3, ignore_errors = True) +    shutil.rmtree(tmpdir4, ignore_errors = True) + +@with_setup_args.with_setup_args(get_filename_setup, get_filename_teardown) +def test_get_filename(tmpdir1, tmpdir2, tmpdir3, tmpdir4): +    assert_is_not_none(apply_update.get_filename(tmpdir1)), "Failed to find installable" +    assert_is_not_none(apply_update.get_filename(tmpdir2)), "Failed to find installable" +    assert_is_not_none(apply_update.get_filename(tmpdir3)), "Failed to find installable" + +@with_setup_args.with_setup_args(get_filename_setup, get_filename_teardown) +def test_missing_get_filename(tmpdir1, tmpdir2, tmpdir3, tmpdir4): +    not_found = not apply_update.get_filename(tmpdir4) +    assert not_found, "False positive, should not find an installable in an empty dir"
\ No newline at end of file diff --git a/indra/viewer_components/manager/tests/test_get_log_file_handle.py b/indra/viewer_components/manager/tests/test_get_log_file_handle.py new file mode 100644 index 0000000000..c5b3c89550 --- /dev/null +++ b/indra/viewer_components/manager/tests/test_get_log_file_handle.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python + +# $LicenseInfo:firstyear=2016&license=internal$ +#  +# Copyright (c) 2016, Linden Research, Inc. +#  +# The following source code is PROPRIETARY AND CONFIDENTIAL. Use of +# this source code is governed by the Linden Lab Source Code Disclosure +# Agreement ("Agreement") previously entered between you and Linden +# Lab. By accessing, using, copying, modifying or distributing this +# software, you acknowledge that you have been informed of your +# obligations under the Agreement and agree to abide by those obligations. +#  +# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +# COMPLETENESS OR PERFORMANCE. +# $/LicenseInfo$ + +""" +@file   test_get_log_file_handle.py +@author coyot +@date   2016-06-08 +""" + +from nose.tools import * + +import os +import shutil +import tempfile +import update_manager +import with_setup_args + +def get_log_file_handle_setup(): +    tmpdir1 = tempfile.mkdtemp(prefix = 'test1') +    tmpdir2 = tempfile.mkdtemp(prefix = 'test2') +    log_file_path = os.path.abspath(os.path.join(tmpdir1,"update_manager.log")) +    #not using tempfile because we want a particular filename +    open(log_file_path, 'w+').close + +    return [tmpdir1,tmpdir2,log_file_path], {} + +def get_log_file_handle_teardown(tmpdir1,tmpdir2,log_file_path): +    shutil.rmtree(tmpdir1, ignore_errors = True) +    shutil.rmtree(tmpdir2, ignore_errors = True) +     +@with_setup_args.with_setup_args(get_log_file_handle_setup, get_log_file_handle_teardown) +def test_existing_get_log_file_handle(tmpdir1,tmpdir2,log_file_path): +    handle = update_manager.get_log_file_handle(tmpdir1) +    if not handle: +        print "Failed to find existing log file" +        assert False +    elif not os.path.exists(os.path.abspath(log_file_path+".old")): +        print "Failed to rotate update manager log" +        assert False +    assert True +     +@with_setup_args.with_setup_args(get_log_file_handle_setup, get_log_file_handle_teardown) +def test_missing_get_log_file_handle(tmpdir1,tmpdir2,log_file_path): +    handle = update_manager.get_log_file_handle(tmpdir2) +    if not os.path.exists(log_file_path): +        print "Failed to touch new log file" +        assert False +    assert True
\ No newline at end of file diff --git a/indra/viewer_components/manager/tests/test_get_parent_path.py b/indra/viewer_components/manager/tests/test_get_parent_path.py new file mode 100644 index 0000000000..3cfd72310e --- /dev/null +++ b/indra/viewer_components/manager/tests/test_get_parent_path.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python + +# $LicenseInfo:firstyear=2016&license=internal$ +#  +# Copyright (c) 2016, Linden Research, Inc. +#  +# The following source code is PROPRIETARY AND CONFIDENTIAL. Use of +# this source code is governed by the Linden Lab Source Code Disclosure +# Agreement ("Agreement") previously entered between you and Linden +# Lab. By accessing, using, copying, modifying or distributing this +# software, you acknowledge that you have been informed of your +# obligations under the Agreement and agree to abide by those obligations. +#  +# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +# COMPLETENESS OR PERFORMANCE. +# $/LicenseInfo$ + +""" +@file   test_get_parent_path.py +@author coyot +@date   2016-06-02 +""" + +from nose.tools import * +from nose import with_setup + +import os +import shutil +import update_manager +import with_setup_args + +def get_parent_path_setup(): +    key = update_manager.get_platform_key() +    try: +        if key == 'mac': +            settings_dir = os.path.join(os.path.expanduser('~'),'Library','Application Support','SecondLife') +        elif key == 'lnx': +            settings_dir = os.path.join(os.path.expanduser('~'),'.secondlife') +        elif key == 'win': +            settings_dir = os.path.join(os.path.expanduser('~'),'AppData','Roaming','SecondLife') +        else: +            raise Exception("Invalid Platform Key") + +        #preserve existing settings dir if any +        if os.path.exists(settings_dir): +            old_dir = settings_dir + ".tmp"  +            if os.path.exists(old_dir): +                shutil.rmtree(old_dir, ignore_errors = True) +            os.rename(settings_dir, old_dir) +        os.makedirs(settings_dir) +    except Exception, e: +        print "get_parent_path_setup failed due to: %s" % str(e) +        assert False + +    #this is we don't have to rediscover settings_dir for test and teardown +    return [settings_dir], {} +  +def get_parent_path_teardown(settings_dir): +    try: +        shutil.rmtree(settings_dir, ignore_errors = True) +        #restore previous settings dir if any +        old_dir = settings_dir + ".tmp" +        if os.path.exists(old_dir): +            os.rename(old_dir, settings_dir) +    except: +        #cleanup is best effort +        pass + +@with_setup_args.with_setup_args(get_parent_path_setup, get_parent_path_teardown) +def test_get_parent_path(settings_dir): +    key = update_manager.get_platform_key() +    got_settings_dir = update_manager.get_parent_path(key) +     +    assert settings_dir, "test_get_parent_path failed to obtain parent path" + +    assert_equal(settings_dir, got_settings_dir) + +    
\ No newline at end of file diff --git a/indra/viewer_components/manager/tests/test_get_platform_key.py b/indra/viewer_components/manager/tests/test_get_platform_key.py new file mode 100644 index 0000000000..37c570532c --- /dev/null +++ b/indra/viewer_components/manager/tests/test_get_platform_key.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python + +# $LicenseInfo:firstyear=2016&license=internal$ +#  +# Copyright (c) 2016, Linden Research, Inc. +#  +# The following source code is PROPRIETARY AND CONFIDENTIAL. Use of +# this source code is governed by the Linden Lab Source Code Disclosure +# Agreement ("Agreement") previously entered between you and Linden +# Lab. By accessing, using, copying, modifying or distributing this +# software, you acknowledge that you have been informed of your +# obligations under the Agreement and agree to abide by those obligations. +#  +# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +# COMPLETENESS OR PERFORMANCE. +# $/LicenseInfo$ + +""" +@file   test_get_platform_key.py +@author coyot +@date   2016-06-01 +""" + +from nose.tools import assert_equal + +import platform +import update_manager + +def test_get_platform_key(): +    key = update_manager.get_platform_key() +    if key == 'mac': +        assert_equal(platform.system(),'Darwin') +    elif key == 'lnx': +        assert_equal(platform.system(),'Linux') +    elif key == 'win': +        assert_equal(platform.system(),'Windows') +    else: +        assert_equal(key, None) +    
\ No newline at end of file diff --git a/indra/viewer_components/manager/tests/test_get_settings.py b/indra/viewer_components/manager/tests/test_get_settings.py new file mode 100644 index 0000000000..46b779cbd5 --- /dev/null +++ b/indra/viewer_components/manager/tests/test_get_settings.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python + +# $LicenseInfo:firstyear=2016&license=internal$ +#  +# Copyright (c) 2016, Linden Research, Inc. +#  +# The following source code is PROPRIETARY AND CONFIDENTIAL. Use of +# this source code is governed by the Linden Lab Source Code Disclosure +# Agreement ("Agreement") previously entered between you and Linden +# Lab. By accessing, using, copying, modifying or distributing this +# software, you acknowledge that you have been informed of your +# obligations under the Agreement and agree to abide by those obligations. +#  +# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +# COMPLETENESS OR PERFORMANCE. +# $/LicenseInfo$ + +""" +@file   test_get_settings.py +@author coyot +@date   2016-06-03 +""" + +from nose.tools import * +from nose import with_setup + +import os +import shutil +import update_manager +import with_setup_args + +def get_settings_setup(): +    try: +        key = update_manager.get_platform_key() +        settings_dir = os.path.join(update_manager.get_parent_path(key), "user_settings") +        print settings_dir + +        #preserve existing settings dir if any +        if os.path.exists(settings_dir): +            old_dir = settings_dir + ".tmp" +            if os.path.exists(old_dir): +                shutil.rmtree(old_dir, ignore_errors = True) +            os.rename(settings_dir, old_dir)   +        os.makedirs(settings_dir) + +        #the data subdir of the tests dir that this script is in +        data_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "data") +        #the test settings file +        settings_file = os.path.join(data_dir, "settings.xml") +        shutil.copyfile(settings_file, os.path.join(settings_dir, "settings.xml")) + +    except Exception, e: +        print "get_settings_setup failed due to: %s" % str(e) +        assert False + +    #this is we don't have to rediscover settings_dir for test and teardown +    return [settings_dir], {} +  +def get_settings_teardown(settings_dir): +    try: +        shutil.rmtree(settings_dir, ignore_errors = True) +        #restore previous settings dir if any +        old_dir = settings_dir + ".tmp" +        if os.path.exists(old_dir): +            os.rename(old_dir, settings_dir) +    except: +        #cleanup is best effort +        pass + +@with_setup_args.with_setup_args(get_settings_setup, get_settings_teardown) +def test_get_settings(settings_dir): +    key = update_manager.get_platform_key() +    parent = update_manager.get_parent_path(key) +    log_file = update_manager.get_log_file_handle(parent) +    got_settings = update_manager.get_settings(log_file, parent) + +    assert got_settings, "test_get_settings failed to find a settings.xml file" + +    #test one key just to make sure it parsed +    assert_equal(got_settings['CurrentGrid']['Value'], 'util.agni.lindenlab.com') + diff --git a/indra/viewer_components/manager/tests/test_make_VVM_UUID_hash.py b/indra/viewer_components/manager/tests/test_make_VVM_UUID_hash.py new file mode 100644 index 0000000000..513502a6ca --- /dev/null +++ b/indra/viewer_components/manager/tests/test_make_VVM_UUID_hash.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python + +# $LicenseInfo:firstyear=2016&license=internal$ +#  +# Copyright (c) 2016, Linden Research, Inc. +#  +# The following source code is PROPRIETARY AND CONFIDENTIAL. Use of +# this source code is governed by the Linden Lab Source Code Disclosure +# Agreement ("Agreement") previously entered between you and Linden +# Lab. By accessing, using, copying, modifying or distributing this +# software, you acknowledge that you have been informed of your +# obligations under the Agreement and agree to abide by those obligations. +#  +# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +# COMPLETENESS OR PERFORMANCE. +# $/LicenseInfo$ + +""" +@file   test_make_VVM_UUID_hash.py +@author coyot +@date   2016-06-03 +""" + +from nose.tools import * + +import update_manager + +def test_make_VVM_UUID_hash(): +    #because the method returns different results on different hosts +    #it is not easy to unit test it reliably.   +    #About the best we can do is check for the exception from subprocess +    key = update_manager.get_platform_key() +    try: +        UUID_hash = update_manager.make_VVM_UUID_hash(key) +    except Exception, e: +        print "Test failed due to: %s" % str(e) +        assert False + +    #make_UUID_hash returned None +    assert UUID_hash, "make_UUID_hash failed to make a hash." + diff --git a/indra/viewer_components/manager/tests/test_make_download_dir.py b/indra/viewer_components/manager/tests/test_make_download_dir.py new file mode 100644 index 0000000000..5198a6de05 --- /dev/null +++ b/indra/viewer_components/manager/tests/test_make_download_dir.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python + +# $LicenseInfo:firstyear=2016&license=internal$ +#  +# Copyright (c) 2016, Linden Research, Inc. +#  +# The following source code is PROPRIETARY AND CONFIDENTIAL. Use of +# this source code is governed by the Linden Lab Source Code Disclosure +# Agreement ("Agreement") previously entered between you and Linden +# Lab. By accessing, using, copying, modifying or distributing this +# software, you acknowledge that you have been informed of your +# obligations under the Agreement and agree to abide by those obligations. +#  +# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +# COMPLETENESS OR PERFORMANCE. +# $/LicenseInfo$ + +""" +@file   test_make_download_dir.py +@author coyot +@date   2016-06-03 +""" + +from nose.tools import * + +import update_manager + +def test_make_download_dir(): +    key = update_manager.get_platform_key() +    path = update_manager.get_parent_path(key) +    version = '1.2.3.456789' +    try: +        download_dir = update_manager.make_download_dir(path, version) +    except OSError, e: +        print "make_download_dir failed to eat OSError %s" % str(e) +        assert False +    except Exception, e: +        print "make_download_dir raised an unexpected exception %s" % str(e) +        assert False + +    assert download_dir, "make_download_dir returned None for path %s and version %s" % (path, version)
\ No newline at end of file diff --git a/indra/viewer_components/manager/tests/test_query_vvm.py b/indra/viewer_components/manager/tests/test_query_vvm.py new file mode 100644 index 0000000000..40a0f7b215 --- /dev/null +++ b/indra/viewer_components/manager/tests/test_query_vvm.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python + +# $LicenseInfo:firstyear=2016&license=internal$ +#  +# Copyright (c) 2016, Linden Research, Inc. +#  +# The following source code is PROPRIETARY AND CONFIDENTIAL. Use of +# this source code is governed by the Linden Lab Source Code Disclosure +# Agreement ("Agreement") previously entered between you and Linden +# Lab. By accessing, using, copying, modifying or distributing this +# software, you acknowledge that you have been informed of your +# obligations under the Agreement and agree to abide by those obligations. +#  +# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +# COMPLETENESS OR PERFORMANCE. +# $/LicenseInfo$ + +""" +@file   test_query_vvm.py +@author coyot +@date   2016-06-08 +""" + +from nose.tools import * + +import os +import re +import shutil +import tempfile +import update_manager +import with_setup_args + +def query_vvm_setup(): +    tmpdir1 = tempfile.mkdtemp(prefix = 'test1') +    handle = update_manager.get_log_file_handle(tmpdir1) + +    return [tmpdir1,handle], {} + +def query_vvm_teardown(tmpdir1, handle): +    shutil.rmtree(tmpdir1, ignore_errors = True) + +@with_setup_args.with_setup_args(query_vvm_setup, query_vvm_teardown) +def test_query_vvm(tmpdir1, handle): +    key = update_manager.get_platform_key() +    parent = update_manager.get_parent_path(key) +    settings = update_manager.get_settings(handle, parent) +    launcher_path = os.path.dirname(os.path.dirname(os.path.abspath(os.path.realpath(__file__)))) +    summary = update_manager.get_summary(key, launcher_path) + +    #for unit testing purposes, just testing a value from results.  If no update, then None and it falls through +    #for formal QA see: +    #   https://docs.google.com/document/d/1WNjOPdKlq0j_7s7gdNe_3QlyGnQDa3bFNvtyVM6Hx8M/edit +    #   https://wiki.lindenlab.com/wiki/Login_Test#Test_Viewer_Updater +    #for test plans on all cases, as it requires setting up a fake VVM service + +    try: +        results = update_manager.query_vvm(handle, key, settings, summary) +    except Exception, e: +        print "query_vvm threw unexpected exception %s" % str(e) +        assert False + +    if results: +        pattern = re.compile('Second Life') +        assert pattern.search(results['channel']), "Bad results returned %s" % str(results) +         +    assert True diff --git a/indra/viewer_components/manager/tests/test_silent_write.py b/indra/viewer_components/manager/tests/test_silent_write.py new file mode 100644 index 0000000000..a55665799f --- /dev/null +++ b/indra/viewer_components/manager/tests/test_silent_write.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python + +# $LicenseInfo:firstyear=2016&license=internal$ +#  +# Copyright (c) 2016, Linden Research, Inc. +#  +# The following source code is PROPRIETARY AND CONFIDENTIAL. Use of +# this source code is governed by the Linden Lab Source Code Disclosure +# Agreement ("Agreement") previously entered between you and Linden +# Lab. By accessing, using, copying, modifying or distributing this +# software, you acknowledge that you have been informed of your +# obligations under the Agreement and agree to abide by those obligations. +#  +# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +# COMPLETENESS OR PERFORMANCE. +# $/LicenseInfo$ + +""" +@file   test_silent_write.py +@author coyot +@date   2016-06-02 +""" + +from nose.tools import * + +import tempfile +import update_manager + +def test_silent_write_to_file():  +    test_log = tempfile.TemporaryFile() +    try: +        update_manager.silent_write(test_log, "This is a test.") +    except Exception, e: +        print "Test failed due to: %s" % str(e) +        assert False + +def test_silent_write_to_null():  +    try: +        update_manager.silent_write(None, "This is a test.") +    except Exception, e: +        print "Test failed due to: %s" % str(e) +        assert False
\ No newline at end of file diff --git a/indra/viewer_components/manager/tests/test_summary.py b/indra/viewer_components/manager/tests/test_summary.py new file mode 100644 index 0000000000..b318012b54 --- /dev/null +++ b/indra/viewer_components/manager/tests/test_summary.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python + +# $LicenseInfo:firstyear=2016&license=internal$ +#  +# Copyright (c) 2016, Linden Research, Inc. +#  +# The following source code is PROPRIETARY AND CONFIDENTIAL. Use of +# this source code is governed by the Linden Lab Source Code Disclosure +# Agreement ("Agreement") previously entered between you and Linden +# Lab. By accessing, using, copying, modifying or distributing this +# software, you acknowledge that you have been informed of your +# obligations under the Agreement and agree to abide by those obligations. +#  +# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +# COMPLETENESS OR PERFORMANCE. +# $/LicenseInfo$ + +""" +@file   test_summary.py +@author coyot +@date   2016-06-02 +""" + +from nose.tools import * + +import os.path +import tempfile +import update_manager + +def test_get_summary(): +    key = update_manager.get_platform_key() +    #launcher is one dir above tests +    launcher_path = os.path.dirname(os.path.dirname(os.path.abspath(os.path.realpath(__file__)))) +    summary_json = update_manager.get_summary(key, launcher_path) + +    #we aren't testing the JSON library, one key pair is enough +    #so we will use the one pair that is actually a constant +    assert_equal(summary_json['Type'],'viewer')
\ No newline at end of file diff --git a/indra/viewer_components/manager/tests/with_setup_args.py b/indra/viewer_components/manager/tests/with_setup_args.py new file mode 100644 index 0000000000..38350ab8c4 --- /dev/null +++ b/indra/viewer_components/manager/tests/with_setup_args.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python + +# $LicenseInfo:firstyear=2016&license=internal$ +#  +# Copyright (c) 2016, Linden Research, Inc. +#  +# The following source code is PROPRIETARY AND CONFIDENTIAL. Use of +# this source code is governed by the Linden Lab Source Code Disclosure +# Agreement ("Agreement") previously entered between you and Linden +# Lab. By accessing, using, copying, modifying or distributing this +# software, you acknowledge that you have been informed of your +# obligations under the Agreement and agree to abide by those obligations. +#  +# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +# COMPLETENESS OR PERFORMANCE. +# $/LicenseInfo$ +#  +# Taken from: https://gist.github.com/garyvdm/392ae20c673c7ee58d76 + +""" +@file   with_setup_args.py +@author garyvdm +@date   2016-06-02 +""" + + +def with_setup_args(setup, teardown=None): +    """Decorator to add setup and/or teardown methods to a test function:: +      @with_setup_args(setup, teardown) +      def test_something(): +          " ... " +    The setup function should return (args, kwargs) which will be passed to +    test function, and teardown function. +    Note that `with_setup_args` is useful *only* for test functions, not for test +    methods or inside of TestCase subclasses. +    """ +    def decorate(func): +        args = [] +        kwargs = {} + +        def test_wrapped(): +            func(*args, **kwargs) + +        test_wrapped.__name__ = func.__name__ + +        def setup_wrapped(): +            a, k = setup() +            args.extend(a) +            kwargs.update(k) +            if hasattr(func, 'setup'): +                func.setup() +        test_wrapped.setup = setup_wrapped + +        if teardown: +            def teardown_wrapped(): +                if hasattr(func, 'teardown'): +                    func.teardown() +                teardown(*args, **kwargs) + +            test_wrapped.teardown = teardown_wrapped +        else: +            if hasattr(func, 'teardown'): +                test_wrapped.teardown = func.teardown() +        return test_wrapped +    return decorate
\ No newline at end of file diff --git a/indra/viewer_components/manager/update_manager.py b/indra/viewer_components/manager/update_manager.py index ec6df17a6c..a7e0a19aef 100755 --- a/indra/viewer_components/manager/update_manager.py +++ b/indra/viewer_components/manager/update_manager.py @@ -204,11 +204,14 @@ def make_VVM_UUID_hash(platform_key):          #fake it          return hashlib.md5(str(uuid.uuid1())).hexdigest() -def query_vvm(log_file_handle, platform_key, settings, summary_dict): +def query_vvm(log_file_handle = None, platform_key = None, settings = None, summary_dict = None, UpdaterServiceURL = None, UpdaterWillingToTest = None):      result_data = None      #URI template /update/v1.1/channelname/version/platformkey/platformversion/willing-to-test/uniqueid      #https://wiki.lindenlab.com/wiki/Viewer_Version_Manager_REST_API#Viewer_Update_Query -    base_URI = 'https://update.secondlife.com/update/' +    if UpdaterServiceURL: +        baseURI = UpdaterServiceURL +    else: +        base_URI = 'https://update.secondlife.com/update/'      channelname = summary_dict['Channel']      #this is kind of a mess because the settings value a) in a map and b) is both the cohort and the version      version = summary_dict['Version'] @@ -229,11 +232,17 @@ def query_vvm(log_file_handle, platform_key, settings, summary_dict):          </map>      </map>      """ -    try: -        test_ok = settings['test']['Value'] -    except KeyError as ke: -        #normal case, no testing key -        test_ok = 'testok' +    if UpdaterWillingToTest is not None: +        if UpdaterWillingToTest: +            test_ok = 'testok' +        else: +            test_ok = 'testno' +    else:    +        try: +            test_ok = settings['test']['Value'] +        except KeyError: +            #normal case, no testing key +            test_ok = 'testok'      UUID = make_VVM_UUID_hash(platform_key)      #because urljoin can't be arsed to take multiple elements      query_string =  '/v1.0/' + channelname + '/' + version + '/' + platform_key + '/' + platform_version + '/' + test_ok + '/' + UUID @@ -245,7 +254,7 @@ def query_vvm(log_file_handle, platform_key, settings, summary_dict):          return None      return result_data -def download(url = None, version = None, download_dir = None, size = 0, background = False): +def download(url = None, version = None, download_dir = None, size = 0, background = False, chunk_size = 1024):      download_tries = 0      download_success = False      #for background execution @@ -259,7 +268,7 @@ def download(url = None, version = None, download_dir = None, size = 0, backgrou              after_frame(message = "Trying again to download new version " + version + " Please wait.")          if not background:              try: -                download_update.download_update(url = url, download_dir = download_dir, size = size, progressbar = True) +                download_update.download_update(url = url, download_dir = download_dir, size = size, progressbar = True, chunk_size = chunk_size)                  download_success = True              except:                  download_tries += 1     @@ -268,7 +277,7 @@ def download(url = None, version = None, download_dir = None, size = 0, backgrou              try:                  #Python does not have a facility to multithread a method, so we make the method a standalone                  #and subprocess that -                subprocess.call(path_to_downloader, "--url = %s --dir = %s --pb --size= %s" % (url, download_dir, size)) +                subprocess.call(path_to_downloader, "--url = %s --dir = %s --pb --size = %s --chunk_size = %s" % (url, download_dir, size, chunk_size))                  download_success = True              except:                  download_tries += 1 @@ -294,11 +303,12 @@ def install(platform_key = None, download_dir = None, log_file_handle = None, in              silent_write(log_file_handle, "Failed to update viewer to " + version)              return False -def download_and_install(downloaded = None, url = None, version = None, download_dir = None, size = None, platform_key = None, log_file_handle = None, in_place = None): +def download_and_install(downloaded = None, url = None, version = None, download_dir = None, size = None,  +                         platform_key = None, log_file_handle = None, in_place = None, chunk_size = 1024):      #extracted to a method because we do it twice in update_manager() and this makes the logic clearer      if not downloaded:          #do the download, exit if we fail -        if not download(url = url, version = version, download_dir = download_dir, size = size):  +        if not download(url = url, version = version, download_dir = download_dir, size = size, chunk_size = chunk_size):               return (False, 'download', version)        #do the install      path_to_new_launcher = install(platform_key = platform_key, download_dir = download_dir,  @@ -313,7 +323,8 @@ def download_and_install(downloaded = None, url = None, version = None, download          #propagate failure          return (False, 'apply', version)     -def update_manager(): +def update_manager(cli_overrides = None): +    #cli_overrides is a dict where the keys are specific parameters of interest and the values are the arguments to       #comments that begin with '323:' are steps taken from the algorithm in the description of SL-323.       #  Note that in the interest of efficiency, such as determining download success once at the top      #  The code does follow precisely the same order as the algorithm. @@ -356,7 +367,11 @@ def update_manager():              print "Update manager exited with (%s, %s, %s)" % (False, 'setup', None)              return (False, 'setup', None) -    settings = get_settings(log_file_handle, parent_dir) +    if cli_overrides['settings'] is not None: +        settings = get_settings(log_file_handle, cli_overrides['settings']) +    else: +        settings = get_settings(log_file_handle, parent_dir) +              if settings is None:          silent_write(log_file_handle, "Failed to load viewer settings")          print "Update manager exited with (%s, %s, %s)" % (False, 'setup', None) @@ -375,22 +390,34 @@ def update_manager():              <string>0</string>          </map>      """ -    try: -        install_automatically = settings['UpdaterServiceSetting']['Value'] -    #because, for some godforsaken reason, we delete the setting rather than changing the value -    except KeyError: -        install_automatically = 1 +    if cli_overrides['set']['UpdaterServiceSetting'] is not None: +        install_automatically = cli_overrides['set']['UpdaterServiceSetting'] +    else: +        try: +            install_automatically = settings['UpdaterServiceSetting']['Value'] +        #because, for some godforsaken reason, we delete the setting rather than changing the value +        except KeyError: +            install_automatically = 1 +     +    #use default chunk size if none is given         +    if cli_overrides['set']['UpdaterMaximumBandwidth ']: +        chunk_size = cli_overrides['set']['UpdaterMaximumBandwidth '] +    else: +        chunk_size = 1024      #get channel and version      try:          summary_dict = get_summary(platform_key, os.path.abspath(os.path.realpath(__file__))) +        if cli_overrides['channel']: +            summary_dict['Channel'] = cli_overrides['channel']      except:          silent_write(log_file_handle, "Could not obtain channel and version, exiting.")          print "Update manager exited with (%s, %s, %s)" % (False, 'setup', None)          return (False, 'setup', None)              #323: On launch, the Viewer Manager should query the Viewer Version Manager update api. -    result_data = query_vvm(log_file_handle, platform_key, settings, summary_dict) +    UpdaterServiceURL = cli_overrides['update-service'] +    result_data = query_vvm(log_file_handle, platform_key, settings, summary_dict, UpdaterServiceURL)      #nothing to do or error      if not result_data:          silent_write.write(og_file_handle, "No update found.") @@ -417,7 +444,7 @@ def update_manager():          #323: Check for a completed download of the required update; if found, display an alert, install the required update, and launch the newly installed viewer.          #323: If [optional download and] Install Automatically: display an alert, install the update and launch updated viewer.          return download_and_install(downloaded = downloaded, url = result_data['url'], version = result_data['version'], download_dir = download_dir,  -                                    size = result_data['size'], platform_key = platform_key, log_file_handle = log_file_handle, in_place = in_place) +                                    size = result_data['size'], platform_key = platform_key, log_file_handle = log_file_handle, in_place = in_place, chunk_size = chunk_size)      else:          #323: If the update response indicates that there is an optional update:           #323: Check to see if the optional update has already been downloaded. @@ -436,7 +463,7 @@ def update_manager():              choice = frame.choice.get()              if choice == 1:                  return download_and_install(downloaded = downloaded, url = result_data['url'], version = result_data['version'], download_dir = download_dir,  -                                    size = result_data['size'], platform_key = platform_key, log_file_handle = log_file_handle, in_place = in_place) +                                    size = result_data['size'], platform_key = platform_key, log_file_handle = log_file_handle, in_place = in_place, chunk_size = chunk_size)              elif choice == 2:                  tempfile.mkstmp(suffix = ".next", dir = download_dir)                  return (True, None, None)  | 
