OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
PropertyScrambler.cs
Go to the documentation of this file.
1 /*
2  * Copyright (c) Contributors, http://opensimulator.org/
3  * See CONTRIBUTORS.TXT for a full list of copyright holders.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of the OpenSimulator Project nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 using System;
29 using System.Collections;
30 using System.Collections.Generic;
31 using System.Linq.Expressions;
32 using System.Reflection;
33 using System.Text;
34 using NUnit.Framework;
35 using OpenMetaverse;
36 using OpenSim.Framework;
37 using OpenSim.Tests.Common;
38 
39 namespace OpenSim.Data.Tests
40 {
41  //This is generic so that the lambda expressions will work right in IDEs.
42  public class PropertyScrambler<T>
43  {
44  readonly System.Collections.Generic.List<string> membersToNotScramble = new List<string>();
45 
46  private void AddExpressionToNotScrableList(Expression expression)
47  {
48  UnaryExpression unaryExpression = expression as UnaryExpression;
49  if (unaryExpression != null)
50  {
51  AddExpressionToNotScrableList(unaryExpression.Operand);
52  return;
53  }
54 
55  MemberExpression memberExpression = expression as MemberExpression;
56  if (memberExpression != null)
57  {
58  if (!(memberExpression.Member is PropertyInfo))
59  {
60  throw new NotImplementedException("I don't know how deal with a MemberExpression that is a " + expression.Type);
61  }
62  membersToNotScramble.Add(memberExpression.Member.Name);
63  return;
64  }
65 
66  throw new NotImplementedException("I don't know how to parse a " + expression.Type);
67  }
68 
69  public PropertyScrambler<T> DontScramble(Expression<Func<T, object>> expression)
70  {
71  AddExpressionToNotScrableList(expression.Body);
72  return this;
73  }
74 
75  public void Scramble(T obj)
76  {
77  internalScramble(obj);
78  }
79 
80  private void internalScramble(object obj)
81  {
82  PropertyInfo[] properties = obj.GetType().GetProperties();
83  foreach (var property in properties)
84  {
85  //Skip indexers of classes. We will assume that everything that has an indexer
86  // is also IEnumberable. May not always be true, but should be true normally.
87  if (property.GetIndexParameters().Length > 0)
88  continue;
89 
90  RandomizeProperty(obj, property, null);
91  }
92  //Now if it implments IEnumberable, it's probably some kind of list, so we should randomize
93  // everything inside of it.
94  IEnumerable enumerable = obj as IEnumerable;
95  if (enumerable != null)
96  {
97  foreach (object value in enumerable)
98  {
99  internalScramble(value);
100  }
101  }
102  }
103 
104  private readonly Random random = new Random();
105  private void RandomizeProperty(object obj, PropertyInfo property, object[] index)
106  {//I'd like a better way to compare, but I had lots of problems with InventoryFolderBase because the ID is inherited.
107  if (membersToNotScramble.Contains(property.Name))
108  return;
109  Type t = property.PropertyType;
110  if (!property.CanWrite)
111  return;
112  object value = property.GetValue(obj, index);
113  if (value == null)
114  return;
115 
116  if (t == typeof(string))
117  property.SetValue(obj, RandomName(), index);
118  else if (t == typeof(UUID))
119  property.SetValue(obj, UUID.Random(), index);
120  else if (t == typeof(sbyte))
121  property.SetValue(obj, (sbyte)random.Next(sbyte.MinValue, sbyte.MaxValue), index);
122  else if (t == typeof(short))
123  property.SetValue(obj, (short)random.Next(short.MinValue, short.MaxValue), index);
124  else if (t == typeof(int))
125  property.SetValue(obj, random.Next(), index);
126  else if (t == typeof(long))
127  property.SetValue(obj, random.Next() * int.MaxValue, index);
128  else if (t == typeof(byte))
129  property.SetValue(obj, (byte)random.Next(byte.MinValue, byte.MaxValue), index);
130  else if (t == typeof(ushort))
131  property.SetValue(obj, (ushort)random.Next(ushort.MinValue, ushort.MaxValue), index);
132  else if (t == typeof(uint))
133  property.SetValue(obj, Convert.ToUInt32(random.Next()), index);
134  else if (t == typeof(ulong))
135  property.SetValue(obj, Convert.ToUInt64(random.Next()) * Convert.ToUInt64(UInt32.MaxValue), index);
136  else if (t == typeof(bool))
137  property.SetValue(obj, true, index);
138  else if (t == typeof(byte[]))
139  {
140  byte[] bytes = new byte[30];
141  random.NextBytes(bytes);
142  property.SetValue(obj, bytes, index);
143  }
144  else
145  internalScramble(value);
146  }
147 
148  private string RandomName()
149  {
150  StringBuilder name = new StringBuilder();
151  int size = random.Next(5, 12);
152  for (int i = 0; i < size; i++)
153  {
154  char ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
155  name.Append(ch);
156  }
157  return name.ToString();
158  }
159  }
160 
161  [TestFixture]
163  {
164  [Test]
165  public void TestScramble()
166  {
167  AssetBase actual = new AssetBase(UUID.Random(), "asset one", (sbyte)AssetType.Texture, UUID.Zero.ToString());
168  new PropertyScrambler<AssetBase>().Scramble(actual);
169  }
170 
171  [Test]
172  public void DontScramble()
173  {
174  UUID uuid = UUID.Random();
175  AssetBase asset = new AssetBase(uuid, "asset", (sbyte)AssetType.Texture, UUID.Zero.ToString());
176  new PropertyScrambler<AssetBase>()
177  .DontScramble(x => x.Metadata)
178  .DontScramble(x => x.FullID)
179  .DontScramble(x => x.ID)
180  .Scramble(asset);
181  Assert.That(asset.FullID, Is.EqualTo(uuid));
182  }
183  }
184 }
PropertyScrambler< T > DontScramble(Expression< Func< T, object >> expression)
Asset class. All Assets are reference by this class or a class derived from this class ...
Definition: AssetBase.cs:49
System.Collections.IEnumerable IEnumerable